diff options
Diffstat (limited to 'src/tools/cargo/tests/testsuite/credential_process.rs')
-rw-r--r-- | src/tools/cargo/tests/testsuite/credential_process.rs | 640 |
1 files changed, 397 insertions, 243 deletions
diff --git a/src/tools/cargo/tests/testsuite/credential_process.rs b/src/tools/cargo/tests/testsuite/credential_process.rs index 8c202c6a3..c010c01cd 100644 --- a/src/tools/cargo/tests/testsuite/credential_process.rs +++ b/src/tools/cargo/tests/testsuite/credential_process.rs @@ -1,8 +1,7 @@ //! Tests for credential-process. -use cargo_test_support::registry::TestRegistry; +use cargo_test_support::registry::{Package, TestRegistry}; use cargo_test_support::{basic_manifest, cargo_process, paths, project, registry, Project}; -use std::fs::{self, read_to_string}; fn toml_bin(proj: &Project, name: &str) -> String { proj.bin(name).display().to_string().replace('\\', "\\\\") @@ -24,7 +23,7 @@ fn gated() { ".cargo/config", r#" [registry] - credential-process = "false" + credential-provider = ["false"] "#, ) .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) @@ -65,80 +64,6 @@ or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN .run(); } -#[cargo_test] -fn warn_both_token_and_process() { - // Specifying both credential-process and a token in config should issue a warning. - let _server = registry::RegistryBuilder::new() - .http_api() - .http_index() - .alternative() - .no_configure_token() - .build(); - let p = project() - .file( - ".cargo/config", - r#" - [registries.alternative] - token = "alternative-sekrit" - credential-process = "false" - "#, - ) - .file( - "Cargo.toml", - r#" - [package] - name = "foo" - version = "0.1.0" - description = "foo" - authors = [] - license = "MIT" - homepage = "https://example.com/" - "#, - ) - .file("src/lib.rs", "") - .build(); - - p.cargo("publish --no-verify --registry alternative -Z credential-process") - .masquerade_as_nightly_cargo(&["credential-process"]) - .with_status(101) - .with_stderr( - "\ -[UPDATING] [..] -[ERROR] both `token` and `credential-process` were specified in the config for registry `alternative`. -Only one of these values may be set, remove one or the other to proceed. -", - ) - .run(); - - // Try with global credential-process, and registry-specific `token`. - // This should silently use the config token, and not run the "false" exe. - p.change_file( - ".cargo/config", - r#" - [registry] - credential-process = "false" - - [registries.alternative] - token = "alternative-sekrit" - "#, - ); - p.cargo("publish --no-verify --registry alternative -Z credential-process") - .masquerade_as_nightly_cargo(&["credential-process"]) - .with_stderr( - "\ -[UPDATING] [..] -[PACKAGING] foo v0.1.0 [..] -[PACKAGED] [..] -[UPLOADING] foo v0.1.0 [..] -[UPLOADED] foo v0.1.0 [..] -note: Waiting [..] -You may press ctrl-c [..] -[PUBLISHED] foo v0.1.0 [..] -", - ) - .run(); -} - /// Setup for a test that will issue a command that needs to fetch a token. /// /// This does the following: @@ -158,29 +83,14 @@ fn get_token_test() -> (Project, TestRegistry) { )) .alternative() .http_api() + .http_index() + .auth_required() .build(); - // The credential process to use. - let cred_proj = project() - .at("cred_proj") - .file("Cargo.toml", &basic_manifest("test-cred", "1.0.0")) - .file( - "src/main.rs", - r#" - use std::fs::File; - use std::io::Write; - fn main() { - let mut f = File::options() - .write(true) - .create(true) - .append(true) - .open("runs.log") - .unwrap(); - write!(f, "+"); - println!("sekrit"); - } "#, - ) - .build(); - cred_proj.cargo("build").run(); + + let provider = build_provider( + "test-cred", + r#"{"Ok":{"kind":"get","token":"sekrit","cache":"session","operation_independent":false}}"#, + ); let p = project() .file( @@ -189,10 +99,9 @@ fn get_token_test() -> (Project, TestRegistry) { r#" [registries.alternative] index = "{}" - credential-process = ["{}"] + credential-provider = ["{provider}"] "#, server.index_url(), - toml_bin(&cred_proj, "test-cred") ), ) .file( @@ -202,7 +111,6 @@ fn get_token_test() -> (Project, TestRegistry) { name = "foo" version = "0.1.0" description = "foo" - authors = [] license = "MIT" homepage = "https://example.com/" "#, @@ -217,24 +125,22 @@ fn publish() { // Checks that credential-process is used for `cargo publish`. let (p, _t) = get_token_test(); - p.cargo("publish --no-verify --registry alternative -Z credential-process") + p.cargo("publish --no-verify --registry alternative -Z credential-process -Z registry-auth") .masquerade_as_nightly_cargo(&["credential-process"]) .with_stderr( - "\ -[UPDATING] [..] + r#"[UPDATING] [..] +{"v":1,"registry":{"index-url":"[..]","name":"alternative","headers":[..]},"kind":"get","operation":"read","args":[]} [PACKAGING] foo v0.1.0 [..] [PACKAGED] [..] +{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"publish","name":"foo","vers":"0.1.0","cksum":"[..]","args":[]} [UPLOADING] foo v0.1.0 [..] [UPLOADED] foo v0.1.0 [..] note: Waiting [..] You may press ctrl-c [..] [PUBLISHED] foo v0.1.0 [..] -", +"#, ) .run(); - - let calls = read_to_string(p.root().join("runs.log")).unwrap().len(); - assert_eq!(calls, 1); } #[cargo_test] @@ -242,15 +148,8 @@ fn basic_unsupported() { // Non-action commands don't support login/logout. let registry = registry::RegistryBuilder::new() .no_configure_token() + .credential_provider(&["cargo:token-from-stdout", "false"]) .build(); - cargo_util::paths::append( - &paths::home().join(".cargo/config"), - br#" - [registry] - credential-process = "false" - "#, - ) - .unwrap(); cargo_process("login -Z credential-process abcdefg") .replace_crates_io(registry.index_url()) @@ -259,9 +158,10 @@ fn basic_unsupported() { .with_stderr( "\ [UPDATING] crates.io index -[ERROR] credential process `false` cannot be used to log in, \ -the credential-process configuration value must pass the \ -`{action}` argument in the config to support this command +[ERROR] credential provider `cargo:token-from-stdout false` failed action `login` + +Caused by: + requested operation not supported ", ) .run(); @@ -272,9 +172,10 @@ the credential-process configuration value must pass the \ .with_status(101) .with_stderr( "\ -[ERROR] credential process `false` cannot be used to log out, \ -the credential-process configuration value must pass the \ -`{action}` argument in the config to support this command +[ERROR] credential provider `cargo:token-from-stdout false` failed action `logout` + +Caused by: + requested operation not supported ", ) .run(); @@ -282,222 +183,475 @@ the credential-process configuration value must pass the \ #[cargo_test] fn login() { + let registry = registry::RegistryBuilder::new() + .no_configure_token() + .credential_provider(&[ + &build_provider("test-cred", r#"{"Ok": {"kind": "login"}}"#), + "cfg1", + "--cfg2", + ]) + .build(); + + cargo_process("login -Z credential-process abcdefg -- cmd3 --cmd4") + .masquerade_as_nightly_cargo(&["credential-process"]) + .replace_crates_io(registry.index_url()) + .with_stderr( + r#"[UPDATING] [..] +{"v":1,"registry":{"index-url":"https://github.com/rust-lang/crates.io-index","name":"crates-io"},"kind":"login","token":"abcdefg","login-url":"[..]","args":["cfg1","--cfg2","cmd3","--cmd4"]} +"#, + ) + .run(); +} + +#[cargo_test] +fn logout() { let server = registry::RegistryBuilder::new() .no_configure_token() + .credential_provider(&[&build_provider( + "test-cred", + r#"{"Ok": {"kind": "logout"}}"#, + )]) .build(); - // The credential process to use. + + cargo_process("logout -Z credential-process") + .masquerade_as_nightly_cargo(&["credential-process"]) + .replace_crates_io(server.index_url()) + .with_stderr( + r#"{"v":1,"registry":{"index-url":"https://github.com/rust-lang/crates.io-index","name":"crates-io"},"kind":"logout","args":[]} +"#, + ) + .run(); +} + +#[cargo_test] +fn yank() { + let (p, _t) = get_token_test(); + + p.cargo("yank --version 0.1.0 --registry alternative -Zcredential-process -Zregistry-auth") + .masquerade_as_nightly_cargo(&["credential-process"]) + .with_stderr( + r#"[UPDATING] [..] +{"v":1,"registry":{"index-url":"[..]","name":"alternative","headers":[..]},"kind":"get","operation":"read","args":[]} +{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"yank","name":"foo","vers":"0.1.0","args":[]} +[YANK] foo@0.1.0 +"#, + ) + .run(); +} + +#[cargo_test] +fn owner() { + let (p, _t) = get_token_test(); + + p.cargo("owner --add username --registry alternative -Zcredential-process -Zregistry-auth") + .masquerade_as_nightly_cargo(&["credential-process"]) + .with_stderr( + r#"[UPDATING] [..] +{"v":1,"registry":{"index-url":"[..]","name":"alternative","headers":[..]},"kind":"get","operation":"read","args":[]} +{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"owners","name":"foo","args":[]} +[OWNER] completed! +"#, + ) + .run(); +} + +#[cargo_test] +fn invalid_token_output() { + // Error when credential process does not output the expected format for a token. let cred_proj = project() .at("cred_proj") .file("Cargo.toml", &basic_manifest("test-cred", "1.0.0")) + .file("src/main.rs", r#"fn main() { print!("a\nb\n"); } "#) + .build(); + cred_proj.cargo("build").run(); + let _server = registry::RegistryBuilder::new() + .alternative() + .credential_provider(&[ + "cargo:token-from-stdout", + &toml_bin(&cred_proj, "test-cred"), + ]) + .no_configure_token() + .build(); + + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish --no-verify --registry alternative -Z credential-process") + .masquerade_as_nightly_cargo(&["credential-process"]) + .with_status(101) + .with_stderr( + "\ +[UPDATING] [..] +[ERROR] credential provider `[..]test-cred[EXE]` failed action `get` + +Caused by: + process `[..]` returned more than one line of output; expected a single token +", + ) + .run(); +} + +/// Builds a credential provider that echos the request from cargo to stderr, +/// and prints the `response` to stdout. +fn build_provider(name: &str, response: &str) -> String { + // The credential process to use. + let cred_proj = project() + .at(name) + .file("Cargo.toml", &basic_manifest(name, "1.0.0")) .file( "src/main.rs", - r#" - use std::io::Read; - - fn main() {{ - assert_eq!(std::env::var("CARGO_REGISTRY_NAME_OPT").unwrap(), "crates-io"); - assert_eq!(std::env::var("CARGO_REGISTRY_INDEX_URL").unwrap(), "https://github.com/rust-lang/crates.io-index"); - assert_eq!(std::env::args().skip(1).next().unwrap(), "store"); + &r####" + fn main() { + println!(r#"{{"v":[1]}}"#); + assert_eq!(std::env::args().skip(1).next().unwrap(), "--cargo-plugin"); let mut buffer = String::new(); - std::io::stdin().read_to_string(&mut buffer).unwrap(); - assert_eq!(buffer, "abcdefg\n"); - std::fs::write("token-store", buffer).unwrap(); - }} - "#, + std::io::stdin().read_line(&mut buffer).unwrap(); + eprint!("{}", buffer); + use std::io::Write; + std::io::stdout().write_all(r###"[RESPONSE]"###.as_bytes()).unwrap(); + println!(); + } "#### + .replace("[RESPONSE]", response), ) .build(); cred_proj.cargo("build").run(); + toml_bin(&cred_proj, name) +} +#[cargo_test] +fn all_not_found() { + let server = registry::RegistryBuilder::new() + .no_configure_token() + .auth_required() + .http_index() + .build(); + let not_found = build_provider("not_found", r#"{"Err": {"kind": "not-found"}}"#); cargo_util::paths::append( &paths::home().join(".cargo/config"), format!( r#" [registry] - credential-process = ["{}", "{{action}}"] + global-credential-providers = ["not_found"] + [credential-alias] + not_found = ["{not_found}"] "#, - toml_bin(&cred_proj, "test-cred") ) .as_bytes(), ) .unwrap(); - cargo_process("login -Z credential-process abcdefg") - .masquerade_as_nightly_cargo(&["credential-process"]) + cargo_process("install -v foo -Zcredential-process -Zregistry-auth") + .masquerade_as_nightly_cargo(&["credential-process", "registry-auth"]) .replace_crates_io(server.index_url()) + .with_status(101) .with_stderr( - "\ -[UPDATING] [..] -[LOGIN] token for `crates.io` saved -", + r#"[UPDATING] [..] +[CREDENTIAL] [..]not_found[..] get crates-io +{"v":1,"registry":{"index-url":"[..]","name":"crates-io","headers":[[..]"WWW-Authenticate: Cargo login_url=\"https://test-registry-login/me\""[..]]},"kind":"get","operation":"read","args":[]} +[ERROR] failed to query replaced source registry `crates-io` + +Caused by: + no token found, please run `cargo login` + or use environment variable CARGO_REGISTRY_TOKEN +"#, ) .run(); - assert_eq!( - fs::read_to_string(paths::root().join("token-store")).unwrap(), - "abcdefg\n" - ); } #[cargo_test] -fn logout() { +fn all_not_supported() { let server = registry::RegistryBuilder::new() .no_configure_token() + .auth_required() + .http_index() .build(); - // The credential process to use. - let cred_proj = project() - .at("cred_proj") - .file("Cargo.toml", &basic_manifest("test-cred", "1.0.0")) - .file( - "src/main.rs", - r#" - use std::io::Read; - - fn main() {{ - assert_eq!(std::env::var("CARGO_REGISTRY_NAME_OPT").unwrap(), "crates-io"); - assert_eq!(std::env::var("CARGO_REGISTRY_INDEX_URL").unwrap(), "https://github.com/rust-lang/crates.io-index"); - assert_eq!(std::env::args().skip(1).next().unwrap(), "erase"); - std::fs::write("token-store", "").unwrap(); - eprintln!("token for `crates-io` has been erased!") - }} - "#, - ) - .build(); - cred_proj.cargo("build").run(); - + let not_supported = + build_provider("not_supported", r#"{"Err": {"kind": "url-not-supported"}}"#); cargo_util::paths::append( &paths::home().join(".cargo/config"), format!( r#" [registry] - credential-process = ["{}", "{{action}}"] + global-credential-providers = ["not_supported"] + [credential-alias] + not_supported = ["{not_supported}"] "#, - toml_bin(&cred_proj, "test-cred") ) .as_bytes(), ) .unwrap(); - cargo_process("logout -Z credential-process") - .masquerade_as_nightly_cargo(&["credential-process"]) + cargo_process("install -v foo -Zcredential-process -Zregistry-auth") + .masquerade_as_nightly_cargo(&["credential-process", "registry-auth"]) .replace_crates_io(server.index_url()) + .with_status(101) .with_stderr( - "\ -token for `crates-io` has been erased! -[LOGOUT] token for `crates-io` has been removed from local storage -[NOTE] This does not revoke the token on the registry server. - If you need to revoke the token, visit <https://crates.io/me> \ - and follow the instructions there. -", + r#"[UPDATING] [..] +[CREDENTIAL] [..]not_supported[..] get crates-io +{"v":1,"registry":{"index-url":"[..]","name":"crates-io","headers":[[..]"WWW-Authenticate: Cargo login_url=\"https://test-registry-login/me\""[..]]},"kind":"get","operation":"read","args":[]} +[ERROR] failed to query replaced source registry `crates-io` + +Caused by: + no credential providers could handle the request +"#, ) .run(); - assert_eq!( - fs::read_to_string(paths::root().join("token-store")).unwrap(), - "" - ); } #[cargo_test] -fn yank() { - let (p, _t) = get_token_test(); +fn multiple_providers() { + let server = registry::RegistryBuilder::new() + .no_configure_token() + .build(); - p.cargo("yank --version 0.1.0 --registry alternative -Z credential-process") + // Set up two credential providers: the first will fail with "UrlNotSupported" + // and Cargo should skip it. The second should succeed. + let url_not_supported = build_provider( + "url_not_supported", + r#"{"Err": {"kind": "url-not-supported"}}"#, + ); + + let success_provider = build_provider("success_provider", r#"{"Ok": {"kind": "login"}}"#); + + cargo_util::paths::append( + &paths::home().join(".cargo/config"), + format!( + r#" + [registry] + global-credential-providers = ["success_provider", "url_not_supported"] + + [credential-alias] + success_provider = ["{success_provider}"] + url_not_supported = ["{url_not_supported}"] + "#, + ) + .as_bytes(), + ) + .unwrap(); + + cargo_process("login -Z credential-process -v abcdefg") .masquerade_as_nightly_cargo(&["credential-process"]) + .replace_crates_io(server.index_url()) .with_stderr( - "\ -[UPDATING] [..] -[YANK] foo@0.1.0 -", + r#"[UPDATING] [..] +[CREDENTIAL] [..]url_not_supported[..] login crates-io +{"v":1,"registry":{"index-url":"https://github.com/rust-lang/crates.io-index","name":"crates-io"},"kind":"login","token":"abcdefg","login-url":"[..]","args":[]} +[CREDENTIAL] [..]success_provider[..] login crates-io +{"v":1,"registry":{"index-url":"https://github.com/rust-lang/crates.io-index","name":"crates-io"},"kind":"login","token":"abcdefg","login-url":"[..]","args":[]} +"#, ) .run(); } #[cargo_test] -fn owner() { - let (p, _t) = get_token_test(); +fn both_token_and_provider() { + let server = registry::RegistryBuilder::new().build(); + cargo_util::paths::append( + &paths::home().join(".cargo/config"), + format!( + r#" + [registry] + credential-provider = ["cargo:token"] + "#, + ) + .as_bytes(), + ) + .unwrap(); - p.cargo("owner --add username --registry alternative -Z credential-process") + cargo_process("login -Z credential-process -v abcdefg") .masquerade_as_nightly_cargo(&["credential-process"]) + .replace_crates_io(server.index_url()) .with_stderr( - "\ -[UPDATING] [..] -[OWNER] completed! -", + r#"[UPDATING] [..] +[WARNING] registry `crates-io` has a token configured in [..]credentials.toml that will be ignored because a credential-provider is configured for this registry` +[CREDENTIAL] cargo:token login crates-io +[LOGIN] token for `crates-io` saved +"#, ) .run(); + let credentials = + std::fs::read_to_string(paths::home().join(".cargo/credentials.toml")).unwrap(); + assert_eq!(credentials, "[registry]\ntoken = \"abcdefg\"\n"); } #[cargo_test] -fn libexec_path() { - // cargo: prefixed names use the sysroot - let server = registry::RegistryBuilder::new() - .no_configure_token() - .build(); +fn both_asymmetric_and_token() { + let server = registry::RegistryBuilder::new().build(); cargo_util::paths::append( &paths::home().join(".cargo/config"), - br#" - [registry] - credential-process = "cargo:doesnotexist" - "#, + format!( + r#" + [registry] + token = "foo" + secret-key = "bar" + "#, + ) + .as_bytes(), ) .unwrap(); - cargo_process("login -Z credential-process abcdefg") + cargo_process("login -Z credential-process -v abcdefg") .masquerade_as_nightly_cargo(&["credential-process"]) .replace_crates_io(server.index_url()) - .with_status(101) .with_stderr( - // FIXME: Update "Caused by" error message once rust/pull/87704 is merged. - // On Windows, changing to a custom executable resolver has changed the - // error messages. - &format!("\ -[UPDATING] [..] -[ERROR] failed to execute `[..]libexec/cargo-credential-doesnotexist[EXE]` to store authentication token for registry `crates-io` - -Caused by: - [..] -"), + r#"[UPDATING] [..] +[WARNING] registry `crates-io` has a `secret_key` configured in [..]config that will be ignored because a `token` is also configured, and the `cargo:token` provider is configured with higher precedence +[CREDENTIAL] cargo:token login crates-io +[LOGIN] token for `crates-io` saved +"#, ) .run(); } #[cargo_test] -fn invalid_token_output() { - // Error when credential process does not output the expected format for a token. - let _server = registry::RegistryBuilder::new() - .alternative() +fn token_caching() { + let server = registry::RegistryBuilder::new() .no_configure_token() + .no_configure_registry() + .token(cargo_test_support::registry::Token::Plaintext( + "sekrit".to_string(), + )) + .alternative() + .http_api() + .http_index() .build(); + + // Token should not be re-used if it is expired + let expired_provider = build_provider( + "test-cred", + r#"{"Ok":{"kind":"get","token":"sekrit","cache":{"expires":0},"operation_independent":true}}"#, + ); + + // Token should not be re-used for a different operation if it is not operation_independent + let non_independent_provider = build_provider( + "test-cred", + r#"{"Ok":{"kind":"get","token":"sekrit","cache":"session","operation_independent":false}}"#, + ); + + let p = project() + .file( + ".cargo/config", + &format!( + r#" + [registries.alternative] + index = "{}" + credential-provider = ["{expired_provider}"] + "#, + server.index_url(), + ), + ) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + description = "foo" + license = "MIT" + homepage = "https://example.com/" + "#, + ) + .file("src/lib.rs", "") + .build(); + + let output = r#"[UPDATING] `alternative` index +{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"read","args":[]} +[PACKAGING] foo v0.1.0 [..] +[PACKAGED] [..] +{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"publish","name":"foo","vers":"0.1.0","cksum":"[..]","args":[]} +[UPLOADING] foo v0.1.0 [..] +[UPLOADED] foo v0.1.0 [..] +note: Waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.1.0 [..] +"#; + + // The output should contain two JSON messages from the provider in boths cases: + // The first because the credential is expired, the second because the provider + // indicated that the token was non-operation-independent. + p.cargo("publish -Z credential-process --registry alternative --no-verify") + .masquerade_as_nightly_cargo(&["credential-process"]) + .with_stderr(output) + .run(); + + p.change_file( + ".cargo/config", + &format!( + r#" + [registries.alternative] + index = "{}" + credential-provider = ["{non_independent_provider}"] + "#, + server.index_url(), + ), + ); + + p.cargo("publish -Z credential-process --registry alternative --no-verify") + .masquerade_as_nightly_cargo(&["credential-process"]) + .with_stderr(output) + .run(); +} + +#[cargo_test] +fn basic_provider() { let cred_proj = project() .at("cred_proj") .file("Cargo.toml", &basic_manifest("test-cred", "1.0.0")) - .file("src/main.rs", r#"fn main() { print!("a\nb\n"); } "#) + .file("src/main.rs", r#"fn main() { + eprintln!("CARGO={:?}", std::env::var("CARGO").ok()); + eprintln!("CARGO_REGISTRY_NAME_OPT={:?}", std::env::var("CARGO_REGISTRY_NAME_OPT").ok()); + eprintln!("CARGO_REGISTRY_INDEX_URL={:?}", std::env::var("CARGO_REGISTRY_INDEX_URL").ok()); + print!("sekrit"); + }"#) .build(); cred_proj.cargo("build").run(); - cargo_util::paths::append( - &paths::home().join(".cargo/config"), - format!( + let _server = registry::RegistryBuilder::new() + .no_configure_token() + .credential_provider(&[ + "cargo:token-from-stdout", + &toml_bin(&cred_proj, "test-cred"), + ]) + .token(cargo_test_support::registry::Token::Plaintext( + "sekrit".to_string(), + )) + .alternative() + .http_api() + .auth_required() + .build(); + + let p = project() + .file( + "Cargo.toml", r#" - [registry] - credential-process = ["{}"] + [package] + name = "foo" + version = "0.0.1" + authors = [] + [dependencies.bar] + version = "0.0.1" + registry = "alternative" "#, - toml_bin(&cred_proj, "test-cred") ) - .as_bytes(), - ) - .unwrap(); - - let p = project() - .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) - .file("src/lib.rs", "") + .file("src/main.rs", "fn main() {}") .build(); + Package::new("bar", "0.0.1").alternative(true).publish(); - p.cargo("publish --no-verify --registry alternative -Z credential-process") - .masquerade_as_nightly_cargo(&["credential-process"]) - .with_status(101) + p.cargo("check -Z credential-process -Z registry-auth") + .masquerade_as_nightly_cargo(&["credential-process", "registry-auth"]) .with_stderr( "\ -[UPDATING] [..] -[ERROR] credential process `[..]test-cred[EXE]` returned more than one line of output; expected a single token +[UPDATING] `alternative` index +CARGO=Some([..]) +CARGO_REGISTRY_NAME_OPT=Some(\"alternative\") +CARGO_REGISTRY_INDEX_URL=Some([..]) +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `alternative`) +[CHECKING] bar v0.0.1 (registry `alternative`) +[CHECKING] foo v0.0.1 ([..]) +[FINISHED] [..] ", ) .run(); |