Files
endorphin-aster-vm/crates/storage/tests/storage.rs
T
codex-bot 50e8fcb5e7
Verify databases and deploy Aster VM / verify-and-deploy (push) Successful in 14m53s
Shorten crate directory names and update workspace paths
2026-10-18 19:57:21 +08:00

98 lines
3.4 KiB
Rust

use aster_storage::{Storage, StorageConfig};
#[test]
fn configuration_defaults_precedence_and_errors() {
assert!(
matches!(StorageConfig::from_values(None, None).unwrap(), StorageConfig::SqliteFile(p) if p.to_str() == Some("data/aster.db"))
);
assert!(matches!(
StorageConfig::from_values(None, Some(":memory:")).unwrap(),
StorageConfig::SqliteMemory
));
assert!(matches!(
StorageConfig::from_values(Some("postgresql://localhost/aster"), Some("")).unwrap(),
StorageConfig::Postgres(_)
));
assert!(StorageConfig::from_values(Some(""), None).is_err());
assert!(StorageConfig::from_values(Some("mysql://localhost/aster"), None).is_err());
assert!(StorageConfig::from_values(None, Some("")).is_err());
let config = StorageConfig::Postgres("postgres://user:secret@localhost/db".into());
assert!(!format!("{config:?}").contains("secret"));
}
#[tokio::test]
async fn memory_store_is_shared_by_clones_but_isolated_between_stores() {
let store = Storage::connect(&StorageConfig::SqliteMemory)
.await
.unwrap();
let other = Storage::connect(&StorageConfig::SqliteMemory)
.await
.unwrap();
store.ping().await.unwrap();
assert_eq!(store.get("missing").await.unwrap(), None);
store.put("message", "你好 ' ? $1 ;").await.unwrap();
assert_eq!(
store.clone().get("message").await.unwrap().as_deref(),
Some("你好 ' ? $1 ;")
);
assert_eq!(other.get("message").await.unwrap(), None);
store.put("message", "updated").await.unwrap();
assert_eq!(
store.get("message").await.unwrap().as_deref(),
Some("updated")
);
store.close().await;
other.close().await;
}
#[tokio::test]
async fn sqlite_file_creates_parents_and_survives_reopen() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("nested/data/metadata.db");
let config = StorageConfig::SqliteFile(path.clone());
let store = Storage::connect(&config).await.unwrap();
store.put("project", "Aster VM").await.unwrap();
store.close().await;
assert!(path.is_file());
let reopened = Storage::connect(&config).await.unwrap();
assert_eq!(
reopened.get("project").await.unwrap().as_deref(),
Some("Aster VM")
);
reopened.put("project", "v2").await.unwrap();
assert_eq!(
reopened.get("project").await.unwrap().as_deref(),
Some("v2")
);
reopened.close().await;
}
#[tokio::test]
async fn invalid_sqlite_directory_reports_error() {
let dir = tempfile::tempdir().unwrap();
let file = dir.path().join("file");
std::fs::write(&file, "occupied").unwrap();
assert!(
Storage::connect(&StorageConfig::SqliteFile(file.join("aster.db")))
.await
.is_err()
);
}
#[tokio::test]
async fn postgres_connection_failure_is_an_error() {
// Hold a TCP port without serving PostgreSQL: deterministic local failure.
let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
let url = format!(
"postgres://aster:secret@{}/aster?sslmode=disable",
listener.local_addr().unwrap()
);
let result = Storage::connect(&StorageConfig::Postgres(url)).await;
let error = match result {
Ok(_) => panic!("unreachable PostgreSQL must fail"),
Err(error) => error,
};
assert!(!error.to_string().contains("secret"));
assert!(error.to_string().contains("no fallback"));
}