@@ -16,162 +16,14 @@ async fn open_db() -> NodeDbLite<RedbStorage> {
1616// ═══════════════════════════════════════════════════════════════════════
1717// 6.1 Standalone Lite (No Origin)
1818// ═══════════════════════════════════════════════════════════════════════
19-
20- /// Correctness-only counterpart of the 1k×384d HNSW workload.
21- /// The full-scale build/search is a benchmark — see
22- /// `nodedb-bench/benches/micro/lite_vector.rs`.
23- #[ tokio:: test]
24- async fn e2e_vector_search_returns_sorted_top_k ( ) {
25- let db = open_db ( ) . await ;
26- let dim = 32 ;
27- let n = 50 ;
28-
29- let vectors: Vec < ( String , Vec < f32 > ) > = ( 0 ..n)
30- . map ( |i| {
31- let emb: Vec < f32 > = ( 0 ..dim) . map ( |d| ( ( i * dim + d) as f32 ) . sin ( ) ) . collect ( ) ;
32- ( format ! ( "v{i}" ) , emb)
33- } )
34- . collect ( ) ;
35- let refs: Vec < ( & str , & [ f32 ] ) > = vectors
36- . iter ( )
37- . map ( |( id, e) | ( id. as_str ( ) , e. as_slice ( ) ) )
38- . collect ( ) ;
39- db. batch_vector_insert ( "kb" , & refs) . unwrap ( ) ;
40-
41- let query: Vec < f32 > = ( 0 ..dim) . map ( |d| ( ( 25 * dim + d) as f32 ) . sin ( ) ) . collect ( ) ;
42- let results = db. vector_search ( "kb" , & query, 5 , None ) . await . unwrap ( ) ;
43-
44- assert_eq ! ( results. len( ) , 5 ) ;
45- for w in results. windows ( 2 ) {
46- assert ! ( w[ 0 ] . distance <= w[ 1 ] . distance) ;
47- }
48- assert ! (
49- results[ 0 ] . distance < 1.0 ,
50- "top result distance {} too large" ,
51- results[ 0 ] . distance
52- ) ;
53- }
54-
55- /// Correctness-only counterpart of the 10k-edge graph workload.
56- /// Scale benchmark lives in `nodedb-bench/benches/micro/lite_graph.rs`.
57- #[ tokio:: test]
58- async fn e2e_graph_bfs_reaches_multiple_hops ( ) {
59- let db = open_db ( ) . await ;
60-
61- // Small graph: 50 nodes, 4 edges each = 200 edges. Enough for 3-hop BFS
62- // to visit several nodes; cheap enough for default `cargo nextest run`.
63- let mut edges: Vec < ( String , String , & str ) > = Vec :: with_capacity ( 200 ) ;
64- for i in 0 ..50 {
65- for j in 1 ..=4 {
66- let dst = ( i + j * 7 ) % 50 ;
67- edges. push ( ( format ! ( "n{i}" ) , format ! ( "n{dst}" ) , "LINK" ) ) ;
68- }
69- }
70- let refs: Vec < ( & str , & str , & str ) > = edges
71- . iter ( )
72- . map ( |( s, d, l) | ( s. as_str ( ) , d. as_str ( ) , * l) )
73- . collect ( ) ;
74- db. batch_graph_insert_edges ( & refs) . unwrap ( ) ;
75- db. compact_graph ( ) . unwrap ( ) ;
76-
77- let sg = db
78- . graph_traverse ( & NodeId :: new ( "n0" ) , 3 , None )
79- . await
80- . unwrap ( ) ;
81- assert ! (
82- sg. node_count( ) > 5 ,
83- "3-hop BFS should reach multiple nodes, found {}" ,
84- sg. node_count( )
85- ) ;
86- assert ! (
87- sg. edge_count( ) > 0 ,
88- "should have edges, found {}" ,
89- sg. edge_count( )
90- ) ;
91- }
92-
93- #[ tokio:: test]
94- async fn e2e_document_crud_lifecycle ( ) {
95- let db = open_db ( ) . await ;
96-
97- // Create.
98- for i in 0 ..50 {
99- let mut doc = Document :: new ( format ! ( "doc-{i}" ) ) ;
100- doc. set ( "title" , Value :: String ( format ! ( "Title {i}" ) ) ) ;
101- doc. set ( "score" , Value :: Float ( i as f64 * 0.1 ) ) ;
102- db. document_put ( "notes" , doc) . await . unwrap ( ) ;
103- }
104-
105- // Read.
106- let doc = db. document_get ( "notes" , "doc-25" ) . await . unwrap ( ) . unwrap ( ) ;
107- assert_eq ! ( doc. id, "doc-25" ) ;
108- assert_eq ! ( doc. get_str( "title" ) , Some ( "Title 25" ) ) ;
109-
110- // Update.
111- let mut updated = Document :: new ( "doc-25" ) ;
112- updated. set ( "title" , Value :: String ( "Updated" . into ( ) ) ) ;
113- db. document_put ( "notes" , updated) . await . unwrap ( ) ;
114- let doc = db. document_get ( "notes" , "doc-25" ) . await . unwrap ( ) . unwrap ( ) ;
115- assert_eq ! ( doc. get_str( "title" ) , Some ( "Updated" ) ) ;
116-
117- // Delete.
118- db. document_delete ( "notes" , "doc-25" ) . await . unwrap ( ) ;
119- assert ! ( db. document_get( "notes" , "doc-25" ) . await . unwrap( ) . is_none( ) ) ;
120-
121- // Neighbors survive.
122- assert ! ( db. document_get( "notes" , "doc-24" ) . await . unwrap( ) . is_some( ) ) ;
123- assert ! ( db. document_get( "notes" , "doc-26" ) . await . unwrap( ) . is_some( ) ) ;
124- }
125-
126- #[ tokio:: test]
127- async fn e2e_flush_reopen_all_data_survives ( ) {
128- let dir = tempfile:: tempdir ( ) . unwrap ( ) ;
129- let path = dir. path ( ) . join ( "e2e.redb" ) ;
130-
131- // Write data + flush.
132- {
133- let storage = RedbStorage :: open ( & path) . unwrap ( ) ;
134- let db = NodeDbLite :: open ( storage, 1 ) . await . unwrap ( ) ;
135-
136- db. batch_vector_insert (
137- "vecs" ,
138- & [ ( "v1" , & [ 1.0f32 , 2.0 , 3.0 ] [ ..] ) , ( "v2" , & [ 4.0 , 5.0 , 6.0 ] ) ] ,
139- )
140- . unwrap ( ) ;
141- db. batch_graph_insert_edges ( & [ ( "a" , "b" , "KNOWS" ) , ( "b" , "c" , "KNOWS" ) ] )
142- . unwrap ( ) ;
143- let mut doc = Document :: new ( "d1" ) ;
144- doc. set ( "key" , Value :: String ( "persistent" . into ( ) ) ) ;
145- db. document_put ( "docs" , doc) . await . unwrap ( ) ;
146-
147- db. flush ( ) . await . unwrap ( ) ;
148- }
149-
150- // Reopen + verify.
151- {
152- let storage = RedbStorage :: open ( & path) . unwrap ( ) ;
153- let db = NodeDbLite :: open ( storage, 1 ) . await . unwrap ( ) ;
154-
155- // Vectors.
156- let results = db
157- . vector_search ( "vecs" , & [ 1.0 , 2.0 , 3.0 ] , 1 , None )
158- . await
159- . unwrap ( ) ;
160- assert ! ( !results. is_empty( ) , "vectors should survive restart" ) ;
161-
162- // Graph.
163- let sg = db. graph_traverse ( & NodeId :: new ( "a" ) , 2 , None ) . await . unwrap ( ) ;
164- assert ! ( sg. node_count( ) >= 3 , "graph should survive restart" ) ;
165-
166- // Document.
167- let doc = db. document_get ( "docs" , "d1" ) . await . unwrap ( ) ;
168- assert ! ( doc. is_some( ) , "document should survive restart" ) ;
169- }
170- }
171-
172- // `e2e_cold_start_timing` was migrated to a benchmark — it asserted only
173- // wall-clock time, no correctness. See:
174- // nodedb-bench/benches/workload/lite_cold_start.rs
19+ //
20+ // Vector search, graph BFS, document CRUD, and flush/reopen correctness
21+ // are covered by the equivalent tests in `integration.rs`
22+ // (`vector_batch_insert_and_search_correctness`,
23+ // `graph_batch_and_traverse_correctness`, `document_crud_100`,
24+ // `flush_and_reopen_persists_all`). Only Lite-specific concerns
25+ // (memory budget, CRDT convergence, compensation, delta ack, native
26+ // smoke) live in this file.
17527
17628#[ tokio:: test]
17729async fn e2e_memory_stays_within_budget ( ) {
0 commit comments