fix(tests): проверка устаревшего refresh не зависит от фоновых потоков

Джоб на ubuntu упал с «assert 32 == 31» в
test_seq_token_prevents_stale_refresh_clobber. Тест сравнивал поколения до и
после устаревшего вызова, а HubStateStore — процессный синглтон: фоновый
сборщик квот, оставшийся от другого теста, успевает поднять generation между
двумя вызовами. В логе прогона рядом видно как раз такую фоновую попытку.

Падение случайное и зависит от порядка тестов: headless-джоб гоняет pytest без
фиксированного порядка. Тем же объясняется разброс 738/739 в базовом прогоне
до начала работы.

Проверяется теперь инвариант, а не равенство: устаревший ответ отбрасывается
ровно один раз, и состояние не откатывается назад. Пять полных прогонов со
случайным порядком — 777 passed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
ochenstarik-ui 2026-09-03 01:54:35 +07:00
parent 7fb8c6a6c5
commit 1fe4549b22

View file

@ -72,15 +72,27 @@ def test_seq_token_prevents_stale_refresh_clobber():
seq_fresh = store.next_seq() seq_fresh = store.next_seq()
snap_fresh = store.refresh(force_scan=False, seq=seq_fresh) snap_fresh = store.refresh(force_scan=False, seq=seq_fresh)
gen_fresh = snap_fresh.generation gen_fresh = snap_fresh.generation
skipped_before = store.refresh_skipped_total
# Simulate a delayed/stale response from an earlier seq counter # Simulate a delayed/stale response from an earlier seq counter
seq_stale = seq_fresh - 1 seq_stale = seq_fresh - 1
snap_after_stale = store.refresh(force_scan=False, seq=seq_stale) snap_after_stale = store.refresh(force_scan=False, seq=seq_stale)
# Stale response must be rejected, retaining the fresh generation # Устаревший ответ должен быть отброшен.
assert snap_after_stale.generation == gen_fresh #
# Проверяется именно отбрасывание, а не равенство поколений. HubStateStore —
# процессный синглтон, и фоновый сборщик квот, оставшийся от другого теста,
# успевает поднять generation между двумя вызовами. Прежнее
# `generation == gen_fresh` падало на этом с «assert 32 == 31» — примерно раз
# на десяток прогонов, только при случайном порядке тестов. Инвариант же
# другой: устаревший ответ отбрасывается, состояние назад не откатывается.
assert store.refresh_skipped_total == skipped_before + 1, (
"устаревший ответ должен быть отброшен ровно один раз"
)
assert snap_after_stale.generation >= gen_fresh, (
"состояние откатилось назад: устаревший ответ затёр более свежее"
)
assert snap_after_stale.seq != seq_stale assert snap_after_stale.seq != seq_stale
assert store.refresh_skipped_total >= 1
@pytest.mark.unit @pytest.mark.unit