From 355c8ae57d582974f4f6a4ba42f635f2253b84a7 Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Fri, 6 Nov 2026 14:24:04 +0100 Subject: Add a wall clock helper so that statedumps can be written and re-read --- tests/integration/test_statefile.py | 43 ++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 20 deletions(-) (limited to 'tests/integration/test_statefile.py') diff --git a/tests/integration/test_statefile.py b/tests/integration/test_statefile.py index 21eefae..a3c8d59 100644 --- a/tests/integration/test_statefile.py +++ b/tests/integration/test_statefile.py @@ -1,12 +1,12 @@ """The state dump and the -l switch that reads it back. -Nothing exercised the load path before, and the dump's second column is now -how long ago a torrent was last touched rather than when, because the clock -counts from boot and an absolute stamp would mean nothing to the process -that reads the file. +The second column is the minute a torrent was last touched, by the wall +clock, which is what the file has recorded for years and the only clock two +runs of the tracker agree on. """ import os +import time import unittest from harness import Tracker, TrackerTestCase @@ -54,23 +54,26 @@ class StateFileRoundTrip(TrackerTestCase): restarted._cleanup() -class StateFileWithNonsenseAges(TrackerTestCase): - """The age column is read as unsigned and handed on as a signed ot_time. - A value at or above 2^63 arrived negative, cleared the timeout check, and +class StateFileWithNonsenseStamps(TrackerTestCase): + """The column is read as unsigned and handed on as a signed ot_time. A + value at or above 2^63 arrived negative, cleared the timeout check, and put the torrent's base in the future, where the cleaner never reaches it. At exactly 2^63 the subtraction itself overflowed.""" - AGES = { - "overflow": 2**63, - "wrapped": 2**63 + 60 * 24, - "minus-one": 2**64 - 1, - "int64-max": 2**63 - 1, - "past-timeout": 60 * 24 + 1, - } - - def test_no_age_outside_the_timeout_builds_a_torrent(self): - lines = ["%s:%d:7" % (self.hash_for(name).hex(), age) for name, age in self.AGES.items()] - lines.append("%s:5:7" % self.hash_for("honest").hex()) + def stamps(self): + now = int(time.time()) // 60 + return { + "overflow": 2**63, + "minus-one": 2**64 - 1, + "int64-max": 2**63 - 1, + "in-the-future": now + 60, + "past-timeout": now - (24 * 60 + 1), + } + + def test_no_stamp_outside_the_timeout_builds_a_torrent(self): + stamps = self.stamps() + lines = ["%s:%d:7" % (self.hash_for(name).hex(), stamp) for name, stamp in stamps.items()] + lines.append("%s:%d:7" % (self.hash_for("honest").hex(), int(time.time()) // 60 - 5)) path = os.path.join(self.tracker.dir, "nonsense") with open(path, "w") as handle: @@ -78,9 +81,9 @@ class StateFileWithNonsenseAges(TrackerTestCase): restarted = Tracker(extra_args=["-l", path]) try: - for name in self.AGES: + for name, stamp in stamps.items(): self.assertNotIn(self.hash_for(name), restarted.scrape(self.hash_for(name))[b"files"], - "the line with age %d was loaded" % self.AGES[name]) + "the line stamped %d was loaded" % stamp) self.assertIn(self.hash_for("honest"), restarted.scrape(self.hash_for("honest"))[b"files"], "the state file was not read at all") self.assertEqual(restarted.torrent_count(), 1) -- cgit v1.3