test_failures.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. # Copyright (C) 2010 Google Inc. All rights reserved.
  2. #
  3. # Redistribution and use in source and binary forms, with or without
  4. # modification, are permitted provided that the following conditions are
  5. # met:
  6. #
  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
  12. # distribution.
  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.
  16. #
  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.
  28. import cPickle
  29. from webkitpy.layout_tests.models import test_expectations
  30. def is_reftest_failure(failure_list):
  31. failure_types = [type(f) for f in failure_list]
  32. return set((FailureReftestMismatch, FailureReftestMismatchDidNotOccur, FailureReftestNoImagesGenerated)).intersection(failure_types)
  33. # FIXME: This is backwards. Each TestFailure subclass should know what
  34. # test_expectation type it corresponds too. Then this method just
  35. # collects them all from the failure list and returns the worst one.
  36. def determine_result_type(failure_list):
  37. """Takes a set of test_failures and returns which result type best fits
  38. the list of failures. "Best fits" means we use the worst type of failure.
  39. Returns:
  40. one of the test_expectations result types - PASS, FAIL, CRASH, etc."""
  41. if not failure_list or len(failure_list) == 0:
  42. return test_expectations.PASS
  43. failure_types = [type(f) for f in failure_list]
  44. if FailureCrash in failure_types:
  45. return test_expectations.CRASH
  46. elif FailureTimeout in failure_types:
  47. return test_expectations.TIMEOUT
  48. elif FailureEarlyExit in failure_types:
  49. return test_expectations.SKIP
  50. elif (FailureMissingResult in failure_types or
  51. FailureMissingImage in failure_types or
  52. FailureMissingImageHash in failure_types or
  53. FailureMissingAudio in failure_types):
  54. return test_expectations.MISSING
  55. else:
  56. is_text_failure = FailureTextMismatch in failure_types
  57. is_image_failure = (FailureImageHashIncorrect in failure_types or
  58. FailureImageHashMismatch in failure_types)
  59. is_audio_failure = (FailureAudioMismatch in failure_types)
  60. if is_text_failure and is_image_failure:
  61. return test_expectations.IMAGE_PLUS_TEXT
  62. elif is_text_failure:
  63. return test_expectations.TEXT
  64. elif is_image_failure or is_reftest_failure(failure_list):
  65. return test_expectations.IMAGE
  66. elif is_audio_failure:
  67. return test_expectations.AUDIO
  68. else:
  69. raise ValueError("unclassifiable set of failures: "
  70. + str(failure_types))
  71. class TestFailure(object):
  72. """Abstract base class that defines the failure interface."""
  73. @staticmethod
  74. def loads(s):
  75. """Creates a TestFailure object from the specified string."""
  76. return cPickle.loads(s)
  77. def message(self):
  78. """Returns a string describing the failure in more detail."""
  79. raise NotImplementedError
  80. def __eq__(self, other):
  81. return self.__class__.__name__ == other.__class__.__name__
  82. def __ne__(self, other):
  83. return self.__class__.__name__ != other.__class__.__name__
  84. def __hash__(self):
  85. return hash(self.__class__.__name__)
  86. def dumps(self):
  87. """Returns the string/JSON representation of a TestFailure."""
  88. return cPickle.dumps(self)
  89. def driver_needs_restart(self):
  90. """Returns True if we should kill DumpRenderTree/WebKitTestRunner before the next test."""
  91. return False
  92. class FailureTimeout(TestFailure):
  93. def __init__(self, is_reftest=False):
  94. super(FailureTimeout, self).__init__()
  95. self.is_reftest = is_reftest
  96. def message(self):
  97. return "test timed out"
  98. def driver_needs_restart(self):
  99. return True
  100. class FailureCrash(TestFailure):
  101. def __init__(self, is_reftest=False, process_name='DumpRenderTree', pid=None):
  102. super(FailureCrash, self).__init__()
  103. self.process_name = process_name
  104. self.pid = pid
  105. self.is_reftest = is_reftest
  106. def message(self):
  107. if self.pid:
  108. return "%s crashed [pid=%d]" % (self.process_name, self.pid)
  109. return self.process_name + " crashed"
  110. def driver_needs_restart(self):
  111. return True
  112. class FailureMissingResult(TestFailure):
  113. def message(self):
  114. return "-expected.txt was missing"
  115. class FailureTextMismatch(TestFailure):
  116. def message(self):
  117. return "text diff"
  118. class FailureMissingImageHash(TestFailure):
  119. def message(self):
  120. return "-expected.png was missing an embedded checksum"
  121. class FailureMissingImage(TestFailure):
  122. def message(self):
  123. return "-expected.png was missing"
  124. class FailureImageHashMismatch(TestFailure):
  125. def __init__(self, diff_percent=0):
  126. super(FailureImageHashMismatch, self).__init__()
  127. self.diff_percent = diff_percent
  128. def message(self):
  129. return "image diff"
  130. class FailureImageHashIncorrect(TestFailure):
  131. def message(self):
  132. return "-expected.png embedded checksum is incorrect"
  133. class FailureReftestMismatch(TestFailure):
  134. def __init__(self, reference_filename=None):
  135. super(FailureReftestMismatch, self).__init__()
  136. self.reference_filename = reference_filename
  137. self.diff_percent = None
  138. def message(self):
  139. return "reference mismatch"
  140. class FailureReftestMismatchDidNotOccur(TestFailure):
  141. def __init__(self, reference_filename=None):
  142. super(FailureReftestMismatchDidNotOccur, self).__init__()
  143. self.reference_filename = reference_filename
  144. def message(self):
  145. return "reference mismatch didn't happen"
  146. class FailureReftestNoImagesGenerated(TestFailure):
  147. def __init__(self, reference_filename=None):
  148. super(FailureReftestNoImagesGenerated, self).__init__()
  149. self.reference_filename = reference_filename
  150. def message(self):
  151. return "reference didn't generate pixel results."
  152. class FailureMissingAudio(TestFailure):
  153. def message(self):
  154. return "expected audio result was missing"
  155. class FailureAudioMismatch(TestFailure):
  156. def message(self):
  157. return "audio mismatch"
  158. class FailureEarlyExit(TestFailure):
  159. def message(self):
  160. return "skipped due to early exit"
  161. # Convenient collection of all failure classes for anything that might
  162. # need to enumerate over them all.
  163. ALL_FAILURE_CLASSES = (FailureTimeout, FailureCrash, FailureMissingResult,
  164. FailureTextMismatch, FailureMissingImageHash,
  165. FailureMissingImage, FailureImageHashMismatch,
  166. FailureImageHashIncorrect, FailureReftestMismatch,
  167. FailureReftestMismatchDidNotOccur, FailureReftestNoImagesGenerated,
  168. FailureMissingAudio, FailureAudioMismatch,
  169. FailureEarlyExit)