auto merge of #9549 : catamorphism/rust/rustpkg-test-command, r=catamorphism,metajack
r? @metajack Towards #7401
This commit is contained in:
commit
e699d914cd
|
@ -246,13 +246,17 @@ impl PkgSrc {
|
||||||
/// Infers crates to build. Called only in the case where there
|
/// Infers crates to build. Called only in the case where there
|
||||||
/// is no custom build logic
|
/// is no custom build logic
|
||||||
pub fn find_crates(&mut self) {
|
pub fn find_crates(&mut self) {
|
||||||
|
self.find_crates_with_filter(|_| true);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_crates_with_filter(&mut self, filter: &fn(&str) -> bool) {
|
||||||
use conditions::missing_pkg_files::cond;
|
use conditions::missing_pkg_files::cond;
|
||||||
|
|
||||||
let prefix = self.start_dir.components.len();
|
let prefix = self.start_dir.components.len();
|
||||||
debug!("Matching against %s", self.id.short_name);
|
debug!("Matching against %s", self.id.short_name);
|
||||||
do os::walk_dir(&self.start_dir) |pth| {
|
do os::walk_dir(&self.start_dir) |pth| {
|
||||||
let maybe_known_crate_set = match pth.filename() {
|
let maybe_known_crate_set = match pth.filename() {
|
||||||
Some(filename) => match filename {
|
Some(filename) if filter(filename) => match filename {
|
||||||
"lib.rs" => Some(&mut self.libs),
|
"lib.rs" => Some(&mut self.libs),
|
||||||
"main.rs" => Some(&mut self.mains),
|
"main.rs" => Some(&mut self.mains),
|
||||||
"test.rs" => Some(&mut self.tests),
|
"test.rs" => Some(&mut self.tests),
|
||||||
|
|
|
@ -33,7 +33,7 @@ use extra::{getopts};
|
||||||
use syntax::{ast, diagnostic};
|
use syntax::{ast, diagnostic};
|
||||||
use util::*;
|
use util::*;
|
||||||
use messages::{error, warn, note};
|
use messages::{error, warn, note};
|
||||||
use path_util::build_pkg_id_in_workspace;
|
use path_util::{build_pkg_id_in_workspace, built_test_in_workspace};
|
||||||
use path_util::{U_RWX, in_rust_path};
|
use path_util::{U_RWX, in_rust_path};
|
||||||
use path_util::{built_executable_in_workspace, built_library_in_workspace, default_workspace};
|
use path_util::{built_executable_in_workspace, built_library_in_workspace, default_workspace};
|
||||||
use path_util::{target_executable_in_workspace, target_library_in_workspace};
|
use path_util::{target_executable_in_workspace, target_library_in_workspace};
|
||||||
|
@ -44,7 +44,7 @@ use context::{Context, BuildContext,
|
||||||
LLVMAssemble, LLVMCompileBitcode};
|
LLVMAssemble, LLVMCompileBitcode};
|
||||||
use package_id::PkgId;
|
use package_id::PkgId;
|
||||||
use package_source::PkgSrc;
|
use package_source::PkgSrc;
|
||||||
use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench};
|
use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench, Tests};
|
||||||
// use workcache_support::{discover_outputs, digest_only_date};
|
// use workcache_support::{discover_outputs, digest_only_date};
|
||||||
use workcache_support::digest_only_date;
|
use workcache_support::digest_only_date;
|
||||||
use exit_codes::COPY_FAILED_CODE;
|
use exit_codes::COPY_FAILED_CODE;
|
||||||
|
@ -177,6 +177,8 @@ impl<'self> PkgScript<'self> {
|
||||||
pub trait CtxMethods {
|
pub trait CtxMethods {
|
||||||
fn run(&self, cmd: &str, args: ~[~str]);
|
fn run(&self, cmd: &str, args: ~[~str]);
|
||||||
fn do_cmd(&self, _cmd: &str, _pkgname: &str);
|
fn do_cmd(&self, _cmd: &str, _pkgname: &str);
|
||||||
|
/// Returns a pair of the selected package ID, and the destination workspace
|
||||||
|
fn build_args(&self, args: ~[~str], what: &WhatToBuild) -> Option<(PkgId, Path)>;
|
||||||
/// Returns the destination workspace
|
/// Returns the destination workspace
|
||||||
fn build(&self, pkg_src: &mut PkgSrc, what: &WhatToBuild) -> Path;
|
fn build(&self, pkg_src: &mut PkgSrc, what: &WhatToBuild) -> Path;
|
||||||
fn clean(&self, workspace: &Path, id: &PkgId);
|
fn clean(&self, workspace: &Path, id: &PkgId);
|
||||||
|
@ -190,43 +192,53 @@ pub trait CtxMethods {
|
||||||
target_workspace: &Path,
|
target_workspace: &Path,
|
||||||
id: &PkgId) -> ~[~str];
|
id: &PkgId) -> ~[~str];
|
||||||
fn prefer(&self, _id: &str, _vers: Option<~str>);
|
fn prefer(&self, _id: &str, _vers: Option<~str>);
|
||||||
fn test(&self);
|
fn test(&self, id: &PkgId, workspace: &Path);
|
||||||
fn uninstall(&self, _id: &str, _vers: Option<~str>);
|
fn uninstall(&self, _id: &str, _vers: Option<~str>);
|
||||||
fn unprefer(&self, _id: &str, _vers: Option<~str>);
|
fn unprefer(&self, _id: &str, _vers: Option<~str>);
|
||||||
fn init(&self);
|
fn init(&self);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CtxMethods for BuildContext {
|
impl CtxMethods for BuildContext {
|
||||||
|
fn build_args(&self, args: ~[~str], what: &WhatToBuild) -> Option<(PkgId, Path)> {
|
||||||
|
if args.len() < 1 {
|
||||||
|
match cwd_to_workspace() {
|
||||||
|
None if self.context.use_rust_path_hack => {
|
||||||
|
let cwd = os::getcwd();
|
||||||
|
let pkgid = PkgId::new(cwd.components[cwd.components.len() - 1]);
|
||||||
|
let mut pkg_src = PkgSrc::new(cwd, true, pkgid);
|
||||||
|
let dest_ws = self.build(&mut pkg_src, what);
|
||||||
|
Some((pkg_src.id, dest_ws))
|
||||||
|
}
|
||||||
|
None => { usage::build(); None }
|
||||||
|
Some((ws, pkgid)) => {
|
||||||
|
let mut pkg_src = PkgSrc::new(ws, false, pkgid);
|
||||||
|
let dest_ws = self.build(&mut pkg_src, what);
|
||||||
|
Some((pkg_src.id, dest_ws))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The package id is presumed to be the first command-line
|
||||||
|
// argument
|
||||||
|
let pkgid = PkgId::new(args[0].clone());
|
||||||
|
let mut dest_ws = None;
|
||||||
|
do each_pkg_parent_workspace(&self.context, &pkgid) |workspace| {
|
||||||
|
debug!("found pkg %s in workspace %s, trying to build",
|
||||||
|
pkgid.to_str(), workspace.to_str());
|
||||||
|
let mut pkg_src = PkgSrc::new(workspace.clone(), false, pkgid.clone());
|
||||||
|
dest_ws = Some(self.build(&mut pkg_src, what));
|
||||||
|
true
|
||||||
|
};
|
||||||
|
assert!(dest_ws.is_some());
|
||||||
|
// n.b. If this builds multiple packages, it only returns the workspace for
|
||||||
|
// the last one. The whole building-multiple-packages-with-the-same-ID is weird
|
||||||
|
// anyway and there are no tests for it, so maybe take it out
|
||||||
|
Some((pkgid, dest_ws.unwrap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
fn run(&self, cmd: &str, args: ~[~str]) {
|
fn run(&self, cmd: &str, args: ~[~str]) {
|
||||||
match cmd {
|
match cmd {
|
||||||
"build" => {
|
"build" => {
|
||||||
if args.len() < 1 {
|
self.build_args(args, &Everything);
|
||||||
match cwd_to_workspace() {
|
|
||||||
None if self.context.use_rust_path_hack => {
|
|
||||||
let cwd = os::getcwd();
|
|
||||||
let pkgid = PkgId::new(cwd.components[cwd.components.len() - 1]);
|
|
||||||
let mut pkg_src = PkgSrc::new(cwd, true, pkgid);
|
|
||||||
self.build(&mut pkg_src, &Everything);
|
|
||||||
}
|
|
||||||
None => { usage::build(); return; }
|
|
||||||
Some((ws, pkgid)) => {
|
|
||||||
let mut pkg_src = PkgSrc::new(ws, false, pkgid);
|
|
||||||
self.build(&mut pkg_src, &Everything);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// The package id is presumed to be the first command-line
|
|
||||||
// argument
|
|
||||||
let pkgid = PkgId::new(args[0].clone());
|
|
||||||
do each_pkg_parent_workspace(&self.context, &pkgid) |workspace| {
|
|
||||||
debug!("found pkg %s in workspace %s, trying to build",
|
|
||||||
pkgid.to_str(), workspace.to_str());
|
|
||||||
let mut pkg_src = PkgSrc::new(workspace.clone(), false, pkgid.clone());
|
|
||||||
self.build(&mut pkg_src, &Everything);
|
|
||||||
true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"clean" => {
|
"clean" => {
|
||||||
if args.len() < 1 {
|
if args.len() < 1 {
|
||||||
|
@ -310,7 +322,17 @@ impl CtxMethods for BuildContext {
|
||||||
self.prefer(args[0], None);
|
self.prefer(args[0], None);
|
||||||
}
|
}
|
||||||
"test" => {
|
"test" => {
|
||||||
self.test();
|
// Build the test executable
|
||||||
|
let maybe_id_and_workspace = self.build_args(args, &Tests);
|
||||||
|
match maybe_id_and_workspace {
|
||||||
|
Some((pkg_id, workspace)) => {
|
||||||
|
// Assuming it's built, run the tests
|
||||||
|
self.test(&pkg_id, &workspace);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
error("Testing failed because building the specified package failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"init" => {
|
"init" => {
|
||||||
if args.len() != 0 {
|
if args.len() != 0 {
|
||||||
|
@ -425,6 +447,8 @@ impl CtxMethods for BuildContext {
|
||||||
match what_to_build {
|
match what_to_build {
|
||||||
// Find crates inside the workspace
|
// Find crates inside the workspace
|
||||||
&Everything => pkg_src.find_crates(),
|
&Everything => pkg_src.find_crates(),
|
||||||
|
// Find only tests
|
||||||
|
&Tests => pkg_src.find_crates_with_filter(|s| { is_test(&Path(s)) }),
|
||||||
// Don't infer any crates -- just build the one that was requested
|
// Don't infer any crates -- just build the one that was requested
|
||||||
&JustOne(ref p) => {
|
&JustOne(ref p) => {
|
||||||
// We expect that p is relative to the package source's start directory,
|
// We expect that p is relative to the package source's start directory,
|
||||||
|
@ -592,9 +616,25 @@ impl CtxMethods for BuildContext {
|
||||||
fail!("prefer not yet implemented");
|
fail!("prefer not yet implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test(&self) {
|
fn test(&self, pkgid: &PkgId, workspace: &Path) {
|
||||||
// stub
|
match built_test_in_workspace(pkgid, workspace) {
|
||||||
fail!("test not yet implemented");
|
Some(test_exec) => {
|
||||||
|
debug!("test: test_exec = %s", test_exec.to_str());
|
||||||
|
let p_output = run::process_output(test_exec.to_str(), [~"--test"]);
|
||||||
|
if p_output.status == 0 {
|
||||||
|
println(str::from_utf8(p_output.output));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println(str::from_utf8(p_output.error));
|
||||||
|
}
|
||||||
|
os::set_exit_status(p_output.status);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
error(fmt!("Internal error: test executable for package ID %s in workspace %s \
|
||||||
|
wasn't built! Please report this as a bug.",
|
||||||
|
pkgid.to_str(), workspace.to_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(&self) {
|
fn init(&self) {
|
||||||
|
|
|
@ -26,6 +26,8 @@ pub enum Target {
|
||||||
pub enum WhatToBuild {
|
pub enum WhatToBuild {
|
||||||
/// Build just one lib.rs file in `path`, which is relative to the active workspace's src/ dir
|
/// Build just one lib.rs file in `path`, which is relative to the active workspace's src/ dir
|
||||||
JustOne(Path),
|
JustOne(Path),
|
||||||
|
/// Build any test.rs files that can be recursively found in the active workspace
|
||||||
|
Tests,
|
||||||
/// Build everything
|
/// Build everything
|
||||||
Everything
|
Everything
|
||||||
}
|
}
|
||||||
|
|
|
@ -350,11 +350,19 @@ fn assert_executable_exists(repo: &Path, short_name: &str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn executable_exists(repo: &Path, short_name: &str) -> bool {
|
fn executable_exists(repo: &Path, short_name: &str) -> bool {
|
||||||
debug!("assert_executable_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
|
debug!("executable_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
|
||||||
let exec = target_executable_in_workspace(&PkgId::new(short_name), repo);
|
let exec = target_executable_in_workspace(&PkgId::new(short_name), repo);
|
||||||
os::path_exists(&exec) && is_rwx(&exec)
|
os::path_exists(&exec) && is_rwx(&exec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_executable_exists(repo: &Path, short_name: &str) -> bool {
|
||||||
|
debug!("test_executable_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
|
||||||
|
let exec = built_test_in_workspace(&PkgId::new(short_name), repo);
|
||||||
|
do exec.map_default(false) |exec| {
|
||||||
|
os::path_exists(exec) && is_rwx(exec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn remove_executable_file(p: &PkgId, workspace: &Path) {
|
fn remove_executable_file(p: &PkgId, workspace: &Path) {
|
||||||
let exec = target_executable_in_workspace(&PkgId::new(p.short_name), workspace);
|
let exec = target_executable_in_workspace(&PkgId::new(p.short_name), workspace);
|
||||||
if os::path_exists(&exec) {
|
if os::path_exists(&exec) {
|
||||||
|
@ -1045,19 +1053,8 @@ fn test_info() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore(reason = "test not yet implemented")]
|
|
||||||
fn test_rustpkg_test() {
|
|
||||||
let expected_results = ~"1 out of 1 tests passed"; // fill in
|
|
||||||
let workspace = create_local_package_with_test(&PkgId::new("foo"));
|
|
||||||
let output = command_line_test([~"test", ~"foo"], &workspace);
|
|
||||||
assert_eq!(str::from_utf8(output.output), expected_results);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[ignore(reason = "test not yet implemented")]
|
|
||||||
fn test_uninstall() {
|
fn test_uninstall() {
|
||||||
let workspace = create_local_package(&PkgId::new("foo"));
|
let workspace = create_local_package(&PkgId::new("foo"));
|
||||||
let _output = command_line_test([~"info", ~"foo"], &workspace);
|
|
||||||
command_line_test([~"uninstall", ~"foo"], &workspace);
|
command_line_test([~"uninstall", ~"foo"], &workspace);
|
||||||
let output = command_line_test([~"list"], &workspace);
|
let output = command_line_test([~"list"], &workspace);
|
||||||
assert!(!str::from_utf8(output.output).contains("foo"));
|
assert!(!str::from_utf8(output.output).contains("foo"));
|
||||||
|
@ -1800,6 +1797,64 @@ fn correct_package_name_with_rust_path_hack() {
|
||||||
assert!(!lib_exists(&foo_workspace, &foo_id.path.clone(), foo_id.version.clone()));
|
assert!(!lib_exists(&foo_workspace, &foo_id.path.clone(), foo_id.version.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rustpkg_test_creates_exec() {
|
||||||
|
let foo_id = PkgId::new("foo");
|
||||||
|
let foo_workspace = create_local_package(&foo_id);
|
||||||
|
writeFile(&foo_workspace.push_many(["src", "foo-0.1", "test.rs"]),
|
||||||
|
"#[test] fn f() { assert!('a' == 'a'); }");
|
||||||
|
command_line_test([~"test", ~"foo"], &foo_workspace);
|
||||||
|
assert!(test_executable_exists(&foo_workspace, "foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rustpkg_test_output() {
|
||||||
|
let workspace = create_local_package_with_test(&PkgId::new("foo"));
|
||||||
|
let output = command_line_test([~"test", ~"foo"], &workspace);
|
||||||
|
let output_str = str::from_utf8(output.output);
|
||||||
|
assert!(output_str.contains("test f ... ok"));
|
||||||
|
assert!(output_str.contains(
|
||||||
|
"test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore(reason = "See issue #9441")]
|
||||||
|
fn test_rebuild_when_needed() {
|
||||||
|
let foo_id = PkgId::new("foo");
|
||||||
|
let foo_workspace = create_local_package(&foo_id);
|
||||||
|
let test_crate = foo_workspace.push_many(["src", "foo-0.1", "test.rs"]);
|
||||||
|
writeFile(&test_crate, "#[test] fn f() { assert!('a' == 'a'); }");
|
||||||
|
command_line_test([~"test", ~"foo"], &foo_workspace);
|
||||||
|
assert!(test_executable_exists(&foo_workspace, "foo"));
|
||||||
|
let test_executable = built_test_in_workspace(&foo_id,
|
||||||
|
&foo_workspace).expect("test_rebuild_when_needed failed");
|
||||||
|
frob_source_file(&foo_workspace, &foo_id, "test.rs");
|
||||||
|
chmod_read_only(&test_executable);
|
||||||
|
match command_line_test_partial([~"test", ~"foo"], &foo_workspace) {
|
||||||
|
Success(*) => fail!("test_rebuild_when_needed didn't rebuild"),
|
||||||
|
Fail(status) if status == 65 => (), // ok
|
||||||
|
Fail(_) => fail!("test_rebuild_when_needed failed for some other reason")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_no_rebuilding() {
|
||||||
|
let foo_id = PkgId::new("foo");
|
||||||
|
let foo_workspace = create_local_package(&foo_id);
|
||||||
|
let test_crate = foo_workspace.push_many(["src", "foo-0.1", "test.rs"]);
|
||||||
|
writeFile(&test_crate, "#[test] fn f() { assert!('a' == 'a'); }");
|
||||||
|
command_line_test([~"test", ~"foo"], &foo_workspace);
|
||||||
|
assert!(test_executable_exists(&foo_workspace, "foo"));
|
||||||
|
let test_executable = built_test_in_workspace(&foo_id,
|
||||||
|
&foo_workspace).expect("test_no_rebuilding failed");
|
||||||
|
chmod_read_only(&test_executable);
|
||||||
|
match command_line_test_partial([~"test", ~"foo"], &foo_workspace) {
|
||||||
|
Success(*) => (), // ok
|
||||||
|
Fail(status) if status == 65 => fail!("test_no_rebuilding failed: it rebuilt the tests"),
|
||||||
|
Fail(_) => fail!("test_no_rebuilding failed for some other reason")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if p exists and is executable
|
/// Returns true if p exists and is executable
|
||||||
fn is_executable(p: &Path) -> bool {
|
fn is_executable(p: &Path) -> bool {
|
||||||
use std::libc::consts::os::posix88::{S_IXUSR};
|
use std::libc::consts::os::posix88::{S_IXUSR};
|
||||||
|
|
Loading…
Reference in New Issue