1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
14 use std::hashmap::HashMap;
15 use std::{io, libc, os, run, str};
16 use extra::tempfile::mkdtemp;
17 use std::run::ProcessOutput;
18 use installed_packages::list_installed_packages;
19 use package_id::{PkgId};
20 use version::{ExactRevision, NoVersion, Version, Tagged};
21 use path_util::{target_executable_in_workspace, target_test_in_workspace,
22 target_bench_in_workspace, make_dir_rwx, U_RWX,
23 library_in_workspace, installed_library_in_workspace,
24 built_bench_in_workspace, built_test_in_workspace,
25 built_library_in_workspace, built_executable_in_workspace};
26 use rustc::metadata::filesearch::rust_path;
27 use rustc::driver::driver::host_triple;
30 /// Returns the last-modified date as an Option
31 fn datestamp(p: &Path) -> Option<libc::time_t> {
32 p.stat().map(|stat| stat.st_mtime)
35 fn fake_ctxt(sysroot_opt: Option<@Path>) -> Ctx {
37 sysroot_opt: sysroot_opt,
39 dep_cache: @mut HashMap::new()
43 fn fake_pkg() -> PkgId {
52 fn git_repo_pkg() -> PkgId {
54 path: Path("mockgithub.com/catamorphism/test-pkg"),
55 short_name: ~"test-pkg",
60 fn git_repo_pkg_with_tag(a_tag: ~str) -> PkgId {
62 path: Path("mockgithub.com/catamorphism/test-pkg"),
63 short_name: ~"test-pkg",
64 version: Tagged(a_tag)
68 fn writeFile(file_path: &Path, contents: &str) {
69 let out = io::file_writer(file_path, [io::Create, io::Truncate]).unwrap();
70 out.write_line(contents);
73 fn mk_empty_workspace(short_name: &Path, version: &Version) -> Path {
74 let workspace_dir = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
75 mk_workspace(&workspace_dir, short_name, version);
79 fn mk_workspace(workspace: &Path, short_name: &Path, version: &Version) -> Path {
80 // include version number in directory name
81 let package_dir = workspace.push("src").push(fmt!("%s-%s",
82 short_name.to_str(), version.to_str()));
83 assert!(os::mkdir_recursive(&package_dir, U_RWX));
87 fn mk_temp_workspace(short_name: &Path, version: &Version) -> Path {
88 let package_dir = mk_empty_workspace(short_name,
89 version).push("src").push(fmt!("%s-%s",
93 debug!("Created %s and does it exist? %?", package_dir.to_str(),
94 os::path_is_dir(&package_dir));
95 // Create main, lib, test, and bench files
96 debug!("mk_workspace: creating %s", package_dir.to_str());
97 assert!(os::mkdir_recursive(&package_dir, U_RWX));
98 debug!("Created %s and does it exist? %?", package_dir.to_str(),
99 os::path_is_dir(&package_dir));
100 // Create main, lib, test, and bench files
102 writeFile(&package_dir.push("main.rs"),
103 "fn main() { let _x = (); }");
104 writeFile(&package_dir.push("lib.rs"),
105 "pub fn f() { let _x = (); }");
106 writeFile(&package_dir.push("test.rs"),
107 "#[test] pub fn f() { (); }");
108 writeFile(&package_dir.push("bench.rs"),
109 "#[bench] pub fn f() { (); }");
113 fn run_git(args: &[~str], env: Option<~[(~str, ~str)]>, cwd: &Path, err_msg: &str) {
114 let cwd = (*cwd).clone();
115 let mut prog = run::Process::new("git", args, run::ProcessOptions {
122 let rslt = prog.finish_with_output();
123 if rslt.status != 0 {
124 fail!("%s [git returned %?, output = %s, error = %s]", err_msg,
125 rslt.status, str::from_bytes(rslt.output), str::from_bytes(rslt.error));
129 /// Should create an empty git repo in p, relative to the tmp dir, and return the new
131 fn init_git_repo(p: &Path) -> Path {
132 assert!(!p.is_absolute());
133 let tmp = mkdtemp(&os::tmpdir(), "git_local").expect("couldn't create temp dir");
134 let work_dir = tmp.push_rel(p);
135 let work_dir_for_opts = work_dir.clone();
136 assert!(os::mkdir_recursive(&work_dir, U_RWX));
137 debug!("Running: git init in %s", work_dir.to_str());
138 let ws = work_dir.to_str();
139 run_git([~"init"], None, &work_dir_for_opts,
140 fmt!("Couldn't initialize git repository in %s", ws));
141 // Add stuff to the dir so that git tag succeeds
142 writeFile(&work_dir.push("README"), "");
143 run_git([~"add", ~"README"], None, &work_dir_for_opts, fmt!("Couldn't add in %s", ws));
144 git_commit(&work_dir_for_opts, ~"whatever");
148 fn add_all_and_commit(repo: &Path) {
150 git_commit(repo, ~"floop");
153 fn git_commit(repo: &Path, msg: ~str) {
154 run_git([~"commit", ~"--author=tester <test@mozilla.com>", ~"-m", msg],
155 None, repo, fmt!("Couldn't commit in %s", repo.to_str()));
158 fn git_add_all(repo: &Path) {
159 run_git([~"add", ~"-A"], None, repo, fmt!("Couldn't add all files in %s", repo.to_str()));
162 fn add_git_tag(repo: &Path, tag: ~str) {
163 assert!(repo.is_absolute());
165 git_commit(repo, ~"whatever");
166 run_git([~"tag", tag.clone()], None, repo,
167 fmt!("Couldn't add git tag %s in %s", tag, repo.to_str()));
170 fn is_rwx(p: &Path) -> bool {
171 use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
174 None => return false,
176 ((m & S_IRUSR as uint) == S_IRUSR as uint
177 && (m & S_IWUSR as uint) == S_IWUSR as uint
178 && (m & S_IXUSR as uint) == S_IXUSR as uint)
182 fn test_sysroot() -> Path {
183 // Totally gross hack but it's just for test cases.
184 // Infer the sysroot from the exe name and pray that it's right.
185 // (Did I mention it was a gross hack?)
186 let self_path = os::self_exe_path().expect("Couldn't get self_exe path");
190 // Returns the path to rustpkg
191 fn rustpkg_exec() -> Path {
193 let first_try = test_sysroot().push("lib").push("rustc")
194 .push(host_triple()).push("bin").push("rustpkg");
195 if is_executable(&first_try) {
199 let second_try = test_sysroot().push("bin").push("rustpkg");
200 if is_executable(&second_try) {
204 fail!("in rustpkg test, can't find an installed rustpkg");
209 fn command_line_test(args: &[~str], cwd: &Path) -> ProcessOutput {
210 command_line_test_with_env(args, cwd, None)
213 /// Runs `rustpkg` (based on the directory that this executable was
214 /// invoked from) with the given arguments, in the given working directory.
215 /// Returns the process's output.
216 fn command_line_test_with_env(args: &[~str], cwd: &Path, env: Option<~[(~str, ~str)]>)
218 let cmd = rustpkg_exec().to_str();
219 debug!("cd %s; %s %s",
220 cwd.to_str(), cmd, args.connect(" "));
221 assert!(os::path_is_dir(&*cwd));
222 let cwd = (*cwd).clone();
223 let mut prog = run::Process::new(cmd, args, run::ProcessOptions {
224 env: env.map(|e| e + os::env()),
230 let output = prog.finish_with_output();
231 debug!("Output from command %s with args %? was %s {%s}[%?]",
232 cmd, args, str::from_bytes(output.output),
233 str::from_bytes(output.error),
236 By the way, rustpkg *won't* return a nonzero exit code if it fails --
238 So tests that use this need to check the existence of a file
239 to make sure the command succeeded
241 if output.status != 0 {
242 fail!("Command %s %? failed with exit code %?; its output was {{{ %s }}}",
243 cmd, args, output.status,
244 str::from_bytes(output.output) + str::from_bytes(output.error));
249 fn create_local_package(pkgid: &PkgId) -> Path {
250 let parent_dir = mk_temp_workspace(&pkgid.path, &pkgid.version);
251 debug!("Created empty package dir for %s, returning %s", pkgid.to_str(), parent_dir.to_str());
252 parent_dir.pop().pop()
255 fn create_local_package_in(pkgid: &PkgId, pkgdir: &Path) -> Path {
257 let package_dir = pkgdir.push("src").push(pkgid.to_str());
259 // Create main, lib, test, and bench files
260 assert!(os::mkdir_recursive(&package_dir, U_RWX));
261 debug!("Created %s and does it exist? %?", package_dir.to_str(),
262 os::path_is_dir(&package_dir));
263 // Create main, lib, test, and bench files
265 writeFile(&package_dir.push("main.rs"),
266 "fn main() { let _x = (); }");
267 writeFile(&package_dir.push("lib.rs"),
268 "pub fn f() { let _x = (); }");
269 writeFile(&package_dir.push("test.rs"),
270 "#[test] pub fn f() { (); }");
271 writeFile(&package_dir.push("bench.rs"),
272 "#[bench] pub fn f() { (); }");
276 fn create_local_package_with_test(pkgid: &PkgId) -> Path {
277 debug!("Dry run -- would create package %s with test");
278 create_local_package(pkgid) // Already has tests???
281 fn create_local_package_with_dep(pkgid: &PkgId, subord_pkgid: &PkgId) -> Path {
282 let package_dir = create_local_package(pkgid);
283 create_local_package_in(subord_pkgid, &package_dir);
284 // Write a main.rs file into pkgid that references subord_pkgid
285 writeFile(&package_dir.push("src").push(pkgid.to_str()).push("main.rs"),
286 fmt!("extern mod %s;\nfn main() {}",
287 subord_pkgid.short_name));
288 // Write a lib.rs file into subord_pkgid that has something in it
289 writeFile(&package_dir.push("src").push(subord_pkgid.to_str()).push("lib.rs"),
291 debug!("Dry run -- would create packages %s and %s in %s",
293 subord_pkgid.to_str(),
294 package_dir.to_str());
298 fn create_local_package_with_custom_build_hook(pkgid: &PkgId,
299 custom_build_hook: &str) -> Path {
300 debug!("Dry run -- would create package %s with custom build hook %s",
301 pkgid.to_str(), custom_build_hook);
302 create_local_package(pkgid)
303 // actually write the pkg.rs with the custom build hook
307 fn assert_lib_exists(repo: &Path, short_name: &str, _v: Version) { // ??? version?
308 debug!("assert_lib_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
309 let lib = installed_library_in_workspace(short_name, repo);
310 debug!("assert_lib_exists: checking whether %? exists", lib);
311 assert!(lib.is_some());
312 let libname = lib.get_ref();
313 assert!(os::path_exists(libname));
314 assert!(is_rwx(libname));
317 fn assert_executable_exists(repo: &Path, short_name: &str) {
318 debug!("assert_executable_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
319 let exec = target_executable_in_workspace(&PkgId::new(short_name), repo);
320 assert!(os::path_exists(&exec));
321 assert!(is_rwx(&exec));
324 fn assert_built_executable_exists(repo: &Path, short_name: &str) {
325 debug!("assert_built_executable_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
326 let exec = built_executable_in_workspace(&PkgId::new(short_name),
327 repo).expect("assert_built_executable_exists failed");
328 assert!(os::path_exists(&exec));
329 assert!(is_rwx(&exec));
332 fn command_line_test_output(args: &[~str]) -> ~[~str] {
333 let mut result = ~[];
334 let p_output = command_line_test(args, &os::getcwd());
335 let test_output = str::from_bytes(p_output.output);
336 for s in test_output.split_iter('\n') {
337 result.push(s.to_owned());
342 fn command_line_test_output_with_env(args: &[~str], env: ~[(~str, ~str)]) -> ~[~str] {
343 let mut result = ~[];
344 let p_output = command_line_test_with_env(args, &os::getcwd(), Some(env));
345 let test_output = str::from_bytes(p_output.output);
346 for s in test_output.split_iter('\n') {
347 result.push(s.to_owned());
352 // assumes short_name and path are one and the same -- I should fix
353 fn lib_output_file_name(workspace: &Path, parent: &str, short_name: &str) -> Path {
354 debug!("lib_output_file_name: given %s and parent %s and short name %s",
355 workspace.to_str(), parent, short_name);
356 library_in_workspace(&Path(short_name),
361 &NoVersion).expect("lib_output_file_name")
364 fn output_file_name(workspace: &Path, short_name: &str) -> Path {
365 workspace.push(fmt!("%s%s", short_name, os::EXE_SUFFIX))
368 fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
369 use conditions::bad_path::cond;
370 let pkg_src_dir = workspace.push("src").push(pkgid.to_str());
371 let contents = os::list_dir_path(&pkg_src_dir);
372 for p in contents.iter() {
373 if p.filetype() == Some(~".rs") {
374 // should be able to do this w/o a process
375 if run::process_output("touch", [p.to_str()]).status != 0 {
376 let _ = cond.raise((pkg_src_dir.clone(), ~"Bad path"));
383 /// Add a blank line at the end
384 fn frob_source_file(workspace: &Path, pkgid: &PkgId) {
385 use conditions::bad_path::cond;
386 let pkg_src_dir = workspace.push("src").push(pkgid.to_str());
387 let contents = os::list_dir_path(&pkg_src_dir);
388 let mut maybe_p = None;
389 for p in contents.iter() {
390 if p.filetype() == Some(~".rs") {
397 let w = io::file_writer(p, &[io::Append]);
399 Err(s) => { let _ = cond.raise((p.clone(), fmt!("Bad path: %s", s))); }
400 Ok(w) => w.write_line("")
403 None => fail!(fmt!("frob_source_file failed to find a source file in %s",
404 pkg_src_dir.to_str()))
409 fn test_make_dir_rwx() {
410 let temp = &os::tmpdir();
411 let dir = temp.push("quux");
412 assert!(!os::path_exists(&dir) ||
413 os::remove_dir_recursive(&dir));
414 debug!("Trying to make %s", dir.to_str());
415 assert!(make_dir_rwx(&dir));
416 assert!(os::path_is_dir(&dir));
417 assert!(is_rwx(&dir));
418 assert!(os::remove_dir_recursive(&dir));
422 fn test_install_valid() {
423 use path_util::installed_library_in_workspace;
425 let sysroot = test_sysroot();
426 debug!("sysroot = %s", sysroot.to_str());
427 let ctxt = fake_ctxt(Some(@sysroot));
428 let temp_pkg_id = fake_pkg();
429 let temp_workspace = mk_temp_workspace(&temp_pkg_id.path, &NoVersion).pop().pop();
430 debug!("temp_workspace = %s", temp_workspace.to_str());
431 // should have test, bench, lib, and main
432 ctxt.install(&temp_workspace, &temp_pkg_id);
433 // Check that all files exist
434 let exec = target_executable_in_workspace(&temp_pkg_id, &temp_workspace);
435 debug!("exec = %s", exec.to_str());
436 assert!(os::path_exists(&exec));
437 assert!(is_rwx(&exec));
439 let lib = installed_library_in_workspace(temp_pkg_id.short_name, &temp_workspace);
440 debug!("lib = %?", lib);
441 assert!(lib.map_default(false, |l| os::path_exists(l)));
442 assert!(lib.map_default(false, |l| is_rwx(l)));
444 // And that the test and bench executables aren't installed
445 assert!(!os::path_exists(&target_test_in_workspace(&temp_pkg_id, &temp_workspace)));
446 let bench = target_bench_in_workspace(&temp_pkg_id, &temp_workspace);
447 debug!("bench = %s", bench.to_str());
448 assert!(!os::path_exists(&bench));
452 fn test_install_invalid() {
453 use conditions::nonexistent_package::cond;
454 use cond1 = conditions::missing_pkg_files::cond;
456 let ctxt = fake_ctxt(None);
457 let pkgid = fake_pkg();
458 let temp_workspace = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
459 let mut error_occurred = false;
460 let mut error1_occurred = false;
462 error1_occurred = true;
465 error_occurred = true;
466 temp_workspace.clone()
468 ctxt.install(&temp_workspace, &pkgid);
471 assert!(error_occurred && error1_occurred);
474 // Tests above should (maybe) be converted to shell out to rustpkg, too
476 fn test_install_git() {
477 let sysroot = test_sysroot();
478 debug!("sysroot = %s", sysroot.to_str());
479 let temp_pkg_id = git_repo_pkg();
480 let repo = init_git_repo(&temp_pkg_id.path);
481 debug!("repo = %s", repo.to_str());
482 let repo_subdir = repo.push("mockgithub.com").push("catamorphism").push("test-pkg");
483 debug!("repo_subdir = %s", repo_subdir.to_str());
485 writeFile(&repo_subdir.push("main.rs"),
486 "fn main() { let _x = (); }");
487 writeFile(&repo_subdir.push("lib.rs"),
488 "pub fn f() { let _x = (); }");
489 writeFile(&repo_subdir.push("test.rs"),
490 "#[test] pub fn f() { (); }");
491 writeFile(&repo_subdir.push("bench.rs"),
492 "#[bench] pub fn f() { (); }");
493 add_git_tag(&repo_subdir, ~"0.1"); // this has the effect of committing the files
495 debug!("test_install_git: calling rustpkg install %s in %s",
496 temp_pkg_id.path.to_str(), repo.to_str());
497 // should have test, bench, lib, and main
498 command_line_test([~"install", temp_pkg_id.path.to_str()], &repo);
499 let ws = repo.push(".rust");
500 // Check that all files exist
501 debug!("Checking for files in %s", ws.to_str());
502 let exec = target_executable_in_workspace(&temp_pkg_id, &ws);
503 debug!("exec = %s", exec.to_str());
504 assert!(os::path_exists(&exec));
505 assert!(is_rwx(&exec));
507 built_library_in_workspace(&temp_pkg_id,
508 &ws).expect("test_install_git: built lib should exist");
509 assert_lib_exists(&ws, temp_pkg_id.short_name, temp_pkg_id.version.clone());
510 let built_test = built_test_in_workspace(&temp_pkg_id,
511 &ws).expect("test_install_git: built test should exist");
512 assert!(os::path_exists(&built_test));
513 let built_bench = built_bench_in_workspace(&temp_pkg_id,
514 &ws).expect("test_install_git: built bench should exist");
515 assert!(os::path_exists(&built_bench));
516 // And that the test and bench executables aren't installed
517 let test = target_test_in_workspace(&temp_pkg_id, &ws);
518 assert!(!os::path_exists(&test));
519 debug!("test = %s", test.to_str());
520 let bench = target_bench_in_workspace(&temp_pkg_id, &ws);
521 debug!("bench = %s", bench.to_str());
522 assert!(!os::path_exists(&bench));
526 fn test_package_ids_must_be_relative_path_like() {
527 use conditions::bad_pkg_id::cond;
531 - One identifier, with no slashes
532 - Several slash-delimited things, with no / at the root
536 - Absolute path (as per os::is_absolute)
540 let whatever = PkgId::new("foo");
542 assert_eq!(~"foo-0.1", whatever.to_str());
543 assert!("github.com/catamorphism/test-pkg-0.1" ==
544 PkgId::new("github.com/catamorphism/test-pkg").to_str());
546 do cond.trap(|(p, e)| {
547 assert!("" == p.to_str());
548 assert!("0-length pkgid" == e);
551 let x = PkgId::new("");
552 assert_eq!(~"foo-0.1", x.to_str());
555 do cond.trap(|(p, e)| {
556 assert_eq!(p.to_str(), os::make_absolute(&Path("foo/bar/quux")).to_str());
557 assert!("absolute pkgid" == e);
560 let z = PkgId::new(os::make_absolute(&Path("foo/bar/quux")).to_str());
561 assert_eq!(~"foo-0.1", z.to_str());
567 fn test_package_version() {
568 let local_path = "mockgithub.com/catamorphism/test_pkg_version";
569 let repo = init_git_repo(&Path(local_path));
570 let repo_subdir = repo.push("mockgithub.com").push("catamorphism").push("test_pkg_version");
571 debug!("Writing files in: %s", repo_subdir.to_str());
572 writeFile(&repo_subdir.push("main.rs"),
573 "fn main() { let _x = (); }");
574 writeFile(&repo_subdir.push("lib.rs"),
575 "pub fn f() { let _x = (); }");
576 writeFile(&repo_subdir.push("test.rs"),
577 "#[test] pub fn f() { (); }");
578 writeFile(&repo_subdir.push("bench.rs"),
579 "#[bench] pub fn f() { (); }");
580 add_git_tag(&repo_subdir, ~"0.4");
582 // It won't pick up the 0.4 version because the dir isn't in the RUST_PATH, but...
583 let temp_pkg_id = PkgId::new("mockgithub.com/catamorphism/test_pkg_version");
584 // This should look at the prefix, clone into a workspace, then build.
585 command_line_test([~"install", ~"mockgithub.com/catamorphism/test_pkg_version"],
587 let ws = repo.push(".rust");
588 // we can still match on the filename to make sure it contains the 0.4 version
589 assert!(match built_library_in_workspace(&temp_pkg_id,
591 Some(p) => p.to_str().ends_with(fmt!("0.4%s", os::consts::DLL_SUFFIX)),
594 assert!(built_executable_in_workspace(&temp_pkg_id, &ws)
595 == Some(ws.push("build").
596 push("mockgithub.com").
597 push("catamorphism").
598 push("test_pkg_version").
599 push("test_pkg_version")));
603 fn test_package_request_version() {
604 let local_path = "mockgithub.com/catamorphism/test_pkg_version";
605 let repo = init_git_repo(&Path(local_path));
606 let repo_subdir = repo.push("mockgithub.com").push("catamorphism").push("test_pkg_version");
607 debug!("Writing files in: %s", repo_subdir.to_str());
608 writeFile(&repo_subdir.push("main.rs"),
609 "fn main() { let _x = (); }");
610 writeFile(&repo_subdir.push("lib.rs"),
611 "pub fn f() { let _x = (); }");
612 writeFile(&repo_subdir.push("test.rs"),
613 "#[test] pub fn f() { (); }");
614 writeFile(&repo_subdir.push("bench.rs"),
615 "#[bench] pub fn f() { (); }");
616 writeFile(&repo_subdir.push("version-0.3-file.txt"), "hi");
617 add_git_tag(&repo_subdir, ~"0.3");
618 writeFile(&repo_subdir.push("version-0.4-file.txt"), "hello");
619 add_git_tag(&repo_subdir, ~"0.4");
621 command_line_test([~"install", fmt!("%s#0.3", local_path)], &repo);
623 assert!(match installed_library_in_workspace("test_pkg_version", &repo.push(".rust")) {
625 debug!("installed: %s", p.to_str());
626 p.to_str().ends_with(fmt!("0.3%s", os::consts::DLL_SUFFIX))
630 let temp_pkg_id = PkgId::new("mockgithub.com/catamorphism/test_pkg_version#0.3");
631 assert!(target_executable_in_workspace(&temp_pkg_id, &repo.push(".rust"))
632 == repo.push(".rust").push("bin").push("test_pkg_version"));
634 assert!(os::path_exists(&repo.push(".rust").push("src")
635 .push("mockgithub.com").push("catamorphism")
636 .push("test_pkg_version-0.3")
637 .push("version-0.3-file.txt")));
638 assert!(!os::path_exists(&repo.push(".rust").push("src")
639 .push("mockgithub.com").push("catamorphism")
640 .push("test_pkg_version-0.3")
641 .push("version-0.4-file.txt")));
645 #[ignore (reason = "http-client not ported to rustpkg yet")]
646 fn rustpkg_install_url_2() {
647 let temp_dir = mkdtemp(&os::tmpdir(), "rustpkg_install_url_2").expect("rustpkg_install_url_2");
648 command_line_test([~"install", ~"github.com/mozilla-servo/rust-http-client"],
653 fn rustpkg_library_target() {
654 let foo_repo = init_git_repo(&Path("foo"));
655 let package_dir = foo_repo.push("foo");
657 debug!("Writing files in: %s", package_dir.to_str());
658 writeFile(&package_dir.push("main.rs"),
659 "fn main() { let _x = (); }");
660 writeFile(&package_dir.push("lib.rs"),
661 "pub fn f() { let _x = (); }");
662 writeFile(&package_dir.push("test.rs"),
663 "#[test] pub fn f() { (); }");
664 writeFile(&package_dir.push("bench.rs"),
665 "#[bench] pub fn f() { (); }");
667 add_git_tag(&package_dir, ~"1.0");
668 command_line_test([~"install", ~"foo"], &foo_repo);
669 assert_lib_exists(&foo_repo.push(".rust"), "foo", ExactRevision(~"1.0"));
673 fn rustpkg_local_pkg() {
674 let dir = create_local_package(&PkgId::new("foo"));
675 command_line_test([~"install", ~"foo"], &dir);
676 assert_executable_exists(&dir, "foo");
680 #[ignore (reason = "test makes bogus assumptions about build directory layout: issue #8690")]
681 fn package_script_with_default_build() {
682 let dir = create_local_package(&PkgId::new("fancy-lib"));
683 debug!("dir = %s", dir.to_str());
684 let source = test_sysroot().pop().pop().pop().push("src").push("librustpkg").
685 push("testsuite").push("pass").push("src").push("fancy-lib").push("pkg.rs");
686 debug!("package_script_with_default_build: %s", source.to_str());
687 if !os::copy_file(&source,
688 &dir.push("src").push("fancy-lib-0.1").push("pkg.rs")) {
689 fail!("Couldn't copy file");
691 command_line_test([~"install", ~"fancy-lib"], &dir);
692 assert_lib_exists(&dir, "fancy-lib", NoVersion);
693 assert!(os::path_exists(&dir.push("build").push("fancy-lib").push("generated.rs")));
697 fn rustpkg_build_no_arg() {
698 let tmp = mkdtemp(&os::tmpdir(), "rustpkg_build_no_arg").expect("rustpkg_build_no_arg failed");
699 let package_dir = tmp.push("src").push("foo");
700 assert!(os::mkdir_recursive(&package_dir, U_RWX));
702 writeFile(&package_dir.push("main.rs"),
703 "fn main() { let _x = (); }");
704 debug!("build_no_arg: dir = %s", package_dir.to_str());
705 command_line_test([~"build"], &package_dir);
706 assert_built_executable_exists(&tmp, "foo");
710 fn rustpkg_install_no_arg() {
711 let tmp = mkdtemp(&os::tmpdir(),
712 "rustpkg_install_no_arg").expect("rustpkg_install_no_arg failed");
713 let package_dir = tmp.push("src").push("foo");
714 assert!(os::mkdir_recursive(&package_dir, U_RWX));
715 writeFile(&package_dir.push("lib.rs"),
716 "fn main() { let _x = (); }");
717 debug!("install_no_arg: dir = %s", package_dir.to_str());
718 command_line_test([~"install"], &package_dir);
719 assert_lib_exists(&tmp, "foo", NoVersion);
723 fn rustpkg_clean_no_arg() {
724 let tmp = mkdtemp(&os::tmpdir(), "rustpkg_clean_no_arg").expect("rustpkg_clean_no_arg failed");
725 let package_dir = tmp.push("src").push("foo");
726 assert!(os::mkdir_recursive(&package_dir, U_RWX));
728 writeFile(&package_dir.push("main.rs"),
729 "fn main() { let _x = (); }");
730 debug!("clean_no_arg: dir = %s", package_dir.to_str());
731 command_line_test([~"build"], &package_dir);
732 assert_built_executable_exists(&tmp, "foo");
733 command_line_test([~"clean"], &package_dir);
734 assert!(!built_executable_in_workspace(&PkgId::new("foo"),
735 &tmp).map_default(false, |m| { os::path_exists(m) }));
739 fn rust_path_test() {
740 let dir_for_path = mkdtemp(&os::tmpdir(), "more_rust").expect("rust_path_test failed");
741 let dir = mk_workspace(&dir_for_path, &Path("foo"), &NoVersion);
742 debug!("dir = %s", dir.to_str());
743 writeFile(&dir.push("main.rs"), "fn main() { let _x = (); }");
745 let cwd = os::getcwd();
746 debug!("cwd = %s", cwd.to_str());
747 // use command_line_test_with_env
748 command_line_test_with_env([~"install", ~"foo"],
750 Some(~[(~"RUST_PATH", dir_for_path.to_str())]));
751 assert_executable_exists(&dir_for_path, "foo");
755 fn rust_path_contents() {
756 use std::unstable::change_dir_locked;
758 let dir = mkdtemp(&os::tmpdir(), "rust_path").expect("rust_path_contents failed");
759 let abc = &dir.push("A").push("B").push("C");
760 assert!(os::mkdir_recursive(&abc.push(".rust"), U_RWX));
761 assert!(os::mkdir_recursive(&abc.pop().push(".rust"), U_RWX));
762 assert!(os::mkdir_recursive(&abc.pop().pop().push(".rust"), U_RWX));
763 assert!(do change_dir_locked(&dir.push("A").push("B").push("C")) {
765 let cwd = os::getcwd().push(".rust");
766 let parent = cwd.pop().pop().push(".rust");
767 let grandparent = cwd.pop().pop().pop().push(".rust");
768 assert!(p.contains(&cwd));
769 assert!(p.contains(&parent));
770 assert!(p.contains(&grandparent));
771 for a_path in p.iter() {
772 assert!(!a_path.components.is_empty());
778 fn rust_path_parse() {
779 os::setenv("RUST_PATH", "/a/b/c:/d/e/f:/g/h/i");
780 let paths = rust_path();
781 assert!(paths.contains(&Path("/g/h/i")));
782 assert!(paths.contains(&Path("/d/e/f")));
783 assert!(paths.contains(&Path("/a/b/c")));
784 os::unsetenv("RUST_PATH");
789 let dir = mkdtemp(&os::tmpdir(), "test_list").expect("test_list failed");
790 let foo = PkgId::new("foo");
791 create_local_package_in(&foo, &dir);
792 let bar = PkgId::new("bar");
793 create_local_package_in(&bar, &dir);
794 let quux = PkgId::new("quux");
795 create_local_package_in(&quux, &dir);
797 // list doesn't output very much right now...
798 command_line_test([~"install", ~"foo"], &dir);
799 let env_arg = ~[(~"RUST_PATH", dir.to_str())];
800 debug!("RUST_PATH = %s", dir.to_str());
801 let list_output = command_line_test_output_with_env([~"list"], env_arg.clone());
802 assert!(list_output.iter().any(|x| x.starts_with("foo")));
804 command_line_test([~"install", ~"bar"], &dir);
805 let list_output = command_line_test_output_with_env([~"list"], env_arg.clone());
806 assert!(list_output.iter().any(|x| x.starts_with("foo")));
807 assert!(list_output.iter().any(|x| x.starts_with("bar")));
809 command_line_test([~"install", ~"quux"], &dir);
810 let list_output = command_line_test_output_with_env([~"list"], env_arg);
811 assert!(list_output.iter().any(|x| x.starts_with("foo")));
812 assert!(list_output.iter().any(|x| x.starts_with("bar")));
813 assert!(list_output.iter().any(|x| x.starts_with("quux")));
817 fn install_remove() {
818 let dir = mkdtemp(&os::tmpdir(), "install_remove").expect("install_remove");
819 let foo = PkgId::new("foo");
820 let bar = PkgId::new("bar");
821 let quux = PkgId::new("quux");
822 create_local_package_in(&foo, &dir);
823 create_local_package_in(&bar, &dir);
824 create_local_package_in(&quux, &dir);
825 let rust_path_to_use = ~[(~"RUST_PATH", dir.to_str())];
826 command_line_test([~"install", ~"foo"], &dir);
827 command_line_test([~"install", ~"bar"], &dir);
828 command_line_test([~"install", ~"quux"], &dir);
829 let list_output = command_line_test_output_with_env([~"list"], rust_path_to_use.clone());
830 assert!(list_output.iter().any(|x| x.starts_with("foo")));
831 assert!(list_output.iter().any(|x| x.starts_with("bar")));
832 assert!(list_output.iter().any(|x| x.starts_with("quux")));
833 command_line_test([~"uninstall", ~"foo"], &dir);
834 let list_output = command_line_test_output_with_env([~"list"], rust_path_to_use.clone());
835 assert!(!list_output.iter().any(|x| x.starts_with("foo")));
836 assert!(list_output.iter().any(|x| x.starts_with("bar")));
837 assert!(list_output.iter().any(|x| x.starts_with("quux")));
841 fn install_check_duplicates() {
842 // should check that we don't install two packages with the same full name *and* version
843 // ("Is already installed -- doing nothing")
844 // check invariant that there are no dups in the pkg database
845 let dir = mkdtemp(&os::tmpdir(), "install_remove").expect("install_remove");
846 let foo = PkgId::new("foo");
847 create_local_package_in(&foo, &dir);
849 command_line_test([~"install", ~"foo"], &dir);
850 command_line_test([~"install", ~"foo"], &dir);
851 let mut contents = ~[];
852 let check_dups = |p: &PkgId| {
853 if contents.contains(p) {
854 fail!("package %s appears in `list` output more than once", p.path.to_str());
857 contents.push((*p).clone());
861 list_installed_packages(check_dups);
865 #[ignore(reason = "Workcache not yet implemented -- see #7075")]
867 let p_id = PkgId::new("foo");
868 let workspace = create_local_package(&p_id);
869 command_line_test([~"build", ~"foo"], &workspace);
870 let date = datestamp(&built_library_in_workspace(&p_id,
871 &workspace).expect("no_rebuilding"));
872 command_line_test([~"build", ~"foo"], &workspace);
873 let newdate = datestamp(&built_library_in_workspace(&p_id,
874 &workspace).expect("no_rebuilding (2)"));
875 assert_eq!(date, newdate);
879 #[ignore(reason = "Workcache not yet implemented -- see #7075")]
880 fn no_rebuilding_dep() {
881 let p_id = PkgId::new("foo");
882 let dep_id = PkgId::new("bar");
883 let workspace = create_local_package_with_dep(&p_id, &dep_id);
884 command_line_test([~"build", ~"foo"], &workspace);
885 let bar_date = datestamp(&lib_output_file_name(&workspace,
888 let foo_date = datestamp(&output_file_name(&workspace, "foo"));
889 assert!(bar_date < foo_date);
892 // n.b. The following two tests are ignored; they worked "accidentally" before,
893 // when the behavior was "always rebuild libraries" (now it's "never rebuild
894 // libraries if they already exist"). They can be un-ignored once #7075 is done.
896 #[ignore(reason = "Workcache not yet implemented -- see #7075")]
897 fn do_rebuild_dep_dates_change() {
898 let p_id = PkgId::new("foo");
899 let dep_id = PkgId::new("bar");
900 let workspace = create_local_package_with_dep(&p_id, &dep_id);
901 command_line_test([~"build", ~"foo"], &workspace);
902 let bar_lib_name = lib_output_file_name(&workspace, "build", "bar");
903 let bar_date = datestamp(&bar_lib_name);
904 debug!("Datestamp on %s is %?", bar_lib_name.to_str(), bar_date);
905 touch_source_file(&workspace, &dep_id);
906 command_line_test([~"build", ~"foo"], &workspace);
907 let new_bar_date = datestamp(&bar_lib_name);
908 debug!("Datestamp on %s is %?", bar_lib_name.to_str(), new_bar_date);
909 assert!(new_bar_date > bar_date);
913 #[ignore(reason = "Workcache not yet implemented -- see #7075")]
914 fn do_rebuild_dep_only_contents_change() {
915 let p_id = PkgId::new("foo");
916 let dep_id = PkgId::new("bar");
917 let workspace = create_local_package_with_dep(&p_id, &dep_id);
918 command_line_test([~"build", ~"foo"], &workspace);
919 let bar_date = datestamp(&lib_output_file_name(&workspace, "build", "bar"));
920 frob_source_file(&workspace, &dep_id);
921 // should adjust the datestamp
922 command_line_test([~"build", ~"foo"], &workspace);
923 let new_bar_date = datestamp(&lib_output_file_name(&workspace, "build", "bar"));
924 assert!(new_bar_date > bar_date);
929 let workspace = create_local_package(&PkgId::new("foo#0.1"));
930 create_local_package(&PkgId::new("foo#0.2"));
931 command_line_test([~"install", ~"foo#0.1"], &workspace);
932 let output = command_line_test_output([~"list"]);
933 // make sure output includes versions
934 assert!(!output.iter().any(|x| x == &~"foo#0.2"));
938 #[ignore(reason = "do not yet implemented")]
939 fn test_build_hooks() {
940 let workspace = create_local_package_with_custom_build_hook(&PkgId::new("foo"),
942 command_line_test([~"do", ~"foo", ~"frob"], &workspace);
947 #[ignore(reason = "info not yet implemented")]
949 let expected_info = ~"package foo"; // fill in
950 let workspace = create_local_package(&PkgId::new("foo"));
951 let output = command_line_test([~"info", ~"foo"], &workspace);
952 assert_eq!(str::from_bytes(output.output), expected_info);
956 #[ignore(reason = "test not yet implemented")]
957 fn test_rustpkg_test() {
958 let expected_results = ~"1 out of 1 tests passed"; // fill in
959 let workspace = create_local_package_with_test(&PkgId::new("foo"));
960 let output = command_line_test([~"test", ~"foo"], &workspace);
961 assert_eq!(str::from_bytes(output.output), expected_results);
965 #[ignore(reason = "test not yet implemented")]
966 fn test_uninstall() {
967 let workspace = create_local_package(&PkgId::new("foo"));
968 let _output = command_line_test([~"info", ~"foo"], &workspace);
969 command_line_test([~"uninstall", ~"foo"], &workspace);
970 let output = command_line_test([~"list"], &workspace);
971 assert!(!str::from_bytes(output.output).contains("foo"));
975 fn test_non_numeric_tag() {
976 let temp_pkg_id = git_repo_pkg();
977 let repo = init_git_repo(&temp_pkg_id.path);
978 let repo_subdir = repo.push("mockgithub.com").push("catamorphism").push("test-pkg");
979 writeFile(&repo_subdir.push("foo"), "foo");
980 writeFile(&repo_subdir.push("lib.rs"),
981 "pub fn f() { let _x = (); }");
982 add_git_tag(&repo_subdir, ~"testbranch");
983 writeFile(&repo_subdir.push("testbranch_only"), "hello");
984 add_git_tag(&repo_subdir, ~"another_tag");
985 writeFile(&repo_subdir.push("not_on_testbranch_only"), "bye bye");
986 add_all_and_commit(&repo_subdir);
988 command_line_test([~"install", fmt!("%s#testbranch", temp_pkg_id.path.to_str())], &repo);
989 let file1 = repo.push_many(["mockgithub.com", "catamorphism",
990 "test-pkg", "testbranch_only"]);
991 let file2 = repo.push_many(["mockgithub.com", "catamorphism", "test-pkg",
993 assert!(os::path_exists(&file1));
994 assert!(!os::path_exists(&file2));
998 fn test_extern_mod() {
999 let dir = mkdtemp(&os::tmpdir(), "test_extern_mod").expect("test_extern_mod");
1000 let main_file = dir.push("main.rs");
1001 let lib_depend_dir = mkdtemp(&os::tmpdir(), "foo").expect("test_extern_mod");
1002 let aux_dir = lib_depend_dir.push_many(["src", "mockgithub.com", "catamorphism", "test_pkg"]);
1003 assert!(os::mkdir_recursive(&aux_dir, U_RWX));
1004 let aux_pkg_file = aux_dir.push("lib.rs");
1006 writeFile(&aux_pkg_file, "pub mod bar { pub fn assert_true() { assert!(true); } }\n");
1007 assert!(os::path_exists(&aux_pkg_file));
1009 writeFile(&main_file,
1010 "extern mod test = \"mockgithub.com/catamorphism/test_pkg\";\nuse test::bar;\
1011 fn main() { bar::assert_true(); }\n");
1013 command_line_test([~"install", ~"mockgithub.com/catamorphism/test_pkg"], &lib_depend_dir);
1015 let exec_file = dir.push("out");
1016 // Be sure to extend the existing environment
1017 let env = Some([(~"RUST_PATH", lib_depend_dir.to_str())] + os::env());
1018 let rustpkg_exec = rustpkg_exec();
1019 let rustc = rustpkg_exec.with_filename("rustc");
1020 debug!("RUST_PATH=%s %s %s \n --sysroot %s -o %s",
1021 lib_depend_dir.to_str(),
1024 test_sysroot().to_str(),
1025 exec_file.to_str());
1027 let mut prog = run::Process::new(rustc.to_str(), [main_file.to_str(),
1028 ~"--sysroot", test_sysroot().to_str(),
1029 ~"-o", exec_file.to_str()],
1030 run::ProcessOptions {
1037 let outp = prog.finish_with_output();
1038 if outp.status != 0 {
1039 fail!("output was %s, error was %s",
1040 str::from_bytes(outp.output),
1041 str::from_bytes(outp.error));
1043 assert!(os::path_exists(&exec_file) && is_executable(&exec_file));
1047 fn test_import_rustpkg() {
1048 let p_id = PkgId::new("foo");
1049 let workspace = create_local_package(&p_id);
1050 writeFile(&workspace.push("src").push("foo-0.1").push("pkg.rs"),
1051 "extern mod rustpkg; fn main() {}");
1052 command_line_test([~"build", ~"foo"], &workspace);
1053 debug!("workspace = %s", workspace.to_str());
1054 assert!(os::path_exists(&workspace.push("build").push("foo").push(fmt!("pkg%s",
1059 fn test_macro_pkg_script() {
1060 let p_id = PkgId::new("foo");
1061 let workspace = create_local_package(&p_id);
1062 writeFile(&workspace.push("src").push("foo-0.1").push("pkg.rs"),
1063 "extern mod rustpkg; fn main() { debug!(\"Hi\"); }");
1064 command_line_test([~"build", ~"foo"], &workspace);
1065 debug!("workspace = %s", workspace.to_str());
1066 assert!(os::path_exists(&workspace.push("build").push("foo").push(fmt!("pkg%s",
1071 fn multiple_workspaces() {
1072 // Make a package foo; build/install in directory A
1073 // Copy the exact same package into directory B and install it
1074 // Set the RUST_PATH to A:B
1075 // Make a third package that uses foo, make sure we can build/install it
1076 let a_loc = mk_temp_workspace(&Path("foo"), &NoVersion).pop().pop();
1077 let b_loc = mk_temp_workspace(&Path("foo"), &NoVersion).pop().pop();
1078 debug!("Trying to install foo in %s", a_loc.to_str());
1079 command_line_test([~"install", ~"foo"], &a_loc);
1080 debug!("Trying to install foo in %s", b_loc.to_str());
1081 command_line_test([~"install", ~"foo"], &b_loc);
1082 let env = Some(~[(~"RUST_PATH", fmt!("%s:%s", a_loc.to_str(), b_loc.to_str()))]);
1083 let c_loc = create_local_package_with_dep(&PkgId::new("bar"), &PkgId::new("foo"));
1084 command_line_test_with_env([~"install", ~"bar"], &c_loc, env);
1087 /// Returns true if p exists and is executable
1088 fn is_executable(p: &Path) -> bool {
1089 use std::libc::consts::os::posix88::{S_IXUSR};
1091 match p.get_mode() {
1093 Some(mode) => mode & S_IXUSR as uint == S_IXUSR as uint