Skip to content

Commit 1cf029c

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 1cf029c

File tree

6 files changed

+160
-45
lines changed

6 files changed

+160
-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 = ~[];
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: 51 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(
@@ -507,6 +506,7 @@ fn output_file_name(workspace: &Path, short_name: ~str) -> Path {
507506
os::EXE_SUFFIX))
508507
}
509508

509+
#[cfg(target_os = "linux")]
510510
fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
511511
use conditions::bad_path::cond;
512512
let pkg_src_dir = workspace.join_many([~"src", pkgid.to_str()]);
@@ -515,7 +515,26 @@ fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
515515
if p.extension_str() == Some("rs") {
516516
// should be able to do this w/o a process
517517
// FIXME (#9639): This needs to handle non-utf8 paths
518-
if run::process_output("touch", [p.as_str().unwrap().to_owned()]).status != 0 {
518+
// n.b. Bumps time up by 2 seconds to get around granularity issues
519+
if run::process_output("touch", [~"-A", ~"02", p.to_str()]).status != 0 {
520+
let _ = cond.raise((pkg_src_dir.clone(), ~"Bad path"));
521+
}
522+
}
523+
}
524+
}
525+
526+
#[cfg(not(target_os = "linux"))]
527+
fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
528+
use conditions::bad_path::cond;
529+
let pkg_src_dir = workspace.join_many([~"src", pkgid.to_str()]);
530+
let contents = os::list_dir_path(&pkg_src_dir);
531+
for p in contents.iter() {
532+
if p.extension_str() == Some("rs") {
533+
// should be able to do this w/o a process
534+
// FIXME (#9639): This needs to handle non-utf8 paths
535+
// n.b. Bumps time up by 2 seconds to get around granularity issues
536+
if run::process_output("touch", [~"-A02",
537+
p.as_str().unwrap().to_owned()]).status != 0 {
519538
let _ = cond.raise((pkg_src_dir.clone(), ~"Bad path"));
520539
}
521540
}
@@ -1033,12 +1052,17 @@ fn no_rebuilding() {
10331052
let workspace = create_local_package(&p_id);
10341053
let workspace = workspace.path();
10351054
command_line_test([~"build", ~"foo"], workspace);
1036-
let date = datestamp(&built_library_in_workspace(&p_id,
1037-
workspace).expect("no_rebuilding"));
1055+
let foo_lib = lib_output_file_name(workspace, "foo");
1056+
// Now make `foo` read-only so that subsequent rebuilds of it will fail
1057+
assert!(chmod_read_only(&foo_lib));
1058+
10381059
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);
1060+
1061+
match command_line_test_partial([~"build", ~"foo"], workspace) {
1062+
Success(*) => (), // ok
1063+
Fail(status) if status == 65 => fail2!("no_rebuilding failed: it tried to rebuild bar"),
1064+
Fail(_) => fail2!("no_rebuilding failed for some other reason")
1065+
}
10421066
}
10431067
10441068
#[test]
@@ -1049,55 +1073,55 @@ fn no_rebuilding_dep() {
10491073
let workspace = workspace.path();
10501074
command_line_test([~"build", ~"foo"], workspace);
10511075
let bar_lib = lib_output_file_name(workspace, "bar");
1052-
let bar_date_1 = datestamp(&bar_lib);
1053-
10541076
frob_source_file(workspace, &p_id, "main.rs");
1055-
10561077
// Now make `bar` read-only so that subsequent rebuilds of it will fail
10571078
assert!(chmod_read_only(&bar_lib));
1058-
10591079
match command_line_test_partial([~"build", ~"foo"], workspace) {
10601080
Success(*) => (), // ok
10611081
Fail(status) if status == 65 => fail2!("no_rebuilding_dep failed: it tried to rebuild bar"),
10621082
Fail(_) => fail2!("no_rebuilding_dep failed for some other reason")
10631083
}
1064-
1065-
let bar_date_2 = datestamp(&bar_lib);
1066-
assert_eq!(bar_date_1, bar_date_2);
10671084
}
10681085
10691086
#[test]
1070-
#[ignore]
10711087
fn do_rebuild_dep_dates_change() {
10721088
let p_id = PkgId::new("foo");
10731089
let dep_id = PkgId::new("bar");
10741090
let workspace = create_local_package_with_dep(&p_id, &dep_id);
10751091
let workspace = workspace.path();
10761092
command_line_test([~"build", ~"foo"], workspace);
10771093
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);
10801094
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);
1095+
1096+
// Now make `bar` read-only so that subsequent rebuilds of it will fail
1097+
assert!(chmod_read_only(&bar_lib_name));
1098+
1099+
match command_line_test_partial([~"build", ~"foo"], workspace) {
1100+
Success(*) => fail2!("do_rebuild_dep_dates_change failed: it didn't rebuild bar"),
1101+
Fail(status) if status == 65 => (), // ok
1102+
Fail(_) => fail2!("do_rebuild_dep_dates_change failed for some other reason")
1103+
}
10851104
}
10861105
10871106
#[test]
1088-
#[ignore]
10891107
fn do_rebuild_dep_only_contents_change() {
10901108
let p_id = PkgId::new("foo");
10911109
let dep_id = PkgId::new("bar");
10921110
let workspace = create_local_package_with_dep(&p_id, &dep_id);
10931111
let workspace = workspace.path();
10941112
command_line_test([~"build", ~"foo"], workspace);
1095-
let bar_date = datestamp(&lib_output_file_name(workspace, "bar"));
10961113
frob_source_file(workspace, &dep_id, "lib.rs");
1114+
let bar_lib_name = lib_output_file_name(workspace, "bar");
1115+
1116+
// Now make `bar` read-only so that subsequent rebuilds of it will fail
1117+
assert!(chmod_read_only(&bar_lib_name));
1118+
10971119
// 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);
1120+
match command_line_test_partial([~"build", ~"foo"], workspace) {
1121+
Success(*) => fail2!("do_rebuild_dep_only_contents_change failed: it didn't rebuild bar"),
1122+
Fail(status) if status == 65 => (), // ok
1123+
Fail(_) => fail2!("do_rebuild_dep_only_contents_change failed for some other reason")
1124+
}
11011125
}
11021126
11031127
#[test]
@@ -2003,7 +2027,7 @@ fn test_rustpkg_test_output() {
20032027
}
20042028
20052029
#[test]
2006-
#[ignore(reason = "See issue #9441")]
2030+
#[ignore(reason = "Issue 9441")]
20072031
fn test_rebuild_when_needed() {
20082032
let foo_id = PkgId::new("foo");
20092033
let foo_workspace = create_local_package(&foo_id);

0 commit comments

Comments
 (0)