1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.mavibot.btree.memory;
21
22
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
26
27 import java.io.IOException;
28
29 import org.apache.directory.mavibot.btree.Tuple;
30 import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
31 import org.apache.directory.mavibot.btree.serializer.LongSerializer;
32 import org.apache.directory.mavibot.btree.serializer.StringSerializer;
33 import org.junit.After;
34 import org.junit.Before;
35 import org.junit.Test;
36
37
38
39
40
41
42
43 public class LeafTest
44 {
45 private BTree<Long, String> btree = null;
46
47
48
49
50
51 @Before
52 public void setup() throws IOException
53 {
54 btree = new BTree<Long, String>( "test", new LongSerializer(), new StringSerializer() );
55 btree.setPageSize( 8 );
56 }
57
58
59 @After
60 public void shutdown() throws IOException
61 {
62 btree.close();
63 }
64
65
66
67
68
69
70 private Leaf<Long, String> insert( Leaf<Long, String> leaf, long key, String value ) throws IOException
71 {
72 InsertResult<Long, String> result = leaf.insert( 1L, key, value );
73
74 return ( Leaf<Long, String> ) ( ( ModifyResult<Long, String> ) result ).getModifiedPage();
75 }
76
77
78
79
80
81
82 @Test
83 public void testDeleteFromEmptyLeaf() throws IOException
84 {
85 Leaf<Long, String> leaf = new Leaf<Long, String>( btree );
86
87 DeleteResult<Long, String> result = leaf.delete( 1L, 1L, null, null, -1 );
88
89 assertEquals( NotPresentResult.NOT_PRESENT, result );
90 }
91
92
93
94
95
96
97 @Test
98 public void testDeleteNotPresentElementFromRootLeaf() throws IOException
99 {
100 Leaf<Long, String> leaf = new Leaf<Long, String>( btree );
101 leaf = insert( leaf, 1L, "v1" );
102 leaf = insert( leaf, 2L, "v2" );
103 leaf = insert( leaf, 3L, "v3" );
104 leaf = insert( leaf, 4L, "v4" );
105
106 DeleteResult<Long, String> result = leaf.delete( 2L, 5L, null, null, -1 );
107
108 assertEquals( NotPresentResult.NOT_PRESENT, result );
109 }
110
111
112
113
114
115
116 @Test
117 public void testDeletePresentElementFromRootLeaf() throws IOException
118 {
119 Leaf<Long, String> leaf = new Leaf<Long, String>( btree );
120 leaf = insert( leaf, 1L, "v1" );
121 leaf = insert( leaf, 2L, "v2" );
122 leaf = insert( leaf, 3L, "v3" );
123 leaf = insert( leaf, 4L, "v4" );
124
125 DeleteResult<Long, String> result = leaf.delete( 4L, 3L, null, null, -1 );
126
127 assertTrue( result instanceof RemoveResult );
128
129 Tuple<Long, String> removedElement = ( ( RemoveResult<Long, String> ) result ).getRemovedElement();
130 Page<Long, String> newLeaf = ( ( RemoveResult<Long, String> ) result ).getModifiedPage();
131
132 assertEquals( Long.valueOf( 3L ), removedElement.getKey() );
133 assertEquals( "v3", removedElement.getValue() );
134 assertEquals( 3, newLeaf.getNbElems() );
135
136 try
137 {
138 assertEquals( "v1", newLeaf.get( 1L ) );
139 assertEquals( "v2", newLeaf.get( 2L ) );
140 assertEquals( "v4", newLeaf.get( 4L ) );
141 }
142 catch ( KeyNotFoundException knfe )
143 {
144 fail();
145 }
146
147 try
148 {
149 newLeaf.get( 3L );
150 fail();
151 }
152 catch ( KeyNotFoundException knfe )
153 {
154
155 }
156 }
157
158
159
160
161
162
163 @Test
164 public void testDeleteFirstElementFromRootLeaf() throws IOException
165 {
166 Leaf<Long, String> leaf = new Leaf<Long, String>( btree );
167 leaf = insert( leaf, 1L, "v1" );
168 leaf = insert( leaf, 2L, "v2" );
169 leaf = insert( leaf, 3L, "v3" );
170 leaf = insert( leaf, 4L, "v4" );
171
172 DeleteResult<Long, String> result = leaf.delete( 4L, 1L, null, null, -1 );
173
174 assertTrue( result instanceof RemoveResult );
175
176 RemoveResult<Long, String> removeResult = ( RemoveResult<Long, String> ) result;
177
178 Tuple<Long, String> removedElement = removeResult.getRemovedElement();
179 Page<Long, String> newLeaf = removeResult.getModifiedPage();
180
181 assertEquals( Long.valueOf( 1L ), removedElement.getKey() );
182 assertEquals( "v1", removedElement.getValue() );
183 assertEquals( 3, newLeaf.getNbElems() );
184
185 try
186 {
187 newLeaf.get( 1L );
188 fail();
189 }
190 catch ( KeyNotFoundException knfe )
191 {
192
193 }
194
195 try
196 {
197 assertEquals( "v2", newLeaf.get( 2L ) );
198 assertEquals( "v3", newLeaf.get( 3L ) );
199 assertEquals( "v4", newLeaf.get( 4L ) );
200 }
201 catch ( KeyNotFoundException knfe )
202 {
203 fail();
204 }
205 }
206
207
208
209
210
211
212
213
214
215
216
217 @Test
218 public void testDeleteBorrowingFromLeftSibling() throws IOException
219 {
220 Node<Long, String> parent = new Node<Long, String>( btree, 1L, 2 );
221 Leaf<Long, String> left = new Leaf<Long, String>( btree );
222 Leaf<Long, String> target = new Leaf<Long, String>( btree );
223 Leaf<Long, String> right = new Leaf<Long, String>( btree );
224
225
226 left = insert( left, 1L, "v1" );
227 left = insert( left, 2L, "v2" );
228 left = insert( left, 3L, "v3" );
229 left = insert( left, 4L, "v4" );
230 left = insert( left, 5L, "v5" );
231
232
233 target = insert( target, 6L, "v6" );
234 target = insert( target, 7L, "v7" );
235 target = insert( target, 8L, "v8" );
236 target = insert( target, 9L, "v9" );
237
238
239 right = insert( right, 10L, "v10" );
240 right = insert( right, 11L, "v11" );
241 right = insert( right, 12L, "v12" );
242 right = insert( right, 13L, "v13" );
243
244 parent.children[0] = new MemoryHolder( btree, left );
245 parent.children[1] = new MemoryHolder( btree, target );
246 parent.children[2] = new MemoryHolder( btree, right );
247
248
249 parent.keys[0] = 6L;
250 parent.keys[1] = 10L;
251
252
253 DeleteResult<Long, String> result = target.delete( 2L, 7L, null, parent, 1 );
254
255 assertTrue( result instanceof BorrowedFromLeftResult );
256
257 BorrowedFromLeftResult<Long, String> borrowed = ( BorrowedFromLeftResult<Long, String> ) result;
258 Tuple<Long, String> removedKey = borrowed.getRemovedElement();
259
260 assertEquals( Long.valueOf( 7L ), removedKey.getKey() );
261
262
263 Leaf<Long, String> newLeaf = ( Leaf<Long, String> ) borrowed.getModifiedPage();
264
265 assertEquals( 4, newLeaf.nbElems );
266 assertEquals( Long.valueOf( 5L ), newLeaf.keys[0] );
267 assertEquals( Long.valueOf( 6L ), newLeaf.keys[1] );
268 assertEquals( Long.valueOf( 8L ), newLeaf.keys[2] );
269 assertEquals( Long.valueOf( 9L ), newLeaf.keys[3] );
270
271
272 Leaf<Long, String> leftSibling = ( Leaf<Long, String> ) borrowed.getModifiedSibling();
273
274 assertEquals( 4, leftSibling.nbElems );
275 assertEquals( Long.valueOf( 1L ), leftSibling.keys[0] );
276 assertEquals( Long.valueOf( 2L ), leftSibling.keys[1] );
277 assertEquals( Long.valueOf( 3L ), leftSibling.keys[2] );
278 assertEquals( Long.valueOf( 4L ), leftSibling.keys[3] );
279 }
280
281
282
283
284
285
286
287 @Test
288 public void testDeleteBorrowingFromRightSibling() throws IOException
289 {
290 Node<Long, String> parent = new Node<Long, String>( btree, 1L, 2 );
291 Leaf<Long, String> left = new Leaf<Long, String>( btree );
292 Leaf<Long, String> target = new Leaf<Long, String>( btree );
293 Leaf<Long, String> right = new Leaf<Long, String>( btree );
294
295
296 left = insert( left, 1L, "v1" );
297 left = insert( left, 2L, "v2" );
298 left = insert( left, 3L, "v3" );
299 left = insert( left, 4L, "v4" );
300
301
302 target = insert( target, 6L, "v6" );
303 target = insert( target, 7L, "v7" );
304 target = insert( target, 8L, "v8" );
305 target = insert( target, 9L, "v9" );
306
307
308 right = insert( right, 10L, "v10" );
309 right = insert( right, 11L, "v11" );
310 right = insert( right, 12L, "v12" );
311 right = insert( right, 13L, "v13" );
312 right = insert( right, 14L, "v14" );
313
314 parent.children[0] = new MemoryHolder( null, left );
315 parent.children[1] = new MemoryHolder( null, target );
316 parent.children[2] = new MemoryHolder( null, right );
317
318
319 parent.keys[0] = 6L;
320 parent.keys[1] = 10L;
321
322
323 DeleteResult<Long, String> result = target.delete( 2L, 7L, null, parent, 1 );
324
325 assertTrue( result instanceof BorrowedFromRightResult );
326
327 BorrowedFromRightResult<Long, String> borrowed = ( BorrowedFromRightResult<Long, String> ) result;
328 assertEquals( Long.valueOf( 11L ), borrowed.getModifiedSibling().getKey( 0 ) );
329 Tuple<Long, String> removedKey = borrowed.getRemovedElement();
330
331 assertEquals( Long.valueOf( 7L ), removedKey.getKey() );
332
333
334 Leaf<Long, String> newLeaf = ( Leaf<Long, String> ) borrowed.getModifiedPage();
335
336 assertEquals( 4, newLeaf.nbElems );
337 assertEquals( Long.valueOf( 6L ), newLeaf.keys[0] );
338 assertEquals( Long.valueOf( 8L ), newLeaf.keys[1] );
339 assertEquals( Long.valueOf( 9L ), newLeaf.keys[2] );
340 assertEquals( Long.valueOf( 10L ), newLeaf.keys[3] );
341
342
343 Leaf<Long, String> rightSibling = ( Leaf<Long, String> ) borrowed.getModifiedSibling();
344
345 assertEquals( 4, rightSibling.nbElems );
346 assertEquals( Long.valueOf( 11L ), rightSibling.keys[0] );
347 assertEquals( Long.valueOf( 12L ), rightSibling.keys[1] );
348 assertEquals( Long.valueOf( 13L ), rightSibling.keys[2] );
349 assertEquals( Long.valueOf( 14L ), rightSibling.keys[3] );
350 }
351
352
353
354
355
356
357
358 @Test
359 public void testDeleteMergeWithSibling() throws IOException
360 {
361 Node<Long, String> parent = new Node<Long, String>( btree, 1L, 2 );
362 Leaf<Long, String> left = new Leaf<Long, String>( btree );
363 Leaf<Long, String> target = new Leaf<Long, String>( btree );
364 Leaf<Long, String> right = new Leaf<Long, String>( btree );
365
366
367 left = insert( left, 1L, "v1" );
368 left = insert( left, 2L, "v2" );
369 left = insert( left, 3L, "v3" );
370 left = insert( left, 4L, "v4" );
371
372
373 target = insert( target, 5L, "v5" );
374 target = insert( target, 6L, "v6" );
375 target = insert( target, 7L, "v7" );
376 target = insert( target, 8L, "v8" );
377
378
379 right = insert( right, 9L, "v9" );
380 right = insert( right, 10L, "v10" );
381 right = insert( right, 11L, "v11" );
382 right = insert( right, 12L, "v12" );
383
384 parent.children[0] = new MemoryHolder( null, left );
385 parent.children[1] = new MemoryHolder( null, target );
386 parent.children[2] = new MemoryHolder( null, right );
387
388
389 parent.keys[0] = 5L;
390 parent.keys[1] = 9L;
391
392
393 DeleteResult<Long, String> result = target.delete( 2L, 7L, null, parent, 1 );
394
395 assertTrue( result instanceof MergedWithSiblingResult );
396
397 MergedWithSiblingResult<Long, String> merged = ( MergedWithSiblingResult<Long, String> ) result;
398 Tuple<Long, String> removedKey = merged.getRemovedElement();
399
400 assertEquals( Long.valueOf( 7L ), removedKey.getKey() );
401
402
403 Leaf<Long, String> newLeaf = ( Leaf<Long, String> ) merged.getModifiedPage();
404
405 assertEquals( 7, newLeaf.nbElems );
406 assertEquals( Long.valueOf( 1L ), newLeaf.keys[0] );
407 assertEquals( Long.valueOf( 2L ), newLeaf.keys[1] );
408 assertEquals( Long.valueOf( 3L ), newLeaf.keys[2] );
409 assertEquals( Long.valueOf( 4L ), newLeaf.keys[3] );
410 assertEquals( Long.valueOf( 5L ), newLeaf.keys[4] );
411 assertEquals( Long.valueOf( 6L ), newLeaf.keys[5] );
412 assertEquals( Long.valueOf( 8L ), newLeaf.keys[6] );
413 }
414
415
416
417
418
419
420 @Test
421 public void testFindPos() throws Exception
422 {
423 Leaf<Long, String> leaf = new Leaf<Long, String>( btree );
424
425
426 for ( long i = 0; i < 8; i++ )
427 {
428 long value = i + i + 1;
429 leaf = ( Leaf<Long, String> ) ( ( ModifyResult<Long, String> ) leaf.insert( 0L, value, "V" + value ) )
430 .getModifiedPage();
431 }
432
433
434 for ( long i = 0; i < 17; i++ )
435 {
436 if ( i % 2 == 1 )
437 {
438 assertEquals( -( i / 2 + 1 ), leaf.findPos( i ) );
439 }
440 else
441 {
442 assertEquals( i / 2, leaf.findPos( i ) );
443 }
444 }
445 }
446 }