# Copyright 2015 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 os

import common
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import global_config
from autotest_lib.server import afe_utils
from autotest_lib.server import test
from autotest_lib.site_utils import acts_lib

CONFIG_FOLDER_LOCATION = global_config.global_config.get_config_value(
    'ACTS', 'acts_config_folder', default='')

TEST_CONFIG_FILE_FOLDER = os.path.join(CONFIG_FOLDER_LOCATION,
                                       'autotest_config')
TEST_CAMPAIGN_FILE_FOLDER = os.path.join(CONFIG_FOLDER_LOCATION,
                                         'autotest_campaign')

DEFAULT_TEST_RELATIVE_LOG_PATH = 'results/logs'


class android_ACTS(test.test):
    """Run an Android CTS test case.

    Component relationship:
    Workstation ----(ssh)---> TestStation -----(adb)-----> Android DUT
    This code runs on Workstation.
    """
    version = 1

    def run_once(self,
                 testbed=None,
                 config_file=None,
                 testbed_name=None,
                 test_case=None,
                 test_file=None,
                 additional_configs=[],
                 override_build_url=None,
                 override_acts_zip=None,
                 override_internal_acts_dir=None,
                 override_python_bin='python',
                 acts_timeout=7200):
        """Runs an acts test case.

        @param testbed: The testbed to test on.
        @config_file: The main config file to use for running the test. This
                      should be relative to the autotest_config folder.
        @param test_case: The test case to run. Should be None when test_file
                          is given.
        @param test_file: The campaign file to run. Should be None when
                          test_case is given. This should be relative to the
                          autotest_campaign folder.
        @param additional_configs: Any additional config files to use.
                                   These should be relative to the
                                   autotest_config folder.
        @param override_build_url: The build url to fetch acts from. If None
                                   then the build url of the first adb device
                                   is used.
        @param override_acts_zip: If given a zip file on the drone is used
                                  rather than pulling a build.
        @param override_internal_acts_dir: The directory within the artifact
                                           where the acts framework folder
                                           lives.
        @param override_python_bin: Overrides the default python binary that
                                    is used.
        @param acts_timeout: How long to wait for acts to finish.
        """
        host = next(v for v in testbed.get_adb_devices().values())

        if not host:
            raise error.TestError('No hosts defined for this test, cannot'
                                  ' determine build to grab artifact from.')

        job_repo_url = afe_utils.get_host_attribute(
                host, host.job_repo_url_attribute)
        test_station = testbed.teststation
        ts_tempfolder = test_station.get_tmp_dir()
        target_zip = os.path.join(ts_tempfolder, 'acts.zip')

        if override_acts_zip and override_build_url:
            raise error.TestError('Cannot give both a url and zip override.')
        elif override_acts_zip:
            package = acts_lib.create_acts_package_from_zip(
                    test_station, override_acts_zip, target_zip)
        elif override_build_url:
            build_url_pieces = override_build_url.split('/')
            if len(build_url_pieces) != 3:
                raise error.TestError('Override build url must be formatted as '
                                      '<branch>/<target>/<build_id>')

            branch = build_url_pieces[0]
            target = build_url_pieces[1]
            build_id = build_url_pieces[2]
            package = acts_lib.create_acts_package_from_artifact(test_station,
                                                                 branch,
                                                                 target,
                                                                 build_id,
                                                                 job_repo_url,
                                                                 target_zip)
        else:
            package = acts_lib.create_acts_package_from_current_artifact(
                    test_station, job_repo_url, target_zip)

        container = package.create_container(ts_tempfolder,
                                             override_internal_acts_dir)

        container.install_sl4a_apk(testbed)
        container.setup_enviroment(python_bin=override_python_bin)

        container.upload_config(config_file)

        if additional_configs:
            for additional_config in additional_configs:
                container.upload_config(additional_config)

        if test_file:
            container.upload_campaign(test_file)

        results = container.run_test(testbed,
                                     config_file,
                                     campaign=test_file,
                                     test_case=test_case,
                                     python_bin=override_python_bin,
                                     testbed_name=testbed_name,
                                     timeout=acts_timeout)

        results.log_output()
        results.upload_to_sponge(self)
        results.report_to_autotest(self)
        results.rethrow_exception()
