1# Copyright 2015, 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 collections 28import multiprocessing 29import re 30import time 31 32import printer 33import thread_pool 34 35REGEXP_MISSING_FEATURES = "Missing features: { ([^,}]+(, [^,}]+)*) }" 36 37class Test(object): 38 # Shared state for multiprocessing. Ideally the context should be passed with 39 # arguments, but constraints from the multiprocessing module prevent us from 40 # doing so: the shared variables (multiprocessing.Value) must be either global 41 # or static, or no work is started. 42 n_tests_passed = multiprocessing.Value('i', 0) 43 n_tests_failed = multiprocessing.Value('i', 0) 44 n_tests_skipped = multiprocessing.Value('i', 0) 45 manager = multiprocessing.Manager() 46 47 def __init__(self, name, shared, **kwargs): 48 self.name = name 49 self.shared = shared 50 self.args = kwargs 51 52class TestQueue(object): 53 def __init__(self, prefix = ''): 54 self.progress_prefix = prefix 55 self.queue = [] 56 self.tests_skipped = Test.manager.dict() 57 self.n_known_failures = 0 58 self.known_failures = collections.Counter() 59 60 def AddKnownFailures(self, reason, n_tests): 61 self.n_known_failures += n_tests 62 self.known_failures[reason] += n_tests 63 64 def AddTest(self, name, **kwargs): 65 self.queue.append(Test(name, self, **kwargs)) 66 67 # Run the specified tests. 68 def Run(self, jobs, verbose, run_function): 69 def InitGlobals(): 70 # Initialisation. 71 self.start_time = time.time() 72 self.n_tests = len(self.queue) 73 if self.n_tests == 0: 74 printer.Print('No tests to run.') 75 return False 76 Test.n_tests_passed.value = 0 77 Test.n_tests_failed.value = 0 78 Test.n_tests_skipped.value = 0 79 self.tests_skipped.clear() 80 return True 81 82 thread_pool.Multithread(run_function, self.queue, jobs, InitGlobals) 83 84 printer.UpdateProgress(self.start_time, 85 Test.n_tests_passed.value, 86 Test.n_tests_failed.value, 87 self.n_tests, 88 Test.n_tests_skipped.value, 89 self.n_known_failures, 90 '== Done ==', 91 prevent_next_overwrite = True, 92 prefix = self.progress_prefix) 93 n_tests_features = 0 94 features = set() 95 for reason, n_tests in self.tests_skipped.items(): 96 m = re.match(REGEXP_MISSING_FEATURES, reason) 97 if m: 98 if verbose: 99 printer.Print("%d tests skipped because the following features are not " 100 "available '%s'" % (n_tests, m.group(1))) 101 else: 102 n_tests_features += n_tests 103 features.update(m.group(1).split(', ')) 104 else: 105 printer.Print("%d tests skipped because '%s'" % (n_tests, reason)) 106 107 n_tests_other = 0 108 if n_tests_features > 0 : 109 printer.Print("%d tests skipped because the CPU does not support " 110 "the following features: '%s'" % 111 (n_tests_features, ", ".join(features))) 112 113 for reason, n_tests in self.known_failures.items(): 114 printer.Print("%d tests skipped because '%s'" % (n_tests, reason)) 115 116 # Empty the queue now that the tests have been run. 117 self.queue = [] 118 # `0` indicates success 119 return Test.n_tests_failed.value 120 121