Files
6krrt/tests/test_dispatcher_helpers.py
adlee-was-taken 7d9988caf3 test: make the HTTP fakes exercise the boundary instead of modelling it
The mojibake in 8518114 survived a green suite, and not by omission. There
is a test called `test_a_stream_is_proxied_verbatim_including_the_telemetry
_comments` which passed for months against a proxy that was decoding the
stream as ISO-8859-1 and re-encoding it as UTF-8. It asserted three ASCII
substrings, and a test that only ever sees ASCII cannot observe a charset
bug.

Two separate lies, both now fixed.

The fakes. `iter_lines` yielded `self._lines` unchanged in both modes, so a
test holding str lines got those str back even under decode_unicode -- a
model of a stream that had ALREADY been decoded correctly. A fake that
hands back the right answer cannot reproduce a decode bug. They now treat
the wire as UTF-8 bytes whatever the test wrote, derive `encoding` from
Content-Type using requests' own `get_encoding_from_headers`, and default
to the charset-less `text/event-stream` OpenRouter really sends. The
hostile case is the default, so a broken passthrough can no longer look
correct.

The assertions. The verbatim test now compares BYTES against every line the
provider emitted, and the shared STREAM_LINES sample carries a raw UTF-8 em
dash, so the whole streaming surface fails if the proxy ever goes back to
decoding and re-encoding.

Measured, by reverting 8518114 and running the suite:

    before this commit   1 test caught it (the one written for it)
    after                2, incl. the verbatim test that had been lying

The dedicated regression test also gets simpler -- it no longer needs a
bespoke response subclass, because the shared fake is now faithful enough.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRQXz5SYZYVWscxS1QqF6U
2026-09-08 14:05:16 -04:00

235 lines
8.5 KiB
Python

