v0.3.3-pre.003
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-postgres-lib/unit_tests/migration.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
fn applied(version: i64, name: &str, checksum: &str) -> super::AppliedMigration {
|
||||
return super::AppliedMigration { checksum: checksum.to_owned(), name: name.to_owned(), version };
|
||||
@@ -10,36 +10,69 @@ fn embedded(version: i64, name: &'static str, sql: &'static str) -> super::Embed
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_002_embedded_registry_keeps_v000_immutable_and_current_version_registry_driven() {
|
||||
assert_eq!(super::EMBEDDED_MIGRATIONS.len(), 1);
|
||||
let migration = &super::EMBEDDED_MIGRATIONS[0];
|
||||
assert_eq!(migration.version, 0);
|
||||
assert_eq!(migration.name, "bootstrap");
|
||||
assert_eq!(migration.hook, super::MigrationHook::None);
|
||||
assert!(migration.sql.contains("CREATE TABLE ksp_store_schema_migrations"));
|
||||
fn pre_003_embedded_registry_keeps_v000_immutable_and_adds_exact_v001() {
|
||||
assert_eq!(super::EMBEDDED_MIGRATIONS.len(), 2);
|
||||
let v000 = &super::EMBEDDED_MIGRATIONS[0];
|
||||
assert_eq!(v000.version, 0);
|
||||
assert_eq!(v000.name, "bootstrap");
|
||||
assert_eq!(v000.hook, super::MigrationHook::None);
|
||||
assert!(v000.sql.contains("CREATE TABLE ksp_store_schema_migrations"));
|
||||
for forbidden in ["RawTransaction", "RawAccountState", "raw_transaction", "raw_account", "CORE", "DECODE", "SPECIALIZED"] {
|
||||
assert!(!migration.sql.contains(forbidden), "business schema leaked into bootstrap SQL: {forbidden}");
|
||||
assert!(!v000.sql.contains(forbidden), "business schema leaked into immutable V000 SQL: {forbidden}");
|
||||
}
|
||||
assert_eq!(super::migration_checksum(v000.sql), "d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450");
|
||||
let v001 = &super::EMBEDDED_MIGRATIONS[1];
|
||||
assert_eq!(v001.version, 1);
|
||||
assert_eq!(v001.name, "raw_transaction");
|
||||
assert_eq!(v001.hook, super::MigrationHook::StoreIdentity);
|
||||
assert_eq!(super::migration_checksum(v001.sql), "6fe57ed0313d2ed295280dd6e49f6d86695d4e4effee2724a25e36db1ea17761");
|
||||
assert!(super::validate_embedded_registry(super::EMBEDDED_MIGRATIONS).is_ok());
|
||||
assert_eq!(crate::current_migration_version(), 0);
|
||||
let checksum = super::migration_checksum(migration.sql);
|
||||
assert_eq!(checksum.len(), 64);
|
||||
assert_eq!(checksum, "d29068b8c13b9dc0cc9ef6aaadd0fa12d41e0fe4c56541a1118c4bfc846a1450");
|
||||
assert_eq!(crate::current_migration_version(), 1);
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_002_ordered_registry_accepts_exact_history_prefix_and_full_history() {
|
||||
fn pre_003_v001_inventory_indexes_and_api_bounds_are_exact() {
|
||||
let sql = super::EMBEDDED_MIGRATIONS[1].sql;
|
||||
for required in [
|
||||
"CREATE TABLE ksp_store_identity",
|
||||
"CREATE TABLE ksp_raw_transactions",
|
||||
"CREATE TABLE ksp_raw_transaction_observations",
|
||||
"CREATE TABLE ksp_raw_transaction_archive_payloads",
|
||||
"CREATE INDEX ix_ksp_raw_transactions_slot_signature",
|
||||
"WHERE retention_state <> 'purged'",
|
||||
"octet_length(signature) = 64",
|
||||
"slot BETWEEN 0 AND 18446744073709551615",
|
||||
"block_time_unix_millis BETWEEN 0 AND 253402300799999",
|
||||
"octet_length(content_hash) = 32",
|
||||
"octet_length(payload) BETWEEN 1 AND 16777216",
|
||||
"format_version BETWEEN 1 AND 4294967295",
|
||||
"received_at_unix_millis BETWEEN 0 AND 253402300799999",
|
||||
"source_payload_size_bytes BETWEEN 0 AND 67108864",
|
||||
"origin IN ('backfill', 'import', 'live', 'repair', 'replay')",
|
||||
"retention_state IN ('full', 'archived', 'purged')",
|
||||
] {
|
||||
assert!(sql.contains(required), "V001 physical contract is missing: {required}");
|
||||
}
|
||||
assert_eq!(sql.matches("PRIMARY KEY").count(), 4);
|
||||
assert_eq!(sql.matches("REFERENCES ksp_raw_transactions(signature) ON DELETE RESTRICT").count(), 2);
|
||||
assert!(!sql.contains("compacted"));
|
||||
assert!(!sql.contains("BIGSERIAL"));
|
||||
assert!(!sql.contains("slot BIGINT"));
|
||||
assert!(sql.contains("network TEXT NOT NULL"));
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_003_ordered_registry_accepts_v000_prefix_and_full_v001_history() {
|
||||
let v000 = super::EMBEDDED_MIGRATIONS[0];
|
||||
let v001 = embedded(1, "synthetic", "SELECT 1;");
|
||||
let registry = [v000, v001];
|
||||
assert!(super::validate_embedded_registry(®istry).is_ok());
|
||||
let v001 = super::EMBEDDED_MIGRATIONS[1];
|
||||
let v000_checksum = super::migration_checksum(v000.sql);
|
||||
let prefix = [applied(0, v000.name, v000_checksum.as_str())];
|
||||
assert_eq!(super::validate_history(&prefix, ®istry).ok(), std::option::Option::Some(1));
|
||||
assert_eq!(super::validate_history(&prefix, super::EMBEDDED_MIGRATIONS).ok(), std::option::Option::Some(1));
|
||||
let v001_checksum = super::migration_checksum(v001.sql);
|
||||
let full = [applied(0, v000.name, v000_checksum.as_str()), applied(1, v001.name, v001_checksum.as_str())];
|
||||
assert_eq!(super::validate_history(&full, ®istry).ok(), std::option::Option::Some(2));
|
||||
assert_eq!(super::validate_history(&full, super::EMBEDDED_MIGRATIONS).ok(), std::option::Option::Some(2));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -58,10 +91,9 @@ fn pre_002_registry_rejects_empty_nonzero_gap_and_empty_metadata_entries() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_002_divergent_missing_or_gapped_history_is_terminal_mismatch() {
|
||||
fn pre_003_divergent_missing_or_gapped_history_is_terminal_mismatch() {
|
||||
let v000 = super::EMBEDDED_MIGRATIONS[0];
|
||||
let v001 = embedded(1, "synthetic", "SELECT 1;");
|
||||
let registry = [v000, v001];
|
||||
let v001 = super::EMBEDDED_MIGRATIONS[1];
|
||||
let v000_checksum = super::migration_checksum(v000.sql);
|
||||
let v001_checksum = super::migration_checksum(v001.sql);
|
||||
let wrong_name = [applied(0, "changed", v000_checksum.as_str())];
|
||||
@@ -69,21 +101,24 @@ fn pre_002_divergent_missing_or_gapped_history_is_terminal_mismatch() {
|
||||
let missing: [super::AppliedMigration; 0] = [];
|
||||
let missing_v000 = [applied(1, v001.name, v001_checksum.as_str())];
|
||||
for history in [&wrong_name[..], &wrong_checksum[..], &missing[..], &missing_v000[..]] {
|
||||
let result = super::validate_history(history, ®istry);
|
||||
let result = super::validate_history(history, super::EMBEDDED_MIGRATIONS);
|
||||
assert_eq!(result.err().map(|value| return value.kind()), std::option::Option::Some(crate::PostgresBackendErrorKind::MigrationMismatch));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_002_newer_history_is_rejected_without_down_migration() {
|
||||
fn pre_003_newer_history_is_rejected_without_down_migration() {
|
||||
let v000 = super::EMBEDDED_MIGRATIONS[0];
|
||||
let v001 = embedded(1, "synthetic", "SELECT 1;");
|
||||
let registry = [v000, v001];
|
||||
let v001 = super::EMBEDDED_MIGRATIONS[1];
|
||||
let v000_checksum = super::migration_checksum(v000.sql);
|
||||
let v001_checksum = super::migration_checksum(v001.sql);
|
||||
let history = [applied(0, v000.name, v000_checksum.as_str()), applied(1, v001.name, v001_checksum.as_str()), applied(2, "future", "future-checksum")];
|
||||
let result = super::validate_history(&history, ®istry);
|
||||
let history = [
|
||||
applied(0, v000.name, v000_checksum.as_str()),
|
||||
applied(1, v001.name, v001_checksum.as_str()),
|
||||
applied(2, "future", "future-checksum"),
|
||||
];
|
||||
let result = super::validate_history(&history, super::EMBEDDED_MIGRATIONS);
|
||||
assert_eq!(result.err().map(|value| return value.kind()), std::option::Option::Some(crate::PostgresBackendErrorKind::SchemaNewer));
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user