Skip to content

Commit bac3f7e

Browse files
committed
rustpkg: Make rustpkg tests stop comparing dates
Instead of scrutinizing modification times in rustpkg tests, change output files to be read-only and detect attempts to write to them (hack suggested by Jack). This avoids time granularity problems. As part of this change, I discovered that some dependencies weren't getting written correctly (involving built executables and library files), so this patch fixes that too. This partly addresses #9441, but one test (test_rebuild_when_needed) is still ignored on Linux.
1 parent 6b07d88 commit bac3f7e

File tree

6 files changed

+141
-45
lines changed

6 files changed

+141
-45
lines changed

src/libextra/workcache.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ impl Logger {
219219
}
220220

221221
pub fn info(&self, i: &str) {
222-
io::println(~"workcache: " + i);
222+
info2!("workcache: {}", i);
223223
}
224224
}
225225

src/librustpkg/conditions.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ condition! {
2323
pub bad_stat: (Path, ~str) -> stat;
2424
}
2525

26+
condition! {
27+
pub bad_kind: (~str) -> ();
28+
}
29+
2630
condition! {
2731
pub nonexistent_package: (PkgId, ~str) -> Path;
2832
}

src/librustpkg/package_source.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ use source_control::{safe_git_clone, git_clone_url, DirToUse, CheckedOutSources}
2121
use source_control::make_read_only;
2222
use path_util::{find_dir_using_rust_path_hack, make_dir_rwx_recursive};
2323
use path_util::{target_build_dir, versionize};
24-
use util::compile_crate;
24+
use util::{compile_crate, DepMap};
2525
use workcache_support;
2626
use workcache_support::crate_tag;
2727
use extra::workcache;
28+
use extra::treemap::TreeMap;
2829

