use reputation_core::Calculator;
use reputation_types::AgentDataBuilder;
use chrono::{Utc, Duration};
#[test]
fn test_did_validation_security() {
let malicious_dids = [
"did:test:../../../etc/passwd",
"did:test://etc/passwd",
"did:test:agent/../../../secret",
"did:test:'; DROP TABLE agents; --",
"did:test:' OR '1'='1",
"did:test:<script>alert('xss')</script>",
"did:test:javascript:alert(1)",
"did:test:\0null",
"did:test:\nnewline",
"did:test:\ttab",
"did::",
"did:test:",
":test:agent",
&format!("did:test:{}", "a".repeat(2000)),
];
for malicious_did in &malicious_dids {
let result = AgentDataBuilder::new(*malicious_did).build();
assert!(
result.is_err(),
"Malicious DID should be rejected: {}",
malicious_did
);
}
}
#[test]
fn test_arithmetic_overflow_protection() {
let calc = Calculator::default();
let agent = AgentDataBuilder::new("did:test:overflow")
.total_interactions(u32::MAX)
.total_reviews(u32::MAX / 2)
.with_reviews(u32::MAX / 2, 5.0)
.build()
.unwrap();
let result = calc.calculate(&agent);
assert!(result.is_ok());
let score = result.unwrap();
assert!(score.score >= 0.0 && score.score <= 100.0);
assert!(score.confidence >= 0.0 && score.confidence <= 1.0);
}
#[test]
fn test_rating_bounds_security() {
let invalid_ratings = [
0.0, 0.5, 0.99999, 5.00001, 6.0, 100.0, -1.0, -5.0, f64::NAN, f64::INFINITY, f64::NEG_INFINITY, ];
for rating in &invalid_ratings {
let result = AgentDataBuilder::new("did:test:rating")
.total_interactions(10)
.with_reviews(5, *rating)
.build();
assert!(
result.is_err(),
"Invalid rating {} should be rejected",
rating
);
}
let valid_ratings = [1.0, 1.000001, 3.0, 4.999999, 5.0];
for rating in &valid_ratings {
let result = AgentDataBuilder::new("did:test:rating-valid")
.total_interactions(10)
.with_reviews(5, *rating)
.build();
assert!(
result.is_ok(),
"Valid rating {} should be accepted",
rating
);
}
}
#[test]
fn test_review_consistency_security() {
let result = AgentDataBuilder::new("did:test:consistency")
.total_interactions(10)
.total_reviews(20) .build();
assert!(result.is_err(), "Reviews cannot exceed interactions");
let large_num = u32::MAX / 2 + 1000;
let result = AgentDataBuilder::new("did:test:large")
.total_interactions(large_num)
.total_reviews(large_num)
.build();
assert!(result.is_ok(), "Should handle large numbers safely");
}
#[test]
fn test_mcp_level_validation_security() {
let invalid_levels = [0, 4, 5, 100, 255];
for level in &invalid_levels {
let result = AgentDataBuilder::new("did:test:mcp")
.mcp_level(*level)
.build();
match level {
0 => assert!(result.is_ok(), "MCP level 0 (None) should be valid"),
_ => assert!(result.is_err(), "Invalid MCP level {} should be rejected", level),
}
}
}
#[test]
fn test_date_validation_security() {
let future_date = Utc::now() + Duration::days(1);
let result = AgentDataBuilder::new("did:test:future")
.created_at(future_date)
.build();
assert!(result.is_err(), "Future creation dates should be rejected");
let old_date = Utc::now() - Duration::days(365 * 10);
let result = AgentDataBuilder::new("did:test:old")
.created_at(old_date)
.build();
assert!(result.is_ok(), "Old dates should be accepted");
}
#[test]
fn test_error_message_security() {
let result = AgentDataBuilder::new("did:test:'; DROP TABLE --")
.build();
if let Err(e) = result {
let error_str = e.to_string();
assert!(
!error_str.contains("DROP TABLE"),
"Error message should not echo malicious input"
);
assert!(
error_str.contains("invalid format") || error_str.contains("DID"),
"Error message should indicate the problem without details"
);
} else {
panic!("Expected error for malicious DID");
}
}
#[test]
fn test_confidence_calculation_bounds() {
let calc = Calculator::default();
let test_cases = [
(0, 0.0), (1, 0.0625), (15, 0.5), (u32::MAX, 1.0), ];
for (interactions, expected_min) in test_cases {
let agent = AgentDataBuilder::new("did:test:conf")
.total_interactions(interactions)
.build()
.unwrap();
let score = calc.calculate(&agent).unwrap();
assert!(
score.confidence >= expected_min - 0.01,
"Confidence {} below expected {} for {} interactions",
score.confidence,
expected_min,
interactions
);
assert!(
score.confidence <= 1.0,
"Confidence {} exceeds maximum",
score.confidence
);
}
}
#[test]
fn test_score_bounds_with_extreme_inputs() {
let calc = Calculator::default();
let extreme_agents = vec![
AgentDataBuilder::new("did:test:max-all")
.total_interactions(u32::MAX)
.with_reviews(u32::MAX / 2, 5.0)
.mcp_level(3)
.identity_verified(true)
.security_audit_passed(true)
.open_source(true)
.created_at(Utc::now() - Duration::days(730))
.build()
.unwrap(),
AgentDataBuilder::new("did:test:min-all")
.build()
.unwrap(),
AgentDataBuilder::new("did:test:high-low")
.total_interactions(100000)
.with_reviews(50000, 1.0)
.build()
.unwrap(),
];
for agent in extreme_agents {
let result = calc.calculate(&agent);
assert!(result.is_ok(), "Should handle extreme inputs");
let score = result.unwrap();
assert!(
score.score >= 0.0 && score.score <= 100.0,
"Score {} out of bounds for agent {}",
score.score,
agent.did
);
}
}
#[test]
fn test_no_panic_paths() {
let calc = Calculator::default();
let interactions = [0, 1, 10, 100, 1000, 10000, u32::MAX];
let ratings = [1.0, 2.5, 3.0, 4.5, 5.0];
let ages = [0, 30, 90, 365, 730];
for &inter in &interactions {
for &rating in &ratings {
for &age in &ages {
let reviews = inter / 2;
let mut builder = AgentDataBuilder::new(&format!("did:test:combo-{}-{}", inter, rating))
.total_interactions(inter)
.created_at(Utc::now() - Duration::days(age));
if reviews > 0 {
builder = builder.with_reviews(reviews, rating);
}
if let Ok(agent) = builder.build() {
let _ = calc.calculate(&agent);
}
}
}
}
}