use northroot_proof_engine::{
validate_iso_time, validate_method_ref, validate_sha256_format, validate_span_commitment,
validate_span_id, validate_trace_id, ArtifactRef, MethodRef, SpanCommitment, SpanStatus,
};
#[test]
fn test_validate_trace_id_edge_cases() {
assert!(validate_trace_id("tr_12345").is_ok());
assert!(validate_trace_id("short").is_err());
assert!(validate_trace_id("trace-abc_123").is_ok());
assert!(validate_trace_id("trace@abc").is_err());
}
#[test]
fn test_validate_span_id_edge_cases() {
assert!(validate_span_id("sp-1").is_ok());
assert!(validate_span_id("").is_err());
assert!(validate_span_id("span_abc-123").is_ok());
}
#[test]
fn test_validate_sha256_format_edge_cases() {
let valid = "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
assert!(validate_sha256_format(valid).is_ok());
assert!(validate_sha256_format("sha512:abc").is_err());
assert!(validate_sha256_format("invalid:abc").is_err());
assert!(validate_sha256_format("sha256:short").is_err());
assert!(validate_sha256_format(
"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0"
)
.is_err());
let uppercase = "sha256:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF";
assert!(validate_sha256_format(uppercase).is_err());
assert!(validate_sha256_format(
"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdeg"
)
.is_err());
}
#[test]
fn test_validate_iso_time_edge_cases() {
assert!(validate_iso_time("2025-11-06T12:00:00.000Z").is_ok());
assert!(validate_iso_time("2025-11-06T12:00:00Z").is_ok());
assert!(validate_iso_time("invalid").is_err());
assert!(validate_iso_time("2025-11-06").is_err()); assert!(validate_iso_time("2025-11-06T12:00:00").is_err()); }
#[test]
fn test_validate_method_ref_edge_cases() {
let valid = MethodRef {
method_id: "com.test/method".to_string(),
version: "1.0.0".to_string(),
method_shape_root:
"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef".to_string(),
image_digest: "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
.to_string(),
method_fingerprint: "git:deadbeef".to_string(),
};
assert!(validate_method_ref(&valid).is_ok());
let mut invalid = valid.clone();
invalid.method_id = String::new();
assert!(validate_method_ref(&invalid).is_err());
let mut invalid = valid.clone();
invalid.version = String::new();
assert!(validate_method_ref(&invalid).is_err());
let mut invalid = valid.clone();
invalid.method_shape_root = "invalid".to_string();
assert!(validate_method_ref(&invalid).is_err());
}
#[test]
fn test_validate_span_commitment_edge_cases() {
let base = SpanCommitment {
schema_version: "proof.v2".to_string(),
trace_id: "tr_01H1234567890".to_string(),
span_id: "sp-0001".to_string(),
method_ref: MethodRef {
method_id: "com.test/method".to_string(),
version: "1.0.0".to_string(),
method_shape_root:
"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
.to_string(),
image_digest: "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
.to_string(),
method_fingerprint: "git:deadbeef".to_string(),
},
data_shape_hash: "sha256:1111111111111111111111111111111111111111111111111111111111111111"
.to_string(),
span_shape_hash: "sha256:2222222222222222222222222222222222222222222222222222222222222222"
.to_string(),
inputs: vec![ArtifactRef {
name: "input.csv".to_string(),
content_hash: "sha256:3333333333333333333333333333333333333333333333333333333333333333"
.to_string(),
uri: None,
}],
outputs: vec![ArtifactRef {
name: "output.json".to_string(),
content_hash: "sha256:4444444444444444444444444444444444444444444444444444444444444444"
.to_string(),
uri: None,
}],
start_time: "2025-11-06T12:00:00.000Z".to_string(),
end_time: "2025-11-06T12:00:00.042Z".to_string(),
status: SpanStatus::OK,
meta: None,
};
assert!(validate_span_commitment(&base).is_ok());
let mut invalid = base.clone();
invalid.inputs.clear();
assert!(validate_span_commitment(&invalid).is_err());
let mut invalid = base.clone();
invalid.outputs.clear();
assert!(validate_span_commitment(&invalid).is_err());
let mut invalid = base.clone();
invalid.start_time = "2025-11-06T12:00:00.042Z".to_string();
invalid.end_time = "2025-11-06T12:00:00.000Z".to_string();
assert!(validate_span_commitment(&invalid).is_err());
let mut invalid = base.clone();
invalid.inputs[0].name = String::new();
assert!(validate_span_commitment(&invalid).is_err());
}
#[test]
fn test_hash_format_consistency() {
use northroot_proof_engine::compute_sha256;
let hash = compute_sha256("test");
assert!(hash.starts_with("sha256:"));
assert_eq!(hash.len(), 71); assert!(hash
.chars()
.skip(7)
.all(|c| c.is_ascii_hexdigit() && !c.is_ascii_uppercase()));
}