use grpctestify::assert::engine::{AssertionEngine, AssertionResult};
use serde_json::json;
use std::collections::HashMap;
#[test]
fn test_uuid_plugin() {
let engine = AssertionEngine::new();
let response = json!({
"id": "123e4567-e89b-12d3-a456-426614174000",
"bad_id": "not-a-uuid"
});
let result = engine
.evaluate("@uuid(.id)", &response, None, None)
.unwrap();
assert_eq!(result, AssertionResult::Pass);
let result = engine
.evaluate("@uuid(.bad_id)", &response, None, None)
.unwrap();
if let AssertionResult::Fail { message: msg, .. } = result {
assert!(msg.contains("Expected valid UUID"));
} else {
panic!("Expected failure for invalid UUID");
}
}
#[test]
fn test_email_plugin() {
let engine = AssertionEngine::new();
let response = json!({
"email": "test@example.com",
"bad_email": "invalid-email"
});
let result = engine
.evaluate("@email(.email)", &response, None, None)
.unwrap();
assert_eq!(result, AssertionResult::Pass);
let result = engine
.evaluate("@email(.bad_email)", &response, None, None)
.unwrap();
assert!(matches!(result, AssertionResult::Fail { .. }));
}
#[test]
fn test_ip_plugin() {
let engine = AssertionEngine::new();
let response = json!({
"ip": "192.168.1.1",
"bad_ip": "999.999.999.999"
});
let result = engine.evaluate("@ip(.ip)", &response, None, None).unwrap();
assert_eq!(result, AssertionResult::Pass);
let result = engine
.evaluate("@ip(.bad_ip)", &response, None, None)
.unwrap();
assert!(matches!(result, AssertionResult::Fail { .. }));
}
#[test]
fn test_url_plugin() {
let engine = AssertionEngine::new();
let response = json!({
"url": "https://example.com",
"bad_url": "not-a-url"
});
let result = engine
.evaluate("@url(.url)", &response, None, None)
.unwrap();
assert_eq!(result, AssertionResult::Pass);
let result = engine
.evaluate("@url(.bad_url)", &response, None, None)
.unwrap();
assert!(matches!(result, AssertionResult::Fail { .. }));
}
#[test]
fn test_timestamp_plugin() {
let engine = AssertionEngine::new();
let response = json!({
"ts": "2023-10-01T12:00:00Z",
"bad_ts": "tomorrow"
});
let result = engine
.evaluate("@timestamp(.ts)", &response, None, None)
.unwrap();
assert_eq!(result, AssertionResult::Pass);
let result = engine
.evaluate("@timestamp(.bad_ts)", &response, None, None)
.unwrap();
assert!(matches!(result, AssertionResult::Fail { .. }));
}
#[test]
fn test_len_plugin() {
let engine = AssertionEngine::new();
let response = json!({
"list": [1, 2, 3],
"text": "hello"
});
let result = engine
.evaluate("@len(.list) == 3", &response, None, None)
.unwrap();
assert_eq!(result, AssertionResult::Pass);
let result = engine
.evaluate("@len(.text) == 5", &response, None, None)
.unwrap();
assert_eq!(result, AssertionResult::Pass);
let result = engine
.evaluate("@len(.list) == 5", &response, None, None)
.unwrap();
assert!(matches!(result, AssertionResult::Fail { .. }));
}
#[test]
fn test_header_plugin() {
let engine = AssertionEngine::new();
let response = json!({});
let mut headers = HashMap::new();
headers.insert("content-type".to_string(), "application/json".to_string());
let result = engine
.evaluate("@header(\"content-type\")", &response, Some(&headers), None)
.unwrap();
assert_eq!(result, AssertionResult::Pass);
let result = engine
.evaluate("@header(\"x-missing\")", &response, Some(&headers), None)
.unwrap();
assert!(matches!(result, AssertionResult::Fail { .. }));
}
#[test]
fn test_uuid_edge_cases() {
let engine = AssertionEngine::new();
let response = json!({"uuid": "550e8400-e29b-41d4-a716-446655440000"});
assert_eq!(
engine
.evaluate("@uuid(.uuid)", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"uuid": "00000000-0000-0000-0000-000000000000"});
assert_eq!(
engine
.evaluate("@uuid(.uuid)", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"uuid": "550e8400e29b41d4a716446655440000"});
assert_eq!(
engine
.evaluate("@uuid(.uuid)", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"uuid": ""});
assert!(matches!(
engine
.evaluate("@uuid(.uuid)", &response, None, None)
.unwrap(),
AssertionResult::Fail { .. }
));
}
#[test]
fn test_email_edge_cases() {
let engine = AssertionEngine::new();
let response = json!({"email": "user@mail.example.com"});
assert_eq!(
engine
.evaluate("@email(.email)", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"email": "user+tag@example.com"});
assert_eq!(
engine
.evaluate("@email(.email)", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"email": "user123@example123.com"});
assert_eq!(
engine
.evaluate("@email(.email)", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"email": "userexample.com"});
assert!(matches!(
engine
.evaluate("@email(.email)", &response, None, None)
.unwrap(),
AssertionResult::Fail { .. }
));
let response = json!({"email": ""});
assert!(matches!(
engine
.evaluate("@email(.email)", &response, None, None)
.unwrap(),
AssertionResult::Fail { .. }
));
}
#[test]
fn test_ip_edge_cases() {
let engine = AssertionEngine::new();
let response = json!({"ip": "::1"});
assert_eq!(
engine.evaluate("@ip(.ip)", &response, None, None).unwrap(),
AssertionResult::Pass
);
let response = json!({"ip": "2001:0db8:85a3:0000:0000:8a2e:0370:7334"});
assert_eq!(
engine.evaluate("@ip(.ip)", &response, None, None).unwrap(),
AssertionResult::Pass
);
let response = json!({"ip": "0.0.0.0"});
assert_eq!(
engine.evaluate("@ip(.ip)", &response, None, None).unwrap(),
AssertionResult::Pass
);
let response = json!({"ip": "255.255.255.255"});
assert_eq!(
engine.evaluate("@ip(.ip)", &response, None, None).unwrap(),
AssertionResult::Pass
);
let response = json!({"ip": "256.0.0.1"});
assert!(matches!(
engine.evaluate("@ip(.ip)", &response, None, None).unwrap(),
AssertionResult::Fail { .. }
));
}
#[test]
fn test_url_edge_cases() {
let engine = AssertionEngine::new();
let response = json!({"url": "https://example.com:8080/path"});
assert_eq!(
engine
.evaluate("@url(.url)", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"url": "https://example.com/path?query=1#anchor"});
assert_eq!(
engine
.evaluate("@url(.url)", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"url": "ftp://ftp.example.com"});
assert_eq!(
engine
.evaluate("@url(.url)", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"url": "example.com"});
assert!(matches!(
engine
.evaluate("@url(.url)", &response, None, None)
.unwrap(),
AssertionResult::Fail { .. }
));
let response = json!({"url": ""});
assert!(matches!(
engine
.evaluate("@url(.url)", &response, None, None)
.unwrap(),
AssertionResult::Fail { .. }
));
}
#[test]
fn test_timestamp_edge_cases() {
let engine = AssertionEngine::new();
let response = json!({"ts": "2024-01-15T10:30:00+03:00"});
assert_eq!(
engine
.evaluate("@timestamp(.ts)", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"ts": "2024-01-15T10:30:00Z"});
assert_eq!(
engine
.evaluate("@timestamp(.ts)", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"ts": "1970-01-01T00:00:00Z"});
assert_eq!(
engine
.evaluate("@timestamp(.ts)", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"ts": "2024-01-15"});
assert!(matches!(
engine
.evaluate("@timestamp(.ts)", &response, None, None)
.unwrap(),
AssertionResult::Fail { .. }
));
let response = json!({"ts": "10:30:00"});
assert!(matches!(
engine
.evaluate("@timestamp(.ts)", &response, None, None)
.unwrap(),
AssertionResult::Fail { .. }
));
}
#[test]
fn test_len_edge_cases() {
let engine = AssertionEngine::new();
let response = json!({"list": []});
assert_eq!(
engine
.evaluate("@len(.list) == 0", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"text": ""});
assert_eq!(
engine
.evaluate("@len(.text) == 0", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"text": "привет"});
assert_eq!(
engine
.evaluate("@len(.text) == 12", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"text": "hello"});
assert_eq!(
engine
.evaluate("@len(.text) == 5", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"list": [[1, 2], [3, 4, 5]]});
assert_eq!(
engine
.evaluate("@len(.list) == 2", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
let response = json!({"num": 12345});
assert!(matches!(
engine
.evaluate("@len(.num) == 5", &response, None, None)
.unwrap(),
AssertionResult::Fail { .. }
));
}
#[test]
fn test_header_case_insensitive() {
let engine = AssertionEngine::new();
let response = json!({});
let mut headers = HashMap::new();
headers.insert("Content-Type".to_string(), "application/json".to_string());
let result = engine
.evaluate(
"@has_header(\"content-type\") == true",
&response,
Some(&headers),
None,
)
.unwrap();
assert!(matches!(result, AssertionResult::Pass), "got: {:?}", result);
}
#[test]
fn test_trailer_plugin_basic() {
let engine = AssertionEngine::new();
let response = json!({});
let mut trailers = HashMap::new();
trailers.insert("grpc-status".to_string(), "0".to_string());
let result = engine
.evaluate(
"@trailer(\"grpc-status\")",
&response,
None,
Some(&trailers),
)
.unwrap();
assert_eq!(result, AssertionResult::Pass);
let result = engine
.evaluate("@trailer(\"x-missing\")", &response, None, Some(&trailers))
.unwrap();
assert!(matches!(result, AssertionResult::Fail { .. }));
}
#[test]
fn test_multiple_plugins_in_one_assertion() {
let engine = AssertionEngine::new();
let response = json!({
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "test@example.com",
"url": "https://example.com",
"items": [1, 2, 3]
});
assert_eq!(
engine
.evaluate("@uuid(.id)", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
assert_eq!(
engine
.evaluate("@email(.email)", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
assert_eq!(
engine
.evaluate("@url(.url)", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
assert_eq!(
engine
.evaluate("@len(.items) == 3", &response, None, None)
.unwrap(),
AssertionResult::Pass
);
}