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