blob: e39fe9c9ef3062dc93ae3404b89d6e1fe3271c10 [file] [log] [blame]
Takuto Ikuta4f4045ad2022-07-29 03:52:341#!/usr/bin/env vpython3
Avi Drissmandfd880852022-09-15 20:11:092# Copyright 2014 The Chromium Authors
Stephen Martinis3c3b0e52019-03-06 18:39:513# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
Stephen Martinis3c3b0e52019-03-06 18:39:516import json
7import logging
8import os
9import shutil
Noah Rose Ledesma3b0c4b72024-08-05 22:57:2510import six
Stephen Martinis3c3b0e52019-03-06 18:39:5111import sys
12import tempfile
13import unittest
Stephen Martinis3c3b0e52019-03-06 18:39:5114
Brian Sheedya4186702024-08-05 21:09:2615import common_merge_script_tests
Noah Rose Ledesma3b0c4b72024-08-05 22:57:2516import six
17
18THIS_DIR = os.path.dirname(os.path.abspath(__file__))
19
20# For 'standard_gtest_merge.py'.
21sys.path.insert(0, os.path.abspath(os.path.join(THIS_DIR, '..', 'resources')))
22
23import mock
24
Stephen Martinis3c3b0e52019-03-06 18:39:5125import standard_gtest_merge
26
Stephen Martinis3c3b0e52019-03-06 18:39:5127# gtest json output for successfully finished shard #0.
28GOOD_GTEST_JSON_0 = {
Ben Pasteneb5c67262024-05-15 21:24:0129 'all_tests': [
30 'AlignedMemoryTest.DynamicAllocation',
31 'AlignedMemoryTest.ScopedDynamicAllocation',
32 'AlignedMemoryTest.StackAlignment',
33 'AlignedMemoryTest.StaticAlignment',
34 ],
35 'disabled_tests': [
36 'ConditionVariableTest.TimeoutAcrossSetTimeOfDay',
37 'FileTest.TouchGetInfo',
38 'MessageLoopTestTypeDefault.EnsureDeletion',
39 ],
40 'global_tags': ['CPU_64_BITS', 'MODE_DEBUG', 'OS_LINUX', 'OS_POSIX'],
41 'per_iteration_data': [{
42 'AlignedMemoryTest.DynamicAllocation': [{
43 'elapsed_time_ms': 0,
44 'losless_snippet': True,
45 'output_snippet': 'blah\\n',
46 'output_snippet_base64': 'YmxhaAo=',
47 'status': 'SUCCESS',
48 }],
49 'AlignedMemoryTest.ScopedDynamicAllocation': [{
50 'elapsed_time_ms': 0,
51 'losless_snippet': True,
52 'output_snippet': 'blah\\n',
53 'output_snippet_base64': 'YmxhaAo=',
54 'status': 'SUCCESS',
55 }],
Stephen Martinis3c3b0e52019-03-06 18:39:5156 }],
Ben Pasteneb5c67262024-05-15 21:24:0157 'test_locations': {
58 'AlignedMemoryTest.DynamicAllocation': {
59 'file': 'foo/bar/allocation_test.cc',
60 'line': 123,
61 },
62 'AlignedMemoryTest.ScopedDynamicAllocation': {
63 'file': 'foo/bar/allocation_test.cc',
64 'line': 456,
65 },
66 # This is a test from a different shard, but this happens in practice
67 # and we should not fail if information is repeated.
68 'AlignedMemoryTest.StaticAlignment': {
69 'file': 'foo/bar/allocation_test.cc',
70 'line': 12,
71 },
Stephen Martinis3c3b0e52019-03-06 18:39:5172 },
Stephen Martinis3c3b0e52019-03-06 18:39:5173}
74
Stephen Martinis3c3b0e52019-03-06 18:39:5175# gtest json output for successfully finished shard #1.
76GOOD_GTEST_JSON_1 = {
Ben Pasteneb5c67262024-05-15 21:24:0177 'all_tests': [
78 'AlignedMemoryTest.DynamicAllocation',
79 'AlignedMemoryTest.ScopedDynamicAllocation',
80 'AlignedMemoryTest.StackAlignment',
81 'AlignedMemoryTest.StaticAlignment',
82 ],
83 'disabled_tests': [
84 'ConditionVariableTest.TimeoutAcrossSetTimeOfDay',
85 'FileTest.TouchGetInfo',
86 'MessageLoopTestTypeDefault.EnsureDeletion',
87 ],
88 'global_tags': ['CPU_64_BITS', 'MODE_DEBUG', 'OS_LINUX', 'OS_POSIX'],
89 'per_iteration_data': [{
90 'AlignedMemoryTest.StackAlignment': [{
91 'elapsed_time_ms': 0,
92 'losless_snippet': True,
93 'output_snippet': 'blah\\n',
94 'output_snippet_base64': 'YmxhaAo=',
95 'status': 'SUCCESS',
96 }],
97 'AlignedMemoryTest.StaticAlignment': [{
98 'elapsed_time_ms': 0,
99 'losless_snippet': True,
100 'output_snippet': 'blah\\n',
101 'output_snippet_base64': 'YmxhaAo=',
102 'status': 'SUCCESS',
103 }],
Stephen Martinis3c3b0e52019-03-06 18:39:51104 }],
Ben Pasteneb5c67262024-05-15 21:24:01105 'test_locations': {
106 'AlignedMemoryTest.StackAlignment': {
107 'file': 'foo/bar/allocation_test.cc',
108 'line': 789,
109 },
110 'AlignedMemoryTest.StaticAlignment': {
111 'file': 'foo/bar/allocation_test.cc',
112 'line': 12,
113 },
Stephen Martinis3c3b0e52019-03-06 18:39:51114 },
Stephen Martinis3c3b0e52019-03-06 18:39:51115}
116
Stephen Martinis3c3b0e52019-03-06 18:39:51117TIMED_OUT_GTEST_JSON_1 = {
Ben Pasteneb5c67262024-05-15 21:24:01118 'disabled_tests': [],
119 'global_tags': [],
120 'all_tests': [
121 'AlignedMemoryTest.DynamicAllocation',
122 'AlignedMemoryTest.ScopedDynamicAllocation',
123 'AlignedMemoryTest.StackAlignment',
124 'AlignedMemoryTest.StaticAlignment',
125 ],
126 'per_iteration_data': [{
127 'AlignedMemoryTest.StackAlignment': [{
128 'elapsed_time_ms': 54000,
129 'losless_snippet': True,
130 'output_snippet': 'timed out',
131 'output_snippet_base64': '',
132 'status': 'FAILURE',
133 }],
134 'AlignedMemoryTest.StaticAlignment': [{
135 'elapsed_time_ms': 0,
136 'losless_snippet': True,
137 'output_snippet': '',
138 'output_snippet_base64': '',
139 'status': 'NOTRUN',
140 }],
Stephen Martinis3c3b0e52019-03-06 18:39:51141 }],
Ben Pasteneb5c67262024-05-15 21:24:01142 'test_locations': {
143 'AlignedMemoryTest.StackAlignment': {
144 'file': 'foo/bar/allocation_test.cc',
145 'line': 789,
146 },
147 'AlignedMemoryTest.StaticAlignment': {
148 'file': 'foo/bar/allocation_test.cc',
149 'line': 12,
150 },
Stephen Martinis3c3b0e52019-03-06 18:39:51151 },
Stephen Martinis3c3b0e52019-03-06 18:39:51152}
153
154# GOOD_GTEST_JSON_0 and GOOD_GTEST_JSON_1 merged.
155GOOD_GTEST_JSON_MERGED = {
Ben Pasteneb5c67262024-05-15 21:24:01156 'all_tests': [
157 'AlignedMemoryTest.DynamicAllocation',
158 'AlignedMemoryTest.ScopedDynamicAllocation',
159 'AlignedMemoryTest.StackAlignment',
160 'AlignedMemoryTest.StaticAlignment',
161 ],
162 'disabled_tests': [
163 'ConditionVariableTest.TimeoutAcrossSetTimeOfDay',
164 'FileTest.TouchGetInfo',
165 'MessageLoopTestTypeDefault.EnsureDeletion',
166 ],
167 'global_tags': ['CPU_64_BITS', 'MODE_DEBUG', 'OS_LINUX', 'OS_POSIX'],
168 'missing_shards': [],
169 'per_iteration_data': [{
170 'AlignedMemoryTest.DynamicAllocation': [{
171 'elapsed_time_ms': 0,
172 'losless_snippet': True,
173 'output_snippet': 'blah\\n',
174 'output_snippet_base64': 'YmxhaAo=',
175 'status': 'SUCCESS',
176 }],
177 'AlignedMemoryTest.ScopedDynamicAllocation': [{
178 'elapsed_time_ms': 0,
179 'losless_snippet': True,
180 'output_snippet': 'blah\\n',
181 'output_snippet_base64': 'YmxhaAo=',
182 'status': 'SUCCESS',
183 }],
184 'AlignedMemoryTest.StackAlignment': [{
185 'elapsed_time_ms': 0,
186 'losless_snippet': True,
187 'output_snippet': 'blah\\n',
188 'output_snippet_base64': 'YmxhaAo=',
189 'status': 'SUCCESS',
190 }],
191 'AlignedMemoryTest.StaticAlignment': [{
192 'elapsed_time_ms': 0,
193 'losless_snippet': True,
194 'output_snippet': 'blah\\n',
195 'output_snippet_base64': 'YmxhaAo=',
196 'status': 'SUCCESS',
197 }],
Stephen Martinis3c3b0e52019-03-06 18:39:51198 }],
Ben Pasteneb5c67262024-05-15 21:24:01199 'swarming_summary': {
200 u'shards': [{
201 u'state': u'COMPLETED',
202 u'outputs_ref': {
203 u'view_url': u'blah',
204 },
205 }],
206 },
207 'test_locations': {
208 'AlignedMemoryTest.StackAlignment': {
209 'file': 'foo/bar/allocation_test.cc',
210 'line': 789,
Stephen Martinis3c3b0e52019-03-06 18:39:51211 },
Ben Pasteneb5c67262024-05-15 21:24:01212 'AlignedMemoryTest.StaticAlignment': {
213 'file': 'foo/bar/allocation_test.cc',
214 'line': 12,
215 },
216 'AlignedMemoryTest.DynamicAllocation': {
217 'file': 'foo/bar/allocation_test.cc',
218 'line': 123,
219 },
220 'AlignedMemoryTest.ScopedDynamicAllocation': {
221 'file': 'foo/bar/allocation_test.cc',
222 'line': 456,
223 },
Stephen Martinis3c3b0e52019-03-06 18:39:51224 },
Stephen Martinis3c3b0e52019-03-06 18:39:51225}
226
Stephen Martinis3c3b0e52019-03-06 18:39:51227# Only shard #1 finished. UNRELIABLE_RESULTS is set.
228BAD_GTEST_JSON_ONLY_1_SHARD = {
Ben Pasteneb5c67262024-05-15 21:24:01229 'all_tests': [
230 'AlignedMemoryTest.DynamicAllocation',
231 'AlignedMemoryTest.ScopedDynamicAllocation',
232 'AlignedMemoryTest.StackAlignment',
233 'AlignedMemoryTest.StaticAlignment',
234 ],
235 'disabled_tests': [
236 'ConditionVariableTest.TimeoutAcrossSetTimeOfDay',
237 'FileTest.TouchGetInfo',
238 'MessageLoopTestTypeDefault.EnsureDeletion',
239 ],
240 'global_tags': [
241 'CPU_64_BITS',
242 'MODE_DEBUG',
243 'OS_LINUX',
244 'OS_POSIX',
245 'UNRELIABLE_RESULTS',
246 ],
247 'missing_shards': [0],
248 'per_iteration_data': [{
249 'AlignedMemoryTest.StackAlignment': [{
250 'elapsed_time_ms': 0,
251 'losless_snippet': True,
252 'output_snippet': 'blah\\n',
253 'output_snippet_base64': 'YmxhaAo=',
254 'status': 'SUCCESS',
255 }],
256 'AlignedMemoryTest.StaticAlignment': [{
257 'elapsed_time_ms': 0,
258 'losless_snippet': True,
259 'output_snippet': 'blah\\n',
260 'output_snippet_base64': 'YmxhaAo=',
261 'status': 'SUCCESS',
262 }],
Stephen Martinis3c3b0e52019-03-06 18:39:51263 }],
Ben Pasteneb5c67262024-05-15 21:24:01264 'test_locations': {
265 'AlignedMemoryTest.StackAlignment': {
266 'file': 'foo/bar/allocation_test.cc',
267 'line': 789,
268 },
269 'AlignedMemoryTest.StaticAlignment': {
270 'file': 'foo/bar/allocation_test.cc',
271 'line': 12,
272 },
Stephen Martinis3c3b0e52019-03-06 18:39:51273 },
Stephen Martinis3c3b0e52019-03-06 18:39:51274}
275
Stephen Martinis3c3b0e52019-03-06 18:39:51276# GOOD_GTEST_JSON_0 and TIMED_OUT_GTEST_JSON_1 merged.
277TIMED_OUT_GTEST_JSON_MERGED = {
Ben Pasteneb5c67262024-05-15 21:24:01278 'all_tests': [
279 'AlignedMemoryTest.DynamicAllocation',
280 'AlignedMemoryTest.ScopedDynamicAllocation',
281 'AlignedMemoryTest.StackAlignment',
282 'AlignedMemoryTest.StaticAlignment',
283 ],
284 'disabled_tests': [
285 'ConditionVariableTest.TimeoutAcrossSetTimeOfDay',
286 'FileTest.TouchGetInfo',
287 'MessageLoopTestTypeDefault.EnsureDeletion',
288 ],
289 'global_tags': ['CPU_64_BITS', 'MODE_DEBUG', 'OS_LINUX', 'OS_POSIX'],
290 'missing_shards': [],
291 'per_iteration_data': [{
292 'AlignedMemoryTest.DynamicAllocation': [{
293 'elapsed_time_ms': 0,
294 'losless_snippet': True,
295 'output_snippet': 'blah\\n',
296 'output_snippet_base64': 'YmxhaAo=',
297 'status': 'SUCCESS',
298 }],
299 'AlignedMemoryTest.ScopedDynamicAllocation': [{
300 'elapsed_time_ms': 0,
301 'losless_snippet': True,
302 'output_snippet': 'blah\\n',
303 'output_snippet_base64': 'YmxhaAo=',
304 'status': 'SUCCESS',
305 }],
306 'AlignedMemoryTest.StackAlignment': [{
307 'elapsed_time_ms': 54000,
308 'losless_snippet': True,
309 'output_snippet': 'timed out',
310 'output_snippet_base64': '',
311 'status': 'FAILURE',
312 }],
313 'AlignedMemoryTest.StaticAlignment': [{
314 'elapsed_time_ms': 0,
315 'losless_snippet': True,
316 'output_snippet': '',
317 'output_snippet_base64': '',
318 'status': 'NOTRUN',
319 }],
Stephen Martinis3c3b0e52019-03-06 18:39:51320 }],
Ben Pasteneb5c67262024-05-15 21:24:01321 'swarming_summary': {
322 u'shards': [
323 {
324 u'state': u'COMPLETED',
325 },
326 {
327 u'state': u'TIMED_OUT',
328 },
329 ],
Stephen Martinis3c3b0e52019-03-06 18:39:51330 },
Ben Pasteneb5c67262024-05-15 21:24:01331 'test_locations': {
332 'AlignedMemoryTest.StackAlignment': {
333 'file': 'foo/bar/allocation_test.cc',
334 'line': 789,
335 },
336 'AlignedMemoryTest.StaticAlignment': {
337 'file': 'foo/bar/allocation_test.cc',
338 'line': 12,
339 },
340 'AlignedMemoryTest.DynamicAllocation': {
341 'file': 'foo/bar/allocation_test.cc',
342 'line': 123,
343 },
344 'AlignedMemoryTest.ScopedDynamicAllocation': {
345 'file': 'foo/bar/allocation_test.cc',
346 'line': 456,
347 },
Stephen Martinis3c3b0e52019-03-06 18:39:51348 },
Stephen Martinis3c3b0e52019-03-06 18:39:51349}
350
351
352class _StandardGtestMergeTest(unittest.TestCase):
353
354 def setUp(self):
355 self.temp_dir = tempfile.mkdtemp()
356
357 def tearDown(self):
358 shutil.rmtree(self.temp_dir)
359
360 def _write_temp_file(self, path, content):
361 abs_path = os.path.join(self.temp_dir, path.replace('/', os.sep))
362 if not os.path.exists(os.path.dirname(abs_path)):
363 os.makedirs(os.path.dirname(abs_path))
364 with open(abs_path, 'w') as f:
365 if isinstance(content, dict):
366 json.dump(content, f)
367 else:
368 assert isinstance(content, str)
369 f.write(content)
370 return abs_path
371
372
373class LoadShardJsonTest(_StandardGtestMergeTest):
374
375 def test_double_digit_jsons(self):
376 jsons_to_merge = []
Wenbin Zhangc56b1252021-10-05 02:49:06377 for i in range(15):
Stephen Martinis3c3b0e52019-03-06 18:39:51378 json_dir = os.path.join(self.temp_dir, str(i))
379 json_path = os.path.join(json_dir, 'output.json')
380 if not os.path.exists(json_dir):
381 os.makedirs(json_dir)
382 with open(json_path, 'w') as f:
383 json.dump({'all_tests': ['LoadShardJsonTest.test%d' % i]}, f)
384 jsons_to_merge.append(json_path)
385
Ben Pasteneb5c67262024-05-15 21:24:01386 content, err = standard_gtest_merge.load_shard_json(0, None, jsons_to_merge)
Stephen Martinis3c3b0e52019-03-06 18:39:51387 self.assertEqual({'all_tests': ['LoadShardJsonTest.test0']}, content)
388 self.assertIsNone(err)
389
Ben Pasteneb5c67262024-05-15 21:24:01390 content, err = standard_gtest_merge.load_shard_json(12, None,
391 jsons_to_merge)
Stephen Martinis3c3b0e52019-03-06 18:39:51392 self.assertEqual({'all_tests': ['LoadShardJsonTest.test12']}, content)
393 self.assertIsNone(err)
394
395 def test_double_task_id_jsons(self):
396 jsons_to_merge = []
Wenbin Zhangc56b1252021-10-05 02:49:06397 for i in range(15):
Stephen Martinis3c3b0e52019-03-06 18:39:51398 json_dir = os.path.join(self.temp_dir, 'deadbeef%d' % i)
399 json_path = os.path.join(json_dir, 'output.json')
400 if not os.path.exists(json_dir):
401 os.makedirs(json_dir)
402 with open(json_path, 'w') as f:
403 json.dump({'all_tests': ['LoadShardJsonTest.test%d' % i]}, f)
404 jsons_to_merge.append(json_path)
405
Ben Pasteneb5c67262024-05-15 21:24:01406 content, err = standard_gtest_merge.load_shard_json(0, 'deadbeef0',
407 jsons_to_merge)
408 self.assertEqual({'all_tests': ['LoadShardJsonTest.test0']}, content)
Stephen Martinis3c3b0e52019-03-06 18:39:51409 self.assertIsNone(err)
410
Ben Pasteneb5c67262024-05-15 21:24:01411 content, err = standard_gtest_merge.load_shard_json(12, 'deadbeef12',
412 jsons_to_merge)
413 self.assertEqual({'all_tests': ['LoadShardJsonTest.test12']}, content)
Stephen Martinis3c3b0e52019-03-06 18:39:51414 self.assertIsNone(err)
415
416
417class MergeShardResultsTest(_StandardGtestMergeTest):
418 """Tests for merge_shard_results function."""
419
Joshua Hoodbb3cd222022-03-03 00:40:48420 # pylint: disable=super-with-arguments
Stephen Martinis3c3b0e52019-03-06 18:39:51421 def setUp(self):
Devlin Cronin34e2be02022-01-08 00:40:46422 super(MergeShardResultsTest, self).setUp()
Stephen Martinis3c3b0e52019-03-06 18:39:51423 self.summary = None
424 self.test_files = []
Ben Pasteneb5c67262024-05-15 21:24:01425
Joshua Hoodbb3cd222022-03-03 00:40:48426 # pylint: enable=super-with-arguments
Stephen Martinis3c3b0e52019-03-06 18:39:51427
428 def stage(self, summary, files):
429 self.summary = self._write_temp_file('summary.json', summary)
Wenbin Zhangc56b1252021-10-05 02:49:06430 for path, content in files.items():
Stephen Martinis3c3b0e52019-03-06 18:39:51431 abs_path = self._write_temp_file(path, content)
432 self.test_files.append(abs_path)
433
434 def call(self):
Joshua Hoodbb3cd222022-03-03 00:40:48435 stdout = six.StringIO()
Stephen Martinis3c3b0e52019-03-06 18:39:51436 with mock.patch('sys.stdout', stdout):
Ben Pasteneb5c67262024-05-15 21:24:01437 merged = standard_gtest_merge.merge_shard_results(self.summary,
438 self.test_files)
Stephen Martinis3c3b0e52019-03-06 18:39:51439 return merged, stdout.getvalue().strip()
440
441 def assertUnicodeEquals(self, expectation, result):
Ben Pasteneb5c67262024-05-15 21:24:01442
Stephen Martinis3c3b0e52019-03-06 18:39:51443 def convert_to_unicode(key_or_value):
444 if isinstance(key_or_value, str):
Wenbin Zhangc56b1252021-10-05 02:49:06445 return six.text_type(key_or_value)
Stephen Martinis3c3b0e52019-03-06 18:39:51446 if isinstance(key_or_value, dict):
Ben Pasteneb5c67262024-05-15 21:24:01447 return {
448 convert_to_unicode(k): convert_to_unicode(v)
449 for k, v in key_or_value.items()
450 }
Stephen Martinis3c3b0e52019-03-06 18:39:51451 if isinstance(key_or_value, list):
452 return [convert_to_unicode(x) for x in key_or_value]
453 return key_or_value
454
455 unicode_expectations = convert_to_unicode(expectation)
456 unicode_result = convert_to_unicode(result)
457 self.assertEquals(unicode_expectations, unicode_result)
458
459 def test_ok(self):
460 # Two shards, both successfully finished.
Ben Pasteneb5c67262024-05-15 21:24:01461 self.stage(
Stephen Martinis3c3b0e52019-03-06 18:39:51462 {
Ben Pasteneb5c67262024-05-15 21:24:01463 u'shards': [
464 {
465 u'state': u'COMPLETED',
466 },
467 {
468 u'state': u'COMPLETED',
469 },
470 ],
471 }, {
472 '0/output.json': GOOD_GTEST_JSON_0,
473 '1/output.json': GOOD_GTEST_JSON_1,
474 })
Stephen Martinis3c3b0e52019-03-06 18:39:51475 merged, stdout = self.call()
476 merged['swarming_summary'] = {
Ben Pasteneb5c67262024-05-15 21:24:01477 'shards': [{
478 u'state': u'COMPLETED',
479 u'outputs_ref': {
480 u'view_url': u'blah',
481 },
482 }],
Stephen Martinis3c3b0e52019-03-06 18:39:51483 }
484 self.assertUnicodeEquals(GOOD_GTEST_JSON_MERGED, merged)
485 self.assertEqual('', stdout)
486
487 def test_timed_out(self):
488 # Two shards, both successfully finished.
Ben Pasteneb5c67262024-05-15 21:24:01489 self.stage(
Stephen Martinis3c3b0e52019-03-06 18:39:51490 {
Ben Pasteneb5c67262024-05-15 21:24:01491 'shards': [
492 {
493 'state': 'COMPLETED',
494 },
495 {
496 'state': 'TIMED_OUT',
497 },
498 ],
499 }, {
500 '0/output.json': GOOD_GTEST_JSON_0,
501 '1/output.json': TIMED_OUT_GTEST_JSON_1,
502 })
Stephen Martinis3c3b0e52019-03-06 18:39:51503 merged, stdout = self.call()
504
505 self.assertUnicodeEquals(TIMED_OUT_GTEST_JSON_MERGED, merged)
Ben Pasteneb5c67262024-05-15 21:24:01506 self.assertIn('Test runtime exceeded allocated time\n', stdout)
Stephen Martinis3c3b0e52019-03-06 18:39:51507
508 def test_missing_summary_json(self):
509 # summary.json is missing, should return None and emit warning.
510 self.summary = os.path.join(self.temp_dir, 'summary.json')
511 merged, output = self.call()
512 self.assertEqual(None, merged)
513 self.assertIn('@@@STEP_WARNINGS@@@', output)
514 self.assertIn('summary.json is missing or can not be read', output)
515
516 def test_unfinished_shards(self):
517 # Only one shard (#1) finished. Shard #0 did not.
518 self.stage({
Ben Pasteneb5c67262024-05-15 21:24:01519 u'shards': [
520 None,
521 {
522 u'state': u'COMPLETED',
523 },
524 ],
525 }, {
526 u'1/output.json': GOOD_GTEST_JSON_1,
Stephen Martinis3c3b0e52019-03-06 18:39:51527 })
528 merged, stdout = self.call()
529 merged.pop('swarming_summary')
530 self.assertUnicodeEquals(BAD_GTEST_JSON_ONLY_1_SHARD, merged)
Ben Pasteneb5c67262024-05-15 21:24:01531 self.assertIn('@@@STEP_WARNINGS@@@\nsome shards did not complete: 0\n',
532 stdout)
Stephen Martinis3c3b0e52019-03-06 18:39:51533 self.assertIn(
534 '@@@STEP_LOG_LINE@some shards did not complete: 0@'
535 'Missing results from the following shard(s): 0@@@\n', stdout)
536
537 def test_missing_output_json(self):
538 # Shard #0 output json is missing.
Ben Pasteneb5c67262024-05-15 21:24:01539 self.stage(
Stephen Martinis3c3b0e52019-03-06 18:39:51540 {
Ben Pasteneb5c67262024-05-15 21:24:01541 u'shards': [
542 {
543 u'state': u'COMPLETED',
544 },
545 {
546 u'state': u'COMPLETED',
547 },
548 ],
549 }, {
550 u'1/output.json': GOOD_GTEST_JSON_1,
551 })
Stephen Martinis3c3b0e52019-03-06 18:39:51552 merged, stdout = self.call()
553 merged.pop('swarming_summary')
554 self.assertUnicodeEquals(BAD_GTEST_JSON_ONLY_1_SHARD, merged)
Ben Pasteneb5c67262024-05-15 21:24:01555 self.assertIn('No result was found: '
556 'shard 0 test output was missing', stdout)
Stephen Martinis3c3b0e52019-03-06 18:39:51557
558 def test_large_output_json(self):
559 # a shard is too large.
Ben Pasteneb5c67262024-05-15 21:24:01560 self.stage(
Stephen Martinis3c3b0e52019-03-06 18:39:51561 {
Ben Pasteneb5c67262024-05-15 21:24:01562 u'shards': [
563 {
564 u'state': u'COMPLETED',
565 },
566 {
567 u'state': u'COMPLETED',
568 },
569 ],
570 }, {
571 '0/output.json': GOOD_GTEST_JSON_0,
572 '1/output.json': GOOD_GTEST_JSON_1,
573 })
Stephen Martinis3c3b0e52019-03-06 18:39:51574 old_json_limit = standard_gtest_merge.OUTPUT_JSON_SIZE_LIMIT
575 len0 = len(json.dumps(GOOD_GTEST_JSON_0))
576 len1 = len(json.dumps(GOOD_GTEST_JSON_1))
577 large_shard = "0" if len0 > len1 else "1"
578 try:
579 # Override max output.json size just for this test.
Ben Pasteneb5c67262024-05-15 21:24:01580 standard_gtest_merge.OUTPUT_JSON_SIZE_LIMIT = min(len0, len1)
Stephen Martinis3c3b0e52019-03-06 18:39:51581 merged, stdout = self.call()
582 merged.pop('swarming_summary')
583 self.assertUnicodeEquals(BAD_GTEST_JSON_ONLY_1_SHARD, merged)
584 self.assertIn(
585 'No result was found: '
586 'shard %s test output exceeded the size limit' % large_shard, stdout)
587 finally:
588 standard_gtest_merge.OUTPUT_JSON_SIZE_LIMIT = old_json_limit
589
590
591class CommandLineTest(common_merge_script_tests.CommandLineTest):
592
Joshua Hoodbb3cd222022-03-03 00:40:48593 # pylint: disable=super-with-arguments
Stephen Martinis3c3b0e52019-03-06 18:39:51594 def __init__(self, methodName='runTest'):
Devlin Cronin34e2be02022-01-08 00:40:46595 super(CommandLineTest, self).__init__(methodName, standard_gtest_merge)
Ben Pasteneb5c67262024-05-15 21:24:01596
Joshua Hoodbb3cd222022-03-03 00:40:48597 # pylint: enable=super-with-arguments
Stephen Martinis3c3b0e52019-03-06 18:39:51598
599
600if __name__ == '__main__':
601 logging.basicConfig(
602 level=logging.DEBUG if '-v' in sys.argv else logging.ERROR)
603 if '-v' in sys.argv:
604 unittest.TestCase.maxDiff = None
605 unittest.main()