#!/usr/bin/env python
#
# Copyright 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.

import difflib
import filecmp
import getopt
import logging
import os
import shutil
import subprocess
import sys
import unittest

from vts.utils.python.common import cmd_utils


class VtscTester(unittest.TestCase):
    """Integration test runner for vtsc in generating the driver/profiler code.

    Runs vtsc with specified mode on a bunch of files and compares the output
    results with canonical ones. Exit code is 0 iff all tests pass.
    Note: need to run the script from the source root to preserve the correct
          path.

    Usage:
        python test_vtsc.py path_to_vtsc canonical_dir output_dir

    example:
        python test/vts/compilation_tools/vtsc/test/test_vtsc.py vtsc
        test/vts/compilation_tools/vtsc/test/golden/ temp_output

    Attributes:
        _hidl_gen_path: the path to run hidl-gen
        _vtsc_path: the path to run vtsc.
        _canonical_dir: root directory contains canonical files for comparison.
        _output_dir: root directory that stores all output files.
        _errors: number of errors generates during the test.
        _temp_dir: temp dir to store the .vts file generated by hidl-gen.
    """

    def __init__(self, testName, hidl_gen_path, vtsc_path, canonical_dir,
                 output_dir):
        super(VtscTester, self).__init__(testName)
        self._hidl_gen_path = hidl_gen_path
        self._vtsc_path = vtsc_path
        self._canonical_dir = canonical_dir
        self._output_dir = output_dir
        self._errors = 0
        self._temp_dir = "test/vts/specification/hal"

    def setUp(self):
        """Removes output dir to prevent interference from previous runs."""
        self.RemoveOutputDir()

    def tearDown(self):
        """If successful, removes the output dir for clean-up."""
        if self._errors == 0:
            self.RemoveOutputDir()

    def testAll(self):
        """Run all tests. """
        self.TestDriver()
        self.TestProfiler()
        self.TestFuzzer()
        self.assertEqual(self._errors, 0)

    def TestDriver(self):
        """Run tests for DRIVER mode. """
        logging.info("Running TestDriver test case.")
        #Tests for Hidl Hals.
        self.GenerateVtsFile("android.hardware.nfc@1.0")
        for component_name in ["Nfc", "types", "NfcClientCallback"]:
            self.RunTest("DRIVER",
                         os.path.join(self._temp_dir, component_name + ".vts"),
                         "%s.driver.cpp" % component_name)
        #Tests for conventional Hals.
        for component_name in [
                "BluetoothHalV1", "BluetoothHalV1bt_interface_t", "WifiHalV1"
        ]:
            self.RunTest("DRIVER",
                         "test/vts/specification/hal_conventional/%s.vts" %
                         component_name, "%s.driver.cpp" % component_name)
        #Tests for shared libraries.
        for component_name in ["libcV1"]:
            self.RunTest("DRIVER", "test/vts/specification/lib_bionic/%s.vts" %
                         component_name, "%s.driver.cpp" % component_name)

    def TestProfiler(self):
        """Run tests for PROFILER mode. """
        logging.info("Running TestProfiler test case.")
        self.GenerateVtsFile("android.hardware.nfc@1.0")
        for component_name in ["Nfc", "types", "NfcClientCallback"]:
            self.RunTest("PROFILER",
                         os.path.join(self._temp_dir, component_name + ".vts"),
                         "%s.profiler.cpp" % component_name)

    def TestFuzzer(self):
        """Run tests for Fuzzer mode. """
        logging.info("Running TestProfiler test case.")
        self.GenerateVtsFile("android.hardware.renderscript@1.0")
        for component_name in ["Context", "Device", "types"]:
            self.RunTest("FUZZER",
                         os.path.join(self._temp_dir, component_name + ".vts"),
                         "%s.fuzzer.cpp" % component_name, "SOURCE")

    def RunFuzzerTest(self, mode, vts_file_path, source_file_name):
        vtsc_cmd = [
            self._vtsc_path, "-m" + mode, vts_file_path,
            os.path.join(self._output_dir, mode),
            os.path.join(self._output_dir, mode, "")
        ]
        return_code = cmd_utils.RunCommand(vtsc_cmd)

        canonical_source_file = os.path.join(self._canonical_dir, mode,
                                             source_file_name)
        output_source_file = os.path.join(self._output_dir, mode,
                                          source_file_name)
        self.CompareOutputFile(output_source_file, canonical_source_file)

    def GenerateVtsFile(self, hal_package_name):
        """Run hidl-gen to generate the .vts files for the give hal package.

        Args:
            hal_package_name: name of hal package e.g. android.hardware.nfc@1.0
        """
        hidl_gen_cmd = [
            self._hidl_gen_path, "-o" + self._temp_dir, "-Lvts",
            "-randroid.hardware:hardware/interfaces",
            "-randroid.hidl:system/libhidl/transport", hal_package_name
        ]
        return_code = cmd_utils.RunCommand(hidl_gen_cmd)
        if (return_code != 0):
            self.Error("Fail to execute command: %s" % hidl_gen_cmd)
        [hal_name, hal_version] = hal_package_name.split("@")
        output_dir = os.path.join(self._temp_dir,
                                  hal_name.replace(".", "/"), hal_version)
        for file in os.listdir(output_dir):
            if file.endswith(".vts"):
                os.rename(
                    os.path.join(output_dir, file),
                    os.path.join(self._temp_dir, file))

    def RunTest(self, mode, vts_file_path, source_file_name, file_type="BOTH"):
        """Run vtsc with given mode for the give vts file and compare the
           output results.

        Args:
            mode: the vtsc mode for generated code. e.g. DRIVER / PROFILER.
            vts_file_path: path of the input vts file.
            source_file_name: name of the generated source file.
            file_type: type of file e.g. HEADER / SOURCE / BOTH.
        """
        vtsc_cmd = [
            self._vtsc_path, "-m" + mode, vts_file_path,
            os.path.join(self._output_dir, mode),
            os.path.join(self._output_dir, mode, source_file_name)
        ]
        return_code = cmd_utils.RunCommand(vtsc_cmd)
        if (return_code != 0):
            self.Error("Fail to execute command: %s" % vtsc_cmd)

        if (file_type == "HEADER" or file_type == "BOTH"):
            header_file_name = vts_file_path + ".h"
            canonical_header_file = os.path.join(self._canonical_dir, mode,
                                                 header_file_name)
            output_header_file = os.path.join(self._output_dir, mode,
                                              header_file_name)
            self.CompareOutputFile(output_header_file, canonical_header_file)
        if (file_type == "SOURCE" or file_type == "BOTH"):
            canonical_source_file = os.path.join(self._canonical_dir, mode,
                                                 source_file_name)
            output_source_file = os.path.join(self._output_dir, mode,
                                              source_file_name)
            self.CompareOutputFile(output_source_file, canonical_source_file)
        else:
            self.Error("No such file_type: %s" % file_type)

    def CompareOutputFile(self, output_file, canonical_file):
        """Compares a given file and the corresponding one under canonical_dir.

        Args:
            canonical_file: name of the canonical file.
            output_file: name of the output file.
        """
        if not os.path.isfile(canonical_file):
            self.Error("Generated unexpected file: %s (for %s)" %
                       (output_file, canonical_file))
        else:
            if not filecmp.cmp(output_file, canonical_file):
                self.Error(
                    "output file: %s does not match the canonical_file: "
                    "%s" % (output_file, canonical_file))
                self.PrintDiffFiles(output_file, canonical_file)

    def PrintDiffFiles(self, output_file, canonical_file):
        with open(output_file, 'r') as file1:
            with open(canonical_file, 'r') as file2:
                diff = difflib.unified_diff(
                    file1.readlines(),
                    file2.readlines(),
                    fromfile=output_file,
                    tofile=canonical_file)
        for line in diff:
            logging.error(line)

    def Error(self, string):
        """Prints an error message and increments error count."""
        logging.error(string)
        self._errors += 1

    def RemoveOutputDir(self):
        """Remove the output_dir if it exists."""
        if os.path.exists(self._output_dir):
            shutil.rmtree(self._output_dir)
        if os.path.exists(self._temp_dir):
            shutil.rmtree(self._temp_dir)


