#
# Copyright (C) 2016 The Android Open Source Project
#
# 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.
#
from __future__ import absolute_import
from __future__ import print_function

import logging
import os
import subprocess
import sys

import adb  # pylint: disable=import-error
import build.lib.build_support
import tests.filters
import tests.printers
import tests.ndk
import tests.testlib
import tests.util


def logger():
    return logging.getLogger(__name__)


def get_device_abis(device):
    # 64-bit devices list their ABIs differently than 32-bit devices. Check all
    # the possible places for stashing ABI info and merge them.
    abi_properties = [
        'ro.product.cpu.abi',
        'ro.product.cpu.abi2',
        'ro.product.cpu.abilist',
    ]
    abis = set()
    properties = device.get_props()
    for abi_prop in abi_properties:
        if abi_prop in properties:
            abis.update(properties[abi_prop].split(','))

    return sorted(list(abis))


def check_adb_works_or_die(device, abi):
    supported_abis = get_device_abis(device)
    if abi is not None and abi not in supported_abis:
        msg = ('The test device ({}) does not support the requested ABI '
               '({}).\nSupported ABIs: {}'.format(device.serial, abi,
                                                  ', '.join(supported_abis)))
        sys.exit(msg)


def can_use_asan(device, abi, api, toolchain):
    # ASAN is currently only supported for 32-bit ARM and x86...
    if not abi.startswith('armeabi') and not abi == 'x86':
        logger().info('Cannot use ASAN: unsupported ABI (%s)', abi)
        return False

    # From non-Windows (asan_device_setup is a shell script)...
    if os.name == 'nt':
        logger().info('Cannot use ASAN: Windows is not supported')
        return False

    # On KitKat and newer...
    if api < 19:
        logger().info('Cannot use ASAN: device is too old '
                      '(is android-%s, minimum android-19)', api)
        return False

    # When using clang...
    if toolchain != 'clang':
        logger().info('Cannot use ASAN: GCC is not supprted')
        return False

    # On rooted devices.
    if int(device.get_prop('ro.debuggable')) == 0:
        logger().info('Cannot use ASAN: device must be rooted')
        return False

    return True


