1 # Copyright (C) 2010 Google Inc. All rights reserved.
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer
11 # in the documentation and/or other materials provided with the
13 # * Neither the name of Google Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived from
15 # this software without specific prior written permission.
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 from webkitpy.layout_tests.models import test_expectations
34 def is_reftest_failure(failure_list):
35 failure_types = [type(f) for f in failure_list]
36 return set((FailureReftestMismatch, FailureReftestMismatchDidNotOccur, FailureReftestNoImagesGenerated)).intersection(failure_types)
38 # FIXME: This is backwards. Each TestFailure subclass should know what
39 # test_expectation type it corresponds too. Then this method just
40 # collects them all from the failure list and returns the worst one.
41 def determine_result_type(failure_list):
42 """Takes a set of test_failures and returns which result type best fits
43 the list of failures. "Best fits" means we use the worst type of failure.
46 one of the test_expectations result types - PASS, FAIL, CRASH, etc."""
48 if not failure_list or len(failure_list) == 0:
49 return test_expectations.PASS
51 failure_types = [type(f) for f in failure_list]
52 if FailureCrash in failure_types:
53 return test_expectations.CRASH
54 elif FailureLeak in failure_types:
55 return test_expectations.LEAK
56 elif FailureTimeout in failure_types:
57 return test_expectations.TIMEOUT
58 elif FailureEarlyExit in failure_types:
59 return test_expectations.SKIP
60 elif (FailureMissingResult in failure_types or
61 FailureMissingImage in failure_types or
62 FailureMissingImageHash in failure_types or
63 FailureMissingAudio in failure_types):
64 return test_expectations.MISSING
66 is_text_failure = (FailureTextMismatch in failure_types or
67 FailureTestHarnessAssertion in failure_types)
68 is_image_failure = (FailureImageHashIncorrect in failure_types or
69 FailureImageHashMismatch in failure_types)
70 is_audio_failure = (FailureAudioMismatch in failure_types)
71 if is_text_failure and is_image_failure:
72 return test_expectations.IMAGE_PLUS_TEXT
74 return test_expectations.TEXT
75 elif is_image_failure or is_reftest_failure(failure_list):
76 return test_expectations.IMAGE
77 elif is_audio_failure:
78 return test_expectations.AUDIO
80 raise ValueError("unclassifiable set of failures: "
84 class TestFailure(object):
85 """Abstract base class that defines the failure interface."""
89 """Creates a TestFailure object from the specified string."""
90 return cPickle.loads(s)
93 """Returns a string describing the failure in more detail."""
94 raise NotImplementedError
96 def __eq__(self, other):
97 return self.__class__.__name__ == other.__class__.__name__
99 def __ne__(self, other):
100 return self.__class__.__name__ != other.__class__.__name__
103 return hash(self.__class__.__name__)
106 """Returns the string/JSON representation of a TestFailure."""
107 return cPickle.dumps(self)
109 def driver_needs_restart(self):
110 """Returns True if we should kill the driver before the next test."""
114 class FailureTimeout(TestFailure):
115 def __init__(self, is_reftest=False):
116 super(FailureTimeout, self).__init__()
117 self.is_reftest = is_reftest
120 return "test timed out"
122 def driver_needs_restart(self):
126 class FailureCrash(TestFailure):
127 def __init__(self, is_reftest=False, process_name='content_shell', pid=None, has_log=False):
128 super(FailureCrash, self).__init__()
129 self.process_name = process_name
131 self.is_reftest = is_reftest
132 self.has_log = has_log
136 return "%s crashed [pid=%d]" % (self.process_name, self.pid)
137 return self.process_name + " crashed"
139 def driver_needs_restart(self):
143 class FailureLeak(TestFailure):
144 def __init__(self, is_reftest=False, log=''):
145 super(FailureLeak, self).__init__()
146 self.is_reftest = is_reftest
150 return "leak detected: %s" % (self.log)
153 class FailureMissingResult(TestFailure):
155 return "-expected.txt was missing"
158 class FailureTestHarnessAssertion(TestFailure):
160 return "asserts failed"
163 class FailureTextMismatch(TestFailure):
168 class FailureMissingImageHash(TestFailure):
170 return "-expected.png was missing an embedded checksum"
173 class FailureMissingImage(TestFailure):
175 return "-expected.png was missing"
178 class FailureImageHashMismatch(TestFailure):
183 class FailureImageHashIncorrect(TestFailure):
185 return "-expected.png embedded checksum is incorrect"
188 class FailureReftestMismatch(TestFailure):
189 def __init__(self, reference_filename=None):
190 super(FailureReftestMismatch, self).__init__()
191 self.reference_filename = reference_filename
194 return "reference mismatch"
197 class FailureReftestMismatchDidNotOccur(TestFailure):
198 def __init__(self, reference_filename=None):
199 super(FailureReftestMismatchDidNotOccur, self).__init__()
200 self.reference_filename = reference_filename
203 return "reference mismatch didn't happen"
206 class FailureReftestNoImagesGenerated(TestFailure):
207 def __init__(self, reference_filename=None):
208 super(FailureReftestNoImagesGenerated, self).__init__()
209 self.reference_filename = reference_filename
212 return "reference didn't generate pixel results."
215 class FailureMissingAudio(TestFailure):
217 return "expected audio result was missing"
220 class FailureAudioMismatch(TestFailure):
222 return "audio mismatch"
225 class FailureEarlyExit(TestFailure):
227 return "skipped due to early exit"
230 # Convenient collection of all failure classes for anything that might
231 # need to enumerate over them all.
232 ALL_FAILURE_CLASSES = (FailureTimeout, FailureCrash, FailureMissingResult,
233 FailureTestHarnessAssertion,
234 FailureTextMismatch, FailureMissingImageHash,
235 FailureMissingImage, FailureImageHashMismatch,
236 FailureImageHashIncorrect, FailureReftestMismatch,
237 FailureReftestMismatchDidNotOccur, FailureReftestNoImagesGenerated,
238 FailureMissingAudio, FailureAudioMismatch,