summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2026-11-06 08:28:16 +0100
committerDirk Engling <erdgeist@erdgeist.org>2026-11-06 08:28:16 +0100
commit83cd3bb631131a116f024cfacfd687e8c4855fd1 (patch)
treed8d75c1eef9a36ffd77cca825fd8be3df33342a3 /tests
parent96b6ad283bf63ab447a3a974a4cba8c04b01df01 (diff)
Bound what load_state will accept for an age
Diffstat (limited to 'tests')
-rw-r--r--tests/integration/test_statefile.py40
1 files changed, 40 insertions, 0 deletions
diff --git a/tests/integration/test_statefile.py b/tests/integration/test_statefile.py
index 9f6db01..21eefae 100644
--- a/tests/integration/test_statefile.py
+++ b/tests/integration/test_statefile.py
@@ -52,3 +52,43 @@ class StateFileRoundTrip(TrackerTestCase):
52 restarted.stop() 52 restarted.stop()
53 finally: 53 finally:
54 restarted._cleanup() 54 restarted._cleanup()
55
56
57class StateFileWithNonsenseAges(TrackerTestCase):
58 """The age column is read as unsigned and handed on as a signed ot_time.
59 A value at or above 2^63 arrived negative, cleared the timeout check, and
60 put the torrent's base in the future, where the cleaner never reaches it.
61 At exactly 2^63 the subtraction itself overflowed."""
62
63 AGES = {
64 "overflow": 2**63,
65 "wrapped": 2**63 + 60 * 24,
66 "minus-one": 2**64 - 1,
67 "int64-max": 2**63 - 1,
68 "past-timeout": 60 * 24 + 1,
69 }
70
71 def test_no_age_outside_the_timeout_builds_a_torrent(self):
72 lines = ["%s:%d:7" % (self.hash_for(name).hex(), age) for name, age in self.AGES.items()]
73 lines.append("%s:5:7" % self.hash_for("honest").hex())
74
75 path = os.path.join(self.tracker.dir, "nonsense")
76 with open(path, "w") as handle:
77 handle.write("\n".join(lines) + "\n")
78
79 restarted = Tracker(extra_args=["-l", path])
80 try:
81 for name in self.AGES:
82 self.assertNotIn(self.hash_for(name), restarted.scrape(self.hash_for(name))[b"files"],
83 "the line with age %d was loaded" % self.AGES[name])
84 self.assertIn(self.hash_for("honest"), restarted.scrape(self.hash_for("honest"))[b"files"],
85 "the state file was not read at all")
86 self.assertEqual(restarted.torrent_count(), 1)
87 complaints = restarted.stop()
88 self.assertEqual(complaints, [], "the tracker reported:\n" + "\n".join(complaints))
89 finally:
90 restarted._cleanup()
91
92
93if __name__ == "__main__":
94 unittest.main()