]> git.proxmox.com Git - cargo.git/blob - tests/testsuite/directory.rs
Auto merge of #6787 - ehuss:code-cleanup, r=alexcrichton
[cargo.git] / tests / testsuite / directory.rs
1 use std::collections::HashMap;
2 use std::fs::{self, File};
3 use std::io::prelude::*;
4 use std::str;
5
6 use serde::Serialize;
7
8 use crate::support::cargo_process;
9 use crate::support::git;
10 use crate::support::paths;
11 use crate::support::registry::{cksum, Package};
12 use crate::support::{basic_manifest, project, ProjectBuilder};
13
14 fn setup() {
15 let root = paths::root();
16 t!(fs::create_dir(&root.join(".cargo")));
17 t!(t!(File::create(root.join(".cargo/config"))).write_all(
18 br#"
19 [source.crates-io]
20 replace-with = 'my-awesome-local-registry'
21
22 [source.my-awesome-local-registry]
23 directory = 'index'
24 "#
25 ));
26 }
27
28 struct VendorPackage {
29 p: Option<ProjectBuilder>,
30 cksum: Checksum,
31 }
32
33 #[derive(Serialize)]
34 struct Checksum {
35 package: Option<String>,
36 files: HashMap<String, String>,
37 }
38
39 impl VendorPackage {
40 fn new(name: &str) -> VendorPackage {
41 VendorPackage {
42 p: Some(project().at(&format!("index/{}", name))),
43 cksum: Checksum {
44 package: Some(String::new()),
45 files: HashMap::new(),
46 },
47 }
48 }
49
50 fn file(&mut self, name: &str, contents: &str) -> &mut VendorPackage {
51 self.p = Some(self.p.take().unwrap().file(name, contents));
52 self.cksum
53 .files
54 .insert(name.to_string(), cksum(contents.as_bytes()));
55 self
56 }
57
58 fn disable_checksum(&mut self) -> &mut VendorPackage {
59 self.cksum.package = None;
60 self
61 }
62
63 fn no_manifest(mut self) -> Self {
64 self.p = self.p.map(|pb| pb.no_manifest());
65 self
66 }
67
68 fn build(&mut self) {
69 let p = self.p.take().unwrap();
70 let json = serde_json::to_string(&self.cksum).unwrap();
71 let p = p.file(".cargo-checksum.json", &json);
72 let _ = p.build();
73 }
74 }
75
76 #[test]
77 fn simple() {
78 setup();
79
80 VendorPackage::new("bar")
81 .file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
82 .file("src/lib.rs", "pub fn bar() {}")
83 .build();
84
85 let p = project()
86 .file(
87 "Cargo.toml",
88 r#"
89 [package]
90 name = "foo"
91 version = "0.1.0"
92 authors = []
93
94 [dependencies]
95 bar = "0.1.0"
96 "#,
97 )
98 .file(
99 "src/lib.rs",
100 "extern crate bar; pub fn foo() { bar::bar(); }",
101 )
102 .build();
103
104 p.cargo("build")
105 .with_stderr(
106 "\
107 [COMPILING] bar v0.1.0
108 [COMPILING] foo v0.1.0 ([CWD])
109 [FINISHED] [..]
110 ",
111 )
112 .run();
113 }
114
115 #[test]
116 fn simple_install() {
117 setup();
118
119 VendorPackage::new("foo")
120 .file("src/lib.rs", "pub fn foo() {}")
121 .build();
122
123 VendorPackage::new("bar")
124 .file(
125 "Cargo.toml",
126 r#"
127 [package]
128 name = "bar"
129 version = "0.1.0"
130 authors = []
131
132 [dependencies]
133 foo = "0.0.1"
134 "#,
135 )
136 .file(
137 "src/main.rs",
138 "extern crate foo; pub fn main() { foo::foo(); }",
139 )
140 .build();
141
142 cargo_process("install bar")
143 .with_stderr(
144 " Installing bar v0.1.0
145 Compiling foo v0.0.1
146 Compiling bar v0.1.0
147 Finished release [optimized] target(s) in [..]s
148 Installing [..]bar[..]
149 warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
150 ",
151 )
152 .run();
153 }
154
155 #[test]
156 fn simple_install_fail() {
157 setup();
158
159 VendorPackage::new("foo")
160 .file("src/lib.rs", "pub fn foo() {}")
161 .build();
162
163 VendorPackage::new("bar")
164 .file(
165 "Cargo.toml",
166 r#"
167 [package]
168 name = "bar"
169 version = "0.1.0"
170 authors = []
171
172 [dependencies]
173 foo = "0.1.0"
174 baz = "9.8.7"
175 "#,
176 )
177 .file(
178 "src/main.rs",
179 "extern crate foo; pub fn main() { foo::foo(); }",
180 )
181 .build();
182
183 cargo_process("install bar")
184 .with_status(101)
185 .with_stderr(
186 " Installing bar v0.1.0
187 error: failed to compile `bar v0.1.0`, intermediate artifacts can be found at `[..]`
188
189 Caused by:
190 no matching package named `baz` found
191 location searched: registry `https://github.com/rust-lang/crates.io-index`
192 perhaps you meant: bar or foo
193 required by package `bar v0.1.0`
194 ",
195 )
196 .run();
197 }
198
199 #[test]
200 fn install_without_feature_dep() {
201 setup();
202
203 VendorPackage::new("foo")
204 .file("src/lib.rs", "pub fn foo() {}")
205 .build();
206
207 VendorPackage::new("bar")
208 .file(
209 "Cargo.toml",
210 r#"
211 [package]
212 name = "bar"
213 version = "0.1.0"
214 authors = []
215
216 [dependencies]
217 foo = "0.0.1"
218 baz = { version = "9.8.7", optional = true }
219
220 [features]
221 wantbaz = ["baz"]
222 "#,
223 )
224 .file(
225 "src/main.rs",
226 "extern crate foo; pub fn main() { foo::foo(); }",
227 )
228 .build();
229
230 cargo_process("install bar")
231 .with_stderr(
232 " Installing bar v0.1.0
233 Compiling foo v0.0.1
234 Compiling bar v0.1.0
235 Finished release [optimized] target(s) in [..]s
236 Installing [..]bar[..]
237 warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
238 ",
239 )
240 .run();
241 }
242
243 #[test]
244 fn not_there() {
245 setup();
246
247 let _ = project().at("index").build();
248
249 let p = project()
250 .file(
251 "Cargo.toml",
252 r#"
253 [package]
254 name = "foo"
255 version = "0.1.0"
256 authors = []
257
258 [dependencies]
259 bar = "0.1.0"
260 "#,
261 )
262 .file(
263 "src/lib.rs",
264 "extern crate bar; pub fn foo() { bar::bar(); }",
265 )
266 .build();
267
268 p.cargo("build")
269 .with_status(101)
270 .with_stderr(
271 "\
272 error: no matching package named `bar` found
273 location searched: [..]
274 required by package `foo v0.1.0 ([..])`
275 ",
276 )
277 .run();
278 }
279
280 #[test]
281 fn multiple() {
282 setup();
283
284 VendorPackage::new("bar-0.1.0")
285 .file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
286 .file("src/lib.rs", "pub fn bar() {}")
287 .file(".cargo-checksum", "")
288 .build();
289
290 VendorPackage::new("bar-0.2.0")
291 .file("Cargo.toml", &basic_manifest("bar", "0.2.0"))
292 .file("src/lib.rs", "pub fn bar() {}")
293 .file(".cargo-checksum", "")
294 .build();
295
296 let p = project()
297 .file(
298 "Cargo.toml",
299 r#"
300 [package]
301 name = "foo"
302 version = "0.1.0"
303 authors = []
304
305 [dependencies]
306 bar = "0.1.0"
307 "#,
308 )
309 .file(
310 "src/lib.rs",
311 "extern crate bar; pub fn foo() { bar::bar(); }",
312 )
313 .build();
314
315 p.cargo("build")
316 .with_stderr(
317 "\
318 [COMPILING] bar v0.1.0
319 [COMPILING] foo v0.1.0 ([CWD])
320 [FINISHED] [..]
321 ",
322 )
323 .run();
324 }
325
326 #[test]
327 fn crates_io_then_directory() {
328 let p = project()
329 .file(
330 "Cargo.toml",
331 r#"
332 [package]
333 name = "foo"
334 version = "0.1.0"
335 authors = []
336
337 [dependencies]
338 bar = "0.1.0"
339 "#,
340 )
341 .file(
342 "src/lib.rs",
343 "extern crate bar; pub fn foo() { bar::bar(); }",
344 )
345 .build();
346
347 let cksum = Package::new("bar", "0.1.0")
348 .file("src/lib.rs", "pub fn bar() -> u32 { 0 }")
349 .publish();
350
351 p.cargo("build")
352 .with_stderr(
353 "\
354 [UPDATING] `[..]` index
355 [DOWNLOADING] crates ...
356 [DOWNLOADED] bar v0.1.0 ([..])
357 [COMPILING] bar v0.1.0
358 [COMPILING] foo v0.1.0 ([CWD])
359 [FINISHED] [..]
360 ",
361 )
362 .run();
363
364 setup();
365
366 let mut v = VendorPackage::new("bar");
367 v.file("Cargo.toml", &basic_manifest("bar", "0.1.0"));
368 v.file("src/lib.rs", "pub fn bar() -> u32 { 1 }");
369 v.cksum.package = Some(cksum);
370 v.build();
371
372 p.cargo("build")
373 .with_stderr(
374 "\
375 [COMPILING] bar v0.1.0
376 [COMPILING] foo v0.1.0 ([CWD])
377 [FINISHED] [..]
378 ",
379 )
380 .run();
381 }
382
383 #[test]
384 fn crates_io_then_bad_checksum() {
385 let p = project()
386 .file(
387 "Cargo.toml",
388 r#"
389 [package]
390 name = "foo"
391 version = "0.1.0"
392 authors = []
393
394 [dependencies]
395 bar = "0.1.0"
396 "#,
397 )
398 .file("src/lib.rs", "")
399 .build();
400
401 Package::new("bar", "0.1.0").publish();
402
403 p.cargo("build").run();
404 setup();
405
406 VendorPackage::new("bar")
407 .file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
408 .file("src/lib.rs", "")
409 .build();
410
411 p.cargo("build")
412 .with_status(101)
413 .with_stderr(
414 "\
415 error: checksum for `bar v0.1.0` changed between lock files
416
417 this could be indicative of a few possible errors:
418
419 * the lock file is corrupt
420 * a replacement source in use (e.g., a mirror) returned a different checksum
421 * the source itself may be corrupt in one way or another
422
423 unable to verify that `bar v0.1.0` is the same as when the lockfile was generated
424
425 ",
426 )
427 .run();
428 }
429
430 #[test]
431 fn bad_file_checksum() {
432 setup();
433
434 VendorPackage::new("bar")
435 .file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
436 .file("src/lib.rs", "")
437 .build();
438
439 let mut f = t!(File::create(paths::root().join("index/bar/src/lib.rs")));
440 t!(f.write_all(b"fn bar() -> u32 { 0 }"));
441
442 let p = project()
443 .file(
444 "Cargo.toml",
445 r#"
446 [package]
447 name = "foo"
448 version = "0.1.0"
449 authors = []
450
451 [dependencies]
452 bar = "0.1.0"
453 "#,
454 )
455 .file("src/lib.rs", "")
456 .build();
457
458 p.cargo("build")
459 .with_status(101)
460 .with_stderr(
461 "\
462 error: the listed checksum of `[..]lib.rs` has changed:
463 expected: [..]
464 actual: [..]
465
466 directory sources are not intended to be edited, if modifications are \
467 required then it is recommended that [replace] is used with a forked copy of \
468 the source
469 ",
470 )
471 .run();
472 }
473
474 #[test]
475 fn only_dot_files_ok() {
476 setup();
477
478 VendorPackage::new("bar")
479 .file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
480 .file("src/lib.rs", "")
481 .build();
482 VendorPackage::new("foo")
483 .no_manifest()
484 .file(".bar", "")
485 .build();
486
487 let p = project()
488 .file(
489 "Cargo.toml",
490 r#"
491 [package]
492 name = "foo"
493 version = "0.1.0"
494 authors = []
495
496 [dependencies]
497 bar = "0.1.0"
498 "#,
499 )
500 .file("src/lib.rs", "")
501 .build();
502
503 p.cargo("build").run();
504 }
505
506 #[test]
507 fn random_files_ok() {
508 setup();
509
510 VendorPackage::new("bar")
511 .file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
512 .file("src/lib.rs", "")
513 .build();
514 VendorPackage::new("foo")
515 .no_manifest()
516 .file("bar", "")
517 .file("../test", "")
518 .build();
519
520 let p = project()
521 .file(
522 "Cargo.toml",
523 r#"
524 [package]
525 name = "foo"
526 version = "0.1.0"
527 authors = []
528
529 [dependencies]
530 bar = "0.1.0"
531 "#,
532 )
533 .file("src/lib.rs", "")
534 .build();
535
536 p.cargo("build").run();
537 }
538
539 #[test]
540 fn git_lock_file_doesnt_change() {
541 let git = git::new("git", |p| {
542 p.file("Cargo.toml", &basic_manifest("git", "0.5.0"))
543 .file("src/lib.rs", "")
544 })
545 .unwrap();
546
547 VendorPackage::new("git")
548 .file("Cargo.toml", &basic_manifest("git", "0.5.0"))
549 .file("src/lib.rs", "")
550 .disable_checksum()
551 .build();
552
553 let p = project()
554 .file(
555 "Cargo.toml",
556 &format!(
557 r#"
558 [package]
559 name = "foo"
560 version = "0.0.1"
561 authors = []
562
563 [dependencies]
564 git = {{ git = '{0}' }}
565 "#,
566 git.url()
567 ),
568 )
569 .file("src/lib.rs", "")
570 .build();
571
572 p.cargo("build").run();
573
574 let mut lock1 = String::new();
575 t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lock1));
576
577 let root = paths::root();
578 t!(fs::create_dir(&root.join(".cargo")));
579 t!(t!(File::create(root.join(".cargo/config"))).write_all(
580 format!(
581 r#"
582 [source.my-git-repo]
583 git = '{}'
584 replace-with = 'my-awesome-local-registry'
585
586 [source.my-awesome-local-registry]
587 directory = 'index'
588 "#,
589 git.url()
590 )
591 .as_bytes()
592 ));
593
594 p.cargo("build")
595 .with_stderr(
596 "\
597 [COMPILING] [..]
598 [COMPILING] [..]
599 [FINISHED] [..]
600 ",
601 )
602 .run();
603
604 let mut lock2 = String::new();
605 t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lock2));
606 assert_eq!(lock1, lock2, "lock files changed");
607 }
608
609 #[test]
610 fn git_override_requires_lockfile() {
611 VendorPackage::new("git")
612 .file("Cargo.toml", &basic_manifest("git", "0.5.0"))
613 .file("src/lib.rs", "")
614 .disable_checksum()
615 .build();
616
617 let p = project()
618 .file(
619 "Cargo.toml",
620 r#"
621 [package]
622 name = "foo"
623 version = "0.0.1"
624 authors = []
625
626 [dependencies]
627 git = { git = 'https://example.com/' }
628 "#,
629 )
630 .file("src/lib.rs", "")
631 .build();
632
633 let root = paths::root();
634 t!(fs::create_dir(&root.join(".cargo")));
635 t!(t!(File::create(root.join(".cargo/config"))).write_all(
636 br#"
637 [source.my-git-repo]
638 git = 'https://example.com/'
639 replace-with = 'my-awesome-local-registry'
640
641 [source.my-awesome-local-registry]
642 directory = 'index'
643 "#
644 ));
645
646 p.cargo("build")
647 .with_status(101)
648 .with_stderr(
649 "\
650 error: failed to load source for a dependency on `git`
651
652 Caused by:
653 Unable to update [..]
654
655 Caused by:
656 the source my-git-repo requires a lock file to be present first before it can be
657 used against vendored source code
658
659 remove the source replacement configuration, generate a lock file, and then
660 restore the source replacement configuration to continue the build
661
662 ",
663 )
664 .run();
665 }
666
667 #[test]
668 fn workspace_different_locations() {
669 let p = project()
670 .no_manifest()
671 .file(
672 "foo/Cargo.toml",
673 r#"
674 [package]
675 name = 'foo'
676 version = '0.1.0'
677
678 [dependencies]
679 baz = "*"
680 "#,
681 )
682 .file("foo/src/lib.rs", "")
683 .file("foo/vendor/baz/Cargo.toml", &basic_manifest("baz", "0.1.0"))
684 .file("foo/vendor/baz/src/lib.rs", "")
685 .file("foo/vendor/baz/.cargo-checksum.json", "{\"files\":{}}")
686 .file(
687 "bar/Cargo.toml",
688 r#"
689 [package]
690 name = 'bar'
691 version = '0.1.0'
692
693 [dependencies]
694 baz = "*"
695 "#,
696 )
697 .file("bar/src/lib.rs", "")
698 .file(
699 ".cargo/config",
700 r#"
701 [build]
702 target-dir = './target'
703
704 [source.crates-io]
705 replace-with = 'my-awesome-local-registry'
706
707 [source.my-awesome-local-registry]
708 directory = 'foo/vendor'
709 "#,
710 )
711 .build();
712
713 p.cargo("build").cwd("foo").run();
714 p.cargo("build")
715 .cwd("bar")
716 .with_stderr(
717 "\
718 [COMPILING] bar [..]
719 [FINISHED] [..]
720 ",
721 )
722 .run();
723 }
724
725 #[test]
726 fn version_missing() {
727 setup();
728
729 VendorPackage::new("foo")
730 .file("src/lib.rs", "pub fn foo() {}")
731 .build();
732
733 VendorPackage::new("bar")
734 .file(
735 "Cargo.toml",
736 r#"
737 [package]
738 name = "bar"
739 version = "0.1.0"
740 authors = []
741
742 [dependencies]
743 foo = "2"
744 "#,
745 )
746 .file("src/main.rs", "fn main() {}")
747 .build();
748
749 cargo_process("install bar")
750 .with_stderr(
751 "\
752 [INSTALLING] bar v0.1.0
753 error: failed to compile [..]
754
755 Caused by:
756 failed to select a version for the requirement `foo = \"^2\"`
757 candidate versions found which didn't match: 0.0.1
758 location searched: directory source `[..] (which is replacing registry `[..]`)
759 required by package `bar v0.1.0`
760 perhaps a crate was updated and forgotten to be re-vendored?
761 ",
762 )
763 .with_status(101)
764 .run();
765 }