#!/usr/bin/python2
#
# 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.
'''Confidence tests for Chrome on Chrome OS.

This script runs a number of confidence tests to ensure that Chrome browser on
Chrome OS is functional.
'''

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

import argparse
import datetime
import logging
import sys

# This sets up import paths for autotest.
import common
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib.cros import arc, arc_common, chrome
from autotest_lib.client.common_lib.error import TestFail
from autotest_lib.client.cros import cryptohome
from six.moves import range


class TelemetryCheck(object):
    """Class for running confidence tests to verify telemetry."""

    def __init__(self,
                 count=1,
                 run_cryptohome=True,
                 run_incognito=True,
                 run_screenlock=True):
        self.count = count
        self.run_cryptohome = run_cryptohome
        self.run_incognito = run_incognito
        self.run_screenlock = run_screenlock

    def Run(self):
        """Run tests."""
        start = datetime.datetime.now()

        for i in range(self.count):
            if self.count > 1:
                logging.info('Starting iteration %d.', i)
            if self.run_cryptohome:
                self.RunCryptohomeTest()
            if self.run_incognito:
                self.RunIncognitoTest()
            if self.run_screenlock:
                self.RunScreenlockTest()

        elapsed = datetime.datetime.now() - start
        logging.info('Tests succeeded in %s seconds.', elapsed.seconds)

    def RunCryptohomeTest(self):
        """Test Cryptohome."""
        logging.info('RunCryptohomeTest: Starting chrome and logging in.')
        # Only run ARC tests for P.
        run_arc_tests = (utils.is_arc_available()
                         and arc.get_android_sdk_version() <= 28)
        arc_mode = arc_common.ARC_MODE_ENABLED if run_arc_tests else None
        with chrome.Chrome(arc_mode=arc_mode, num_tries=1) as cr:
            # Check that the cryptohome is mounted.
            # is_vault_mounted throws an exception if it fails.
            logging.info('Checking mounted cryptohome.')
            cryptohome.is_vault_mounted(user=cr.username, allow_fail=False)
            # Navigate to about:blank.
            tab = cr.browser.tabs[0]
            tab.Navigate('about:blank')

            # Evaluate some javascript.
            logging.info('Evaluating JavaScript.')
            if tab.EvaluateJavaScript('2+2') != 4:
                raise TestFail('EvaluateJavaScript failed')

            # ARC test.
            if run_arc_tests:
                arc.wait_for_adb_ready()
                logging.info('Android booted successfully.')
                arc.wait_for_android_process('org.chromium.arc.intent_helper')
                if not arc.is_package_installed('android'):
                    raise TestFail(
                            '"android" system package was not listed by '
                            'Package Manager.')

        if run_arc_tests:
            utils.poll_for_condition(lambda: not arc.
                                     is_android_container_alive(),
                                     timeout=15,
                                     desc='Android container still running '
                                     'after Chrome shutdown.')

    def RunIncognitoTest(self):
        """Test Incognito mode."""
        logging.info('RunIncognitoTest')
        with chrome.Chrome(logged_in=False):
            if not cryptohome.is_guest_vault_mounted():
                raise TestFail('Expected to find a guest vault mounted.')
        if cryptohome.is_guest_vault_mounted(allow_fail=True):
            raise TestFail('Expected to NOT find a guest vault mounted.')

    def RunScreenlockTest(self):
        """Run a test that locks the screen."""
        logging.info('RunScreenlockTest')
        with chrome.Chrome(autotest_ext=True) as cr:
            cr.autotest_ext.ExecuteJavaScript(
                    'chrome.autotestPrivate.lockScreen();')
            utils.poll_for_condition(lambda: cr.login_status['isScreenLocked'],
                                     timeout=15,
                                     exception=TestFail('Screen not locked'))

    @staticmethod
    def ParseArgs(argv):
        """Parse command line.

    Args:
      argv: List of command line arguments.

    Returns:
      List of parsed opts.
    """
        parser = argparse.ArgumentParser(description=__doc__)
        parser.add_argument('--count',
                            type=int,
                            default=1,
                            help='Number of iterations of the test to run.')
        parser.add_argument('--run-all',
                            default=False,
                            action='store_true',
                            help='Run all tests.')
        parser.add_argument('--run-cryptohome',
                            default=False,
                            action='store_true',
                            help='Run Cryptohome test.')
        parser.add_argument('--run-incognito',
                            default=False,
                            action='store_true',
                            help='Run Incognito test.')
        parser.add_argument('--run-screenlock',
                            default=False,
                            action='store_true',
                            help='Run Screenlock test.')
        return parser.parse_args(argv)


def main(argv):
    '''The main function.'''
    opts = TelemetryCheck.ParseArgs(argv)

    # Run all tests if none are specified.
    if opts.run_all or not (opts.run_cryptohome or opts.run_incognito
                            or opts.run_screenlock):
        opts.run_cryptohome = opts.run_screenlock = True
        opts.run_incognito = False  # crbug.com/970065

    TelemetryCheck(opts.count, opts.run_cryptohome, opts.run_incognito,
                   opts.run_screenlock).Run()


if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
