blob: 3d14954496e7ecd5dd20181ce3bfec1de4c12a4b [file] [log] [blame]
# 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.
# repohooks/pre-upload.py currently does not run pylint. But for developers who
# want to check their code manually we disable several harmless pylint warnings
# which just distract from more serious remaining issues.
#
# The instance variable _android_gts is not defined in __init__().
# pylint: disable=attribute-defined-outside-init
#
# Many short variable names don't follow the naming convention.
# pylint: disable=invalid-name
import logging
import os
import re
from autotest_lib.client.common_lib import error
from autotest_lib.server import utils
from autotest_lib.server.cros import tradefed_test
_PARTNER_GTS_LOCATION = 'gs://chromeos-partner-gts/android-gts-3.0r6.zip'
class cheets_GTS(tradefed_test.TradefedTest):
"""Sets up tradefed to run GTS tests."""
version = 1
def setup(self, uri=None):
"""Set up GTS bundle from Google Storage.
@param uri: The location to pull the GTS bundle from.
"""
if uri:
self._android_gts = self._install_bundle(uri)
else:
self._android_gts = self._install_bundle(_PARTNER_GTS_LOCATION)
self.waivers = self._get_expected_failures('expectations')
def _run_gts_tradefed(self, target_package):
"""This tests runs the GTS(XTS) tradefed binary and collects results.
@param target_package: the name of test package to be run. If None is
set, full GTS set will run.
@raise TestFail: when a test failure is detected.
"""
self._target_package = target_package
gts_tradefed = os.path.join(
self._android_gts,
'android-gts',
'tools',
'gts-tradefed')
logging.info('GTS-tradefed path: %s', gts_tradefed)
#TODO(dhaddock): remove --skip-device-info with GTS 4.1_r2 (b/32889514)
gts_tradefed_args = ['run', 'commandAndExit', 'gts',
'--skip-device-info', '--module',
self._target_package]
# Run GTS via tradefed and obtain stdout, sterr as output.
with tradefed_test.adb_keepalive(self._get_adb_target(),
self._install_paths):
output = self._run(
gts_tradefed,
args=gts_tradefed_args,
verbose=True,
# Make sure to tee tradefed stdout/stderr to autotest logs
# already during the test run.
stdout_tee=utils.TEE_TO_LOGS,
stderr_tee=utils.TEE_TO_LOGS)
# Parse stdout to obtain datetime IDs of directories into which tradefed
# wrote result xml files and logs.
datetime_id = self._parse_tradefed_datetime(output)
repository = os.path.join(self._android_gts, 'android-gts')
autotest = os.path.join(self.resultsdir, 'android-gts')
self._collect_logs(repository, datetime_id, autotest)
# Result parsing must come after all other essential operations as test
# warnings, errors and failures can be raised here.
tests, passed, failed, not_executed = self._parse_result(output,
self.waivers)
if tests != passed or failed > 0 or not_executed > 0:
raise error.TestFail('Failed: Passed (%d), Failed (%d), '
'Not Executed (%d)' %
(passed, failed, not_executed))
# All test has passed successfully, here.
logging.info('The test has passed successfully.')
def _parse_tradefed_datetime(self, result):
"""This parses the tradefed datetime object from the GTS output.
:param result: the tradefed result object
:return: the datetime
"""
#TODO(dhaddock): Merge this into tradefed_test when N is working
match = re.search(r': Starting invocation for .+ (\S+) on device',
result.stdout)
datetime_id = match.group(1)
logging.info('Tradefed identified results and logs with %s.',
datetime_id)
return datetime_id
def _parse_result(self, result, waivers=None):
"""Check the result from the tradefed output.
This extracts the test pass/fail/executed list from the output of
tradefed. It is up to the caller to handle inconsistencies.
@param result: The result object from utils.run.
@param waivers: a set() of tests which are permitted to fail.
"""
# TODO(dhaddock): This function overrides the parent version while GTS
# uses the updated version with modules and new output.
# This will be merged into the tradefed_test.py class eventually.
match = re.search(r': Invocation finished in (.*). PASSED: (\d+), '
r'FAILED: (\d+), '
r'NOT EXECUTED: (\d+), MODULES: ('
r'\d+) of (\d+)', result.stdout)
if not match:
raise error.Test('Test log does not contain a summary.')
passed = int(match.group(2))
failed = int(match.group(3))
not_executed = int(match.group(4))
# Some tests may be split into several groups. E.g. per architecture as
# follows;
# Starting x86 GtsAccountsHostTestCases with 3 tests
# Starting armeabi-v7a GtsAccountsHostTestCases with 3 tests
group_list = re.findall(r'Starting (.+) %s with (\d+(?:,\d+)?) tests' %
self._target_package,
result.stdout)
abis = []
if group_list:
tests = sum(int(num_tests[1].replace(',', ''))
for num_tests in group_list)
abis = [abi[0] for abi in group_list]
else:
# Unfortunately this happens. Assume it made no other mistakes.
logging.warning('Tradefed forgot to print number of tests.')
tests = passed + failed + not_executed
# TODO(rohitbm): make failure parsing more robust by extracting the list
# of failing tests instead of searching in the result blob.
if waivers:
for testname in waivers:
fail_count = result.stdout.count(testname + ' fail')
if fail_count:
# For arm only, we repeat the test cases with output like
# Starting armeabi-v7a GtsPlacementTestCases with 12 tests
# Continuing armeabi-v7a GtsPlacementTestcase with 12 tests
if abis == ['armeabi-v7a']:
fail_count /= 2
if fail_count > len(abis):
raise error.TestFail('Error: Found %d failures for %s '
'but there are only %d abis: %s' %
(fail_count, testname, len(abis),
abis))
failed -= fail_count
# To maintain total count consistency.
passed += fail_count
logging.info('Waived failure for %s %d time(s)',
testname, fail_count)
logging.info('tests=%d, passed=%d, failed=%d, not_executed=%d',
tests, passed, failed, not_executed)
if failed < 0:
raise error.TestFail('Error: Internal waiver book keeping has '
'become inconsistent.')
return (tests, passed, failed, not_executed)
def run_once(self, target_package=None):
"""Runs GTS target package exactly once."""
with self._login_chrome():
self._connect_adb()
self._disable_adb_install_dialog()
self._wait_for_arc_boot()
self._run_gts_tradefed(target_package)