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.exception.KeyNotFoundException;
30 import org.apache.directory.mavibot.btree.serializer.LongSerializer;
31 import org.apache.directory.mavibot.btree.serializer.StringSerializer;
32 import org.junit.After;
33 import org.junit.Before;
34 import org.junit.Test;
35
36
37
38
39
40
41
42 public class InMemoryLeafTest
43 {
44 private BTree<Long, String> btree = null;
45
46
47
48
49
50 @Before
51 public void setup() throws IOException
52 {
53 btree = BTreeFactory.createInMemoryBTree( "test", LongSerializer.INSTANCE, StringSerializer.INSTANCE );
54 btree.setPageSize( 8 );
55 }
56
57
58 @After
59 public void shutdown() throws IOException
60 {
61 btree.close();
62 }
63
64
65
66
67
68
69 private InMemoryLeaf<Long, String> insert( InMemoryLeaf<Long, String> leaf, long key, String value )
70 throws IOException
71 {
72 InsertResult<Long, String> result = leaf.insert( key, value, 1L );
73
74 return ( InMemoryLeaf<Long, String> ) ( ( ModifyResult<Long, String> ) result ).getModifiedPage();
75 }
76
77
78
79
80
81
82 @Test
83 public void testDeleteFromEmptyLeaf() throws IOException
84 {
85 InMemoryLeaf<Long, String> leaf = new InMemoryLeaf<Long, String>( btree );
86
87 DeleteResult<Long, String> result = leaf.delete( 1L, null, 1L, 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 InMemoryLeaf<Long, String> leaf = new InMemoryLeaf<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( 5L, null, 2L, 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 InMemoryLeaf<Long, String> leaf = new InMemoryLeaf<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( 3L, null, 4L, 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 InMemoryLeaf<Long, String> leaf = new InMemoryLeaf<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( 1L, null, 4L, 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 InMemoryNode<Long, String> parent = new InMemoryNode<Long, String>( btree, 1L, 2 );
221 InMemoryLeaf<Long, String> left = new InMemoryLeaf<Long, String>( btree );
222 InMemoryLeaf<Long, String> target = new InMemoryLeaf<Long, String>( btree );
223 InMemoryLeaf<Long, String> right = new InMemoryLeaf<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.setPageHolder( 0, new PageHolder<Long, String>( btree, left ) );
245 parent.setPageHolder( 1, new PageHolder<Long, String>( btree, target ) );
246 parent.setPageHolder( 2, new PageHolder<Long, String>( btree, right ) );
247
248
249 parent.setKey( 0, new KeyHolder<Long>( 6L ) );
250 parent.setKey( 1, new KeyHolder<Long>( 10L ) );
251
252
253 DeleteResult<Long, String> result = target.delete( 7L, null, 2L, 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 InMemoryLeaf<Long, String> newLeaf = ( InMemoryLeaf<Long, String> ) borrowed.getModifiedPage();
264
265 assertEquals( 4, newLeaf.getNbElems() );
266 assertEquals( Long.valueOf( 5L ), newLeaf.getKey( 0 ) );
267 assertEquals( Long.valueOf( 6L ), newLeaf.getKey( 1 ) );
268 assertEquals( Long.valueOf( 8L ), newLeaf.getKey( 2 ) );
269 assertEquals( Long.valueOf( 9L ), newLeaf.getKey( 3 ) );
270
271
272 InMemoryLeaf<Long, String> leftSibling = ( InMemoryLeaf<Long, String> ) borrowed.getModifiedSibling();
273
274 assertEquals( 4, leftSibling.getNbElems() );
275 assertEquals( Long.valueOf( 1L ), leftSibling.getKey( 0 ) );
276 assertEquals( Long.valueOf( 2L ), leftSibling.getKey( 1 ) );
277 assertEquals( Long.valueOf( 3L ), leftSibling.getKey( 2 ) );
278 assertEquals( Long.valueOf( 4L ), leftSibling.getKey( 3 ) );
279 }
280
281
282
283
284
285
286
287 @Test
288 public void testDeleteBorrowingFromRightSibling() throws IOException
289 {
290 InMemoryNode<Long, String> parent = new InMemoryNode<Long, String>( btree, 1L, 2 );
291 InMemoryLeaf<Long, String> left = new InMemoryLeaf<Long, String>( btree );
292 InMemoryLeaf<Long, String> target = new InMemoryLeaf<Long, String>( btree );
293 InMemoryLeaf<Long, String> right = new InMemoryLeaf<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.setPageHolder( 0, new PageHolder<Long, String>( btree, left ) );
315 parent.setPageHolder( 1, new PageHolder<Long, String>( btree, target ) );
316 parent.setPageHolder( 2, new PageHolder<Long, String>( btree, right ) );
317
318
319 parent.setKey( 0, new KeyHolder<Long>( 6L ) );
320 parent.setKey( 1, new KeyHolder<Long>( 10L ) );
321
322
323 DeleteResult<Long, String> result = target.delete( 7L, null, 2L, 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 InMemoryLeaf<Long, String> newLeaf = ( InMemoryLeaf<Long, String> ) borrowed.getModifiedPage();
335
336 assertEquals( 4, newLeaf.getNbElems() );
337 assertEquals( Long.valueOf( 6L ), newLeaf.getKey( 0 ) );
338 assertEquals( Long.valueOf( 8L ), newLeaf.getKey( 1 ) );
339 assertEquals( Long.valueOf( 9L ), newLeaf.getKey( 2 ) );
340 assertEquals( Long.valueOf( 10L ), newLeaf.getKey( 3 ) );
341
342
343 InMemoryLeaf<Long, String> rightSibling = ( InMemoryLeaf<Long, String> ) borrowed.getModifiedSibling();
344
345 assertEquals( 4, rightSibling.getNbElems() );
346 assertEquals( Long.valueOf( 11L ), rightSibling.getKey( 0 ) );
347 assertEquals( Long.valueOf( 12L ), rightSibling.getKey( 1 ) );
348 assertEquals( Long.valueOf( 13L ), rightSibling.getKey( 2 ) );
349 assertEquals( Long.valueOf( 14L ), rightSibling.getKey( 3 ) );
350 }
351
352
353
354
355
356
357
358 @Test
359 public void testDeleteMergeWithSibling() throws IOException
360 {
361 InMemoryNode<Long, String> parent = new InMemoryNode<Long, String>( btree, 1L, 2 );
362 InMemoryLeaf<Long, String> left = new InMemoryLeaf<Long, String>( btree );
363 InMemoryLeaf<Long, String> target = new InMemoryLeaf<Long, String>( btree );
364 InMemoryLeaf<Long, String> right = new InMemoryLeaf<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.setPageHolder( 0, new PageHolder<Long, String>( btree, left ) );
385 parent.setPageHolder( 1, new PageHolder<Long, String>( btree, target ) );
386 parent.setPageHolder( 2, new PageHolder<Long, String>( btree, right ) );
387
388
389 parent.setKey( 0, new KeyHolder<Long>( 5L ) );
390 parent.setKey( 1, new KeyHolder<Long>( 9L ) );
391
392
393 DeleteResult<Long, String> result = target.delete( 7L, null, 2L, 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 InMemoryLeaf<Long, String> newLeaf = ( InMemoryLeaf<Long, String> ) merged.getModifiedPage();
404
405 assertEquals( 7, newLeaf.getNbElems() );
406 assertEquals( Long.valueOf( 1L ), newLeaf.getKey( 0 ) );
407 assertEquals( Long.valueOf( 2L ), newLeaf.getKey( 1 ) );
408 assertEquals( Long.valueOf( 3L ), newLeaf.getKey( 2 ) );
409 assertEquals( Long.valueOf( 4L ), newLeaf.getKey( 3 ) );
410 assertEquals( Long.valueOf( 5L ), newLeaf.getKey( 4 ) );
411 assertEquals( Long.valueOf( 6L ), newLeaf.getKey( 5 ) );
412 assertEquals( Long.valueOf( 8L ), newLeaf.getKey( 6 ) );
413 }
414
415
416
417
418
419
420 @Test
421 public void testFindPos() throws Exception
422 {
423 InMemoryLeaf<Long, String> leaf = new InMemoryLeaf<Long, String>( btree );
424
425
426 for ( long i = 0; i < 8; i++ )
427 {
428 long value = i + i + 1;
429 leaf = ( InMemoryLeaf<Long, String> ) ( ( ModifyResult<Long, String> ) leaf.insert( value, "V" + value, 0L ) )
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 }