1*f5c631daSSadaf Ebrahimi# Copyright 2015, VIXL authors 2*f5c631daSSadaf Ebrahimi# All rights reserved. 3*f5c631daSSadaf Ebrahimi# 4*f5c631daSSadaf Ebrahimi# Redistribution and use in source and binary forms, with or without 5*f5c631daSSadaf Ebrahimi# modification, are permitted provided that the following conditions are met: 6*f5c631daSSadaf Ebrahimi# 7*f5c631daSSadaf Ebrahimi# * Redistributions of source code must retain the above copyright notice, 8*f5c631daSSadaf Ebrahimi# this list of conditions and the following disclaimer. 9*f5c631daSSadaf Ebrahimi# * Redistributions in binary form must reproduce the above copyright notice, 10*f5c631daSSadaf Ebrahimi# this list of conditions and the following disclaimer in the documentation 11*f5c631daSSadaf Ebrahimi# and/or other materials provided with the distribution. 12*f5c631daSSadaf Ebrahimi# * Neither the name of ARM Limited nor the names of its contributors may be 13*f5c631daSSadaf Ebrahimi# used to endorse or promote products derived from this software without 14*f5c631daSSadaf Ebrahimi# specific prior written permission. 15*f5c631daSSadaf Ebrahimi# 16*f5c631daSSadaf Ebrahimi# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17*f5c631daSSadaf Ebrahimi# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18*f5c631daSSadaf Ebrahimi# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19*f5c631daSSadaf Ebrahimi# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20*f5c631daSSadaf Ebrahimi# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21*f5c631daSSadaf Ebrahimi# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22*f5c631daSSadaf Ebrahimi# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23*f5c631daSSadaf Ebrahimi# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24*f5c631daSSadaf Ebrahimi# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25*f5c631daSSadaf Ebrahimi# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26*f5c631daSSadaf Ebrahimi 27*f5c631daSSadaf Ebrahimiimport collections 28*f5c631daSSadaf Ebrahimiimport multiprocessing 29*f5c631daSSadaf Ebrahimiimport re 30*f5c631daSSadaf Ebrahimiimport time 31*f5c631daSSadaf Ebrahimi 32*f5c631daSSadaf Ebrahimiimport printer 33*f5c631daSSadaf Ebrahimiimport thread_pool 34*f5c631daSSadaf Ebrahimi 35*f5c631daSSadaf EbrahimiREGEXP_MISSING_FEATURES = "Missing features: { ([^,}]+(, [^,}]+)*) }" 36*f5c631daSSadaf Ebrahimi 37*f5c631daSSadaf Ebrahimiclass Test(object): 38*f5c631daSSadaf Ebrahimi # Shared state for multiprocessing. Ideally the context should be passed with 39*f5c631daSSadaf Ebrahimi # arguments, but constraints from the multiprocessing module prevent us from 40*f5c631daSSadaf Ebrahimi # doing so: the shared variables (multiprocessing.Value) must be either global 41*f5c631daSSadaf Ebrahimi # or static, or no work is started. 42*f5c631daSSadaf Ebrahimi n_tests_passed = multiprocessing.Value('i', 0) 43*f5c631daSSadaf Ebrahimi n_tests_failed = multiprocessing.Value('i', 0) 44*f5c631daSSadaf Ebrahimi n_tests_skipped = multiprocessing.Value('i', 0) 45*f5c631daSSadaf Ebrahimi manager = multiprocessing.Manager() 46*f5c631daSSadaf Ebrahimi 47*f5c631daSSadaf Ebrahimi def __init__(self, name, shared, **kwargs): 48*f5c631daSSadaf Ebrahimi self.name = name 49*f5c631daSSadaf Ebrahimi self.shared = shared 50*f5c631daSSadaf Ebrahimi self.args = kwargs 51*f5c631daSSadaf Ebrahimi 52*f5c631daSSadaf Ebrahimiclass TestQueue(object): 53*f5c631daSSadaf Ebrahimi def __init__(self, prefix = ''): 54*f5c631daSSadaf Ebrahimi self.progress_prefix = prefix 55*f5c631daSSadaf Ebrahimi self.queue = [] 56*f5c631daSSadaf Ebrahimi self.tests_skipped = Test.manager.dict() 57*f5c631daSSadaf Ebrahimi self.n_known_failures = 0 58*f5c631daSSadaf Ebrahimi self.known_failures = collections.Counter() 59*f5c631daSSadaf Ebrahimi 60*f5c631daSSadaf Ebrahimi def AddKnownFailures(self, reason, n_tests): 61*f5c631daSSadaf Ebrahimi self.n_known_failures += n_tests 62*f5c631daSSadaf Ebrahimi self.known_failures[reason] += n_tests 63*f5c631daSSadaf Ebrahimi 64*f5c631daSSadaf Ebrahimi def AddTest(self, name, **kwargs): 65*f5c631daSSadaf Ebrahimi self.queue.append(Test(name, self, **kwargs)) 66*f5c631daSSadaf Ebrahimi 67*f5c631daSSadaf Ebrahimi # Run the specified tests. 68*f5c631daSSadaf Ebrahimi def Run(self, jobs, verbose, run_function): 69*f5c631daSSadaf Ebrahimi def InitGlobals(): 70*f5c631daSSadaf Ebrahimi # Initialisation. 71*f5c631daSSadaf Ebrahimi self.start_time = time.time() 72*f5c631daSSadaf Ebrahimi self.n_tests = len(self.queue) 73*f5c631daSSadaf Ebrahimi if self.n_tests == 0: 74*f5c631daSSadaf Ebrahimi printer.Print('No tests to run.') 75*f5c631daSSadaf Ebrahimi return False 76*f5c631daSSadaf Ebrahimi Test.n_tests_passed.value = 0 77*f5c631daSSadaf Ebrahimi Test.n_tests_failed.value = 0 78*f5c631daSSadaf Ebrahimi Test.n_tests_skipped.value = 0 79*f5c631daSSadaf Ebrahimi self.tests_skipped.clear() 80*f5c631daSSadaf Ebrahimi return True 81*f5c631daSSadaf Ebrahimi 82*f5c631daSSadaf Ebrahimi thread_pool.Multithread(run_function, self.queue, jobs, InitGlobals) 83*f5c631daSSadaf Ebrahimi 84*f5c631daSSadaf Ebrahimi printer.UpdateProgress(self.start_time, 85*f5c631daSSadaf Ebrahimi Test.n_tests_passed.value, 86*f5c631daSSadaf Ebrahimi Test.n_tests_failed.value, 87*f5c631daSSadaf Ebrahimi self.n_tests, 88*f5c631daSSadaf Ebrahimi Test.n_tests_skipped.value, 89*f5c631daSSadaf Ebrahimi self.n_known_failures, 90*f5c631daSSadaf Ebrahimi '== Done ==', 91*f5c631daSSadaf Ebrahimi prevent_next_overwrite = True, 92*f5c631daSSadaf Ebrahimi prefix = self.progress_prefix) 93*f5c631daSSadaf Ebrahimi n_tests_features = 0 94*f5c631daSSadaf Ebrahimi features = set() 95*f5c631daSSadaf Ebrahimi for reason, n_tests in self.tests_skipped.items(): 96*f5c631daSSadaf Ebrahimi m = re.match(REGEXP_MISSING_FEATURES, reason) 97*f5c631daSSadaf Ebrahimi if m: 98*f5c631daSSadaf Ebrahimi if verbose: 99*f5c631daSSadaf Ebrahimi printer.Print("%d tests skipped because the following features are not " 100*f5c631daSSadaf Ebrahimi "available '%s'" % (n_tests, m.group(1))) 101*f5c631daSSadaf Ebrahimi else: 102*f5c631daSSadaf Ebrahimi n_tests_features += n_tests 103*f5c631daSSadaf Ebrahimi features.update(m.group(1).split(', ')) 104*f5c631daSSadaf Ebrahimi else: 105*f5c631daSSadaf Ebrahimi printer.Print("%d tests skipped because '%s'" % (n_tests, reason)) 106*f5c631daSSadaf Ebrahimi 107*f5c631daSSadaf Ebrahimi n_tests_other = 0 108*f5c631daSSadaf Ebrahimi if n_tests_features > 0 : 109*f5c631daSSadaf Ebrahimi printer.Print("%d tests skipped because the CPU does not support " 110*f5c631daSSadaf Ebrahimi "the following features: '%s'" % 111*f5c631daSSadaf Ebrahimi (n_tests_features, ", ".join(features))) 112*f5c631daSSadaf Ebrahimi 113*f5c631daSSadaf Ebrahimi for reason, n_tests in self.known_failures.items(): 114*f5c631daSSadaf Ebrahimi printer.Print("%d tests skipped because '%s'" % (n_tests, reason)) 115*f5c631daSSadaf Ebrahimi 116*f5c631daSSadaf Ebrahimi # Empty the queue now that the tests have been run. 117*f5c631daSSadaf Ebrahimi self.queue = [] 118*f5c631daSSadaf Ebrahimi # `0` indicates success 119*f5c631daSSadaf Ebrahimi return Test.n_tests_failed.value 120*f5c631daSSadaf Ebrahimi 121