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

''' Autotest program for verifying trackpad X level driver '''

import glob
import logging
import os
import shutil

import trackpad_util
import trackpad_summary

from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros import cros_ui

from trackpad_device import TrackpadDevice
from trackpad_util import read_trackpad_test_conf, get_prefix, KEY_LOG, KEY_SEQ
from Xcapture import Xcapture
from Xcheck import Xcheck


class TrackpadData:
    ''' An empty class to hold global trackpad test data for communication
    between threads
    '''
    pass

''' tdata: trackpad data as a global variable used between threads
(1) The main thread runs in the hardware_Trackpad class will derive the test
    result through Xcheck class. The test result is stored in tdata.
    It requires read/write access to tdata.
(2) A second thread will launch a HTTP server that communicates with a
    chrome extension on the target machine to display the test result
    on the fly during the test procedure. When the result of a gesture file
    test has been derived, it is sent to the browser for display.

Note: it is not required to use mutex to protect the global tdata for two
    reasons:
    - tdata will be accessed sequentially between the two threads.
    - The main thread is a writer, and the HTTP server thread is a reader.
      No lock is needed in this case.
'''
tdata = TrackpadData()


class hardware_Trackpad(test.test):
    ''' Play back device packets through the trackpad device. Capture the
    resultant X events. Analyze whether the X events meet the criteria
    of the functionality.
    '''
    version = 1

    def initialize(self):
        self.vlog = trackpad_util.VerificationLog()
        self.local_path = self.bindir
        self.model = trackpad_util.get_model()
        self.regression_gestures = None
        self.autotest_log_path = trackpad_util.get_logger_filename(
                logging.getLogger(), logging.INFO)

        # Get some parameters from the config file
        self.regression_subset_list = read_trackpad_test_conf(
                'regression_subset_list', self.local_path)
        self.regression_default_subset = read_trackpad_test_conf(
                'regression_default_subset', self.local_path)
        self.functionality_list = read_trackpad_test_conf(
                'functionality_list', self.local_path)
        self.regression_gestures_dict = read_trackpad_test_conf(
                'regression_gestures_dict', self.local_path)

        # Get some file paths from the config file
        self.gesture_files_path_results = self.read_gesture_files_path(
                self.local_path, 'gesture_files_path_results')
        self.gesture_files_subpath_regression = self.read_gesture_files_path(
                self.local_path, 'gesture_files_subpath_regression')
        self.regression_gesture_sets = self.read_gesture_files_path(
                self.local_path, 'regression_gesture_sets')
        self.gesture_files_path_autotest = self.read_gesture_files_path(
                self.local_path, 'gesture_files_path_autotest')
        self.gesture_files_path_latest = self.read_gesture_files_path(
                self.local_path, 'gesture_files_path_latest')

    def read_gesture_files_path(self, local_path, name):
        ''' Read gesture file path from config file. '''
        pathname = read_trackpad_test_conf(name, local_path)
        logging.info('Path of %s: %s' % (name, pathname))
        return pathname

    def _is_in_regression_gestures(self, gesture_file):
        ''' Determine if a gesture file is in the regression gestures list.

        For current settings,
        - long regression test: self.regression_gestures is None, which means
                                all gesture files will be used for regression
                                test.
        - short regression test: self.regression_gestures is read from the file
                                 './data/gestures/regression_gestures_short'
                                 Only gesture files listed in the file will be
                                 used for regression test.

        A gesture file name looks like
            'click-no_cursor_wobble.tap-alex-user-20120430_114910.dat'
        We want to extract the left half part of the file name which looks like
            'click-no_cursor_wobble.tap'
        and check if this gesture exists in the regression_gestures.
        '''
        result = gesture_file.split('-%s-' % self.model)
        gesture = None if result is None else result[0]
        return (self.regression_gestures is None or
                gesture in self.regression_gestures)

    def _extract_tarball_to_work_dir(self, subset):
        ''' Extract the gesture files tarball to working directory '''
        # Set up an empty work directory
        gesture_files_path_work = self.read_gesture_files_path(
                self.local_path, 'gesture_files_path_work')
        if os.path.isdir(gesture_files_path_work):
            shutil.rmtree(gesture_files_path_work, True)
        if not os.path.isdir(gesture_files_path_work):
            os.makedirs(gesture_files_path_work)
            logging.info('  The work path "%s" is created successfully.' %
                         gesture_files_path_work)

        regression_tarball = 'regression_files_%s.tar' % subset
        regression_tarball_path = os.path.join(self.local_path,
                self.gesture_files_subpath_regression, regression_tarball)

        if not os.path.isfile(regression_tarball_path):
            logging.warn('  The regression tarball does not exist: "%s"' %
                         regression_tarball_path)
            return None

        # Extract files from the tarball
        strip_level = 0 if subset == 'short' else 1
        untar_cmd = ('tar --strip-components %d -xvf %s -C %s' %
                     (strip_level,
                      regression_tarball_path,
                      gesture_files_path_work))
        rc = utils.system(untar_cmd)
        if rc != 0:
            logging.warn('  Failed in executing "%s".' % untar_cmd)
            return None
        logging.info('  Succeeded in executing "%s".' % untar_cmd)
        return gesture_files_path_work

    def _set_regression_gestures(self, subset):
        ''' Read regression_gestures based on the subset

        When self.regression_gestures is set to None, it means that all of the
        gesture files in the specified gesture set will be used.
        '''
        if subset is None or self.regression_gestures_dict[subset] is None:
            self.regression_gestures = None
        else:
            gestures_path = os.path.join(self.local_path,
                                         self.regression_gestures_dict[subset])
            execfile(gestures_path, globals())
            if self.model in regression_gestures:
                self.regression_gestures = regression_gestures[self.model]
            else:
                self.regression_gestures = baseline_regression_gestures

    def _get_regression_gesture_set(self, subset):
        ''' Get the regression gesture set. '''
        model = self.model
        if subset not in self.regression_subset_list:
            subset = self.regression_default_subset

        # Skip those models that are not specified the regression gesture sets.
        # There are two possible reasons:
        #   (1) the gestures are not captured yet.
        #   (2) it is a model without built-in trackpad.
        if model not in self.regression_gesture_sets[subset]:
            return None

        regression_gesture_set = self.regression_gesture_sets[subset][model]
        gesture_set_path = os.path.join(self.local_path,
                self.gesture_files_subpath_regression, regression_gesture_set)

        # Make a symlink for autotest.
        trackpad_util.write_symlink(gesture_set_path,
                                    self.gesture_files_path_autotest)

        return subset

    def _setup_gesture_files_path(self, test_set, subset):
        ''' Set up gesture files path

        If it is a tarball, extract files from the tarball and set up its path.
        If it is an ordinary directory, just returns its path.
        '''
        # If this is a regression test, let gesture_files_path_autotest
        # point to the regression gesture set specified in conf.
        if test_set == 'regression':
            subset = self._get_regression_gesture_set(subset)

        # If this is a test on a gesture set captured in the local machine,
        # let gesture_files_path_autotest point to the 'latest' symlink if it
        # exists. Otherwise, let it point to the default regression gesture set.
        elif test_set == 'localhost':
            if os.path.exists(self.gesture_files_path_latest):
                trackpad_util.write_symlink(self.gesture_files_path_latest,
                                            self.gesture_files_path_autotest)
            else:
                subset = self._get_regression_gesture_set(subset)

        # Skip those models without the regression gesture sets.
        if subset is None:
            return None

        # Determine gestures to test
        self._set_regression_gestures(subset)

        logging.info('  test_set: %s' % test_set)
        logging.info('  subset: %s' % subset)
        logging.info('  gesture_files_path_autotest: %s' %
                     os.path.realpath(self.gesture_files_path_autotest))

        return self.gesture_files_path_autotest

    def run_once(self, test_set='localhost', subset=None):
        ''' test_set determines the path of gesture files.

        The test_set could be
            localhost: run locally from the client side
            regression: run by control.regression
        '''
        global tdata
        tdata.file_basename = None
        tdata.chrome_request = 0
        tdata.report_finished = False
        local_path = self.local_path
        functionality_list = self.functionality_list
        gesture_files_path_results = self.gesture_files_path_results

        # Set up regression path
        gesture_files_path_autotest = self._setup_gesture_files_path(test_set,
                                                                     subset)

        # Skip those models without regression gesture sets.
        if gesture_files_path_autotest is None:
            logging.info('No gesture sets are specified for this model: %s' %
                         self.model)
            return

        # Exit if the gesture files path for autotest does not exist.
        if (gesture_files_path_autotest is None or
            not os.path.exists(gesture_files_path_autotest)):
            raise error.TestError('  The autotest path does not exist: %s.' %
                    str(os.path.realpath(gesture_files_path_autotest)))

        if not os.path.exists(gesture_files_path_results):
            os.makedirs(gesture_files_path_results)
            logging.info('  The result path "%s" is created successfully.' %
                         gesture_files_path_results)
        self.ilog = trackpad_util.IterationLog(gesture_files_path_results,
                                               gesture_files_path_autotest,
                                               self.autotest_log_path)

        # Start tpcontrol log and get the gesture library version
        self.tpcontrol_log = trackpad_util.TpcontrolLog()
        gesture_version = self.tpcontrol_log.get_gesture_version()
        logging.info('Gesture library version: %s' % gesture_version)

        # Initialization of statistics
        tdata.num_wrong_file_name = 0
        tdata.num_files_tested = {}
        tdata.num_files_tested_fullname = {}
        tdata.subname_list = {}
        tdata.tot_fail_count = 0
        tdata.tot_num_files_tested = 0
        tdata.fail_count = dict([(tp_func.name, 0)
                                 for tp_func in functionality_list])
        tdata.fail_count_fullname = {}
        vlog_dict = {}
        vlog_dict[KEY_LOG] = {}
        vlog_dict[KEY_SEQ] = []
        logging.info('')
        logging.info('*** hardware_Trackpad autotest is started ***')

        # Start Trackpad Input Device
        self.tp_device = TrackpadDevice()

        # Get an instance of AutoX to handle X related issues
        autox = cros_ui.get_autox()

        # Start X events capture
        self.xcapture = Xcapture(error, local_path, autox)

        # Initialize X events Check
        self.xcheck = Xcheck(self.tp_device, local_path)

        # Processing every functionality in functionality_list
        # An example functionality is 'any_finger_click'
        for tdata.func in functionality_list:
            flag_logging_func_name = False
            tdata.num_files_tested[tdata.func.name] = 0
            tdata.subname_list[tdata.func.name] = []

            # Some cases of specifying gesture files in the configuration file:
            # Case 1:
            #   If gesture files are set to None in this functionality, skip it.
            #   It looks as:
            #       files=None,         or
            #       files=(None,),
            #
            # Case 2:
            #   '*' means all files starting with the functionality name
            #   Its setting in the configuration file looks as
            #       files='*',          or
            #       files=('*',),
            #
            # Case 3:
            # In other case, gesture files could be set as:
            #       ('any_finger_click.l1-*', 'any_finger_click.r*')
            if tdata.func.files is None or tdata.func.files.count(None) > 0:
                logging.info('    Gesture files is set to None. Skipped.')
                continue
            elif tdata.func.files == '*' or tdata.func.files.count('*') > 0:
                group_name_list = ('*',)
            else:
                group_name_list = tdata.func.files

            # A group name can be '*', or something looks like
            #                     'any_finger_click.l1-*', or
            #                     'any_finger_click.r*'), etc.
            for group_name in group_name_list:
                # prefix is the area name as default
                tdata.prefix = get_prefix(tdata.func)
                if tdata.prefix is not None:
                    # E.g., prefix = 'click-'
                    prefix = tdata.prefix + '-'
                group_path = os.path.join(gesture_files_path_autotest, prefix)

                if group_name == '*':
                    # E.g., group_path = '.../click-any_finger_click'
                    group_path += tdata.func.name
                    # Two possibilities of the gesture_file_group:
                    # 1. '.../click-any_finger_click.*':
                    #    variations exists (subname is not None)
                    # 2. '.../click-any_finger_click-*': no variations
                    #    no variations (subname is None)
                    # Note: attributes are separated by dash ('-')
                    #       variations are separated by dot ('.')
                    gesture_file_group = (glob.glob(group_path + '.*') +
                                          glob.glob(group_path + '-*'))
                else:
                    group_path += group_name
                    gesture_file_group = glob.glob(group_path)

                # Process each specific gesture_file now.
                for gesture_file in gesture_file_group:
                    tdata.file_basename = os.path.basename(gesture_file)
                    # If regression_gestures have been specified, this file
                    # should be in the regression_gestures.
                    # Currently, the short regression test has been specified
                    # the regression_gestures.
                    if not self._is_in_regression_gestures(tdata.file_basename):
                        continue

                    # Every gesture file name should start with the correct
                    # functionality name, because we use the functionality to
                    # determine the test criteria for the file. Otherwise,
                    # a warning message is shown.
                    start_flag0 = tdata.file_basename.startswith(
                                  tdata.func.name)
                    start_flag1 = tdata.file_basename.split('-')[1].startswith(
                                  tdata.func.name)
                    if ((tdata.prefix is None and not start_flag0) or
                        (tdata.prefix is not None and not start_flag1)):
                        warn_msg = ('The gesture file does not start with '
                                    'correct functionality: %s')
                        logging.warning(warn_msg % gesture_file)
                        tdata.num_wrong_file_name += 1

                    gesture_file_path = os.path.join(
                        gesture_files_path_autotest, gesture_file)

                    if not flag_logging_func_name:
                        flag_logging_func_name = True
                        logging.info('\nFunctionality: %s  (Area: %s)' %
                                     (tdata.func.name, tdata.func.area[1]))
                    logging.info('\n    gesture file: %s' % tdata.file_basename)

                    # Start X events capture
                    self.xcapture.start(tdata.file_basename)

                    # Play back the gesture file
                    self.tp_device.playback(gesture_file_path)

                    # Wait until there are no more incoming X events.
                    normal_timeout_flag = self.xcapture.wait()

                    # Stop X events capture
                    self.xcapture.stop()

                    # Check X events
                    xevent_str = self.xcapture.read()
                    output = self.xcheck.run(tdata.func, tdata, xevent_str)
                    tdata.result = output['result'] and normal_timeout_flag

                    # Insert the verification log into the vlog dictionary
                    self.vlog.insert_vlog_dict(vlog_dict, gesture_file,
                                               output['result'], output['vlog'])

                    logging.info('...................vlog.................')
                    logging.info(str(output['vlog']))

                    # Save tpcontrol log if this gesture file failed.
                    if not tdata.result:
                        self.tpcontrol_log.save_log(tdata.file_basename)

                    # Initialization for this subname
                    fullname = trackpad_util.get_fullname(tdata.file_basename)
                    if not tdata.subname_list[tdata.func.name]:
                        tdata.subname_list[tdata.func.name] = []
                    if fullname not in tdata.num_files_tested_fullname:
                        tdata.num_files_tested_fullname[fullname] = 0
                        tdata.subname_list[tdata.func.name].append(fullname)
                        tdata.fail_count_fullname[fullname] = 0

                    # Update statistics
                    tdata.num_files_tested[tdata.func.name] += 1
                    tdata.num_files_tested_fullname[fullname] += 1
                    tdata.tot_num_files_tested += 1
                    if not tdata.result:
                        tdata.fail_count[tdata.func.name] += 1
                        tdata.fail_count_fullname[fullname] += 1
                        tdata.tot_fail_count += 1

        # Terminate X event capture process
        self.xcapture.terminate()

        # Logging test summary
        tot_pass_count = tdata.tot_num_files_tested - tdata.tot_fail_count
        msg = trackpad_summary.format_result_header(self.ilog.result_file_name,
                                                    tot_pass_count,
                                                    tdata.tot_num_files_tested)
        self.ilog.write_result_log(msg)

        area_name = None
        for tp_func in functionality_list:
            # if not tp_func.enabled:
            #     continue
            func_name = tp_func.name
            test_count = tdata.num_files_tested[func_name]
            if test_count == 0:
                continue
            if tp_func.area[0] != area_name:
                area_name = tp_func.area[0]
                msg = trackpad_summary.format_result_area(area_name)
                self.ilog.write_result_log(msg)

            for fullname in tdata.subname_list[func_name]:
                test_count_fullname = tdata.num_files_tested_fullname[fullname]
                fail_count_fullname = tdata.fail_count_fullname[fullname]
                pass_count_fullname = test_count_fullname - fail_count_fullname
                msg = trackpad_summary.format_result_pass_rate(fullname,
                      pass_count_fullname, test_count_fullname)
                self.ilog.write_result_log(msg)

        msg = trackpad_summary.format_result_tail()
        self.ilog.write_result_log(msg)
        self.ilog.write_result_log('Verification Log = %s' % vlog_dict)
        self.ilog.write_result_log('\n\n\n')
        self.ilog.close_result_log()
        self.ilog.append_detailed_log(self.autodir)

        # Raise error.TestFail if there is any test failed.
        if tdata.tot_fail_count > 0:
            fail_str = 'Total number of failed files: %d'
            raise error.TestFail(fail_str % tdata.tot_fail_count)
