1# Copyright 2019, VIXL authors 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are met: 6# 7# * Redistributions of source code must retain the above copyright notice, 8# this list of conditions and the following disclaimer. 9# * Redistributions in binary form must reproduce the above copyright notice, 10# this list of conditions and the following disclaimer in the documentation 11# and/or other materials provided with the distribution. 12# * Neither the name of ARM Limited nor the names of its contributors may be 13# used to endorse or promote products derived from this software without 14# specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27import re 28import subprocess 29 30from known_test_failures import FilterKnownTestFailures 31import printer 32import threaded_tests 33from threaded_tests import Test 34import util 35 36# Scan matching tests and return a test manifest. 37def GetTests(runner, filters = []): 38 cmd = runner + ' --list' 39 rc, output = util.getstatusoutput(cmd) 40 if rc != 0: util.abort("Failed to list all tests. Output of " + cmd + ":\n" + output) 41 42 tests = output.split() 43 for f in filters: 44 tests = filter(re.compile(f).search, tests) 45 46 return tests 47 48def RunTest(test): 49 command = test.args['command'] 50 p = subprocess.Popen(command, 51 stdout=subprocess.PIPE, 52 stderr=subprocess.STDOUT) 53 p_out, p_err = p.communicate() 54 rc = p.poll() 55 56 if rc == 0: 57 skipped = False 58 lines = p_out.split('\n') 59 skipped_id = "SKIPPED: " 60 for i in range(len(lines)): 61 if lines[i].startswith(skipped_id): 62 skipped = True 63 reason = lines[i][len(skipped_id):] 64 with Test.n_tests_skipped.get_lock(): 65 Test.n_tests_skipped.value += 1 66 test.shared.tests_skipped.setdefault(reason, 0) 67 test.shared.tests_skipped[reason] += 1 68 break 69 if not skipped: 70 with Test.n_tests_passed.get_lock(): Test.n_tests_passed.value += 1 71 else: 72 with Test.n_tests_failed.get_lock(): Test.n_tests_failed.value += 1 73 74 printer.__print_lock__.acquire() 75 76 printer.UpdateProgress(test.shared.start_time, 77 Test.n_tests_passed.value, 78 Test.n_tests_failed.value, 79 test.shared.n_tests, 80 Test.n_tests_skipped.value, 81 test.shared.n_known_failures, 82 test.name, 83 prevent_next_overwrite = (rc != 0), 84 has_lock = True, 85 prefix = test.shared.progress_prefix) 86 87 if rc != 0: 88 printer.Print('FAILED: ' + test.name, has_lock = True) 89 printer.Print(printer.COLOUR_RED + ' '.join(command) + printer.NO_COLOUR, 90 has_lock = True) 91 printer.Print(p_out, has_lock = True) 92 93 printer.__print_lock__.release() 94 95class TestQueue(threaded_tests.TestQueue): 96 def __init__(self): 97 super(TestQueue, self).__init__('test_runner: ') 98 99 def AddTests(self, test_runner_command, filters, runtime_options, under_valgrind): 100 tests = GetTests(test_runner_command, filters) 101 n_tests_total = len(tests) 102 tests, skipped = FilterKnownTestFailures(tests, under_valgrind = under_valgrind) 103 for n_tests, reason in skipped: 104 if n_tests > 0: 105 self.AddKnownFailures(reason, n_tests) 106 107 if len(tests) == 0: 108 printer.Print('No tests to run.') 109 return 110 111 base_command = [] 112 if under_valgrind: 113 base_command += ['valgrind'] 114 base_command += [test_runner_command] 115 for test in tests: 116 command = base_command + [test] + runtime_options 117 self.AddTest(test, command = command) 118 119 def Run(self, jobs, verbose): 120 return super(TestQueue, self).Run(jobs, verbose, RunTest) 121