// file: crates/ksp-job-backfill-lib/unit_tests/request.rs // version: 3 fn signature(character: char) -> std::option::Option { return match crate::BackfillSignature::new(character.to_string().repeat(crate::MIN_BACKFILL_SIGNATURE_TEXT_BYTES)) { std::result::Result::Ok(value) => std::option::Option::Some(value), std::result::Result::Err(_) => std::option::Option::None, }; } fn network(value: &str) -> std::option::Option { return match ksp_store_lib::RawNetworkId::new(value) { std::result::Result::Ok(value) => std::option::Option::Some(value), std::result::Result::Err(_) => std::option::Option::None, }; } fn job_id(value: &str) -> std::option::Option { return match ksp_job_api::JobId::new(value) { std::result::Result::Ok(value) => std::option::Option::Some(value), std::result::Result::Err(_) => std::option::Option::None, }; } #[test] fn pre_005_signature_shape_is_bounded_and_debug_redacted() { let minimum = crate::BackfillSignature::new("1".repeat(crate::MIN_BACKFILL_SIGNATURE_TEXT_BYTES)); assert!(minimum.is_ok()); let maximum = crate::BackfillSignature::new("z".repeat(crate::MAX_BACKFILL_SIGNATURE_TEXT_BYTES)); assert!(maximum.is_ok()); assert!(crate::BackfillSignature::new("1".repeat(crate::MIN_BACKFILL_SIGNATURE_TEXT_BYTES - 1)).is_err()); assert!(crate::BackfillSignature::new("1".repeat(crate::MAX_BACKFILL_SIGNATURE_TEXT_BYTES + 1)).is_err()); assert!(crate::BackfillSignature::new(format!("{}0", "1".repeat(crate::MIN_BACKFILL_SIGNATURE_TEXT_BYTES - 1))).is_err()); let minimum = match minimum { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let debug = format!("{minimum:?}"); assert_eq!(debug, "BackfillSignature(..)"); assert!(!debug.contains(minimum.as_str())); return; } #[test] fn pre_005_explicit_scope_deduplicates_at_first_occurrence_without_reordering() { let first = match signature('1') { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let second = match signature('2') { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let scope_result = crate::BackfillScope::explicit_signatures(std::vec![first.clone(), second.clone(), first.clone(), second.clone()]); assert!(scope_result.is_ok()); let scope = match scope_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let signatures = match scope.signatures() { std::option::Option::Some(value) => value, std::option::Option::None => return, }; assert_eq!(signatures, &[first, second]); let debug = format!("{scope:?}"); assert!(debug.contains("signature_count")); assert!(!debug.contains(signatures[0].as_str())); return; } #[test] fn pre_005_request_bounds_are_exact_and_explicit_context_is_rejected() { let network = match network("devnet") { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let job_id = match job_id("backfill:test") { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let role = ksp_onchain_transport_lib::HttpRoleName::new("history"); let address = ksp_core_lib::Pubkey::new_from_array([7_u8; 32]); let scope = crate::BackfillScope::latest_address(address); let valid = crate::BackfillRequest::new( job_id.clone(), network.clone(), role.clone(), crate::BackfillCommitment::Confirmed, scope.clone(), crate::MAX_BACKFILL_PAGE_SIZE, crate::MAX_BACKFILL_PAGES, crate::MAX_BACKFILL_CANDIDATES, crate::MAX_BACKFILL_HYDRATION_CONCURRENCY, std::option::Option::Some(1), ); assert!(valid.is_ok()); for (page_size, max_pages, max_candidates, concurrency) in [ (0, 1, 1, 1), (crate::MAX_BACKFILL_PAGE_SIZE + 1, 1, 1, 1), (1, 0, 1, 1), (1, crate::MAX_BACKFILL_PAGES + 1, 1, 1), (1, 1, 0, 1), (1, 1, crate::MAX_BACKFILL_CANDIDATES + 1, 1), (1, 1, 1, 0), (1, 1, 1, crate::MAX_BACKFILL_HYDRATION_CONCURRENCY + 1), ] { let result = crate::BackfillRequest::new( job_id.clone(), network.clone(), role.clone(), crate::BackfillCommitment::Finalized, scope.clone(), page_size, max_pages, max_candidates, concurrency, std::option::Option::None, ); assert!(result.is_err()); } let explicit_signature = match signature('3') { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let explicit_scope = crate::BackfillScope::explicit_signatures(std::vec![explicit_signature]); let explicit_scope = match explicit_scope { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let explicit_with_context = crate::BackfillRequest::new(job_id, network, role, crate::BackfillCommitment::Confirmed, explicit_scope, 1, 1, 1, 1, std::option::Option::Some(10)); assert!(explicit_with_context.is_err()); return; } #[test] fn pre_005_scope_fingerprint_is_network_semantic_and_transport_source_independent() { let signature = match signature('4') { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let scope_result = crate::BackfillScope::explicit_signatures(std::vec![signature]); let scope = match scope_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; 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 first_job = match job_id("backfill:first") { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let second_job = match job_id("backfill:second") { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let first = crate::BackfillRequest::new( first_job, devnet.clone(), ksp_onchain_transport_lib::HttpRoleName::new("primary-http"), crate::BackfillCommitment::Confirmed, scope.clone(), 100, 5, 10, 1, std::option::Option::None, ); let second = crate::BackfillRequest::new( second_job, devnet, ksp_onchain_transport_lib::HttpRoleName::new("fallback-http"), crate::BackfillCommitment::Confirmed, scope.clone(), 100, 5, 10, 64, std::option::Option::None, ); let other_network = crate::BackfillRequest::new( match job_id("backfill:third") { std::option::Option::Some(value) => value, std::option::Option::None => return, }, mainnet, ksp_onchain_transport_lib::HttpRoleName::new("primary-http"), crate::BackfillCommitment::Confirmed, scope, 100, 5, 10, 1, std::option::Option::None, ); let first = match first { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let second = match second { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let other_network = match other_network { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; assert_eq!(first.scope_fingerprint(), second.scope_fingerprint()); assert_ne!(first.scope_fingerprint(), other_network.scope_fingerprint()); return; } #[test] fn pre_005_scope_kind_and_anchor_are_distinct_semantics() { let anchor = match signature('5') { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let address = ksp_core_lib::Pubkey::new_from_array([9_u8; 32]); let before = crate::BackfillScope::before_address(address, anchor.clone()); let after = crate::BackfillScope::after_address(address, anchor); assert_eq!(before.kind(), crate::BackfillScopeKind::BeforeAddress); assert_eq!(after.kind(), crate::BackfillScopeKind::AfterAddress); assert!(before.anchor().is_some()); assert!(after.anchor().is_some()); assert_ne!(before, after); return; } #[test] fn pre_011_resume_reissues_checkpoint_for_new_job_without_changing_scope_semantics() { let network = match network("mainnet") { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let original_job = match job_id("backfill:resume-original") { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let resumed_job = match job_id("backfill:resume-next") { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let request = crate::BackfillRequest::new( original_job.clone(), network, ksp_onchain_transport_lib::HttpRoleName::new("backfill_pool"), crate::BackfillCommitment::Finalized, crate::BackfillScope::before_address( ksp_core_lib::Pubkey::new_from_array([11_u8; 32]), match signature('8') { std::option::Option::Some(value) => value, std::option::Option::None => return, }, ), 100, 10, 1000, 4, std::option::Option::Some(42), ); let request = match request { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let resume_before = match signature('9') { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let checkpoint = crate::BackfillCheckpoint::new(original_job, request.scope_fingerprint(), 7, std::option::Option::Some(resume_before.clone())); let resumed = request.resume_for_job(resumed_job.clone(), checkpoint); assert!(resumed.is_ok()); let resumed = match resumed { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; assert_eq!(resumed.job_id(), &resumed_job); assert_eq!(resumed.scope_fingerprint(), request.scope_fingerprint()); assert_eq!(resumed.network(), request.network()); assert_eq!(resumed.role(), request.role()); assert_eq!(resumed.commitment(), request.commitment()); assert_eq!(resumed.scope(), request.scope()); assert_eq!(resumed.page_size(), request.page_size()); assert_eq!(resumed.max_pages(), request.max_pages()); assert_eq!(resumed.max_candidates(), request.max_candidates()); assert_eq!(resumed.hydration_concurrency(), request.hydration_concurrency()); assert_eq!(resumed.min_context_slot(), request.min_context_slot()); let checkpoint = resumed.checkpoint(); assert!(checkpoint.is_some()); if let std::option::Option::Some(checkpoint) = checkpoint { assert_eq!(checkpoint.job_id(), &resumed_job); assert_eq!(checkpoint.scope_fingerprint(), request.scope_fingerprint()); assert_eq!(checkpoint.completed_prefix(), 7); assert_eq!(checkpoint.resume_before(), std::option::Option::Some(&resume_before)); } }