mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-25 11:14:46 +00:00
4656 lines
123 KiB
Rust
4656 lines
123 KiB
Rust
//! Tests for normal registry dependencies.
|
|
|
|
use std::fmt::Write;
|
|
use std::fs::{self, File};
|
|
use std::path::{Path, PathBuf};
|
|
use std::sync::Arc;
|
|
use std::sync::Mutex;
|
|
|
|
use crate::prelude::*;
|
|
use crate::utils::cargo_process;
|
|
use cargo::core::SourceId;
|
|
use cargo_test_support::paths;
|
|
use cargo_test_support::registry::{
|
|
self, Dependency, Package, RegistryBuilder, Response, TestRegistry, registry_path,
|
|
};
|
|
use cargo_test_support::{basic_manifest, project, str};
|
|
use cargo_test_support::{git, t};
|
|
use cargo_util::paths::remove_dir_all;
|
|
|
|
fn setup_http() -> TestRegistry {
|
|
RegistryBuilder::new().http_index().build()
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn test_server_stops() {
|
|
let server = setup_http();
|
|
server.join(); // ensure the server fully shuts down
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn simple_http() {
|
|
let _server = setup_http();
|
|
simple(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn simple_git() {
|
|
simple(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
fn simple(pre_clean_expected: impl IntoData, post_clean_expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = ">= 0.0.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("bar", "0.0.1").publish();
|
|
|
|
p.cargo("check").with_stderr_data(pre_clean_expected).run();
|
|
|
|
p.cargo("clean").run();
|
|
|
|
assert!(paths::home().join(".cargo/registry/CACHEDIR.TAG").is_file());
|
|
|
|
// Don't download a second time
|
|
p.cargo("check").with_stderr_data(post_clean_expected).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn deps_http() {
|
|
let _server = setup_http();
|
|
deps(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)
|
|
[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] baz v0.0.1
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn deps_git() {
|
|
deps(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)
|
|
[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] baz v0.0.1
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn deps(expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = ">= 0.0.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("baz", "0.0.1").publish();
|
|
Package::new("bar", "0.0.1").dep("baz", "*").publish();
|
|
|
|
p.cargo("check").with_stderr_data(expected).run();
|
|
|
|
assert!(paths::home().join(".cargo/registry/CACHEDIR.TAG").is_file());
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn nonexistent_http() {
|
|
let _server = setup_http();
|
|
nonexistent(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] no matching package named `nonexistent` found
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn nonexistent_git() {
|
|
nonexistent(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] no matching package named `nonexistent` found
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn nonexistent(expected: impl IntoData) {
|
|
Package::new("init", "0.0.1").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
nonexistent = ">= 0.0.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.with_status(101)
|
|
.with_stderr_data(expected)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn wrong_case_http() {
|
|
let _server = setup_http();
|
|
wrong_case(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] no matching package found
|
|
searched package name: `Init`
|
|
perhaps you meant: init
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn wrong_case_git() {
|
|
wrong_case(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] no matching package found
|
|
searched package name: `Init`
|
|
perhaps you meant: init
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn wrong_case(expected: impl IntoData) {
|
|
Package::new("init", "0.0.1").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
Init = ">= 0.0.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
// #5678 to make this work
|
|
p.cargo("check")
|
|
.with_status(101)
|
|
.with_stderr_data(expected)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn mis_hyphenated_http() {
|
|
let _server = setup_http();
|
|
mis_hyphenated(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] no matching package found
|
|
searched package name: `mis_hyphenated`
|
|
perhaps you meant: mis-hyphenated
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn mis_hyphenated_git() {
|
|
mis_hyphenated(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] no matching package found
|
|
searched package name: `mis_hyphenated`
|
|
perhaps you meant: mis-hyphenated
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn mis_hyphenated(expected: impl IntoData) {
|
|
Package::new("mis-hyphenated", "0.0.1").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
mis_hyphenated = ">= 0.0.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
// #2775 to make this work
|
|
p.cargo("check")
|
|
.with_status(101)
|
|
.with_stderr_data(expected)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn wrong_version_http() {
|
|
let _server = setup_http();
|
|
wrong_version(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `foo = ">=1.0.0"`
|
|
candidate versions found which didn't match: 0.0.2, 0.0.1
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
perhaps a crate was updated and forgotten to be re-vendored?
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `foo = ">=1.0.0"`
|
|
candidate versions found which didn't match: 0.0.4, 0.0.3, 0.0.2, ...
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
perhaps a crate was updated and forgotten to be re-vendored?
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn wrong_version_git() {
|
|
wrong_version(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `foo = ">=1.0.0"`
|
|
candidate versions found which didn't match: 0.0.2, 0.0.1
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
perhaps a crate was updated and forgotten to be re-vendored?
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `foo = ">=1.0.0"`
|
|
candidate versions found which didn't match: 0.0.4, 0.0.3, 0.0.2, ...
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
perhaps a crate was updated and forgotten to be re-vendored?
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
fn wrong_version(pre_publish_expected: impl IntoData, post_publish_expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = ">= 1.0.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("foo", "0.0.1").publish();
|
|
Package::new("foo", "0.0.2").publish();
|
|
|
|
p.cargo("check")
|
|
.with_status(101)
|
|
.with_stderr_data(pre_publish_expected)
|
|
.run();
|
|
|
|
Package::new("foo", "0.0.3").publish();
|
|
Package::new("foo", "0.0.4").publish();
|
|
|
|
p.cargo("check")
|
|
.with_status(101)
|
|
.with_stderr_data(post_publish_expected)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn bad_cksum_http() {
|
|
let _server = setup_http();
|
|
bad_cksum(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bad-cksum v0.0.1 (registry `dummy-registry`)
|
|
[ERROR] failed to download replaced source registry `crates-io`
|
|
|
|
Caused by:
|
|
failed to verify the checksum of `bad-cksum v0.0.1 (registry `dummy-registry`)`
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn bad_cksum_git() {
|
|
bad_cksum(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bad-cksum v0.0.1 (registry `dummy-registry`)
|
|
[ERROR] failed to download replaced source registry `crates-io`
|
|
|
|
Caused by:
|
|
failed to verify the checksum of `bad-cksum v0.0.1 (registry `dummy-registry`)`
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn bad_cksum(expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bad-cksum = ">= 0.0.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
let pkg = Package::new("bad-cksum", "0.0.1");
|
|
pkg.publish();
|
|
t!(File::create(&pkg.archive_dst()));
|
|
|
|
p.cargo("check -v")
|
|
.with_status(101)
|
|
.with_stderr_data(expected)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_registry_http() {
|
|
let _server = setup_http();
|
|
update_registry(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] no matching package named `notyet` found
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] notyet v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] notyet v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_registry_git() {
|
|
update_registry(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] no matching package named `notyet` found
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] notyet v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] notyet v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
fn update_registry(pre_publish_expected: impl IntoData, post_publish_expected: impl IntoData) {
|
|
Package::new("init", "0.0.1").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
notyet = ">= 0.0.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.with_status(101)
|
|
.with_stderr_data(pre_publish_expected)
|
|
.run();
|
|
|
|
Package::new("notyet", "0.0.1").publish();
|
|
|
|
p.cargo("check")
|
|
.with_stderr_data(post_publish_expected)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn package_with_path_deps_http() {
|
|
let _server = setup_http();
|
|
package_with_path_deps(
|
|
str![[r#"
|
|
[PACKAGING] foo v0.0.1 ([ROOT]/foo)
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to prepare local package for uploading
|
|
|
|
Caused by:
|
|
no matching package named `notyet` found
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[PACKAGING] foo v0.0.1 ([ROOT]/foo)
|
|
[UPDATING] `dummy-registry` index
|
|
[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)
|
|
[VERIFYING] foo v0.0.1 ([ROOT]/foo)
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] notyet v0.0.1 (registry `dummy-registry`)
|
|
[COMPILING] notyet v0.0.1
|
|
[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn package_with_path_deps_git() {
|
|
package_with_path_deps(
|
|
str![[r#"
|
|
[PACKAGING] foo v0.0.1 ([ROOT]/foo)
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to prepare local package for uploading
|
|
|
|
Caused by:
|
|
no matching package named `notyet` found
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[PACKAGING] foo v0.0.1 ([ROOT]/foo)
|
|
[UPDATING] `dummy-registry` index
|
|
[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)
|
|
[VERIFYING] foo v0.0.1 ([ROOT]/foo)
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] notyet v0.0.1 (registry `dummy-registry`)
|
|
[COMPILING] notyet v0.0.1
|
|
[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
fn package_with_path_deps(
|
|
pre_publish_expected: impl IntoData,
|
|
post_publish_expected: impl IntoData,
|
|
) {
|
|
Package::new("init", "0.0.1").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
license = "MIT"
|
|
description = "foo"
|
|
repository = "bar"
|
|
|
|
[dependencies.notyet]
|
|
version = "0.0.1"
|
|
path = "notyet"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.file("notyet/Cargo.toml", &basic_manifest("notyet", "0.0.1"))
|
|
.file("notyet/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("package")
|
|
.with_status(101)
|
|
.with_stderr_data(pre_publish_expected)
|
|
.run();
|
|
|
|
Package::new("notyet", "0.0.1").publish();
|
|
|
|
p.cargo("package")
|
|
.with_stderr_data(post_publish_expected)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn lockfile_locks_http() {
|
|
let _server = setup_http();
|
|
lockfile_locks(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn lockfile_locks_git() {
|
|
lockfile_locks(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
fn lockfile_locks(pre_publish_expected: impl IntoData, post_publish_expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("bar", "0.0.1").publish();
|
|
|
|
p.cargo("check")
|
|
.with_stderr_data(pre_publish_expected)
|
|
.run();
|
|
|
|
p.root().move_into_the_past();
|
|
Package::new("bar", "0.0.2").publish();
|
|
|
|
p.cargo("check")
|
|
.with_stderr_data(post_publish_expected)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn lockfile_locks_transitively_http() {
|
|
let _server = setup_http();
|
|
lockfile_locks_transitively(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)
|
|
[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] baz v0.0.1
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn lockfile_locks_transitively_git() {
|
|
lockfile_locks_transitively(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)
|
|
[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] baz v0.0.1
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
fn lockfile_locks_transitively(
|
|
pre_publish_expected: impl IntoData,
|
|
post_publish_expected: impl IntoData,
|
|
) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("baz", "0.0.1").publish();
|
|
Package::new("bar", "0.0.1").dep("baz", "*").publish();
|
|
|
|
p.cargo("check")
|
|
.with_stderr_data(pre_publish_expected)
|
|
.run();
|
|
|
|
p.root().move_into_the_past();
|
|
Package::new("baz", "0.0.2").publish();
|
|
Package::new("bar", "0.0.2").dep("baz", "*").publish();
|
|
|
|
p.cargo("check")
|
|
.with_stderr_data(post_publish_expected)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn yanks_are_not_used_http() {
|
|
let _server = setup_http();
|
|
yanks_are_not_used(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)
|
|
[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] baz v0.0.1
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn yanks_are_not_used_git() {
|
|
yanks_are_not_used(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)
|
|
[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] baz v0.0.1
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn yanks_are_not_used(expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("baz", "0.0.1").publish();
|
|
Package::new("baz", "0.0.2").yanked(true).publish();
|
|
Package::new("bar", "0.0.1").dep("baz", "*").publish();
|
|
Package::new("bar", "0.0.2")
|
|
.dep("baz", "*")
|
|
.yanked(true)
|
|
.publish();
|
|
|
|
p.cargo("check").with_stderr_data(expected).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn relying_on_a_yank_is_bad_http() {
|
|
let _server = setup_http();
|
|
relying_on_a_yank_is_bad(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `baz = "=0.0.2"`
|
|
version 0.0.2 is yanked
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `bar v0.0.1`
|
|
... which satisfies dependency `bar = "*"` of package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn relying_on_a_yank_is_bad_git() {
|
|
relying_on_a_yank_is_bad(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `baz = "=0.0.2"`
|
|
version 0.0.2 is yanked
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `bar v0.0.1`
|
|
... which satisfies dependency `bar = "*"` of package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn relying_on_a_yank_is_bad(expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("baz", "0.0.1").publish();
|
|
Package::new("baz", "0.0.2").yanked(true).publish();
|
|
Package::new("bar", "0.0.1").dep("baz", "=0.0.2").publish();
|
|
|
|
p.cargo("check")
|
|
.with_status(101)
|
|
.with_stderr_data(expected)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn yanks_in_lockfiles_are_ok_http() {
|
|
let _server = setup_http();
|
|
yanks_in_lockfiles_are_ok(
|
|
str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `bar = "*"`
|
|
version 0.0.1 is yanked
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn yanks_in_lockfiles_are_ok_git() {
|
|
yanks_in_lockfiles_are_ok(
|
|
str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `bar = "*"`
|
|
version 0.0.1 is yanked
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
fn yanks_in_lockfiles_are_ok(expected_check: impl IntoData, expected_update: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("bar", "0.0.1").publish();
|
|
|
|
p.cargo("check").run();
|
|
|
|
registry_path().join("3").rm_rf();
|
|
|
|
Package::new("bar", "0.0.1").yanked(true).publish();
|
|
|
|
p.cargo("check").with_stderr_data(expected_check).run();
|
|
|
|
p.cargo("update")
|
|
.with_status(101)
|
|
.with_stderr_data(expected_update)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn yanks_in_lockfiles_are_ok_for_other_update_http() {
|
|
let _server = setup_http();
|
|
yanks_in_lockfiles_are_ok_for_other_update(
|
|
str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `bar = "*"`
|
|
version 0.0.1 is yanked
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] baz v0.0.1 -> v0.0.2
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn yanks_in_lockfiles_are_ok_for_other_update_git() {
|
|
yanks_in_lockfiles_are_ok_for_other_update(
|
|
str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `bar = "*"`
|
|
version 0.0.1 is yanked
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] baz v0.0.1 -> v0.0.2
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
fn yanks_in_lockfiles_are_ok_for_other_update(
|
|
expected_check: impl IntoData,
|
|
expected_update: impl IntoData,
|
|
expected_other_update: impl IntoData,
|
|
) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "*"
|
|
baz = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("bar", "0.0.1").publish();
|
|
Package::new("baz", "0.0.1").publish();
|
|
|
|
p.cargo("check").run();
|
|
|
|
registry_path().join("3").rm_rf();
|
|
|
|
Package::new("bar", "0.0.1").yanked(true).publish();
|
|
Package::new("baz", "0.0.1").publish();
|
|
|
|
p.cargo("check").with_stderr_data(expected_check).run();
|
|
|
|
Package::new("baz", "0.0.2").publish();
|
|
|
|
p.cargo("update")
|
|
.with_status(101)
|
|
.with_stderr_data(expected_update)
|
|
.run();
|
|
|
|
p.cargo("update baz")
|
|
.with_stderr_data(expected_other_update)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn yanks_in_lockfiles_are_ok_with_new_dep_http() {
|
|
let _server = setup_http();
|
|
yanks_in_lockfiles_are_ok_with_new_dep(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[ADDING] baz v0.0.1
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] baz v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] baz v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn yanks_in_lockfiles_are_ok_with_new_dep_git() {
|
|
yanks_in_lockfiles_are_ok_with_new_dep(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[ADDING] baz v0.0.1
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] baz v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] baz v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn yanks_in_lockfiles_are_ok_with_new_dep(expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("bar", "0.0.1").publish();
|
|
|
|
p.cargo("check").run();
|
|
|
|
registry_path().join("3").rm_rf();
|
|
|
|
Package::new("bar", "0.0.1").yanked(true).publish();
|
|
Package::new("baz", "0.0.1").publish();
|
|
|
|
p.change_file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "*"
|
|
baz = "*"
|
|
"#,
|
|
);
|
|
|
|
p.cargo("check").with_stderr_data(expected).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_with_lockfile_if_packages_missing_http() {
|
|
let _server = setup_http();
|
|
update_with_lockfile_if_packages_missing(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_with_lockfile_if_packages_missing_git() {
|
|
update_with_lockfile_if_packages_missing(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn update_with_lockfile_if_packages_missing(expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("bar", "0.0.1").publish();
|
|
p.cargo("check").run();
|
|
p.root().move_into_the_past();
|
|
|
|
paths::home().join(".cargo/registry").rm_rf();
|
|
p.cargo("check").with_stderr_data(expected).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_lockfile_http() {
|
|
let _server = setup_http();
|
|
update_lockfile(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[UPDATING] bar v0.0.1 -> v0.0.2
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.2 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.0.2
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] bar v0.0.2 -> v0.0.3
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.3 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.0.3
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[UPDATING] bar v0.0.3 -> v0.0.4
|
|
[ADDING] spam v0.2.5
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] bar v0.0.4 -> v0.0.5
|
|
[REMOVING] spam v0.2.5
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_lockfile_git() {
|
|
update_lockfile(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[UPDATING] bar v0.0.1 -> v0.0.2
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.2 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.0.2
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] bar v0.0.2 -> v0.0.3
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.3 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.0.3
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[UPDATING] bar v0.0.3 -> v0.0.4
|
|
[ADDING] spam v0.2.5
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] bar v0.0.4 -> v0.0.5
|
|
[REMOVING] spam v0.2.5
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
fn update_lockfile(
|
|
expected_update: impl IntoData,
|
|
expected_check: impl IntoData,
|
|
expected_other_update: impl IntoData,
|
|
expected_other_check: impl IntoData,
|
|
expected_new_update: impl IntoData,
|
|
expected_new_check: impl IntoData,
|
|
) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
println!("0.0.1");
|
|
Package::new("bar", "0.0.1").publish();
|
|
p.cargo("check").run();
|
|
|
|
Package::new("bar", "0.0.2").publish();
|
|
Package::new("bar", "0.0.3").publish();
|
|
paths::home().join(".cargo/registry").rm_rf();
|
|
println!("0.0.2 update");
|
|
p.cargo("update bar --precise 0.0.2")
|
|
.with_stderr_data(expected_update)
|
|
.run();
|
|
|
|
println!("0.0.2 build");
|
|
p.cargo("check").with_stderr_data(expected_check).run();
|
|
|
|
println!("0.0.3 update");
|
|
p.cargo("update bar")
|
|
.with_stderr_data(expected_other_update)
|
|
.run();
|
|
|
|
println!("0.0.3 build");
|
|
p.cargo("check")
|
|
.with_stderr_data(expected_other_check)
|
|
.run();
|
|
|
|
println!("new dependencies update");
|
|
Package::new("bar", "0.0.4").dep("spam", "0.2.5").publish();
|
|
Package::new("spam", "0.2.5").publish();
|
|
p.cargo("update bar")
|
|
.with_stderr_data(expected_new_update)
|
|
.run();
|
|
|
|
println!("new dependencies update");
|
|
Package::new("bar", "0.0.5").publish();
|
|
p.cargo("update bar")
|
|
.with_stderr_data(expected_new_check)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn dev_dependency_not_used_http() {
|
|
let _server = setup_http();
|
|
dev_dependency_not_used(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn dev_dependency_not_used_git() {
|
|
dev_dependency_not_used(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn dev_dependency_not_used(expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("baz", "0.0.1").publish();
|
|
Package::new("bar", "0.0.1").dev_dep("baz", "*").publish();
|
|
|
|
p.cargo("check").with_stderr_data(expected).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn bad_license_file_http() {
|
|
let registry = setup_http();
|
|
bad_license_file(
|
|
®istry,
|
|
str![[r#"
|
|
...
|
|
[ERROR] license-file `foo` does not appear to exist (relative to `[ROOT]/foo`).
|
|
...
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn bad_license_file_git() {
|
|
let registry = registry::init();
|
|
bad_license_file(
|
|
®istry,
|
|
str![[r#"
|
|
...
|
|
[ERROR] license-file `foo` does not appear to exist (relative to `[ROOT]/foo`).
|
|
...
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
fn bad_license_file(registry: &TestRegistry, expected: impl IntoData) {
|
|
Package::new("foo", "1.0.0").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
license-file = "foo"
|
|
description = "bar"
|
|
repository = "baz"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
p.cargo("publish -v")
|
|
.replace_crates_io(registry.index_url())
|
|
.with_status(101)
|
|
.with_stderr_data(expected)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn updating_a_dep_http() {
|
|
let _server = setup_http();
|
|
updating_a_dep(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] a v0.0.1 ([ROOT]/foo/a)
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] bar v0.0.1 -> v0.1.0
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.1.0
|
|
[CHECKING] a v0.0.1 ([ROOT]/foo/a)
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn updating_a_dep_git() {
|
|
updating_a_dep(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] a v0.0.1 ([ROOT]/foo/a)
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] bar v0.0.1 -> v0.1.0
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.1.0
|
|
[CHECKING] a v0.0.1 ([ROOT]/foo/a)
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
fn updating_a_dep(pre_update_expected: impl IntoData, post_update_expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies.a]
|
|
path = "a"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.file(
|
|
"a/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "*"
|
|
"#,
|
|
)
|
|
.file("a/src/lib.rs", "")
|
|
.build();
|
|
|
|
Package::new("bar", "0.0.1").publish();
|
|
|
|
p.cargo("check").with_stderr_data(pre_update_expected).run();
|
|
assert!(paths::home().join(".cargo/registry/CACHEDIR.TAG").is_file());
|
|
|
|
// Now delete the CACHEDIR.TAG file: this is the situation we'll be in after
|
|
// upgrading from a version of Cargo that doesn't mark this directory, to one that
|
|
// does. It should be recreated.
|
|
fs::remove_file(paths::home().join(".cargo/registry/CACHEDIR.TAG"))
|
|
.expect("remove CACHEDIR.TAG");
|
|
|
|
p.change_file(
|
|
"a/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "0.1.0"
|
|
"#,
|
|
);
|
|
Package::new("bar", "0.1.0").publish();
|
|
|
|
println!("second");
|
|
p.cargo("check")
|
|
.with_stderr_data(post_update_expected)
|
|
.run();
|
|
|
|
assert!(
|
|
paths::home().join(".cargo/registry/CACHEDIR.TAG").is_file(),
|
|
"CACHEDIR.TAG recreated in existing registry"
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn git_and_registry_dep_http() {
|
|
let _server = setup_http();
|
|
git_and_registry_dep(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[UPDATING] git repository `[ROOTURL]/b`
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] a v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] a v0.0.1
|
|
[CHECKING] b v0.0.1 ([ROOTURL]/b#[..])
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn git_and_registry_dep_git() {
|
|
git_and_registry_dep(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[UPDATING] git repository `[ROOTURL]/b`
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] a v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] a v0.0.1
|
|
[CHECKING] b v0.0.1 ([ROOTURL]/b#[..])
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
fn git_and_registry_dep(pre_move_expected: impl IntoData, post_move_expected: impl IntoData) {
|
|
let b = git::repo(&paths::root().join("b"))
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "b"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
a = "0.0.1"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
a = "0.0.1"
|
|
|
|
[dependencies.b]
|
|
git = '{}'
|
|
"#,
|
|
b.url()
|
|
),
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("a", "0.0.1").publish();
|
|
|
|
p.root().move_into_the_past();
|
|
p.cargo("check").with_stderr_data(pre_move_expected).run();
|
|
p.root().move_into_the_past();
|
|
|
|
println!("second");
|
|
p.cargo("check").with_stderr_data(post_move_expected).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_publish_then_update_http() {
|
|
let _server = setup_http();
|
|
update_publish_then_update(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] a v0.1.1 (registry `dummy-registry`)
|
|
[COMPILING] a v0.1.1
|
|
[COMPILING] foo v0.5.0 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_publish_then_update_git() {
|
|
update_publish_then_update(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] a v0.1.1 (registry `dummy-registry`)
|
|
[COMPILING] a v0.1.1
|
|
[COMPILING] foo v0.5.0 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn update_publish_then_update(expected: impl IntoData) {
|
|
// First generate a Cargo.lock and a clone of the registry index at the
|
|
// "head" of the current registry.
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
a = "0.1.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
Package::new("a", "0.1.0").publish();
|
|
p.cargo("build").run();
|
|
|
|
// Next, publish a new package and back up the copy of the registry we just
|
|
// created.
|
|
Package::new("a", "0.1.1").publish();
|
|
let registry = paths::home().join(".cargo/registry");
|
|
let backup = paths::root().join("registry-backup");
|
|
t!(fs::rename(®istry, &backup));
|
|
|
|
// Generate a Cargo.lock with the newer version, and then move the old copy
|
|
// of the registry back into place.
|
|
let p2 = project()
|
|
.at("foo2")
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
a = "0.1.1"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
p2.cargo("build").run();
|
|
registry.rm_rf();
|
|
t!(fs::rename(&backup, ®istry));
|
|
t!(fs::rename(
|
|
p2.root().join("Cargo.lock"),
|
|
p.root().join("Cargo.lock")
|
|
));
|
|
|
|
// Finally, build the first project again (with our newer Cargo.lock) which
|
|
// should force an update of the old registry, download the new crate, and
|
|
// then build everything again.
|
|
p.cargo("build").with_stderr_data(expected).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn fetch_downloads_http() {
|
|
let _server = setup_http();
|
|
fetch_downloads(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] a v0.1.0 (registry `dummy-registry`)
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn fetch_downloads_git() {
|
|
fetch_downloads(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] a v0.1.0 (registry `dummy-registry`)
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn fetch_downloads(expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
a = "0.1.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("a", "0.1.0").publish();
|
|
|
|
p.cargo("fetch").with_stderr_data(expected).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_transitive_dependency_http() {
|
|
let _server = setup_http();
|
|
update_transitive_dependency(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] b v0.1.0 -> v0.1.1
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] b v0.1.1 (registry `dummy-registry`)
|
|
[CHECKING] b v0.1.1
|
|
[CHECKING] a v0.1.0
|
|
[CHECKING] foo v0.5.0 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_transitive_dependency_git() {
|
|
update_transitive_dependency(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] b v0.1.0 -> v0.1.1
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] b v0.1.1 (registry `dummy-registry`)
|
|
[CHECKING] b v0.1.1
|
|
[CHECKING] a v0.1.0
|
|
[CHECKING] foo v0.5.0 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
fn update_transitive_dependency(expected_update: impl IntoData, expected_check: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
a = "0.1.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("a", "0.1.0").dep("b", "*").publish();
|
|
Package::new("b", "0.1.0").publish();
|
|
|
|
p.cargo("fetch").run();
|
|
|
|
Package::new("b", "0.1.1").publish();
|
|
|
|
p.cargo("update b").with_stderr_data(expected_update).run();
|
|
|
|
p.cargo("check").with_stderr_data(expected_check).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_backtracking_ok_http() {
|
|
let _server = setup_http();
|
|
update_backtracking_ok(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[UPDATING] hyper v0.6.5 -> v0.6.6
|
|
[UPDATING] openssl v0.1.0 -> v0.1.1
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_backtracking_ok_git() {
|
|
update_backtracking_ok(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[UPDATING] hyper v0.6.5 -> v0.6.6
|
|
[UPDATING] openssl v0.1.0 -> v0.1.1
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn update_backtracking_ok(expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
webdriver = "0.1"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("webdriver", "0.1.0")
|
|
.dep("hyper", "0.6")
|
|
.publish();
|
|
Package::new("hyper", "0.6.5")
|
|
.dep("openssl", "0.1")
|
|
.dep("cookie", "0.1")
|
|
.publish();
|
|
Package::new("cookie", "0.1.0")
|
|
.dep("openssl", "0.1")
|
|
.publish();
|
|
Package::new("openssl", "0.1.0").publish();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
|
|
Package::new("openssl", "0.1.1").publish();
|
|
Package::new("hyper", "0.6.6")
|
|
.dep("openssl", "0.1.1")
|
|
.dep("cookie", "0.1.0")
|
|
.publish();
|
|
|
|
p.cargo("update hyper").with_stderr_data(expected).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_multiple_packages_http() {
|
|
let _server = setup_http();
|
|
update_multiple_packages(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[UPDATING] a v0.1.0 -> v0.1.1
|
|
[UPDATING] b v0.1.0 -> v0.1.1
|
|
[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] c v0.1.0 -> v0.1.1
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] a v0.1.1 (registry `dummy-registry`)
|
|
[DOWNLOADED] b v0.1.1 (registry `dummy-registry`)
|
|
[DOWNLOADED] c v0.1.1 (registry `dummy-registry`)
|
|
[CHECKING] a v0.1.1
|
|
[CHECKING] c v0.1.1
|
|
[CHECKING] b v0.1.1
|
|
[CHECKING] foo v0.5.0 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_multiple_packages_git() {
|
|
update_multiple_packages(
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[UPDATING] a v0.1.0 -> v0.1.1
|
|
[UPDATING] b v0.1.0 -> v0.1.1
|
|
[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] c v0.1.0 -> v0.1.1
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] c v0.1.1 (registry `dummy-registry`)
|
|
[DOWNLOADED] b v0.1.1 (registry `dummy-registry`)
|
|
[DOWNLOADED] a v0.1.1 (registry `dummy-registry`)
|
|
[CHECKING] b v0.1.1
|
|
[CHECKING] a v0.1.1
|
|
[CHECKING] c v0.1.1
|
|
[CHECKING] foo v0.5.0 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
fn update_multiple_packages(
|
|
expected_update: impl IntoData,
|
|
expected_other_update: impl IntoData,
|
|
expected_check: impl IntoData,
|
|
) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
a = "*"
|
|
b = "*"
|
|
c = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("a", "0.1.0").publish();
|
|
Package::new("b", "0.1.0").publish();
|
|
Package::new("c", "0.1.0").publish();
|
|
|
|
p.cargo("fetch").run();
|
|
|
|
Package::new("a", "0.1.1").publish();
|
|
Package::new("b", "0.1.1").publish();
|
|
Package::new("c", "0.1.1").publish();
|
|
|
|
p.cargo("update a b")
|
|
.with_stderr_data(expected_update)
|
|
.run();
|
|
|
|
p.cargo("update b c")
|
|
.with_stderr_data(expected_other_update)
|
|
.run();
|
|
|
|
p.cargo("check")
|
|
.with_stderr_data(IntoData::unordered(expected_check))
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn bundled_crate_in_registry_http() {
|
|
let _server = setup_http();
|
|
bundled_crate_in_registry();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn bundled_crate_in_registry_git() {
|
|
bundled_crate_in_registry();
|
|
}
|
|
|
|
fn bundled_crate_in_registry() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "0.1"
|
|
baz = "0.1"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("bar", "0.1.0").publish();
|
|
Package::new("baz", "0.1.0")
|
|
.dep("bar", "0.1.0")
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "baz"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = { path = "bar", version = "0.1.0" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
|
|
.file("bar/src/lib.rs", "")
|
|
.publish();
|
|
|
|
p.cargo("run").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_same_prefix_oh_my_how_was_this_a_bug_http() {
|
|
let _server = setup_http();
|
|
update_same_prefix_oh_my_how_was_this_a_bug();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_same_prefix_oh_my_how_was_this_a_bug_git() {
|
|
update_same_prefix_oh_my_how_was_this_a_bug();
|
|
}
|
|
|
|
fn update_same_prefix_oh_my_how_was_this_a_bug() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "ugh"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = "0.1"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("foobar", "0.2.0").publish();
|
|
Package::new("foo", "0.1.0")
|
|
.dep("foobar", "0.2.0")
|
|
.publish();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
p.cargo("update foobar --precise=0.2.0").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn use_semver_http() {
|
|
let _server = setup_http();
|
|
use_semver();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn use_semver_git() {
|
|
use_semver();
|
|
}
|
|
|
|
fn use_semver() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = "1.2.3-alpha.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("foo", "1.2.3-alpha.0").publish();
|
|
|
|
p.cargo("check").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn use_semver_package_incorrectly_http() {
|
|
let _server = setup_http();
|
|
use_semver_package_incorrectly(str![[r#"
|
|
[ERROR] failed to select a version for the requirement `a = "^0.1"`
|
|
candidate versions found which didn't match: 0.1.1-alpha.0
|
|
location searched: [ROOT]/foo/a
|
|
required by package `b v0.1.0 ([ROOT]/foo/b)`
|
|
if you are looking for the prerelease package it needs to be specified explicitly
|
|
a = { version = "0.1.1-alpha.0" }
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn use_semver_package_incorrectly_git() {
|
|
use_semver_package_incorrectly(str![[r#"
|
|
[ERROR] failed to select a version for the requirement `a = "^0.1"`
|
|
candidate versions found which didn't match: 0.1.1-alpha.0
|
|
location searched: [ROOT]/foo/a
|
|
required by package `b v0.1.0 ([ROOT]/foo/b)`
|
|
if you are looking for the prerelease package it needs to be specified explicitly
|
|
a = { version = "0.1.1-alpha.0" }
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn use_semver_package_incorrectly(expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
members = ["a", "b"]
|
|
"#,
|
|
)
|
|
.file(
|
|
"a/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.1.1-alpha.0"
|
|
edition = "2015"
|
|
authors = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"b/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "b"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
a = { version = "^0.1", path = "../a" }
|
|
"#,
|
|
)
|
|
.file("a/src/main.rs", "fn main() {}")
|
|
.file("b/src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.with_status(101)
|
|
.with_stderr_data(expected)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn only_download_relevant_http() {
|
|
let _server = setup_http();
|
|
only_download_relevant(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 3 packages to latest compatible versions
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`)
|
|
[CHECKING] baz v0.1.0
|
|
[CHECKING] bar v0.5.0 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn only_download_relevant_git() {
|
|
only_download_relevant(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 3 packages to latest compatible versions
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`)
|
|
[CHECKING] baz v0.1.0
|
|
[CHECKING] bar v0.5.0 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn only_download_relevant(expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[target.foo.dependencies]
|
|
foo = "*"
|
|
[dev-dependencies]
|
|
bar = "*"
|
|
[dependencies]
|
|
baz = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("foo", "0.1.0").publish();
|
|
Package::new("bar", "0.1.0").publish();
|
|
Package::new("baz", "0.1.0").publish();
|
|
|
|
p.cargo("check").with_stderr_data(expected).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn resolve_and_backtracking_http() {
|
|
let _server = setup_http();
|
|
resolve_and_backtracking();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn resolve_and_backtracking_git() {
|
|
resolve_and_backtracking();
|
|
}
|
|
|
|
fn resolve_and_backtracking() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("foo", "0.1.1")
|
|
.feature_dep("bar", "0.1", &["a", "b"])
|
|
.publish();
|
|
Package::new("foo", "0.1.0").publish();
|
|
|
|
p.cargo("check").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn upstream_warnings_on_extra_verbose_http() {
|
|
let _server = setup_http();
|
|
upstream_warnings_on_extra_verbose(str![[r#"
|
|
...
|
|
[WARNING] function `unused` is never used
|
|
...
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn upstream_warnings_on_extra_verbose_git() {
|
|
upstream_warnings_on_extra_verbose(str![[r#"
|
|
...
|
|
[WARNING] function `unused` is never used
|
|
...
|
|
"#]]);
|
|
}
|
|
|
|
fn upstream_warnings_on_extra_verbose(expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("foo", "0.1.0")
|
|
.file("src/lib.rs", "fn unused() {}")
|
|
.publish();
|
|
|
|
p.cargo("check -vv").with_stderr_data(expected).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn disallow_network_http() {
|
|
let _server = setup_http();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("check --frozen")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] no matching package named `foo` found
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `bar v0.5.0 ([ROOT]/foo)`
|
|
As a reminder, you're using offline mode (--frozen) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without `--frozen`.
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn disallow_network_git() {
|
|
let _server = RegistryBuilder::new().build();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = "*"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("check --frozen")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] no matching package named `foo` found
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `bar v0.5.0 ([ROOT]/foo)`
|
|
As a reminder, you're using offline mode (--frozen) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without `--frozen`.
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn add_dep_dont_update_registry_http() {
|
|
let _server = setup_http();
|
|
add_dep_dont_update_registry(str![[r#"
|
|
[CHECKING] bar v0.5.0 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn add_dep_dont_update_registry_git() {
|
|
add_dep_dont_update_registry(str![[r#"
|
|
[CHECKING] bar v0.5.0 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn add_dep_dont_update_registry(expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
baz = { path = "baz" }
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.file(
|
|
"baz/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "baz"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
remote = "0.3"
|
|
"#,
|
|
)
|
|
.file("baz/src/lib.rs", "")
|
|
.build();
|
|
|
|
Package::new("remote", "0.3.4").publish();
|
|
|
|
p.cargo("check").run();
|
|
|
|
p.change_file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
baz = { path = "baz" }
|
|
remote = "0.3"
|
|
"#,
|
|
);
|
|
|
|
p.cargo("check").with_stderr_data(expected).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn bump_version_dont_update_registry_http() {
|
|
let _server = setup_http();
|
|
bump_version_dont_update_registry(str![[r#"
|
|
[CHECKING] bar v0.6.0 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn bump_version_dont_update_registry_git() {
|
|
bump_version_dont_update_registry(str![[r#"
|
|
[CHECKING] bar v0.6.0 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn bump_version_dont_update_registry(expected: impl IntoData) {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
baz = { path = "baz" }
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.file(
|
|
"baz/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "baz"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
remote = "0.3"
|
|
"#,
|
|
)
|
|
.file("baz/src/lib.rs", "")
|
|
.build();
|
|
|
|
Package::new("remote", "0.3.4").publish();
|
|
|
|
p.cargo("check").run();
|
|
|
|
p.change_file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.6.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
baz = { path = "baz" }
|
|
"#,
|
|
);
|
|
|
|
p.cargo("check").with_stderr_data(expected).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn toml_lies_but_index_is_truth_http() {
|
|
let _server = setup_http();
|
|
toml_lies_but_index_is_truth();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn toml_lies_but_index_is_truth_git() {
|
|
toml_lies_but_index_is_truth();
|
|
}
|
|
|
|
fn toml_lies_but_index_is_truth() {
|
|
Package::new("foo", "0.2.0").publish();
|
|
Package::new("bar", "0.3.0")
|
|
.dep("foo", "0.2.0")
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.3.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = "0.1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "extern crate foo;")
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "0.3"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("check -v").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn vv_prints_warnings_http() {
|
|
let _server = setup_http();
|
|
vv_prints_warnings();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn vv_prints_warnings_git() {
|
|
vv_prints_warnings();
|
|
}
|
|
|
|
fn vv_prints_warnings() {
|
|
Package::new("foo", "0.2.0")
|
|
.file(
|
|
"src/lib.rs",
|
|
"#![deny(warnings)] fn foo() {} // unused function",
|
|
)
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "fo"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = "0.2"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("check -vv").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn bad_and_or_malicious_packages_rejected_http() {
|
|
let _server = setup_http();
|
|
bad_and_or_malicious_packages_rejected(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] foo v0.2.0 (registry `dummy-registry`)
|
|
[ERROR] failed to download replaced source registry `crates-io`
|
|
|
|
Caused by:
|
|
failed to unpack package `foo v0.2.0 (registry `dummy-registry`)`
|
|
|
|
Caused by:
|
|
invalid tarball downloaded, contains a file at "foo-0.1.0/src/lib.rs" which isn't under "foo-0.2.0"
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn bad_and_or_malicious_packages_rejected_git() {
|
|
bad_and_or_malicious_packages_rejected(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] foo v0.2.0 (registry `dummy-registry`)
|
|
[ERROR] failed to download replaced source registry `crates-io`
|
|
|
|
Caused by:
|
|
failed to unpack package `foo v0.2.0 (registry `dummy-registry`)`
|
|
|
|
Caused by:
|
|
invalid tarball downloaded, contains a file at "foo-0.1.0/src/lib.rs" which isn't under "foo-0.2.0"
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn bad_and_or_malicious_packages_rejected(expected: impl IntoData) {
|
|
Package::new("foo", "0.2.0")
|
|
.extra_file("foo-0.1.0/src/lib.rs", "")
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "fo"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = "0.2"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("check -vv")
|
|
.with_status(101)
|
|
.with_stderr_data(expected)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn git_init_templatedir_missing_http() {
|
|
let _server = setup_http();
|
|
git_init_templatedir_missing();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn git_init_templatedir_missing_git() {
|
|
git_init_templatedir_missing();
|
|
}
|
|
|
|
fn git_init_templatedir_missing() {
|
|
Package::new("foo", "0.2.0").dep("bar", "*").publish();
|
|
Package::new("bar", "0.2.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "fo"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = "0.2"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
|
|
remove_dir_all(paths::home().join(".cargo/registry")).unwrap();
|
|
fs::write(
|
|
paths::home().join(".gitconfig"),
|
|
r#"
|
|
[init]
|
|
templatedir = nowhere
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
p.cargo("check").run();
|
|
p.cargo("check").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn rename_deps_and_features_http() {
|
|
let _server = setup_http();
|
|
rename_deps_and_features();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn rename_deps_and_features_git() {
|
|
rename_deps_and_features();
|
|
}
|
|
|
|
fn rename_deps_and_features() {
|
|
Package::new("foo", "0.1.0")
|
|
.file("src/lib.rs", "pub fn f1() {}")
|
|
.publish();
|
|
Package::new("foo", "0.2.0")
|
|
.file("src/lib.rs", "pub fn f2() {}")
|
|
.publish();
|
|
Package::new("bar", "0.2.0")
|
|
.add_dep(
|
|
Dependency::new("foo01", "0.1.0")
|
|
.package("foo")
|
|
.optional(true),
|
|
)
|
|
.add_dep(Dependency::new("foo02", "0.2.0").package("foo"))
|
|
.feature("another", &["foo01"])
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
extern crate foo02;
|
|
#[cfg(feature = "foo01")]
|
|
extern crate foo01;
|
|
|
|
pub fn foo() {
|
|
foo02::f2();
|
|
#[cfg(feature = "foo01")]
|
|
foo01::f1();
|
|
}
|
|
"#,
|
|
)
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "0.2"
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/main.rs",
|
|
"
|
|
extern crate bar;
|
|
fn main() { bar::foo(); }
|
|
",
|
|
)
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
p.cargo("check --features bar/foo01").run();
|
|
p.cargo("check --features bar/another").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn ignore_invalid_json_lines_http() {
|
|
let _server = setup_http();
|
|
ignore_invalid_json_lines();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn ignore_invalid_json_lines_git() {
|
|
ignore_invalid_json_lines();
|
|
}
|
|
|
|
fn ignore_invalid_json_lines() {
|
|
Package::new("foo", "0.1.0").publish();
|
|
Package::new("foo", "0.1.1")
|
|
.invalid_index_line(true)
|
|
.publish();
|
|
Package::new("foo", "0.2.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = '0.1.0'
|
|
foo02 = { version = '0.2.0', package = 'foo' }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn invalid_json_lines_error() {
|
|
Package::new("foo", "0.1.0")
|
|
.rust_version("1.0")
|
|
.schema_version(2)
|
|
.publish();
|
|
Package::new("foo", "0.1.1")
|
|
// Bad name field, too corrupt to use
|
|
.invalid_index_line(true)
|
|
.publish();
|
|
Package::new("foo", "0.1.2")
|
|
// Bad version field, too corrupt to use
|
|
.index_line(
|
|
r#"{"cksum":"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79","deps":[],"features":{},"links":null,"name":"foo","vers":"bad","yanked":false,"rust_version":"1.2345","v":1000000000}"#,
|
|
)
|
|
.publish();
|
|
Package::new("foo", "0.1.3")
|
|
// Bad field, report rust version
|
|
.index_line(
|
|
r#"{"cksum":"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79","deps":[],"features":"bad","links":null,"name":"foo","vers":"0.1.3","yanked":false,"rust_version":"1.2345","v":1000000000}"#,
|
|
)
|
|
.publish();
|
|
Package::new("foo", "0.1.4")
|
|
// Bad field, report schema
|
|
.index_line(
|
|
r#"{"cksum":"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79","deps":[],"features":"bad","links":null,"name":"foo","vers":"0.1.4","yanked":false,"v":1000000000}"#,
|
|
)
|
|
.publish();
|
|
Package::new("foo", "0.1.5")
|
|
// Bad field, report error
|
|
.index_line(
|
|
r#"{"cksum":"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79","deps":[],"features":"bad","links":null,"name":"foo","vers":"0.1.5","yanked":false}"#,
|
|
)
|
|
.publish();
|
|
Package::new("foo", "0.1.6")
|
|
// Bad field with bad rust version, report schema
|
|
.index_line(
|
|
r#"{"cksum":"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79","deps":[],"features":"bad","links":null,"name":"foo","vers":"0.1.6","yanked":false,"rust_version":"bad","v":1000000000}"#,
|
|
)
|
|
.publish();
|
|
Package::new("foo", "0.1.7")
|
|
// Bad field with bad rust version and schema, report error
|
|
.index_line(
|
|
r#"{"cksum":"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79","deps":[],"features":"bad","links":null,"name":"foo","vers":"0.1.7","yanked":false,"rust_version":"bad","v":"bad"}"#,
|
|
)
|
|
.publish();
|
|
Package::new("foo", "0.2.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = "0.1.1"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `foo = "^0.1.1"`
|
|
version 0.1.3 requires cargo 1.2345
|
|
version 0.1.4 requires a Cargo version that supports index version 1000000000
|
|
version 0.1.5's index entry is invalid
|
|
version 0.1.6 requires a Cargo version that supports index version 1000000000
|
|
version 0.1.7's index entry is invalid
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `a v0.5.0 ([ROOT]/foo)`
|
|
|
|
"#]])
|
|
.run();
|
|
p.cargo("generate-lockfile")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `foo = "^0.1.1"`
|
|
version 0.1.3 requires cargo 1.2345
|
|
version 0.1.4 requires a Cargo version that supports index version 1000000000
|
|
version 0.1.5's index entry is invalid
|
|
version 0.1.6 requires a Cargo version that supports index version 1000000000
|
|
version 0.1.7's index entry is invalid
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `a v0.5.0 ([ROOT]/foo)`
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn readonly_registry_still_works_http() {
|
|
let _server = setup_http();
|
|
readonly_registry_still_works();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn readonly_registry_still_works_git() {
|
|
readonly_registry_still_works();
|
|
}
|
|
|
|
fn readonly_registry_still_works() {
|
|
Package::new("foo", "0.1.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = '0.1.0'
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
p.cargo("fetch --locked").run();
|
|
chmod_readonly(&paths::home(), true);
|
|
p.cargo("check").run();
|
|
// make sure we un-readonly the files afterwards so "cargo clean" can remove them (#6934)
|
|
chmod_readonly(&paths::home(), false);
|
|
|
|
fn chmod_readonly(path: &Path, readonly: bool) {
|
|
for entry in t!(path.read_dir()) {
|
|
let entry = t!(entry);
|
|
let path = entry.path();
|
|
if t!(entry.file_type()).is_dir() {
|
|
chmod_readonly(&path, readonly);
|
|
} else {
|
|
set_readonly(&path, readonly);
|
|
}
|
|
}
|
|
set_readonly(path, readonly);
|
|
}
|
|
|
|
fn set_readonly(path: &Path, readonly: bool) {
|
|
let mut perms = t!(path.metadata()).permissions();
|
|
perms.set_readonly(readonly);
|
|
t!(fs::set_permissions(path, perms));
|
|
}
|
|
}
|
|
|
|
#[cargo_test(ignore_windows = "On Windows setting file attributes is a bit complicated")]
|
|
fn unaccessible_registry_cache_still_works() {
|
|
Package::new("foo", "0.1.0").publish();
|
|
Package::new("fo2", "0.1.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.5.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = '0.1.0'
|
|
fo2 = '0.1.0'
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
p.cargo("fetch --locked").run();
|
|
|
|
let cache_path = inner_dir(&paths::cargo_home().join("registry/index")).join(".cache");
|
|
let f_cache_path = cache_path.join("3/f");
|
|
|
|
// Remove the permissions from the cache path that contains the "foo" crate
|
|
set_permissions(&f_cache_path, 0o000);
|
|
|
|
// Now run a build and make sure we properly build and warn the user
|
|
p.cargo("build")
|
|
.with_stderr_data(str![[r#"
|
|
[WARNING] failed to write cache, path: [ROOT]/home/.cargo/registry/index/-[HASH]/.cache/3/f/fo[..], [ERROR] Permission denied (os error 13)
|
|
[COMPILING] fo[..] v0.1.0
|
|
[COMPILING] fo[..] v0.1.0
|
|
[COMPILING] a v0.5.0 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
// make sure we add the permissions to the files afterwards so "cargo clean" can remove them (#6934)
|
|
set_permissions(&f_cache_path, 0o777);
|
|
|
|
#[cfg_attr(windows, allow(unused_variables))]
|
|
fn set_permissions(path: &Path, permissions: u32) {
|
|
#[cfg(not(windows))]
|
|
{
|
|
use std::os::unix::fs::PermissionsExt;
|
|
let mut perms = t!(path.metadata()).permissions();
|
|
perms.set_mode(permissions);
|
|
t!(fs::set_permissions(path, perms));
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
panic!("This test is not supported on windows. See the reason in the #[cargo_test] macro");
|
|
}
|
|
|
|
fn inner_dir(path: &Path) -> PathBuf {
|
|
for entry in t!(path.read_dir()) {
|
|
let path = t!(entry).path();
|
|
|
|
if path.is_dir() {
|
|
return path;
|
|
}
|
|
}
|
|
|
|
panic!("could not find inner directory of {path:?}");
|
|
}
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn registry_index_rejected_http() {
|
|
let _server = setup_http();
|
|
registry_index_rejected(
|
|
str![[r#"
|
|
[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`
|
|
|
|
Caused by:
|
|
the `registry.index` config value is no longer supported
|
|
Use `[source]` replacement to alter the default index for crates.io.
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[ERROR] the `registry.index` config value is no longer supported
|
|
Use `[source]` replacement to alter the default index for crates.io.
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn registry_index_rejected_git() {
|
|
registry_index_rejected(
|
|
str![[r#"
|
|
[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`
|
|
|
|
Caused by:
|
|
the `registry.index` config value is no longer supported
|
|
Use `[source]` replacement to alter the default index for crates.io.
|
|
|
|
"#]],
|
|
str![[r#"
|
|
[ERROR] the `registry.index` config value is no longer supported
|
|
Use `[source]` replacement to alter the default index for crates.io.
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
fn registry_index_rejected(expected_check: impl IntoData, expected_login: impl IntoData) {
|
|
Package::new("dep", "0.1.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
".cargo/config.toml",
|
|
r#"
|
|
[registry]
|
|
index = "https://example.com/"
|
|
"#,
|
|
)
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
dep = "0.1"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.with_status(101)
|
|
.with_stderr_data(expected_check)
|
|
.run();
|
|
|
|
p.cargo("login")
|
|
.with_status(101)
|
|
.with_stderr_data(expected_login)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn package_lock_inside_package_is_overwritten() {
|
|
let registry = registry::init();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = ">= 0.0.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("bar", "0.0.1")
|
|
.file("src/lib.rs", "")
|
|
.file(".cargo-ok", "")
|
|
.publish();
|
|
|
|
p.cargo("check").run();
|
|
|
|
let id = SourceId::for_registry(registry.index_url()).unwrap();
|
|
let hash = cargo::util::hex::short_hash(&id);
|
|
let ok = paths::cargo_home()
|
|
.join("registry")
|
|
.join("src")
|
|
.join(format!("-{}", hash))
|
|
.join("bar-0.0.1")
|
|
.join(".cargo-ok");
|
|
|
|
assert_eq!(ok.metadata().unwrap().len(), 7);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn package_lock_as_a_symlink_inside_package_is_overwritten() {
|
|
let registry = registry::init();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = ">= 0.0.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("bar", "0.0.1")
|
|
.file("src/lib.rs", "pub fn f() {}")
|
|
.symlink(".cargo-ok", "src/lib.rs")
|
|
.publish();
|
|
|
|
p.cargo("check").run();
|
|
|
|
let id = SourceId::for_registry(registry.index_url()).unwrap();
|
|
let hash = cargo::util::hex::short_hash(&id);
|
|
let pkg_root = paths::cargo_home()
|
|
.join("registry")
|
|
.join("src")
|
|
.join(format!("-{}", hash))
|
|
.join("bar-0.0.1");
|
|
let ok = pkg_root.join(".cargo-ok");
|
|
let librs = pkg_root.join("src/lib.rs");
|
|
|
|
// Is correctly overwritten and doesn't affect the file linked to
|
|
assert_eq!(ok.metadata().unwrap().len(), 7);
|
|
assert_eq!(fs::read_to_string(librs).unwrap(), "pub fn f() {}");
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn ignores_unknown_index_version_http() {
|
|
let _server = setup_http();
|
|
ignores_unknown_index_version(str![[r#"
|
|
foo v0.1.0 ([ROOT]/foo)
|
|
└── bar v1.0.0
|
|
|
|
"#]]);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn ignores_unknown_index_version_git() {
|
|
ignores_unknown_index_version(str![[r#"
|
|
foo v0.1.0 ([ROOT]/foo)
|
|
└── bar v1.0.0
|
|
|
|
"#]]);
|
|
}
|
|
|
|
fn ignores_unknown_index_version(expected: impl IntoData) {
|
|
// If the version field is not understood, it is ignored.
|
|
Package::new("bar", "1.0.0").publish();
|
|
Package::new("bar", "1.0.1")
|
|
.schema_version(u32::MAX)
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
bar = "1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("tree").with_stdout_data(expected).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn unknown_index_version_error() {
|
|
Package::new("bar", "0.0.1").publish();
|
|
// If the version field is not understood, it is ignored.
|
|
Package::new("bar", "1.0.1")
|
|
.schema_version(u32::MAX)
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
bar = "1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `bar = "^1.0"`
|
|
version 1.0.1 requires a Cargo version that supports index version 4294967295
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.1.0 ([ROOT]/foo)`
|
|
|
|
"#]])
|
|
.run();
|
|
p.cargo("generate-lockfile")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `bar = "^1.0"`
|
|
version 1.0.1 requires a Cargo version that supports index version 4294967295
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.1.0 ([ROOT]/foo)`
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn unknown_index_version_with_msrv_error() {
|
|
Package::new("bar", "0.0.1").publish();
|
|
// If the version field is not understood, it is ignored.
|
|
Package::new("bar", "1.0.1")
|
|
.schema_version(u32::MAX)
|
|
.rust_version("1.2345")
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
bar = "1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `bar = "^1.0"`
|
|
version 1.0.1 requires cargo 1.2345
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.1.0 ([ROOT]/foo)`
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn protocol() {
|
|
cargo_process("install bar")
|
|
.with_status(101)
|
|
.env("CARGO_REGISTRIES_CRATES_IO_PROTOCOL", "invalid")
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] unsupported registry protocol `invalid` (defined in environment variable `CARGO_REGISTRIES_CRATES_IO_PROTOCOL`)
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn http_requires_trailing_slash() {
|
|
cargo_process("install bar --index sparse+https://invalid.crates.io/test")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] sparse registry url must end in a slash `/`: sparse+https://invalid.crates.io/test
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
// Limit the test to debug builds so that `__CARGO_TEST_MAX_UNPACK_SIZE` will take affect.
|
|
#[cfg(debug_assertions)]
|
|
#[cargo_test]
|
|
fn reach_max_unpack_size() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
bar = ">= 0.0.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
// Size of bar.crate is around 180 bytes.
|
|
Package::new("bar", "0.0.1").publish();
|
|
|
|
p.cargo("check")
|
|
.env("__CARGO_TEST_MAX_UNPACK_SIZE", "8") // hit 8 bytes limit and boom!
|
|
.env("__CARGO_TEST_MAX_UNPACK_RATIO", "0")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
|
|
[ERROR] failed to download replaced source registry `crates-io`
|
|
|
|
Caused by:
|
|
failed to unpack package `bar v0.0.1 (registry `dummy-registry`)`
|
|
|
|
Caused by:
|
|
failed to iterate over archive
|
|
|
|
Caused by:
|
|
maximum limit reached when reading
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// Restore to the default ratio and it should compile.
|
|
p.cargo("check")
|
|
.env("__CARGO_TEST_MAX_UNPACK_SIZE", "8")
|
|
.with_stderr_data(str![[r#"
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn sparse_blocking_count() {
|
|
let fail_count = Mutex::new(0);
|
|
let _registry = RegistryBuilder::new()
|
|
.http_index()
|
|
.add_responder("/index/3/b/bar", move |req, server| {
|
|
let mut fail_count = fail_count.lock().unwrap();
|
|
if *fail_count < 1 {
|
|
*fail_count += 1;
|
|
server.internal_server_error(req)
|
|
} else {
|
|
server.index(req)
|
|
}
|
|
})
|
|
.build();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = ">= 0.0.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("bar", "0.0.1").publish();
|
|
|
|
// Ensure we have the expected number of `block_until_ready` calls.
|
|
// The 1st (0 transfers pending), is the deliberate extra call in `ensure_loaded` for a source.
|
|
// The 2nd (1 transfers pending), is the registry `config.json`.
|
|
// the 3rd (1 transfers pending), is the package metadata for `bar`.
|
|
|
|
p.cargo("check")
|
|
.env("CARGO_LOG", "network::HttpRegistry::block_until_ready=trace")
|
|
.with_stderr_data(str![[r#"
|
|
[..] TRACE network::HttpRegistry::block_until_ready: 0 transfers pending
|
|
[UPDATING] `dummy-registry` index
|
|
[..] TRACE network::HttpRegistry::block_until_ready: 1 transfers pending
|
|
[..] TRACE network::HttpRegistry::block_until_ready: 1 transfers pending
|
|
[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `[..]/index/3/b/bar` ([..]), got 500
|
|
body:
|
|
internal server error
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn sparse_retry_single() {
|
|
let fail_count = Mutex::new(0);
|
|
let _registry = RegistryBuilder::new()
|
|
.http_index()
|
|
.add_responder("/index/3/b/bar", move |req, server| {
|
|
let mut fail_count = fail_count.lock().unwrap();
|
|
if *fail_count < 2 {
|
|
*fail_count += 1;
|
|
server.internal_server_error(req)
|
|
} else {
|
|
server.index(req)
|
|
}
|
|
})
|
|
.build();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = ">= 0.0.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("bar", "0.0.1").publish();
|
|
|
|
p.cargo("check").with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 500
|
|
body:
|
|
internal server error
|
|
[WARNING] spurious network error (2 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 500
|
|
body:
|
|
internal server error
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn sparse_retry_multiple() {
|
|
// Tests retry behavior of downloading lots of packages with various
|
|
// failure rates accessing the sparse index.
|
|
|
|
// The index is the number of retries, the value is the number of packages
|
|
// that retry that number of times. Thus 50 packages succeed on first try,
|
|
// 25 on second, etc.
|
|
const RETRIES: &[u32] = &[50, 25, 12, 6];
|
|
|
|
let pkgs: Vec<_> = RETRIES
|
|
.iter()
|
|
.enumerate()
|
|
.flat_map(|(retries, num)| {
|
|
(0..*num)
|
|
.into_iter()
|
|
.map(move |n| (retries as u32, format!("{}-{n}-{retries}", rand_prefix())))
|
|
})
|
|
.collect();
|
|
|
|
let mut builder = RegistryBuilder::new().http_index();
|
|
let fail_counts: Arc<Mutex<Vec<u32>>> = Arc::new(Mutex::new(vec![0; pkgs.len()]));
|
|
let mut cargo_toml = r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
"#
|
|
.to_string();
|
|
// The expected stderr output.
|
|
let mut expected = "\
|
|
[UPDATING] `dummy-registry` index
|
|
[DOWNLOADING] crates ...
|
|
"
|
|
.to_string();
|
|
for (n, (retries, name)) in pkgs.iter().enumerate() {
|
|
let count_clone = fail_counts.clone();
|
|
let retries = *retries;
|
|
let ab = &name[..2];
|
|
let cd = &name[2..4];
|
|
builder = builder.add_responder(format!("/index/{ab}/{cd}/{name}"), move |req, server| {
|
|
let mut fail_counts = count_clone.lock().unwrap();
|
|
if fail_counts[n] < retries {
|
|
fail_counts[n] += 1;
|
|
server.internal_server_error(req)
|
|
} else {
|
|
server.index(req)
|
|
}
|
|
});
|
|
write!(&mut cargo_toml, "{name} = \"1.0.0\"\n").unwrap();
|
|
for retry in 0..retries {
|
|
let remain = 3 - retry;
|
|
write!(
|
|
&mut expected,
|
|
"[WARNING] spurious network error ({remain} {} remaining): \
|
|
failed to get successful HTTP response from \
|
|
`http://127.0.0.1:[..]/{ab}/{cd}/{name}` (127.0.0.1), got 500\n\
|
|
body:\n\
|
|
internal server error\n",
|
|
if remain != 1 { "tries" } else { "try" }
|
|
)
|
|
.unwrap();
|
|
}
|
|
write!(
|
|
&mut expected,
|
|
"\
|
|
[DOWNLOADED] {name} v1.0.0 (registry `dummy-registry`)
|
|
"
|
|
)
|
|
.unwrap();
|
|
}
|
|
write!(
|
|
&mut expected,
|
|
"\
|
|
[LOCKING] 93 packages to latest compatible versions
|
|
"
|
|
)
|
|
.unwrap();
|
|
let _server = builder.build();
|
|
for (_, name) in &pkgs {
|
|
Package::new(name, "1.0.0").publish();
|
|
}
|
|
let p = project()
|
|
.file("Cargo.toml", &cargo_toml)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
p.cargo("fetch")
|
|
.with_stderr_data(IntoData::unordered(expected))
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn dl_retry_single() {
|
|
// Tests retry behavior of downloading a package.
|
|
// This tests a single package which exercises the code path that causes
|
|
// it to block.
|
|
let fail_count = Mutex::new(0);
|
|
let _server = RegistryBuilder::new()
|
|
.http_index()
|
|
.add_responder("/dl/bar/1.0.0/download", move |req, server| {
|
|
let mut fail_count = fail_count.lock().unwrap();
|
|
if *fail_count < 2 {
|
|
*fail_count += 1;
|
|
server.internal_server_error(req)
|
|
} else {
|
|
server.dl(req)
|
|
}
|
|
})
|
|
.build();
|
|
Package::new("bar", "1.0.0").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
bar = "1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
p.cargo("fetch").with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 500
|
|
body:
|
|
internal server error
|
|
[WARNING] spurious network error (2 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 500
|
|
body:
|
|
internal server error
|
|
[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)
|
|
|
|
"#]]).run();
|
|
}
|
|
|
|
/// Creates a random prefix to randomly spread out the package names
|
|
/// to somewhat evenly distribute the different failures at different
|
|
/// points.
|
|
fn rand_prefix() -> String {
|
|
use rand::Rng;
|
|
const CHARS: &[u8] = b"abcdefghijklmnopqrstuvwxyz";
|
|
let mut rng = rand::rng();
|
|
(0..5)
|
|
.map(|_| CHARS[rng.random_range(0..CHARS.len())] as char)
|
|
.collect()
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn dl_retry_multiple() {
|
|
// Tests retry behavior of downloading lots of packages with various
|
|
// failure rates.
|
|
|
|
// The index is the number of retries, the value is the number of packages
|
|
// that retry that number of times. Thus 50 packages succeed on first try,
|
|
// 25 on second, etc.
|
|
const RETRIES: &[u32] = &[50, 25, 12, 6];
|
|
|
|
let pkgs: Vec<_> = RETRIES
|
|
.iter()
|
|
.enumerate()
|
|
.flat_map(|(retries, num)| {
|
|
(0..*num)
|
|
.into_iter()
|
|
.map(move |n| (retries as u32, format!("{}-{n}-{retries}", rand_prefix())))
|
|
})
|
|
.collect();
|
|
|
|
let mut builder = RegistryBuilder::new().http_index();
|
|
let fail_counts: Arc<Mutex<Vec<u32>>> = Arc::new(Mutex::new(vec![0; pkgs.len()]));
|
|
let mut cargo_toml = r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
"#
|
|
.to_string();
|
|
// The expected stderr output.
|
|
let mut expected = "\
|
|
[UPDATING] `dummy-registry` index
|
|
[DOWNLOADING] crates ...
|
|
"
|
|
.to_string();
|
|
for (n, (retries, name)) in pkgs.iter().enumerate() {
|
|
let count_clone = fail_counts.clone();
|
|
let retries = *retries;
|
|
builder =
|
|
builder.add_responder(format!("/dl/{name}/1.0.0/download"), move |req, server| {
|
|
let mut fail_counts = count_clone.lock().unwrap();
|
|
if fail_counts[n] < retries {
|
|
fail_counts[n] += 1;
|
|
server.internal_server_error(req)
|
|
} else {
|
|
server.dl(req)
|
|
}
|
|
});
|
|
write!(&mut cargo_toml, "{name} = \"1.0.0\"\n").unwrap();
|
|
for retry in 0..retries {
|
|
let remain = 3 - retry;
|
|
write!(
|
|
&mut expected,
|
|
"[WARNING] spurious network error ({remain} {} remaining): \
|
|
failed to get successful HTTP response from \
|
|
`http://127.0.0.1:[..]/dl/{name}/1.0.0/download` (127.0.0.1), got 500\n\
|
|
body:\n\
|
|
internal server error\n",
|
|
if remain != 1 { "tries" } else { "try" }
|
|
)
|
|
.unwrap();
|
|
}
|
|
write!(
|
|
&mut expected,
|
|
"[DOWNLOADED] {name} v1.0.0 (registry `dummy-registry`)\n"
|
|
)
|
|
.unwrap();
|
|
}
|
|
write!(
|
|
&mut expected,
|
|
"[LOCKING] 93 packages to latest compatible versions\n"
|
|
)
|
|
.unwrap();
|
|
let _server = builder.build();
|
|
for (_, name) in &pkgs {
|
|
Package::new(name, "1.0.0").publish();
|
|
}
|
|
let p = project()
|
|
.file("Cargo.toml", &cargo_toml)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
p.cargo("fetch")
|
|
.with_stderr_data(IntoData::unordered(expected))
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn retry_too_many_requests() {
|
|
let fail_count = Mutex::new(0);
|
|
let _registry = RegistryBuilder::new()
|
|
.http_index()
|
|
.add_responder("/index/3/b/bar", move |req, server| {
|
|
let mut fail_count = fail_count.lock().unwrap();
|
|
if *fail_count < 1 {
|
|
*fail_count += 1;
|
|
server.too_many_requests(req, std::time::Duration::from_secs(1))
|
|
} else {
|
|
server.index(req)
|
|
}
|
|
})
|
|
.build();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = ">= 0.0.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("bar", "0.0.1").publish();
|
|
|
|
p.cargo("check")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `[..]/index/3/b/bar` ([..]), got 429
|
|
body:
|
|
too many requests, try again in 1 seconds
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
|
|
[CHECKING] bar v0.0.1
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn deleted_entry() {
|
|
// Checks the behavior when a package is removed from the index.
|
|
// This is done occasionally on crates.io to handle things like
|
|
// copyright takedowns.
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
bar = "0.1"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
// First, test removing a single version, but leaving an older version.
|
|
Package::new("bar", "0.1.0").publish();
|
|
let bar_path = Path::new("3/b/bar");
|
|
let bar_reg_path = registry_path().join(&bar_path);
|
|
let old_index = fs::read_to_string(&bar_reg_path).unwrap();
|
|
Package::new("bar", "0.1.1").publish();
|
|
p.cargo("tree")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.1.1 (registry `dummy-registry`)
|
|
|
|
"#]])
|
|
.with_stdout_data(str![[r#"
|
|
foo v0.1.0 ([ROOT]/foo)
|
|
└── bar v0.1.1
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// Remove 0.1.1
|
|
fs::remove_file(paths::root().join("dl/bar/0.1.1/download")).unwrap();
|
|
let repo = git2::Repository::open(registry_path()).unwrap();
|
|
let mut index = repo.index().unwrap();
|
|
fs::write(&bar_reg_path, &old_index).unwrap();
|
|
index.add_path(&bar_path).unwrap();
|
|
index.write().unwrap();
|
|
git::commit(&repo);
|
|
|
|
// With `Cargo.lock` unchanged, it shouldn't have an impact.
|
|
p.cargo("tree")
|
|
.with_stderr_data("")
|
|
.with_stdout_data(str![[r#"
|
|
foo v0.1.0 ([ROOT]/foo)
|
|
└── bar v0.1.1
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// Regenerating Cargo.lock should switch to old version.
|
|
fs::remove_file(p.root().join("Cargo.lock")).unwrap();
|
|
p.cargo("tree")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)
|
|
|
|
"#]])
|
|
.with_stdout_data(str![[r#"
|
|
foo v0.1.0 ([ROOT]/foo)
|
|
└── bar v0.1.0
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// Remove the package entirely.
|
|
fs::remove_file(paths::root().join("dl/bar/0.1.0/download")).unwrap();
|
|
let mut index = repo.index().unwrap();
|
|
index.remove(&bar_path, 0).unwrap();
|
|
index.write().unwrap();
|
|
git::commit(&repo);
|
|
fs::remove_file(&bar_reg_path).unwrap();
|
|
|
|
// With `Cargo.lock` unchanged, it shouldn't have an impact.
|
|
p.cargo("tree")
|
|
.with_stderr_data("")
|
|
.with_stdout_data(str![[r#"
|
|
foo v0.1.0 ([ROOT]/foo)
|
|
└── bar v0.1.0
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// Regenerating Cargo.lock should fail.
|
|
fs::remove_file(p.root().join("Cargo.lock")).unwrap();
|
|
p.cargo("tree")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] no matching package named `bar` found
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.1.0 ([ROOT]/foo)`
|
|
|
|
"#]])
|
|
.with_status(101)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn corrupted_ok_overwritten() {
|
|
// Checks what happens if .cargo-ok gets truncated, such as if the file is
|
|
// created, but the flush/close is interrupted.
|
|
Package::new("bar", "1.0.0").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
bar = "1"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
p.cargo("fetch")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)
|
|
|
|
"#]])
|
|
.run();
|
|
let ok = glob::glob(
|
|
paths::home()
|
|
.join(".cargo/registry/src/*/bar-1.0.0/.cargo-ok")
|
|
.to_str()
|
|
.unwrap(),
|
|
)
|
|
.unwrap()
|
|
.next()
|
|
.unwrap()
|
|
.unwrap();
|
|
// Simulate cargo being interrupted, or filesystem corruption.
|
|
fs::write(&ok, "").unwrap();
|
|
assert_eq!(fs::read_to_string(&ok).unwrap(), "");
|
|
p.cargo("fetch").with_stderr_data("").run();
|
|
assert_eq!(fs::read_to_string(&ok).unwrap(), r#"{"v":1}"#);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn not_found_permutations() {
|
|
// Test for querying permutations for a missing dependency.
|
|
let misses = Arc::new(Mutex::new(Vec::new()));
|
|
let misses2 = misses.clone();
|
|
let _registry = RegistryBuilder::new()
|
|
.http_index()
|
|
.not_found_handler(move |req, _server| {
|
|
let mut misses = misses2.lock().unwrap();
|
|
misses.push(req.url.path().to_string());
|
|
Response {
|
|
code: 404,
|
|
headers: vec![],
|
|
body: b"not found".to_vec(),
|
|
}
|
|
})
|
|
.build();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
a-b_c = "1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] no matching package named `a-b_c` found
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]])
|
|
.run();
|
|
let mut misses = misses.lock().unwrap();
|
|
misses.sort();
|
|
assert_eq!(
|
|
&*misses,
|
|
&[
|
|
"/index/a-/b-/a-b-c",
|
|
"/index/a-/b_/a-b_c",
|
|
"/index/a_/b_/a_b_c"
|
|
]
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn default_auth_error() {
|
|
// Check for the error message for an authentication error when default is set.
|
|
let crates_io = RegistryBuilder::new().http_api().build();
|
|
let _alternative = RegistryBuilder::new().http_api().alternative().build();
|
|
|
|
paths::home().join(".cargo/credentials.toml").rm_rf();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
license = "MIT"
|
|
description = "foo"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
// Test output before setting the default.
|
|
p.cargo("publish --no-verify")
|
|
.replace_crates_io(crates_io.index_url())
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] crates.io index
|
|
[ERROR] no token found, please run `cargo login`
|
|
or use environment variable CARGO_REGISTRY_TOKEN
|
|
|
|
"#]])
|
|
.with_status(101)
|
|
.run();
|
|
|
|
p.cargo("publish --no-verify --registry alternative")
|
|
.replace_crates_io(crates_io.index_url())
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `alternative` index
|
|
[ERROR] no token found for `alternative`, please run `cargo login --registry alternative`
|
|
or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN
|
|
|
|
"#]])
|
|
.with_status(101)
|
|
.run();
|
|
|
|
// Test the output with the default.
|
|
cargo_util::paths::append(
|
|
&paths::cargo_home().join("config.toml"),
|
|
br#"
|
|
[registry]
|
|
default = "alternative"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
p.cargo("publish --no-verify")
|
|
.replace_crates_io(crates_io.index_url())
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `alternative` index
|
|
[ERROR] no token found for `alternative`, please run `cargo login --registry alternative`
|
|
or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN
|
|
|
|
"#]])
|
|
.with_status(101)
|
|
.run();
|
|
|
|
p.cargo("publish --no-verify --registry crates-io")
|
|
.replace_crates_io(crates_io.index_url())
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] crates.io index
|
|
[ERROR] no token found, please run `cargo login --registry crates-io`
|
|
or use environment variable CARGO_REGISTRY_TOKEN
|
|
|
|
"#]])
|
|
.with_status(101)
|
|
.run();
|
|
}
|
|
|
|
const SAMPLE_HEADERS: &[&str] = &[
|
|
"x-amz-cf-pop: SFO53-P2",
|
|
"x-amz-cf-id: vEc3osJrCAXVaciNnF4Vev-hZFgnYwmNZtxMKRJ5bF6h9FTOtbTMnA==",
|
|
"x-cache: Hit from cloudfront",
|
|
"server: AmazonS3",
|
|
"x-amz-version-id: pvsJYY_JGsWiSETZvLJKb7DeEW5wWq1W",
|
|
"x-amz-server-side-encryption: AES256",
|
|
"content-type: text/plain",
|
|
"via: 1.1 bcbc5b46216015493e082cfbcf77ef10.cloudfront.net (CloudFront)",
|
|
];
|
|
|
|
#[cargo_test]
|
|
fn debug_header_message_index() {
|
|
// The error message should include some headers for debugging purposes.
|
|
let _server = RegistryBuilder::new()
|
|
.http_index()
|
|
.add_responder("/index/3/b/bar", |_, _| Response {
|
|
code: 503,
|
|
headers: SAMPLE_HEADERS.iter().map(|s| s.to_string()).collect(),
|
|
body: b"Please slow down".to_vec(),
|
|
})
|
|
.build();
|
|
Package::new("bar", "1.0.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
bar = "1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
p.cargo("fetch")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 503
|
|
body:
|
|
Please slow down
|
|
[WARNING] spurious network error (2 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 503
|
|
body:
|
|
Please slow down
|
|
[WARNING] spurious network error (1 try remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 503
|
|
body:
|
|
Please slow down
|
|
[ERROR] failed to get `bar` as a dependency of package `foo v0.1.0 ([ROOT]/foo)`
|
|
|
|
Caused by:
|
|
failed to query replaced source registry `crates-io`
|
|
|
|
Caused by:
|
|
download of 3/b/bar failed
|
|
|
|
Caused by:
|
|
failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 503
|
|
debug headers:
|
|
x-amz-cf-pop: SFO53-P2
|
|
x-amz-cf-id: vEc3osJrCAXVaciNnF4Vev-hZFgnYwmNZtxMKRJ5bF6h9FTOtbTMnA==
|
|
x-cache: Hit from cloudfront
|
|
body:
|
|
Please slow down
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn debug_header_message_dl() {
|
|
// Same as debug_header_message_index, but for the dl endpoint which goes
|
|
// through a completely different code path.
|
|
let _server = RegistryBuilder::new()
|
|
.http_index()
|
|
.add_responder("/dl/bar/1.0.0/download", |_, _| Response {
|
|
code: 503,
|
|
headers: SAMPLE_HEADERS.iter().map(|s| s.to_string()).collect(),
|
|
body: b"Please slow down".to_vec(),
|
|
})
|
|
.build();
|
|
Package::new("bar", "1.0.0").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
bar = "1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("fetch")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 503
|
|
body:
|
|
Please slow down
|
|
[WARNING] spurious network error (2 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 503
|
|
body:
|
|
Please slow down
|
|
[WARNING] spurious network error (1 try remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 503
|
|
body:
|
|
Please slow down
|
|
[ERROR] failed to download from `http://127.0.0.1:[..]/dl/bar/1.0.0/download`
|
|
|
|
Caused by:
|
|
failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 503
|
|
debug headers:
|
|
x-amz-cf-pop: SFO53-P2
|
|
x-amz-cf-id: vEc3osJrCAXVaciNnF4Vev-hZFgnYwmNZtxMKRJ5bF6h9FTOtbTMnA==
|
|
x-cache: Hit from cloudfront
|
|
body:
|
|
Please slow down
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
#[cargo_test]
|
|
fn set_mask_during_unpacking() {
|
|
use std::os::unix::fs::MetadataExt;
|
|
|
|
Package::new("bar", "1.0.0")
|
|
.file_with_mode("example.sh", 0o777, "#!/bin/sh")
|
|
.file_with_mode("src/lib.rs", 0o666, "")
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
bar = "1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("fetch")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)
|
|
|
|
"#]])
|
|
.run();
|
|
let src_file_path = |path: &str| {
|
|
glob::glob(
|
|
paths::home()
|
|
.join(".cargo/registry/src/*/bar-1.0.0/")
|
|
.join(path)
|
|
.to_str()
|
|
.unwrap(),
|
|
)
|
|
.unwrap()
|
|
.next()
|
|
.unwrap()
|
|
.unwrap()
|
|
};
|
|
|
|
let umask = cargo::util::get_umask();
|
|
let metadata = fs::metadata(src_file_path("src/lib.rs")).unwrap();
|
|
assert_eq!(metadata.mode() & 0o777, 0o666 & !umask);
|
|
let metadata = fs::metadata(src_file_path("example.sh")).unwrap();
|
|
assert_eq!(metadata.mode() & 0o777, 0o777 & !umask);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn unpack_again_when_cargo_ok_is_unrecognized() {
|
|
Package::new("bar", "1.0.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
bar = "1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("fetch")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
let src_file_path = |path: &str| {
|
|
glob::glob(
|
|
paths::home()
|
|
.join(".cargo/registry/src/*/bar-1.0.0/")
|
|
.join(path)
|
|
.to_str()
|
|
.unwrap(),
|
|
)
|
|
.unwrap()
|
|
.next()
|
|
.unwrap()
|
|
.unwrap()
|
|
};
|
|
|
|
// Change permissions to simulate the old behavior not respecting umask.
|
|
let lib_rs = src_file_path("src/lib.rs");
|
|
let cargo_ok = src_file_path(".cargo-ok");
|
|
let mut perms = fs::metadata(&lib_rs).unwrap().permissions();
|
|
assert!(!perms.readonly());
|
|
perms.set_readonly(true);
|
|
fs::set_permissions(&lib_rs, perms).unwrap();
|
|
let ok = fs::read_to_string(&cargo_ok).unwrap();
|
|
assert_eq!(&ok, r#"{"v":1}"#);
|
|
|
|
p.cargo("fetch").with_stderr_data("").run();
|
|
|
|
// Without changing `.cargo-ok`, a unpack won't be triggered.
|
|
let perms = fs::metadata(&lib_rs).unwrap().permissions();
|
|
assert!(perms.readonly());
|
|
|
|
// Write "ok" to simulate the old behavior and trigger the unpack again.
|
|
fs::write(&cargo_ok, "ok").unwrap();
|
|
|
|
p.cargo("fetch").with_stderr_data("").run();
|
|
|
|
// Permission has been restored and `.cargo-ok` is in the new format.
|
|
let perms = fs::metadata(lib_rs).unwrap().permissions();
|
|
assert!(!perms.readonly());
|
|
let ok = fs::read_to_string(&cargo_ok).unwrap();
|
|
assert_eq!(&ok, r#"{"v":1}"#);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn differ_only_by_metadata() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
baz = "=0.0.1"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("baz", "0.0.1+b").publish();
|
|
Package::new("baz", "0.0.1+c").yanked(true).publish();
|
|
|
|
p.cargo("check")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] baz v0.0.1+b (registry `dummy-registry`)
|
|
[CHECKING] baz v0.0.1+b
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
Package::new("baz", "0.0.1+d").publish();
|
|
|
|
p.cargo("clean").run();
|
|
p.cargo("check")
|
|
.with_stderr_data(str![[r#"
|
|
[CHECKING] baz v0.0.1+b
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn differ_only_by_metadata_with_lockfile() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
baz = "=0.0.1"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
Package::new("baz", "0.0.1+a").publish();
|
|
Package::new("baz", "0.0.1+b").publish();
|
|
Package::new("baz", "0.0.1+c").publish();
|
|
|
|
p.cargo("update --package baz --precise 0.0.1+b")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[UPDATING] baz v0.0.1+c -> v0.0.1+b
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("check")
|
|
.with_stderr_data(str![[r#"
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] baz v0.0.1+b (registry `dummy-registry`)
|
|
[CHECKING] baz v0.0.1+b
|
|
[CHECKING] foo v0.0.1 ([ROOT]/foo)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn builtin_source_replacement() {
|
|
// errors for builtin source replacement of crates.io
|
|
// should not include mention of source replacement in the error message.
|
|
let server = RegistryBuilder::new().build();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
bad-cksum = ">= 0.0.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
let pkg = Package::new("bad-cksum", "0.0.1");
|
|
pkg.publish();
|
|
t!(File::create(&pkg.archive_dst()));
|
|
|
|
p.cargo("check -v")
|
|
.replace_crates_io(&server.index_url())
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] crates.io index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] bad-cksum v0.0.1
|
|
[ERROR] failed to verify the checksum of `bad-cksum v0.0.1`
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn builtin_source_replacement_no_vendor_error() {
|
|
// errors for builtin source replacement of crates.io
|
|
// should not mention outdated vendor dependencies
|
|
let server = RegistryBuilder::new().build();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
dep = "0.2.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
let pkg = Package::new("dep", "0.1.0");
|
|
pkg.publish();
|
|
|
|
p.cargo("check -v")
|
|
.replace_crates_io(&server.index_url())
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] crates.io index
|
|
[ERROR] failed to select a version for the requirement `dep = "^0.2.0"`
|
|
candidate versions found which didn't match: 0.1.0
|
|
location searched: crates.io index
|
|
required by package `foo v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]])
|
|
.run();
|
|
}
|