#![cfg(feature = "context-aware")]
use confers::context::{ContextAwareField, ContextValue, EvaluationContext};
#[test]
fn test_evaluation_context_default() {
let ctx = EvaluationContext::new();
assert!(ctx.targeting_key().is_none());
assert!(ctx.attributes().is_empty());
}
#[test]
fn test_evaluation_context_with_key() {
let ctx = EvaluationContext::new().with_key("user-123");
assert_eq!(ctx.targeting_key(), Some("user-123"));
}
#[test]
fn test_evaluation_context_with_attributes() {
let ctx = EvaluationContext::new()
.with_key("user-123")
.attr("plan", ContextValue::String("enterprise".into()))
.attr("region", ContextValue::String("us-east-1".into()))
.attr("age", ContextValue::Number(25.0));
assert_eq!(ctx.attributes().len(), 3);
assert_eq!(
ctx.attributes().get("plan"),
Some(&ContextValue::String("enterprise".into()))
);
assert_eq!(
ctx.attributes().get("region"),
Some(&ContextValue::String("us-east-1".into()))
);
assert_eq!(
ctx.attributes().get("age"),
Some(&ContextValue::Number(25.0))
);
}
#[test]
fn test_context_value_from_primitives() {
let cv: ContextValue = "test".into();
assert!(matches!(cv, ContextValue::String(_)));
let cv: ContextValue = true.into();
assert!(matches!(cv, ContextValue::Boolean(true)));
let cv: ContextValue = 42i64.into();
assert!(matches!(cv, ContextValue::Number(n) if n == 42.0));
let cv: ContextValue = std::f64::consts::PI.into();
assert!(matches!(cv, ContextValue::Number(n) if (n - std::f64::consts::PI).abs() < 0.001));
}
#[test]
fn test_context_aware_field_default() {
let field = ContextAwareField::new(100u64);
let ctx = EvaluationContext::new();
let value = field.evaluate(&ctx);
assert_eq!(value, &100u64);
}
#[test]
fn test_context_aware_field_with_matching_predicate() {
let field = ContextAwareField::new(100u64).when(
|ctx: &EvaluationContext| {
ctx.attributes().get("plan") == Some(&ContextValue::String("enterprise".into()))
},
10_737_418_240u64,
);
let ctx = EvaluationContext::new().attr("plan", ContextValue::String("enterprise".into()));
let value = field.evaluate(&ctx);
assert_eq!(value, &10_737_418_240u64);
}
#[test]
fn test_context_aware_field_no_match_returns_default() {
let field = ContextAwareField::new(100u64).when(
|ctx: &EvaluationContext| {
ctx.attributes().get("plan") == Some(&ContextValue::String("enterprise".into()))
},
10_737_418_240u64,
);
let ctx = EvaluationContext::new().attr("plan", ContextValue::String("basic".into()));
let value = field.evaluate(&ctx);
assert_eq!(value, &100u64);
}
#[test]
fn test_context_aware_field_multiple_rules() {
let field = ContextAwareField::new(100u64)
.when(
|ctx: &EvaluationContext| {
ctx.attributes().get("plan") == Some(&ContextValue::String("basic".into()))
},
524_288_000u64,
)
.when(
|ctx: &EvaluationContext| {
ctx.attributes().get("plan") == Some(&ContextValue::String("pro".into()))
},
10_737_418_240u64,
)
.when(
|ctx: &EvaluationContext| {
ctx.attributes().get("plan") == Some(&ContextValue::String("enterprise".into()))
},
10_737_418_240u64,
);
let ctx = EvaluationContext::new().attr("plan", ContextValue::String("enterprise".into()));
let value = field.evaluate(&ctx);
assert_eq!(value, &10_737_418_240u64);
}
#[test]
fn test_context_aware_field_evaluate_returns_reference() {
let field = ContextAwareField::new(String::from("default"));
let ctx = EvaluationContext::new();
let value = field.evaluate(&ctx);
assert_eq!(value, &String::from("default"));
}
#[test]
fn test_context_aware_field_clone() {
let field1 = ContextAwareField::new(100u64).when(
|ctx: &EvaluationContext| {
ctx.attributes().get("plan") == Some(&ContextValue::String("enterprise".into()))
},
10_737_418_240u64,
);
let field2 = field1.clone();
let ctx = EvaluationContext::new().attr("plan", ContextValue::String("enterprise".into()));
assert_eq!(field1.evaluate(&ctx), field2.evaluate(&ctx));
}
#[test]
fn test_evaluation_context_clone() {
let ctx1 = EvaluationContext::new()
.with_key("user-123")
.attr("plan", ContextValue::String("enterprise".into()));
let ctx2 = ctx1.clone();
assert_eq!(ctx1.targeting_key(), ctx2.targeting_key());
assert_eq!(ctx1.attributes().get("plan"), ctx2.attributes().get("plan"));
}
#[test]
fn test_evaluation_context_debug() {
let ctx = EvaluationContext::new()
.with_key("user-123")
.attr("plan", ContextValue::String("enterprise".into()));
let debug_str = format!("{:?}", ctx);
assert!(debug_str.contains("EvaluationContext"));
assert!(debug_str.contains("user-123"));
}
#[test]
fn test_context_value_debug() {
let cv_string = ContextValue::String("test".into());
let cv_number = ContextValue::Number(42.5);
let cv_bool = ContextValue::Boolean(true);
assert!(format!("{:?}", cv_string).contains("test"));
assert!(format!("{:?}", cv_number).contains("42.5"));
assert!(format!("{:?}", cv_bool).contains("true"));
}
#[test]
fn test_upload_limit_use_case() {
let upload_limit: ContextAwareField<u64> = ContextAwareField::new(100 * 1024 * 1024)
.when(
|ctx: &EvaluationContext| {
ctx.attributes().get("plan") == Some(&ContextValue::String("enterprise".into()))
},
10 * 1024 * 1024 * 1024,
)
.when(
|ctx: &EvaluationContext| {
ctx.attributes().get("plan") == Some(&ContextValue::String("pro".into()))
},
1024 * 1024 * 1024,
)
.when(
|ctx: &EvaluationContext| {
ctx.attributes().get("region") == Some(&ContextValue::String("cn-north".into()))
},
500 * 1024 * 1024,
);
let ctx = EvaluationContext::new()
.with_key("user_123")
.attr("plan", "enterprise")
.attr("region", "us-east-1");
assert_eq!(upload_limit.evaluate(&ctx), &(10 * 1024 * 1024 * 1024));
let ctx = EvaluationContext::new().attr("plan", "pro");
assert_eq!(upload_limit.evaluate(&ctx), &(1024 * 1024 * 1024));
let ctx = EvaluationContext::new().attr("plan", "basic");
assert_eq!(upload_limit.evaluate(&ctx), &(100 * 1024 * 1024));
let ctx = EvaluationContext::new()
.attr("plan", "enterprise")
.attr("region", "cn-north");
assert_eq!(upload_limit.evaluate(&ctx), &(10 * 1024 * 1024 * 1024));
}
#[test]
fn test_evaluation_context_environment() {
let ctx = EvaluationContext::new().with_environment("production");
assert_eq!(ctx.environment().as_ref(), "production");
}
#[test]
fn test_evaluation_context_region() {
let ctx = EvaluationContext::new().with_region("us-west-2");
assert_eq!(ctx.region().as_ref(), "us-west-2");
}
#[test]
fn test_context_aware_field_send_sync() {
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
assert_send::<ContextAwareField<u32>>();
assert_sync::<ContextAwareField<u32>>();
}