use rusqlite::Connection;
use sqlitegraph::schema::ensure_schema;
use sqlitegraph::{
SqliteGraph,
graph_opt::{GraphEntityCreate, bulk_insert_entities},
};
#[test]
fn test_default_connection_no_wal() {
let conn = Connection::open_in_memory().unwrap();
ensure_schema(&conn).unwrap();
let journal_mode: String = conn
.prepare("PRAGMA journal_mode")
.unwrap()
.query_row([], |row| row.get(0))
.unwrap();
assert_eq!(journal_mode, "memory");
let temp_store: i64 = conn
.prepare("PRAGMA temp_store")
.unwrap()
.query_row([], |row| row.get(0))
.unwrap();
assert_eq!(temp_store, 0);
let cache_size: i64 = conn
.prepare("PRAGMA cache_size")
.unwrap()
.query_row([], |row| row.get(0))
.unwrap();
assert_eq!(cache_size, -2000); }
#[test]
fn test_wal_mode_activation() {
let conn = Connection::open_in_memory().unwrap();
let journal_mode: String = conn
.prepare("PRAGMA journal_mode=WAL")
.unwrap()
.query_row([], |row| row.get(0))
.unwrap();
assert_eq!(journal_mode, "memory");
let foreign_keys: i64 = conn
.prepare("PRAGMA foreign_keys")
.unwrap()
.query_row([], |row| row.get(0))
.unwrap();
assert_eq!(foreign_keys, 1);
}
#[test]
fn test_performance_pragmas_configuration() {
let conn = Connection::open_in_memory().unwrap();
let default_cache_size: i64 = conn
.prepare("PRAGMA cache_size")
.unwrap()
.query_row([], |row| row.get(0))
.unwrap();
assert_eq!(default_cache_size, -2000);
conn.execute("PRAGMA cache_size=-64000", []).unwrap();
let new_cache_size: i64 = conn
.prepare("PRAGMA cache_size")
.unwrap()
.query_row([], |row| row.get(0))
.unwrap();
assert_eq!(new_cache_size, -64000);
conn.execute("PRAGMA temp_store=MEMORY", []).unwrap();
let temp_store: i64 = conn
.prepare("PRAGMA temp_store")
.unwrap()
.query_row([], |row| row.get(0))
.unwrap();
assert_eq!(temp_store, 2);
conn.execute("PRAGMA synchronous=NORMAL", []).unwrap();
let synchronous: i64 = conn
.prepare("PRAGMA synchronous")
.unwrap()
.query_row([], |row| row.get(0))
.unwrap();
assert_eq!(synchronous, 1); }
#[test]
fn test_prepared_statement_cache_with_wal() {
let conn = Connection::open_in_memory().unwrap();
conn.set_prepared_statement_cache_capacity(128);
let mut stmt = conn.prepare_cached("SELECT 1 as test_col").unwrap();
let result: i64 = stmt.query_row([], |row| row.get(0)).unwrap();
assert_eq!(result, 1);
let mut stmt2 = conn.prepare_cached("SELECT 1 as test_col").unwrap();
let result2: i64 = stmt2.query_row([], |row| row.get(0)).unwrap();
assert_eq!(result2, 1);
}
#[test]
fn test_wal_checkpoint_operation() {
let conn = Connection::open_in_memory().unwrap();
conn.execute("CREATE TABLE test (id INTEGER, data TEXT)", [])
.unwrap();
for i in 0..100 {
conn.execute(
"INSERT INTO test (id, data) VALUES (?1, ?2)",
rusqlite::params![i, format!("data_{}", i)],
)
.unwrap();
}
}
#[test]
fn test_transaction_rollback_on_error() {
let graph = SqliteGraph::open_in_memory().unwrap();
let entity = GraphEntityCreate {
kind: "test".to_string(),
name: "initial".to_string(),
file_path: None,
data: serde_json::json!({"value": "initial"}),
};
let initial_id = bulk_insert_entities(&graph, &[entity]).unwrap();
assert_eq!(initial_id.len(), 1);
let initial_entity = graph.get_entity(initial_id[0]).unwrap();
assert_eq!(initial_entity.name, "initial");
let valid_entities = vec![
GraphEntityCreate {
kind: "test".to_string(),
name: "valid1".to_string(),
file_path: None,
data: serde_json::json!({"value": "valid1"}),
},
GraphEntityCreate {
kind: "".to_string(), name: "invalid".to_string(),
file_path: None,
data: serde_json::json!({"value": "invalid"}),
},
GraphEntityCreate {
kind: "test".to_string(),
name: "valid2".to_string(),
file_path: None,
data: serde_json::json!({"value": "valid2"}),
},
];
let result = bulk_insert_entities(&graph, &valid_entities);
assert!(result.is_err());
let all_ids = graph.list_entity_ids().unwrap();
assert_eq!(all_ids.len(), 1); assert_eq!(all_ids[0], initial_id[0]);
}
#[test]
fn test_manual_transaction_rollback() {
let conn = Connection::open_in_memory().unwrap();
ensure_schema(&conn).unwrap();
conn.execute("BEGIN IMMEDIATE", []).unwrap();
conn.execute(
"INSERT INTO graph_entities(kind, name, data) VALUES (?1, ?2, ?3)",
["test", "temp", "{}"],
)
.unwrap();
let count: i64 = conn
.prepare("SELECT COUNT(*) FROM graph_entities WHERE name = 'temp'")
.unwrap()
.query_row([], |row| row.get(0))
.unwrap();
assert_eq!(count, 1);
conn.execute("ROLLBACK", []).unwrap();
let count_after: i64 = conn
.prepare("SELECT COUNT(*) FROM graph_entities WHERE name = 'temp'")
.unwrap()
.query_row([], |row| row.get(0))
.unwrap();
assert_eq!(count_after, 0);
}
#[test]
fn test_transaction_commit_persistence() {
let conn = Connection::open_in_memory().unwrap();
ensure_schema(&conn).unwrap();
conn.execute("BEGIN IMMEDIATE", []).unwrap();
conn.execute(
"INSERT INTO graph_entities(kind, name, data) VALUES (?1, ?2, ?3)",
["test", "persistent", "{}"],
)
.unwrap();
conn.execute("COMMIT", []).unwrap();
let count: i64 = conn
.prepare("SELECT COUNT(*) FROM graph_entities WHERE name = 'persistent'")
.unwrap()
.query_row([], |row| row.get(0))
.unwrap();
assert_eq!(count, 1);
conn.execute("BEGIN IMMEDIATE", []).unwrap();
let count_in_new_tx: i64 = conn
.prepare("SELECT COUNT(*) FROM graph_entities WHERE name = 'persistent'")
.unwrap()
.query_row([], |row| row.get(0))
.unwrap();
assert_eq!(count_in_new_tx, 1);
conn.execute("COMMIT", []).unwrap();
}
#[test]
fn test_prepared_statement_caching_verification() {
let graph = SqliteGraph::open_in_memory().unwrap();
let initial_snapshot = graph.metrics_snapshot();
for _i in 0..10 {
let _ = graph.get_entity(1); }
let final_snapshot = graph.metrics_snapshot();
assert!(final_snapshot.prepare_cache_hits >= initial_snapshot.prepare_cache_hits);
assert!(final_snapshot.prepare_count >= initial_snapshot.prepare_count);
}
#[test]
fn test_batch_size_limits() {
let graph = SqliteGraph::open_in_memory().unwrap();
let mut large_batch = Vec::new();
for i in 0..1500 {
large_batch.push(GraphEntityCreate {
kind: "test".to_string(),
name: format!("entity_{}", i),
file_path: None,
data: serde_json::json!({"id": i}),
});
}
let result = bulk_insert_entities(&graph, &large_batch);
assert!(result.is_ok());
let ids = result.unwrap();
assert_eq!(ids.len(), 1500);
let all_ids = graph.list_entity_ids().unwrap();
assert_eq!(all_ids.len(), 1500);
}
#[test]
fn test_concurrent_read_isolation() {
let graph = SqliteGraph::open_in_memory().unwrap();
let entity = GraphEntityCreate {
kind: "test".to_string(),
name: "concurrent_test".to_string(),
file_path: None,
data: serde_json::json!({"value": "initial"}),
};
let entity_id = bulk_insert_entities(&graph, &[entity]).unwrap()[0];
let initial_entity = graph.get_entity(entity_id).unwrap();
assert_eq!(initial_entity.name, "concurrent_test");
let mut updated_entity = graph.get_entity(entity_id).unwrap();
updated_entity.name = "modified".to_string();
graph.update_entity(&updated_entity).unwrap();
let final_entity = graph.get_entity(entity_id).unwrap();
assert_eq!(final_entity.name, "modified");
}