2930
// An enumeration of the unpacked source of a package workspace.
3031
// This contains a list of files found in the source workspace.
@@ -370,6 +371,7 @@ impl PkgSrc {
370371

371372
fn build_crates(&self,
372373
ctx: &BuildContext,
374+
deps: &mut DepMap,
373375
crates: &[Crate],
374376
cfgs: &[~str],
375377
what: OutputType) {
@@ -389,12 +391,14 @@ impl PkgSrc {
389391
let id = self.id.clone();
390392
let sub_dir = self.build_workspace().clone();
391393
let sub_flags = crate.flags.clone();
394+
let sub_deps = deps.clone();
392395
do prep.exec |exec| {
393396
let result = compile_crate(&subcx,
394397
exec,
395398
&id,
396399
&subpath,
397400
&sub_dir,
401+
&mut (sub_deps.clone()),
398402
sub_flags,
399403
subcfgs,
400404
false,
@@ -428,24 +432,27 @@ impl PkgSrc {
428432
}
429433
}
430434

431-
// It would be better if build returned a Path, but then Path would have to derive
432-
// Encodable.
433435
pub fn build(&self,
434436
build_context: &BuildContext,
435-
cfgs: ~[~str]) {
437+
// DepMap is a map from str (crate name) to (kind, name) --
438+
// it tracks discovered dependencies per-crate
439+
cfgs: ~[~str]) -> DepMap {
440+
let mut deps = TreeMap::new();
441+
436442
let libs = self.libs.clone();
437443
let mains = self.mains.clone();
438444
let tests = self.tests.clone();
439445
let benchs = self.benchs.clone();
440446
debug2!("Building libs in {}, destination = {}",
441447
self.source_workspace.display(), self.build_workspace().display());
442-
self.build_crates(build_context, libs, cfgs, Lib);
448+
self.build_crates(build_context, &mut deps, libs, cfgs, Lib);
443449
debug2!("Building mains");
444-
self.build_crates(build_context, mains, cfgs, Main);
450+
self.build_crates(build_context, &mut deps, mains, cfgs, Main);
445451
debug2!("Building tests");
446-
self.build_crates(build_context, tests, cfgs, Test);
452+
self.build_crates(build_context, &mut deps, tests, cfgs, Test);
447453
debug2!("Building benches");
448-
self.build_crates(build_context, benchs, cfgs, Bench);
454+
self.build_crates(build_context, &mut deps, benchs, cfgs, Bench);
455+
deps
449456
}
450457

451458
/// Return the workspace to put temporary files in. See the comment on `PkgSrc`

src/librustpkg/rustpkg.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,8 @@ pub trait CtxMethods {
197197
fn install(&self, src: PkgSrc, what: &WhatToBuild) -> (~[Path], ~[(~str, ~str)]);
198198
/// Returns a list of installed files
199199
fn install_no_build(&self,
200-
source_workspace: &Path,
200+
build_workspace: &Path,
201+
build_inputs: &[Path],
201202
target_workspace: &Path,
202203
id: &PkgId) -> ~[~str];
203204
fn prefer(&self, _id: &str, _vers: Option<~str>);
@@ -542,6 +543,7 @@ impl CtxMethods for BuildContext {
542543

543544
let mut installed_files = ~[];
544545
let mut inputs = ~[];
546+
let mut build_inputs = ~[]; // NOTE: sigh
545547

546548
debug2!("Installing package source: {}", pkg_src.to_str());
547549

@@ -554,14 +556,16 @@ impl CtxMethods for BuildContext {
554556
debug2!("In declare inputs for {}", id.to_str());
555557
for cs in to_do.iter() {
556558
for c in cs.iter() {
557-
let path = pkg_src.start_dir.join(&c.file);
559+
let path = pkg_src.start_dir.join(&c.file).normalize();
558560
debug2!("Recording input: {}", path.display());
559561
// FIXME (#9639): This needs to handle non-utf8 paths
560562
inputs.push((~"file", path.as_str().unwrap().to_owned()));
563+
build_inputs.push(path);
561564
}
562565
}
563566

564567
let result = self.install_no_build(pkg_src.build_workspace(),
568+
build_inputs,
565569
&pkg_src.destination_workspace,
566570
&id).map(|s| Path::new(s.as_slice()));
567571
debug2!("install: id = {}, about to call discover_outputs, {:?}",
@@ -576,6 +580,7 @@ impl CtxMethods for BuildContext {
576580
// again, working around lack of Encodable for Path
577581
fn install_no_build(&self,
578582
build_workspace: &Path,
583+
build_inputs: &[Path],
579584
target_workspace: &Path,
580585
id: &PkgId) -> ~[~str] {
581586
use conditions::copy_failed::cond;
@@ -612,9 +617,28 @@ impl CtxMethods for BuildContext {
612617
let sublib = maybe_library.clone();
613618
let sub_target_ex = target_exec.clone();
614619
let sub_target_lib = target_lib.clone();
615-
620+
let sub_build_inputs = build_inputs.to_owned();
616621
do prep.exec |exe_thing| {
617622
let mut outputs = ~[];
623+
// Declare all the *inputs* to the declared input too, as inputs
624+
for executable in subex.iter() {
625+
exe_thing.discover_input("binary",
626+
executable.to_str(),
627+
workcache_support::digest_only_date(executable));
628+
}
629+
for library in sublib.iter() {
630+
exe_thing.discover_input("binary",
631+
library.to_str(),
632+
workcache_support::digest_only_date(library));
633+
}
634+
635+
for transitive_dependency in sub_build_inputs.iter() {
636+
exe_thing.discover_input(
637+
"file",
638+
transitive_dependency.to_str(),
639+
workcache_support::digest_file_with_date(transitive_dependency));
640+
}
641+
618642

619643
for exec in subex.iter() {
620644
debug2!("Copying: {} -> {}", exec.display(), sub_target_ex.display());

src/librustpkg/tests.rs

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ use target::*;
3737
use package_source::PkgSrc;
3838
use source_control::{CheckedOutSources, DirToUse, safe_git_clone};
3939
use exit_codes::{BAD_FLAG_CODE, COPY_FAILED_CODE};
40-
use util::datestamp;
4140

4241
fn fake_ctxt(sysroot: Path, workspace: &Path) -> BuildContext {
4342
let context = workcache::Context::new(
@@ -515,7 +514,8 @@ fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
515514
if p.extension_str() == Some("rs") {
516515
// should be able to do this w/o a process
517516
// FIXME (#9639): This needs to handle non-utf8 paths
518-
if run::process_output("touch", [p.as_str().unwrap().to_owned()]).status != 0 {
517+
// n.b. Bumps time up by 2 seconds to get around granularity issues
518+
if run::process_output("touch", [~"-A", ~"02", p.to_str()]).status != 0 {
519519
let _ = cond.raise((pkg_src_dir.clone(), ~"Bad path"));
520520
}
521521
}
@@ -1033,12 +1033,17 @@ fn no_rebuilding() {
10331033
let workspace = create_local_package(&p_id);
10341034
let workspace = workspace.path();
10351035
command_line_test([~"build", ~"foo"], workspace);
1036-
let date = datestamp(&built_library_in_workspace(&p_id,
1037-
workspace).expect("no_rebuilding"));
1036+
let foo_lib = lib_output_file_name(workspace, "foo");
1037+
// Now make `foo` read-only so that subsequent rebuilds of it will fail
1038+
assert!(chmod_read_only(&foo_lib));
1039+
10381040
command_line_test([~"build", ~"foo"], workspace);
1039-
let newdate = datestamp(&built_library_in_workspace(&p_id,
1040-
workspace).expect("no_rebuilding (2)"));
1041-
assert_eq!(date, newdate);
1041+
1042+
match command_line_test_partial([~"build", ~"foo"], workspace) {
1043+
Success(*) => (), // ok
1044+
Fail(status) if status == 65 => fail2!("no_rebuilding failed: it tried to rebuild bar"),
1045+
Fail(_) => fail2!("no_rebuilding failed for some other reason")
1046+
}
10421047
}
10431048
10441049
#[test]
@@ -1049,55 +1054,55 @@ fn no_rebuilding_dep() {
10491054
let workspace = workspace.path();
10501055
command_line_test([~"build", ~"foo"], workspace);
10511056
let bar_lib = lib_output_file_name(workspace, "bar");
1052-
let bar_date_1 = datestamp(&bar_lib);
1053-
10541057
frob_source_file(workspace, &p_id, "main.rs");
1055-
10561058
// Now make `bar` read-only so that subsequent rebuilds of it will fail
10571059
assert!(chmod_read_only(&bar_lib));
1058-
10591060
match command_line_test_partial([~"build", ~"foo"], workspace) {
10601061
Success(*) => (), // ok
10611062
Fail(status) if status == 65 => fail2!("no_rebuilding_dep failed: it tried to rebuild bar"),
10621063
Fail(_) => fail2!("no_rebuilding_dep failed for some other reason")
10631064
}
1064-
1065-
let bar_date_2 = datestamp(&bar_lib);
1066-
assert_eq!(bar_date_1, bar_date_2);
10671065
}
10681066
10691067
#[test]
1070-
#[ignore]
10711068
fn do_rebuild_dep_dates_change() {
10721069
let p_id = PkgId::new("foo");
10731070
let dep_id = PkgId::new("bar");
10741071
let workspace = create_local_package_with_dep(&p_id, &dep_id);
10751072
let workspace = workspace.path();
10761073
command_line_test([~"build", ~"foo"], workspace);
10771074
let bar_lib_name = lib_output_file_name(workspace, "bar");
1078-
let bar_date = datestamp(&bar_lib_name);
1079-
debug2!("Datestamp on {} is {:?}", bar_lib_name.display(), bar_date);
10801075
touch_source_file(workspace, &dep_id);
1081-
command_line_test([~"build", ~"foo"], workspace);
1082-
let new_bar_date = datestamp(&bar_lib_name);
1083-
debug2!("Datestamp on {} is {:?}", bar_lib_name.display(), new_bar_date);
1084-
assert!(new_bar_date > bar_date);
1076+
1077+
// Now make `bar` read-only so that subsequent rebuilds of it will fail
1078+
assert!(chmod_read_only(&bar_lib_name));
1079+
1080+
match command_line_test_partial([~"build", ~"foo"], workspace) {
1081+
Success(*) => fail2!("do_rebuild_dep_dates_change failed: it didn't rebuild bar"),
1082+
Fail(status) if status == 65 => (), // ok
1083+
Fail(_) => fail2!("do_rebuild_dep_dates_change failed for some other reason")
1084+
}
10851085
}
10861086
10871087
#[test]
1088-
#[ignore]
10891088
fn do_rebuild_dep_only_contents_change() {
10901089
let p_id = PkgId::new("foo");
10911090
let dep_id = PkgId::new("bar");
10921091
let workspace = create_local_package_with_dep(&p_id, &dep_id);
10931092
let workspace = workspace.path();
10941093
command_line_test([~"build", ~"foo"], workspace);
1095-
let bar_date = datestamp(&lib_output_file_name(workspace, "bar"));
10961094
frob_source_file(workspace, &dep_id, "lib.rs");
1095+
let bar_lib_name = lib_output_file_name(workspace, "bar");
1096+
1097+
// Now make `bar` read-only so that subsequent rebuilds of it will fail
1098+
assert!(chmod_read_only(&bar_lib_name));
1099+
10971100
// should adjust the datestamp
1098-
command_line_test([~"build", ~"foo"], workspace);
1099-
let new_bar_date = datestamp(&lib_output_file_name(workspace, "bar"));
1100-
assert!(new_bar_date > bar_date);
1101+
match command_line_test_partial([~"build", ~"foo"], workspace) {
1102+
Success(*) => fail2!("do_rebuild_dep_only_contents_change failed: it didn't rebuild bar"),
1103+
Fail(status) if status == 65 => (), // ok
1104+
Fail(_) => fail2!("do_rebuild_dep_only_contents_change failed for some other reason")
1105+
}
11011106
}
11021107
11031108
#[test]
@@ -2003,7 +2008,7 @@ fn test_rustpkg_test_output() {
20032008
}
20042009
20052010
#[test]
2006-
#[ignore(reason = "See issue #9441")]
2011+
#[ignore(reason = "Issue 9441")]
20072012
fn test_rebuild_when_needed() {
20082013
let foo_id = PkgId::new("foo");
20092014
let foo_workspace = create_local_package(&foo_id);

0 commit comments

Comments
 (0)