summaryrefslogtreecommitdiffstats
path: root/lldb/packages/Python/lldbsuite/test/test_results.py
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/packages/Python/lldbsuite/test/test_results.py')
-rw-r--r--lldb/packages/Python/lldbsuite/test/test_results.py97
1 files changed, 74 insertions, 23 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/test_results.py b/lldb/packages/Python/lldbsuite/test/test_results.py
index 6f9cefe31d6..12fb2e51d77 100644
--- a/lldb/packages/Python/lldbsuite/test/test_results.py
+++ b/lldb/packages/Python/lldbsuite/test/test_results.py
@@ -29,11 +29,20 @@ from six.moves import cPickle
# LLDB modules
+
class EventBuilder(object):
"""Helper class to build test result event dictionaries."""
BASE_DICTIONARY = None
+ # Test Status Tags
+ STATUS_SUCCESS = "success"
+ STATUS_FAILURE = "failure"
+ STATUS_EXPECTED_FAILURE = "expected_failure"
+ STATUS_UNEXPECTED_SUCCESS = "unexpected_success"
+ STATUS_SKIP = "skip"
+ STATUS_ERROR = "error"
+
@staticmethod
def _get_test_name_info(test):
"""Returns (test-class-name, test-method-name) from a test case instance.
@@ -182,7 +191,8 @@ class EventBuilder(object):
@return the event dictionary
"""
- return EventBuilder._event_dictionary_test_result(test, "success")
+ return EventBuilder._event_dictionary_test_result(
+ test, EventBuilder.STATUS_SUCCESS)
@staticmethod
def event_for_unexpected_success(test, bugnumber):
@@ -199,7 +209,7 @@ class EventBuilder(object):
"""
event = EventBuilder._event_dictionary_test_result(
- test, "unexpected_success")
+ test, EventBuilder.STATUS_UNEXPECTED_SUCCESS)
if bugnumber:
event["bugnumber"] = str(bugnumber)
return event
@@ -216,7 +226,7 @@ class EventBuilder(object):
@return the event dictionary
"""
return EventBuilder._event_dictionary_issue(
- test, "failure", error_tuple)
+ test, EventBuilder.STATUS_FAILURE, error_tuple)
@staticmethod
def event_for_expected_failure(test, error_tuple, bugnumber):
@@ -234,7 +244,7 @@ class EventBuilder(object):
"""
event = EventBuilder._event_dictionary_issue(
- test, "expected_failure", error_tuple)
+ test, EventBuilder.STATUS_EXPECTED_FAILURE, error_tuple)
if bugnumber:
event["bugnumber"] = str(bugnumber)
return event
@@ -249,7 +259,8 @@ class EventBuilder(object):
@return the event dictionary
"""
- event = EventBuilder._event_dictionary_test_result(test, "skip")
+ event = EventBuilder._event_dictionary_test_result(
+ test, EventBuilder.STATUS_SKIP)
event["skip_reason"] = reason
return event
@@ -264,7 +275,8 @@ class EventBuilder(object):
@return the event dictionary
"""
- return EventBuilder._event_dictionary_issue(test, "error", error_tuple)
+ return EventBuilder._event_dictionary_issue(
+ test, EventBuilder.STATUS_ERROR, error_tuple)
@staticmethod
def event_for_cleanup_error(test, error_tuple):
@@ -279,7 +291,7 @@ class EventBuilder(object):
@return the event dictionary
"""
event = EventBuilder._event_dictionary_issue(
- test, "error", error_tuple)
+ test, EventBuilder.STATUS_ERROR, error_tuple)
event["issue_phase"] = "cleanup"
return event
@@ -376,7 +388,6 @@ class ResultsFormatter(object):
expectations about when the call should be chained.
"""
-
@classmethod
def arg_parser(cls):
"""@return arg parser used to parse formatter-specific options."""
@@ -396,6 +407,16 @@ class ResultsFormatter(object):
self.start_time_by_test = {}
self.terminate_called = False
+ # Store counts of test_result events by status.
+ self.result_status_counts = {
+ EventBuilder.STATUS_SUCCESS: 0,
+ EventBuilder.STATUS_EXPECTED_FAILURE: 0,
+ EventBuilder.STATUS_SKIP: 0,
+ EventBuilder.STATUS_UNEXPECTED_SUCCESS: 0,
+ EventBuilder.STATUS_FAILURE: 0,
+ EventBuilder.STATUS_ERROR: 0
+ }
+
# Lock that we use while mutating inner state, like the
# total test count and the elements. We minimize how
# long we hold the lock just to keep inner state safe, not
@@ -417,14 +438,19 @@ class ResultsFormatter(object):
# atexit() cleanup can call the "terminate if it hasn't been
# called yet".
if test_event is not None:
- if test_event.get("event", "") == "terminate":
+ event_type = test_event.get("event", "")
+ if event_type == "terminate":
self.terminate_called = True
+ elif event_type == "test_result":
+ # Keep track of event counts per test result status type
+ status = test_event["status"]
+ self.result_status_counts[status] += 1
def track_start_time(self, test_class, test_name, start_time):
- """Tracks the start time of a test so elapsed time can be computed.
+ """tracks the start time of a test so elapsed time can be computed.
- This alleviates the need for test results to be processed serially
- by test. It will save the start time for the test so that
+ this alleviates the need for test results to be processed serially
+ by test. it will save the start time for the test so that
elapsed_time_for_test() can compute the elapsed time properly.
"""
if test_class is None or test_name is None:
@@ -435,9 +461,9 @@ class ResultsFormatter(object):
self.start_time_by_test[test_key] = start_time
def elapsed_time_for_test(self, test_class, test_name, end_time):
- """Returns the elapsed time for a test.
+ """returns the elapsed time for a test.
- This function can only be called once per test and requires that
+ this function can only be called once per test and requires that
the track_start_time() method be called sometime prior to calling
this method.
"""
@@ -454,16 +480,38 @@ class ResultsFormatter(object):
return end_time - start_time
def is_using_terminal(self):
- """Returns True if this results formatter is using the terminal and
+ """returns true if this results formatter is using the terminal and
output should be avoided."""
return self.using_terminal
def send_terminate_as_needed(self):
- """Sends the terminate event if it hasn't been received yet."""
+ """sends the terminate event if it hasn't been received yet."""
if not self.terminate_called:
terminate_event = EventBuilder.bare_event("terminate")
self.handle_event(terminate_event)
+ # Derived classes may require self access
+ # pylint: disable=no-self-use
+ def replaces_summary(self):
+ """Returns whether the results formatter includes a summary
+ suitable to replace the old lldb test run results.
+
+ @return True if the lldb test runner can skip its summary
+ generation when using this results formatter; False otherwise.
+ """
+ return False
+
+ def counts_by_test_result_status(self, status):
+ """Returns number of test method results for the given status.
+
+ @status_result a test result status (e.g. success, fail, skip)
+ as defined by the EventBuilder.STATUS_* class members.
+
+ @return an integer returning the number of test methods matching
+ the given test result status.
+ """
+ return self.result_status_counts[status]
+
class XunitFormatter(ResultsFormatter):
"""Provides xUnit-style formatted output.
@@ -527,7 +575,8 @@ class XunitFormatter(ResultsFormatter):
unicode_content = str_or_unicode.decode('utf-8')
else:
unicode_content = str_or_unicode
- return self.invalid_xml_re.sub(six.u('?'), unicode_content).encode('utf-8')
+ return self.invalid_xml_re.sub(
+ six.u('?'), unicode_content).encode('utf-8')
@classmethod
def arg_parser(cls):
@@ -622,12 +671,14 @@ class XunitFormatter(ResultsFormatter):
}
self.status_handlers = {
- "success": self._handle_success,
- "failure": self._handle_failure,
- "error": self._handle_error,
- "skip": self._handle_skip,
- "expected_failure": self._handle_expected_failure,
- "unexpected_success": self._handle_unexpected_success
+ EventBuilder.STATUS_SUCCESS: self._handle_success,
+ EventBuilder.STATUS_FAILURE: self._handle_failure,
+ EventBuilder.STATUS_ERROR: self._handle_error,
+ EventBuilder.STATUS_SKIP: self._handle_skip,
+ EventBuilder.STATUS_EXPECTED_FAILURE:
+ self._handle_expected_failure,
+ EventBuilder.STATUS_UNEXPECTED_SUCCESS:
+ self._handle_unexpected_success
}
def handle_event(self, test_event):
OpenPOWER on IntegriCloud