#!/usr/bin/env python3 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file # for details. All rights reserved. Use of this source code is governed by a # BSD-style license that can be found in the LICENSE file. import database import idlparser import logging.config import os import os.path import shutil import tempfile import unittest from databasebuilder import * class DatabaseBuilderTestCase(unittest.TestCase): def _create_input(self, idl_file_name, content): file_name = os.path.join(self._input_dir, idl_file_name) f = open(file_name, 'w') f.write(content) f.close() return file_name def _assert_interface_exists(self, path): file_path = os.path.join(self._database_dir, path) self.assertTrue(os.path.exists(file_path)) def _assert_content_equals(self, path, expected_content): def clean(content): return ' '.join( filter(len, list(map(str.strip, content.split('\n'))))) file_path = os.path.join(self._database_dir, path) self.assertTrue(os.path.exists(file_path)) f = open(file_path, 'r') actual_content = f.read() f.close() if clean(actual_content) != clean(expected_content): msg = ''' FILE: %s EXPECTED: %s ACTUAL: %s ''' % (file_path, expected_content, actual_content) self.fail(msg) def setUp(self): working_dir = tempfile.mkdtemp() self._database_dir = os.path.join(working_dir, 'database') self.assertFalse(os.path.exists(self._database_dir)) self._input_dir = os.path.join(working_dir, 'inputdir') os.makedirs(self._input_dir) self._db = database.Database(self._database_dir) self.assertTrue(os.path.exists(self._database_dir)) self._builder = DatabaseBuilder(self._db) def tearDown(self): shutil.rmtree(self._database_dir) def test_basic_import(self): file_name = self._create_input( 'input.idl', ''' module M { interface I { attribute int a; }; };''') self._builder.import_idl_file(file_name) self._builder.merge_imported_interfaces([]) self._db.Save() self._assert_interface_exists('I.idl') def test_splitting(self): file_name = self._create_input( 'input.idl', ''' module M { interface I { readonly attribute int a; int o(in int x, in optional int y); }; };''') self._builder.import_idl_file(file_name) self._builder.merge_imported_interfaces([]) self._db.Save() self._assert_content_equals( 'I.idl', ''' interface I { /* Attributes */ getter attribute int a; /* Operations */ int o(in int x); int o(in int x, in int y); };''') def test_renames(self): file_name = self._create_input( 'input.idl', ''' module M { [Constructor(in T x)] interface I { T op(T x); readonly attribute N::T attr; }; };''') options = DatabaseBuilderOptions(type_rename_map={'I': 'i', 'T': 't'}) self._builder.import_idl_file(file_name, options) self._builder.merge_imported_interfaces([]) self._db.Save() self._assert_content_equals( 'i.idl', ''' [Constructor(in t x)] interface i { /* Attributes */ getter attribute t attr; /* Operations */ t op(in t x); };''') def test_type_defs(self): file_name = self._create_input( 'input.idl', ''' module M { typedef T S; interface I : S { S op(S x); readonly attribute S attr; }; };''') options = DatabaseBuilderOptions() self._builder.import_idl_file(file_name, options) self._builder.merge_imported_interfaces([]) self._db.Save() self._assert_content_equals( 'I.idl', ''' interface I : T { /* Attributes */ getter attribute T attr; /* Operations */ T op(in T x); };''') def test_merge(self): file_name1 = self._create_input( 'input1.idl', ''' module M { interface I { const int CONST_BOTH = 0; const int CONST_ONLY_FIRST = 0; const int CONST_BOTH_DIFFERENT_VALUE = 0; readonly attribute int attr_only_first; readonly attribute int attr_both; readonly attribute int attr_both_readonly_difference; readonly attribute int attr_both_int_long_difference; int op_only_first(); int op_both(int a); int op_both_optionals_difference(int a, in optional int b); int op_both_arg_rename(int arg); }; };''') self._builder.import_idl_file( file_name1, DatabaseBuilderOptions( source='1st', idl_syntax=idlparser.FREMONTCUT_SYNTAX)) file_name2 = self._create_input( 'input2.idl', ''' module M { interface I { const int CONST_BOTH = 0; const int CONST_ONLY_SECOND = 0; const int CONST_BOTH_DIFFERENT_VALUE = 1; readonly attribute int attr_only_second; readonly attribute int attr_both; readonly attribute long attr_both_int_long_difference; attribute int attr_both_readonly_difference; int op_only_second(); int op_both(int a); int op_both_optionals_difference(int a, optional boolean b); int op_both_arg_rename(int betterName); }; };''') self._builder.import_idl_file( file_name2, DatabaseBuilderOptions( source='2nd', idl_syntax=idlparser.FREMONTCUT_SYNTAX)) self._builder.set_same_signatures({'int': 'long'}) self._builder.merge_imported_interfaces([]) self._db.Save() self._assert_content_equals( 'I.idl', ''' @1st(module=M) @2nd(module=M) interface I { /* Constants */ @1st @2nd const int CONST_BOTH = 0; @1st const int CONST_BOTH_DIFFERENT_VALUE = 0; @2nd const int CONST_BOTH_DIFFERENT_VALUE = 1; @1st const int CONST_ONLY_FIRST = 0; @2nd const int CONST_ONLY_SECOND = 0; /* Attributes */ @1st @2nd getter attribute int attr_both; @1st @2nd getter attribute int attr_both_int_long_difference; @1st @2nd getter attribute int attr_both_readonly_difference; @2nd setter attribute int attr_both_readonly_difference; @1st getter attribute int attr_only_first; @2nd getter attribute int attr_only_second; /* Operations */ @1st @2nd int op_both(in t a); @1st @2nd int op_both_arg_rename(in t betterName); @1st @2nd int op_both_optionals_difference(in t a); @1st int op_both_optionals_difference(in t a, in int b); @2nd int op_both_optionals_difference(in t a, in boolean b); @1st int op_only_first(); @2nd int op_only_second(); };''') def test_mergeDartName(self): file_name1 = self._create_input( 'input1.idl', ''' module M { interface I { [ImplementationFunction=foo] int member(in int a); }; };''') self._builder.import_idl_file( file_name1, DatabaseBuilderOptions( source='1st', idl_syntax=idlparser.FREMONTCUT_SYNTAX)) file_name2 = self._create_input( 'input2.idl', ''' module M { interface I { [DartName=bar] int member(in int a); }; };''') self._builder.import_idl_file( file_name2, DatabaseBuilderOptions( source='2nd', idl_syntax=idlparser.FREMONTCUT_SYNTAX)) self._builder.merge_imported_interfaces([]) self._db.Save() self._assert_content_equals( 'I.idl', ''' @1st(module=M) @2nd(module=M) interface I { /* Operations */ @1st @2nd [DartName=bar, ImplementationFunction=foo] int member(in int a); };''') def test_supplemental(self): file_name = self._create_input( 'input1.idl', ''' module M { interface I { readonly attribute int a; }; [Supplemental] interface I { readonly attribute int b; }; };''') self._builder.import_idl_file(file_name, DatabaseBuilderOptions(source='Src')) self._builder.merge_imported_interfaces([]) self._db.Save() self._assert_content_equals( 'I.idl', ''' @Src(module=M) [Supplemental] interface I { /* Attributes */ @Src getter attribute int a; @Src getter attribute int b; };''') def test_impl_stmt(self): file_name = self._create_input( 'input.idl', ''' module M { interface I {}; I implements J; };''') self._builder.import_idl_file(file_name, DatabaseBuilderOptions(source='Src')) self._builder.merge_imported_interfaces([]) self._db.Save() self._assert_content_equals( 'I.idl', ''' @Src(module=M) interface I : @Src J { };''') def test_obsolete(self): file_name1 = self._create_input( 'input1.idl', ''' module M { interface I { readonly attribute int keep; readonly attribute int obsolete; // Would be removed }; };''') self._builder.import_idl_file(file_name1, DatabaseBuilderOptions(source='src')) file_name2 = self._create_input( 'input2.idl', ''' module M { interface I { readonly attribute int keep; readonly attribute int new; }; };''') self._builder.import_idl_file( file_name2, DatabaseBuilderOptions( source='src', obsolete_old_declarations=True)) self._builder.merge_imported_interfaces([]) self._db.Save() self._assert_content_equals( 'I.idl', ''' @src(module=M) interface I { /* Attributes */ @src getter attribute int keep; @src getter attribute int new; };''') def test_annotation_normalization(self): file_name = self._create_input( 'input.idl', ''' module M { interface I : J{ const int C = 0; readonly attribute int a; int op(); }; };''') self._builder.import_idl_file( file_name, DatabaseBuilderOptions(source='Src', source_attributes={'x': 'y'})) self._builder.merge_imported_interfaces([]) interface = self._db.GetInterface('I') interface.parents[0].annotations['Src']['x'] = 'u' interface.constants[0].annotations['Src']['z'] = 'w' interface.attributes[0].annotations['Src']['x'] = 'u' self._db.Save() # Before normalization self._assert_content_equals( 'I.idl', ''' @Src(module=M, x=y) interface I : @Src(x=u) J { /* Constants */ @Src(x=y, z=w) const int C = 0; /* Attributes */ @Src(x=u) getter attribute int a; /* Operations */ @Src(x=y) int op(); };''') # Normalize self._builder.normalize_annotations(['Src']) self._db.Save() # After normalization self._assert_content_equals( 'I.idl', ''' @Src(module=M, x=y) interface I : @Src(x=u) J { /* Constants */ @Src(z=w) const int C = 0; /* Attributes */ @Src(x=u) getter attribute int a; /* Operations */ @Src int op(); };''') def test_fix_displacements(self): file_name1 = self._create_input( 'input1.idl', ''' module M { interface I {}; interface J : I { readonly attribute int attr; }; };''') self._builder.import_idl_file(file_name1, DatabaseBuilderOptions(source='1st')) file_name2 = self._create_input( 'input2.idl', ''' module M { interface I { readonly attribute int attr; }; interface J : I {}; };''') self._builder.import_idl_file(file_name2, DatabaseBuilderOptions(source='2nd')) self._builder.merge_imported_interfaces([]) self._builder.fix_displacements('2nd') self._db.Save() self._assert_content_equals( 'J.idl', ''' @1st(module=M) @2nd(module=M) interface J : @1st @2nd I { /* Attributes */ @1st @2nd(via=I) getter attribute int attr; };''') if __name__ == "__main__": logging.config.fileConfig("logging.conf") if __name__ == '__main__': unittest.main()