use remora_domain::{ BucketName, FailureDisposition, JobPhase, MemberPath, RuntimeFailureClass, StorageScope, Target, TargetPrefix, TargetStoreId, fingerprint, }; use serde::Deserialize; use serde_json::Value; #[derive(Deserialize)] struct Corpus { job_phases: Vec, runtime_failures: Vec, buckets: ValidationCases, target_prefixes: ValidationCases, reserved_target_prefixes: Vec, member_paths: ValidationCases, scope_coverage: Vec, fingerprints: Vec, } #[derive(Deserialize)] struct FailureCase { class: RuntimeFailureClass, disposition: FailureDisposition, } #[derive(Deserialize)] struct ValidationCases { valid: Vec, invalid: Vec, } #[derive(Deserialize)] struct CanonicalCase { input: String, canonical: String, } #[derive(Deserialize)] struct FingerprintCase { value: Value, canonical: String, sha256: String, } #[derive(Deserialize)] struct ScopeCase { scope: [String; 3], target: [String; 3], covers: bool, } #[derive(Deserialize)] struct ReservedPrefixCase { input: String, reserved: Vec, } fn corpus() -> Corpus { serde_json::from_str(include_str!("../../../contracts/golden/domain.json")).unwrap() } #[test] fn protocol_phase_vocabulary_is_exact() { let phases = corpus().job_phases; assert_eq!(phases.len(), 7); assert!(phases[..4].iter().all(|phase| !phase.is_terminal())); assert!(phases[4..].iter().all(|phase| phase.is_terminal())); } #[test] fn runtime_failure_dispositions_match_the_architecture() { for case in corpus().runtime_failures { assert_eq!(case.class.disposition(), case.disposition); } } #[test] fn domain_values_validate_and_normalize() { let corpus = corpus(); for value in corpus.buckets.valid { assert_eq!(BucketName::parse(&value).unwrap().as_str(), value); } for value in corpus.buckets.invalid { assert!(BucketName::parse(value).is_err()); } for case in corpus.target_prefixes.valid { assert_eq!( TargetPrefix::parse(&case.input, []).unwrap().canonical(), case.canonical ); } for value in corpus.target_prefixes.invalid { assert!(TargetPrefix::parse(&value, []).is_err()); } for case in corpus.reserved_target_prefixes { assert!( TargetPrefix::parse(&case.input, case.reserved.iter().map(String::as_str)).is_err() ); } for case in corpus.member_paths.valid { assert_eq!( MemberPath::parse(&case.input).unwrap().canonical(), case.canonical ); } for value in corpus.member_paths.invalid { assert!(MemberPath::parse(&value).is_err()); } } #[test] fn request_fingerprints_match_the_shared_corpus() { for case in corpus().fingerprints { assert_eq!( serde_json_canonicalizer::to_string(&case.value).unwrap(), case.canonical ); assert_eq!(fingerprint(&case.value).unwrap().to_hex(), case.sha256); } } #[test] fn storage_scope_coverage_uses_exact_segment_tuples() { for case in corpus().scope_coverage { let scope = StorageScope { store: TargetStoreId::parse(&case.scope[0]).unwrap(), bucket: BucketName::parse(&case.scope[1]).unwrap(), prefix: TargetPrefix::parse(&case.scope[2], []).unwrap(), }; let target = Target { store: TargetStoreId::parse(&case.target[0]).unwrap(), bucket: BucketName::parse(&case.target[1]).unwrap(), prefix: TargetPrefix::parse(&case.target[2], []).unwrap(), }; assert_eq!(scope.covers(&target), case.covers); } }