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  package org.apache.directory.server.core.partition.impl.btree.jdbm;
20  
21  
22  import org.junit.*;
23  import static org.junit.Assert.assertNotNull;
24  import static org.junit.Assert.assertTrue;
25  import static org.junit.Assert.assertEquals;
26  import static org.junit.Assert.assertFalse;
27  import static org.junit.Assert.fail;
28  import static org.junit.Assert.assertNull;
29  
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  
33  import jdbm.RecordManager;
34  import jdbm.helper.StringComparator;
35  import jdbm.helper.TupleBrowser;
36  import jdbm.helper.Tuple;
37  import jdbm.btree.BTree;
38  import jdbm.recman.BaseRecordManager;
39  
40  import java.io.File;
41  import java.util.Comparator;
42  
43  
44  
45  /**
46   * Document me!
47   *
48   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
49   * @version $Rev$, $Date$
50   */
51  public class KeyCursorTest
52  {
53      private static final Logger LOG = LoggerFactory.getLogger( KeyCursorTest.class.getSimpleName() );
54      private static final byte[] EMPTY_BYTES = new byte[0];
55      private static final String TEST_OUTPUT_PATH = "test.output.path";
56  
57      File dbFile;
58      RecordManager recman;
59      BTree bt;
60      Comparator<String> comparator;
61  
62      KeyBTreeCursor<String> cursor;
63  
64  
65      @SuppressWarnings({"unchecked"})
66      @Before
67      public void createCursor() throws Exception
68      {
69          File tmpDir = null;
70          if ( System.getProperty( TEST_OUTPUT_PATH, null ) != null )
71          {
72              tmpDir = new File( System.getProperty( TEST_OUTPUT_PATH ) );
73          }
74  
75          dbFile = File.createTempFile( KeyCursorTest.class.getName(), "db", tmpDir );
76          recman = new BaseRecordManager( dbFile.getAbsolutePath() );
77          comparator = new StringComparator();
78          bt = BTree.createInstance( recman, comparator );
79  
80          // add some data to it
81          bt.insert( "0", EMPTY_BYTES, true );
82          bt.insert( "1", EMPTY_BYTES, true );
83          bt.insert( "2", EMPTY_BYTES, true );
84          bt.insert( "3", EMPTY_BYTES, true );
85          bt.insert( "4", EMPTY_BYTES, true );
86          bt.insert( "5", EMPTY_BYTES, true );
87          bt.insert( "6", EMPTY_BYTES, true );
88          bt.insert( "7", EMPTY_BYTES, true );
89          bt.insert( "8", EMPTY_BYTES, true );
90          bt.insert( "9", EMPTY_BYTES, true );
91  
92          cursor = new KeyBTreeCursor<String>( bt, comparator );
93          LOG.debug( "Created new KeyBTreeCursor and populated it's btree" );
94      }
95  
96  
97      @After
98      public void destryCursor() throws Exception
99      {
100         recman.close();
101         recman = null;
102         dbFile.deleteOnExit();
103 
104         String fileToDelete = dbFile.getAbsolutePath();
105         new File( fileToDelete + ".db" ).delete();
106         new File( fileToDelete + ".lg" ).delete();
107 
108         dbFile = null;
109     }
110 
111 
112     @Test
113     public void testPreviousBeforePositioning() throws Exception
114     {
115         // test initial setup, advances after, and before inside elements
116         assertInvalidCursor();
117 
118         assertTrue( cursor.previous() );
119         assertEquals( "9", cursor.get() );
120     }
121 
122 
123     @Test
124     public void testNextBeforePositioning() throws Exception
125     {
126         // test initial setup, advances after, and before inside elements
127         assertInvalidCursor();
128 
129         assertTrue( cursor.next() );
130         assertEquals( "0", cursor.get() );
131     }
132 
133 
134     @Test
135     public void testOperations() throws Exception
136     {
137         // test initial setup, advances after, and before inside elements
138         assertInvalidCursor();
139 
140         assertTrue( cursor.next() );
141         assertEquals( "0", cursor.get() );
142 
143         cursor.after( "5" );
144         assertInvalidCursor();
145         assertTrue( cursor.next() );
146         assertEquals( "6", cursor.get() );
147 
148         cursor.before( "2" );
149         assertInvalidCursor();
150         assertTrue( cursor.next() );
151         assertEquals( "2", cursor.get() );
152 
153         // test advances up to and past the tail end
154         cursor.after( "9" );
155         assertInvalidCursor();
156         assertFalse( cursor.next() );
157         assertTrue( cursor.previous() );
158         assertEquals( "9", cursor.get() );
159 
160         cursor.after( "a" );
161         assertInvalidCursor();
162         assertFalse( cursor.next() );
163         assertTrue( cursor.previous() );
164         assertEquals( "9", cursor.get() );
165 
166         cursor.before( "a" );
167         assertInvalidCursor();
168         assertFalse( cursor.next() );
169         assertTrue( cursor.previous() );
170         assertEquals( "9", cursor.get() );
171 
172         // test advances up to and past the head
173         cursor.before( "0" );
174         assertInvalidCursor();
175         assertFalse( cursor.previous() );
176         assertTrue( cursor.next() );
177         assertEquals( "0", cursor.get() );
178 
179         cursor.after( "*" );
180         assertInvalidCursor();
181         assertFalse( cursor.previous() );
182         assertTrue( cursor.next() );
183         assertEquals( "0", cursor.get() );
184 
185         cursor.before( "*" );
186         assertInvalidCursor();
187         assertFalse( cursor.previous() );
188         assertTrue( cursor.next() );
189         assertEquals( "0", cursor.get() );
190         
191         bt.remove( "0" );
192         bt.remove( "1" );
193         bt.remove( "2" );
194         bt.remove( "3" );
195         bt.remove( "4" );
196         bt.remove( "6" );
197         bt.remove( "7" );
198         bt.remove( "8" );
199         bt.remove( "9" );
200 
201         // now test with only one element: "5" remains now with others deleted
202         cursor.before( "5" );
203         assertInvalidCursor();
204         assertFalse( cursor.previous() );
205         assertTrue( cursor.next() );
206         assertEquals( "5", cursor.get() );
207         assertFalse( cursor.next() );
208 
209         cursor.after( "5" );
210         assertInvalidCursor();
211         assertFalse( cursor.next() );
212         assertTrue( cursor.previous() );
213         assertEquals( "5", cursor.get() );
214         assertFalse( cursor.previous() );
215     }
216 
217 
218     @Test
219     public void testJdbmBrowse() throws Exception
220     {
221         bt.remove( "0" );
222         bt.remove( "5" );
223         bt.remove( "6" );
224         bt.remove( "7" );
225         bt.remove( "9" );
226 
227         assertNull( bt.find( "0" ) );
228         assertNotNull( bt.find( "1" ) );
229         assertNotNull( bt.find( "2" ) );
230         assertNotNull( bt.find( "3" ) );
231         assertNotNull( bt.find( "4" ) );
232         assertNull( bt.find( "5" ) );
233         assertNull( bt.find( "6" ) );
234         assertNull( bt.find( "7" ) );
235         assertNotNull( bt.find( "8" ) );
236         assertNull( bt.find( "9" ) );
237 
238         // browse will position us right after "4" and getNext() will return 8
239         // since "5", "6", and "7" do not exist
240         TupleBrowser browser = bt.browse( "5" );
241         assertNotNull( browser );
242         Tuple tuple = new Tuple();
243         browser.getNext( tuple );
244         assertEquals( "8", tuple.getKey() );
245 
246         // browse will position us right after "1" and getNext() will return 2
247         // since "2" exists.
248         browser = bt.browse( "2" );
249         assertNotNull( browser );
250         tuple = new Tuple();
251         browser.getNext( tuple );
252         assertEquals( "2", tuple.getKey() );
253 
254         // browse will position us right after "8" and getNext() will null
255         // since nothing else exists past 8.  We've come to the end.
256         browser = bt.browse( "9" );
257         assertNotNull( browser );
258         tuple = new Tuple();
259         browser.getNext( tuple );
260         assertNull( tuple.getKey() );
261 
262         // browse will position us right before "1" and getPrevious() will
263         // null since nothing else exists before 1.  We've come to the end.
264         // getNext() will however return "1".
265         browser = bt.browse( "0" );
266         assertNotNull( browser );
267         tuple = new Tuple();
268         browser.getPrevious( tuple );
269         assertNull( tuple.getKey() );
270         browser.getNext( tuple );
271         assertEquals( "1", tuple.getKey() );
272     }
273 
274     
275     @Test
276     public void testMiscelleneous() throws Exception
277     {
278         // Test available()
279         
280         assertFalse( cursor.available() );
281         cursor.beforeFirst();
282         assertFalse( cursor.available() );
283         cursor.afterLast();
284         assertFalse( cursor.available() );
285         cursor.first();
286         assertTrue( cursor.available() );
287         cursor.last();
288         assertTrue( cursor.available() );
289         
290         // Test isElementReused()
291         
292         assertFalse( cursor.isElementReused() );
293     }
294     
295 
296     private void assertInvalidCursor()
297     {
298         try
299         {
300             cursor.get();
301             fail( "Invalid Cursor should not return valid value from get()" );
302         }
303         catch ( Exception e )
304         {
305             assertNotNull( e );
306         }
307     }
308 }