#![allow(
clippy::unwrap_used,
clippy::expect_used,
reason = "test code: unwrap/expect on assert_cmd assertions is the expected diagnostic"
)]
mod common;
use std::path::{Path, PathBuf};
use predicates::prelude::PredicateBooleanExt;
use predicates::str::contains;
use tempfile::tempdir;
use common::aviso;
fn write(dir: &Path, name: &str, body: &str) -> PathBuf {
let path = dir.join(name);
std::fs::write(&path, body).expect("write fixture");
path
}
#[test]
fn credentials_file_is_used_when_nothing_else_is_set() {
let dir = tempdir().unwrap();
let credentials = write(
dir.path(),
"credentials.yaml",
"bearer:\n token: from-file\n",
);
aviso()
.env("AVISO_CREDENTIALS_FILE", &credentials)
.args(["config", "dump"])
.assert()
.success()
.stdout(contains("source: credentials file"));
}
#[test]
fn config_file_auth_beats_the_credentials_file() {
let dir = tempdir().unwrap();
let config = write(
dir.path(),
"config.yaml",
"auth:\n bearer_token: from-config\n",
);
let credentials = write(
dir.path(),
"credentials.yaml",
"bearer:\n token: from-file\n",
);
aviso()
.env("AVISO_CREDENTIALS_FILE", &credentials)
.arg("--config")
.arg(&config)
.args(["config", "dump"])
.assert()
.success()
.stdout(contains("source: config file"));
}
#[test]
fn environment_beats_the_config_file() {
let dir = tempdir().unwrap();
let config = write(
dir.path(),
"config.yaml",
"auth:\n bearer_token: from-config\n",
);
let credentials = write(
dir.path(),
"credentials.yaml",
"bearer:\n token: from-file\n",
);
aviso()
.env("AVISO_CREDENTIALS_FILE", &credentials)
.env("AVISO_TOKEN", "from-environment")
.arg("--config")
.arg(&config)
.args(["config", "dump"])
.assert()
.success()
.stdout(contains("source: environment"));
}
#[test]
fn the_token_flag_beats_the_environment() {
let dir = tempdir().unwrap();
let credentials = write(
dir.path(),
"credentials.yaml",
"bearer:\n token: from-file\n",
);
aviso()
.env("AVISO_CREDENTIALS_FILE", &credentials)
.env("AVISO_TOKEN", "from-environment")
.args(["--token", "from-flag", "config", "dump"])
.assert()
.success()
.stdout(contains("source: flag"));
}
#[test]
fn no_credentials_anywhere_reports_no_source() {
aviso()
.args(["config", "dump"])
.assert()
.success()
.stdout(contains("provider: <unset>"))
.stdout(contains("source: <unset>"));
}
#[test]
fn a_credentials_file_that_cannot_be_parsed_is_reported() {
let dir = tempdir().unwrap();
let credentials = write(dir.path(), "credentials.yaml", "bearer:\n toke: typo\n");
aviso()
.env("AVISO_CREDENTIALS_FILE", &credentials)
.args(["config", "dump"])
.assert()
.failure()
.stderr(contains("credentials.yaml"))
.stderr(contains("unknown field `toke`"));
}
#[test]
fn a_missing_credentials_file_is_not_an_error() {
let dir = tempdir().unwrap();
aviso()
.env("AVISO_CREDENTIALS_FILE", dir.path().join("absent.yaml"))
.args(["config", "dump"])
.assert()
.success()
.stdout(contains("source: <unset>"));
}
#[test]
fn the_json_form_reports_the_source_too() {
let dir = tempdir().unwrap();
let credentials = write(
dir.path(),
"credentials.yaml",
"bearer:\n token: from-file\n",
);
let assertion = aviso()
.env("AVISO_CREDENTIALS_FILE", &credentials)
.args(["config", "dump", "--json"])
.assert()
.success();
let stdout = String::from_utf8_lossy(&assertion.get_output().stdout);
let parsed: serde_json::Value = serde_json::from_str(&stdout).expect("valid JSON");
assert_eq!(parsed["auth"]["source"], "credentials file");
assert_eq!(parsed["auth"]["provider_set"], true);
}
#[test]
fn the_credentials_file_does_not_leak_its_token_into_the_dump() {
let dir = tempdir().unwrap();
let credentials = write(
dir.path(),
"credentials.yaml",
"bearer:\n token: super-secret-value\n",
);
aviso()
.env("AVISO_CREDENTIALS_FILE", &credentials)
.args(["config", "dump"])
.assert()
.success()
.stdout(contains("super-secret-value").not());
}
#[test]
fn an_unusable_credentials_file_does_not_break_a_command_that_has_a_token() {
let dir = tempdir().unwrap();
let credentials = write(dir.path(), "credentials.yaml", "bearer:\n toke: typo\n");
aviso()
.env("AVISO_CREDENTIALS_FILE", &credentials)
.args(["--token", "from-flag", "config", "dump"])
.assert()
.success()
.stdout(contains("source: flag"));
}
#[test]
fn an_unusable_credentials_file_does_not_break_a_command_that_has_env_credentials() {
let dir = tempdir().unwrap();
let credentials = write(dir.path(), "credentials.yaml", "bearer:\n toke: typo\n");
aviso()
.env("AVISO_CREDENTIALS_FILE", &credentials)
.env("AVISO_TOKEN", "from-environment")
.args(["config", "dump"])
.assert()
.success()
.stdout(contains("source: environment"));
}
#[test]
fn config_dump_reports_a_source_it_would_refuse_to_send() {
let dir = tempdir().unwrap();
let credentials = write(dir.path(), "credentials.yaml", "bearer:\n token: sekrit\n");
aviso()
.env("AVISO_CREDENTIALS_FILE", &credentials)
.args(["--base-url", "http://remote.example.org", "config", "dump"])
.assert()
.success()
.stdout(contains("source: credentials file"));
}
#[test]
fn a_network_command_refuses_a_discovered_credential_for_a_plaintext_address() {
let dir = tempdir().unwrap();
let credentials = write(dir.path(), "credentials.yaml", "bearer:\n token: sekrit\n");
aviso()
.env("AVISO_CREDENTIALS_FILE", &credentials)
.args([
"--base-url",
"http://user:pw@remote.example.org",
"schema",
"list",
])
.assert()
.failure()
.stderr(contains("not https and not a loopback address"))
.stderr(contains("pw@").not())
.stderr(contains("sekrit").not());
}
#[cfg(unix)]
#[test]
fn a_dangling_config_symlink_is_an_error_rather_than_an_absent_file() {
let dir = tempdir().unwrap();
let link = dir.path().join("config.yaml");
std::os::unix::fs::symlink(dir.path().join("target-does-not-exist.yaml"), &link).unwrap();
aviso()
.arg("--config")
.arg(&link)
.args(["config", "dump"])
.assert()
.failure()
.stderr(contains("config.yaml"));
}
#[cfg(unix)]
#[test]
fn a_dangling_config_symlink_is_reported_even_when_a_flag_supplies_the_credential() {
let dir = tempdir().unwrap();
let link = dir.path().join("config.yaml");
std::os::unix::fs::symlink(dir.path().join("target-does-not-exist.yaml"), &link).unwrap();
aviso()
.arg("--config")
.arg(&link)
.args(["--token", "from-flag", "config", "dump"])
.assert()
.failure()
.stderr(contains("config.yaml"));
}
#[test]
fn completions_work_even_when_every_configuration_source_is_broken() {
let dir = tempdir().unwrap();
let config = write(dir.path(), "config.yaml", "not: [valid yaml\n");
let credentials = write(dir.path(), "credentials.yaml", "bearer:\n toke: typo\n");
aviso()
.env("AVISO_CREDENTIALS_FILE", &credentials)
.arg("--config")
.arg(&config)
.args(["completions", "bash"])
.assert()
.success()
.stdout(contains("_aviso"));
}