From ab9c1719eec0a3d0cd9a81c40d29671a8e646a4d Mon Sep 17 00:00:00 2001 From: theater <1347507191@qq.com> Date: Sun, 6 Sep 2026 10:10:08 +0800 Subject: [PATCH] fix(tests): make test_list_by_thread independent of host clock granularity (#5210) test_list_by_thread creates two runs back-to-back and expects the newer one to sort first under list_by_thread's newest-first ordering. That relies on the wall clock advancing between the two create() calls. On Windows, datetime.now() has a coarse granularity (~15.6 ms), so both runs can receive an identical created_at. Python's stable sort then keeps insertion order and the assertion fails; on this host 50 consecutive now_iso() calls return identical strings. Drive the clock with a controlled 1 ms-per-call fake (same monkeypatch pattern as test_list_by_thread_is_stable_when_timestamps_tie) so the strictly-newer assumption no longer depends on the host clock. The tie case stays covered by the existing dedicated test. Co-authored-by: Willem Jiang --- backend/tests/test_run_manager.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/backend/tests/test_run_manager.py b/backend/tests/test_run_manager.py index 61abacef7..750017cd5 100644 --- a/backend/tests/test_run_manager.py +++ b/backend/tests/test_run_manager.py @@ -1,9 +1,11 @@ """Tests for RunManager.""" import asyncio +import itertools import logging import re import sqlite3 +from datetime import UTC, datetime, timedelta from typing import Any import pytest @@ -616,8 +618,18 @@ async def test_cancel_not_inflight(manager: RunManager): @pytest.mark.anyio -async def test_list_by_thread(manager: RunManager): +async def test_list_by_thread(manager: RunManager, monkeypatch: pytest.MonkeyPatch): """Same thread should return multiple runs.""" + # Advance the fake clock 1ms per call so r2 gets a strictly newer + # created_at than r1 even on hosts with coarse wall-clock granularity + # (Windows timestamps can repeat across consecutive creates). + base = datetime.now(UTC) + calls = itertools.count() + monkeypatch.setattr( + "deerflow.runtime.runs.manager._now_iso", + lambda: (base + timedelta(milliseconds=next(calls))).isoformat(), + ) + r1 = await manager.create("thread-1") r2 = await manager.create("thread-1") await manager.create("thread-2")