Viewing files at commit b297e8a25d08Commit detailsView latest

Browse files
tests/test_rows.py 152 lines · 5.5 KB · python
1
"""Tests for the row contract: accessors and per-lane validation."""
2
3
from __future__ import annotations
4
5
import sys
6
from pathlib import Path
7
8
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts"))
9
10
import unittest
11
12
from oakbench.rows import (
13
    number_or_none,
14
    output_bytes,
15
    output_truncated,
16
    token_total,
17
    tool_calls,
18
    validate_rows,
19
)
20
21
22
class TokenTotalTest(unittest.TestCase):
23
    def test_provider_reported_wins(self) -> None:
24
        row = {
25
            "token_metrics": {"total_tokens_reported": 1234, "transcript_chars": 999999},
26
            "estimated_tokens_total": 7,
27
        }
28
        self.assertEqual(token_total(row), 1234.0)
29
30
    def test_reported_parts_summed(self) -> None:
31
        row = {
32
            "token_metrics": {
33
                "total_tokens_reported": None,
34
                "input_tokens_reported": 100,
35
                "output_tokens_reported": 40,
36
                "reasoning_tokens_reported": None,
37
            }
38
        }
39
        self.assertEqual(token_total(row), 140.0)
40
41
    def test_flat_estimate(self) -> None:
42
        self.assertEqual(token_total({"estimated_tokens_total": 88}), 88.0)
43
44
    def test_char_fallback(self) -> None:
45
        row = {"token_metrics": {"total_tokens_reported": None, "transcript_chars": 401}}
46
        self.assertEqual(token_total(row), 101.0)
47
48
    def test_no_signal_is_none(self) -> None:
49
        self.assertIsNone(token_total({"operation": "proc.spawn"}))
50
51
    def test_non_finite_and_boolean_numbers_are_unmeasured(self) -> None:
52
        for value in (True, "nan", "inf", float("nan"), float("inf")):
53
            with self.subTest(value=value):
54
                self.assertIsNone(number_or_none(value))
55
                self.assertIsNone(token_total({"estimated_tokens_total": value}))
56
                self.assertIsNone(output_bytes({"raw_output_bytes": value}))
57
58
59
class OtherAccessorsTest(unittest.TestCase):
60
    def test_tool_calls_paths(self) -> None:
61
        self.assertEqual(tool_calls({"tool_call_count": 3}), 3.0)
62
        self.assertEqual(tool_calls({"tool_calls": {"total": 5}}), 5.0)
63
        self.assertEqual(tool_calls({"tool_call_metrics": {"tool_calls_total": 9}}), 9.0)
64
        self.assertIsNone(tool_calls({}))
65
66
    def test_output_bytes_paths(self) -> None:
67
        self.assertEqual(output_bytes({"raw_output_bytes": 10}), 10.0)
68
        self.assertEqual(output_bytes({"stdout_bytes": 4, "stderr_bytes": 6}), 10.0)
69
        self.assertEqual(output_bytes({"token_estimate": {"stdout_bytes": 7, "stderr_bytes": 3}}), 10.0)
70
        self.assertIsNone(output_bytes({}))
71
72
    def test_output_truncated(self) -> None:
73
        self.assertTrue(output_truncated({"output_truncated": True}))
74
        self.assertTrue(output_truncated({"token_estimate": {"stderr_truncated": True}}))
75
        self.assertFalse(output_truncated({}))
76
77
78
def minimal_core_row(**overrides) -> dict:
79
    row = {
80
        "bench_id": "20260610T000000Z",
81
        "profile": "smoke",
82
        "scenario": "tiny_text",
83
        "operation": "status.clean",
84
        "run": 0,
85
        "subject": "git",
86
        "subject_kind": "git",
87
        "elapsed_ms": 1.5,
88
        "returncode": 0,
89
        "command": ["git", "status", "--short"],
90
    }
91
    row.update(overrides)
92
    return row
93
94
95
class LaneValidationTest(unittest.TestCase):
96
    def test_valid_core_row(self) -> None:
97
        self.assertEqual(validate_rows([minimal_core_row()], "core"), [])
98
99
    def test_missing_key_flagged(self) -> None:
100
        row = minimal_core_row()
101
        del row["elapsed_ms"]
102
        errors = validate_rows([row], "core")
103
        self.assertEqual(len(errors), 1)
104
        self.assertIn("elapsed_ms", errors[0])
105
106
    def test_type_checks(self) -> None:
107
        errors = validate_rows([minimal_core_row(elapsed_ms="fast")], "core")
108
        self.assertTrue(any("must be numeric" in error for error in errors))
109
        errors = validate_rows([minimal_core_row(returncode=True)], "core")
110
        self.assertTrue(any("must be an integer" in error for error in errors))
111
112
    def test_elapsed_ms_rejects_bool_negative_and_non_finite(self) -> None:
113
        for value in (True, -1.0, float("nan"), float("inf")):
114
            with self.subTest(value=value):
115
                errors = validate_rows([minimal_core_row(elapsed_ms=value)], "core")
116
                self.assertTrue(any("elapsed_ms" in error for error in errors))
117
118
    def test_unknown_lane(self) -> None:
119
        errors = validate_rows([], "warp")
120
        self.assertEqual(len(errors), 1)
121
        self.assertIn("unknown lane", errors[0])
122
123
    def test_contention_lane_requires_mode_and_workers(self) -> None:
124
        row = minimal_core_row()
125
        errors = validate_rows([row], "contention")
126
        joined = "\n".join(errors)
127
        self.assertIn("contention_mode", joined)
128
        self.assertIn("workers", joined)
129
130
    def test_optional_provenance_fields_are_type_checked(self) -> None:
131
        row = minimal_core_row(
132
            runner_id="abc123",
133
            runner_class="macos-apple-silicon",
134
            runner_profile={"system": "Darwin"},
135
            fixture_id="large-mixed-v1",
136
            fixture_seed="seed",
137
            binary_sha256="0" * 64,
138
            env_isolation_version="1",
139
        )
140
        self.assertEqual(validate_rows([row], "core"), [])
141
        errors = validate_rows(
142
            [minimal_core_row(runner_profile="not-object", runner_id=7, env_isolation_version=1)],
143
            "core",
144
        )
145
        joined = "\n".join(errors)
146
        self.assertIn("runner_profile", joined)
147
        self.assertIn("runner_id", joined)
148
        self.assertIn("env_isolation_version", joined)
149
150
151
if __name__ == "__main__":
152
    unittest.main()