diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-10 10:49:27 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-10 10:49:27 +0200 |
| commit | ae1b825b458d14cc1fa251a56331767d5fcf4ec6 (patch) | |
| tree | 9d6b53a64ee3a987f5f8545c5429491fc4535dec /tests/test_init.py | |
| parent | 37d723f2ffd55dcca141831ee2368b5b49618de8 (diff) | |
| download | abusectl-ae1b825b458d14cc1fa251a56331767d5fcf4ec6.tar.gz abusectl-ae1b825b458d14cc1fa251a56331767d5fcf4ec6.zip | |
fix: stop init duplicating its own preamble on every rewrite
The carry-across preserved every line before the first [table], but that
text is build()'s own header, not the user's. A second init emitted it
twice and a third three times, with [general] missing from the tail half,
so the file grew a copy per run. It still parsed, which is why the suite
stayed green and only a hand test found it.
Preserving from the first table onward fixes the trailing "Later parts"
block too: it trails whichever table came last, so it is already inside a
skipped section. A separate guard for it passed its own mutation check
and was removed as redundant.
Required prompts now say so. The relay question and the hop picker cannot
be skipped, because with no trust boundary parse refuses and init is the
route out, but they read like the reporter questions that do offer a skip.
The cases prompt says "Enter for <default>" rather than showing the
default in brackets, which was the same ambiguity in the other direction.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LByBnw83xr9YP85nskzkyE
Diffstat (limited to 'tests/test_init.py')
| -rw-r--r-- | tests/test_init.py | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/tests/test_init.py b/tests/test_init.py index 46b1a26..4f2042c 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -321,3 +321,30 @@ class TestWriteGuard(unittest.TestCase): if __name__ == "__main__": unittest.main() + + +class TestRepeatedInit(unittest.TestCase): + """build()'s own preamble and footer must not accrete across rewrites. + + Found by hand test, not by the suite: a single rewrite looks fine, and + the file still parses, so only the third run makes it obvious. The + carried text is build()'s, not the user's, so preserving it duplicated + the header once per run. + """ + + def test_the_preamble_and_footer_survive_four_rewrites_exactly_once(self): + answers = {"trusted_relays": ["192.0.2.0/24"], "cases": ""} + with tempfile.TemporaryDirectory() as tmp: + path = pathlib.Path(tmp) / "config.toml" + init.write(path, answers) + path.write_text( + path.read_text() + '\n[misp]\napi_key = "SECRET"\n' + ) + for _ in range(3): + init.write(path, answers, force=True) + + text = path.read_text() + self.assertEqual(text.count("# abusectl configuration."), 1) + self.assertEqual(text.count("# Later parts of abusectl"), 1) + # The unknown section still rides across untouched. + self.assertEqual(tomllib.loads(text)["misp"]["api_key"], "SECRET") |
