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.server.xdbm.search.impl;
21  
22  
23  import org.slf4j.Logger;
24  import org.slf4j.LoggerFactory;
25  import org.apache.directory.server.xdbm.Store;
26  import org.apache.directory.server.xdbm.ForwardIndexEntry;
27  import org.apache.directory.server.xdbm.IndexEntry;
28  import org.apache.directory.server.xdbm.tools.StoreUtils;
29  import org.apache.directory.server.schema.registries.*;
30  import org.apache.directory.server.schema.bootstrap.*;
31  import org.apache.directory.server.schema.SerializableComparator;
32  import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmStore;
33  import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex;
34  import org.apache.directory.server.core.cursor.InvalidCursorPositionException;
35  import org.apache.directory.server.core.entry.ServerEntry;
36  import org.apache.directory.server.core.entry.DefaultServerEntry;
37  import org.apache.directory.shared.ldap.constants.SchemaConstants;
38  import org.apache.directory.shared.ldap.filter.ScopeNode;
39  import org.apache.directory.shared.ldap.filter.SearchScope;
40  import org.apache.directory.shared.ldap.message.AliasDerefMode;
41  import org.apache.directory.shared.ldap.name.LdapDN;
42  import org.apache.commons.io.FileUtils;
43  import org.junit.Before;
44  import org.junit.After;
45  import org.junit.Test;
46  import static org.junit.Assert.assertTrue;
47  import static org.junit.Assert.assertFalse;
48  import static org.junit.Assert.assertNotNull;
49  import static org.junit.Assert.assertEquals;
50  import static org.junit.Assert.assertNull;
51  
52  import java.io.File;
53  import java.util.Set;
54  import java.util.HashSet;
55  
56  
57  /**
58   * Tests to for SubtreeScopeEvaluator and SubtreeScopeCursor.
59   *
60   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
61   * @version $$Rev$$
62   */
63  public class SubtreeScopeTest
64  {
65      public static final Logger LOG = LoggerFactory.getLogger( SubtreeScopeTest.class );
66  
67  
68      File wkdir;
69      Store<ServerEntry> store;
70      Registries registries = null;
71      AttributeTypeRegistry attributeRegistry;
72  
73  
74      public SubtreeScopeTest() throws Exception
75      {
76          // setup the standard registries
77          BootstrapSchemaLoader loader = new BootstrapSchemaLoader();
78          OidRegistry oidRegistry = new DefaultOidRegistry();
79          registries = new DefaultRegistries( "bootstrap", loader, oidRegistry );
80          SerializableComparator.setRegistry( registries.getComparatorRegistry() );
81  
82          // load essential bootstrap schemas
83          Set<Schema> bootstrapSchemas = new HashSet<Schema>();
84          bootstrapSchemas.add( new ApachemetaSchema() );
85          bootstrapSchemas.add( new ApacheSchema() );
86          bootstrapSchemas.add( new CoreSchema() );
87          bootstrapSchemas.add( new SystemSchema() );
88          bootstrapSchemas.add( new CollectiveSchema() );
89          loader.loadWithDependencies( bootstrapSchemas, registries );
90          attributeRegistry = registries.getAttributeTypeRegistry();
91      }
92  
93  
94      @Before
95      public void createStore() throws Exception
96      {
97          destryStore();
98  
99          // setup the working directory for the store
100         wkdir = File.createTempFile( getClass().getSimpleName(), "db" );
101         wkdir.delete();
102         wkdir = new File( wkdir.getParentFile(), getClass().getSimpleName() );
103         wkdir.mkdirs();
104 
105         // initialize the store
106         store = new JdbmStore<ServerEntry>();
107         store.setName( "example" );
108         store.setCacheSize( 10 );
109         store.setWorkingDirectory( wkdir );
110         store.setSyncOnWrite( true );
111 
112         store.addIndex( new JdbmIndex( SchemaConstants.OU_AT_OID ) );
113         store.addIndex( new JdbmIndex( SchemaConstants.CN_AT_OID ) );
114         StoreUtils.loadExampleData( store, registries );
115         LOG.debug( "Created new store" );
116     }
117 
118 
119     @After
120     public void destryStore() throws Exception
121     {
122         if ( store != null )
123         {
124             store.destroy();
125         }
126 
127         store = null;
128         if ( wkdir != null )
129         {
130             FileUtils.deleteDirectory( wkdir );
131         }
132 
133         wkdir = null;
134     }
135 
136 
137     @Test
138     public void testCursorNoDeref() throws Exception
139     {
140         ScopeNode node = new ScopeNode( AliasDerefMode.NEVER_DEREF_ALIASES,
141             SchemaConstants.OU_AT_OID + "=sales," +
142             SchemaConstants.O_AT_OID  + "=good times co.", SearchScope.SUBTREE);
143         SubtreeScopeEvaluator<ServerEntry> evaluator = new SubtreeScopeEvaluator<ServerEntry>( store, node );
144         SubtreeScopeCursor cursor = new SubtreeScopeCursor( store, evaluator );
145 
146         assertTrue( cursor.isElementReused() );
147 
148 
149         // --------- Test beforeFirst() ---------
150 
151         cursor.beforeFirst();
152         assertFalse( cursor.available() );
153 
154         assertTrue( cursor.next() );
155         assertTrue( cursor.available() );
156         IndexEntry<Long,ServerEntry> indexEntry = cursor.get();
157         assertNotNull( indexEntry );
158         assertEquals( 2L, ( long ) indexEntry.getId() );
159         assertEquals( 2L, ( long ) indexEntry.getValue() );
160 
161         assertTrue( cursor.next() );
162         assertTrue( cursor.available() );
163         indexEntry = cursor.get();
164         assertNotNull( indexEntry );
165         assertEquals( 5L, ( long ) indexEntry.getId() );
166         assertEquals( 2L, ( long ) indexEntry.getValue() );
167 
168         assertTrue( cursor.next() );
169         assertTrue( cursor.available() );
170         indexEntry = cursor.get();
171         assertNotNull( indexEntry );
172         assertEquals( 6L, ( long ) indexEntry.getId() );
173         assertEquals( 2L, ( long ) indexEntry.getValue() );
174 
175         assertFalse( cursor.next() );
176         assertFalse( cursor.available() );
177 
178         // --------- Test first() ---------
179 
180         cursor = new SubtreeScopeCursor( store, evaluator );
181         assertFalse( cursor.available() );
182         cursor.first();
183 
184         assertTrue( cursor.available() );
185         indexEntry = cursor.get();
186         assertNotNull( indexEntry );
187         assertEquals( 2L, ( long ) indexEntry.getId() );
188         assertEquals( 2L, ( long ) indexEntry.getValue() );
189 
190         assertTrue( cursor.next() );
191         assertTrue( cursor.available() );
192         indexEntry = cursor.get();
193         assertNotNull( indexEntry );
194         assertEquals( 5L, ( long ) indexEntry.getId() );
195         assertEquals( 2L, ( long ) indexEntry.getValue() );
196 
197         assertTrue( cursor.next() );
198         assertTrue( cursor.available() );
199         indexEntry = cursor.get();
200         assertNotNull( indexEntry );
201         assertEquals( 6L, ( long ) indexEntry.getId() );
202         assertEquals( 2L, ( long ) indexEntry.getValue() );
203 
204         assertFalse( cursor.next() );
205         assertFalse( cursor.available() );
206 
207         // --------- Test afterLast() ---------
208 
209         cursor = new SubtreeScopeCursor( store, evaluator );
210         cursor.afterLast();
211         assertFalse( cursor.available() );
212 
213         assertTrue( cursor.previous() );
214         assertTrue( cursor.available() );
215         indexEntry = cursor.get();
216         assertNotNull( indexEntry );
217         assertEquals( 6L, ( long ) indexEntry.getId() );
218         assertEquals( 2L, ( long ) indexEntry.getValue() );
219 
220         assertTrue( cursor.previous() );
221         assertTrue( cursor.available() );
222         indexEntry = cursor.get();
223         assertNotNull( indexEntry );
224         assertEquals( 5L, ( long ) indexEntry.getId() );
225         assertEquals( 2L, ( long ) indexEntry.getValue() );
226 
227         assertTrue( cursor.previous() );
228         assertTrue( cursor.available() );
229         indexEntry = cursor.get();
230         assertNotNull( indexEntry );
231         assertEquals( 2L, ( long ) indexEntry.getId() );
232         assertEquals( 2L, ( long ) indexEntry.getValue() );
233 
234         assertFalse( cursor.previous() );
235         assertFalse( cursor.available() );
236 
237         // --------- Test last() ---------
238 
239         cursor = new SubtreeScopeCursor( store, evaluator );
240         assertFalse( cursor.available() );
241         cursor.last();
242 
243         assertTrue( cursor.available() );
244         indexEntry = cursor.get();
245         assertNotNull( indexEntry );
246         assertEquals( 6L, ( long ) indexEntry.getId() );
247         assertEquals( 2L, ( long ) indexEntry.getValue() );
248 
249         assertTrue( cursor.previous() );
250         assertTrue( cursor.available() );
251         indexEntry = cursor.get();
252         assertNotNull( indexEntry );
253         assertEquals( 5L, ( long ) indexEntry.getId() );
254         assertEquals( 2L, ( long ) indexEntry.getValue() );
255 
256         assertTrue( cursor.previous() );
257         assertTrue( cursor.available() );
258         indexEntry = cursor.get();
259         assertNotNull( indexEntry );
260         assertEquals( 2L, ( long ) indexEntry.getId() );
261         assertEquals( 2L, ( long ) indexEntry.getValue() );
262 
263         assertFalse( cursor.previous() );
264         assertFalse( cursor.available() );
265 
266         // --------- Test previous() before positioning ---------
267 
268         cursor = new SubtreeScopeCursor( store, evaluator );
269         assertFalse( cursor.available() );
270         cursor.previous();
271 
272         assertTrue( cursor.available() );
273         indexEntry = cursor.get();
274         assertNotNull( indexEntry );
275         assertEquals( 6L, ( long ) indexEntry.getId() );
276         assertEquals( 2L, ( long ) indexEntry.getValue() );
277 
278         assertTrue( cursor.previous() );
279         assertTrue( cursor.available() );
280         indexEntry = cursor.get();
281         assertNotNull( indexEntry );
282         assertEquals( 5L, ( long ) indexEntry.getId() );
283         assertEquals( 2L, ( long ) indexEntry.getValue() );
284 
285         assertTrue( cursor.previous() );
286         assertTrue( cursor.available() );
287         indexEntry = cursor.get();
288         assertNotNull( indexEntry );
289         assertEquals( 2L, ( long ) indexEntry.getId() );
290         assertEquals( 2L, ( long ) indexEntry.getValue() );
291 
292         assertFalse( cursor.previous() );
293         assertFalse( cursor.available() );
294     }
295 
296 
297     @Test
298     public void testCursorWithDereferencing() throws Exception
299     {
300         ScopeNode node = new ScopeNode( AliasDerefMode.DEREF_IN_SEARCHING,
301             SchemaConstants.OU_AT_OID + "=board of directors," +
302             SchemaConstants.O_AT_OID  + "=good times co.", SearchScope.SUBTREE );
303         SubtreeScopeEvaluator<ServerEntry> evaluator = new SubtreeScopeEvaluator<ServerEntry>( store, node );
304         SubtreeScopeCursor cursor = new SubtreeScopeCursor( store, evaluator );
305 
306         assertTrue( cursor.isElementReused() );
307 
308 
309         // --------- Test beforeFirst() ---------
310 
311         cursor.beforeFirst();
312         assertFalse( cursor.available() );
313 
314         assertTrue( cursor.next() );
315         assertTrue( cursor.available() );
316         IndexEntry<Long,ServerEntry> indexEntry = cursor.get();
317         assertNotNull( indexEntry );
318         assertEquals( 3L, ( long ) indexEntry.getId() );
319         assertEquals( 3L, ( long ) indexEntry.getValue() );
320 
321         assertTrue( cursor.next() );
322         assertTrue( cursor.available() );
323         indexEntry = cursor.get();
324         assertNotNull( indexEntry );
325         assertEquals( 7L, ( long ) indexEntry.getId() );
326         assertEquals( 3L, ( long ) indexEntry.getValue() );
327 
328         assertTrue( cursor.next() );
329         assertTrue( cursor.available() );
330         indexEntry = cursor.get();
331         assertNotNull( indexEntry );
332         assertEquals( 6L, ( long ) indexEntry.getId() );
333         assertEquals( 3L, ( long ) indexEntry.getValue() );
334 
335         assertFalse( cursor.next() );
336         assertFalse( cursor.available() );
337 
338         // --------- Test first() ---------
339 
340         cursor = new SubtreeScopeCursor( store, evaluator );
341         assertFalse( cursor.available() );
342         cursor.first();
343 
344         assertTrue( cursor.available() );
345         indexEntry = cursor.get();
346         assertNotNull( indexEntry );
347         assertEquals( 3L, ( long ) indexEntry.getId() );
348         assertEquals( 3L, ( long ) indexEntry.getValue() );
349 
350         assertTrue( cursor.next() );
351         assertTrue( cursor.available() );
352         indexEntry = cursor.get();
353         assertNotNull( indexEntry );
354         assertEquals( 7L, ( long ) indexEntry.getId() );
355         assertEquals( 3L, ( long ) indexEntry.getValue() );
356 
357         assertTrue( cursor.next() );
358         assertTrue( cursor.available() );
359         indexEntry = cursor.get();
360         assertNotNull( indexEntry );
361         assertEquals( 6L, ( long ) indexEntry.getId() );
362         assertEquals( 3L, ( long ) indexEntry.getValue() );
363 
364         assertFalse( cursor.next() );
365         assertFalse( cursor.available() );
366 
367         // --------- Test afterLast() ---------
368 
369         cursor = new SubtreeScopeCursor( store, evaluator );
370         cursor.afterLast();
371         assertFalse( cursor.available() );
372 
373         assertTrue( cursor.previous() );
374         assertTrue( cursor.available() );
375         indexEntry = cursor.get();
376         assertNotNull( indexEntry );
377         assertEquals( 6L, ( long ) indexEntry.getId() );
378         assertEquals( 3L, ( long ) indexEntry.getValue() );
379 
380         assertTrue( cursor.previous() );
381         assertTrue( cursor.available() );
382         indexEntry = cursor.get();
383         assertNotNull( indexEntry );
384         assertEquals( 7L, ( long ) indexEntry.getId() );
385         assertEquals( 3L, ( long ) indexEntry.getValue() );
386 
387         assertTrue( cursor.previous() );
388         assertTrue( cursor.available() );
389         indexEntry = cursor.get();
390         assertNotNull( indexEntry );
391         assertEquals( 3L, ( long ) indexEntry.getId() );
392         assertEquals( 3L, ( long ) indexEntry.getValue() );
393 
394         assertFalse( cursor.previous() );
395         assertFalse( cursor.available() );
396 
397         // --------- Test last() ---------
398 
399         cursor = new SubtreeScopeCursor( store, evaluator );
400         assertFalse( cursor.available() );
401         cursor.last();
402 
403         assertTrue( cursor.available() );
404         indexEntry = cursor.get();
405         assertNotNull( indexEntry );
406         assertEquals( 6L, ( long ) indexEntry.getId() );
407         assertEquals( 3L, ( long ) indexEntry.getValue() );
408 
409         assertTrue( cursor.previous() );
410         assertTrue( cursor.available() );
411         indexEntry = cursor.get();
412         assertNotNull( indexEntry );
413         assertEquals( 7L, ( long ) indexEntry.getId() );
414         assertEquals( 3L, ( long ) indexEntry.getValue() );
415 
416         assertTrue( cursor.previous() );
417         assertTrue( cursor.available() );
418         indexEntry = cursor.get();
419         assertNotNull( indexEntry );
420         assertEquals( 3L, ( long ) indexEntry.getId() );
421         assertEquals( 3L, ( long ) indexEntry.getValue() );
422 
423         assertFalse( cursor.previous() );
424         assertFalse( cursor.available() );
425 
426         // --------- Test previous() before positioning ---------
427 
428         cursor = new SubtreeScopeCursor( store, evaluator );
429         assertFalse( cursor.available() );
430         cursor.previous();
431 
432         assertTrue( cursor.available() );
433         indexEntry = cursor.get();
434         assertNotNull( indexEntry );
435         assertEquals( 6L, ( long ) indexEntry.getId() );
436         assertEquals( 3L, ( long ) indexEntry.getValue() );
437 
438         assertTrue( cursor.previous() );
439         assertTrue( cursor.available() );
440         indexEntry = cursor.get();
441         assertNotNull( indexEntry );
442         assertEquals( 7L, ( long ) indexEntry.getId() );
443         assertEquals( 3L, ( long ) indexEntry.getValue() );
444 
445         assertTrue( cursor.previous() );
446         assertTrue( cursor.available() );
447         indexEntry = cursor.get();
448         assertNotNull( indexEntry );
449         assertEquals( 3L, ( long ) indexEntry.getId() );
450         assertEquals( 3L, ( long ) indexEntry.getValue() );
451 
452         assertFalse( cursor.previous() );
453         assertFalse( cursor.available() );
454 
455         // --------- Test next() before positioning ---------
456 
457         cursor = new SubtreeScopeCursor( store, evaluator );
458         assertFalse( cursor.available() );
459         cursor.next();
460 
461         assertTrue( cursor.available() );
462         indexEntry = cursor.get();
463         assertNotNull( indexEntry );
464         assertEquals( 3L, ( long ) indexEntry.getId() );
465         assertEquals( 3L, ( long ) indexEntry.getValue() );
466 
467         assertTrue( cursor.next() );
468         assertTrue( cursor.available() );
469         indexEntry = cursor.get();
470         assertNotNull( indexEntry );
471         assertEquals( 7L, ( long ) indexEntry.getId() );
472         assertEquals( 3L, ( long ) indexEntry.getValue() );
473 
474         assertTrue( cursor.next() );
475         assertTrue( cursor.available() );
476         indexEntry = cursor.get();
477         assertNotNull( indexEntry );
478         assertEquals( 6L, ( long ) indexEntry.getId() );
479         assertEquals( 3L, ( long ) indexEntry.getValue() );
480 
481         assertFalse( cursor.next() );
482         assertFalse( cursor.available() );
483     }
484 
485 
486 
487 
488     @Test
489     public void testCursorWithDereferencing2() throws Exception
490     {
491         ScopeNode node = new ScopeNode( AliasDerefMode.DEREF_IN_SEARCHING,
492             SchemaConstants.OU_AT_OID + "=apache," +
493             SchemaConstants.OU_AT_OID + "=board of directors," +
494             SchemaConstants.O_AT_OID  + "=good times co.", SearchScope.SUBTREE );
495         SubtreeScopeEvaluator<ServerEntry> evaluator = new SubtreeScopeEvaluator<ServerEntry>( store, node );
496         SubtreeScopeCursor cursor = new SubtreeScopeCursor( store, evaluator );
497 
498         assertTrue( cursor.isElementReused() );
499 
500 
501         // --------- Test beforeFirst() ---------
502 
503         cursor.beforeFirst();
504         assertFalse( cursor.available() );
505 
506         assertTrue( cursor.next() );
507         assertTrue( cursor.available() );
508         IndexEntry<Long,ServerEntry> indexEntry = cursor.get();
509         assertNotNull( indexEntry );
510         assertEquals( 7L, ( long ) indexEntry.getId() );
511         assertEquals( 7L, ( long ) indexEntry.getValue() );
512 
513         assertTrue( cursor.next() );
514         assertTrue( cursor.available() );
515         indexEntry = cursor.get();
516         assertNotNull( indexEntry );
517         assertEquals( 6L, ( long ) indexEntry.getId() );
518         assertEquals( 7L, ( long ) indexEntry.getValue() );
519 
520         assertFalse( cursor.next() );
521         assertFalse( cursor.available() );
522 
523         // --------- Test first() ---------
524 
525         cursor = new SubtreeScopeCursor( store, evaluator );
526         assertFalse( cursor.available() );
527         cursor.first();
528 
529         assertTrue( cursor.available() );
530         indexEntry = cursor.get();
531         assertNotNull( indexEntry );
532         assertEquals( 7L, ( long ) indexEntry.getId() );
533         assertEquals( 7L, ( long ) indexEntry.getValue() );
534 
535         assertTrue( cursor.next() );
536         assertTrue( cursor.available() );
537         indexEntry = cursor.get();
538         assertNotNull( indexEntry );
539         assertEquals( 6L, ( long ) indexEntry.getId() );
540         assertEquals( 7L, ( long ) indexEntry.getValue() );
541 
542         assertFalse( cursor.next() );
543         assertFalse( cursor.available() );
544 
545         // --------- Test afterLast() ---------
546 
547         cursor = new SubtreeScopeCursor( store, evaluator );
548         cursor.afterLast();
549         assertFalse( cursor.available() );
550 
551         assertTrue( cursor.previous() );
552         assertTrue( cursor.available() );
553         indexEntry = cursor.get();
554         assertNotNull( indexEntry );
555         assertEquals( 6L, ( long ) indexEntry.getId() );
556         assertEquals( 7L, ( long ) indexEntry.getValue() );
557 
558         assertTrue( cursor.previous() );
559         assertTrue( cursor.available() );
560         indexEntry = cursor.get();
561         assertNotNull( indexEntry );
562         assertEquals( 7L, ( long ) indexEntry.getId() );
563         assertEquals( 7L, ( long ) indexEntry.getValue() );
564 
565         assertFalse( cursor.previous() );
566         assertFalse( cursor.available() );
567 
568         // --------- Test last() ---------
569 
570         cursor = new SubtreeScopeCursor( store, evaluator );
571         assertFalse( cursor.available() );
572         cursor.last();
573 
574         assertTrue( cursor.available() );
575         indexEntry = cursor.get();
576         assertNotNull( indexEntry );
577         assertEquals( 6L, ( long ) indexEntry.getId() );
578         assertEquals( 7L, ( long ) indexEntry.getValue() );
579 
580         assertTrue( cursor.previous() );
581         assertTrue( cursor.available() );
582         indexEntry = cursor.get();
583         assertNotNull( indexEntry );
584         assertEquals( 7L, ( long ) indexEntry.getId() );
585         assertEquals( 7L, ( long ) indexEntry.getValue() );
586 
587         assertFalse( cursor.previous() );
588         assertFalse( cursor.available() );
589 
590         // --------- Test previous() before positioning ---------
591 
592         cursor = new SubtreeScopeCursor( store, evaluator );
593         assertFalse( cursor.available() );
594         cursor.previous();
595 
596         assertTrue( cursor.available() );
597         indexEntry = cursor.get();
598         assertNotNull( indexEntry );
599         assertEquals( 6L, ( long ) indexEntry.getId() );
600         assertEquals( 7L, ( long ) indexEntry.getValue() );
601 
602         assertTrue( cursor.previous() );
603         assertTrue( cursor.available() );
604         indexEntry = cursor.get();
605         assertNotNull( indexEntry );
606         assertEquals( 7L, ( long ) indexEntry.getId() );
607         assertEquals( 7L, ( long ) indexEntry.getValue() );
608 
609         assertFalse( cursor.previous() );
610         assertFalse( cursor.available() );
611     }
612 
613 
614     @Test
615     public void testCursorWithDereferencing3() throws Exception
616     {
617         LdapDN dn = new LdapDN(
618             SchemaConstants.CN_AT_OID + "=jd," +
619             SchemaConstants.OU_AT_OID + "=board of directors," +
620             SchemaConstants.O_AT_OID  + "=good times co."
621         );
622         dn.normalize( attributeRegistry.getNormalizerMapping() );
623 
624         ServerEntry attrs = new DefaultServerEntry( registries, dn );
625         attrs.add( "objectClass", "alias", "extensibleObject" );
626         attrs.add( "cn", "jd" );
627         attrs.add( "aliasedObjectName", "cn=Jack Daniels,ou=Engineering,o=Good Times Co." );
628         store.add( dn, attrs );
629 
630         dn = new LdapDN(
631             SchemaConstants.CN_AT_OID + "=jdoe," +
632             SchemaConstants.OU_AT_OID + "=board of directors," +
633             SchemaConstants.O_AT_OID  + "=good times co."
634         );
635         dn.normalize( attributeRegistry.getNormalizerMapping() );
636 
637         attrs = new DefaultServerEntry( registries, dn );
638         attrs.add( "objectClass", "person" );
639         attrs.add( "cn", "jdoe" );
640         attrs.add( "sn", "doe" );
641         store.add( dn, attrs );
642 
643         ScopeNode node = new ScopeNode( AliasDerefMode.DEREF_IN_SEARCHING,
644             SchemaConstants.OU_AT_OID + "=board of directors," +
645             SchemaConstants.O_AT_OID  + "=good times co.", SearchScope.SUBTREE );
646         SubtreeScopeEvaluator<ServerEntry> evaluator = new SubtreeScopeEvaluator<ServerEntry>( store, node );
647         SubtreeScopeCursor cursor = new SubtreeScopeCursor( store, evaluator );
648 
649         assertTrue( cursor.isElementReused() );
650 
651 
652         // --------- Test beforeFirst() ---------
653 
654         cursor.beforeFirst();
655         assertFalse( cursor.available() );
656 
657         assertTrue( cursor.next() );
658         assertTrue( cursor.available() );
659         IndexEntry<Long,ServerEntry> indexEntry = cursor.get();
660         assertNotNull( indexEntry );
661         assertEquals( 3L, ( long ) indexEntry.getId() );
662         assertEquals( 3L, ( long ) indexEntry.getValue() );
663 
664         assertTrue( cursor.next() );
665         assertTrue( cursor.available() );
666         indexEntry = cursor.get();
667         assertNotNull( indexEntry );
668         assertEquals( 7L, ( long ) indexEntry.getId() );
669         assertEquals( 3L, ( long ) indexEntry.getValue() );
670 
671         assertTrue( cursor.next() );
672         assertTrue( cursor.available() );
673         indexEntry = cursor.get();
674         assertNotNull( indexEntry );
675         assertEquals( 13L, ( long ) indexEntry.getId() );
676         assertEquals( 3L, ( long ) indexEntry.getValue() );
677 
678         assertTrue( cursor.next() );
679         assertTrue( cursor.available() );
680         indexEntry = cursor.get();
681         assertNotNull( indexEntry );
682         assertEquals( 6L, ( long ) indexEntry.getId() );
683         assertEquals( 3L, ( long ) indexEntry.getValue() );
684 
685         assertTrue( cursor.next() );
686         assertTrue( cursor.available() );
687         indexEntry = cursor.get();
688         assertNotNull( indexEntry );
689         assertEquals( 8L, ( long ) indexEntry.getId() );
690         assertEquals( 3L, ( long ) indexEntry.getValue() );
691 
692         assertFalse( cursor.next() );
693         assertFalse( cursor.available() );
694 
695         // --------- Test first() ---------
696 
697         cursor = new SubtreeScopeCursor( store, evaluator );
698         assertFalse( cursor.available() );
699         cursor.first();
700 
701         assertTrue( cursor.next() );
702         assertTrue( cursor.available() );
703         indexEntry = cursor.get();
704         assertNotNull( indexEntry );
705         assertEquals( 7L, ( long ) indexEntry.getId() );
706         assertEquals( 3L, ( long ) indexEntry.getValue() );
707 
708         assertTrue( cursor.next() );
709         assertTrue( cursor.available() );
710         indexEntry = cursor.get();
711         assertNotNull( indexEntry );
712         assertEquals( 13L, ( long ) indexEntry.getId() );
713         assertEquals( 3L, ( long ) indexEntry.getValue() );
714 
715         assertTrue( cursor.next() );
716         assertTrue( cursor.available() );
717         indexEntry = cursor.get();
718         assertNotNull( indexEntry );
719         assertEquals( 6L, ( long ) indexEntry.getId() );
720         assertEquals( 3L, ( long ) indexEntry.getValue() );
721 
722         assertTrue( cursor.next() );
723         assertTrue( cursor.available() );
724         indexEntry = cursor.get();
725         assertNotNull( indexEntry );
726         assertEquals( 8L, ( long ) indexEntry.getId() );
727         assertEquals( 3L, ( long ) indexEntry.getValue() );
728 
729         assertFalse( cursor.next() );
730         assertFalse( cursor.available() );
731 
732         // --------- Test afterLast() ---------
733 
734         cursor = new SubtreeScopeCursor( store, evaluator );
735         cursor.afterLast();
736         assertFalse( cursor.available() );
737 
738         assertTrue( cursor.previous() );
739         assertTrue( cursor.available() );
740         indexEntry = cursor.get();
741         assertNotNull( indexEntry );
742         assertEquals( 8L, ( long ) indexEntry.getId() );
743         assertEquals( 3L, ( long ) indexEntry.getValue() );
744 
745         assertTrue( cursor.previous() );
746         assertTrue( cursor.available() );
747         indexEntry = cursor.get();
748         assertNotNull( indexEntry );
749         assertEquals( 6L, ( long ) indexEntry.getId() );
750         assertEquals( 3L, ( long ) indexEntry.getValue() );
751 
752         assertTrue( cursor.previous() );
753         assertTrue( cursor.available() );
754         indexEntry = cursor.get();
755         assertNotNull( indexEntry );
756         assertEquals( 13L, ( long ) indexEntry.getId() );
757         assertEquals( 3L, ( long ) indexEntry.getValue() );
758 
759         assertTrue( cursor.previous() );
760         assertTrue( cursor.available() );
761         indexEntry = cursor.get();
762         assertNotNull( indexEntry );
763         assertEquals( 7L, ( long ) indexEntry.getId() );
764         assertEquals( 3L, ( long ) indexEntry.getValue() );
765 
766         assertTrue( cursor.previous() );
767         assertTrue( cursor.available() );
768         indexEntry = cursor.get();
769         assertNotNull( indexEntry );
770         assertEquals( 3L, ( long ) indexEntry.getId() );
771         assertEquals( 3L, ( long ) indexEntry.getValue() );
772 
773         assertFalse( cursor.previous() );
774         assertFalse( cursor.available() );
775 
776         // --------- Test last() ---------
777 
778         cursor = new SubtreeScopeCursor( store, evaluator );
779         assertFalse( cursor.available() );
780         cursor.last();
781 
782         assertTrue( cursor.available() );
783         indexEntry = cursor.get();
784         assertNotNull( indexEntry );
785         assertEquals( 8L, ( long ) indexEntry.getId() );
786         assertEquals( 3L, ( long ) indexEntry.getValue() );
787 
788         assertTrue( cursor.previous() );
789         assertTrue( cursor.available() );
790         indexEntry = cursor.get();
791         assertNotNull( indexEntry );
792         assertEquals( 6L, ( long ) indexEntry.getId() );
793         assertEquals( 3L, ( long ) indexEntry.getValue() );
794 
795         assertTrue( cursor.previous() );
796         assertTrue( cursor.available() );
797         indexEntry = cursor.get();
798         assertNotNull( indexEntry );
799         assertEquals( 13L, ( long ) indexEntry.getId() );
800         assertEquals( 3L, ( long ) indexEntry.getValue() );
801 
802         assertTrue( cursor.previous() );
803         assertTrue( cursor.available() );
804         indexEntry = cursor.get();
805         assertNotNull( indexEntry );
806         assertEquals( 7L, ( long ) indexEntry.getId() );
807         assertEquals( 3L, ( long ) indexEntry.getValue() );
808 
809         assertTrue( cursor.previous() );
810         assertTrue( cursor.available() );
811         indexEntry = cursor.get();
812         assertNotNull( indexEntry );
813         assertEquals( 3L, ( long ) indexEntry.getId() );
814         assertEquals( 3L, ( long ) indexEntry.getValue() );
815 
816         assertFalse( cursor.previous() );
817         assertFalse( cursor.available() );
818 
819         // --------- Test previous() before positioning ---------
820 
821         cursor = new SubtreeScopeCursor( store, evaluator );
822         assertFalse( cursor.available() );
823         cursor.previous();
824 
825         assertTrue( cursor.available() );
826         indexEntry = cursor.get();
827         assertNotNull( indexEntry );
828         assertEquals( 8L, ( long ) indexEntry.getId() );
829         assertEquals( 3L, ( long ) indexEntry.getValue() );
830 
831         assertTrue( cursor.previous() );
832         assertTrue( cursor.available() );
833         indexEntry = cursor.get();
834         assertNotNull( indexEntry );
835         assertEquals( 6L, ( long ) indexEntry.getId() );
836         assertEquals( 3L, ( long ) indexEntry.getValue() );
837 
838         assertTrue( cursor.previous() );
839         assertTrue( cursor.available() );
840         indexEntry = cursor.get();
841         assertNotNull( indexEntry );
842         assertEquals( 13L, ( long ) indexEntry.getId() );
843         assertEquals( 3L, ( long ) indexEntry.getValue() );
844 
845         assertTrue( cursor.previous() );
846         assertTrue( cursor.available() );
847         indexEntry = cursor.get();
848         assertNotNull( indexEntry );
849         assertEquals( 7L, ( long ) indexEntry.getId() );
850         assertEquals( 3L, ( long ) indexEntry.getValue() );
851 
852         assertTrue( cursor.previous() );
853         assertTrue( cursor.available() );
854         indexEntry = cursor.get();
855         assertNotNull( indexEntry );
856         assertEquals( 3L, ( long ) indexEntry.getId() );
857         assertEquals( 3L, ( long ) indexEntry.getValue() );
858 
859         assertFalse( cursor.previous() );
860         assertFalse( cursor.available() );
861 
862         // --------- Test next() before positioning ---------
863 
864         cursor = new SubtreeScopeCursor( store, evaluator );
865         assertFalse( cursor.available() );
866         cursor.next();
867 
868         assertTrue( cursor.available() );
869         indexEntry = cursor.get();
870         assertNotNull( indexEntry );
871         assertEquals( 3L, ( long ) indexEntry.getId() );
872         assertEquals( 3L, ( long ) indexEntry.getValue() );
873 
874         assertTrue( cursor.next() );
875         assertTrue( cursor.available() );
876         indexEntry = cursor.get();
877         assertNotNull( indexEntry );
878         assertEquals( 7L, ( long ) indexEntry.getId() );
879         assertEquals( 3L, ( long ) indexEntry.getValue() );
880 
881         assertTrue( cursor.next() );
882         assertTrue( cursor.available() );
883         indexEntry = cursor.get();
884         assertNotNull( indexEntry );
885         assertEquals( 13L, ( long ) indexEntry.getId() );
886         assertEquals( 3L, ( long ) indexEntry.getValue() );
887 
888         assertTrue( cursor.next() );
889         assertTrue( cursor.available() );
890         indexEntry = cursor.get();
891         assertNotNull( indexEntry );
892         assertEquals( 6L, ( long ) indexEntry.getId() );
893         assertEquals( 3L, ( long ) indexEntry.getValue() );
894 
895         assertTrue( cursor.next() );
896         assertTrue( cursor.available() );
897         indexEntry = cursor.get();
898         assertNotNull( indexEntry );
899         assertEquals( 8L, ( long ) indexEntry.getId() );
900         assertEquals( 3L, ( long ) indexEntry.getValue() );
901 
902         assertFalse( cursor.next() );
903         assertFalse( cursor.available() );
904     }
905 
906 
907     @Test
908     public void testEvaluatorNoDereferencing() throws Exception
909     {
910         ScopeNode node = new ScopeNode( AliasDerefMode.NEVER_DEREF_ALIASES,
911             SchemaConstants.OU_AT_OID + "=sales," +
912             SchemaConstants.O_AT_OID  + "=good times co.", SearchScope.SUBTREE );
913         SubtreeScopeEvaluator<ServerEntry> evaluator = new SubtreeScopeEvaluator<ServerEntry>( store, node );
914 
915         ForwardIndexEntry<Long,ServerEntry> indexEntry = new ForwardIndexEntry<Long,ServerEntry>();
916         indexEntry.setId( 6L );
917         assertTrue( evaluator.evaluate( indexEntry ) );
918     }
919 
920 
921     @Test
922     public void testEvaluatorWithDereferencing() throws Exception
923     {
924         ScopeNode node = new ScopeNode( AliasDerefMode.DEREF_ALWAYS,
925             SchemaConstants.OU_AT_OID + "=engineering," +
926             SchemaConstants.O_AT_OID  + "=good times co.", SearchScope.SUBTREE );
927         SubtreeScopeEvaluator<ServerEntry> evaluator = new SubtreeScopeEvaluator<ServerEntry>( store, node );
928         assertEquals( node, evaluator.getExpression() );
929 
930         /*
931          * With dereferencing the evaluator does not accept candidates that
932          * are aliases.  This is done to filter out aliases from the results.
933          */
934         ForwardIndexEntry<Long,ServerEntry> indexEntry = new ForwardIndexEntry<Long,ServerEntry>();
935         indexEntry.setId( 11L );
936         assertFalse( evaluator.evaluate( indexEntry ) );
937 
938         indexEntry = new ForwardIndexEntry<Long,ServerEntry>();
939         indexEntry.setId( 8L );
940         assertTrue( evaluator.evaluate( indexEntry ) );
941 
942         indexEntry = new ForwardIndexEntry<Long,ServerEntry>();
943         indexEntry.setId( 6L );
944         assertFalse( evaluator.evaluate( indexEntry ) );
945     }
946 
947 
948     @Test ( expected = InvalidCursorPositionException.class )
949     public void testInvalidCursorPositionException() throws Exception
950     {
951         ScopeNode node = new ScopeNode( AliasDerefMode.NEVER_DEREF_ALIASES,
952             SchemaConstants.OU_AT_OID + "=sales," +
953             SchemaConstants.O_AT_OID  + "=good times co.", SearchScope.SUBTREE );
954         SubtreeScopeEvaluator<ServerEntry> evaluator = new SubtreeScopeEvaluator<ServerEntry>( store, node );
955         SubtreeScopeCursor cursor = new SubtreeScopeCursor( store, evaluator );
956         cursor.get();
957     }
958 
959 
960     @Test ( expected = UnsupportedOperationException.class )
961     public void testUnsupportBeforeWithoutIndex() throws Exception
962     {
963         ScopeNode node = new ScopeNode( AliasDerefMode.NEVER_DEREF_ALIASES,
964             SchemaConstants.OU_AT_OID + "=sales," +
965             SchemaConstants.O_AT_OID  + "=good times co.", SearchScope.SUBTREE );
966         SubtreeScopeEvaluator<ServerEntry> evaluator = new SubtreeScopeEvaluator<ServerEntry>( store, node );
967         SubtreeScopeCursor cursor = new SubtreeScopeCursor( store, evaluator );
968 
969         // test before()
970         ForwardIndexEntry<Long,ServerEntry> entry = new ForwardIndexEntry<Long,ServerEntry>();
971         entry.setValue( 3L );
972         cursor.before( entry );
973     }
974 
975 
976     @Test ( expected = UnsupportedOperationException.class )
977     public void testUnsupportAfterWithoutIndex() throws Exception
978     {
979         ScopeNode node = new ScopeNode( AliasDerefMode.NEVER_DEREF_ALIASES,
980             SchemaConstants.OU_AT_OID + "=sales," +
981             SchemaConstants.O_AT_OID  + "=good times co.", SearchScope.SUBTREE );
982         SubtreeScopeEvaluator<ServerEntry> evaluator = new SubtreeScopeEvaluator<ServerEntry>( store, node );
983         SubtreeScopeCursor cursor = new SubtreeScopeCursor( store, evaluator );
984 
985         // test after()
986         ForwardIndexEntry<Long,ServerEntry> entry = new ForwardIndexEntry<Long,ServerEntry>();
987         entry.setValue( 3L );
988         cursor.after( entry );
989     }
990 
991 
992     @Test ( expected = IllegalStateException.class )
993     public void testIllegalStateBadScope() throws Exception
994     {
995         ScopeNode node = new ScopeNode( AliasDerefMode.NEVER_DEREF_ALIASES,
996             SchemaConstants.OU_AT_OID + "=sales," +
997             SchemaConstants.O_AT_OID  + "=good times co.", SearchScope.ONELEVEL );
998         SubtreeScopeEvaluator<ServerEntry> evaluator = new SubtreeScopeEvaluator<ServerEntry>( store, node );
999         assertNull( evaluator );
1000     }
1001 }