if __name__ == "__main__":
    # Default values of the input parameter, could be overridden by command.
    vtsc_path = "vtsc"
    canonical_dir = "test/vts/compilation_tools/vtsc/test/golden/"
    output_dir = "test/vts/compilation_tools/vtsc/test/temp_coutput/"
    # Parse the arguments and set the provided value for
    # hidl-gen/vtsc_path/canonical_dar/output_dir.
    try:
        opts, _ = getopt.getopt(sys.argv[1:], "h:p:c:o:")
    except getopt.GetoptError, err:
        print "Usage: python test_vtsc.py [-h hidl_gen_path] [-p vtsc_path] " \
              "[-c canonical_dir] [-o output_dir]"
        sys.exit(1)
    for opt, val in opts:
        if opt == "-h":
            hidl_gen_path = val
        elif opt == "-p":
            vtsc_path = val
        elif opt == "-c":
            canonical_dir = val
        elif opt == "-o":
            output_dir = val
        else:
            print "unhandled option %s" % (opt, )
            sys.exit(1)

    suite = unittest.TestSuite()
    suite.addTest(
        VtscTester('testAll', hidl_gen_path, vtsc_path, canonical_dir,
                   output_dir))
    result = unittest.TextTestRunner(verbosity=2).run(suite)
    if not result.wasSuccessful():
        sys.exit(-1)
