aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_init.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_init.py')
-rw-r--r--tests/test_init.py138
1 files changed, 138 insertions, 0 deletions
diff --git a/tests/test_init.py b/tests/test_init.py
index 619d6ba..46b1a26 100644
--- a/tests/test_init.py
+++ b/tests/test_init.py
@@ -59,6 +59,144 @@ class TestBuildConfig(unittest.TestCase):
"cases": 'x" \ntrusted_relays = ["0.0.0.0/0"]\n#'})
+class TestReporterSection(unittest.TestCase):
+ def test_the_identity_becomes_a_reporter_table(self):
+ text = init.build({
+ "trusted_relays": ["192.0.2.0/24"],
+ "reporter_name": "A Reporter",
+ "reporter_org": "Example Ltd",
+ "reporter_email": "abuse@example.org",
+ })
+ parsed = tomllib.loads(text)
+ self.assertEqual(parsed["reporter"], {
+ "name": "A Reporter",
+ "org": "Example Ltd",
+ "email": "abuse@example.org",
+ })
+
+ def test_a_fully_skipped_identity_emits_no_table_at_all(self):
+ # Not an empty [reporter]: an empty table reads as configured, and
+ # the reader would then report an identity of nothing rather than
+ # saying plainly that none is set.
+ text = init.build({
+ "trusted_relays": ["192.0.2.0/24"],
+ "reporter_name": "",
+ "reporter_org": "",
+ "reporter_email": "",
+ })
+ self.assertNotIn("[reporter]", text)
+ self.assertNotIn("reporter", tomllib.loads(text))
+
+ def test_a_skipped_answer_is_absent_not_empty(self):
+ # Same rule as the cases path: "" reads as configured-and-broken.
+ text = init.build({
+ "trusted_relays": ["192.0.2.0/24"],
+ "reporter_name": "A Reporter",
+ "reporter_org": "",
+ "reporter_email": " ",
+ })
+ reporter = tomllib.loads(text)["reporter"]
+ self.assertEqual(reporter, {"name": "A Reporter"})
+
+ def test_values_are_written_stripped(self):
+ # config.load() strips on read, so writing unstripped would make the
+ # file disagree with what every consumer sees.
+ text = init.build({
+ "trusted_relays": ["192.0.2.0/24"],
+ "reporter_name": " A Reporter ",
+ })
+ self.assertEqual(tomllib.loads(text)["reporter"]["name"], "A Reporter")
+
+ def test_a_quote_in_an_identity_cannot_break_out_of_the_toml(self):
+ with self.assertRaises(ValueError):
+ init.build({
+ "trusted_relays": ["192.0.2.0/24"],
+ "reporter_name": 'x"\nemail = "attacker@example.invalid"',
+ })
+
+ def test_the_identity_loads_back_through_config(self):
+ # The seam report.build() consumes: what init writes must arrive as
+ # the dict shape the reader hands over, keys and all.
+ with tempfile.TemporaryDirectory() as tmp:
+ path = pathlib.Path(tmp) / "config.toml"
+ path.write_text(init.build({
+ "trusted_relays": ["192.0.2.0/24"],
+ "reporter_name": "A Reporter",
+ "reporter_org": "Example Ltd",
+ "reporter_email": "abuse@example.org",
+ }), encoding="utf-8")
+ self.assertEqual(config.load(path).reporter, {
+ "name": "A Reporter",
+ "org": "Example Ltd",
+ "email": "abuse@example.org",
+ })
+
+ def test_a_partial_identity_loads_back_with_only_what_was_given(self):
+ with tempfile.TemporaryDirectory() as tmp:
+ path = pathlib.Path(tmp) / "config.toml"
+ path.write_text(init.build({
+ "trusted_relays": ["192.0.2.0/24"],
+ "reporter_email": "abuse@example.org",
+ }), encoding="utf-8")
+ self.assertEqual(config.load(path).reporter,
+ {"email": "abuse@example.org"})
+
+
+class TestReporterCarryAcross(unittest.TestCase):
+ def test_an_identity_set_by_hand_survives_a_relays_only_rewrite(self):
+ # AGENTS.md: sections build() does not produce are carried across
+ # verbatim. Skipping all three answers must not delete an identity
+ # the user set earlier; there would be no warning that it went.
+ with tempfile.TemporaryDirectory() as tmp:
+ path = pathlib.Path(tmp) / "config.toml"
+ path.write_text(
+ '[general]\ntrusted_relays = ["10.0.0.0/8"]\n\n'
+ '[reporter]\nname = "A Reporter"\nemail = "abuse@example.org"\n',
+ encoding="utf-8",
+ )
+ init.write(path, {"trusted_relays": ["192.0.2.0/24"]}, force=True)
+ self.assertEqual(config.load(path).reporter,
+ {"name": "A Reporter", "email": "abuse@example.org"})
+
+ def test_a_new_identity_replaces_the_old_one_without_duplicating_it(self):
+ # A section the builder DOES produce must not also be carried across:
+ # two [reporter] tables in one file is not merely untidy, tomllib
+ # refuses the whole file and the config becomes unreadable.
+ with tempfile.TemporaryDirectory() as tmp:
+ path = pathlib.Path(tmp) / "config.toml"
+ path.write_text(
+ '[general]\ntrusted_relays = ["10.0.0.0/8"]\n\n'
+ '[reporter]\nname = "Old Name"\n',
+ encoding="utf-8",
+ )
+ init.write(path, {
+ "trusted_relays": ["192.0.2.0/24"],
+ "reporter_name": "New Name",
+ }, force=True)
+
+ self.assertEqual(path.read_text().count("[reporter]"), 1)
+ self.assertEqual(config.load(path).reporter, {"name": "New Name"})
+
+ def test_an_unrelated_section_still_survives_alongside_an_identity(self):
+ with tempfile.TemporaryDirectory() as tmp:
+ path = pathlib.Path(tmp) / "config.toml"
+ path.write_text(
+ '[general]\ntrusted_relays = ["10.0.0.0/8"]\n\n'
+ '[reporter]\nname = "Old Name"\n\n'
+ '[misp]\napi_key = "kept"\n',
+ encoding="utf-8",
+ )
+ init.write(path, {
+ "trusted_relays": ["192.0.2.0/24"],
+ "reporter_name": "New Name",
+ }, force=True)
+
+ rewritten = path.read_text()
+ self.assertIn("kept", rewritten)
+ self.assertNotIn("Old Name", rewritten)
+ self.assertEqual(config.load(path).reporter, {"name": "New Name"})
+
+
class TestProviderTable(unittest.TestCase):
def test_a_known_provider_resolves_to_ranges(self):
self.assertTrue(init.provider_relays("gmail"))