• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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