89 lines
3.1 KiB
Rust
89 lines
3.1 KiB
Rust
//! Regression tests for replay segment persistence/integrity.
|
|
//!
|
|
//! The replay segment is written to the `.mv2` file when ending a recording session.
|
|
//! Historically this could corrupt Tantivy (lexical) segments by writing replay bytes
|
|
//! at an incorrect offset and moving the TOC footer backwards.
|
|
|
|
#[cfg(all(feature = "lex", feature = "replay"))]
|
|
use memvid_core::{Memvid, PutOptions, SearchRequest};
|
|
#[cfg(all(feature = "lex", feature = "replay"))]
|
|
use tempfile::TempDir;
|
|
|
|
#[test]
|
|
#[cfg(all(feature = "lex", feature = "replay"))]
|
|
fn replay_save_does_not_corrupt_lex_index() {
|
|
let dir = TempDir::new().unwrap();
|
|
let path = dir.path().join("replay_integrity.mv2");
|
|
|
|
// Create a memory with a Tantivy-backed lexical index.
|
|
{
|
|
let mut mem = Memvid::create(&path).unwrap();
|
|
mem.enable_lex().unwrap();
|
|
|
|
let opts = PutOptions {
|
|
uri: Some("mv2://doc/0".to_string()),
|
|
title: Some("Doc".to_string()),
|
|
search_text: Some("Climate change and sustainability are important.".to_string()),
|
|
..Default::default()
|
|
};
|
|
mem.put_bytes_with_options(b"climate", opts).unwrap();
|
|
mem.commit().unwrap();
|
|
|
|
// Record a session that includes a FIND action.
|
|
mem.start_session(Some("Test".to_string()), None).unwrap();
|
|
let _ = mem
|
|
.search(SearchRequest {
|
|
query: "climate".to_string(),
|
|
top_k: 5,
|
|
snippet_chars: 120,
|
|
uri: None,
|
|
scope: None,
|
|
cursor: None,
|
|
#[cfg(feature = "temporal_track")]
|
|
temporal: None,
|
|
as_of_frame: None,
|
|
as_of_ts: None,
|
|
no_sketch: false,
|
|
acl_context: None,
|
|
acl_enforcement_mode: memvid_core::types::AclEnforcementMode::Audit,
|
|
})
|
|
.unwrap();
|
|
mem.end_session().unwrap();
|
|
|
|
// Mirror CLI behaviour: finalize, save replay, then commit again.
|
|
mem.commit().unwrap();
|
|
mem.save_replay_sessions().unwrap();
|
|
mem.commit().unwrap();
|
|
}
|
|
|
|
// Reopen and ensure Tantivy loads and lexical search still works.
|
|
let mut reopened = Memvid::open_read_only(&path).unwrap();
|
|
let results = reopened
|
|
.search(SearchRequest {
|
|
query: "climate".to_string(),
|
|
top_k: 5,
|
|
snippet_chars: 120,
|
|
uri: None,
|
|
scope: None,
|
|
cursor: None,
|
|
#[cfg(feature = "temporal_track")]
|
|
temporal: None,
|
|
as_of_frame: None,
|
|
as_of_ts: None,
|
|
no_sketch: false,
|
|
acl_context: None,
|
|
acl_enforcement_mode: memvid_core::types::AclEnforcementMode::Audit,
|
|
})
|
|
.unwrap();
|
|
|
|
assert!(
|
|
!results.hits.is_empty(),
|
|
"expected lexical search to work after saving replay sessions"
|
|
);
|
|
|
|
// Also ensure replay sessions can be loaded (read-only is fine).
|
|
reopened.load_replay_sessions().unwrap();
|
|
let sessions = reopened.list_sessions();
|
|
assert_eq!(sessions.len(), 1, "expected one recorded replay session");
|
|
}
|