#![cfg(feature = "slow-tests")]
#[path = "migration_support/mod.rs"]
mod support;
use serial_test::serial;
use support::{conn_ro, index_exists, init_isolated_db, sgr_on, table_exists, trigger_exists};
use tempfile::TempDir;
#[test]
#[serial]
fn init_creates_16_migrations_v001_to_v016() {
let (_tmp, db_path) = init_isolated_db();
let conn = conn_ro(&db_path);
let versions: Vec<i64> = {
let mut stmt = conn
.prepare("SELECT version FROM refinery_schema_history ORDER BY version ASC")
.expect("prepare must work");
stmt.query_map([], |row| row.get(0))
.expect("query must work")
.map(|r| r.expect("row must be readable"))
.collect()
};
assert_eq!(
versions.len(),
16,
"exactly 16 migrations must be applied, found: {versions:?}"
);
assert_eq!(
versions,
vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
"expected versions V001-V016"
);
}
#[test]
#[serial]
fn trigger_trg_fts_ai_exists() {
let (_tmp, db_path) = init_isolated_db();
let conn = conn_ro(&db_path);
assert!(
trigger_exists(&conn, "trg_fts_ai"),
"trigger trg_fts_ai must exist after V004"
);
}
#[test]
#[serial]
fn trigger_trg_fts_ad_exists() {
let (_tmp, db_path) = init_isolated_db();
let conn = conn_ro(&db_path);
assert!(
trigger_exists(&conn, "trg_fts_ad"),
"trigger trg_fts_ad must exist after V004"
);
}
#[test]
#[serial]
fn trigger_trg_fts_au_absent_handled_in_rust() {
let (_tmp, db_path) = init_isolated_db();
let conn = conn_ro(&db_path);
assert!(
!trigger_exists(&conn, "trg_fts_au"),
"trigger trg_fts_au must NOT exist — FTS5 sync is handled in Rust (edit.rs, rename.rs, restore.rs)"
);
}
#[test]
#[serial]
fn memory_embeddings_blob_dim_384() {
let (_tmp, db_path) = init_isolated_db();
let conn = conn_ro(&db_path);
let ddl: String = conn
.query_row(
"SELECT sql FROM sqlite_master WHERE name = 'memory_embeddings'",
[],
|row| row.get(0),
)
.expect("memory_embeddings must exist in sqlite_master");
assert!(
ddl.contains("BLOB"),
"memory_embeddings must declare embedding as BLOB, DDL was: {ddl}"
);
assert!(
ddl.contains("dim"),
"memory_embeddings must declare a dim column, DDL was: {ddl}"
);
assert!(
ddl.contains("384"),
"memory_embeddings must default dim to 384, DDL was: {ddl}"
);
let vec_present: i64 = conn
.query_row(
"SELECT COUNT(*) FROM sqlite_master WHERE name = 'vec_memories'",
[],
|row| row.get(0),
)
.unwrap_or(1);
assert_eq!(
vec_present, 0,
"vec_memories must NOT exist after V013, but it is still present"
);
}
#[test]
#[serial]
fn memory_embeddings_partition_indexes() {
let (_tmp, db_path) = init_isolated_db();
let conn = conn_ro(&db_path);
let has_ns_index: i64 = conn
.query_row(
"SELECT COUNT(*) FROM sqlite_master WHERE name = 'idx_memory_embeddings_ns'",
[],
|row| row.get(0),
)
.unwrap_or(0);
assert_eq!(
has_ns_index, 1,
"idx_memory_embeddings_ns must exist (namespace partition)"
);
let has_source_index: i64 = conn
.query_row(
"SELECT COUNT(*) FROM sqlite_master WHERE name = 'idx_memory_embeddings_source'",
[],
|row| row.get(0),
)
.unwrap_or(0);
assert_eq!(
has_source_index, 1,
"idx_memory_embeddings_source must exist (source partition)"
);
}
#[test]
#[serial]
fn fts_memories_tokenizer_unicode61_remove_diacritics() {
let (_tmp, db_path) = init_isolated_db();
let conn = conn_ro(&db_path);
let ddl: String = conn
.query_row(
"SELECT sql FROM sqlite_master WHERE name = 'fts_memories'",
[],
|row| row.get(0),
)
.expect("fts_memories must exist in sqlite_master");
assert!(
ddl.contains("unicode61"),
"fts_memories must use the unicode61 tokenizer, DDL: {ddl}"
);
assert!(
ddl.contains("remove_diacritics"),
"fts_memories must declare remove_diacritics, DDL: {ddl}"
);
}
#[test]
#[serial]
fn fts5_matching_with_accents_cafe_cafe() {
let tmp = TempDir::new().expect("TempDir must be created");
let db_path = tmp.path().join("test.sqlite");
sgr_on(&tmp, &db_path).args(["init"]).assert().success();
sgr_on(&tmp, &db_path)
.args([
"remember",
"--name",
"nota-cafe",
"--type",
"user",
"--description",
"note about café",
"--body",
"Brazilian café is famous worldwide for its quality",
])
.assert()
.success();
let conn = conn_ro(&db_path);
let count: i64 = conn
.query_row(
"SELECT COUNT(*) FROM fts_memories WHERE fts_memories MATCH 'cafe'",
[],
|row| row.get(0),
)
.expect("FTS5 query must work");
assert!(
count >= 1,
"FTS5 with remove_diacritics must match 'café' when searching 'cafe', count={count}"
);
}
#[test]
#[serial]
fn all_main_tables_exist_after_init() {
let (_tmp, db_path) = init_isolated_db();
let conn = conn_ro(&db_path);
let tables = [
"schema_meta",
"memories",
"memory_versions",
"memory_chunks",
"entities",
"relationships",
"memory_entities",
"memory_relationships",
"fts_memories",
];
for name in tables {
assert!(
table_exists(&conn, name),
"table '{name}' must exist after init"
);
}
}
#[test]
#[serial]
fn main_indexes_exist_after_init() {
let (_tmp, db_path) = init_isolated_db();
let conn = conn_ro(&db_path);
let indexes = [
"idx_memories_ns_type",
"idx_memories_ns_live",
"idx_memories_body_hash",
"idx_entities_ns",
"idx_me_entity",
"idx_relationships_source",
"idx_relationships_target",
"idx_relationships_ns",
"idx_relationships_ns_relation",
"idx_entities_namespace_degree",
"idx_memory_chunks_memory_id",
"idx_memory_relationships_relationship_id",
];
for name in indexes {
assert!(
index_exists(&conn, name),
"index '{name}' must exist after init"
);
}
}
#[test]
#[serial]
fn schema_meta_required_keys_exist() {
let (_tmp, db_path) = init_isolated_db();
let conn = conn_ro(&db_path);
let expected_keys = [
"schema_version",
"model",
"dim",
"created_at",
"namespace_initial",
];
for key in expected_keys {
let count: i64 = conn
.query_row(
"SELECT COUNT(*) FROM schema_meta WHERE key = ?1",
rusqlite::params![key],
|row| row.get(0),
)
.expect("schema_meta query must work");
assert!(count > 0, "schema_meta must contain key '{key}' after init");
}
}
#[test]
#[serial]
fn schema_version_meta_equals_16() {
let (_tmp, db_path) = init_isolated_db();
let conn = conn_ro(&db_path);
let version: String = conn
.query_row(
"SELECT value FROM schema_meta WHERE key = 'schema_version'",
[],
|row| row.get(0),
)
.expect("schema_version must exist in schema_meta");
assert_eq!(
version, "16",
"schema_version in schema_meta must be '16' after V016"
);
}