use std::fs::{self, File}; use std::io::prelude::*; use cargo::core::Shell; use cargo::util::config::Config; use support::cargo_process; use support::install::cargo_home; use support::registry::registry; use toml; const TOKEN: &str = "test-token"; const ORIGINAL_TOKEN: &str = "api-token"; const CONFIG_FILE: &str = r#" [registry] token = "api-token" [registries.test-reg] index = "http://dummy_index/" "#; fn setup_old_credentials() { let config = cargo_home().join("config"); t!(fs::create_dir_all(config.parent().unwrap())); t!(t!(File::create(&config)).write_all(CONFIG_FILE.as_bytes())); } fn setup_new_credentials() { let config = cargo_home().join("credentials"); t!(fs::create_dir_all(config.parent().unwrap())); t!(t!(File::create(&config)) .write_all(format!(r#"token = "{token}""#, token = ORIGINAL_TOKEN).as_bytes())); } fn check_token(expected_token: &str, registry: Option<&str>) -> bool { let credentials = cargo_home().join("credentials"); assert!(credentials.is_file()); let mut contents = String::new(); File::open(&credentials) .unwrap() .read_to_string(&mut contents) .unwrap(); let toml: toml::Value = contents.parse().unwrap(); let token = match (registry, toml) { // A registry has been provided, so check that the token exists in a // table for the registry. (Some(registry), toml::Value::Table(table)) => table .get("registries") .and_then(|registries_table| registries_table.get(registry)) .and_then(|registry_table| match registry_table.get("token") { Some(&toml::Value::String(ref token)) => Some(token.as_str().to_string()), _ => None, }), // There is no registry provided, so check the global token instead. (None, toml::Value::Table(table)) => table .get("registry") .and_then(|registry_table| registry_table.get("token")) .and_then(|v| match v { toml::Value::String(ref token) => Some(token.as_str().to_string()), _ => None, }), _ => None, }; if let Some(token_val) = token { token_val == expected_token } else { false } } #[test] fn login_with_old_credentials() { setup_old_credentials(); cargo_process("login --host") .arg(registry().to_string()) .arg(TOKEN) .run(); let config = cargo_home().join("config"); assert!(config.is_file()); let mut contents = String::new(); File::open(&config) .unwrap() .read_to_string(&mut contents) .unwrap(); assert_eq!(CONFIG_FILE, contents); // Ensure that we get the new token for the registry assert!(check_token(TOKEN, None)); } #[test] fn login_with_new_credentials() { setup_new_credentials(); cargo_process("login --host") .arg(registry().to_string()) .arg(TOKEN) .run(); let config = cargo_home().join("config"); assert!(!config.is_file()); // Ensure that we get the new token for the registry assert!(check_token(TOKEN, None)); } #[test] fn login_with_old_and_new_credentials() { setup_new_credentials(); login_with_old_credentials(); } #[test] fn login_without_credentials() { cargo_process("login --host") .arg(registry().to_string()) .arg(TOKEN) .run(); let config = cargo_home().join("config"); assert!(!config.is_file()); // Ensure that we get the new token for the registry assert!(check_token(TOKEN, None)); } #[test] fn new_credentials_is_used_instead_old() { setup_old_credentials(); setup_new_credentials(); cargo_process("login --host") .arg(registry().to_string()) .arg(TOKEN) .run(); let config = Config::new(Shell::new(), cargo_home(), cargo_home()); let token = config.get_string("registry.token").unwrap().map(|p| p.val); assert_eq!(token.unwrap(), TOKEN); } #[test] fn registry_credentials() { setup_old_credentials(); setup_new_credentials(); let reg = "test-reg"; cargo_process("login --registry") .arg(reg) .arg(TOKEN) .arg("-Zunstable-options") .masquerade_as_nightly_cargo() .run(); // Ensure that we have not updated the default token assert!(check_token(ORIGINAL_TOKEN, None)); // Also ensure that we get the new token for the registry assert!(check_token(TOKEN, Some(reg))); }