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.slf4j.Logger;
23  import org.slf4j.LoggerFactory;
24  import org.junit.Before;
25  import org.junit.After;
26  import org.junit.Test;
27  import static org.junit.Assert.*;
28  
29  import org.apache.directory.server.xdbm.Table;
30  import org.apache.directory.server.schema.SerializableComparator;
31  import org.apache.directory.server.schema.registries.ComparatorRegistry;
32  import org.apache.directory.shared.ldap.schema.syntax.ComparatorDescription;
33  
34  import java.io.File;
35  import java.util.Comparator;
36  import java.util.Iterator;
37  
38  import jdbm.RecordManager;
39  import jdbm.recman.BaseRecordManager;
40  
41  import javax.naming.NamingException;
42  
43  
44  /**
45   * Document me!
46   *
47   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
48   * @version $Rev$, $Date$
49   */
50  public class JdbmTableNoDuplicatesTest
51  {
52      private static final Logger LOG = LoggerFactory.getLogger( JdbmTableNoDuplicatesTest.class.getSimpleName() );
53      private static final String TEST_OUTPUT_PATH = "test.output.path";
54  
55      transient Table<Integer,Integer> table;
56      transient File dbFile;
57      transient RecordManager recman;
58  
59  
60      @Before
61      public void createTable() throws Exception
62      {
63          destryTable();
64          File tmpDir = null;
65          if ( System.getProperty( TEST_OUTPUT_PATH, null ) != null )
66          {
67              tmpDir = new File( System.getProperty( TEST_OUTPUT_PATH ) );
68          }
69  
70          dbFile = File.createTempFile( getClass().getSimpleName(), "db", tmpDir );
71          recman = new BaseRecordManager( dbFile.getAbsolutePath() );
72  
73          // gosh this is a terrible use of a global static variable
74          SerializableComparator.setRegistry( new MockComparatorRegistry() );
75          table = new JdbmTable<Integer,Integer>( "test", recman, new SerializableComparator<Integer>( "" ), null, null );
76          LOG.debug( "Created new table and populated it with data" );
77      }
78  
79  
80      @After
81      public void destryTable() throws Exception
82      {
83          if ( table != null )
84          {
85              table.close();
86          }
87  
88          table = null;
89  
90          if ( recman != null )
91          {
92              recman.close();
93          }
94  
95          recman = null;
96  
97          if ( dbFile != null )
98          {
99              String fileToDelete = dbFile.getAbsolutePath();
100             new File( fileToDelete + ".db" ).delete();
101             new File( fileToDelete + ".lg" ).delete();
102 
103             dbFile.delete();
104         }
105         
106         dbFile = null;
107     }
108     
109 
110     @Test
111     public void testCloseReopen() throws Exception
112     {
113         table.put( 1, 2 );
114         table.close();
115         table = new JdbmTable<Integer,Integer>( "test", recman, new SerializableComparator<Integer>( "" ), null, null );
116         assertTrue( 2 == table.get( 1 ) );
117     }
118 
119     
120     @Test 
121     public void testConfigMethods() throws Exception
122     {
123         assertFalse( table.isDupsEnabled() );
124         assertEquals( "test", table.getName() );
125         assertNotNull( table.getKeyComparator() );
126     }
127 
128     
129     @Test
130     public void testWhenEmpty() throws Exception
131     {
132         // Test the count methods
133         assertEquals( 0, table.count() );
134         assertEquals( 0, table.count( 1 ) );
135 
136         // Test get method
137         assertNull( table.get( 0 ) );
138         
139         // Test remove methods
140         table.remove( 1 );
141         assertNull( table.get( 1 ) );
142         
143         // Test has operations
144         assertFalse( table.has( 1 ) );
145         assertFalse( table.has( 1, 0 ) );
146         assertFalse( table.hasGreaterOrEqual( 1 ) );
147         assertFalse( table.hasLessOrEqual( 1 ) );
148 
149         try
150         {
151             assertFalse( table.hasGreaterOrEqual( 1, 0 ) );
152             fail( "Should never get here." );
153         }
154         catch ( UnsupportedOperationException e )
155         {
156         }
157 
158         try
159         {
160             assertFalse( table.hasLessOrEqual( 1, 0 ) );
161             fail( "Should never get here." );
162         }
163         catch ( UnsupportedOperationException e )
164         {
165         }
166     }
167 
168     
169     @Test
170     public void testLoadData() throws Exception
171     {
172         // add some data to it
173         for ( int ii = 0; ii < 10; ii++ )
174         {
175             table.put( ii, ii );
176         }
177         
178         assertEquals( 10, table.count() );
179         assertEquals( 1, table.count( 0 ) );
180         
181         /*
182          * If counts are exact then we can test for exact values.  Again this 
183          * is not a critical function but one used for optimization so worst 
184          * case guesses are allowed.
185          */
186         
187         if ( table.isCountExact() )
188         {
189             assertEquals( 5, table.lessThanCount( 5 ) );
190             assertEquals( 4, table.greaterThanCount( 5 ) );
191         }
192         else
193         {
194             assertEquals( 10, table.lessThanCount( 5 ) );
195             assertEquals( 10, table.greaterThanCount( 5 ) );
196         }
197     }
198     
199     
200     /**
201      * Let's test keys with a null or lack of any values.
202      * @throws Exception on error
203      */
204     @Test
205     public void testNullOrEmptyKeyValue() throws Exception
206     {
207         assertEquals( 0, table.count() );
208         
209         try
210         {
211             table.put( 1, null );
212             fail( "should never get here due to IllegalArgumentException" );
213         }
214         catch( IllegalArgumentException e )
215         {
216             assertNotNull( e );
217         }
218         
219         try
220         {
221             table.put( null, 2 );
222             fail( "should never get here due to IllegalArgumentException" );
223         }
224         catch( IllegalArgumentException e )
225         {
226             assertNotNull( e );
227         }
228         
229         assertEquals( 0, table.count() );
230         assertEquals( null, table.get( 1 ) );
231         
232         // Let's add the key with a valid value and remove just the value
233         assertEquals( 0, table.count( 1 ) );
234         table.remove( 1 );
235         assertEquals( 0, table.count( 1 ) );
236         table.put( 1, 1 );
237         assertEquals( 1, table.count( 1 ) );
238         table.remove( 1, 1 );
239         assertEquals( 0, table.count( 1 ) );
240         assertNull( table.get( 1 ) );
241         assertFalse( table.has( 1 ) );
242     }
243     
244 
245     @Test
246     public void testRemove() throws Exception
247     {
248         table.put( 1, 1 );
249         table.remove( 1 );
250         assertNull( table.get( 1 ) );
251 
252         table.put( 10, 10 );
253         
254         table.remove( 10, 11 );
255         assertFalse( table.has( 10, 11 ) );
256         
257 //        assertNull( table.remove( null ) );
258 //        assertNull( table.remove( null, null ) );
259     }
260 
261 
262     @Test
263     public void testPut() throws Exception
264     {
265         final int SIZE = 15;
266 
267         for ( int ii = 0; ii < SIZE; ii++ )
268         {
269             table.put( ii, ii );
270         }
271         assertEquals( SIZE, table.count() );
272         table.put( 0, 0 );
273         assertTrue( table.has( 0, 0 ) );
274     }
275     
276 
277     @Test
278     public void testHas() throws Exception
279     {
280         assertFalse( table.has( 1 ) );
281         final int SIZE = 15;
282         
283         for ( int ii = 0; ii < SIZE; ii++ )
284         {
285             table.put( ii, ii );
286         }
287         assertEquals( SIZE, table.count() );
288 
289         assertFalse( table.has( -1 ) );
290         assertTrue( table.hasGreaterOrEqual( -1 ) );
291         assertFalse( table.hasLessOrEqual( -1 ) );
292         
293         assertTrue( table.has( 0 ) );
294         assertTrue( table.hasGreaterOrEqual( 0 ) );
295         assertTrue( table.hasLessOrEqual( 0 ) );
296         
297         assertTrue( table.has( SIZE - 1 ) );
298         assertTrue( table.hasGreaterOrEqual( SIZE - 1 ) );
299         assertTrue( table.hasLessOrEqual( SIZE - 1 ) );
300         
301         assertFalse( table.has( SIZE ) );
302         assertFalse( table.hasGreaterOrEqual( SIZE ) );
303         assertTrue( table.hasLessOrEqual( SIZE ) );
304         table.remove( 10 );
305         table.remove( 11 );
306         assertTrue( table.hasLessOrEqual( 11 ) );
307         
308         try
309         {
310             assertFalse( table.hasGreaterOrEqual( 1, 1 ) );
311             fail( "Should never get here." );
312         }
313         catch ( UnsupportedOperationException e )
314         {
315         }
316 
317         try
318         {
319             assertFalse( table.hasLessOrEqual( 1, 1 ) );
320             fail( "Should never get here." );
321         }
322         catch ( UnsupportedOperationException e )
323         {
324         }
325 
326         try
327         {
328             assertTrue( table.hasLessOrEqual( 1, 2 ) );
329             fail( "Should never get here since no dups tables " +
330             		"freak when they cannot find a value comparator" );
331         } 
332         catch ( UnsupportedOperationException e )
333         {
334             assertNotNull( e );
335         }
336     }
337     
338     
339     private class MockComparatorRegistry implements ComparatorRegistry
340     {
341         private Comparator comparator = new Comparator<Integer>()
342         {
343             public int compare( Integer i1, Integer i2 )
344             {
345                 return i1.compareTo( i2 );
346             }
347         };
348         
349 
350         public String getSchemaName( String oid ) throws NamingException
351         {
352             return null;
353         }
354 
355 
356         public void register( ComparatorDescription description, Comparator comparator ) throws NamingException
357         {
358         }
359 
360 
361         public Comparator lookup( String oid ) throws NamingException
362         {
363             return comparator;
364         }
365 
366 
367         public boolean hasComparator( String oid )
368         {
369             return true;
370         }
371 
372 
373         public Iterator<String> oidIterator()
374         {
375             return null;
376         }
377 
378 
379         public Iterator<ComparatorDescription> comparatorDescriptionIterator()
380         {
381             return null;
382         }
383 
384 
385         public void unregister( String oid ) throws NamingException
386         {
387         }
388 
389 
390         public void unregisterSchemaElements( String schemaName )
391         {
392         }
393 
394 
395         public void renameSchema( String originalSchemaName, String newSchemaName )
396         {
397         }
398     }
399 }