0.3.16-pre.3.fix.1

This commit is contained in:
2026-09-21 10:33:06 +02:00
parent 05cdb4e2ab
commit 540b1bc305
36 changed files with 1852 additions and 62 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-store-postgres-lib/unit_tests/migration.rs
// version: 8
// version: 9
fn applied(version: i64, name: &str, checksum: &str) -> super::AppliedMigration {
return super::AppliedMigration { checksum: checksum.to_owned(), name: name.to_owned(), version };
@@ -51,7 +51,7 @@ fn pre_003_v002_registry_is_complete_and_keeps_v000_v001_checksums_stable() {
assert_eq!(v002.resources.len(), 32);
assert_eq!(super::migration_checksum(v002), "ff21605ed45f7ab4c0f92bbb692700b4118a9488b04d50a31d259ac59bdb550e");
assert!(super::validate_embedded_registry(super::EMBEDDED_MIGRATIONS).is_ok());
assert_eq!(crate::current_migration_version(), 2);
assert_eq!(crate::current_migration_version(), 3);
let full = [
applied(0, v000.name, super::migration_checksum(v000).as_str()),
applied(1, v001.name, super::migration_checksum(v001).as_str()),

View File

@@ -0,0 +1,87 @@
// file: crates/ksp-store-postgres-lib/unit_tests/migration_v003.rs
// version: 2
fn applied(version: i64, name: &str, checksum: &str) -> super::AppliedMigration {
return super::AppliedMigration { checksum: checksum.to_owned(), name: name.to_owned(), version };
}
#[test]
fn pre_003_v003_extension_preserves_frozen_history_and_advances_current_version() {
assert_eq!(crate::current_migration_version(), 3);
assert_eq!(super::V000_CHECKSUM, "d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450");
assert_eq!(super::V001_CHECKSUM, "31488cda2f08f3f46c4cdbdbb6c18c243662fada02eac4487040c8735d72cc51");
assert_eq!(super::V002_CHECKSUM, "ff21605ed45f7ab4c0f92bbb692700b4118a9488b04d50a31d259ac59bdb550e");
let prefix = [
applied(0, "bootstrap", super::V000_CHECKSUM),
applied(1, "raw_transaction", super::V001_CHECKSUM),
applied(2, "raw_account_state", super::V002_CHECKSUM),
];
assert_eq!(super::validate_history(&prefix).ok(), std::option::Option::Some(3));
return;
}
#[test]
fn pre_003_v003_resource_checksum_and_history_are_stable() {
let checksum = super::migration_checksum_v003();
assert_eq!(checksum, "3c9cf41877c96944a378abb41ee7a8d8ab7f99fc6dc2bb7a26c295cf8f9fc914");
let full = [
applied(0, "bootstrap", super::V000_CHECKSUM),
applied(1, "raw_transaction", super::V001_CHECKSUM),
applied(2, "raw_account_state", super::V002_CHECKSUM),
applied(3, super::V003_NAME, checksum.as_str()),
];
assert_eq!(super::validate_history(&full).ok(), std::option::Option::Some(4));
return;
}
#[test]
fn pre_003_v003_history_rejects_divergence_and_future_versions() {
let checksum = super::migration_checksum_v003();
let divergent = [
applied(0, "bootstrap", super::V000_CHECKSUM),
applied(1, "raw_transaction", super::V001_CHECKSUM),
applied(2, "raw_account_state", super::V002_CHECKSUM),
applied(3, super::V003_NAME, "changed"),
];
let divergent_result = super::validate_history(&divergent);
assert_eq!(divergent_result.err().map(|value| return value.kind()), std::option::Option::Some(crate::PostgresBackendErrorKind::MigrationMismatch));
let future = [
applied(0, "bootstrap", super::V000_CHECKSUM),
applied(1, "raw_transaction", super::V001_CHECKSUM),
applied(2, "raw_account_state", super::V002_CHECKSUM),
applied(3, super::V003_NAME, checksum.as_str()),
applied(4, "future", "future"),
];
let future_result = super::validate_history(&future);
assert_eq!(future_result.err().map(|value| return value.kind()), std::option::Option::Some(crate::PostgresBackendErrorKind::SchemaNewer));
let direct_future = [
applied(0, "bootstrap", super::V000_CHECKSUM),
applied(1, "raw_transaction", super::V001_CHECKSUM),
applied(2, "raw_account_state", super::V002_CHECKSUM),
applied(4, "future", "future"),
];
let direct_future_result = super::validate_history(&direct_future);
assert_eq!(
direct_future_result.err().map(|value| return value.kind()),
std::option::Option::Some(crate::PostgresBackendErrorKind::SchemaNewer),
);
return;
}
#[test]
fn pre_003_v003_bootstrap_uses_legacy_engine_only_before_v002_and_absorbs_completed_v003_race() {
assert!(super::legacy_bootstrap_required(std::option::Option::None));
assert!(super::legacy_bootstrap_required(std::option::Option::Some(0)));
assert!(super::legacy_bootstrap_required(std::option::Option::Some(1)));
assert!(!super::legacy_bootstrap_required(std::option::Option::Some(2)));
assert!(!super::legacy_bootstrap_required(std::option::Option::Some(3)));
assert!(super::legacy_schema_newer_is_completed_v003(std::option::Option::Some(3)));
assert!(!super::legacy_schema_newer_is_completed_v003(std::option::Option::Some(2)));
assert!(!super::legacy_schema_newer_is_completed_v003(std::option::Option::Some(4)));
assert!(super::v003_apply_allowed(false, false));
assert!(super::v003_apply_allowed(false, true));
assert!(super::v003_apply_allowed(true, true));
assert!(!super::v003_apply_allowed(true, false));
return;
}

View File

@@ -0,0 +1,54 @@
// file: crates/ksp-store-postgres-lib/unit_tests/schema_v003.rs
// version: 2
#[test]
fn pre_003_v003_resource_inventory_is_exact_and_ordered() {
let resources = crate::V003_RESOURCES;
assert_eq!(resources.len(), 25);
let ids = resources.iter().map(|resource| return resource.id).collect::<std::vec::Vec<_>>();
assert_eq!(ids.iter().filter(|id| return id.starts_with("tables/")).count(), 4);
assert_eq!(ids.iter().filter(|id| return id.starts_with("constraints/")).count(), 18);
assert_eq!(ids.iter().filter(|id| return id.starts_with("indexes/")).count(), 3);
assert!(ids[..4].iter().all(|id| return id.starts_with("tables/")));
assert!(ids[4..22].iter().all(|id| return id.starts_with("constraints/")));
assert!(ids[22..].iter().all(|id| return id.starts_with("indexes/")));
let mut unique = std::collections::BTreeSet::<&str>::new();
for id in ids {
assert!(unique.insert(id), "duplicate V003 resource id: {id}");
}
return;
}
#[test]
fn pre_003_v003_schema_is_additive_payload_bounded_and_hash_non_unique() {
let sql = crate::V003_RESOURCES.iter().map(|resource| return resource.sql).collect::<std::vec::Vec<_>>().concat();
for required in [
"CREATE TABLE IF NOT EXISTS ksp_raw_transaction_variants",
"CREATE TABLE IF NOT EXISTS ksp_raw_transaction_canonical_selectors",
"CREATE TABLE IF NOT EXISTS ksp_raw_transaction_observation_variants",
"CREATE TABLE IF NOT EXISTS ksp_raw_transaction_conflicts",
"PRIMARY KEY (transaction_signature, variant_id)",
"FOREIGN KEY (transaction_signature) REFERENCES ksp_raw_transactions(signature)",
"FOREIGN KEY (observation_key) REFERENCES ksp_raw_transaction_observations(observation_key)",
"octet_length(payload) <= 16777216",
"origin_kind = 'native' OR origin_kind = 'synthetic'",
"latest_relation = 'conflict' OR latest_relation = 'incomparable'",
"latest_reason_code = 'content_hash_collision'",
"latest_reason_code = 'unsupported_canonical_difference'",
] {
assert!(sql.contains(required), "missing V003 schema invariant: {required}");
}
for forbidden in ["UNIQUE (content_hash", "UNIQUE(content_hash", "BIGSERIAL", "INSERT INTO", "UPDATE ksp_raw_transactions"] {
assert!(!sql.contains(forbidden), "forbidden V003 migration behavior: {forbidden}");
}
return;
}
#[test]
fn pre_003_v003_observation_mapping_does_not_fabricate_legacy_rows() {
let sql = crate::V003_RESOURCES.iter().map(|resource| return resource.sql).collect::<std::vec::Vec<_>>().concat();
assert!(sql.contains("ksp_raw_transaction_observation_variants"));
assert!(!sql.contains("SELECT observation_key FROM ksp_raw_transaction_observations"));
assert!(!sql.contains("INSERT INTO ksp_raw_transaction_observation_variants"));
return;
}