| OLD | NEW |
| (Empty) |
| 1 # Copyright 2012 the V8 project authors. All rights reserved. | |
| 2 # Redistribution and use in source and binary forms, with or without | |
| 3 # modification, are permitted provided that the following conditions are | |
| 4 # met: | |
| 5 # | |
| 6 # * Redistributions of source code must retain the above copyright | |
| 7 # notice, this list of conditions and the following disclaimer. | |
| 8 # * Redistributions in binary form must reproduce the above | |
| 9 # copyright notice, this list of conditions and the following | |
| 10 # disclaimer in the documentation and/or other materials provided | |
| 11 # with the distribution. | |
| 12 # * Neither the name of Google Inc. nor the names of its | |
| 13 # contributors may be used to endorse or promote products derived | |
| 14 # from this software without specific prior written permission. | |
| 15 # | |
| 16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 27 | |
| 28 | |
| 29 import imp | |
| 30 import os | |
| 31 | |
| 32 from . import statusfile | |
| 33 | |
| 34 class TestSuite(object): | |
| 35 | |
| 36 @staticmethod | |
| 37 def LoadTestSuite(root): | |
| 38 name = root.split(os.path.sep)[-1] | |
| 39 f = None | |
| 40 try: | |
| 41 (f, pathname, description) = imp.find_module("testcfg", [root]) | |
| 42 module = imp.load_module("testcfg", f, pathname, description) | |
| 43 suite = module.GetSuite(name, root) | |
| 44 finally: | |
| 45 if f: | |
| 46 f.close() | |
| 47 return suite | |
| 48 | |
| 49 def __init__(self, name, root): | |
| 50 self.name = name # string | |
| 51 self.root = root # string containing path | |
| 52 self.tests = None # list of TestCase objects | |
| 53 self.rules = None # dictionary mapping test path to list of outcomes | |
| 54 self.wildcards = None # dictionary mapping test paths to list of outcomes | |
| 55 self.total_duration = None # float, assigned on demand | |
| 56 | |
| 57 def shell(self): | |
| 58 return "d8" | |
| 59 | |
| 60 def suffix(self): | |
| 61 return ".js" | |
| 62 | |
| 63 def status_file(self): | |
| 64 return "%s/%s.status" % (self.root, self.name) | |
| 65 | |
| 66 # Used in the status file and for stdout printing. | |
| 67 def CommonTestName(self, testcase): | |
| 68 return testcase.path | |
| 69 | |
| 70 def ListTests(self, context): | |
| 71 raise NotImplementedError | |
| 72 | |
| 73 def VariantFlags(self): | |
| 74 return None | |
| 75 | |
| 76 def DownloadData(self): | |
| 77 pass | |
| 78 | |
| 79 def ReadStatusFile(self, variables): | |
| 80 (self.rules, self.wildcards) = \ | |
| 81 statusfile.ReadStatusFile(self.status_file(), variables) | |
| 82 | |
| 83 def ReadTestCases(self, context): | |
| 84 self.tests = self.ListTests(context) | |
| 85 | |
| 86 def FilterTestCasesByStatus(self, warn_unused_rules): | |
| 87 filtered = [] | |
| 88 used_rules = set() | |
| 89 for t in self.tests: | |
| 90 testname = self.CommonTestName(t) | |
| 91 if testname in self.rules: | |
| 92 used_rules.add(testname) | |
| 93 outcomes = self.rules[testname] | |
| 94 t.outcomes = outcomes # Even for skipped tests, as the TestCase | |
| 95 # object stays around and PrintReport() uses it. | |
| 96 if statusfile.DoSkip(outcomes): | |
| 97 continue # Don't add skipped tests to |filtered|. | |
| 98 if len(self.wildcards) != 0: | |
| 99 skip = False | |
| 100 for rule in self.wildcards: | |
| 101 assert rule[-1] == '*' | |
| 102 if testname.startswith(rule[:-1]): | |
| 103 used_rules.add(rule) | |
| 104 outcomes = self.wildcards[rule] | |
| 105 t.outcomes = outcomes | |
| 106 if statusfile.DoSkip(outcomes): | |
| 107 skip = True | |
| 108 break # "for rule in self.wildcards" | |
| 109 if skip: continue # "for t in self.tests" | |
| 110 filtered.append(t) | |
| 111 self.tests = filtered | |
| 112 | |
| 113 if not warn_unused_rules: | |
| 114 return | |
| 115 | |
| 116 for rule in self.rules: | |
| 117 if rule not in used_rules: | |
| 118 print("Unused rule: %s -> %s" % (rule, self.rules[rule])) | |
| 119 for rule in self.wildcards: | |
| 120 if rule not in used_rules: | |
| 121 print("Unused rule: %s -> %s" % (rule, self.wildcards[rule])) | |
| 122 | |
| 123 def FilterTestCasesByArgs(self, args): | |
| 124 filtered = [] | |
| 125 filtered_args = [] | |
| 126 for a in args: | |
| 127 argpath = a.split(os.path.sep) | |
| 128 if argpath[0] != self.name: | |
| 129 continue | |
| 130 if len(argpath) == 1 or (len(argpath) == 2 and argpath[1] == '*'): | |
| 131 return # Don't filter, run all tests in this suite. | |
| 132 path = os.path.sep.join(argpath[1:]) | |
| 133 if path[-1] == '*': | |
| 134 path = path[:-1] | |
| 135 filtered_args.append(path) | |
| 136 for t in self.tests: | |
| 137 for a in filtered_args: | |
| 138 if t.path.startswith(a): | |
| 139 filtered.append(t) | |
| 140 break | |
| 141 self.tests = filtered | |
| 142 | |
| 143 def GetFlagsForTestCase(self, testcase, context): | |
| 144 raise NotImplementedError | |
| 145 | |
| 146 def GetSourceForTest(self, testcase): | |
| 147 return "(no source available)" | |
| 148 | |
| 149 def IsFailureOutput(self, output, testpath): | |
| 150 return output.exit_code != 0 | |
| 151 | |
| 152 def IsNegativeTest(self, testcase): | |
| 153 return False | |
| 154 | |
| 155 def HasFailed(self, testcase): | |
| 156 execution_failed = self.IsFailureOutput(testcase.output, testcase.path) | |
| 157 if self.IsNegativeTest(testcase): | |
| 158 return not execution_failed | |
| 159 else: | |
| 160 return execution_failed | |
| 161 | |
| 162 def HasUnexpectedOutput(self, testcase): | |
| 163 if testcase.output.HasCrashed(): | |
| 164 outcome = statusfile.CRASH | |
| 165 elif testcase.output.HasTimedOut(): | |
| 166 outcome = statusfile.TIMEOUT | |
| 167 elif self.HasFailed(testcase): | |
| 168 outcome = statusfile.FAIL | |
| 169 else: | |
| 170 outcome = statusfile.PASS | |
| 171 if not testcase.outcomes: | |
| 172 return outcome != statusfile.PASS | |
| 173 return not outcome in testcase.outcomes | |
| 174 | |
| 175 def StripOutputForTransmit(self, testcase): | |
| 176 if not self.HasUnexpectedOutput(testcase): | |
| 177 testcase.output.stdout = "" | |
| 178 testcase.output.stderr = "" | |
| 179 | |
| 180 def CalculateTotalDuration(self): | |
| 181 self.total_duration = 0.0 | |
| 182 for t in self.tests: | |
| 183 self.total_duration += t.duration | |
| 184 return self.total_duration | |
| OLD | NEW |