| ... |
... |
@@ -569,6 +569,33 @@ def extra_ways( ways: List[WayName] ): |
|
569
|
569
|
|
|
570
|
570
|
return helper
|
|
571
|
571
|
|
|
|
572
|
+# -----
|
|
|
573
|
+
|
|
|
574
|
+def _io_managers( name: TestName, opts, io_mgrs: List[str] ) -> None:
|
|
|
575
|
+ opts.io_managers = io_mgrs
|
|
|
576
|
+
|
|
|
577
|
+def io_managers( io_mgrs: List[str] ):
|
|
|
578
|
+ """
|
|
|
579
|
+ Run this test once for each of the given I/O managers (identified by
|
|
|
580
|
+ the name used with GHC's `--io-manager` RTS flag, e.g. 'mio',
|
|
|
581
|
+ 'select', 'winio'), instead of the usual set of ways. I/O managers
|
|
|
582
|
+ that are not supported on the current platform/build are silently
|
|
|
583
|
+ skipped.
|
|
|
584
|
+ """
|
|
|
585
|
+ return lambda name, opts: _io_managers(name, opts, io_mgrs)
|
|
|
586
|
+
|
|
|
587
|
+def all_io_managers( name: TestName, opts ):
|
|
|
588
|
+ """
|
|
|
589
|
+ Run this test once for each I/O manager supported by this
|
|
|
590
|
+ platform/build.
|
|
|
591
|
+ """
|
|
|
592
|
+ _io_managers(name, opts, config.io_managers_all)
|
|
|
593
|
+
|
|
|
594
|
+def all_io_managers_except(exclude: List[str]):
|
|
|
595
|
+ """
|
|
|
596
|
+ Like all_io_managers, but excluding the given I/O managers.
|
|
|
597
|
+ """
|
|
|
598
|
+ return lambda name, opts: _io_managers(name, opts, list(set(config.io_managers_all) - set(exclude)))
|
|
572
|
599
|
|
|
573
|
600
|
# -----
|
|
574
|
601
|
|
| ... |
... |
@@ -1573,6 +1600,12 @@ do_not_copy = ('.hi', '.o', '.dyn_hi' |
|
1573
|
1600
|
, '.dyn_o', '.out'
|
|
1574
|
1601
|
,'.hi-boot', '.o-boot') # 12112
|
|
1575
|
1602
|
|
|
|
1603
|
+def way_supports_io_manager(way: WayName, io_manager: None | str) -> bool:
|
|
|
1604
|
+ if not io_manager:
|
|
|
1605
|
+ return True
|
|
|
1606
|
+ way_is_threaded = '-threaded' in config.way_rts_flags[way]
|
|
|
1607
|
+ return io_manager in config.io_managers_threaded if way_is_threaded else io_manager in config.io_managers_nonthreaded
|
|
|
1608
|
+
|
|
1576
|
1609
|
async def test_common_work(name: TestName, opts,
|
|
1577
|
1610
|
func, args) -> None:
|
|
1578
|
1611
|
try:
|
| ... |
... |
@@ -1582,11 +1615,14 @@ async def test_common_work(name: TestName, opts, |
|
1582
|
1615
|
package_conf_cache_file_start_timestamp = get_package_cache_timestamp()
|
|
1583
|
1616
|
|
|
1584
|
1617
|
# All the ways we might run this test
|
|
|
1618
|
+ func_has_io_manager_param = False
|
|
1585
|
1619
|
if func == compile or func == multimod_compile:
|
|
1586
|
1620
|
all_ways = config.compile_ways
|
|
1587
|
1621
|
elif func in [compile_and_run, multi_compile_and_run, multimod_compile_and_run]:
|
|
1588
|
1622
|
all_ways = config.run_ways
|
|
|
1623
|
+ func_has_io_manager_param = True
|
|
1589
|
1624
|
elif func == ghci_script or func == ghci_multiunit_script:
|
|
|
1625
|
+ func_has_io_manager_param = True
|
|
1590
|
1626
|
if config.have_interp:
|
|
1591
|
1627
|
all_ways = [WayName('ghci'), WayName('ghci-opt')]
|
|
1592
|
1628
|
else:
|
| ... |
... |
@@ -1616,12 +1652,28 @@ async def test_common_work(name: TestName, opts, |
|
1616
|
1652
|
if needsTargetWrapper():
|
|
1617
|
1653
|
opts.skip = True
|
|
1618
|
1654
|
else:
|
|
|
1655
|
+ if func in [backpack_run, warn_and_run]:
|
|
|
1656
|
+ func_has_io_manager_param = True
|
|
1619
|
1657
|
all_ways = [WayName('normal')]
|
|
1620
|
1658
|
|
|
1621
|
1659
|
# A test itself can request extra ways by setting opts.extra_ways
|
|
1622
|
1660
|
all_ways = list(OrderedDict.fromkeys(all_ways + [way for way in opts.extra_ways if way not in all_ways]))
|
|
1623
|
1661
|
|
|
1624
|
|
- t.total_test_cases += len(all_ways)
|
|
|
1662
|
+ # We run each way over each io manager
|
|
|
1663
|
+ all_io_managers = opts.io_managers if func_has_io_manager_param and opts.io_managers else [None]
|
|
|
1664
|
+ all_ways_and_io_managers = dict(
|
|
|
1665
|
+ (
|
|
|
1666
|
+ way,
|
|
|
1667
|
+ [io_manager
|
|
|
1668
|
+ for io_manager in all_io_managers
|
|
|
1669
|
+ if way_supports_io_manager(way, io_manager)
|
|
|
1670
|
+ ]
|
|
|
1671
|
+ )
|
|
|
1672
|
+ for way in all_ways
|
|
|
1673
|
+ )
|
|
|
1674
|
+
|
|
|
1675
|
+ for io_managers in all_ways_and_io_managers.values():
|
|
|
1676
|
+ t.total_test_cases += len(io_managers)
|
|
1625
|
1677
|
|
|
1626
|
1678
|
only_ways = getTestOpts().only_ways
|
|
1627
|
1679
|
ok_way = lambda way: \
|
| ... |
... |
@@ -1704,17 +1756,26 @@ async def test_common_work(name: TestName, opts, |
|
1704
|
1756
|
|
|
1705
|
1757
|
# Run the required tests...
|
|
1706
|
1758
|
for way in do_ways:
|
|
1707
|
|
- if stopping():
|
|
1708
|
|
- break
|
|
1709
|
|
- try:
|
|
1710
|
|
- await do_test(name, way, func, args, files)
|
|
1711
|
|
- except KeyboardInterrupt:
|
|
1712
|
|
- stopNow()
|
|
1713
|
|
- except Exception as e:
|
|
1714
|
|
- traceback.print_exc()
|
|
1715
|
|
- framework_fail(name, way, traceback.format_exc())
|
|
|
1759
|
+ for io_manager in all_ways_and_io_managers[way]:
|
|
|
1760
|
+ if stopping():
|
|
|
1761
|
+ break
|
|
|
1762
|
+ try:
|
|
|
1763
|
+ await do_test(
|
|
|
1764
|
+ name,
|
|
|
1765
|
+ way,
|
|
|
1766
|
+ io_manager,
|
|
|
1767
|
+ func,
|
|
|
1768
|
+ args,
|
|
|
1769
|
+ files)
|
|
|
1770
|
+ except KeyboardInterrupt:
|
|
|
1771
|
+ stopNow()
|
|
|
1772
|
+ except Exception as e:
|
|
|
1773
|
+ traceback.print_exc()
|
|
|
1774
|
+ framework_fail(name, way, traceback.format_exc())
|
|
|
1775
|
+
|
|
|
1776
|
+ for skipped_way in set(all_ways) - set(do_ways):
|
|
|
1777
|
+ t.n_tests_skipped += len(all_ways_and_io_managers[skipped_way])
|
|
1716
|
1778
|
|
|
1717
|
|
- t.n_tests_skipped += len(set(all_ways) - set(do_ways))
|
|
1718
|
1779
|
if getTestOpts().expect == 'missing-lib': t.n_missing_libs += 1
|
|
1719
|
1780
|
|
|
1720
|
1781
|
if config.cleanup and do_ways:
|
| ... |
... |
@@ -1733,6 +1794,7 @@ async def test_common_work(name: TestName, opts, |
|
1733
|
1794
|
|
|
1734
|
1795
|
async def do_test(name: TestName,
|
|
1735
|
1796
|
way: WayName,
|
|
|
1797
|
+ io_manager: None | str,
|
|
1736
|
1798
|
func: Callable[..., Awaitable[PassFail]],
|
|
1737
|
1799
|
args,
|
|
1738
|
1800
|
files: Set[str]
|
| ... |
... |
@@ -1740,6 +1802,8 @@ async def do_test(name: TestName, |
|
1740
|
1802
|
opts = getTestOpts()
|
|
1741
|
1803
|
|
|
1742
|
1804
|
full_name = name + '(' + way + ')'
|
|
|
1805
|
+ if io_manager:
|
|
|
1806
|
+ full_name += ' (IO Manager: {})'.format(io_manager)
|
|
1743
|
1807
|
test_n = len(allTestNames)
|
|
1744
|
1808
|
progress_args = [ full_name, t.total_tests, test_n,
|
|
1745
|
1809
|
[len(t.unexpected_passes),
|
| ... |
... |
@@ -1820,7 +1884,8 @@ async def do_test(name: TestName, |
|
1820
|
1884
|
# Don't continue and try to run the test if the pre_cmd fails.
|
|
1821
|
1885
|
return
|
|
1822
|
1886
|
|
|
1823
|
|
- result = await func(*[name,way] + args)
|
|
|
1887
|
+ io_manager_arg = [io_manager] if io_manager else []
|
|
|
1888
|
+ result = await func(*[name,way] + io_manager_arg + args)
|
|
1824
|
1889
|
|
|
1825
|
1890
|
if opts.expect not in ['pass', 'fail', 'missing-lib']:
|
|
1826
|
1891
|
framework_fail(name, way, 'bad expected ' + opts.expect)
|
| ... |
... |
@@ -1909,19 +1974,19 @@ def framework_warn(name: TestName, way: WayName, reason: str) -> None: |
|
1909
|
1974
|
# run_command.
|
|
1910
|
1975
|
|
|
1911
|
1976
|
async def run_command( name, way, cmd ):
|
|
1912
|
|
- return await simple_run( name, '', override_options(cmd), '' )
|
|
|
1977
|
+ return await simple_run( name, '', None, override_options(cmd), '' )
|
|
1913
|
1978
|
|
|
1914
|
1979
|
async def makefile_test( name, way, target=None ):
|
|
1915
|
1980
|
if target is None:
|
|
1916
|
1981
|
target = name
|
|
1917
|
1982
|
|
|
1918
|
1983
|
cmd = '$MAKE -s --no-print-directory {target}'.format(target=target)
|
|
1919
|
|
- return await run_command(name, way, cmd)
|
|
|
1984
|
+ return await run_command(name, way, None, cmd)
|
|
1920
|
1985
|
|
|
1921
|
1986
|
# -----------------------------------------------------------------------------
|
|
1922
|
1987
|
# GHCi tests
|
|
1923
|
1988
|
|
|
1924
|
|
-async def ghci_script( name, way, script):
|
|
|
1989
|
+async def ghci_script( name, way, io_manager, script):
|
|
1925
|
1990
|
flags = ' '.join(get_compiler_flags())
|
|
1926
|
1991
|
way_flags = ' '.join(config.way_flags[way])
|
|
1927
|
1992
|
|
| ... |
... |
@@ -1932,9 +1997,9 @@ async def ghci_script( name, way, script): |
|
1932
|
1997
|
# NB: put way_flags before flags so that flags in all.T can override others
|
|
1933
|
1998
|
|
|
1934
|
1999
|
getTestOpts().stdin = script
|
|
1935
|
|
- return await simple_run( name, way, cmd, getTestOpts().extra_run_opts )
|
|
|
2000
|
+ return await simple_run( name, way, io_manager, cmd, getTestOpts().extra_run_opts )
|
|
1936
|
2001
|
|
|
1937
|
|
-async def ghci_multiunit_script( name, way, units, script):
|
|
|
2002
|
+async def ghci_multiunit_script( name, way, io_manager, units, script):
|
|
1938
|
2003
|
flags = ' '.join(get_compiler_flags())
|
|
1939
|
2004
|
way_flags = ' '.join(config.way_flags[way])
|
|
1940
|
2005
|
unit_flags = ' '.join(['-unit @%s' % unit for unit in units])
|
| ... |
... |
@@ -1946,7 +2011,7 @@ async def ghci_multiunit_script( name, way, units, script): |
|
1946
|
2011
|
# NB: put way_flags before flags so that flags in all.T can override others
|
|
1947
|
2012
|
|
|
1948
|
2013
|
getTestOpts().stdin = script
|
|
1949
|
|
- return await simple_run( name, way, cmd, getTestOpts().extra_run_opts )
|
|
|
2014
|
+ return await simple_run( name, way, io_manager, cmd, getTestOpts().extra_run_opts )
|
|
1950
|
2015
|
|
|
1951
|
2016
|
# -----------------------------------------------------------------------------
|
|
1952
|
2017
|
# Compile-only tests
|
| ... |
... |
@@ -2126,6 +2191,7 @@ async def compile_grep_core(name: TestName, |
|
2126
|
2191
|
|
|
2127
|
2192
|
async def compile_and_run__(name: TestName,
|
|
2128
|
2193
|
way: WayName,
|
|
|
2194
|
+ io_manager: None | str,
|
|
2129
|
2195
|
top_mod: Path,
|
|
2130
|
2196
|
extra_mods: List[str],
|
|
2131
|
2197
|
extra_hc_opts: str,
|
| ... |
... |
@@ -2168,22 +2234,22 @@ async def compile_and_run__(name: TestName, |
|
2168
|
2234
|
cmd = './' + name + extension
|
|
2169
|
2235
|
|
|
2170
|
2236
|
# we don't check the compiler's stderr for a compile-and-run test
|
|
2171
|
|
- return await simple_run( name, way, cmd, getTestOpts().extra_run_opts )
|
|
|
2237
|
+ return await simple_run( name, way, io_manager, cmd, getTestOpts().extra_run_opts )
|
|
2172
|
2238
|
|
|
2173
|
|
-async def compile_and_run( name, way, extra_hc_opts ):
|
|
2174
|
|
- return await compile_and_run__( name, way, None, [], extra_hc_opts)
|
|
|
2239
|
+async def compile_and_run( name, way, io_manager, extra_hc_opts ):
|
|
|
2240
|
+ return await compile_and_run__( name, way, io_manager, None, [], extra_hc_opts)
|
|
2175
|
2241
|
|
|
2176
|
|
-async def backpack_run( name, way, extra_hc_opts ):
|
|
2177
|
|
- return await compile_and_run__( name, way, None, [], extra_hc_opts, backpack=True )
|
|
|
2242
|
+async def backpack_run( name, way, io_manager, extra_hc_opts ):
|
|
|
2243
|
+ return await compile_and_run__( name, way, io_manager, None, [], extra_hc_opts, backpack=True )
|
|
2178
|
2244
|
|
|
2179
|
|
-async def multimod_compile_and_run( name, way, top_mod, extra_hc_opts ):
|
|
2180
|
|
- return await compile_and_run__( name, way, top_mod, [], extra_hc_opts)
|
|
|
2245
|
+async def multimod_compile_and_run( name, way, io_manager, top_mod, extra_hc_opts ):
|
|
|
2246
|
+ return await compile_and_run__( name, way, io_manager, top_mod, [], extra_hc_opts)
|
|
2181
|
2247
|
|
|
2182
|
|
-async def multi_compile_and_run( name, way, top_mod, extra_mods, extra_hc_opts ):
|
|
2183
|
|
- return await compile_and_run__( name, way, top_mod, extra_mods, extra_hc_opts)
|
|
|
2248
|
+async def multi_compile_and_run( name, way, io_manager, top_mod, extra_mods, extra_hc_opts ):
|
|
|
2249
|
+ return await compile_and_run__( name, way, io_manager, top_mod, extra_mods, extra_hc_opts)
|
|
2184
|
2250
|
|
|
2185
|
|
-async def warn_and_run( name, way, extra_hc_opts ):
|
|
2186
|
|
- return await compile_and_run__( name, way, None, [], extra_hc_opts, compile_stderr = True)
|
|
|
2251
|
+async def warn_and_run( name, way, io_manager, extra_hc_opts ):
|
|
|
2252
|
+ return await compile_and_run__( name, way, io_manager, None, [], extra_hc_opts, compile_stderr = True)
|
|
2187
|
2253
|
|
|
2188
|
2254
|
async def static_stats( name, way ):
|
|
2189
|
2255
|
opts = getTestOpts()
|
| ... |
... |
@@ -2390,7 +2456,7 @@ async def simple_build(name: Union[TestName, str], |
|
2390
|
2456
|
# from /dev/null. Route output to testname.run.stdout and
|
|
2391
|
2457
|
# testname.run.stderr. Returns the exit code of the run.
|
|
2392
|
2458
|
|
|
2393
|
|
-async def simple_run(name: TestName, way: WayName, prog: str, extra_run_opts: str) -> Any:
|
|
|
2459
|
+async def simple_run(name: TestName, way: WayName, io_manager: None | str, prog: str, extra_run_opts: str) -> Any:
|
|
2394
|
2460
|
opts = getTestOpts()
|
|
2395
|
2461
|
|
|
2396
|
2462
|
# figure out what to use for stdin
|
| ... |
... |
@@ -2409,6 +2475,9 @@ async def simple_run(name: TestName, way: WayName, prog: str, extra_run_opts: st |
|
2409
|
2475
|
|
|
2410
|
2476
|
my_rts_flags = rts_flags(way)
|
|
2411
|
2477
|
|
|
|
2478
|
+ if io_manager:
|
|
|
2479
|
+ my_rts_flags += '+RTS --io-manager={0} -RTS'.format(io_manager)
|
|
|
2480
|
+
|
|
2412
|
2481
|
# Collect runtime stats if necessary:
|
|
2413
|
2482
|
# isStatsTest and not isCompilerStatsTest():
|
|
2414
|
2483
|
# assume we are running a ghc compiled program. Collect stats.
|