Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: build/android/pylib/gtest/gtest_test_instance.py

Issue 788753002: [Android] Implement gtest and local in platform mode. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix findbugs + move log parsing up to GtestTestInstance Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import logging 5 import logging
6 import os 6 import os
7 import re
7 import shutil 8 import shutil
8 import sys 9 import sys
9 10
10 from pylib import constants 11 from pylib import constants
12 from pylib.base import base_test_result
11 from pylib.base import test_instance 13 from pylib.base import test_instance
12 14
13 sys.path.append(os.path.join( 15 sys.path.append(os.path.join(
14 constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib', 'common')) 16 constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib', 'common'))
15 import unittest_util 17 import unittest_util
16 18
17 19
18 # Used for filtering large data deps at a finer grain than what's allowed in 20 # Used for filtering large data deps at a finer grain than what's allowed in
19 # isolate files since pushing deps to devices is expensive. 21 # isolate files since pushing deps to devices is expensive.
20 # Wildcards are allowed. 22 # Wildcards are allowed.
(...skipping 10 matching lines...) Expand all
31 'chrome/test/data/safari_import', 33 'chrome/test/data/safari_import',
32 'chrome/test/data/scroll', 34 'chrome/test/data/scroll',
33 'chrome/test/data/third_party', 35 'chrome/test/data/third_party',
34 'third_party/hunspell_dictionaries/*.dic', 36 'third_party/hunspell_dictionaries/*.dic',
35 # crbug.com/258690 37 # crbug.com/258690
36 'webkit/data/bmp_decoder', 38 'webkit/data/bmp_decoder',
37 'webkit/data/ico_decoder', 39 'webkit/data/ico_decoder',
38 ] 40 ]
39 41
40 42
43 # TODO(jbudorick): Remove these once we're no longer parsing stdout to generate
44 # results.
45 _RE_TEST_STATUS = re.compile(
46 r'\[ +((?:RUN)|(?:FAILED)|(?:OK)) +\] ?([^ ]+)(?: \((\d+) ms\))?$')
47 _RE_TEST_RUN_STATUS = re.compile(
48 r'\[ +(PASSED|RUNNER_FAILED|CRASHED) \] ?[^ ]+')
49
50
51 # TODO(jbudorick): Make this a class method of GtestTestInstance once
52 # test_package_apk and test_package_exe are gone.
53 def ParseGTestListTests(raw_list):
54 """Parses a raw test list as provided by --gtest_list_tests.
55
56 Args:
57 raw_list: The raw test listing with the following format:
58
59 IPCChannelTest.
60 SendMessageInChannelConnected
61 IPCSyncChannelTest.
62 Simple
63 DISABLED_SendWithTimeoutMixedOKAndTimeout
64
65 Returns:
66 A list of all tests. For the above raw listing:
67
68 [IPCChannelTest.SendMessageInChannelConnected, IPCSyncChannelTest.Simple,
69 IPCSyncChannelTest.DISABLED_SendWithTimeoutMixedOKAndTimeout]
70 """
71 ret = []
72 current = ''
73 for test in raw_list:
74 if not test:
75 continue
76 if test[0] != ' ':
77 test_case = test.split()[0]
78 if test_case.endswith('.'):
79 current = test_case
80 elif not 'YOU HAVE' in test:
81 test_name = test.split()[0]
82 ret += [current + test_name]
83 return ret
84
85
41 class GtestTestInstance(test_instance.TestInstance): 86 class GtestTestInstance(test_instance.TestInstance):
42 87
43 def __init__(self, options, isolate_delegate): 88 def __init__(self, args, isolate_delegate, error_func):
44 super(GtestTestInstance, self).__init__() 89 super(GtestTestInstance, self).__init__()
45 # TODO(jbudorick): Support multiple test suites. 90 # TODO(jbudorick): Support multiple test suites.
46 if len(options.suite_name) > 1: 91 if len(args.suite_name) > 1:
47 raise ValueError('Platform mode currently supports only 1 gtest suite') 92 raise ValueError('Platform mode currently supports only 1 gtest suite')
48 self._apk_path = os.path.join( 93 self._suite = args.suite_name[0]
49 constants.GetOutDirectory(), '%s_apk' % options.suite_name[0], 94
50 '%s-debug.apk' % options.suite_name[0]) 95 if self._suite == 'content_browsertests':
96 error_func('content_browsertests are not currently supported '
97 'in platform mode.')
98 self._apk_path = os.path.join(
99 constants.GetOutDirectory(), 'apks', '%s.apk' % self._suite)
100 else:
101 self._apk_path = os.path.join(
102 constants.GetOutDirectory(), '%s_apk' % self._suite,
103 '%s-debug.apk' % self._suite)
104 self._exe_path = os.path.join(constants.GetOutDirectory(),
105 self._suite)
106 if not os.path.exists(self._apk_path):
107 self._apk_path = None
108 if not os.path.exists(self._exe_path):
109 self._exe_path = None
110 if not self._apk_path and not self._exe_path:
111 error_func('Could not find apk or executable for %s' % self._suite)
112
51 self._data_deps = [] 113 self._data_deps = []
52 self._gtest_filter = options.test_filter 114 self._gtest_filter = args.test_filter
53 if options.isolate_file_path: 115 if args.isolate_file_path:
54 self._isolate_abs_path = os.path.abspath(options.isolate_file_path) 116 self._isolate_abs_path = os.path.abspath(args.isolate_file_path)
55 self._isolate_delegate = isolate_delegate 117 self._isolate_delegate = isolate_delegate
56 self._isolated_abs_path = os.path.join( 118 self._isolated_abs_path = os.path.join(
57 constants.GetOutDirectory(), '%s.isolated' % options.suite_name) 119 constants.GetOutDirectory(), '%s.isolated' % self._suite)
58 else: 120 else:
59 logging.warning('No isolate file provided. No data deps will be pushed.'); 121 logging.warning('No isolate file provided. No data deps will be pushed.');
60 self._isolate_delegate = None 122 self._isolate_delegate = None
61 self._suite = options.suite_name
62 123
63 #override 124 #override
64 def TestType(self): 125 def TestType(self):
65 return 'gtest' 126 return 'gtest'
66 127
67 #override 128 #override
68 def SetUp(self): 129 def SetUp(self):
69 """Map data dependencies via isolate.""" 130 """Map data dependencies via isolate."""
70 if self._isolate_delegate: 131 if self._isolate_delegate:
71 self._isolate_delegate.Remap( 132 self._isolate_delegate.Remap(
72 self._isolate_abs_path, self._isolated_abs_path) 133 self._isolate_abs_path, self._isolated_abs_path)
73 self._isolate_delegate.PurgeExcluded(_DEPS_EXCLUSION_LIST) 134 self._isolate_delegate.PurgeExcluded(_DEPS_EXCLUSION_LIST)
74 self._isolate_delegate.MoveOutputDeps() 135 self._isolate_delegate.MoveOutputDeps()
75 self._data_deps.extend([(constants.ISOLATE_DEPS_DIR, None)]) 136 dest_dir = None
137 if self._suite == 'breakpad_unittests':
138 dest_dir = '/data/local/tmp/'
139 self._data_deps.extend([(constants.ISOLATE_DEPS_DIR, dest_dir)])
140
76 141
77 def GetDataDependencies(self): 142 def GetDataDependencies(self):
78 """Returns the test suite's data dependencies. 143 """Returns the test suite's data dependencies.
79 144
80 Returns: 145 Returns:
81 A list of (host_path, device_path) tuples to push. If device_path is 146 A list of (host_path, device_path) tuples to push. If device_path is
82 None, the client is responsible for determining where to push the file. 147 None, the client is responsible for determining where to push the file.
83 """ 148 """
84 return self._data_deps 149 return self._data_deps
85 150
86 def FilterTests(self, test_list, disabled_prefixes=None): 151 def FilterTests(self, test_list, disabled_prefixes=None):
87 """Filters |test_list| based on prefixes and, if present, a filter string. 152 """Filters |test_list| based on prefixes and, if present, a filter string.
88 153
89 Args: 154 Args:
90 test_list: The list of tests to filter. 155 test_list: The list of tests to filter.
91 disabled_prefixes: A list of test prefixes to filter. Defaults to 156 disabled_prefixes: A list of test prefixes to filter. Defaults to
92 DISABLED_, FLAKY_, FAILS_, PRE_, and MANUAL_ 157 DISABLED_, FLAKY_, FAILS_, PRE_, and MANUAL_
93 Returns: 158 Returns:
94 A filtered list of tests to run. 159 A filtered list of tests to run.
95 """ 160 """
96 gtest_filter_strings = [ 161 gtest_filter_strings = [
97 self._GenerateDisabledFilterString(disabled_prefixes)] 162 self._GenerateDisabledFilterString(disabled_prefixes)]
98 if self._gtest_filter: 163 if self._gtest_filter:
99 gtest_filter_strings.append(self._gtest_filter) 164 gtest_filter_strings.append(self._gtest_filter)
100 165
101 filtered_test_list = test_list 166 filtered_test_list = test_list
102 for gtest_filter_string in gtest_filter_strings: 167 for gtest_filter_string in gtest_filter_strings:
103 logging.info('gtest filter string: %s' % gtest_filter_string)
104 filtered_test_list = unittest_util.FilterTestNames( 168 filtered_test_list = unittest_util.FilterTestNames(
105 filtered_test_list, gtest_filter_string) 169 filtered_test_list, gtest_filter_string)
106 logging.info('final list of tests: %s' % (str(filtered_test_list)))
107 return filtered_test_list 170 return filtered_test_list
108 171
109 def _GenerateDisabledFilterString(self, disabled_prefixes): 172 def _GenerateDisabledFilterString(self, disabled_prefixes):
110 disabled_filter_items = [] 173 disabled_filter_items = []
111 174
112 if disabled_prefixes is None: 175 if disabled_prefixes is None:
113 disabled_prefixes = ['DISABLED_', 'FLAKY_', 'FAILS_', 'PRE_', 'MANUAL_'] 176 disabled_prefixes = ['DISABLED_', 'FLAKY_', 'FAILS_', 'PRE_', 'MANUAL_']
114 disabled_filter_items += ['%s*' % dp for dp in disabled_prefixes] 177 disabled_filter_items += ['%s*' % dp for dp in disabled_prefixes]
178 disabled_filter_items += ['*.%s*' % dp for dp in disabled_prefixes]
115 179
116 disabled_tests_file_path = os.path.join( 180 disabled_tests_file_path = os.path.join(
117 constants.DIR_SOURCE_ROOT, 'build', 'android', 'pylib', 'gtest', 181 constants.DIR_SOURCE_ROOT, 'build', 'android', 'pylib', 'gtest',
118 'filter', '%s_disabled' % self._suite) 182 'filter', '%s_disabled' % self._suite)
119 if disabled_tests_file_path and os.path.exists(disabled_tests_file_path): 183 if disabled_tests_file_path and os.path.exists(disabled_tests_file_path):
120 with open(disabled_tests_file_path) as disabled_tests_file: 184 with open(disabled_tests_file_path) as disabled_tests_file:
121 disabled_filter_items += [ 185 disabled_filter_items += [
122 '%s' % l for l in (line.strip() for line in disabled_tests_file) 186 '%s' % l for l in (line.strip() for line in disabled_tests_file)
123 if l and not l.startswith('#')] 187 if l and not l.startswith('#')]
124 188
125 return '*-%s' % ':'.join(disabled_filter_items) 189 return '*-%s' % ':'.join(disabled_filter_items)
126 190
191 def ParseGTestOutput(self, output):
192 """Parses raw gtest output and returns a list of results.
193
194 Args:
195 output: A list of output lines.
196 Returns:
197 A list of base_test_result.BaseTestResults.
198 """
199 results = []
200 for l in output:
201 matcher = _RE_TEST_STATUS.match(l)
202 if matcher:
203 result_type = None
204 if matcher.group(1) == 'OK':
205 result_type = base_test_result.ResultType.PASS
206 elif matcher.group(1) == 'FAILED':
207 result_type = base_test_result.ResultType.FAIL
208
209 if result_type:
210 test_name = matcher.group(2)
211 duration = matcher.group(3) if matcher.group(3) else 0
212 results.append(base_test_result.BaseTestResult(
213 test_name, result_type, duration))
214 logging.info(l)
215 return results
216
127 #override 217 #override
128 def TearDown(self): 218 def TearDown(self):
129 """Clear the mappings created by SetUp.""" 219 """Clear the mappings created by SetUp."""
130 if self._isolate_delegate: 220 if self._isolate_delegate:
131 self._isolate_delegate.Clear() 221 self._isolate_delegate.Clear()
132 222
133 @property 223 @property
134 def apk(self): 224 def apk(self):
135 return self._apk_path 225 return self._apk_path
136 226
137 @property 227 @property
228 def exe(self):
229 return self._exe_path
230
231 @property
138 def suite(self): 232 def suite(self):
139 return self._suite 233 return self._suite
140 234
OLDNEW
« no previous file with comments | « build/android/pylib/base/test_run_factory.py ('k') | build/android/pylib/gtest/gtest_test_instance_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698