View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.directory.mavibot.btree;
21  
22  
23  import static org.junit.Assert.assertEquals;
24  
25  import java.io.File;
26  import java.lang.reflect.Method;
27  import java.nio.ByteBuffer;
28  
29  import org.junit.Rule;
30  import org.junit.Test;
31  import org.junit.rules.TemporaryFolder;
32  
33  
34  /**
35   * Test the RecordManager.store() method using reflection
36   *
37   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
38   */
39  public class PersistedStoreTest
40  {
41      @Rule
42      public TemporaryFolder tempFolder = new TemporaryFolder();
43  
44  
45      /**
46       * Test the store( int ) method
47       */
48      @Test
49      public void testInjectInt() throws Exception
50      {
51          File tempFile = tempFolder.newFile( "mavibot.db" );
52          String tempFileName = tempFile.getAbsolutePath();
53  
54          RecordManager recordManager = new RecordManager( tempFileName, 4 * 1024 );
55          Method method = RecordManager.class.getDeclaredMethod( "store", long.class, int.class, PageIO[].class );
56          method.setAccessible( true );
57  
58          // Allocate some Pages
59          PageIO[] pageIos = new PageIO[2];
60          pageIos[0] = new PageIO();
61          pageIos[0].setData( ByteBuffer.allocate( recordManager.getPageSize() ) );
62          pageIos[1] = new PageIO();
63          pageIos[1].setData( ByteBuffer.allocate( recordManager.getPageSize() ) );
64  
65          // Set the int at the beginning
66          long position = ( Long ) method.invoke( recordManager, 0, 0x12345678, pageIos );
67  
68          assertEquals( 4, position );
69          int pos = 12;
70          assertEquals( 0x12, pageIos[0].getData().get( pos++ ) );
71          assertEquals( 0x34, pageIos[0].getData().get( pos++ ) );
72          assertEquals( 0x56, pageIos[0].getData().get( pos++ ) );
73          assertEquals( 0x78, pageIos[0].getData().get( pos++ ) );
74  
75          // Set the int at the end of the first page
76          position = ( Long ) method.invoke( recordManager, 4080, 0x12345678, pageIos );
77  
78          assertEquals( 4084, position );
79          pos = 4092;
80          assertEquals( 0x12, pageIos[0].getData().get( pos++ ) );
81          assertEquals( 0x34, pageIos[0].getData().get( pos++ ) );
82          assertEquals( 0x56, pageIos[0].getData().get( pos++ ) );
83          assertEquals( 0x78, pageIos[0].getData().get( pos++ ) );
84  
85          // Set the int at the end of the first page and overlapping on the second page
86          // 1 byte overlapping
87          position = ( Long ) method.invoke( recordManager, 4081, 0x12345678, pageIos );
88  
89          assertEquals( 4085, position );
90          pos = 4093;
91          assertEquals( 0x12, pageIos[0].getData().get( pos++ ) );
92          assertEquals( 0x34, pageIos[0].getData().get( pos++ ) );
93          assertEquals( 0x56, pageIos[0].getData().get( pos++ ) );
94          pos = 8;
95          assertEquals( 0x78, pageIos[1].getData().get( pos++ ) );
96  
97          // Set the int at the end of the first page and overlapping on the second page
98          // 2 bytes overlapping
99          position = ( Long ) method.invoke( recordManager, 4082, 0x12345678, pageIos );
100 
101         assertEquals( 4086, position );
102         pos = 4094;
103         assertEquals( 0x12, pageIos[0].getData().get( pos++ ) );
104         assertEquals( 0x34, pageIos[0].getData().get( pos++ ) );
105         pos = 8;
106         assertEquals( 0x56, pageIos[1].getData().get( pos++ ) );
107         assertEquals( 0x78, pageIos[1].getData().get( pos++ ) );
108 
109         // Set the int at the end of the first page and overlapping on the second page
110         // 3 bytes overlapping
111         position = ( Long ) method.invoke( recordManager, 4083, 0x12345678, pageIos );
112 
113         assertEquals( 4087, position );
114         pos = 4095;
115         assertEquals( 0x12, pageIos[0].getData().get( pos++ ) );
116         pos = 8;
117         assertEquals( 0x34, pageIos[1].getData().get( pos++ ) );
118         assertEquals( 0x56, pageIos[1].getData().get( pos++ ) );
119         assertEquals( 0x78, pageIos[1].getData().get( pos++ ) );
120 
121         // Set the int at the beginning of the second page
122         position = ( Long ) method.invoke( recordManager, 4084, 0x12345678, pageIos );
123 
124         assertEquals( 4088, position );
125         pos = 8;
126         assertEquals( 0x12, pageIos[1].getData().get( pos++ ) );
127         assertEquals( 0x34, pageIos[1].getData().get( pos++ ) );
128         assertEquals( 0x56, pageIos[1].getData().get( pos++ ) );
129         assertEquals( 0x78, pageIos[1].getData().get( pos++ ) );
130 
131         recordManager.close();
132     }
133 
134 
135     /**
136      * Test the store( long ) method
137      */
138     @Test
139     public void testInjectLong() throws Exception
140     {
141         File tempFile = tempFolder.newFile( "mavibot.db" );
142         String tempFileName = tempFile.getAbsolutePath();
143 
144         RecordManager recordManager = new RecordManager( tempFileName, 4 * 1024 );
145         Method method = RecordManager.class.getDeclaredMethod( "store", long.class, long.class, PageIO[].class );
146         method.setAccessible( true );
147 
148         // Allocate some Pages
149         PageIO[] pageIos = new PageIO[2];
150         pageIos[0] = new PageIO();
151         pageIos[0].setData( ByteBuffer.allocate( recordManager.getPageSize() ) );
152         pageIos[1] = new PageIO();
153         pageIos[1].setData( ByteBuffer.allocate( recordManager.getPageSize() ) );
154 
155         // Set the long at the beginning
156         long position = ( Long ) method.invoke( recordManager, 0, 0x0123456789ABCDEFL, pageIos );
157 
158         assertEquals( 8, position );
159         int pos = 12;
160         assertEquals( 0x01, pageIos[0].getData().get( pos++ ) );
161         assertEquals( 0x23, pageIos[0].getData().get( pos++ ) );
162         assertEquals( 0x45, pageIos[0].getData().get( pos++ ) );
163         assertEquals( 0x67, pageIos[0].getData().get( pos++ ) );
164         assertEquals( ( byte ) 0x89, pageIos[0].getData().get( pos++ ) );
165         assertEquals( ( byte ) 0xAB, pageIos[0].getData().get( pos++ ) );
166         assertEquals( ( byte ) 0xCD, pageIos[0].getData().get( pos++ ) );
167         assertEquals( ( byte ) 0xEF, pageIos[0].getData().get( pos++ ) );
168 
169         // Set the long at the end of the first page
170         position = ( Long ) method.invoke( recordManager, 4076, 0x0123456789ABCDEFL, pageIos );
171 
172         assertEquals( 4084, position );
173         pos = 4088;
174         assertEquals( 0x01, pageIos[0].getData().get( pos++ ) );
175         assertEquals( 0x23, pageIos[0].getData().get( pos++ ) );
176         assertEquals( 0x45, pageIos[0].getData().get( pos++ ) );
177         assertEquals( 0x67, pageIos[0].getData().get( pos++ ) );
178         assertEquals( ( byte ) 0x89, pageIos[0].getData().get( pos++ ) );
179         assertEquals( ( byte ) 0xAB, pageIos[0].getData().get( pos++ ) );
180         assertEquals( ( byte ) 0xCD, pageIos[0].getData().get( pos++ ) );
181         assertEquals( ( byte ) 0xEF, pageIos[0].getData().get( pos++ ) );
182 
183         // Set the long at the end of the first page and overlapping on the second page
184         // 1 byte overlapping
185         position = ( Long ) method.invoke( recordManager, 4077, 0x0123456789ABCDEFL, pageIos );
186 
187         assertEquals( 4085, position );
188         pos = 4089;
189         assertEquals( 0x01, pageIos[0].getData().get( pos++ ) );
190         assertEquals( 0x23, pageIos[0].getData().get( pos++ ) );
191         assertEquals( 0x45, pageIos[0].getData().get( pos++ ) );
192         assertEquals( 0x67, pageIos[0].getData().get( pos++ ) );
193         assertEquals( ( byte ) 0x89, pageIos[0].getData().get( pos++ ) );
194         assertEquals( ( byte ) 0xAB, pageIos[0].getData().get( pos++ ) );
195         assertEquals( ( byte ) 0xCD, pageIos[0].getData().get( pos++ ) );
196         pos = 8;
197         assertEquals( ( byte ) 0xEF, pageIos[1].getData().get( pos++ ) );
198 
199         // Set the long at the end of the first page and overlapping on the second page
200         // 2 bytes overlapping
201         position = ( Long ) method.invoke( recordManager, 4078, 0x0123456789ABCDEFL, pageIos );
202 
203         assertEquals( 4086, position );
204         pos = 4090;
205         assertEquals( 0x01, pageIos[0].getData().get( pos++ ) );
206         assertEquals( 0x23, pageIos[0].getData().get( pos++ ) );
207         assertEquals( 0x45, pageIos[0].getData().get( pos++ ) );
208         assertEquals( 0x67, pageIos[0].getData().get( pos++ ) );
209         assertEquals( ( byte ) 0x89, pageIos[0].getData().get( pos++ ) );
210         assertEquals( ( byte ) 0xAB, pageIos[0].getData().get( pos++ ) );
211         pos = 8;
212         assertEquals( ( byte ) 0xCD, pageIos[1].getData().get( pos++ ) );
213         assertEquals( ( byte ) 0xEF, pageIos[1].getData().get( pos++ ) );
214 
215         // Set the long at the end of the first page and overlapping on the second page
216         // 3 bytes overlapping
217         position = ( Long ) method.invoke( recordManager, 4079, 0x0123456789ABCDEFL, pageIos );
218 
219         assertEquals( 4087, position );
220         pos = 4091;
221         assertEquals( 0x01, pageIos[0].getData().get( pos++ ) );
222         assertEquals( 0x23, pageIos[0].getData().get( pos++ ) );
223         assertEquals( 0x45, pageIos[0].getData().get( pos++ ) );
224         assertEquals( 0x67, pageIos[0].getData().get( pos++ ) );
225         assertEquals( ( byte ) 0x89, pageIos[0].getData().get( pos++ ) );
226         pos = 8;
227         assertEquals( ( byte ) 0xAB, pageIos[1].getData().get( pos++ ) );
228         assertEquals( ( byte ) 0xCD, pageIos[1].getData().get( pos++ ) );
229         assertEquals( ( byte ) 0xEF, pageIos[1].getData().get( pos++ ) );
230 
231         // Set the long at the end of the first page and overlapping on the second page
232         // 4 byte overlapping
233         position = ( Long ) method.invoke( recordManager, 4080, 0x0123456789ABCDEFL, pageIos );
234 
235         assertEquals( 4088, position );
236         pos = 4092;
237         assertEquals( 0x01, pageIos[0].getData().get( pos++ ) );
238         assertEquals( 0x23, pageIos[0].getData().get( pos++ ) );
239         assertEquals( 0x45, pageIos[0].getData().get( pos++ ) );
240         assertEquals( 0x67, pageIos[0].getData().get( pos++ ) );
241         pos = 8;
242         assertEquals( ( byte ) 0x89, pageIos[1].getData().get( pos++ ) );
243         assertEquals( ( byte ) 0xAB, pageIos[1].getData().get( pos++ ) );
244         assertEquals( ( byte ) 0xCD, pageIos[1].getData().get( pos++ ) );
245         assertEquals( ( byte ) 0xEF, pageIos[1].getData().get( pos++ ) );
246 
247         // Set the long at the end of the first page and overlapping on the second page
248         // 5 bytes overlapping
249         position = ( Long ) method.invoke( recordManager, 4081, 0x0123456789ABCDEFL, pageIos );
250 
251         assertEquals( 4089, position );
252         pos = 4093;
253         assertEquals( 0x01, pageIos[0].getData().get( pos++ ) );
254         assertEquals( 0x23, pageIos[0].getData().get( pos++ ) );
255         assertEquals( 0x45, pageIos[0].getData().get( pos++ ) );
256         pos = 8;
257         assertEquals( 0x67, pageIos[1].getData().get( pos++ ) );
258         assertEquals( ( byte ) 0x89, pageIos[1].getData().get( pos++ ) );
259         assertEquals( ( byte ) 0xAB, pageIos[1].getData().get( pos++ ) );
260         assertEquals( ( byte ) 0xCD, pageIos[1].getData().get( pos++ ) );
261         assertEquals( ( byte ) 0xEF, pageIos[1].getData().get( pos++ ) );
262 
263         // Set the long at the end of the first page and overlapping on the second page
264         // 6 bytes overlapping
265         position = ( Long ) method.invoke( recordManager, 4082, 0x0123456789ABCDEFL, pageIos );
266 
267         assertEquals( 4090, position );
268         pos = 4094;
269         assertEquals( 0x01, pageIos[0].getData().get( pos++ ) );
270         assertEquals( 0x23, pageIos[0].getData().get( pos++ ) );
271         pos = 8;
272         assertEquals( 0x45, pageIos[1].getData().get( pos++ ) );
273         assertEquals( 0x67, pageIos[1].getData().get( pos++ ) );
274         assertEquals( ( byte ) 0x89, pageIos[1].getData().get( pos++ ) );
275         assertEquals( ( byte ) 0xAB, pageIos[1].getData().get( pos++ ) );
276         assertEquals( ( byte ) 0xCD, pageIos[1].getData().get( pos++ ) );
277         assertEquals( ( byte ) 0xEF, pageIos[1].getData().get( pos++ ) );
278 
279         // Set the long at the end of the first page and overlapping on the second page
280         // 7 bytes overlapping
281         position = ( Long ) method.invoke( recordManager, 4083, 0x0123456789ABCDEFL, pageIos );
282 
283         assertEquals( 4091, position );
284         pos = 4095;
285         assertEquals( 0x01, pageIos[0].getData().get( pos++ ) );
286         pos = 8;
287         assertEquals( 0x23, pageIos[1].getData().get( pos++ ) );
288         assertEquals( 0x45, pageIos[1].getData().get( pos++ ) );
289         assertEquals( 0x67, pageIos[1].getData().get( pos++ ) );
290         assertEquals( ( byte ) 0x89, pageIos[1].getData().get( pos++ ) );
291         assertEquals( ( byte ) 0xAB, pageIos[1].getData().get( pos++ ) );
292         assertEquals( ( byte ) 0xCD, pageIos[1].getData().get( pos++ ) );
293         assertEquals( ( byte ) 0xEF, pageIos[1].getData().get( pos++ ) );
294 
295         // Set the long at the beginning of the second page
296         position = ( Long ) method.invoke( recordManager, 4084, 0x0123456789ABCDEFL, pageIos );
297 
298         assertEquals( 4092, position );
299         pos = 8;
300         assertEquals( 0x01, pageIos[1].getData().get( pos++ ) );
301         assertEquals( 0x23, pageIos[1].getData().get( pos++ ) );
302         assertEquals( 0x45, pageIos[1].getData().get( pos++ ) );
303         assertEquals( 0x67, pageIos[1].getData().get( pos++ ) );
304         assertEquals( ( byte ) 0x89, pageIos[1].getData().get( pos++ ) );
305         assertEquals( ( byte ) 0xAB, pageIos[1].getData().get( pos++ ) );
306         assertEquals( ( byte ) 0xCD, pageIos[1].getData().get( pos++ ) );
307         assertEquals( ( byte ) 0xEF, pageIos[1].getData().get( pos++ ) );
308 
309         recordManager.close();
310     }
311 
312 
313     /**
314      * Test the store( bytes ) method
315      */
316     @Test
317     public void testInjectBytes() throws Exception
318     {
319         File tempFile = tempFolder.newFile( "mavibot.db" );
320         String tempFileName = tempFile.getAbsolutePath();
321 
322         // We use smaller pages
323         RecordManager recordManager = new RecordManager( tempFileName, 32 );
324         Method storeMethod = RecordManager.class.getDeclaredMethod( "store", long.class, byte[].class, PageIO[].class );
325         storeMethod.setAccessible( true );
326 
327         // Allocate some Pages
328         PageIO[] pageIos = new PageIO[3];
329         pageIos[0] = new PageIO();
330         pageIos[0].setData( ByteBuffer.allocate( recordManager.getPageSize() ) );
331         pageIos[1] = new PageIO();
332         pageIos[1].setData( ByteBuffer.allocate( recordManager.getPageSize() ) );
333         pageIos[2] = new PageIO();
334         pageIos[2].setData( ByteBuffer.allocate( recordManager.getPageSize() ) );
335 //        pageIos[3] = new PageIO();
336 //        pageIos[3].setData( ByteBuffer.allocate( recordManager.getPageSize() ) );
337 
338         // We start with 4 bytes
339         byte[] bytes = new byte[]
340             { 0x01, 0x23, 0x45, 0x67 };
341 
342         // Set the bytes at the beginning
343         long position = ( Long ) storeMethod.invoke( recordManager, 0L, bytes, pageIos );
344 
345         assertEquals( 8, position );
346         int pos = 12;
347         // The byte length
348         assertEquals( 0x00, pageIos[0].getData().get( pos++ ) );
349         assertEquals( 0x00, pageIos[0].getData().get( pos++ ) );
350         assertEquals( 0x00, pageIos[0].getData().get( pos++ ) );
351         assertEquals( 0x04, pageIos[0].getData().get( pos++ ) );
352         // The data
353         assertEquals( 0x01, pageIos[0].getData().get( pos++ ) );
354         assertEquals( 0x23, pageIos[0].getData().get( pos++ ) );
355         assertEquals( 0x45, pageIos[0].getData().get( pos++ ) );
356         assertEquals( 0x67, pageIos[0].getData().get( pos++ ) );
357 
358         // Set the bytes at the end of the first page
359         position = ( Long ) storeMethod.invoke( recordManager, 12L, bytes, pageIos );
360 
361         assertEquals( 20, position );
362         pos = 24;
363         // The byte length
364         assertEquals( 0x00, pageIos[0].getData().get( pos++ ) );
365         assertEquals( 0x00, pageIos[0].getData().get( pos++ ) );
366         assertEquals( 0x00, pageIos[0].getData().get( pos++ ) );
367         assertEquals( 0x04, pageIos[0].getData().get( pos++ ) );
368         // The data
369         assertEquals( 0x01, pageIos[0].getData().get( pos++ ) );
370         assertEquals( 0x23, pageIos[0].getData().get( pos++ ) );
371         assertEquals( 0x45, pageIos[0].getData().get( pos++ ) );
372         assertEquals( 0x67, pageIos[0].getData().get( pos++ ) );
373 
374         // Set A full page of bytes in the first page
375         bytes = new byte[16];
376 
377         for ( int i = 0; i < 16; i++ )
378         {
379             bytes[i] = ( byte ) ( i + 1 );
380         }
381 
382         position = ( Long ) storeMethod.invoke( recordManager, 0L, bytes, pageIos );
383 
384         assertEquals( 20, position );
385         pos = 12;
386         // The byte length
387         assertEquals( 0x00, pageIos[0].getData().get( pos++ ) );
388         assertEquals( 0x00, pageIos[0].getData().get( pos++ ) );
389         assertEquals( 0x00, pageIos[0].getData().get( pos++ ) );
390         assertEquals( 0x10, pageIos[0].getData().get( pos++ ) );
391 
392         // The data
393         for ( int i = 0; i < 16; i++ )
394         {
395             assertEquals( ( byte ) ( i + 1 ), pageIos[0].getData().get( pos++ ) );
396         }
397 
398         // Write the bytes over 2 pages
399         position = ( Long ) storeMethod.invoke( recordManager, 47L, bytes, pageIos );
400 
401         assertEquals( 67, position );
402         pos = 59;
403         // The byte length
404         assertEquals( 0x00, pageIos[0].getData().get( pos++ ) );
405         assertEquals( 0x00, pageIos[0].getData().get( pos++ ) );
406         assertEquals( 0x00, pageIos[0].getData().get( pos++ ) );
407         assertEquals( 0x10, pageIos[0].getData().get( pos++ ) );
408 
409         // The data in the first page
410         assertEquals( 1, pageIos[0].getData().get( pos++ ) );
411 
412         // and in the second page
413         pos = 8;
414 
415         for ( int i = 0; i < 15; i++ )
416         {
417             assertEquals( ( byte ) ( i + 2 ), pageIos[1].getData().get( pos++ ) );
418         }
419 
420         // Write the bytes over 4 pages
421         bytes = new byte[112];
422 
423         for ( int i = 0; i < 112; i++ )
424         {
425             bytes[i] = ( byte ) ( i + 1 );
426         }
427 
428         position = ( Long ) storeMethod.invoke( recordManager, 2L, bytes, pageIos );
429 
430         assertEquals( 118, position );
431         pos = 14;
432         // The byte length
433         assertEquals( 0x00, pageIos[0].getData().get( pos++ ) );
434         assertEquals( 0x00, pageIos[0].getData().get( pos++ ) );
435         assertEquals( 0x00, pageIos[0].getData().get( pos++ ) );
436         assertEquals( 0x70, pageIos[0].getData().get( pos++ ) );
437 
438         // The data in the first page
439         for ( int i = 0; i < 46; i++ )
440         {
441             assertEquals( ( byte ) ( i + 1 ), pageIos[0].getData().get( pos++ ) );
442         }
443 
444         // The data in the second page
445         pos = 8;
446 
447         for ( int i = 46; i < 102; i++ )
448         {
449             assertEquals( ( byte ) ( i + 1 ), pageIos[1].getData().get( pos++ ) );
450         }
451 
452         // The data in the third page
453         pos = 8;
454 
455         for ( int i = 102; i < 112; i++ )
456         {
457             assertEquals( ( byte ) ( i + 1 ), pageIos[2].getData().get( pos++ ) );
458         }
459 
460         recordManager.close();
461     }
462 }