Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions tests/test_graph_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from __future__ import annotations

import hashlib
import os
import time
from datetime import UTC, datetime
from typing import Any
Expand Down Expand Up @@ -686,10 +687,18 @@ async def test_fuzzy_match_via_mock_store(self):


class TestFuzzyMatchPerformance:
"""Benchmark fuzzy_match_entities: must complete in <500ms for 10K entities."""
"""Benchmark fuzzy_match_entities: guard against algorithmic regressions.

The bound exists to catch order-of-magnitude blowups (e.g. an accidental
O(n^2) rewrite), not to be a precise benchmark. Shared CI runners are
slower and noisier than dev machines (this test failed at 636ms on a
GitHub runner with code that runs in ~200ms locally), so:
- take the best of 3 runs to damp scheduler/CPU-frequency noise
- relax the budget 3x when CI is set (GitHub Actions sets CI=true)
"""

@pytest.mark.asyncio
async def test_fuzzy_match_10k_under_500ms(self):
async def test_fuzzy_match_10k_perf_budget(self):
store = MockGraphStore()
# Seed 10K entities with synthetic names
entities = [
Expand All @@ -698,12 +707,17 @@ async def test_fuzzy_match_10k_under_500ms(self):
]
await store.batch_upsert_entities(entities)

t0 = time.monotonic()
results = await store.fuzzy_match_entities("Entity_05000_F", threshold=0.9)
elapsed_ms = (time.monotonic() - t0) * 1000

assert elapsed_ms < 500, (
f"fuzzy_match_entities took {elapsed_ms:.0f}ms for 10K entities (must be <500ms)"
best_ms = float("inf")
results: list[Any] = []
for _ in range(3):
t0 = time.monotonic()
results = await store.fuzzy_match_entities("Entity_05000_F", threshold=0.9)
best_ms = min(best_ms, (time.monotonic() - t0) * 1000)

limit_ms = 1500 if os.environ.get("CI") else 500
assert best_ms < limit_ms, (
f"fuzzy_match_entities took {best_ms:.0f}ms (best of 3) for 10K entities "
f"(must be <{limit_ms}ms)"
)
# Should find at least the exact or near-exact match
assert len(results) >= 1
Expand Down
9 changes: 5 additions & 4 deletions web/src/components/settings/__tests__/AgentModelsTab.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,13 +189,14 @@ describe("AgentModelsTab", () => {
fireEvent.click(screen.getByText("Gemini balanced"));

// CI runners are slower than local — the toast lands after the POST
// returns + a setState flush. The inner waitFor needs 5000ms headroom,
// so the outer test budget must exceed it (default vitest is 5000ms).
// returns + a setState flush. 5000ms was not enough headroom (failed at
// 5082ms on a GitHub runner on 2026-06-01); give the inner waitFor 10s
// and keep the outer test budget above it.
await waitFor(
() => expect(screen.getByText(/Applied 'Gemini balanced' — 1 updated/)).toBeTruthy(),
{ timeout: 5000 },
{ timeout: 10000 },
);
}, 15000);
}, 20000);

it("a vision-required consumer with a no-vision model shows the red capability badge", async () => {
const fetchMock = vi.mocked(globalThis.fetch);
Expand Down
Loading