xref: /aosp_15_r20/external/vixl/tools/threaded_tests.py (revision f5c631da2f1efdd72b5fd1e20510e4042af13d77)
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