Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • testsuite/driver/junit.py
    ... ... @@ -2,10 +2,33 @@ from my_typing import *
    2 2
     from datetime import datetime
    
    3 3
     import xml.etree.ElementTree as ET
    
    4 4
     
    
    5
    -from testglobals import TestRun
    
    5
    +from testglobals import TestRun, TestResult
    
    6
    +
    
    7
    +
    
    8
    +def add_testcase(testsuite: ET.Element, test_result: TestResult) -> ET.Element:
    
    9
    +    """Adds the xml element representing the testcase."""
    
    10
    +    testcase = ET.SubElement(testsuite, 'testcase',
    
    11
    +                             classname = test_result.way,
    
    12
    +                             name = '%s(%s)' % (test_result.testname, test_result.way))
    
    13
    +    if test_result.runtime is not None:
    
    14
    +        testcase.set('time', '%.3f' % test_result.runtime)
    
    15
    +    return testcase
    
    16
    +
    
    17
    +def add_result(testcase: ET.Element, kind: str, res_type: str,
    
    18
    +               reason: Optional[str], text: str) -> ET.Element:
    
    19
    +    """Add a result to the testcase."""
    
    20
    +    # GitLab ignores the message attribute and shows only the text.
    
    21
    +    result = ET.SubElement(testcase, kind,
    
    22
    +                           type = res_type,
    
    23
    +                           message = reason or '')
    
    24
    +    result.text = text
    
    25
    +    return result
    
    6 26
     
    
    7 27
     def junit(t: TestRun) -> ET.ElementTree:
    
    8
    -    testsuites = ET.Element('testsuites')
    
    28
    +    # Report time spent in testsuite.
    
    29
    +    assert t.start_time is not None
    
    30
    +    elapsed = '%.3f' % (datetime.now() - t.start_time).total_seconds()
    
    31
    +    testsuites = ET.Element('testsuites', time = elapsed)
    
    9 32
         testsuite = ET.SubElement(testsuites, 'testsuite',
    
    10 33
                                   id = "0",
    
    11 34
                                   package = 'ghc',
    
    ... ... @@ -15,6 +38,7 @@ def junit(t: TestRun) -> ET.ElementTree:
    15 38
                                                  + len(t.unexpected_passes)),
    
    16 39
                                   errors = str(len(t.framework_failures)),
    
    17 40
                                   skipped = str(len(t.fragile_failures)),
    
    41
    +                              time = elapsed,
    
    18 42
                                   timestamp = datetime.now().isoformat())
    
    19 43
     
    
    20 44
         for kind, res_type, group in [('failure', 'stat failure', t.unexpected_stat_failures),
    
    ... ... @@ -22,9 +46,7 @@ def junit(t: TestRun) -> ET.ElementTree:
    22 46
                                       ('failure', 'unexpected pass', t.unexpected_passes),
    
    23 47
                                       ('skipped', 'fragile failure', t.fragile_failures)]:
    
    24 48
             for tr in group:
    
    25
    -            testcase = ET.SubElement(testsuite, 'testcase',
    
    26
    -                                     classname = tr.way,
    
    27
    -                                     name = '%s(%s)' % (tr.testname, tr.way))
    
    49
    +            testcase = add_testcase(testsuite, tr)
    
    28 50
                 message = [] # type: List[str]
    
    29 51
                 if tr.diff:
    
    30 52
                     message += ['diff:', '==========', tr.diff]
    
    ... ... @@ -35,23 +57,16 @@ def junit(t: TestRun) -> ET.ElementTree:
    35 57
                 if not message:
    
    36 58
                     message = [tr.reason]
    
    37 59
     
    
    38
    -            result = ET.SubElement(testcase, kind,
    
    39
    -                                   type = res_type,
    
    40
    -                                   message = tr.reason)
    
    41
    -            result.text = '\n'.join(message)
    
    60
    +            add_result(testcase, kind, res_type, tr.reason, '\n'.join(message))
    
    42 61
     
    
    43 62
         for tr in t.framework_failures:
    
    44
    -        testcase = ET.SubElement(testsuite, 'testcase',
    
    45
    -                                 classname = tr.way,
    
    46
    -                                 name = '%s(%s)' % (tr.testname, tr.way))
    
    47
    -        result = ET.SubElement(testcase, 'error',
    
    48
    -                               type = "framework failure",
    
    49
    -                               message = tr.reason)
    
    50
    -
    
    51
    -    for tr in t.expected_passes:
    
    52
    -        testcase = ET.SubElement(testsuite, 'testcase',
    
    53
    -                                 classname = tr.way,
    
    54
    -                                 name = '%s(%s)' % (tr.testname, tr.way))
    
    63
    +        testcase = add_testcase(testsuite, tr)
    
    64
    +        add_result(testcase, 'error', 'framework failure', tr.reason, tr.reason)
    
    65
    +
    
    66
    +    # Expected failures (expect_broken) behaved as expected, so they count as
    
    67
    +    # passes, like in the driver's exit code.
    
    68
    +    for tr in t.expected_passes + t.expected_failures + t.fragile_passes:
    
    69
    +        add_testcase(testsuite, tr)
    
    55 70
     
    
    56 71
         return ET.ElementTree(testsuites)
    
    57 72
     

  • testsuite/driver/testglobals.py
    ... ... @@ -288,10 +288,10 @@ ghc_env = os.environ.copy()
    288 288
     class TestResult:
    
    289 289
         """
    
    290 290
         A result from the execution of a test. These live in the expected_passes,
    
    291
    -    framework_failures, framework_warnings, unexpected_passes,
    
    291
    +    expected_failures, framework_failures, framework_warnings, unexpected_passes,
    
    292 292
         unexpected_failures, unexpected_stat_failures lists of TestRun.
    
    293 293
         """
    
    294
    -    __slots__ = 'directory', 'testname', 'reason', 'way', 'stdout', 'stderr', 'diff'
    
    294
    +    __slots__ = 'directory', 'testname', 'reason', 'way', 'stdout', 'stderr', 'diff', 'runtime'
    
    295 295
         def __init__(self,
    
    296 296
                      directory: str,
    
    297 297
                      testname: TestName,
    
    ... ... @@ -299,7 +299,8 @@ class TestResult:
    299 299
                      way: WayName,
    
    300 300
                      stdout: Optional[str]=None,
    
    301 301
                      stderr: Optional[str]=None,
    
    302
    -                 diff: Optional[str]=None) -> None:
    
    302
    +                 diff: Optional[str]=None,
    
    303
    +                 runtime: Optional[float]=None) -> None:
    
    303 304
             self.directory = directory
    
    304 305
             self.testname = testname
    
    305 306
             self.reason = reason
    
    ... ... @@ -307,6 +308,7 @@ class TestResult:
    307 308
             self.stdout = stdout
    
    308 309
             self.stderr = stderr
    
    309 310
             self.diff = diff
    
    311
    +        self.runtime = runtime # Walltime
    
    310 312
     
    
    311 313
     # A performance metric measured in this test run.
    
    312 314
     PerfMetric = NamedTuple('PerfMetric',
    
    ... ... @@ -322,13 +324,12 @@ class TestRun:
    322 324
     
    
    323 325
            self.n_tests_skipped = 0
    
    324 326
            self.n_missing_libs = 0
    
    325
    -       self.n_expected_passes = 0
    
    326
    -       self.n_expected_failures = 0
    
    327 327
     
    
    328 328
            self.framework_failures = [] # type: List[TestResult]
    
    329 329
            self.framework_warnings = [] # type: List[TestResult]
    
    330 330
     
    
    331 331
            self.expected_passes = [] # type: List[TestResult]
    
    332
    +       self.expected_failures = [] # type: List[TestResult]
    
    332 333
            self.unexpected_passes = [] # type: List[TestResult]
    
    333 334
            self.unexpected_failures = [] # type: List[TestResult]
    
    334 335
            self.unexpected_stat_failures = [] # type: List[TestResult]
    

  • testsuite/driver/testlib.py
    ... ... @@ -1706,13 +1706,15 @@ async def test_common_work(name: TestName, opts,
    1706 1706
             for way in do_ways:
    
    1707 1707
                 if stopping():
    
    1708 1708
                     break
    
    1709
    +            start = time.monotonic()
    
    1709 1710
                 try:
    
    1710 1711
                     await do_test(name, way, func, args, files)
    
    1711 1712
                 except KeyboardInterrupt:
    
    1712 1713
                     stopNow()
    
    1713 1714
                 except Exception as e:
    
    1714 1715
                     traceback.print_exc()
    
    1715
    -                framework_fail(name, way, traceback.format_exc())
    
    1716
    +                framework_fail(name, way, traceback.format_exc(),
    
    1717
    +                               runtime=time.monotonic() - start)
    
    1716 1718
     
    
    1717 1719
             t.n_tests_skipped += len(set(all_ways) - set(do_ways))
    
    1718 1720
             if getTestOpts().expect == 'missing-lib': t.n_missing_libs += 1
    
    ... ... @@ -1738,6 +1740,7 @@ async def do_test(name: TestName,
    1738 1740
                 files: Set[str]
    
    1739 1741
                 ) -> None:
    
    1740 1742
         opts = getTestOpts()
    
    1743
    +    start = time.monotonic()
    
    1741 1744
     
    
    1742 1745
         full_name = name + '(' + way + ')'
    
    1743 1746
         test_n = len(allTestNames)
    
    ... ... @@ -1787,7 +1790,8 @@ async def do_test(name: TestName,
    1787 1790
                     pass
    
    1788 1791
                 else:
    
    1789 1792
                     framework_fail(name, way,
    
    1790
    -                    'extra_file does not exist: ' + extra_file)
    
    1793
    +                    'extra_file does not exist: ' + extra_file,
    
    1794
    +                    runtime=time.monotonic() - start)
    
    1791 1795
     
    
    1792 1796
         if func.__name__ == 'run_command' or func.__name__ == 'makefile_test' or opts.pre_cmd:
    
    1793 1797
             # When running 'MAKE' make sure 'TOP' still points to the
    
    ... ... @@ -1811,7 +1815,8 @@ async def do_test(name: TestName,
    1811 1815
     
    
    1812 1816
             # If user used expect_broken then don't record failures of pre_cmd
    
    1813 1817
             if exit_code != 0 and opts.expect not in ['fail']:
    
    1814
    -            framework_fail(name, way, 'pre_cmd failed: {0}'.format(exit_code))
    
    1818
    +            framework_fail(name, way, 'pre_cmd failed: {0}'.format(exit_code),
    
    1819
    +                           runtime=time.monotonic() - start)
    
    1815 1820
                 if_verbose(1, '** pre_cmd was "{0}".'.format(override_options(opts.pre_cmd)))
    
    1816 1821
                 stderr_contents = stderr_path.read_text(encoding='UTF-8', errors='replace')
    
    1817 1822
                 stdout_contents = stdout_path.read_text(encoding='UTF-8', errors='replace')
    
    ... ... @@ -1821,45 +1826,54 @@ async def do_test(name: TestName,
    1821 1826
                 return
    
    1822 1827
     
    
    1823 1828
         result = await func(*[name,way] + args)
    
    1829
    +    runtime = time.monotonic() - start
    
    1824 1830
     
    
    1825 1831
         if opts.expect not in ['pass', 'fail', 'missing-lib']:
    
    1826
    -        framework_fail(name, way, 'bad expected ' + opts.expect)
    
    1832
    +        framework_fail(name, way, 'bad expected ' + opts.expect, runtime=runtime)
    
    1827 1833
     
    
    1828 1834
         directory = _result_directory(opts)
    
    1829 1835
     
    
    1830 1836
         if way in opts.fragile_ways:
    
    1831 1837
             if_verbose(1, '*** fragile test %s resulted in %s' % (full_name, 'pass' if result.passed else 'fail'))
    
    1832 1838
             if result.passed:
    
    1833
    -            t.fragile_passes.append(TestResult(directory, name, 'fragile', way))
    
    1839
    +            t.fragile_passes.append(TestResult(directory, name, 'fragile', way,
    
    1840
    +                                               runtime=runtime))
    
    1834 1841
             else:
    
    1835 1842
                 reason = '%s (fragile)' % result.reason if result.reason else 'fragile'
    
    1836 1843
                 t.fragile_failures.append(TestResult(directory, name, reason, way,
    
    1837 1844
                                                      stdout=result.stdout,
    
    1838 1845
                                                      stderr=result.stderr,
    
    1839
    -                                                 diff=result.diff))
    
    1846
    +                                                 diff=result.diff,
    
    1847
    +                                                 runtime=runtime))
    
    1840 1848
         elif result.passed:
    
    1841 1849
             if _expect_pass(way):
    
    1842
    -            t.expected_passes.append(TestResult(directory, name, "", way))
    
    1843
    -            t.n_expected_passes += 1
    
    1850
    +            t.expected_passes.append(TestResult(directory, name, "", way,
    
    1851
    +                                                runtime=runtime))
    
    1844 1852
             else:
    
    1845 1853
                 if_verbose(1, '*** unexpected pass for %s' % full_name)
    
    1846
    -            t.unexpected_passes.append(TestResult(directory, name, 'unexpected', way))
    
    1854
    +            t.unexpected_passes.append(TestResult(directory, name, 'unexpected', way,
    
    1855
    +                                                  runtime=runtime))
    
    1847 1856
         else:
    
    1848 1857
             if _expect_pass(way):
    
    1849 1858
                 reason = result.reason
    
    1850 1859
                 tag = result.tag
    
    1851 1860
                 if tag == 'stat':
    
    1852 1861
                     if_verbose(1, '*** unexpected stat test failure for %s' % full_name)
    
    1853
    -                t.unexpected_stat_failures.append(TestResult(directory, name, reason, way))
    
    1862
    +                t.unexpected_stat_failures.append(TestResult(directory, name, reason, way,
    
    1863
    +                                                             runtime=runtime))
    
    1854 1864
                 else:
    
    1855 1865
                     if_verbose(1, '*** unexpected failure for %s' % full_name)
    
    1856 1866
                     tr = TestResult(directory, name, reason, way,
    
    1857 1867
                                     stdout=result.stdout,
    
    1858 1868
                                     stderr=result.stderr,
    
    1859
    -                                diff=result.diff)
    
    1869
    +                                diff=result.diff,
    
    1870
    +                                runtime=runtime)
    
    1860 1871
                     t.unexpected_failures.append(tr)
    
    1861 1872
             else:
    
    1862
    -            t.n_expected_failures += 1
    
    1873
    +            # Only keep the reason: nothing reports the output of expected
    
    1874
    +            # failures.
    
    1875
    +            t.expected_failures.append(TestResult(directory, name, result.reason, way,
    
    1876
    +                                                  runtime=runtime))
    
    1863 1877
     
    
    1864 1878
     # Make is often invoked with -s, which means if it fails, we get
    
    1865 1879
     # no feedback at all. This is annoying. So let's remove the option
    
    ... ... @@ -1873,7 +1887,8 @@ def override_options(pre_cmd):
    1873 1887
     
    
    1874 1888
         return pre_cmd
    
    1875 1889
     
    
    1876
    -def framework_fail(name: Optional[TestName], way: Optional[WayName], reason: str) -> None:
    
    1890
    +def framework_fail(name: Optional[TestName], way: Optional[WayName], reason: str,
    
    1891
    +                   runtime: Optional[float]=None) -> None:
    
    1877 1892
         opts = getTestOpts()
    
    1878 1893
         # framework_fail can be called before testdir is initialised,
    
    1879 1894
         # so we need to take care not to blow up with the wrong way
    
    ... ... @@ -1888,7 +1903,8 @@ def framework_fail(name: Optional[TestName], way: Optional[WayName], reason: str
    1888 1903
         way2 = way if way is not None else WayName('none')
    
    1889 1904
         if way not in opts.fragile_ways:
    
    1890 1905
             # If the test is fragile then we rather report this as a fragile test failure
    
    1891
    -        t.framework_failures.append(TestResult(directory, name2, reason, way2))
    
    1906
    +        t.framework_failures.append(TestResult(directory, name2, reason, way2,
    
    1907
    +                                               runtime=runtime))
    
    1892 1908
     
    
    1893 1909
     def framework_warn(name: TestName, way: WayName, reason: str) -> None:
    
    1894 1910
         opts = getTestOpts()
    
    ... ... @@ -3649,9 +3665,9 @@ def summary(t: TestRun, file: TextIO, color=False, junit_path: Optional[Path]=No
    3649 3665
                    + repr(t.n_missing_libs).rjust(8)
    
    3650 3666
                    + ' had missing libraries\n'
    
    3651 3667
                    + '\n'
    
    3652
    -               + repr(t.n_expected_passes).rjust(8)
    
    3668
    +               + repr(len(t.expected_passes)).rjust(8)
    
    3653 3669
                    + ' expected passes\n'
    
    3654
    -               + repr(t.n_expected_failures).rjust(8)
    
    3670
    +               + repr(len(t.expected_failures)).rjust(8)
    
    3655 3671
                    + ' expected failures\n'
    
    3656 3672
                    + '\n'
    
    3657 3673
                    + repr(len(t.framework_failures)).rjust(8)
    

  • testsuite/tests/perf/compiler/all.T
    ... ... @@ -363,15 +363,20 @@ test('T13379',
    363 363
     # (though the size of the fluctuations does perhaps suggest that it
    
    364 364
     # would be valuable to solve the pathology in a more general way).
    
    365 365
     
    
    366
    +# Note [MultiLayerModules* test timeout]
    
    367
    +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    368
    +# These tests are relatively sensitive to system load and cane
    
    369
    +# take a while to run. This caused a fair number of CI failures
    
    370
    +# in the past. So we give them some headroom.
    
    371
    +# We need to ensure to use the right timeout for those test. In the past
    
    372
    +# we used the compile timeout for the GHCi versions by accident.
    
    373
    +
    
    366 374
     test('MultiLayerModules',
    
    367 375
          [ collect_compiler_stats('bytes allocated',2),
    
    368 376
            pre_cmd('./genMultiLayerModules'),
    
    369 377
            extra_files(['genMultiLayerModules']),
    
    378
    +       # See Note [MultiLayerModules* test timeout]
    
    370 379
            compile_timeout_multiplier(5)
    
    371
    -       # this is _a lot_
    
    372
    -       # but this test has been failing every now and then,
    
    373
    -       # especially on i386. Let's just give it some room
    
    374
    -       # to complete successfully reliably everywhere.
    
    375 380
          ],
    
    376 381
          multimod_compile,
    
    377 382
          # see Note [Increased initial stack size for MultiLayerModules]
    
    ... ... @@ -382,11 +387,8 @@ test('MultiLayerModulesRecomp',
    382 387
          [ collect_compiler_stats('bytes allocated',2),
    
    383 388
            pre_cmd('$MAKE -s --no-print-directory MultiModulesRecomp'),
    
    384 389
            extra_files(['genMultiLayerModules']),
    
    390
    +       # See Note [MultiLayerModules* test timeout]
    
    385 391
            compile_timeout_multiplier(5)
    
    386
    -       # this is _a lot_
    
    387
    -       # but this test has been failing every now and then,
    
    388
    -       # especially on i386. Let's just give it some room
    
    389
    -       # to complete successfully reliably everywhere.
    
    390 392
          ],
    
    391 393
          multimod_compile,
    
    392 394
          # see Note [Increased initial stack size for MultiLayerModules]
    
    ... ... @@ -398,6 +400,7 @@ test('MultiLayerModulesTH_Make',
    398 400
          [ collect_compiler_stats('bytes allocated',2),
    
    399 401
            pre_cmd('$MAKE -s --no-print-directory MultiLayerModulesTH_Make_Prep'),
    
    400 402
            extra_files(['genMultiLayerModulesTH']),
    
    403
    +       # See Note [MultiLayerModules* test timeout]
    
    401 404
            compile_timeout_multiplier(5),
    
    402 405
            when(arch('wasm32'), fragile(25336)),
    
    403 406
            # We skip the test on darwin due to recent regression due to toolchain
    
    ... ... @@ -413,6 +416,7 @@ test('MultiLayerModulesTH_OneShot',
    413 416
          [ collect_compiler_stats('bytes allocated',2),
    
    414 417
            pre_cmd('$MAKE -s --no-print-directory MultiLayerModulesTH_OneShot_Prep'),
    
    415 418
            extra_files(['genMultiLayerModulesTH']),
    
    419
    +       # See Note [MultiLayerModules* test timeout]
    
    416 420
            compile_timeout_multiplier(5),
    
    417 421
            when(arch('wasm32'), fragile(25336)),
    
    418 422
            # We skip the test on darwin due to recent regression due to toolchain
    
    ... ... @@ -427,11 +431,8 @@ test('MultiLayerModulesDefsGhci',
    427 431
          [ collect_compiler_residency(15),
    
    428 432
            pre_cmd('./genMultiLayerModulesDefs'),
    
    429 433
            extra_files(['genMultiLayerModulesDefs']),
    
    430
    -       compile_timeout_multiplier(5)
    
    431
    -       # this is _a lot_
    
    432
    -       # but this test has been failing every now and then,
    
    433
    -       # especially on i386. Let's just give it some room
    
    434
    -       # to complete successfully reliably everywhere.
    
    434
    +       # See Note [MultiLayerModules* test timeout]
    
    435
    +       run_timeout_multiplier(5)
    
    435 436
          ],
    
    436 437
          ghci_script,
    
    437 438
          ['MultiLayerModulesDefsGhci.script'])
    
    ... ... @@ -440,11 +441,9 @@ test('MultiLayerModulesDefsGhciWithCore',
    440 441
          [ collect_compiler_residency(15),
    
    441 442
            pre_cmd('$MAKE -s --no-print-directory MultiModulesRecompDefsWithCore'),
    
    442 443
            extra_files(['genMultiLayerModulesCore', 'MultiLayerModulesDefsGhciWithCore.script']),
    
    443
    -       compile_timeout_multiplier(5),
    
    444
    -       # this is _a lot_
    
    445
    -       # but this test has been failing every now and then,
    
    446
    -       # especially on i386. Let's just give it some room
    
    447
    -       # to complete successfully reliably everywhere.
    
    444
    +       # See Note [MultiLayerModules* test timeout]
    
    445
    +       pre_cmd_timeout_multiplier(5),
    
    446
    +       run_timeout_multiplier(5),
    
    448 447
            extra_run_opts('-fwrite-if-simplified-core MultiLayerModules')
    
    449 448
          ],
    
    450 449
          ghci_script,
    
    ... ... @@ -454,11 +453,9 @@ test('MultiLayerModulesDefsGhciWithBytecodeFiles',
    454 453
          [ collect_compiler_residency(15),
    
    455 454
            pre_cmd('$MAKE -s --no-print-directory MultiModulesRecompDefsWithBytecodeFiles'),
    
    456 455
            extra_files(['genMultiLayerModulesCore', 'MultiLayerModulesDefsGhciWithBytecodeFiles.script']),
    
    457
    -       compile_timeout_multiplier(5),
    
    458
    -       # this is _a lot_
    
    459
    -       # but this test has been failing every now and then,
    
    460
    -       # especially on i386. Let's just give it some room
    
    461
    -       # to complete successfully reliably everywhere.
    
    456
    +       # See Note [MultiLayerModules* test timeout]
    
    457
    +       pre_cmd_timeout_multiplier(5),
    
    458
    +       run_timeout_multiplier(5),
    
    462 459
            extra_run_opts('-fwrite-byte-code MultiLayerModules')
    
    463 460
          ],
    
    464 461
          ghci_script,
    
    ... ... @@ -468,11 +465,8 @@ test('MultiLayerModulesDefsGhcWithCore',
    468 465
          [ collect_compiler_residency(15),
    
    469 466
            pre_cmd('$MAKE -s --no-print-directory MultiModulesDefsWithCore'),
    
    470 467
            extra_files(['genMultiLayerModulesCore']),
    
    468
    +       # See Note [MultiLayerModules* test timeout]
    
    471 469
            compile_timeout_multiplier(5)
    
    472
    -       # this is _a lot_
    
    473
    -       # but this test has been failing every now and then,
    
    474
    -       # especially on i386. Let's just give it some room
    
    475
    -       # to complete successfully reliably everywhere.
    
    476 470
          ],
    
    477 471
          multimod_compile,
    
    478 472
          ['MultiLayerModules', '-v0 -fwrite-if-simplified-core'])
    
    ... ... @@ -481,11 +475,8 @@ test('MultiLayerModulesDefsGhciReload',
    481 475
          [ collect_compiler_residency(15),
    
    482 476
            pre_cmd('./genMultiLayerModulesDefs'),
    
    483 477
            extra_files(['genMultiLayerModulesDefs']),
    
    484
    -       compile_timeout_multiplier(10)
    
    485
    -       # this is _a lot_
    
    486
    -       # but this test has been failing every now and then,
    
    487
    -       # especially on i386. Let's just give it some room
    
    488
    -       # to complete successfully reliably everywhere.
    
    478
    +       # See Note [MultiLayerModules* test timeout]
    
    479
    +       run_timeout_multiplier(5)
    
    489 480
          ],
    
    490 481
          ghci_script,
    
    491 482
          ['MultiLayerModulesDefsGhciReload.script'])
    
    ... ... @@ -504,11 +495,8 @@ test('InstanceMatching1',
    504 495
          [ collect_compiler_stats('bytes allocated',3),
    
    505 496
            pre_cmd('./genMatchingTest 1'),
    
    506 497
            extra_files(['genMatchingTest']),
    
    498
    +       # See Note [MultiLayerModules* test timeout]
    
    507 499
            compile_timeout_multiplier(5)
    
    508
    -       # this is _a lot_
    
    509
    -       # but this test has been failing every now and then,
    
    510
    -       # especially on i386. Let's just give it some room
    
    511
    -       # to complete successfully reliably everywhere.
    
    512 500
          ],
    
    513 501
          multimod_compile,
    
    514 502
          ['Defs', '-fno-code -fwrite-interface -v0'])
    
    ... ... @@ -518,11 +506,8 @@ test('MultiLayerModulesNoCode',
    518 506
          [ collect_compiler_residency(15),
    
    519 507
            pre_cmd('./genMultiLayerModulesNoCode'),
    
    520 508
            extra_files(['genMultiLayerModulesNoCode']),
    
    521
    -       compile_timeout_multiplier(5)
    
    522
    -       # this is _a lot_
    
    523
    -       # but this test has been failing every now and then,
    
    524
    -       # especially on i386. Let's just give it some room
    
    525
    -       # to complete successfully reliably everywhere.
    
    509
    +       # See Note [MultiLayerModules* test timeout]
    
    510
    +       run_timeout_multiplier(5)
    
    526 511
          ],
    
    527 512
          ghci_script,
    
    528 513
          ['MultiLayerModulesNoCode.script'])