| 1 | """Negative controls for all four FEAT-026 extraction findings.""" |
| 2 | import importlib.util |
| 3 | from pathlib import Path |
| 4 | import tempfile |
| 5 | import unittest |
| 6 | |
| 7 | path = Path(__file__).with_name("check-command-session-proof.py") |
| 8 | spec = importlib.util.spec_from_file_location("session_proof", path) |
| 9 | proof = importlib.util.module_from_spec(spec) |
| 10 | spec.loader.exec_module(proof) |
| 11 | |
| 12 | |
| 13 | class SessionProofTests(unittest.TestCase): |
| 14 | def fixture(self, root): |
| 15 | group = root / proof.GROUP |
| 16 | wrapper = root / proof.PROOF |
| 17 | group.parent.mkdir(parents=True) |
| 18 | wrapper.parent.mkdir(parents=True) |
| 19 | group.write_text((proof.ROOT / proof.GROUP).read_text()) |
| 20 | wrapper.write_text((proof.ROOT / proof.PROOF).read_text()) |
| 21 | return group, wrapper |
| 22 | |
| 23 | def test_real_whole_group_is_included(self): |
| 24 | self.assertEqual(proof.violations(proof.ROOT), []) |
| 25 | |
| 26 | def test_selected_leaf_or_stub_is_rejected(self): |
| 27 | for replacement in ['pub mod session {}', '#[path = "structcopy.rs"] pub mod session;']: |
| 28 | with self.subTest(replacement=replacement), tempfile.TemporaryDirectory() as tmp: |
| 29 | root = Path(tmp) |
| 30 | _, wrapper = self.fixture(root) |
| 31 | wrapper.write_text(replacement) |
| 32 | self.assertTrue(proof.violations(root)) |
| 33 | |
| 34 | def test_sibling_action_and_host_registration_are_rejected(self): |
| 35 | for source in ['use crate::tui::app::AppAction;', |
| 36 | 'use crate::commands::traits::ContextualCommand;', |
| 37 | 'use crate::commands::CommandResult;', |
| 38 | 'use codewhale_secrets::sanitize;']: |
| 39 | with self.subTest(source=source), tempfile.TemporaryDirectory() as tmp: |
| 40 | root = Path(tmp) |
| 41 | group, _ = self.fixture(root) |
| 42 | (group.parent / 'new_helper.rs').write_text(source) |
| 43 | self.assertTrue(proof.violations(root)) |
| 44 | |
| 45 | def test_indirect_runtime_and_credential_dependencies_are_rejected(self): |
| 46 | for package in ['codewhale-core', 'codewhale-state', 'codewhale-secrets', |
| 47 | 'codewhale-tui', 'keyring', 'dbus', 'reqwest', 'tokio', 'rusqlite']: |
| 48 | with self.subTest(package=package): |
| 49 | self.assertEqual(len(proof.graph_violations(f'{package} v1.0.0')), 1) |
| 50 | |
| 51 | def test_shared_shapes_and_pure_libraries_are_allowed(self): |
| 52 | self.assertEqual(proof.graph_violations('codewhale-command-contract v0.10.1\ncodewhale-protocol v0.10.1\ncodewhale-sanitize v0.10.1\nserde v1.0.0\nurl v2.5.0'), []) |
| 53 |