commit 29a52a6c8b2a1aa1c096294de65d48176153dbfc
parent 2eac6175e6622501d26d75ee494be4a1038d1de2
Author: triesap <tyson@radroots.org>
Date: Fri, 6 Mar 2026 16:55:16 +0000
replica-sync: expand ingest error-path coverage
- add queryfail executor coverage helpers in ingest tests
- exercise profile farm plot and list-set failure branches with targeted sql needles
- add parser and state-write error assertions for ingest edge paths
- preserve runtime behavior while increasing replica-sync test path coverage
Diffstat:
1 file changed, 626 insertions(+), 16 deletions(-)
diff --git a/crates/replica-sync/src/ingest.rs b/crates/replica-sync/src/ingest.rs
@@ -1186,6 +1186,42 @@ mod tests {
}
}
+ struct QueryFailExecutor<'a> {
+ inner: &'a SqliteExecutor,
+ needle: &'static str,
+ err: SqlError,
+ }
+
+ impl SqlExecutor for QueryFailExecutor<'_> {
+ fn exec(&self, sql: &str, params_json: &str) -> Result<ExecOutcome, SqlError> {
+ let normalized = sql.to_ascii_lowercase();
+ if normalized.contains(self.needle) {
+ return Err(self.err.clone());
+ }
+ self.inner.exec(sql, params_json)
+ }
+
+ fn query_raw(&self, sql: &str, params_json: &str) -> Result<String, SqlError> {
+ let normalized = sql.to_ascii_lowercase();
+ if normalized.contains(self.needle) {
+ return Err(self.err.clone());
+ }
+ self.inner.query_raw(sql, params_json)
+ }
+
+ fn begin(&self) -> Result<(), SqlError> {
+ self.inner.begin()
+ }
+
+ fn commit(&self) -> Result<(), SqlError> {
+ self.inner.commit()
+ }
+
+ fn rollback(&self) -> Result<(), SqlError> {
+ self.inner.rollback()
+ }
+ }
+
fn sample_gcs(lat: f64, lng: f64, geohash: &str) -> RadrootsGcsLocation {
RadrootsGcsLocation {
lat,
@@ -1484,7 +1520,10 @@ mod tests {
assert!(begin_err.to_string().contains("replica_sync.sql"));
assert!(begin_executor.commit().is_ok());
assert_eq!(
- begin_executor.exec("select 1", "[]").expect_err("exec").code(),
+ begin_executor
+ .exec("select 1", "[]")
+ .expect_err("exec")
+ .code(),
"ERR_UNSUPPORTED_PLATFORM"
);
assert_eq!(
@@ -2163,8 +2202,7 @@ mod tests {
let claims = farm_list_sets::member_of_farms_list_set(vec![farm_pubkey.clone()])
.expect("claims list set");
- let claims_event =
- list_set_event(504, &profile_pubkey, 54, KIND_LIST_SET_GENERIC, &claims);
+ let claims_event = list_set_event(504, &profile_pubkey, 54, KIND_LIST_SET_GENERIC, &claims);
assert_eq!(
ingest_list_set_event(&pass, &claims_event).expect("claims list set"),
RadrootsReplicaIngestOutcome::Applied
@@ -2193,8 +2231,13 @@ mod tests {
image: None,
};
assert!(
- upsert_farm_members(&pass, &farm_row.id, ListSetRole::Members, &mixed_member_entries)
- .is_ok()
+ upsert_farm_members(
+ &pass,
+ &farm_row.id,
+ ListSetRole::Members,
+ &mixed_member_entries
+ )
+ .is_ok()
);
let mixed_claim_entries = RadrootsListSet {
d_tag: "member_of.farms".to_string(),
@@ -2344,8 +2387,8 @@ mod tests {
ingest_profile_event(&pass_txn, &profile_event_row).expect("txn profile"),
RadrootsReplicaIngestOutcome::Applied
);
- let profile_decision = event_state_decision(&pass_txn, &profile_event_row, "")
- .expect("profile decision");
+ let profile_decision =
+ event_state_decision(&pass_txn, &profile_event_row, "").expect("profile decision");
assert!(!profile_decision.apply);
assert!(
radroots_replica_ingest_event_state(
@@ -2357,8 +2400,12 @@ mod tests {
.is_ok()
);
assert_eq!(
- radroots_replica_ingest_event_with_factory(&pass_txn, &profile_event_row, &FixedFactory)
- .expect("txn wrapper"),
+ radroots_replica_ingest_event_with_factory(
+ &pass_txn,
+ &profile_event_row,
+ &FixedFactory
+ )
+ .expect("txn wrapper"),
RadrootsReplicaIngestOutcome::Skipped
);
@@ -2418,7 +2465,9 @@ mod tests {
assert!(upsert_plot_tags(&pass_txn, &plot_id, Some(vec!["y".to_string()])).is_ok());
assert!(clear_farm_locations(&pass_txn, &farm_row.id).is_ok());
assert!(clear_plot_locations(&pass_txn, &plot_id).is_ok());
- assert!(create_gcs_location(&pass_txn, sample_gcs(14.0, 24.0, "s4"), &FixedFactory).is_ok());
+ assert!(
+ create_gcs_location(&pass_txn, sample_gcs(14.0, 24.0, "s4"), &FixedFactory).is_ok()
+ );
assert!(
upsert_farm_location(
&pass_txn,
@@ -2455,8 +2504,8 @@ mod tests {
upsert_farm_members(&pass_txn, &farm_row.id, ListSetRole::Members, &members_list)
.is_ok()
);
- let member_of_list = farm_list_sets::member_of_farms_list_set(vec![farm_pubkey.clone()])
- .expect("member_of");
+ let member_of_list =
+ farm_list_sets::member_of_farms_list_set(vec![farm_pubkey.clone()]).expect("member_of");
assert!(upsert_member_claims(&pass_txn, &"m".repeat(64), &member_of_list).is_ok());
let rollback_count = Arc::new(AtomicUsize::new(0));
@@ -2470,8 +2519,10 @@ mod tests {
assert!(ingest_profile_event(&txn, &profile_event_row).is_err());
assert!(event_state_decision(&txn, &profile_event_row, "").is_err());
assert!(radroots_replica_ingest_event_state(&txn, &profile_event_row, "", "hash").is_err());
- assert!(radroots_replica_ingest_event_with_factory(&txn, &profile_event_row, &FixedFactory)
- .is_err());
+ assert!(
+ radroots_replica_ingest_event_with_factory(&txn, &profile_event_row, &FixedFactory)
+ .is_err()
+ );
assert!(ingest_farm_event(&txn, &farm_event_row, &FixedFactory).is_err());
@@ -2513,9 +2564,568 @@ mod tests {
)
.is_err()
);
+ assert!(upsert_farm_members(&txn, "farm-id", ListSetRole::Members, &members_list).is_err());
+ assert!(upsert_member_claims(&txn, &"m".repeat(64), &member_of_list).is_err());
+ }
+
+ #[test]
+ fn ingest_sqlite_queryfail_and_parser_edges_are_covered() {
+ let exec = SqliteExecutor::open_memory().expect("db");
+ migrations::run_all_up(&exec).expect("migrations");
+ let pass_through = QueryFailExecutor {
+ inner: &exec,
+ needle: "__missing__",
+ err: SqlError::Internal,
+ };
+ assert!(pass_through.query_raw("select 1", "[]").is_ok());
assert!(
- upsert_farm_members(&txn, "farm-id", ListSetRole::Members, &members_list).is_err()
+ pass_through
+ .exec(
+ "create table if not exists coverage_probe (id integer)",
+ "[]"
+ )
+ .is_ok()
+ );
+ let _ = pass_through.begin();
+ let _ = pass_through.rollback();
+ let _ = pass_through.commit();
+
+ let farm_pubkey = "f".repeat(64);
+ let farm_d_tag = "AAAAAAAAAAAAAAAAAAAAAA";
+ let plot_d_tag = "AAAAAAAAAAAAAAAAAAAAAQ";
+ let profile_pubkey = "p".repeat(64);
+
+ let profile = profile_event(
+ 800,
+ &profile_pubkey,
+ 80,
+ Some(RadrootsProfileType::Individual),
+ "profile-base",
+ );
+ let mut profile_bad_content = profile.clone();
+ profile_bad_content.content = "{".to_string();
+ assert!(ingest_profile_event(&exec, &profile_bad_content).is_err());
+
+ let profile_query_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "nostr_profile",
+ err: SqlError::Internal,
+ };
+ assert!(ingest_profile_event(&profile_query_fail, &profile).is_err());
+
+ assert_eq!(
+ ingest_profile_event(&exec, &profile).expect("profile seed"),
+ RadrootsReplicaIngestOutcome::Applied
+ );
+ let profile_update = profile_event(
+ 801,
+ &profile_pubkey,
+ 81,
+ Some(RadrootsProfileType::Individual),
+ "profile-update",
+ );
+ let profile_update_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "update nostr_profile",
+ err: SqlError::Internal,
+ };
+ assert!(ingest_profile_event(&profile_update_fail, &profile_update).is_err());
+
+ let profile_create_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "insert into nostr_profile",
+ err: SqlError::Internal,
+ };
+ let profile_new = profile_event(
+ 802,
+ &"n".repeat(64),
+ 82,
+ Some(RadrootsProfileType::Individual),
+ "profile-new",
+ );
+ assert!(ingest_profile_event(&profile_create_fail, &profile_new).is_err());
+
+ let profile_state_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "nostr_event_state",
+ err: SqlError::Internal,
+ };
+ let profile_state_event = profile_event(
+ 803,
+ &"s".repeat(64),
+ 83,
+ Some(RadrootsProfileType::Individual),
+ "profile-state",
+ );
+ assert!(ingest_profile_event(&profile_state_fail, &profile_state_event).is_err());
+
+ let farm_seed = farm_event(
+ 810,
+ &farm_pubkey,
+ 90,
+ farm_d_tag,
+ "farm-seed",
+ Some(RadrootsFarmLocation {
+ primary: Some("primary".to_string()),
+ city: Some("city".to_string()),
+ region: Some("region".to_string()),
+ country: Some("country".to_string()),
+ gcs: sample_gcs(10.0, 20.0, "s0"),
+ }),
+ Some(vec!["seed".to_string()]),
+ );
+ assert_eq!(
+ ingest_farm_event(&exec, &farm_seed, &FixedFactory).expect("farm seed"),
+ RadrootsReplicaIngestOutcome::Applied
+ );
+
+ let mut farm_bad_content = farm_seed.clone();
+ farm_bad_content.content = "{".to_string();
+ assert!(ingest_farm_event(&exec, &farm_bad_content, &FixedFactory).is_err());
+
+ let farm_query_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "from farm",
+ err: SqlError::Internal,
+ };
+ let farm_query_event = farm_event(
+ 811,
+ &"q".repeat(64),
+ 91,
+ farm_d_tag,
+ "farm-query",
+ None,
+ None,
+ );
+ assert!(ingest_farm_event(&farm_query_fail, &farm_query_event, &FixedFactory).is_err());
+
+ let farm_update_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "update farm",
+ err: SqlError::Internal,
+ };
+ let farm_update = farm_event(
+ 812,
+ &farm_pubkey,
+ 92,
+ farm_d_tag,
+ "farm-update",
+ None,
+ Some(vec!["u".to_string()]),
+ );
+ assert!(ingest_farm_event(&farm_update_fail, &farm_update, &FixedFactory).is_err());
+
+ let farm_create_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "insert into farm",
+ err: SqlError::Internal,
+ };
+ let farm_create = farm_event(
+ 813,
+ &"c".repeat(64),
+ 93,
+ farm_d_tag,
+ "farm-create",
+ None,
+ None,
+ );
+ assert!(ingest_farm_event(&farm_create_fail, &farm_create, &FixedFactory).is_err());
+
+ let farm_tag_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "farm_tag",
+ err: SqlError::Internal,
+ };
+ let farm_tag_event = farm_event(
+ 814,
+ &"t".repeat(64),
+ 94,
+ farm_d_tag,
+ "farm-tag",
+ None,
+ Some(vec!["coffee".to_string()]),
+ );
+ assert!(ingest_farm_event(&farm_tag_fail, &farm_tag_event, &FixedFactory).is_err());
+
+ let farm_gcs_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "gcs_location",
+ err: SqlError::Internal,
+ };
+ let farm_gcs_event = farm_event(
+ 815,
+ &"g".repeat(64),
+ 95,
+ farm_d_tag,
+ "farm-gcs",
+ Some(RadrootsFarmLocation {
+ primary: Some("primary".to_string()),
+ city: None,
+ region: None,
+ country: None,
+ gcs: sample_gcs(11.0, 21.0, "s1"),
+ }),
+ None,
+ );
+ assert!(ingest_farm_event(&farm_gcs_fail, &farm_gcs_event, &FixedFactory).is_err());
+
+ let farm_rel_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "farm_gcs_location",
+ err: SqlError::Internal,
+ };
+ let farm_rel_event = farm_event(
+ 816,
+ &"r".repeat(64),
+ 96,
+ farm_d_tag,
+ "farm-rel",
+ Some(RadrootsFarmLocation {
+ primary: Some("primary".to_string()),
+ city: None,
+ region: None,
+ country: None,
+ gcs: sample_gcs(12.0, 22.0, "s2"),
+ }),
+ None,
+ );
+ assert!(ingest_farm_event(&farm_rel_fail, &farm_rel_event, &FixedFactory).is_err());
+
+ let farm_state_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "nostr_event_state",
+ err: SqlError::Internal,
+ };
+ let farm_state_event = farm_event(
+ 817,
+ &"w".repeat(64),
+ 97,
+ farm_d_tag,
+ "farm-state",
+ None,
+ None,
+ );
+ assert!(ingest_farm_event(&farm_state_fail, &farm_state_event, &FixedFactory).is_err());
+
+ let mut bad_point = sample_gcs(13.0, 23.0, "s3");
+ bad_point.point.coordinates = [f64::NAN, 13.0];
+ let farm_bad_point = farm_event(
+ 818,
+ &"x".repeat(64),
+ 98,
+ farm_d_tag,
+ "farm-bad-point",
+ Some(RadrootsFarmLocation {
+ primary: Some("primary".to_string()),
+ city: None,
+ region: None,
+ country: None,
+ gcs: bad_point,
+ }),
+ None,
+ );
+ assert!(ingest_farm_event(&exec, &farm_bad_point, &FixedFactory).is_err());
+
+ let mut bad_polygon = sample_gcs(14.0, 24.0, "s4");
+ bad_polygon.polygon.coordinates[0][1][0] = f64::NAN;
+ let farm_bad_polygon = farm_event(
+ 819,
+ &"y".repeat(64),
+ 99,
+ farm_d_tag,
+ "farm-bad-polygon",
+ Some(RadrootsFarmLocation {
+ primary: Some("primary".to_string()),
+ city: None,
+ region: None,
+ country: None,
+ gcs: bad_polygon,
+ }),
+ None,
+ );
+ assert!(ingest_farm_event(&exec, &farm_bad_polygon, &FixedFactory).is_err());
+
+ let plot_seed = plot_event(
+ 820,
+ &farm_pubkey,
+ 100,
+ plot_d_tag,
+ RadrootsFarmRef {
+ pubkey: farm_pubkey.clone(),
+ d_tag: farm_d_tag.to_string(),
+ },
+ "plot-seed",
+ Some(RadrootsPlotLocation {
+ primary: Some("primary".to_string()),
+ city: None,
+ region: None,
+ country: None,
+ gcs: sample_gcs(15.0, 25.0, "s5"),
+ }),
+ Some(vec!["orchard".to_string()]),
+ );
+ assert_eq!(
+ ingest_plot_event(&exec, &plot_seed, &FixedFactory).expect("plot seed"),
+ RadrootsReplicaIngestOutcome::Applied
+ );
+
+ let mut plot_bad_content = plot_seed.clone();
+ plot_bad_content.content = "{".to_string();
+ assert!(ingest_plot_event(&exec, &plot_bad_content, &FixedFactory).is_err());
+
+ let plot_query_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "from plot",
+ err: SqlError::Internal,
+ };
+ let plot_query = plot_event(
+ 821,
+ &farm_pubkey,
+ 101,
+ plot_d_tag,
+ RadrootsFarmRef {
+ pubkey: farm_pubkey.clone(),
+ d_tag: farm_d_tag.to_string(),
+ },
+ "plot-query",
+ None,
+ None,
+ );
+ assert!(ingest_plot_event(&plot_query_fail, &plot_query, &FixedFactory).is_err());
+
+ let plot_update_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "update plot",
+ err: SqlError::Internal,
+ };
+ let plot_update = plot_event(
+ 822,
+ &farm_pubkey,
+ 102,
+ plot_d_tag,
+ RadrootsFarmRef {
+ pubkey: farm_pubkey.clone(),
+ d_tag: farm_d_tag.to_string(),
+ },
+ "plot-update",
+ None,
+ Some(vec!["u".to_string()]),
+ );
+ assert!(ingest_plot_event(&plot_update_fail, &plot_update, &FixedFactory).is_err());
+
+ let plot_create_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "insert into plot",
+ err: SqlError::Internal,
+ };
+ let plot_create = plot_event(
+ 823,
+ &farm_pubkey,
+ 103,
+ "AAAAAAAAAAAAAAAAAAAAAg",
+ RadrootsFarmRef {
+ pubkey: farm_pubkey.clone(),
+ d_tag: farm_d_tag.to_string(),
+ },
+ "plot-create",
+ None,
+ None,
+ );
+ assert!(ingest_plot_event(&plot_create_fail, &plot_create, &FixedFactory).is_err());
+
+ let plot_tag_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "plot_tag",
+ err: SqlError::Internal,
+ };
+ let plot_tag_event = plot_event(
+ 824,
+ &farm_pubkey,
+ 104,
+ "AAAAAAAAAAAAAAAAAAAAAw",
+ RadrootsFarmRef {
+ pubkey: farm_pubkey.clone(),
+ d_tag: farm_d_tag.to_string(),
+ },
+ "plot-tag",
+ None,
+ Some(vec!["tag".to_string()]),
+ );
+ assert!(ingest_plot_event(&plot_tag_fail, &plot_tag_event, &FixedFactory).is_err());
+
+ let plot_gcs_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "gcs_location",
+ err: SqlError::Internal,
+ };
+ let plot_gcs_event = plot_event(
+ 825,
+ &farm_pubkey,
+ 105,
+ "AAAAAAAAAAAAAAAAAAAAAw",
+ RadrootsFarmRef {
+ pubkey: farm_pubkey.clone(),
+ d_tag: farm_d_tag.to_string(),
+ },
+ "plot-gcs",
+ Some(RadrootsPlotLocation {
+ primary: Some("primary".to_string()),
+ city: None,
+ region: None,
+ country: None,
+ gcs: sample_gcs(16.0, 26.0, "s6"),
+ }),
+ None,
+ );
+ assert!(ingest_plot_event(&plot_gcs_fail, &plot_gcs_event, &FixedFactory).is_err());
+
+ let plot_rel_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "plot_gcs_location",
+ err: SqlError::Internal,
+ };
+ let plot_rel_event = plot_event(
+ 826,
+ &farm_pubkey,
+ 106,
+ "AAAAAAAAAAAAAAAAAAAAAw",
+ RadrootsFarmRef {
+ pubkey: farm_pubkey.clone(),
+ d_tag: farm_d_tag.to_string(),
+ },
+ "plot-rel",
+ Some(RadrootsPlotLocation {
+ primary: Some("primary".to_string()),
+ city: None,
+ region: None,
+ country: None,
+ gcs: sample_gcs(17.0, 27.0, "s7"),
+ }),
+ None,
+ );
+ assert!(ingest_plot_event(&plot_rel_fail, &plot_rel_event, &FixedFactory).is_err());
+
+ let plot_state_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "nostr_event_state",
+ err: SqlError::Internal,
+ };
+ let plot_state_event = plot_event(
+ 827,
+ &farm_pubkey,
+ 107,
+ "AAAAAAAAAAAAAAAAAAAAAw",
+ RadrootsFarmRef {
+ pubkey: farm_pubkey.clone(),
+ d_tag: farm_d_tag.to_string(),
+ },
+ "plot-state",
+ None,
+ None,
+ );
+ assert!(ingest_plot_event(&plot_state_fail, &plot_state_event, &FixedFactory).is_err());
+
+ let mut list_decode_fail = profile_event(
+ 830,
+ &farm_pubkey,
+ 108,
+ Some(RadrootsProfileType::Farm),
+ "unused",
+ );
+ list_decode_fail.kind = KIND_LIST_SET_GENERIC;
+ list_decode_fail.content = "{".to_string();
+ list_decode_fail.tags = Vec::new();
+ assert!(ingest_list_set_event(&exec, &list_decode_fail).is_err());
+
+ let members_list = farm_list_sets::farm_members_list_set(farm_d_tag, vec!["m".repeat(64)])
+ .expect("members list");
+ let member_event =
+ list_set_event(831, &farm_pubkey, 109, KIND_LIST_SET_GENERIC, &members_list);
+ let list_decision_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "nostr_event_state",
+ err: SqlError::Internal,
+ };
+ assert!(ingest_list_set_event(&list_decision_fail, &member_event).is_err());
+
+ let member_of =
+ farm_list_sets::member_of_farms_list_set(vec![farm_pubkey.clone()]).expect("member-of");
+ let member_of_event =
+ list_set_event(832, &"m".repeat(64), 110, KIND_LIST_SET_GENERIC, &member_of);
+ let claims_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "farm_member_claim",
+ err: SqlError::Internal,
+ };
+ assert!(ingest_list_set_event(&claims_fail, &member_of_event).is_err());
+
+ let claims_state_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "nostr_event_state",
+ err: SqlError::Internal,
+ };
+ assert!(ingest_list_set_event(&claims_state_fail, &member_of_event).is_err());
+
+ let plots_list = farm_list_sets::farm_plots_list_set(
+ farm_d_tag,
+ &farm_pubkey,
+ vec![plot_d_tag.to_string()],
+ )
+ .expect("plots list");
+ let plots_event =
+ list_set_event(833, &farm_pubkey, 111, KIND_LIST_SET_GENERIC, &plots_list);
+ let plots_state_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "nostr_event_state",
+ err: SqlError::Internal,
+ };
+ assert!(ingest_list_set_event(&plots_state_fail, &plots_event).is_err());
+
+ let missing_farm_members =
+ farm_list_sets::farm_members_list_set(farm_d_tag, vec!["n".repeat(64)]).expect("list");
+ let missing_farm_event = list_set_event(
+ 834,
+ &"z".repeat(64),
+ 112,
+ KIND_LIST_SET_GENERIC,
+ &missing_farm_members,
+ );
+ assert!(ingest_list_set_event(&exec, &missing_farm_event).is_err());
+
+ let members_create_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "farm_member",
+ err: SqlError::Internal,
+ };
+ assert!(ingest_list_set_event(&members_create_fail, &member_event).is_err());
+
+ let members_state_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "nostr_event_state",
+ err: SqlError::Internal,
+ };
+ assert!(ingest_list_set_event(&members_state_fail, &member_event).is_err());
+
+ assert!(parse_farm_list_set_d_tag("").is_none());
+ assert!(parse_farm_list_set_d_tag("farm").is_none());
+
+ let state_create_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "nostr_event_state",
+ err: SqlError::Internal,
+ };
+ assert!(
+ radroots_replica_ingest_event_state(&state_create_fail, &profile, "", "hash").is_err()
+ );
+
+ radroots_replica_ingest_event_state(&exec, &profile, "", "hash").expect("seed state");
+ let state_update_fail = QueryFailExecutor {
+ inner: &exec,
+ needle: "update nostr_event_state",
+ err: SqlError::Internal,
+ };
+ assert!(
+ radroots_replica_ingest_event_state(&state_update_fail, &profile, "", "hash2").is_err()
);
- assert!(upsert_member_claims(&txn, &"m".repeat(64), &member_of_list).is_err());
}
}