| #!/usr/bin/env python3 | |
| # Copyright (c) 2012, 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. | |
| """Tests for dartgenerator.""" | |
| import logging.config | |
| import os.path | |
| import re | |
| import shutil | |
| import tempfile | |
| import unittest | |
| import dartgenerator | |
| import database | |
| import idlnode | |
| import idlparser | |
| class DartGeneratorTestCase(unittest.TestCase): | |
| def _InDatabase(self, interface_name): | |
| return os.path.exists( | |
| os.path.join(self._database_dir, '%s.idl' % interface_name)) | |
| def _FilePathForDartInterface(self, interface_name): | |
| return os.path.join(self._generator._output_dir, 'src', 'interface', | |
| '%s.dart' % interface_name) | |
| def _InOutput(self, interface_name): | |
| return os.path.exists(self._FilePathForDartInterface(interface_name)) | |
| def _ReadOutputFile(self, interface_name): | |
| self.assertTrue(self._InOutput(interface_name)) | |
| file_path = self._FilePathForDartInterface(interface_name) | |
| f = open(file_path, 'r') | |
| content = f.read() | |
| f.close() | |
| return content, file_path | |
| def _AssertOutputSansHeaderEquals(self, interface_name, expected_content): | |
| full_actual_content, file_path = self._ReadOutputFile(interface_name) | |
| # Remove file header comments in // or multiline /* ... */ syntax. | |
| header_re = re.compile(r'^(\s*(//.*|/\*([^*]|\*[^/])*\*/)\s*)*') | |
| actual_content = header_re.sub('', full_actual_content) | |
| if expected_content != actual_content: | |
| msg = """ | |
| FILE: %s | |
| EXPECTED: | |
| %s | |
| ACTUAL: | |
| %s | |
| """ % (file_path, expected_content, actual_content) | |
| self.fail(msg) | |
| def _AssertOutputContains(self, interface_name, expected_content): | |
| actual_content, file_path = self._ReadOutputFile(interface_name) | |
| if expected_content not in actual_content: | |
| msg = """ | |
| STRING: %s | |
| Was found not in output file: %s | |
| FILE CONTENT: | |
| %s | |
| """ % (expected_content, file_path, actual_content) | |
| self.fail(msg) | |
| def _AssertOutputDoesNotContain(self, interface_name, expected_content): | |
| actual_content, file_path = self._ReadOutputFile(interface_name) | |
| if expected_content in actual_content: | |
| msg = """ | |
| STRING: %s | |
| Was found in output file: %s | |
| FILE CONTENT: | |
| %s | |
| """ % (expected_content, file_path, actual_content) | |
| self.fail(msg) | |
| def setUp(self): | |
| self._working_dir = tempfile.mkdtemp() | |
| self._output_dir = os.path.join(self._working_dir, 'output') | |
| self._database_dir = os.path.join(self._working_dir, 'database') | |
| self._auxiliary_dir = os.path.join(self._working_dir, 'auxiliary') | |
| self.assertFalse(os.path.exists(self._database_dir)) | |
| # Create database and add one interface. | |
| db = database.Database(self._database_dir) | |
| os.mkdir(self._auxiliary_dir) | |
| self.assertTrue(os.path.exists(self._database_dir)) | |
| content = """ | |
| module shapes { | |
| @A1 @A2 | |
| interface Shape { | |
| @A1 @A2 getter attribute int attr; | |
| @A1 setter attribute int attr; | |
| @A3 boolean op(); | |
| const long CONSTANT = 1; | |
| getter attribute DOMString strAttr; | |
| Shape create(); | |
| boolean compare(Shape s); | |
| Rectangle createRectangle(); | |
| void addLine(lines::Line line); | |
| void someDartType(File file); | |
| void someUnidentifiedType(UnidentifiableType t); | |
| }; | |
| }; | |
| module rectangles { | |
| @A3 | |
| interface Rectangle : @A3 shapes::Shape { | |
| void someTemplatedType(List<Shape> list); | |
| }; | |
| }; | |
| module lines { | |
| @A1 | |
| interface Line : shapes::Shape { | |
| }; | |
| }; | |
| """ | |
| parser = idlparser.IDLParser(idlparser.FREMONTCUT_SYNTAX) | |
| ast = parser.parse(content) | |
| idl_file = idlnode.IDLFile(ast) | |
| for interface in idl_file.interfaces: | |
| db.AddInterface(interface) | |
| db.Save() | |
| self.assertTrue(self._InDatabase('Shape')) | |
| self.assertTrue(self._InDatabase('Rectangle')) | |
| self.assertTrue(self._InDatabase('Line')) | |
| self._database = database.Database(self._database_dir) | |
| self._generator = dartgenerator.DartGenerator(self._auxiliary_dir, | |
| '../templates', 'test') | |
| def tearDown(self): | |
| shutil.rmtree(self._database_dir) | |
| shutil.rmtree(self._auxiliary_dir) | |
| def testBasicGeneration(self): | |
| # Generate all interfaces: | |
| self._database.Load() | |
| self._generator.Generate(self._database, self._output_dir) | |
| self._generator.Flush() | |
| self.assertTrue(self._InOutput('Shape')) | |
| self.assertTrue(self._InOutput('Rectangle')) | |
| self.assertTrue(self._InOutput('Line')) | |
| def testFilterByAnnotations(self): | |
| self._database.Load() | |
| self._generator.FilterInterfaces(self._database, ['A1', 'A2'], ['A3']) | |
| self._generator.Generate(self._database, self._output_dir) | |
| self._generator.Flush() | |
| # Only interfaces with (@A1 and @A2) or @A3 should be generated: | |
| self.assertTrue(self._InOutput('Shape')) | |
| self.assertTrue(self._InOutput('Rectangle')) | |
| self.assertFalse(self._InOutput('Line')) | |
| # Only members with (@A1 and @A2) or @A3 should be generated: | |
| # TODO(sra): make th | |
| self._AssertOutputSansHeaderEquals( | |
| 'Shape', """interface Shape { | |
| final int attr; | |
| bool op(); | |
| } | |
| """) | |
| self._AssertOutputContains('Rectangle', | |
| 'interface Rectangle extends shapes::Shape') | |
| def testTypeRenames(self): | |
| self._database.Load() | |
| # Translate 'Shape' to spanish: | |
| self._generator.RenameTypes(self._database, {'Shape': 'Forma'}, False) | |
| self._generator.Generate(self._database, self._output_dir) | |
| self._generator.Flush() | |
| # Validate that all references to Shape have been converted: | |
| self._AssertOutputContains('Forma', 'interface Forma') | |
| self._AssertOutputContains('Forma', 'Forma create();') | |
| self._AssertOutputContains('Forma', 'bool compare(Forma s);') | |
| self._AssertOutputContains('Rectangle', | |
| 'interface Rectangle extends Forma') | |
| def testQualifiedDartTypes(self): | |
| self._database.Load() | |
| self._generator.FilterMembersWithUnidentifiedTypes(self._database) | |
| self._generator.Generate(self._database, self._output_dir) | |
| self._generator.Flush() | |
| # Verify primitive conversions are working: | |
| self._AssertOutputContains('Shape', 'static const int CONSTANT = 1') | |
| self._AssertOutputContains('Shape', 'final String strAttr;') | |
| # Verify interface names are converted: | |
| self._AssertOutputContains('Shape', 'interface Shape {') | |
| self._AssertOutputContains('Shape', ' Shape create();') | |
| # TODO(sra): Why is this broken? Output contains qualified type. | |
| #self._AssertOutputContains('Shape', | |
| # 'void addLine(Line line);') | |
| self._AssertOutputContains('Shape', 'Rectangle createRectangle();') | |
| # TODO(sra): Why is this broken? Output contains qualified type. | |
| #self._AssertOutputContains('Rectangle', | |
| # 'interface Rectangle extends Shape') | |
| # Verify dart names are preserved: | |
| # TODO(vsm): Re-enable when package / namespaces are enabled. | |
| # self._AssertOutputContains('shapes', 'Shape', | |
| # 'void someDartType(File file);') | |
| # Verify that unidentified types are not removed: | |
| self._AssertOutputDoesNotContain('Shape', 'someUnidentifiedType') | |
| # Verify template conversion: | |
| # TODO(vsm): Re-enable when core collections are supported. | |
| # self._AssertOutputContains('rectangles', 'Rectangle', | |
| # 'void someTemplatedType(List<Shape> list)') | |
| if __name__ == '__main__': | |
| logging.config.fileConfig('logging.conf') | |
| if __name__ == '__main__': | |
| unittest.main() |