| Index: build/android/pylib/gtest/gtest_test_instance.py
|
| diff --git a/build/android/pylib/gtest/gtest_test_instance.py b/build/android/pylib/gtest/gtest_test_instance.py
|
| index f4623e414a3e5719f6aba7a9de4fb1ff98c3b685..755573a75cb9d4a4602877d8bd056e51aafaf4a0 100644
|
| --- a/build/android/pylib/gtest/gtest_test_instance.py
|
| +++ b/build/android/pylib/gtest/gtest_test_instance.py
|
| @@ -4,10 +4,12 @@
|
|
|
| import logging
|
| import os
|
| +import re
|
| import shutil
|
| import sys
|
|
|
| from pylib import constants
|
| +from pylib.base import base_test_result
|
| from pylib.base import test_instance
|
|
|
| sys.path.append(os.path.join(
|
| @@ -38,27 +40,86 @@ _DEPS_EXCLUSION_LIST = [
|
| ]
|
|
|
|
|
| +# TODO(jbudorick): Remove these once we're no longer parsing stdout to generate
|
| +# results.
|
| +_RE_TEST_STATUS = re.compile(
|
| + r'\[ +((?:RUN)|(?:FAILED)|(?:OK)) +\] ?([^ ]+)(?: \((\d+) ms\))?$')
|
| +_RE_TEST_RUN_STATUS = re.compile(
|
| + r'\[ +(PASSED|RUNNER_FAILED|CRASHED) \] ?[^ ]+')
|
| +
|
| +
|
| +# TODO(jbudorick): Make this a class method of GtestTestInstance once
|
| +# test_package_apk and test_package_exe are gone.
|
| +def ParseGTestListTests(raw_list):
|
| + """Parses a raw test list as provided by --gtest_list_tests.
|
| +
|
| + Args:
|
| + raw_list: The raw test listing with the following format:
|
| +
|
| + IPCChannelTest.
|
| + SendMessageInChannelConnected
|
| + IPCSyncChannelTest.
|
| + Simple
|
| + DISABLED_SendWithTimeoutMixedOKAndTimeout
|
| +
|
| + Returns:
|
| + A list of all tests. For the above raw listing:
|
| +
|
| + [IPCChannelTest.SendMessageInChannelConnected, IPCSyncChannelTest.Simple,
|
| + IPCSyncChannelTest.DISABLED_SendWithTimeoutMixedOKAndTimeout]
|
| + """
|
| + ret = []
|
| + current = ''
|
| + for test in raw_list:
|
| + if not test:
|
| + continue
|
| + if test[0] != ' ':
|
| + test_case = test.split()[0]
|
| + if test_case.endswith('.'):
|
| + current = test_case
|
| + elif not 'YOU HAVE' in test:
|
| + test_name = test.split()[0]
|
| + ret += [current + test_name]
|
| + return ret
|
| +
|
| +
|
| class GtestTestInstance(test_instance.TestInstance):
|
|
|
| - def __init__(self, options, isolate_delegate):
|
| + def __init__(self, args, isolate_delegate, error_func):
|
| super(GtestTestInstance, self).__init__()
|
| # TODO(jbudorick): Support multiple test suites.
|
| - if len(options.suite_name) > 1:
|
| + if len(args.suite_name) > 1:
|
| raise ValueError('Platform mode currently supports only 1 gtest suite')
|
| - self._apk_path = os.path.join(
|
| - constants.GetOutDirectory(), '%s_apk' % options.suite_name[0],
|
| - '%s-debug.apk' % options.suite_name[0])
|
| + self._suite = args.suite_name[0]
|
| +
|
| + if self._suite == 'content_browsertests':
|
| + error_func('content_browsertests are not currently supported '
|
| + 'in platform mode.')
|
| + self._apk_path = os.path.join(
|
| + constants.GetOutDirectory(), 'apks', '%s.apk' % self._suite)
|
| + else:
|
| + self._apk_path = os.path.join(
|
| + constants.GetOutDirectory(), '%s_apk' % self._suite,
|
| + '%s-debug.apk' % self._suite)
|
| + self._exe_path = os.path.join(constants.GetOutDirectory(),
|
| + self._suite)
|
| + if not os.path.exists(self._apk_path):
|
| + self._apk_path = None
|
| + if not os.path.exists(self._exe_path):
|
| + self._exe_path = None
|
| + if not self._apk_path and not self._exe_path:
|
| + error_func('Could not find apk or executable for %s' % self._suite)
|
| +
|
| self._data_deps = []
|
| - self._gtest_filter = options.test_filter
|
| - if options.isolate_file_path:
|
| - self._isolate_abs_path = os.path.abspath(options.isolate_file_path)
|
| + self._gtest_filter = args.test_filter
|
| + if args.isolate_file_path:
|
| + self._isolate_abs_path = os.path.abspath(args.isolate_file_path)
|
| self._isolate_delegate = isolate_delegate
|
| self._isolated_abs_path = os.path.join(
|
| - constants.GetOutDirectory(), '%s.isolated' % options.suite_name)
|
| + constants.GetOutDirectory(), '%s.isolated' % self._suite)
|
| else:
|
| logging.warning('No isolate file provided. No data deps will be pushed.');
|
| self._isolate_delegate = None
|
| - self._suite = options.suite_name
|
|
|
| #override
|
| def TestType(self):
|
| @@ -72,7 +133,11 @@ class GtestTestInstance(test_instance.TestInstance):
|
| self._isolate_abs_path, self._isolated_abs_path)
|
| self._isolate_delegate.PurgeExcluded(_DEPS_EXCLUSION_LIST)
|
| self._isolate_delegate.MoveOutputDeps()
|
| - self._data_deps.extend([(constants.ISOLATE_DEPS_DIR, None)])
|
| + dest_dir = None
|
| + if self._suite == 'breakpad_unittests':
|
| + dest_dir = '/data/local/tmp/'
|
| + self._data_deps.extend([(constants.ISOLATE_DEPS_DIR, dest_dir)])
|
| +
|
|
|
| def GetDataDependencies(self):
|
| """Returns the test suite's data dependencies.
|
| @@ -100,10 +165,8 @@ class GtestTestInstance(test_instance.TestInstance):
|
|
|
| filtered_test_list = test_list
|
| for gtest_filter_string in gtest_filter_strings:
|
| - logging.info('gtest filter string: %s' % gtest_filter_string)
|
| filtered_test_list = unittest_util.FilterTestNames(
|
| filtered_test_list, gtest_filter_string)
|
| - logging.info('final list of tests: %s' % (str(filtered_test_list)))
|
| return filtered_test_list
|
|
|
| def _GenerateDisabledFilterString(self, disabled_prefixes):
|
| @@ -112,6 +175,7 @@ class GtestTestInstance(test_instance.TestInstance):
|
| if disabled_prefixes is None:
|
| disabled_prefixes = ['DISABLED_', 'FLAKY_', 'FAILS_', 'PRE_', 'MANUAL_']
|
| disabled_filter_items += ['%s*' % dp for dp in disabled_prefixes]
|
| + disabled_filter_items += ['*.%s*' % dp for dp in disabled_prefixes]
|
|
|
| disabled_tests_file_path = os.path.join(
|
| constants.DIR_SOURCE_ROOT, 'build', 'android', 'pylib', 'gtest',
|
| @@ -124,6 +188,32 @@ class GtestTestInstance(test_instance.TestInstance):
|
|
|
| return '*-%s' % ':'.join(disabled_filter_items)
|
|
|
| + def ParseGTestOutput(self, output):
|
| + """Parses raw gtest output and returns a list of results.
|
| +
|
| + Args:
|
| + output: A list of output lines.
|
| + Returns:
|
| + A list of base_test_result.BaseTestResults.
|
| + """
|
| + results = []
|
| + for l in output:
|
| + matcher = _RE_TEST_STATUS.match(l)
|
| + if matcher:
|
| + result_type = None
|
| + if matcher.group(1) == 'OK':
|
| + result_type = base_test_result.ResultType.PASS
|
| + elif matcher.group(1) == 'FAILED':
|
| + result_type = base_test_result.ResultType.FAIL
|
| +
|
| + if result_type:
|
| + test_name = matcher.group(2)
|
| + duration = matcher.group(3) if matcher.group(3) else 0
|
| + results.append(base_test_result.BaseTestResult(
|
| + test_name, result_type, duration))
|
| + logging.info(l)
|
| + return results
|
| +
|
| #override
|
| def TearDown(self):
|
| """Clear the mappings created by SetUp."""
|
| @@ -135,6 +225,10 @@ class GtestTestInstance(test_instance.TestInstance):
|
| return self._apk_path
|
|
|
| @property
|
| + def exe(self):
|
| + return self._exe_path
|
| +
|
| + @property
|
| def suite(self):
|
| return self._suite
|
|
|
|
|