pdbethke/warp, scoped to crates/secret_redaction, at 325d4d4701: the project's own tests caught 0 of 26 planted faults, 26 got through, and corral proved 26 of those missing tests by writing a test and running it.
#[cfg(test)]
mod corral_tests {
use super::super::*;
use regex::Regex;
#[test]
fn test_corral_first_user_pattern_retains_user_level_at_enterprise_boundary() {
for enterprise_count in 0..=1 {
let enterprise = Regex::new("ENTERPRISE").unwrap();
let user = Regex::new("USER").unwrap();
let patterns = if enterprise_count == 0 {
vec![user.as_str()]
} else {
vec![enterprise.as_str(), user.as_str()]
};
let secrets_regex = SecretsRegex {
regex: regex_automata::meta::Regex::new_many(&patterns).unwrap(),
dfas: regex_dfas::RegexDFAs::new_many(&patterns, false, true).unwrap(),
level_metadata: RegexLevelMetadata {
enterprise_count,
user_count: 1,
},
};
let matches =
find_secrets_in_text_with_levels_using_regex("!USER!", &secrets_regex);
assert_eq!(matches.len(), 1);
assert_eq!(matches[0].0.byte_range, 1..5);
assert_eq!(matches[0].0.char_range, 1..5);
assert_eq!(matches[0].1, SecretLevel::User);
if enterprise_count == 1 {
let enterprise_matches =
find_secrets_in_text_with_levels_using_regex("!ENTERPRISE!", &secrets_regex);
assert_eq!(enterprise_matches.len(), 1);
assert_eq!(enterprise_matches[0].0.byte_range, 1..11);
assert_eq!(enterprise_matches[0].1, SecretLevel::Enterprise);
}
}
}
#[test]
fn corral_secret_pattern_source_levels_are_not_reversed() {
let enterprise = Regex::new("enterprise-secret").expect("Test regex did not compile");
let user = Regex::new("user-secret").expect("Test regex did not compile");
let patterns = [enterprise.as_str(), user.as_str()];
let secrets_regex = SecretsRegex {
regex: regex_automata::meta::Regex::new_many(&patterns)
.expect("Test regex did not compile"),
dfas: regex_dfas::RegexDFAs::new_many(&patterns, false, true)
.expect("Test regex DFA did not compile"),
level_metadata: RegexLevelMetadata {
enterprise_count: 1,
user_count: 1,
},
};
let matches = find_secrets_in_text_with_levels_using_regex(
"enterprise-secret | user-secret",
&secrets_regex,
);
assert_eq!(matches.len(), 2);
assert_eq!(matches[0].0.byte_range, 0..17);
assert_eq!(matches[0].0.char_range, 0..17);
assert_eq!(matches[0].1, SecretLevel::Enterprise);
assert_eq!(matches[1].0.byte_range, 20..31);
assert_eq!(matches[1].0.char_range, 20..31);
assert_eq!(matches[1].1, SecretLevel::User);
}
#[test]
fn corral_secret_match_ranges_include_the_final_byte_and_character() {
let enterprise = Regex::new("企").expect("Test regex did not compile");
let user = Regex::new("user").expect("Test regex did not compile");
let patterns = [enterprise.as_str(), user.as_str()];
let secrets_regex = SecretsRegex {
regex: regex_automata::meta::Regex::new_many(&patterns)
.expect("Test regex did not compile"),
dfas: RegexDFAs::new_many(&patterns, false, true)
.expect("Test regex DFA did not compile"),
level_metadata: RegexLevelMetadata {
enterprise_count: 1,
user_count: 1,
},
};
let text = "é:user:企!";
let matches = find_secrets_in_text_with_levels_using_regex(text, &secrets_regex);
assert_eq!(matches.len(), 2);
assert_eq!(matches[0].0.byte_range, 3..7);
assert_eq!(matches[0].0.char_range, 2..6);
assert_eq!(matches[0].1, SecretLevel::User);
assert_eq!(matches[1].0.byte_range, 8..11);
assert_eq!(matches[1].0.char_range, 7..8);
assert_eq!(matches[1].1, SecretLevel::Enterprise);
}
#[test]
fn corral_secret_matches_preserve_first_byte_and_source_level() {
let enterprise = Regex::new("ENTER").expect("Test regex did not compile");
let user = Regex::new("USER").expect("Test regex did not compile");
let patterns = [enterprise.as_str(), user.as_str()];
let secrets_regex = SecretsRegex {
regex: regex_automata::meta::Regex::new_many(&patterns)
.expect("Test regex did not compile"),
dfas: regex_dfas::RegexDFAs::new_many(&patterns, false, true)
.expect("Test regex DFA did not compile"),
level_metadata: RegexLevelMetadata {
enterprise_count: 1,
user_count: 1,
},
};
let text = "é ENTER / USER!";
let matches = find_secrets_in_text_with_levels_using_regex(text, &secrets_regex);
assert_eq!(matches.len(), 2);
assert_eq!(matches[0].0.byte_range, 3..8);
assert_eq!(matches[0].0.char_range, 2..7);
assert_eq!(matches[0].1, SecretLevel::Enterprise);
assert_eq!(&text[matches[0].0.byte_range.clone()], "ENTER");
assert_eq!(matches[1].0.byte_range, 11..15);
assert_eq!(matches[1].0.char_range, 10..14);
assert_eq!(matches[1].1, SecretLevel::User);
assert_eq!(&text[matches[1].0.byte_range.clone()], "USER");
}
#[test]
fn corral_last_pattern_match_preserves_user_level_and_unicode_offsets() {
let enterprise = Regex::new("ORG_SECRET").expect("Test regex did not compile");
let user = Regex::new("秘密").expect("Test regex did not compile");
let patterns = [enterprise.as_str(), user.as_str()];
let secrets_regex = SecretsRegex {
regex: regex_automata::meta::Regex::new_many(&patterns)
.expect("Test regex did not compile"),
dfas: regex_dfas::RegexDFAs::new_many(&patterns, false, true)
.expect("Test regex DFA did not compile"),
level_metadata: RegexLevelMetadata {
enterprise_count: 1,
user_count: 1,
},
};
let matches =
find_secrets_in_text_with_levels_using_regex("é ORG_SECRET | 秘密!", &secrets_regex);
assert_eq!(matches.len(), 2);
assert_eq!(matches[0].0.char_range, 2..12);
assert_eq!(matches[0].0.byte_range, 3..13);
assert_eq!(matches[0].1, SecretLevel::Enterprise);
assert_eq!(matches[1].0.char_range, 15..17);
assert_eq!(matches[1].0.byte_range, 16..22);
assert_eq!(matches[1].1, SecretLevel::User);
}
#[test]
fn corral_merge_preserves_enterprise_priority_in_both_orders() {
for (first_level, second_level) in [
(SecretLevel::User, SecretLevel::Enterprise),
(SecretLevel::Enterprise, SecretLevel::User),
] {
for second_start in [2, 4] {
let merged = merge_sorted_ranges_with_levels(vec![
(
StringRange {
char_range: 0..4,
byte_range: 0..4,
},
first_level,
),
(
StringRange {
char_range: second_start..6,
byte_range: second_start..6,
},
second_level,
),
(
StringRange {
char_range: 8..10,
byte_range: 8..10,
},
SecretLevel::User,
),
]);
assert_eq!(merged.len(), 2);
assert_eq!(merged[0].0.char_range, 0..6);
assert_eq!(merged[0].0.byte_range, 0..6);
assert_eq!(merged[0].1, SecretLevel::Enterprise);
assert_eq!(merged[1].0.char_range, 8..10);
assert_eq!(merged[1].0.byte_range, 8..10);
assert_eq!(merged[1].1, SecretLevel::User);
}
}
}
#[test]
fn corral_adjacent_secret_ranges_merge_with_enterprise_priority() {
for (first_level, second_level) in [
(SecretLevel::User, SecretLevel::Enterprise),
(SecretLevel::Enterprise, SecretLevel::User),
] {
let merged = merge_sorted_ranges_with_levels(vec![
(
StringRange {
char_range: 1..3,
byte_range: 2..6,
},
first_level,
),
(
StringRange {
char_range: 3..4,
byte_range: 6..9,
},
second_level,
),
(
StringRange {
char_range: 5..6,
byte_range: 10..11,
},
SecretLevel::User,
),
]);
assert_eq!(merged.len(), 2);
assert_eq!(merged[0].0.char_range, 1..4);
assert_eq!(merged[0].0.byte_range, 2..9);
assert_eq!(merged[0].1, SecretLevel::Enterprise);
assert_eq!(merged[1].0.char_range, 5..6);
assert_eq!(merged[1].0.byte_range, 10..11);
assert_eq!(merged[1].1, SecretLevel::User);
}
}
#[test]
fn corral_merge_preserves_final_disjoint_group_and_its_highest_priority() {
let merged = merge_sorted_ranges_with_levels(vec![
(
StringRange {
char_range: 1..3,
byte_range: 2..6,
},
SecretLevel::User,
),
(
StringRange {
char_range: 5..8,
byte_range: 10..16,
},
SecretLevel::User,
),
(
StringRange {
char_range: 7..9,
byte_range: 14..18,
},
SecretLevel::Enterprise,
),
(
StringRange {
char_range: 9..11,
byte_range: 18..22,
},
SecretLevel::User,
),
]);
assert_eq!(merged.len(), 2);
assert_eq!(merged[0].0.char_range, 1..3);
assert_eq!(merged[0].0.byte_range, 2..6);
assert_eq!(merged[0].1, SecretLevel::User);
assert_eq!(merged[1].0.char_range, 5..11);
assert_eq!(merged[1].0.byte_range, 10..22);
assert_eq!(merged[1].1, SecretLevel::Enterprise);
}
#[test]
fn corral_disjoint_user_range_does_not_inherit_enterprise_level() {
let merged = merge_sorted_ranges_with_levels(vec![
(
StringRange {
char_range: 1..3,
byte_range: 1..5,
},
SecretLevel::Enterprise,
),
(
StringRange {
char_range: 4..6,
byte_range: 6..10,
},
SecretLevel::User,
),
]);
assert_eq!(merged.len(), 2);
assert_eq!(merged[0].0.char_range, 1..3);
assert_eq!(merged[0].0.byte_range, 1..5);
assert_eq!(merged[0].1, SecretLevel::Enterprise);
assert_eq!(merged[1].0.char_range, 4..6);
assert_eq!(merged[1].0.byte_range, 6..10);
assert_eq!(merged[1].1, SecretLevel::User);
}
#[test]
fn test_corral_merge_preserves_full_union_and_enterprise_priority() {
for second_start in [2, 4] {
let merged = merge_sorted_ranges_with_levels(vec![
(
StringRange {
char_range: 1..4,
byte_range: 2..8,
},
SecretLevel::Enterprise,
),
(
StringRange {
char_range: second_start..6,
byte_range: (second_start * 2)..12,
},
SecretLevel::User,
),
]);
assert_eq!(merged.len(), 1);
assert_eq!(merged[0].0.char_range, 1..6);
assert_eq!(merged[0].0.byte_range, 2..12);
assert_eq!(merged[0].1, SecretLevel::Enterprise);
}
}
#[test]
fn test_corral_merge_contained_enterprise_preserves_outer_user_range() {
let merged = merge_sorted_ranges_with_levels(vec![
(
StringRange {
char_range: 1..8,
byte_range: 2..16,
},
SecretLevel::User,
),
(
StringRange {
char_range: 3..5,
byte_range: 6..10,
},
SecretLevel::Enterprise,
),
]);
assert_eq!(merged.len(), 1);
assert_eq!(merged[0].0.char_range, 1..8);
assert_eq!(merged[0].0.byte_range, 2..16);
assert_eq!(merged[0].1, SecretLevel::Enterprise);
}
#[test]
fn corral_enterprise_and_user_patterns_retain_their_source_levels() {
let enterprise = Regex::new("corral_enterprise_secret").unwrap();
let user = Regex::new("corral_user_secret").unwrap();
set_user_and_enterprise_secret_regexes([&user], [&enterprise]);
let compiled = SECRETS_REGEX.lock().clone();
for (text, expected_level) in [
("corral_enterprise_secret", SecretLevel::Enterprise),
("corral_user_secret", SecretLevel::User),
] {
let matches = find_secrets_in_text_with_levels_using_regex(text, &compiled);
assert_eq!(matches.len(), 1);
assert_eq!(matches[0].0.byte_range, 0..text.len());
assert_eq!(matches[0].0.char_range, 0..text.chars().count());
assert_eq!(matches[0].1, expected_level);
}
}
#[test]
fn test_corral_unequal_pattern_counts_preserve_secret_sources() {
let enterprise = [
Regex::new("corral_enterprise_alpha").unwrap(),
Regex::new("corral_enterprise_beta").unwrap(),
];
let user = [Regex::new("corral_user_gamma").unwrap()];
let previous = SECRETS_REGEX.lock().clone();
set_user_and_enterprise_secret_regexes(user.iter(), enterprise.iter());
let configured = {
let mut current = SECRETS_REGEX.lock();
let configured = current.clone();
*current = previous;
configured
};
assert_eq!(configured.level_metadata.enterprise_count, 2);
assert_eq!(configured.level_metadata.user_count, 1);
for (text, expected_level) in [
("corral_enterprise_alpha", SecretLevel::Enterprise),
("corral_enterprise_beta", SecretLevel::Enterprise),
("corral_user_gamma", SecretLevel::User),
] {
let matches = find_secrets_in_text_with_levels_using_regex(text, &configured);
assert_eq!(matches.len(), 1);
assert_eq!(matches[0].0.byte_range, 0..text.len());
assert_eq!(matches[0].0.char_range, 0..text.chars().count());
assert_eq!(matches[0].1, expected_level);
}
}
#[test]
fn corral_unique_user_patterns_survive_enterprise_deduplication() {
let enterprise = Regex::new("corral_enterprise_secret").unwrap();
let user = Regex::new("corral_user_secret").unwrap();
set_user_and_enterprise_secret_regexes(
[&enterprise, &user, &user],
[&enterprise],
);
let compiled = SECRETS_REGEX.lock().clone();
assert_eq!(compiled.level_metadata.enterprise_count, 1);
assert_eq!(compiled.level_metadata.user_count, 1);
let text = "corral_user_secret | corral_enterprise_secret";
let matches = find_secrets_in_text_with_levels_using_regex(text, &compiled);
assert_eq!(matches.len(), 2);
assert_eq!(matches[0].0.byte_range, 0..18);
assert_eq!(matches[0].0.char_range, 0..18);
assert_eq!(matches[0].1, SecretLevel::User);
assert_eq!(matches[1].0.byte_range, 21..45);
assert_eq!(matches[1].0.char_range, 21..45);
assert_eq!(matches[1].1, SecretLevel::Enterprise);
}
#[test]
fn test_corral_enterprise_boundary_preserves_pattern_levels() {
let enterprise_patterns = [
Regex::new("corral_enterprise_first").unwrap(),
Regex::new("corral_enterprise_last").unwrap(),
];
let user_patterns = [Regex::new("corral_user_first").unwrap()];
set_user_and_enterprise_secret_regexes(user_patterns.iter(), enterprise_patterns.iter());
let compiled = SECRETS_REGEX.lock().clone();
for (text, expected_level) in [
("corral_enterprise_first", SecretLevel::Enterprise),
("corral_enterprise_last", SecretLevel::Enterprise),
("corral_user_first", SecretLevel::User),
] {
let matches = find_secrets_in_text_with_levels_using_regex(text, &compiled);
assert_eq!(matches.len(), 1, "Expected one match for {text}");
assert_eq!(matches[0].0.byte_range, 0..text.len());
assert_eq!(matches[0].0.char_range, 0..text.chars().count());
assert_eq!(matches[0].1, expected_level, "Incorrect level for {text}");
}
}
#[test]
fn corral_first_user_pattern_is_retained_after_enterprise_patterns() {
let enterprise = Regex::new("ENTERPRISE").expect("Test regex did not compile");
let first_user = Regex::new("FIRST_USER").expect("Test regex did not compile");
let second_user = Regex::new("SECOND_USER").expect("Test regex did not compile");
let previous = SECRETS_REGEX.lock().clone();
set_user_and_enterprise_secret_regexes(
[&first_user, &second_user],
[&enterprise],
);
let configured = {
let mut current = SECRETS_REGEX.lock();
std::mem::replace(&mut *current, previous)
};
for (text, expected_level) in [
("ENTERPRISE", SecretLevel::Enterprise),
("FIRST_USER", SecretLevel::User),
("SECOND_USER", SecretLevel::User),
] {
let matches = find_secrets_in_text_with_levels_using_regex(text, &configured);
assert_eq!(matches.len(), 1, "Pattern was omitted for {text}");
assert_eq!(matches[0].0.byte_range, 0..text.len());
assert_eq!(matches[0].0.char_range, 0..text.chars().count());
assert_eq!(matches[0].1, expected_level);
}
}
#[test]
fn corral_enterprise_priority_survives_overlapping_and_adjacent_user_ranges() {
for (first_level, second_level) in [
(SecretLevel::User, SecretLevel::Enterprise),
(SecretLevel::Enterprise, SecretLevel::User),
] {
for second_start in [2, 4] {
let merged = merge_sorted_ranges_with_levels(vec![
(
StringRange {
char_range: 0..4,
byte_range: 0..4,
},
first_level,
),
(
StringRange {
char_range: second_start..6,
byte_range: second_start..6,
},
second_level,
),
]);
assert_eq!(merged.len(), 1);
assert_eq!(merged[0].0.char_range, 0..6);
assert_eq!(merged[0].0.byte_range, 0..6);
assert_eq!(merged[0].1, SecretLevel::Enterprise);
}
}
}
#[test]
fn corral_enterprise_priority_survives_overlap_and_adjacency() {
let merged = merge_sorted_ranges_with_levels(vec![
(
StringRange {
char_range: 1..5,
byte_range: 2..10,
},
SecretLevel::User,
),
(
StringRange {
char_range: 3..7,
byte_range: 6..14,
},
SecretLevel::Enterprise,
),
(
StringRange {
char_range: 7..9,
byte_range: 14..18,
},
SecretLevel::User,
),
]);
assert_eq!(merged.len(), 1);
assert_eq!(merged[0].0.char_range, 1..9);
assert_eq!(merged[0].0.byte_range, 2..18);
assert_eq!(merged[0].1, SecretLevel::Enterprise);
assert!(SecretLevel::Enterprise.priority() > SecretLevel::User.priority());
}
#[test]
fn corral_redaction_preserves_every_secret_byte_and_surrounding_text() {
const CHILD_ENV: &str = "CORRAL_REDACTION_BYTE_LENGTH_CHILD_S4_M1";
// Isolate the process-wide regex configuration from concurrently running tests.
if std::env::var_os(CHILD_ENV).is_none() {
let output = std::process::Command::new(
std::env::current_exe().expect("test executable should be available"),
)
.arg("corral_redaction_preserves_every_secret_byte_and_surrounding_text")
.arg("--test-threads=1")
.env(CHILD_ENV, "1")
.output()
.expect("isolated redaction test should run");
assert!(
output.status.success(),
"isolated redaction test failed:\n{}\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr),
);
return;
}
let user_pattern = Regex::new("é|x").expect("user regex should compile");
let enterprise_pattern = Regex::new("秘密").expect("enterprise regex should compile");
set_user_and_enterprise_secret_regexes([&user_pattern], [&enterprise_pattern]);
let original = "α|é|x|秘密|ω";
let mut redacted = original.to_owned();
redact_secrets(&mut redacted);
assert_eq!(redacted.len(), original.len());
assert_eq!(redacted, "α|**|*|******|ω");
}
#[test]
fn corral_redaction_replaces_first_and_every_secret_byte_without_shifting_text() {
let user_pattern = Regex::new("SECRET").expect("Test regex did not compile");
let enterprise_pattern = Regex::new("TOKEN").expect("Test regex did not compile");
let previous = SECRETS_REGEX.lock().clone();
set_user_and_enterprise_secret_regexes([&user_pattern], [&enterprise_pattern]);
let original = "é:SECRET|TOKEN!SECRET TOKEN";
let mut redacted = original.to_owned();
redact_secrets(&mut redacted);
*SECRETS_REGEX.lock() = previous;
assert!(redacted == "é:******|*****!****** *****");
assert!(redacted.len() == original.len());
}
#[test]
fn corral_first_secret_is_preserved_and_redacted_byte_for_byte() {
const CHILD_ENV: &str = "CORRAL_FIRST_SECRET_REDACTION_CHILD";
if std::env::var_os(CHILD_ENV).is_none() {
let output = std::process::Command::new(
std::env::current_exe().expect("Test executable should be available"),
)
.arg("corral_first_secret_is_preserved_and_redacted_byte_for_byte")
.arg("--nocapture")
.env(CHILD_ENV, "1")
.output()
.expect("Isolated test should run");
assert!(
output.status.success(),
"Isolated test failed:\n{}\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
return;
}
let user_pattern = Regex::new("秘密").expect("Test regex should compile");
let enterprise_pattern = Regex::new("TOKEN").expect("Test regex should compile");
set_user_and_enterprise_secret_regexes([&user_pattern], [&enterprise_pattern]);
let original = "é[秘密]🙂[TOKEN]終";
let ranges = find_secrets_in_text(original);
assert_eq!(ranges.len(), 2);
assert_eq!(ranges[0].byte_range, 3..9);
assert_eq!(ranges[0].char_range, 2..4);
assert_eq!(ranges[1].byte_range, 15..20);
assert_eq!(ranges[1].char_range, 7..12);
let levels = find_secrets_in_text_with_levels(original);
assert_eq!(levels.len(), 2);
assert_eq!(levels[0].1, SecretLevel::User);
assert_eq!(levels[1].1, SecretLevel::Enterprise);
let mut redacted = original.to_owned();
redact_secrets(&mut redacted);
assert_eq!(redacted, "é[******]🙂[*****]終");
assert_eq!(redacted.len(), original.len());
}
#[test]
fn corral_public_secret_lookup_preserves_pattern_source_levels() {
struct CorralRestoreSecretRegex(std::sync::Arc<SecretsRegex>);
impl Drop for CorralRestoreSecretRegex {
fn drop(&mut self) {
*SECRETS_REGEX.lock() = self.0.clone();
}
}
let _restore = CorralRestoreSecretRegex(SECRETS_REGEX.lock().clone());
let enterprise = Regex::new("CORRAL_ENTERPRISE_SECRET").expect("Test regex did not compile");
let user = Regex::new("CORRAL_USER_SECRET").expect("Test regex did not compile");
set_user_and_enterprise_secret_regexes([&user], [&enterprise]);
let text = "prefix CORRAL_ENTERPRISE_SECRET | CORRAL_USER_SECRET suffix";
let matches = find_secrets_in_text_with_levels(text);
assert_eq!(matches.len(), 2);
for (index, (secret, expected_level)) in [
("CORRAL_ENTERPRISE_SECRET", SecretLevel::Enterprise),
("CORRAL_USER_SECRET", SecretLevel::User),
]
.into_iter()
.enumerate()
{
let start = text.find(secret).expect("Secret must appear in test input");
let expected_range = start..start + secret.len();
assert_eq!(matches[index].0.byte_range, expected_range);
assert_eq!(matches[index].0.char_range, expected_range);
assert_eq!(matches[index].1, expected_level);
}
}
#[test]
fn test_corral_first_secret_survives_public_scan_and_redaction() {
const CHILD_ENV: &str = "CORRAL_FIRST_SECRET_SCAN_CHILD";
if std::env::var_os(CHILD_ENV).is_none() {
let full_name = concat!(
module_path!(),
"::test_corral_first_secret_survives_public_scan_and_redaction"
);
let test_name = full_name.split_once("::").unwrap().1;
let output = std::process::Command::new(std::env::current_exe().unwrap())
.args(["--exact", test_name, "--nocapture"])
.env(CHILD_ENV, "1")
.output()
.expect("Could not run isolated secret scanning test");
assert!(
output.status.success(),
"Isolated test failed:\n{}\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
return;
}
let user = Regex::new("user秘密").unwrap();
let enterprise = Regex::new("org🔑").unwrap();
set_user_and_enterprise_secret_regexes([&user], [&enterprise]);
let original = "é user秘密 | org🔑 fin";
let found = find_secrets_in_text_with_levels(original);
assert!(found.len() == 2);
assert!(found[0].0.byte_range == (3..13));
assert!(found[0].0.char_range == (2..8));
assert!(found[0].1 == SecretLevel::User);
assert!(found[1].0.byte_range == (16..23));
assert!(found[1].0.char_range == (11..15));
assert!(found[1].1 == SecretLevel::Enterprise);
let ranges = find_secrets_in_text(original);
assert!(ranges.len() == 2);
assert!(ranges[0].byte_range == (3..13));
assert!(ranges[1].byte_range == (16..23));
let mut redacted = original.to_owned();
redact_secrets(&mut redacted);
assert!(redacted == "é ********** | ******* fin");
assert!(redacted.len() == original.len());
let singleton = find_secrets_in_text_with_levels("user秘密");
assert!(singleton.len() == 1);
assert!(singleton[0].0.byte_range == (0..10));
assert!(singleton[0].1 == SecretLevel::User);
}
#[test]
fn corral_leading_whitespace_preserves_secret_offsets_and_redaction() {
let saved_regex = SECRETS_REGEX.lock().clone();
let enterprise_pattern = Regex::new("TOKEN").expect("Test regex did not compile");
set_user_and_enterprise_secret_regexes(
std::iter::empty::<&Regex>(),
std::iter::once(&enterprise_pattern),
);
let original = " \t\nTOKEN! keep TOKEN?\n";
let detected = find_secrets_in_text_with_levels(original);
let mut redacted = original.to_owned();
redact_secrets(&mut redacted);
*SECRETS_REGEX.lock() = saved_regex;
let expected_ranges: Vec<_> = original
.match_indices("TOKEN")
.map(|(start, secret)| start..start + secret.len())
.collect();
assert_eq!(detected.len(), expected_ranges.len());
for ((range, level), expected) in detected.iter().zip(expected_ranges) {
assert_eq!(range.byte_range, expected);
assert_eq!(range.char_range, expected);
assert_eq!(*level, SecretLevel::Enterprise);
}
assert_eq!(redacted.len(), original.len());
assert_eq!(redacted, " \t\n*****! keep *****?\n");
}
#[test]
fn corral_secret_level_enterprise_classification_matches_source() {
assert!(SecretLevel::Enterprise.is_enterprise());
assert!(!SecretLevel::User.is_enterprise());
assert!(SecretLevel::User.is_user());
assert!(!SecretLevel::Enterprise.is_user());
assert!(SecretLevel::Enterprise.priority() > SecretLevel::User.priority());
}
#[test]
fn corral_detected_secret_levels_have_correct_user_classification() {
let enterprise = Regex::new("enterprise_secret").unwrap();
let user = Regex::new("user_secret").unwrap();
let patterns = [enterprise.as_str(), user.as_str()];
let secrets = SecretsRegex {
regex: regex_automata::meta::Regex::new_many(&patterns).unwrap(),
dfas: RegexDFAs::new_many(&patterns, false, true).unwrap(),
level_metadata: RegexLevelMetadata {
enterprise_count: 1,
user_count: 1,
},
};
let enterprise_matches =
find_secrets_in_text_with_levels_using_regex("enterprise_secret", &secrets);
assert_eq!(enterprise_matches.len(), 1);
assert_eq!(enterprise_matches[0].1, SecretLevel::Enterprise);
assert!(!enterprise_matches[0].1.is_user());
assert!(enterprise_matches[0].1.is_enterprise());
let user_matches =
find_secrets_in_text_with_levels_using_regex("user_secret", &secrets);
assert_eq!(user_matches.len(), 1);
assert_eq!(user_matches[0].1, SecretLevel::User);
assert!(user_matches[0].1.is_user());
assert!(!user_matches[0].1.is_enterprise());
}
}
// --- corral: separate test file (unmergeable) — s3/m3 ---
// lang: 2 authored parts each declare "corral_enterprise_priority_survives_overlapping_and_adjacent_user_ranges", which is not a test and cannot be renamed safely
#[cfg(test)]
mod corral_tests {
use super::super::*;
#[test]
fn corral_enterprise_priority_survives_overlapping_and_adjacent_user_ranges() {
for (first_level, second_level) in [
(SecretLevel::User, SecretLevel::Enterprise),
(SecretLevel::Enterprise, SecretLevel::User),
] {
for second_start in [2, 3] {
let merged = merge_sorted_ranges_with_levels(vec![
(
StringRange {
char_range: 1..3,
byte_range: 1..3,
},
first_level,
),
(
StringRange {
char_range: second_start..5,
byte_range: second_start..5,
},
second_level,
),
]);
assert_eq!(merged.len(), 1);
assert_eq!(merged[0].0.char_range, 1..5);
assert_eq!(merged[0].0.byte_range, 1..5);
assert_eq!(merged[0].1, SecretLevel::Enterprise);
}
}
}
}
A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.
s6/m1 · line 75 proven
- matches!(self, SecretLevel::Enterprise) + !matches!(self, SecretLevel::Enterprise)
s7/m1 · line 80 proven
- matches!(self, SecretLevel::User) + !matches!(self, SecretLevel::User)
s3/m1 · line 87 proven
- SecretLevel::User => 0, - SecretLevel::Enterprise => 1, + SecretLevel::User => 1, + SecretLevel::Enterprise => 0,
s3/m2 · line 87 proven
- SecretLevel::Enterprise => 1, + SecretLevel::Enterprise => 0,
s3/m3 · line 87 proven
- SecretLevel::User => 0, + SecretLevel::User => 2,
s2/m3 · line 114 proven
- .filter(|r| seen_patterns.insert(r.as_str())) + .filter(|r| !seen_patterns.insert(r.as_str()))
s2/m1 · line 118 proven
- let all_secrets = enterprise_secrets_vec - .iter() - .map(|regex| regex.as_str()) - .chain(filtered_user_secrets_vec.iter().map(|regex| regex.as_str())) + let all_secrets = filtered_user_secrets_vec + .iter() + .map(|regex| regex.as_str()) + .chain(enterprise_secrets_vec.iter().map(|regex| regex.as_str()))
s2/m5 · line 121 proven
- .chain(filtered_user_secrets_vec.iter().map(|regex| regex.as_str())) + .chain(filtered_user_secrets_vec.iter().skip(1).map(|regex| regex.as_str()))
s2/m2 · line 141 proven
- enterprise_count: enterprise_secrets_vec.len(), - user_count: filtered_user_secrets_vec.len(), + enterprise_count: filtered_user_secrets_vec.len(), + user_count: enterprise_secrets_vec.len(),
s2/m4 · line 141 proven
- enterprise_count: enterprise_secrets_vec.len(), + enterprise_count: enterprise_secrets_vec.len().saturating_sub(1),
s4/m3 · line 160 proven
+ .skip(1)
s5/m1 · line 168 proven
+ .into_iter()
+ .map(|(r, l)| {
+ (
+ r,
+ match l {
+ SecretLevel::Enterprise => SecretLevel::User,
+ _ => SecretLevel::Enterprise,
+ },
+ )
+ })
+ .collect()s5/m2 · line 168 proven
+ .into_iter() + .skip(1) + .collect()
s5/m3 · line 168 proven
- find_secrets_in_text_with_levels_using_regex(text, &secrets_regex) + find_secrets_in_text_with_levels_using_regex(text.trim_start(), &secrets_regex)
s0/m3 · line 200 proven
+ let end_byte = end_byte.saturating_sub(1).max(start_byte);
s0/m4 · line 200 proven
+ let start_byte = (start_byte + 1).min(end_byte); + let start_char = byte_to_char_index[start_byte];
s0/m5 · line 204 proven
- if pattern_id >= total_patterns {
+ if pattern_id + 1 >= total_patterns {s0/m1 · line 212 proven
- let secret_level = if pattern_id < level_metadata.enterprise_count {
+ let secret_level = if pattern_id <= level_metadata.enterprise_count {s0/m2 · line 212 proven
- SecretLevel::Enterprise
- } else {
- SecretLevel::User
+ SecretLevel::User
+ } else {
+ SecretLevel::Enterprises1/m2 · line 245 proven
- if range.char_range.start <= current_range.char_range.end {
+ if range.char_range.start < current_range.char_range.end {s1/m5 · line 246 proven
- current_range.extend_range_end(&range); + current_range = range;
s1/m1 · line 249 proven
- if level.priority() > current_level.priority() {
+ if level.priority() < current_level.priority() {s1/m4 · line 254 proven
- current_level = level;
s1/m3 · line 260 proven
- merged_ranges.push((current_range, current_level));
+ if merged_ranges.is_empty() {
+ merged_ranges.push((current_range, current_level));
+ }s4/m1 · line 275 proven
- SECRET_REDACTION_REPLACEMENT_CHARACTER.repeat(range.end.saturating_sub(range.start)); + SECRET_REDACTION_REPLACEMENT_CHARACTER.repeat(range.end.saturating_sub(range.start).saturating_sub(1));
s4/m2 · line 277 proven
- input.replace_range(range.start..range.end, &replacement); + input.replace_range((range.start + 1).min(range.end)..range.end, &replacement);