v0.3.8-pre.005
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-postgres-lib/tests/dependency_boundary.rs
|
||||
// version: 26
|
||||
// version: 27
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -184,6 +184,7 @@ fn pre_005_raw_account_acquisition_is_atomic_idempotent_and_keeps_trait_impls_ou
|
||||
assert!(!raw.contains(forbidden), "pre.005 account module contains later/destructive scope: {forbidden}");
|
||||
}
|
||||
for implementation in [
|
||||
"impl ksp_store_api::RawAccountStateInspectionRead for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountStateRead for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountStateWrite for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountObservationRead for PostgresBackend",
|
||||
@@ -218,6 +219,7 @@ fn pre_006_raw_account_additional_observation_is_reference_guarded_cancellation_
|
||||
assert!(!raw.contains(forbidden), "pre.006 account module contains later/destructive scope: {forbidden}");
|
||||
}
|
||||
for implementation in [
|
||||
"impl ksp_store_api::RawAccountStateInspectionRead for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountStateRead for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountStateWrite for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountObservationRead for PostgresBackend",
|
||||
@@ -374,11 +376,36 @@ fn pre_007_raw_account_pagination_is_keyset_cursor_bound_and_policy_free() {
|
||||
assert!(cursor.contains(required), "missing pre.007 account cursor/binding contract: {required}");
|
||||
}
|
||||
assert!(index.contains("ON ksp_raw_account_states (slot, pubkey, state_hash)"));
|
||||
for forbidden in [" OFFSET ", "limit.min(", "clamp(", "500", "1000"] {
|
||||
let ascending = raw.lines().find(|line| return line.starts_with("const LIST_ACCOUNT_STATES_ASC_SQL"));
|
||||
let ascending = match ascending {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => panic!("missing canonical account ascending keyset SQL"),
|
||||
};
|
||||
let descending = raw.lines().find(|line| return line.starts_with("const LIST_ACCOUNT_STATES_DESC_SQL"));
|
||||
let descending = match descending {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => panic!("missing canonical account descending keyset SQL"),
|
||||
};
|
||||
let by_pubkey_ascending = raw.lines().find(|line| return line.starts_with("const LIST_ACCOUNT_STATES_BY_PUBKEY_ASC_SQL"));
|
||||
let by_pubkey_ascending = match by_pubkey_ascending {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => panic!("missing canonical account pubkey ascending keyset SQL"),
|
||||
};
|
||||
let by_pubkey_descending = raw.lines().find(|line| return line.starts_with("const LIST_ACCOUNT_STATES_BY_PUBKEY_DESC_SQL"));
|
||||
let by_pubkey_descending = match by_pubkey_descending {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => panic!("missing canonical account pubkey descending keyset SQL"),
|
||||
};
|
||||
for statement in [ascending, descending, by_pubkey_ascending, by_pubkey_descending] {
|
||||
assert!(!statement.contains(" OFFSET "), "pre.007 canonical account keyset SQL must remain OFFSET-free");
|
||||
}
|
||||
assert!(!cursor.contains(" OFFSET "), "pre.007 account cursor contains forbidden OFFSET material");
|
||||
for forbidden in ["limit.min(", "clamp(", "500", "1000"] {
|
||||
assert!(!raw.contains(forbidden), "pre.007 account source contains forbidden pagination/policy material: {forbidden}");
|
||||
assert!(!cursor.contains(forbidden), "pre.007 account cursor contains forbidden pagination/policy material: {forbidden}");
|
||||
}
|
||||
for forbidden in [
|
||||
"impl ksp_store_api::RawAccountStateInspectionRead for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountStateRead for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountStateWrite for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountObservationRead for PostgresBackend",
|
||||
@@ -422,11 +449,12 @@ fn pre_007_raw_retention_is_atomic_compare_and_transition_without_fake_compactio
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_8_pre_004_backend_trait_implementations_cover_exact_eleven_raw_capabilities_in_runtime_bridge() {
|
||||
fn v0_3_8_pre_005_backend_trait_implementations_cover_exact_twelve_raw_capabilities_in_runtime_bridge() {
|
||||
let runtime = include_str!("../src/runtime.rs");
|
||||
for implementation in [
|
||||
"impl ksp_store_api::RawAccountObservationRead for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountObservationWrite for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountStateInspectionRead for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountStateRead for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountStateWrite for PostgresBackend",
|
||||
"impl ksp_store_api::RawTransactionInspectionRead for PostgresBackend",
|
||||
@@ -439,6 +467,6 @@ fn v0_3_8_pre_004_backend_trait_implementations_cover_exact_eleven_raw_capabilit
|
||||
] {
|
||||
assert_eq!(runtime.matches(implementation).count(), 1, "unexpected PostgreSQL RAW capability inventory: {implementation}");
|
||||
}
|
||||
assert_eq!(runtime.matches("impl ksp_store_api::Raw").count(), 11);
|
||||
assert_eq!(runtime.matches("impl ksp_store_api::Raw").count(), 12);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-postgres-lib/tests/hardening_completeness.rs
|
||||
// version: 19
|
||||
// version: 20
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -250,6 +250,9 @@ fn pre_009_live_raw_account_proof_is_opt_in_isolated_secret_safe_and_cross_famil
|
||||
"prove_additional_observations",
|
||||
"ReferenceNotFound",
|
||||
"prove_pagination_and_cursors",
|
||||
"prove_account_inspection",
|
||||
"inspect_raw_account_states",
|
||||
"RawAccountStateInspectionQuery",
|
||||
"KSPT",
|
||||
"prove_cross_family_coexistence",
|
||||
"persist_raw_transaction_acquisition",
|
||||
@@ -299,11 +302,12 @@ fn pre_009_live_raw_transaction_proof_is_opt_in_isolated_and_secret_safe() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_8_pre_004_raw_capability_implementation_inventory_is_exactly_eleven() {
|
||||
fn v0_3_8_pre_005_raw_capability_implementation_inventory_is_exactly_twelve() {
|
||||
let runtime = include_str!("../src/runtime.rs");
|
||||
let capability_impls = [
|
||||
"impl ksp_store_api::RawAccountObservationRead for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountObservationWrite for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountStateInspectionRead for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountStateRead for PostgresBackend",
|
||||
"impl ksp_store_api::RawAccountStateWrite for PostgresBackend",
|
||||
"impl ksp_store_api::RawTransactionInspectionRead for PostgresBackend",
|
||||
@@ -317,7 +321,7 @@ fn v0_3_8_pre_004_raw_capability_implementation_inventory_is_exactly_eleven() {
|
||||
for implementation in capability_impls {
|
||||
assert_eq!(runtime.matches(implementation).count(), 1, "unexpected PostgreSQL capability implementation inventory: {implementation}");
|
||||
}
|
||||
assert_eq!(runtime.matches("impl ksp_store_api::Raw").count(), 11);
|
||||
assert_eq!(runtime.matches("impl ksp_store_api::Raw").count(), 12);
|
||||
let migration = include_str!("../src/migration.rs");
|
||||
assert!(migration.contains("raw_account_state"));
|
||||
assert!(migration.contains("crate::V002_RESOURCES"));
|
||||
@@ -466,3 +470,38 @@ fn pre_010_v002_schema_inventory_is_exact_family_local_and_query_justified() {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_8_pre_005_raw_account_keyset_sql_remains_offset_free_while_inspection_is_random_access() {
|
||||
let source = include_str!("../src/raw_account.rs");
|
||||
for name in [
|
||||
"const LIST_ACCOUNT_STATES_ASC_SQL",
|
||||
"const LIST_ACCOUNT_STATES_DESC_SQL",
|
||||
"const LIST_ACCOUNT_STATES_BY_PUBKEY_ASC_SQL",
|
||||
"const LIST_ACCOUNT_STATES_BY_PUBKEY_DESC_SQL",
|
||||
] {
|
||||
let statement = source.lines().find(|line| return line.starts_with(name));
|
||||
let statement = match statement {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => panic!("missing canonical account keyset SQL: {name}"),
|
||||
};
|
||||
assert!(!statement.contains(" OFFSET "));
|
||||
}
|
||||
for name in ["const INSPECT_ACCOUNT_STATES_ASC_SQL", "const INSPECT_ACCOUNT_STATES_DESC_SQL"] {
|
||||
let statement = source.lines().find(|line| return line.starts_with(name));
|
||||
let statement = match statement {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => panic!("missing account inspection SQL: {name}"),
|
||||
};
|
||||
for required in ["COUNT(*)", "LEFT JOIN LATERAL", "OCTET_LENGTH(account_row.data)", "LIMIT $4 OFFSET $5"] {
|
||||
assert!(statement.contains(required), "missing account inspection SQL contract: {required}");
|
||||
}
|
||||
assert!(!statement.contains("account_row.data,"));
|
||||
assert!(!statement.contains("SELECT account_row.data"));
|
||||
assert!(statement.contains("ORDER BY account_row.slot"));
|
||||
assert!(statement.contains("account_row.pubkey"));
|
||||
assert!(statement.contains("account_row.state_hash"));
|
||||
}
|
||||
assert_eq!(source.matches(" OFFSET ").count(), 2);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-postgres-lib/tests/postgres_raw_account_live.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -68,7 +68,10 @@ enum LiveAccountPersistResult {
|
||||
#[test]
|
||||
#[ignore = "opt-in real PostgreSQL RawAccountState proof; reads one dedicated URI from stdin"]
|
||||
fn pre_009_real_postgres_raw_account_vertical_slice_is_atomic_concurrent_and_recoverable() {
|
||||
eprintln!("KSP Store RawAccountState live proof: reading one dedicated URI from stdin without echoing it from the test.");
|
||||
eprintln!(
|
||||
"KSP Store RawAccountState live proof: waiting for one dedicated PostgreSQL URI line on stdin; the scenario does not start until Enter is pressed."
|
||||
);
|
||||
eprintln!("KSP Store RawAccountState live proof: the test itself never echoes the URI.");
|
||||
let uri_result = read_uri_from_stdin();
|
||||
let uri = match uri_result {
|
||||
std::result::Result::Ok(value) => value,
|
||||
@@ -179,6 +182,7 @@ async fn run_raw_account_scenario(admin: &mut tokio_postgres::Client, uri: &str,
|
||||
prove_atomic_idempotence_and_conflicts(&backend).await,
|
||||
prove_additional_observations(&backend).await,
|
||||
prove_pagination_and_cursors(&backend).await,
|
||||
prove_account_inspection(&backend).await,
|
||||
prove_cross_family_coexistence(&backend, admin).await,
|
||||
] {
|
||||
if let std::result::Result::Err(error) = proof {
|
||||
@@ -561,6 +565,80 @@ async fn prove_pagination_and_cursors(backend: &ksp_store_postgres_lib::Postgres
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
|
||||
async fn prove_account_inspection(backend: &ksp_store_postgres_lib::PostgresBackend) -> std::result::Result<(), LiveFailure> {
|
||||
let filtered_query = match account_inspection_query(
|
||||
std::option::Option::Some(ksp_store_api::Pubkey::new_from_array([50; 32])),
|
||||
200,
|
||||
202,
|
||||
ksp_store_api::RawSortDirection::Ascending,
|
||||
1,
|
||||
2,
|
||||
) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let filtered = match backend.inspect_raw_account_states(&filtered_query).await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(LiveFailure::new("inspection_filtered_query")),
|
||||
};
|
||||
if filtered.filtered_items() != 3 || filtered.total_items() < 5 || filtered.items().len() != 2 {
|
||||
return std::result::Result::Err(LiveFailure::new("inspection_filtered_counts"));
|
||||
}
|
||||
let first = &filtered.items()[0];
|
||||
let second = &filtered.items()[1];
|
||||
if first.reference().slot() != 200
|
||||
|| first.reference().pubkey() != &ksp_store_api::Pubkey::new_from_array([50; 32])
|
||||
|| first.reference().state_hash() != ksp_store_api::RawContentHash::new([51; 32])
|
||||
|| first.data_length_bytes() != 2
|
||||
|| second.reference().slot() != 201
|
||||
|| second.reference().state_hash() != ksp_store_api::RawContentHash::new([52; 32])
|
||||
|| second.data_length_bytes() != 2
|
||||
{
|
||||
return std::result::Result::Err(LiveFailure::new("inspection_filtered_order"));
|
||||
}
|
||||
let descending_query = match account_inspection_query(std::option::Option::None, 200, 202, ksp_store_api::RawSortDirection::Descending, 1, 2) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let descending = match backend.inspect_raw_account_states(&descending_query).await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(LiveFailure::new("inspection_descending_query")),
|
||||
};
|
||||
if descending.filtered_items() != 5 || descending.items().len() != 2 {
|
||||
return std::result::Result::Err(LiveFailure::new("inspection_descending_counts"));
|
||||
}
|
||||
let descending_first = &descending.items()[0];
|
||||
let descending_second = &descending.items()[1];
|
||||
if descending_first.reference().slot() != 201
|
||||
|| descending_first.reference().pubkey() != &ksp_store_api::Pubkey::new_from_array([51; 32])
|
||||
|| descending_first.reference().state_hash() != ksp_store_api::RawContentHash::new([53; 32])
|
||||
|| descending_second.reference().slot() != 201
|
||||
|| descending_second.reference().pubkey() != &ksp_store_api::Pubkey::new_from_array([50; 32])
|
||||
|| descending_second.reference().state_hash() != ksp_store_api::RawContentHash::new([52; 32])
|
||||
{
|
||||
return std::result::Result::Err(LiveFailure::new("inspection_descending_order"));
|
||||
}
|
||||
let deep_query = match account_inspection_query(
|
||||
std::option::Option::Some(ksp_store_api::Pubkey::new_from_array([50; 32])),
|
||||
200,
|
||||
202,
|
||||
ksp_store_api::RawSortDirection::Ascending,
|
||||
10_000,
|
||||
2,
|
||||
) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let deep = match backend.inspect_raw_account_states(&deep_query).await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(LiveFailure::new("inspection_deep_query")),
|
||||
};
|
||||
if deep.filtered_items() != 3 || deep.total_items() != filtered.total_items() || !deep.items().is_empty() {
|
||||
return std::result::Result::Err(LiveFailure::new("inspection_deep_page"));
|
||||
}
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
|
||||
async fn prove_cross_family_coexistence(
|
||||
backend: &ksp_store_postgres_lib::PostgresBackend,
|
||||
admin: &tokio_postgres::Client,
|
||||
@@ -850,6 +928,30 @@ fn account_query(
|
||||
return std::result::Result::Ok(ksp_store_api::RawAccountStateQuery::new(network, pubkey, slots, direction, page));
|
||||
}
|
||||
|
||||
fn account_inspection_query(
|
||||
pubkey: std::option::Option<ksp_store_api::Pubkey>,
|
||||
start: u64,
|
||||
end: u64,
|
||||
direction: ksp_store_api::RawSortDirection,
|
||||
offset: u64,
|
||||
limit: u64,
|
||||
) -> std::result::Result<ksp_store_api::RawAccountStateInspectionQuery, LiveFailure> {
|
||||
let network = match network("devnet") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let slots = match ksp_store_api::RawSlotRange::new(std::option::Option::Some(start), std::option::Option::Some(end)) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(LiveFailure::new("inspection_model_slot_range")),
|
||||
};
|
||||
let limit = match ksp_store_api::RawPageLimit::new(limit) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(LiveFailure::new("inspection_model_page_limit")),
|
||||
};
|
||||
let page = ksp_store_api::RawInspectionPageRequest::new(offset, limit);
|
||||
return std::result::Result::Ok(ksp_store_api::RawAccountStateInspectionQuery::new(network, pubkey, slots, direction, page));
|
||||
}
|
||||
|
||||
fn account_reference(pubkey_seed: u8, slot: u64, hash_seed: u8) -> std::result::Result<ksp_store_api::RawAccountStateReference, LiveFailure> {
|
||||
let network = match network("devnet") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-postgres-lib/tests/public_api.rs
|
||||
// version: 15
|
||||
// version: 16
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -117,9 +117,11 @@ fn pre_005_raw_write_bridge_uses_only_backend_independent_models_and_outcomes()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_8_pre_004_raw_list_and_inspection_bridges_use_only_backend_independent_models() {
|
||||
let _list = ksp_store_postgres_lib::PostgresBackend::list_raw_transactions;
|
||||
let _inspection = ksp_store_postgres_lib::PostgresBackend::inspect_raw_transactions;
|
||||
fn v0_3_8_pre_005_raw_list_and_inspection_bridges_use_only_backend_independent_models() {
|
||||
let _account_list = ksp_store_postgres_lib::PostgresBackend::list_raw_account_states;
|
||||
let _account_inspection = ksp_store_postgres_lib::PostgresBackend::inspect_raw_account_states;
|
||||
let _transaction_list = ksp_store_postgres_lib::PostgresBackend::list_raw_transactions;
|
||||
let _transaction_inspection = ksp_store_postgres_lib::PostgresBackend::inspect_raw_transactions;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -133,6 +135,7 @@ fn assert_raw_capabilities<T>()
|
||||
where
|
||||
T: ksp_store_api::RawAccountObservationRead
|
||||
+ ksp_store_api::RawAccountObservationWrite
|
||||
+ ksp_store_api::RawAccountStateInspectionRead
|
||||
+ ksp_store_api::RawAccountStateRead
|
||||
+ ksp_store_api::RawAccountStateWrite
|
||||
+ ksp_store_api::RawTransactionInspectionRead
|
||||
@@ -148,7 +151,7 @@ where
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_8_pre_004_postgres_backend_implements_transaction_inspection_as_capability_11_of_11() {
|
||||
fn v0_3_8_pre_005_postgres_backend_implements_both_inspection_capabilities_as_12_of_12() {
|
||||
assert_raw_capabilities::<ksp_store_postgres_lib::PostgresBackend>();
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user