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'), '', 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.