-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathintegration.rs
More file actions
165 lines (128 loc) · 4.8 KB
/
Copy pathintegration.rs
File metadata and controls
165 lines (128 loc) · 4.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Copyright (c) 2026 vectorless developers
// SPDX-License-Identifier: Apache-2.0
//! Integration tests for the Engine client.
//!
//! These tests exercise the full index → persist → query lifecycle
//! without requiring a real LLM endpoint, using the no-LLM pipeline.
use std::path::PathBuf;
use vectorless::__test_support::build_test_engine;
use vectorless::{Engine, IndexContext, IndexMode};
async fn setup() -> (Engine, tempfile::TempDir) {
let tmp = tempfile::tempdir().unwrap();
let engine = build_test_engine(tmp.path()).await;
(engine, tmp)
}
#[tokio::test]
async fn test_index_and_persist_single_markdown() {
let (engine, tmp) = setup().await;
// Write a test markdown file
let md_path = tmp.path().join("test.md");
std::fs::write(&md_path, "# Hello\n\nWorld content here.").unwrap();
let ctx = IndexContext::from_path(&md_path).with_mode(IndexMode::Force);
let result = engine.index(ctx).await.unwrap();
assert_eq!(result.len(), 1);
assert!(!result.has_failures());
let doc_id = result.doc_id().unwrap();
assert!(!doc_id.is_empty());
// Verify persisted
assert!(engine.exists(doc_id).await.unwrap());
// List should contain 1 doc
let docs = engine.list().await.unwrap();
assert_eq!(docs.len(), 1);
assert_eq!(docs[0].name, "test");
// Remove
assert!(engine.remove(doc_id).await.unwrap());
assert!(!engine.exists(doc_id).await.unwrap());
}
#[tokio::test]
async fn test_index_from_content() {
let (engine, _tmp) = setup().await;
let ctx = IndexContext::from_content(
"# Title\n\nParagraph 1\n\n## Section\n\nParagraph 2",
vectorless::DocumentFormat::Markdown,
)
.with_name("inline-doc");
let result = engine.index(ctx).await.unwrap();
assert_eq!(result.len(), 1);
let doc_id = result.doc_id().unwrap();
// Verify it's persisted and loadable
assert!(engine.exists(doc_id).await.unwrap());
// Clean up
engine.remove(doc_id).await.unwrap();
}
#[tokio::test]
async fn test_index_multiple_sources_parallel() {
let (engine, tmp) = setup().await;
// Create 3 markdown files
let paths: Vec<PathBuf> = (0..3)
.map(|i| {
let p = tmp.path().join(format!("doc{i}.md"));
std::fs::write(&p, format!("# Doc {i}\n\nContent {i}")).unwrap();
p
})
.collect();
let ctx = IndexContext::from_paths(paths).with_mode(IndexMode::Force);
let result = engine.index(ctx).await.unwrap();
assert_eq!(result.len(), 3);
assert!(!result.has_failures());
let docs = engine.list().await.unwrap();
assert_eq!(docs.len(), 3);
// Clear all
let count = engine.clear().await.unwrap();
assert_eq!(count, 3);
}
#[tokio::test]
async fn test_index_default_mode_skips_existing() {
let (engine, tmp) = setup().await;
let md_path = tmp.path().join("existing.md");
std::fs::write(&md_path, "# Original\n\nOriginal content.").unwrap();
// First index
let ctx = IndexContext::from_path(&md_path);
let result1 = engine.index(ctx).await.unwrap();
assert_eq!(result1.len(), 1);
let id1 = result1.doc_id().unwrap().to_string();
// Second index with Default mode — should skip
let ctx = IndexContext::from_path(&md_path);
let result2 = engine.index(ctx).await.unwrap();
assert_eq!(result2.len(), 1);
assert!(!result2.has_failures());
// Same doc ID — not re-indexed
assert_eq!(result2.doc_id().unwrap(), id1);
}
#[tokio::test]
async fn test_force_mode_reindexes() {
let (engine, tmp) = setup().await;
let md_path = tmp.path().join("force.md");
std::fs::write(&md_path, "# Version 1").unwrap();
// First index
let ctx = IndexContext::from_path(&md_path);
let result1 = engine.index(ctx).await.unwrap();
let id1 = result1.doc_id().unwrap().to_string();
// Force re-index — should get a new doc ID
let ctx = IndexContext::from_path(&md_path).with_mode(IndexMode::Force);
let result2 = engine.index(ctx).await.unwrap();
assert_eq!(result2.len(), 1);
// Different doc ID — re-indexed
assert_ne!(result2.doc_id().unwrap(), id1);
}
#[tokio::test]
async fn test_clear_empty_workspace() {
let (engine, _tmp) = setup().await;
let count = engine.clear().await.unwrap();
assert_eq!(count, 0);
}
#[tokio::test]
async fn test_remove_nonexistent() {
let (engine, _tmp) = setup().await;
let removed = engine.remove("nonexistent-id").await.unwrap();
assert!(!removed);
}
#[tokio::test]
async fn test_index_from_bytes() {
let (engine, _tmp) = setup().await;
let ctx = IndexContext::from_bytes(vec![1, 2, 3, 4], vectorless::DocumentFormat::Pdf)
.with_name("test-bytes");
// This will fail at parse (not a real PDF), but should error gracefully
let result = engine.index(ctx).await;
assert!(result.is_err());
}