mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-05 08:07:05 +00:00
* wip * refactor(tests): move sdk function tracing into rust python harness * dead code * fix: handle harness keyboard interrupts * refactor(tests): deduplicate rust python harness helpers * fix(harness): expose validated strategy choices * wip * refactor(harness): let strategies own parity reports * docs(harness): update strategy structure * refactor(harness): localize strategy report views * wip * fix(harness): satisfy mapping runner type checks * fix(harness): clarify trace parity output * wip * fix(harness): clarify unit mapping report * fix(harness): finalize trace parity contracts * refactor(harness): structure parity contracts * feat: derive unit test mapping from traces * feat(harness): map rstest test families * feat(ocr): port Azure document intelligence tests * feat(harness): enforce complete unit mappings * feat(ocr): add reducto core transforms * feat(harness): classify host-only unit tests * fix(ocr): complete Rust provider plumbing * fix(harness): reuse OCR parity workers
157 lines
6.4 KiB
Python
157 lines
6.4 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Final
|
|
|
|
import pytest
|
|
|
|
from .profiler import FunctionTraceEvent
|
|
from .steps import Engine, TraceContract, mapping, pipeline_projection, trace_depths, trace_diff
|
|
|
|
MAPPINGS: Final = (
|
|
mapping(rust_span="route", python_frame=r"entry$"),
|
|
mapping(rust_span="provider", python_frame=r"provider$"),
|
|
mapping(rust_span="request", python_frame=r"request$"),
|
|
mapping(rust_span="http", python_frame=r"post$"),
|
|
mapping(rust_span="response", python_frame=r"response$"),
|
|
)
|
|
|
|
|
|
def event(event_id: int, function: str, parent_id: int | None = None) -> FunctionTraceEvent:
|
|
return FunctionTraceEvent(event_id, parent_id, function)
|
|
|
|
|
|
def test_python_projection_collapses_unmapped_parents_and_counts_noise() -> None:
|
|
events: Final = (
|
|
event(0, "module.py:1 entry"),
|
|
event(1, "noise", 0),
|
|
event(2, "module.py:2 provider", 1),
|
|
event(3, "module.py:3 request", 0),
|
|
event(4, "client.py:4 post", 3),
|
|
event(5, "module.py:5 response", 0),
|
|
)
|
|
projection: Final = pipeline_projection("python", events, MAPPINGS)
|
|
assert projection.unmatched == 1
|
|
assert [(step.id, step.parent_id, step.span, step.raw) for step in projection.steps] == [
|
|
(0, None, "route", "module.py:1 entry"),
|
|
(2, 0, "provider", "module.py:2 provider"),
|
|
(3, 0, "request", "module.py:3 request"),
|
|
(4, 3, "http", "client.py:4 post"),
|
|
(5, 0, "response", "module.py:5 response"),
|
|
]
|
|
|
|
|
|
def test_rust_projection_keeps_unknown_spans() -> None:
|
|
projection: Final = pipeline_projection("rust", (event(0, "route"), event(1, "new_span", 0)), MAPPINGS)
|
|
assert [(step.span, step.parent_id) for step in projection.steps] == [("route", None), ("new_span", 0)]
|
|
|
|
|
|
def test_projection_preserves_repeated_occurrences() -> None:
|
|
projection: Final = pipeline_projection(
|
|
"rust",
|
|
(event(0, "route"), event(1, "http", 0), event(2, "http", 0)),
|
|
MAPPINGS,
|
|
)
|
|
assert [step.span for step in projection.steps] == ["route", "http", "http"]
|
|
|
|
|
|
def test_projection_preserves_multiple_roots() -> None:
|
|
projection: Final = pipeline_projection("rust", (event(0, "route"), event(1, "request")), MAPPINGS)
|
|
assert trace_depths(projection.steps) == {0: 0, 1: 0}
|
|
|
|
|
|
def test_projection_rejects_duplicate_and_unknown_parent_ids() -> None:
|
|
with pytest.raises(ValueError, match="duplicate trace event id"):
|
|
pipeline_projection("rust", (event(0, "route"), event(0, "request")), MAPPINGS)
|
|
with pytest.raises(ValueError, match="unknown or later parent"):
|
|
pipeline_projection("rust", (event(1, "request", 0),), MAPPINGS)
|
|
|
|
|
|
@pytest.mark.parametrize("engine", ("python", "rust"))
|
|
def test_rust_only_mappings_do_not_swallow_python_frames(engine: Engine) -> None:
|
|
projection: Final = pipeline_projection(
|
|
engine,
|
|
(event(0, "anything"),),
|
|
(mapping(rust_span="rust_only_span"),),
|
|
)
|
|
if engine == "python":
|
|
assert projection.unmatched == 1
|
|
assert projection.steps == ()
|
|
else:
|
|
assert projection.unmatched == 0
|
|
assert projection.steps[0].span == "anything"
|
|
|
|
|
|
def test_mapping_builder_rejects_empty_and_ambiguous_declarations() -> None:
|
|
with pytest.raises(ValueError, match="mapping needs"):
|
|
mapping()
|
|
with pytest.raises(ValueError, match="python-only mapping needs"):
|
|
mapping(python_frame=r"frame$")
|
|
with pytest.raises(ValueError, match="disagrees with"):
|
|
mapping(rust_span="span_a", python_frame=r"frame$", span="span_b")
|
|
|
|
|
|
def test_projection_rejects_ambiguous_python_mapping() -> None:
|
|
mappings: Final = (
|
|
mapping(rust_span="first", python_frame=r"same$"),
|
|
mapping(rust_span="second", python_frame=r"same$"),
|
|
)
|
|
with pytest.raises(ValueError, match="multiple trace mappings"):
|
|
pipeline_projection("python", (event(0, "module.py:1 same"),), mappings)
|
|
|
|
|
|
def test_trace_diff_matches_identical_occurrence_trees() -> None:
|
|
mappings: Final = (MAPPINGS[0], MAPPINGS[2])
|
|
steps: Final = pipeline_projection(
|
|
"rust", (event(0, "route"), event(1, "request", 0), event(2, "request", 0)), mappings
|
|
).steps
|
|
assert trace_diff(steps, steps, mappings).matches
|
|
|
|
|
|
def test_trace_diff_rejects_missing_occurrence_and_parent_drift() -> None:
|
|
python: Final = pipeline_projection(
|
|
"rust", (event(0, "route"), event(1, "request", 0), event(2, "request", 0)), MAPPINGS
|
|
).steps
|
|
missing: Final = pipeline_projection("rust", (event(0, "route"), event(1, "request", 0)), MAPPINGS).steps
|
|
reparented: Final = pipeline_projection(
|
|
"rust", (event(0, "route"), event(1, "request", 0), event(2, "request", 1)), MAPPINGS
|
|
).steps
|
|
assert trace_diff(python, missing, MAPPINGS).python_only == ("request",)
|
|
assert not trace_diff(python, reparented, MAPPINGS).matches
|
|
|
|
|
|
def test_trace_diff_rejects_sequential_reorder() -> None:
|
|
first: Final = pipeline_projection(
|
|
"rust", (event(0, "route"), event(1, "request", 0), event(2, "response", 0)), MAPPINGS
|
|
).steps
|
|
second: Final = pipeline_projection(
|
|
"rust", (event(0, "route"), event(1, "response", 0), event(2, "request", 0)), MAPPINGS
|
|
).steps
|
|
diff: Final = trace_diff(first, second, MAPPINGS)
|
|
assert not diff.matches
|
|
assert diff.first_difference == "root/child[1]/route/child[1]: Python='request', Rust='response'"
|
|
|
|
|
|
def test_trace_diff_allows_reordered_concurrent_children() -> None:
|
|
mappings: Final = (MAPPINGS[0], MAPPINGS[2], MAPPINGS[4])
|
|
first: Final = pipeline_projection(
|
|
"rust", (event(0, "route"), event(1, "request", 0), event(2, "response", 0)), mappings
|
|
).steps
|
|
second: Final = pipeline_projection(
|
|
"rust", (event(0, "route"), event(1, "response", 0), event(2, "request", 0)), mappings
|
|
).steps
|
|
contract: Final = TraceContract(frozenset({"route"}))
|
|
assert trace_diff(first, second, mappings, contract).matches
|
|
|
|
|
|
def test_trace_diff_prunes_declared_engine_only_nodes_but_requires_them() -> None:
|
|
mappings: Final = (MAPPINGS[0], mapping(rust_span="rust_prepare"))
|
|
python: Final = pipeline_projection("python", (event(0, "module.py:1 entry"),), mappings).steps
|
|
rust: Final = pipeline_projection(
|
|
"rust", (event(0, "route"), event(1, "rust_prepare", 0)), mappings
|
|
).steps
|
|
assert trace_diff(python, rust, mappings).matches
|
|
assert trace_diff(python, rust[:1], mappings).missing_mappings == ("rust_prepare",)
|
|
|
|
|
|
def test_trace_diff_does_not_claim_empty_traces_match() -> None:
|
|
assert not trace_diff((), ()).matches
|