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