1#!/usr/bin/env python 2# Copyright 2018, Google Inc. 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: 8# 9# * Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# * Redistributions in binary form must reproduce the above 12# copyright notice, this list of conditions and the following disclaimer 13# in the documentation and/or other materials provided with the 14# distribution. 15# * Neither the name of Google Inc. nor the names of its 16# contributors may be used to endorse or promote products derived from 17# this software without specific prior written permission. 18# 19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31"""Unit test for the gtest_json_output module.""" 32 33import datetime 34import errno 35import json 36import os 37import re 38import sys 39 40from googletest.test import gtest_json_test_utils 41from googletest.test import gtest_test_utils 42 43GTEST_FILTER_FLAG = '--gtest_filter' 44GTEST_LIST_TESTS_FLAG = '--gtest_list_tests' 45GTEST_OUTPUT_FLAG = '--gtest_output' 46GTEST_DEFAULT_OUTPUT_FILE = 'test_detail.json' 47GTEST_PROGRAM_NAME = 'gtest_xml_output_unittest_' 48 49# The flag indicating stacktraces are not supported 50NO_STACKTRACE_SUPPORT_FLAG = '--no_stacktrace_support' 51 52SUPPORTS_STACK_TRACES = NO_STACKTRACE_SUPPORT_FLAG not in sys.argv 53 54if SUPPORTS_STACK_TRACES: 55 STACK_TRACE_TEMPLATE = '\nStack trace:\n*' 56else: 57 STACK_TRACE_TEMPLATE = '\n' 58 59EXPECTED_NON_EMPTY = { 60 'tests': 26, 61 'failures': 5, 62 'disabled': 2, 63 'errors': 0, 64 'timestamp': '*', 65 'time': '*', 66 'ad_hoc_property': '42', 67 'name': 'AllTests', 68 'testsuites': [ 69 { 70 'name': 'SuccessfulTest', 71 'tests': 1, 72 'failures': 0, 73 'disabled': 0, 74 'errors': 0, 75 'time': '*', 76 'timestamp': '*', 77 'testsuite': [{ 78 'name': 'Succeeds', 79 'file': 'gtest_xml_output_unittest_.cc', 80 'line': 53, 81 'status': 'RUN', 82 'result': 'COMPLETED', 83 'time': '*', 84 'timestamp': '*', 85 'classname': 'SuccessfulTest', 86 }], 87 }, 88 { 89 'name': 'FailedTest', 90 'tests': 1, 91 'failures': 1, 92 'disabled': 0, 93 'errors': 0, 94 'time': '*', 95 'timestamp': '*', 96 'testsuite': [{ 97 'name': 'Fails', 98 'file': 'gtest_xml_output_unittest_.cc', 99 'line': 61, 100 'status': 'RUN', 101 'result': 'COMPLETED', 102 'time': '*', 103 'timestamp': '*', 104 'classname': 'FailedTest', 105 'failures': [{ 106 'failure': ( 107 'gtest_xml_output_unittest_.cc:*\n' 108 'Expected equality of these values:\n' 109 ' 1\n 2' 110 + STACK_TRACE_TEMPLATE 111 ), 112 'type': '', 113 }], 114 }], 115 }, 116 { 117 'name': 'DisabledTest', 118 'tests': 1, 119 'failures': 0, 120 'disabled': 1, 121 'errors': 0, 122 'time': '*', 123 'timestamp': '*', 124 'testsuite': [{ 125 'name': 'DISABLED_test_not_run', 126 'file': 'gtest_xml_output_unittest_.cc', 127 'line': 68, 128 'status': 'NOTRUN', 129 'result': 'SUPPRESSED', 130 'time': '*', 131 'timestamp': '*', 132 'classname': 'DisabledTest', 133 }], 134 }, 135 { 136 'name': 'SkippedTest', 137 'tests': 3, 138 'failures': 1, 139 'disabled': 0, 140 'errors': 0, 141 'time': '*', 142 'timestamp': '*', 143 'testsuite': [ 144 { 145 'name': 'Skipped', 146 'file': 'gtest_xml_output_unittest_.cc', 147 'line': 75, 148 'status': 'RUN', 149 'result': 'SKIPPED', 150 'time': '*', 151 'timestamp': '*', 152 'classname': 'SkippedTest', 153 }, 154 { 155 'name': 'SkippedWithMessage', 156 'file': 'gtest_xml_output_unittest_.cc', 157 'line': 79, 158 'status': 'RUN', 159 'result': 'SKIPPED', 160 'time': '*', 161 'timestamp': '*', 162 'classname': 'SkippedTest', 163 }, 164 { 165 'name': 'SkippedAfterFailure', 166 'file': 'gtest_xml_output_unittest_.cc', 167 'line': 83, 168 'status': 'RUN', 169 'result': 'COMPLETED', 170 'time': '*', 171 'timestamp': '*', 172 'classname': 'SkippedTest', 173 'failures': [{ 174 'failure': ( 175 'gtest_xml_output_unittest_.cc:*\n' 176 'Expected equality of these values:\n' 177 ' 1\n 2' 178 + STACK_TRACE_TEMPLATE 179 ), 180 'type': '', 181 }], 182 }, 183 ], 184 }, 185 { 186 'name': 'MixedResultTest', 187 'tests': 3, 188 'failures': 1, 189 'disabled': 1, 190 'errors': 0, 191 'time': '*', 192 'timestamp': '*', 193 'testsuite': [ 194 { 195 'name': 'Succeeds', 196 'file': 'gtest_xml_output_unittest_.cc', 197 'line': 88, 198 'status': 'RUN', 199 'result': 'COMPLETED', 200 'time': '*', 201 'timestamp': '*', 202 'classname': 'MixedResultTest', 203 }, 204 { 205 'name': 'Fails', 206 'file': 'gtest_xml_output_unittest_.cc', 207 'line': 93, 208 'status': 'RUN', 209 'result': 'COMPLETED', 210 'time': '*', 211 'timestamp': '*', 212 'classname': 'MixedResultTest', 213 'failures': [ 214 { 215 'failure': ( 216 'gtest_xml_output_unittest_.cc:*\n' 217 'Expected equality of these values:\n' 218 ' 1\n 2' 219 + STACK_TRACE_TEMPLATE 220 ), 221 'type': '', 222 }, 223 { 224 'failure': ( 225 'gtest_xml_output_unittest_.cc:*\n' 226 'Expected equality of these values:\n' 227 ' 2\n 3' 228 + STACK_TRACE_TEMPLATE 229 ), 230 'type': '', 231 }, 232 ], 233 }, 234 { 235 'name': 'DISABLED_test', 236 'file': 'gtest_xml_output_unittest_.cc', 237 'line': 98, 238 'status': 'NOTRUN', 239 'result': 'SUPPRESSED', 240 'time': '*', 241 'timestamp': '*', 242 'classname': 'MixedResultTest', 243 }, 244 ], 245 }, 246 { 247 'name': 'XmlQuotingTest', 248 'tests': 1, 249 'failures': 1, 250 'disabled': 0, 251 'errors': 0, 252 'time': '*', 253 'timestamp': '*', 254 'testsuite': [{ 255 'name': 'OutputsCData', 256 'file': 'gtest_xml_output_unittest_.cc', 257 'line': 102, 258 'status': 'RUN', 259 'result': 'COMPLETED', 260 'time': '*', 261 'timestamp': '*', 262 'classname': 'XmlQuotingTest', 263 'failures': [{ 264 'failure': ( 265 'gtest_xml_output_unittest_.cc:*\n' 266 'Failed\nXML output: <?xml encoding="utf-8">' 267 '<top><![CDATA[cdata text]]></top>' 268 + STACK_TRACE_TEMPLATE 269 ), 270 'type': '', 271 }], 272 }], 273 }, 274 { 275 'name': 'InvalidCharactersTest', 276 'tests': 1, 277 'failures': 1, 278 'disabled': 0, 279 'errors': 0, 280 'time': '*', 281 'timestamp': '*', 282 'testsuite': [{ 283 'name': 'InvalidCharactersInMessage', 284 'file': 'gtest_xml_output_unittest_.cc', 285 'line': 109, 286 'status': 'RUN', 287 'result': 'COMPLETED', 288 'time': '*', 289 'timestamp': '*', 290 'classname': 'InvalidCharactersTest', 291 'failures': [{ 292 'failure': ( 293 'gtest_xml_output_unittest_.cc:*\n' 294 'Failed\nInvalid characters in brackets' 295 ' [\x01\x02]' 296 + STACK_TRACE_TEMPLATE 297 ), 298 'type': '', 299 }], 300 }], 301 }, 302 { 303 'name': 'PropertyRecordingTest', 304 'tests': 4, 305 'failures': 0, 306 'disabled': 0, 307 'errors': 0, 308 'time': '*', 309 'timestamp': '*', 310 'SetUpTestSuite': 'yes', 311 'TearDownTestSuite': 'aye', 312 'testsuite': [ 313 { 314 'name': 'OneProperty', 315 'file': 'gtest_xml_output_unittest_.cc', 316 'line': 121, 317 'status': 'RUN', 318 'result': 'COMPLETED', 319 'time': '*', 320 'timestamp': '*', 321 'classname': 'PropertyRecordingTest', 322 'key_1': '1', 323 }, 324 { 325 'name': 'IntValuedProperty', 326 'file': 'gtest_xml_output_unittest_.cc', 327 'line': 125, 328 'status': 'RUN', 329 'result': 'COMPLETED', 330 'time': '*', 331 'timestamp': '*', 332 'classname': 'PropertyRecordingTest', 333 'key_int': '1', 334 }, 335 { 336 'name': 'ThreeProperties', 337 'file': 'gtest_xml_output_unittest_.cc', 338 'line': 129, 339 'status': 'RUN', 340 'result': 'COMPLETED', 341 'time': '*', 342 'timestamp': '*', 343 'classname': 'PropertyRecordingTest', 344 'key_1': '1', 345 'key_2': '2', 346 'key_3': '3', 347 }, 348 { 349 'name': 'TwoValuesForOneKeyUsesLastValue', 350 'file': 'gtest_xml_output_unittest_.cc', 351 'line': 135, 352 'status': 'RUN', 353 'result': 'COMPLETED', 354 'time': '*', 355 'timestamp': '*', 356 'classname': 'PropertyRecordingTest', 357 'key_1': '2', 358 }, 359 ], 360 }, 361 { 362 'name': 'NoFixtureTest', 363 'tests': 3, 364 'failures': 0, 365 'disabled': 0, 366 'errors': 0, 367 'time': '*', 368 'timestamp': '*', 369 'testsuite': [ 370 { 371 'name': 'RecordProperty', 372 'file': 'gtest_xml_output_unittest_.cc', 373 'line': 140, 374 'status': 'RUN', 375 'result': 'COMPLETED', 376 'time': '*', 377 'timestamp': '*', 378 'classname': 'NoFixtureTest', 379 'key': '1', 380 }, 381 { 382 'name': 'ExternalUtilityThatCallsRecordIntValuedProperty', 383 'file': 'gtest_xml_output_unittest_.cc', 384 'line': 153, 385 'status': 'RUN', 386 'result': 'COMPLETED', 387 'time': '*', 388 'timestamp': '*', 389 'classname': 'NoFixtureTest', 390 'key_for_utility_int': '1', 391 }, 392 { 393 'name': ( 394 'ExternalUtilityThatCallsRecordStringValuedProperty' 395 ), 396 'file': 'gtest_xml_output_unittest_.cc', 397 'line': 157, 398 'status': 'RUN', 399 'result': 'COMPLETED', 400 'time': '*', 401 'timestamp': '*', 402 'classname': 'NoFixtureTest', 403 'key_for_utility_string': '1', 404 }, 405 ], 406 }, 407 { 408 'name': 'TypedTest/0', 409 'tests': 1, 410 'failures': 0, 411 'disabled': 0, 412 'errors': 0, 413 'time': '*', 414 'timestamp': '*', 415 'testsuite': [{ 416 'name': 'HasTypeParamAttribute', 417 'type_param': 'int', 418 'file': 'gtest_xml_output_unittest_.cc', 419 'line': 173, 420 'status': 'RUN', 421 'result': 'COMPLETED', 422 'time': '*', 423 'timestamp': '*', 424 'classname': 'TypedTest/0', 425 }], 426 }, 427 { 428 'name': 'TypedTest/1', 429 'tests': 1, 430 'failures': 0, 431 'disabled': 0, 432 'errors': 0, 433 'time': '*', 434 'timestamp': '*', 435 'testsuite': [{ 436 'name': 'HasTypeParamAttribute', 437 'type_param': 'long', 438 'file': 'gtest_xml_output_unittest_.cc', 439 'line': 173, 440 'status': 'RUN', 441 'result': 'COMPLETED', 442 'time': '*', 443 'timestamp': '*', 444 'classname': 'TypedTest/1', 445 }], 446 }, 447 { 448 'name': 'Single/TypeParameterizedTestSuite/0', 449 'tests': 1, 450 'failures': 0, 451 'disabled': 0, 452 'errors': 0, 453 'time': '*', 454 'timestamp': '*', 455 'testsuite': [{ 456 'name': 'HasTypeParamAttribute', 457 'type_param': 'int', 458 'file': 'gtest_xml_output_unittest_.cc', 459 'line': 180, 460 'status': 'RUN', 461 'result': 'COMPLETED', 462 'time': '*', 463 'timestamp': '*', 464 'classname': 'Single/TypeParameterizedTestSuite/0', 465 }], 466 }, 467 { 468 'name': 'Single/TypeParameterizedTestSuite/1', 469 'tests': 1, 470 'failures': 0, 471 'disabled': 0, 472 'errors': 0, 473 'time': '*', 474 'timestamp': '*', 475 'testsuite': [{ 476 'name': 'HasTypeParamAttribute', 477 'type_param': 'long', 478 'file': 'gtest_xml_output_unittest_.cc', 479 'line': 180, 480 'status': 'RUN', 481 'result': 'COMPLETED', 482 'time': '*', 483 'timestamp': '*', 484 'classname': 'Single/TypeParameterizedTestSuite/1', 485 }], 486 }, 487 { 488 'name': 'Single/ValueParamTest', 489 'tests': 4, 490 'failures': 0, 491 'disabled': 0, 492 'errors': 0, 493 'time': '*', 494 'timestamp': '*', 495 'testsuite': [ 496 { 497 'name': 'HasValueParamAttribute/0', 498 'value_param': '33', 499 'file': 'gtest_xml_output_unittest_.cc', 500 'line': 164, 501 'status': 'RUN', 502 'result': 'COMPLETED', 503 'time': '*', 504 'timestamp': '*', 505 'classname': 'Single/ValueParamTest', 506 }, 507 { 508 'name': 'HasValueParamAttribute/1', 509 'value_param': '42', 510 'file': 'gtest_xml_output_unittest_.cc', 511 'line': 164, 512 'status': 'RUN', 513 'result': 'COMPLETED', 514 'time': '*', 515 'timestamp': '*', 516 'classname': 'Single/ValueParamTest', 517 }, 518 { 519 'name': 'AnotherTestThatHasValueParamAttribute/0', 520 'value_param': '33', 521 'file': 'gtest_xml_output_unittest_.cc', 522 'line': 165, 523 'status': 'RUN', 524 'result': 'COMPLETED', 525 'time': '*', 526 'timestamp': '*', 527 'classname': 'Single/ValueParamTest', 528 }, 529 { 530 'name': 'AnotherTestThatHasValueParamAttribute/1', 531 'value_param': '42', 532 'file': 'gtest_xml_output_unittest_.cc', 533 'line': 165, 534 'status': 'RUN', 535 'result': 'COMPLETED', 536 'time': '*', 537 'timestamp': '*', 538 'classname': 'Single/ValueParamTest', 539 }, 540 ], 541 }, 542 ], 543} 544 545EXPECTED_FILTERED = { 546 'tests': 1, 547 'failures': 0, 548 'disabled': 0, 549 'errors': 0, 550 'time': '*', 551 'timestamp': '*', 552 'name': 'AllTests', 553 'ad_hoc_property': '42', 554 'testsuites': [{ 555 'name': 'SuccessfulTest', 556 'tests': 1, 557 'failures': 0, 558 'disabled': 0, 559 'errors': 0, 560 'time': '*', 561 'timestamp': '*', 562 'testsuite': [{ 563 'name': 'Succeeds', 564 'file': 'gtest_xml_output_unittest_.cc', 565 'line': 53, 566 'status': 'RUN', 567 'result': 'COMPLETED', 568 'time': '*', 569 'timestamp': '*', 570 'classname': 'SuccessfulTest', 571 }], 572 }], 573} 574 575EXPECTED_NO_TEST = { 576 'tests': 0, 577 'failures': 0, 578 'disabled': 0, 579 'errors': 0, 580 'time': '*', 581 'timestamp': '*', 582 'name': 'AllTests', 583 'testsuites': [{ 584 'name': 'NonTestSuiteFailure', 585 'tests': 1, 586 'failures': 1, 587 'disabled': 0, 588 'skipped': 0, 589 'errors': 0, 590 'time': '*', 591 'timestamp': '*', 592 'testsuite': [{ 593 'name': '', 594 'status': 'RUN', 595 'result': 'COMPLETED', 596 'time': '*', 597 'timestamp': '*', 598 'classname': '', 599 'failures': [{ 600 'failure': ( 601 'gtest_no_test_unittest.cc:*\n' 602 'Expected equality of these values:\n' 603 ' 1\n 2' 604 + STACK_TRACE_TEMPLATE 605 ), 606 'type': '', 607 }], 608 }], 609 }], 610} 611 612GTEST_PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath(GTEST_PROGRAM_NAME) 613 614SUPPORTS_TYPED_TESTS = ( 615 'TypedTest' 616 in gtest_test_utils.Subprocess( 617 [GTEST_PROGRAM_PATH, GTEST_LIST_TESTS_FLAG], capture_stderr=False 618 ).output 619) 620 621 622class GTestJsonOutputUnitTest(gtest_test_utils.TestCase): 623 """Unit test for Google Test's JSON output functionality.""" 624 625 # This test currently breaks on platforms that do not support typed and 626 # type-parameterized tests, so we don't run it under them. 627 if SUPPORTS_TYPED_TESTS: 628 629 def testNonEmptyJsonOutput(self): 630 """Verifies JSON output for a Google Test binary with non-empty output. 631 632 Runs a test program that generates a non-empty JSON output, and 633 tests that the JSON output is expected. 634 """ 635 self._TestJsonOutput(GTEST_PROGRAM_NAME, EXPECTED_NON_EMPTY, 1) 636 637 def testNoTestJsonOutput(self): 638 """Verifies JSON output for a Google Test binary without actual tests. 639 640 Runs a test program that generates an JSON output for a binary with no 641 tests, and tests that the JSON output is expected. 642 """ 643 644 self._TestJsonOutput('gtest_no_test_unittest', EXPECTED_NO_TEST, 0) 645 646 def testTimestampValue(self): 647 """Checks whether the timestamp attribute in the JSON output is valid. 648 649 Runs a test program that generates an empty JSON output, and checks if 650 the timestamp attribute in the testsuites tag is valid. 651 """ 652 actual = self._GetJsonOutput('gtest_no_test_unittest', [], 0) 653 date_time_str = actual['timestamp'] 654 # datetime.strptime() is only available in Python 2.5+ so we have to 655 # parse the expected datetime manually. 656 match = re.match(r'(\d+)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)', date_time_str) 657 self.assertTrue( 658 re.match, 659 'JSON datettime string %s has incorrect format' % date_time_str, 660 ) 661 date_time_from_json = datetime.datetime( 662 year=int(match.group(1)), 663 month=int(match.group(2)), 664 day=int(match.group(3)), 665 hour=int(match.group(4)), 666 minute=int(match.group(5)), 667 second=int(match.group(6)), 668 ) 669 670 time_delta = abs(datetime.datetime.now() - date_time_from_json) 671 # timestamp value should be near the current local time 672 self.assertTrue( 673 time_delta < datetime.timedelta(seconds=600), 674 'time_delta is %s' % time_delta, 675 ) 676 677 def testDefaultOutputFile(self): 678 """Verifies the default output file name. 679 680 Confirms that Google Test produces an JSON output file with the expected 681 default name if no name is explicitly specified. 682 """ 683 output_file = os.path.join( 684 gtest_test_utils.GetTempDir(), GTEST_DEFAULT_OUTPUT_FILE 685 ) 686 gtest_prog_path = gtest_test_utils.GetTestExecutablePath( 687 'gtest_no_test_unittest' 688 ) 689 try: 690 os.remove(output_file) 691 except OSError: 692 e = sys.exc_info()[1] 693 if e.errno != errno.ENOENT: 694 raise 695 696 p = gtest_test_utils.Subprocess( 697 [gtest_prog_path, '%s=json' % GTEST_OUTPUT_FLAG], 698 working_dir=gtest_test_utils.GetTempDir(), 699 ) 700 self.assertTrue(p.exited) 701 self.assertEqual(0, p.exit_code) 702 self.assertTrue(os.path.isfile(output_file)) 703 704 def testSuppressedJsonOutput(self): 705 """Verifies that no JSON output is generated. 706 707 Tests that no JSON file is generated if the default JSON listener is 708 shut down before RUN_ALL_TESTS is invoked. 709 """ 710 711 json_path = os.path.join( 712 gtest_test_utils.GetTempDir(), GTEST_PROGRAM_NAME + 'out.json' 713 ) 714 if os.path.isfile(json_path): 715 os.remove(json_path) 716 717 command = [ 718 GTEST_PROGRAM_PATH, 719 '%s=json:%s' % (GTEST_OUTPUT_FLAG, json_path), 720 '--shut_down_xml', 721 ] 722 p = gtest_test_utils.Subprocess(command) 723 if p.terminated_by_signal: 724 # p.signal is available only if p.terminated_by_signal is True. 725 self.assertFalse( 726 p.terminated_by_signal, 727 '%s was killed by signal %d' % (GTEST_PROGRAM_NAME, p.signal), 728 ) 729 else: 730 self.assertTrue(p.exited) 731 self.assertEqual( 732 1, 733 p.exit_code, 734 "'%s' exited with code %s, which doesn't match " 735 'the expected exit code %s.' % (command, p.exit_code, 1), 736 ) 737 738 self.assertTrue(not os.path.isfile(json_path)) 739 740 def testFilteredTestJsonOutput(self): 741 """Verifies JSON output when a filter is applied. 742 743 Runs a test program that executes only some tests and verifies that 744 non-selected tests do not show up in the JSON output. 745 """ 746 747 self._TestJsonOutput( 748 GTEST_PROGRAM_NAME, 749 EXPECTED_FILTERED, 750 0, 751 extra_args=['%s=SuccessfulTest.*' % GTEST_FILTER_FLAG], 752 ) 753 754 def _GetJsonOutput(self, gtest_prog_name, extra_args, expected_exit_code): 755 """Returns the JSON output generated by running the program gtest_prog_name. 756 757 Furthermore, the program's exit code must be expected_exit_code. 758 759 Args: 760 gtest_prog_name: Google Test binary name. 761 extra_args: extra arguments to binary invocation. 762 expected_exit_code: program's exit code. 763 """ 764 json_path = os.path.join( 765 gtest_test_utils.GetTempDir(), gtest_prog_name + 'out.json' 766 ) 767 gtest_prog_path = gtest_test_utils.GetTestExecutablePath(gtest_prog_name) 768 769 command = [ 770 gtest_prog_path, 771 '%s=json:%s' % (GTEST_OUTPUT_FLAG, json_path), 772 ] + extra_args 773 p = gtest_test_utils.Subprocess(command) 774 if p.terminated_by_signal: 775 self.assertTrue( 776 False, '%s was killed by signal %d' % (gtest_prog_name, p.signal) 777 ) 778 else: 779 self.assertTrue(p.exited) 780 self.assertEqual( 781 expected_exit_code, 782 p.exit_code, 783 "'%s' exited with code %s, which doesn't match " 784 'the expected exit code %s.' 785 % (command, p.exit_code, expected_exit_code), 786 ) 787 with open(json_path) as f: 788 actual = json.load(f) 789 return actual 790 791 def _TestJsonOutput( 792 self, gtest_prog_name, expected, expected_exit_code, extra_args=None 793 ): 794 """Checks the JSON output generated by the Google Test binary. 795 796 Asserts that the JSON document generated by running the program 797 gtest_prog_name matches expected_json, a string containing another 798 JSON document. Furthermore, the program's exit code must be 799 expected_exit_code. 800 801 Args: 802 gtest_prog_name: Google Test binary name. 803 expected: expected output. 804 expected_exit_code: program's exit code. 805 extra_args: extra arguments to binary invocation. 806 """ 807 808 actual = self._GetJsonOutput( 809 gtest_prog_name, extra_args or [], expected_exit_code 810 ) 811 self.assertEqual(expected, gtest_json_test_utils.normalize(actual)) 812 813 814if __name__ == '__main__': 815 if NO_STACKTRACE_SUPPORT_FLAG in sys.argv: 816 # unittest.main() can't handle unknown flags 817 sys.argv.remove(NO_STACKTRACE_SUPPORT_FLAG) 818 819 os.environ['GTEST_STACK_TRACE_DEPTH'] = '1' 820 gtest_test_utils.Main() 821