use std::collections::HashSet;
use crate::modules::pxconstants::WHITELIST_EXT;
use crate::pxconfig::*;
use crate::pxcontext::PXModuleMode;
use regex::Regex;
#[test]
fn strip_json_quotes_removes_surrounding_quotes() {
assert_eq!(strip_json_quotes(r#""active_blocking""#), "active_blocking");
assert_eq!(strip_json_quotes(r#""monitor""#), "monitor");
assert_eq!(strip_json_quotes(r#""hello""#), "hello");
}
#[test]
fn strip_json_quotes_leaves_unquoted_strings() {
assert_eq!(strip_json_quotes("active_blocking"), "active_blocking");
assert_eq!(strip_json_quotes("monitor"), "monitor");
assert_eq!(strip_json_quotes(""), "");
}
#[test]
fn strip_json_quotes_ignores_partial_quotes() {
assert_eq!(strip_json_quotes(r#""only_start"#), r#""only_start"#);
assert_eq!(strip_json_quotes(r#"only_end""#), r#"only_end""#);
}
#[test]
fn set_from_raw_parses_quoted_module_mode() {
let mut conf = PXConfig::default();
assert_eq!(conf.module_mode, PXModuleMode::Monitor);
conf.set_from_raw(PXConfigKey::ModuleMode, r#""active_blocking""#);
assert_eq!(conf.module_mode, PXModuleMode::Blocking);
}
#[test]
fn set_from_raw_parses_unquoted_module_mode() {
let mut conf = PXConfig::default();
conf.set_from_raw(PXConfigKey::ModuleMode, "active_blocking");
assert_eq!(conf.module_mode, PXModuleMode::Blocking);
}
#[test]
fn default_filter_by_extension_uses_whitelist_ext() {
let conf = PXConfig::default();
let expected: Vec<String> = WHITELIST_EXT.iter().map(|ext| (*ext).to_owned()).collect();
assert_eq!(conf.filter_by_extension, expected);
}
#[test]
fn parse_vec_csv_input() {
assert_eq!(parse_vec("a, b, c"), vec!["a", "b", "c"]);
assert_eq!(parse_vec("a,,b"), vec!["a", "b"]);
assert_eq!(parse_vec("a, , b"), vec!["a", "b"]);
assert_eq!(parse_vec(" , , "), Vec::<String>::new());
assert_eq!(parse_vec(""), Vec::<String>::new());
}
#[test]
fn parse_vec_json_array_input() {
assert_eq!(parse_vec(r#"["a","b","c"]"#), vec!["a", "b", "c"]);
assert_eq!(parse_vec(r#"["/api","/health"]"#), vec!["/api", "/health"]);
}
#[test]
fn parse_vec_empty_json_array() {
assert_eq!(parse_vec("[]"), Vec::<String>::new());
}
#[test]
fn parse_vec_json_array_filters_empty_strings() {
assert_eq!(parse_vec(r#"["a","","b"]"#), vec!["a", "b"]);
assert_eq!(parse_vec(r#"["",""]"#), Vec::<String>::new());
}
#[test]
#[cfg(feature = "kv_store")]
fn json_value_to_raw_store_strings() {
let v = serde_json::json!("active_blocking");
assert_eq!(json_value_to_raw_store(&v), "active_blocking");
}
#[test]
#[cfg(feature = "kv_store")]
fn json_value_to_raw_store_arrays() {
let v = serde_json::json!(["/api", "/health"]);
assert_eq!(json_value_to_raw_store(&v), "/api,/health");
let empty = serde_json::json!([]);
assert_eq!(json_value_to_raw_store(&empty), "");
}
#[test]
#[cfg(feature = "kv_store")]
fn json_value_to_raw_store_ci_endpoint_objects() {
let v = serde_json::json!([{
"method": "post",
"path": "/login",
"sent_through": "body",
"user_field": "username",
"pass_field": "password"
}]);
let stored = json_value_to_raw_store(&v);
let mut conf = PXConfig::default();
conf.set_from_raw(PXConfigKey::LoginCredentialsExtraction, &stored);
assert_eq!(conf.login_credentials_extraction.len(), 1);
assert_eq!(conf.prepared_ci_endpoints.len(), 1);
assert_eq!(
conf.login_credentials_extraction
.first()
.map(|e| e.path.as_str()),
Some("/login")
);
}
#[test]
fn set_from_raw_ci_endpoint_empty_object_resets_endpoints() {
let mut conf = PXConfig::default();
conf.set_from_raw(
PXConfigKey::LoginCredentialsExtraction,
r#"[{
"method": "post",
"path": "/login",
"sent_through": "body",
"user_field": "username",
"pass_field": "password"
}]"#,
);
assert_eq!(conf.login_credentials_extraction.len(), 1);
assert_eq!(conf.prepared_ci_endpoints.len(), 1);
conf.set_from_raw(PXConfigKey::LoginCredentialsExtraction, "[{}]");
assert!(conf.login_credentials_extraction.is_empty());
assert!(conf.prepared_ci_endpoints.is_empty());
}
#[test]
fn set_from_value_ci_endpoint_empty_object_resets_endpoints() {
let mut conf = PXConfig {
login_credentials_extraction: vec![PXCredentialEndpointConfig {
path: "/login".to_owned(),
method: "post".to_owned(),
..Default::default()
}],
..Default::default()
};
rebuild_prepared_ci_endpoints(&mut conf);
assert_eq!(conf.prepared_ci_endpoints.len(), 1);
let set_result = conf.set_from_value(
PXConfigKey::LoginCredentialsExtraction,
&serde_json::json!({}),
);
assert!(set_result.is_ok());
assert!(conf.login_credentials_extraction.is_empty());
assert!(conf.prepared_ci_endpoints.is_empty());
}
#[test]
fn set_from_raw_vec_excludes_empty_strings() {
let mut conf = PXConfig::default();
conf.set_from_raw(PXConfigKey::EnforcedRoutes, "");
assert!(conf.enforced_routes.is_empty());
conf.set_from_raw(PXConfigKey::EnforcedRoutes, " , , ");
assert!(conf.enforced_routes.is_empty());
conf.set_from_raw(PXConfigKey::EnforcedRoutes, "/api, , /health");
assert_eq!(conf.enforced_routes, vec!["/api", "/health"]);
}
#[test]
fn set_from_raw_vec_handles_json_array() {
let mut conf = PXConfig::default();
conf.set_from_raw(PXConfigKey::EnforcedRoutes, "[]");
assert!(conf.enforced_routes.is_empty());
conf.set_from_raw(PXConfigKey::EnforcedRoutes, r#"["/api","/health"]"#);
assert_eq!(conf.enforced_routes, vec!["/api", "/health"]);
}
#[test]
fn set_from_raw_graphql_keywords_parses_patterns() {
let mut conf = PXConfig::default();
conf.set_from_raw(PXConfigKey::GraphqlKeywords, r#"["user","friends?","id"]"#);
let pats: Vec<&str> = conf.graphql_keywords.iter().map(Regex::as_str).collect();
assert_eq!(pats, vec!["user", "friends?", "id"]);
}
#[test]
fn graphql_keywords_set_from_value() {
let mut conf = PXConfig::default();
let v = serde_json::json!(["user", "friends?", "id"]);
let set_result = conf.set_from_value(PXConfigKey::GraphqlKeywords, &v);
assert!(set_result.is_ok());
let pats: Vec<&str> = conf.graphql_keywords.iter().map(Regex::as_str).collect();
assert_eq!(pats, vec!["user", "friends?", "id"]);
}
#[test]
fn secret_store_keys_contains_only_expected_fields() {
let keys: HashSet<PXConfigKey> = secret_store_keys().iter().copied().collect();
let expected: HashSet<PXConfigKey> = [
PXConfigKey::AppId,
PXConfigKey::CookieSecret,
PXConfigKey::AuthToken,
PXConfigKey::LoggerAuthToken,
]
.into();
assert_eq!(keys, expected);
}
#[test]
fn apply_secret_values_overrides_config_fields() {
let mut conf = PXConfig::default();
conf.set_from_raw(PXConfigKey::AppId, "PXFROMCONFIG");
conf.set_from_raw(PXConfigKey::CookieSecret, "config-secret");
conf.set_from_raw(PXConfigKey::AuthToken, "config-token");
conf.set_from_raw(PXConfigKey::LoggerAuthToken, "config-logger");
apply_secret_values(
&mut conf,
&[
(PXConfigKey::AppId, "PXFROMSECRET"),
(PXConfigKey::CookieSecret, "secret-cookie"),
(PXConfigKey::AuthToken, "secret-auth"),
(PXConfigKey::LoggerAuthToken, "secret-logger"),
],
);
assert_eq!(conf.app_id, "PXFROMSECRET");
assert_eq!(conf.cookie_secret, "secret-cookie");
assert_eq!(conf.auth_token, "secret-auth");
assert_eq!(conf.logger_auth_token, "secret-logger");
}
#[test]
fn apply_secret_values_partial_overlay_keeps_existing_config() {
let mut conf = PXConfig::default();
conf.set_from_raw(PXConfigKey::AppId, "PXKEPT");
conf.set_from_raw(PXConfigKey::AuthToken, "kept-token");
apply_secret_values(&mut conf, &[(PXConfigKey::CookieSecret, "new-secret")]);
assert_eq!(conf.app_id, "PXKEPT");
assert_eq!(conf.auth_token, "kept-token");
assert_eq!(conf.cookie_secret, "new-secret");
assert!(conf.logger_auth_token.is_empty());
}
#[test]
fn recompute_derived_uses_config_store_app_id_for_default_hosts() {
let mut conf = PXConfig::default();
conf.set_from_raw(PXConfigKey::AppId, "PXFROMCONFIG");
recompute_derived(&mut conf, "");
assert_eq!(conf.human_sapi_host, "sapi-PXFROMCONFIG.perimeterx.net");
assert_eq!(
conf.human_collector_host,
"collector-PXFROMCONFIG.perimeterx.net"
);
}
#[test]
fn recompute_derived_preserves_config_store_custom_hosts() {
let mut conf = PXConfig::default();
conf.set_from_raw(PXConfigKey::AppId, "PXFROMCONFIG");
conf.set_from_raw(PXConfigKey::HumanSapiHost, "custom-sapi.example.com");
conf.set_from_raw(
PXConfigKey::HumanCollectorHost,
"custom-collector.example.com",
);
recompute_derived(&mut conf, "");
assert_eq!(conf.human_sapi_host, "custom-sapi.example.com");
assert_eq!(conf.human_collector_host, "custom-collector.example.com");
}
#[test]
fn recompute_derived_updates_generated_hosts_after_secret_app_id_override() {
let mut conf = PXConfig::default();
conf.set_from_raw(PXConfigKey::AppId, "PXFROMCONFIG");
recompute_derived(&mut conf, "");
let app_id_before_secrets = conf.app_id.clone();
apply_secret_values(&mut conf, &[(PXConfigKey::AppId, "PXFROMSECRET")]);
recompute_derived(&mut conf, &app_id_before_secrets);
assert_eq!(conf.human_sapi_host, "sapi-PXFROMSECRET.perimeterx.net");
assert_eq!(
conf.human_collector_host,
"collector-PXFROMSECRET.perimeterx.net"
);
}
#[test]
fn load_secrets_from_store_ignores_empty_store_name() {
let mut conf = PXConfig::default();
conf.set_from_raw(PXConfigKey::AppId, "PXKEPT");
conf.set_from_raw(PXConfigKey::CookieSecret, "kept-cookie");
conf.set_from_raw(PXConfigKey::AuthToken, "kept-auth");
conf.set_from_raw(PXConfigKey::LoggerAuthToken, "kept-logger");
load_secrets_from_store(&mut conf, "");
assert_eq!(conf.app_id, "PXKEPT");
assert_eq!(conf.cookie_secret, "kept-cookie");
assert_eq!(conf.auth_token, "kept-auth");
assert_eq!(conf.logger_auth_token, "kept-logger");
}