| import string |
| import unittest |
| |
| from ..util import PseudoStr, StrProxy, Object |
| from .. import tool_imports_for_tests |
| with tool_imports_for_tests(): |
| from c_analyzer.common.info import ID |
| from c_analyzer.symbols.info import Symbol |
| |
| |
| class SymbolTests(unittest.TestCase): |
| |
| VALID_ARGS = ( |
| ID('x/y/z/spam.c', 'func', 'eggs'), |
| Symbol.KIND.VARIABLE, |
| False, |
| ) |
| VALID_KWARGS = dict(zip(Symbol._fields, VALID_ARGS)) |
| VALID_EXPECTED = VALID_ARGS |
| |
| def test_init_typical_binary_local(self): |
| id = ID(None, None, 'spam') |
| symbol = Symbol( |
| id=id, |
| kind=Symbol.KIND.VARIABLE, |
| external=False, |
| ) |
| |
| self.assertEqual(symbol, ( |
| id, |
| Symbol.KIND.VARIABLE, |
| False, |
| )) |
| |
| def test_init_typical_binary_global(self): |
| id = ID('Python/ceval.c', None, 'spam') |
| symbol = Symbol( |
| id=id, |
| kind=Symbol.KIND.VARIABLE, |
| external=False, |
| ) |
| |
| self.assertEqual(symbol, ( |
| id, |
| Symbol.KIND.VARIABLE, |
| False, |
| )) |
| |
| def test_init_coercion(self): |
| tests = [ |
| ('str subclass', |
| dict( |
| id=PseudoStr('eggs'), |
| kind=PseudoStr('variable'), |
| external=0, |
| ), |
| (ID(None, None, 'eggs'), |
| Symbol.KIND.VARIABLE, |
| False, |
| )), |
| ('with filename', |
| dict( |
| id=('x/y/z/spam.c', 'eggs'), |
| kind=PseudoStr('variable'), |
| external=0, |
| ), |
| (ID('x/y/z/spam.c', None, 'eggs'), |
| Symbol.KIND.VARIABLE, |
| False, |
| )), |
| ('non-str 1', |
| dict( |
| id=('a', 'b', 'c'), |
| kind=StrProxy('variable'), |
| external=0, |
| ), |
| (ID('a', 'b', 'c'), |
| Symbol.KIND.VARIABLE, |
| False, |
| )), |
| ('non-str 2', |
| dict( |
| id=('a', 'b', 'c'), |
| kind=Object(), |
| external=0, |
| ), |
| (ID('a', 'b', 'c'), |
| '<object>', |
| False, |
| )), |
| ] |
| for summary, kwargs, expected in tests: |
| with self.subTest(summary): |
| symbol = Symbol(**kwargs) |
| |
| for field in Symbol._fields: |
| value = getattr(symbol, field) |
| if field == 'external': |
| self.assertIs(type(value), bool) |
| elif field == 'id': |
| self.assertIs(type(value), ID) |
| else: |
| self.assertIs(type(value), str) |
| self.assertEqual(tuple(symbol), expected) |
| |
| def test_init_all_missing(self): |
| id = ID(None, None, 'spam') |
| |
| symbol = Symbol(id) |
| |
| self.assertEqual(symbol, ( |
| id, |
| Symbol.KIND.VARIABLE, |
| None, |
| )) |
| |
| def test_fields(self): |
| id = ID('z', 'x', 'a') |
| |
| symbol = Symbol(id, 'b', False) |
| |
| self.assertEqual(symbol.id, id) |
| self.assertEqual(symbol.kind, 'b') |
| self.assertIs(symbol.external, False) |
| |
| def test___getattr__(self): |
| id = ID('z', 'x', 'a') |
| symbol = Symbol(id, 'b', False) |
| |
| filename = symbol.filename |
| funcname = symbol.funcname |
| name = symbol.name |
| |
| self.assertEqual(filename, 'z') |
| self.assertEqual(funcname, 'x') |
| self.assertEqual(name, 'a') |
| |
| def test_validate_typical(self): |
| id = ID('z', 'x', 'a') |
| |
| symbol = Symbol( |
| id=id, |
| kind=Symbol.KIND.VARIABLE, |
| external=False, |
| ) |
| |
| symbol.validate() # This does not fail. |
| |
| def test_validate_missing_field(self): |
| for field in Symbol._fields: |
| with self.subTest(field): |
| symbol = Symbol(**self.VALID_KWARGS) |
| symbol = symbol._replace(**{field: None}) |
| |
| with self.assertRaises(TypeError): |
| symbol.validate() |
| |
| def test_validate_bad_field(self): |
| badch = tuple(c for c in string.punctuation + string.digits) |
| notnames = ( |
| '1a', |
| 'a.b', |
| 'a-b', |
| '&a', |
| 'a++', |
| ) + badch |
| tests = [ |
| ('id', notnames), |
| ('kind', ('bogus',)), |
| ] |
| seen = set() |
| for field, invalid in tests: |
| for value in invalid: |
| if field != 'kind': |
| seen.add(value) |
| with self.subTest(f'{field}={value!r}'): |
| symbol = Symbol(**self.VALID_KWARGS) |
| symbol = symbol._replace(**{field: value}) |
| |
| with self.assertRaises(ValueError): |
| symbol.validate() |
| |
| for field, invalid in tests: |
| if field == 'kind': |
| continue |
| valid = seen - set(invalid) |
| for value in valid: |
| with self.subTest(f'{field}={value!r}'): |
| symbol = Symbol(**self.VALID_KWARGS) |
| symbol = symbol._replace(**{field: value}) |
| |
| symbol.validate() # This does not fail. |