| #!/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() |