def testImportFromDataNoExtraneousImports(self): """Tests that arrays, maps and interface requests are not imported.""" module = mojom.Module('test_module', 'test_namespace') imported_module = mojom.Module('import_module', 'import_namespace') #TODO(azani): Init values in module.py. imported_module.values = {} imported_data = {'module': imported_module} array = mojom.Array(mojom.INT16, length=20) imported_module.kinds[array.spec] = array map_kind = mojom.Map(mojom.INT16, mojom.INT16) imported_module.kinds[map_kind.spec] = map_kind interface = mojom.Interface('TestInterface', module=module) imported_module.kinds[interface.spec] = interface interface_req = mojom.InterfaceRequest(interface) imported_module.kinds[interface_req.spec] = interface_req data.ImportFromData(module, imported_data) self.assertNotIn(array.spec, module.kinds) self.assertNotIn(map_kind.spec, module.kinds) self.assertNotIn(interface_req.spec, module.kinds)
def testStructDataConversion(self): """Tests that a struct can be converted from data.""" module = mojom.Module('test_module', 'test_namespace') struct_data = { 'name': 'SomeStruct', 'enums': [], 'constants': [], 'fields': [{ 'name': 'field1', 'kind': 'i32' }, { 'name': 'field2', 'kind': 'i32', 'ordinal': 10 }, { 'name': 'field3', 'kind': 'i32', 'default': 15 }] } struct = data.StructFromData(module, struct_data) struct.fields = map( lambda field: data.StructFieldFromData(module, field, struct), struct.fields_data) self.assertEquals(struct_data, data.StructToData(struct))
def testNonInterfaceAsInterfaceRequest(self): """Tests that a non-interface cannot be used for interface requests.""" module = mojom.Module('test_module', 'test_namespace') struct = mojom.Struct('TestStruct', module=module) with self.assertRaises(Exception) as e: mojom.InterfaceRequest(struct) self.assertEquals( e.exception.__str__(), 'Interface request requires \'x:TestStruct\' to be an interface.')
def testImportFromDataNoMissingImports(self): """Tests that unions, structs, interfaces and enums are imported.""" module = mojom.Module('test_module', 'test_namespace') imported_module = mojom.Module('import_module', 'import_namespace') #TODO(azani): Init values in module.py. #TODO(azani): Test that values are imported. imported_module.values = {} imported_data = {'module' : imported_module} struct = mojom.Struct('TestStruct', module=module) imported_module.kinds[struct.spec] = struct union = mojom.Union('TestUnion', module=module) imported_module.kinds[union.spec] = union interface = mojom.Interface('TestInterface', module=module) imported_module.kinds[interface.spec] = interface enum = mojom.Enum('TestEnum', module=module) imported_module.kinds[enum.spec] = enum data.ImportFromData(module, imported_data) # Test that the kind was imported. self.assertIn(struct.spec, module.kinds) self.assertEquals(struct.name, module.kinds[struct.spec].name) self.assertIn(union.spec, module.kinds) self.assertEquals(union.name, module.kinds[union.spec].name) self.assertIn(interface.spec, module.kinds) self.assertEquals(interface.name, module.kinds[interface.spec].name) self.assertIn(enum.spec, module.kinds) self.assertEquals(enum.name, module.kinds[enum.spec].name) # Test that the imported kind is a copy and not the original. self.assertIsNot(struct, module.kinds[struct.spec]) self.assertIsNot(union, module.kinds[union.spec]) self.assertIsNot(interface, module.kinds[interface.spec]) self.assertIsNot(enum, module.kinds[enum.spec])
def testUnionDataConversion(self): """Tests that a union can be converted from data.""" module = mojom.Module('test_module', 'test_namespace') union_data = { 'name': 'SomeUnion', 'fields': [ {'name': 'field1', 'kind': 'i32'}, {'name': 'field2', 'kind': 'i32', 'ordinal': 10}]} union = data.UnionFromData(module, union_data) union.fields = map(lambda field: data.FieldFromData(module, field, union), union.fields_data) self.assertEquals(union_data, data.UnionToData(union))
def testNonInterfaceAsInterfaceRequest(self): """Tests that a non-interface cannot be used for interface requests.""" module = mojom.Module('test_module', 'test_namespace') interface = mojom.Interface('TestInterface', module=module) method_dict = { 'name': 'Foo', 'parameters': [{ 'name': 'foo', 'kind': 'r:i32' }], } with self.assertRaises(Exception) as e: data.MethodFromData(module, method_dict, interface) self.assertEquals( e.exception.__str__(), 'Interface request requires \'i32\' to be an interface.')
def _Module(tree, path, imports): """ Args: tree: {ast.Mojom} The parse tree. path: {str} The path to the mojom file. imports: {Dict[str, mojom.Module]} Mapping from filenames, as they appear in the import list, to already processed modules. Used to process imports. Returns: {mojom.Module} An AST for the mojom. """ module = mojom.Module(path=path) module.kinds = {} for kind in mojom.PRIMITIVES: module.kinds[kind.spec] = kind module.values = {} module.mojom_namespace = tree.module.mojom_namespace[1] if tree.module else '' # Imports must come first, because they add to module.kinds which is used # by by the others. module.imports = [ _Import(module, imports[imp.import_filename]) for imp in tree.import_list] if tree.module and tree.module.attribute_list: assert isinstance(tree.module.attribute_list, ast.AttributeList) # TODO(vtl): Check for duplicate keys here. module.attributes = dict((attribute.key, attribute.value) for attribute in tree.module.attribute_list) filename = os.path.basename(path) # First pass collects kinds. module.enums = list( map(lambda enum: _Enum(module, enum, None), _ElemsOfType(tree.definition_list, ast.Enum, filename))) module.structs = list( map(lambda struct: _Struct(module, struct), _ElemsOfType(tree.definition_list, ast.Struct, filename))) module.unions = list( map(lambda union: _Union(module, union), _ElemsOfType(tree.definition_list, ast.Union, filename))) module.interfaces = list( map(lambda interface: _Interface(module, interface), _ElemsOfType(tree.definition_list, ast.Interface, filename))) module.constants = list( map(lambda constant: _Constant(module, constant, None), _ElemsOfType(tree.definition_list, ast.Const, filename))) # Second pass expands fields and methods. This allows fields and parameters # to refer to kinds defined anywhere in the mojom. all_defined_kinds = {} for struct in module.structs: struct.fields = list( map(lambda field: _StructField(module, field, struct), struct.fields_data)) del struct.fields_data all_defined_kinds[struct.spec] = struct for enum in struct.enums: all_defined_kinds[enum.spec] = enum for union in module.unions: union.fields = map(lambda field: _UnionField(module, field, union), union.fields_data) del union.fields_data all_defined_kinds[union.spec] = union for interface in module.interfaces: interface.methods = list( map(lambda method: _Method(module, method, interface), interface.methods_data)) del interface.methods_data all_defined_kinds[interface.spec] = interface for enum in interface.enums: all_defined_kinds[enum.spec] = enum for enum in module.enums: all_defined_kinds[enum.spec] = enum all_referenced_kinds = _CollectReferencedKinds(module, all_defined_kinds.values()) imported_kind_specs = set(all_referenced_kinds.keys()).difference( set(all_defined_kinds.keys())) module.imported_kinds = dict((spec, all_referenced_kinds[spec]) for spec in imported_kind_specs) return module
def _Module(tree, path, imports): """ Args: tree: {ast.Mojom} The parse tree. path: {str} The path to the mojom file. imports: {Dict[str, mojom.Module]} Mapping from filenames, as they appear in the import list, to already processed modules. Used to process imports. Returns: {mojom.Module} An AST for the mojom. """ module = mojom.Module(path=path) module.kinds = {} for kind in mojom.PRIMITIVES: module.kinds[kind.spec] = kind module.values = {} module.mojom_namespace = tree.module.mojom_namespace[ 1] if tree.module else '' # Imports must come first, because they add to module.kinds which is used # by by the others. module.imports = [ _Import(module, imports[imp.import_filename]) for imp in tree.import_list ] if tree.module and tree.module.attribute_list: assert isinstance(tree.module.attribute_list, ast.AttributeList) # TODO(vtl): Check for duplicate keys here. module.attributes = dict((attribute.key, attribute.value) for attribute in tree.module.attribute_list) filename = os.path.basename(path) # First pass collects kinds. module.constants = [] module.enums = [] module.structs = [] module.unions = [] module.interfaces = [] _ProcessElements( filename, tree.definition_list, { ast.Const: lambda const: module.constants.append( _Constant(module, const, None)), ast.Enum: lambda enum: module.enums.append(_Enum(module, enum, None)), ast.Struct: lambda struct: module.structs.append(_Struct(module, struct)), ast.Union: lambda union: module.unions.append(_Union(module, union)), ast.Interface: lambda interface: module.interfaces.append( _Interface(module, interface)), }) # Second pass expands fields and methods. This allows fields and parameters # to refer to kinds defined anywhere in the mojom. all_defined_kinds = {} for struct in module.structs: struct.fields = list( map(lambda field: _StructField(module, field, struct), struct.fields_data)) _AssignDefaultOrdinals(struct.fields) del struct.fields_data all_defined_kinds[struct.spec] = struct for enum in struct.enums: all_defined_kinds[enum.spec] = enum for union in module.unions: union.fields = list( map(lambda field: _UnionField(module, field, union), union.fields_data)) _AssignDefaultOrdinals(union.fields) del union.fields_data all_defined_kinds[union.spec] = union for interface in module.interfaces: interface.methods = list( map(lambda method: _Method(module, method, interface), interface.methods_data)) _AssignDefaultOrdinals(interface.methods) del interface.methods_data all_defined_kinds[interface.spec] = interface for enum in interface.enums: all_defined_kinds[enum.spec] = enum for enum in module.enums: all_defined_kinds[enum.spec] = enum all_referenced_kinds = _CollectReferencedKinds(module, all_defined_kinds.values()) imported_kind_specs = set(all_referenced_kinds.keys()).difference( set(all_defined_kinds.keys())) module.imported_kinds = dict( (spec, all_referenced_kinds[spec]) for spec in imported_kind_specs) generator.AddComputedData(module) for iface in module.interfaces: for method in iface.methods: if method.param_struct: _AssignDefaultOrdinals(method.param_struct.fields) if method.response_param_struct: _AssignDefaultOrdinals(method.response_param_struct.fields) # Ensure that all types marked [Stable] are actually stable. Enums are # automatically OK since they don't depend on other definitions. for kinds in (module.structs, module.unions, module.interfaces): for kind in kinds: if kind.stable: _AssertTypeIsStable(kind) return module