fix(dev): stabilize macOS signing and isolate test keys
This commit is contained in:
99 files changed
+1022
-533
No files matched your search
@@ -5,6 +5,7 @@ edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
|
||||
[features]
|
||||
test-support = []
|
||||
default = ["duckdb-sidecar", "dynamodb", "mq-admin", "sqlite-sqlcipher", "system-fonts"]
|
||||
duckdb-sidecar = ["dbx-sql/duckdb-sidecar", "dbx-drivers/duckdb-sidecar"]
|
||||
dynamodb = ["dbx-drivers/dynamodb"]
|
||||
@@ -92,6 +93,7 @@ tempfile = "3"
|
||||
windows-sys = { version = "0.61", features = ["Win32_Storage_FileSystem", "Win32_Foundation", "Win32_Security"] }
|
||||
|
||||
[dev-dependencies]
|
||||
dbx-core = { path = ".", default-features = false, features = ["test-support"] }
|
||||
zstd = "0.13"
|
||||
dbx-drivers = { path = "../dbx-drivers", default-features = false, features = ["test-support"] }
|
||||
dbx-plugin-runtime = { path = "../dbx-plugin-runtime", features = ["test-support"] }
|
||||
|
||||
@@ -894,7 +894,6 @@ async fn ensure_connection_writable(state: &AppState, conn_id: &str, operation:
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use crate::storage::Storage;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
fn mq_connection(read_only: bool) -> ConnectionConfig {
|
||||
@@ -987,7 +986,8 @@ mod tests {
|
||||
SystemTime::now().duration_since(UNIX_EPOCH).expect("system time should be after UNIX epoch").as_nanos();
|
||||
let dir = std::env::temp_dir().join(format!("dbx-mq-service-test-{stamp}"));
|
||||
std::fs::create_dir_all(&dir).expect("failed to create test directory");
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.expect("failed to open test storage");
|
||||
let storage =
|
||||
crate::persistence::test_storage::open(&dir.join("storage.db")).await.expect("failed to open test storage");
|
||||
let state = AppState::new_with_plugin_dir(storage, dir.join("plugins"));
|
||||
state.configs.write().await.insert(config.id.clone(), config);
|
||||
(state, dir)
|
||||
|
||||
@@ -639,7 +639,7 @@ mod tests {
|
||||
async fn raw_mutation_requires_writable_connection_before_adapter_build() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-nacos-service-test-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = crate::storage::Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let mut cfg = crate::models::connection::ConnectionConfig {
|
||||
docs_notes_path: None,
|
||||
@@ -721,7 +721,7 @@ mod tests {
|
||||
async fn config_rollback_requires_writable_connection_before_adapter_build() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-nacos-service-test-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = crate::storage::Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let cfg = crate::models::connection::ConnectionConfig {
|
||||
docs_notes_path: None,
|
||||
|
||||
@@ -276,7 +276,7 @@ mod tests {
|
||||
"query_timeout_secs": 30
|
||||
}))
|
||||
.unwrap();
|
||||
let storage = crate::storage::Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(config.id.clone(), config.clone());
|
||||
state
|
||||
|
||||
@@ -1690,7 +1690,7 @@ mod tests {
|
||||
|
||||
async fn gate_context(session_id: Option<&str>) -> (tempfile::TempDir, AgentLoopContext) {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let storage = crate::storage::Storage::open(&temp_dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_dir.path().join("storage.db")).await.unwrap();
|
||||
let ctx = AgentLoopContext {
|
||||
state: Arc::new(AppState::new(storage)),
|
||||
connection_id: "db".to_string(),
|
||||
|
||||
@@ -1592,8 +1592,6 @@ mod tests {
|
||||
use crate::db::agent_driver::{AgentDriverClient, AgentLaunchSpec};
|
||||
#[cfg(unix)]
|
||||
use crate::models::connection::{default_redis_key_separator, ConnectionConfig};
|
||||
#[cfg(unix)]
|
||||
use crate::storage::Storage;
|
||||
|
||||
#[cfg(unix)]
|
||||
async fn spawn_recording_agent(record_path: &std::path::Path) -> (AgentDriverClient, tempfile::NamedTempFile) {
|
||||
@@ -1789,7 +1787,7 @@ for line in sys.stdin:
|
||||
assert!(!confirmed_execute_query.description.contains("confirmed write"));
|
||||
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&temp_dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_dir.path().join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let call = ToolCall {
|
||||
id: "mongo-find-one".to_string(),
|
||||
@@ -1818,7 +1816,7 @@ for line in sys.stdin:
|
||||
#[tokio::test]
|
||||
async fn mongodb_agent_keeps_all_writes_blocked_after_sql_confirmation() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&temp_dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_dir.path().join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let permissions = AgentSqlPermissions {
|
||||
allow_writes: true,
|
||||
@@ -2139,7 +2137,7 @@ for line in sys.stdin:
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let record_path = temp_dir.path().join("agent-requests.jsonl");
|
||||
let (client, _script) = spawn_recording_agent(&record_path).await;
|
||||
let storage = Storage::open(&temp_dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_dir.path().join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let connection = agent_test_connection("dameng-1", "Dameng", DatabaseType::Dameng, "APPDB");
|
||||
state.configs.write().await.insert(connection.id.clone(), connection);
|
||||
@@ -2207,7 +2205,7 @@ for line in sys.stdin:
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let record_path = temp_dir.path().join("agent-requests.jsonl");
|
||||
let (client, _script) = spawn_recording_agent(&record_path).await;
|
||||
let storage = Storage::open(&temp_dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_dir.path().join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let connection = agent_test_connection("mysql-1", "MySQL", DatabaseType::Mysql, "rs_main");
|
||||
state.configs.write().await.insert(connection.id.clone(), connection);
|
||||
@@ -2605,7 +2603,7 @@ for line in sys.stdin:
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
rt.block_on(async {
|
||||
let storage = crate::storage::Storage::open(&temp_dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_dir.path().join("storage.db")).await.unwrap();
|
||||
let state = std::sync::Arc::new(crate::connection::AppState::new(storage));
|
||||
let tool_call = ToolCall {
|
||||
id: "call-gct".to_string(),
|
||||
|
||||
@@ -1117,7 +1117,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn stale_tool_bindings_cannot_bypass_revoked_ai_access() {
|
||||
let root = tempfile::tempdir().unwrap();
|
||||
let storage = crate::storage::Storage::open(&root.path().join("dbx.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&root.path().join("dbx.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.storage.set_ai_plugin_tool_plugin_enabled("io.dbx.kafka", true).await.unwrap();
|
||||
let set = build_tool_set(
|
||||
|
||||
@@ -6925,7 +6925,6 @@ mod tests {
|
||||
};
|
||||
use crate::query;
|
||||
use crate::schema;
|
||||
use crate::storage::Storage;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
@@ -7139,7 +7138,7 @@ mod tests {
|
||||
async fn apply_session_credential_injects_saved_password_only_for_no_save_connections() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-core-session-cred-{}", std::process::id()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new_with_plugin_dir(storage, dir.join("plugins"));
|
||||
let _ = state.session_credentials.set("", "conn-a", "s3cret");
|
||||
|
||||
@@ -7173,7 +7172,7 @@ mod tests {
|
||||
async fn apply_session_credential_reads_owner_scoped_credentials_only() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-core-session-cred-owner-{}", std::process::id()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new_with_plugin_dir(storage, dir.join("plugins"));
|
||||
|
||||
let mut config = mysql_config(None);
|
||||
@@ -7205,7 +7204,7 @@ mod tests {
|
||||
async fn pool_credential_owner_mismatch_prevents_cross_session_pool_reuse() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-core-pool-owner-{}", std::process::id()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new_with_plugin_dir(storage, dir.join("plugins"));
|
||||
|
||||
let mut config = mysql_config(None);
|
||||
@@ -7820,7 +7819,7 @@ mod tests {
|
||||
async fn test_app_state() -> (AppState, std::path::PathBuf) {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-core-test-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
(AppState::new(storage), dir)
|
||||
}
|
||||
|
||||
@@ -8064,7 +8063,7 @@ mod tests {
|
||||
async fn app_state_uses_explicit_agent_dir() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-core-agent-dir-test-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let agent_dir = dir.join("agents");
|
||||
|
||||
let state = AppState::new_with_plugin_and_agent_dir_and_app_version(
|
||||
@@ -8329,7 +8328,7 @@ mod tests {
|
||||
async fn jdbc_plugin_env_uses_managed_jre_when_installed() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-core-jdbc-managed-jre-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new_with_plugin_and_agent_dir_and_app_version(
|
||||
storage,
|
||||
dir.join("plugins"),
|
||||
@@ -8349,7 +8348,7 @@ mod tests {
|
||||
async fn jdbc_plugin_env_keeps_wrapper_fallback_when_managed_jre_is_missing() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-core-jdbc-missing-jre-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new_with_plugin_and_agent_dir_and_app_version(
|
||||
storage,
|
||||
dir.join("plugins"),
|
||||
@@ -8367,7 +8366,7 @@ mod tests {
|
||||
async fn jdbc_plugin_env_uses_custom_java_runtime() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-core-jdbc-custom-jre-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new_with_plugin_and_agent_dir_and_app_version(
|
||||
storage,
|
||||
dir.join("plugins"),
|
||||
|
||||
@@ -131,7 +131,7 @@ mod tests {
|
||||
|
||||
async fn app_state() -> (AppState, tempfile::TempDir) {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = crate::storage::Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
(AppState::new(storage), dir)
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,6 @@ mod tests {
|
||||
use super::{export_table_data_csv_core, CsvQuoteMode, TableCsvExportOptions};
|
||||
use crate::connection::AppState;
|
||||
use crate::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use crate::storage::Storage;
|
||||
|
||||
fn salesforce_config(id: &str) -> ConnectionConfig {
|
||||
let mut config = serde_json::from_value::<ConnectionConfig>(serde_json::json!({
|
||||
@@ -148,7 +147,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn salesforce_table_csv_export_is_refused_before_a_file_is_created() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let config = salesforce_config("sfdc-csv");
|
||||
state.configs.write().await.insert(config.id.clone(), config);
|
||||
|
||||
@@ -4077,7 +4077,6 @@ mod tests {
|
||||
use super::{ExportProgress, LenientExportErrors};
|
||||
use crate::connection::AppState;
|
||||
use crate::models::connection::DatabaseType;
|
||||
use crate::storage::Storage;
|
||||
use crate::types::SpatialColumn;
|
||||
use crate::types::{ObjectInfo, ObjectSourceKind, TableInfo};
|
||||
use serde_json::{json, Value};
|
||||
@@ -6510,7 +6509,7 @@ mod tests {
|
||||
}
|
||||
|
||||
async fn test_app_state(scratch_dir: &std::path::Path) -> AppState {
|
||||
let storage = Storage::open(&scratch_dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&scratch_dir.join("storage.db")).await.unwrap();
|
||||
AppState::new(storage)
|
||||
}
|
||||
|
||||
|
||||
@@ -4014,7 +4014,6 @@ mod tests {
|
||||
|
||||
use crate::db::agent_driver::{AgentDriverClient, AgentLaunchSpec};
|
||||
use crate::models::connection::ConnectionConfig;
|
||||
use crate::storage::Storage;
|
||||
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let mut file = tempfile::NamedTempFile::new_in(directory.path()).unwrap();
|
||||
@@ -4047,7 +4046,7 @@ for line in sys.stdin:
|
||||
.await
|
||||
.unwrap();
|
||||
client.try_optional_handshake("test").await.unwrap();
|
||||
let storage = Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = crate::connection::AppState::new(storage);
|
||||
let config: ConnectionConfig = serde_json::from_value(serde_json::json!({
|
||||
"id": "legacy",
|
||||
|
||||
@@ -2665,7 +2665,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn manual_file_missing_session_never_falls_back_to_ordinary_execution() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = crate::storage::Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let request = SqlFileRequest {
|
||||
txn_session_id: Some("expired-session".to_string()),
|
||||
@@ -2945,7 +2945,7 @@ mod tests {
|
||||
async fn file_progress_executor_preserves_success_cancellation_and_failure() {
|
||||
let directory = std::env::temp_dir().join(format!("dbx-file-progress-{}", uuid::Uuid::new_v4()));
|
||||
tokio::fs::create_dir_all(&directory).await.unwrap();
|
||||
let storage = crate::storage::Storage::open(&directory.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&directory.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let comments = "-- no database operation\n".repeat(40_000).into_bytes();
|
||||
for (bytes, cancel, terminal) in [
|
||||
@@ -3348,7 +3348,7 @@ mod tests {
|
||||
async fn streaming_gaussdb_on_error_stop_overrides_continue_on_error_at_script_position() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-sql-file-stop-on-error-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = crate::storage::Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = crate::connection::AppState::new(storage);
|
||||
let config: crate::models::connection::ConnectionConfig = serde_json::from_value(serde_json::json!({
|
||||
"id": "gauss-stream",
|
||||
|
||||
@@ -2300,7 +2300,6 @@ mod tests {
|
||||
use crate::plugins::{
|
||||
InstalledPlugin, PluginDriverManifest, PluginDriverSession, PluginManifest, PluginRuntimeEnv,
|
||||
};
|
||||
use crate::storage::Storage;
|
||||
use crate::xlsx_export::{build_xlsx_workbook, XlsxWorksheetData};
|
||||
use serde_json::json;
|
||||
use std::io::Read;
|
||||
@@ -2390,7 +2389,7 @@ mod tests {
|
||||
"query_timeout_secs": 30
|
||||
}))
|
||||
.unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(config.id.clone(), config.clone());
|
||||
let export_id = format!("export-{}", uuid::Uuid::new_v4());
|
||||
@@ -2566,7 +2565,7 @@ mod tests {
|
||||
"query_timeout_secs": 30
|
||||
}))
|
||||
.unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(config.id.clone(), config);
|
||||
let export_id = format!("export-{}", uuid::Uuid::new_v4());
|
||||
|
||||
@@ -7507,7 +7507,6 @@ where
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use crate::storage::Storage;
|
||||
use crate::xlsx_export::{build_xlsx_workbook_multi, XlsxWorksheetData};
|
||||
use std::io::{Cursor, Write};
|
||||
|
||||
@@ -9493,7 +9492,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn truncate_xlsx_with_malformed_tail_preserves_existing_rows() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "xlsx-truncate-tail";
|
||||
let pool_key = format!("{connection_id}:session:import");
|
||||
@@ -9585,7 +9584,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn cancelling_xlsx_after_validation_prevents_non_transactional_truncate() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "cancel-xlsx-after-validation";
|
||||
let pool_key = format!("{connection_id}:session:import");
|
||||
@@ -9673,7 +9672,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn cancelling_before_first_truncate_batch_preserves_existing_rows() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "cancel-truncate-first-batch";
|
||||
let pool_key = format!("{connection_id}:session:import");
|
||||
@@ -11312,7 +11311,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn sqlserver_staging_cleanup_failure_invalidates_cached_pool() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let pool_key = "sqlserver-cleanup-failure";
|
||||
let database_path = dir.path().join("target.db");
|
||||
@@ -11360,7 +11359,7 @@ mod tests {
|
||||
use std::sync::Arc;
|
||||
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let pool_key = "cancel-sql-sub-batches:session:import";
|
||||
let database_path = dir.path().join("target.db");
|
||||
@@ -11427,7 +11426,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn pending_postgres_copy_is_not_flushed_after_cancellation() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let mut accumulator = Some(PostgresCopyAccumulator::with_limits("COPY items".to_string(), 1024, 100));
|
||||
accumulator.as_mut().unwrap().append_row(b"1\n");
|
||||
@@ -11455,7 +11454,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn postgres_copy_internal_flush_stops_before_write_when_cancelled() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let plan = CompiledImportPlan {
|
||||
mapped_source_indexes: vec![0],
|
||||
@@ -11579,7 +11578,7 @@ mod tests {
|
||||
impl SqliteAppendTestContext {
|
||||
async fn new(test_name: &str, max_rows: usize) -> Self {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let pool_key = format!("{test_name}:session:import");
|
||||
let database_path = dir.path().join("target.db");
|
||||
@@ -11695,7 +11694,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn delimited_sqlite_append_import_flushes_the_final_window() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "sqlite-delimited-append";
|
||||
let pool_key = format!("{connection_id}:session:import");
|
||||
@@ -11929,7 +11928,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn oracle_jdbc_import_maps_xls_rows_to_insert_all() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "oracle-jdbc-import";
|
||||
let config: ConnectionConfig = serde_json::from_value(serde_json::json!({
|
||||
|
||||
@@ -10871,7 +10871,7 @@ CREATE TABLE "Other"."prefix""Source"."NAME" ("ID" INT);"#;
|
||||
async fn test_app_state() -> (AppState, std::path::PathBuf) {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-transfer-test-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = crate::storage::Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
(AppState::new(storage), dir)
|
||||
}
|
||||
|
||||
|
||||
@@ -244,7 +244,7 @@ mod tests {
|
||||
|
||||
async fn state_fixture() -> (Arc<AppState>, tempfile::TempDir) {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = crate::storage::Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new_with_plugin_dir(storage, directory.path().join("plugins")));
|
||||
(state, directory)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use serde_json::json;
|
||||
|
||||
async fn sqlite_fixture() -> (tempfile::TempDir, Arc<AppState>, TransferRequest, String, String) {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = crate::storage::Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new_with_plugin_dir(storage, directory.path().join("plugins")));
|
||||
for id in ["source", "target"] {
|
||||
let path = directory.path().join(format!("{id}.db"));
|
||||
@@ -118,7 +118,7 @@ async fn transfer_rebuild_preview_plans_without_executing_ddl() {
|
||||
#[tokio::test]
|
||||
async fn transfer_keyset_pagination_copies_every_row_across_many_batches() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = crate::storage::Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new_with_plugin_dir(storage, directory.path().join("plugins")));
|
||||
for id in ["source", "target"] {
|
||||
let path = directory.path().join(format!("{id}.db"));
|
||||
|
||||
@@ -1083,7 +1083,7 @@ mod tests {
|
||||
|
||||
async fn sqlite_dependency_fixture() -> (AppState, crate::db::sqlite::SqliteHandle, tempfile::TempDir) {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = crate::storage::Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let pool =
|
||||
crate::db::sqlite::connect_path_create_if_missing(directory.path().join("target.db").to_str().unwrap())
|
||||
|
||||
@@ -2264,7 +2264,6 @@ mod tests {
|
||||
default_redis_key_separator, ConnectionConfig, DatabaseType, SshTunnelConfig, TransportLayerConfig,
|
||||
};
|
||||
use crate::persistence::secret_codec::{managed_key_path, SecretKeyPolicy};
|
||||
use crate::storage::Storage;
|
||||
|
||||
fn make_test_config(name: &str, is_default: bool) -> AiConfigItem {
|
||||
AiConfigItem {
|
||||
@@ -2683,7 +2682,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn webdav_upload_terminates_collection_request_paths() {
|
||||
let storage = Storage::open(&temp_db_path("webdav-collection-paths")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("webdav-collection-paths")).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&storage, "test-version", None, None).await.unwrap();
|
||||
let (endpoint, server) = spawn_webdav_server(vec![201, 201, 200], true).await;
|
||||
let client = WebDavClient::new(WebDavConfig {
|
||||
@@ -2707,7 +2706,8 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn webdav_upload_accepts_existing_collections() {
|
||||
let storage = Storage::open(&temp_db_path("webdav-existing-collections")).await.unwrap();
|
||||
let storage =
|
||||
crate::persistence::test_storage::open(&temp_db_path("webdav-existing-collections")).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&storage, "test-version", None, None).await.unwrap();
|
||||
let (endpoint, server) = spawn_webdav_server(vec![405, 405, 200], false).await;
|
||||
let client = WebDavClient::new(WebDavConfig {
|
||||
@@ -2731,7 +2731,8 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn webdav_upload_preserves_collection_conflicts() {
|
||||
let storage = Storage::open(&temp_db_path("webdav-collection-conflict")).await.unwrap();
|
||||
let storage =
|
||||
crate::persistence::test_storage::open(&temp_db_path("webdav-collection-conflict")).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&storage, "test-version", None, None).await.unwrap();
|
||||
let (endpoint, server) = spawn_webdav_server(vec![409], false).await;
|
||||
let client = WebDavClient::new(WebDavConfig {
|
||||
@@ -2749,7 +2750,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn webdav_upload_skips_collection_requests_for_single_file() {
|
||||
let storage = Storage::open(&temp_db_path("webdav-single-file")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("webdav-single-file")).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&storage, "test-version", None, None).await.unwrap();
|
||||
let (endpoint, server) = spawn_webdav_server(vec![200], false).await;
|
||||
let client = WebDavClient::new(WebDavConfig {
|
||||
@@ -2916,7 +2917,8 @@ mod tests {
|
||||
assert_eq!(tls["truststore_password"], "");
|
||||
assert_eq!(tls["keystore_password"], "");
|
||||
|
||||
let storage = Storage::open(&temp_db_path("cassandra-sensitive-payload")).await.unwrap();
|
||||
let storage =
|
||||
crate::persistence::test_storage::open(&temp_db_path("cassandra-sensitive-payload")).await.unwrap();
|
||||
let payload = build_sensitive_payload(&storage, &[config], &[]).await.unwrap();
|
||||
assert!(payload.connection_secrets.iter().any(|secret| {
|
||||
secret.connection_id == "cassandra"
|
||||
@@ -2999,7 +3001,8 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn encrypted_snippet_snapshot_hides_and_restores_the_full_snapshot() {
|
||||
let storage = Storage::open(&temp_db_path("encrypted-snippet-snapshot")).await.unwrap();
|
||||
let storage =
|
||||
crate::persistence::test_storage::open(&temp_db_path("encrypted-snippet-snapshot")).await.unwrap();
|
||||
storage.save_connections(&[postgres_connection("pg", "db-secret")]).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&storage, "test-version", None, Some("sync-pass")).await.unwrap();
|
||||
|
||||
@@ -3017,7 +3020,8 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn encrypted_snippet_can_exclude_secrets_and_keep_local_credentials_on_restore() {
|
||||
let source = Storage::open(&temp_db_path("snippet-without-secrets-source")).await.unwrap();
|
||||
let source =
|
||||
crate::persistence::test_storage::open(&temp_db_path("snippet-without-secrets-source")).await.unwrap();
|
||||
source.save_connections(&[postgres_connection("pg", "remote-secret")]).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&source, "test-version", None, None).await.unwrap();
|
||||
assert!(snapshot.encrypted_secrets.is_none());
|
||||
@@ -3025,7 +3029,8 @@ mod tests {
|
||||
let encrypted = encrypt_snippet_snapshot(&snapshot, "snippet-password").unwrap();
|
||||
let restored =
|
||||
parse_snippet_snapshot(&serde_json::to_string(&encrypted).unwrap(), Some("snippet-password")).unwrap();
|
||||
let target = Storage::open(&temp_db_path("snippet-without-secrets-target")).await.unwrap();
|
||||
let target =
|
||||
crate::persistence::test_storage::open(&temp_db_path("snippet-without-secrets-target")).await.unwrap();
|
||||
target.save_connections(&[postgres_connection("pg", "local-secret")]).await.unwrap();
|
||||
|
||||
let summary = apply_sync_snapshot(
|
||||
@@ -3042,7 +3047,8 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn skipping_snippet_secret_restore_keeps_local_credentials() {
|
||||
let source = Storage::open(&temp_db_path("snippet-skip-secrets-source")).await.unwrap();
|
||||
let source =
|
||||
crate::persistence::test_storage::open(&temp_db_path("snippet-skip-secrets-source")).await.unwrap();
|
||||
source.save_connections(&[postgres_connection("pg", "remote-secret")]).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&source, "test-version", None, Some("secrets-password")).await.unwrap();
|
||||
assert!(snapshot.encrypted_secrets.is_some());
|
||||
@@ -3050,7 +3056,8 @@ mod tests {
|
||||
let encrypted = encrypt_snippet_snapshot(&snapshot, "snippet-password").unwrap();
|
||||
let restored =
|
||||
parse_snippet_snapshot(&serde_json::to_string(&encrypted).unwrap(), Some("snippet-password")).unwrap();
|
||||
let target = Storage::open(&temp_db_path("snippet-skip-secrets-target")).await.unwrap();
|
||||
let target =
|
||||
crate::persistence::test_storage::open(&temp_db_path("snippet-skip-secrets-target")).await.unwrap();
|
||||
target.save_connections(&[postgres_connection("pg", "local-secret")]).await.unwrap();
|
||||
|
||||
let summary = apply_sync_snapshot(
|
||||
@@ -3067,7 +3074,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn existing_encrypted_snippet_rejects_wrong_password_without_patch() {
|
||||
let storage = Storage::open(&temp_db_path("snippet-password-guard")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("snippet-password-guard")).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&storage, "test-version", None, None).await.unwrap();
|
||||
let encrypted = encrypt_snippet_snapshot(&snapshot, "correct-password").unwrap();
|
||||
let (base, server) =
|
||||
@@ -3089,7 +3096,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn existing_encrypted_snippet_accepts_correct_password_before_patch() {
|
||||
let storage = Storage::open(&temp_db_path("snippet-password-update")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("snippet-password-update")).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&storage, "test-version", None, None).await.unwrap();
|
||||
let encrypted = encrypt_snippet_snapshot(&snapshot, "correct-password").unwrap();
|
||||
let (base, server) = spawn_snippet_server(vec![
|
||||
@@ -3114,7 +3121,8 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn legacy_migration_skips_delete_when_remote_content_changes() {
|
||||
let storage = Storage::open(&temp_db_path("legacy-snippet-change-guard")).await.unwrap();
|
||||
let storage =
|
||||
crate::persistence::test_storage::open(&temp_db_path("legacy-snippet-change-guard")).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&storage, "test-version", None, None).await.unwrap();
|
||||
let legacy_content = serde_json::to_string(&snapshot).unwrap();
|
||||
let changed_content =
|
||||
@@ -3153,7 +3161,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn pending_legacy_cleanup_survives_response_loss_and_retries_after_restart() {
|
||||
let db = temp_db_path("legacy-snippet-cleanup-retry");
|
||||
let storage = Storage::open(&db).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&db).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&storage, "test-version", None, None).await.unwrap();
|
||||
let legacy_content = serde_json::to_string(&snapshot).unwrap();
|
||||
let (base, server) = spawn_snippet_server(vec![
|
||||
@@ -3178,7 +3186,7 @@ mod tests {
|
||||
assert_eq!(server.await.unwrap(), vec!["GET /gists/legacy-id HTTP/1.1", "POST /gists HTTP/1.1"]);
|
||||
drop(storage);
|
||||
|
||||
let storage = Storage::open(&db).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&db).await.unwrap();
|
||||
let settings = snippet_sync_settings(&storage, SnippetProvider::GitHub).await.unwrap();
|
||||
assert_eq!(settings.snippet_id.as_deref(), Some("new-id"));
|
||||
assert_eq!(settings.legacy_cleanup_required_id.as_deref(), Some("legacy-id"));
|
||||
@@ -3206,7 +3214,8 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn legacy_snippet_migration_preserves_remote_snapshot() {
|
||||
let storage = Storage::open(&temp_db_path("legacy-snippet-migration-guard")).await.unwrap();
|
||||
let storage =
|
||||
crate::persistence::test_storage::open(&temp_db_path("legacy-snippet-migration-guard")).await.unwrap();
|
||||
let local_snapshot = build_sync_snapshot(&storage, "local-version", None, None).await.unwrap();
|
||||
let remote_snapshot = build_sync_snapshot(&storage, "remote-version", None, None).await.unwrap();
|
||||
let mut legacy = serde_json::to_value(remote_snapshot).unwrap();
|
||||
@@ -3228,7 +3237,8 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn legacy_snippet_migration_refuses_unverifiable_encrypted_secrets() {
|
||||
let storage = Storage::open(&temp_db_path("legacy-snippet-migration-secrets")).await.unwrap();
|
||||
let storage =
|
||||
crate::persistence::test_storage::open(&temp_db_path("legacy-snippet-migration-secrets")).await.unwrap();
|
||||
storage.save_connections(&[postgres_connection("pg", "db-secret")]).await.unwrap();
|
||||
let remote_snapshot = build_sync_snapshot(&storage, "remote-version", None, Some("remote-pass")).await.unwrap();
|
||||
let content = serde_json::to_string(&remote_snapshot).unwrap();
|
||||
@@ -3254,7 +3264,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn snippet_sync_id_is_persisted_per_provider() {
|
||||
let storage = Storage::open(&temp_db_path("snippet-sync-id")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("snippet-sync-id")).await.unwrap();
|
||||
|
||||
save_snippet_sync_id(&storage, SnippetProvider::GitHub, Some("github-id")).await.unwrap();
|
||||
save_snippet_sync_id(&storage, SnippetProvider::Gitee, Some("gitee-id")).await.unwrap();
|
||||
@@ -3309,7 +3319,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn gitlab_instances_keep_saved_tokens_ids_and_cleanup_separate() {
|
||||
let storage = Storage::open(&temp_db_path("gitlab-instance-isolation")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("gitlab-instance-isolation")).await.unwrap();
|
||||
let first = "https://gitlab.example.com";
|
||||
let second = "https://gitlab.other.com";
|
||||
let config = |instance: &str| SnippetSyncConfig {
|
||||
@@ -3349,7 +3359,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn gitlab_create_and_download_use_private_personal_snippet_and_raw_file() {
|
||||
let storage = Storage::open(&temp_db_path("gitlab-create-download")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("gitlab-create-download")).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&storage, "test-version", None, None).await.unwrap();
|
||||
let encrypted = encrypt_snippet_snapshot(&snapshot, "password").unwrap();
|
||||
let (base, server) = spawn_gitlab_server(vec![
|
||||
@@ -3385,7 +3395,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn gitlab_download_uses_snippet_raw_url_branch() {
|
||||
let storage = Storage::open(&temp_db_path("gitlab-raw-url-branch")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("gitlab-raw-url-branch")).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&storage, "test-version", None, None).await.unwrap();
|
||||
let encrypted = serde_json::to_string(&encrypt_snippet_snapshot(&snapshot, "password").unwrap()).unwrap();
|
||||
let (base, server) = spawn_gitlab_server_with_status(vec![
|
||||
@@ -3416,7 +3426,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn gitlab_download_falls_back_to_master_when_main_raw_file_is_missing() {
|
||||
let storage = Storage::open(&temp_db_path("gitlab-master-fallback")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("gitlab-master-fallback")).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&storage, "test-version", None, None).await.unwrap();
|
||||
let encrypted = serde_json::to_string(&encrypt_snippet_snapshot(&snapshot, "password").unwrap()).unwrap();
|
||||
let (base, server) = spawn_gitlab_server_with_status(vec![
|
||||
@@ -3463,7 +3473,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn gitlab_update_checks_existing_password_before_put() {
|
||||
let storage = Storage::open(&temp_db_path("gitlab-password-guard")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("gitlab-password-guard")).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&storage, "test-version", None, None).await.unwrap();
|
||||
let encrypted = serde_json::to_string(&encrypt_snippet_snapshot(&snapshot, "password").unwrap()).unwrap();
|
||||
let (base, server) = spawn_gitlab_server(vec![
|
||||
@@ -3492,7 +3502,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn gitlab_wrong_password_never_updates_existing_snippet() {
|
||||
let storage = Storage::open(&temp_db_path("gitlab-wrong-password")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("gitlab-wrong-password")).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&storage, "test-version", None, None).await.unwrap();
|
||||
let encrypted = serde_json::to_string(&encrypt_snippet_snapshot(&snapshot, "correct").unwrap()).unwrap();
|
||||
let (base, server) =
|
||||
@@ -3514,7 +3524,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn gitlab_legacy_migration_creates_before_deleting_and_tracks_instance() {
|
||||
let storage = Storage::open(&temp_db_path("gitlab-legacy-migration")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("gitlab-legacy-migration")).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&storage, "test-version", None, None).await.unwrap();
|
||||
let legacy_content = serde_json::to_string(&snapshot).unwrap();
|
||||
let metadata = serde_json::json!({"files": [{"path": "dbx-sync.json"}]}).to_string();
|
||||
@@ -3604,7 +3614,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn webdav_sync_secrets_preference_round_trips_and_clears_passphrase() {
|
||||
let storage = Storage::open(&temp_db_path("sync-secrets-preference")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("sync-secrets-preference")).await.unwrap();
|
||||
|
||||
let status = webdav_sync_secrets_status(&storage).await.unwrap();
|
||||
assert!(!status.enabled);
|
||||
@@ -3627,7 +3637,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn saved_sync_passphrase_encrypts_snapshot_secrets_without_exposing_connection_passwords() {
|
||||
let storage = Storage::open(&temp_db_path("saved-sync-snapshot")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("saved-sync-snapshot")).await.unwrap();
|
||||
storage.save_connections(&[postgres_connection("pg", "db-secret")]).await.unwrap();
|
||||
|
||||
let plain_snapshot =
|
||||
@@ -3651,7 +3661,7 @@ mod tests {
|
||||
async fn legacy_sync_payload_preserves_credentials_but_explicit_empty_clears_them() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let database_path = directory.path().join("dbx.db");
|
||||
let target = Storage::open_unmigrated(&database_path)
|
||||
let target = crate::persistence::test_storage::open_unmigrated(&database_path)
|
||||
.await
|
||||
.unwrap()
|
||||
.with_secret_key_policy(SecretKeyPolicy::ManagedDataDir);
|
||||
@@ -3685,7 +3695,7 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
drop(target);
|
||||
let target = Storage::open_unmigrated(&database_path)
|
||||
let target = crate::persistence::test_storage::open_unmigrated(&database_path)
|
||||
.await
|
||||
.unwrap()
|
||||
.with_secret_key_policy(SecretKeyPolicy::ManagedDataDir);
|
||||
@@ -3709,7 +3719,7 @@ mod tests {
|
||||
assert_eq!(restored_snippet.token.as_deref(), (!restore_secrets).then_some("local-token"));
|
||||
}
|
||||
drop(target);
|
||||
let target = Storage::open_unmigrated(&database_path)
|
||||
let target = crate::persistence::test_storage::open_unmigrated(&database_path)
|
||||
.await
|
||||
.unwrap()
|
||||
.with_secret_key_policy(SecretKeyPolicy::ManagedDataDir);
|
||||
@@ -3725,12 +3735,12 @@ mod tests {
|
||||
async fn metadata_only_sync_roundtrip_preserves_public_url_params_and_target_secrets() {
|
||||
let source_directory = tempfile::tempdir().unwrap();
|
||||
let target_directory = tempfile::tempdir().unwrap();
|
||||
let source = Storage::open_unmigrated(&source_directory.path().join("dbx.db"))
|
||||
let source = crate::persistence::test_storage::open_unmigrated(&source_directory.path().join("dbx.db"))
|
||||
.await
|
||||
.unwrap()
|
||||
.with_secret_key_policy(SecretKeyPolicy::ManagedDataDir);
|
||||
let target_path = target_directory.path().join("dbx.db");
|
||||
let target = Storage::open_unmigrated(&target_path)
|
||||
let target = crate::persistence::test_storage::open_unmigrated(&target_path)
|
||||
.await
|
||||
.unwrap()
|
||||
.with_secret_key_policy(SecretKeyPolicy::ManagedDataDir);
|
||||
@@ -3758,7 +3768,7 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
drop(target);
|
||||
let target = Storage::open_unmigrated(&target_path)
|
||||
let target = crate::persistence::test_storage::open_unmigrated(&target_path)
|
||||
.await
|
||||
.unwrap()
|
||||
.with_secret_key_policy(SecretKeyPolicy::ManagedDataDir);
|
||||
@@ -3782,7 +3792,7 @@ mod tests {
|
||||
assert!(encrypted.starts_with("dbxenc1."));
|
||||
|
||||
let locked_directory = tempfile::tempdir().unwrap();
|
||||
let locked_target = Storage::open_unmigrated(&locked_directory.path().join("dbx.db"))
|
||||
let locked_target = crate::persistence::test_storage::open_unmigrated(&locked_directory.path().join("dbx.db"))
|
||||
.await
|
||||
.unwrap()
|
||||
.with_secret_key_policy(SecretKeyPolicy::ManagedDataDir)
|
||||
@@ -3831,7 +3841,8 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn sync_credentials_are_rewrapped_for_the_destination_device() {
|
||||
let source = Storage::open(&temp_db_path("sync-global-credentials-source")).await.unwrap();
|
||||
let source =
|
||||
crate::persistence::test_storage::open(&temp_db_path("sync-global-credentials-source")).await.unwrap();
|
||||
let webdav = WebDavConfig {
|
||||
endpoint: "https://dav.example.test/remote.php/dav/files/alice".to_string(),
|
||||
username: Some("alice".to_string()),
|
||||
@@ -3860,7 +3871,7 @@ mod tests {
|
||||
assert!(credentials.iter().any(|credential| credential.secret == "github-token"));
|
||||
|
||||
let target_path = temp_db_path("sync-global-credentials-target");
|
||||
let target = Storage::open(&target_path).await.unwrap();
|
||||
let target = crate::persistence::test_storage::open(&target_path).await.unwrap();
|
||||
apply_sync_snapshot(
|
||||
&target,
|
||||
&snapshot,
|
||||
@@ -3880,7 +3891,7 @@ mod tests {
|
||||
// database does not affect the restored credentials.
|
||||
drop(target);
|
||||
drop(source);
|
||||
let target = Storage::open(&target_path).await.unwrap();
|
||||
let target = crate::persistence::test_storage::open(&target_path).await.unwrap();
|
||||
let mut reopened_webdav = webdav.clone();
|
||||
resolve_webdav_password(&target, &mut reopened_webdav).await.unwrap();
|
||||
assert_eq!(reopened_webdav.password.as_deref(), Some("webdav-secret"));
|
||||
@@ -3910,7 +3921,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn plugin_connection_secrets_are_scrubbed_from_public_sync_metadata() {
|
||||
let storage = Storage::open(&temp_db_path("plugin-public-sync")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("plugin-public-sync")).await.unwrap();
|
||||
let mut config = postgres_connection("plugin", "");
|
||||
config.db_type = DatabaseType::Plugin;
|
||||
config.plugin_id = Some("example.plugin".to_string());
|
||||
@@ -3932,7 +3943,8 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn plugin_secrets_export_even_when_primary_password_is_not_saved() {
|
||||
let storage = Storage::open(&temp_db_path("plugin-secret-without-password")).await.unwrap();
|
||||
let storage =
|
||||
crate::persistence::test_storage::open(&temp_db_path("plugin-secret-without-password")).await.unwrap();
|
||||
let mut config = postgres_connection("plugin-no-password", "");
|
||||
config.db_type = DatabaseType::Plugin;
|
||||
config.save_password = false;
|
||||
@@ -3965,7 +3977,8 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn excluded_plugin_secrets_do_not_clear_destination_credentials() {
|
||||
let source = Storage::open(&temp_db_path("plugin-secret-excluded-source")).await.unwrap();
|
||||
let source =
|
||||
crate::persistence::test_storage::open(&temp_db_path("plugin-secret-excluded-source")).await.unwrap();
|
||||
let mut config = postgres_connection("plugin-preserve", "");
|
||||
config.db_type = DatabaseType::Plugin;
|
||||
config.plugin_id = Some("example.plugin".to_string());
|
||||
@@ -3987,7 +4000,8 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let target = Storage::open(&temp_db_path("plugin-secret-excluded-target")).await.unwrap();
|
||||
let target =
|
||||
crate::persistence::test_storage::open(&temp_db_path("plugin-secret-excluded-target")).await.unwrap();
|
||||
let mut target_config = config.clone();
|
||||
target_config.connection_secrets.insert("api_token".to_string(), "local-plugin-secret".to_string());
|
||||
target.save_connections(std::slice::from_ref(&target_config)).await.unwrap();
|
||||
@@ -4007,12 +4021,14 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn sync_restore_does_not_revive_password_when_connection_disables_saving() {
|
||||
let source = Storage::open(&temp_db_path("sync-no-save-password-source")).await.unwrap();
|
||||
let source =
|
||||
crate::persistence::test_storage::open(&temp_db_path("sync-no-save-password-source")).await.unwrap();
|
||||
source.save_connections(&[postgres_connection("pg", "remote-secret")]).await.unwrap();
|
||||
let mut snapshot = build_sync_snapshot(&source, "test-version", None, Some("sync-pass")).await.unwrap();
|
||||
snapshot.connections[0].save_password = false;
|
||||
|
||||
let target = Storage::open(&temp_db_path("sync-no-save-password-target")).await.unwrap();
|
||||
let target =
|
||||
crate::persistence::test_storage::open(&temp_db_path("sync-no-save-password-target")).await.unwrap();
|
||||
apply_sync_snapshot(
|
||||
&target,
|
||||
&snapshot,
|
||||
@@ -4027,11 +4043,11 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn wrong_sync_passphrase_does_not_modify_the_destination() {
|
||||
let source = Storage::open(&temp_db_path("sync-wrong-pass-source")).await.unwrap();
|
||||
let source = crate::persistence::test_storage::open(&temp_db_path("sync-wrong-pass-source")).await.unwrap();
|
||||
source.save_connections(&[postgres_connection("remote", "remote-secret")]).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&source, "test-version", None, Some("correct-pass")).await.unwrap();
|
||||
|
||||
let target = Storage::open(&temp_db_path("sync-wrong-pass-target")).await.unwrap();
|
||||
let target = crate::persistence::test_storage::open(&temp_db_path("sync-wrong-pass-target")).await.unwrap();
|
||||
target.save_connections(&[postgres_connection("local", "local-secret")]).await.unwrap();
|
||||
let before = target.load_connections().await.unwrap();
|
||||
assert!(apply_sync_snapshot(
|
||||
@@ -4048,14 +4064,16 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn legacy_plaintext_snapshot_secrets_are_migrated_only_on_explicit_restore() {
|
||||
let source = Storage::open(&temp_db_path("legacy-plaintext-sync-source")).await.unwrap();
|
||||
let source =
|
||||
crate::persistence::test_storage::open(&temp_db_path("legacy-plaintext-sync-source")).await.unwrap();
|
||||
source.save_connections(&[postgres_connection("legacy", "unused")]).await.unwrap();
|
||||
let mut snapshot = build_sync_snapshot(&source, "legacy-version", None, None).await.unwrap();
|
||||
snapshot.schema_version = LEGACY_SNAPSHOT_SCHEMA_VERSION;
|
||||
snapshot.connections[0].password = "legacy-password".to_string();
|
||||
snapshot.connections[0].init_script = Some("CREATE SECRET legacy".to_string());
|
||||
|
||||
let target = Storage::open(&temp_db_path("legacy-plaintext-sync-target")).await.unwrap();
|
||||
let target =
|
||||
crate::persistence::test_storage::open(&temp_db_path("legacy-plaintext-sync-target")).await.unwrap();
|
||||
apply_sync_snapshot(
|
||||
&target,
|
||||
&snapshot,
|
||||
@@ -4066,7 +4084,8 @@ mod tests {
|
||||
assert_eq!(target.get_secret("legacy", "password").await.unwrap().as_deref(), Some("legacy-password"));
|
||||
assert_eq!(target.get_secret("legacy", "init_script").await.unwrap().as_deref(), Some("CREATE SECRET legacy"));
|
||||
|
||||
let metadata_only_target = Storage::open(&temp_db_path("legacy-plaintext-sync-metadata-only")).await.unwrap();
|
||||
let metadata_only_target =
|
||||
crate::persistence::test_storage::open(&temp_db_path("legacy-plaintext-sync-metadata-only")).await.unwrap();
|
||||
apply_sync_snapshot(
|
||||
&metadata_only_target,
|
||||
&snapshot,
|
||||
@@ -4080,13 +4099,17 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn metadata_only_sync_removes_existing_password_when_connection_disables_saving() {
|
||||
let source = Storage::open(&temp_db_path("sync-no-save-password-metadata-source")).await.unwrap();
|
||||
let source = crate::persistence::test_storage::open(&temp_db_path("sync-no-save-password-metadata-source"))
|
||||
.await
|
||||
.unwrap();
|
||||
let mut source_connection = postgres_connection("pg", "unused");
|
||||
source_connection.save_password = false;
|
||||
source.save_connections(&[source_connection]).await.unwrap();
|
||||
let snapshot = build_sync_snapshot(&source, "test-version", None, None).await.unwrap();
|
||||
|
||||
let target = Storage::open(&temp_db_path("sync-no-save-password-metadata-target")).await.unwrap();
|
||||
let target = crate::persistence::test_storage::open(&temp_db_path("sync-no-save-password-metadata-target"))
|
||||
.await
|
||||
.unwrap();
|
||||
target.save_connections(&[postgres_connection("pg", "local-secret")]).await.unwrap();
|
||||
apply_sync_snapshot(&target, &snapshot, ApplySnapshotOptions::default()).await.unwrap();
|
||||
|
||||
@@ -4096,7 +4119,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn saved_sync_passphrase_encrypts_nacos_auth_password_without_exposing_it() {
|
||||
let storage = Storage::open(&temp_db_path("saved-sync-nacos-snapshot")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("saved-sync-nacos-snapshot")).await.unwrap();
|
||||
storage.save_connections(&[nacos_connection("nacos", "nacos-secret")]).await.unwrap();
|
||||
|
||||
save_webdav_sync_secrets_preference(&storage, true, Some("sync-pass")).await.unwrap();
|
||||
@@ -4115,7 +4138,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn sync_never_snapshots_or_restores_nacos_passwords_when_saving_is_disabled() {
|
||||
let source = Storage::open(&temp_db_path("sync-no-save-nacos-source")).await.unwrap();
|
||||
let source = crate::persistence::test_storage::open(&temp_db_path("sync-no-save-nacos-source")).await.unwrap();
|
||||
let mut config = nacos_connection("nacos", "transient-secret");
|
||||
config.save_password = false;
|
||||
let payload = build_sensitive_payload(&source, std::slice::from_ref(&config), &[]).await.unwrap();
|
||||
@@ -4150,7 +4173,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn sync_snapshot_round_trips_tunnel_profiles() {
|
||||
let storage = Storage::open(&temp_db_path("tunnel-profiles-src")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("tunnel-profiles-src")).await.unwrap();
|
||||
let profile = TransportLayerConfig::Ssh(SshTunnelConfig {
|
||||
id: "profile-1".to_string(),
|
||||
name: "Bastion".to_string(),
|
||||
@@ -4179,7 +4202,7 @@ mod tests {
|
||||
assert!(!public_json.contains("tunnel-secret"));
|
||||
|
||||
// Applying with the passphrase restores the full profile on the target.
|
||||
let target = Storage::open(&temp_db_path("tunnel-profiles-dst")).await.unwrap();
|
||||
let target = crate::persistence::test_storage::open(&temp_db_path("tunnel-profiles-dst")).await.unwrap();
|
||||
apply_sync_snapshot(
|
||||
&target,
|
||||
&snapshot,
|
||||
@@ -4194,7 +4217,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn sensitive_payload_ai_configs_none_falls_through_to_legacy() {
|
||||
let storage = Storage::open(&temp_db_path("ai-cfg-none")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("ai-cfg-none")).await.unwrap();
|
||||
|
||||
// No ai_configs in payload — fall through to ai_config (legacy) branch
|
||||
let payload = SensitiveSyncPayload {
|
||||
@@ -4212,7 +4235,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn sensitive_payload_ai_configs_empty_clears_table() {
|
||||
let storage = Storage::open(&temp_db_path("ai-cfg-empty")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("ai-cfg-empty")).await.unwrap();
|
||||
|
||||
// Pre-populate with a config
|
||||
let cfg = make_test_config("to-be-cleared", true);
|
||||
@@ -4234,7 +4257,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn sensitive_payload_ai_configs_some_saves_configs() {
|
||||
let storage = Storage::open(&temp_db_path("ai-cfg-some")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("ai-cfg-some")).await.unwrap();
|
||||
|
||||
let mut cfg = make_test_config("synced", true);
|
||||
cfg.config.provider = crate::ai::AiProvider::OpenCodeCli;
|
||||
@@ -4274,7 +4297,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn sensitive_payload_legacy_ai_config_replaces_local_configs_with_same_name() {
|
||||
let storage = Storage::open(&temp_db_path("ai-cfg-legacy-replace")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&temp_db_path("ai-cfg-legacy-replace")).await.unwrap();
|
||||
storage.save_ai_config_item(&make_test_config("openai", true)).await.unwrap();
|
||||
storage.save_ai_config_item(&make_test_config("local-only", false)).await.unwrap();
|
||||
|
||||
|
||||
@@ -477,7 +477,7 @@ mod tests {
|
||||
let tmp = std::env::temp_dir().join(uuid::Uuid::new_v4().to_string());
|
||||
std::fs::create_dir_all(&tmp).unwrap();
|
||||
let db_path = tmp.join("test_governance.db");
|
||||
let storage = Arc::new(Storage::open(&db_path).await.unwrap());
|
||||
let storage = Arc::new(crate::persistence::test_storage::open(&db_path).await.unwrap());
|
||||
std::mem::forget(tmp);
|
||||
storage
|
||||
}
|
||||
@@ -972,7 +972,7 @@ mod tests {
|
||||
std::fs::create_dir_all(&tmp).unwrap();
|
||||
let db_path = tmp.join("test_snapshot.db");
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
let storage = Arc::new(rt.block_on(Storage::open(&db_path)).unwrap());
|
||||
let storage = Arc::new(rt.block_on(crate::persistence::test_storage::open(&db_path)).unwrap());
|
||||
std::mem::forget(tmp);
|
||||
storage
|
||||
}
|
||||
|
||||
@@ -5,3 +5,5 @@ pub mod saved_sql;
|
||||
pub mod secret_codec;
|
||||
pub mod state_persistence;
|
||||
pub mod storage;
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub mod test_storage;
|
||||
@@ -34,6 +34,8 @@ pub enum SecretKeyPolicy {
|
||||
PlatformDefault,
|
||||
ManagedDataDir,
|
||||
ExternalOnly,
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
TestDataDir,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@@ -111,6 +113,10 @@ impl SecretCodec {
|
||||
where
|
||||
F: Fn(&str) -> Option<std::ffi::OsString>,
|
||||
{
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
if matches!(policy, SecretKeyPolicy::TestDataDir) {
|
||||
return Self::resolve_managed_data_dir(data_dir, allow_create);
|
||||
}
|
||||
if let Some(path) = env_lookup("DBX_SECRET_KEY_FILE") {
|
||||
let path = std::path::PathBuf::from(path);
|
||||
let codec = Self::read_key_file(&path, false)?;
|
||||
@@ -123,34 +129,36 @@ impl SecretCodec {
|
||||
}
|
||||
|
||||
match policy {
|
||||
SecretKeyPolicy::ManagedDataDir => {
|
||||
let path = managed_key_path(data_dir);
|
||||
match path.symlink_metadata() {
|
||||
Ok(metadata) if metadata.file_type().is_symlink() => Err("KEY_FILE_UNAVAILABLE".to_string()),
|
||||
Ok(_) => {
|
||||
if allow_create {
|
||||
secure_managed_key_permissions(&path)?;
|
||||
}
|
||||
let codec = read_key_file_with_retry(&path, true)?;
|
||||
Ok(SecretKeyResolution { codec, source: SecretKeySource::ManagedDataDir })
|
||||
}
|
||||
Err(error) if error.kind() == std::io::ErrorKind::NotFound && allow_create => {
|
||||
let codec = create_managed_key(&path)?;
|
||||
Ok(SecretKeyResolution { codec, source: SecretKeySource::ManagedDataDir })
|
||||
}
|
||||
Err(error) if error.kind() == std::io::ErrorKind::NotFound => {
|
||||
Err("MISSING_MANAGED_KEY".to_string())
|
||||
}
|
||||
Err(_) => Err("KEY_FILE_UNAVAILABLE".to_string()),
|
||||
}
|
||||
}
|
||||
SecretKeyPolicy::ManagedDataDir => Self::resolve_managed_data_dir(data_dir, allow_create),
|
||||
SecretKeyPolicy::ExternalOnly => Err("MISSING_EXTERNAL_KEY".to_string()),
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
SecretKeyPolicy::TestDataDir => Self::resolve_managed_data_dir(data_dir, allow_create),
|
||||
SecretKeyPolicy::PlatformDefault => {
|
||||
Self::resolve_platform_default(default_key_path(), allow_create, platform_keyring_codec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_managed_data_dir(data_dir: &std::path::Path, allow_create: bool) -> Result<SecretKeyResolution, String> {
|
||||
let path = managed_key_path(data_dir);
|
||||
match path.symlink_metadata() {
|
||||
Ok(metadata) if metadata.file_type().is_symlink() => Err("KEY_FILE_UNAVAILABLE".to_string()),
|
||||
Ok(_) => {
|
||||
if allow_create {
|
||||
secure_managed_key_permissions(&path)?;
|
||||
}
|
||||
let codec = read_key_file_with_retry(&path, true)?;
|
||||
Ok(SecretKeyResolution { codec, source: SecretKeySource::ManagedDataDir })
|
||||
}
|
||||
Err(error) if error.kind() == std::io::ErrorKind::NotFound && allow_create => {
|
||||
let codec = create_managed_key(&path)?;
|
||||
Ok(SecretKeyResolution { codec, source: SecretKeySource::ManagedDataDir })
|
||||
}
|
||||
Err(error) if error.kind() == std::io::ErrorKind::NotFound => Err("MISSING_MANAGED_KEY".to_string()),
|
||||
Err(_) => Err("KEY_FILE_UNAVAILABLE".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_platform_default<F>(
|
||||
compatibility_path: Option<std::path::PathBuf>,
|
||||
allow_create: bool,
|
||||
@@ -514,6 +522,18 @@ fn aad(namespace: &str, key: &str) -> String {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn isolated_test_policy_never_reads_process_credentials() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let resolved =
|
||||
super::SecretCodec::resolve_with_env(super::SecretKeyPolicy::TestDataDir, directory.path(), true, |_| {
|
||||
panic!("test storage must not inspect process credential overrides")
|
||||
})
|
||||
.unwrap();
|
||||
assert_eq!(resolved.source, super::SecretKeySource::ManagedDataDir);
|
||||
assert!(super::managed_key_path(directory.path()).is_file());
|
||||
}
|
||||
|
||||
use super::{
|
||||
managed_key_path, read_key_file_with_retry, run_secret_service_operation, SecretCodec, SecretKeyPolicy,
|
||||
SecretKeySource,
|
||||
|
||||
@@ -933,7 +933,7 @@ mod tests {
|
||||
|
||||
async fn create_local_backend() -> LocalBackend {
|
||||
let path = temp_db_path("local-backend");
|
||||
let storage = Arc::new(Storage::open(&path).await.unwrap());
|
||||
let storage = Arc::new(crate::persistence::test_storage::open(&path).await.unwrap());
|
||||
LocalBackend::new(storage)
|
||||
}
|
||||
|
||||
@@ -1315,7 +1315,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn storage_compare_and_swap_new_key() {
|
||||
let path = temp_db_path("cas-new-key");
|
||||
let storage = Arc::new(Storage::open(&path).await.unwrap());
|
||||
let storage = Arc::new(crate::persistence::test_storage::open(&path).await.unwrap());
|
||||
let success = storage.compare_and_swap_state("cas-new", None, b"data", "text/plain").await.unwrap();
|
||||
assert!(success);
|
||||
let (data, _) = storage.load_state("cas-new").await.unwrap().unwrap();
|
||||
@@ -1325,7 +1325,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn storage_compare_and_swap_exact_version() {
|
||||
let path = temp_db_path("cas-exact");
|
||||
let storage = Arc::new(Storage::open(&path).await.unwrap());
|
||||
let storage = Arc::new(crate::persistence::test_storage::open(&path).await.unwrap());
|
||||
storage.save_state("cas-key", b"v1", "text/plain").await.unwrap();
|
||||
let version = storage.get_state_version("cas-key").await.unwrap().unwrap();
|
||||
assert_eq!(version, 1);
|
||||
@@ -1339,7 +1339,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn storage_compare_and_swap_wrong_version() {
|
||||
let path = temp_db_path("cas-wrong-ver");
|
||||
let storage = Arc::new(Storage::open(&path).await.unwrap());
|
||||
let storage = Arc::new(crate::persistence::test_storage::open(&path).await.unwrap());
|
||||
storage.save_state("cas-key", b"v1", "text/plain").await.unwrap();
|
||||
let success = storage.compare_and_swap_state("cas-key", Some(999), b"v2", "text/plain").await.unwrap();
|
||||
assert!(!success);
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,42 @@
|
||||
use super::{
|
||||
secret_codec::{SecretCodec, SecretKeyPolicy},
|
||||
storage::Storage,
|
||||
};
|
||||
use std::path::Path;
|
||||
|
||||
pub async fn open(path: &Path) -> Result<Storage, String> {
|
||||
let directory = path.parent().ok_or("Test storage requires a data directory")?;
|
||||
SecretCodec::resolve(SecretKeyPolicy::TestDataDir, directory, true)?;
|
||||
Storage::open_with_secret_key_policy(path, SecretKeyPolicy::TestDataDir).await
|
||||
}
|
||||
|
||||
pub async fn open_unmigrated(path: &Path) -> Result<Storage, String> {
|
||||
Ok(Storage::open_unmigrated(path).await?.with_secret_key_policy(SecretKeyPolicy::TestDataDir))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::persistence::secret_codec::{managed_key_path, SecretCodec};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_storage_keys_are_isolated_and_persist_across_reopens() {
|
||||
let first_dir = tempfile::tempdir().unwrap();
|
||||
let second_dir = tempfile::tempdir().unwrap();
|
||||
let first_path = first_dir.path().join("dbx.db");
|
||||
let first = open(&first_path).await.unwrap();
|
||||
let first_key = SecretCodec::resolve(SecretKeyPolicy::TestDataDir, first_dir.path(), true).unwrap();
|
||||
let second_key = SecretCodec::resolve(SecretKeyPolicy::TestDataDir, second_dir.path(), true).unwrap();
|
||||
let encrypted = first_key.codec.encrypt("test", "credential", "fixture-value").unwrap();
|
||||
assert!(second_key.codec.decrypt("test", "credential", &encrypted).is_err());
|
||||
let first_bytes = std::fs::read(managed_key_path(first_dir.path())).unwrap();
|
||||
let second_bytes = std::fs::read(managed_key_path(second_dir.path())).unwrap();
|
||||
assert_ne!(first_bytes, second_bytes);
|
||||
assert_eq!(first_key.source, second_key.source);
|
||||
drop(first);
|
||||
let _reopened = open(&first_path).await.unwrap();
|
||||
let reopened_key = SecretCodec::resolve(SecretKeyPolicy::TestDataDir, first_dir.path(), false).unwrap();
|
||||
assert_eq!(reopened_key.codec.decrypt("test", "credential", &encrypted).unwrap(), "fixture-value");
|
||||
assert_eq!(first_bytes, std::fs::read(managed_key_path(first_dir.path())).unwrap());
|
||||
}
|
||||
}
|
||||
@@ -7026,7 +7026,9 @@ mod tests {
|
||||
fail_once: Option<&'static str>,
|
||||
) -> (AppState, Arc<Mutex<Vec<String>>>, tempfile::TempDir) {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let state = AppState::new(Storage::open(&directory.path().join("storage.db")).await.unwrap());
|
||||
let state = AppState::new(
|
||||
crate::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap(),
|
||||
);
|
||||
let config = test_connection_config(DatabaseType::Postgres);
|
||||
state.configs.write().await.insert(config.id.clone(), config);
|
||||
let commands = Arc::new(Mutex::new(Vec::new()));
|
||||
@@ -7546,7 +7548,8 @@ mod tests {
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
let dir = tempfile::tempdir().expect("temp dir");
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.expect("open test storage");
|
||||
let storage =
|
||||
crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.expect("open test storage");
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let connection_id = "sqlite-cancel-session";
|
||||
let client_session_id = "query-tab-8414";
|
||||
@@ -7764,7 +7767,6 @@ mod tests {
|
||||
InstalledPlugin, PluginCompatibility, PluginDriverManifest, PluginDriverSession, PluginManifest,
|
||||
PluginRuntimeEnv,
|
||||
};
|
||||
use crate::storage::Storage;
|
||||
|
||||
#[cfg(unix)]
|
||||
async fn spawn_agent_batch_timeout_test_client() -> (AgentDriverClient, tempfile::NamedTempFile) {
|
||||
@@ -7855,7 +7857,7 @@ for line in sys.stdin:
|
||||
async fn query_and_transaction_paths_resolve_catalog_dialect_from_connection() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-catalog-dialect-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
|
||||
let mut doris = test_connection_config(DatabaseType::Doris);
|
||||
@@ -8117,7 +8119,7 @@ for line in sys.stdin:
|
||||
let (host, port) = address.rsplit_once(':').expect("DynamoDB endpoint must include a port");
|
||||
let dir = std::env::temp_dir().join(format!("dbx-query-dynamodb-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let mut config = test_connection_config(DatabaseType::DynamoDb);
|
||||
config.host = host.to_string();
|
||||
@@ -8205,7 +8207,7 @@ for line in sys.stdin:
|
||||
.unwrap();
|
||||
runtime.increment_session_count();
|
||||
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert("conn-1".to_string(), test_connection_config(DatabaseType::SqlServer));
|
||||
state
|
||||
@@ -8322,7 +8324,7 @@ for line in sys.stdin:
|
||||
.unwrap();
|
||||
runtime.increment_session_count();
|
||||
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert("conn-1".to_string(), test_connection_config(DatabaseType::Dameng));
|
||||
state
|
||||
@@ -8381,7 +8383,7 @@ for line in sys.stdin:
|
||||
async fn native_pre_dispatch_cancellation_stays_typed() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-query-native-cancel-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "sqlite-cancel";
|
||||
let sqlite = db::sqlite::connect_path_create_if_missing(dir.join("query.db").to_str().unwrap()).await.unwrap();
|
||||
@@ -8561,7 +8563,7 @@ for line in sys.stdin:
|
||||
#[tokio::test]
|
||||
async fn ddl_schema_cache_invalidates_persisted_object_snapshots() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "schema-cache";
|
||||
let sqlite =
|
||||
@@ -8603,7 +8605,7 @@ for line in sys.stdin:
|
||||
("BEGIN; ALTER TABLE users ADD COLUMN added INTEGER; COMMIT", false, false, true),
|
||||
] {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let sqlite = db::sqlite::connect_path_create_if_missing(dir.path().join("query.db").to_str().unwrap())
|
||||
.await
|
||||
@@ -8662,7 +8664,7 @@ for line in sys.stdin:
|
||||
async fn ddl_schema_cache_storage_failure_preserves_sql_outcome() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage_path = dir.path().join("storage.db");
|
||||
let state = AppState::new(Storage::open(&storage_path).await.unwrap());
|
||||
let state = AppState::new(crate::persistence::test_storage::open(&storage_path).await.unwrap());
|
||||
let sqlite =
|
||||
db::sqlite::connect_path_create_if_missing(dir.path().join("query.db").to_str().unwrap()).await.unwrap();
|
||||
state
|
||||
@@ -8691,7 +8693,7 @@ for line in sys.stdin:
|
||||
async fn assert_sqlite_batch_error_behavior(failure_first: bool, continue_on_error: bool) {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-query-batch-error-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "sqlite-batch";
|
||||
let sqlite = db::sqlite::connect_path_create_if_missing(dir.join("query.db").to_str().unwrap()).await.unwrap();
|
||||
@@ -8742,7 +8744,7 @@ for line in sys.stdin:
|
||||
async fn transactional_sqlite_batch_rolls_back_when_a_later_statement_fails() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-query-transaction-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "sqlite-transaction";
|
||||
let sqlite = db::sqlite::connect_path_create_if_missing(dir.join("query.db").to_str().unwrap()).await.unwrap();
|
||||
@@ -8785,7 +8787,7 @@ for line in sys.stdin:
|
||||
async fn transactional_batch_rejects_an_unsupported_backend_before_execution() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-query-unsupported-transaction-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "message-queue-transaction";
|
||||
state
|
||||
@@ -8877,7 +8879,7 @@ for line in sys.stdin:
|
||||
async fn connection_pool_is_sqlserver_agent_detects_agent_and_native_pools() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-query-sqlserver-agent-flag-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
|
||||
// Non-SQL-Server connections never use the SQL Server agent splitter.
|
||||
@@ -8913,7 +8915,7 @@ for line in sys.stdin:
|
||||
// on failure for DDL that cannot be rolled back.
|
||||
let dir = std::env::temp_dir().join(format!("dbx-query-tx-predispatch-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "message-queue-tx-ddl";
|
||||
state
|
||||
@@ -8987,7 +8989,7 @@ for line in sys.stdin:
|
||||
async fn gaussdb_on_error_stop_overrides_continue_on_error() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-query-gaussdb-on-error-stop-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "gaussdb-on-error-stop";
|
||||
let sqlite = db::sqlite::connect_path_create_if_missing(dir.join("query.db").to_str().unwrap()).await.unwrap();
|
||||
@@ -10233,7 +10235,7 @@ for line in sys.stdin:
|
||||
.await
|
||||
.expect("plugin should start"),
|
||||
);
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let mut config = test_connection_config(DatabaseType::Jdbc);
|
||||
config.id = "jdbc-conn".to_string();
|
||||
@@ -11457,7 +11459,7 @@ for line in sys.stdin:
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-manual-txn-{}", uuid::Uuid::new_v4().simple()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let mut config = test_connection_config(db_type);
|
||||
config.id = "agent-conn".to_string();
|
||||
|
||||
@@ -1637,8 +1637,6 @@ mod tests {
|
||||
use crate::db::agent_driver::{AgentDriverClient, AgentLaunchSpec};
|
||||
#[cfg(unix)]
|
||||
use crate::models::connection::ConnectionConfig;
|
||||
#[cfg(unix)]
|
||||
use crate::storage::Storage;
|
||||
|
||||
#[cfg(unix)]
|
||||
async fn legacy_mongo_state(
|
||||
@@ -1796,7 +1794,7 @@ for line in sys.stdin:
|
||||
.await
|
||||
.unwrap();
|
||||
client.try_optional_handshake("test").await.unwrap();
|
||||
let storage = Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let config: ConnectionConfig = serde_json::from_value(serde_json::json!({
|
||||
"id": "legacy",
|
||||
|
||||
@@ -114,7 +114,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn ddl_schema_cache_encoding_and_connection_isolation() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let id = "conn:% 中文";
|
||||
assert_eq!(metadata_cache_segment(id), "conn%3A%25%20%E4%B8%AD%E6%96%87");
|
||||
let prefix = object_metadata_cache_prefix(id, "db% name");
|
||||
|
||||
@@ -402,7 +402,7 @@ mod tests {
|
||||
installer
|
||||
.install_bytes(&ui_plugin_package("sample.nodata", &[]), PluginInstallPolicy::LocalDevelopment)
|
||||
.unwrap();
|
||||
let storage = crate::storage::Storage::open(&root.path().join("dbx.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&root.path().join("dbx.db")).await.unwrap();
|
||||
let state = AppState::new_with_plugin_dir_and_app_version(storage, plugin_dir, "0.6.0");
|
||||
|
||||
let path = root.path().join("orders.db");
|
||||
|
||||
@@ -533,7 +533,6 @@ pub fn plugin_plan_timeout_secs(timeout_ms: Option<u64>, config: &ConnectionConf
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::connection::PoolKind;
|
||||
use crate::storage::Storage;
|
||||
|
||||
fn config(db_type: DatabaseType, query_timeout_secs: u64) -> ConnectionConfig {
|
||||
serde_json::from_value(serde_json::json!({
|
||||
@@ -560,7 +559,8 @@ mod tests {
|
||||
/// disconnected" situation the plan boundary has to refuse.
|
||||
async fn saved_connection_state(configs: &[ConnectionConfig]) -> (AppState, tempfile::TempDir) {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.expect("open storage");
|
||||
let storage =
|
||||
crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.expect("open storage");
|
||||
let state = AppState::new_with_plugin_dir(storage, dir.path().join("plugins"));
|
||||
{
|
||||
let mut stored = state.configs.write().await;
|
||||
|
||||
@@ -529,9 +529,8 @@ mod tests {
|
||||
}
|
||||
|
||||
async fn make_2pc() -> (TwoPhaseCommit, std::path::PathBuf) {
|
||||
use crate::storage::Storage;
|
||||
let path = std::env::temp_dir().join(format!("test_2pc_{}.db", uuid::Uuid::new_v4()));
|
||||
let storage = Arc::new(Storage::open(&path).await.unwrap());
|
||||
let storage = Arc::new(crate::persistence::test_storage::open(&path).await.unwrap());
|
||||
let backend: Arc<dyn StateBackend> = Arc::new(crate::state_persistence::LocalBackend::new(storage));
|
||||
(TwoPhaseCommit::new(backend), path)
|
||||
}
|
||||
|
||||
@@ -97,7 +97,6 @@ mod tests {
|
||||
use crate::models::connection::ConnectionConfig;
|
||||
use crate::query::{check_read_only_for_connection, connection_readonly_name};
|
||||
use crate::session_credentials::with_credential_owner;
|
||||
use crate::storage::Storage;
|
||||
|
||||
fn mysql_config(id: &str, name: &str, read_only: bool) -> ConnectionConfig {
|
||||
serde_json::from_value(serde_json::json!({
|
||||
@@ -116,7 +115,8 @@ mod tests {
|
||||
|
||||
async fn test_state(configs: &[ConnectionConfig]) -> (AppState, tempfile::TempDir) {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.expect("open storage");
|
||||
let storage =
|
||||
crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.expect("open storage");
|
||||
let state = AppState::new_with_plugin_dir(storage, dir.path().join("plugins"));
|
||||
{
|
||||
let mut stored = state.configs.write().await;
|
||||
|
||||
@@ -118,7 +118,7 @@ async fn recovery_preserves_queued_jobs_and_marks_orphaned_running_jobs_failed()
|
||||
}
|
||||
|
||||
async fn service(dir: &std::path::Path, root: Option<std::path::PathBuf>) -> BackupService {
|
||||
let storage = crate::storage::Storage::open(&dir.join("dbx.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("dbx.db")).await.unwrap();
|
||||
BackupService::new(Arc::new(crate::connection::AppState::new(storage)), dir, root)
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ async fn worker_waits_for_security_migration_and_resumes_without_restarting() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let legacy_path = directory.path().join("connections.json");
|
||||
std::fs::write(&legacy_path, "[]").unwrap();
|
||||
let storage = crate::storage::Storage::open_unmigrated(&directory.path().join("dbx.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open_unmigrated(&directory.path().join("dbx.db")).await.unwrap();
|
||||
let service = BackupService::new(Arc::new(crate::connection::AppState::new(storage)), directory.path(), None);
|
||||
let queued = service.store.enqueue(request(schedule(directory.path()).config)).await.unwrap();
|
||||
assert!(!service.state.storage.inspect_data_migration().await.unwrap().is_ready());
|
||||
|
||||
@@ -3164,7 +3164,6 @@ mod tests {
|
||||
use crate::plugins::{
|
||||
InstalledPlugin, PluginDriverManifest, PluginDriverSession, PluginManifest, PluginRuntimeEnv,
|
||||
};
|
||||
use crate::storage::Storage;
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -3295,7 +3294,7 @@ mod tests {
|
||||
async fn turso_test_state(base_url: &str) -> (AppState, std::path::PathBuf) {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-turso-schema-test-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let mut config = test_connection_config(DatabaseType::Turso);
|
||||
config.database = Some("main".to_string());
|
||||
@@ -3623,7 +3622,7 @@ done
|
||||
let session = std::sync::Arc::new(
|
||||
PluginDriverSession::start_for_test(plugin, "jdbc".to_string(), PluginRuntimeEnv::default()).await.unwrap(),
|
||||
);
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let mut config = test_connection_config(DatabaseType::Jdbc);
|
||||
config.id = "mysql-wrapper".to_string();
|
||||
@@ -3785,7 +3784,7 @@ done
|
||||
let session = std::sync::Arc::new(
|
||||
PluginDriverSession::start_for_test(plugin, "jdbc".to_string(), PluginRuntimeEnv::default()).await.unwrap(),
|
||||
);
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let mut config = test_connection_config(DatabaseType::Jdbc);
|
||||
config.id = "oracle-synonym".to_string();
|
||||
@@ -3933,7 +3932,7 @@ done
|
||||
let session = std::sync::Arc::new(
|
||||
PluginDriverSession::start_for_test(plugin, "jdbc".into(), PluginRuntimeEnv::default()).await.unwrap(),
|
||||
);
|
||||
let state = AppState::new(Storage::open(&dir.join("storage.db")).await.unwrap());
|
||||
let state = AppState::new(crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap());
|
||||
let mut config = test_connection_config(DatabaseType::Jdbc);
|
||||
config.id = "oracle-ddl".into();
|
||||
config.database = Some("demo".into());
|
||||
@@ -4528,7 +4527,7 @@ done
|
||||
async fn metadata_pool_races_retry_once_and_saturation_returns_busy() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-schema-metadata-pool-race-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = crate::storage::Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = crate::connection::AppState::new(storage);
|
||||
state.configs.write().await.insert("conn".to_string(), test_connection_config(DatabaseType::Mysql));
|
||||
|
||||
@@ -4581,7 +4580,7 @@ done
|
||||
async fn metadata_pool_snapshot_releases_global_connections_lock() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-schema-metadata-snapshot-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = crate::storage::Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = crate::connection::AppState::new(storage);
|
||||
let pool = crate::db::sqlite::connect_path(":memory:").await.unwrap();
|
||||
state
|
||||
@@ -4623,7 +4622,7 @@ done
|
||||
async fn metadata_fail_stop_detaches_base_pool_without_client_session() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-schema-metadata-fail-stop-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = crate::storage::Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = crate::connection::AppState::new(storage);
|
||||
let mut config = test_connection_config(DatabaseType::Dameng);
|
||||
config.id = "conn".to_string();
|
||||
@@ -4647,7 +4646,7 @@ done
|
||||
async fn metadata_timeout_detaches_pool_without_replaying_operation() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-schema-metadata-timeout-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = crate::storage::Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = crate::connection::AppState::new(storage);
|
||||
let mut config = test_connection_config(DatabaseType::Dameng);
|
||||
config.id = "conn".to_string();
|
||||
@@ -4676,7 +4675,7 @@ done
|
||||
async fn metadata_second_quarantine_detaches_replacement_pool() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-schema-metadata-quarantine-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = crate::storage::Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = crate::connection::AppState::new(storage);
|
||||
let mut config = test_connection_config(DatabaseType::Sqlite);
|
||||
config.id = "conn".to_string();
|
||||
@@ -4758,7 +4757,7 @@ for line in sys.stdin:
|
||||
runtime.increment_session_count();
|
||||
let client =
|
||||
crate::db::agent_driver::AgentDriverClient::shared_session(runtime.clone(), "metadata-session".to_string());
|
||||
let storage = crate::storage::Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = crate::connection::AppState::new(storage);
|
||||
let mut config = test_connection_config(DatabaseType::Dameng);
|
||||
config.id = "conn".to_string();
|
||||
@@ -5988,7 +5987,7 @@ done
|
||||
let session = std::sync::Arc::new(
|
||||
PluginDriverSession::start_for_test(plugin, "jdbc".to_string(), PluginRuntimeEnv::default()).await.unwrap(),
|
||||
);
|
||||
let state = AppState::new(Storage::open(&dir.join("storage.db")).await.unwrap());
|
||||
let state = AppState::new(crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap());
|
||||
let mut config = test_connection_config(DatabaseType::Jdbc);
|
||||
config.id = "jdbc-oracle-columns".to_string();
|
||||
config.database = Some("demo".to_string());
|
||||
@@ -6094,7 +6093,7 @@ done
|
||||
let session = std::sync::Arc::new(
|
||||
PluginDriverSession::start_for_test(plugin, "jdbc".to_string(), PluginRuntimeEnv::default()).await.unwrap(),
|
||||
);
|
||||
let state = AppState::new(Storage::open(&dir.join("storage.db")).await.unwrap());
|
||||
let state = AppState::new(crate::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap());
|
||||
let mut config = test_connection_config(DatabaseType::Jdbc);
|
||||
config.id = "jdbc-mysql-columns".to_string();
|
||||
config.database = Some("demo".to_string());
|
||||
|
||||
@@ -193,7 +193,6 @@ fn field_capability(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::storage::Storage;
|
||||
|
||||
fn config() -> crate::models::connection::ConnectionConfig {
|
||||
serde_json::from_value(serde_json::json!({
|
||||
@@ -269,7 +268,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn saved_but_disconnected_context_is_rejected_without_creating_a_pool() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new_with_plugin_dir(storage, dir.path().join("plugins"));
|
||||
let config = config();
|
||||
state.configs.write().await.insert(config.id.clone(), config);
|
||||
|
||||
@@ -5,14 +5,13 @@ use super::{
|
||||
use crate::connection::{AppState, PoolKind, METADATA_POOL_ACQUIRE_TIMEOUT};
|
||||
use crate::db::agent_driver::{AgentDriverClient, AgentLaunchSpec, AgentRuntimeClient};
|
||||
use crate::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use crate::storage::Storage;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
async fn state(db_type: DatabaseType) -> (tempfile::TempDir, AppState) {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let storage = crate::persistence::test_storage::open(&dir.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new_with_plugin_and_agent_dir_and_app_version(
|
||||
storage,
|
||||
dir.path().join("plugins"),
|
||||
|
||||
@@ -17,7 +17,6 @@ use std::sync::Arc;
|
||||
|
||||
use dbx_core::connection::AppState;
|
||||
use dbx_core::database_export::{export_database_sql_core, DatabaseExportRequest};
|
||||
use dbx_core::storage::Storage;
|
||||
use support::{
|
||||
postgres_test_config, psql, psql_allow_failure, start_docker_postgres, start_docker_postgres_with_server_args,
|
||||
DockerPostgres,
|
||||
@@ -76,7 +75,7 @@ async fn run_database_export_of_partition_tree_has_no_duplicates_and_replays() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-export-partition-ddl-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
|
||||
let connection_id = "export-partition-ddl-conn";
|
||||
@@ -237,7 +236,7 @@ async fn partition_tree_ddl_query_count_does_not_scale_with_partition_count() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-partition-query-count-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let connection_id = "partition-query-count-conn";
|
||||
state.configs.write().await.insert(connection_id.to_string(), postgres_test_config(connection_id, container.port));
|
||||
@@ -305,7 +304,7 @@ async fn display_ddl_error_distinguishes_wrong_relkind_from_missing_relation() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-partition-relkind-error-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let connection_id = "partition-relkind-error-conn";
|
||||
state.configs.write().await.insert(connection_id.to_string(), postgres_test_config(connection_id, container.port));
|
||||
|
||||
@@ -7,7 +7,6 @@ use std::process::Command;
|
||||
|
||||
use dbx_core::connection::AppState;
|
||||
use dbx_core::database_export::{export_database_sql_core, DatabaseExportRequest};
|
||||
use dbx_core::storage::Storage;
|
||||
use std::sync::Arc;
|
||||
use support::{postgres_test_config, psql, start_docker_postgres};
|
||||
|
||||
@@ -54,7 +53,7 @@ async fn run_database_export_writes_structure_and_data_for_all_tables() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-export-prefetch-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
|
||||
let connection_id = "export-prefetch-conn";
|
||||
|
||||
@@ -10,7 +10,6 @@ use dbx_core::docs::annotations::{
|
||||
AnnotationFile, ColumnAnnotation, GroupAnnotation, ProjectAnnotation, TableAnnotation,
|
||||
};
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::storage::Storage;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
fn live_postgres_config(
|
||||
@@ -140,7 +139,7 @@ async fn dump_keycloak_fixture() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-dump-docs-fixture-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(config.id.clone(), config.clone());
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use dbx_core::connection::AppState;
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::query_result_export::{export_query_result_core, ExportStatus, QueryResultExportRequest};
|
||||
use dbx_core::storage::Storage;
|
||||
use dbx_core::table_import::parse_xlsx_file;
|
||||
|
||||
fn live_clickhouse_config(
|
||||
@@ -66,7 +65,7 @@ async fn live_clickhouse_query_result_export_xlsx_streams_random_order_query_onc
|
||||
let config = live_clickhouse_config(&connection_id, &host, port, &user, &password, &database);
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-clickhouse-query-export-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(config.id.clone(), config);
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ use std::time::Duration;
|
||||
use dbx_core::connection::{connect_bare_metadata_pool, AppState};
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::schema::get_columns_core;
|
||||
use dbx_core::storage::Storage;
|
||||
use mysql_async::prelude::Queryable;
|
||||
|
||||
fn live_doris_config(id: &str) -> ConnectionConfig {
|
||||
@@ -42,7 +41,7 @@ fn live_doris_config(id: &str) -> ConnectionConfig {
|
||||
async fn doris_qualified_table_metadata_resolves_schema_database_with_comments() {
|
||||
let config = live_doris_config("doris-6590-live");
|
||||
let db_path = std::env::temp_dir().join(format!("dbx-doris-6590-{}.db", uuid::Uuid::new_v4().simple()));
|
||||
let storage = Storage::open(&db_path).await.expect("open temp storage");
|
||||
let storage = dbx_core::persistence::test_storage::open(&db_path).await.expect("open temp storage");
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(config.id.clone(), config.clone());
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ use dbx_core::query::{
|
||||
execute_in_manual_transaction_with_options, execute_sql_statement, rollback_manual_transaction,
|
||||
ManualTransactionExecutionOptions,
|
||||
};
|
||||
use dbx_core::storage::Storage;
|
||||
use std::sync::Arc;
|
||||
|
||||
fn live_config(prefix: &str, database_type: DatabaseType, default_port: u16) -> ConnectionConfig {
|
||||
@@ -29,7 +28,9 @@ fn live_config(prefix: &str, database_type: DatabaseType, default_port: u16) ->
|
||||
|
||||
async fn setup(config: ConnectionConfig) -> (Arc<AppState>, std::path::PathBuf, String) {
|
||||
let storage_path = std::env::temp_dir().join(format!("dbx-snapshot-rotation-{}.db", uuid::Uuid::new_v4().simple()));
|
||||
let state = Arc::new(AppState::new(Storage::open(&storage_path).await.expect("temporary storage")));
|
||||
let state = Arc::new(AppState::new(
|
||||
dbx_core::persistence::test_storage::open(&storage_path).await.expect("temporary storage"),
|
||||
));
|
||||
let table_name = format!("dbx_pr9434_{}", uuid::Uuid::new_v4().simple());
|
||||
let database = config.database.clone().expect("database");
|
||||
state.configs.write().await.insert(config.id.clone(), config.clone());
|
||||
|
||||
@@ -8,7 +8,6 @@ use dbx_core::query::{
|
||||
begin_manual_transaction, commit_manual_transaction, execute_in_manual_transaction, execute_sql_statement,
|
||||
rollback_manual_transaction, stream_rows_in_manual_transaction,
|
||||
};
|
||||
use dbx_core::storage::Storage;
|
||||
use std::sync::{
|
||||
atomic::{AtomicU64, Ordering},
|
||||
Arc,
|
||||
@@ -46,7 +45,7 @@ fn live_config(prefix: &str, db_type: DatabaseType, default_port: u16) -> Connec
|
||||
|
||||
async fn app_state_with_config(config: ConnectionConfig) -> (Arc<AppState>, std::path::PathBuf) {
|
||||
let db_path = std::env::temp_dir().join(format!("dbx-live-manual-txn-{}.db", uuid::Uuid::new_v4().simple()));
|
||||
let storage = Storage::open(&db_path).await.expect("open temp storage");
|
||||
let storage = dbx_core::persistence::test_storage::open(&db_path).await.expect("open temp storage");
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(config.id.clone(), config);
|
||||
(state, db_path)
|
||||
|
||||
@@ -8,7 +8,6 @@ use dbx_core::agent_tools::{execute_tool, AgentSqlPermissions};
|
||||
use dbx_core::connection::{AppState, PoolKind};
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::mongo_ops::mongo_create_index_core;
|
||||
use dbx_core::storage::Storage;
|
||||
use mongodb::bson::{doc, Bson};
|
||||
use mongodb::event::{command::CommandEvent, EventHandler};
|
||||
use mongodb::options::ClientOptions;
|
||||
@@ -76,7 +75,7 @@ async fn call_agent_tool_with_limit(
|
||||
#[ignore = "requires DBX_LIVE_MONGODB_* env vars pointing at a MongoDB database with a non-empty stores collection"]
|
||||
async fn mongodb_agent_find_one_returns_real_data_and_keeps_writes_blocked() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let config = live_mongodb_config("live-mongodb-agent");
|
||||
let database = config.database.clone().expect("database");
|
||||
@@ -96,7 +95,7 @@ async fn mongodb_agent_find_one_returns_real_data_and_keeps_writes_blocked() {
|
||||
#[ignore = "requires DBX_LIVE_MONGODB_* env vars pointing at a MongoDB database with a products collection containing at least 8 documents"]
|
||||
async fn mongodb_agent_enforces_limits_and_find_skips_total_count() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let config = live_mongodb_config("live-mongodb-agent-limits");
|
||||
let database = config.database.clone().expect("database");
|
||||
@@ -143,7 +142,7 @@ async fn mongodb_agent_enforces_limits_and_find_skips_total_count() {
|
||||
async fn stalled_mongodb_index_build_does_not_block_another_connection() {
|
||||
let uri = std::env::var("DBX_LIVE_MONGODB_42_URL").expect("DBX_LIVE_MONGODB_42_URL");
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let primary_id = "live-mongodb-42-index";
|
||||
let database = "dbx_issue_7720_primary";
|
||||
|
||||
@@ -53,7 +53,8 @@ async fn find_and_modify_commands_run_over_the_legacy_agent() {
|
||||
let (host, port) = endpoint.split_once(':').expect("host:port");
|
||||
let files = tempfile::tempdir().unwrap();
|
||||
let database = format!("dbx_legacy_fam_{}", uuid::Uuid::new_v4().simple());
|
||||
let state = AppState::new(Storage::open(&files.path().join("storage.db")).await.unwrap());
|
||||
let state =
|
||||
AppState::new(dbx_core::persistence::test_storage::open(&files.path().join("storage.db")).await.unwrap());
|
||||
let id = "legacy-find-and-modify-test";
|
||||
let config: ConnectionConfig = serde_json::from_value(serde_json::json!({ "id": id, "name": "Legacy findAndModify test", "db_type": "mongodb", "host": host, "port": port.parse::<u16>().unwrap(), "username": "", "password": "", "database": database, "driver_profile": "mongodb-legacy" })).unwrap();
|
||||
state.configs.write().await.insert(id.into(), config);
|
||||
@@ -163,7 +164,8 @@ async fn distinct_runs_over_the_legacy_agent() {
|
||||
let (host, port) = endpoint.split_once(':').expect("host:port");
|
||||
let files = tempfile::tempdir().unwrap();
|
||||
let database = format!("dbx_legacy_distinct_{}", uuid::Uuid::new_v4().simple());
|
||||
let state = AppState::new(Storage::open(&files.path().join("storage.db")).await.unwrap());
|
||||
let state =
|
||||
AppState::new(dbx_core::persistence::test_storage::open(&files.path().join("storage.db")).await.unwrap());
|
||||
let id = "legacy-distinct-test";
|
||||
let config: ConnectionConfig = serde_json::from_value(serde_json::json!({ "id": id, "name": "Legacy distinct test", "db_type": "mongodb", "host": host, "port": port.parse::<u16>().unwrap(), "username": "", "password": "", "database": database, "driver_profile": "mongodb-legacy" })).unwrap();
|
||||
state.configs.write().await.insert(id.into(), config);
|
||||
@@ -212,7 +214,8 @@ async fn collection_stats_and_create_database_run_over_the_legacy_agent() {
|
||||
let (host, port) = endpoint.split_once(':').expect("host:port");
|
||||
let files = tempfile::tempdir().unwrap();
|
||||
let database = format!("dbx_legacy_admin_{}", uuid::Uuid::new_v4().simple());
|
||||
let state = AppState::new(Storage::open(&files.path().join("storage.db")).await.unwrap());
|
||||
let state =
|
||||
AppState::new(dbx_core::persistence::test_storage::open(&files.path().join("storage.db")).await.unwrap());
|
||||
let id = "legacy-admin-test";
|
||||
let config: ConnectionConfig = serde_json::from_value(serde_json::json!({ "id": id, "name": "Legacy admin test", "db_type": "mongodb", "host": host, "port": port.parse::<u16>().unwrap(), "username": "", "password": "", "database": database, "driver_profile": "mongodb-legacy" })).unwrap();
|
||||
state.configs.write().await.insert(id.into(), config);
|
||||
@@ -298,7 +301,8 @@ async fn dump_and_export_resolve_the_per_database_pool() {
|
||||
let (host, port) = endpoint.split_once(':').expect("host:port");
|
||||
let files = tempfile::tempdir().unwrap();
|
||||
let database = format!("dbx_legacy_pool_{}", uuid::Uuid::new_v4().simple());
|
||||
let state = AppState::new(Storage::open(&files.path().join("storage.db")).await.unwrap());
|
||||
let state =
|
||||
AppState::new(dbx_core::persistence::test_storage::open(&files.path().join("storage.db")).await.unwrap());
|
||||
let id = "legacy-pool-key-test";
|
||||
let config: ConnectionConfig = serde_json::from_value(serde_json::json!({ "id": id, "name": "Legacy pool key test", "db_type": "mongodb", "host": host, "port": port.parse::<u16>().unwrap(), "username": "", "password": "", "database": database, "driver_profile": "mongodb-legacy" })).unwrap();
|
||||
state.configs.write().await.insert(id.into(), config);
|
||||
|
||||
@@ -13,7 +13,6 @@ use dbx_core::query::{
|
||||
use dbx_core::query_result_export::{export_query_result_core, ExportStatus, QueryResultExportRequest};
|
||||
use dbx_core::sql::{split_sql_statements_for_database, SqlFileRequest};
|
||||
use dbx_core::sql_file_import::execute_sql_file_path;
|
||||
use dbx_core::storage::Storage;
|
||||
use dbx_core::table_import::{
|
||||
build_import_insert_batch_from_rows, parse_csv_bytes, parse_xlsx_file, TableImportColumnMapping,
|
||||
};
|
||||
@@ -46,7 +45,7 @@ fn live_mysql_sql_file_config(id: &str) -> ConnectionConfig {
|
||||
|
||||
async fn app_state_with_config(config: ConnectionConfig) -> (AppState, std::path::PathBuf) {
|
||||
let db_path = std::env::temp_dir().join(format!("dbx-live-sql-file-{}.db", uuid::Uuid::new_v4().simple()));
|
||||
let storage = Storage::open(&db_path).await.expect("open temp storage");
|
||||
let storage = dbx_core::persistence::test_storage::open(&db_path).await.expect("open temp storage");
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(config.id.clone(), config);
|
||||
(state, db_path)
|
||||
@@ -436,7 +435,7 @@ async fn live_mysql_query_result_export_xlsx_streams_single_query_without_duplic
|
||||
let config = live_mysql_query_export_config(&connection_id, &host, port, &user, &password, &database);
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-mysql-query-export-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(config.id.clone(), config);
|
||||
|
||||
@@ -531,7 +530,7 @@ async fn live_mysql_csv_temporal_export_round_trip_preserves_dbx_force_text_valu
|
||||
let config = live_mysql_query_export_config(&connection_id, &host, port, &user, &password, &database);
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-issue-8803-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(config.id.clone(), config);
|
||||
|
||||
@@ -645,7 +644,7 @@ async fn live_mysql_xlsx_export_can_outlive_query_timeout_while_rows_keep_arrivi
|
||||
let config = live_mysql_query_export_config(&connection_id, &host, port, &user, &password, &database);
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-mysql-query-export-timeout-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(config.id.clone(), config);
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ use dbx_core::query::{
|
||||
execute_multi_core_with_options_for_client_typed, execute_sql_statement, execute_sql_statement_with_options,
|
||||
ExecuteMultiResult, QueryExecutionOptions,
|
||||
};
|
||||
use dbx_core::storage::Storage;
|
||||
use std::sync::Arc;
|
||||
|
||||
fn live_config(prefix: &str) -> ConnectionConfig {
|
||||
@@ -36,7 +35,9 @@ fn live_config(prefix: &str) -> ConnectionConfig {
|
||||
async fn setup(config: &ConnectionConfig) -> (Arc<AppState>, std::path::PathBuf, String) {
|
||||
let storage_path =
|
||||
std::env::temp_dir().join(format!("dbx-autocommit-snapshot-{}.db", uuid::Uuid::new_v4().simple()));
|
||||
let state = Arc::new(AppState::new(Storage::open(&storage_path).await.expect("temporary storage")));
|
||||
let state = Arc::new(AppState::new(
|
||||
dbx_core::persistence::test_storage::open(&storage_path).await.expect("temporary storage"),
|
||||
));
|
||||
let table_name = format!("dbx_issue_9479_{}", uuid::Uuid::new_v4().simple());
|
||||
let database = config.database.clone().expect("database");
|
||||
state.configs.write().await.insert(config.id.clone(), config.clone());
|
||||
@@ -122,7 +123,9 @@ async fn run_in_tab_keeping_transactions(
|
||||
/// cases, seeded with `(1, 0)`.
|
||||
async fn setup_probe(config: &ConnectionConfig, tag: &str) -> (Arc<AppState>, std::path::PathBuf, String) {
|
||||
let storage_path = std::env::temp_dir().join(format!("{tag}-{}.db", uuid::Uuid::new_v4().simple()));
|
||||
let state = Arc::new(AppState::new(Storage::open(&storage_path).await.expect("temporary storage")));
|
||||
let state = Arc::new(AppState::new(
|
||||
dbx_core::persistence::test_storage::open(&storage_path).await.expect("temporary storage"),
|
||||
));
|
||||
let table_name = format!("dbx_issue_9749_{}", uuid::Uuid::new_v4().simple());
|
||||
let database = config.database.clone().expect("database");
|
||||
state.configs.write().await.insert(config.id.clone(), config.clone());
|
||||
|
||||
@@ -4,7 +4,6 @@ use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::query::execute_sql_statement;
|
||||
use dbx_core::sql::SqlFileRequest;
|
||||
use dbx_core::sql_file_import::execute_sql_file_path;
|
||||
use dbx_core::storage::Storage;
|
||||
use std::sync::Arc;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
@@ -51,7 +50,7 @@ async fn live_mysql_selected_table_restore_preserves_unselected_tables() {
|
||||
let database = format!("dbx_restore_{suffix}");
|
||||
let dir = std::env::temp_dir().join(format!("dbx-selected-restore-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(connection_id.clone(), live_mysql_config(&connection_id));
|
||||
execute_sql_statement(&state, &connection_id, "", &format!("CREATE DATABASE `{database}`"), None, None)
|
||||
@@ -121,7 +120,7 @@ async fn live_mysql_database_export_restores_dependent_views() {
|
||||
let database = format!("dbx_export_{suffix}");
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-mysql-export-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), live_mysql_config(&connection_id));
|
||||
|
||||
@@ -248,7 +247,7 @@ async fn run_live_mysql_database_export_handles_many_tables_including_empty_tabl
|
||||
let database = format!("dbx_export_many_{suffix}");
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-mysql-export-many-tables-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), live_mysql_config(&connection_id));
|
||||
|
||||
@@ -354,7 +353,7 @@ async fn live_mysql_database_export_creates_missing_destination_directory() {
|
||||
let database = format!("dbx_export_missing_dir_{suffix}");
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-mysql-export-missing-dir-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), live_mysql_config(&connection_id));
|
||||
|
||||
@@ -422,7 +421,7 @@ async fn live_mysql_database_export_refuses_to_recreate_a_destination_that_disap
|
||||
let database = format!("dbx_export_vanished_dir_{suffix}");
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-mysql-export-vanished-dir-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), live_mysql_config(&connection_id));
|
||||
|
||||
@@ -504,7 +503,7 @@ async fn live_mysql_database_export_refuses_a_destination_that_vanished_before_i
|
||||
let database = format!("dbx_export_precfg_vanished_{suffix}");
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-mysql-export-preconfigured-vanished-dir-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), live_mysql_config(&connection_id));
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ use dbx_core::connection::AppState;
|
||||
use dbx_core::database_export::{export_database_sql_core, DatabaseExportRequest};
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::query::execute_sql_statement;
|
||||
use dbx_core::storage::Storage;
|
||||
use std::sync::Arc;
|
||||
|
||||
fn live_mysql_config(id: &str) -> ConnectionConfig {
|
||||
@@ -54,7 +53,7 @@ async fn live_mysql_database_export_table_order_is_not_alphabetical_when_fk_reor
|
||||
let database = format!("dbx_export_order_{suffix}");
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-mysql-export-order-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), live_mysql_config(&connection_id));
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
use dbx_core::connection::AppState;
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::query::execute_sql_statement;
|
||||
use dbx_core::storage::Storage;
|
||||
|
||||
fn live_mysql_config(connection_id: &str, database: &str) -> ConnectionConfig {
|
||||
let host = std::env::var("DBX_LIVE_MYSQL_HOST").expect("DBX_LIVE_MYSQL_HOST");
|
||||
@@ -50,7 +49,7 @@ async fn live_mysql_object_statistics_refresh_after_writes() {
|
||||
let table = format!("dbx_stats_fresh_{}", &suffix[..12]);
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-mysql-object-statistics-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(connection_id.clone(), live_mysql_config(&connection_id, &database));
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use dbx_core::connection::AppState;
|
||||
use dbx_core::db::mysql;
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::storage::Storage;
|
||||
use dbx_core::transfer::{
|
||||
drop_backup_tables, execute_on_pool, rename_tables_to_backup, sort_tables_by_fk_dependency_with_foreign_keys,
|
||||
transfer_table, TransferContent, TransferMode, TransferOwnershipPolicy, TransferRequest, TransferTableNameCase,
|
||||
@@ -174,7 +173,7 @@ async fn run_live_mysql_cross_version_transfer_completes_on_small_stack() {
|
||||
);
|
||||
let dir = task_tmp.join(format!("small-stack-transfer-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(source_connection_id.clone(), source_config);
|
||||
state.configs.write().await.insert(target_connection_id.clone(), target_config);
|
||||
@@ -329,7 +328,7 @@ async fn live_mysql_transfer_keeps_columns_whose_comment_mentions_foreign_key()
|
||||
);
|
||||
let dir = task_tmp.join(format!("live-mysql-fk-comment-transfer-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(source_connection_id.clone(), source_config);
|
||||
state.configs.write().await.insert(target_connection_id.clone(), target_config);
|
||||
@@ -486,7 +485,7 @@ async fn live_mysql_transfer_downgrades_unsupported_source_collations() {
|
||||
);
|
||||
let dir = task_tmp.join(format!("live-mysql-collation-transfer-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(source_connection_id.clone(), source_config);
|
||||
state.configs.write().await.insert(target_connection_id.clone(), target_config);
|
||||
@@ -673,7 +672,7 @@ async fn live_mysql_transfer_preserves_spatial_values_and_modes() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-mysql-transfer-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), config);
|
||||
let source_pool_key = state.get_or_create_pool(&connection_id, Some(&source_database)).await.unwrap();
|
||||
@@ -856,7 +855,7 @@ async fn live_mysql_transfer_structure_overwrite_rejects_incompatible_target_col
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-mysql-transfer-struct-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), config);
|
||||
let source_pool_key = state.get_or_create_pool(&connection_id, Some(&source_database)).await.unwrap();
|
||||
@@ -1012,7 +1011,7 @@ async fn live_mysql_transfer_structure_only_rejects_incompatible_target_columns(
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-mysql-transfer-structonly-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), config);
|
||||
let source_pool_key = state.get_or_create_pool(&connection_id, Some(&source_database)).await.unwrap();
|
||||
@@ -1111,7 +1110,7 @@ async fn live_mysql_transfer_drop_target_parent_child_foreign_key() {
|
||||
mysql::execute_query(&setup_pool, &setup, true).await.unwrap();
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-mysql-parent-child-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), config);
|
||||
let source_pool_key = state.get_or_create_pool(&connection_id, Some(&source_database)).await.unwrap();
|
||||
@@ -1304,7 +1303,7 @@ async fn live_mysql_transfer_drop_target_rebuilds_incompatible_structure() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-mysql-drop-rebuild-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), config);
|
||||
let source_pool_key = state.get_or_create_pool(&connection_id, Some(&source_database)).await.unwrap();
|
||||
@@ -1493,7 +1492,7 @@ async fn live_mysql_transfer_drop_target_rejects_external_incoming_fk() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-mysql-ext-fk-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), config);
|
||||
let pool_key = state.get_or_create_pool(&connection_id, Some(&database)).await.unwrap();
|
||||
@@ -1583,7 +1582,7 @@ async fn live_mysql_transfer_drop_target_circular_foreign_keys() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-mysql-circular-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), config);
|
||||
let source_pool_key = state.get_or_create_pool(&connection_id, Some(&source_database)).await.unwrap();
|
||||
@@ -1812,7 +1811,7 @@ async fn live_mysql_transfer_drop_target_retains_backup_on_failure() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-mysql-retain-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), config);
|
||||
let source_pool_key = state.get_or_create_pool(&connection_id, Some(&source_database)).await.unwrap();
|
||||
@@ -1989,7 +1988,7 @@ async fn live_mysql_keyset_pagination_copies_every_row() {
|
||||
);
|
||||
let dir = task_tmp.join(format!("live-mysql-keyset-transfer-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(source_connection_id.clone(), source_config);
|
||||
state.configs.write().await.insert(target_connection_id.clone(), target_config);
|
||||
@@ -2109,7 +2108,7 @@ async fn live_mysql_progress_read_survives_total_duration_beyond_timeout() {
|
||||
);
|
||||
let dir = task_tmp.join(format!("live-mysql-progress-transfer-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
// The read runs under the source's query timeout; keep it at 1s so the test only
|
||||
// passes when the transfer treats it as an inactivity budget, not a wall clock.
|
||||
@@ -2215,7 +2214,7 @@ async fn live_mysql_transfer_drop_target_inspects_dependent_views_without_the_us
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-mysql-legacy-dependency-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), config);
|
||||
let pool_key = state.get_or_create_pool(&connection_id, Some(&target_database)).await.unwrap();
|
||||
|
||||
@@ -7,7 +7,6 @@ use dbx_core::query::{
|
||||
begin_manual_transaction, commit_manual_transaction, execute_sql_statement, rollback_manual_transaction,
|
||||
};
|
||||
use dbx_core::sql::{SqlFileRequest, SqlFileStatus};
|
||||
use dbx_core::storage::Storage;
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
@@ -38,7 +37,7 @@ async fn verify_committed_value(state: &AppState, database: &str, table: &str, e
|
||||
#[ignore = "requires an installed OceanBase Oracle agent and writable DBX_LIVE_SQL_FILE_OB_* environment"]
|
||||
async fn live_oceanbase_sql_files_commit_rollback_failure_and_cancel() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&directory.path().join("state.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&directory.path().join("state.db")).await.unwrap();
|
||||
let state = AppState::new_with_plugin_and_agent_dir_and_app_version(
|
||||
storage,
|
||||
directory.path().join("plugins"),
|
||||
|
||||
@@ -4,7 +4,6 @@ use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::query::execute_sql_statement;
|
||||
use dbx_core::sql::SqlFileRequest;
|
||||
use dbx_core::sql_file_import::execute_sql_file_path;
|
||||
use dbx_core::storage::Storage;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
@@ -44,7 +43,8 @@ async fn live_postgres_all_schema_export_restores_one_sql_file() {
|
||||
let source_connection_id = format!("postgres-all-schema-source-{suffix}");
|
||||
let target_connection_id = format!("postgres-all-schema-target-{suffix}");
|
||||
let dir = tempfile::tempdir().expect("create export temp directory");
|
||||
let storage = Storage::open(&dir.path().join("storage.db")).await.expect("open temp storage");
|
||||
let storage =
|
||||
dbx_core::persistence::test_storage::open(&dir.path().join("storage.db")).await.expect("open temp storage");
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state
|
||||
.configs
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
use dbx_core::connection::AppState;
|
||||
use dbx_core::docs::{NoteSource, SnapshotWarning};
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::storage::Storage;
|
||||
|
||||
fn live_postgres_config(
|
||||
id: &str,
|
||||
@@ -130,7 +129,7 @@ async fn annotations_reach_the_generated_dbml() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-postgres-docs-annotations-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(config.id.clone(), config.clone());
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use dbx_core::connection::AppState;
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::storage::Storage;
|
||||
|
||||
fn live_postgres_config(
|
||||
id: &str,
|
||||
@@ -93,7 +92,7 @@ async fn collects_a_snapshot_and_serializes_valid_dbml() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-postgres-docs-snapshot-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(config.id.clone(), config.clone());
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ use dbx_core::db::postgres;
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::query::{execute_multi_core_with_options_for_client_and_progress_typed, QueryExecutionOptions};
|
||||
use dbx_core::sql_error_position::{encode_marker, take_message_position, SqlErrorPosition, SQL_ERROR_POSITION_MARKER};
|
||||
use dbx_core::storage::Storage;
|
||||
|
||||
fn live_env() -> (String, u16, String, String, String) {
|
||||
let host = std::env::var("DBX_LIVE_POSTGRES_HOST").unwrap_or_else(|_| "127.0.0.1".to_string());
|
||||
@@ -110,7 +109,7 @@ async fn live_pg_multi_core_reports_error_position_in_the_backend_envelope() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-pg-position-{}", uuid::Uuid::new_v4().simple()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "live-pg-position";
|
||||
state.configs.write().await.insert(
|
||||
|
||||
@@ -7,7 +7,6 @@ use dbx_core::db::postgres;
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::query::execute_sql_statement;
|
||||
use dbx_core::query_result_export::{export_query_result_core, ExportStatus, QueryResultExportRequest};
|
||||
use dbx_core::storage::Storage;
|
||||
|
||||
fn live_postgres_config(
|
||||
id: &str,
|
||||
@@ -117,7 +116,7 @@ async fn live_postgres_query_result_export_uses_single_streamed_query() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-postgres-query-export-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "live-postgres-query-export";
|
||||
let config = live_postgres_config(connection_id, &host, port, &user, &password, &database);
|
||||
@@ -206,7 +205,7 @@ async fn live_postgres_query_result_xlsx_preserves_temporal_cell_types() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-postgres-xlsx-temporal-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "live-postgres-xlsx-temporal";
|
||||
let config = live_postgres_config(connection_id, &host, port, &user, &password, &database);
|
||||
@@ -275,7 +274,7 @@ async fn live_postgres_numeric_xlsx_ignores_fractional_trailing_zeros() {
|
||||
let suffix = uuid::Uuid::new_v4().simple().to_string();
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-postgres-xlsx-numeric-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "live-postgres-xlsx-numeric";
|
||||
let config = live_postgres_config(connection_id, &host, port, &user, &password, &database);
|
||||
@@ -354,7 +353,7 @@ async fn live_postgres_truncated_batch_result_export_replays_safe_temp_setup() {
|
||||
let config = live_postgres_config(&connection_id, &host, port, &user, &password, &database);
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-postgres-temp-export-{short_suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(config.id.clone(), config);
|
||||
|
||||
@@ -447,7 +446,7 @@ async fn live_postgres_xlsx_export_can_outlive_query_timeout_while_rows_keep_arr
|
||||
let config = live_postgres_config(&connection_id, &host, port, &user, &password, &database);
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-postgres-query-export-timeout-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(config.id.clone(), config);
|
||||
|
||||
@@ -521,7 +520,7 @@ async fn live_postgres_stream_still_times_out_without_progress_and_recovers() {
|
||||
let config = live_postgres_config(&connection_id, &host, port, &user, &password, &database);
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-postgres-query-export-stall-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
state.configs.write().await.insert(config.id.clone(), config);
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use dbx_core::connection::{AppState, PoolKind};
|
||||
use dbx_core::db::postgres;
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::storage::Storage;
|
||||
use dbx_core::transfer::{
|
||||
drop_backup_tables, get_db_type, rename_tables_to_backup, transfer_postgres_schema_dependencies,
|
||||
transfer_postgres_schema_objects, transfer_table, TransferContent, TransferMode, TransferObjectKind,
|
||||
@@ -216,7 +215,7 @@ async fn live_postgres_transfer_upserts_generated_always_identity_values() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-always-transfer-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let source_connection_id = "live-always-source";
|
||||
let target_connection_id = "live-always-target";
|
||||
@@ -393,7 +392,7 @@ async fn live_postgres_structure_only_preserves_table_indexes() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-structure-only-transfer-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let source_connection_id = "live-structure-only-source";
|
||||
let target_connection_id = "live-structure-only-target";
|
||||
@@ -675,7 +674,7 @@ async fn live_postgres_transfer_preserves_data_and_schema_objects() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-transfer-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
|
||||
let source_connection_id = "live-source";
|
||||
@@ -977,7 +976,7 @@ async fn live_postgres_transfer_skips_create_ddl_for_existing_target_table() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-existing-transfer-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
|
||||
let source_connection_id = "live-existing-source";
|
||||
@@ -1103,7 +1102,7 @@ async fn live_postgres_transfer_creates_selected_sequence_before_referencing_tab
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-sequence-transfer-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let source_connection_id = "live-sequence-source";
|
||||
let target_connection_id = "live-sequence-target";
|
||||
@@ -1305,7 +1304,7 @@ async fn live_postgres_transfer_drop_target_rebuilds_structure_and_indexes() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-drop-rebuild-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), config);
|
||||
|
||||
@@ -1496,7 +1495,9 @@ impl PostgresRebuildFixture {
|
||||
let source_pool_key = format!("{source_connection_id}:{source_database}");
|
||||
let target_pool_key = format!("{target_connection_id}:{target_database}");
|
||||
let storage_dir = tempfile::tempdir().unwrap();
|
||||
let state = Arc::new(AppState::new(Storage::open(&storage_dir.path().join("storage.db")).await.unwrap()));
|
||||
let state = Arc::new(AppState::new(
|
||||
dbx_core::persistence::test_storage::open(&storage_dir.path().join("storage.db")).await.unwrap(),
|
||||
));
|
||||
state
|
||||
.update_connection_pools(|connections| {
|
||||
connections.insert(source_pool_key.clone(), PoolKind::Postgres(source_pool.clone()));
|
||||
@@ -1816,7 +1817,7 @@ async fn live_postgres_keyset_pagination_copies_every_row() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-pg-keyset-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let source_connection_id = "live-pg-keyset-source";
|
||||
let target_connection_id = "live-pg-keyset-target";
|
||||
@@ -1928,7 +1929,7 @@ async fn live_postgres_progress_read_survives_total_duration_beyond_timeout() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-pg-progress-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let source_connection_id = "live-pg-progress-source";
|
||||
let target_connection_id = "live-pg-progress-target";
|
||||
@@ -2034,7 +2035,7 @@ async fn live_postgres_keyset_large_batch_copies_every_row() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-pg-largebatch-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let source_connection_id = "live-pg-largebatch-source";
|
||||
let target_connection_id = "live-pg-largebatch-target";
|
||||
|
||||
@@ -7,7 +7,6 @@ use dbx_core::redis_ops::{
|
||||
redis_delete_keys_in_db_core, redis_get_ttl_in_db_core, redis_set_keys_expire_at_in_db_core,
|
||||
redis_set_keys_ttl_in_db_core, redis_set_string_in_db_core,
|
||||
};
|
||||
use dbx_core::storage::Storage;
|
||||
|
||||
/// Shared Redis fixtures used by the batch-expiration coverage below.
|
||||
///
|
||||
@@ -20,7 +19,7 @@ async fn live_state(connection_id: &str) -> Arc<AppState> {
|
||||
let username = std::env::var("DBX_LIVE_REDIS_USERNAME").unwrap_or_default();
|
||||
let password = std::env::var("DBX_LIVE_REDIS_PASSWORD").unwrap_or_default();
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let redis_config: ConnectionConfig = serde_json::from_value(serde_json::json!({
|
||||
"id": connection_id,
|
||||
|
||||
@@ -4,7 +4,6 @@ use std::time::Duration;
|
||||
use dbx_core::connection::AppState;
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::redis_ops::redis_execute_command_core;
|
||||
use dbx_core::storage::Storage;
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore = "requires DBX_LIVE_REDIS_HOST and DBX_LIVE_REDIS_PORT"]
|
||||
@@ -12,7 +11,7 @@ async fn blocking_redis_command_does_not_block_another_connection() {
|
||||
let host = std::env::var("DBX_LIVE_REDIS_HOST").expect("DBX_LIVE_REDIS_HOST");
|
||||
let port = std::env::var("DBX_LIVE_REDIS_PORT").expect("DBX_LIVE_REDIS_PORT").parse::<u16>().expect("Redis port");
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let redis_config: ConnectionConfig = serde_json::from_value(serde_json::json!({
|
||||
"id": "live-redis-blocking",
|
||||
|
||||
@@ -3,7 +3,6 @@ use dbx_core::models::connection::DatabaseType;
|
||||
use dbx_core::query_result_export::{export_query_result_core, ExportStatus, QueryResultExportRequest};
|
||||
use dbx_core::sql::{SqlFileRequest, SqlFileStatus};
|
||||
use dbx_core::sql_file_import::execute_sql_file_content;
|
||||
use dbx_core::storage::Storage;
|
||||
use dbx_core::table_import::{
|
||||
build_import_insert_batches, import_table_file_core, parse_delimited_file_with_options, TableImportColumnMapping,
|
||||
TableImportMode, TableImportParseOptions, TableImportRequest, TableImportSourceFormat, TableImportStatus,
|
||||
@@ -91,7 +90,8 @@ async fn live_sqlserver_import_state(
|
||||
) -> (AppState, String, std::path::PathBuf) {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-sqlserver-import-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).expect("create live import directory");
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.expect("open live import storage");
|
||||
let storage =
|
||||
dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.expect("open live import storage");
|
||||
let state = AppState::new(storage);
|
||||
let config = live_sqlserver_config(connection_id, database);
|
||||
state.configs.write().await.insert(connection_id.to_string(), config);
|
||||
@@ -1169,7 +1169,7 @@ async fn live_sqlserver_query_result_export_streams_cte_query_to_csv() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-sqlserver-export-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "live-sqlserver-export";
|
||||
let pool_key = format!("{connection_id}:{database}");
|
||||
@@ -1262,7 +1262,7 @@ async fn live_sqlserver_sql_file_import_executes_go_batches() {
|
||||
let procedure = format!("dbx_sql_file_proc_{suffix}");
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-sqlserver-file-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "live-sqlserver-file";
|
||||
let mut config = live_sqlserver_config(connection_id, &database);
|
||||
@@ -1369,7 +1369,7 @@ async fn live_sqlserver_transfer_table_skips_rowversion_insert_column() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-sqlserver-rowversion-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let config = live_sqlserver_config("live-sqlserver-rowversion", &database);
|
||||
state.configs.write().await.insert(config.id.clone(), config);
|
||||
@@ -1565,7 +1565,7 @@ async fn live_sqlserver_cross_database_metadata_and_query() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-sqlserver-cross-database-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "live-sqlserver-cross-database";
|
||||
let mut config = live_sqlserver_config(connection_id, &default_database);
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
use dbx_core::connection::AppState;
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::query::execute_sql_statement;
|
||||
use dbx_core::storage::Storage;
|
||||
use std::sync::Arc;
|
||||
|
||||
fn live_sqlserver_config(id: &str, database: &str) -> ConnectionConfig {
|
||||
@@ -44,7 +43,7 @@ async fn live_sqlserver_display_ddl_reads_foreign_key_actions() {
|
||||
let database = format!("dbx_ddl_fk_{suffix}");
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-sqlserver-ddl-fk-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), live_sqlserver_config(&connection_id, "master"));
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use dbx_core::connection::{AppState, PoolKind};
|
||||
use dbx_core::models::connection::DatabaseType;
|
||||
use dbx_core::query_result_export::{export_query_result_core, ExportStatus, QueryResultExportRequest};
|
||||
use dbx_core::storage::Storage;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
@@ -89,7 +88,7 @@ async fn live_sqlserver_xlsx_export_can_outlive_query_timeout_while_rows_keep_ar
|
||||
let suffix = uuid::Uuid::new_v4().simple().to_string();
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-sqlserver-xlsx-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "live-sqlserver-xlsx-export";
|
||||
let pool_key = format!("{connection_id}:{database}");
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use dbx_core::connection::AppState;
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::storage::Storage;
|
||||
use dbx_core::transfer::{
|
||||
drop_backup_tables, rename_tables_to_backup, transfer_table, TransferContent, TransferMode,
|
||||
TransferOwnershipPolicy, TransferRequest, TransferTableNameCase,
|
||||
@@ -155,7 +154,8 @@ async fn live_sqlserver_transfer_rebuild_releases_constraint_and_index_names() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-sqlserver-rebuild-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).expect("create rebuild directory");
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.expect("open rebuild storage");
|
||||
let storage =
|
||||
dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.expect("open rebuild storage");
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let config = live_sqlserver_config(&connection_id, &source_db);
|
||||
state.configs.write().await.insert(connection_id.clone(), config);
|
||||
@@ -318,7 +318,8 @@ async fn live_sqlserver_transfer_overwrite_handles_existing_identity_target() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-sqlserver-8690-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).expect("create issue #8690 directory");
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.expect("open issue #8690 storage");
|
||||
let storage =
|
||||
dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.expect("open issue #8690 storage");
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state.configs.write().await.insert(connection_id.clone(), live_sqlserver_config(&connection_id, &database));
|
||||
let pool_key = state.get_or_create_pool(&connection_id, Some(&database)).await.expect("create SQL Server pool");
|
||||
@@ -423,7 +424,8 @@ async fn live_sqlserver_keyset_pagination_copies_every_row() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-sqlserver-keyset-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).expect("create keyset directory");
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.expect("open keyset storage");
|
||||
let storage =
|
||||
dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.expect("open keyset storage");
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state
|
||||
.configs
|
||||
@@ -543,7 +545,8 @@ async fn live_sqlserver_progress_read_survives_total_duration_beyond_timeout() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-sqlserver-progress-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).expect("create progress directory");
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.expect("open progress storage");
|
||||
let storage =
|
||||
dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.expect("open progress storage");
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
// The read runs under the source's query timeout; keep it at 1s so the test only
|
||||
// passes when the transfer treats it as an inactivity budget, not a wall clock.
|
||||
@@ -662,7 +665,7 @@ async fn live_sqlserver_keyset_uniqueidentifier_datetime2_composite_key() {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-live-sqlserver-typed-{suffix}"));
|
||||
std::fs::create_dir_all(&dir).expect("create typed directory");
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.expect("open typed storage");
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.expect("open typed storage");
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
state
|
||||
.configs
|
||||
|
||||
@@ -11,12 +11,11 @@ use dbx_core::db::mongo_driver;
|
||||
use dbx_core::models::connection::{ConnectionConfig, DatabaseType};
|
||||
use dbx_core::mongo_ops::mongo_run_command_core;
|
||||
use dbx_core::schema::get_columns_core;
|
||||
use dbx_core::storage::Storage;
|
||||
use serde_json::json;
|
||||
|
||||
async fn state_with_pool(pool: PoolKind, db_type: DatabaseType, database: &str) -> (Arc<AppState>, tempfile::TempDir) {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(AppState::new(storage));
|
||||
let config: ConnectionConfig = serde_json::from_value(json!({
|
||||
"id": "metadata", "name": "Column metadata regression", "db_type": db_type,
|
||||
|
||||
@@ -186,7 +186,7 @@ async fn official_tools_round_trip_through_dbx_core() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let client = mongodb::Client::with_uri_str(&uri).await.unwrap();
|
||||
let database = format!("dbx_dump_test_{}", uuid::Uuid::new_v4().simple());
|
||||
let storage = Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = AppState::new(storage);
|
||||
let connection_id = "mongo-dump-test";
|
||||
let config: ConnectionConfig = serde_json::from_value(serde_json::json!({
|
||||
@@ -403,7 +403,8 @@ async fn official_database_tools_round_trip_through_dbx() {
|
||||
db.run_command(doc! { "create": "z_view", "viewOn": "records", "pipeline": [ { "$match": { "score": { "$gte": 1 } } } ], "collation": { "locale": "en", "strength": 2 } }).await.unwrap();
|
||||
db.run_command(doc! { "create": "a_nested", "viewOn": "z_view", "pipeline": [], "collation": { "locale": "en", "strength": 2 } }).await.unwrap();
|
||||
let collections = ["records", "empty", "capped", "odd/name", "z_view", "a_nested"];
|
||||
let state = AppState::new(Storage::open(&files.path().join("storage.db")).await.unwrap());
|
||||
let state =
|
||||
AppState::new(dbx_core::persistence::test_storage::open(&files.path().join("storage.db")).await.unwrap());
|
||||
let connection_id = "database-dump-test";
|
||||
let config: ConnectionConfig = serde_json::from_value(serde_json::json!({ "id": connection_id, "name": "Database dump test", "db_type": "mongodb", "host": "127.0.0.1", "port": 27090, "username": "", "password": "", "database": database, "connection_string": uri, "driver_profile": "mongodb-native" })).unwrap();
|
||||
state.configs.write().await.insert(connection_id.into(), config);
|
||||
@@ -776,7 +777,8 @@ async fn legacy_agent_database_round_trip_through_dbx() {
|
||||
let (host, port) = endpoint.split_once(':').expect("host:port");
|
||||
let files = tempfile::tempdir().unwrap();
|
||||
let database = format!("dbx_legacy_{}", uuid::Uuid::new_v4().simple());
|
||||
let state = AppState::new(Storage::open(&files.path().join("storage.db")).await.unwrap());
|
||||
let state =
|
||||
AppState::new(dbx_core::persistence::test_storage::open(&files.path().join("storage.db")).await.unwrap());
|
||||
let id = "legacy-dump-test";
|
||||
let config: ConnectionConfig = serde_json::from_value(serde_json::json!({ "id": id, "name": "Legacy dump test", "db_type": "mongodb", "host": host, "port": port.parse::<u16>().unwrap(), "username": "", "password": "", "database": database, "driver_profile": "mongodb-legacy" })).unwrap();
|
||||
state.configs.write().await.insert(id.into(), config);
|
||||
@@ -961,7 +963,7 @@ async fn directory_preview_does_not_read_bson_and_source_identity_is_checked_bef
|
||||
.unwrap();
|
||||
assert_eq!(preview.catalog.collections[0].documents, None);
|
||||
assert_eq!(preview.catalog.collections[0].size_bytes, 16);
|
||||
let state = AppState::new(Storage::open(&files.path().join("state.db")).await.unwrap());
|
||||
let state = AppState::new(dbx_core::persistence::test_storage::open(&files.path().join("state.db")).await.unwrap());
|
||||
let request: MongoDatabaseRestoreRequest = serde_json::from_value(serde_json::json!({
|
||||
"taskId":"validation-test", "connectionId":"missing", "database":"target", "sourceDatabase":"source",
|
||||
"sourceRef":preview.source_ref, "dropExisting":true
|
||||
|
||||
@@ -5,7 +5,6 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
|
||||
use dbx_core::mq::token::{sign_pulsar_token, token_fingerprint};
|
||||
use dbx_core::mq::{MqTokenIssueRequest, MqTokenRecord, MqTokenSigningAlgorithm, MqTokenSigningConfig};
|
||||
use dbx_core::storage::Storage;
|
||||
|
||||
#[test]
|
||||
fn hs256_token_contains_pulsar_subject_and_expiry() {
|
||||
@@ -45,7 +44,7 @@ fn token_signing_requires_configured_key() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn token_records_are_saved_without_token_plaintext() {
|
||||
let storage = Storage::open(&temp_db_path("mq-token-records")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&temp_db_path("mq-token-records")).await.unwrap();
|
||||
let record = MqTokenRecord {
|
||||
id: "rec-1".to_string(),
|
||||
connection_id: "conn-1".to_string(),
|
||||
|
||||
@@ -51,4 +51,5 @@ mime_guess = { version = "2", optional = true }
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
dbx-core = { path = "../dbx-core", default-features = false, features = ["test-support"] }
|
||||
reqwest = { version = "0.12", default-features = false, features = ["multipart"] }
|
||||
@@ -310,7 +310,8 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn demo_connect_guard_requires_a_pool_equivalent_stored_connection() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = dbx_core::storage::Storage::open_unmigrated(&directory.path().join("dbx.db")).await.unwrap();
|
||||
let storage =
|
||||
dbx_core::persistence::test_storage::open_unmigrated(&directory.path().join("dbx.db")).await.unwrap();
|
||||
let app = std::sync::Arc::new(dbx_core::connection::AppState::new(storage));
|
||||
|
||||
let unknown = stored_config();
|
||||
@@ -334,7 +335,8 @@ mod tests {
|
||||
use axum::routing::{get, post};
|
||||
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = dbx_core::storage::Storage::open_unmigrated(&directory.path().join("dbx.db")).await.unwrap();
|
||||
let storage =
|
||||
dbx_core::persistence::test_storage::open_unmigrated(&directory.path().join("dbx.db")).await.unwrap();
|
||||
let app = std::sync::Arc::new(dbx_core::connection::AppState::new(storage));
|
||||
let state = {
|
||||
let mut web_state = crate::state::WebState::for_tests(app, directory.path().to_path_buf());
|
||||
@@ -364,7 +366,7 @@ mod tests {
|
||||
|
||||
// 关闭开关后同一中间件直接放行。
|
||||
let app = std::sync::Arc::new(dbx_core::connection::AppState::new(
|
||||
dbx_core::storage::Storage::open_unmigrated(&directory.path().join("dbx.db")).await.unwrap(),
|
||||
dbx_core::persistence::test_storage::open_unmigrated(&directory.path().join("dbx.db")).await.unwrap(),
|
||||
));
|
||||
let state = std::sync::Arc::new(crate::state::WebState::for_tests(app, directory.path().to_path_buf()));
|
||||
let router = axum::Router::new()
|
||||
|
||||
@@ -1452,7 +1452,8 @@ mod tests {
|
||||
async fn migration_http_gate_blocks_business_until_ready_but_allows_cleanup_handler() {
|
||||
use std::sync::{atomic::Ordering, Arc};
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = dbx_core::storage::Storage::open_unmigrated(&directory.path().join("dbx.db")).await.unwrap();
|
||||
let storage =
|
||||
dbx_core::persistence::test_storage::open_unmigrated(&directory.path().join("dbx.db")).await.unwrap();
|
||||
let app = Arc::new(dbx_core::connection::AppState::new(storage));
|
||||
let state = Arc::new(crate::state::WebState::for_tests(app, directory.path().to_path_buf()));
|
||||
state.migration_ready.store(false, Ordering::Release);
|
||||
|
||||
@@ -659,7 +659,7 @@ mod tests {
|
||||
|
||||
let dir = std::env::temp_dir().join(format!("dbx-web-intg-max-retries-{}", uuid::Uuid::new_v4()));
|
||||
let _ = std::fs::create_dir_all(&dir);
|
||||
let storage = dbx_core::storage::Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
storage.save_max_retries(0).await.unwrap();
|
||||
assert_eq!(storage.load_max_retries().await.unwrap(), 0);
|
||||
|
||||
|
||||
@@ -387,7 +387,6 @@ mod tests {
|
||||
use axum::Json;
|
||||
use dbx_core::cloud_sync::SnippetProvider;
|
||||
use dbx_core::connection::AppState;
|
||||
use dbx_core::storage::Storage;
|
||||
|
||||
use crate::state::WebState;
|
||||
|
||||
@@ -396,11 +395,11 @@ mod tests {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-web-snippet-cleanup-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let db = dir.join("storage.db");
|
||||
let storage = Storage::open(&db).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&db).await.unwrap();
|
||||
storage.save_snippet_migration_state("github", "replacement-id", "legacy-id", "content-hash").await.unwrap();
|
||||
drop(storage);
|
||||
|
||||
let storage = Storage::open(&db).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&db).await.unwrap();
|
||||
let app = Arc::new(AppState::new_with_plugin_dir(storage, dir.join("plugins")));
|
||||
let state = Arc::new(WebState::for_tests(app, dir.clone()));
|
||||
let Json(settings) = super::snippet_sync_settings(
|
||||
|
||||
@@ -972,7 +972,7 @@ mod tests {
|
||||
use dbx_core::nacos::config::{
|
||||
NacosAuthConfig, NacosRNacosConsoleAuth, NACOS_CONSOLE_SESSION_PASSWORD, NACOS_PRIMARY_SESSION_PASSWORD,
|
||||
};
|
||||
use dbx_core::storage::{McpGlobalPolicy, Storage};
|
||||
use dbx_core::storage::McpGlobalPolicy;
|
||||
use std::sync::Arc;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpListener;
|
||||
@@ -1180,7 +1180,7 @@ mod tests {
|
||||
async fn test_web_state() -> (Arc<WebState>, std::path::PathBuf) {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-web-test-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let app = Arc::new(AppState::new_with_plugin_dir(storage, dir.join("plugins")));
|
||||
let state = Arc::new(WebState::for_tests(app, dir.clone()));
|
||||
(state, dir)
|
||||
@@ -1697,7 +1697,7 @@ mod tests {
|
||||
.await
|
||||
})
|
||||
.await;
|
||||
assert!(result.is_ok());
|
||||
assert!(result.is_ok(), "{result:?}");
|
||||
|
||||
// 全局运行态配置不含明文密码(泄露面消除)。
|
||||
let stored = state.app.configs.read().await.get("conn-a").cloned().unwrap();
|
||||
|
||||
@@ -1023,7 +1023,7 @@ mod tests {
|
||||
};
|
||||
use dbx_core::connection::AppState;
|
||||
use dbx_core::models::connection::ConnectionConfig;
|
||||
use dbx_core::storage::{McpGlobalPolicy, Storage};
|
||||
use dbx_core::storage::McpGlobalPolicy;
|
||||
use std::sync::Arc;
|
||||
|
||||
fn mongo_config(is_production: bool) -> ConnectionConfig {
|
||||
@@ -1044,7 +1044,7 @@ mod tests {
|
||||
async fn test_web_state() -> (Arc<WebState>, std::path::PathBuf) {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-web-mongo-policy-test-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let app = Arc::new(AppState::new_with_plugin_dir(storage, dir.join("plugins")));
|
||||
let state = Arc::new(WebState::for_tests(app, dir.clone()));
|
||||
(state, dir)
|
||||
|
||||
@@ -613,11 +613,12 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn export_failure_and_cancellation_are_replayed_to_late_subscribers() {
|
||||
use axum::response::IntoResponse;
|
||||
use dbx_core::{connection::AppState, storage::Storage};
|
||||
use dbx_core::connection::AppState;
|
||||
|
||||
for cancelled in [false, true] {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage =
|
||||
dbx_core::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(WebState::for_tests(Arc::new(AppState::new(storage)), directory.path().into()));
|
||||
let id = uuid::Uuid::new_v4().to_string();
|
||||
let expected = if cancelled { MongoExportStatus::Cancelled } else { MongoExportStatus::Error };
|
||||
@@ -674,10 +675,10 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn early_import_failure_finishes_progress_and_cleans_source() {
|
||||
use dbx_core::{connection::AppState, storage::Storage};
|
||||
use dbx_core::connection::AppState;
|
||||
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let storage = Storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&directory.path().join("storage.db")).await.unwrap();
|
||||
let state = Arc::new(WebState::for_tests(Arc::new(AppState::new(storage)), directory.path().into()));
|
||||
let upload_dir = import_upload_dir(directory.path());
|
||||
std::fs::create_dir_all(&upload_dir).unwrap();
|
||||
|
||||
@@ -1554,7 +1554,7 @@ mod tests {
|
||||
async fn test_web_state() -> (Arc<WebState>, std::path::PathBuf) {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-web-mq-policy-test-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let app = Arc::new(AppState::new_with_plugin_dir(storage, dir.join("plugins")));
|
||||
let state = Arc::new(WebState {
|
||||
app,
|
||||
|
||||
@@ -6,11 +6,8 @@ use axum::{
|
||||
Router,
|
||||
};
|
||||
use dbx_core::{
|
||||
agent_tools::AgentSqlPermissions,
|
||||
connection::AppState,
|
||||
models::connection::ConnectionConfig,
|
||||
query::QueryExecutionOptions,
|
||||
storage::{McpGlobalPolicy, Storage},
|
||||
agent_tools::AgentSqlPermissions, connection::AppState, models::connection::ConnectionConfig,
|
||||
query::QueryExecutionOptions, storage::McpGlobalPolicy,
|
||||
};
|
||||
use dbx_mcp::{DbxBackend, LocalBackend, WebBackend};
|
||||
use serde_json::{json, Value};
|
||||
@@ -19,7 +16,7 @@ use std::sync::Arc;
|
||||
async fn run_object_cache_regression(postgres: bool) {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-object-cache-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let database =
|
||||
if postgres { std::env::var("DBX_LIVE_POSTGRES_DATABASE").expect("test database") } else { "main".into() };
|
||||
let config: ConnectionConfig = serde_json::from_value(json!({
|
||||
|
||||
@@ -1311,12 +1311,11 @@ mod tests {
|
||||
use crate::state::WebState;
|
||||
use axum::extract::State as AxumState;
|
||||
use dbx_core::connection::AppState;
|
||||
use dbx_core::storage::Storage;
|
||||
|
||||
async fn test_web_state() -> (Arc<WebState>, std::path::PathBuf) {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-web-query-test-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let app = Arc::new(AppState::new_with_plugin_dir(storage, dir.join("plugins")));
|
||||
let state = Arc::new(WebState::for_tests(app, dir.clone()));
|
||||
(state, dir)
|
||||
|
||||
@@ -182,7 +182,6 @@ mod tests {
|
||||
use super::*;
|
||||
use axum::body::to_bytes;
|
||||
use dbx_core::connection::AppState;
|
||||
use dbx_core::storage::Storage;
|
||||
|
||||
use crate::state::WebExportFile;
|
||||
|
||||
@@ -190,7 +189,7 @@ mod tests {
|
||||
async fn query_result_export_download_uses_the_requested_web_filename() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-web-query-export-download-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let app = Arc::new(AppState::new_with_plugin_dir(storage, dir.join("plugins")));
|
||||
let state = Arc::new(WebState::for_tests(app, dir.clone()));
|
||||
let file_path = dir.join("query-export.csv");
|
||||
|
||||
@@ -499,7 +499,7 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
async fn restore_state(directory: &Path) -> WebState {
|
||||
let storage = dbx_core::storage::Storage::open(&directory.join("dbx.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&directory.join("dbx.db")).await.unwrap();
|
||||
WebState::for_tests(Arc::new(dbx_core::connection::AppState::new(storage)), directory.to_path_buf())
|
||||
}
|
||||
|
||||
|
||||
@@ -170,7 +170,6 @@ mod tests {
|
||||
use super::*;
|
||||
use axum::body::to_bytes;
|
||||
use dbx_core::connection::AppState;
|
||||
use dbx_core::storage::Storage;
|
||||
|
||||
use crate::state::WebExportFile;
|
||||
|
||||
@@ -178,7 +177,7 @@ mod tests {
|
||||
async fn table_export_download_uses_the_requested_web_filename() {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-web-table-export-download-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let app = Arc::new(AppState::new_with_plugin_dir(storage, dir.join("plugins")));
|
||||
let state = Arc::new(WebState::for_tests(app, dir.clone()));
|
||||
let file_path = dir.join("table-export.xlsx");
|
||||
|
||||
@@ -667,7 +667,6 @@ mod tests {
|
||||
default_connect_timeout_secs, default_idle_timeout_secs, default_keepalive_interval_secs,
|
||||
default_query_timeout_secs, ConnectionConfig, DatabaseType,
|
||||
};
|
||||
use dbx_core::storage::Storage;
|
||||
use dbx_core::transfer::{
|
||||
TransferContent, TransferMode, TransferOwnershipPolicy, TransferRequest, TransferTableNameCase,
|
||||
};
|
||||
@@ -742,7 +741,7 @@ mod tests {
|
||||
async fn test_web_state() -> (Arc<WebState>, std::path::PathBuf) {
|
||||
let dir = std::env::temp_dir().join(format!("dbx-web-transfer-test-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let storage = Storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let storage = dbx_core::persistence::test_storage::open(&dir.join("storage.db")).await.unwrap();
|
||||
let app = Arc::new(AppState::new_with_plugin_dir(storage, dir.join("plugins")));
|
||||
let state = Arc::new(WebState::for_tests(app, dir.clone()));
|
||||
(state, dir)
|
||||
|
||||
Reference in new issue
Block a user