]> git.lizzy.rs Git - rust.git/blob - src/librustpkg/tests.rs
828be5dce12788c0495e010b1d784f15f5127ed0
[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::Ctx;
14 use std::hashmap::HashMap;
15 use std::{io, libc, os, result, run, str};
16 use extra::tempfile::mkdtemp;
17 use std::run::ProcessOutput;
18 use installed_packages::list_installed_packages;
19 use package_path::*;
20 use package_id::{PkgId};
21 use version::{ExactRevision, NoVersion, Version, Tagged};
22 use path_util::{target_executable_in_workspace, target_library_in_workspace,
23                target_test_in_workspace, target_bench_in_workspace,
24                make_dir_rwx, U_RWX, library_in_workspace,
25                built_bench_in_workspace, built_test_in_workspace,
26                built_library_in_workspace, built_executable_in_workspace,
27                 installed_library_in_workspace, rust_path};
28 use target::*;
29
30 /// Returns the last-modified date as an Option
31 fn datestamp(p: &Path) -> Option<libc::time_t> {
32     p.stat().map(|stat| stat.st_mtime)
33 }
34
35 fn fake_ctxt(sysroot_opt: Option<@Path>) -> Ctx {
36     Ctx {
37         sysroot_opt: sysroot_opt,
38         json: false,
39         dep_cache: @mut HashMap::new()
40     }
41 }
42
43 fn fake_pkg() -> PkgId {
44     let sn = ~"bogus";
45     let remote = RemotePath(Path(sn));
46     PkgId {
47         local_path: normalize(remote.clone()),
48         remote_path: remote,
49         short_name: sn,
50         version: NoVersion
51     }
52 }
53
54 fn git_repo_pkg() -> PkgId {
55     let remote = RemotePath(Path("mockgithub.com/catamorphism/test-pkg"));
56     PkgId {
57         local_path: normalize(remote.clone()),
58         remote_path: remote,
59         short_name: ~"test_pkg",
60         version: NoVersion
61     }
62 }
63
64 fn git_repo_pkg_with_tag(a_tag: ~str) -> PkgId {
65     let remote = RemotePath(Path("mockgithub.com/catamorphism/test-pkg"));
66     PkgId {
67         local_path: normalize(remote.clone()),
68         remote_path: remote,
69         short_name: ~"test_pkg",
70         version: Tagged(a_tag)
71     }
72 }
73
74 fn writeFile(file_path: &Path, contents: &str) {
75     let out = io::file_writer(file_path, [io::Create, io::Truncate]).unwrap();
76     out.write_line(contents);
77 }
78
79 fn mk_empty_workspace(short_name: &LocalPath, version: &Version) -> Path {
80     let workspace_dir = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
81     mk_workspace(&workspace_dir, short_name, version);
82     workspace_dir
83 }
84
85 fn mk_workspace(workspace: &Path, short_name: &LocalPath, version: &Version) -> Path {
86     // include version number in directory name
87     let package_dir = workspace.push("src").push(fmt!("%s-%s",
88                                                       short_name.to_str(), version.to_str()));
89     assert!(os::mkdir_recursive(&package_dir, U_RWX));
90     package_dir
91 }
92
93 fn mk_temp_workspace(short_name: &LocalPath, version: &Version) -> Path {
94     let package_dir = mk_empty_workspace(short_name,
95                                          version).push("src").push(fmt!("%s-%s",
96                                                             short_name.to_str(),
97                                                             version.to_str()));
98
99     debug!("Created %s and does it exist? %?", package_dir.to_str(),
100           os::path_is_dir(&package_dir));
101     // Create main, lib, test, and bench files
102     debug!("mk_workspace: creating %s", package_dir.to_str());
103     assert!(os::mkdir_recursive(&package_dir, U_RWX));
104     debug!("Created %s and does it exist? %?", package_dir.to_str(),
105           os::path_is_dir(&package_dir));
106     // Create main, lib, test, and bench files
107
108     writeFile(&package_dir.push("main.rs"),
109               "fn main() { let _x = (); }");
110     writeFile(&package_dir.push("lib.rs"),
111               "pub fn f() { let _x = (); }");
112     writeFile(&package_dir.push("test.rs"),
113               "#[test] pub fn f() { (); }");
114     writeFile(&package_dir.push("bench.rs"),
115               "#[bench] pub fn f() { (); }");
116     package_dir
117 }
118
119 /// Should create an empty git repo in p, relative to the tmp dir, and return the new
120 /// absolute path
121 fn init_git_repo(p: &Path) -> Path {
122     assert!(!p.is_absolute());
123     let tmp = mkdtemp(&os::tmpdir(), "git_local").expect("couldn't create temp dir");
124     let work_dir = tmp.push_rel(p);
125     let work_dir_for_opts = work_dir.clone();
126     assert!(os::mkdir_recursive(&work_dir, U_RWX));
127     debug!("Running: git init in %s", work_dir.to_str());
128     let opts = run::ProcessOptions {
129         env: None,
130         dir: Some(&work_dir_for_opts),
131         in_fd: None,
132         out_fd: None,
133         err_fd: None
134     };
135     let mut prog = run::Process::new("git", [~"init"], opts);
136     let mut output = prog.finish_with_output();
137     if output.status == 0 {
138         // Add stuff to the dir so that git tag succeeds
139         writeFile(&work_dir.push("README"), "");
140         prog = run::Process::new("git", [~"add", ~"README"], opts);
141         output = prog.finish_with_output();
142         if output.status == 0 {
143             prog = run::Process::new("git", [~"commit", ~"-m", ~"whatever"], opts);
144             output = prog.finish_with_output();
145             if output.status == 0 {
146                 tmp
147             }
148             else {
149                 fail!("Couldn't commit in %s", work_dir.to_str());
150             }
151         }
152         else {
153             fail!("Couldn't add in %s", work_dir.to_str());
154         }
155     }
156     else {
157         fail!("Couldn't initialize git repository in %s", work_dir.to_str())
158     }
159 }
160
161 fn add_all_and_commit(repo: &Path) {
162     git_add_all(repo);
163     git_commit(repo, ~"floop");
164 }
165
166 fn git_commit(repo: &Path, msg: ~str) {
167     let mut prog = run::Process::new("git", [~"commit", ~"-m", msg],
168                                      run::ProcessOptions { env: None,
169                                                           dir: Some(repo),
170                                                           in_fd: None,
171                                                           out_fd: None,
172                                                           err_fd: None
173                                                          });
174     let output = prog.finish_with_output();
175     if output.status != 0 {
176         fail!("Couldn't commit in %s: output was %s", repo.to_str(),
177               str::from_bytes(output.output + output.error))
178     }
179
180 }
181
182 fn git_add_all(repo: &Path) {
183     let mut prog = run::Process::new("git", [~"add", ~"-A"],
184                                      run::ProcessOptions { env: None,
185                                                           dir: Some(repo),
186                                                           in_fd: None,
187                                                           out_fd: None,
188                                                           err_fd: None
189                                                          });
190     let output = prog.finish_with_output();
191     if output.status != 0 {
192         fail!("Couldn't add all files in %s: output was %s",
193               repo.to_str(), str::from_bytes(output.output + output.error))
194     }
195 }
196
197 fn add_git_tag(repo: &Path, tag: ~str) {
198     assert!(repo.is_absolute());
199     git_add_all(repo);
200     git_commit(repo, ~"whatever");
201     let mut prog = run::Process::new("git", [~"tag", tag.clone()],
202                                      run::ProcessOptions { env: None,
203                                                           dir: Some(repo),
204                                                           in_fd: None,
205                                                           out_fd: None,
206                                                           err_fd: None
207                                                          });
208     let output = prog.finish_with_output();
209     if output.status != 0 {
210         fail!("Couldn't add git tag %s in %s", tag, repo.to_str())
211     }
212 }
213
214 fn is_rwx(p: &Path) -> bool {
215     use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
216
217     match p.get_mode() {
218         None => return false,
219         Some(m) =>
220             ((m & S_IRUSR as uint) == S_IRUSR as uint
221             && (m & S_IWUSR as uint) == S_IWUSR as uint
222             && (m & S_IXUSR as uint) == S_IXUSR as uint)
223     }
224 }
225
226 fn test_sysroot() -> Path {
227     // Totally gross hack but it's just for test cases.
228     // Infer the sysroot from the exe name and pray that it's right.
229     // (Did I mention it was a gross hack?)
230     let self_path = os::self_exe_path().expect("Couldn't get self_exe path");
231     self_path.pop()
232 }
233
234 fn command_line_test(args: &[~str], cwd: &Path) -> ProcessOutput {
235     command_line_test_with_env(args, cwd, None)
236 }
237
238 /// Runs `rustpkg` (based on the directory that this executable was
239 /// invoked from) with the given arguments, in the given working directory.
240 /// Returns the process's output.
241 fn command_line_test_with_env(args: &[~str], cwd: &Path, env: Option<~[(~str, ~str)]>)
242     -> ProcessOutput {
243     let cmd = test_sysroot().push("bin").push("rustpkg").to_str();
244     debug!("About to run command: %? %? in %s", cmd, args, cwd.to_str());
245     assert!(os::path_is_dir(&*cwd));
246     let cwd = (*cwd).clone();
247     let mut prog = run::Process::new(cmd, args, run::ProcessOptions {
248         env: env.map(|v| v.slice(0, v.len())),
249         dir: Some(&cwd),
250         in_fd: None,
251         out_fd: None,
252         err_fd: None
253     });
254     let output = prog.finish_with_output();
255     debug!("Output from command %s with args %? was %s {%s}[%?]",
256                     cmd, args, str::from_bytes(output.output),
257                    str::from_bytes(output.error),
258                    output.status);
259 /*
260 By the way, rustpkg *won't* return a nonzero exit code if it fails --
261 see #4547
262 So tests that use this need to check the existence of a file
263 to make sure the command succeeded
264 */
265     if output.status != 0 {
266         fail!("Command %s %? failed with exit code %?",
267               cmd, args, output.status);
268     }
269     output
270 }
271
272 fn create_local_package(pkgid: &PkgId) -> Path {
273     let parent_dir = mk_temp_workspace(&pkgid.local_path, &pkgid.version);
274     debug!("Created empty package dir for %s, returning %s", pkgid.to_str(), parent_dir.to_str());
275     parent_dir.pop().pop()
276 }
277
278 fn create_local_package_in(pkgid: &PkgId, pkgdir: &Path) -> Path {
279
280     let package_dir = pkgdir.push("src").push(pkgid.to_str());
281
282     // Create main, lib, test, and bench files
283     assert!(os::mkdir_recursive(&package_dir, U_RWX));
284     debug!("Created %s and does it exist? %?", package_dir.to_str(),
285           os::path_is_dir(&package_dir));
286     // Create main, lib, test, and bench files
287
288     writeFile(&package_dir.push("main.rs"),
289               "fn main() { let _x = (); }");
290     writeFile(&package_dir.push("lib.rs"),
291               "pub fn f() { let _x = (); }");
292     writeFile(&package_dir.push("test.rs"),
293               "#[test] pub fn f() { (); }");
294     writeFile(&package_dir.push("bench.rs"),
295               "#[bench] pub fn f() { (); }");
296     package_dir
297 }
298
299 fn create_local_package_with_test(pkgid: &PkgId) -> Path {
300     debug!("Dry run -- would create package %s with test");
301     create_local_package(pkgid) // Already has tests???
302 }
303
304 fn create_local_package_with_dep(pkgid: &PkgId, subord_pkgid: &PkgId) -> Path {
305     let package_dir = create_local_package(pkgid);
306     create_local_package_in(subord_pkgid, &package_dir);
307     // Write a main.rs file into pkgid that references subord_pkgid
308     writeFile(&package_dir.push("src").push(pkgid.to_str()).push("main.rs"),
309               fmt!("extern mod %s;\nfn main() {}",
310                    subord_pkgid.short_name));
311     // Write a lib.rs file into subord_pkgid that has something in it
312     writeFile(&package_dir.push("src").push(subord_pkgid.to_str()).push("lib.rs"),
313               "pub fn f() {}");
314     debug!("Dry run -- would create packages %s and %s in %s",
315            pkgid.to_str(),
316            subord_pkgid.to_str(),
317            package_dir.to_str());
318     package_dir
319 }
320
321 fn create_local_package_with_custom_build_hook(pkgid: &PkgId,
322                                                custom_build_hook: &str) -> Path {
323     debug!("Dry run -- would create package %s with custom build hook %s",
324            pkgid.to_str(), custom_build_hook);
325     create_local_package(pkgid)
326     // actually write the pkg.rs with the custom build hook
327
328 }
329
330 fn assert_lib_exists(repo: &Path, short_name: &str, v: Version) {
331     debug!("assert_lib_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
332     let lib = target_library_in_workspace(&(PkgId {
333         version: v, ..PkgId::new(short_name, repo)}
334                                            ), repo);
335     debug!("assert_lib_exists: checking whether %s exists", lib.to_str());
336     assert!(os::path_exists(&lib));
337     assert!(is_rwx(&lib));
338 }
339
340 fn assert_executable_exists(repo: &Path, short_name: &str) {
341     debug!("assert_executable_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
342     let exec = target_executable_in_workspace(&PkgId::new(short_name, repo), repo);
343     assert!(os::path_exists(&exec));
344     assert!(is_rwx(&exec));
345 }
346
347 fn assert_built_executable_exists(repo: &Path, short_name: &str) {
348     debug!("assert_built_executable_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
349     let exec = built_executable_in_workspace(&PkgId::new(short_name, repo),
350                                              repo).expect("assert_built_executable_exists failed");
351     assert!(os::path_exists(&exec));
352     assert!(is_rwx(&exec));
353 }
354
355 fn command_line_test_output(args: &[~str]) -> ~[~str] {
356     let mut result = ~[];
357     let p_output = command_line_test(args, &os::getcwd());
358     let test_output = str::from_bytes(p_output.output);
359     for s in test_output.split_iter('\n') {
360         result.push(s.to_owned());
361     }
362     result
363 }
364
365 fn command_line_test_output_with_env(args: &[~str], env: ~[(~str, ~str)]) -> ~[~str] {
366     let mut result = ~[];
367     let p_output = command_line_test_with_env(args, &os::getcwd(), Some(env));
368     let test_output = str::from_bytes(p_output.output);
369     for s in test_output.split_iter('\n') {
370         result.push(s.to_owned());
371     }
372     result
373 }
374
375 // assumes short_name and local_path are one and the same -- I should fix
376 fn lib_output_file_name(workspace: &Path, parent: &str, short_name: &str) -> Path {
377     debug!("lib_output_file_name: given %s and parent %s and short name %s",
378            workspace.to_str(), parent, short_name);
379     library_in_workspace(&normalize(RemotePath(Path(short_name))),
380                          short_name,
381                          Build,
382                          workspace,
383                          "build").expect("lib_output_file_name")
384 }
385
386 fn output_file_name(workspace: &Path, short_name: &str) -> Path {
387     workspace.push(fmt!("%s%s", short_name, os::EXE_SUFFIX))
388 }
389
390 fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
391     use conditions::bad_path::cond;
392     let pkg_src_dir = workspace.push("src").push(pkgid.to_str());
393     let contents = os::list_dir_path(&pkg_src_dir);
394     for p in contents.iter() {
395         if p.filetype() == Some(~".rs") {
396             // should be able to do this w/o a process
397             if run::process_output("touch", [p.to_str()]).status != 0 {
398                 let _ = cond.raise((pkg_src_dir.clone(), ~"Bad path"));
399             }
400             break;
401         }
402     }
403 }
404
405 /// Add a blank line at the end
406 fn frob_source_file(workspace: &Path, pkgid: &PkgId) {
407     use conditions::bad_path::cond;
408     let pkg_src_dir = workspace.push("src").push(pkgid.to_str());
409     let contents = os::list_dir_path(&pkg_src_dir);
410     let mut maybe_p = None;
411     for p in contents.iter() {
412         if p.filetype() == Some(~".rs") {
413             maybe_p = Some(p);
414             break;
415         }
416     }
417     match maybe_p {
418         Some(p) => {
419             let w = io::file_writer(p, &[io::Append]);
420             match w {
421                 Err(s) => { let _ = cond.raise((p.clone(), fmt!("Bad path: %s", s))); }
422                 Ok(w)  => w.write_line("")
423             }
424         }
425         None => fail!(fmt!("frob_source_file failed to find a source file in %s",
426                            pkg_src_dir.to_str()))
427     }
428 }
429
430 // FIXME(#7249): these tests fail on multi-platform builds, so for now they're
431 //               only run one x86
432
433 #[test] #[ignore(cfg(target_arch = "x86"))]
434 fn test_make_dir_rwx() {
435     let temp = &os::tmpdir();
436     let dir = temp.push("quux");
437     assert!(!os::path_exists(&dir) ||
438             os::remove_dir_recursive(&dir));
439     debug!("Trying to make %s", dir.to_str());
440     assert!(make_dir_rwx(&dir));
441     assert!(os::path_is_dir(&dir));
442     assert!(is_rwx(&dir));
443     assert!(os::remove_dir_recursive(&dir));
444 }
445
446 #[test] #[ignore(cfg(target_arch = "x86"))]
447 fn test_install_valid() {
448     use path_util::installed_library_in_workspace;
449
450     let sysroot = test_sysroot();
451     debug!("sysroot = %s", sysroot.to_str());
452     let ctxt = fake_ctxt(Some(@sysroot));
453     let temp_pkg_id = fake_pkg();
454     let temp_workspace = mk_temp_workspace(&temp_pkg_id.local_path, &NoVersion).pop().pop();
455     debug!("temp_workspace = %s", temp_workspace.to_str());
456     // should have test, bench, lib, and main
457     ctxt.install(&temp_workspace, &temp_pkg_id);
458     // Check that all files exist
459     let exec = target_executable_in_workspace(&temp_pkg_id, &temp_workspace);
460     debug!("exec = %s", exec.to_str());
461     assert!(os::path_exists(&exec));
462     assert!(is_rwx(&exec));
463
464     let lib = installed_library_in_workspace(temp_pkg_id.short_name, &temp_workspace);
465     debug!("lib = %?", lib);
466     assert!(lib.map_default(false, |l| os::path_exists(l)));
467     assert!(lib.map_default(false, |l| is_rwx(l)));
468
469     // And that the test and bench executables aren't installed
470     assert!(!os::path_exists(&target_test_in_workspace(&temp_pkg_id, &temp_workspace)));
471     let bench = target_bench_in_workspace(&temp_pkg_id, &temp_workspace);
472     debug!("bench = %s", bench.to_str());
473     assert!(!os::path_exists(&bench));
474 }
475
476 #[test] #[ignore(cfg(target_arch = "x86"))]
477 fn test_install_invalid() {
478     use conditions::nonexistent_package::cond;
479     use cond1 = conditions::missing_pkg_files::cond;
480
481     let ctxt = fake_ctxt(None);
482     let pkgid = fake_pkg();
483     let temp_workspace = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
484     let mut error_occurred = false;
485     let mut error1_occurred = false;
486     do cond1.trap(|_| {
487         error1_occurred = true;
488     }).inside {
489         do cond.trap(|_| {
490             error_occurred = true;
491             temp_workspace.clone()
492         }).inside {
493             ctxt.install(&temp_workspace, &pkgid);
494         }
495     }
496     assert!(error_occurred && error1_occurred);
497 }
498
499 // Tests above should (maybe) be converted to shell out to rustpkg, too
500
501 // FIXME: #7956: temporarily disabled
502 #[ignore(cfg(target_arch = "x86"))]
503 fn test_install_git() {
504     let sysroot = test_sysroot();
505     debug!("sysroot = %s", sysroot.to_str());
506     let temp_pkg_id = git_repo_pkg();
507     let repo = init_git_repo(&Path(temp_pkg_id.local_path.to_str()));
508     let repo_subdir = repo.push("mockgithub.com").push("catamorphism").push("test_pkg");
509     writeFile(&repo_subdir.push("main.rs"),
510               "fn main() { let _x = (); }");
511     writeFile(&repo_subdir.push("lib.rs"),
512               "pub fn f() { let _x = (); }");
513     writeFile(&repo_subdir.push("test.rs"),
514               "#[test] pub fn f() { (); }");
515     writeFile(&repo_subdir.push("bench.rs"),
516               "#[bench] pub fn f() { (); }");
517     add_git_tag(&repo_subdir, ~"0.1"); // this has the effect of committing the files
518
519     debug!("test_install_git: calling rustpkg install %s in %s",
520            temp_pkg_id.local_path.to_str(), repo.to_str());
521     // should have test, bench, lib, and main
522     command_line_test([~"install", temp_pkg_id.local_path.to_str()], &repo);
523     // Check that all files exist
524     debug!("Checking for files in %s", repo.to_str());
525     let exec = target_executable_in_workspace(&temp_pkg_id, &repo);
526     debug!("exec = %s", exec.to_str());
527     assert!(os::path_exists(&exec));
528     assert!(is_rwx(&exec));
529     let _built_lib =
530         built_library_in_workspace(&temp_pkg_id,
531                                    &repo).expect("test_install_git: built lib should exist");
532     let lib = target_library_in_workspace(&temp_pkg_id, &repo);
533     debug!("lib = %s", lib.to_str());
534     assert!(os::path_exists(&lib));
535     assert!(is_rwx(&lib));
536     let built_test = built_test_in_workspace(&temp_pkg_id,
537                          &repo).expect("test_install_git: built test should exist");
538     assert!(os::path_exists(&built_test));
539     let built_bench = built_bench_in_workspace(&temp_pkg_id,
540                           &repo).expect("test_install_git: built bench should exist");
541     assert!(os::path_exists(&built_bench));
542     // And that the test and bench executables aren't installed
543     let test = target_test_in_workspace(&temp_pkg_id, &repo);
544     assert!(!os::path_exists(&test));
545     debug!("test = %s", test.to_str());
546     let bench = target_bench_in_workspace(&temp_pkg_id, &repo);
547     debug!("bench = %s", bench.to_str());
548     assert!(!os::path_exists(&bench));
549 }
550
551 #[test] #[ignore(cfg(target_arch = "x86"))]
552 fn test_package_ids_must_be_relative_path_like() {
553     use conditions::bad_pkg_id::cond;
554
555     /*
556     Okay:
557     - One identifier, with no slashes
558     - Several slash-delimited things, with no / at the root
559
560     Not okay:
561     - Empty string
562     - Absolute path (as per os::is_absolute)
563
564     */
565
566     let whatever = PkgId::new("foo", &os::getcwd());
567
568     assert_eq!(~"foo-0.1", whatever.to_str());
569     assert!("github.com/catamorphism/test_pkg-0.1" ==
570             PkgId::new("github.com/catamorphism/test-pkg", &os::getcwd()).to_str());
571
572     do cond.trap(|(p, e)| {
573         assert!("" == p.to_str());
574         assert!("0-length pkgid" == e);
575         whatever.clone()
576     }).inside {
577         let x = PkgId::new("", &os::getcwd());
578         assert_eq!(~"foo-0.1", x.to_str());
579     }
580
581     do cond.trap(|(p, e)| {
582         assert_eq!(p.to_str(), os::make_absolute(&Path("foo/bar/quux")).to_str());
583         assert!("absolute pkgid" == e);
584         whatever.clone()
585     }).inside {
586         let z = PkgId::new(os::make_absolute(&Path("foo/bar/quux")).to_str(),
587                            &os::getcwd());
588         assert_eq!(~"foo-0.1", z.to_str());
589     }
590
591 }
592
593 // FIXME: #7956: temporarily disabled
594 #[ignore(cfg(target_arch = "x86"))]
595 fn test_package_version() {
596     let local_path = "mockgithub.com/catamorphism/test_pkg_version";
597     let repo = init_git_repo(&Path(local_path));
598     let repo_subdir = repo.push("mockgithub.com").push("catamorphism").push("test_pkg_version");
599     debug!("Writing files in: %s", repo_subdir.to_str());
600     writeFile(&repo_subdir.push("main.rs"),
601               "fn main() { let _x = (); }");
602     writeFile(&repo_subdir.push("lib.rs"),
603               "pub fn f() { let _x = (); }");
604     writeFile(&repo_subdir.push("test.rs"),
605               "#[test] pub fn f() { (); }");
606     writeFile(&repo_subdir.push("bench.rs"),
607               "#[bench] pub fn f() { (); }");
608     add_git_tag(&repo_subdir, ~"0.4");
609
610     let temp_pkg_id = PkgId::new("mockgithub.com/catamorphism/test_pkg_version", &repo);
611     match temp_pkg_id.version {
612         ExactRevision(~"0.4") => (),
613         _ => fail!(fmt!("test_package_version: package version was %?, expected Some(0.4)",
614                         temp_pkg_id.version))
615     }
616     // This should look at the prefix, clone into a workspace, then build.
617     command_line_test([~"install", ~"mockgithub.com/catamorphism/test_pkg_version"],
618                       &repo);
619     assert!(match built_library_in_workspace(&temp_pkg_id,
620                                              &repo) {
621         Some(p) => p.to_str().ends_with(fmt!("0.4%s", os::consts::DLL_SUFFIX)),
622         None    => false
623     });
624     assert!(built_executable_in_workspace(&temp_pkg_id, &repo)
625             == Some(repo.push("build").
626                     push("mockgithub.com").
627                     push("catamorphism").
628                     push("test_pkg_version").
629                     push("test_pkg_version")));
630 }
631
632 fn test_package_request_version() {
633     let local_path = "mockgithub.com/catamorphism/test_pkg_version";
634     let repo = init_git_repo(&Path(local_path));
635     let repo_subdir = repo.push("mockgithub.com").push("catamorphism").push("test_pkg_version");
636     debug!("Writing files in: %s", repo_subdir.to_str());
637     writeFile(&repo_subdir.push("main.rs"),
638               "fn main() { let _x = (); }");
639     writeFile(&repo_subdir.push("lib.rs"),
640               "pub fn f() { let _x = (); }");
641     writeFile(&repo_subdir.push("test.rs"),
642               "#[test] pub fn f() { (); }");
643     writeFile(&repo_subdir.push("bench.rs"),
644               "#[bench] pub fn f() { (); }");
645     writeFile(&repo_subdir.push("version-0.3-file.txt"), "hi");
646     add_git_tag(&repo_subdir, ~"0.3");
647     writeFile(&repo_subdir.push("version-0.4-file.txt"), "hello");
648     add_git_tag(&repo_subdir, ~"0.4");
649
650     command_line_test([~"install", fmt!("%s#0.3", local_path)], &repo);
651
652     assert!(match installed_library_in_workspace("test_pkg_version", &repo.push(".rust")) {
653         Some(p) => {
654             debug!("installed: %s", p.to_str());
655             p.to_str().ends_with(fmt!("0.3%s", os::consts::DLL_SUFFIX))
656         }
657         None    => false
658     });
659     let temp_pkg_id = PkgId::new("mockgithub.com/catamorphism/test_pkg_version#0.3", &repo);
660     assert!(target_executable_in_workspace(&temp_pkg_id, &repo.push(".rust"))
661             == repo.push(".rust").push("bin").push("test_pkg_version"));
662
663     assert!(os::path_exists(&repo.push(".rust").push("src")
664                             .push("mockgithub.com").push("catamorphism")
665                             .push("test_pkg_version-0.3")
666                             .push("version-0.3-file.txt")));
667     assert!(!os::path_exists(&repo.push(".rust").push("src")
668                             .push("mockgithub.com").push("catamorphism")
669                              .push("test_pkg_version-0.3")
670                             .push("version-0.4-file.txt")));
671 }
672
673 #[test]
674 #[ignore (reason = "http-client not ported to rustpkg yet")]
675 fn rustpkg_install_url_2() {
676     let temp_dir = mkdtemp(&os::tmpdir(), "rustpkg_install_url_2").expect("rustpkg_install_url_2");
677     command_line_test([~"install", ~"github.com/mozilla-servo/rust-http-client"],
678                      &temp_dir);
679 }
680
681 // FIXME: #7956: temporarily disabled
682 #[test]
683 fn rustpkg_library_target() {
684     let foo_repo = init_git_repo(&Path("foo"));
685     let package_dir = foo_repo.push("foo");
686
687     debug!("Writing files in: %s", package_dir.to_str());
688     writeFile(&package_dir.push("main.rs"),
689               "fn main() { let _x = (); }");
690     writeFile(&package_dir.push("lib.rs"),
691               "pub fn f() { let _x = (); }");
692     writeFile(&package_dir.push("test.rs"),
693               "#[test] pub fn f() { (); }");
694     writeFile(&package_dir.push("bench.rs"),
695               "#[bench] pub fn f() { (); }");
696
697     add_git_tag(&package_dir, ~"1.0");
698     command_line_test([~"install", ~"foo"], &foo_repo);
699     assert_lib_exists(&foo_repo, "foo", ExactRevision(~"1.0"));
700 }
701
702 #[test]
703 fn rustpkg_local_pkg() {
704     let dir = create_local_package(&PkgId::new("foo", &os::getcwd()));
705     command_line_test([~"install", ~"foo"], &dir);
706     assert_executable_exists(&dir, "foo");
707 }
708
709 // FIXME: #7956: temporarily disabled
710 //  Failing on dist-linux bot
711 #[test]
712 #[ignore]
713 fn package_script_with_default_build() {
714     let dir = create_local_package(&PkgId::new("fancy-lib", &os::getcwd()));
715     debug!("dir = %s", dir.to_str());
716     let source = test_sysroot().pop().pop().pop().push("src").push("librustpkg").
717         push("testsuite").push("pass").push("src").push("fancy-lib").push("pkg.rs");
718     debug!("package_script_with_default_build: %s", source.to_str());
719     if !os::copy_file(&source,
720                       & dir.push("src").push("fancy_lib-0.1").push("pkg.rs")) {
721         fail!("Couldn't copy file");
722     }
723     command_line_test([~"install", ~"fancy-lib"], &dir);
724     assert_lib_exists(&dir, "fancy-lib", NoVersion);
725     assert!(os::path_exists(&dir.push("build").push("fancy_lib").push("generated.rs")));
726 }
727
728 #[test]
729 fn rustpkg_build_no_arg() {
730     let tmp = mkdtemp(&os::tmpdir(), "rustpkg_build_no_arg").expect("rustpkg_build_no_arg failed");
731     let package_dir = tmp.push("src").push("foo");
732     assert!(os::mkdir_recursive(&package_dir, U_RWX));
733
734     writeFile(&package_dir.push("main.rs"),
735               "fn main() { let _x = (); }");
736     debug!("build_no_arg: dir = %s", package_dir.to_str());
737     command_line_test([~"build"], &package_dir);
738     assert_built_executable_exists(&tmp, "foo");
739 }
740
741 #[test]
742 fn rustpkg_install_no_arg() {
743     let tmp = mkdtemp(&os::tmpdir(),
744                       "rustpkg_install_no_arg").expect("rustpkg_build_no_arg failed");
745     let package_dir = tmp.push("src").push("foo");
746     assert!(os::mkdir_recursive(&package_dir, U_RWX));
747     writeFile(&package_dir.push("lib.rs"),
748               "fn main() { let _x = (); }");
749     debug!("install_no_arg: dir = %s", package_dir.to_str());
750     command_line_test([~"install"], &package_dir);
751     assert_lib_exists(&tmp, "foo", NoVersion);
752 }
753
754 #[test]
755 fn rustpkg_clean_no_arg() {
756     let tmp = mkdtemp(&os::tmpdir(), "rustpkg_clean_no_arg").expect("rustpkg_clean_no_arg failed");
757     let package_dir = tmp.push("src").push("foo");
758     assert!(os::mkdir_recursive(&package_dir, U_RWX));
759
760     writeFile(&package_dir.push("main.rs"),
761               "fn main() { let _x = (); }");
762     debug!("clean_no_arg: dir = %s", package_dir.to_str());
763     command_line_test([~"build"], &package_dir);
764     assert_built_executable_exists(&tmp, "foo");
765     command_line_test([~"clean"], &package_dir);
766     assert!(!built_executable_in_workspace(&PkgId::new("foo", &package_dir),
767                 &tmp).map_default(false, |m| { os::path_exists(m) }));
768 }
769
770 #[test]
771 #[ignore (reason = "Specifying env doesn't work -- see #8028")]
772 fn rust_path_test() {
773     let dir_for_path = mkdtemp(&os::tmpdir(), "more_rust").expect("rust_path_test failed");
774     let dir = mk_workspace(&dir_for_path, &normalize(RemotePath(Path("foo"))), &NoVersion);
775     debug!("dir = %s", dir.to_str());
776     writeFile(&dir.push("main.rs"), "fn main() { let _x = (); }");
777
778     let cwd = os::getcwd();
779     debug!("cwd = %s", cwd.to_str());
780     debug!("Running command: cd %s; RUST_LOG=rustpkg RUST_PATH=%s rustpkg install foo",
781            cwd.to_str(), dir_for_path.to_str());
782     let mut prog = run::Process::new("rustpkg",
783                                      [~"install", ~"foo"],
784                                      run::ProcessOptions { env: Some(&[(~"RUST_LOG",
785                                                                         ~"rustpkg"),
786                                                                        (~"RUST_PATH",
787                                                                        dir_for_path.to_str())]),
788                                                           dir: Some(&cwd),
789                                                           in_fd: None,
790                                                           out_fd: None,
791                                                           err_fd: None
792                                                          });
793     prog.finish_with_output();
794     assert_executable_exists(&dir_for_path, "foo");
795 }
796
797 #[test]
798 fn rust_path_contents() {
799     use std::unstable::change_dir_locked;
800
801     let dir = mkdtemp(&os::tmpdir(), "rust_path").expect("rust_path_contents failed");
802     let abc = &dir.push("A").push("B").push("C");
803     assert!(os::mkdir_recursive(&abc.push(".rust"), U_RWX));
804     assert!(os::mkdir_recursive(&abc.pop().push(".rust"), U_RWX));
805     assert!(os::mkdir_recursive(&abc.pop().pop().push(".rust"), U_RWX));
806     assert!(do change_dir_locked(&dir.push("A").push("B").push("C")) {
807         let p = rust_path();
808         let cwd = os::getcwd().push(".rust");
809         let parent = cwd.pop().pop().push(".rust");
810         let grandparent = cwd.pop().pop().pop().push(".rust");
811         assert!(p.contains(&cwd));
812         assert!(p.contains(&parent));
813         assert!(p.contains(&grandparent));
814         for a_path in p.iter() {
815             assert!(!a_path.components.is_empty());
816         }
817     });
818 }
819
820 #[test]
821 fn rust_path_parse() {
822     os::setenv("RUST_PATH", "/a/b/c:/d/e/f:/g/h/i");
823     let paths = rust_path();
824     assert!(paths.contains(&Path("/g/h/i")));
825     assert!(paths.contains(&Path("/d/e/f")));
826     assert!(paths.contains(&Path("/a/b/c")));
827     os::unsetenv("RUST_PATH");
828 }
829
830 #[test]
831 fn test_list() {
832     let dir = mkdtemp(&os::tmpdir(), "test_list").expect("test_list failed");
833     let foo = PkgId::new("foo", &dir);
834     create_local_package_in(&foo, &dir);
835     let bar = PkgId::new("bar", &dir);
836     create_local_package_in(&bar, &dir);
837     let quux = PkgId::new("quux", &dir);
838     create_local_package_in(&quux, &dir);
839
840 // NOTE Not really great output, though...
841 // NOTE do any tests need to be unignored?
842     command_line_test([~"install", ~"foo"], &dir);
843     let env_arg = ~[(~"RUST_PATH", dir.to_str())];
844     debug!("RUST_PATH = %s", dir.to_str());
845     let list_output = command_line_test_output_with_env([~"list"], env_arg.clone());
846     assert!(list_output.iter().any(|x| x.starts_with("libfoo_")));
847
848     command_line_test([~"install", ~"bar"], &dir);
849     let list_output = command_line_test_output_with_env([~"list"], env_arg.clone());
850     assert!(list_output.iter().any(|x| x.starts_with("libfoo_")));
851     assert!(list_output.iter().any(|x| x.starts_with("libbar_")));
852
853     command_line_test([~"install", ~"quux"], &dir);
854     let list_output = command_line_test_output_with_env([~"list"], env_arg);
855     assert!(list_output.iter().any(|x| x.starts_with("libfoo_")));
856     assert!(list_output.iter().any(|x| x.starts_with("libbar_")));
857     assert!(list_output.iter().any(|x| x.starts_with("libquux_")));
858 }
859
860 #[test]
861 fn install_remove() {
862     let dir = mkdtemp(&os::tmpdir(), "install_remove").expect("install_remove");
863     let foo = PkgId::new("foo", &dir);
864     let bar = PkgId::new("bar", &dir);
865     let quux = PkgId::new("quux", &dir);
866     create_local_package_in(&foo, &dir);
867     create_local_package_in(&bar, &dir);
868     create_local_package_in(&quux, &dir);
869     let rust_path_to_use = ~[(~"RUST_PATH", dir.to_str())];
870     command_line_test([~"install", ~"foo"], &dir);
871     command_line_test([~"install", ~"bar"], &dir);
872     command_line_test([~"install", ~"quux"], &dir);
873     let list_output = command_line_test_output_with_env([~"list"], rust_path_to_use.clone());
874     assert!(list_output.iter().any(|x| x.starts_with("foo")));
875     assert!(list_output.iter().any(|x| x.starts_with("bar")));
876     assert!(list_output.iter().any(|x| x.starts_with("quux")));
877     command_line_test([~"uninstall", ~"foo"], &dir);
878     let list_output = command_line_test_output_with_env([~"list"], rust_path_to_use.clone());
879     assert!(!list_output.iter().any(|x| x.starts_with("foo")));
880     assert!(list_output.iter().any(|x| x.starts_with("bar")));
881     assert!(list_output.iter().any(|x| x.starts_with("quux")));
882 }
883
884 #[test]
885 fn install_check_duplicates() {
886     // should check that we don't install two packages with the same full name *and* version
887     // ("Is already installed -- doing nothing")
888     // check invariant that there are no dups in the pkg database
889     let dir = mkdtemp(&os::tmpdir(), "install_remove").expect("install_remove");
890     let foo = PkgId::new("foo", &dir);
891     create_local_package_in(&foo, &dir);
892
893     command_line_test([~"install", ~"foo"], &dir);
894     command_line_test([~"install", ~"foo"], &dir);
895     let mut contents = ~[];
896     let check_dups = |p: &PkgId| {
897         if contents.contains(p) {
898             fail!("package %s appears in `list` output more than once", p.local_path.to_str());
899         }
900         else {
901             contents.push((*p).clone());
902         }
903         false
904     };
905     list_installed_packages(check_dups);
906 }
907
908 #[test]
909 #[ignore(reason = "Workcache not yet implemented -- see #7075")]
910 fn no_rebuilding() {
911     let p_id = PkgId::new("foo", &os::getcwd());
912     let workspace = create_local_package(&p_id);
913     command_line_test([~"build", ~"foo"], &workspace);
914     let date = datestamp(&built_library_in_workspace(&p_id,
915                                                     &workspace).expect("no_rebuilding"));
916     command_line_test([~"build", ~"foo"], &workspace);
917     let newdate = datestamp(&built_library_in_workspace(&p_id,
918                                                        &workspace).expect("no_rebuilding (2)"));
919     assert_eq!(date, newdate);
920 }
921
922 #[test]
923 #[ignore(reason = "Workcache not yet implemented -- see #7075")]
924 fn no_rebuilding_dep() {
925     let p_id = PkgId::new("foo", &os::getcwd());
926     let dep_id = PkgId::new("bar", &os::getcwd());
927     let workspace = create_local_package_with_dep(&p_id, &dep_id);
928     command_line_test([~"build", ~"foo"], &workspace);
929     let bar_date = datestamp(&lib_output_file_name(&workspace,
930                                                   ".rust",
931                                                   "bar"));
932     let foo_date = datestamp(&output_file_name(&workspace, "foo"));
933     assert!(bar_date < foo_date);
934 }
935
936 #[test]
937 fn do_rebuild_dep_dates_change() {
938     let p_id = PkgId::new("foo", &os::getcwd());
939     let dep_id = PkgId::new("bar", &os::getcwd());
940     let workspace = create_local_package_with_dep(&p_id, &dep_id);
941     command_line_test([~"build", ~"foo"], &workspace);
942     let bar_date = datestamp(&lib_output_file_name(&workspace, "build", "bar"));
943     touch_source_file(&workspace, &dep_id);
944     command_line_test([~"build", ~"foo"], &workspace);
945     let new_bar_date = datestamp(&lib_output_file_name(&workspace, "build", "bar"));
946     assert!(new_bar_date > bar_date);
947 }
948
949 #[test]
950 fn do_rebuild_dep_only_contents_change() {
951     let p_id = PkgId::new("foo", &os::getcwd());
952     let dep_id = PkgId::new("bar", &os::getcwd());
953     let workspace = create_local_package_with_dep(&p_id, &dep_id);
954     command_line_test([~"build", ~"foo"], &workspace);
955     let bar_date = datestamp(&lib_output_file_name(&workspace, "build", "bar"));
956     frob_source_file(&workspace, &dep_id);
957     // should adjust the datestamp
958     command_line_test([~"build", ~"foo"], &workspace);
959     let new_bar_date = datestamp(&lib_output_file_name(&workspace, "build", "bar"));
960     assert!(new_bar_date > bar_date);
961 }
962
963 #[test]
964 fn test_versions() {
965     let workspace = create_local_package(&PkgId::new("foo#0.1", &os::getcwd()));
966     create_local_package(&PkgId::new("foo#0.2", &os::getcwd()));
967     command_line_test([~"install", ~"foo#0.1"], &workspace);
968     let output = command_line_test_output([~"list"]);
969     // make sure output includes versions
970     assert!(!output.iter().any(|x| x == &~"foo#0.2"));
971 }
972
973 #[test]
974 #[ignore(reason = "do not yet implemented")]
975 fn test_build_hooks() {
976     let workspace = create_local_package_with_custom_build_hook(&PkgId::new("foo", &os::getcwd()),
977                                                                 "frob");
978     command_line_test([~"do", ~"foo", ~"frob"], &workspace);
979 }
980
981
982 #[test]
983 #[ignore(reason = "info not yet implemented")]
984 fn test_info() {
985     let expected_info = ~"package foo"; // fill in
986     let workspace = create_local_package(&PkgId::new("foo", &os::getcwd()));
987     let output = command_line_test([~"info", ~"foo"], &workspace);
988     assert_eq!(str::from_bytes(output.output), expected_info);
989 }
990
991 #[test]
992 #[ignore(reason = "test not yet implemented")]
993 fn test_rustpkg_test() {
994     let expected_results = ~"1 out of 1 tests passed"; // fill in
995     let workspace = create_local_package_with_test(&PkgId::new("foo", &os::getcwd()));
996     let output = command_line_test([~"test", ~"foo"], &workspace);
997     assert_eq!(str::from_bytes(output.output), expected_results);
998 }
999
1000 #[test]
1001 fn test_uninstall() {
1002     let workspace = create_local_package(&PkgId::new("foo", &os::getcwd()));
1003     let _output = command_line_test([~"info", ~"foo"], &workspace);
1004     command_line_test([~"uninstall", ~"foo"], &workspace);
1005     let output = command_line_test([~"list"], &workspace);
1006     assert!(!str::from_bytes(output.output).contains("foo"));
1007 }
1008
1009 #[test]
1010 fn test_non_numeric_tag() {
1011     let temp_pkg_id = git_repo_pkg();
1012     let repo = init_git_repo(&Path(temp_pkg_id.local_path.to_str()));
1013     let repo_subdir = repo.push("mockgithub.com").push("catamorphism").push("test_pkg");
1014     writeFile(&repo_subdir.push("foo"), "foo");
1015     writeFile(&repo_subdir.push("lib.rs"),
1016               "pub fn f() { let _x = (); }");
1017     add_git_tag(&repo_subdir, ~"testbranch");
1018     writeFile(&repo_subdir.push("testbranch_only"), "hello");
1019     add_git_tag(&repo_subdir, ~"another_tag");
1020     writeFile(&repo_subdir.push("not_on_testbranch_only"), "bye bye");
1021     add_all_and_commit(&repo_subdir);
1022
1023
1024     command_line_test([~"install", fmt!("%s#testbranch", temp_pkg_id.remote_path.to_str())],
1025                       &repo);
1026     let file1 = repo.push_many(["mockgithub.com", "catamorphism",
1027                                 "test_pkg", "testbranch_only"]);
1028     let file2 = repo.push_many(["mockgithub.com", "catamorphism", "test_pkg",
1029                                 "master_only"]);
1030     assert!(os::path_exists(&file1));
1031     assert!(!os::path_exists(&file2));
1032 }