mirror of
https://github.com/Such-Software/adaptive-multi-protocol-browser.git
synced 2026-10-18 23:08:33 +02:00
Harden browser docs and transport recovery
This commit is contained in:
@@ -126,6 +126,55 @@ class CliOpenTest(unittest.TestCase):
|
||||
helper.assert_called_once()
|
||||
self.assertEqual(9876, helper.call_args.kwargs["watch_pid"])
|
||||
|
||||
def test_transport_command_prints_setup_hint(self) -> None:
|
||||
result = ManagedTransportResult(
|
||||
transport="i2p",
|
||||
provider="-",
|
||||
status="missing-provider",
|
||||
endpoint="http://127.0.0.1:4444",
|
||||
owned=False,
|
||||
pid=0,
|
||||
state_dir=".ampb/transports/i2p",
|
||||
command=(),
|
||||
message="I2P provider not found.",
|
||||
setup_hint="Install i2pd with Homebrew: brew install i2pd.",
|
||||
install_command=("brew", "install", "i2pd"),
|
||||
)
|
||||
|
||||
with patch("ampbrowser.cli.transport_status", return_value=result):
|
||||
with patch.object(sys, "stdout", new_callable=io.StringIO) as stdout:
|
||||
code = main(["transport", "status", "i2p"])
|
||||
|
||||
self.assertEqual(0, code)
|
||||
output = stdout.getvalue()
|
||||
self.assertIn('install_command="brew install i2pd"', output)
|
||||
self.assertIn('setup_hint="Install i2pd with Homebrew: brew install i2pd."', output)
|
||||
|
||||
def test_transport_repair_command_prints_result(self) -> None:
|
||||
result = ManagedTransportResult(
|
||||
transport="tor",
|
||||
provider="arti",
|
||||
status="repaired",
|
||||
endpoint="socks5://127.0.0.1:9050",
|
||||
owned=True,
|
||||
pid=1234,
|
||||
state_dir=".ampb/transports/tor",
|
||||
command=("/tmp/arti", "proxy"),
|
||||
message="removed AMPB-owned tor runtime state",
|
||||
provider_source="bundled-sidecar",
|
||||
)
|
||||
|
||||
with patch("ampbrowser.cli.repair_managed_transport", return_value=result) as repair:
|
||||
with patch.object(sys, "stdout", new_callable=io.StringIO) as stdout:
|
||||
code = main(["transport", "repair", "tor"])
|
||||
|
||||
self.assertEqual(0, code)
|
||||
repair.assert_called_once()
|
||||
output = stdout.getvalue()
|
||||
self.assertIn("status=repaired", output)
|
||||
self.assertIn("provider=arti", output)
|
||||
self.assertIn('message="removed AMPB-owned tor runtime state"', output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -180,10 +180,12 @@ class PrepareOpenTest(unittest.TestCase):
|
||||
background = (extension / "background.js").read_text(encoding="utf-8")
|
||||
setup = (extension / "setup.html").read_text(encoding="utf-8")
|
||||
self.assertIn("webNavigation", manifest)
|
||||
self.assertIn("install_command", background)
|
||||
self.assertIn("http://127.0.0.1:", background)
|
||||
self.assertNotIn("__AMPB_ROUTE_HELPER_URL__", background)
|
||||
self.assertNotIn("__AMPB_ROUTE_HELPER_TOKEN__", background)
|
||||
self.assertIn("Set Up Transport", setup)
|
||||
self.assertIn("install-command", setup)
|
||||
|
||||
def test_execute_open_blocks_when_runtime_is_missing(self) -> None:
|
||||
config = AppConfig(runtime_path="/missing/ampb/firefox", transport_modes={})
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
PRIVATE_TARGET_TERMS = (
|
||||
"wowrace",
|
||||
"wowngeon",
|
||||
"smirk-monorepo",
|
||||
"medusa-multi-tenant-platform",
|
||||
"ai-gen-bot",
|
||||
)
|
||||
|
||||
|
||||
class PublicPrivateSplitTest(unittest.TestCase):
|
||||
def test_private_target_names_do_not_appear_in_public_docs(self) -> None:
|
||||
failures = []
|
||||
for path in sorted(ROOT.rglob("*.md")):
|
||||
rel = path.relative_to(ROOT)
|
||||
if rel.parts[0] in {".git", "docs"} and "private" in rel.parts:
|
||||
continue
|
||||
if "docs" in rel.parts and "generated" in rel.parts:
|
||||
continue
|
||||
text = path.read_text(encoding="utf-8").lower()
|
||||
for term in PRIVATE_TARGET_TERMS:
|
||||
if term in text:
|
||||
failures.append(f"{rel}: contains private target term {term!r}")
|
||||
self.assertEqual([], failures)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -51,6 +51,8 @@ class RouteHelperTest(unittest.TestCase):
|
||||
command=("/opt/i2pd",),
|
||||
message="started managed i2pd transport",
|
||||
provider_source="system-package",
|
||||
setup_hint="Install i2pd with Homebrew: brew install i2pd.",
|
||||
install_command=("brew", "install", "i2pd"),
|
||||
)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
@@ -64,6 +66,8 @@ class RouteHelperTest(unittest.TestCase):
|
||||
self.assertTrue(response["ok"])
|
||||
self.assertTrue(response["ready"])
|
||||
self.assertEqual("started", response["status"])
|
||||
self.assertEqual("Install i2pd with Homebrew: brew install i2pd.", response["setup_hint"])
|
||||
self.assertEqual(["brew", "install", "i2pd"], response["install_command"])
|
||||
ensure.assert_called_once()
|
||||
|
||||
def test_blocks_unsupported_routes(self) -> None:
|
||||
|
||||
@@ -6,7 +6,7 @@ import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from ampbrowser.config import AppConfig
|
||||
from ampbrowser.transport_manager import ensure_transport_ready, stop_managed_transport, transport_status
|
||||
from ampbrowser.transport_manager import ensure_transport_ready, repair_managed_transport, stop_managed_transport, transport_status
|
||||
from ampbrowser.transports import TransportStatus
|
||||
|
||||
|
||||
@@ -181,6 +181,51 @@ class TransportManagerTest(unittest.TestCase):
|
||||
self.assertEqual("arti", result.provider)
|
||||
self.assertFalse(state_path.exists())
|
||||
|
||||
def test_repair_managed_transport_removes_runtime_state(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
root = Path(tmp)
|
||||
state_dir = root / ".ampb/transports/tor"
|
||||
profile_dir = root / ".ampb/profiles/tor"
|
||||
state_dir.mkdir(parents=True)
|
||||
profile_dir.mkdir(parents=True)
|
||||
state_path = state_dir / "ampb-owned.json"
|
||||
state_path.write_text('{"pid": 1234, "provider": "arti", "endpoint": "socks5://127.0.0.1:9050"}\n', encoding="utf-8")
|
||||
(state_dir / "arti.log").write_text("warn\n", encoding="utf-8")
|
||||
(profile_dir / "user.js").write_text("prefs\n", encoding="utf-8")
|
||||
|
||||
live = [True]
|
||||
|
||||
def fake_alive(pid: int) -> bool:
|
||||
return live[0]
|
||||
|
||||
def fake_kill(pid: int, sig: int) -> None:
|
||||
live[0] = False
|
||||
|
||||
with patch("ampbrowser.transport_manager._pid_alive", side_effect=fake_alive):
|
||||
with patch("ampbrowser.transport_manager.os.kill", side_effect=fake_kill):
|
||||
result = repair_managed_transport("tor", config=AppConfig(transport_modes={}), root=root)
|
||||
|
||||
self.assertEqual("repaired", result.status)
|
||||
self.assertFalse(state_dir.exists())
|
||||
self.assertTrue((profile_dir / "user.js").exists())
|
||||
self.assertIn("runtime state", result.message)
|
||||
|
||||
def test_repair_managed_transport_blocks_when_stop_fails(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
root = Path(tmp)
|
||||
state_dir = root / ".ampb/transports/tor"
|
||||
state_dir.mkdir(parents=True)
|
||||
state_path = state_dir / "ampb-owned.json"
|
||||
state_path.write_text('{"pid": 1234, "provider": "arti", "endpoint": "socks5://127.0.0.1:9050"}\n', encoding="utf-8")
|
||||
|
||||
with patch("ampbrowser.transport_manager._pid_alive", return_value=True):
|
||||
with patch("ampbrowser.transport_manager.os.kill", side_effect=OSError("nope")):
|
||||
result = repair_managed_transport("tor", config=AppConfig(transport_modes={}), root=root)
|
||||
|
||||
self.assertEqual("repair-blocked", result.status)
|
||||
self.assertTrue(state_path.exists())
|
||||
self.assertIn("could not repair", result.message)
|
||||
|
||||
def test_starts_configured_classic_tor_provider_with_ampb_state(self) -> None:
|
||||
status = TransportStatus(
|
||||
transport="tor",
|
||||
@@ -270,14 +315,16 @@ class TransportManagerTest(unittest.TestCase):
|
||||
)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
with patch("ampbrowser.transport_manager.shutil.which", return_value=None):
|
||||
with patch("ampbrowser.transport_manager._bundled_i2pd_path", return_value=""):
|
||||
result = ensure_transport_ready("i2p", config=AppConfig(transport_modes={}), root=Path(tmp), status=status)
|
||||
with patch("ampbrowser.transport_manager.sys.platform", "darwin"):
|
||||
with patch("ampbrowser.transport_manager.shutil.which", return_value=None):
|
||||
with patch("ampbrowser.transport_manager._bundled_i2pd_path", return_value=""):
|
||||
result = ensure_transport_ready("i2p", config=AppConfig(transport_modes={}), root=Path(tmp), status=status)
|
||||
|
||||
self.assertEqual("missing-provider", result.status)
|
||||
self.assertFalse(result.ready)
|
||||
self.assertIn("I2P provider not found", result.message)
|
||||
self.assertIn("brew install i2pd", result.message)
|
||||
self.assertIn("brew install i2pd", result.setup_hint)
|
||||
self.assertEqual(("brew", "install", "i2pd"), result.install_command)
|
||||
|
||||
def test_finds_homebrew_i2pd_provider_when_not_on_path(self) -> None:
|
||||
status = TransportStatus(
|
||||
|
||||
Reference in New Issue
Block a user