// file: crates/ksp-job-backfill-lib/unit_tests/checkpoint.rs // version: 2 fn signature(character: char) -> std::option::Option { return crate::BackfillSignature::new(character.to_string().repeat(crate::MIN_BACKFILL_SIGNATURE_TEXT_BYTES)).ok(); } fn request(scope: crate::BackfillScope) -> std::option::Option { let job_id = match ksp_job_api::JobId::new("backfill:checkpoint-test") { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return std::option::Option::None, }; let network = match ksp_store_lib::RawNetworkId::new("devnet") { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return std::option::Option::None, }; return crate::BackfillRequest::new( job_id, network, ksp_onchain_transport_lib::HttpRoleName::new("history"), crate::BackfillCommitment::Confirmed, scope, 100, 10, 10, 4, std::option::Option::None, ) .ok(); } fn candidate(request: &crate::BackfillRequest, character: char) -> std::option::Option { let signature = match signature(character) { std::option::Option::Some(value) => value, std::option::Option::None => return std::option::Option::None, }; let identity = crate::BackfillCandidateIdentity::new(request.network().clone(), signature); return std::option::Option::Some(crate::BackfillCandidate::new(identity, std::option::Option::None)); } fn discovery( request: &crate::BackfillRequest, characters: &[char], boundary: crate::BackfillDiscoveryBoundary, ) -> std::option::Option { let mut candidates = std::vec::Vec::with_capacity(characters.len()); for character in characters { let value = match candidate(request, *character) { std::option::Option::Some(value) => value, std::option::Option::None => return std::option::Option::None, }; candidates.push(value); } return std::option::Option::Some(crate::BackfillDiscovery::new(request.network().clone(), request.scope_fingerprint(), candidates, 1, boundary)); } #[test] fn pre_008_frontier_advances_only_across_contiguous_durable_results() { let mut frontier = crate::CompletionFrontier::new(4); assert!(frontier.mark_durable(1).is_ok()); assert_eq!(frontier.contiguous_completed(), 0); assert!(frontier.mark_durable(0).is_ok()); assert_eq!(frontier.contiguous_completed(), 2); assert!(frontier.mark_durable(3).is_ok()); assert_eq!(frontier.contiguous_completed(), 2); assert!(frontier.mark_durable(2).is_ok()); assert_eq!(frontier.contiguous_completed(), 4); return; } #[test] fn pre_008_checkpoint_is_bound_to_job_and_scope_fingerprint() { let scope = crate::BackfillScope::latest_address(ksp_core_lib::Pubkey::new_from_array([1_u8; 32])); let primary_request = match request(scope) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let other_job = match ksp_job_api::JobId::new("backfill:other") { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let wrong_job = crate::BackfillCheckpoint::new(other_job, primary_request.scope_fingerprint(), 0, std::option::Option::None); let result = primary_request.clone().with_checkpoint(wrong_job); assert!(result.is_err()); if let std::result::Result::Err(error) = result { assert_eq!(error.code(), crate::ERROR_CODE_BACKFILL_CHECKPOINT_INVALID); } let other_scope = crate::BackfillScope::latest_address(ksp_core_lib::Pubkey::new_from_array([2_u8; 32])); let other_request = match request(other_scope) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let wrong_scope = crate::BackfillCheckpoint::new(primary_request.job_id().clone(), other_request.scope_fingerprint(), 0, std::option::Option::None); assert!(primary_request.with_checkpoint(wrong_scope).is_err()); return; } #[test] fn pre_008_before_checkpoint_is_cumulative_and_tracks_last_contiguous_candidate() { let anchor = match signature('8') { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let scope = crate::BackfillScope::before_address(ksp_core_lib::Pubkey::new_from_array([3_u8; 32]), anchor); let request = match request(scope) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let first_discovery = match discovery(&request, &['7', '6', '5'], crate::BackfillDiscoveryBoundary::RpcBoundary) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let mut first_frontier = crate::CompletionFrontier::new(3); assert!(first_frontier.mark_durable(1).is_ok()); assert_eq!(first_frontier.contiguous_completed(), 0); assert!(first_frontier.mark_durable(0).is_ok()); let first = match crate::checkpoint_from_frontier(&request, &first_discovery, &first_frontier) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; assert_eq!(first.completed_prefix(), 2); let expected_first = "6".repeat(64); assert_eq!(first.resume_before().map(crate::BackfillSignature::as_str), std::option::Option::Some(expected_first.as_str())); let resumed = match request.with_checkpoint(first) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let second_discovery = match discovery(&resumed, &['5', '4'], crate::BackfillDiscoveryBoundary::RpcBoundary) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let mut second_frontier = crate::CompletionFrontier::new(2); assert!(second_frontier.mark_durable(0).is_ok()); let second = match crate::checkpoint_from_frontier(&resumed, &second_discovery, &second_frontier) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; assert_eq!(second.completed_prefix(), 3); let expected_second = "5".repeat(64); assert_eq!(second.resume_before().map(crate::BackfillSignature::as_str), std::option::Option::Some(expected_second.as_str())); return; } #[test] fn pre_008_after_anchor_not_reached_never_advances_checkpoint() { let anchor = match signature('1') { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let scope = crate::BackfillScope::after_address(ksp_core_lib::Pubkey::new_from_array([4_u8; 32]), anchor); let request = match request(scope) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let partial = match discovery(&request, &['7', '6', '5'], crate::BackfillDiscoveryBoundary::AfterAnchorNotReached) { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let mut frontier = crate::CompletionFrontier::new(3); assert!(frontier.mark_durable(0).is_ok()); assert!(frontier.mark_durable(1).is_ok()); let checkpoint = match crate::checkpoint_from_frontier(&request, &partial, &frontier) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; assert_eq!(checkpoint.completed_prefix(), 0); return; }