# Copyright 2017 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.
"""Contains utilities to create black box tests and run them."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import argparse
import importlib
import logging
import random
import socket
import sys
import unittest

from cobalt.black_box_tests import black_box_cobalt_runner
from cobalt.black_box_tests.proxy_server import ProxyServer
from starboard.tools import abstract_launcher
from starboard.tools import build
from starboard.tools import command_line
from starboard.tools import log_level

_DISABLED_BLACKBOXTEST_CONFIGS = [
    'android-arm/devel',
    'android-arm64/devel',
    'android-x86/devel',
    'raspi-0/devel',
]

_PORT_SELECTION_RETRY_LIMIT = 10
_PORT_SELECTION_RANGE = [5000, 7000]
# List of blocked ports.
_RESTRICTED_PORTS = [6000, 6665, 6666, 6667, 6668, 6669, 6697]
_SERVER_EXIT_TIMEOUT_SECONDS = 30
_SOCKET_SUCCESS = 0
# These tests can only be run on platforms whose app launcher can send suspend/
# resume signals.
_TESTS_NEEDING_SYSTEM_SIGNAL = [
    'cancel_sync_loads_when_suspended',
    'pointer_test',
    'preload_font',
    'preload_visibility',
    'preload_launch_parameter',
    'signal_handler_doesnt_crash',
    'suspend_visibility',
    'timer_hit_after_preload',
    'timer_hit_in_preload',
]
# These tests only need app launchers with webdriver.
_TESTS_NO_SIGNAL = [
    'allow_eval',
    'compression_test',
    'disable_eval_with_csp',
    # http_cache is disabled due to flakiness. Planned update to make use of
    # transferSize rather than load timings to make it more consistent.
    'http_cache',
    'persistent_cookie',
    'soft_mic_platform_service_test',
    'text_encoding_test',
    'web_crypto_api_test',
    'web_debugger',
    'web_platform_tests',
    'web_worker_test',
    'service_worker_test',
]
# These tests can only be run on platforms whose app launcher can send deep
# links.
_TESTS_NEEDING_DEEP_LINK = [
    'deep_links',
]
# Location of test files.
_TEST_DIR_PATH = 'cobalt.black_box_tests.tests.'
# Platform configuration and device information parameters.
_launcher_params = None
# Binding address used to create the test server.
_binding_address = None
# Port used to create the web platform test http server.
_wpt_http_port = None


class BlackBoxTestCase(unittest.TestCase):
  """Base class for Cobalt black box test cases."""

  def __init__(self, *args, **kwargs):
    super(BlackBoxTestCase, self).__init__(*args, **kwargs)
    self.launcher_params = _launcher_params
    self.platform_config = build.GetPlatformConfig(_launcher_params.platform)
    self.cobalt_config = self.platform_config.GetApplicationConfiguration(
        'cobalt')

  @classmethod
  def setUpClass(cls):
    super(BlackBoxTestCase, cls).setUpClass()
    logging.info('Running %s', cls.__name__)

  @classmethod
  def tearDownClass(cls):
    super(BlackBoxTestCase, cls).tearDownClass()
    logging.info('Done %s', cls.__name__)

  def CreateCobaltRunner(self, url, target_params=None):
    all_target_params = list(target_params) if target_params else []
    if _launcher_params.target_params is not None:
      all_target_params += _launcher_params.target_params
    new_runner = black_box_cobalt_runner.BlackBoxCobaltRunner(
        launcher_params=_launcher_params,
        url=url,
        target_params=all_target_params)
    return new_runner

  def GetBindingAddress(self):
    return _binding_address

  def GetWptHttpPort(self):
    return _wpt_http_port


def LoadTests(launcher_params):
  launcher = abstract_launcher.LauncherFactory(
      launcher_params.platform,
      'cobalt',
      launcher_params.config,
      device_id=launcher_params.device_id,
      target_params=None,
      output_file=None,
      out_directory=launcher_params.out_directory,
      loader_platform=launcher_params.loader_platform,
      loader_config=launcher_params.loader_config,
      loader_out_directory=launcher_params.loader_out_directory)

  test_targets = _TESTS_NO_SIGNAL

  if launcher.SupportsSuspendResume():
    test_targets += _TESTS_NEEDING_SYSTEM_SIGNAL

  if launcher.SupportsDeepLink():
    test_targets += _TESTS_NEEDING_DEEP_LINK

  test_suite = unittest.TestSuite()
  for test in test_targets:
    test_suite.addTest(unittest.TestLoader().loadTestsFromModule(
        importlib.import_module(_TEST_DIR_PATH + test)))
  return test_suite


class BlackBoxTests(object):
  """Helper class to run all black box tests and return results."""

  def __init__(self,
               server_binding_address,
               proxy_address=None,
               proxy_port=None,
               test_name=None,
               wpt_http_port=None,
               device_ips=None,
               device_id=None):
    # Setup global variables used by test cases.
    global _launcher_params
    _launcher_params = command_line.CreateLauncherParams()
    # Keep other modules from seeing these args.
    sys.argv = sys.argv[:1]
    global _binding_address
    _binding_address = server_binding_address
    # Port used to create the web platform test http server. If not specified,
    # a random free port is used.
    if wpt_http_port is None:
      wpt_http_port = str(self.GetUnusedPort([server_binding_address]))
    global _wpt_http_port
    _wpt_http_port = wpt_http_port
    # TODO: Remove generation of --dev_servers_listen_ip once executable will
    # be able to bind correctly with incomplete support of IPv6
    if device_id and IsValidIpAddress(device_id):
      _launcher_params.target_params.append(
          '--dev_servers_listen_ip={}'.format(device_id))
    elif IsValidIpAddress(server_binding_address):
      _launcher_params.target_params.append(
          '--dev_servers_listen_ip={}'.format(server_binding_address))
    _launcher_params.target_params.append(
        '--web-platform-test-server=http://web-platform.test:{}'.format(
            wpt_http_port))

    # Port used to create the proxy server. If not specified, a random free
    # port is used.
    if proxy_port is None:
      proxy_port = str(self.GetUnusedPort([server_binding_address]))
    if proxy_address is None:
      proxy_address = server_binding_address
    _launcher_params.target_params.append('--proxy=%s:%s' %
                                          (proxy_address, proxy_port))

    self.proxy_port = proxy_port
    self.test_name = test_name
    self.device_ips = device_ips

    # Test domains used in web platform tests to be resolved to the server
    # binding address.
    hosts = [
        'web-platform.test', 'www.web-platform.test', 'www1.web-platform.test',
        'www2.web-platform.test', 'xn--n8j6ds53lwwkrqhv28a.web-platform.test',
        'xn--lve-6lad.web-platform.test'
    ]
    self.host_resolve_map = {host: server_binding_address for host in hosts}

  def Run(self):
    if self.proxy_port == '-1':
      return 1

    # Temporary means to determine if we are running on CI
    # TODO: Update to IS_CI environment variable or similar
    out_dir = _launcher_params.out_directory
    is_ci = out_dir and 'mh_lab' in out_dir  # pylint: disable=unsupported-membership-test

    target = (_launcher_params.platform, _launcher_params.config)
    if is_ci and '{}/{}'.format(*target) in _DISABLED_BLACKBOXTEST_CONFIGS:
      logging.warning('Blackbox tests disabled for platform:%s config:%s',
                      *target)
      return 0

    logging.info('Using proxy port: %s', self.proxy_port)

    with ProxyServer(
        port=self.proxy_port,
        host_resolve_map=self.host_resolve_map,
        client_ips=self.device_ips):
      if self.test_name:
        suite = unittest.TestLoader().loadTestsFromModule(
            importlib.import_module(_TEST_DIR_PATH + self.test_name))
      else:
        suite = LoadTests(_launcher_params)
      return_code = not unittest.TextTestRunner(
          verbosity=0, stream=sys.stdout).run(suite).wasSuccessful()
      return return_code

  def GetUnusedPort(self, addresses):
    """Find a free port on the list of addresses by pinging with sockets."""

    if not addresses:
      logging.error('Can not find unused port on invalid addresses.')
      return -1

    socks = []
    for address in addresses:
      socks.append((address, socket.socket(socket.AF_INET, socket.SOCK_STREAM)))
    try:
      for _ in range(_PORT_SELECTION_RETRY_LIMIT):
        port = random.choice([
            i for i in range(_PORT_SELECTION_RANGE[0], _PORT_SELECTION_RANGE[1])
            if i not in _RESTRICTED_PORTS
        ])
        unused = True
        for sock in socks:
          result = sock[1].connect_ex((sock[0], port))
          if result == _SOCKET_SUCCESS:
            unused = False
            break
        if unused:
          return port
      logging.error('Can not find unused port on addresses within %s attempts.',
                    _PORT_SELECTION_RETRY_LIMIT)
      return -1
    finally:
      for sock in socks:
        sock[1].close()


def IsValidIpAddress(address):
  """Checks if address is valid IP address."""
  return IsValidIpv4Address(address) or IsValidIpv6Address(address)


def IsValidIpv4Address(address):
  """Checks if address is valid IPv4 address."""
  try:
    socket.inet_pton(socket.AF_INET, address)
    return True
  except socket.error:  # not a valid address
    return False


def IsValidIpv6Address(address):
  """Checks if address is valid IPv6 address."""
  try:
    socket.inet_pton(socket.AF_INET6, address)
    return True
  except socket.error:  # not a valid address
    return False


def main():
  parser = argparse.ArgumentParser()
  parser.add_argument('-v', '--verbose', required=False, action='store_true')
  parser.add_argument(
      '--server_binding_address',
      default='127.0.0.1',
      help='Binding address used to create the test server.')
  parser.add_argument(
      '--proxy_address',
      default=None,
      help=('Address to the proxy server that all black box'
            'tests are run through. If not specified, the'
            'server binding address is used.'))
  parser.add_argument(
      '--proxy_port',
      default=None,
      help=('Port used to create the proxy server that all'
            'black box tests are run through. If not'
            'specified, a random free port is used.'))
  parser.add_argument(
      '--test_name',
      default=None,
      help=('Name of test to be run. If not specified, all '
            'tests are run.'))
  parser.add_argument(
      '--wpt_http_port',
      default=None,
      help=('Port used to create the web platform test http'
            'server. If not specified, a random free port is'
            'used.'))
  parser.add_argument(
      '--device_id',
      default=None,
      help=('ID of test device to connect. If specified, it will be passed '
            'as --dev_servers_listen_ip param on the test device.'))
  parser.add_argument(
      '--device_ips',
      default=None,
      nargs='*',
      help=('IPs of test devices that will be allowed to connect. If not '
            'specified, all IPs will be allowed to connect.'))
  args, _ = parser.parse_known_args()

  log_level.InitializeLogging(args)

  test_object = BlackBoxTests(args.server_binding_address, args.proxy_address,
                              args.proxy_port, args.test_name,
                              args.wpt_http_port, args.device_ips,
                              args.device_id)
  sys.exit(test_object.Run())


if __name__ == '__main__':
  # Running this script on the command line and importing this file are
  # different and create two modules.
  # Import this module to ensure we are using the same module as the tests to
  # make module-owned variables like launcher_param accessible to the tests.
  main_module = importlib.import_module(
      'cobalt.black_box_tests.black_box_tests')
  sys.exit(main_module.main())
