just/src/integration.rs

630 lines
8.7 KiB
Rust
Raw Normal View History

2016-10-28 15:25:59 -07:00
extern crate tempdir;
extern crate brev;
2016-10-31 21:53:31 -07:00
extern crate regex;
2016-10-28 15:25:59 -07:00
use tempdir::TempDir;
2016-10-28 19:38:03 -07:00
use super::std::process::Command;
2016-10-28 15:25:59 -07:00
fn integration_test(
args: &[&str],
justfile: &str,
expected_status: i32,
expected_stdout: &str,
expected_stderr: &str,
) {
2016-10-30 16:15:18 -07:00
let tmp = TempDir::new("just-integration")
2016-10-28 15:25:59 -07:00
.unwrap_or_else(|err| panic!("tmpdir: failed to create temporary directory: {}", err));
let mut path = tmp.path().to_path_buf();
path.push("justfile");
brev::dump(path, justfile);
2016-10-28 19:38:03 -07:00
let mut binary = super::std::env::current_dir().unwrap();
binary.push("./target/debug/just");
2016-10-28 15:25:59 -07:00
let output = Command::new(binary)
.current_dir(tmp.path())
.args(args)
.output()
.expect("just invocation failed");
2016-10-28 15:25:59 -07:00
let mut failure = false;
let status = output.status.code().unwrap();
if status != expected_status {
println!("bad status: {} != {}", status, expected_status);
failure = true;
}
2016-10-28 19:38:03 -07:00
let stdout = super::std::str::from_utf8(&output.stdout).unwrap();
2016-10-28 15:25:59 -07:00
if stdout != expected_stdout {
2016-10-28 19:38:03 -07:00
println!("bad stdout:\ngot:\n{}\n\nexpected:\n{}", stdout, expected_stdout);
2016-10-28 15:25:59 -07:00
failure = true;
}
2016-10-28 19:38:03 -07:00
let stderr = super::std::str::from_utf8(&output.stderr).unwrap();
2016-10-28 15:25:59 -07:00
if stderr != expected_stderr {
println!("bad stderr:\ngot:\n{}\n\nexpected:\n{}", stderr, expected_stderr);
2016-10-28 15:25:59 -07:00
failure = true;
}
if failure {
panic!("test failed");
}
}
#[test]
2016-10-28 15:59:50 -07:00
fn default() {
2016-10-28 15:25:59 -07:00
integration_test(
&[],
2016-10-28 15:59:50 -07:00
"default:\n echo hello\nother: \n echo bar",
2016-10-28 15:25:59 -07:00
0,
"hello\n",
"echo hello\n",
)
}
2016-10-28 15:34:01 -07:00
#[test]
fn quiet() {
integration_test(
&[],
"default:\n @echo hello",
0,
"hello\n",
"",
)
}
#[test]
fn order() {
let text = "
b: a
echo b
@mv a b
a:
echo a
@touch F
@touch a
d: c
echo d
@rm c
c: b
echo c
@mv b c";
integration_test(
&["a", "d"],
text,
0,
"a\nb\nc\nd\n",
"echo a\necho b\necho c\necho d\n",
);
}
2016-10-28 15:59:50 -07:00
#[test]
fn list() {
let text =
"b: a
a:
d: c
c: b";
integration_test(
&["--list"],
text,
0,
"a b c d\n",
"",
);
}
#[test]
fn select() {
let text =
"b:
@echo b
a:
@echo a
d:
@echo d
c:
@echo c";
integration_test(
&["d", "c"],
text,
0,
"d\nc\n",
"",
);
}
#[test]
fn print() {
let text =
"b:
echo b
a:
echo a
d:
echo d
c:
echo c";
integration_test(
&["d", "c"],
text,
0,
"d\nc\n",
"echo d\necho c\n",
);
}
#[test]
fn show() {
let text =
r#"hello = "foo"
bar = hello + hello
recipe:
echo {{hello + "bar" + bar}}"#;
integration_test(
&["--show", "recipe"],
text,
0,
r#"recipe:
echo {{hello + "bar" + bar}}
"#,
"",
);
}
2016-10-29 21:51:39 -07:00
/*
2016-10-28 19:38:03 -07:00
#[test]
fn debug() {
let text =
r#"hello = "foo"
bar = hello + hello
recipe:
echo {{hello + "bar" + bar}}"#;
integration_test(
&["--debug"],
text,
0,
r#"bar = hello + hello # "foofoo"
hello = "foo" # "foo"
recipe:
echo {{hello + "bar" + bar # "foobarfoofoo"}}
"#,
"",
);
}
2016-10-29 21:51:39 -07:00
*/
2016-10-28 19:38:03 -07:00
2016-10-28 15:59:50 -07:00
#[test]
fn status_passthrough() {
2016-10-28 15:59:50 -07:00
let text =
"
recipe:
@exit 100";
2016-10-28 15:59:50 -07:00
integration_test(
&[],
text,
100,
"",
"Recipe \"recipe\" failed with exit code 100\n",
);
}
2016-10-28 20:34:25 -07:00
#[test]
fn error() {
integration_test(
&[],
"bar:\nhello:\nfoo: bar baaaaaaaz hello",
255,
"",
2016-10-28 20:40:16 -07:00
"error: recipe `foo` has unknown dependency `baaaaaaaz`
2016-10-28 20:34:25 -07:00
|
3 | foo: bar baaaaaaaz hello
| ^^^^^^^^^
",
);
}
#[test]
fn backtick_success() {
integration_test(
&[],
"a = `printf Hello,`\nbar:\n printf '{{a + `printf ' world!'`}}'",
0,
"Hello, world!",
"printf 'Hello, world!'\n",
);
}
#[test]
fn backtick_trimming() {
integration_test(
&[],
"a = `echo Hello,`\nbar:\n echo '{{a + `echo ' world!'`}}'",
0,
"Hello, world!\n",
"echo 'Hello, world!'\n",
);
}
2016-10-30 01:27:05 -07:00
#[test]
fn backtick_code_assignment() {
integration_test(
&[],
"b = a\na = `exit 100`\nbar:\n echo '{{`exit 200`}}'",
2016-10-30 01:27:05 -07:00
100,
"",
"backtick failed with exit code 100
|
2 | a = `exit 100`
| ^^^^^^^^^^
2016-10-30 01:27:05 -07:00
",
);
}
#[test]
fn backtick_code_interpolation() {
integration_test(
&[],
"b = a\na = `echo hello`\nbar:\n echo '{{`exit 200`}}'",
2016-10-30 01:27:05 -07:00
200,
"",
"backtick failed with exit code 200
|
4 | echo '{{`exit 200`}}'
| ^^^^^^^^^^
2016-10-30 01:27:05 -07:00
",
);
}
#[test]
fn shebang_backtick_failure() {
integration_test(
&[],
"foo:
#!/bin/sh
echo hello
echo {{`exit 123`}}",
123,
"",
"backtick failed with exit code 123
|
4 | echo {{`exit 123`}}
| ^^^^^^^^^^
",
);
}
#[test]
fn command_backtick_failure() {
integration_test(
&[],
"foo:
echo hello
echo {{`exit 123`}}",
123,
"hello\n",
"echo hello\nbacktick failed with exit code 123
|
3 | echo {{`exit 123`}}
| ^^^^^^^^^^
",
);
}
#[test]
fn assignment_backtick_failure() {
integration_test(
&[],
"foo:
echo hello
echo {{`exit 111`}}
a = `exit 222`",
222,
"",
"backtick failed with exit code 222
|
4 | a = `exit 222`
| ^^^^^^^^^^
",
);
}
2016-10-30 03:08:28 -07:00
#[test]
fn unknown_override_options() {
integration_test(
&["--set", "foo", "bar", "a", "b", "--set", "baz", "bob", "--set", "a", "b"],
"foo:
echo hello
echo {{`exit 111`}}
a = `exit 222`",
255,
"",
"baz and foo set on the command line but not present in justfile\n",
);
}
#[test]
fn unknown_override_args() {
integration_test(
&["foo=bar", "baz=bob", "a=b", "a", "b"],
"foo:
echo hello
echo {{`exit 111`}}
a = `exit 222`",
255,
"",
"baz and foo set on the command line but not present in justfile\n",
);
}
#[test]
fn overrides_first() {
integration_test(
&["foo=bar", "a=b", "recipe", "baz=bar"],
r#"
foo = "foo"
a = "a"
baz = "baz"
recipe arg:
echo arg={{arg}}
echo {{foo + a + baz}}"#,
0,
"arg=baz=bar\nbarbbaz\n",
"echo arg=baz=bar\necho barbbaz\n",
);
}
2016-10-30 13:14:39 -07:00
// shebangs are printed
#[test]
fn dry_run() {
integration_test(
&["--dry-run", "shebang", "command"],
r#"
var = `echo stderr 1>&2; echo backtick`
command:
@touch /this/is/not/a/file
{{var}}
echo {{`echo command interpolation`}}
shebang:
#!/bin/sh
touch /this/is/not/a/file
{{var}}
echo {{`echo shebang interpolation`}}"#,
0,
"",
"stderr
#!/bin/sh
touch /this/is/not/a/file
backtick
echo shebang interpolation
touch /this/is/not/a/file
backtick
echo command interpolation
",
);
}
#[test]
fn evaluate() {
integration_test(
&["--evaluate"],
r#"
foo = "a\t"
baz = "c"
bar = "b\t"
abc = foo + bar + baz
wut:
touch /this/is/not/a/file
"#,
0,
r#"abc = "a b c"
bar = "b "
baz = "c"
foo = "a "
"#,
"",
);
}
2016-10-30 16:15:18 -07:00
#[test]
fn export_success() {
integration_test(
&[],
r#"
export foo = "a"
baz = "c"
export bar = "b"
export abc = foo + bar + baz
wut:
echo $foo $bar $abc
"#,
0,
"a b abc\n",
"echo $foo $bar $abc\n",
);
}
#[test]
fn export_shebang() {
integration_test(
&[],
r#"
export foo = "a"
baz = "c"
export bar = "b"
export abc = foo + bar + baz
wut:
#!/bin/sh
echo $foo $bar $abc
"#,
0,
"a b abc\n",
"",
);
}
#[test]
fn export_recipe_backtick() {
integration_test(
&[],
r#"
export exported_variable = "A-IS-A"
recipe:
echo {{`echo recipe $exported_variable`}}
"#,
0,
"recipe A-IS-A\n",
"echo recipe A-IS-A\n",
);
}
2016-10-30 16:56:22 -07:00
#[test]
fn raw_string() {
integration_test(
&[],
r#"
export exported_variable = '\\\\\\"'
recipe:
echo {{`echo recipe $exported_variable`}}
"#,
0,
"recipe \\\"\n",
"echo recipe \\\\\\\"\n",
);
}
2016-10-31 21:53:31 -07:00
#[test]
fn line_error_spacing() {
integration_test(
&[],
r#"
???
"#,
255,
"",
"error: unknown start of token:
|
10 | ???
| ^
",
);
}
#[test]
fn quiet_flag_no_stdout() {
integration_test(
&["--quiet"],
r#"
default:
@echo hello
"#,
0,
"",
"",
);
}
#[test]
fn quiet_flag_no_stderr() {
integration_test(
&["--quiet"],
r#"
default:
@echo hello 1>&2
"#,
0,
"",
"",
);
}
#[test]
fn quiet_flag_no_command_echoing() {
integration_test(
&["--quiet"],
r#"
default:
exit
"#,
0,
"",
"",
);
}
#[test]
fn quiet_flag_no_error_messages() {
integration_test(
&["--quiet"],
r#"
default:
exit 100
"#,
100,
"",
"",
);
}
#[test]
fn quiet_flag_no_assignment_backtick_stderr() {
integration_test(
&["--quiet"],
r#"
a = `echo hello 1>&2`
default:
exit 100
"#,
100,
"",
"",
);
}
#[test]
fn quiet_flag_no_interpolation_backtick_stderr() {
integration_test(
&["--quiet"],
r#"
default:
echo `echo hello 1>&2`
exit 100
"#,
100,
"",
"",
);
}
#[test]
fn quiet_flag_or_dry_run_flag() {
integration_test(
&["--quiet", "--dry-run"],
r#""#,
255,
"",
"--dry-run and --quiet may not be used together\n",
);
}