Repository navigation
Expand file tree
/
Copy pathtest_import.cpp
More file actions
198 lines (177 loc) · 7.16 KB
/
Copy pathtest_import.cpp
File metadata and controls
198 lines (177 loc) · 7.16 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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/**
* Import chunking tests
*/
#include "import.h"
#include <cassert>
#include <iostream>
#include <print>
using ragger::heading_level;
using ragger::heading_text;
using ragger::chunk_markdown;
// -----------------------------------------------------------------------
// heading_level tests
// -----------------------------------------------------------------------
void test_heading_levels() {
assert(heading_level("# Title") == 1);
assert(heading_level("## Subtitle") == 2);
assert(heading_level("### Level 3") == 3);
assert(heading_level("###### Level 6") == 6);
assert(heading_level("Not a heading") == 0);
assert(heading_level("") == 0);
assert(heading_level("#NoSpace") == 0); // No space after #
assert(heading_level("##NoSpace") == 0);
}
void test_heading_text_extraction() {
assert(heading_text("# Title") == "Title");
assert(heading_text("## Sub Title") == "Sub Title");
assert(heading_text("### Multi Word Heading") == "Multi Word Heading");
}
// -----------------------------------------------------------------------
// chunk_markdown tests
// -----------------------------------------------------------------------
void test_empty_input() {
auto chunks = chunk_markdown("", 300);
assert(chunks.empty());
}
void test_no_headings() {
std::string text = "This is a paragraph of text without any headings.\n\n"
"This is another paragraph that should be merged.";
auto chunks = chunk_markdown(text, 300);
// Both paragraphs are short, should merge into one chunk
assert(chunks.size() == 1);
assert(chunks[0].section.empty());
}
void test_single_heading_with_content() {
std::string text = "# My Document\n\n"
"This is the content under the heading. "
"It has enough text to be meaningful.";
auto chunks = chunk_markdown(text, 10);
assert(!chunks.empty());
// First chunk should include the heading
assert(chunks[0].text.find("# My Document") != std::string::npos);
assert(chunks[0].section == "My Document");
}
void test_multiple_headings() {
std::string text = "# Chapter One\n\n"
"Content for chapter one goes here with plenty of words to exceed the minimum chunk size easily.\n\n"
"# Chapter Two\n\n"
"Content for chapter two goes here with plenty of words to exceed the minimum chunk size easily.\n\n"
"# Chapter Three\n\n"
"Content for chapter three.";
auto chunks = chunk_markdown(text, 50);
assert(chunks.size() >= 2); // Should split on headings
}
void test_nested_headings() {
std::string text = "# Title\n\n"
"## Section A\n\n"
"Content A with enough text to be a real chunk by itself when needed.\n\n"
"## Section B\n\n"
"Content B with enough text to be a real chunk by itself when needed.\n\n"
"### Subsection B1\n\n"
"Content B1 details.";
auto chunks = chunk_markdown(text, 30);
// Check section breadcrumbs
bool found_nested = false;
for (auto& c : chunks) {
if (c.section.find("\xC2\xBB") != std::string::npos) {
found_nested = true; // Found a "»" separator = nested section
}
}
assert(found_nested);
}
void test_heading_level_reset() {
// When a same-or-higher level heading appears, the stack should pop
std::string text = "# A\n\n## A1\n\nContent A1.\n\n# B\n\nContent B.";
auto chunks = chunk_markdown(text, 10);
// The "B" chunk should NOT have "A" in its section
bool b_clean = false;
for (auto& c : chunks) {
if (c.text.find("Content B") != std::string::npos) {
assert(c.section.find("A1") == std::string::npos);
b_clean = true;
}
}
assert(b_clean);
}
void test_minimum_chunk_size_merging() {
std::string text = "# Title\n\nShort.\n\nAlso short.\n\nStill short.";
// With high min_chunk_size, everything should merge
auto chunks = chunk_markdown(text, 1000);
assert(chunks.size() == 1);
}
void test_minimum_chunk_size_splitting() {
std::string text = "# Title\n\n";
// Add enough content to exceed min_chunk_size
for (int i = 0; i < 20; ++i) {
text += "Paragraph number " + std::to_string(i) + " with some filler text to bulk it up.\n\n";
}
auto chunks = chunk_markdown(text, 50);
assert(chunks.size() > 1);
}
void test_base64_stripping() {
std::string text = "# Doc\n\n"
"Some text before image.\n\n"
"\n\n"
"Some text after image.";
auto chunks = chunk_markdown(text, 10);
// base64 data should be stripped
for (auto& c : chunks) {
assert(c.text.find("base64") == std::string::npos);
}
}
void test_whitespace_collapsing() {
std::string text = "# Title\n\n"
"Text with multiple spaces.\n\n\n\n\n"
"After many blank lines.";
auto chunks = chunk_markdown(text, 10);
// Multiple spaces collapsed, excessive newlines collapsed
for (auto& c : chunks) {
assert(c.text.find(" ") == std::string::npos ||
c.text.find(" ") == std::string::npos); // some tolerance
}
}
void test_tiny_file() {
std::string text = "Hi.";
auto chunks = chunk_markdown(text, 300);
assert(chunks.size() == 1);
assert(chunks[0].text == "Hi.");
}
// -----------------------------------------------------------------------
// clean_document_text tests
// -----------------------------------------------------------------------
void test_clean_document_text() {
using ragger::clean_document_text;
assert(clean_document_text("## Heading") == "Heading");
assert(clean_document_text(" ### Sub ") == "Sub");
assert(clean_document_text("#") == "");
assert(clean_document_text(" # ") == "");
assert(clean_document_text("No markup here") == "No markup here");
assert(clean_document_text(" leading spaces") == "leading spaces");
assert(clean_document_text("trailing spaces ") == "trailing spaces");
assert(clean_document_text("line1\n## line2\nline3 \n") ==
"line1\nline2\nline3");
assert(clean_document_text("###No space heading") == "No space heading");
assert(clean_document_text("mid # hash stays") == "mid # hash stays");
assert(clean_document_text("line1\r\n## line2\r\n") == "line1\nline2");
}
// -----------------------------------------------------------------------
// Main
// -----------------------------------------------------------------------
int main() {
test_heading_levels();
test_heading_text_extraction();
test_empty_input();
test_no_headings();
test_single_heading_with_content();
test_multiple_headings();
test_nested_headings();
test_heading_level_reset();
test_minimum_chunk_size_merging();
test_minimum_chunk_size_splitting();
test_base64_stripping();
test_whitespace_collapsing();
test_tiny_file();
test_clean_document_text();
std::println("test_import: all passed");
return 0;
}