Skip to content

Commit 4e1b5fa

Browse files
Mansib RahmanMansib Rahman
authored andcommitted
Added tests for CaseValidator.flag() and ast_analyzer._build_local_param_map fix
1 parent bc4f96e commit 4e1b5fa

1 file changed

Lines changed: 76 additions & 0 deletions

File tree

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"""
2+
Tests for CaseValidator.flag() and ast_analyzer._build_local_param_map fix.
3+
"""
4+
5+
import ast
6+
import unittest
7+
8+
from ..case_validator import CaseValidator
9+
from ..params.ast_analyzer import CaseValidatorAnalyzer
10+
11+
12+
def _param_map(source: str) -> dict:
13+
"""Parse a single method body and return its local-param map."""
14+
wrapped = "class _V:\n" + "\n".join(" " + l for l in source.splitlines())
15+
func = ast.parse(wrapped).body[0].body[0]
16+
a = CaseValidatorAnalyzer.__new__(CaseValidatorAnalyzer)
17+
return a._build_local_param_map(func)
18+
19+
20+
class TestFlag(unittest.TestCase):
21+
22+
def test_true_when_set_to_T(self):
23+
self.assertTrue(CaseValidator({"chemistry": "T"}).flag("chemistry"))
24+
25+
def test_false_when_set_to_F(self):
26+
self.assertFalse(CaseValidator({"chemistry": "F"}).flag("chemistry"))
27+
28+
def test_false_when_absent(self):
29+
self.assertFalse(CaseValidator({}).flag("chemistry"))
30+
31+
def test_only_uppercase_T_is_truthy(self):
32+
"""Lowercase, integers, and booleans must not count as set."""
33+
for val in ("t", "True", 1, True, None):
34+
self.assertFalse(CaseValidator({"x": val}).flag("x"), f"Expected False for {val!r}")
35+
36+
def test_returns_bool(self):
37+
self.assertIsInstance(CaseValidator({"x": "T"}).flag("x"), bool)
38+
39+
40+
class TestASTCoupling(unittest.TestCase):
41+
42+
def test_flag_call_recorded_by_analyzer(self):
43+
"""self.flag('x') must register 'x' in the param map, same as self.get('x','F')=='T'."""
44+
m = _param_map("def check(self):\n chemistry = self.flag('chemistry')")
45+
self.assertEqual(m.get("chemistry"), "chemistry")
46+
47+
def test_get_call_still_recorded(self):
48+
"""Existing self.get() pattern must not regress."""
49+
m = _param_map("def check(self):\n d = self.get('chem_params%diffusion', 'F') == 'T'")
50+
self.assertEqual(m.get("d"), "chem_params%diffusion")
51+
52+
def test_old_matcher_would_have_missed_flag(self):
53+
"""Demonstrate the pre-fix bug: attr=='get' silently dropped flag() calls."""
54+
source = "def check(self):\n chemistry = self.flag('chemistry')"
55+
wrapped = "class _V:\n" + "\n".join(" " + l for l in source.splitlines())
56+
func = ast.parse(wrapped).body[0].body[0]
57+
58+
broken = {}
59+
for node in ast.walk(func):
60+
if isinstance(node, ast.Assign):
61+
v = node.value.left if isinstance(node.value, ast.Compare) else node.value
62+
if isinstance(v, ast.Call) and isinstance(v.func, ast.Attribute):
63+
if v.func.value.id == "self" and v.func.attr == "get": # old check
64+
for t in node.targets:
65+
if isinstance(t, ast.Name):
66+
broken[t.id] = v.args[0].value
67+
68+
self.assertNotIn("chemistry", broken, "Old matcher should miss flag() — that was the bug")
69+
70+
a = CaseValidatorAnalyzer.__new__(CaseValidatorAnalyzer)
71+
fixed = a._build_local_param_map(func)
72+
self.assertIn("chemistry", fixed, "Fixed matcher must capture flag() calls")
73+
74+
75+
if __name__ == "__main__":
76+
unittest.main()

0 commit comments

Comments
 (0)