// file: crates/ksp-store-api/unit_tests/model/raw_conflict.rs // version: 1 fn network(value: &str) -> std::option::Option { return crate::RawNetworkId::new(value.to_owned()).ok(); } fn transaction_reference(network: crate::RawNetworkId, signature_byte: u8) -> crate::RawTransactionReference { return crate::RawTransactionReference::new(network, crate::RawTransactionSignature::new([signature_byte; 64])); } fn variant_reference(transaction: crate::RawTransactionReference, variant_id: u64) -> std::option::Option { let variant_id = match crate::RawTransactionVariantId::try_new(variant_id) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return std::option::Option::None, }; return std::option::Option::Some(crate::RawTransactionVariantReference::new(transaction, variant_id)); } fn timestamp(value: u64) -> std::option::Option { return crate::RawTimestamp::from_unix_millis(value).ok(); } fn page() -> std::option::Option { let limit = match crate::RawPageLimit::new(25) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return std::option::Option::None, }; return std::option::Option::Some(crate::RawInspectionPageRequest::new(0, limit)); } #[test] fn v0_3_17_pre_002_conflict_and_variant_queries_enforce_network_scope() { let mainnet = match network("mainnet") { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let devnet = match network("devnet") { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let transaction = transaction_reference(devnet, 1); let page = match page() { std::option::Option::Some(value) => value, std::option::Option::None => return, }; assert!( crate::RawTransactionVariantInspectionQuery::try_new( mainnet.clone(), std::option::Option::Some(transaction.clone()), crate::RawSortDirection::Ascending, page, ) .is_err() ); assert!( crate::RawTransactionConflictInspectionQuery::try_new( mainnet, std::option::Option::Some(crate::RawTransactionConflictStatus::Open), std::option::Option::Some(transaction), crate::RawSortDirection::Ascending, page, ) .is_err() ); return; } #[test] fn v0_3_17_pre_002_action_request_requires_positive_double_revision_and_same_transaction_target() { let mainnet = match network("mainnet") { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let transaction = transaction_reference(mainnet.clone(), 2); let conflict = crate::RawTransactionConflictReference::new(transaction.clone()); let target = match variant_reference(transaction, 2) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; assert!( crate::RawTransactionConflictActionRequest::try_new(conflict.clone(), 0, 1, crate::RawTransactionConflictAction::PromoteVariant(target.clone()),) .is_err() ); let other = transaction_reference(mainnet, 3); let other_target = match variant_reference(other, 3) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; assert!( crate::RawTransactionConflictActionRequest::try_new(conflict.clone(), 1, 1, crate::RawTransactionConflictAction::PromoteVariant(other_target),) .is_err() ); let request = crate::RawTransactionConflictActionRequest::try_new( conflict, 5, 7, crate::RawTransactionConflictAction::Resolve(crate::RawTransactionConflictResolution::PromoteVariant(target)), ); assert!(request.is_ok()); let request = match request { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; assert_eq!(request.expected_conflict_revision(), 5); assert_eq!(request.expected_canonical_revision(), 7); return; } #[test] fn v0_3_17_pre_002_conflict_projection_enforces_status_resolution_and_conflict_relation() { let mainnet = match network("mainnet") { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let transaction = transaction_reference(mainnet, 4); let conflict = crate::RawTransactionConflictReference::new(transaction.clone()); let canonical = match variant_reference(transaction.clone(), 1) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let incoming = match variant_reference(transaction, 2) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let created_at = match timestamp(1_000) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let updated_at = match timestamp(2_000) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let open = crate::RawTransactionConflictSummary::try_new( conflict.clone(), crate::RawTransactionConflictStatus::Open, 3, canonical.clone(), 2, incoming.clone(), crate::RawTransactionVariantRelation::Conflict, crate::RawTransactionVariantRelationReason::CanonicalPayloadConflict, std::option::Option::None, std::option::Option::None, 2, created_at, updated_at, ); assert!(open.is_ok()); let invalid_resolved = crate::RawTransactionConflictSummary::try_new( conflict, crate::RawTransactionConflictStatus::Resolved, 4, canonical, 3, incoming, crate::RawTransactionVariantRelation::Exact, crate::RawTransactionVariantRelationReason::ExactCanonicalContent, std::option::Option::None, std::option::Option::None, 2, created_at, updated_at, ); assert!(invalid_resolved.is_err()); return; } #[test] fn v0_3_17_pre_002_conflict_detail_requires_unique_complete_participant_projection() { let mainnet = match network("mainnet") { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let transaction = transaction_reference(mainnet, 5); let conflict = crate::RawTransactionConflictReference::new(transaction.clone()); let canonical = match variant_reference(transaction.clone(), 1) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let incoming = match variant_reference(transaction, 2) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let created_at = match timestamp(1_000) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let updated_at = match timestamp(2_000) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let summary = crate::RawTransactionConflictSummary::try_new( conflict, crate::RawTransactionConflictStatus::Open, 2, canonical.clone(), 1, incoming.clone(), crate::RawTransactionVariantRelation::Incomparable, crate::RawTransactionVariantRelationReason::UnsupportedCanonicalDifference, std::option::Option::None, std::option::Option::None, 2, created_at, updated_at, ); let summary = match summary { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let first = match crate::RawTransactionConflictParticipantSummary::try_new(canonical, 1, created_at) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let second = match crate::RawTransactionConflictParticipantSummary::try_new(incoming, 2, updated_at) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; assert!(crate::RawTransactionConflictDetail::try_new(summary, std::vec![first, second]).is_ok()); return; } #[test] fn v0_3_17_pre_002_history_event_requires_resolution_action_only_for_resolution_events() { let mainnet = match network("mainnet") { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let transaction = transaction_reference(mainnet, 6); let conflict = crate::RawTransactionConflictReference::new(transaction.clone()); let canonical = match variant_reference(transaction.clone(), 1) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let incoming = match variant_reference(transaction, 2) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let comparison = crate::RawTransactionVariantComparison::try_new( crate::RawTransactionVariantRelation::Conflict, crate::RawTransactionVariantRelationReason::CanonicalPayloadConflict, ); let comparison = match comparison { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let at = match timestamp(1_000) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; assert!( crate::RawTransactionConflictEventSummary::try_new( conflict.clone(), 1, crate::RawTransactionConflictEventKind::Opened, crate::RawTransactionConflictEventOrigin::Automatic, std::option::Option::Some(canonical.clone()), std::option::Option::Some(incoming), std::option::Option::Some(canonical.clone()), std::option::Option::Some(comparison), std::option::Option::None, at, ) .is_ok() ); assert!( crate::RawTransactionConflictEventSummary::try_new( conflict, 2, crate::RawTransactionConflictEventKind::ResolvedKeepCanonical, crate::RawTransactionConflictEventOrigin::Operator, std::option::Option::Some(canonical.clone()), std::option::Option::None, std::option::Option::Some(canonical), std::option::Option::None, std::option::Option::None, at, ) .is_err() ); return; } #[test] fn v0_3_17_pre_002_action_outcomes_and_codes_are_stable_and_distinct() { assert_eq!(crate::RawTransactionConflictResolutionAction::KeepCurrentCanonical.code(), "keep_current_canonical"); assert_eq!(crate::RawTransactionConflictEventKind::ParticipantAdded.code(), "participant_added"); assert_eq!(crate::RawTransactionConflictEventOrigin::Operator.code(), "operator"); assert_ne!(crate::RawTransactionConflictActionOutcome::Applied, crate::RawTransactionConflictActionOutcome::AlreadyAtTarget); assert_ne!(crate::RawTransactionConflictActionOutcome::AlreadyAtTarget, crate::RawTransactionConflictActionOutcome::StaleRevision); return; }