| 1 | """Tests for the token-estimate calibration classifier."""
|
| 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 | import token_calibration
|
| 13 |
|
| 14 |
|
| 15 | class CompositionTest(unittest.TestCase):
|
| 16 | def test_classes_partition_the_text(self) -> None:
|
| 17 | text = "commit 4f2a9c8be1d34f7a line 42, words here!\n"
|
| 18 | counts = token_calibration.classify_chars(text)
|
| 19 | self.assertEqual(sum(counts.values()), len(text))
|
| 20 |
|
| 21 | def test_hex_runs_detected(self) -> None:
|
| 22 | counts = token_calibration.classify_chars("deadbeefcafe1234")
|
| 23 | self.assertEqual(counts["hex_run"], 16)
|
| 24 |
|
| 25 |
|
| 26 | class BiasDirectionTest(unittest.TestCase):
|
| 27 | """Pins the HEURISTIC path: optional enhancers (tiktoken, ADR-0001) must
|
| 28 | not flip test behavior depending on what happens to be installed, so
|
| 29 | exact_tokens is forced off. Direction claims under a real tokenizer are
|
| 30 | asserted separately in TokenizerBiasDirectionTest."""
|
| 31 |
|
| 32 | def factor(self, sample_name: str) -> float:
|
| 33 | text = token_calibration.SELF_TEST_SAMPLES[sample_name]
|
| 34 | original = token_calibration.exact_tokens
|
| 35 | token_calibration.exact_tokens = lambda _text: (None, None)
|
| 36 | try:
|
| 37 | result = token_calibration.analyze_text(sample_name, text)
|
| 38 | finally:
|
| 39 | token_calibration.exact_tokens = original
|
| 40 | return result["calibration_factor_vs_char_div_4"]
|
| 41 |
|
| 42 | def test_hash_heavy_underestimated_by_char_div_4(self) -> None:
|
| 43 | # factor > 1 means char/4 UNDERESTIMATES; hash-heavy log output is the
|
| 44 | # worst case and the reason cross-subject token deltas need calibration.
|
| 45 | self.assertGreater(self.factor("hash_heavy_log"), 1.3)
|
| 46 |
|
| 47 | def test_prose_close_to_char_div_4(self) -> None:
|
| 48 | self.assertLess(self.factor("prose_readme"), 1.0)
|
| 49 | self.assertGreater(self.factor("prose_readme"), 0.8)
|
| 50 |
|
| 51 | def test_diff_between_the_two(self) -> None:
|
| 52 | self.assertGreater(self.factor("git_diff_like"), 1.0)
|
| 53 | self.assertLess(self.factor("git_diff_like"), self.factor("hash_heavy_log"))
|
| 54 |
|
| 55 |
|
| 56 | class TokenizerBiasDirectionTest(unittest.TestCase):
|
| 57 | """Direction-only claims when a real tokenizer is present; skipped
|
| 58 | otherwise. Bounds are loose on purpose — exact values are calibration
|
| 59 | output, not test fixtures."""
|
| 60 |
|
| 61 | def setUp(self) -> None:
|
| 62 | exact, _ = token_calibration.exact_tokens("probe")
|
| 63 | if exact is None:
|
| 64 | self.skipTest("tiktoken not installed")
|
| 65 |
|
| 66 | def factor(self, sample_name: str) -> float:
|
| 67 | text = token_calibration.SELF_TEST_SAMPLES[sample_name]
|
| 68 | return token_calibration.analyze_text(sample_name, text)["calibration_factor_vs_char_div_4"]
|
| 69 |
|
| 70 | def test_hash_heavy_still_underestimated(self) -> None:
|
| 71 | self.assertGreater(self.factor("hash_heavy_log"), 1.0)
|
| 72 |
|
| 73 | def test_prose_not_underestimated(self) -> None:
|
| 74 | self.assertLess(self.factor("prose_readme"), 1.0)
|
| 75 |
|
| 76 | def test_ordering_preserved(self) -> None:
|
| 77 | self.assertLess(self.factor("prose_readme"), self.factor("git_diff_like"))
|
| 78 | self.assertLess(self.factor("git_diff_like"), self.factor("hash_heavy_log"))
|
| 79 |
|
| 80 |
|
| 81 | class AggregateTest(unittest.TestCase):
|
| 82 | def test_aggregate_reports_method_honestly(self) -> None:
|
| 83 | results = [
|
| 84 | token_calibration.analyze_text(name, text)
|
| 85 | for name, text in token_calibration.SELF_TEST_SAMPLES.items()
|
| 86 | ]
|
| 87 | aggregate = token_calibration.aggregate(results, label="self-test")
|
| 88 | self.assertEqual(aggregate["samples"], 3)
|
| 89 | self.assertIn(aggregate["method"], {"exact_tokenizer", "mixed", "composition_heuristic"})
|
| 90 | self.assertIsNotNone(aggregate["calibration_factor_vs_char_div_4"])
|
| 91 |
|
| 92 |
|
| 93 | if __name__ == "__main__":
|
| 94 | unittest.main()
|