// file: crates/ksp-app-backfill-desk/unit_tests/backfill_request.rs // version: 4 fn ready_options() -> crate::BackfillDeskOptionsDto { let limits = crate::backfill_request_limits(); assert!(limits.is_ok()); let limits = match limits { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => crate::BackfillRequestLimitsDto { default_hydration_concurrency: 1, default_max_candidates: 1, default_max_pages: 1, default_page_size: 1, max_hydration_concurrency: 1, max_candidates: 1, max_pages: 1, max_page_size: 1, max_signature_text_bytes: 88, min_signature_text_bytes: 64, }, }; return crate::BackfillDeskOptionsDto { commitments: crate::backfill_commitment_codes(), composition_ready: true, configured_networks: vec!["mainnet".to_owned()], http_routes: vec![ crate::BackfillHttpRouteOptionDto { pooled: true, providers: vec!["publicnode".to_owned(), "solana-public".to_owned()], role: "backfill_pool".to_owned(), }, crate::BackfillHttpRouteOptionDto { pooled: false, providers: vec!["publicnode".to_owned()], role: "backfill_publicnode".to_owned() }, ], limits, network_coherent: true, program_id_options: crate::program_id_autocomplete_options(), scope_kinds: crate::backfill_scope_kind_codes(), store_diagnostic: std::option::Option::None, store_network: std::option::Option::Some("mainnet".to_owned()), store_ready: true, transport_diagnostic: std::option::Option::None, transport_ready: true, }; } fn request(scope_kind: &str) -> crate::BackfillStartRequestDto { return crate::BackfillStartRequestDto { address: std::option::Option::Some("11111111111111111111111111111111".to_owned()), anchor_signature: std::option::Option::None, commitment: "finalized".to_owned(), explicit_signatures: std::vec::Vec::new(), hydration_concurrency: 4, http_role: "backfill_pool".to_owned(), max_candidates: 100, max_pages: 10, min_context_slot: std::option::Option::Some("123456".to_owned()), page_size: 100, scope_kind: scope_kind.to_owned(), }; } fn job_id() -> std::option::Option { let job_id = ksp_job_api::JobId::new("request-mapping-test"); assert!(job_id.is_ok()); return match job_id { std::result::Result::Ok(value) => std::option::Option::Some(value), std::result::Result::Err(_) => std::option::Option::None, }; } #[test] fn latest_address_maps_to_backend_network_role_commitment_and_bounds() { let job_id = job_id(); let job_id = match job_id { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let mapped = crate::map_backfill_request(request("latest_address"), &ready_options(), job_id); assert!(mapped.is_ok()); let mapped = match mapped { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; assert_eq!(mapped.network().as_str(), "mainnet"); assert_eq!(mapped.role().as_str(), "backfill_pool"); assert_eq!(mapped.commitment(), ksp_job_backfill_lib::BackfillCommitment::Finalized); assert_eq!(mapped.scope().kind(), ksp_job_backfill_lib::BackfillScopeKind::LatestAddress); assert_eq!(mapped.page_size(), 100); assert_eq!(mapped.max_pages(), 10); assert_eq!(mapped.max_candidates(), 100); assert_eq!(mapped.hydration_concurrency(), 4); assert_eq!(mapped.min_context_slot(), std::option::Option::Some(123456)); } #[test] fn before_and_after_scopes_require_an_exact_anchor_shape() { for scope_kind in ["before_address", "after_address"] { let job_id = job_id(); let job_id = match job_id { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let mut input = request(scope_kind); input.anchor_signature = std::option::Option::Some("1".repeat(64)); let mapped = crate::map_backfill_request(input, &ready_options(), job_id); assert!(mapped.is_ok(), "scope {scope_kind} should map with a bounded anchor"); } let job_id = job_id(); let job_id = match job_id { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let missing_anchor = crate::map_backfill_request(request("before_address"), &ready_options(), job_id); assert!(missing_anchor.is_err()); } #[test] fn explicit_signatures_reject_address_context_and_deduplicate_in_job_contract() { let request_job_id = job_id(); let request_job_id = match request_job_id { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let mut input = request("explicit_signatures"); input.address = std::option::Option::None; input.min_context_slot = std::option::Option::None; input.explicit_signatures = vec!["1".repeat(64), "1".repeat(64), "2".repeat(64)]; let mapped = crate::map_backfill_request(input, &ready_options(), request_job_id); assert!(mapped.is_ok()); let mapped = match mapped { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let signatures = mapped.scope().signatures(); assert!(signatures.is_some()); if let std::option::Option::Some(signatures) = signatures { assert_eq!(signatures.len(), 2); } let mut hostile = request("explicit_signatures"); hostile.address = std::option::Option::None; hostile.min_context_slot = std::option::Option::None; hostile.explicit_signatures = vec![" 1".to_owned()]; let hostile_job_id = job_id(); let hostile_job_id = match hostile_job_id { std::option::Option::Some(value) => value, std::option::Option::None => return, }; assert!(crate::map_backfill_request(hostile, &ready_options(), hostile_job_id).is_err()); } #[test] fn route_inventory_and_composition_are_revalidated_before_mapping() { let first_job_id = job_id(); let first_job_id = match first_job_id { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let mut unknown_route = request("latest_address"); unknown_route.http_role = "provider-from-frontend".to_owned(); let rejected = crate::map_backfill_request(unknown_route, &ready_options(), first_job_id); assert!(rejected.is_err()); let mut unavailable = ready_options(); unavailable.composition_ready = false; let second_job_id = job_id(); let second_job_id = match second_job_id { std::option::Option::Some(value) => value, std::option::Option::None => return, }; assert!(crate::map_backfill_request(request("latest_address"), &unavailable, second_job_id).is_err()); } #[test] fn request_preview_never_contains_address_or_signature_values() { let job_id = job_id(); let job_id = match job_id { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let mapped = crate::map_backfill_request(request("latest_address"), &ready_options(), job_id); assert!(mapped.is_ok()); let mapped = match mapped { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let preview = crate::project_backfill_request(&mapped); assert!(preview.is_ok()); let preview = match preview { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let serialized = serde_json::to_string(&preview); assert!(serialized.is_ok()); if let std::result::Result::Ok(serialized) = serialized { assert!(!serialized.contains("11111111111111111111111111111111")); assert!(!serialized.contains(&"1".repeat(64))); assert!(serialized.contains("mainnet")); assert!(serialized.contains("backfill_pool")); } }