From ef942b93d1e9bfc28bf607dfaf501cc7d9685e7b Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Thu, 24 Sep 2026 17:42:10 +0200 Subject: test(node): read the daemon's source wherever it is split Tests that read daemon.py now take their text from node_source (daemon.py, NodeDaemon's bases, the cli package once it exists). The CLI tests that sliced main() run the CLI instead. Co-Authored-By: Claude Opus 5.5 --- .../tests/test_root_paths_are_operator_only.py | 44 ++++++++++++++++------ 1 file changed, 32 insertions(+), 12 deletions(-) (limited to 'packages/meshbay-node/tests/test_root_paths_are_operator_only.py') diff --git a/packages/meshbay-node/tests/test_root_paths_are_operator_only.py b/packages/meshbay-node/tests/test_root_paths_are_operator_only.py index 0e89afa..a18e9fa 100644 --- a/packages/meshbay-node/tests/test_root_paths_are_operator_only.py +++ b/packages/meshbay-node/tests/test_root_paths_are_operator_only.py @@ -19,6 +19,7 @@ them in the member payload too. import inspect import re +import sys from pathlib import Path from meshbay_node import daemon as daemon_mod @@ -85,21 +86,16 @@ def test_the_loopback_api_asks_for_paths(): "list_groups uses the member form, so every path it reports is missing") -def test_the_cli_only_reads_fields_the_payload_carries(): +def test_the_cli_only_reads_fields_the_payload_carries(monkeypatch, tmp_path, capsys): """ The gap this whole file exists for. The CLI reads a dict and the API returns a dict; nothing between them says which keys are owed, so a name that is simply absent prints as a placeholder and looks like a node problem. - """ - source = inspect.getsource(daemon_mod.main) - start = source.index('if args.command == "root":') - block = source[start:source.index('if args.command == "operator":', start)] - - read = set(re.findall(r"r\.get\(['\"](\w+)['\"]", block)) - read |= set(re.findall(r"r\[['\"](\w+)['\"]\]", block)) - assert read, "the root CLI no longer reads the payload this way" + `root list` is run against a payload that records every key it is asked + for, so this holds wherever the CLI's code lives. + """ class _Any: path = Path("/tmp/x") name = "x" @@ -107,7 +103,31 @@ def test_the_cli_only_reads_fields_the_payload_carries(): writable = removable = ejected = False available = True - offered = set(RootSet(roots=[_Any()]).describe(with_paths=True)[0]) - assert read <= offered, ( + offered = RootSet(roots=[_Any()]).describe(with_paths=True)[0] + read: set[str] = set() + + class _Recording(dict): + def __getitem__(self, key): + read.add(key) + return super().__getitem__(key) + + def get(self, key, default=None): + read.add(key) + return super().get(key, default) + + gid = "g" * 32 + monkeypatch.setattr(daemon_mod, "_daemon_api", lambda cfg, path, **kw: { + "groups": [{"id": gid, "roots": [_Recording(offered)]}]}) + monkeypatch.setattr(daemon_mod, "_resolve_group", lambda cfg, g: gid) + conf = tmp_path / "node.toml" + conf.write_text('[hub]\nurl = "https://example.invalid"\n') + monkeypatch.setattr(daemon_mod, "DEFAULT_CONFIG_PATH", conf) + monkeypatch.setattr(sys, "argv", ["meshbay-node", "root", "list"]) + + daemon_mod.main() + + assert read, "the root CLI no longer reads the payload this way" + assert "/tmp/x" in capsys.readouterr().out + assert read <= set(offered), ( f"the `root` CLI reads keys the loopback payload does not carry: " - f"{sorted(read - offered)}") + f"{sorted(read - set(offered))}") -- cgit v1.2.3