add option exec-env to set env variables during test execution
This commit is contained in:
parent
d2482fd763
commit
dfc548ddda
5 changed files with 69 additions and 34 deletions
|
@ -17,13 +17,16 @@ type test_props = {
|
||||||
// pretty-printed
|
// pretty-printed
|
||||||
pp_exact: option<str>,
|
pp_exact: option<str>,
|
||||||
// Modules from aux directory that should be compiled
|
// Modules from aux directory that should be compiled
|
||||||
aux_builds: [str]
|
aux_builds: [str],
|
||||||
|
// Environment settings to use during execution
|
||||||
|
exec_env: [(str,str)]
|
||||||
};
|
};
|
||||||
|
|
||||||
// Load any test directives embedded in the file
|
// Load any test directives embedded in the file
|
||||||
fn load_props(testfile: str) -> test_props {
|
fn load_props(testfile: str) -> test_props {
|
||||||
let mut error_patterns = [];
|
let mut error_patterns = [];
|
||||||
let mut aux_builds = [];
|
let mut aux_builds = [];
|
||||||
|
let mut exec_env = [];
|
||||||
let mut compile_flags = option::none;
|
let mut compile_flags = option::none;
|
||||||
let mut pp_exact = option::none;
|
let mut pp_exact = option::none;
|
||||||
iter_header(testfile) {|ln|
|
iter_header(testfile) {|ln|
|
||||||
|
@ -43,12 +46,17 @@ fn load_props(testfile: str) -> test_props {
|
||||||
option::iter(parse_aux_build(ln)) {|ab|
|
option::iter(parse_aux_build(ln)) {|ab|
|
||||||
aux_builds += [ab];
|
aux_builds += [ab];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
option::iter(parse_exec_env(ln)) {|ee|
|
||||||
|
exec_env += [ee];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
ret {
|
ret {
|
||||||
error_patterns: error_patterns,
|
error_patterns: error_patterns,
|
||||||
compile_flags: compile_flags,
|
compile_flags: compile_flags,
|
||||||
pp_exact: pp_exact,
|
pp_exact: pp_exact,
|
||||||
aux_builds: aux_builds
|
aux_builds: aux_builds,
|
||||||
|
exec_env: exec_env
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +105,18 @@ fn parse_compile_flags(line: str) -> option<str> {
|
||||||
parse_name_value_directive(line, "compile-flags")
|
parse_name_value_directive(line, "compile-flags")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_exec_env(line: str) -> option<(str, str)> {
|
||||||
|
parse_name_value_directive(line, "exec-env").map {|nv|
|
||||||
|
// nv is either FOO or FOO=BAR
|
||||||
|
let strs = str::splitn_char(nv, '=', 1u);
|
||||||
|
alt strs.len() {
|
||||||
|
1u { (strs[0], "") }
|
||||||
|
2u { (strs[0], strs[1]) }
|
||||||
|
n { fail #fmt["Expected 1 or 2 strings, not %u", n]; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_pp_exact(line: str, testfile: str) -> option<str> {
|
fn parse_pp_exact(line: str, testfile: str) -> option<str> {
|
||||||
alt parse_name_value_directive(line, "pp-exact") {
|
alt parse_name_value_directive(line, "pp-exact") {
|
||||||
option::some(s) { option::some(s) }
|
option::some(s) { option::some(s) }
|
||||||
|
|
|
@ -5,7 +5,7 @@ import libc::{c_int, pid_t};
|
||||||
export run;
|
export run;
|
||||||
|
|
||||||
#[cfg(target_os = "win32")]
|
#[cfg(target_os = "win32")]
|
||||||
fn target_env(lib_path: str, prog: str) -> option<[(str,str)]> {
|
fn target_env(lib_path: str, prog: str) -> [(str,str)] {
|
||||||
|
|
||||||
let env = os::env();
|
let env = os::env();
|
||||||
|
|
||||||
|
@ -17,25 +17,29 @@ fn target_env(lib_path: str, prog: str) -> option<[(str,str)]> {
|
||||||
if str::ends_with(prog, "rustc.exe") {
|
if str::ends_with(prog, "rustc.exe") {
|
||||||
env += [("RUST_THREADS", "1")]
|
env += [("RUST_THREADS", "1")]
|
||||||
}
|
}
|
||||||
ret some(env);
|
ret env;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
#[cfg(target_os = "freebsd")]
|
#[cfg(target_os = "freebsd")]
|
||||||
fn target_env(_lib_path: str, _prog: str) -> option<[(str,str)]> {
|
fn target_env(_lib_path: str, _prog: str) -> [(str,str)] {
|
||||||
none
|
[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn run(lib_path: str, prog: str, args: [str],
|
fn run(lib_path: str,
|
||||||
|
prog: str,
|
||||||
|
args: [str],
|
||||||
|
env: [(str, str)],
|
||||||
input: option<str>) -> {status: int, out: str, err: str} {
|
input: option<str>) -> {status: int, out: str, err: str} {
|
||||||
|
|
||||||
let pipe_in = os::pipe();
|
let pipe_in = os::pipe();
|
||||||
let pipe_out = os::pipe();
|
let pipe_out = os::pipe();
|
||||||
let pipe_err = os::pipe();
|
let pipe_err = os::pipe();
|
||||||
let pid = spawn_process(prog, args, target_env(lib_path, prog), none,
|
let pid = spawn_process(prog, args,
|
||||||
pipe_in.in, pipe_out.out, pipe_err.out);
|
some(env + target_env(lib_path, prog)),
|
||||||
|
none, pipe_in.in, pipe_out.out, pipe_err.out);
|
||||||
|
|
||||||
os::close(pipe_in.in);
|
os::close(pipe_in.in);
|
||||||
os::close(pipe_out.out);
|
os::close(pipe_out.out);
|
||||||
|
|
|
@ -81,7 +81,6 @@ fn run_rpass_test(config: config, props: test_props, testfile: str) {
|
||||||
|
|
||||||
procres = exec_compiled_test(config, props, testfile);
|
procres = exec_compiled_test(config, props, testfile);
|
||||||
|
|
||||||
|
|
||||||
if procres.status != 0 { fatal_procres("test run failed!", procres); }
|
if procres.status != 0 { fatal_procres("test run failed!", procres); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,8 +138,8 @@ fn run_pretty_test(config: config, props: test_props, testfile: str) {
|
||||||
ret;
|
ret;
|
||||||
|
|
||||||
fn print_source(config: config, testfile: str, src: str) -> procres {
|
fn print_source(config: config, testfile: str, src: str) -> procres {
|
||||||
compose_and_run(config, testfile, make_pp_args,
|
compose_and_run(config, testfile, make_pp_args(config, testfile),
|
||||||
config.compile_lib_path, option::some(src))
|
[], config.compile_lib_path, option::some(src))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_pp_args(config: config, _testfile: str) -> procargs {
|
fn make_pp_args(config: config, _testfile: str) -> procargs {
|
||||||
|
@ -172,7 +171,9 @@ actual:\n\
|
||||||
fn typecheck_source(config: config, props: test_props,
|
fn typecheck_source(config: config, props: test_props,
|
||||||
testfile: str, src: str) -> procres {
|
testfile: str, src: str) -> procres {
|
||||||
compose_and_run_compiler(
|
compose_and_run_compiler(
|
||||||
config, props, testfile, make_typecheck_args, option::some(src))
|
config, props, testfile,
|
||||||
|
make_typecheck_args(config, testfile),
|
||||||
|
option::some(src))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_typecheck_args(config: config, testfile: str) -> procargs {
|
fn make_typecheck_args(config: config, testfile: str) -> procargs {
|
||||||
|
@ -292,24 +293,26 @@ type procres = {status: int, stdout: str, stderr: str, cmdline: str};
|
||||||
fn compile_test(config: config, props: test_props,
|
fn compile_test(config: config, props: test_props,
|
||||||
testfile: str) -> procres {
|
testfile: str) -> procres {
|
||||||
let link_args = ["-L", aux_output_dir_name(config, testfile)];
|
let link_args = ["-L", aux_output_dir_name(config, testfile)];
|
||||||
compose_and_run_compiler(config, props, testfile,
|
compose_and_run_compiler(
|
||||||
make_compile_args(_, props, link_args,
|
config, props, testfile,
|
||||||
make_exe_name, _),
|
make_compile_args(config, props, link_args,
|
||||||
none)
|
make_exe_name, testfile),
|
||||||
|
none)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exec_compiled_test(config: config, props: test_props,
|
fn exec_compiled_test(config: config, props: test_props,
|
||||||
testfile: str) -> procres {
|
testfile: str) -> procres {
|
||||||
compose_and_run(config, testfile,
|
compose_and_run(config, testfile,
|
||||||
bind make_run_args(_, props, _),
|
make_run_args(config, props, testfile),
|
||||||
config.run_lib_path, option::none)
|
props.exec_env,
|
||||||
|
config.run_lib_path, option::none)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compose_and_run_compiler(
|
fn compose_and_run_compiler(
|
||||||
config: config,
|
config: config,
|
||||||
props: test_props,
|
props: test_props,
|
||||||
testfile: str,
|
testfile: str,
|
||||||
mk_args: fn(config: config, _testfile: str) -> procargs,
|
args: procargs,
|
||||||
input: option<str>) -> procres {
|
input: option<str>) -> procres {
|
||||||
|
|
||||||
if props.aux_builds.is_not_empty() {
|
if props.aux_builds.is_not_empty() {
|
||||||
|
@ -320,10 +323,10 @@ fn compose_and_run_compiler(
|
||||||
|
|
||||||
vec::iter(props.aux_builds) {|rel_ab|
|
vec::iter(props.aux_builds) {|rel_ab|
|
||||||
let abs_ab = path::connect(config.aux_base, rel_ab);
|
let abs_ab = path::connect(config.aux_base, rel_ab);
|
||||||
let mk_compile_args =
|
let aux_args =
|
||||||
make_compile_args(_, props, ["--lib"] + extra_link_args,
|
make_compile_args(config, props, ["--lib"] + extra_link_args,
|
||||||
bind make_lib_name(_, _, testfile), _);
|
bind make_lib_name(_, _, testfile), abs_ab);
|
||||||
let auxres = compose_and_run(config, abs_ab, mk_compile_args,
|
let auxres = compose_and_run(config, abs_ab, aux_args, [],
|
||||||
config.compile_lib_path, option::none);
|
config.compile_lib_path, option::none);
|
||||||
if auxres.status != 0 {
|
if auxres.status != 0 {
|
||||||
fatal_procres(
|
fatal_procres(
|
||||||
|
@ -332,7 +335,7 @@ fn compose_and_run_compiler(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compose_and_run(config, testfile, mk_args,
|
compose_and_run(config, testfile, args, [],
|
||||||
config.compile_lib_path, input)
|
config.compile_lib_path, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,11 +347,12 @@ fn ensure_dir(path: path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compose_and_run(config: config, testfile: str,
|
fn compose_and_run(config: config, testfile: str,
|
||||||
make_args: fn(config, str) -> procargs, lib_path: str,
|
procargs: procargs,
|
||||||
|
procenv: [(str, str)],
|
||||||
|
lib_path: str,
|
||||||
input: option<str>) -> procres {
|
input: option<str>) -> procres {
|
||||||
let procargs = make_args(config, testfile);
|
|
||||||
ret program_output(config, testfile, lib_path,
|
ret program_output(config, testfile, lib_path,
|
||||||
procargs.prog, procargs.args, input);
|
procargs.prog, procargs.args, procenv, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_compile_args(config: config, props: test_props, extras: [str],
|
fn make_compile_args(config: config, props: test_props, extras: [str],
|
||||||
|
@ -405,14 +409,15 @@ fn split_maybe_args(argstr: option<str>) -> [str] {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn program_output(config: config, testfile: str, lib_path: str, prog: str,
|
fn program_output(config: config, testfile: str, lib_path: str, prog: str,
|
||||||
args: [str], input: option<str>) -> procres {
|
args: [str], env: [(str, str)],
|
||||||
|
input: option<str>) -> procres {
|
||||||
let cmdline =
|
let cmdline =
|
||||||
{
|
{
|
||||||
let cmdline = make_cmdline(lib_path, prog, args);
|
let cmdline = make_cmdline(lib_path, prog, args);
|
||||||
logv(config, #fmt["executing %s", cmdline]);
|
logv(config, #fmt["executing %s", cmdline]);
|
||||||
cmdline
|
cmdline
|
||||||
};
|
};
|
||||||
let res = procsrv::run(lib_path, prog, args, input);
|
let res = procsrv::run(lib_path, prog, args, env, input);
|
||||||
dump_output(config, testfile, res.out, res.err);
|
dump_output(config, testfile, res.out, res.err);
|
||||||
ret {status: res.status,
|
ret {status: res.status,
|
||||||
stdout: res.out,
|
stdout: res.out,
|
||||||
|
|
|
@ -98,7 +98,7 @@ fn with_envp<T>(env: option<[(str,str)]>,
|
||||||
// On posixy systems we can pass a char** for envp, which is
|
// On posixy systems we can pass a char** for envp, which is
|
||||||
// a null-terminated array of "k=v\n" strings.
|
// a null-terminated array of "k=v\n" strings.
|
||||||
alt env {
|
alt env {
|
||||||
some (es) {
|
some(es) if !vec::is_empty(es) {
|
||||||
let mut tmps = [];
|
let mut tmps = [];
|
||||||
let mut ptrs = [];
|
let mut ptrs = [];
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ fn with_envp<T>(env: option<[(str,str)]>,
|
||||||
ptrs += [ptr::null()];
|
ptrs += [ptr::null()];
|
||||||
vec::as_buf(ptrs) { |p| cb(::unsafe::reinterpret_cast(p)) }
|
vec::as_buf(ptrs) { |p| cb(::unsafe::reinterpret_cast(p)) }
|
||||||
}
|
}
|
||||||
none {
|
_ {
|
||||||
cb(ptr::null())
|
cb(ptr::null())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ fn with_envp<T>(env: option<[(str,str)]>,
|
||||||
// rather a concatenation of null-terminated k=v\0 sequences, with a final
|
// rather a concatenation of null-terminated k=v\0 sequences, with a final
|
||||||
// \0 to terminate.
|
// \0 to terminate.
|
||||||
alt env {
|
alt env {
|
||||||
some (es) {
|
some(es) if !vec::is_empty(es) {
|
||||||
let mut blk : [u8] = [];
|
let mut blk : [u8] = [];
|
||||||
for vec::each(es) {|e|
|
for vec::each(es) {|e|
|
||||||
let (k,v) = e;
|
let (k,v) = e;
|
||||||
|
@ -136,7 +136,7 @@ fn with_envp<T>(env: option<[(str,str)]>,
|
||||||
blk += [0_u8];
|
blk += [0_u8];
|
||||||
vec::as_buf(blk) {|p| cb(::unsafe::reinterpret_cast(p)) }
|
vec::as_buf(blk) {|p| cb(::unsafe::reinterpret_cast(p)) }
|
||||||
}
|
}
|
||||||
none {
|
_ {
|
||||||
cb(ptr::null())
|
cb(ptr::null())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
6
src/test/run-pass/exec-env.rs
Normal file
6
src/test/run-pass/exec-env.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
// xfail-fast (exec-env not supported in fast mode)
|
||||||
|
// exec-env:TEST_EXEC_ENV=22
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert os::getenv("TEST_EXEC_ENV") == some("22");
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue