Files
agent-orchestrator-benchmark/calculators/builder-adversary-stateless/run-03/calc/test_lexer.py

127 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Unit tests for calc.lexer — covers D1D3."""
import unittest
from calc.lexer import tokenize, Token, LexError
def kinds(src: str) -> list[str]:
return [t.kind for t in tokenize(src)]
def values(src: str) -> list:
return [t.value for t in tokenize(src)]
class TestNumbers(unittest.TestCase):
def test_integer(self):
toks = tokenize("42")
self.assertEqual(toks, [Token("NUMBER", 42), Token("EOF", None)])
self.assertIsInstance(toks[0].value, int)
def test_float_standard(self):
toks = tokenize("3.14")
self.assertEqual(len(toks), 2)
self.assertEqual(toks[0].kind, "NUMBER")
self.assertAlmostEqual(toks[0].value, 3.14)
self.assertIsInstance(toks[0].value, float)
def test_float_leading_dot(self):
toks = tokenize(".5")
self.assertEqual(toks[0].kind, "NUMBER")
self.assertAlmostEqual(toks[0].value, 0.5)
self.assertIsInstance(toks[0].value, float)
def test_float_trailing_dot(self):
toks = tokenize("10.")
self.assertEqual(toks[0].kind, "NUMBER")
self.assertAlmostEqual(toks[0].value, 10.0)
self.assertIsInstance(toks[0].value, float)
def test_zero(self):
toks = tokenize("0")
self.assertEqual(toks[0], Token("NUMBER", 0))
class TestOperatorsAndParens(unittest.TestCase):
def test_plus(self):
self.assertIn("PLUS", kinds("1+2"))
def test_minus(self):
self.assertIn("MINUS", kinds("1-2"))
def test_star(self):
self.assertIn("STAR", kinds("1*2"))
def test_slash(self):
self.assertIn("SLASH", kinds("1/2"))
def test_lparen(self):
self.assertIn("LPAREN", kinds("(1)"))
def test_rparen(self):
self.assertIn("RPAREN", kinds("(1)"))
def test_expr_kinds(self):
self.assertEqual(
kinds("1+2*3"),
["NUMBER", "PLUS", "NUMBER", "STAR", "NUMBER", "EOF"],
)
def test_eof_always_last(self):
for src in ["", "1", "1+2", "()"]:
self.assertEqual(tokenize(src)[-1].kind, "EOF")
class TestWhitespaceAndErrors(unittest.TestCase):
def test_spaces_between_tokens(self):
self.assertEqual(
kinds(" 12 + 3 "),
["NUMBER", "PLUS", "NUMBER", "EOF"],
)
toks = tokenize(" 12 + 3 ")
self.assertEqual(toks[0].value, 12)
self.assertEqual(toks[2].value, 3)
def test_tabs_skipped(self):
self.assertEqual(kinds("\t1\t+\t2\t"), ["NUMBER", "PLUS", "NUMBER", "EOF"])
def test_complex_expr(self):
self.assertEqual(
kinds("3.5*(1-2)"),
["NUMBER", "STAR", "LPAREN", "NUMBER", "MINUS", "NUMBER", "RPAREN", "EOF"],
)
toks = tokenize("3.5*(1-2)")
self.assertAlmostEqual(toks[0].value, 3.5)
self.assertEqual(toks[3].value, 1)
self.assertEqual(toks[5].value, 2)
def test_invalid_at_raises(self):
with self.assertRaises(LexError):
tokenize("1 @ 2")
def test_invalid_dollar_raises(self):
with self.assertRaises(LexError):
tokenize("$")
def test_invalid_letter_raises(self):
with self.assertRaises(LexError):
tokenize("a")
def test_lex_error_message_contains_char(self):
try:
tokenize("1 @ 2")
self.fail("LexError not raised")
except LexError as e:
self.assertIn("@", str(e))
def test_lex_error_message_contains_position(self):
try:
tokenize("1 @ 2")
self.fail("LexError not raised")
except LexError as e:
self.assertIn("2", str(e))
if __name__ == "__main__":
unittest.main()