OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 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 """Base class representing GTest test packages.""" |
5 | 6 |
6 import logging | |
7 import os | 7 import os |
8 import re | |
9 | 8 |
10 from pylib import constants | 9 from pylib import constants |
11 from pylib import pexpect | |
12 from pylib.android_commands import errors | |
13 from pylib.base import base_test_result | |
14 from pylib.perf_tests_helper import PrintPerfResult | |
15 | 10 |
16 | 11 |
17 class TestPackage(object): | 12 class TestPackage(object): |
18 """A helper base class for both APK and stand-alone executables. | 13 """A helper base class for both APK and stand-alone executables. |
19 | 14 |
20 Args: | 15 Args: |
21 adb: ADB interface the tests are using. | 16 adb: ADB interface the tests are using. |
22 device: Device to run the tests. | 17 device: Device to run the tests. |
23 test_suite: A specific test suite to run, empty to run all. | 18 test_suite: A specific test suite to run, empty to run all. |
24 timeout: Timeout for each test. | |
25 cleanup_test_files: Whether or not to cleanup test files on device. | |
26 tool: Name of the Valgrind tool. | 19 tool: Name of the Valgrind tool. |
27 """ | 20 """ |
28 | 21 |
29 def __init__(self, adb, device, test_suite, timeout, | 22 def __init__(self, adb, device, test_suite, tool): |
30 cleanup_test_files, tool): | |
31 self.adb = adb | 23 self.adb = adb |
32 self.device = device | 24 self.device = device |
33 self.test_suite_full = test_suite | 25 self.test_suite_full = test_suite |
34 self.test_suite = os.path.splitext(test_suite)[0] | 26 self.test_suite = os.path.splitext(test_suite)[0] |
35 self.test_suite_basename = self._GetTestSuiteBaseName() | 27 self.test_suite_basename = self._GetTestSuiteBaseName() |
36 self.test_suite_dirname = os.path.dirname( | 28 self.test_suite_dirname = os.path.dirname( |
37 self.test_suite.split(self.test_suite_basename)[0]) | 29 self.test_suite.split(self.test_suite_basename)[0]) |
38 self.cleanup_test_files = cleanup_test_files | |
39 self.tool = tool | 30 self.tool = tool |
40 if timeout == 0: | |
41 timeout = 60 | |
42 # On a VM (e.g. chromium buildbots), this timeout is way too small. | |
43 if os.environ.get('BUILDBOT_SLAVENAME'): | |
44 timeout = timeout * 2 | |
45 self.timeout = timeout * self.tool.GetTimeoutScale() | |
46 | 31 |
47 def ClearApplicationState(self): | 32 def ClearApplicationState(self): |
48 """Clears the application state.""" | 33 """Clears the application state.""" |
49 raise NotImplementedError('Method must be overriden.') | 34 raise NotImplementedError('Method must be overriden.') |
50 | 35 |
| 36 def CreateCommandLineFileOnDevice(self, test_filter, test_arguments): |
| 37 """Creates a test runner script and pushes to the device. |
| 38 |
| 39 Args: |
| 40 test_filter: A test_filter flag. |
| 41 test_arguments: Additional arguments to pass to the test binary. |
| 42 """ |
| 43 raise NotImplementedError('Method must be overriden.') |
| 44 |
| 45 def GetAllTests(self): |
| 46 """Returns a list of all tests available in the test suite.""" |
| 47 raise NotImplementedError('Method must be overriden.') |
| 48 |
| 49 def GetGTestReturnCode(self): |
| 50 return None |
| 51 |
| 52 def SpawnTestProcess(self): |
| 53 """Spawn the test process. |
| 54 |
| 55 Returns: |
| 56 An instance of pexpect spawn class. |
| 57 """ |
| 58 raise NotImplementedError('Method must be overriden.') |
| 59 |
| 60 def Install(self): |
| 61 """Install the test package to the device.""" |
| 62 raise NotImplementedError('Method must be overriden.') |
| 63 |
51 def GetDisabledPrefixes(self): | 64 def GetDisabledPrefixes(self): |
52 return ['DISABLED_', 'FLAKY_', 'FAILS_'] | 65 return ['DISABLED_', 'FLAKY_', 'FAILS_'] |
53 | 66 |
54 def _ParseGTestListTests(self, all_tests): | 67 def _ParseGTestListTests(self, all_tests): |
55 """Parses and filters the raw test lists. | 68 """Parses and filters the raw test lists. |
56 | 69 |
57 Args: | 70 Args: |
58 all_tests: The raw test listing with the following format: | 71 all_tests: The raw test listing with the following format: |
59 | 72 |
60 IPCChannelTest. | 73 IPCChannelTest. |
61 SendMessageInChannelConnected | 74 SendMessageInChannelConnected |
62 IPCSyncChannelTest. | 75 IPCSyncChannelTest. |
63 Simple | 76 Simple |
64 DISABLED_SendWithTimeoutMixedOKAndTimeout | 77 DISABLED_SendWithTimeoutMixedOKAndTimeout |
65 | 78 |
66 Returns: | 79 Returns: |
67 A list of non-disabled tests. For the above raw listing: | 80 A list of non-disabled tests. For the above raw listing: |
68 | 81 |
(...skipping 10 matching lines...) Expand all Loading... |
79 continue | 92 continue |
80 if test[0] != ' ' and test.endswith('.'): | 93 if test[0] != ' ' and test.endswith('.'): |
81 current = test | 94 current = test |
82 continue | 95 continue |
83 if 'YOU HAVE' in test: | 96 if 'YOU HAVE' in test: |
84 break | 97 break |
85 test_name = test[2:] | 98 test_name = test[2:] |
86 if not any([test_name.startswith(x) for x in disabled_prefixes]): | 99 if not any([test_name.startswith(x) for x in disabled_prefixes]): |
87 ret += [current + test_name] | 100 ret += [current + test_name] |
88 return ret | 101 return ret |
89 | |
90 def _WatchTestOutput(self, p): | |
91 """Watches the test output. | |
92 | |
93 Args: | |
94 p: the process generating output as created by pexpect.spawn. | |
95 | |
96 Returns: | |
97 A TestRunResults object. | |
98 """ | |
99 results = base_test_result.TestRunResults() | |
100 | |
101 # Test case statuses. | |
102 re_run = re.compile('\[ RUN \] ?(.*)\r\n') | |
103 re_fail = re.compile('\[ FAILED \] ?(.*)\r\n') | |
104 re_ok = re.compile('\[ OK \] ?(.*?) .*\r\n') | |
105 | |
106 # Test run statuses. | |
107 re_passed = re.compile('\[ PASSED \] ?(.*)\r\n') | |
108 re_runner_fail = re.compile('\[ RUNNER_FAILED \] ?(.*)\r\n') | |
109 # Signal handlers are installed before starting tests | |
110 # to output the CRASHED marker when a crash happens. | |
111 re_crash = re.compile('\[ CRASHED \](.*)\r\n') | |
112 | |
113 log = '' | |
114 try: | |
115 while True: | |
116 full_test_name = None | |
117 found = p.expect([re_run, re_passed, re_runner_fail], | |
118 timeout=self.timeout) | |
119 if found == 1: # re_passed | |
120 break | |
121 elif found == 2: # re_runner_fail | |
122 break | |
123 else: # re_run | |
124 full_test_name = p.match.group(1).replace('\r', '') | |
125 found = p.expect([re_ok, re_fail, re_crash], timeout=self.timeout) | |
126 log = p.before.replace('\r', '') | |
127 if found == 0: # re_ok | |
128 if full_test_name == p.match.group(1).replace('\r', ''): | |
129 results.AddResult(base_test_result.BaseTestResult( | |
130 full_test_name, base_test_result.ResultType.PASS, | |
131 log=log)) | |
132 elif found == 2: # re_crash | |
133 results.AddResult(base_test_result.BaseTestResult( | |
134 full_test_name, base_test_result.ResultType.CRASH, | |
135 log=log)) | |
136 break | |
137 else: # re_fail | |
138 results.AddResult(base_test_result.BaseTestResult( | |
139 full_test_name, base_test_result.ResultType.FAIL, log=log)) | |
140 except pexpect.EOF: | |
141 logging.error('Test terminated - EOF') | |
142 # We're here because either the device went offline, or the test harness | |
143 # crashed without outputting the CRASHED marker (crbug.com/175538). | |
144 if not self.adb.IsOnline(): | |
145 raise errors.DeviceUnresponsiveError('Device %s went offline.' % | |
146 self.device) | |
147 if full_test_name: | |
148 results.AddResult(base_test_result.BaseTestResult( | |
149 full_test_name, base_test_result.ResultType.CRASH, | |
150 log=p.before.replace('\r', ''))) | |
151 except pexpect.TIMEOUT: | |
152 logging.error('Test terminated after %d second timeout.', | |
153 self.timeout) | |
154 if full_test_name: | |
155 results.AddResult(base_test_result.BaseTestResult( | |
156 full_test_name, base_test_result.ResultType.TIMEOUT, | |
157 log=p.before.replace('\r', ''))) | |
158 finally: | |
159 p.close() | |
160 | |
161 ret_code = self._GetGTestReturnCode() | |
162 if ret_code: | |
163 logging.critical( | |
164 'gtest exit code: %d\npexpect.before: %s\npexpect.after: %s', | |
165 ret_code, p.before, p.after) | |
166 | |
167 return results | |
OLD | NEW |