@@ -374,3 +374,137 @@ impl MemoryStorePort for SqliteMemoryStore {
374374 Ok ( hits)
375375 }
376376}
377+
378+ #[ cfg( test) ]
379+ mod tests {
380+ use alice_core:: memory:: domain:: { HybridWeights , MemoryEntry , MemoryImportance , RecallQuery } ;
381+ use tempfile:: NamedTempFile ;
382+
383+ use super :: * ;
384+
385+ fn create_temp_db ( ) -> SqliteMemoryStore {
386+ let temp_file = NamedTempFile :: new ( ) . unwrap ( ) ;
387+ let path = temp_file. path ( ) ;
388+ SqliteMemoryStore :: open ( path, 384 , true ) . unwrap ( )
389+ }
390+
391+ #[ test]
392+ fn open_creates_schema ( ) {
393+ let store = create_temp_db ( ) ;
394+ // Should not panic - schema creation should work
395+ let conn = store. conn . lock ( ) ;
396+ let count: i64 = conn
397+ . query_row ( "SELECT COUNT(*) FROM sqlite_master WHERE type='table'" , [ ] , |row| {
398+ row. get ( 0 )
399+ } )
400+ . unwrap ( ) ;
401+ assert ! ( count > 0 , "schema should be created" ) ;
402+ }
403+
404+ #[ test]
405+ fn insert_and_recall_memory ( ) {
406+ let store = create_temp_db ( ) ;
407+ let entry = MemoryEntry {
408+ id : "test-id" . to_string ( ) ,
409+ session_id : "test-session" . to_string ( ) ,
410+ topic : "test topic" . to_string ( ) ,
411+ summary : "test summary" . to_string ( ) ,
412+ raw_excerpt : "The quick brown fox jumps over the lazy dog" . to_string ( ) ,
413+ keywords : vec ! [ "test" . to_string( ) , "fox" . to_string( ) ] ,
414+ importance : MemoryImportance :: Medium ,
415+ embedding : Some ( vec ! [ 0.1 , 0.2 , 0.3 ] ) ,
416+ created_at_epoch_ms : 1234567890 ,
417+ } ;
418+
419+ // Store the entry
420+ store. insert ( & entry) . unwrap ( ) ;
421+
422+ // Recall using hybrid search
423+ let query = RecallQuery {
424+ session_id : Some ( "test-session" . to_string ( ) ) ,
425+ text : "fox" . to_string ( ) ,
426+ query_embedding : None ,
427+ limit : 10 ,
428+ } ;
429+
430+ let hits = store. recall_hybrid ( & query, HybridWeights :: default ( ) ) . unwrap ( ) ;
431+ assert_eq ! ( hits. len( ) , 1 ) ;
432+ assert_eq ! ( hits[ 0 ] . entry. id, entry. id) ;
433+ assert_eq ! ( hits[ 0 ] . entry. raw_excerpt, entry. raw_excerpt) ;
434+ }
435+
436+ #[ test]
437+ fn recall_with_different_queries ( ) {
438+ let store = create_temp_db ( ) ;
439+ let entry1 = MemoryEntry {
440+ id : "test-1" . to_string ( ) ,
441+ session_id : "test-session" . to_string ( ) ,
442+ topic : "fox story" . to_string ( ) ,
443+ summary : "A story about a fox" . to_string ( ) ,
444+ raw_excerpt : "The quick brown fox jumps over the lazy dog" . to_string ( ) ,
445+ keywords : vec ! [ "fox" . to_string( ) , "dog" . to_string( ) ] ,
446+ importance : MemoryImportance :: High ,
447+ embedding : None ,
448+ created_at_epoch_ms : 1234567890 ,
449+ } ;
450+ let entry2 = MemoryEntry {
451+ id : "test-2" . to_string ( ) ,
452+ session_id : "test-session" . to_string ( ) ,
453+ topic : "cat story" . to_string ( ) ,
454+ summary : "A story about cats" . to_string ( ) ,
455+ raw_excerpt : "A completely different story about cats" . to_string ( ) ,
456+ keywords : vec ! [ "cat" . to_string( ) ] ,
457+ importance : MemoryImportance :: Medium ,
458+ embedding : None ,
459+ created_at_epoch_ms : 1234567891 ,
460+ } ;
461+
462+ store. insert ( & entry1) . unwrap ( ) ;
463+ store. insert ( & entry2) . unwrap ( ) ;
464+
465+ let query = RecallQuery {
466+ session_id : Some ( "test-session" . to_string ( ) ) ,
467+ text : "fox" . to_string ( ) ,
468+ query_embedding : None ,
469+ limit : 10 ,
470+ } ;
471+
472+ let hits = store. recall_hybrid ( & query, HybridWeights :: default ( ) ) . unwrap ( ) ;
473+ assert_eq ! ( hits. len( ) , 1 ) ;
474+ assert_eq ! ( hits[ 0 ] . entry. id, "test-1" ) ;
475+ }
476+
477+ #[ test]
478+ fn vector_disabled_fallback ( ) {
479+ let temp_path =
480+ std:: env:: temp_dir ( ) . join ( format ! ( "alice-test-vector-{}.db" , std:: process:: id( ) ) ) ;
481+ let store = SqliteMemoryStore :: open ( & temp_path, 384 , false ) . unwrap ( ) ;
482+
483+ let entry = MemoryEntry {
484+ id : "test-vector-disabled" . to_string ( ) ,
485+ session_id : "test-session" . to_string ( ) ,
486+ topic : "vector test" . to_string ( ) ,
487+ summary : "test content" . to_string ( ) ,
488+ raw_excerpt : "test content" . to_string ( ) ,
489+ keywords : vec ! [ "test" . to_string( ) ] ,
490+ importance : MemoryImportance :: Medium ,
491+ embedding : Some ( vec ! [ 0.1 , 0.2 , 0.3 ] ) , // Embedding provided but vector disabled
492+ created_at_epoch_ms : 1234567890 ,
493+ } ;
494+
495+ // Should store successfully even with embedding when vector is disabled
496+ store. insert ( & entry) . unwrap ( ) ;
497+
498+ // Test recall still works with FTS only
499+ let query = RecallQuery {
500+ session_id : Some ( "test-session" . to_string ( ) ) ,
501+ text : "test" . to_string ( ) ,
502+ query_embedding : None ,
503+ limit : 10 ,
504+ } ;
505+
506+ let hits = store. recall_hybrid ( & query, HybridWeights :: default ( ) ) . unwrap ( ) ;
507+ assert_eq ! ( hits. len( ) , 1 ) ;
508+ assert_eq ! ( hits[ 0 ] . entry. id, "test-vector-disabled" ) ;
509+ }
510+ }
0 commit comments