OLD | NEW |
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 Queue | 7 import Queue |
8 import re | 8 import re |
9 import subprocess | 9 import subprocess |
10 import sys | 10 import sys |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 # Abort when 20 fixtures, or a tenth of the apptest fixtures, have failed. | 55 # Abort when 20 fixtures, or a tenth of the apptest fixtures, have failed. |
56 # base::TestLauncher does this for timeouts and unknown results. | 56 # base::TestLauncher does this for timeouts and unknown results. |
57 if len(failed) >= max(20, len(fixtures) / 10): | 57 if len(failed) >= max(20, len(fixtures) / 10): |
58 print 'Too many failing fixtures (%d), exiting now.' % len(failed) | 58 print 'Too many failing fixtures (%d), exiting now.' % len(failed) |
59 return (fixtures, failed + [apptest + ' aborted for excessive failures.']) | 59 return (fixtures, failed + [apptest + ' aborted for excessive failures.']) |
60 return (fixtures, failed) | 60 return (fixtures, failed) |
61 | 61 |
62 | 62 |
63 # TODO(msw): Determine proper test retry counts; allow configuration. | 63 # TODO(msw): Determine proper test retry counts; allow configuration. |
64 def _run_apptest_with_retry(config, shell, args, apptest, retry_count=2): | 64 def _run_apptest_with_retry(config, shell, args, apptest, retry_count=2): |
65 '''Runs an apptest, retrying on failure; returns the tests and failures.''' | 65 '''Runs an apptest, retrying on failure; returns the fixtures and failures.''' |
66 (tests, failed) = _run_apptest(config, shell, args, apptest) | 66 (tests, failed) = _run_apptest(config, shell, args, apptest) |
67 for retry in range(retry_count if failed else 0): | 67 while failed and retry_count: |
68 print 'Retrying failed tests: retry %s/%s.' % (retry + 1, retry_count) | 68 print 'Retrying failed tests (%d attempts remaining)' % retry_count |
69 # Retry only the failing fixtures; gtest honors its final filter argument. | 69 arguments = args |
70 arguments = args + ['--gtest_filter=%s' % ':'.join(failed)] | 70 # Retry only the failing fixtures if there is no existing filter specified. |
71 (_, failed) = _run_apptest(config, shell, arguments, apptest) | 71 if failed != [apptest] and not [a for a in args if '--gtest_filter=' in a]: |
| 72 arguments += ['--gtest_filter=%s' % ':'.join(failed)] |
| 73 failed = _run_apptest(config, shell, arguments, apptest)[1] |
| 74 retry_count -= 1 |
72 return (tests, failed) | 75 return (tests, failed) |
73 | 76 |
74 | 77 |
75 def _run_apptest(config, shell, args, apptest): | 78 def _run_apptest(config, shell, args, apptest): |
76 '''Runs an apptest; returns the list of tests and the list of failures.''' | 79 '''Runs an apptest; returns the list of fixtures and the list of failures.''' |
77 command = _build_command_line(config, args, apptest) | 80 command = _build_command_line(config, args, apptest) |
78 logging.getLogger().debug('Command: %s' % ' '.join(command)) | 81 logging.getLogger().debug('Command: %s' % ' '.join(command)) |
79 start_time = time.time() | 82 start_time = time.time() |
80 | 83 |
81 try: | 84 try: |
82 output = _run_test_with_xvfb(config, shell, args, apptest) | 85 output = _run_test_with_xvfb(config, shell, args, apptest) |
83 except Exception as e: | 86 except Exception as e: |
84 _print_exception(command, e) | 87 _print_exception(command, e) |
85 return ([apptest], [apptest]) | 88 return ([apptest], [apptest]) |
86 | 89 |
87 # Find all fixtures begun from gtest's '[ RUN ] <Suite.Fixture>' output. | 90 # Find all fixtures begun from gtest's '[ RUN ] <Suite.Fixture>' output. |
88 tests = [x for x in output.split('\n') if x.find('[ RUN ] ') != -1] | 91 tests = [x for x in output.split('\n') if x.find('[ RUN ] ') != -1] |
89 # The '[ RUN ] ' string is 23 chars with colored output escape sequences. | 92 tests = [x.strip(' \t\n\r')[x.find('[ RUN ] ') + 13:] for x in tests] |
90 substring_length = 13 if config.target_os == Config.OS_ANDROID else 23 | |
91 tests = [x.strip(' \t\n\r')[substring_length:] for x in tests] | |
92 | 93 |
93 # Fail on output with gtest's '[ FAILED ]' or a lack of '[ OK ]'. | 94 # Fail on output with gtest's '[ FAILED ]' or a lack of '[ OK ]'. |
94 # The latter check ensures failure on broken command lines, hung output, etc. | 95 # The latter check ensures failure on broken command lines, hung output, etc. |
95 # Check output instead of exit codes because mojo shell always exits with 0. | 96 # Check output instead of exit codes because mojo shell always exits with 0. |
96 failed = [x for x in tests if (re.search('\[ FAILED \].*' + x, output) or | 97 failed = [x for x in tests if (re.search('\[ FAILED \].*' + x, output) or |
97 not re.search('\[ OK \].*' + x, output))] | 98 not re.search('\[ OK \].*' + x, output))] |
98 | 99 |
99 ms = int(round(1000 * (time.time() - start_time))) | 100 ms = int(round(1000 * (time.time() - start_time))) |
100 if failed: | 101 if failed: |
101 _print_exception(command, output, ms) | 102 _print_exception(command, output, ms) |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 (r, w) = os.pipe() | 233 (r, w) = os.pipe() |
233 with os.fdopen(r, 'r') as rf: | 234 with os.fdopen(r, 'r') as rf: |
234 with os.fdopen(w, 'w') as wf: | 235 with os.fdopen(w, 'w') as wf: |
235 arguments = args + [apptest] | 236 arguments = args + [apptest] |
236 shell.StartActivity('MojoShellActivity', arguments, wf, wf.close) | 237 shell.StartActivity('MojoShellActivity', arguments, wf, wf.close) |
237 output = rf.read() | 238 output = rf.read() |
238 except Exception as e: | 239 except Exception as e: |
239 output += (e.output + '\n') if hasattr(e, 'output') else '' | 240 output += (e.output + '\n') if hasattr(e, 'output') else '' |
240 exception += str(e) | 241 exception += str(e) |
241 result.put((output, exception)) | 242 result.put((output, exception)) |
OLD | NEW |