A Python port of the Invisible Internet Project (I2P)
1"""Tests for setup wizard — TDD: tests before implementation."""
2
3import json
4import os
5import tempfile
6from unittest.mock import patch, MagicMock
7
8import pytest
9
10from i2p_apps.setup.wizard import SetupWizard
11from i2p_apps.setup.local_probe import LocalProbeResult
12from i2p_apps.setup.stun_probe import NatProbeResult
13from i2p_apps.setup.config_advisor import ConfigRecommendation
14
15
16def _mock_local():
17 return LocalProbeResult(
18 crypto_ops_per_sec=15000,
19 available_ram_bytes=8_000_000_000,
20 total_ram_bytes=16_000_000_000,
21 cpu_count=8,
22 disk_write_mbps=200.0,
23 disk_free_bytes=100_000_000_000,
24 )
25
26
27def _mock_nat():
28 return NatProbeResult(
29 nat_present=True,
30 nat_type="cone",
31 external_ip="203.0.113.42",
32 external_port=54321,
33 servers_reached=2,
34 )
35
36
37class TestSetupWizard:
38 def test_is_first_run_no_config(self):
39 with tempfile.TemporaryDirectory() as tmpdir:
40 wiz = SetupWizard(data_dir=tmpdir)
41 assert wiz.is_first_run() is True
42
43 def test_is_first_run_with_config(self):
44 with tempfile.TemporaryDirectory() as tmpdir:
45 config_path = os.path.join(tmpdir, "router.config.json")
46 with open(config_path, "w") as f:
47 json.dump({"version": 1}, f)
48 wiz = SetupWizard(data_dir=tmpdir)
49 assert wiz.is_first_run() is False
50
51 def test_save_config(self):
52 with tempfile.TemporaryDirectory() as tmpdir:
53 wiz = SetupWizard(data_dir=tmpdir)
54 config = {"bandwidth_limit_kbps": 5000, "share_percentage": 60}
55 wiz.save_config(config)
56 path = os.path.join(tmpdir, "router.config.json")
57 assert os.path.exists(path)
58 with open(path) as f:
59 saved = json.load(f)
60 assert saved["bandwidth_limit_kbps"] == 5000
61
62 def test_load_config_exists(self):
63 with tempfile.TemporaryDirectory() as tmpdir:
64 config_path = os.path.join(tmpdir, "router.config.json")
65 with open(config_path, "w") as f:
66 json.dump({"version": 1, "share_percentage": 70}, f)
67 wiz = SetupWizard(data_dir=tmpdir)
68 loaded = wiz.load_config()
69 assert loaded is not None
70 assert loaded["share_percentage"] == 70
71
72 def test_load_config_missing(self):
73 with tempfile.TemporaryDirectory() as tmpdir:
74 wiz = SetupWizard(data_dir=tmpdir)
75 assert wiz.load_config() is None
76
77 def test_run_auto_normal(self):
78 with tempfile.TemporaryDirectory() as tmpdir:
79 wiz = SetupWizard(data_dir=tmpdir)
80 with patch("i2p_apps.setup.wizard.run_local_probes", return_value=_mock_local()), \
81 patch("i2p_apps.setup.wizard.detect_nat_type", return_value=_mock_nat()), \
82 patch("i2p_apps.setup.wizard.run_network_probes") as mock_net:
83 from i2p_apps.setup.network_probe import (
84 DnsProbeResult, LatencyProbeResult, BandwidthEstimate, NetworkProbeResult,
85 )
86 mock_net.return_value = NetworkProbeResult(
87 dns=DnsProbeResult(True, True, True, 10.0),
88 latency=LatencyProbeResult(45.0, 8.0, 3, 3),
89 bandwidth=BandwidthEstimate(12.0, "cdn_download"),
90 reseed_reachable=True,
91 )
92 config = wiz.run_auto(mode="normal")
93 assert isinstance(config, dict)
94 assert "bandwidth_limit_kbps" in config
95 assert "share_percentage" in config
96
97 def test_run_auto_paranoid_skips_network(self):
98 with tempfile.TemporaryDirectory() as tmpdir:
99 wiz = SetupWizard(data_dir=tmpdir)
100 with patch("i2p_apps.setup.wizard.run_local_probes", return_value=_mock_local()), \
101 patch("i2p_apps.setup.wizard.detect_nat_type") as mock_nat, \
102 patch("i2p_apps.setup.wizard.run_network_probes") as mock_net:
103 config = wiz.run_auto(mode="paranoid")
104 mock_nat.assert_not_called()
105 mock_net.assert_not_called()
106 assert isinstance(config, dict)
107
108 def test_run_auto_saves_config(self):
109 with tempfile.TemporaryDirectory() as tmpdir:
110 wiz = SetupWizard(data_dir=tmpdir)
111 with patch("i2p_apps.setup.wizard.run_local_probes", return_value=_mock_local()), \
112 patch("i2p_apps.setup.wizard.detect_nat_type", return_value=_mock_nat()), \
113 patch("i2p_apps.setup.wizard.run_network_probes") as mock_net:
114 from i2p_apps.setup.network_probe import (
115 DnsProbeResult, LatencyProbeResult, BandwidthEstimate, NetworkProbeResult,
116 )
117 mock_net.return_value = NetworkProbeResult(
118 dns=DnsProbeResult(True, True, True, 10.0),
119 latency=LatencyProbeResult(45.0, 8.0, 3, 3),
120 bandwidth=BandwidthEstimate(12.0, "cdn_download"),
121 reseed_reachable=True,
122 )
123 wiz.run_auto(mode="normal")
124 assert not wiz.is_first_run() # config was saved
125
126 def test_run_auto_performance_mode(self):
127 """Performance mode should use higher resource allocation."""
128 with tempfile.TemporaryDirectory() as tmpdir:
129 wiz = SetupWizard(data_dir=tmpdir)
130 with patch("i2p_apps.setup.wizard.run_local_probes", return_value=_mock_local()), \
131 patch("i2p_apps.setup.wizard.detect_nat_type", return_value=_mock_nat()), \
132 patch("i2p_apps.setup.wizard.run_network_probes") as mock_net:
133 from i2p_apps.setup.network_probe import (
134 DnsProbeResult, LatencyProbeResult, BandwidthEstimate, NetworkProbeResult,
135 )
136 mock_net.return_value = NetworkProbeResult(
137 dns=DnsProbeResult(True, True, True, 10.0),
138 latency=LatencyProbeResult(45.0, 8.0, 3, 3),
139 bandwidth=BandwidthEstimate(100.0, "cdn_download"),
140 reseed_reachable=True,
141 )
142 config = wiz.run_auto(mode="performance")
143 assert isinstance(config, dict)