diff options
author | Mark Doffman <mark.doffman@codethink.co.uk> | 2014-03-27 20:50:21 +0000 |
---|---|---|
committer | Mark Doffman <mark.doffman@codethink.co.uk> | 2014-03-27 20:50:21 +0000 |
commit | 68ff94340891f1ae4ea24546acdbbc39c4dcbcd0 (patch) | |
tree | 46f02cba671bcb321482c7961acd91aeee57ced5 /tests/scanner/test_transformer.py | |
parent | 19da3f81593614198206c45527f973a22cdd621e (diff) | |
parent | 89e84d06dffbc732bac26a105244b7270c42e3ec (diff) | |
download | gobject-introspection-baserock/markdoffman/1_39_90-merge.tar.gz |
Merge tag 'GOBJECT_INTROSPECTION_1_39_90' into baserock/markdoffman/1_39_90-mergebaserock/markdoffman/1_39_90-merge
Tag 1_39_90
Conflicts:
autogen.sh
configure.ac
Diffstat (limited to 'tests/scanner/test_transformer.py')
-rw-r--r-- | tests/scanner/test_transformer.py | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/tests/scanner/test_transformer.py b/tests/scanner/test_transformer.py new file mode 100644 index 00000000..39c54a4d --- /dev/null +++ b/tests/scanner/test_transformer.py @@ -0,0 +1,445 @@ +import unittest +import tempfile +import os +import sys +import __builtin__ + + +os.environ['GI_SCANNER_DISABLE_CACHE'] = '1' +path = os.getenv('UNINSTALLED_INTROSPECTION_SRCDIR', None) +assert path is not None +sys.path.insert(0, path) + +# Not correct, but enough to get the tests going uninstalled +__builtin__.__dict__['DATADIR'] = path + +from giscanner import ast +from giscanner.sourcescanner import SourceScanner +from giscanner.transformer import Transformer +from giscanner.message import MessageLogger, WARNING, ERROR, FATAL + + +def create_scanner_from_source_string(source): + ss = SourceScanner() + tmp_fd, tmp_name = tempfile.mkstemp(suffix='.h', text=True) + file = os.fdopen(tmp_fd, 'wt') + file.write(source) + file.close() + + ss.parse_files([tmp_name]) + return ss + + +def load_namespace_from_source_string(namespace, source): + ss = create_scanner_from_source_string(source) + xformer = Transformer(namespace) + xformer.parse(ss.get_symbols()) + + +class TestStructTypedefs(unittest.TestCase): + def setUp(self): + # Hack to set logging singleton + self.namespace = ast.Namespace('Test', '1.0') + logger = MessageLogger.get(namespace=self.namespace) + logger.enable_warnings((WARNING, ERROR, FATAL)) + + def test_anonymous_typedef(self): + load_namespace_from_source_string(self.namespace, """ + typedef struct { + int value; + } TestStruct; + """) + self.assertEqual(len(self.namespace.names), 1) + node = self.namespace.get('Struct') + self.assertTrue(node is not None) + self.assertTrue(isinstance(node, ast.Record)) + self.assertFalse(node.disguised) + self.assertEqual(len(node.fields), 1) + + def test_typedef_before(self): + load_namespace_from_source_string(self.namespace, """ + typedef struct _TestStruct TestStruct; + struct _TestStruct { + int value; + }; + """) + self.assertEqual(len(self.namespace.names), 1) + node = self.namespace.get('Struct') + self.assertTrue(node is not None) + self.assertTrue(isinstance(node, ast.Record)) + self.assertFalse(node.disguised) + self.assertEqual(len(node.fields), 1) + + def test_typedef_after(self): + load_namespace_from_source_string(self.namespace, """ + struct _TestStruct { + int value; + }; + typedef struct _TestStruct TestStruct; + """) + self.assertEqual(len(self.namespace.names), 1) + node = self.namespace.get('Struct') + self.assertTrue(node is not None) + self.assertTrue(isinstance(node, ast.Record)) + self.assertFalse(node.disguised) + self.assertEqual(len(node.fields), 1) + + def test_tag_and_typedef(self): + load_namespace_from_source_string(self.namespace, """ + typedef struct _TestStruct { + int value; + } TestStruct; + """) + self.assertEqual(len(self.namespace.names), 1) + node = self.namespace.get('Struct') + self.assertTrue(node is not None) + self.assertTrue(isinstance(node, ast.Record)) + self.assertFalse(node.disguised) + self.assertEqual(len(node.fields), 1) + + def test_struct_tag_only(self): + load_namespace_from_source_string(self.namespace, """ + struct TestStruct { + int value; + }; + """) + self.assertEqual(len(self.namespace.names), 1) + node = self.namespace.get('Struct') + self.assertTrue(node is not None) + self.assertTrue(isinstance(node, ast.Record)) + self.assertFalse(node.disguised) + self.assertEqual(len(node.fields), 1) + + def test_struct_aliases(self): + load_namespace_from_source_string(self.namespace, """ + typedef struct { + int value; + } TestStruct; + typedef TestStruct TestStructAlias1; + typedef TestStruct TestStructAlias2; + """) + self.assertEqual(len(self.namespace.names), 3) + + node = self.namespace.get('Struct') + self.assertTrue(node is not None) + self.assertTrue(isinstance(node, ast.Record)) + self.assertFalse(node.disguised) + self.assertEqual(len(node.fields), 1) + + alias = self.namespace.get('StructAlias1') + self.assertTrue(isinstance(alias, ast.Alias)) + self.assertEqual(alias.target, node) + self.assertEqual(alias.ctype, 'TestStructAlias1') + + alias = self.namespace.get('StructAlias2') + self.assertTrue(isinstance(alias, ast.Alias)) + self.assertEqual(alias.target, node) + self.assertEqual(alias.ctype, 'TestStructAlias2') + + def test_struct_tag_aliases_before(self): + # This test is similar to how GObject and GInitiallyUnowned are setup + load_namespace_from_source_string(self.namespace, """ + typedef struct _TestStruct TestStruct; + typedef struct _TestStruct TestStructAlias; + struct _TestStruct { + int value; + }; + """) + self.assertEqual(len(self.namespace.names), 2) + + node = self.namespace.get('Struct') + self.assertTrue(node is not None) + self.assertTrue(isinstance(node, ast.Record)) + self.assertFalse(node.disguised) + self.assertEqual(len(node.fields), 1) + self.assertEqual(node.ctype, 'TestStruct') + + shared = self.namespace.get('StructAlias') + self.assertTrue(shared is not None) + self.assertTrue(isinstance(shared, ast.Record)) + self.assertFalse(shared.disguised) + self.assertEqual(len(shared.fields), 1) + self.assertEqual(shared.ctype, 'TestStructAlias') + + def test_struct_tag_aliases_after(self): + load_namespace_from_source_string(self.namespace, """ + struct _TestStruct { + int value; + }; + typedef struct _TestStruct TestStruct; + typedef struct _TestStruct TestStructAlias; + """) + self.assertEqual(len(self.namespace.names), 2) + + node = self.namespace.get('Struct') + self.assertTrue(node is not None) + self.assertTrue(isinstance(node, ast.Record)) + self.assertFalse(node.disguised) + self.assertEqual(len(node.fields), 1) + self.assertEqual(node.ctype, 'TestStruct') + + shared = self.namespace.get('StructAlias') + self.assertTrue(shared is not None) + self.assertTrue(isinstance(shared, ast.Record)) + self.assertFalse(shared.disguised) + self.assertEqual(len(shared.fields), 1) + self.assertEqual(shared.ctype, 'TestStructAlias') + + def test_struct_pointer(self): + load_namespace_from_source_string(self.namespace, """ + typedef struct { + int value; + } TestStruct; + typedef TestStruct* TestStructPtr; + """) + self.assertEqual(len(self.namespace.names), 2) + + node = self.namespace.get('Struct') + self.assertTrue(node is not None) + self.assertTrue(isinstance(node, ast.Record)) + self.assertEqual(len(node.fields), 1) + self.assertEqual(node.ctype, 'TestStruct') + + ptr = self.namespace.get('StructPtr') + self.assertTrue(ptr is not None) + self.assertTrue(isinstance(ptr, ast.Alias)) + self.assertEqual(ptr.ctype, 'TestStructPtr') + # This loses type information about the struct which seems broken. + self.assertEqual(ptr.target, ast.TYPE_ANY) + + def test_struct_tag_pointer(self): + load_namespace_from_source_string(self.namespace, """ + typedef struct _TestStruct TestStruct; + struct _TestStruct{ + int value; + }; + typedef struct _TestStruct* TestStructPtr; + """) + self.assertEqual(len(self.namespace.names), 2) + + node = self.namespace.get('Struct') + self.assertTrue(node is not None) + self.assertTrue(isinstance(node, ast.Record)) + self.assertFalse(node.disguised) + self.assertEqual(node.ctype, 'TestStruct') + self.assertEqual(len(node.fields), 1) + + ptr = self.namespace.get('StructPtr') + self.assertTrue(ptr is not None) + # This currently gives a disguised Record instead of an Alias + self.assertTrue(isinstance(ptr, ast.Record)) + self.assertTrue(ptr.disguised) + self.assertEqual(len(ptr.fields), 0) + self.assertEqual(ptr.ctype, 'TestStructPtr') + + +class TestNestedStructs(unittest.TestCase): + def setUp(self): + # Hack to set logging singleton + self.namespace = ast.Namespace('Test', '1.0') + logger = MessageLogger.get(namespace=self.namespace) + logger.enable_warnings((WARNING, ERROR, FATAL)) + + def test_nested_named(self): + load_namespace_from_source_string(self.namespace, """ + typedef struct { + int value; + } TestSimpleStruct; + + typedef struct { + TestSimpleStruct nested_struct; + } TestStructWithNested; + """) + self.assertEqual(len(self.namespace.names), 2) + node = self.namespace.get('StructWithNested') + self.assertEqual(len(node.fields), 1) + + simple = self.namespace.get('SimpleStruct') + self.assertTrue(node is not None) + + field = node.fields[0] + self.assertTrue(field is not None) + self.assertTrue(isinstance(field, ast.Field)) + self.assertEqual(field.type, simple) + self.assertEqual(field.name, 'nested_struct') + + def test_nested_anonymous(self): + load_namespace_from_source_string(self.namespace, """ + typedef struct { + struct { + int value; + }; + } TestStructWithNestedAnon; + """) + self.assertEqual(len(self.namespace.names), 1) + node = self.namespace.get('StructWithNestedAnon') + self.assertEqual(len(node.fields), 1) + + field = node.fields[0] + self.assertTrue(field is not None) + self.assertTrue(isinstance(field, ast.Field)) + self.assertEqual(field.name, None) + + anon = field.anonymous_node + self.assertTrue(isinstance(anon, ast.Record)) + self.assertEqual(len(anon.fields), 1) + + anon_field = anon.fields[0] + self.assertTrue(anon_field is not None) + self.assertTrue(isinstance(anon_field, ast.Field)) + self.assertEqual(anon_field.name, 'value') + + def test_nested(self): + load_namespace_from_source_string(self.namespace, """ + typedef struct { + struct { + int value; + } nested; + } TestStructWithNested; + """) + self.assertEqual(len(self.namespace.names), 1) + node = self.namespace.get('StructWithNested') + self.assertEqual(len(node.fields), 1) + + field = node.fields[0] + self.assertTrue(field is not None) + self.assertTrue(isinstance(field, ast.Field)) + self.assertEqual(field.name, 'nested') + + nested = field.anonymous_node + self.assertTrue(isinstance(nested, ast.Record)) + self.assertEqual(len(nested.fields), 1) + self.assertEqual(nested.name, 'nested') + + nested_field = nested.fields[0] + self.assertTrue(nested_field is not None) + self.assertTrue(isinstance(nested_field, ast.Field)) + self.assertEqual(nested_field.name, 'value') + + def test_struct_ptr(self): + load_namespace_from_source_string(self.namespace, """ + typedef struct { + int value; + } TestSimpleStruct; + + typedef struct { + TestSimpleStruct *struct_ptr; + } TestStructWithNestedPtr; + """) + self.assertEqual(len(self.namespace.names), 2) + node = self.namespace.get('StructWithNestedPtr') + self.assertEqual(len(node.fields), 1) + + simple = self.namespace.get('SimpleStruct') + self.assertTrue(node is not None) + + field = node.fields[0] + self.assertTrue(field is not None) + self.assertTrue(isinstance(field, ast.Field)) + self.assertEqual(field.type.ctype, 'TestSimpleStruct*') + self.assertEqual(field.name, 'struct_ptr') + + +class TestUnions(unittest.TestCase): + def setUp(self): + # Hack to set logging singleton + self.namespace = ast.Namespace('Test', '1.0') + logger = MessageLogger.get(namespace=self.namespace) + logger.enable_warnings((WARNING, ERROR, FATAL)) + + def test_union_with_struct(self): + load_namespace_from_source_string(self.namespace, """ + typedef struct { + int value; + } TestSimpleStruct; + + typedef union { + TestSimpleStruct nested_struct; + int value; + } TestUnionWithNested; + """) + self.assertEqual(len(self.namespace.names), 2) + node = self.namespace.get('UnionWithNested') + self.assertEqual(len(node.fields), 2) + + simple = self.namespace.get('SimpleStruct') + self.assertTrue(node is not None) + + field = node.fields[0] + self.assertEqual(field.type, simple) + self.assertEqual(field.name, 'nested_struct') + + field = node.fields[1] + self.assertEqual(field.type.ctype, 'int') + self.assertEqual(field.name, 'value') + + def test_nested(self): + load_namespace_from_source_string(self.namespace, """ + typedef struct { + union { + int ival; + float fval; + } nested; + } TestNestedUnion; + """) + self.assertEqual(len(self.namespace.names), 1) + node = self.namespace.get('NestedUnion') + self.assertEqual(len(node.fields), 1) + + field = node.fields[0] + self.assertEqual(field.name, 'nested') + + nested = field.anonymous_node + self.assertTrue(isinstance(nested, ast.Union)) + self.assertEqual(nested.name, 'nested') + self.assertEqual(len(nested.fields), 2) + + self.assertEqual(nested.fields[0].name, 'ival') + self.assertEqual(nested.fields[1].name, 'fval') + + def test_nested_anonymous(self): + load_namespace_from_source_string(self.namespace, """ + typedef struct { + union { + int ival; + float fval; + }; + } TestStructWithNestedUnion; + """) + self.assertEqual(len(self.namespace.names), 1) + node = self.namespace.get('StructWithNestedUnion') + self.assertEqual(len(node.fields), 1) + + field = node.fields[0] + self.assertEqual(field.name, None) + + nested = field.anonymous_node + self.assertTrue(isinstance(nested, ast.Union)) + self.assertEqual(nested.name, None) + self.assertEqual(len(nested.fields), 2) + + self.assertEqual(nested.fields[0].name, 'ival') + self.assertEqual(nested.fields[0].type.ctype, 'int') + + self.assertEqual(nested.fields[1].name, 'fval') + self.assertEqual(nested.fields[1].type.ctype, 'float') + + +class TestCallbacks(unittest.TestCase): + def setUp(self): + # Hack to set logging singleton + self.namespace = ast.Namespace('Test', '1.0') + logger = MessageLogger.get(namespace=self.namespace) + logger.enable_warnings((WARNING, ERROR, FATAL)) + + def test_union_with_struct(self): + load_namespace_from_source_string(self.namespace, """ + typedef void (*TestCallback)(int value); + """) + self.assertEqual(len(self.namespace.names), 1) + node = self.namespace.get('Callback') + self.assertTrue(isinstance(node, ast.Callback)) + + +if __name__ == '__main__': + unittest.main() |