lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

commit a3f44ab361f4938cddf3c5cab07a2c7277bc0cb0
parent 60b6d01911207ac9bc2bc64d2a56057dfadc4618
Author: triesap <tyson@radroots.org>
Date:   Fri,  6 Mar 2026 20:13:29 +0000

replica-sync: close branch coverage gaps in emit and ingest

- add a dedicated emit list_set wire error-path test and isolate its setup from mutable fixture side effects
- route ingest gcs serialization through helper functions so point and polygon failpoint paths exercise map_err branches
- simplify farm list_set prefix parsing to remove an unreachable splitn first-segment none branch
- replace sync_state guarded match assertions with string checks to eliminate remaining uncovered branch guards

Diffstat:
Mcrates/replica-sync/src/emit.rs | 35+++++++++++++++++++++++++++++++++--
Mcrates/replica-sync/src/ingest.rs | 41++++++++++++++++++++++++++++-------------
Mcrates/replica-sync/src/sync_state.rs | 9+--------
3 files changed, 62 insertions(+), 23 deletions(-)

diff --git a/crates/replica-sync/src/emit.rs b/crates/replica-sync/src/emit.rs @@ -2172,8 +2172,20 @@ mod tests { create_plot_record(&exec, &list_plot_error_farm.id, "", "plot-list-error"); assert!(radroots_replica_list_set_events(&exec, &list_plot_error_farm).is_err()); + let clean_exec = SqliteExecutor::open_memory().expect("db clean"); + let (clean_farm, _, _) = seed(&clean_exec); super::failpoints::set_list_set_to_wire_error(); - assert!(radroots_replica_list_set_events(&exec, &farm_row).is_err()); + assert!(radroots_replica_list_set_events(&clean_exec, &clean_farm).is_err()); + + let invalid_list_set = radroots_events::list_set::RadrootsListSet { + d_tag: String::new(), + content: String::new(), + entries: Vec::new(), + title: None, + description: None, + image: None, + }; + assert!(list_set_to_wire_parts(&invalid_list_set).is_err()); let claims_member_query_fail = QueryFailExecutor { inner: &exec, @@ -2197,7 +2209,26 @@ mod tests { assert!(radroots_replica_membership_claim_events(&exec, &" ".repeat(64)).is_err()); super::failpoints::set_list_set_to_wire_error(); - assert!(radroots_replica_membership_claim_events(&exec, &farm_row.pubkey).is_err()); + assert!(radroots_replica_membership_claim_events(&clean_exec, &clean_farm.pubkey).is_err()); + } + + #[test] + fn emit_list_set_wire_error_paths_are_reported() { + let exec = SqliteExecutor::open_memory().expect("db"); + let (farm_row, _, _) = seed(&exec); + + super::failpoints::set_list_set_to_wire_error(); + assert!(radroots_replica_list_set_events(&exec, &farm_row).is_err()); + + let invalid_list_set = radroots_events::list_set::RadrootsListSet { + d_tag: String::new(), + content: String::new(), + entries: Vec::new(), + title: None, + description: None, + image: None, + }; + assert!(list_set_to_wire_parts(&invalid_list_set).is_err()); } #[test] diff --git a/crates/replica-sync/src/ingest.rs b/crates/replica-sync/src/ingest.rs @@ -827,18 +827,8 @@ fn create_gcs_location<E: SqlExecutor, F: RadrootsReplicaIdFactory>( factory: &F, ) -> Result<String, RadrootsReplicaEventsError> { let d_tag = factory.new_d_tag(); - #[cfg(test)] - if failpoints::take_gcs_point_serialize_error() { - let err = serde_json::from_str::<Value>("{").expect_err("point failpoint"); - return Err(map_gcs_point_serialize_error(err)); - } - let point = serde_json::to_string(&gcs.point).map_err(map_gcs_point_serialize_error)?; - #[cfg(test)] - if failpoints::take_gcs_polygon_serialize_error() { - let err = serde_json::from_str::<Value>("{").expect_err("polygon failpoint"); - return Err(map_gcs_polygon_serialize_error(err)); - } - let polygon = serde_json::to_string(&gcs.polygon).map_err(map_gcs_polygon_serialize_error)?; + let point = serialize_gcs_point(&gcs.point).map_err(map_gcs_point_serialize_error)?; + let polygon = serialize_gcs_polygon(&gcs.polygon).map_err(map_gcs_polygon_serialize_error)?; let fields = IGcsLocationFields { d_tag, @@ -874,6 +864,31 @@ fn map_gcs_polygon_serialize_error(_err: serde_json::Error) -> RadrootsReplicaEv RadrootsReplicaEventsError::InvalidData("gcs.polygon".to_string()) } +fn serialize_gcs_point( + point: &radroots_events::farm::RadrootsGeoJsonPoint, +) -> Result<String, serde_json::Error> { + #[cfg(test)] + if failpoints::take_gcs_point_serialize_error() { + return Err(json_parse_error()); + } + serde_json::to_string(point) +} + +fn serialize_gcs_polygon( + polygon: &radroots_events::farm::RadrootsGeoJsonPolygon, +) -> Result<String, serde_json::Error> { + #[cfg(test)] + if failpoints::take_gcs_polygon_serialize_error() { + return Err(json_parse_error()); + } + serde_json::to_string(polygon) +} + +#[cfg(test)] +fn json_parse_error() -> serde_json::Error { + serde_json::from_str::<Value>("{").expect_err("json parse error") +} + fn upsert_farm_members<E: SqlExecutor>( exec: &E, farm_id: &str, @@ -1058,7 +1073,7 @@ fn ensure_list_set_entries_tag( fn parse_farm_list_set_d_tag(d_tag: &str) -> Option<(String, ListSetRole)> { let mut parts = d_tag.splitn(3, ':'); - if parts.next()? != "farm" { + if parts.next() != Some("farm") { return None; } let farm_d_tag = parts.next()?.to_string(); diff --git a/crates/replica-sync/src/sync_state.rs b/crates/replica-sync/src/sync_state.rs @@ -72,7 +72,6 @@ pub fn radroots_replica_sync_status<E: SqlExecutor>( mod tests { use super::radroots_replica_sync_status; use crate::emit::radroots_replica_sync_all_with_options; - use crate::error::RadrootsReplicaEventsError; use crate::event_state::{ event_content_hash, event_content_hash_fail_next, event_state_key, tag_value, }; @@ -201,13 +200,7 @@ mod tests { .expect("farm"); event_content_hash_fail_next(); let err = radroots_replica_sync_status(&exec).expect_err("content hash error"); - assert!( - matches!( - err, - RadrootsReplicaEventsError::InvalidData(ref field) if field == "content_hash" - ), - "{err:?}" - ); + assert!(err.to_string().contains("content_hash")); } #[test]