Skip to content

Commit 399a425

Browse files
committed
auto merge of #9799 : catamorphism/rust/rustpkg-exitcodes, r=catamorphism,metajack
r? @metajack When I started writing the rustpkg tests, task failure didn't set the exit code properly. But bblum's work from July fixed that. Hooray! I just didn't know about it till now. So, now rustpkg uses exit codes in a more conventional way, and some of the tests are simpler. The bigger issue will be to make task failure propagate the error message. Right now, rustpkg does most of the work in separate tasks, which means if a task fails, rustpkg can't distinguish between different types of failure (see #3408)
2 parents 80878ff + 7472bae commit 399a425

File tree

4 files changed

+72
-27
lines changed

4 files changed

+72
-27
lines changed

src/librustpkg/context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,11 @@ impl RustcFlags {
210210
}
211211

212212
/// Returns true if any of the flags given are incompatible with the cmd
213-
pub fn flags_ok_for_cmd(flags: &RustcFlags,
213+
pub fn flags_forbidden_for_cmd(flags: &RustcFlags,
214214
cfgs: &[~str],
215215
cmd: &str, user_supplied_opt_level: bool) -> bool {
216216
let complain = |s| {
217-
println!("The {} option can only be used with the build command:
217+
println!("The {} option can only be used with the `build` command:
218218
rustpkg [options..] build {} [package-ID]", s, s);
219219
};
220220

src/librustpkg/exit_codes.rs

+3
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@
99
// except according to those terms.
1010

1111
pub static COPY_FAILED_CODE: int = 65;
12+
pub static BAD_FLAG_CODE: int = 67;
13+
pub static NONEXISTENT_PACKAGE_CODE: int = 68;
14+

src/librustpkg/rustpkg.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use package_source::PkgSrc;
5050
use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench, Tests};
5151
// use workcache_support::{discover_outputs, digest_only_date};
5252
use workcache_support::digest_only_date;
53-
use exit_codes::COPY_FAILED_CODE;
53+
use exit_codes::{COPY_FAILED_CODE, BAD_FLAG_CODE};
5454

5555
pub mod api;
5656
mod conditions;
@@ -701,7 +701,7 @@ pub fn main_args(args: &[~str]) -> int {
701701
return 1;
702702
}
703703
};
704-
let mut help = matches.opt_present("h") ||
704+
let help = matches.opt_present("h") ||
705705
matches.opt_present("help");
706706
let no_link = matches.opt_present("no-link");
707707
let no_trans = matches.opt_present("no-trans");
@@ -798,8 +798,11 @@ pub fn main_args(args: &[~str]) -> int {
798798
return 0;
799799
}
800800
Some(cmd) => {
801-
help |= context::flags_ok_for_cmd(&rustc_flags, cfgs, *cmd, user_supplied_opt_level);
802-
if help {
801+
let bad_option = context::flags_forbidden_for_cmd(&rustc_flags,
802+
cfgs,
803+
*cmd,
804+
user_supplied_opt_level);
805+
if help || bad_option {
803806
match *cmd {
804807
~"build" => usage::build(),
805808
~"clean" => usage::clean(),
@@ -814,7 +817,12 @@ pub fn main_args(args: &[~str]) -> int {
814817
~"unprefer" => usage::unprefer(),
815818
_ => usage::general()
816819
};
817-
return 0;
820+
if bad_option {
821+
return BAD_FLAG_CODE;
822+
}
823+
else {
824+
return 0;
825+
}
818826
} else {
819827
cmd
820828
}

src/librustpkg/tests.rs

+54-20
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use syntax::diagnostic;
3636
use target::*;
3737
use package_source::PkgSrc;
3838
use source_control::{CheckedOutSources, DirToUse, safe_git_clone};
39+
use exit_codes::{BAD_FLAG_CODE, COPY_FAILED_CODE};
3940
use util::datestamp;
4041

4142
fn fake_ctxt(sysroot: Path, workspace: &Path) -> BuildContext {
@@ -244,14 +245,26 @@ fn rustpkg_exec() -> Path {
244245
fn command_line_test(args: &[~str], cwd: &Path) -> ProcessOutput {
245246
match command_line_test_with_env(args, cwd, None) {
246247
Success(r) => r,
247-
_ => fail2!("Command line test failed")
248+
Fail(error) => fail2!("Command line test failed with error {}", error)
248249
}
249250
}
250251

251252
fn command_line_test_partial(args: &[~str], cwd: &Path) -> ProcessResult {
252253
command_line_test_with_env(args, cwd, None)
253254
}
254255

256+
fn command_line_test_expect_fail(args: &[~str],
257+
cwd: &Path,
258+
env: Option<~[(~str, ~str)]>,
259+
expected_exitcode: int) {
260+
match command_line_test_with_env(args, cwd, env) {
261+
Success(_) => fail2!("Should have failed with {}, but it succeeded", expected_exitcode),
262+
Fail(error) if error == expected_exitcode => (), // ok
263+
Fail(other) => fail2!("Expected to fail with {}, but failed with {} instead",
264+
expected_exitcode, other)
265+
}
266+
}
267+
255268
enum ProcessResult {
256269
Success(ProcessOutput),
257270
Fail(int) // exit code
@@ -1448,11 +1461,11 @@ fn compile_flag_fail() {
14481461
let p_id = PkgId::new("foo");
14491462
let workspace = create_local_package(&p_id);
14501463
let workspace = workspace.path();
1451-
command_line_test([test_sysroot().to_str(),
1464+
command_line_test_expect_fail([test_sysroot().to_str(),
14521465
~"install",
14531466
~"--no-link",
14541467
~"foo"],
1455-
workspace);
1468+
workspace, None, BAD_FLAG_CODE);
14561469
assert!(!built_executable_exists(workspace, "foo"));
14571470
assert!(!object_file_exists(workspace, "foo"));
14581471
}
@@ -1488,14 +1501,11 @@ fn notrans_flag_fail() {
14881501
let flags_to_test = [~"--no-trans", ~"--parse-only",
14891502
~"--pretty", ~"-S"];
14901503
for flag in flags_to_test.iter() {
1491-
command_line_test([test_sysroot().to_str(),
1504+
command_line_test_expect_fail([test_sysroot().to_str(),
14921505
~"install",
14931506
flag.clone(),
14941507
~"foo"],
1495-
workspace);
1496-
// Ideally we'd test that rustpkg actually fails, but
1497-
// since task failure doesn't set the exit code properly,
1498-
// we can't tell
1508+
workspace, None, BAD_FLAG_CODE);
14991509
assert!(!built_executable_exists(workspace, "foo"));
15001510
assert!(!object_file_exists(workspace, "foo"));
15011511
assert!(!lib_exists(workspace, &Path("foo"), NoVersion));
@@ -1522,11 +1532,11 @@ fn dash_S_fail() {
15221532
let p_id = PkgId::new("foo");
15231533
let workspace = create_local_package(&p_id);
15241534
let workspace = workspace.path();
1525-
command_line_test([test_sysroot().to_str(),
1535+
command_line_test_expect_fail([test_sysroot().to_str(),
15261536
~"install",
15271537
~"-S",
15281538
~"foo"],
1529-
workspace);
1539+
workspace, None, BAD_FLAG_CODE);
15301540
assert!(!built_executable_exists(workspace, "foo"));
15311541
assert!(!object_file_exists(workspace, "foo"));
15321542
assert!(!assembly_file_exists(workspace, "foo"));
@@ -1587,11 +1597,13 @@ fn test_emit_llvm_S_fail() {
15871597
let p_id = PkgId::new("foo");
15881598
let workspace = create_local_package(&p_id);
15891599
let workspace = workspace.path();
1590-
command_line_test([test_sysroot().to_str(),
1600+
command_line_test_expect_fail([test_sysroot().to_str(),
15911601
~"install",
15921602
~"-S", ~"--emit-llvm",
15931603
~"foo"],
1594-
workspace);
1604+
workspace,
1605+
None,
1606+
BAD_FLAG_CODE);
15951607
assert!(!built_executable_exists(workspace, "foo"));
15961608
assert!(!object_file_exists(workspace, "foo"));
15971609
assert!(!llvm_assembly_file_exists(workspace, "foo"));
@@ -1620,11 +1632,13 @@ fn test_emit_llvm_fail() {
16201632
let p_id = PkgId::new("foo");
16211633
let workspace = create_local_package(&p_id);
16221634
let workspace = workspace.path();
1623-
command_line_test([test_sysroot().to_str(),
1635+
command_line_test_expect_fail([test_sysroot().to_str(),
16241636
~"install",
16251637
~"--emit-llvm",
16261638
~"foo"],
1627-
workspace);
1639+
workspace,
1640+
None,
1641+
BAD_FLAG_CODE);
16281642
assert!(!built_executable_exists(workspace, "foo"));
16291643
assert!(!object_file_exists(workspace, "foo"));
16301644
assert!(!llvm_bitcode_file_exists(workspace, "foo"));
@@ -1665,11 +1679,10 @@ fn test_build_install_flags_fail() {
16651679
~[~"--target", host_triple()],
16661680
~[~"--target-cpu", ~"generic"],
16671681
~[~"-Z", ~"--time-passes"]];
1682+
let cwd = os::getcwd();
16681683
for flag in forbidden.iter() {
1669-
let output = command_line_test_output([test_sysroot().to_str(),
1670-
~"list"] + *flag);
1671-
assert!(output.len() > 1);
1672-
assert!(output[1].find_str("can only be used with").is_some());
1684+
command_line_test_expect_fail([test_sysroot().to_str(),
1685+
~"list"] + *flag, &cwd, None, BAD_FLAG_CODE);
16731686
}
16741687
}
16751688

@@ -1686,6 +1699,7 @@ fn test_optimized_build() {
16861699
assert!(built_executable_exists(workspace, "foo"));
16871700
}
16881701

1702+
#[test]
16891703
fn pkgid_pointing_to_subdir() {
16901704
// The actual repo is mockgithub.com/mozilla/some_repo
16911705
// rustpkg should recognize that and treat the part after some_repo/ as a subdir
@@ -1717,6 +1731,7 @@ fn pkgid_pointing_to_subdir() {
17171731
assert_executable_exists(workspace, "testpkg");
17181732
}
17191733
1734+
#[test]
17201735
fn test_recursive_deps() {
17211736
let a_id = PkgId::new("a");
17221737
let b_id = PkgId::new("b");
@@ -1762,6 +1777,7 @@ fn test_install_to_rust_path() {
17621777
assert!(!executable_exists(second_workspace, "foo"));
17631778
}
17641779
1780+
#[test]
17651781
fn test_target_specific_build_dir() {
17661782
let p_id = PkgId::new("foo");
17671783
let workspace = create_local_package(&p_id);
@@ -1870,8 +1886,9 @@ fn correct_package_name_with_rust_path_hack() {
18701886
let rust_path = Some(~[(~"RUST_PATH", format!("{}:{}", dest_workspace.to_str(),
18711887
foo_workspace.push_many(["src", "foo-0.1"]).to_str()))]);
18721888
// bar doesn't exist, but we want to make sure rustpkg doesn't think foo is bar
1873-
command_line_test_with_env([~"install", ~"--rust-path-hack", ~"bar"],
1874-
dest_workspace, rust_path);
1889+
command_line_test_expect_fail([~"install", ~"--rust-path-hack", ~"bar"],
1890+
// FIXME #3408: Should be NONEXISTENT_PACKAGE_CODE
1891+
dest_workspace, rust_path, COPY_FAILED_CODE);
18751892
assert!(!executable_exists(dest_workspace, "bar"));
18761893
assert!(!lib_exists(dest_workspace, &bar_id.path.clone(), bar_id.version.clone()));
18771894
assert!(!executable_exists(dest_workspace, "foo"));
@@ -2050,6 +2067,23 @@ fn test_7402() {
20502067
assert_executable_exists(dest_workspace, "foo");
20512068
}
20522069
2070+
#[test]
2071+
fn test_compile_error() {
2072+
let foo_id = PkgId::new("foo");
2073+
let foo_workspace = create_local_package(&foo_id);
2074+
let foo_workspace = foo_workspace.path();
2075+
let main_crate = foo_workspace.push_many(["src", "foo-0.1", "main.rs"]);
2076+
// Write something bogus
2077+
writeFile(&main_crate, "pub fn main() { if 42 != ~\"the answer\" { fail!(); } }");
2078+
let result = command_line_test_partial([~"build", ~"foo"], foo_workspace);
2079+
match result {
2080+
Success(*) => fail2!("Failed by succeeding!"), // should be a compile error
2081+
Fail(status) => {
2082+
debug2!("Failed with status {:?}... that's good, right?", status);
2083+
}
2084+
}
2085+
}
2086+
20532087
/// Returns true if p exists and is executable
20542088
fn is_executable(p: &Path) -> bool {
20552089
use std::libc::consts::os::posix88::{S_IXUSR};

0 commit comments

Comments
 (0)