def asan_device_setup():
    path = os.path.join(
        os.environ['NDK'], 'toolchains', 'llvm', 'prebuilt',
        tests.ndk.get_host_tag(), 'bin', 'asan_device_setup')
    try:
        # Don't want to use check_call because we want to keep this quiet
        # unless there's a problem.
        subprocess.check_output([path], stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as ex:
        print(ex.output)
        raise ex


class ResultStats(object):
    def __init__(self, suites, results):
        self.num_tests = sum(len(s) for s in results.values())

        zero_stats = {'pass': 0, 'skip': 0, 'fail': 0}
        self.global_stats = dict(zero_stats)
        self.suite_stats = {suite: dict(zero_stats) for suite in suites}
        self._analyze_results(results)

    def _analyze_results(self, results):
        for suite, test_results in results.items():
            for result in test_results:
                if result.failed():
                    self.suite_stats[suite]['fail'] += 1
                    self.global_stats['fail'] += 1
                elif result.passed():
                    self.suite_stats[suite]['pass'] += 1
                    self.global_stats['pass'] += 1
                else:
                    self.suite_stats[suite]['skip'] += 1
                    self.global_stats['skip'] += 1


def run_single_configuration(ndk_path, out_dir, printer, abi, toolchain,
                             build_api_level=None, verbose_build=False,
                             suites=None, test_filter=None,
                             device_serial=None, skip_run=False):
    """Runs all the tests for the given configuration.

    Sets up the necessary build flags and environment, checks that the device
    under test is in working order and performs device setup (if running device
    tests), and finally runs the tests for the selected suites.

    Args:
        ndk_path: Absolute path the the NDK being tested.
        out_dir: Directory to use when building tests.
        printer: Instance of printers.Printer that will be used to print test
            results.
        abi: ABI to test against.
        toolchain: Toolchain to build with.
        build_api_level: API level to build against. If None, will default to
            the value set in the test's Application.mk, or ndk-build's default.
        verbose_build: Show verbose output from ndk-build and cmake.
        suites: Set of strings denoting which test suites to run. Possible
            values are 'awk', 'build', and 'device'. If None, will run all
            suites.
        test_filter: Filter string for selecting a subset of tests.
        device_serial: Serial number of the device to use for device tests. If
            none, will try to find a device from ANDROID_SERIAL or a unique
            attached device.
        skip_run: Skip running the tests; just build. Useful for post-build
            steps if CI doesn't have the device available.

    Returns:
        Tuple of (result, details).

        result is True if all tests completed successfully, False if there were
        failures.

        details is the dict returned by tests.TestRunner: {
            "suite_name": [
                tests.TestResult,
                ...
            ],
            ...
        }
    """
    if suites is None:
        suites = ('awk', 'build', 'device')

    os.chdir(os.path.dirname(os.path.realpath(__file__)))

    os.environ['NDK'] = ndk_path

    ndk_build_flags = []
    cmake_flags = []
    if verbose_build:
        # Don't decrease our log level.
        root_logger = logging.getLogger()
        if root_logger.getEffectiveLevel() != logging.DEBUG:
            root_logger.setLevel(logging.INFO)
        ndk_build_flags.append('V=1')
        cmake_flags.append('-DCMAKE_VERBOSE_MAKEFILE=ON')

    force_pie = False

    # Do this early so we find any device issues now rather than after we've
    # run all the build tests.
    if 'device' in suites and not skip_run:
        device = adb.get_device(device_serial)
        check_adb_works_or_die(device, abi)
        device_api_level = int(device.get_prop('ro.build.version.sdk'))

        # PIE is required in L. All of the device tests are written toward the
        # ndk-build defaults, so we need to inform the build that we need PIE
        # if we're running on a newer device.
        if device_api_level >= 21:
            force_pie = True
            ndk_build_flags.append('APP_PIE=true')
            cmake_flags.append('-DANDROID_PIE=TRUE')

        os.environ['ANDROID_SERIAL'] = device.serial

        if can_use_asan(device, abi, device_api_level, toolchain):
            asan_device_setup()

        # Do this as part of initialization rather than with a `mkdir -p` later
        # because Gingerbread didn't actually support -p :(
        device.shell_nocheck(['rm -r /data/local/tmp/ndk-tests 2>&1'])
        device.shell(['mkdir /data/local/tmp/ndk-tests 2>&1'])
        device.shell_nocheck(['rm -r /data/local/tmp/cmake-tests 2>&1'])
        device.shell(['mkdir /data/local/tmp/cmake-tests 2>&1'])
    elif skip_run:
        # We need to fake these if we're skipping running the tests. Set device
        # to None so any attempt to interact with it will raise an error, and
        # set the API level to the minimum supported by the ABI so
        # test_config.py checks still behave as expected.
        device = None
        device_api_level = build.lib.build_support.minimum_platform_level(abi)

    runner = tests.testlib.TestRunner(printer)
    if 'awk' in suites:
        awk_scanner = tests.testlib.AwkTestScanner()
        runner.add_suite('awk', 'awk', awk_scanner)
    if 'build' in suites:
        build_scanner = tests.testlib.BuildTestScanner()
        build_scanner.add_build_configuration(
            abi, build_api_level, toolchain, force_pie, verbose_build)
        runner.add_suite('build', 'build', build_scanner)
    if 'device' in suites:
        device_scanner = tests.testlib.DeviceTestScanner()
        device_scanner.add_device_configuration(
            abi, build_api_level, toolchain, force_pie, verbose_build, device,
            device_api_level, skip_run)
        runner.add_suite('device', 'device', device_scanner)

    test_filters = tests.filters.TestFilter.from_string(test_filter)
    results = runner.run(out_dir, test_filters)

    stats = ResultStats(suites, results)

    printer.print_summary(results, stats)
    return stats.global_stats['fail'] == 0, results


def run_tests(ndk_path, device, abi, toolchain, out_dir, log_dir, test_filter):
    print('Running {} {} tests for {}... '.format(toolchain, abi, device),
          end='')
    sys.stdout.flush()

    toolchain_name = 'gcc' if toolchain == '4.9' else toolchain
    log_file_name = '{}-{}-{}.log'.format(toolchain_name, abi, device.version)
    with open(os.path.join(log_dir, log_file_name), 'w') as log_file:
        printer = tests.printers.FilePrinter(log_file)
        good, details = run_single_configuration(
            ndk_path, out_dir, printer, abi, toolchain,
            device_serial=device.serial, test_filter=test_filter)
        print('PASS' if good else 'FAIL')
        return good, details


def run_for_fleet(ndk_path, fleet, out_dir, log_dir, test_filter,
                  use_color=False):
    # Note that we are duplicating some testing here.
    #
    # * The awk tests only need to be run once because they do not vary by
    #   configuration.
    # * The build tests only vary per-device by the PIE configuration, so we
    #   only need to run them twice per ABI/toolchain.
    # * The build tests are already run as a part of the build process.
    results = []
    details = {}
    good = True
    for version in fleet.get_versions():
        details[version] = {}
        for abi in fleet.get_abis(version):
            details[version][abi] = {}
            device = fleet.get_device(version, abi)
            for toolchain in ('clang', '4.9'):
                if device is None:
                    results.append('android-{} {} {}: {}'.format(
                        version, abi, toolchain, 'SKIP'))
                    continue

                details[version][abi][toolchain] = None

                result, run_details = run_tests(
                    ndk_path, device, abi, toolchain, out_dir, log_dir,
                    test_filter)
                pass_label = tests.util.maybe_color('PASS', 'green', use_color)
                fail_label = tests.util.maybe_color('FAIL', 'red', use_color)
                results.append('android-{} {} {}: {}'.format(
                    version, abi, toolchain,
                    pass_label if result else fail_label))
                details[version][abi][toolchain] = run_details
                if not result:
                    good = False

    print('\n'.join(results))
    return good, details
