Enhance replication check, matching pattern, logging in dump comparator (#19677)
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import json
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
from sglang.srt.debug_utils.comparator.log_sink import LogSink
|
||||
from sglang.srt.debug_utils.comparator.output_types import (
|
||||
ErrorLog,
|
||||
InfoLog,
|
||||
report_sink,
|
||||
)
|
||||
from sglang.test.ci.ci_register import register_cpu_ci
|
||||
|
||||
register_cpu_ci(est_time=10, suite="default", nightly=True)
|
||||
|
||||
|
||||
def _make_error_log(**overrides) -> ErrorLog:
|
||||
defaults: dict = dict(
|
||||
category="test",
|
||||
message="test warning",
|
||||
)
|
||||
defaults.update(overrides)
|
||||
return ErrorLog(**defaults)
|
||||
|
||||
|
||||
class TestLogSink:
|
||||
def test_basic_collection(self) -> None:
|
||||
sink = LogSink()
|
||||
log = _make_error_log()
|
||||
|
||||
with sink.context() as collected:
|
||||
sink.add(log)
|
||||
|
||||
assert len(collected) == 1
|
||||
assert collected[0] is log
|
||||
|
||||
def test_nested_contexts(self) -> None:
|
||||
sink = LogSink()
|
||||
outer_log = _make_error_log(message="outer")
|
||||
inner_log = _make_error_log(message="inner")
|
||||
|
||||
with sink.context() as outer:
|
||||
sink.add(outer_log)
|
||||
with sink.context() as inner:
|
||||
sink.add(inner_log)
|
||||
assert len(inner) == 1
|
||||
assert inner[0] is inner_log
|
||||
|
||||
assert len(outer) == 1
|
||||
assert outer[0] is outer_log
|
||||
|
||||
def test_empty_context(self) -> None:
|
||||
sink = LogSink()
|
||||
with sink.context() as collected:
|
||||
pass
|
||||
assert collected == []
|
||||
|
||||
def test_add_outside_context_prints(self, capsys) -> None:
|
||||
sink = LogSink()
|
||||
report_sink.configure(output_format="text")
|
||||
|
||||
sink.add(_make_error_log())
|
||||
|
||||
captured = capsys.readouterr()
|
||||
assert "test warning" in captured.out
|
||||
|
||||
def test_context_captures_instead_of_printing(self, capsys) -> None:
|
||||
sink = LogSink()
|
||||
report_sink.configure(output_format="text")
|
||||
|
||||
with sink.context() as collected:
|
||||
sink.add(_make_error_log())
|
||||
|
||||
assert len(collected) == 1
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == ""
|
||||
|
||||
def test_json_output_outside_context(self, capsys) -> None:
|
||||
sink = LogSink()
|
||||
report_sink.configure(output_format="json")
|
||||
|
||||
sink.add(_make_error_log())
|
||||
|
||||
captured = capsys.readouterr()
|
||||
parsed: dict = json.loads(captured.out.strip())
|
||||
assert "errors" in parsed
|
||||
assert len(parsed["errors"]) == 1
|
||||
|
||||
def test_info_log_outside_context_routes_to_infos(self, capsys) -> None:
|
||||
"""InfoLog added outside context populates LogRecord.infos, not errors."""
|
||||
sink = LogSink()
|
||||
report_sink.configure(output_format="json")
|
||||
|
||||
sink.add(InfoLog(category="test", message="info msg"))
|
||||
|
||||
parsed: dict = json.loads(capsys.readouterr().out.strip())
|
||||
assert len(parsed["infos"]) == 1
|
||||
assert len(parsed["errors"]) == 0
|
||||
|
||||
def test_exception_in_context_cleans_stack(self, capsys) -> None:
|
||||
sink = LogSink()
|
||||
report_sink.configure(output_format="text")
|
||||
|
||||
with pytest.raises(RuntimeError):
|
||||
with sink.context() as collected:
|
||||
sink.add(_make_error_log())
|
||||
raise RuntimeError("boom")
|
||||
|
||||
assert len(collected) == 1
|
||||
|
||||
sink.add(_make_error_log(message="after exception"))
|
||||
captured = capsys.readouterr()
|
||||
assert "after exception" in captured.out
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(pytest.main([__file__]))
|
||||
Reference in New Issue
Block a user