mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-10-26 05:06:59 +00:00
test(sandbox): make prewarm clock regression deterministic (#7513)
This commit is contained in:
parent
885062e197
commit
00678f060b
@ -18,6 +18,10 @@ ownership and capture cleanup. Retain the real XLSX conversion coverage.
|
||||
|
||||
Backend tests must preserve the runtime invariants they exercise without changing production execution topology.
|
||||
|
||||
`test_bench_sandbox_prewarm.py` controls observation timestamps through the
|
||||
benchmark module's clock binding. Keep asyncio's clock real, initialize
|
||||
`Trace.started` from the controlled clock, and advance ticks at event gates.
|
||||
|
||||
`test_doctor_script.py` runs a copied doctor from a temporary checkout with an
|
||||
empty-model config. Drop inherited `DEER_FLOW_*`, `PYTHONPATH` and `PYTHONHOME`
|
||||
from child processes; cover help, invalid flags, normal reporting and an
|
||||
|
||||
@ -4,9 +4,7 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import math
|
||||
import threading
|
||||
import time
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
@ -141,43 +139,33 @@ async def test_real_graph_prewarm_starts_during_model_and_is_claimed_once(observ
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_prewarm_reused_survives_a_coarse_clock_tie(observed, monkeypatch):
|
||||
"""Pin #7044: a same-tick acquire/tool timestamp must not unclassify a reused lease.
|
||||
|
||||
Coarse monotonic clocks (Windows, ~15.6 ms granularity) can quantize the
|
||||
prewarm acquire and the tool request into the same tick; the former strict
|
||||
`<` classification then dropped the genuine prewarm from the speculative
|
||||
set. Event-state capture must keep it classified as speculative.
|
||||
"""
|
||||
@pytest.mark.parametrize("tool_tick_offset", [0.0, 0.015], ids=["same-tick", "next-tick"])
|
||||
async def test_prewarm_reused_uses_event_order_with_coarse_clock(observed, monkeypatch, tool_tick_offset: float):
|
||||
"""Pin #7044: prewarm classification follows event order, even when timestamps tie."""
|
||||
provider, config = observed
|
||||
coarse_s = 0.015
|
||||
real_monotonic = time.monotonic
|
||||
|
||||
def coarse_monotonic():
|
||||
return math.floor(real_monotonic() / coarse_s) * coarse_s
|
||||
|
||||
monkeypatch.setattr(bench.time, "monotonic", coarse_monotonic)
|
||||
# Spin until a fresh quantized bucket starts, so the whole overlap scenario
|
||||
# lands inside the same tick deterministically.
|
||||
current_bucket = coarse_monotonic()
|
||||
while coarse_monotonic() == current_bucket:
|
||||
await asyncio.sleep(0.001)
|
||||
tick = 100.0
|
||||
# Isolate the benchmark's observation clock; asyncio timeouts keep real time.
|
||||
monkeypatch.setattr(bench, "time", SimpleNamespace(monotonic=lambda: tick))
|
||||
|
||||
model_gate = asyncio.Event()
|
||||
trace = bench.Trace()
|
||||
trace = bench.Trace(started=tick)
|
||||
task = asyncio.create_task(bench.run_case(provider, config, case="tool", prewarm=True, model_delay=0, thread_id="coarse-tick", user_id="alice", trace=trace, model_gate=model_gate))
|
||||
try:
|
||||
await asyncio.wait_for(trace.model_started.wait(), 2)
|
||||
await asyncio.wait_for(provider.started.wait(), 2)
|
||||
provider.finish.set()
|
||||
await asyncio.wait_for(trace.acquire_ready.wait(), 2)
|
||||
# Advance only at this event boundary, independently of scheduler delays.
|
||||
tick += tool_tick_offset
|
||||
model_gate.set()
|
||||
row = await asyncio.wait_for(task, 3)
|
||||
finally:
|
||||
provider.finish.set()
|
||||
model_gate.set()
|
||||
await asyncio.gather(task, return_exceptions=True)
|
||||
assert trace.acquisitions[0]["started"] == trace.timestamps["tool_requested"], "precondition: the acquire and the tool request must share one quantized tick"
|
||||
assert trace.acquisitions[0]["started"] == trace.started
|
||||
assert trace.timestamps["tool_requested"] == trace.started + tool_tick_offset
|
||||
assert trace.acquisitions[0]["precedes_tool_request"] is True
|
||||
assert row["success"], json.dumps(row)
|
||||
assert row["acquire_calls"] == 1
|
||||
assert row["prewarm_reused"] is True
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user