1   /*
2    *   Copyright 2004 The Apache Software Foundation
3    *
4    *   Licensed under the Apache License, Version 2.0 (the "License");
5    *   you may not use this file except in compliance with the License.
6    *   You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *   Unless required by applicable law or agreed to in writing, software
11   *   distributed under the License is distributed on an "AS IS" BASIS,
12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *   See the License for the specific language governing permissions and
14   *   limitations under the License.
15   *
16   */
17  package org.apache.ldap.server.exception;
18  
19  
20  import javax.naming.Context;
21  import javax.naming.NamingEnumeration;
22  import javax.naming.NamingException;
23  import javax.naming.directory.Attribute;
24  import javax.naming.directory.Attributes;
25  import javax.naming.directory.BasicAttribute;
26  import javax.naming.directory.BasicAttributes;
27  import javax.naming.directory.DirContext;
28  import javax.naming.directory.ModificationItem;
29  import javax.naming.directory.SearchControls;
30  import javax.naming.directory.SearchResult;
31  import javax.naming.ldap.LdapContext;
32  
33  import org.apache.ldap.common.exception.LdapContextNotEmptyException;
34  import org.apache.ldap.common.exception.LdapNameAlreadyBoundException;
35  import org.apache.ldap.common.exception.LdapNameNotFoundException;
36  import org.apache.ldap.common.exception.LdapNamingException;
37  import org.apache.ldap.common.message.ResultCodeEnum;
38  import org.apache.ldap.server.AbstractAdminTestCase;
39  
40  
41  /***
42   * Tests the correct operation of the ServerExceptionService.
43   *
44   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
45   * @version $Rev: 264732 $
46   */
47  public class ExceptionServiceTest extends AbstractAdminTestCase
48  {
49      // ------------------------------------------------------------------------
50      // Search Operation Tests
51      // ------------------------------------------------------------------------
52  
53  
54      /***
55       * Test search operation failure when the search base is non-existant.
56       */
57      public void testFailSearchNoSuchObject() throws NamingException
58      {
59          SearchControls ctls = new SearchControls();
60          try
61          {
62              sysRoot.search( "ou=blah", "(objectClass=*)", ctls );
63              fail( "Execution should never get here due to exception!" );
64          }
65          catch( LdapNameNotFoundException e )
66          {
67              assertEquals( "ou=system", e.getResolvedName().toString() );
68              assertEquals( ResultCodeEnum.NOSUCHOBJECT, e.getResultCode() );
69          }
70      }
71  
72  
73      /***
74       * Search operation control to test if normal search operations occur
75       * correctly.
76       */
77      public void testSearchControl() throws NamingException
78      {
79          SearchControls ctls = new SearchControls();
80          NamingEnumeration list = sysRoot.search( "ou=users", "(objectClass=*)", ctls );
81  
82          if ( list.hasMore() )
83          {
84              SearchResult result = ( SearchResult ) list.next();
85              assertNotNull( result.getAttributes() );
86              assertEquals( "uid=akarasulu,ou=users,ou=system", result.getName().toString() );
87          }
88  
89          assertFalse( list.hasMore() );
90      }
91  
92  
93      // ------------------------------------------------------------------------
94      // Move Operation Tests
95      // ------------------------------------------------------------------------
96  
97  
98      /***
99       * Test move operation failure when the object moved is non-existant.
100      */
101     public void testFailMoveEntryAlreadyExists() throws NamingException
102     {
103         try
104         {
105             sysRoot.createSubcontext( "ou=users,ou=groups" );
106             sysRoot.rename( "ou=users", "ou=users,ou=groups" );
107             fail( "Execution should never get here due to exception!" );
108         }
109         catch( LdapNameAlreadyBoundException e )
110         {
111             assertEquals( "ou=users,ou=groups,ou=system", e.getResolvedName().toString() );
112             assertEquals( ResultCodeEnum.ENTRYALREADYEXISTS, e.getResultCode() );
113         }
114 
115         try
116         {
117             sysRoot.createSubcontext( "ou=uzerz,ou=groups" );
118             sysRoot.addToEnvironment( "java.naming.ldap.deleteRDN", "false" );
119             sysRoot.rename( "ou=users", "ou=uzerz,ou=groups" );
120             sysRoot.removeFromEnvironment( "java.naming.ldap.deleteRDN" );
121             fail( "Execution should never get here due to exception!" );
122         }
123         catch( LdapNameAlreadyBoundException e )
124         {
125             assertEquals( "ou=uzerz,ou=groups,ou=system", e.getResolvedName().toString() );
126             assertEquals( ResultCodeEnum.ENTRYALREADYEXISTS, e.getResultCode() );
127         }
128     }
129 
130 
131     /***
132      * Test move operation failure when the object moved is non-existant.
133      */
134     public void testFailMoveNoSuchObject() throws NamingException
135     {
136         try
137         {
138             sysRoot.rename( "ou=blah", "ou=blah,ou=groups" );
139             fail( "Execution should never get here due to exception!" );
140         }
141         catch( LdapNameNotFoundException e )
142         {
143             assertEquals( "ou=system", e.getResolvedName().toString() );
144             assertEquals( ResultCodeEnum.NOSUCHOBJECT, e.getResultCode() );
145         }
146 
147         try
148         {
149             sysRoot.addToEnvironment( "java.naming.ldap.deleteRDN", "false" );
150             sysRoot.rename( "ou=blah", "ou=blah2,ou=groups" );
151             sysRoot.removeFromEnvironment( "java.naming.ldap.deleteRDN" );
152             fail( "Execution should never get here due to exception!" );
153         }
154         catch( LdapNameNotFoundException e )
155         {
156             assertEquals( "ou=system", e.getResolvedName().toString() );
157             assertEquals( ResultCodeEnum.NOSUCHOBJECT, e.getResultCode() );
158         }
159     }
160 
161 
162     /***
163      * Move operation control to test if normal move operations occur
164      * correctly.
165      */
166     public void testMoveControl() throws NamingException
167     {
168         sysRoot.rename( "ou=users", "ou=users,ou=groups" );
169         assertNotNull( sysRoot.lookup( "ou=users,ou=groups" ) );
170 
171         try
172         {
173             sysRoot.lookup( "ou=users" );
174             fail( "Execution should never get here due to exception!" );
175         }
176         catch( NamingException e )
177         {
178             assertEquals( "ou=system", e.getResolvedName().toString() );
179             assertTrue( e instanceof LdapNameNotFoundException );
180         }
181     }
182 
183 
184     // ------------------------------------------------------------------------
185     // ModifyRdn Operation Tests
186     // ------------------------------------------------------------------------
187 
188     /***
189      * Test modifyRdn operation failure when the object renamed is non-existant.
190      */
191     public void testFailModifyRdnEntryAlreadyExists() throws NamingException
192     {
193         try
194         {
195             sysRoot.rename( "ou=users", "ou=groups" );
196             fail( "Execution should never get here due to exception!" );
197         }
198         catch( LdapNameAlreadyBoundException e )
199         {
200             assertEquals( "ou=groups,ou=system", e.getResolvedName().toString() );
201             assertEquals( ResultCodeEnum.ENTRYALREADYEXISTS, e.getResultCode() );
202         }
203     }
204 
205 
206     /***
207      * Test modifyRdn operation failure when the object renamed is non-existant.
208      */
209     public void testFailModifyRdnNoSuchObject() throws NamingException
210     {
211         try
212         {
213             sysRoot.rename( "ou=blah", "ou=asdf" );
214             fail( "Execution should never get here due to exception!" );
215         }
216         catch( LdapNameNotFoundException e )
217         {
218             assertEquals( "ou=system", e.getResolvedName().toString() );
219             assertEquals( ResultCodeEnum.NOSUCHOBJECT, e.getResultCode() );
220         }
221     }
222 
223 
224     /***
225      * Modify operation control to test if normal modify operations occur
226      * correctly.
227      */
228     public void testModifyRdnControl() throws NamingException
229     {
230         sysRoot.rename( "ou=users", "ou=asdf" );
231         assertNotNull( sysRoot.lookup( "ou=asdf" ) );
232 
233         try
234         {
235             sysRoot.lookup( "ou=users" );
236             fail( "Execution should never get here due to exception!" );
237         }
238         catch( NamingException e )
239         {
240             assertEquals( "ou=system", e.getResolvedName().toString() );
241             assertTrue( e instanceof LdapNameNotFoundException );
242         }
243     }
244 
245 
246     // ------------------------------------------------------------------------
247     // Modify Operation Tests
248     // ------------------------------------------------------------------------
249 
250     /***
251      * Test modify operation failure when the object modified is non-existant.
252      */
253     public void testFailModifyNoSuchObject() throws NamingException
254     {
255         Attributes attrs = new BasicAttributes( true );
256         Attribute ou = new BasicAttribute( "ou" );
257         ou.add( "users" );
258         ou.add( "dummyValue" );
259         attrs.put( ou );
260 
261         try
262         {
263             sysRoot.modifyAttributes( "ou=blah", DirContext.ADD_ATTRIBUTE, attrs );
264             fail( "Execution should never get here due to exception!" );
265         }
266         catch( LdapNameNotFoundException e )
267         {
268             assertEquals( "ou=system", e.getResolvedName().toString() );
269             assertEquals( ResultCodeEnum.NOSUCHOBJECT, e.getResultCode() );
270         }
271 
272 
273         ModificationItem[] mods = new ModificationItem[] {
274             new ModificationItem( DirContext.ADD_ATTRIBUTE, ou )
275         };
276 
277         try
278         {
279             sysRoot.modifyAttributes( "ou=blah", mods );
280             fail( "Execution should never get here due to exception!" );
281         }
282         catch( LdapNameNotFoundException e )
283         {
284             assertEquals( "ou=system", e.getResolvedName().toString() );
285             assertEquals( ResultCodeEnum.NOSUCHOBJECT, e.getResultCode() );
286         }
287     }
288 
289 
290     /***
291      * Modify operation control to test if normal modify operations occur
292      * correctly.
293      */
294     public void testModifyControl() throws NamingException
295     {
296         Attributes attrs = new BasicAttributes( true );
297         Attribute attr = new BasicAttribute( "ou" );
298         attr.add( "users" );
299         attr.add( "dummyValue" );
300         attrs.put( attr );
301         sysRoot.modifyAttributes( "ou=users", DirContext.ADD_ATTRIBUTE, attrs );
302         Attribute ou = sysRoot.getAttributes( "ou=users" ).get( "ou" );
303         assertTrue( ou.contains( "users" ) );
304         assertTrue( ou.contains( "dummyValue" ) );
305 
306         attr.add( "another" );
307         ModificationItem[] mods = new ModificationItem[] {
308             new ModificationItem( DirContext.ADD_ATTRIBUTE, attr )
309         };
310 
311         sysRoot.modifyAttributes( "ou=users", mods );
312         ou = sysRoot.getAttributes( "ou=users" ).get( "ou" );
313         assertTrue( ou.contains( "users" ) );
314         assertTrue( ou.contains( "dummyValue" ) );
315         assertTrue( ou.contains( "another" ) );
316     }
317 
318 
319     // ------------------------------------------------------------------------
320     // Lookup Operation Tests
321     // ------------------------------------------------------------------------
322 
323     /***
324      * Test lookup operation failure when the object looked up is non-existant.
325      */
326     public void testFailLookupNoSuchObject() throws NamingException
327     {
328         try
329         {
330             sysRoot.lookup( "ou=blah" );
331             fail( "Execution should never get here due to exception!" );
332         }
333         catch( LdapNameNotFoundException e )
334         {
335             assertEquals( "ou=system", e.getResolvedName().toString() );
336             assertEquals( ResultCodeEnum.NOSUCHOBJECT, e.getResultCode() );
337         }
338     }
339 
340 
341     /***
342      * Lookup operation control to test if normal lookup operations occur
343      * correctly.
344      */
345     public void testLookupControl() throws NamingException
346     {
347         LdapContext ctx = ( LdapContext ) sysRoot.lookup( "ou=users" );
348         assertNotNull( ctx );
349         assertEquals( "users", ctx.getAttributes("").get( "ou" ).get() );
350     }
351 
352 
353     // ------------------------------------------------------------------------
354     // List Operation Tests
355     // ------------------------------------------------------------------------
356 
357 
358     /***
359      * Test list operation failure when the base searched is non-existant.
360      */
361     public void testFailListNoSuchObject() throws NamingException
362     {
363         try
364         {
365             sysRoot.list( "ou=blah" );
366             fail( "Execution should never get here due to exception!" );
367         }
368         catch( LdapNameNotFoundException e )
369         {
370             assertEquals( "ou=system", e.getResolvedName().toString() );
371             assertEquals( ResultCodeEnum.NOSUCHOBJECT, e.getResultCode() );
372         }
373     }
374 
375 
376     /***
377      * List operation control to test if normal list operations occur correctly.
378      */
379     public void testListControl() throws NamingException
380     {
381         NamingEnumeration list = sysRoot.list( "ou=users" );
382 
383         if ( list.hasMore() )
384         {
385             SearchResult result = ( SearchResult ) list.next();
386             assertNotNull( result.getAttributes() );
387             assertEquals( "uid=akarasulu,ou=users,ou=system", result.getName().toString() );
388         }
389 
390         assertFalse( list.hasMore() );
391     }
392 
393 
394     // ------------------------------------------------------------------------
395     // Add Operation Tests
396     // ------------------------------------------------------------------------
397 
398 
399     /***
400      * Tests for add operation failure when the parent of the entry to add does
401      * not exist.
402      */
403     public void testFailAddOnAlias() throws NamingException
404     {
405         Attributes attrs = new BasicAttributes( true );
406         Attribute attr = new BasicAttribute( "objectClass" );
407         attr.add( "top" );
408         attr.add( "alias" );
409         attrs.put( attr );
410         attrs.put( "aliasedObjectName", "ou=users,ou=system" );
411 
412         sysRoot.createSubcontext( "cn=toanother", attrs );
413 
414         try
415         {
416             sysRoot.createSubcontext( "ou=blah,cn=toanother" );
417             fail( "Execution should never get here due to exception!" );
418         }
419         catch( LdapNamingException e )
420         {
421             assertEquals( "cn=toanother,ou=system", e.getResolvedName().toString() );
422             assertEquals( ResultCodeEnum.ALIASPROBLEM, e.getResultCode() );
423         }
424     }
425 
426 
427     /***
428      * Tests for add operation failure when the parent of the entry to add does
429      * not exist.
430      */
431     public void testFailAddNoSuchEntry() throws NamingException
432     {
433         try
434         {
435             sysRoot.createSubcontext( "ou=blah,ou=abc" );
436             fail( "Execution should never get here due to exception!" );
437         }
438         catch( LdapNameNotFoundException e )
439         {
440             assertEquals( "ou=system", e.getResolvedName().toString() );
441             assertEquals( ResultCodeEnum.NOSUCHOBJECT, e.getResultCode() );
442         }
443     }
444 
445 
446     /***
447      * Tests for add operation failure when the entry to add already exists.
448      */
449     public void testFailAddEntryAlreadyExists() throws NamingException
450     {
451         sysRoot.createSubcontext( "ou=blah" );
452 
453         try
454         {
455             sysRoot.createSubcontext( "ou=blah" );
456             fail( "Execution should never get here due to exception!" );
457         }
458         catch( LdapNameAlreadyBoundException e )
459         {
460             assertEquals( "ou=blah,ou=system", e.getResolvedName().toString() );
461             assertEquals( ResultCodeEnum.ENTRYALREADYEXISTS, e.getResultCode() );
462         }
463     }
464 
465 
466     /***
467      * Add operation control to test if normal add operations occur correctly.
468      */
469     public void testAddControl() throws NamingException
470     {
471         Context ctx = sysRoot.createSubcontext( "ou=blah" );
472         ctx.createSubcontext( "ou=subctx" );
473         Object obj = sysRoot.lookup( "ou=subctx,ou=blah" );
474         assertNotNull( obj );
475     }
476 
477 
478     // ------------------------------------------------------------------------
479     // Delete Operation Tests
480     // ------------------------------------------------------------------------
481 
482 
483     /***
484      * Tests for delete failure when the entry to be deleted has child entires.
485      */
486     public void testFailDeleteNotAllowedOnNonLeaf() throws NamingException
487     {
488         Context ctx = sysRoot.createSubcontext( "ou=blah" );
489         ctx.createSubcontext( "ou=subctx" );
490 
491         try
492         {
493             sysRoot.destroySubcontext( "ou=blah" );
494             fail( "Execution should never get here due to exception!" );
495         }
496         catch( LdapContextNotEmptyException e )
497         {
498             assertEquals( "ou=blah,ou=system", e.getResolvedName().toString() );
499             assertEquals( ResultCodeEnum.NOTALLOWEDONNONLEAF, e.getResultCode() );
500         }
501     }
502 
503 
504     /***
505      * Tests delete to make sure it fails when we try to delete an entry that
506      * does not exist.
507      */
508     public void testFailDeleteNoSuchObject() throws NamingException
509     {
510         try
511         {
512             sysRoot.destroySubcontext( "ou=blah" );
513             fail( "Execution should never get here due to exception!" );
514         }
515         catch( LdapNameNotFoundException e )
516         {
517             assertEquals( "ou=system", e.getResolvedName().toString() );
518             assertEquals( ResultCodeEnum.NOSUCHOBJECT, e.getResultCode() );
519         }
520     }
521 
522 
523     /***
524      * Delete operation control to test if normal delete operations occur.
525      */
526     public void testDeleteControl() throws NamingException
527     {
528         sysRoot.createSubcontext( "ou=blah" );
529         Object obj = sysRoot.lookup( "ou=blah" );
530         assertNotNull( obj );
531         sysRoot.destroySubcontext( "ou=blah" );
532 
533         try
534         {
535             sysRoot.lookup( "ou=blah" );
536             fail( "Execution should never get here due to exception!" );
537         }
538         catch( LdapNameNotFoundException e )
539         {
540             assertEquals( "ou=system", e.getResolvedName().toString() );
541             assertEquals( ResultCodeEnum.NOSUCHOBJECT, e.getResultCode() );
542         }
543     }
544 }