-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTestOther9.cs
More file actions
235 lines (190 loc) · 8.03 KB
/
TestOther9.cs
File metadata and controls
235 lines (190 loc) · 8.03 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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
using ArcOne;
using UnitTestOne;
namespace UnitTestNine
{
[TestClass]
public sealed class UnitNine
{
private bool IsDebugStress = TestSettings.CanDebugStress;
// This acts as your "Fake Drive"
private Dictionary<int, BNode> FakeDisk = new Dictionary<int, BNode>();
// Helper to add nodes to the fake drive
private void MockDiskWrite(int id, BNode node) => FakeDisk[id] = node;
// This is the function we will "pass" to the BTree
private BNode MockDiskRead(int id)
{
if (FakeDisk.ContainsKey(id)) return FakeDisk[id];
throw new System.Exception($"Node {id} not found.");
}
[TestMethod]
public void FindLeafInThreeLevelTree()
{
// 1. Clear the fake disk before starting.
FakeDisk.Clear();
// 1. Setup Tree Hierarchy:
// [20] (ID:1)
// / \
// [5,10](ID:2) [40] (ID:3)
// / \
// [25,30](ID:4) [40,50](ID:5)
// 2. Setup tree.
var root = new BNode(4, false).WithId(1).WithKeys(20).WithChildren(2, 3);
var leafA = new BNode(4, true).WithId(2).WithKeys(5, 10);
var internalB = new BNode(4, false).WithId(3).WithKeys(40).WithChildren(4, 5);
var leafC = new BNode(4, true).WithId(4).WithKeys(25, 30);
var leafD = new BNode(4, true).WithId(5).WithKeys(40, 50);
// 3. Mock DiskRead behavior.
MockDiskWrite(root.Id, root);
MockDiskWrite(leafA.Id, leafA);
MockDiskWrite(internalB.Id, internalB);
MockDiskWrite(leafC.Id, leafC);
MockDiskWrite(leafD.Id, leafD);
// 4. Search for key 45 from root.
// 45 is > 20 (goes to ID 3) and > 40 (goes to ID 5)
BNode result = FindLeaf(1, 45);
Assert.IsNotNull(result);
Assert.IsTrue(result.Leaf);
Assert.AreEqual(5, result.Id);
// 5. Search for key 45 from leaf.
result = FindLeaf(5, 45);
Assert.IsNotNull(result);
Assert.IsTrue(result.Leaf);
Assert.AreEqual(5, result.Id);
// 7. Search for 7.
result = FindLeaf(1, 7);
Assert.AreEqual(2, result.Id);
}
public BNode FindLeaf(int nodeId, int key)
{
if (nodeId == -1) return null;
int currentId = nodeId;
while (true)
{
BNode node = MockDiskRead(currentId);
if (node.Leaf) return node;
// Binary Search for the child index
int low = 0, high = node.NumKeys - 1;
while (low <= high)
{
int mid = (low + high) / 2;
if (key >= node.Keys[mid].Key) low = mid + 1;
else high = mid - 1;
}
// low is the correct index for the child pointer
currentId = node.Kids[low];
}
}
[TestMethod]
public void WriteToFileTest()
{
// 1. Setup: Use a real temporary file name
string path = "swan.db";
string tempFile = "export.txt";
File.Delete(path);
File.Delete(tempFile);
using (var tree = new BTree(path))
{
// Fill the tree with enough data to force multiple leaves (e.g., 20 keys)
for (int i = 1; i <= 20; i++)
{
tree.Insert(i, i * 10); // Key, Data
}
// 2. Act
tree.WriteToFile(tempFile);
// 3. Assert
Assert.IsTrue(File.Exists(tempFile), "Export file should exist.");
string[] lines = File.ReadAllLines(tempFile);
// Check if we got all 20 keys
Assert.AreEqual(20, lines.Length, "Should have 20 lines.");
// Check the lines.
Assert.AreEqual("1, 10", lines[0]);
Assert.AreEqual("10, 100", lines[9]);
Assert.AreEqual("20, 200", lines[19]);
}
// Cleanup
File.Delete(path);
File.Delete(tempFile);
}
[TestMethod]
public void GetKeyRangeTest()
{
string path = "gamma.db";
File.Delete(path);
using (var tree = new BTree(path, 4))
{
for (int i = 10; i <= 40; i += 10) tree.Insert(i, i);
// Helper to keep it to one line per test case
void VerifyRange(int start, int end, params int[] expected)
{
var actual = tree.GetKeyRange(start, end);
CollectionAssert.AreEqual(expected, actual);
}
VerifyRange(15, 35, 20, 30); // Middle
VerifyRange(-1, 15, 10); // Start
VerifyRange(38, 60, 40); // End
VerifyRange(-1, 60, 10, 20, 30, 40); // Full
VerifyRange(-20, 0); // Outside Lower
VerifyRange(50, 100); // Outside Upper
VerifyRange(20, 20, 20); // Single Point
VerifyRange(50, 10); // Inverted
}
File.Delete(path);
}
[TestMethod]
public void GetElementRangeTest()
{
string path = "theta.db";
File.Delete(path);
using (var tree = new BTree(path, 4))
{
for (int i = 10; i <= 60; i += 10)
tree.Insert(new Element(i, i * 10));
// LOCAL HELPER: Automatically "sees" the tree variable
void Verify(int start, int end, params int[] expected)
{
var actual = tree.GetElementRange(start, end).Select(e => e.Key).ToArray();
CollectionAssert.AreEqual(expected, actual, $"Failed for range {start} to {end}");
}
// Now the calls are incredibly clean
Verify(15, 35, 20, 30);
Verify(-1, 15, 10);
Verify(38, 60, 40, 50, 60);
Verify(-1, 60, 10, 20, 30, 40, 50, 60);
Verify(-20, 0);
Verify(100, 200);
}
File.Delete(path);
}
[TestMethod]
public void RangeScanStressTest()
{
string path = "oscar.db";
File.Delete(path);
using (var tree = new BTree(path, 4))
{
// 1. Setup: Insert 20 keys to force multiple splits and levels
// We use a specific gap (5) so we can test "between" values
for (int i = 5; i <= 100; i += 5)
tree.Insert(i, i * 10);
// Local helper captures 'tree' for clean syntax
void Verify(int start, int end, params int[] expected)
{
var actual = tree.GetKeyRange(start, end);
CollectionAssert.AreEqual(expected, actual, $"Failed for {start}-{end}");
}
// 2. Test: Start, Middle, and End across the leaf nodes
Verify(1, 12, 5, 10); // Start boundary
Verify(42, 63, 45, 50, 55, 60); // Middle bridge (spans nodes)
Verify(92, 150, 95, 100); // End boundary
// 3. Delete keys to create holes.
tree.Delete(50, 0);
tree.Delete(55, 0);
// 4. Test the ranges.
Verify(42, 63, 45, 60);
Verify(71, 74);
Verify(48, 62, 60);
}
File.Delete(path);
}
}
}