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 = list(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 p_out = p_out.decode() 55 rc = p.poll() 56 57 if rc == 0: 58 skipped = False 59 lines = p_out.split('\n') 60 skipped_id = "SKIPPED: " 61 for i in range(len(lines)): 62 if lines[i].startswith(skipped_id): 63 skipped = True 64 reason = lines[i][len(skipped_id):] 65 with Test.n_tests_skipped.get_lock(): 66 Test.n_tests_skipped.value += 1 67 test.shared.tests_skipped.setdefault(reason, 0) 68 test.shared.tests_skipped[reason] += 1 69 break 70 if not skipped: 71 with Test.n_tests_passed.get_lock(): Test.n_tests_passed.value += 1 72 else: 73 with Test.n_tests_failed.get_lock(): Test.n_tests_failed.value += 1 74 75 printer.__print_lock__.acquire() 76 77 printer.UpdateProgress(test.shared.start_time, 78 Test.n_tests_passed.value, 79 Test.n_tests_failed.value, 80 test.shared.n_tests, 81 Test.n_tests_skipped.value, 82 test.shared.n_known_failures, 83 test.name, 84 prevent_next_overwrite = (rc != 0), 85 has_lock = True, 86 prefix = test.shared.progress_prefix) 87 88 if rc != 0: 89 printer.Print('FAILED: ' + test.name, has_lock = True) 90 printer.Print(printer.COLOUR_RED + ' '.join(command) + printer.NO_COLOUR, 91 has_lock = True) 92 printer.Print(p_out, has_lock = True) 93 94 printer.__print_lock__.release() 95 96class TestQueue(threaded_tests.TestQueue): 97 def __init__(self): 98 super(TestQueue, self).__init__('test_runner: ') 99 100 def AddTests(self, test_runner_command, filters, runtime_options, under_valgrind): 101 tests = GetTests(test_runner_command, filters) 102 n_tests_total = len(tests) 103 tests, skipped = FilterKnownTestFailures(tests, under_valgrind = under_valgrind) 104 for n_tests, reason in skipped: 105 if n_tests > 0: 106 self.AddKnownFailures(reason, n_tests) 107 108 if len(tests) == 0: 109 printer.Print('No tests to run.') 110 return 111 112 base_command = [] 113 if under_valgrind: 114 base_command += ['valgrind'] 115 base_command += [test_runner_command] 116 for test in tests: 117 command = base_command + [test] + runtime_options 118 self.AddTest(test, command = command) 119 120 def Run(self, jobs, verbose): 121 return super(TestQueue, self).Run(jobs, verbose, RunTest) 122