#!/usr/bin/env python3
#
# Copyright 2016 The Cobalt Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Unit tests for FlattenedInterface class."""

import os
import platform
import unittest

from cobalt.bindings import flatten_idls


def _TestDataPath():
  return os.path.join(os.path.dirname(__file__), 'testdata')


def _TestDataPathGenerator(files):
  test_data_path = _TestDataPath()
  for f in files:
    yield os.path.join(test_data_path, f)


@unittest.skip('Test has bitrotted.')
class FlattenedInterfacesTest(unittest.TestCase):
  # pylint: disable=protected-access

  def testFlattenIdl(self):
    test_idls = ['TestInterface.idl']
    result = flatten_idls._FlattenInterfaces(_TestDataPathGenerator(test_idls))
    self.assertEqual(1, len(result))
    self.assertEqual('TestInterface', result[0].name)
    self.assertItemsEqual(['peach', 'banana'], result[0].attributes)
    self.assertItemsEqual(['Tomato'], result[0].operations)
    self.assertItemsEqual(['PORK_CHOP'], result[0].constants)
    self.assertItemsEqual(['TestInterface'], result[0].constructors)

  def testNoInterfaceObject(self):
    test_idls = ['NoInterfaceObject.idl']
    result = flatten_idls._FlattenInterfaces(_TestDataPathGenerator(test_idls))
    self.assertEqual(1, len(result))
    self.assertEqual('NoInterfaceObject', result[0].name)

  def testNamedConstructor(self):
    test_idls = ['NamedConstructorInterface.idl']
    result = flatten_idls._FlattenInterfaces(_TestDataPathGenerator(test_idls))
    self.assertEqual(1, len(result))
    self.assertEqual('NamedConstructorInterface', result[0].name)
    self.assertItemsEqual(['Apple', 'NamedConstructorInterface'],
                          result[0].constructors)

  def testNamedConstructorWithNoInterfaceObject(self):
    test_idls = ['NamedConstructorInterfaceWithNoInterfaceObject.idl']
    result = flatten_idls._FlattenInterfaces(_TestDataPathGenerator(test_idls))
    self.assertEqual(1, len(result))
    self.assertEqual('NamedConstructorInterfaceWithNoInterfaceObject',
                     result[0].name)
    self.assertItemsEqual(['Orange'], result[0].constructors)

  def testPartialInterface(self):
    test_idls = ['TestInterface.idl', 'TestInterface_partial.idl']
    result = flatten_idls._FlattenInterfaces(_TestDataPathGenerator(test_idls))
    self.assertEqual(1, len(result))
    self.assertEqual('TestInterface', result[0].name)
    self.assertItemsEqual(['peach', 'banana', 'blueberry'],
                          result[0].attributes)

  def testImplementedInterface(self):
    test_idls = ['TestInterface.idl', 'ImplementedInterface.idl']
    result = flatten_idls._FlattenInterfaces(_TestDataPathGenerator(test_idls))
    self.assertEqual(1, len(result))
    self.assertEqual('TestInterface', result[0].name)
    self.assertItemsEqual(['Tomato', 'Onion'], result[0].operations)


@unittest.skip('Another test here has bitrotted.')
class FlattenedInterfaceDifferenceTest(unittest.TestCase):

  def testAssertsOnDifferentInterfaces(self):
    lhs = flatten_idls.FlattenedInterface(
        name='Toyota',
        operations=[],
        attributes=[],
        constants=[],
        constructors=[])
    rhs = flatten_idls.FlattenedInterface(
        name='Honda',
        operations=[],
        attributes=[],
        constants=[],
        constructors=[])
    with self.assertRaises(AssertionError):
      flatten_idls.FlattenedInterface.Difference(lhs, rhs)

  def testDifference(self):
    lhs = flatten_idls.FlattenedInterface(
        name='Bunny',
        operations=['Hop', 'Skip'],
        attributes=['wheels'],
        constants=['NUM_EARS', 'NUM_FEET', 'NUM_EYES'],
        constructors=[])
    rhs = flatten_idls.FlattenedInterface(
        name='Bunny',
        operations=['Hop', 'Jump'],
        attributes=['wheels'],
        constants=['NUM_FEET', 'NUM_EYES', 'NUM_TEETH'],
        constructors=[])
    diff = flatten_idls.FlattenedInterface.Difference(lhs, rhs)
    self.assertEqual('Bunny', diff.name)
    self.assertFalse(diff.attributes)
    self.assertItemsEqual(['Skip'], diff.operations)
    self.assertItemsEqual(['NUM_EARS'], diff.constants)
    self.assertFalse(diff.constructors)


if __name__ == '__main__':
  if platform.system() == 'Linux':
    unittest.main()
