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