# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging
import os
import os.path

import mojo_unittest
import validation_test_interfaces_mojom

# pylint: disable=E0611
from mojo import system
from mojo.bindings import messaging
from mojo.tests import validation_util
from mopy.paths import Paths

logging.basicConfig(level=logging.ERROR)
paths = Paths()


class RoutingMessageReceiver(messaging.MessageReceiver):
  def __init__(self, request, response):
    self.request = request
    self.response = response

  def Accept(self, message):
    if message.header.is_response:
      return self.response.Accept(message)
    else:
      return self.request.Accept(message)


class SinkMessageReceiver(messaging.MessageReceiverWithResponder):

  def Accept(self, message):
    return False

  def AcceptWithResponder(self, message, responder):
    return False

  def Close(self):
    pass


class HandleMock(object):
  def IsValid(self):
    return True

  def Close(self):
    pass


class ValidationTest(mojo_unittest.MojoTestCase):

  @staticmethod
  def ParseData(data_dir, filename):
    data = validation_util.ParseData(
        open(os.path.join(data_dir, filename), 'r').read())
    expect_file = filename[:-4] + 'expected'
    expected_error = open(
        os.path.join(data_dir, expect_file), 'r').read().strip();
    success = expected_error == 'PASS'
    return (filename, data, success)

  @staticmethod
  def GetData(prefix):
    data_dir = os.path.join(paths.src_root, 'mojo', 'public', 'interfaces',
                            'bindings', 'tests', 'data', 'validation')
    return [ValidationTest.ParseData(data_dir, x) for x in os.listdir(data_dir)
            if x.startswith(prefix) and x.endswith('.data')]

  def runTest(self, prefix, message_receiver):
    for (filename, data, expected) in ValidationTest.GetData(prefix):
      self.assertEquals(len(data.error_message), 0)
      handles = [HandleMock() for _ in xrange(data.num_handles)]
      message = messaging.Message(data.data, handles)
      self.assertEquals(message_receiver.Accept(message), expected,
                        'Unexpected result for test: %s' % filename)

  def testConformance(self):
    manager = validation_test_interfaces_mojom.ConformanceTestInterface.manager
    proxy = manager._InternalProxy(SinkMessageReceiver(), None)
    stub = manager._Stub(proxy)
    self.runTest('conformance_', stub)
