993 lines · python
1# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.2# See https://llvm.org/LICENSE.txt for license information.3# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception4 5# To run these tests:6# python -m unittest generate_test_report_lib_test.py7 8import unittest9from io import StringIO10from textwrap import dedent11import tempfile12import os13 14from junitparser import JUnitXml15 16import generate_test_report_lib17 18 19def junit_from_xml(xml):20 return JUnitXml.fromfile(StringIO(xml))21 22 23class TestReports(unittest.TestCase):24 def test_find_failure_ninja_logs(self):25 failures = generate_test_report_lib.find_failure_in_ninja_logs(26 [27 [28 "[1/5] test/1.stamp",29 "[2/5] test/2.stamp",30 "[3/5] test/3.stamp",31 "[4/5] test/4.stamp",32 "FAILED: touch test/4.stamp",33 "Wow! This system is really broken!",34 "[5/5] test/5.stamp",35 ],36 ]37 )38 self.assertEqual(len(failures), 1)39 self.assertEqual(40 failures[0],41 (42 "touch test/4.stamp",43 dedent(44 """\45 FAILED: touch test/4.stamp46 Wow! This system is really broken!"""47 ),48 ),49 )50 51 def test_no_failure_ninja_log(self):52 failures = generate_test_report_lib.find_failure_in_ninja_logs(53 [54 [55 "[1/3] test/1.stamp",56 "[2/3] test/2.stamp",57 "[3/3] test/3.stamp",58 ]59 ]60 )61 self.assertEqual(failures, [])62 63 def test_ninja_log_end(self):64 failures = generate_test_report_lib.find_failure_in_ninja_logs(65 [66 [67 "[1/3] test/1.stamp",68 "[2/3] test/2.stamp",69 "[3/3] test/3.stamp",70 "FAILED: touch test/3.stamp",71 "Wow! This system is really broken!",72 "ninja: build stopped: subcommand failed.",73 ]74 ]75 )76 self.assertEqual(len(failures), 1)77 self.assertEqual(78 failures[0],79 (80 "touch test/3.stamp",81 dedent(82 """\83 FAILED: touch test/3.stamp84 Wow! This system is really broken!"""85 ),86 ),87 )88 89 def test_ninja_log_multiple_failures(self):90 failures = generate_test_report_lib.find_failure_in_ninja_logs(91 [92 [93 "[1/5] test/1.stamp",94 "[2/5] test/2.stamp",95 "FAILED: touch test/2.stamp",96 "Wow! This system is really broken!",97 "[3/5] test/3.stamp",98 "[4/5] test/4.stamp",99 "FAILED: touch test/4.stamp",100 "Wow! This system is maybe broken!",101 "[5/5] test/5.stamp",102 ]103 ]104 )105 self.assertEqual(len(failures), 2)106 self.assertEqual(107 failures[0],108 (109 "touch test/2.stamp",110 dedent(111 """\112 FAILED: touch test/2.stamp113 Wow! This system is really broken!"""114 ),115 ),116 )117 self.assertEqual(118 failures[1],119 (120 "touch test/4.stamp",121 dedent(122 """\123 FAILED: touch test/4.stamp124 Wow! This system is maybe broken!"""125 ),126 ),127 )128 129 # Test that we can correctly handle the runtimes build. the LLVM runtimes130 # build will involve ninja invoking more ninja processes within the131 # runtimes directory. This means that we see two failures for a failure in132 # the runtimes build: one from the inner ninja containing the actual action133 # that failed, and one for the sub ninja invocation that failed.134 def test_ninja_log_runtimes_failure(self):135 failures = generate_test_report_lib.find_failure_in_ninja_logs(136 [137 [138 "[1/5] test/1.stamp",139 "[2/5] test/2.stamp",140 "FAILED: touch test/2.stamp",141 "Wow! This system is really broken!",142 "ninja: build stopped: subcommand failed.",143 "FAILED: running check-runtime failed.",144 "<some random command>",145 "ninja: build stopped: subcommand failed.",146 ]147 ]148 )149 self.assertEqual(len(failures), 1)150 self.assertEqual(151 failures[0],152 (153 "touch test/2.stamp",154 dedent(155 """\156 FAILED: touch test/2.stamp157 Wow! This system is really broken!"""158 ),159 ),160 )161 162 # Test that we correctly handle cases where the FAILED: line does not163 # match up with the progress indicator.164 def test_ninja_log_mismatched_failed(self):165 failures = generate_test_report_lib.find_failure_in_ninja_logs(166 [167 [168 "[1/5] test/1.stamp",169 "[2/5] test/2.stamp",170 "ModuleNotFoundError: No module named 'mount_langley'",171 "FAILED: tools/check-langley",172 "Wow! This system is really broken!",173 "[5/5] test/5.stamp",174 ]175 ]176 )177 self.assertEqual(len(failures), 1)178 self.assertEqual(179 failures[0],180 (181 "tools/check-langley",182 dedent(183 """\184 FAILED: tools/check-langley185 Wow! This system is really broken!"""186 ),187 ),188 )189 190 def test_title_only(self):191 self.assertEqual(192 generate_test_report_lib.generate_report("Foo", 0, [], []),193 dedent(194 """\195 # Foo196 197 The build succeeded and no tests ran. This is expected in some build configurations."""198 ),199 )200 201 def test_title_only_failure(self):202 self.assertEqual(203 generate_test_report_lib.generate_report("Foo", 1, [], []),204 dedent(205 """\206 # Foo207 208 The build failed before running any tests. Detailed information about the build failure could not be automatically obtained.209 210 Download the build's log file to see the details.211 212 If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""213 ),214 )215 216 def test_title_only_failure_ninja_log(self):217 self.assertEqual(218 generate_test_report_lib.generate_report(219 "Foo",220 1,221 [],222 [223 [224 "[1/5] test/1.stamp",225 "[2/5] test/2.stamp",226 "[3/5] test/3.stamp",227 "[4/5] test/4.stamp",228 "FAILED: test/4.stamp",229 "touch test/4.stamp",230 "Wow! Risk!",231 "[5/5] test/5.stamp",232 ]233 ],234 ),235 dedent(236 """\237 # Foo238 239 The build failed before running any tests. Click on a failure below to see the details.240 241 <details>242 <summary>test/4.stamp</summary>243 244 ```245 FAILED: test/4.stamp246 touch test/4.stamp247 Wow! Risk!248 ```249 </details>250 251 If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""252 ),253 )254 255 def test_no_tests_in_testsuite(self):256 self.assertEqual(257 generate_test_report_lib.generate_report(258 "Foo",259 1,260 [261 junit_from_xml(262 dedent(263 """\264 <?xml version="1.0" encoding="UTF-8"?>265 <testsuites time="0.00">266 <testsuite name="Empty" tests="0" failures="0" skipped="0" time="0.00">267 </testsuite>268 </testsuites>"""269 )270 )271 ],272 [],273 ),274 dedent(275 """\276 # Foo277 278 The build failed before running any tests. Detailed information about the build failure could not be automatically obtained.279 280 Download the build's log file to see the details.281 282 If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""283 ),284 )285 286 def test_no_failures(self):287 self.assertEqual(288 generate_test_report_lib.generate_report(289 "Foo",290 0,291 [292 junit_from_xml(293 dedent(294 """\295 <?xml version="1.0" encoding="UTF-8"?>296 <testsuites time="0.00">297 <testsuite name="Passed" tests="1" failures="0" skipped="0" time="0.00">298 <testcase classname="Bar/test_1" name="test_1" time="0.00"/>299 </testsuite>300 </testsuites>"""301 )302 )303 ],304 [],305 ),306 (307 dedent(308 """\309 # Foo310 311 * 1 test passed"""312 )313 ),314 )315 316 def test_no_failures_build_failed(self):317 self.assertEqual(318 generate_test_report_lib.generate_report(319 "Foo",320 1,321 [322 junit_from_xml(323 dedent(324 """\325 <?xml version="1.0" encoding="UTF-8"?>326 <testsuites time="0.00">327 <testsuite name="Passed" tests="1" failures="0" skipped="0" time="0.00">328 <testcase classname="Bar/test_1" name="test_1" time="0.00"/>329 </testsuite>330 </testsuites>"""331 )332 )333 ],334 [],335 ),336 (337 dedent(338 """\339 # Foo340 341 * 1 test passed342 343 All tests passed but another part of the build **failed**. Information about the build failure could not be automatically obtained.344 345 Download the build's log file to see the details.346 347 If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""348 )349 ),350 )351 352 def test_no_failures_build_failed_ninja_log(self):353 self.assertEqual(354 generate_test_report_lib.generate_report(355 "Foo",356 1,357 [358 junit_from_xml(359 dedent(360 """\361 <?xml version="1.0" encoding="UTF-8"?>362 <testsuites time="0.00">363 <testsuite name="Passed" tests="1" failures="0" skipped="0" time="0.00">364 <testcase classname="Bar/test_1" name="test_1" time="0.00"/>365 </testsuite>366 </testsuites>"""367 )368 )369 ],370 [371 [372 "[1/5] test/1.stamp",373 "[2/5] test/2.stamp",374 "[3/5] test/3.stamp",375 "[4/5] test/4.stamp",376 "FAILED: test/4.stamp",377 "touch test/4.stamp",378 "Wow! Close To You!",379 "[5/5] test/5.stamp",380 ]381 ],382 ),383 (384 dedent(385 """\386 # Foo387 388 * 1 test passed389 390 All tests passed but another part of the build **failed**. Click on a failure below to see the details.391 392 <details>393 <summary>test/4.stamp</summary>394 395 ```396 FAILED: test/4.stamp397 touch test/4.stamp398 Wow! Close To You!399 ```400 </details>401 402 If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""403 )404 ),405 )406 407 def test_no_failures_multiple_build_failed_ninja_log(self):408 test = generate_test_report_lib.generate_report(409 "Foo",410 1,411 [412 junit_from_xml(413 dedent(414 """\415 <?xml version="1.0" encoding="UTF-8"?>416 <testsuites time="0.00">417 <testsuite name="Passed" tests="1" failures="0" skipped="0" time="0.00">418 <testcase classname="Bar/test_1" name="test_1" time="0.00"/>419 </testsuite>420 </testsuites>"""421 )422 )423 ],424 [425 [426 "[1/5] test/1.stamp",427 "[2/5] test/2.stamp",428 "FAILED: touch test/2.stamp",429 "Wow! Be Kind!",430 "[3/5] test/3.stamp",431 "[4/5] test/4.stamp",432 "FAILED: touch test/4.stamp",433 "Wow! I Dare You!",434 "[5/5] test/5.stamp",435 ]436 ],437 )438 self.assertEqual(439 generate_test_report_lib.generate_report(440 "Foo",441 1,442 [443 junit_from_xml(444 dedent(445 """\446 <?xml version="1.0" encoding="UTF-8"?>447 <testsuites time="0.00">448 <testsuite name="Passed" tests="1" failures="0" skipped="0" time="0.00">449 <testcase classname="Bar/test_1" name="test_1" time="0.00"/>450 </testsuite>451 </testsuites>"""452 )453 )454 ],455 [456 [457 "[1/5] test/1.stamp",458 "[2/5] test/2.stamp",459 "FAILED: touch test/2.stamp",460 "Wow! Be Kind!",461 "[3/5] test/3.stamp",462 "[4/5] test/4.stamp",463 "FAILED: touch test/4.stamp",464 "Wow! I Dare You!",465 "[5/5] test/5.stamp",466 ]467 ],468 ),469 (470 dedent(471 """\472 # Foo473 474 * 1 test passed475 476 All tests passed but another part of the build **failed**. Click on a failure below to see the details.477 478 <details>479 <summary>touch test/2.stamp</summary>480 481 ```482 FAILED: touch test/2.stamp483 Wow! Be Kind!484 ```485 </details>486 <details>487 <summary>touch test/4.stamp</summary>488 489 ```490 FAILED: touch test/4.stamp491 Wow! I Dare You!492 ```493 </details>494 495 If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""496 )497 ),498 )499 500 def test_report_single_file_single_testsuite(self):501 self.assertEqual(502 generate_test_report_lib.generate_report(503 "Foo",504 1,505 [506 junit_from_xml(507 dedent(508 """\509 <?xml version="1.0" encoding="UTF-8"?>510 <testsuites time="8.89">511 <testsuite name="Bar" tests="4" failures="2" skipped="1" time="410.63">512 <testcase classname="Bar/test_1" name="test_1" time="0.02"/>513 <testcase classname="Bar/test_2" name="test_2" time="0.02">514 <skipped message="Reason"/>515 </testcase>516 <testcase classname="Bar/test_3" name="test_3" time="0.02">517 <failure><![CDATA[Output goes here]]></failure>518 </testcase>519 <testcase classname="Bar/test_4" name="test_4" time="0.02">520 <failure><![CDATA[Other output goes here]]></failure>521 </testcase>522 </testsuite>523 </testsuites>"""524 )525 )526 ],527 [],528 ),529 (530 dedent(531 """\532 # Foo533 534 * 1 test passed535 * 1 test skipped536 * 2 tests failed537 538 ## Failed Tests539 (click on a test name to see its output)540 541 ### Bar542 <details>543 <summary>Bar/test_3/test_3</summary>544 545 ```546 Output goes here547 ```548 </details>549 <details>550 <summary>Bar/test_4/test_4</summary>551 552 ```553 Other output goes here554 ```555 </details>556 557 If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""558 )559 ),560 )561 562 MULTI_SUITE_OUTPUT = dedent(563 """\564 # ABC and DEF565 566 * 1 test passed567 * 1 test skipped568 * 2 tests failed569 570 ## Failed Tests571 (click on a test name to see its output)572 573 ### ABC574 <details>575 <summary>ABC/test_2/test_2</summary>576 577 ```578 ABC/test_2 output goes here579 ```580 </details>581 582 ### DEF583 <details>584 <summary>DEF/test_2/test_2</summary>585 586 ```587 DEF/test_2 output goes here588 ```589 </details>590 591 If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""592 )593 594 def test_report_single_file_multiple_testsuites(self):595 self.assertEqual(596 generate_test_report_lib.generate_report(597 "ABC and DEF",598 1,599 [600 junit_from_xml(601 dedent(602 """\603 <?xml version="1.0" encoding="UTF-8"?>604 <testsuites time="8.89">605 <testsuite name="ABC" tests="2" failures="1" skipped="0" time="410.63">606 <testcase classname="ABC/test_1" name="test_1" time="0.02"/>607 <testcase classname="ABC/test_2" name="test_2" time="0.02">608 <failure><![CDATA[ABC/test_2 output goes here]]></failure>609 </testcase>610 </testsuite>611 <testsuite name="DEF" tests="2" failures="1" skipped="1" time="410.63">612 <testcase classname="DEF/test_1" name="test_1" time="0.02">613 <skipped message="reason"/>614 </testcase>615 <testcase classname="DEF/test_2" name="test_2" time="0.02">616 <failure><![CDATA[DEF/test_2 output goes here]]></failure>617 </testcase>618 </testsuite>619 </testsuites>"""620 )621 )622 ],623 [],624 ),625 self.MULTI_SUITE_OUTPUT,626 )627 628 def test_report_multiple_files_multiple_testsuites(self):629 self.assertEqual(630 generate_test_report_lib.generate_report(631 "ABC and DEF",632 1,633 [634 junit_from_xml(635 dedent(636 """\637 <?xml version="1.0" encoding="UTF-8"?>638 <testsuites time="8.89">639 <testsuite name="ABC" tests="2" failures="1" skipped="0" time="410.63">640 <testcase classname="ABC/test_1" name="test_1" time="0.02"/>641 <testcase classname="ABC/test_2" name="test_2" time="0.02">642 <failure><![CDATA[ABC/test_2 output goes here]]></failure>643 </testcase>644 </testsuite>645 </testsuites>"""646 )647 ),648 junit_from_xml(649 dedent(650 """\651 <?xml version="1.0" encoding="UTF-8"?>652 <testsuites time="8.89">653 <testsuite name="DEF" tests="2" failures="1" skipped="1" time="410.63">654 <testcase classname="DEF/test_1" name="test_1" time="0.02">655 <skipped message="reason"/>656 </testcase>657 <testcase classname="DEF/test_2" name="test_2" time="0.02">658 <failure><![CDATA[DEF/test_2 output goes here]]></failure>659 </testcase>660 </testsuite>661 </testsuites>"""662 )663 ),664 ],665 [],666 ),667 self.MULTI_SUITE_OUTPUT,668 )669 670 def test_report_dont_list_failures(self):671 self.assertEqual(672 generate_test_report_lib.generate_report(673 "Foo",674 1,675 [676 junit_from_xml(677 dedent(678 """\679 <?xml version="1.0" encoding="UTF-8"?>680 <testsuites time="0.02">681 <testsuite name="Bar" tests="1" failures="1" skipped="0" time="0.02">682 <testcase classname="Bar/test_1" name="test_1" time="0.02">683 <failure><![CDATA[Output goes here]]></failure>684 </testcase>685 </testsuite>686 </testsuites>"""687 )688 )689 ],690 [],691 list_failures=False,692 ),693 (694 dedent(695 """\696 # Foo697 698 * 1 test failed699 700 Failed tests and their output was too large to report. Download the build's log file to see the details.701 702 If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""703 )704 ),705 )706 707 def test_report_dont_list_failures_link_to_log(self):708 self.assertEqual(709 generate_test_report_lib.generate_report(710 "Foo",711 1,712 [713 junit_from_xml(714 dedent(715 """\716 <?xml version="1.0" encoding="UTF-8"?>717 <testsuites time="0.02">718 <testsuite name="Bar" tests="1" failures="1" skipped="0" time="0.02">719 <testcase classname="Bar/test_1" name="test_1" time="0.02">720 <failure><![CDATA[Output goes here]]></failure>721 </testcase>722 </testsuite>723 </testsuites>"""724 )725 )726 ],727 [],728 list_failures=False,729 ),730 (731 dedent(732 """\733 # Foo734 735 * 1 test failed736 737 Failed tests and their output was too large to report. Download the build's log file to see the details.738 739 If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""740 )741 ),742 )743 744 def test_report_size_limit(self):745 test_output = "f" * 1000746 self.assertEqual(747 generate_test_report_lib.generate_report(748 "Foo",749 1,750 [751 junit_from_xml(752 dedent(753 """\754 <?xml version="1.0" encoding="UTF-8"?>755 <testsuites time="0.02">756 <testsuite name="Bar" tests="1" failures="1" skipped="0" time="0.02">757 <testcase classname="Bar/test_1" name="test_1" time="0.02">758 <failure><![CDATA[{output}]]></failure>759 </testcase>760 </testsuite>761 </testsuites>""".format(762 output=test_output763 )764 )765 )766 ],767 [],768 size_limit=512,769 ),770 (771 dedent(772 """\773 # Foo774 775 * 1 test failed776 777 Failed tests and their output was too large to report. Download the build's log file to see the details.778 779 If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""780 )781 ),782 )783 784 def test_report_ninja_explanation(self):785 self.assertEqual(786 generate_test_report_lib.generate_report(787 "Foo",788 1,789 [],790 [791 [792 "[1/5] test/1.stamp",793 "[2/5] test/2.stamp",794 "[3/5] test/3.stamp",795 "[4/5] test/4.stamp",796 "FAILED: test/4.stamp",797 "touch test/4.stamp",798 "Half Moon Bay.",799 "[5/5] test/5.stamp",800 ]801 ],802 failure_explanations_list=[803 {804 "name": "test/4.stamp",805 "explained": True,806 "reason": "Failing at head",807 }808 ],809 ),810 dedent(811 """\812 # Foo813 814 The build failed before running any tests. Click on a failure below to see the details.815 816 <details>817 <summary>test/4.stamp (Likely Already Failing)</summary>818 Failing at head819 820 ```821 FAILED: test/4.stamp822 touch test/4.stamp823 Half Moon Bay.824 ```825 </details>826 827 If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""828 ),829 )830 831 def test_report_test_failure_explanation(self):832 self.assertEqual(833 generate_test_report_lib.generate_report(834 "Foo",835 1,836 [837 junit_from_xml(838 dedent(839 """\840 <?xml version="1.0" encoding="UTF-8"?>841 <testsuites time="8.89">842 <testsuite name="Bar" tests="1" failures="1" skipped="0" time="410.63">843 <testcase classname="Bar/test_3" name="test_3" time="0.02">844 <failure><![CDATA[Error! Expected Big Sur to be next to the ocean.]]></failure>845 </testcase>846 </testsuite>847 </testsuites>"""848 )849 )850 ],851 [],852 failure_explanations_list=[853 {854 "name": "Bar/test_3/test_3",855 "explained": True,856 "reason": "Big Sur is next to the Pacific.",857 }858 ],859 ),860 (861 dedent(862 """\863 # Foo864 865 * 1 test failed866 867 ## Failed Tests868 (click on a test name to see its output)869 870 ### Bar871 <details>872 <summary>Bar/test_3/test_3 (Likely Already Failing)</summary>873 Big Sur is next to the Pacific.874 875 ```876 Error! Expected Big Sur to be next to the ocean.877 ```878 </details>879 880 If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""881 )882 ),883 )884 885 def test_report_test_failure_have_explanation_explained_false(self):886 self.assertEqual(887 generate_test_report_lib.generate_report(888 "Foo",889 1,890 [891 junit_from_xml(892 dedent(893 """\894 <?xml version="1.0" encoding="UTF-8"?>895 <testsuites time="8.89">896 <testsuite name="Bar" tests="1" failures="1" skipped="0" time="410.63">897 <testcase classname="Bar/test_3" name="test_3" time="0.02">898 <failure><![CDATA[Error! Expected Mt. Shasta to be next in the Eastern Sierras.]]></failure>899 </testcase>900 </testsuite>901 </testsuites>"""902 )903 )904 ],905 [],906 failure_explanations_list=[907 {908 "name": "Bar/test_3/test_3",909 "explained": False,910 "reason": "Mt. Shasta is in the Cascades",911 }912 ],913 ),914 (915 dedent(916 """\917 # Foo918 919 * 1 test failed920 921 ## Failed Tests922 (click on a test name to see its output)923 924 ### Bar925 <details>926 <summary>Bar/test_3/test_3</summary>927 928 ```929 Error! Expected Mt. Shasta to be next in the Eastern Sierras.930 ```931 </details>932 933 If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""934 )935 ),936 )937 938 def test_generate_report_end_to_end(self):939 with tempfile.TemporaryDirectory() as temp_dir:940 junit_xml_file = os.path.join(temp_dir, "junit.xml")941 with open(junit_xml_file, "w") as junit_xml_handle:942 junit_xml_handle.write(943 dedent(944 """\945 <?xml version="1.0" encoding="UTF-8"?>946 <testsuites time="0.00">947 <testsuite name="Passed" tests="1" failures="0" skipped="0" time="0.00">948 <testcase classname="Bar/test_1" name="test_1" time="0.00"/>949 </testsuite>950 </testsuites>"""951 )952 )953 ninja_log_file = os.path.join(temp_dir, "ninja.log")954 with open(ninja_log_file, "w") as ninja_log_handle:955 ninja_log_handle.write(956 dedent(957 """\958 [1/5] test/1.stamp959 [2/5] test/2.stamp960 [3/5] test/3.stamp961 [4/5] test/4.stamp962 FAILED: test/4.stamp963 touch test/4.stamp964 Wow! That's so True!965 [5/5] test/5.stamp"""966 )967 )968 self.assertEqual(969 generate_test_report_lib.generate_report_from_files(970 "Foo", 1, [junit_xml_file, ninja_log_file]971 ),972 dedent(973 """\974 # Foo975 976 * 1 test passed977 978 All tests passed but another part of the build **failed**. Click on a failure below to see the details.979 980 <details>981 <summary>test/4.stamp</summary>982 983 ```984 FAILED: test/4.stamp985 touch test/4.stamp986 Wow! That's so True!987 ```988 </details>989 990 If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""991 ),992 )993