"""Unit tests for the new availability/relevance helpers in dispatcher.py.
Offline. Mocks ``requests.post`` so no model/network is reached. Covers the
fail-safe ``_embed_for_relevance``, the min_candidates/disabled gates in
``_relevance_order_for``, the circuit-breaker exclusion set ``_open_circuits``,
and the connection-opening helper ``_open_upstream``.
"""
from __future__ import annotations
import dispatcher
import circuit_breaker
class _FakeResp:
def __init__(self, status_code=200, text="", json_payload=None, lines=None):
self.status_code = status_code
self._text = text
self._json = json_payload
self._lines = lines or []
self.closed = False
@property
def text(self):
return self._text
def json(self):
if self._json is None:
raise ValueError("no json")
return self._json
def close(self):
self.closed = True
@property
def encoding(self):
"""The charset requests would pick, by requests' own rule.
Derived rather than asserted, so this fake tracks requests instead of
restating a belief about it. The default is a charset-less
``text/event-stream`` on purpose: that is what OpenRouter actually
sends, and `get_encoding_from_headers` answers ISO-8859-1 for any
``text/*`` without a charset. Decoding a UTF-8 stream with that and
re-encoding it produced mojibake on every streamed non-ASCII
character -- so the hostile case is the DEFAULT here, and a fake can
no longer make a broken passthrough look correct.
"""
from requests.structures import CaseInsensitiveDict
from requests.utils import get_encoding_from_headers
headers = CaseInsensitiveDict(
getattr(self, "headers", None) or {"Content-Type": "text/event-stream"}
)
return get_encoding_from_headers(headers) or "utf-8"
def iter_lines(self, decode_unicode=False):
# Faithful to requests in both modes: BYTES unless decode_unicode is
# set, and when it is set the charset comes from Content-Type.
#
# The `wire` line is the load-bearing one. Whatever a test wrote into
# `lines`, what a provider actually puts on the wire is UTF-8 bytes,
# so that is what gets decoded. An earlier version of this fake passed
# str lines straight through under decode_unicode, which modelled a
# stream that had ALREADY been decoded correctly -- and a fake that
# hands back the right answer cannot reproduce a charset bug. It let
# the whole streaming suite pass against a proxy that was mangling
# every non-ASCII character.
for line in self._lines:
wire = line.encode("utf-8") if isinstance(line, str) else line
yield wire.decode(self.encoding) if decode_unicode else wire
def _cfg_with_relevance(enabled=True, min_candidates=2):
class _Rel:
enabled = True
model = "nomic-embed-text"
base_url = "http://localhost:11434/v1"
timeout_seconds = 10
min_candidates = 2
if not enabled:
_Rel.enabled = False
if min_candidates != 2:
_Rel.min_candidates = min_candidates
class _Pinch:
enabled = True
keep_last_turns = 1
budget_tokens = 100
max_summarize_chars = 4000
relevance = _Rel()
class _CB:
enabled = False
class _Cfg:
pinch = _Pinch()
circuit_breaker = _CB()
return _Cfg()
def _embedding_data(n_vectors, dim=4):
data = []
for i in range(n_vectors):
vec = [0.0] * dim
vec[i % dim] = 1.0
data.append({"embedding": vec, "index": i})
return data
def test_embed_for_relevance_happy_path_returns_order(monkeypatch):
captured = {}
def fake_post(url, headers=None, json=None, timeout=None):
captured["json"] = json
# Return vectors: query (idx0), candidate0 = same as query (most
# relevant), candidate1 = orthogonal (least relevant).
payload = {
"data": [
{"embedding": [1.0, 0.0, 0.0, 0.0]},
{"embedding": [1.0, 0.0, 0.0, 0.0]},
{"embedding": [0.0, 1.0, 0.0, 0.0]},
]
}
return _FakeResp(status_code=200, json_payload=payload)
monkeypatch.setattr(dispatcher.requests, "post", fake_post)
order = dispatcher._embed_for_relevance("hi", ["a", "b"], _cfg_with_relevance())
# candidate1 (b) is least relevant, so it is compressed first -> index 1.
assert order == [1, 0]
assert captured["json"]["model"] == "nomic-embed-text"
def test_embed_for_relevance_failure_paths_return_none(monkeypatch):
cases = [
_FakeResp(status_code=500, text="err"), # non-200
_FakeResp(status_code=200), # unparseable (no json)
_FakeResp(status_code=200, json_payload={"data": None}), # malformed
_FakeResp(status_code=200, json_payload={"data": [{"embedding": []}]}),
]
for resp in cases:
monkeypatch.setattr(dispatcher.requests, "post", lambda *a, _r=resp, **k: _r)
assert dispatcher._embed_for_relevance("q", ["a"], _cfg_with_relevance()) is None
def test_embed_for_relevance_request_exception_returns_none(monkeypatch):
def boom(*a, **k):
raise dispatcher.requests.RequestException("timeout")
monkeypatch.setattr(dispatcher.requests, "post", boom)
assert dispatcher._embed_for_relevance("q", ["a"], _cfg_with_relevance()) is None
def test_relevance_order_for_returns_none_when_disabled():
cfg = _cfg_with_relevance(enabled=False)
assert dispatcher._relevance_order_for([], cfg, budget_tokens=100) is None
def test_relevance_order_for_below_min_candidates_skips_embedding(monkeypatch):
called = {"n": 0}
def fake_post(*a, **k):
called["n"] += 1
return _FakeResp(status_code=200, json_payload={"data": None})
monkeypatch.setattr(dispatcher.requests, "post", fake_post)
cfg = _cfg_with_relevance(enabled=True, min_candidates=2)
# One candidate only -> below min_candidates -> no embed call.
messages = [
{"role": "user", "content": "q"},
{"role": "tool", "name": "read", "content": "x" * 6000},
{"role": "assistant", "content": "a"},
]
assert dispatcher._relevance_order_for(messages, cfg, budget_tokens=100) is None
assert called["n"] == 0
def test_relevance_order_for_skips_embedding_when_under_budget(monkeypatch):
called = {"n": 0}
def fake_post(*a, **k):
called["n"] += 1
return _FakeResp(status_code=200, json_payload={"data": None})
monkeypatch.setattr(dispatcher.requests, "post", fake_post)
cfg = _cfg_with_relevance(enabled=True, min_candidates=2)
# Two short tool-results -> token estimate under budget -> no embed call.
messages = [
{"role": "user", "content": "q"},
{"role": "tool", "name": "read", "content": "short"},
{"role": "tool", "name": "read", "content": "also short"},
{"role": "assistant", "content": "a"},
]
assert dispatcher._relevance_order_for(messages, cfg, budget_tokens=50000) is None
assert called["n"] == 0
def test_open_circuits_empty_when_disabled():
cfg = _cfg_with_relevance()
cfg.circuit_breaker.enabled = False
rows = [{"model_id": "m1", "provider": "p1"}]
assert dispatcher._open_circuits(rows, cfg) == set()
def test_open_circuits_lists_down_models(monkeypatch):
cfg = _cfg_with_relevance()
cfg.circuit_breaker.enabled = True
circuit_breaker.clear()
try:
monkeypatch.setattr(circuit_breaker.time, "time", lambda: 1000.0)
circuit_breaker.record_failure("m1", "p1", 30, 600, 2.0)
rows = [
{"model_id": "m1", "provider": "p1"}, # down
{"model_id": "m2", "provider": "p1"}, # fine
]
assert dispatcher._open_circuits(rows, cfg) == {"m1"}
finally:
circuit_breaker.clear()
def test_open_upstream_posts_stream_with_candidate_model(monkeypatch):
captured = {}
def fake_post(url, headers=None, json=None, stream=None, timeout=None):
captured["model"] = json["model"]
captured["stream"] = stream
return _FakeResp(status_code=200)
monkeypatch.setattr(dispatcher.requests, "post", fake_post)
dispatcher._open_upstream("candidate-model", "http://x", {"authorization": "Bearer k"},
{"model": "ignore", "messages": []})
assert captured["model"] == "candidate-model"
assert captured["stream"] is True