#![allow(clippy::unwrap_used, clippy::expect_used)]
const SURFACE: &[&str] = &[
"mod db",
"mod delete",
"mod error",
"mod export",
"mod macros",
"mod prelude",
"mod promql",
"mod retention",
"mod rollup",
"mod chronix_core",
"mod chronix_encoding",
"mod chronix_engine",
"mod chronix_query",
"BackupManifest",
"Chronix",
"DatabaseStatistics",
"DbError",
"DeleteBuilder",
"DeleteOutcome",
"DeleteRequest",
"InsertResult",
"ParquetCompression",
"ParquetExportConfig",
"SegmentInfo",
"RollupAggFn",
"RollupBuilder",
"RollupConfig",
"RollupRegistry",
"RollupState",
"fields",
"tags",
];
const FEATURE_SURFACE: &[(&str, &[&str])] = &[
(
"analytics",
&[
"mod analytics",
"mod chronix_analytics",
"AnomalyConfig",
"ForecastConfig",
],
),
("object-store", &["mod cold_archive"]),
("sql", &["mod sql"]),
("streaming", &["mod chronix_streaming"]),
("security", &["mod chronix_security"]),
("pipeline", &["mod pipeline", "Pipeline", "PipelineConfig"]),
];
fn declared_surface() -> (Vec<String>, Vec<(String, String)>) {
let full = include_str!("../src/lib.rs");
let src = full
.split_once("pub mod prelude {")
.map_or(full, |(head, _)| head);
let mut always = Vec::new();
let mut gated: Vec<(String, String)> = Vec::new();
let mut pending_feature: Option<String> = None;
for line in src.lines() {
let trimmed = line.trim();
if let Some(rest) = trimmed.strip_prefix("#[cfg(feature = \"") {
if let Some(name) = rest.split('"').next() {
pending_feature = Some(name.to_string());
}
continue;
}
if trimmed.starts_with("//") || trimmed.is_empty() {
continue;
}
let mut names: Vec<String> = Vec::new();
if let Some(rest) = trimmed.strip_prefix("pub mod ") {
let name = rest.trim_end_matches(';').trim_end_matches('{').trim();
names.push(format!("mod {name}"));
} else if let Some(rest) = trimmed.strip_prefix("pub use ") {
let rest = rest.trim_end_matches(';');
if !rest.contains("::") {
names.push(format!("mod {rest}"));
} else {
let (_path, tail) = rest.rsplit_once("::").unwrap_or(("", rest));
if let Some(group) = tail.strip_prefix('{') {
for item in group.trim_end_matches('}').split(',') {
let item = item.trim();
if !item.is_empty() {
names.push(item.to_string());
}
}
} else {
names.push(tail.to_string());
}
}
}
let feature = pending_feature.take();
for name in names {
match &feature {
Some(f) => gated.push((f.clone(), name)),
None => always.push(name),
}
}
if !trimmed.starts_with('#') {
pending_feature = None;
}
}
(always, gated)
}
fn exported_macros() -> Vec<String> {
let src = include_str!("../src/macros.rs");
let mut out = Vec::new();
let mut armed = false;
for line in src.lines() {
let t = line.trim();
if t.starts_with("#[macro_export]") {
armed = true;
continue;
}
if armed {
if let Some(rest) = t.strip_prefix("macro_rules! ") {
out.push(rest.trim_end_matches(" {").trim().to_string());
armed = false;
} else if !t.starts_with('#') && !t.is_empty() && !t.starts_with("//") {
armed = false;
}
}
}
out
}
#[test]
fn the_public_surface_is_the_one_that_was_reviewed() {
let (always, _gated) = declared_surface();
let mut actual: Vec<String> = always;
actual.extend(exported_macros());
if include_str!("../src/lib.rs").contains("pub mod prelude {") {
actual.push("mod prelude".to_string());
}
actual.sort();
actual.dedup();
let mut expected: Vec<String> = SURFACE.iter().map(|s| (*s).to_string()).collect();
expected.sort();
expected.dedup();
let added: Vec<&String> = actual.iter().filter(|a| !expected.contains(a)).collect();
let removed: Vec<&String> = expected.iter().filter(|e| !actual.contains(e)).collect();
assert!(
added.is_empty() && removed.is_empty(),
"the public surface changed.\n added: {added:?}\n removed: {removed:?}\n\
If this was deliberate, update SURFACE in this file in the same commit; \
if it was not, the item probably wants `pub(crate)`."
);
}
#[test]
fn feature_gated_items_are_declared_under_their_feature() {
let (_, gated) = declared_surface();
for (feature, expected) in FEATURE_SURFACE {
let found: Vec<&String> = gated
.iter()
.filter(|(f, _)| f == feature)
.map(|(_, n)| n)
.collect();
for want in *expected {
assert!(
found.iter().any(|f| f.as_str() == *want),
"`{want}` should be gated behind `{feature}`, found {found:?}"
);
}
}
}
#[test]
fn the_prelude_is_the_one_that_was_reviewed() {
const PRELUDE: &[&str] = &[
"AggFn",
"BucketWidth",
"ChronixConfig",
"ChronixConfigBuilder",
"ChronixError",
"Chronix",
"ColumnDef",
"ColumnRole",
"ColumnType",
"CompressionCodec",
"DbError",
"Decimal",
"FieldValue",
"FloatEncoding",
"FsyncPolicy",
"InsertResult",
"MeasurementSchema",
"Point",
"QueryBuilder",
"QueryPlan",
"RecordBatch",
"RollupAggFn",
"RollupBuilder",
"SeriesKey",
"TimeBucket",
"Timestamp",
"fields",
"tags",
];
let src = include_str!("../src/lib.rs");
let body = src
.split_once("pub mod prelude {")
.expect("a prelude module")
.1;
let body = &body[..body.find("\n}").expect("a closing brace")];
let mut actual: Vec<String> = Vec::new();
for chunk in body.split("pub use ").skip(1) {
let stmt = chunk.split(';').next().unwrap_or_default();
let tail = stmt.rsplit_once("::").map_or(stmt, |(_, t)| t);
if let Some(group) = tail.trim().strip_prefix('{') {
for item in group.trim_end_matches('}').split(',') {
let item = item.trim();
if !item.is_empty() {
actual.push(item.to_string());
}
}
} else {
actual.push(tail.trim().to_string());
}
}
actual.sort();
actual.dedup();
let mut expected: Vec<String> = PRELUDE.iter().map(|s| (*s).to_string()).collect();
expected.sort();
assert_eq!(
actual, expected,
"the prelude changed; update PRELUDE in this file in the same commit"
);
}
const HANDLE_SURFACE: &[&str] = &[
"close",
"open",
"open_small",
"backfill",
"declare_field",
"insert",
"insert_batch",
"execute",
"execute_iter",
"execute_stream",
"execute_with_stats",
"last_value",
"promql",
"promql_range",
"query",
"sql",
"sql_async",
"config",
"data_dir",
"has_measurement_in",
"measurement_names_in",
"schema",
"schema_registry",
"segment_count",
"segments",
"segments_of",
"statistics",
"disk_usage_bytes",
"tag_keys",
"tag_values",
"delete_builder",
"delete_series",
"drop_measurement",
"execute_delete",
"is_measurement_pending_drop",
"restore_measurement",
"check_writable",
"compact",
"enforce_configured_retention",
"enforce_retention",
"flush",
"flush_shard",
"gc",
"gc_pending_measurement_drops",
"gc_tombstones",
"create_rollup",
"delete_rollup",
"list_rollups",
"materialise_rollups",
"refresh_rollup",
"rollup",
"rollup_state",
"rollup_where",
"auto_forecast",
"detect_anomalies",
"fetch_series_data",
"forecast",
"preprocess",
"backup",
"restore",
"verify_backup",
"custom_udafs",
"custom_udfs",
"event_bus",
"export_parquet",
"register_udaf",
"register_udf",
"session_context",
"subscribe",
"scan_memtable",
"wal_replayed_records",
"wal_sequence",
];
fn handle_methods() -> Vec<String> {
let mut out = Vec::new();
for src in [
include_str!("../src/db/accessors.rs"),
include_str!("../src/db/analytics_api.rs"),
include_str!("../src/db/backup.rs"),
include_str!("../src/db/delete.rs"),
include_str!("../src/db/lifecycle.rs"),
include_str!("../src/db/mod.rs"),
include_str!("../src/db/query.rs"),
include_str!("../src/db/rollup.rs"),
include_str!("../src/db/stream.rs"),
include_str!("../src/db/write.rs"),
] {
let mut in_chronix_impl = false;
for line in src.lines() {
if !line.starts_with(char::is_whitespace) && line.contains("impl ") {
let head = line.split_once("impl").map_or("", |(_, t)| t);
let head = head.trim_start().trim_start_matches("super::");
in_chronix_impl = head.starts_with("Chronix") && !head.contains(" for ");
continue;
}
if !in_chronix_impl {
continue;
}
let t = line.trim();
let Some(rest) = t
.strip_prefix("pub async fn ")
.or_else(|| t.strip_prefix("pub fn "))
else {
continue;
};
let name: String = rest
.chars()
.take_while(|c| c.is_alphanumeric() || *c == '_')
.collect();
if !name.is_empty() {
out.push(name);
}
}
}
out.sort();
out.dedup();
assert!(
out.len() > 40,
"the scanner found only {} methods, which means it stopped matching \
the source layout rather than that the surface shrank",
out.len()
);
out
}
#[test]
fn the_handle_surface_is_the_one_that_was_reviewed() {
let actual = handle_methods();
let mut expected: Vec<String> = HANDLE_SURFACE.iter().map(|s| (*s).to_string()).collect();
expected.sort();
expected.dedup();
let added: Vec<_> = actual.iter().filter(|m| !expected.contains(m)).collect();
let removed: Vec<_> = expected.iter().filter(|m| !actual.contains(m)).collect();
assert!(
added.is_empty() && removed.is_empty(),
"the `Chronix` handle's surface changed.\n\
\n added (new public methods, not in HANDLE_SURFACE): {added:?}\
\n removed (in HANDLE_SURFACE, no longer public): {removed:?}\n\
\nIf the change is deliberate, edit `HANDLE_SURFACE` in this file in\n\
the same commit. Before adding one, ask the question this guard exists\n\
for: can a caller outside this crate *name* every type in the\n\
signature, and can they hold the result across another call without\n\
deadlocking the maintenance thread? Six methods that failed both were\n\
deleted rather than documented."
);
}
#[test]
fn the_handle_hands_out_no_internal_locks() {
for (file, src) in [
("accessors.rs", include_str!("../src/db/accessors.rs")),
("lifecycle.rs", include_str!("../src/db/lifecycle.rs")),
("mod.rs", include_str!("../src/db/mod.rs")),
("query.rs", include_str!("../src/db/query.rs")),
("rollup.rs", include_str!("../src/db/rollup.rs")),
("stream.rs", include_str!("../src/db/stream.rs")),
("write.rs", include_str!("../src/db/write.rs")),
] {
for (i, line) in src.lines().enumerate() {
let t = line.trim();
if !t.starts_with("pub fn ") && !t.starts_with("pub async fn ") {
continue;
}
let Some((_, ret)) = t.split_once("->") else {
continue;
};
for lock in [
"CatalogLock",
"BloomsLock",
"TombstonesLock",
"RollupRegistryLock",
] {
assert!(
!ret.contains(lock),
"{file}:{} returns `{lock}`, one of this crate's ordered locks.\n\
A caller outside the crate cannot name it (the module is\n\
`pub(crate)`) and can deadlock the maintenance thread with it.\n\
Return an owned snapshot instead — see `Chronix::segments`.",
i + 1
);
}
}
}
}