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