summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Miedema <thomasmiedema@gmail.com>2016-06-20 14:36:03 +0200
committerThomas Miedema <thomasmiedema@gmail.com>2016-06-28 12:25:29 +0200
commit58f0086b70f2f409b9f88de1611efcf18756f9e5 (patch)
tree80ac7bb98d0047b5e28f7c5b30953b3e2a333085
parentbafd615e40c2a11af1390e736f6122033eecc4c6 (diff)
downloadhaskell-58f0086b70f2f409b9f88de1611efcf18756f9e5.tar.gz
Testsuite: open/close stdin/stdout/stderr explicitly
This allows run_command's to contain `|`, and `no_stdin` isn't necessary anymore. Unfortunately it doesn't fix T7037 on Windows which I had hoped it would (testsuite driver tries to read a file that it just created itself, but the OS says it doesn't exist). The only drawback of this commit is that the command that the testsuite prints to the terminal (for debugging purposes) doesn't mention the files that stdout and stderr are redirected to anymore. This is probably ok. Update submodule unix. Differential Revision: https://phabricator.haskell.org/D1234
-rw-r--r--libraries/base/tests/IO/all.T7
m---------libraries/unix0
-rw-r--r--testsuite/driver/testglobals.py3
-rw-r--r--testsuite/driver/testlib.py137
-rw-r--r--testsuite/tests/ghc-e/should_run/Makefile2
-rw-r--r--testsuite/tests/rts/all.T2
6 files changed, 67 insertions, 84 deletions
diff --git a/libraries/base/tests/IO/all.T b/libraries/base/tests/IO/all.T
index 295553fa9a..56bb44df49 100644
--- a/libraries/base/tests/IO/all.T
+++ b/libraries/base/tests/IO/all.T
@@ -41,9 +41,8 @@ test('hReady001', normal, compile_and_run, ['-cpp'])
# data to read. It relies on piping input from 'sleep 1', which doesn't
# work for the 'ghci' way because in that case we already pipe input from
# a script, so hence omit_ways(['ghci'])
-test('hReady002', [ no_stdin, cmd_prefix('sleep 1 |'),
- omit_ways(['ghci']) ],
- compile_and_run, [''])
+test('hReady002', [cmd_prefix('sleep 1 |'), omit_ways(['ghci'])],
+ compile_and_run, [''])
test('hSeek001', normal, compile_and_run, [''])
test('hSeek002', normal, compile_and_run, ['-cpp'])
@@ -61,7 +60,7 @@ test('hSetBuffering004', set_stdin('hSetBuffering004.hs'), compile_and_run, ['']
test('ioeGetErrorString001', normal, compile_and_run, ['-cpp'])
test('ioeGetFileName001', normal, compile_and_run, ['-cpp'])
test('ioeGetHandle001', normal, compile_and_run, ['-cpp'])
-test('isEOF001', normal, compile_and_run, [''])
+test('isEOF001', extra_run_opts('</dev/null'), compile_and_run, [''])
test('misc001',
[extra_run_opts('misc001.hs misc001.out'),
diff --git a/libraries/unix b/libraries/unix
-Subproject 5b2e91a09190f1686ea195d25183abda1757d77
+Subproject 40820da5fb35c53aed53c211277c3e6077c1ddf
diff --git a/testsuite/driver/testglobals.py b/testsuite/driver/testglobals.py
index 23fd2f5d54..84921e43bc 100644
--- a/testsuite/driver/testglobals.py
+++ b/testsuite/driver/testglobals.py
@@ -183,9 +183,6 @@ class TestOptions:
# don't compare output
self.ignore_output = 0
- # don't give anything as stdin
- self.no_stdin = 0
-
# We sometimes want to modify the compiler_always_flags, so
# they are copied from config.compiler_always_flags when we
# make a new instance of TestOptions.
diff --git a/testsuite/driver/testlib.py b/testsuite/driver/testlib.py
index 44c2096907..af1fc66c38 100644
--- a/testsuite/driver/testlib.py
+++ b/testsuite/driver/testlib.py
@@ -175,9 +175,6 @@ def req_smp( name, opts ):
def ignore_output( name, opts ):
opts.ignore_output = 1
-def no_stdin( name, opts ):
- opts.no_stdin = 1
-
def combined_output( name, opts ):
opts.combined_output = True
@@ -1059,7 +1056,7 @@ def compile_and_run__( name, way, top_mod, extra_mods, extra_hc_opts ):
extra_hc_opts = result['hc_opts']
if way.startswith('ghci'): # interpreted...
- return interpreter_run( name, way, extra_hc_opts, 0, top_mod )
+ return interpreter_run(name, way, extra_hc_opts, top_mod)
else: # compiled...
result = simple_build(name, way, extra_hc_opts, 0, top_mod, 1, 1)
if badResult(result):
@@ -1149,7 +1146,10 @@ def extras_build( way, extra_mods, extra_hc_opts ):
def simple_build(name, way, extra_hc_opts, should_fail, top_mod, link, addsuf):
opts = getTestOpts()
- errname = add_suffix(name, 'comp.stderr')
+
+ # Redirect stdout and stderr to the same file
+ stdout = in_testdir(name, 'comp.stderr')
+ stderr = subprocess.STDOUT
if top_mod != '':
srcname = top_mod
@@ -1186,11 +1186,10 @@ def simple_build(name, way, extra_hc_opts, should_fail, top_mod, link, addsuf):
flags = ' '.join(get_compiler_flags() + config.way_flags[way])
cmd = ('cd "{opts.testdir}" && {cmd_prefix} '
- '{{compiler}} {to_do} {srcname} {flags} {extra_hc_opts} '
- '> {errname} 2>&1'
+ '{{compiler}} {to_do} {srcname} {flags} {extra_hc_opts}'
).format(**locals())
- exit_code = runCmd(cmd, opts.compile_timeout_multiplier)
+ exit_code = runCmd(cmd, None, stdout, stderr, opts.compile_timeout_multiplier)
if exit_code != 0 and not should_fail:
if config.verbose >= 1 and _expect_pass(way):
@@ -1225,17 +1224,18 @@ def simple_run(name, way, prog, extra_run_opts):
opts = getTestOpts()
# figure out what to use for stdin
- if opts.stdin != '':
- use_stdin = opts.stdin
+ if opts.stdin:
+ stdin = in_testdir(opts.stdin)
+ elif os.path.exists(in_testdir(name, 'stdin')):
+ stdin = in_testdir(name, 'stdin')
else:
- stdin_file = add_suffix(name, 'stdin')
- if os.path.exists(in_testdir(stdin_file)):
- use_stdin = stdin_file
- else:
- use_stdin = '/dev/null'
+ stdin = None
- run_stdout = add_suffix(name,'run.stdout')
- run_stderr = add_suffix(name,'run.stderr')
+ stdout = in_testdir(name, 'run.stdout')
+ if opts.combined_output:
+ stderr = subprocess.STDOUT
+ else:
+ stderr = in_testdir(name, 'run.stderr')
my_rts_flags = rts_flags(way)
@@ -1245,32 +1245,16 @@ def simple_run(name, way, prog, extra_run_opts):
else:
stats_args = ''
- if opts.no_stdin:
- stdin_comes_from = ''
- else:
- stdin_comes_from = ' <' + use_stdin
-
- if opts.combined_output:
- redirection = ' > {0} 2>&1'.format(run_stdout)
- redirection_append = ' >> {0} 2>&1'.format(run_stdout)
- else:
- redirection = ' > {0} 2> {1}'.format(run_stdout, run_stderr)
- redirection_append = ' >> {0} 2>> {1}'.format(run_stdout, run_stderr)
-
# Put extra_run_opts last: extra_run_opts('+RTS foo') should work.
- cmd = prog + stats_args + ' ' \
- + my_rts_flags + ' ' \
- + extra_run_opts + ' ' \
- + stdin_comes_from \
- + redirection
+ cmd = prog + stats_args + ' ' + my_rts_flags + ' ' + extra_run_opts
if opts.cmd_wrapper != None:
- cmd = opts.cmd_wrapper(cmd) + redirection_append
+ cmd = opts.cmd_wrapper(cmd)
cmd = 'cd "{opts.testdir}" && {cmd}'.format(**locals())
# run the command
- exit_code = runCmd(cmd, opts.run_timeout_multiplier)
+ exit_code = runCmd(cmd, stdin, stdout, stderr, opts.run_timeout_multiplier)
# check the exit code
if exit_code != opts.exit_code:
@@ -1305,73 +1289,60 @@ def rts_flags(way):
# -----------------------------------------------------------------------------
# Run a program in the interpreter and check its output
-def interpreter_run( name, way, extra_hc_opts, compile_only, top_mod ):
+def interpreter_run(name, way, extra_hc_opts, top_mod):
opts = getTestOpts()
- outname = add_suffix(name, 'interp.stdout')
- errname = add_suffix(name, 'interp.stderr')
+ stdout = in_testdir(name, 'interp.stdout')
+ stderr = in_testdir(name, 'interp.stderr')
+ script = in_testdir(name, 'genscript')
+
+ if opts.combined_output:
+ framework_fail(name, 'unsupported',
+ 'WAY=ghci and combined_output together is not supported')
if (top_mod == ''):
srcname = add_hs_lhs_suffix(name)
else:
srcname = top_mod
- scriptname = add_suffix(name, 'genscript')
- qscriptname = in_testdir(scriptname)
-
delimiter = '===== program output begins here\n'
- script = open(qscriptname, 'w')
- if not compile_only:
+ with open(script, 'w') as f:
# set the prog name and command-line args to match the compiled
# environment.
- script.write(':set prog ' + name + '\n')
- script.write(':set args ' + getTestOpts().extra_run_opts + '\n')
+ f.write(':set prog ' + name + '\n')
+ f.write(':set args ' + opts.extra_run_opts + '\n')
# Add marker lines to the stdout and stderr output files, so we
# can separate GHCi's output from the program's.
- script.write(':! echo ' + delimiter)
- script.write(':! echo 1>&2 ' + delimiter)
+ f.write(':! echo ' + delimiter)
+ f.write(':! echo 1>&2 ' + delimiter)
# Set stdout to be line-buffered to match the compiled environment.
- script.write('System.IO.hSetBuffering System.IO.stdout System.IO.LineBuffering\n')
+ f.write('System.IO.hSetBuffering System.IO.stdout System.IO.LineBuffering\n')
# wrapping in GHC.TopHandler.runIO ensures we get the same output
# in the event of an exception as for the compiled program.
- script.write('GHC.TopHandler.runIOFastExit Main.main Prelude.>> Prelude.return ()\n')
- script.close()
-
- # figure out what to use for stdin
- if getTestOpts().stdin != '':
- stdin_file = in_testdir(opts.stdin)
- else:
- stdin_file = in_testdir(name, 'stdin')
+ f.write('GHC.TopHandler.runIOFastExit Main.main Prelude.>> Prelude.return ()\n')
- if os.path.exists(stdin_file):
- os.system('cat "{0}" >> "{1}"'.format(stdin_file, qscriptname))
+ stdin = in_testdir(opts.stdin if opts.stdin else add_suffix(name, 'stdin'))
+ if os.path.exists(stdin):
+ os.system('cat "{0}" >> "{1}"'.format(stdin, script))
flags = ' '.join(get_compiler_flags() + config.way_flags[way])
- if getTestOpts().combined_output:
- redirection = ' > {0} 2>&1'.format(outname)
- redirection_append = ' >> {0} 2>&1'.format(outname)
- else:
- redirection = ' > {0} 2> {1}'.format(outname, errname)
- redirection_append = ' >> {0} 2>> {1}'.format(outname, errname)
-
- cmd = ('{{compiler}} {srcname} {flags} {extra_hc_opts} '
- '< {scriptname} {redirection}'
+ cmd = ('{{compiler}} {srcname} {flags} {extra_hc_opts}'
).format(**locals())
if getTestOpts().cmd_wrapper != None:
- cmd = getTestOpts().cmd_wrapper(cmd) + redirection_append;
+ cmd = opts.cmd_wrapper(cmd);
cmd = 'cd "{opts.testdir}" && {cmd}'.format(**locals())
- exit_code = runCmd(cmd, opts.run_timeout_multiplier)
+ exit_code = runCmd(cmd, script, stdout, stderr, opts.run_timeout_multiplier)
# split the stdout into compilation/program output
- split_file(in_testdir(outname), delimiter,
+ split_file(stdout, delimiter,
in_testdir(name, 'comp.stdout'),
in_testdir(name, 'run.stdout'))
- split_file(in_testdir(errname), delimiter,
+ split_file(stderr, delimiter,
in_testdir(name, 'comp.stderr'),
in_testdir(name, 'run.stderr'))
@@ -1784,19 +1755,35 @@ def if_verbose_dump( n, f ):
except:
print('')
-def runCmd(cmd, timeout_multiplier=1.0):
+def runCmd(cmd, stdin=None, stdout=None, stderr=None, timeout_multiplier=1.0):
timeout_prog = strip_quotes(config.timeout_prog)
timeout = str(int(ceil(config.timeout * timeout_multiplier)))
# Format cmd using config. Example: cmd='{hpc} report A.tix'
cmd = cmd.format(**config.__dict__)
- if_verbose( 3, cmd )
+ if_verbose(3, cmd + ('< ' + os.path.basename(stdin) if stdin else ''))
+
+ if stdin:
+ stdin = open(stdin, 'r')
+ if stdout:
+ stdout = open(stdout, 'w')
+ if stderr and stderr is not subprocess.STDOUT:
+ stderr = open(stderr, 'w')
# cmd is a complex command in Bourne-shell syntax
# e.g (cd . && 'C:/users/simonpj/HEAD/inplace/bin/ghc-stage2' ...etc)
# Hence it must ultimately be run by a Bourne shell. It's timeout's job
# to invoke the Bourne shell
- r = subprocess.call([timeout_prog, timeout, cmd])
+ r = subprocess.call([timeout_prog, timeout, cmd],
+ stdin=stdin, stdout=stdout, stderr=stderr)
+
+ if stdin:
+ stdin.close()
+ if stdout:
+ stdout.close()
+ if stderr and stderr is not subprocess.STDOUT:
+ stderr.close()
+
if r == 98:
# The python timeout program uses 98 to signal that ^C was pressed
stopNow()
diff --git a/testsuite/tests/ghc-e/should_run/Makefile b/testsuite/tests/ghc-e/should_run/Makefile
index c98b98ada7..29b4e9fef6 100644
--- a/testsuite/tests/ghc-e/should_run/Makefile
+++ b/testsuite/tests/ghc-e/should_run/Makefile
@@ -22,7 +22,7 @@ ghc-e006:
'$(TEST_HC)' $(TEST_HC_OPTS) -ignore-dot-ghci -e "data X = X deriving Show" -e "X"
T2228:
- '$(TEST_HC)' $(TEST_HC_OPTS) -ignore-dot-ghci -e ":main" T2228.hs
+ '$(TEST_HC)' $(TEST_HC_OPTS) -ignore-dot-ghci -e ":main" T2228.hs </dev/null
T2636:
'$(TEST_HC)' $(TEST_HC_OPTS) -ignore-dot-ghci -e ":main" T2636.hs; if [ "$?" != 0 ]; then true; else false; fi
diff --git a/testsuite/tests/rts/all.T b/testsuite/tests/rts/all.T
index 15f9806e3d..bfdf3182c1 100644
--- a/testsuite/tests/rts/all.T
+++ b/testsuite/tests/rts/all.T
@@ -306,7 +306,7 @@ test('linker_error3',
run_command,
['$MAKE -s --no-print-directory linker_error3'])
-test('T9839_01', [ no_stdin, ignore_output],
+test('T9839_01', ignore_output,
run_command,
['{compiler} -e 1 +RTS -T-s 2>&1 | \
grep "flag -T given an argument when none was expected: -T-s"'])