diff --git a/tests/source/recorder.py b/tests/source/recorder.py index 531d5fe..9fbab4c 100644 --- a/tests/source/recorder.py +++ b/tests/source/recorder.py @@ -229,19 +229,32 @@ def first_sync_config(owner: str, name: str) -> TrackingConfig: async def record_first_sync( - token: str, owner: str, name: str, *, inner: httpx.AsyncBaseTransport | None = None + token: str, + owner: str, + name: str, + *, + inner: httpx.AsyncBaseTransport | None = None, + clock: Clock | None = None, ) -> list[Unit]: """Run a first sync of ``owner/name`` into a scratch database through the recording transport; every unit it asked for. A private repository is refused after the sync's resolve (its label pages included) and before any other request; a failed item or a run that does not - exit 0 stops it too.""" + exit 0 stops it too. + + ``clock`` is the run's clock, the system clock by default. A replay of recorded units passes a + fixed one: the sync's 24-hour refresh measures each account from its recorded ``Date``, so on + the system clock a replay asks for lookups the recording does not hold once a day has + passed.""" _refuse_listed(owner, name) + run_clock = clock or SystemClock() recorded_at = datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ") recording = RecordingTransport(inner or httpx.AsyncHTTPTransport(), recorded_at) opened: list[PublicOnlySource] = [] def open_source(deadline: datetime | None) -> PublicOnlySource: - opened.append(PublicOnlySource(token, http_transport=recording, deadline=deadline)) + opened.append( + PublicOnlySource(token, http_transport=recording, clock=run_clock, deadline=deadline) + ) return opened[-1] config = first_sync_config(owner, name) @@ -256,7 +269,7 @@ def open_source(deadline: datetime | None) -> PublicOnlySource: code_version="recorder", ), open_source=open_source, - clock=SystemClock(), + clock=run_clock, ) # The engine fails the run on the refusal, before the index. refused = [source.refused for source in opened if source.refused is not None] diff --git a/tests/source/test_recorder.py b/tests/source/test_recorder.py index e06566d..af89084 100644 --- a/tests/source/test_recorder.py +++ b/tests/source/test_recorder.py @@ -125,7 +125,9 @@ async def test_a_listed_private_repository_is_never_requested(owner: str, name: with pytest.raises(PrivateRepository): await record("test-token", inner=replay.transport(), scenarios=scenarios) with pytest.raises(PrivateRepository): - await record_first_sync("test-token", owner, name, inner=replay.transport()) + await record_first_sync( + "test-token", owner, name, inner=replay.transport(), clock=FakeClock() + ) assert replay.seen == [] @@ -278,7 +280,9 @@ async def test_recording_a_first_sync_of_its_recordings_gives_them_back() -> Non """The first sync asks for exactly the recorded units, and records each as it was.""" replay = Replay.from_directory(FIRST_SYNC) owner, name = FIRST_SYNC_REPOSITORY - units = await record_first_sync("test-token", owner, name, inner=replay.transport()) + units = await record_first_sync( + "test-token", owner, name, inner=replay.transport(), clock=FakeClock() + ) assert replay.problems == [] # One resolve, the sync's own: the resolution the privacy check reads is the one it uses. assert [seen.operation for seen in replay.seen] == [ @@ -306,7 +310,9 @@ async def test_a_private_repository_stops_a_first_sync_after_its_resolve() -> No unit.data["isPrivate"] = True replay.add(unit) with pytest.raises(PrivateRepository, match=f"{owner}/{name}"): - await record_first_sync("test-token", owner, name, inner=replay.transport()) + await record_first_sync( + "test-token", owner, name, inner=replay.transport(), clock=FakeClock() + ) assert [seen.operation for seen in replay.seen] == ["Resolve"] @@ -318,7 +324,9 @@ async def test_a_retried_item_records_one_unit_per_file(first_sync: bool) -> Non replay.modify(_batch_alias_error, when=lambda seen: seen.operation == "PullRequestBatch") if first_sync: owner, name = FIRST_SYNC_REPOSITORY - units = await record_first_sync("test-token", owner, name, inner=replay.transport()) + units = await record_first_sync( + "test-token", owner, name, inner=replay.transport(), clock=FakeClock() + ) else: units = await record("test-token", inner=replay.transport()) batches = [seen.numbers for seen in replay.seen if seen.operation == "PullRequestBatch"] @@ -371,7 +379,9 @@ async def test_a_first_sync_that_fails_names_why( change(replay) owner, name = FIRST_SYNC_REPOSITORY with pytest.raises(RecordingFailed) as raised: - await record_first_sync("test-token", owner, name, inner=replay.transport()) + await record_first_sync( + "test-token", owner, name, inner=replay.transport(), clock=FakeClock() + ) assert str(raised.value) == message assert [seen.operation for seen in replay.seen] == ["Resolve"] @@ -383,13 +393,17 @@ async def test_a_first_sync_that_does_not_exit_0_stops_the_recording() -> None: ) owner, name = FIRST_SYNC_REPOSITORY with pytest.raises(RecordingFailed, match="first sync exited 2"): - await record_first_sync("test-token", owner, name, inner=replay.transport()) + await record_first_sync( + "test-token", owner, name, inner=replay.transport(), clock=FakeClock() + ) def _first_sync_units() -> list[Any]: owner, name = FIRST_SYNC_REPOSITORY replay = Replay.from_directory(FIRST_SYNC) - return asyncio.run(record_first_sync("test-token", owner, name, inner=replay.transport())) + return asyncio.run( + record_first_sync("test-token", owner, name, inner=replay.transport(), clock=FakeClock()) + ) @pytest.mark.parametrize("oversized", [False, True])