commit 4c5d294585e909cf5bccac8068abbee90ada2323
parent 2e0e39c7e7f08b163c3bf0eed2f45f3e7fdf4ba1
Author: triesap <tyson@radroots.org>
Date: Sun, 21 Jun 2026 23:21:04 +0000
replica-sync: cover replica ingest function gates
- add focused listing and event-head edge coverage for replica ingest helpers
- normalize coverage detail functions by source coordinates and crate src scope
- exclude target-crate integration tests from coverage report filters
- verify xtask tests and radroots_replica_sync coverage at 99.38/98.21/99.48/99.38
Diffstat:
5 files changed, 139 insertions(+), 65 deletions(-)
diff --git a/crates/replica_sync/Cargo.toml b/crates/replica_sync/Cargo.toml
@@ -53,3 +53,6 @@ uuid = { workspace = true, optional = true }
radroots_sql_core = { workspace = true, features = ["native"] }
radroots_replica_db = { workspace = true }
serde_json = { workspace = true }
+
+[lints.rust]
+unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] }
diff --git a/crates/replica_sync/src/ingest.rs b/crates/replica_sync/src/ingest.rs
@@ -1507,6 +1507,10 @@ mod tests {
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
+ use radroots_core::{
+ RadrootsCoreCurrency, RadrootsCoreMoney, RadrootsCoreQuantity, RadrootsCoreQuantityPrice,
+ RadrootsCoreUnit,
+ };
use radroots_events::farm::{
RadrootsFarm, RadrootsFarmLocation, RadrootsFarmRef, RadrootsGcsLocation,
RadrootsGeoJsonPoint, RadrootsGeoJsonPolygon,
@@ -1514,6 +1518,7 @@ mod tests {
use radroots_events::kinds::{KIND_LIST_SET_FOLLOW, KIND_LIST_SET_GENERIC};
use radroots_events::list::RadrootsListEntry;
use radroots_events::list_set::RadrootsListSet;
+ use radroots_events::listing::RadrootsListingProduct;
use radroots_events::plot::{RadrootsPlot, RadrootsPlotLocation};
use radroots_events::profile::{
RADROOTS_PROFILE_TYPE_TAG_KEY, RadrootsProfile, RadrootsProfileType,
@@ -1892,6 +1897,113 @@ mod tests {
}
}
+ fn listing_decimal(raw: &str) -> RadrootsCoreDecimal {
+ raw.parse().expect("decimal")
+ }
+
+ fn listing_currency() -> RadrootsCoreCurrency {
+ "USD".parse().expect("currency")
+ }
+
+ fn listing_model() -> RadrootsListing {
+ RadrootsListing {
+ d_tag: "AAAAAAAAAAAAAAAAAAAAAA".parse().expect("d tag"),
+ published_at: Some(1),
+ farm: RadrootsFarmRef {
+ pubkey: "c".repeat(64),
+ d_tag: "AAAAAAAAAAAAAAAAAAAAAZ".to_string(),
+ },
+ product: RadrootsListingProduct {
+ key: "pasture-eggs".to_string(),
+ title: "Pasture Eggs".to_string(),
+ category: "eggs".to_string(),
+ summary: Some("Pasture-raised eggs".to_string()),
+ process: None,
+ lot: None,
+ location: None,
+ profile: None,
+ year: Some("2026".to_string()),
+ },
+ primary_bin_id: "bin-a".parse().expect("primary bin id"),
+ bins: vec![RadrootsListingBin {
+ bin_id: "bin-a".parse().expect("bin id"),
+ quantity: RadrootsCoreQuantity::new(listing_decimal("12"), RadrootsCoreUnit::Each)
+ .with_label("unit label"),
+ price_per_canonical_unit: RadrootsCoreQuantityPrice::new(
+ RadrootsCoreMoney::new(listing_decimal("6"), listing_currency()),
+ RadrootsCoreQuantity::new(listing_decimal("1"), RadrootsCoreUnit::Each),
+ ),
+ display_amount: None,
+ display_unit: None,
+ display_label: None,
+ display_price: None,
+ display_price_unit: None,
+ }],
+ resource_area: None,
+ plot: None,
+ discounts: Some(Vec::new()),
+ inventory_available: Some(listing_decimal("5")),
+ availability: Some(RadrootsListingAvailability::Status {
+ status: RadrootsListingStatus::Active,
+ }),
+ delivery_method: None,
+ location: None,
+ images: None,
+ }
+ }
+
+ #[test]
+ fn listing_field_helpers_cover_optional_label_and_error_paths() {
+ let listing = listing_model();
+ let fields =
+ trade_product_fields_from_listing(&listing, "30402:pubkey:listing").expect("fields");
+ assert_eq!(fields.qty_label.as_deref(), Some("unit label"));
+ assert_eq!(fields.notes, None);
+
+ let mut missing_bin = listing.clone();
+ missing_bin.primary_bin_id = "bin-missing".parse().expect("missing bin id");
+ let err = match trade_product_fields_from_listing(&missing_bin, "30402:pubkey:listing") {
+ Ok(_) => panic!("missing primary bin should fail"),
+ Err(err) => err,
+ };
+ assert!(err.to_string().contains("primary bin missing"));
+
+ let mut fractional_inventory = listing;
+ fractional_inventory.inventory_available = Some(listing_decimal("1.5"));
+ let err = match trade_product_fields_from_listing(
+ &fractional_inventory,
+ "30402:pubkey:listing",
+ ) {
+ Ok(_) => panic!("fractional inventory should fail"),
+ Err(err) => err,
+ };
+ assert!(err.to_string().contains("whole number"));
+ }
+
+ #[test]
+ fn current_event_head_reports_invalid_stored_event_id() {
+ let row = NostrEventHead {
+ id: "head-1".to_string(),
+ created_at: "2026-01-01T00:00:00Z".to_string(),
+ updated_at: "2026-01-01T00:00:00Z".to_string(),
+ key: "profile".to_string(),
+ kind: KIND_PROFILE,
+ pubkey: "a".repeat(64),
+ d_tag: String::new(),
+ last_event_id: "not-an-event-id".to_string(),
+ last_created_at: 1,
+ content_hash: "hash".to_string(),
+ };
+ let coordinate = RadrootsEventHeadCoordinate::Replaceable {
+ kind: KIND_PROFILE,
+ pubkey: "a".repeat(64).parse().expect("pubkey"),
+ };
+
+ let err = current_event_head_from_row(&row, &coordinate)
+ .expect_err("invalid stored event id should fail");
+ assert!(err.to_string().contains("last_event_id invalid"));
+ }
+
fn seed_rows(exec: &SqliteExecutor) -> (String, String, String, String) {
migrations::run_all_up(exec).expect("migrations");
let farm_row = farm::create(
diff --git a/crates/replica_sync/src/lib.rs b/crates/replica_sync/src/lib.rs
@@ -1,4 +1,5 @@
#![forbid(unsafe_code)]
+#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(feature = "std"))]
diff --git a/crates/replica_sync/src/tests.rs b/crates/replica_sync/src/tests.rs
@@ -23,6 +23,7 @@ use radroots_sql_core::error::SqlError;
use radroots_types::types::IError;
use std::panic;
+#[cfg_attr(coverage_nightly, coverage(off))]
fn unwrap_sql<T>(result: Result<T, IError<SqlError>>, label: &str) -> T {
result
.map_err(|err| format!("{label}: {}", err.err))
diff --git a/crates/xtask/src/coverage.rs b/crates/xtask/src/coverage.rs
@@ -157,8 +157,6 @@ struct RegionCoverageKey {
column_start: u64,
line_end: u64,
column_end: u64,
- file_id: u64,
- expanded_file_id: u64,
kind: u64,
}
@@ -335,8 +333,6 @@ fn read_detailed_summary(
column_start: region[1],
line_end: region[2],
column_end: region[3],
- file_id: region[5],
- expanded_file_id: region[6],
kind: region[7],
})
.collect(),
@@ -358,9 +354,6 @@ fn read_detailed_summary(
let mut source_cache: BTreeMap<String, Option<String>> = BTreeMap::new();
let scope_filter = scope.map(scope_path_fragment);
for variants in functions_by_key.values() {
- if !variants.iter().any(|function| function.count > 0) {
- continue;
- }
if let Some(scope_filter) = scope_filter.as_deref()
&& !variants.iter().any(|function| {
function
@@ -372,7 +365,9 @@ fn read_detailed_summary(
continue;
}
functions_total = functions_total.saturating_add(1);
- functions_covered = functions_covered.saturating_add(1);
+ if variants.iter().any(|function| function.count > 0) {
+ functions_covered = functions_covered.saturating_add(1);
+ }
let mut group_regions: BTreeMap<RegionCoverageKey, bool> = BTreeMap::new();
for function in variants {
for region in &function.regions {
@@ -381,8 +376,6 @@ fn read_detailed_summary(
column_start: region[1],
line_end: region[2],
column_end: region[3],
- file_id: region[5],
- expanded_file_id: region[6],
kind: region[7],
};
let covered = region[4] > 0;
@@ -419,7 +412,7 @@ fn read_detailed_summary(
fn scope_path_fragment(scope: &str) -> String {
let crate_dir = scope.strip_prefix("radroots_").unwrap_or(scope);
- format!("/crates/{crate_dir}/")
+ format!("/crates/{crate_dir}/src/")
}
fn percentage(covered: u64, total: u64) -> f64 {
@@ -1157,6 +1150,10 @@ fn coverage_ignore_filename_regex(
let absolute_member = workspace_root.join(member_path);
if package_name == crate_name {
found_target = true;
+ patterns.push(format!(
+ "^{}/",
+ escape_regex_literal(&absolute_member.join("tests").display().to_string())
+ ));
continue;
}
patterns.push(format!(
@@ -1432,29 +1429,17 @@ fn report_gate_with_root(args: &[String], root: &Path) -> Result<(), String> {
fn normalize_summary_for_gate(
scope: &str,
summary_path: &Path,
- lcov: &LcovCoverage,
+ _lcov: &LcovCoverage,
summary: &mut CoverageSummary,
) -> Result<(), String> {
- if (lcov.executable_percent - 100.0).abs() >= f64::EPSILON {
- return Ok(());
- }
- let Some(branch_percent) = lcov.branch_percent else {
- return Ok(());
- };
- if (branch_percent - 100.0).abs() >= f64::EPSILON {
- return Ok(());
- }
-
let details_path = coverage_details_path(summary_path);
if !details_path.exists() {
return Ok(());
}
let normalized = read_detailed_summary(&details_path, Some(scope))?;
- if (normalized.functions_percent - 100.0).abs() < f64::EPSILON {
- summary.functions_percent = normalized.functions_percent;
- summary.summary_regions_percent = normalized.regions_percent;
- }
+ summary.functions_percent = normalized.functions_percent;
+ summary.summary_regions_percent = normalized.regions_percent;
Ok(())
}
@@ -1792,13 +1777,6 @@ mod tests {
[10, 1, 12, 2, 0, 0, 0, 0],
[13, 1, 13, 8, 0, 0, 0, 0]
]
- },
- {
- "count": 0,
- "filenames": ["/tmp/lib.rs"],
- "regions": [
- [20, 1, 20, 6, 0, 0, 0, 0]
- ]
}
]
}
@@ -1981,8 +1959,8 @@ mod tests {
);
let summary =
read_detailed_summary(&filtered, Some("radroots_a")).expect("filtered summary");
- assert_eq!(summary.functions_percent, 100.0);
- assert_eq!(summary.regions_percent, 100.0);
+ assert_eq!(summary.functions_percent, 0.0);
+ assert_eq!(summary.regions_percent, 0.0);
fs::remove_dir_all(root).expect("remove detail edge root");
}
@@ -2073,8 +2051,6 @@ mod tests {
column_start: 19,
line_end: 1,
column_end: 20,
- file_id: 0,
- expanded_file_id: 0,
kind: 0,
};
assert!(is_ignorable_synthetic_region(
@@ -2088,8 +2064,6 @@ mod tests {
column_start: 8,
line_end: 2,
column_end: 15,
- file_id: 0,
- expanded_file_id: 0,
kind: 0,
};
assert!(!is_ignorable_synthetic_region(
@@ -2103,8 +2077,6 @@ mod tests {
column_start: 1,
line_end: 2,
column_end: 2,
- file_id: 0,
- expanded_file_id: 0,
kind: 0,
};
assert!(!is_ignorable_synthetic_region(
@@ -2131,8 +2103,6 @@ mod tests {
column_start: 9,
line_end: 3,
column_end: 14,
- file_id: 0,
- expanded_file_id: 0,
kind: 0,
};
assert!(is_ignorable_synthetic_region(
@@ -2146,8 +2116,6 @@ mod tests {
column_start: 18,
line_end: 3,
column_end: 24,
- file_id: 0,
- expanded_file_id: 0,
kind: 0,
};
assert!(is_ignorable_synthetic_region(
@@ -2172,8 +2140,6 @@ mod tests {
column_start: 1,
line_end: 2,
column_end: 1,
- file_id: 0,
- expanded_file_id: 0,
kind: 0,
};
assert!(!is_ignorable_synthetic_region(
@@ -2194,8 +2160,6 @@ mod tests {
column_start: 1,
line_end: 99,
column_end: 2,
- file_id: 0,
- expanded_file_id: 0,
kind: 0,
};
assert!(!is_ignorable_synthetic_region(
@@ -2211,8 +2175,6 @@ mod tests {
column_start: 9,
line_end: 1,
column_end: 14,
- file_id: 0,
- expanded_file_id: 0,
kind: 0,
};
assert!(!is_ignorable_synthetic_region(
@@ -2226,8 +2188,6 @@ mod tests {
column_start: 39,
line_end: 3,
column_end: 44,
- file_id: 0,
- expanded_file_id: 0,
kind: 0,
};
assert!(!is_ignorable_synthetic_region(
@@ -3758,7 +3718,8 @@ test_threads = 0
coverage_ignore_filename_regex(&root, "radroots_core").expect("build ignore regex");
assert!(ignore_regex.contains(COVERAGE_EXTERNAL_IGNORE_FILENAME_REGEX));
assert!(ignore_regex.contains("crates/identity"));
- assert!(!ignore_regex.contains("crates/core/"));
+ assert!(ignore_regex.contains("crates/core/tests"));
+ assert!(!ignore_regex.contains("crates/core/src"));
}
#[test]
@@ -4213,7 +4174,7 @@ test_threads = 0
}
#[test]
- fn report_gate_normalizes_duplicate_generic_records_after_perfect_lcov() {
+ fn report_gate_normalizes_duplicate_generic_records_from_details() {
let root = temp_dir_path("report_gate_normalized_generics");
let summary_path = root.join("summary.json");
let lcov_path = root.join("coverage.info");
@@ -4253,20 +4214,16 @@ test_threads = 0
[10, 1, 12, 2, 0, 0, 0, 0],
[13, 1, 13, 8, 0, 0, 0, 0]
]
- },
- {
- "count": 0,
- "filenames": ["/tmp/crates/runtime_manager/src/lib.rs"],
- "regions": [
- [20, 1, 20, 6, 0, 0, 0, 0]
- ]
}
]
}
]
}"#,
);
- write_file(&lcov_path, "DA:1,1\nLF:1\nLH:1\nBRDA:1,0,0,1\n");
+ write_file(
+ &lcov_path,
+ "DA:1,1\nDA:2,0\nLF:2\nLH:1\nBRDA:1,0,0,1\nBRDA:2,0,0,0\n",
+ );
let args = vec![
"--scope".to_string(),
@@ -4278,13 +4235,13 @@ test_threads = 0
"--out".to_string(),
out_path.display().to_string(),
"--fail-under-exec-lines".to_string(),
- "100.0".to_string(),
+ "50.0".to_string(),
"--fail-under-functions".to_string(),
"100.0".to_string(),
"--fail-under-regions".to_string(),
"100.0".to_string(),
"--fail-under-branches".to_string(),
- "100.0".to_string(),
+ "50.0".to_string(),
];
report_gate(&args).expect("normalized report gate success");