// file: crates/knowledge-store-postgres-lib/tests/postgres_migration.rs // version: 2 //! Integration test for the initial PostgreSQL migration in an isolated schema. fn test_schema_name() -> String { let elapsed = match std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH) { Ok(value) => value, Err(_) => return format!("knowledge_test_{}", std::process::id()), }; return format!("knowledge_test_{}_{}", std::process::id(), elapsed.as_nanos()); } fn database_url_with_search_path(database_url: &str, schema: &str) -> String { let separator = if database_url.contains('?') { '&' } else { '?' }; return format!("{database_url}{separator}options=-c%20search_path%3D{schema}"); } async fn connect(database_url: &str) -> Option { let connection_result = tokio_postgres::connect(database_url, tokio_postgres::NoTls).await; assert!(connection_result.is_ok(), "test PostgreSQL connection failed"); let (client, connection) = match connection_result { Ok(value) => value, Err(_) => return None, }; let _connection_task = tokio::spawn(async move { let _connection_result = connection.await; return; }); return Some(client); } #[tokio::test] #[ignore = "requires KNOWLEDGE_POSTGRES_TEST_URL"] async fn initial_migration_runs_in_isolated_schema() { let database_url_result = std::env::var("KNOWLEDGE_POSTGRES_TEST_URL"); assert!(database_url_result.is_ok(), "KNOWLEDGE_POSTGRES_TEST_URL is required"); let database_url = match database_url_result { Ok(value) => value, Err(_) => return, }; let schema = test_schema_name(); let admin = match connect(database_url.as_str()).await { Some(value) => value, None => return, }; let create_schema = format!("CREATE SCHEMA {schema}"); let create_result = admin.batch_execute(create_schema.as_str()).await; assert!(create_result.is_ok(), "isolated PostgreSQL schema creation failed"); if create_result.is_err() { return; } let isolated_url = database_url_with_search_path(database_url.as_str(), schema.as_str()); let config_result = knowledge_store_postgres_lib::PostgresStoreConfig::new(isolated_url.as_str(), 2); assert!(config_result.is_ok(), "PostgreSQL store configuration failed"); let config = match config_result { Ok(value) => value, Err(_) => return, }; let store_result = knowledge_store_postgres_lib::PostgresStore::new(config); assert!(store_result.is_ok(), "PostgreSQL store construction failed"); let store = match store_result { Ok(value) => value, Err(_) => return, }; let migration_result = store.apply_migrations().await; assert!(migration_result.is_ok(), "initial PostgreSQL migration failed"); let table_result = admin .query( "SELECT table_name FROM information_schema.tables WHERE table_schema = $1 AND table_name IN ('knowledge_sources', 'knowledge_source_sync_state', 'refinery_schema_history') ORDER BY table_name", &[&schema], ) .await; assert!(table_result.is_ok(), "PostgreSQL migration verification query failed"); let table_rows = match table_result { Ok(value) => value, Err(_) => return, }; assert_eq!(table_rows.len(), 3); if table_rows.len() == 3 { assert_eq!(table_rows[0].get::(0), "knowledge_source_sync_state"); assert_eq!(table_rows[1].get::(0), "knowledge_sources"); assert_eq!(table_rows[2].get::(0), "refinery_schema_history"); } drop(store); let drop_schema = format!("DROP SCHEMA {schema} CASCADE"); let drop_result = admin.batch_execute(drop_schema.as_str()).await; assert!(drop_result.is_ok(), "isolated PostgreSQL schema cleanup failed"); return; }