Serenity Operating System
1/*
2 * Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <unistd.h>
8
9#include <AK/ScopeGuard.h>
10#include <LibSQL/BTree.h>
11#include <LibSQL/Heap.h>
12#include <LibSQL/Key.h>
13#include <LibSQL/Meta.h>
14#include <LibSQL/TupleDescriptor.h>
15#include <LibSQL/Value.h>
16#include <LibTest/TestCase.h>
17
18constexpr static int keys[] = {
19 39,
20 87,
21 77,
22 42,
23 98,
24 40,
25 53,
26 8,
27 37,
28 12,
29 90,
30 72,
31 73,
32 11,
33 88,
34 22,
35 10,
36 82,
37 25,
38 61,
39 97,
40 18,
41 60,
42 68,
43 21,
44 3,
45 58,
46 29,
47 13,
48 17,
49 89,
50 81,
51 16,
52 64,
53 5,
54 41,
55 36,
56 91,
57 38,
58 24,
59 32,
60 50,
61 34,
62 94,
63 49,
64 47,
65 1,
66 6,
67 44,
68 76,
69};
70constexpr static u32 pointers[] = {
71 92,
72 4,
73 50,
74 47,
75 68,
76 73,
77 24,
78 28,
79 50,
80 93,
81 60,
82 36,
83 92,
84 72,
85 53,
86 26,
87 91,
88 84,
89 25,
90 43,
91 88,
92 12,
93 62,
94 35,
95 96,
96 27,
97 96,
98 27,
99 99,
100 30,
101 21,
102 89,
103 54,
104 60,
105 37,
106 68,
107 35,
108 55,
109 80,
110 2,
111 33,
112 26,
113 93,
114 70,
115 45,
116 44,
117 3,
118 66,
119 75,
120 4,
121};
122
123NonnullRefPtr<SQL::BTree> setup_btree(SQL::Serializer&);
124void insert_and_get_to_and_from_btree(int);
125void insert_into_and_scan_btree(int);
126
127NonnullRefPtr<SQL::BTree> setup_btree(SQL::Serializer& serializer)
128{
129 NonnullRefPtr<SQL::TupleDescriptor> tuple_descriptor = adopt_ref(*new SQL::TupleDescriptor);
130 tuple_descriptor->append({ "schema", "table", "key_value", SQL::SQLType::Integer, SQL::Order::Ascending });
131
132 auto root_pointer = serializer.heap().user_value(0);
133 if (!root_pointer) {
134 root_pointer = serializer.heap().new_record_pointer();
135 serializer.heap().set_user_value(0, root_pointer);
136 }
137 auto btree = SQL::BTree::construct(serializer, tuple_descriptor, true, root_pointer);
138 btree->on_new_root = [&]() {
139 serializer.heap().set_user_value(0, btree->root());
140 };
141 return btree;
142}
143
144void insert_and_get_to_and_from_btree(int num_keys)
145{
146 ScopeGuard guard([]() { unlink("/tmp/test.db"); });
147 {
148 auto heap = SQL::Heap::construct("/tmp/test.db");
149 EXPECT(!heap->open().is_error());
150 SQL::Serializer serializer(heap);
151 auto btree = setup_btree(serializer);
152
153 for (auto ix = 0; ix < num_keys; ix++) {
154 SQL::Key k(btree->descriptor());
155 k[0] = keys[ix];
156 k.set_pointer(pointers[ix]);
157 btree->insert(k);
158 }
159#ifdef LIST_TREE
160 btree->list_tree();
161#endif
162 }
163
164 {
165 auto heap = SQL::Heap::construct("/tmp/test.db");
166 EXPECT(!heap->open().is_error());
167 SQL::Serializer serializer(heap);
168 auto btree = setup_btree(serializer);
169
170 for (auto ix = 0; ix < num_keys; ix++) {
171 SQL::Key k(btree->descriptor());
172 k[0] = keys[ix];
173 auto pointer_opt = btree->get(k);
174 VERIFY(pointer_opt.has_value());
175 EXPECT_EQ(pointer_opt.value(), pointers[ix]);
176 }
177 }
178}
179
180void insert_into_and_scan_btree(int num_keys)
181{
182 ScopeGuard guard([]() { unlink("/tmp/test.db"); });
183 {
184 auto heap = SQL::Heap::construct("/tmp/test.db");
185 EXPECT(!heap->open().is_error());
186 SQL::Serializer serializer(heap);
187 auto btree = setup_btree(serializer);
188
189 for (auto ix = 0; ix < num_keys; ix++) {
190 SQL::Key k(btree->descriptor());
191 k[0] = keys[ix];
192 k.set_pointer(pointers[ix]);
193 btree->insert(k);
194 }
195
196#ifdef LIST_TREE
197 btree->list_tree();
198#endif
199 }
200
201 {
202 auto heap = SQL::Heap::construct("/tmp/test.db");
203 EXPECT(!heap->open().is_error());
204 SQL::Serializer serializer(heap);
205 auto btree = setup_btree(serializer);
206
207 int count = 0;
208 SQL::Tuple prev;
209 for (auto iter = btree->begin(); !iter.is_end(); iter++, count++) {
210 auto key = (*iter);
211 if (prev.size()) {
212 EXPECT(prev < key);
213 }
214 auto key_value = key[0].to_int<i32>();
215 for (auto ix = 0; ix < num_keys; ix++) {
216 if (keys[ix] == key_value) {
217 EXPECT_EQ(key.pointer(), pointers[ix]);
218 break;
219 }
220 }
221 prev = key;
222 }
223 EXPECT_EQ(count, num_keys);
224 }
225}
226
227TEST_CASE(btree_one_key)
228{
229 insert_and_get_to_and_from_btree(1);
230}
231
232TEST_CASE(btree_four_keys)
233{
234 insert_and_get_to_and_from_btree(4);
235}
236
237TEST_CASE(btree_five_keys)
238{
239 insert_and_get_to_and_from_btree(5);
240}
241
242TEST_CASE(btree_10_keys)
243{
244 insert_and_get_to_and_from_btree(10);
245}
246
247TEST_CASE(btree_13_keys)
248{
249 insert_and_get_to_and_from_btree(13);
250}
251
252TEST_CASE(btree_20_keys)
253{
254 insert_and_get_to_and_from_btree(20);
255}
256
257TEST_CASE(btree_25_keys)
258{
259 insert_and_get_to_and_from_btree(25);
260}
261
262TEST_CASE(btree_30_keys)
263{
264 insert_and_get_to_and_from_btree(30);
265}
266
267TEST_CASE(btree_35_keys)
268{
269 insert_and_get_to_and_from_btree(35);
270}
271
272TEST_CASE(btree_40_keys)
273{
274 insert_and_get_to_and_from_btree(40);
275}
276
277TEST_CASE(btree_45_keys)
278{
279 insert_and_get_to_and_from_btree(45);
280}
281
282TEST_CASE(btree_50_keys)
283{
284 insert_and_get_to_and_from_btree(50);
285}
286
287TEST_CASE(btree_scan_one_key)
288{
289 insert_into_and_scan_btree(1);
290}
291
292TEST_CASE(btree_scan_four_keys)
293{
294 insert_into_and_scan_btree(4);
295}
296
297TEST_CASE(btree_scan_five_keys)
298{
299 insert_into_and_scan_btree(5);
300}
301
302TEST_CASE(btree_scan_10_keys)
303{
304 insert_into_and_scan_btree(10);
305}
306
307TEST_CASE(btree_scan_15_keys)
308{
309 insert_into_and_scan_btree(15);
310}
311
312TEST_CASE(btree_scan_30_keys)
313{
314 insert_into_and_scan_btree(15);
315}
316
317TEST_CASE(btree_scan_50_keys)
318{
319 insert_into_and_scan_btree(50);
320}