"""Tests for setup wizard — TDD: tests before implementation.""" import json import os import tempfile from unittest.mock import patch, MagicMock import pytest from i2p_apps.setup.wizard import SetupWizard from i2p_apps.setup.local_probe import LocalProbeResult from i2p_apps.setup.stun_probe import NatProbeResult from i2p_apps.setup.config_advisor import ConfigRecommendation def _mock_local(): return LocalProbeResult( crypto_ops_per_sec=15000, available_ram_bytes=8_000_000_000, total_ram_bytes=16_000_000_000, cpu_count=8, disk_write_mbps=200.0, disk_free_bytes=100_000_000_000, ) def _mock_nat(): return NatProbeResult( nat_present=True, nat_type="cone", external_ip="203.0.113.42", external_port=54321, servers_reached=2, ) class TestSetupWizard: def test_is_first_run_no_config(self): with tempfile.TemporaryDirectory() as tmpdir: wiz = SetupWizard(data_dir=tmpdir) assert wiz.is_first_run() is True def test_is_first_run_with_config(self): with tempfile.TemporaryDirectory() as tmpdir: config_path = os.path.join(tmpdir, "router.config.json") with open(config_path, "w") as f: json.dump({"version": 1}, f) wiz = SetupWizard(data_dir=tmpdir) assert wiz.is_first_run() is False def test_save_config(self): with tempfile.TemporaryDirectory() as tmpdir: wiz = SetupWizard(data_dir=tmpdir) config = {"bandwidth_limit_kbps": 5000, "share_percentage": 60} wiz.save_config(config) path = os.path.join(tmpdir, "router.config.json") assert os.path.exists(path) with open(path) as f: saved = json.load(f) assert saved["bandwidth_limit_kbps"] == 5000 def test_load_config_exists(self): with tempfile.TemporaryDirectory() as tmpdir: config_path = os.path.join(tmpdir, "router.config.json") with open(config_path, "w") as f: json.dump({"version": 1, "share_percentage": 70}, f) wiz = SetupWizard(data_dir=tmpdir) loaded = wiz.load_config() assert loaded is not None assert loaded["share_percentage"] == 70 def test_load_config_missing(self): with tempfile.TemporaryDirectory() as tmpdir: wiz = SetupWizard(data_dir=tmpdir) assert wiz.load_config() is None def test_run_auto_normal(self): with tempfile.TemporaryDirectory() as tmpdir: wiz = SetupWizard(data_dir=tmpdir) with patch("i2p_apps.setup.wizard.run_local_probes", return_value=_mock_local()), \ patch("i2p_apps.setup.wizard.detect_nat_type", return_value=_mock_nat()), \ patch("i2p_apps.setup.wizard.run_network_probes") as mock_net: from i2p_apps.setup.network_probe import ( DnsProbeResult, LatencyProbeResult, BandwidthEstimate, NetworkProbeResult, ) mock_net.return_value = NetworkProbeResult( dns=DnsProbeResult(True, True, True, 10.0), latency=LatencyProbeResult(45.0, 8.0, 3, 3), bandwidth=BandwidthEstimate(12.0, "cdn_download"), reseed_reachable=True, ) config = wiz.run_auto(mode="normal") assert isinstance(config, dict) assert "bandwidth_limit_kbps" in config assert "share_percentage" in config def test_run_auto_paranoid_skips_network(self): with tempfile.TemporaryDirectory() as tmpdir: wiz = SetupWizard(data_dir=tmpdir) with patch("i2p_apps.setup.wizard.run_local_probes", return_value=_mock_local()), \ patch("i2p_apps.setup.wizard.detect_nat_type") as mock_nat, \ patch("i2p_apps.setup.wizard.run_network_probes") as mock_net: config = wiz.run_auto(mode="paranoid") mock_nat.assert_not_called() mock_net.assert_not_called() assert isinstance(config, dict) def test_run_auto_saves_config(self): with tempfile.TemporaryDirectory() as tmpdir: wiz = SetupWizard(data_dir=tmpdir) with patch("i2p_apps.setup.wizard.run_local_probes", return_value=_mock_local()), \ patch("i2p_apps.setup.wizard.detect_nat_type", return_value=_mock_nat()), \ patch("i2p_apps.setup.wizard.run_network_probes") as mock_net: from i2p_apps.setup.network_probe import ( DnsProbeResult, LatencyProbeResult, BandwidthEstimate, NetworkProbeResult, ) mock_net.return_value = NetworkProbeResult( dns=DnsProbeResult(True, True, True, 10.0), latency=LatencyProbeResult(45.0, 8.0, 3, 3), bandwidth=BandwidthEstimate(12.0, "cdn_download"), reseed_reachable=True, ) wiz.run_auto(mode="normal") assert not wiz.is_first_run() # config was saved def test_run_auto_performance_mode(self): """Performance mode should use higher resource allocation.""" with tempfile.TemporaryDirectory() as tmpdir: wiz = SetupWizard(data_dir=tmpdir) with patch("i2p_apps.setup.wizard.run_local_probes", return_value=_mock_local()), \ patch("i2p_apps.setup.wizard.detect_nat_type", return_value=_mock_nat()), \ patch("i2p_apps.setup.wizard.run_network_probes") as mock_net: from i2p_apps.setup.network_probe import ( DnsProbeResult, LatencyProbeResult, BandwidthEstimate, NetworkProbeResult, ) mock_net.return_value = NetworkProbeResult( dns=DnsProbeResult(True, True, True, 10.0), latency=LatencyProbeResult(45.0, 8.0, 3, 3), bandwidth=BandwidthEstimate(100.0, "cdn_download"), reseed_reachable=True, ) config = wiz.run_auto(mode="performance") assert isinstance(config, dict)