# Copyright 2016 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.

import logging, re, time

from autotest_lib.client.common_lib import error
from autotest_lib.server import test
from autotest_lib.server.cros.dark_resume_utils import DarkResumeUtils
from autotest_lib.server.cros.faft.config.config import Config as FAFTConfig

SUSPEND_DURATION = 15
NUM_DARK_RESUMES = 10
ERROR_FILE = '/sys/kernel/debug/dri/0/i915_crtc_errors'


class power_DarkResumeDisplay(test.test):
    """ Ensure we don't have display errors after dark resume """
    version = 1
    dark_resume_utils = None


    def initialize(self, host):
        self.dark_resume_utils = DarkResumeUtils(host,
                                                 duration=SUSPEND_DURATION)


    def verify_host_supports_test(self, host):
        """Check if the test works on the given host

        @param host: reference to the host object
        """
        platform = host.run_output('mosys platform name')
        logging.info('Checking platform %s for compatibility with display test',
                     platform)

        # TODO(seanpaul) Look at backporting i915_crtc_errors accounting to
        # other kernels.
        kernel_ver = host.run('uname -r').stdout.rstrip()
        logging.info('kernel version is %s', kernel_ver)
        if not kernel_ver.startswith('3.14') and \
           not kernel_ver.startswith('3.18'):
            raise error.TestNAError('Test support on 3.14 | 3.18 kernels only')

        client_attr = FAFTConfig(platform)
        if client_attr.dark_resume_capable == False:
            raise error.TestNAError('platform is not capable of dark resume')

        cmd = host.run('test -r %s' % ERROR_FILE, ignore_status=True)
        logging.info("node_exists=%s", str(cmd.exit_status))
        if cmd.exit_status != 0:
            raise error.TestError('%s file not found.' % ERROR_FILE)


    def get_crtc_error_count(self, host):
        """Get the current crtc error count for the dut

        @returns: A dict whose key is the crtc id, and whose value is a
                  dict of {pipe, errors}
        """
        output = host.run_output('cat %s' % ERROR_FILE)
        pattern = 'Crtc ([0-9]+) Pipe ([A-Za-z]+) errors:\t\t([0-9a-fA-F]{8})'
        regex = re.compile(pattern)
        counts = {}
        for line in output.splitlines():
            match = regex.match(line)
            if match == None:
                raise error.TestError('Unexpected error file string: %s' % line)

            counts[int(match.group(1))] = {
                'pipe': match.group(2),
                'errors': int(match.group(3), 16),
            }
        return counts


    def run_once(self, host=None):
        """Run the test.

           Setup preferences so that a dark resume will happen shortly after
           suspending the machine.

           store the current crtc error count
           suspend the machine
           wait for dark resume
           wake the machine
           retrieve the current crtc error count after suspend
           ensure the error counts did not increase while suspended

        @param host: The machine to run the tests on
        """
        self.verify_host_supports_test(host)

        pre_err_count = self.get_crtc_error_count(host)

        # The DUT will perform a dark resume every SUSPEND_DURATION seconds
        # while it is suspended. Suspend the device and wait for the amount
        # of time to have performed NUM_DARK_RESUMES, plus half the
        # SUSPEND_DURATION to ensure the last dark resume has a chance to
        # complete.
        wait_time = SUSPEND_DURATION * NUM_DARK_RESUMES + SUSPEND_DURATION / 2
        logging.info('suspending host, and waiting %ds', wait_time)
        with self.dark_resume_utils.suspend() as _:
            time.sleep(wait_time)

        dark_resume_count = self.dark_resume_utils.count_dark_resumes()
        logging.info('dark resume count = %d', dark_resume_count)
        if dark_resume_count == 0:
            raise error.TestError('Device did not enter dark resume!')

        logging.info('retrieving post-suspend error counts')
        post_err_count = self.get_crtc_error_count(host)
        for k in pre_err_count:
            pre = pre_err_count[k]['errors']
            post = post_err_count[k]['errors']
            if pre != post:
                raise error.TestError('Crtc %d Pipe %s err count changed %d/%d'
                                      % (k, pre_err_count[k]['pipe'], pre,
                                         post))
            logging.info('error counts for Crtc %d Pipe %s constant at %d', k,
                         pre_err_count[k]['pipe'], pre)


    def cleanup(self, _):
        self.dark_resume_utils.teardown()

