diff options
Diffstat (limited to 'meta/lib/oeqa/core/utils/concurrencytest.py')
-rw-r--r-- | meta/lib/oeqa/core/utils/concurrencytest.py | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/meta/lib/oeqa/core/utils/concurrencytest.py b/meta/lib/oeqa/core/utils/concurrencytest.py index 6bf7718863..fa6fa34b0e 100644 --- a/meta/lib/oeqa/core/utils/concurrencytest.py +++ b/meta/lib/oeqa/core/utils/concurrencytest.py | |||
@@ -21,6 +21,7 @@ import testtools | |||
21 | import threading | 21 | import threading |
22 | import time | 22 | import time |
23 | import io | 23 | import io |
24 | import json | ||
24 | import subunit | 25 | import subunit |
25 | 26 | ||
26 | from queue import Queue | 27 | from queue import Queue |
@@ -28,6 +29,8 @@ from itertools import cycle | |||
28 | from subunit import ProtocolTestCase, TestProtocolClient | 29 | from subunit import ProtocolTestCase, TestProtocolClient |
29 | from subunit.test_results import AutoTimingTestResultDecorator | 30 | from subunit.test_results import AutoTimingTestResultDecorator |
30 | from testtools import ThreadsafeForwardingResult, iterate_tests | 31 | from testtools import ThreadsafeForwardingResult, iterate_tests |
32 | from testtools.content import Content | ||
33 | from testtools.content_type import ContentType | ||
31 | from oeqa.utils.commands import get_test_layer | 34 | from oeqa.utils.commands import get_test_layer |
32 | 35 | ||
33 | import bb.utils | 36 | import bb.utils |
@@ -70,6 +73,58 @@ class BBThreadsafeForwardingResult(ThreadsafeForwardingResult): | |||
70 | self.semaphore.release() | 73 | self.semaphore.release() |
71 | super(BBThreadsafeForwardingResult, self)._add_result_with_semaphore(method, test, *args, **kwargs) | 74 | super(BBThreadsafeForwardingResult, self)._add_result_with_semaphore(method, test, *args, **kwargs) |
72 | 75 | ||
76 | class ProxyTestResult: | ||
77 | # a very basic TestResult proxy, in order to modify add* calls | ||
78 | def __init__(self, target): | ||
79 | self.result = target | ||
80 | |||
81 | def _addResult(self, method, test, *args, **kwargs): | ||
82 | return method(test, *args, **kwargs) | ||
83 | |||
84 | def addError(self, test, *args, **kwargs): | ||
85 | self._addResult(self.result.addError, test, *args, **kwargs) | ||
86 | |||
87 | def addFailure(self, test, *args, **kwargs): | ||
88 | self._addResult(self.result.addFailure, test, *args, **kwargs) | ||
89 | |||
90 | def addSuccess(self, test, *args, **kwargs): | ||
91 | self._addResult(self.result.addSuccess, test, *args, **kwargs) | ||
92 | |||
93 | def addExpectedFailure(self, test, *args, **kwargs): | ||
94 | self._addResult(self.result.addExpectedFailure, test, *args, **kwargs) | ||
95 | |||
96 | def addUnexpectedSuccess(self, test, *args, **kwargs): | ||
97 | self._addResult(self.result.addUnexpectedSuccess, test, *args, **kwargs) | ||
98 | |||
99 | def __getattr__(self, attr): | ||
100 | return getattr(self.result, attr) | ||
101 | |||
102 | class ExtraResultsDecoderTestResult(ProxyTestResult): | ||
103 | def _addResult(self, method, test, *args, **kwargs): | ||
104 | if "details" in kwargs and "extraresults" in kwargs["details"]: | ||
105 | if isinstance(kwargs["details"]["extraresults"], Content): | ||
106 | kwargs = kwargs.copy() | ||
107 | kwargs["details"] = kwargs["details"].copy() | ||
108 | extraresults = kwargs["details"]["extraresults"] | ||
109 | data = bytearray() | ||
110 | for b in extraresults.iter_bytes(): | ||
111 | data += b | ||
112 | extraresults = json.loads(data.decode()) | ||
113 | kwargs["details"]["extraresults"] = extraresults | ||
114 | return method(test, *args, **kwargs) | ||
115 | |||
116 | class ExtraResultsEncoderTestResult(ProxyTestResult): | ||
117 | def _addResult(self, method, test, *args, **kwargs): | ||
118 | if hasattr(test, "extraresults"): | ||
119 | extras = lambda : [json.dumps(test.extraresults).encode()] | ||
120 | kwargs = kwargs.copy() | ||
121 | if "details" not in kwargs: | ||
122 | kwargs["details"] = {} | ||
123 | else: | ||
124 | kwargs["details"] = kwargs["details"].copy() | ||
125 | kwargs["details"]["extraresults"] = Content(ContentType("application", "json", {'charset': 'utf8'}), extras) | ||
126 | return method(test, *args, **kwargs) | ||
127 | |||
73 | # | 128 | # |
74 | # We have to patch subunit since it doesn't understand how to handle addError | 129 | # We have to patch subunit since it doesn't understand how to handle addError |
75 | # outside of a running test case. This can happen if classSetUp() fails | 130 | # outside of a running test case. This can happen if classSetUp() fails |
@@ -116,7 +171,9 @@ class ConcurrentTestSuite(unittest.TestSuite): | |||
116 | result.threadprogress = {} | 171 | result.threadprogress = {} |
117 | for i, (test, testnum) in enumerate(tests): | 172 | for i, (test, testnum) in enumerate(tests): |
118 | result.threadprogress[i] = [] | 173 | result.threadprogress[i] = [] |
119 | process_result = BBThreadsafeForwardingResult(result, semaphore, i, testnum, totaltests) | 174 | process_result = BBThreadsafeForwardingResult( |
175 | ExtraResultsDecoderTestResult(result), | ||
176 | semaphore, i, testnum, totaltests) | ||
120 | # Force buffering of stdout/stderr so the console doesn't get corrupted by test output | 177 | # Force buffering of stdout/stderr so the console doesn't get corrupted by test output |
121 | # as per default in parent code | 178 | # as per default in parent code |
122 | process_result.buffer = True | 179 | process_result.buffer = True |
@@ -231,7 +288,7 @@ def fork_for_tests(concurrency_num, suite): | |||
231 | # as per default in parent code | 288 | # as per default in parent code |
232 | subunit_client.buffer = True | 289 | subunit_client.buffer = True |
233 | subunit_result = AutoTimingTestResultDecorator(subunit_client) | 290 | subunit_result = AutoTimingTestResultDecorator(subunit_client) |
234 | process_suite.run(subunit_result) | 291 | process_suite.run(ExtraResultsEncoderTestResult(subunit_result)) |
235 | if ourpid != os.getpid(): | 292 | if ourpid != os.getpid(): |
236 | os._exit(0) | 293 | os._exit(0) |
237 | if newbuilddir: | 294 | if newbuilddir: |