/3rd_party/llvm/utils/lit/lit/Test.py

https://code.google.com/p/softart/ · Python · 190 lines · 97 code · 37 blank · 56 comment · 12 complexity · 1e15bfbc343744bf7cc2ffa45d3377a2 MD5 · raw file

  1. import os
  2. # Test result codes.
  3. class ResultCode(object):
  4. """Test result codes."""
  5. # We override __new__ and __getnewargs__ to ensure that pickling still
  6. # provides unique ResultCode objects in any particular instance.
  7. _instances = {}
  8. def __new__(cls, name, isFailure):
  9. res = cls._instances.get(name)
  10. if res is None:
  11. cls._instances[name] = res = super(ResultCode, cls).__new__(cls)
  12. return res
  13. def __getnewargs__(self):
  14. return (self.name, self.isFailure)
  15. def __init__(self, name, isFailure):
  16. self.name = name
  17. self.isFailure = isFailure
  18. def __repr__(self):
  19. return '%s%r' % (self.__class__.__name__,
  20. (self.name, self.isFailure))
  21. PASS = ResultCode('PASS', False)
  22. XFAIL = ResultCode('XFAIL', False)
  23. FAIL = ResultCode('FAIL', True)
  24. XPASS = ResultCode('XPASS', True)
  25. UNRESOLVED = ResultCode('UNRESOLVED', True)
  26. UNSUPPORTED = ResultCode('UNSUPPORTED', False)
  27. # Test metric values.
  28. class MetricValue(object):
  29. def format(self):
  30. """
  31. format() -> str
  32. Convert this metric to a string suitable for displaying as part of the
  33. console output.
  34. """
  35. raise RuntimeError("abstract method")
  36. def todata(self):
  37. """
  38. todata() -> json-serializable data
  39. Convert this metric to content suitable for serializing in the JSON test
  40. output.
  41. """
  42. raise RuntimeError("abstract method")
  43. class IntMetricValue(MetricValue):
  44. def __init__(self, value):
  45. self.value = value
  46. def format(self):
  47. return str(self.value)
  48. def todata(self):
  49. return self.value
  50. class RealMetricValue(MetricValue):
  51. def __init__(self, value):
  52. self.value = value
  53. def format(self):
  54. return '%.4f' % self.value
  55. def todata(self):
  56. return self.value
  57. # Test results.
  58. class Result(object):
  59. """Wrapper for the results of executing an individual test."""
  60. def __init__(self, code, output='', elapsed=None):
  61. # The result code.
  62. self.code = code
  63. # The test output.
  64. self.output = output
  65. # The wall timing to execute the test, if timing.
  66. self.elapsed = elapsed
  67. # The metrics reported by this test.
  68. self.metrics = {}
  69. def addMetric(self, name, value):
  70. """
  71. addMetric(name, value)
  72. Attach a test metric to the test result, with the given name and list of
  73. values. It is an error to attempt to attach the metrics with the same
  74. name multiple times.
  75. Each value must be an instance of a MetricValue subclass.
  76. """
  77. if name in self.metrics:
  78. raise ValueError("result already includes metrics for %r" % (
  79. name,))
  80. if not isinstance(value, MetricValue):
  81. raise TypeError("unexpected metric value: %r" % (value,))
  82. self.metrics[name] = value
  83. # Test classes.
  84. class TestSuite:
  85. """TestSuite - Information on a group of tests.
  86. A test suite groups together a set of logically related tests.
  87. """
  88. def __init__(self, name, source_root, exec_root, config):
  89. self.name = name
  90. self.source_root = source_root
  91. self.exec_root = exec_root
  92. # The test suite configuration.
  93. self.config = config
  94. def getSourcePath(self, components):
  95. return os.path.join(self.source_root, *components)
  96. def getExecPath(self, components):
  97. return os.path.join(self.exec_root, *components)
  98. class Test:
  99. """Test - Information on a single test instance."""
  100. def __init__(self, suite, path_in_suite, config):
  101. self.suite = suite
  102. self.path_in_suite = path_in_suite
  103. self.config = config
  104. # A list of conditions under which this test is expected to fail. These
  105. # can optionally be provided by test format handlers, and will be
  106. # honored when the test result is supplied.
  107. self.xfails = []
  108. # The test result, once complete.
  109. self.result = None
  110. def setResult(self, result):
  111. if self.result is not None:
  112. raise ArgumentError("test result already set")
  113. if not isinstance(result, Result):
  114. raise ArgumentError("unexpected result type")
  115. self.result = result
  116. # Apply the XFAIL handling to resolve the result exit code.
  117. if self.isExpectedToFail():
  118. if self.result.code == PASS:
  119. self.result.code = XPASS
  120. elif self.result.code == FAIL:
  121. self.result.code = XFAIL
  122. def getFullName(self):
  123. return self.suite.config.name + ' :: ' + '/'.join(self.path_in_suite)
  124. def getSourcePath(self):
  125. return self.suite.getSourcePath(self.path_in_suite)
  126. def getExecPath(self):
  127. return self.suite.getExecPath(self.path_in_suite)
  128. def isExpectedToFail(self):
  129. """
  130. isExpectedToFail() -> bool
  131. Check whether this test is expected to fail in the current
  132. configuration. This check relies on the test xfails property which by
  133. some test formats may not be computed until the test has first been
  134. executed.
  135. """
  136. # Check if any of the xfails match an available feature or the target.
  137. for item in self.xfails:
  138. # If this is the wildcard, it always fails.
  139. if item == '*':
  140. return True
  141. # If this is an exact match for one of the features, it fails.
  142. if item in self.config.available_features:
  143. return True
  144. # If this is a part of the target triple, it fails.
  145. if item in self.suite.config.target_triple:
  146. return True
  147. return False