Files
codex/codex-rs/config/src/shell_environment_policy_tests.rs
T
Abhinav 7442f5f932 Add keyed shell environment policy filters (#34590)
## What changed

- Add `shell_environment_policy.filters`, mapping environment-variable patterns to `include` or `exclude`, while continuing to accept the legacy `exclude` and `include_only` arrays.
- Merge filter keys case-insensitively across config layers so higher-precedence entries can override individual patterns. Switching representations replaces the other representation instead of combining them.
- Reject mixed, duplicate, or malformed filter definitions in enabled layers, config writes, and reloads, while retaining the previous session configuration when a reload is invalid.
- Make config-manager reads and writes representation-aware and preserve existing formatting when updating individual policy values.

## Testing

Add coverage for parsing, schema constraints, layered merging, validation and diagnostics, config writes, override metadata, and invalid session reloads.

GitOrigin-RevId: e15464bca53e6e7ef31fcc97537fda60ed5d670a
2026-07-21 18:23:26 +00:00

110 lines
2.9 KiB
Rust

use super::*;
use pretty_assertions::assert_eq;
#[test]
fn shell_environment_policy_accepts_legacy_lists_or_filters() {
let legacy: ShellEnvironmentPolicyToml = toml::from_str(
r#"
exclude = ["LEGACY_*", "SHARED_*"]
include_only = ["PATH", "HOME"]
"#,
)
.expect("legacy arrays should remain valid in config.toml");
assert_eq!(
legacy,
ShellEnvironmentPolicyToml {
exclude: Some(vec!["LEGACY_*".to_string(), "SHARED_*".to_string()]),
include_only: Some(vec!["PATH".to_string(), "HOME".to_string()]),
..Default::default()
}
);
let filtered: ShellEnvironmentPolicyToml = toml::from_str(
r#"
[filters]
"FLIP_TO_EXCLUDE" = "exclude"
"FLIP_TO_INCLUDE" = "include"
"#,
)
.expect("filters should be valid in config.toml");
assert_eq!(
filtered,
ShellEnvironmentPolicyToml {
filters: Some(BTreeMap::from([
(
"FLIP_TO_EXCLUDE".to_string(),
ShellEnvironmentPolicyFilter::Exclude,
),
(
"FLIP_TO_INCLUDE".to_string(),
ShellEnvironmentPolicyFilter::Include,
),
])),
..Default::default()
}
);
assert_eq!(
ShellEnvironmentPolicy::from(filtered),
ShellEnvironmentPolicy::from(ShellEnvironmentPolicyToml {
exclude: Some(vec!["FLIP_TO_EXCLUDE".to_string()]),
include_only: Some(vec!["FLIP_TO_INCLUDE".to_string()]),
..Default::default()
})
);
}
#[test]
fn shell_environment_policy_rejects_mixed_legacy_lists_and_filters() {
let error = toml::from_str::<ShellEnvironmentPolicyToml>(
r#"
exclude = ["LEGACY_*"]
[filters]
"CANONICAL_*" = "include"
"#,
)
.expect_err("one config layer must not mix legacy lists and filters");
assert!(
error
.to_string()
.contains("cannot mix `filters` with legacy `exclude` or `include_only`")
);
}
#[test]
fn shell_environment_policy_rejects_case_variant_filters_within_layer() {
let error = toml::from_str::<ShellEnvironmentPolicyToml>(
r#"
[filters]
"AWS_*" = "exclude"
"aws_*" = "include"
"#,
)
.expect_err("case-variant filters in one layer should be rejected");
assert!(
error
.to_string()
.contains("duplicate shell environment filter")
);
}
#[test]
fn shell_environment_policy_rejects_unicode_case_variant_filters_within_layer() {
let error = toml::from_str::<ShellEnvironmentPolicyToml>(
r#"
[filters]
"СЕКРЕТ_*" = "exclude"
"секрет_*" = "include"
"#,
)
.expect_err("Unicode case-variant filters in one layer should be rejected");
assert!(
error
.to_string()
.contains("duplicate shell environment filter")
);
}