]> git.lizzy.rs Git - rust.git/blob - src/librustpkg/tests.rs
Add generation of static libraries to rustc
[rust.git] / src / librustpkg / tests.rs
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.
4 //
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.
10
11 // rustpkg unit tests
12
13 use context::{BuildContext, Context, RustcFlags};
14 use std::{os, run, str, task};
15 use std::io;
16 use std::io::fs;
17 use std::io::File;
18 use std::io::process;
19 use std::io::process::ProcessExit;
20 use extra::arc::Arc;
21 use extra::arc::RWArc;
22 use extra::tempfile::TempDir;
23 use extra::workcache;
24 use extra::workcache::{Database, Logger};
25 use extra::treemap::TreeMap;
26 use extra::getopts::groups::getopts;
27 use std::run::ProcessOutput;
28 use installed_packages::list_installed_packages;
29 use package_id::{PkgId};
30 use version::{ExactRevision, NoVersion, Version, Tagged};
31 use path_util::{target_executable_in_workspace, target_test_in_workspace,
32                target_bench_in_workspace, make_dir_rwx,
33                library_in_workspace, installed_library_in_workspace,
34                built_bench_in_workspace, built_test_in_workspace,
35                built_library_in_workspace, built_executable_in_workspace, target_build_dir,
36                chmod_read_only, platform_library_name};
37 use rustc::back::link::get_cc_prog;
38 use rustc::metadata::filesearch::rust_path;
39 use rustc::driver::session;
40 use rustc::driver::driver::{build_session, build_session_options, host_triple, optgroups};
41 use syntax::diagnostic;
42 use target::*;
43 use package_source::PkgSrc;
44 use source_control::{CheckedOutSources, DirToUse, safe_git_clone};
45 use exit_codes::{BAD_FLAG_CODE, COPY_FAILED_CODE};
46
47 fn fake_ctxt(sysroot: Path, workspace: &Path) -> BuildContext {
48     let context = workcache::Context::new(
49         RWArc::new(Database::new(workspace.join("rustpkg_db.json"))),
50         RWArc::new(Logger::new()),
51         Arc::new(TreeMap::new()));
52     BuildContext {
53         workcache_context: context,
54         context: Context {
55             cfgs: ~[],
56             rustc_flags: RustcFlags::default(),
57
58             use_rust_path_hack: false,
59             sysroot: sysroot
60         }
61     }
62 }
63
64 fn fake_pkg() -> PkgId {
65     let sn = ~"bogus";
66     PkgId {
67         path: Path::init(sn.as_slice()),
68         short_name: sn,
69         version: NoVersion
70     }
71 }
72
73 fn git_repo_pkg() -> PkgId {
74     PkgId {
75         path: Path::init("mockgithub.com/catamorphism/test-pkg"),
76         short_name: ~"test-pkg",
77         version: NoVersion
78     }
79 }
80
81 fn git_repo_pkg_with_tag(a_tag: ~str) -> PkgId {
82     PkgId {
83         path: Path::init("mockgithub.com/catamorphism/test-pkg"),
84         short_name: ~"test-pkg",
85         version: Tagged(a_tag)
86     }
87 }
88
89 fn writeFile(file_path: &Path, contents: &str) {
90     let mut out = File::create(file_path);
91     out.write(contents.as_bytes());
92     out.write(['\n' as u8]);
93 }
94
95 fn mk_emptier_workspace(tag: &str) -> TempDir {
96     let workspace = TempDir::new(tag).expect("couldn't create temp dir");
97     let package_dir = workspace.path().join("src");
98     fs::mkdir_recursive(&package_dir, io::UserRWX);
99     workspace
100 }
101
102 fn mk_empty_workspace(short_name: &Path, version: &Version, tag: &str) -> TempDir {
103     let workspace_dir = TempDir::new(tag).expect("couldn't create temp dir");
104     mk_workspace(workspace_dir.path(), short_name, version);
105     workspace_dir
106 }
107
108 fn mk_workspace(workspace: &Path, short_name: &Path, version: &Version) -> Path {
109     // include version number in directory name
110     // FIXME (#9639): This needs to handle non-utf8 paths
111     let package_dir = workspace.join_many([~"src", format!("{}-{}",
112                                            short_name.as_str().unwrap(), version.to_str())]);
113     fs::mkdir_recursive(&package_dir, io::UserRWX);
114     package_dir
115 }
116
117 fn mk_temp_workspace(short_name: &Path, version: &Version) -> (TempDir, Path) {
118     let workspace_dir = mk_empty_workspace(short_name, version, "temp_workspace");
119     // FIXME (#9639): This needs to handle non-utf8 paths
120     let package_dir = workspace_dir.path().join_many([~"src",
121                                                       format!("{}-{}",
122                                                               short_name.as_str().unwrap(),
123                                                               version.to_str())]);
124
125     debug!("Created {} and does it exist? {:?}", package_dir.display(),
126            package_dir.is_dir());
127     // Create main, lib, test, and bench files
128     debug!("mk_workspace: creating {}", package_dir.display());
129     fs::mkdir_recursive(&package_dir, io::UserRWX);
130     debug!("Created {} and does it exist? {:?}", package_dir.display(),
131            package_dir.is_dir());
132     // Create main, lib, test, and bench files
133
134     writeFile(&package_dir.join("main.rs"),
135               "fn main() { let _x = (); }");
136     writeFile(&package_dir.join("lib.rs"),
137               "pub fn f() { let _x = (); }");
138     writeFile(&package_dir.join("test.rs"),
139               "#[test] pub fn f() { (); }");
140     writeFile(&package_dir.join("bench.rs"),
141               "#[bench] pub fn f() { (); }");
142     (workspace_dir, package_dir)
143 }
144
145 fn run_git(args: &[~str], env: Option<~[(~str, ~str)]>, cwd: &Path, err_msg: &str) {
146     let cwd = (*cwd).clone();
147     let mut prog = run::Process::new("git", args, run::ProcessOptions {
148         env: env,
149         dir: Some(&cwd),
150         in_fd: None,
151         out_fd: None,
152         err_fd: None
153     });
154     let rslt = prog.finish_with_output();
155     if !rslt.status.success() {
156         fail!("{} [git returned {:?}, output = {}, error = {}]", err_msg,
157            rslt.status, str::from_utf8(rslt.output), str::from_utf8(rslt.error));
158     }
159 }
160
161 /// Should create an empty git repo in p, relative to the tmp dir, and return the new
162 /// absolute path
163 fn init_git_repo(p: &Path) -> TempDir {
164     assert!(p.is_relative());
165     let tmp = TempDir::new("git_local").expect("couldn't create temp dir");
166     let work_dir = tmp.path().join(p);
167     let work_dir_for_opts = work_dir.clone();
168     fs::mkdir_recursive(&work_dir, io::UserRWX);
169     debug!("Running: git init in {}", work_dir.display());
170     run_git([~"init"], None, &work_dir_for_opts,
171         format!("Couldn't initialize git repository in {}", work_dir.display()));
172     // Add stuff to the dir so that git tag succeeds
173     writeFile(&work_dir.join("README"), "");
174     run_git([~"add", ~"README"], None, &work_dir_for_opts, format!("Couldn't add in {}",
175                                                                 work_dir.display()));
176     git_commit(&work_dir_for_opts, ~"whatever");
177     tmp
178 }
179
180 fn add_all_and_commit(repo: &Path) {
181     git_add_all(repo);
182     git_commit(repo, ~"floop");
183 }
184
185 fn git_commit(repo: &Path, msg: ~str) {
186     run_git([~"commit", ~"--author=tester <test@mozilla.com>", ~"-m", msg],
187             None, repo, format!("Couldn't commit in {}", repo.display()));
188 }
189
190 fn git_add_all(repo: &Path) {
191     run_git([~"add", ~"-A"], None, repo, format!("Couldn't add all files in {}", repo.display()));
192 }
193
194 fn add_git_tag(repo: &Path, tag: ~str) {
195     assert!(repo.is_absolute());
196     git_add_all(repo);
197     git_commit(repo, ~"whatever");
198     run_git([~"tag", tag.clone()], None, repo,
199             format!("Couldn't add git tag {} in {}", tag, repo.display()));
200 }
201
202 fn is_rwx(p: &Path) -> bool {
203     if !p.exists() { return false }
204     p.stat().perm & io::UserRWX == io::UserRWX
205 }
206
207 fn is_read_only(p: &Path) -> bool {
208     if !p.exists() { return false }
209     p.stat().perm & io::UserRWX == io::UserRead
210 }
211
212 fn test_sysroot() -> Path {
213     // Totally gross hack but it's just for test cases.
214     // Infer the sysroot from the exe name and pray that it's right.
215     // (Did I mention it was a gross hack?)
216     let mut self_path = os::self_exe_path().expect("Couldn't get self_exe path");
217     self_path.pop();
218     self_path
219 }
220
221 // Returns the path to rustpkg
222 fn rustpkg_exec() -> Path {
223     // Ugh
224     let first_try = test_sysroot().join_many(
225         [~"lib", ~"rustc", host_triple(), ~"bin", ~"rustpkg"]);
226     if is_executable(&first_try) {
227         first_try
228     }
229     else {
230         let second_try = test_sysroot().join_many(["bin", "rustpkg"]);
231         if is_executable(&second_try) {
232             second_try
233         }
234         else {
235             fail!("in rustpkg test, can't find an installed rustpkg");
236         }
237     }
238 }
239
240 fn command_line_test(args: &[~str], cwd: &Path) -> ProcessOutput {
241     match command_line_test_with_env(args, cwd, None) {
242         Success(r) => r,
243         Fail(error) => fail!("Command line test failed with error {}",
244                              error.status)
245     }
246 }
247
248 fn command_line_test_partial(args: &[~str], cwd: &Path) -> ProcessResult {
249     command_line_test_with_env(args, cwd, None)
250 }
251
252 fn command_line_test_expect_fail(args: &[~str],
253                                  cwd: &Path,
254                                  env: Option<~[(~str, ~str)]>,
255                                  expected_exitcode: int) {
256     match command_line_test_with_env(args, cwd, env) {
257         Success(_) => fail!("Should have failed with {}, but it succeeded", expected_exitcode),
258         Fail(ref error) if error.status.matches_exit_status(expected_exitcode) => (), // ok
259         Fail(other) => fail!("Expected to fail with {}, but failed with {} instead",
260                               expected_exitcode, other.status)
261     }
262 }
263
264 enum ProcessResult {
265     Success(ProcessOutput),
266     Fail(ProcessOutput)
267 }
268
269 /// Runs `rustpkg` (based on the directory that this executable was
270 /// invoked from) with the given arguments, in the given working directory.
271 /// Returns the process's output.
272 fn command_line_test_with_env(args: &[~str], cwd: &Path, env: Option<~[(~str, ~str)]>)
273     -> ProcessResult {
274     // FIXME (#9639): This needs to handle non-utf8 paths
275     let exec_path = rustpkg_exec();
276     let cmd = exec_path.as_str().unwrap().to_owned();
277     let env_str = match env {
278         Some(ref pairs) => pairs.map(|&(ref k, ref v)| { format!("{}={}", *k, *v) }).connect(","),
279         None        => ~""
280     };
281     debug!("{} cd {}; {} {}", env_str, cwd.display(), cmd, args.connect(" "));
282     assert!(cwd.is_dir());
283     let cwd = (*cwd).clone();
284     let mut prog = run::Process::new(cmd, args, run::ProcessOptions {
285         env: env.map(|e| e + os::env()),
286         dir: Some(&cwd),
287         in_fd: None,
288         out_fd: None,
289         err_fd: None
290     });
291     let output = prog.finish_with_output();
292     debug!("Output from command {} with args {:?} was {} \\{{}\\}[{:?}]",
293                     cmd, args, str::from_utf8(output.output),
294                    str::from_utf8(output.error),
295                    output.status);
296     if !output.status.success() {
297         debug!("Command {} {:?} failed with exit code {:?}; its output was --- {} ---",
298               cmd, args, output.status,
299               str::from_utf8(output.output) + str::from_utf8(output.error));
300         Fail(output)
301     }
302     else {
303         Success(output)
304     }
305 }
306
307 fn create_local_package(pkgid: &PkgId) -> TempDir {
308     let (workspace, parent_dir) = mk_temp_workspace(&pkgid.path, &pkgid.version);
309     debug!("Created empty package dir for {}, returning {}", pkgid.to_str(), parent_dir.display());
310     workspace
311 }
312
313 fn create_local_package_in(pkgid: &PkgId, pkgdir: &Path) -> Path {
314
315     let package_dir = pkgdir.join_many([~"src", pkgid.to_str()]);
316
317     // Create main, lib, test, and bench files
318     fs::mkdir_recursive(&package_dir, io::UserRWX);
319     debug!("Created {} and does it exist? {:?}", package_dir.display(),
320            package_dir.is_dir());
321     // Create main, lib, test, and bench files
322
323     writeFile(&package_dir.join("main.rs"),
324               "fn main() { let _x = (); }");
325     writeFile(&package_dir.join("lib.rs"),
326               "pub fn f() { let _x = (); }");
327     writeFile(&package_dir.join("test.rs"),
328               "#[test] pub fn f() { (); }");
329     writeFile(&package_dir.join("bench.rs"),
330               "#[bench] pub fn f() { (); }");
331     package_dir
332 }
333
334 fn create_local_package_with_test(pkgid: &PkgId) -> TempDir {
335     debug!("Dry run -- would create package {:?} with test", pkgid);
336     create_local_package(pkgid) // Already has tests???
337 }
338
339 fn create_local_package_with_dep(pkgid: &PkgId, subord_pkgid: &PkgId) -> TempDir {
340     let package_dir = create_local_package(pkgid);
341     create_local_package_in(subord_pkgid, package_dir.path());
342     // Write a main.rs file into pkgid that references subord_pkgid
343     writeFile(&package_dir.path().join_many([~"src", pkgid.to_str(), ~"main.rs"]),
344               format!("extern mod {};\nfn main() \\{\\}",
345                    subord_pkgid.short_name));
346     // Write a lib.rs file into subord_pkgid that has something in it
347     writeFile(&package_dir.path().join_many([~"src", subord_pkgid.to_str(), ~"lib.rs"]),
348               "pub fn f() {}");
349     package_dir
350 }
351
352 fn create_local_package_with_custom_build_hook(pkgid: &PkgId,
353                                                custom_build_hook: &str) -> TempDir {
354     debug!("Dry run -- would create package {} with custom build hook {}",
355            pkgid.to_str(), custom_build_hook);
356     create_local_package(pkgid)
357     // actually write the pkg.rs with the custom build hook
358
359 }
360
361 fn assert_lib_exists(repo: &Path, pkg_path: &Path, v: Version) {
362     assert!(lib_exists(repo, pkg_path, v));
363 }
364
365 fn lib_exists(repo: &Path, pkg_path: &Path, _v: Version) -> bool { // ??? version?
366     debug!("assert_lib_exists: repo = {}, pkg_path = {}", repo.display(), pkg_path.display());
367     let lib = installed_library_in_workspace(pkg_path, repo);
368     debug!("assert_lib_exists: checking whether {:?} exists", lib);
369     lib.is_some() && {
370         let libname = lib.get_ref();
371         libname.exists() && is_rwx(libname)
372     }
373 }
374
375 fn assert_executable_exists(repo: &Path, short_name: &str) {
376     assert!(executable_exists(repo, short_name));
377 }
378
379 fn executable_exists(repo: &Path, short_name: &str) -> bool {
380     debug!("executable_exists: repo = {}, short_name = {}", repo.display(), short_name);
381     let exec = target_executable_in_workspace(&PkgId::new(short_name), repo);
382     exec.exists() && is_rwx(&exec)
383 }
384
385 fn test_executable_exists(repo: &Path, short_name: &str) -> bool {
386     debug!("test_executable_exists: repo = {}, short_name = {}", repo.display(), short_name);
387     let exec = built_test_in_workspace(&PkgId::new(short_name), repo);
388     exec.map_default(false, |exec| exec.exists() && is_rwx(&exec))
389 }
390
391 fn remove_executable_file(p: &PkgId, workspace: &Path) {
392     let exec = target_executable_in_workspace(&PkgId::new(p.short_name), workspace);
393     if exec.exists() {
394         fs::unlink(&exec);
395     }
396 }
397
398 fn assert_built_executable_exists(repo: &Path, short_name: &str) {
399     assert!(built_executable_exists(repo, short_name));
400 }
401
402 fn built_executable_exists(repo: &Path, short_name: &str) -> bool {
403     debug!("assert_built_executable_exists: repo = {}, short_name = {}",
404             repo.display(), short_name);
405     let exec = built_executable_in_workspace(&PkgId::new(short_name), repo);
406     exec.is_some() && {
407        let execname = exec.get_ref();
408        execname.exists() && is_rwx(execname)
409     }
410 }
411
412 fn remove_built_executable_file(p: &PkgId, workspace: &Path) {
413     let exec = built_executable_in_workspace(&PkgId::new(p.short_name), workspace);
414     match exec {
415         Some(r) => fs::unlink(&r),
416         None    => ()
417     }
418 }
419
420 fn object_file_exists(repo: &Path, short_name: &str) -> bool {
421     file_exists(repo, short_name, "o")
422 }
423
424 fn assembly_file_exists(repo: &Path, short_name: &str) -> bool {
425     file_exists(repo, short_name, "s")
426 }
427
428 fn llvm_assembly_file_exists(repo: &Path, short_name: &str) -> bool {
429     file_exists(repo, short_name, "ll")
430 }
431
432 fn llvm_bitcode_file_exists(repo: &Path, short_name: &str) -> bool {
433     file_exists(repo, short_name, "bc")
434 }
435
436 fn file_exists(repo: &Path, short_name: &str, extension: &str) -> bool {
437     target_build_dir(repo).join_many([short_name.to_owned(),
438                                      format!("{}.{}", short_name, extension)])
439                           .exists()
440 }
441
442 fn assert_built_library_exists(repo: &Path, short_name: &str) {
443     assert!(built_library_exists(repo, short_name));
444 }
445
446 fn built_library_exists(repo: &Path, short_name: &str) -> bool {
447     debug!("assert_built_library_exists: repo = {}, short_name = {}", repo.display(), short_name);
448     let lib = built_library_in_workspace(&PkgId::new(short_name), repo);
449     lib.is_some() && {
450         let libname = lib.get_ref();
451         libname.exists() && is_rwx(libname)
452     }
453 }
454
455 fn command_line_test_output(args: &[~str]) -> ~[~str] {
456     let mut result = ~[];
457     let p_output = command_line_test(args, &os::getcwd());
458     let test_output = str::from_utf8(p_output.output);
459     for s in test_output.split('\n') {
460         result.push(s.to_owned());
461     }
462     result
463 }
464
465 fn command_line_test_output_with_env(args: &[~str], env: ~[(~str, ~str)]) -> ~[~str] {
466     let mut result = ~[];
467     let p_output = match command_line_test_with_env(args,
468         &os::getcwd(), Some(env)) {
469         Fail(_) => fail!("Command-line test failed"),
470         Success(r) => r
471     };
472     let test_output = str::from_utf8(p_output.output);
473     for s in test_output.split('\n') {
474         result.push(s.to_owned());
475     }
476     result
477 }
478
479 // assumes short_name and path are one and the same -- I should fix
480 fn lib_output_file_name(workspace: &Path, short_name: &str) -> Path {
481     debug!("lib_output_file_name: given {} and short name {}",
482            workspace.display(), short_name);
483     library_in_workspace(&Path::init(short_name),
484                          short_name,
485                          Build,
486                          workspace,
487                          "build",
488                          &NoVersion).expect("lib_output_file_name")
489 }
490
491 fn output_file_name(workspace: &Path, short_name: ~str) -> Path {
492     target_build_dir(workspace).join(short_name.as_slice()).join(format!("{}{}", short_name,
493                                                                          os::EXE_SUFFIX))
494 }
495
496 #[cfg(target_os = "linux")]
497 fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
498     use conditions::bad_path::cond;
499     let pkg_src_dir = workspace.join_many([~"src", pkgid.to_str()]);
500     let contents = fs::readdir(&pkg_src_dir);
501     for p in contents.iter() {
502         if p.extension_str() == Some("rs") {
503             // should be able to do this w/o a process
504             // FIXME (#9639): This needs to handle non-utf8 paths
505             // n.b. Bumps time up by 2 seconds to get around granularity issues
506             if !run::process_output("touch", [~"--date",
507                                              ~"+2 seconds",
508                                              p.as_str().unwrap().to_owned()]).status.success() {
509                 let _ = cond.raise((pkg_src_dir.clone(), ~"Bad path"));
510             }
511         }
512     }
513 }
514
515 #[cfg(not(target_os = "linux"))]
516 fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
517     use conditions::bad_path::cond;
518     let pkg_src_dir = workspace.join_many([~"src", pkgid.to_str()]);
519     let contents = fs::readdir(&pkg_src_dir);
520     for p in contents.iter() {
521         if p.extension_str() == Some("rs") {
522             // should be able to do this w/o a process
523             // FIXME (#9639): This needs to handle non-utf8 paths
524             // n.b. Bumps time up by 2 seconds to get around granularity issues
525             if !run::process_output("touch", [~"-A02",
526                                              p.as_str().unwrap().to_owned()]).status.success() {
527                 let _ = cond.raise((pkg_src_dir.clone(), ~"Bad path"));
528             }
529         }
530     }
531 }
532
533 /// Add a comment at the end
534 fn frob_source_file(workspace: &Path, pkgid: &PkgId, filename: &str) {
535     use conditions::bad_path::cond;
536     let pkg_src_dir = workspace.join_many([~"src", pkgid.to_str()]);
537     let mut maybe_p = None;
538     let maybe_file = pkg_src_dir.join(filename);
539     debug!("Trying to frob {} -- {}", pkg_src_dir.display(), filename);
540     if maybe_file.exists() {
541         maybe_p = Some(maybe_file);
542     }
543     debug!("Frobbed? {:?}", maybe_p);
544     match maybe_p {
545         Some(ref p) => {
546             io::io_error::cond.trap(|e| {
547                 cond.raise((p.clone(), format!("Bad path: {}", e.desc)));
548             }).inside(|| {
549                 let mut w = File::open_mode(p, io::Append, io::Write);
550                 w.write(bytes!("/* hi */\n"));
551             })
552         }
553         None => fail!("frob_source_file failed to find a source file in {}",
554                            pkg_src_dir.display())
555     }
556 }
557
558 #[test]
559 fn test_make_dir_rwx() {
560     let temp = &os::tmpdir();
561     let dir = temp.join("quux");
562     if dir.exists() {
563         fs::rmdir_recursive(&dir);
564     }
565     debug!("Trying to make {}", dir.display());
566     assert!(make_dir_rwx(&dir));
567     assert!(dir.is_dir());
568     assert!(is_rwx(&dir));
569     fs::rmdir_recursive(&dir);
570 }
571
572 // n.b. I ignored the next two tests for now because something funny happens on linux
573 // and I don't want to debug the issue right now (calling into the rustpkg lib directly
574 // is a little sketchy anyway)
575 #[test]
576 #[ignore]
577 fn test_install_valid() {
578     use path_util::installed_library_in_workspace;
579
580     let sysroot = test_sysroot();
581     debug!("sysroot = {}", sysroot.display());
582     let temp_pkg_id = fake_pkg();
583     let (temp_workspace, _pkg_dir) = mk_temp_workspace(&temp_pkg_id.path, &NoVersion);
584     let temp_workspace = temp_workspace.path();
585     let ctxt = fake_ctxt(sysroot, temp_workspace);
586     debug!("temp_workspace = {}", temp_workspace.display());
587     // should have test, bench, lib, and main
588     let src = PkgSrc::new(temp_workspace.clone(),
589                           temp_workspace.clone(),
590                           false,
591                           temp_pkg_id.clone());
592     ctxt.install(src, &WhatToBuild::new(MaybeCustom, Everything));
593     // Check that all files exist
594     let exec = target_executable_in_workspace(&temp_pkg_id, temp_workspace);
595     debug!("exec = {}", exec.display());
596     assert!(exec.exists());
597     assert!(is_rwx(&exec));
598
599     let lib = installed_library_in_workspace(&temp_pkg_id.path, temp_workspace);
600     debug!("lib = {:?}", lib);
601     assert!(lib.as_ref().map_default(false, |l| l.exists()));
602     assert!(lib.as_ref().map_default(false, |l| is_rwx(l)));
603
604     // And that the test and bench executables aren't installed
605     assert!(!target_test_in_workspace(&temp_pkg_id, temp_workspace).exists());
606     let bench = target_bench_in_workspace(&temp_pkg_id, temp_workspace);
607     debug!("bench = {}", bench.display());
608     assert!(!bench.exists());
609
610     // Make sure the db isn't dirty, so that it doesn't try to save()
611     // asynchronously after the temporary directory that it wants to save
612     // to has been deleted.
613     ctxt.workcache_context.db.write(|db| db.db_dirty = false);
614 }
615
616 #[test]
617 #[ignore]
618 fn test_install_invalid() {
619     let sysroot = test_sysroot();
620     let pkgid = fake_pkg();
621     let temp_workspace = TempDir::new("test").expect("couldn't create temp dir");
622     let temp_workspace = temp_workspace.path().clone();
623     let ctxt = fake_ctxt(sysroot, &temp_workspace);
624
625     // Uses task::try because of #9001
626     let result = do task::try {
627         let pkg_src = PkgSrc::new(temp_workspace.clone(),
628                                   temp_workspace.clone(),
629                                   false,
630                                   pkgid.clone());
631         ctxt.install(pkg_src, &WhatToBuild::new(MaybeCustom, Everything));
632     };
633     assert!(result.unwrap_err()
634             .to_str().contains("supplied path for package dir does not exist"));
635 }
636
637 #[test]
638 fn test_install_valid_external() {
639     let temp_pkg_id = PkgId::new("foo");
640     let (tempdir, _) = mk_temp_workspace(&temp_pkg_id.path,
641                                          &temp_pkg_id.version);
642     let temp_workspace = tempdir.path();
643     command_line_test([~"install", ~"foo"], temp_workspace);
644
645     // Check that all files exist
646     let exec = target_executable_in_workspace(&temp_pkg_id, temp_workspace);
647     debug!("exec = {}", exec.display());
648     assert!(exec.exists());
649     assert!(is_rwx(&exec));
650
651     let lib = installed_library_in_workspace(&temp_pkg_id.path, temp_workspace);
652     debug!("lib = {:?}", lib);
653     assert!(lib.as_ref().map_default(false, |l| l.exists()));
654     assert!(lib.as_ref().map_default(false, |l| is_rwx(l)));
655
656     // And that the test and bench executables aren't installed
657     assert!(!target_test_in_workspace(&temp_pkg_id, temp_workspace).exists());
658     let bench = target_bench_in_workspace(&temp_pkg_id, temp_workspace);
659     debug!("bench = {}", bench.display());
660     assert!(!bench.exists());
661
662 }
663
664 #[test]
665 #[ignore(reason = "9994")]
666 fn test_install_invalid_external() {
667     let cwd = os::getcwd();
668     command_line_test_expect_fail([~"install", ~"foo"],
669                                   &cwd,
670                                   None,
671                                   // FIXME #3408: Should be NONEXISTENT_PACKAGE_CODE
672                                   COPY_FAILED_CODE);
673 }
674
675 #[test]
676 fn test_install_git() {
677     let temp_pkg_id = git_repo_pkg();
678     let repo = init_git_repo(&temp_pkg_id.path);
679     let repo = repo.path();
680     debug!("repo = {}", repo.display());
681     let repo_subdir = repo.join_many(["mockgithub.com", "catamorphism", "test-pkg"]);
682     debug!("repo_subdir = {}", repo_subdir.display());
683
684     writeFile(&repo_subdir.join("main.rs"),
685               "fn main() { let _x = (); }");
686     writeFile(&repo_subdir.join("lib.rs"),
687               "pub fn f() { let _x = (); }");
688     writeFile(&repo_subdir.join("test.rs"),
689               "#[test] pub fn f() { (); }");
690     writeFile(&repo_subdir.join("bench.rs"),
691               "#[bench] pub fn f() { (); }");
692     add_git_tag(&repo_subdir, ~"0.1"); // this has the effect of committing the files
693
694     debug!("test_install_git: calling rustpkg install {} in {}",
695            temp_pkg_id.path.display(), repo.display());
696     // should have test, bench, lib, and main
697     // FIXME (#9639): This needs to handle non-utf8 paths
698     command_line_test([~"install", temp_pkg_id.path.as_str().unwrap().to_owned()], repo);
699     let ws = repo.join(".rust");
700     // Check that all files exist
701     debug!("Checking for files in {}", ws.display());
702     let exec = target_executable_in_workspace(&temp_pkg_id, &ws);
703     debug!("exec = {}", exec.display());
704     assert!(exec.exists());
705     assert!(is_rwx(&exec));
706     let _built_lib =
707         built_library_in_workspace(&temp_pkg_id,
708                                    &ws).expect("test_install_git: built lib should exist");
709     assert_lib_exists(&ws, &temp_pkg_id.path, temp_pkg_id.version.clone());
710     let built_test = built_test_in_workspace(&temp_pkg_id,
711                          &ws).expect("test_install_git: built test should exist");
712     assert!(built_test.exists());
713     let built_bench = built_bench_in_workspace(&temp_pkg_id,
714                           &ws).expect("test_install_git: built bench should exist");
715     assert!(built_bench.exists());
716     // And that the test and bench executables aren't installed
717     let test = target_test_in_workspace(&temp_pkg_id, &ws);
718     assert!(!test.exists());
719     debug!("test = {}", test.display());
720     let bench = target_bench_in_workspace(&temp_pkg_id, &ws);
721     debug!("bench = {}", bench.display());
722     assert!(!bench.exists());
723 }
724
725 #[test]
726 fn test_package_ids_must_be_relative_path_like() {
727     use conditions::bad_pkg_id::cond;
728
729     /*
730     Okay:
731     - One identifier, with no slashes
732     - Several slash-delimited things, with no / at the root
733
734     Not okay:
735     - Empty string
736     - Absolute path (as per os::is_absolute)
737
738     */
739
740     let whatever = PkgId::new("foo");
741
742     assert_eq!(~"foo-0.1", whatever.to_str());
743     assert!("github.com/catamorphism/test-pkg-0.1" ==
744             PkgId::new("github.com/catamorphism/test-pkg").to_str());
745
746     cond.trap(|(p, e)| {
747         assert!(p.filename().is_none())
748         assert!("0-length pkgid" == e);
749         whatever.clone()
750     }).inside(|| {
751         let x = PkgId::new("");
752         assert_eq!(~"foo-0.1", x.to_str());
753     });
754
755     cond.trap(|(p, e)| {
756         let abs = os::make_absolute(&Path::init("foo/bar/quux"));
757         assert_eq!(p, abs);
758         assert!("absolute pkgid" == e);
759         whatever.clone()
760     }).inside(|| {
761         let zp = os::make_absolute(&Path::init("foo/bar/quux"));
762         // FIXME (#9639): This needs to handle non-utf8 paths
763         let z = PkgId::new(zp.as_str().unwrap());
764         assert_eq!(~"foo-0.1", z.to_str());
765     })
766
767 }
768
769 #[test]
770 fn test_package_version() {
771     let local_path = "mockgithub.com/catamorphism/test_pkg_version";
772     let repo = init_git_repo(&Path::init(local_path));
773     let repo = repo.path();
774     let repo_subdir = repo.join_many(["mockgithub.com", "catamorphism", "test_pkg_version"]);
775     debug!("Writing files in: {}", repo_subdir.display());
776     fs::mkdir_recursive(&repo_subdir, io::UserRWX);
777     writeFile(&repo_subdir.join("main.rs"),
778               "fn main() { let _x = (); }");
779     writeFile(&repo_subdir.join("lib.rs"),
780               "pub fn f() { let _x = (); }");
781     writeFile(&repo_subdir.join("test.rs"),
782               "#[test] pub fn f() { (); }");
783     writeFile(&repo_subdir.join("bench.rs"),
784               "#[bench] pub fn f() { (); }");
785     add_git_tag(&repo_subdir, ~"0.4");
786
787     // It won't pick up the 0.4 version because the dir isn't in the RUST_PATH, but...
788     let temp_pkg_id = PkgId::new("mockgithub.com/catamorphism/test_pkg_version");
789     // This should look at the prefix, clone into a workspace, then build.
790     command_line_test([~"install", ~"mockgithub.com/catamorphism/test_pkg_version"],
791                       repo);
792     let ws = repo.join(".rust");
793     // we can still match on the filename to make sure it contains the 0.4 version
794     assert!(match built_library_in_workspace(&temp_pkg_id,
795                                              &ws) {
796         Some(p) => {
797             let suffix = format!("0.4{}", os::consts::DLL_SUFFIX);
798             p.as_vec().ends_with(suffix.as_bytes())
799         }
800         None    => false
801     });
802     assert!(built_executable_in_workspace(&temp_pkg_id, &ws)
803             == Some(target_build_dir(&ws).join_many(["mockgithub.com",
804                                                      "catamorphism",
805                                                      "test_pkg_version",
806                                                      "test_pkg_version"])));
807 }
808
809 #[test]
810 fn test_package_request_version() {
811     let local_path = "mockgithub.com/catamorphism/test_pkg_version";
812     let repo = init_git_repo(&Path::init(local_path));
813     let repo = repo.path();
814     let repo_subdir = repo.join_many(["mockgithub.com", "catamorphism", "test_pkg_version"]);
815     debug!("Writing files in: {}", repo_subdir.display());
816     writeFile(&repo_subdir.join("main.rs"),
817               "fn main() { let _x = (); }");
818     writeFile(&repo_subdir.join("lib.rs"),
819               "pub fn f() { let _x = (); }");
820     writeFile(&repo_subdir.join("test.rs"),
821               "#[test] pub fn f() { (); }");
822     writeFile(&repo_subdir.join("bench.rs"),
823               "#[bench] pub fn f() { (); }");
824     writeFile(&repo_subdir.join("version-0.3-file.txt"), "hi");
825     add_git_tag(&repo_subdir, ~"0.3");
826     writeFile(&repo_subdir.join("version-0.4-file.txt"), "hello");
827     add_git_tag(&repo_subdir, ~"0.4");
828
829     command_line_test([~"install", format!("{}\\#0.3", local_path)], repo);
830
831     assert!(match installed_library_in_workspace(&Path::init("test_pkg_version"),
832                                                  &repo.join(".rust")) {
833         Some(p) => {
834             debug!("installed: {}", p.display());
835             let suffix = format!("0.3{}", os::consts::DLL_SUFFIX);
836             p.as_vec().ends_with(suffix.as_bytes())
837         }
838         None    => false
839     });
840     let temp_pkg_id = PkgId::new("mockgithub.com/catamorphism/test_pkg_version#0.3");
841     assert!(target_executable_in_workspace(&temp_pkg_id, &repo.join(".rust"))
842             == repo.join_many([".rust", "bin", "test_pkg_version"]));
843
844     let mut dir = target_build_dir(&repo.join(".rust"));
845     dir.push(&Path::init("src/mockgithub.com/catamorphism/test_pkg_version-0.3"));
846     debug!("dir = {}", dir.display());
847     assert!(dir.is_dir());
848     assert!(dir.join("version-0.3-file.txt").exists());
849     assert!(!dir.join("version-0.4-file.txt").exists());
850 }
851
852 #[test]
853 #[ignore (reason = "http-client not ported to rustpkg yet")]
854 fn rustpkg_install_url_2() {
855     let temp_dir = TempDir::new("rustpkg_install_url_2").expect("rustpkg_install_url_2");
856     command_line_test([~"install", ~"github.com/mozilla-servo/rust-http-client"],
857                      temp_dir.path());
858 }
859
860 #[test]
861 fn rustpkg_library_target() {
862     let foo_repo = init_git_repo(&Path::init("foo"));
863     let foo_repo = foo_repo.path();
864     let package_dir = foo_repo.join("foo");
865
866     debug!("Writing files in: {}", package_dir.display());
867     writeFile(&package_dir.join("main.rs"),
868               "fn main() { let _x = (); }");
869     writeFile(&package_dir.join("lib.rs"),
870               "pub fn f() { let _x = (); }");
871     writeFile(&package_dir.join("test.rs"),
872               "#[test] pub fn f() { (); }");
873     writeFile(&package_dir.join("bench.rs"),
874               "#[bench] pub fn f() { (); }");
875
876     add_git_tag(&package_dir, ~"1.0");
877     command_line_test([~"install", ~"foo"], foo_repo);
878     assert_lib_exists(&foo_repo.join(".rust"), &Path::init("foo"), ExactRevision(~"1.0"));
879 }
880
881 #[test]
882 fn rustpkg_local_pkg() {
883     let dir = create_local_package(&PkgId::new("foo"));
884     command_line_test([~"install", ~"foo"], dir.path());
885     assert_executable_exists(dir.path(), "foo");
886 }
887
888 #[test]
889 #[ignore(reason="busted")]
890 fn package_script_with_default_build() {
891     let dir = create_local_package(&PkgId::new("fancy-lib"));
892     let dir = dir.path();
893     debug!("dir = {}", dir.display());
894     let mut source = test_sysroot().dir_path();
895     source.pop(); source.pop();
896     let source = Path::init(file!()).dir_path().join_many(
897         [~"testsuite", ~"pass", ~"src", ~"fancy-lib", ~"pkg.rs"]);
898     debug!("package_script_with_default_build: {}", source.display());
899     fs::copy(&source, &dir.join_many(["src", "fancy-lib-0.1", "pkg.rs"]));
900     command_line_test([~"install", ~"fancy-lib"], dir);
901     assert_lib_exists(dir, &Path::init("fancy-lib"), NoVersion);
902     assert!(target_build_dir(dir).join_many([~"fancy-lib", ~"generated.rs"]).exists());
903     let generated_path = target_build_dir(dir).join_many([~"fancy-lib", ~"generated.rs"]);
904     debug!("generated path = {}", generated_path.display());
905     assert!(generated_path.exists());
906 }
907
908 #[test]
909 fn rustpkg_build_no_arg() {
910     let tmp = TempDir::new("rustpkg_build_no_arg").expect("rustpkg_build_no_arg failed");
911     let tmp = tmp.path().join(".rust");
912     let package_dir = tmp.join_many(["src", "foo"]);
913     fs::mkdir_recursive(&package_dir, io::UserRWX);
914
915     writeFile(&package_dir.join("main.rs"),
916               "fn main() { let _x = (); }");
917     debug!("build_no_arg: dir = {}", package_dir.display());
918     command_line_test([~"build"], &package_dir);
919     assert_built_executable_exists(&tmp, "foo");
920 }
921
922 #[test]
923 fn rustpkg_install_no_arg() {
924     let tmp = TempDir::new("rustpkg_install_no_arg").expect("rustpkg_install_no_arg failed");
925     let tmp = tmp.path().join(".rust");
926     let package_dir = tmp.join_many(["src", "foo"]);
927     fs::mkdir_recursive(&package_dir, io::UserRWX);
928     writeFile(&package_dir.join("lib.rs"),
929               "fn main() { let _x = (); }");
930     debug!("install_no_arg: dir = {}", package_dir.display());
931     command_line_test([~"install"], &package_dir);
932     assert_lib_exists(&tmp, &Path::init("foo"), NoVersion);
933 }
934
935 #[test]
936 fn rustpkg_clean_no_arg() {
937     let tmp = TempDir::new("rustpkg_clean_no_arg").expect("rustpkg_clean_no_arg failed");
938     let tmp = tmp.path().join(".rust");
939     let package_dir = tmp.join_many(["src", "foo"]);
940     fs::mkdir_recursive(&package_dir, io::UserRWX);
941
942     writeFile(&package_dir.join("main.rs"),
943               "fn main() { let _x = (); }");
944     debug!("clean_no_arg: dir = {}", package_dir.display());
945     command_line_test([~"build"], &package_dir);
946     assert_built_executable_exists(&tmp, "foo");
947     command_line_test([~"clean"], &package_dir);
948     let res = built_executable_in_workspace(&PkgId::new("foo"), &tmp);
949     assert!(!res.as_ref().map_default(false, |m| m.exists()));
950 }
951
952 #[test]
953 fn rust_path_test() {
954     let dir_for_path = TempDir::new("more_rust").expect("rust_path_test failed");
955     let dir = mk_workspace(dir_for_path.path(), &Path::init("foo"), &NoVersion);
956     debug!("dir = {}", dir.display());
957     writeFile(&dir.join("main.rs"), "fn main() { let _x = (); }");
958
959     let cwd = os::getcwd();
960     debug!("cwd = {}", cwd.display());
961                                      // use command_line_test_with_env
962     // FIXME (#9639): This needs to handle non-utf8 paths
963     command_line_test_with_env([~"install", ~"foo"],
964                                &cwd,
965                                Some(~[(~"RUST_PATH",
966                                        dir_for_path.path().as_str().unwrap().to_owned())]));
967     assert_executable_exists(dir_for_path.path(), "foo");
968 }
969
970 #[test]
971 #[ignore] // FIXME(#9184) tests can't change the cwd (other tests are sad then)
972 fn rust_path_contents() {
973     let dir = TempDir::new("rust_path").expect("rust_path_contents failed");
974     let abc = &dir.path().join_many(["A", "B", "C"]);
975     fs::mkdir_recursive(&abc.join(".rust"), io::UserRWX);
976     fs::mkdir_recursive(&abc.with_filename(".rust"), io::UserRWX);
977     fs::mkdir_recursive(&abc.dir_path().with_filename(".rust"), io::UserRWX);
978     assert!(os::change_dir(abc));
979
980     let p = rust_path();
981     let cwd = os::getcwd().join(".rust");
982     let parent = cwd.dir_path().with_filename(".rust");
983     let grandparent = cwd.dir_path().dir_path().with_filename(".rust");
984     assert!(p.contains(&cwd));
985     assert!(p.contains(&parent));
986     assert!(p.contains(&grandparent));
987     for a_path in p.iter() {
988         assert!(a_path.filename().is_some());
989     }
990 }
991
992 #[test]
993 fn rust_path_parse() {
994     os::setenv("RUST_PATH", "/a/b/c:/d/e/f:/g/h/i");
995     let paths = rust_path();
996     assert!(paths.contains(&Path::init("/g/h/i")));
997     assert!(paths.contains(&Path::init("/d/e/f")));
998     assert!(paths.contains(&Path::init("/a/b/c")));
999     os::unsetenv("RUST_PATH");
1000 }
1001
1002 #[test]
1003 fn test_list() {
1004     let dir = TempDir::new("test_list").expect("test_list failed");
1005     let dir = dir.path();
1006     let foo = PkgId::new("foo");
1007     create_local_package_in(&foo, dir);
1008     let bar = PkgId::new("bar");
1009     create_local_package_in(&bar, dir);
1010     let quux = PkgId::new("quux");
1011     create_local_package_in(&quux, dir);
1012
1013 // list doesn't output very much right now...
1014     command_line_test([~"install", ~"foo"], dir);
1015     // FIXME (#9639): This needs to handle non-utf8 paths
1016     let env_arg = ~[(~"RUST_PATH", dir.as_str().unwrap().to_owned())];
1017     let list_output = command_line_test_output_with_env([~"list"], env_arg.clone());
1018     assert!(list_output.iter().any(|x| x.starts_with("foo")));
1019
1020     command_line_test([~"install", ~"bar"], dir);
1021     let list_output = command_line_test_output_with_env([~"list"], env_arg.clone());
1022     assert!(list_output.iter().any(|x| x.starts_with("foo")));
1023     assert!(list_output.iter().any(|x| x.starts_with("bar")));
1024
1025     command_line_test([~"install", ~"quux"], dir);
1026     let list_output = command_line_test_output_with_env([~"list"], env_arg);
1027     assert!(list_output.iter().any(|x| x.starts_with("foo")));
1028     assert!(list_output.iter().any(|x| x.starts_with("bar")));
1029     assert!(list_output.iter().any(|x| x.starts_with("quux")));
1030 }
1031
1032 #[test]
1033 fn install_remove() {
1034     let dir = TempDir::new("install_remove").expect("install_remove");
1035     let dir = dir.path();
1036     let foo = PkgId::new("foo");
1037     let bar = PkgId::new("bar");
1038     let quux = PkgId::new("quux");
1039     create_local_package_in(&foo, dir);
1040     create_local_package_in(&bar, dir);
1041     create_local_package_in(&quux, dir);
1042     // FIXME (#9639): This needs to handle non-utf8 paths
1043     let rust_path_to_use = ~[(~"RUST_PATH", dir.as_str().unwrap().to_owned())];
1044     command_line_test([~"install", ~"foo"], dir);
1045     command_line_test([~"install", ~"bar"], dir);
1046     command_line_test([~"install", ~"quux"], dir);
1047     let list_output = command_line_test_output_with_env([~"list"], rust_path_to_use.clone());
1048     assert!(list_output.iter().any(|x| x.starts_with("foo")));
1049     assert!(list_output.iter().any(|x| x.starts_with("bar")));
1050     assert!(list_output.iter().any(|x| x.starts_with("quux")));
1051     command_line_test([~"uninstall", ~"foo"], dir);
1052     let list_output = command_line_test_output_with_env([~"list"], rust_path_to_use.clone());
1053     assert!(!list_output.iter().any(|x| x.starts_with("foo")));
1054     assert!(list_output.iter().any(|x| x.starts_with("bar")));
1055     assert!(list_output.iter().any(|x| x.starts_with("quux")));
1056 }
1057
1058 #[test]
1059 fn install_check_duplicates() {
1060     // should check that we don't install two packages with the same full name *and* version
1061     // ("Is already installed -- doing nothing")
1062     // check invariant that there are no dups in the pkg database
1063     let dir = TempDir::new("install_remove").expect("install_remove");
1064     let dir = dir.path();
1065     let foo = PkgId::new("foo");
1066     create_local_package_in(&foo, dir);
1067
1068     command_line_test([~"install", ~"foo"], dir);
1069     command_line_test([~"install", ~"foo"], dir);
1070     let mut contents = ~[];
1071     let check_dups = |p: &PkgId| {
1072         if contents.contains(p) {
1073             fail!("package {} appears in `list` output more than once", p.path.display());
1074         }
1075         else {
1076             contents.push((*p).clone());
1077         }
1078         true
1079     };
1080     list_installed_packages(check_dups);
1081 }
1082
1083 #[test]
1084 fn no_rebuilding() {
1085     let p_id = PkgId::new("foo");
1086     let workspace = create_local_package(&p_id);
1087     let workspace = workspace.path();
1088     command_line_test([~"build", ~"foo"], workspace);
1089     let foo_lib = lib_output_file_name(workspace, "foo");
1090     // Now make `foo` read-only so that subsequent rebuilds of it will fail
1091     assert!(chmod_read_only(&foo_lib));
1092
1093     command_line_test([~"build", ~"foo"], workspace);
1094
1095     match command_line_test_partial([~"build", ~"foo"], workspace) {
1096         Success(..) => (), // ok
1097         Fail(ref status) if status.status.matches_exit_status(65) =>
1098             fail!("no_rebuilding failed: it tried to rebuild bar"),
1099         Fail(_) => fail!("no_rebuilding failed for some other reason")
1100     }
1101 }
1102
1103 #[test]
1104 fn no_recopying() {
1105     let p_id = PkgId::new("foo");
1106     let workspace = create_local_package(&p_id);
1107     let workspace = workspace.path();
1108     command_line_test([~"install", ~"foo"], workspace);
1109     let foo_lib = installed_library_in_workspace(&p_id.path, workspace);
1110     assert!(foo_lib.is_some());
1111     // Now make `foo` read-only so that subsequent attempts to copy to it will fail
1112     assert!(chmod_read_only(&foo_lib.unwrap()));
1113
1114     match command_line_test_partial([~"install", ~"foo"], workspace) {
1115         Success(..) => (), // ok
1116         Fail(ref status) if status.status.matches_exit_status(65) =>
1117             fail!("no_recopying failed: it tried to re-copy foo"),
1118         Fail(_) => fail!("no_copying failed for some other reason")
1119     }
1120 }
1121
1122 #[test]
1123 fn no_rebuilding_dep() {
1124     let p_id = PkgId::new("foo");
1125     let dep_id = PkgId::new("bar");
1126     let workspace = create_local_package_with_dep(&p_id, &dep_id);
1127     let workspace = workspace.path();
1128     command_line_test([~"build", ~"foo"], workspace);
1129     let bar_lib = lib_output_file_name(workspace, "bar");
1130     frob_source_file(workspace, &p_id, "main.rs");
1131     // Now make `bar` read-only so that subsequent rebuilds of it will fail
1132     assert!(chmod_read_only(&bar_lib));
1133     match command_line_test_partial([~"build", ~"foo"], workspace) {
1134         Success(..) => (), // ok
1135         Fail(ref r) if r.status.matches_exit_status(65) =>
1136             fail!("no_rebuilding_dep failed: it tried to rebuild bar"),
1137         Fail(_) => fail!("no_rebuilding_dep failed for some other reason")
1138     }
1139 }
1140
1141 #[test]
1142 fn do_rebuild_dep_dates_change() {
1143     let p_id = PkgId::new("foo");
1144     let dep_id = PkgId::new("bar");
1145     let workspace = create_local_package_with_dep(&p_id, &dep_id);
1146     let workspace = workspace.path();
1147     command_line_test([~"build", ~"foo"], workspace);
1148     let bar_lib_name = lib_output_file_name(workspace, "bar");
1149     touch_source_file(workspace, &dep_id);
1150
1151     // Now make `bar` read-only so that subsequent rebuilds of it will fail
1152     assert!(chmod_read_only(&bar_lib_name));
1153
1154     match command_line_test_partial([~"build", ~"foo"], workspace) {
1155         Success(..) => fail!("do_rebuild_dep_dates_change failed: it didn't rebuild bar"),
1156         Fail(ref r) if r.status.matches_exit_status(65) => (), // ok
1157         Fail(_) => fail!("do_rebuild_dep_dates_change failed for some other reason")
1158     }
1159 }
1160
1161 #[test]
1162 fn do_rebuild_dep_only_contents_change() {
1163     let p_id = PkgId::new("foo");
1164     let dep_id = PkgId::new("bar");
1165     let workspace = create_local_package_with_dep(&p_id, &dep_id);
1166     let workspace = workspace.path();
1167     command_line_test([~"build", ~"foo"], workspace);
1168     frob_source_file(workspace, &dep_id, "lib.rs");
1169     let bar_lib_name = lib_output_file_name(workspace, "bar");
1170
1171     // Now make `bar` read-only so that subsequent rebuilds of it will fail
1172     assert!(chmod_read_only(&bar_lib_name));
1173
1174     // should adjust the datestamp
1175     match command_line_test_partial([~"build", ~"foo"], workspace) {
1176         Success(..) => fail!("do_rebuild_dep_only_contents_change failed: it didn't rebuild bar"),
1177         Fail(ref r) if r.status.matches_exit_status(65) => (), // ok
1178         Fail(_) => fail!("do_rebuild_dep_only_contents_change failed for some other reason")
1179     }
1180 }
1181
1182 #[test]
1183 fn test_versions() {
1184     let workspace = create_local_package(&PkgId::new("foo#0.1"));
1185     let _other_workspace = create_local_package(&PkgId::new("foo#0.2"));
1186     command_line_test([~"install", ~"foo#0.1"], workspace.path());
1187     let output = command_line_test_output([~"list"]);
1188     // make sure output includes versions
1189     assert!(!output.iter().any(|x| x == &~"foo#0.2"));
1190 }
1191
1192 #[test]
1193 #[ignore(reason = "do not yet implemented")]
1194 fn test_build_hooks() {
1195     let workspace = create_local_package_with_custom_build_hook(&PkgId::new("foo"),
1196                                                                 "frob");
1197     command_line_test([~"do", ~"foo", ~"frob"], workspace.path());
1198 }
1199
1200
1201 #[test]
1202 #[ignore(reason = "info not yet implemented")]
1203 fn test_info() {
1204     let expected_info = ~"package foo"; // fill in
1205     let workspace = create_local_package(&PkgId::new("foo"));
1206     let output = command_line_test([~"info", ~"foo"], workspace.path());
1207     assert_eq!(str::from_utf8(output.output), expected_info);
1208 }
1209
1210 #[test]
1211 fn test_uninstall() {
1212     let workspace = create_local_package(&PkgId::new("foo"));
1213     command_line_test([~"uninstall", ~"foo"], workspace.path());
1214     let output = command_line_test([~"list"], workspace.path());
1215     assert!(!str::from_utf8(output.output).contains("foo"));
1216 }
1217
1218 #[test]
1219 fn test_non_numeric_tag() {
1220     let temp_pkg_id = git_repo_pkg();
1221     let repo = init_git_repo(&temp_pkg_id.path);
1222     let repo = repo.path();
1223     let repo_subdir = repo.join_many(["mockgithub.com", "catamorphism", "test-pkg"]);
1224     writeFile(&repo_subdir.join("foo"), "foo");
1225     writeFile(&repo_subdir.join("lib.rs"),
1226               "pub fn f() { let _x = (); }");
1227     add_git_tag(&repo_subdir, ~"testbranch");
1228     writeFile(&repo_subdir.join("testbranch_only"), "hello");
1229     add_git_tag(&repo_subdir, ~"another_tag");
1230     writeFile(&repo_subdir.join("not_on_testbranch_only"), "bye bye");
1231     add_all_and_commit(&repo_subdir);
1232
1233     // FIXME (#9639): This needs to handle non-utf8 paths
1234     command_line_test([~"install", format!("{}\\#testbranch",
1235                                            temp_pkg_id.path.as_str().unwrap())], repo);
1236     let file1 = repo.join_many(["mockgithub.com", "catamorphism", "test-pkg", "testbranch_only"]);
1237     let file2 = repo.join_many(["mockgithub.com", "catamorphism", "test-pkg", "master_only"]);
1238     assert!(file1.exists());
1239     assert!(!file2.exists());
1240 }
1241
1242 #[test]
1243 fn test_extern_mod() {
1244     let dir = TempDir::new("test_extern_mod").expect("test_extern_mod");
1245     let dir = dir.path();
1246     let main_file = dir.join("main.rs");
1247     let lib_depend_dir = TempDir::new("foo").expect("test_extern_mod");
1248     let lib_depend_dir = lib_depend_dir.path();
1249     let aux_dir = lib_depend_dir.join_many(["src", "mockgithub.com", "catamorphism", "test_pkg"]);
1250     fs::mkdir_recursive(&aux_dir, io::UserRWX);
1251     let aux_pkg_file = aux_dir.join("lib.rs");
1252
1253     writeFile(&aux_pkg_file, "pub mod bar { pub fn assert_true() {  assert!(true); } }\n");
1254     assert!(aux_pkg_file.exists());
1255
1256     writeFile(&main_file,
1257               "extern mod test = \"mockgithub.com/catamorphism/test_pkg\";\nuse test::bar;\
1258                fn main() { bar::assert_true(); }\n");
1259
1260     command_line_test([~"install", ~"mockgithub.com/catamorphism/test_pkg"], lib_depend_dir);
1261
1262     let exec_file = dir.join("out");
1263     // Be sure to extend the existing environment
1264     // FIXME (#9639): This needs to handle non-utf8 paths
1265     let env = Some([(~"RUST_PATH", lib_depend_dir.as_str().unwrap().to_owned())] + os::env());
1266     let rustpkg_exec = rustpkg_exec();
1267     let rustc = rustpkg_exec.with_filename("rustc");
1268
1269     let test_sys = test_sysroot();
1270     // FIXME (#9639): This needs to handle non-utf8 paths
1271     let mut prog = run::Process::new(rustc.as_str().unwrap(),
1272                                      [main_file.as_str().unwrap().to_owned(),
1273                                       ~"--sysroot", test_sys.as_str().unwrap().to_owned(),
1274                                       ~"-o", exec_file.as_str().unwrap().to_owned()],
1275                                      run::ProcessOptions {
1276         env: env,
1277         dir: Some(dir),
1278         in_fd: None,
1279         out_fd: None,
1280         err_fd: None
1281     });
1282     let outp = prog.finish_with_output();
1283     if !outp.status.success() {
1284         fail!("output was {}, error was {}",
1285               str::from_utf8(outp.output),
1286               str::from_utf8(outp.error));
1287     }
1288     assert!(exec_file.exists() && is_executable(&exec_file));
1289 }
1290
1291 #[test]
1292 fn test_extern_mod_simpler() {
1293     let dir = TempDir::new("test_extern_mod_simpler").expect("test_extern_mod_simpler");
1294     let dir = dir.path();
1295     let main_file = dir.join("main.rs");
1296     let lib_depend_dir = TempDir::new("foo").expect("test_extern_mod_simpler");
1297     let lib_depend_dir = lib_depend_dir.path();
1298     let aux_dir = lib_depend_dir.join_many(["src", "rust-awesomeness"]);
1299     fs::mkdir_recursive(&aux_dir, io::UserRWX);
1300     let aux_pkg_file = aux_dir.join("lib.rs");
1301
1302     writeFile(&aux_pkg_file, "pub mod bar { pub fn assert_true() {  assert!(true); } }\n");
1303     assert!(aux_pkg_file.exists());
1304
1305     writeFile(&main_file,
1306               "extern mod test = \"rust-awesomeness\";\nuse test::bar;\
1307                fn main() { bar::assert_true(); }\n");
1308
1309     command_line_test([~"install", ~"rust-awesomeness"], lib_depend_dir);
1310
1311     let exec_file = dir.join("out");
1312     // Be sure to extend the existing environment
1313     // FIXME (#9639): This needs to handle non-utf8 paths
1314     let env = Some([(~"RUST_PATH", lib_depend_dir.as_str().unwrap().to_owned())] + os::env());
1315     let rustpkg_exec = rustpkg_exec();
1316     let rustc = rustpkg_exec.with_filename("rustc");
1317     let test_sys = test_sysroot();
1318     debug!("RUST_PATH={} {} {} \n --sysroot {} -o {}",
1319                      lib_depend_dir.display(),
1320                      rustc.display(),
1321                      main_file.display(),
1322                      test_sys.display(),
1323                      exec_file.display());
1324
1325     // FIXME (#9639): This needs to handle non-utf8 paths
1326     let mut prog = run::Process::new(rustc.as_str().unwrap(),
1327                                      [main_file.as_str().unwrap().to_owned(),
1328                                       ~"--sysroot", test_sys.as_str().unwrap().to_owned(),
1329                                       ~"-o", exec_file.as_str().unwrap().to_owned()],
1330                                      run::ProcessOptions {
1331         env: env,
1332         dir: Some(dir),
1333         in_fd: None,
1334         out_fd: None,
1335         err_fd: None
1336     });
1337     let outp = prog.finish_with_output();
1338     if !outp.status.success() {
1339         fail!("output was {}, error was {}",
1340               str::from_utf8(outp.output),
1341               str::from_utf8(outp.error));
1342     }
1343     assert!(exec_file.exists() && is_executable(&exec_file));
1344 }
1345
1346 #[test]
1347 fn test_import_rustpkg() {
1348     let p_id = PkgId::new("foo");
1349     let workspace = create_local_package(&p_id);
1350     let workspace = workspace.path();
1351     writeFile(&workspace.join_many(["src", "foo-0.1", "pkg.rs"]),
1352               "extern mod rustpkg; fn main() {}");
1353     command_line_test([~"build", ~"foo"], workspace);
1354     debug!("workspace = {}", workspace.display());
1355     assert!(target_build_dir(workspace).join("foo").join(format!("pkg{}",
1356         os::EXE_SUFFIX)).exists());
1357 }
1358
1359 #[test]
1360 fn test_macro_pkg_script() {
1361     let p_id = PkgId::new("foo");
1362     let workspace = create_local_package(&p_id);
1363     let workspace = workspace.path();
1364     writeFile(&workspace.join_many(["src", "foo-0.1", "pkg.rs"]),
1365               "extern mod rustpkg; fn main() { debug!(\"Hi\"); }");
1366     command_line_test([~"build", ~"foo"], workspace);
1367     debug!("workspace = {}", workspace.display());
1368     assert!(target_build_dir(workspace).join("foo").join(format!("pkg{}",
1369         os::EXE_SUFFIX)).exists());
1370 }
1371
1372 #[test]
1373 fn multiple_workspaces() {
1374 // Make a package foo; build/install in directory A
1375 // Copy the exact same package into directory B and install it
1376 // Set the RUST_PATH to A:B
1377 // Make a third package that uses foo, make sure we can build/install it
1378     let (a_loc, _pkg_dir) = mk_temp_workspace(&Path::init("foo"), &NoVersion);
1379     let (b_loc, _pkg_dir) = mk_temp_workspace(&Path::init("foo"), &NoVersion);
1380     let (a_loc, b_loc) = (a_loc.path(), b_loc.path());
1381     debug!("Trying to install foo in {}", a_loc.display());
1382     command_line_test([~"install", ~"foo"], a_loc);
1383     debug!("Trying to install foo in {}", b_loc.display());
1384     command_line_test([~"install", ~"foo"], b_loc);
1385     // FIXME (#9639): This needs to handle non-utf8 paths
1386     let env = Some(~[(~"RUST_PATH", format!("{}:{}", a_loc.as_str().unwrap(),
1387                                             b_loc.as_str().unwrap()))]);
1388     let c_loc = create_local_package_with_dep(&PkgId::new("bar"), &PkgId::new("foo"));
1389     command_line_test_with_env([~"install", ~"bar"], c_loc.path(), env);
1390 }
1391
1392 fn rust_path_hack_test(hack_flag: bool) {
1393 /*
1394       Make a workspace containing a pkg foo [A]
1395       Make a second, empty workspace        [B]
1396       Set RUST_PATH to B:A
1397       rustpkg install foo
1398       make sure built files for foo are in B
1399       make sure nothing gets built into A or A/../build[lib,bin]
1400 */
1401    let p_id = PkgId::new("foo");
1402    let workspace = create_local_package(&p_id);
1403    let workspace = workspace.path();
1404    let dest_workspace = mk_empty_workspace(&Path::init("bar"), &NoVersion, "dest_workspace");
1405    let dest_workspace = dest_workspace.path();
1406    let foo_path = workspace.join_many(["src", "foo-0.1"]);
1407    let rust_path = Some(~[(~"RUST_PATH",
1408        format!("{}:{}",
1409                dest_workspace.as_str().unwrap(),
1410                foo_path.as_str().unwrap()))]);
1411    command_line_test_with_env(~[~"install"] + if hack_flag { ~[~"--rust-path-hack"] } else { ~[] } +
1412                                ~[~"foo"], dest_workspace, rust_path);
1413    assert_lib_exists(dest_workspace, &Path::init("foo"), NoVersion);
1414    assert_executable_exists(dest_workspace, "foo");
1415    assert_built_library_exists(dest_workspace, "foo");
1416    assert_built_executable_exists(dest_workspace, "foo");
1417    assert!(!lib_exists(workspace, &Path::init("foo"), NoVersion));
1418    assert!(!executable_exists(workspace, "foo"));
1419    assert!(!built_library_exists(workspace, "foo"));
1420    assert!(!built_executable_exists(workspace, "foo"));
1421 }
1422
1423 // Notice that this is the only test case where the --rust-path-hack
1424 // flag is actually needed
1425 #[test]
1426 fn test_rust_path_can_contain_package_dirs_with_flag() {
1427 /*
1428    Test that the temporary hack added for bootstrapping Servo builds
1429    works. That is: if you add $FOO/src/some_pkg to the RUST_PATH,
1430    it will find the sources in some_pkg, build them, and install them
1431    into the first entry in the RUST_PATH.
1432
1433    When the hack is removed, we should change this to a should_fail test.
1434 */
1435    rust_path_hack_test(true);
1436 }
1437
1438 #[test]
1439 #[should_fail]
1440 fn test_rust_path_can_contain_package_dirs_without_flag() {
1441    rust_path_hack_test(false);
1442 }
1443
1444 #[test]
1445 fn rust_path_hack_cwd() {
1446    // Same as rust_path_hack_test, but the CWD is the dir to build out of
1447    let cwd = TempDir::new("foo").expect("rust_path_hack_cwd");
1448    let cwd = cwd.path().join("foo");
1449    fs::mkdir_recursive(&cwd, io::UserRWX);
1450    writeFile(&cwd.join("lib.rs"), "pub fn f() { }");
1451
1452    let dest_workspace = mk_empty_workspace(&Path::init("bar"), &NoVersion, "dest_workspace");
1453    let dest_workspace = dest_workspace.path();
1454    // FIXME (#9639): This needs to handle non-utf8 paths
1455    let rust_path = Some(~[(~"RUST_PATH", dest_workspace.as_str().unwrap().to_owned())]);
1456    command_line_test_with_env([~"install", ~"--rust-path-hack", ~"foo"], &cwd, rust_path);
1457    debug!("Checking that foo exists in {}", dest_workspace.display());
1458    assert_lib_exists(dest_workspace, &Path::init("foo"), NoVersion);
1459    assert_built_library_exists(dest_workspace, "foo");
1460    assert!(!lib_exists(&cwd, &Path::init("foo"), NoVersion));
1461    assert!(!built_library_exists(&cwd, "foo"));
1462 }
1463
1464 #[test]
1465 fn rust_path_hack_multi_path() {
1466    // Same as rust_path_hack_test, but with a more complex package ID
1467    let cwd = TempDir::new("pkg_files").expect("rust_path_hack_cwd");
1468    let subdir = cwd.path().join_many(["foo", "bar", "quux"]);
1469    fs::mkdir_recursive(&subdir, io::UserRWX);
1470    writeFile(&subdir.join("lib.rs"), "pub fn f() { }");
1471    let name = ~"foo/bar/quux";
1472
1473    let dest_workspace = mk_empty_workspace(&Path::init("bar"), &NoVersion, "dest_workspace");
1474    let dest_workspace = dest_workspace.path();
1475    // FIXME (#9639): This needs to handle non-utf8 paths
1476    let rust_path = Some(~[(~"RUST_PATH", dest_workspace.as_str().unwrap().to_owned())]);
1477    command_line_test_with_env([~"install", ~"--rust-path-hack", name.clone()], &subdir, rust_path);
1478    debug!("Checking that {} exists in {}", name, dest_workspace.display());
1479    assert_lib_exists(dest_workspace, &Path::init("quux"), NoVersion);
1480    assert_built_library_exists(dest_workspace, name);
1481    assert!(!lib_exists(&subdir, &Path::init("quux"), NoVersion));
1482    assert!(!built_library_exists(&subdir, name));
1483 }
1484
1485 #[test]
1486 fn rust_path_hack_install_no_arg() {
1487    // Same as rust_path_hack_cwd, but making rustpkg infer the pkg id
1488    let cwd = TempDir::new("pkg_files").expect("rust_path_hack_install_no_arg");
1489    let cwd = cwd.path();
1490    let source_dir = cwd.join("foo");
1491    assert!(make_dir_rwx(&source_dir));
1492    writeFile(&source_dir.join("lib.rs"), "pub fn f() { }");
1493
1494    let dest_workspace = mk_empty_workspace(&Path::init("bar"), &NoVersion, "dest_workspace");
1495    let dest_workspace = dest_workspace.path();
1496    // FIXME (#9639): This needs to handle non-utf8 paths
1497    let rust_path = Some(~[(~"RUST_PATH", dest_workspace.as_str().unwrap().to_owned())]);
1498    command_line_test_with_env([~"install", ~"--rust-path-hack"], &source_dir, rust_path);
1499    debug!("Checking that foo exists in {}", dest_workspace.display());
1500    assert_lib_exists(dest_workspace, &Path::init("foo"), NoVersion);
1501    assert_built_library_exists(dest_workspace, "foo");
1502    assert!(!lib_exists(&source_dir, &Path::init("foo"), NoVersion));
1503    assert!(!built_library_exists(cwd, "foo"));
1504 }
1505
1506 #[test]
1507 fn rust_path_hack_build_no_arg() {
1508    // Same as rust_path_hack_install_no_arg, but building instead of installing
1509    let cwd = TempDir::new("pkg_files").expect("rust_path_hack_build_no_arg");
1510    let source_dir = cwd.path().join("foo");
1511    assert!(make_dir_rwx(&source_dir));
1512    writeFile(&source_dir.join("lib.rs"), "pub fn f() { }");
1513
1514    let dest_workspace = mk_empty_workspace(&Path::init("bar"), &NoVersion, "dest_workspace");
1515    let dest_workspace = dest_workspace.path();
1516    // FIXME (#9639): This needs to handle non-utf8 paths
1517    let rust_path = Some(~[(~"RUST_PATH", dest_workspace.as_str().unwrap().to_owned())]);
1518    command_line_test_with_env([~"build", ~"--rust-path-hack"], &source_dir, rust_path);
1519    debug!("Checking that foo exists in {}", dest_workspace.display());
1520    assert_built_library_exists(dest_workspace, "foo");
1521    assert!(!built_library_exists(&source_dir, "foo"));
1522 }
1523
1524 #[test]
1525 fn rust_path_hack_build_with_dependency() {
1526     let foo_id = PkgId::new("foo");
1527     let dep_id = PkgId::new("dep");
1528     // Tests that when --rust-path-hack is in effect, dependencies get built
1529     // into the destination workspace and not the source directory
1530     let work_dir = create_local_package(&foo_id);
1531     let work_dir = work_dir.path();
1532     let dep_workspace = create_local_package(&dep_id);
1533     let dep_workspace = dep_workspace.path();
1534     let dest_workspace = mk_emptier_workspace("dep");
1535     let dest_workspace = dest_workspace.path();
1536     let source_dir = work_dir.join_many(["src", "foo-0.1"]);
1537     writeFile(&source_dir.join("lib.rs"), "extern mod dep; pub fn f() { }");
1538     let dep_dir = dep_workspace.join_many(["src", "dep-0.1"]);
1539     let rust_path = Some(~[(~"RUST_PATH",
1540                           format!("{}:{}",
1541                                   dest_workspace.display(),
1542                                   dep_dir.display()))]);
1543     command_line_test_with_env([~"build", ~"--rust-path-hack", ~"foo"], work_dir, rust_path);
1544     assert_built_library_exists(dest_workspace, "dep");
1545     assert!(!built_library_exists(dep_workspace, "dep"));
1546 }
1547
1548 #[test]
1549 fn rust_path_install_target() {
1550     let dir_for_path = TempDir::new(
1551         "source_workspace").expect("rust_path_install_target failed");
1552     let mut dir = mk_workspace(dir_for_path.path(), &Path::init("foo"), &NoVersion);
1553     debug!("dir = {}", dir.display());
1554     writeFile(&dir.join("main.rs"), "fn main() { let _x = (); }");
1555     let dir_to_install_to = TempDir::new(
1556         "dest_workspace").expect("rust_path_install_target failed");
1557     let dir_to_install_to = dir_to_install_to.path();
1558     dir.pop(); dir.pop();
1559
1560     // FIXME (#9639): This needs to handle non-utf8 paths
1561     let rust_path = Some(~[(~"RUST_PATH", format!("{}:{}",
1562                                                   dir_to_install_to.as_str().unwrap(),
1563                                                   dir.as_str().unwrap()))]);
1564     let cwd = os::getcwd();
1565     command_line_test_with_env([~"install", ~"foo"],
1566                                &cwd,
1567                                rust_path);
1568
1569     assert_executable_exists(dir_to_install_to, "foo");
1570
1571 }
1572
1573 #[test]
1574 fn sysroot_flag() {
1575     let p_id = PkgId::new("foo");
1576     let workspace = create_local_package(&p_id);
1577     let workspace = workspace.path();
1578     // no-op sysroot setting; I'm not sure how else to test this
1579     let test_sys = test_sysroot();
1580     // FIXME (#9639): This needs to handle non-utf8 paths
1581     command_line_test([~"--sysroot",
1582                        test_sys.as_str().unwrap().to_owned(),
1583                        ~"build",
1584                        ~"foo"],
1585                       workspace);
1586     assert_built_executable_exists(workspace, "foo");
1587 }
1588
1589 #[test]
1590 fn compile_flag_build() {
1591     let p_id = PkgId::new("foo");
1592     let workspace = create_local_package(&p_id);
1593     let workspace = workspace.path();
1594     let test_sys = test_sysroot();
1595     // FIXME (#9639): This needs to handle non-utf8 paths
1596     command_line_test([test_sys.as_str().unwrap().to_owned(),
1597                        ~"build",
1598                        ~"--no-link",
1599                        ~"foo"],
1600                       workspace);
1601     assert!(!built_executable_exists(workspace, "foo"));
1602     assert!(object_file_exists(workspace, "foo"));
1603 }
1604
1605 #[test]
1606 fn compile_flag_fail() {
1607     // --no-link shouldn't be accepted for install
1608     let p_id = PkgId::new("foo");
1609     let workspace = create_local_package(&p_id);
1610     let workspace = workspace.path();
1611     let test_sys = test_sysroot();
1612     // FIXME (#9639): This needs to handle non-utf8 paths
1613     command_line_test_expect_fail([test_sys.as_str().unwrap().to_owned(),
1614                        ~"install",
1615                        ~"--no-link",
1616                        ~"foo"],
1617                       workspace, None, BAD_FLAG_CODE);
1618     assert!(!built_executable_exists(workspace, "foo"));
1619     assert!(!object_file_exists(workspace, "foo"));
1620 }
1621
1622 #[test]
1623 fn notrans_flag_build() {
1624     let p_id = PkgId::new("foo");
1625     let workspace = create_local_package(&p_id);
1626     let workspace = workspace.path();
1627     let flags_to_test = [~"--no-trans", ~"--parse-only",
1628                          ~"--pretty", ~"-S"];
1629
1630     for flag in flags_to_test.iter() {
1631         let test_sys = test_sysroot();
1632         // FIXME (#9639): This needs to handle non-utf8 paths
1633         command_line_test([test_sys.as_str().unwrap().to_owned(),
1634                            ~"build",
1635                            flag.clone(),
1636                            ~"foo"],
1637                           workspace);
1638         // Ideally we'd test that rustpkg actually succeeds, but
1639         // since task failure doesn't set the exit code properly,
1640         // we can't tell
1641         assert!(!built_executable_exists(workspace, "foo"));
1642         assert!(!object_file_exists(workspace, "foo"));
1643     }
1644 }
1645
1646 #[test]
1647 fn notrans_flag_fail() {
1648     // --no-trans shouldn't be accepted for install
1649     let p_id = PkgId::new("foo");
1650     let workspace = create_local_package(&p_id);
1651     let workspace = workspace.path();
1652     let flags_to_test = [~"--no-trans", ~"--parse-only",
1653                          ~"--pretty", ~"-S"];
1654     for flag in flags_to_test.iter() {
1655         let test_sys = test_sysroot();
1656         // FIXME (#9639): This needs to handle non-utf8 paths
1657         command_line_test_expect_fail([test_sys.as_str().unwrap().to_owned(),
1658                            ~"install",
1659                            flag.clone(),
1660                            ~"foo"],
1661                           workspace, None, BAD_FLAG_CODE);
1662         assert!(!built_executable_exists(workspace, "foo"));
1663         assert!(!object_file_exists(workspace, "foo"));
1664         assert!(!lib_exists(workspace, &Path::init("foo"), NoVersion));
1665     }
1666 }
1667
1668 #[test]
1669 fn dash_S() {
1670     let p_id = PkgId::new("foo");
1671     let workspace = create_local_package(&p_id);
1672     let workspace = workspace.path();
1673     let test_sys = test_sysroot();
1674     // FIXME (#9639): This needs to handle non-utf8 paths
1675     command_line_test([test_sys.as_str().unwrap().to_owned(),
1676                        ~"build",
1677                        ~"-S",
1678                        ~"foo"],
1679                       workspace);
1680     assert!(!built_executable_exists(workspace, "foo"));
1681     assert!(!object_file_exists(workspace, "foo"));
1682     assert!(assembly_file_exists(workspace, "foo"));
1683 }
1684
1685 #[test]
1686 fn dash_S_fail() {
1687     let p_id = PkgId::new("foo");
1688     let workspace = create_local_package(&p_id);
1689     let workspace = workspace.path();
1690     let test_sys = test_sysroot();
1691     // FIXME (#9639): This needs to handle non-utf8 paths
1692     command_line_test_expect_fail([test_sys.as_str().unwrap().to_owned(),
1693                        ~"install",
1694                        ~"-S",
1695                        ~"foo"],
1696                        workspace, None, BAD_FLAG_CODE);
1697     assert!(!built_executable_exists(workspace, "foo"));
1698     assert!(!object_file_exists(workspace, "foo"));
1699     assert!(!assembly_file_exists(workspace, "foo"));
1700 }
1701
1702 #[test]
1703 fn test_cfg_build() {
1704     let p_id = PkgId::new("foo");
1705     let workspace = create_local_package(&p_id);
1706     let workspace = workspace.path();
1707     // If the cfg flag gets messed up, this won't compile
1708     writeFile(&workspace.join_many(["src", "foo-0.1", "main.rs"]),
1709                "#[cfg(quux)] fn main() {}");
1710     let test_sys = test_sysroot();
1711     // FIXME (#9639): This needs to handle non-utf8 paths
1712     command_line_test([test_sys.as_str().unwrap().to_owned(),
1713                        ~"build",
1714                        ~"--cfg",
1715                        ~"quux",
1716                        ~"foo"],
1717                       workspace);
1718     assert_built_executable_exists(workspace, "foo");
1719 }
1720
1721 #[test]
1722 fn test_cfg_fail() {
1723     let p_id = PkgId::new("foo");
1724     let workspace = create_local_package(&p_id);
1725     let workspace = workspace.path();
1726     writeFile(&workspace.join_many(["src", "foo-0.1", "main.rs"]),
1727                "#[cfg(quux)] fn main() {}");
1728     let test_sys = test_sysroot();
1729     // FIXME (#9639): This needs to handle non-utf8 paths
1730     match command_line_test_partial([test_sys.as_str().unwrap().to_owned(),
1731                        ~"build",
1732                        ~"foo"],
1733                       workspace) {
1734         Success(..) => fail!("test_cfg_fail failed"),
1735         _          => ()
1736     }
1737 }
1738
1739
1740 #[test]
1741 fn test_emit_llvm_S_build() {
1742     let p_id = PkgId::new("foo");
1743     let workspace = create_local_package(&p_id);
1744     let workspace = workspace.path();
1745     let test_sys = test_sysroot();
1746     // FIXME (#9639): This needs to handle non-utf8 paths
1747     command_line_test([test_sys.as_str().unwrap().to_owned(),
1748                        ~"build",
1749                        ~"-S", ~"--emit-llvm",
1750                        ~"foo"],
1751                       workspace);
1752     assert!(!built_executable_exists(workspace, "foo"));
1753     assert!(!object_file_exists(workspace, "foo"));
1754     assert!(llvm_assembly_file_exists(workspace, "foo"));
1755     assert!(!assembly_file_exists(workspace, "foo"));
1756 }
1757
1758 #[test]
1759 fn test_emit_llvm_S_fail() {
1760     let p_id = PkgId::new("foo");
1761     let workspace = create_local_package(&p_id);
1762     let workspace = workspace.path();
1763     let test_sys = test_sysroot();
1764     // FIXME (#9639): This needs to handle non-utf8 paths
1765     command_line_test_expect_fail([test_sys.as_str().unwrap().to_owned(),
1766                        ~"install",
1767                        ~"-S", ~"--emit-llvm",
1768                        ~"foo"],
1769                        workspace,
1770                        None,
1771                        BAD_FLAG_CODE);
1772     assert!(!built_executable_exists(workspace, "foo"));
1773     assert!(!object_file_exists(workspace, "foo"));
1774     assert!(!llvm_assembly_file_exists(workspace, "foo"));
1775     assert!(!assembly_file_exists(workspace, "foo"));
1776 }
1777
1778 #[test]
1779 fn test_emit_llvm_build() {
1780     let p_id = PkgId::new("foo");
1781     let workspace = create_local_package(&p_id);
1782     let workspace = workspace.path();
1783     let test_sys = test_sysroot();
1784     // FIXME (#9639): This needs to handle non-utf8 paths
1785     command_line_test([test_sys.as_str().unwrap().to_owned(),
1786                        ~"build",
1787                        ~"--emit-llvm",
1788                        ~"foo"],
1789                       workspace);
1790     assert!(!built_executable_exists(workspace, "foo"));
1791     assert!(!object_file_exists(workspace, "foo"));
1792     assert!(llvm_bitcode_file_exists(workspace, "foo"));
1793     assert!(!assembly_file_exists(workspace, "foo"));
1794     assert!(!llvm_assembly_file_exists(workspace, "foo"));
1795 }
1796
1797 #[test]
1798 fn test_emit_llvm_fail() {
1799     let p_id = PkgId::new("foo");
1800     let workspace = create_local_package(&p_id);
1801     let workspace = workspace.path();
1802     let test_sys = test_sysroot();
1803     // FIXME (#9639): This needs to handle non-utf8 paths
1804     command_line_test_expect_fail([test_sys.as_str().unwrap().to_owned(),
1805                        ~"install",
1806                        ~"--emit-llvm",
1807                        ~"foo"],
1808                                   workspace,
1809                                   None,
1810                                   BAD_FLAG_CODE);
1811     assert!(!built_executable_exists(workspace, "foo"));
1812     assert!(!object_file_exists(workspace, "foo"));
1813     assert!(!llvm_bitcode_file_exists(workspace, "foo"));
1814     assert!(!llvm_assembly_file_exists(workspace, "foo"));
1815     assert!(!assembly_file_exists(workspace, "foo"));
1816 }
1817
1818 #[test]
1819 fn test_linker_build() {
1820     let p_id = PkgId::new("foo");
1821     let workspace = create_local_package(&p_id);
1822     let workspace = workspace.path();
1823     let matches = getopts([], optgroups());
1824     let options = build_session_options(@"rustpkg",
1825                                         matches.get_ref(),
1826                                         @diagnostic::DefaultEmitter as
1827                                             @diagnostic::Emitter);
1828     let sess = build_session(options,
1829                              @diagnostic::DefaultEmitter as
1830                                 @diagnostic::Emitter);
1831     let test_sys = test_sysroot();
1832     // FIXME (#9639): This needs to handle non-utf8 paths
1833     let cc = get_cc_prog(sess);
1834     command_line_test([test_sys.as_str().unwrap().to_owned(),
1835                        ~"install",
1836                        ~"--linker",
1837                        cc,
1838                        ~"foo"],
1839                       workspace);
1840     assert_executable_exists(workspace, "foo");
1841 }
1842
1843 #[test]
1844 fn test_build_install_flags_fail() {
1845     // The following flags can only be used with build or install:
1846     let forbidden = [~[~"--linker", ~"ld"],
1847                      ~[~"--link-args", ~"quux"],
1848                      ~[~"-O"],
1849                      ~[~"--opt-level", ~"2"],
1850                      ~[~"--save-temps"],
1851                      ~[~"--target", host_triple()],
1852                      ~[~"--target-cpu", ~"generic"],
1853                      ~[~"-Z", ~"--time-passes"]];
1854     let cwd = os::getcwd();
1855     for flag in forbidden.iter() {
1856         let test_sys = test_sysroot();
1857     // FIXME (#9639): This needs to handle non-utf8 paths
1858         command_line_test_expect_fail([test_sys.as_str().unwrap().to_owned(),
1859                            ~"list"] + *flag, &cwd, None, BAD_FLAG_CODE);
1860     }
1861 }
1862
1863 #[test]
1864 fn test_optimized_build() {
1865     let p_id = PkgId::new("foo");
1866     let workspace = create_local_package(&p_id);
1867     let workspace = workspace.path();
1868     let test_sys = test_sysroot();
1869     // FIXME (#9639): This needs to handle non-utf8 paths
1870     command_line_test([test_sys.as_str().unwrap().to_owned(),
1871                        ~"build",
1872                        ~"-O",
1873                        ~"foo"],
1874                       workspace);
1875     assert!(built_executable_exists(workspace, "foo"));
1876 }
1877
1878 #[test]
1879 fn pkgid_pointing_to_subdir() {
1880     // The actual repo is mockgithub.com/mozilla/some_repo
1881     // rustpkg should recognize that and treat the part after some_repo/ as a subdir
1882     let workspace = TempDir::new("parent_repo").expect("Couldn't create temp dir");
1883     let workspace = workspace.path();
1884     fs::mkdir_recursive(&workspace.join_many(["src", "mockgithub.com",
1885                                                 "mozilla", "some_repo"]),
1886                           io::UserRWX);
1887
1888     let foo_dir = workspace.join_many(["src", "mockgithub.com", "mozilla", "some_repo",
1889                                        "extras", "foo"]);
1890     let bar_dir = workspace.join_many(["src", "mockgithub.com", "mozilla", "some_repo",
1891                                        "extras", "bar"]);
1892     fs::mkdir_recursive(&foo_dir, io::UserRWX);
1893     fs::mkdir_recursive(&bar_dir, io::UserRWX);
1894     writeFile(&foo_dir.join("lib.rs"), "pub fn f() {}");
1895     writeFile(&bar_dir.join("lib.rs"), "pub fn g() {}");
1896
1897     debug!("Creating a file in {}", workspace.display());
1898     let testpkg_dir = workspace.join_many(["src", "testpkg-0.1"]);
1899     fs::mkdir_recursive(&testpkg_dir, io::UserRWX);
1900
1901     writeFile(&testpkg_dir.join("main.rs"),
1902               "extern mod foo = \"mockgithub.com/mozilla/some_repo/extras/foo\";\n
1903                extern mod bar = \"mockgithub.com/mozilla/some_repo/extras/bar\";\n
1904                use foo::f; use bar::g; \n
1905                fn main() { f(); g(); }");
1906
1907     command_line_test([~"install", ~"testpkg"], workspace);
1908     assert_executable_exists(workspace, "testpkg");
1909 }
1910
1911 #[test]
1912 fn test_recursive_deps() {
1913     let a_id = PkgId::new("a");
1914     let b_id = PkgId::new("b");
1915     let c_id = PkgId::new("c");
1916     let b_workspace = create_local_package_with_dep(&b_id, &c_id);
1917     let b_workspace = b_workspace.path();
1918     writeFile(&b_workspace.join_many(["src", "c-0.1", "lib.rs"]),
1919                "pub fn g() {}");
1920     let a_workspace = create_local_package(&a_id);
1921     let a_workspace = a_workspace.path();
1922     writeFile(&a_workspace.join_many(["src", "a-0.1", "main.rs"]),
1923                "extern mod b; use b::f; fn main() { f(); }");
1924     writeFile(&b_workspace.join_many(["src", "b-0.1", "lib.rs"]),
1925                "extern mod c; use c::g; pub fn f() { g(); }");
1926     // FIXME (#9639): This needs to handle non-utf8 paths
1927     let environment = Some(~[(~"RUST_PATH", b_workspace.as_str().unwrap().to_owned())]);
1928     debug!("RUST_PATH={}", b_workspace.display());
1929     command_line_test_with_env([~"install", ~"a"],
1930                                a_workspace,
1931                                environment);
1932     assert_lib_exists(a_workspace, &Path::init("a"), NoVersion);
1933     assert_lib_exists(b_workspace, &Path::init("b"), NoVersion);
1934     assert_lib_exists(b_workspace, &Path::init("c"), NoVersion);
1935 }
1936
1937 #[test]
1938 fn test_install_to_rust_path() {
1939     let p_id = PkgId::new("foo");
1940     let second_workspace = create_local_package(&p_id);
1941     let second_workspace = second_workspace.path();
1942     let first_workspace = mk_empty_workspace(&Path::init("p"), &NoVersion, "dest");
1943     let first_workspace = first_workspace.path();
1944     // FIXME (#9639): This needs to handle non-utf8 paths
1945     let rust_path = Some(~[(~"RUST_PATH",
1946                             format!("{}:{}", first_workspace.as_str().unwrap(),
1947                                     second_workspace.as_str().unwrap()))]);
1948     debug!("RUST_PATH={}:{}", first_workspace.display(), second_workspace.display());
1949     let test_sys = test_sysroot();
1950     // FIXME (#9639): This needs to handle non-utf8 paths
1951     command_line_test_with_env([test_sys.as_str().unwrap().to_owned(),
1952                        ~"install",
1953                        ~"foo"],
1954                       &os::getcwd(), rust_path);
1955     assert!(!built_executable_exists(first_workspace, "foo"));
1956     assert!(built_executable_exists(second_workspace, "foo"));
1957     assert_executable_exists(first_workspace, "foo");
1958     assert!(!executable_exists(second_workspace, "foo"));
1959 }
1960
1961 #[test]
1962 fn test_target_specific_build_dir() {
1963     let p_id = PkgId::new("foo");
1964     let workspace = create_local_package(&p_id);
1965     let workspace = workspace.path();
1966     let test_sys = test_sysroot();
1967     // FIXME (#9639): This needs to handle non-utf8 paths
1968     command_line_test([test_sys.as_str().unwrap().to_owned(),
1969                        ~"build",
1970                        ~"foo"],
1971                       workspace);
1972     assert!(target_build_dir(workspace).is_dir());
1973     assert!(built_executable_exists(workspace, "foo"));
1974     assert!(fs::readdir(&workspace.join("build")).len() == 1);
1975 }
1976
1977 #[test]
1978 fn test_target_specific_install_dir() {
1979     let p_id = PkgId::new("foo");
1980     let workspace = create_local_package(&p_id);
1981     let workspace = workspace.path();
1982     let test_sys = test_sysroot();
1983     // FIXME (#9639): This needs to handle non-utf8 paths
1984     command_line_test([test_sys.as_str().unwrap().to_owned(),
1985                        ~"install",
1986                        ~"foo"],
1987                       workspace);
1988     assert!(workspace.join_many([~"lib", host_triple()]).is_dir());
1989     assert_lib_exists(workspace, &Path::init("foo"), NoVersion);
1990     assert!(fs::readdir(&workspace.join("lib")).len() == 1);
1991     assert!(workspace.join("bin").is_dir());
1992     assert_executable_exists(workspace, "foo");
1993 }
1994
1995 #[test]
1996 #[ignore(reason = "See #7240")]
1997 fn test_dependencies_terminate() {
1998     let b_id = PkgId::new("b");
1999     let workspace = create_local_package(&b_id);
2000     let workspace = workspace.path();
2001     let b_dir = workspace.join_many(["src", "b-0.1"]);
2002     let b_subdir = b_dir.join("test");
2003     fs::mkdir_recursive(&b_subdir, io::UserRWX);
2004     writeFile(&b_subdir.join("test.rs"),
2005               "extern mod b; use b::f; #[test] fn g() { f() }");
2006     command_line_test([~"install", ~"b"], workspace);
2007 }
2008
2009 #[test]
2010 fn install_after_build() {
2011     let b_id = PkgId::new("b");
2012     let workspace = create_local_package(&b_id);
2013     let workspace = workspace.path();
2014     command_line_test([~"build", ~"b"], workspace);
2015     command_line_test([~"install", ~"b"], workspace);
2016     assert_executable_exists(workspace, b_id.short_name);
2017     assert_lib_exists(workspace, &b_id.path, NoVersion);
2018 }
2019
2020 #[test]
2021 fn reinstall() {
2022     let b = PkgId::new("b");
2023     let workspace = create_local_package(&b);
2024     let workspace = workspace.path();
2025     // 1. Install, then remove executable file, then install again,
2026     // and make sure executable was re-installed
2027     command_line_test([~"install", ~"b"], workspace);
2028     assert_executable_exists(workspace, b.short_name);
2029     assert_lib_exists(workspace, &b.path, NoVersion);
2030     remove_executable_file(&b, workspace);
2031     command_line_test([~"install", ~"b"], workspace);
2032     assert_executable_exists(workspace, b.short_name);
2033     // 2. Build, then remove build executable file, then build again,
2034     // and make sure executable was re-built.
2035     command_line_test([~"build", ~"b"], workspace);
2036     remove_built_executable_file(&b, workspace);
2037     command_line_test([~"build", ~"b"], workspace);
2038     assert_built_executable_exists(workspace, b.short_name);
2039     // 3. Install, then remove both executable and built executable,
2040     // then install again, make sure both were recreated
2041     command_line_test([~"install", ~"b"], workspace);
2042     remove_executable_file(&b, workspace);
2043     remove_built_executable_file(&b, workspace);
2044     command_line_test([~"install", ~"b"], workspace);
2045     assert_executable_exists(workspace, b.short_name);
2046     assert_built_executable_exists(workspace, b.short_name);
2047 }
2048
2049 #[test]
2050 fn correct_package_name_with_rust_path_hack() {
2051     /*
2052     Set rust_path_hack flag
2053
2054     Try to install bar
2055     Check that:
2056     - no output gets produced in any workspace
2057     - there's an error
2058     */
2059
2060     // Set RUST_PATH to something containing only the sources for foo
2061     let foo_id = PkgId::new("foo");
2062     let bar_id = PkgId::new("bar");
2063     let foo_workspace = create_local_package(&foo_id);
2064     let foo_workspace = foo_workspace.path();
2065     let dest_workspace = mk_empty_workspace(&Path::init("bar"), &NoVersion, "dest_workspace");
2066     let dest_workspace = dest_workspace.path();
2067
2068     writeFile(&dest_workspace.join_many(["src", "bar-0.1", "main.rs"]),
2069               "extern mod blat; fn main() { let _x = (); }");
2070
2071     let foo_path = foo_workspace.join_many(["src", "foo-0.1"]);
2072     // FIXME (#9639): This needs to handle non-utf8 paths
2073     let rust_path = Some(~[(~"RUST_PATH", format!("{}:{}", dest_workspace.as_str().unwrap(),
2074                                                   foo_path.as_str().unwrap()))]);
2075     // bar doesn't exist, but we want to make sure rustpkg doesn't think foo is bar
2076     command_line_test_expect_fail([~"install", ~"--rust-path-hack", ~"bar"],
2077                                   // FIXME #3408: Should be NONEXISTENT_PACKAGE_CODE
2078                                dest_workspace, rust_path, COPY_FAILED_CODE);
2079     assert!(!executable_exists(dest_workspace, "bar"));
2080     assert!(!lib_exists(dest_workspace, &bar_id.path.clone(), bar_id.version.clone()));
2081     assert!(!executable_exists(dest_workspace, "foo"));
2082     assert!(!lib_exists(dest_workspace, &foo_id.path.clone(), foo_id.version.clone()));
2083     assert!(!executable_exists(foo_workspace, "bar"));
2084     assert!(!lib_exists(foo_workspace, &bar_id.path.clone(), bar_id.version.clone()));
2085     assert!(!executable_exists(foo_workspace, "foo"));
2086     assert!(!lib_exists(foo_workspace, &foo_id.path.clone(), foo_id.version.clone()));
2087 }
2088
2089 #[test]
2090 fn test_rustpkg_test_creates_exec() {
2091     let foo_id = PkgId::new("foo");
2092     let foo_workspace = create_local_package(&foo_id);
2093     let foo_workspace = foo_workspace.path();
2094     writeFile(&foo_workspace.join_many(["src", "foo-0.1", "test.rs"]),
2095               "#[test] fn f() { assert!('a' == 'a'); }");
2096     command_line_test([~"test", ~"foo"], foo_workspace);
2097     assert!(test_executable_exists(foo_workspace, "foo"));
2098 }
2099
2100 #[test]
2101 fn test_rustpkg_test_output() {
2102     let workspace = create_local_package_with_test(&PkgId::new("foo"));
2103     let output = command_line_test([~"test", ~"foo"], workspace.path());
2104     let output_str = str::from_utf8(output.output);
2105     // The first two assertions are separate because test output may
2106     // contain color codes, which could appear between "test f" and "ok".
2107     assert!(output_str.contains("test f"));
2108     assert!(output_str.contains("ok"));
2109     assert!(output_str.contains("1 passed; 0 failed; 0 ignored; 0 measured"));
2110 }
2111
2112 #[test]
2113 fn test_rustpkg_test_failure_exit_status() {
2114     let foo_id = PkgId::new("foo");
2115     let foo_workspace = create_local_package(&foo_id);
2116     let foo_workspace = foo_workspace.path();
2117     writeFile(&foo_workspace.join_many(["src", "foo-0.1", "test.rs"]),
2118               "#[test] fn f() { assert!('a' != 'a'); }");
2119     let res = command_line_test_partial([~"test", ~"foo"], foo_workspace);
2120     match res {
2121         Fail(_) => {},
2122         Success(..) => fail!("Expected test failure but got success")
2123     }
2124 }
2125
2126 #[test]
2127 fn test_rustpkg_test_cfg() {
2128     let foo_id = PkgId::new("foo");
2129     let foo_workspace = create_local_package(&foo_id);
2130     let foo_workspace = foo_workspace.path();
2131     writeFile(&foo_workspace.join_many(["src", "foo-0.1", "test.rs"]),
2132               "#[test] #[cfg(not(foobar))] fn f() { assert!('a' != 'a'); }");
2133     let output = command_line_test([~"test", ~"--cfg", ~"foobar", ~"foo"],
2134                                    foo_workspace);
2135     let output_str = str::from_utf8(output.output);
2136     assert!(output_str.contains("0 passed; 0 failed; 0 ignored; 0 measured"));
2137 }
2138
2139 #[test]
2140 fn test_rebuild_when_needed() {
2141     let foo_id = PkgId::new("foo");
2142     let foo_workspace = create_local_package(&foo_id);
2143     let foo_workspace = foo_workspace.path();
2144     let test_crate = foo_workspace.join_many(["src", "foo-0.1", "test.rs"]);
2145     writeFile(&test_crate, "#[test] fn f() { assert!('a' == 'a'); }");
2146     command_line_test([~"test", ~"foo"], foo_workspace);
2147     assert!(test_executable_exists(foo_workspace, "foo"));
2148     let test_executable = built_test_in_workspace(&foo_id,
2149             foo_workspace).expect("test_rebuild_when_needed failed");
2150     frob_source_file(foo_workspace, &foo_id, "test.rs");
2151     chmod_read_only(&test_executable);
2152     match command_line_test_partial([~"test", ~"foo"], foo_workspace) {
2153         Success(..) => fail!("test_rebuild_when_needed didn't rebuild"),
2154         Fail(ref r) if r.status.matches_exit_status(65) => (), // ok
2155         Fail(_) => fail!("test_rebuild_when_needed failed for some other reason")
2156     }
2157 }
2158
2159 #[test]
2160 #[ignore] // FIXME (#10257): This doesn't work as is since a read only file can't execute
2161 fn test_no_rebuilding() {
2162     let foo_id = PkgId::new("foo");
2163     let foo_workspace = create_local_package(&foo_id);
2164     let foo_workspace = foo_workspace.path();
2165     let test_crate = foo_workspace.join_many(["src", "foo-0.1", "test.rs"]);
2166     writeFile(&test_crate, "#[test] fn f() { assert!('a' == 'a'); }");
2167     command_line_test([~"test", ~"foo"], foo_workspace);
2168     assert!(test_executable_exists(foo_workspace, "foo"));
2169     let test_executable = built_test_in_workspace(&foo_id,
2170                             foo_workspace).expect("test_no_rebuilding failed");
2171     chmod_read_only(&test_executable);
2172     match command_line_test_partial([~"test", ~"foo"], foo_workspace) {
2173         Success(..) => (), // ok
2174         Fail(ref r) if r.status.matches_exit_status(65) =>
2175             fail!("test_no_rebuilding failed: it rebuilt the tests"),
2176         Fail(_) => fail!("test_no_rebuilding failed for some other reason")
2177     }
2178 }
2179
2180 #[test]
2181 fn test_installed_read_only() {
2182     // Install sources from a "remote" (actually a local github repo)
2183     // Check that afterward, sources are read-only and installed under build/
2184     let temp_pkg_id = git_repo_pkg();
2185     let repo = init_git_repo(&temp_pkg_id.path);
2186     let repo = repo.path();
2187     debug!("repo = {}", repo.display());
2188     let repo_subdir = repo.join_many(["mockgithub.com", "catamorphism", "test-pkg"]);
2189     debug!("repo_subdir = {}", repo_subdir.display());
2190
2191     writeFile(&repo_subdir.join("main.rs"),
2192               "fn main() { let _x = (); }");
2193     writeFile(&repo_subdir.join("lib.rs"),
2194               "pub fn f() { let _x = (); }");
2195     add_git_tag(&repo_subdir, ~"0.1"); // this has the effect of committing the files
2196
2197     // FIXME (#9639): This needs to handle non-utf8 paths
2198     command_line_test([~"install", temp_pkg_id.path.as_str().unwrap().to_owned()], repo);
2199
2200     let ws = repo.join(".rust");
2201     // Check that all files exist
2202     debug!("Checking for files in {}", ws.display());
2203     let exec = target_executable_in_workspace(&temp_pkg_id, &ws);
2204     debug!("exec = {}", exec.display());
2205     assert!(exec.exists());
2206     assert!(is_rwx(&exec));
2207     let built_lib =
2208         built_library_in_workspace(&temp_pkg_id,
2209                                    &ws).expect("test_install_git: built lib should exist");
2210     assert!(built_lib.exists());
2211     assert!(is_rwx(&built_lib));
2212
2213     // Make sure sources are (a) under "build" and (b) read-only
2214     let src1 = target_build_dir(&ws).join_many([~"src", temp_pkg_id.to_str(), ~"main.rs"]);
2215     let src2 = target_build_dir(&ws).join_many([~"src", temp_pkg_id.to_str(), ~"lib.rs"]);
2216     assert!(src1.exists());
2217     assert!(src2.exists());
2218     assert!(is_read_only(&src1));
2219     assert!(is_read_only(&src2));
2220 }
2221
2222 #[test]
2223 fn test_installed_local_changes() {
2224     let temp_pkg_id = git_repo_pkg();
2225     let repo = init_git_repo(&temp_pkg_id.path);
2226     let repo = repo.path();
2227     debug!("repo = {}", repo.display());
2228     let repo_subdir = repo.join_many(["mockgithub.com", "catamorphism", "test-pkg"]);
2229     debug!("repo_subdir = {}", repo_subdir.display());
2230     fs::mkdir_recursive(&repo.join_many([".rust", "src"]), io::UserRWX);
2231
2232     writeFile(&repo_subdir.join("main.rs"),
2233               "fn main() { let _x = (); }");
2234     writeFile(&repo_subdir.join("lib.rs"),
2235               "pub fn f() { let _x = (); }");
2236     add_git_tag(&repo_subdir, ~"0.1"); // this has the effect of committing the files
2237
2238     // FIXME (#9639): This needs to handle non-utf8 paths
2239     command_line_test([~"install", temp_pkg_id.path.as_str().unwrap().to_owned()], repo);
2240
2241
2242     // We installed the dependency.
2243     // Now start a new workspace and clone it into it
2244     let hacking_workspace = mk_emptier_workspace("hacking_workspace");
2245     let hacking_workspace = hacking_workspace.path();
2246     let target_dir = hacking_workspace.join_many(["src",
2247                                                   "mockgithub.com",
2248                                                   "catamorphism",
2249                                                   "test-pkg-0.1"]);
2250     debug!("---- git clone {} {}", repo_subdir.display(), target_dir.display());
2251
2252     let c_res = safe_git_clone(&repo_subdir, &NoVersion, &target_dir);
2253
2254     match c_res {
2255         DirToUse(_) => fail!("test_installed_local_changes failed"),
2256         CheckedOutSources => ()
2257     };
2258
2259     // Make a local change to it
2260     writeFile(&target_dir.join("lib.rs"),
2261               "pub fn g() { let _x = (); }");
2262
2263     // Finally, make *another* package that uses it
2264     let importer_pkg_id = fake_pkg();
2265     let main_subdir = create_local_package_in(&importer_pkg_id, hacking_workspace);
2266     writeFile(&main_subdir.join("main.rs"),
2267               "extern mod test = \"mockgithub.com/catamorphism/test-pkg\"; \
2268               use test::g;
2269               fn main() { g(); }");
2270     // And make sure we can build it
2271
2272     // FIXME (#9639): This needs to handle non-utf8 paths
2273     command_line_test([~"build", importer_pkg_id.path.as_str().unwrap().to_owned()],
2274                       hacking_workspace);
2275 }
2276
2277 #[test]
2278 fn test_7402() {
2279     let dir = create_local_package(&PkgId::new("foo"));
2280     let dest_workspace = TempDir::new("more_rust").expect("test_7402");
2281     let dest_workspace = dest_workspace.path();
2282     // FIXME (#9639): This needs to handle non-utf8 paths
2283     let rust_path = Some(~[(~"RUST_PATH",
2284                             format!("{}:{}", dest_workspace.as_str().unwrap(),
2285                                     dir.path().as_str().unwrap()))]);
2286     let cwd = os::getcwd();
2287     command_line_test_with_env([~"install", ~"foo"], &cwd, rust_path);
2288     assert_executable_exists(dest_workspace, "foo");
2289 }
2290
2291 #[test]
2292 fn test_compile_error() {
2293     let foo_id = PkgId::new("foo");
2294     let foo_workspace = create_local_package(&foo_id);
2295     let foo_workspace = foo_workspace.path();
2296     let main_crate = foo_workspace.join_many(["src", "foo-0.1", "main.rs"]);
2297     // Write something bogus
2298     writeFile(&main_crate, "pub fn main() { if 42 != ~\"the answer\" { fail!(); } }");
2299     let result = command_line_test_partial([~"build", ~"foo"], foo_workspace);
2300     match result {
2301         Success(..) => fail!("Failed by succeeding!"), // should be a compile error
2302         Fail(ref status) => {
2303             debug!("Failed with status {:?}... that's good, right?", status);
2304         }
2305     }
2306 }
2307
2308 #[test]
2309 fn find_sources_in_cwd() {
2310     let temp_dir = TempDir::new("sources").expect("find_sources_in_cwd failed");
2311     let temp_dir = temp_dir.path();
2312     let source_dir = temp_dir.join("foo");
2313     fs::mkdir_recursive(&source_dir, io::UserRWX);
2314     writeFile(&source_dir.join("main.rs"),
2315               "fn main() { let _x = (); }");
2316     command_line_test([~"install", ~"foo"], &source_dir);
2317     assert_executable_exists(&source_dir.join(".rust"), "foo");
2318 }
2319
2320 #[test]
2321 #[ignore(reason="busted")]
2322 fn test_c_dependency_ok() {
2323     // Pkg has a custom build script that adds a single C file as a dependency, and
2324     // registers a hook to build it if it's not fresh
2325     // After running `build`, test that the C library built
2326
2327     let dir = create_local_package(&PkgId::new("cdep"));
2328     let dir = dir.path();
2329     writeFile(&dir.join_many(["src", "cdep-0.1", "main.rs"]),
2330               "#[link_args = \"-lfoo\"]\nextern { fn f(); } \
2331               \nfn main() { unsafe { f(); } }");
2332     writeFile(&dir.join_many(["src", "cdep-0.1", "foo.c"]), "void f() {}");
2333
2334     debug!("dir = {}", dir.display());
2335     let source = Path::init(file!()).dir_path().join_many(
2336         [~"testsuite", ~"pass", ~"src", ~"c-dependencies", ~"pkg.rs"]);
2337     fs::copy(&source, &dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"]));
2338     command_line_test([~"build", ~"cdep"], dir);
2339     assert_executable_exists(dir, "cdep");
2340     let out_dir = target_build_dir(dir).join("cdep");
2341     let c_library_path = out_dir.join(platform_library_name("foo"));
2342     debug!("c library path: {}", c_library_path.display());
2343     assert!(c_library_path.exists());
2344 }
2345
2346 #[test]
2347 #[ignore(reason="busted")]
2348 fn test_c_dependency_no_rebuilding() {
2349     let dir = create_local_package(&PkgId::new("cdep"));
2350     let dir = dir.path();
2351     writeFile(&dir.join_many(["src", "cdep-0.1", "main.rs"]),
2352               "#[link_args = \"-lfoo\"]\nextern { fn f(); } \
2353               \nfn main() { unsafe { f(); } }");
2354     writeFile(&dir.join_many(["src", "cdep-0.1", "foo.c"]), "void f() {}");
2355
2356     debug!("dir = {}", dir.display());
2357     let source = Path::init(file!()).dir_path().join_many(
2358         [~"testsuite", ~"pass", ~"src", ~"c-dependencies", ~"pkg.rs"]);
2359     fs::copy(&source, &dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"]));
2360     command_line_test([~"build", ~"cdep"], dir);
2361     assert_executable_exists(dir, "cdep");
2362     let out_dir = target_build_dir(dir).join("cdep");
2363     let c_library_path = out_dir.join(platform_library_name("foo"));
2364     debug!("c library path: {}", c_library_path.display());
2365     assert!(c_library_path.exists());
2366
2367     // Now, make it read-only so rebuilding will fail
2368     assert!(chmod_read_only(&c_library_path));
2369
2370     match command_line_test_partial([~"build", ~"cdep"], dir) {
2371         Success(..) => (), // ok
2372         Fail(ref r) if r.status.matches_exit_status(65) =>
2373             fail!("test_c_dependency_no_rebuilding failed: \
2374                     it tried to rebuild foo.c"),
2375         Fail(_) =>
2376             fail!("test_c_dependency_no_rebuilding failed for some other reason")
2377     }
2378 }
2379
2380 #[test]
2381 #[ignore(reason="busted")]
2382 fn test_c_dependency_yes_rebuilding() {
2383     let dir = create_local_package(&PkgId::new("cdep"));
2384     let dir = dir.path();
2385     writeFile(&dir.join_many(["src", "cdep-0.1", "main.rs"]),
2386               "#[link_args = \"-lfoo\"]\nextern { fn f(); } \
2387               \nfn main() { unsafe { f(); } }");
2388     let c_file_name = dir.join_many(["src", "cdep-0.1", "foo.c"]);
2389     writeFile(&c_file_name, "void f() {}");
2390
2391     let source = Path::init(file!()).dir_path().join_many(
2392         [~"testsuite", ~"pass", ~"src", ~"c-dependencies", ~"pkg.rs"]);
2393     let target = dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"]);
2394     debug!("Copying {} -> {}", source.display(), target.display());
2395     fs::copy(&source, &target);
2396     command_line_test([~"build", ~"cdep"], dir);
2397     assert_executable_exists(dir, "cdep");
2398     let out_dir = target_build_dir(dir).join("cdep");
2399     let c_library_path = out_dir.join(platform_library_name("foo"));
2400     debug!("c library path: {}", c_library_path.display());
2401     assert!(c_library_path.exists());
2402
2403     // Now, make the Rust library read-only so rebuilding will fail
2404     match built_library_in_workspace(&PkgId::new("cdep"), dir) {
2405         Some(ref pth) => assert!(chmod_read_only(pth)),
2406         None => assert_built_library_exists(dir, "cdep")
2407     }
2408
2409     match command_line_test_partial([~"build", ~"cdep"], dir) {
2410         Success(..) => fail!("test_c_dependency_yes_rebuilding failed: \
2411                             it didn't rebuild and should have"),
2412         Fail(ref r) if r.status.matches_exit_status(65) => (),
2413         Fail(_) => fail!("test_c_dependency_yes_rebuilding failed for some other reason")
2414     }
2415 }
2416
2417 // n.b. This might help with #10253, or at least the error will be different.
2418 #[test]
2419 fn correct_error_dependency() {
2420     // Supposing a package we're trying to install via a dependency doesn't
2421     // exist, we should throw a condition, and not ICE
2422     let dir = create_local_package(&PkgId::new("badpkg"));
2423
2424     let dir = dir.path();
2425     writeFile(&dir.join_many(["src", "badpkg-0.1", "main.rs"]),
2426               "extern mod p = \"some_package_that_doesnt_exist\";
2427                fn main() {}");
2428
2429     match command_line_test_partial([~"build", ~"badpkg"], dir) {
2430         Fail(ProcessOutput{ error: error, output: output, .. }) => {
2431             assert!(str::is_utf8(error));
2432             assert!(str::is_utf8(output));
2433             let error_str = str::from_utf8(error);
2434             let out_str   = str::from_utf8(output);
2435             debug!("ss = {}", error_str);
2436             debug!("out_str = {}", out_str);
2437             if out_str.contains("Package badpkg depends on some_package_that_doesnt_exist") &&
2438                 !error_str.contains("nonexistent_package") {
2439                 // Ok
2440                 ()
2441             } else {
2442                 fail!("Wrong error");
2443             }
2444         }
2445         Success(..)       => fail!("Test passed when it should have failed")
2446     }
2447 }
2448
2449 /// Returns true if p exists and is executable
2450 fn is_executable(p: &Path) -> bool {
2451     p.exists() && p.stat().perm & io::UserExecute == io::UserExecute
2452 }