use crate::{config::Config, format};
const TOKEN_PREFIX_LENGTH: usize = 4;
pub fn maybe_print(config: &Config, text: &str) {
if config.verbose.unwrap_or_default() || config.args.verbose {
print(text);
}
}
pub fn maybe_print_redacted_config(config: &Config) {
if config.verbose.unwrap_or_default() || config.args.verbose {
let token = config.token.as_ref().map(|token| redact_token(token));
let mut redacted_config = config.clone();
redacted_config.token = token;
print(&format!("{redacted_config:#?}"));
}
}
fn redact_token(token: &str) -> String {
let visible: String = token.chars().take(TOKEN_PREFIX_LENGTH).collect();
let redacted_length = token.chars().count().saturating_sub(TOKEN_PREFIX_LENGTH);
format!("{visible}{}", "x".repeat(redacted_length))
}
pub fn print(text: &str) {
let text = format!("=== DEBUG ===\n{text}\n===");
let text = format::debug_string(&text);
println!("{text}");
}
#[cfg(test)]
mod tests {
use super::*;
use crate::config::Config;
use std::io::Read;
#[test]
fn redact_token_keeps_first_four_chars() {
let redacted = redact_token("abcd1234");
assert_eq!(redacted, "abcdxxxx");
}
#[test]
fn redact_token_handles_short_tokens() {
let redacted = redact_token("abc");
assert_eq!(redacted, "abc");
}
#[test]
fn maybe_print_redacted_config_with_token_does_not_panic() {
let mut config = Config::default_test();
config.verbose = Some(true);
config.token = Some("abcd1234".to_string());
maybe_print_redacted_config(&config);
}
#[test]
fn buffer_redirect_tests_cannot_run_in_parallel() {
{
let mut config = Config::default_test();
config.verbose = None;
config.args.verbose = false;
let mut buf = gag::BufferRedirect::stdout().expect("should buffer stdout");
maybe_print(&config, "should not appear");
let mut output = String::new();
buf.read_to_string(&mut output)
.expect("output should be readable");
assert!(output.is_empty());
}
{
let mut config = Config::default_test();
config.verbose = Some(true);
config.args.verbose = false;
let mut buf = gag::BufferRedirect::stdout().expect("should buffer stdout");
maybe_print(&config, "should appear");
let mut output = String::new();
buf.read_to_string(&mut output)
.expect("output should be readable");
assert!(output.contains("should appear"));
}
{
let mut config = Config::default_test();
config.verbose = None;
config.args.verbose = true;
let mut buf = gag::BufferRedirect::stdout().expect("should buffer stdout");
maybe_print(&config, "should appear");
let mut output = String::new();
buf.read_to_string(&mut output)
.expect("output should be readable");
assert!(output.contains("should appear"));
}
{
let mut config = Config::default_test();
config.verbose = None;
config.args.verbose = false;
config.token = Some("abcd1234".to_string());
let mut buf = gag::BufferRedirect::stdout().expect("should buffer stdout");
maybe_print_redacted_config(&config);
let mut output = String::new();
buf.read_to_string(&mut output)
.expect("output should be readable");
assert!(output.is_empty());
}
{
let mut config = Config::default_test();
config.verbose = Some(true);
config.args.verbose = false;
config.token = Some("abcd1234".to_string());
let mut buf = gag::BufferRedirect::stdout().expect("should buffer stdout");
maybe_print_redacted_config(&config);
let mut output = String::new();
buf.read_to_string(&mut output)
.expect("output should be readable");
assert!(output.contains("abcdxxxx"));
}
}
}