You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by se...@apache.org on 2010/05/02 20:01:54 UTC
svn commit: r940280 - in /directory/apacheds/trunk/core-integ/src/test:
java/org/apache/directory/server/core/operations/search/AliasSearchIT.java
java/org/apache/directory/server/core/suites/StockCoreISuite.java
resources/AliasSearchIT.ldif
Author: seelmann
Date: Sun May 2 18:01:54 2010
New Revision: 940280
URL: http://svn.apache.org/viewvc?rev=940280&view=rev
Log:
Added basic alias search tests
Added:
directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/operations/search/AliasSearchIT.java
directory/apacheds/trunk/core-integ/src/test/resources/AliasSearchIT.ldif
Modified:
directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/suites/StockCoreISuite.java
Added: directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/operations/search/AliasSearchIT.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/operations/search/AliasSearchIT.java?rev=940280&view=auto
==============================================================================
--- directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/operations/search/AliasSearchIT.java (added)
+++ directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/operations/search/AliasSearchIT.java Sun May 2 18:01:54 2010
@@ -0,0 +1,608 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.directory.server.core.operations.search;
+
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.server.core.annotations.ApplyLdifFiles;
+import org.apache.directory.server.core.annotations.CreateDS;
+import org.apache.directory.server.core.annotations.CreatePartition;
+import org.apache.directory.server.core.filtering.EntryFilteringCursor;
+import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
+import org.apache.directory.server.core.integ.FrameworkRunner;
+import org.apache.directory.shared.ldap.exception.LdapNoSuchObjectException;
+import org.apache.directory.shared.ldap.filter.ExprNode;
+import org.apache.directory.shared.ldap.filter.FilterParser;
+import org.apache.directory.shared.ldap.filter.SearchScope;
+import org.apache.directory.shared.ldap.message.AliasDerefMode;
+import org.apache.directory.shared.ldap.name.DN;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Tests to make sure the server is operating correctly when handling aliases.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 545029 $
+ */
+@RunWith(FrameworkRunner.class)
+@CreateDS(name = "AliasSearchDS", partitions =
+ { @CreatePartition(name = "example", suffix = "dc=example,dc=com"),
+ @CreatePartition(name = "acme", suffix = "o=acme") })
+@ApplyLdifFiles(
+ { "AliasSearchIT.ldif" })
+public class AliasSearchIT extends AbstractLdapTestUnit
+{
+
+ Logger LOG = LoggerFactory.getLogger( AliasSearchIT.class );
+
+
+ @Ignore
+ @Test
+ public void dump() throws Exception
+ {
+ List<String> results1 = search( "dc=example,dc=com", SearchScope.SUBTREE, "(objectClass=*)",
+ AliasDerefMode.NEVER_DEREF_ALIASES );
+ for ( String dn : results1 )
+ {
+ System.out.println( dn );
+ }
+ //List<String> results2 = search( "o=acme", SearchScope.SUBTREE, "(objectClass=*)",
+ // AliasDerefMode.NEVER_DEREF_ALIASES );
+ //for ( String dn : results2 )
+ //{
+ // System.out.println( dn );
+ //}
+ }
+
+
+ @Test(expected = LdapNoSuchObjectException.class)
+ public void testNonexistingPartition() throws Exception
+ {
+ search( "dc=x", SearchScope.SUBTREE, "(objectClass=*)", AliasDerefMode.NEVER_DEREF_ALIASES );
+ }
+
+
+ /**
+ * Search from context entry.
+ */
+ @Test
+ public void testContextEntry() throws Exception
+ {
+ // use filter
+ verifyCounts( "dc=example,dc=com", SearchScope.OBJECT, "(uid=user1)", 0, 0, 0, 0 );
+ verifyCounts( "dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user1)", 0, 0, 0, 0 );
+ verifyCounts( "dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)", 3, 3, 1, 1 );
+
+ // check some important case: no deref -> aliases and non-alias must be contained in result
+ verifyResults( "dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)", AliasDerefMode.NEVER_DEREF_ALIASES,
+ "uid=user1,ou=managers,dc=example,dc=com", "uid=user1,ou=engineering,ou=users,dc=example,dc=com",
+ "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+
+ // check some important case: deref -> aliases must not be contained in result
+ verifyResults( "dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)", AliasDerefMode.DEREF_ALWAYS,
+ "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+
+ // use true filter
+ verifyCounts( "dc=example,dc=com", SearchScope.OBJECT, "(objectClass=*)", 1, 1, 1, 1 );
+ verifyCounts( "dc=example,dc=com", SearchScope.ONELEVEL, "(objectClass=*)", 4, 4, 3, 3 );
+ // 23 entries below dc=example,dc=com, 9 alias entries
+ verifyCounts( "dc=example,dc=com", SearchScope.SUBTREE, "(objectClass=*)", 23, 23, 23 - 9, 23 - 9 );
+
+ // check an important case: no deref -> ou=people must be contained in result
+ verifyResults( "dc=example,dc=com", SearchScope.ONELEVEL, "(objectClass=*)",
+ AliasDerefMode.NEVER_DEREF_ALIASES, "ou=users,dc=example,dc=com", "ou=people,dc=example,dc=com",
+ "ou=managers,dc=example,dc=com", "ou=newsfeeds,dc=example,dc=com" );
+
+ // check an important case: deref -> ou=people is alias to ou=users must not be contained in result
+ verifyResults( "dc=example,dc=com", SearchScope.ONELEVEL, "(objectClass=*)", AliasDerefMode.DEREF_ALWAYS,
+ "ou=users,dc=example,dc=com", "ou=managers,dc=example,dc=com", "ou=newsfeeds,dc=example,dc=com" );
+ }
+
+
+ /**
+ * Search from ou=managers.
+ * There is one child entry that is an alias:
+ * uid=user1,ou=managers,dc=example,dc=com ->
+ * uid=user1,ou=sales,ou=users,dc=example,dc=com
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testOuManagers() throws Exception
+ {
+ verifyCounts( "ou=managers,dc=example,dc=com", SearchScope.OBJECT, "(uid=user1)", 0, 0, 0, 0 );
+ verifyCounts( "ou=managers,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user1)", 1, 1, 1, 1 );
+ verifyCounts( "ou=managers,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)", 1, 1, 1, 1 );
+
+ // get the alias (not dereferenced)
+ verifyResults( "ou=managers,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user1)",
+ AliasDerefMode.NEVER_DEREF_ALIASES, "uid=user1,ou=managers,dc=example,dc=com" );
+
+ // get the alias (not dereferenced)
+ verifyResults( "ou=managers,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user1)",
+ AliasDerefMode.DEREF_FINDING_BASE_OBJ, "uid=user1,ou=managers,dc=example,dc=com" );
+
+ // get the target (dereferenced)
+ verifyResults( "ou=managers,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user1)",
+ AliasDerefMode.DEREF_IN_SEARCHING, "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+
+ // get the target (dereferenced)
+ verifyResults( "ou=managers,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user1)",
+ AliasDerefMode.DEREF_ALWAYS, "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+ }
+
+
+ /**
+ * Search from ou=users.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testOuUsers() throws Exception
+ {
+ // use filter
+ verifyCounts( "ou=users,dc=example,dc=com", SearchScope.OBJECT, "(uid=user1)", 0, 0, 0, 0 );
+ verifyCounts( "ou=users,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user1)", 0, 0, 0, 0 );
+ verifyCounts( "ou=users,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)", 2, 2, 1, 1 );
+
+ // finding: uid=user1,ou=engineering is not dereferenced
+ verifyResults( "ou=users,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)",
+ AliasDerefMode.DEREF_FINDING_BASE_OBJ, "uid=user1,ou=sales,ou=users,dc=example,dc=com",
+ "uid=user1,ou=engineering,ou=users,dc=example,dc=com" );
+
+ // searching: uid=user1,ou=engineering is dereferenced to uid=user1,ou=sales, no duplicates.
+ verifyResults( "ou=users,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)",
+ AliasDerefMode.DEREF_IN_SEARCHING, "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+ }
+
+
+ /**
+ * Test dereferencing to branch sibling. Search from ou=people, that is an alias to ou=users.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testOuPeople() throws Exception
+ {
+ verifyCounts( "ou=people,dc=example,dc=com", SearchScope.OBJECT, "(uid=user1)", 0, 0, 0, 0 );
+ verifyCounts( "ou=people,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user1)", 0, 0, 0, 0 );
+ verifyCounts( "ou=people,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)", 0, 2, 0, 1 );
+
+ // finding: ou=people is dereferenced to ou=users, but uid=user1,ou=engineering is not dereferenced
+ verifyResults( "ou=people,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)",
+ AliasDerefMode.DEREF_FINDING_BASE_OBJ, "uid=user1,ou=sales,ou=users,dc=example,dc=com",
+ "uid=user1,ou=engineering,ou=users,dc=example,dc=com" );
+
+ // always: ou=people is dereferenced to ou=users and uid=user1,ou=engineering is
+ // dereferenced to uid=user1,ou=sales.
+ verifyResults( "ou=people,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)", AliasDerefMode.DEREF_ALWAYS,
+ "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+
+ verifyCounts( "ou=people,dc=example,dc=com", SearchScope.OBJECT, "(uid=*)", 0, 0, 0, 0 );
+ verifyCounts( "ou=people,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=*)", 0, 0, 0, 0 );
+ verifyCounts( "ou=people,dc=example,dc=com", SearchScope.SUBTREE, "(uid=*)", 0, 5, 0, 3 );
+ }
+
+
+ /**
+ * Search from ou=sales,ou=users. Ensure that no duplicate entries are returned due to
+ * alias of cn=deputy.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testOuSales() throws Exception
+ {
+ verifyCounts( "ou=sales,ou=users,dc=example,dc=com", SearchScope.OBJECT, "(uid=user1)", 0, 0, 0, 0 );
+ verifyCounts( "ou=sales,ou=users,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user1)", 1, 1, 1, 1 );
+ verifyCounts( "ou=sales,ou=users,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)", 1, 1, 1, 1 );
+
+ verifyCounts( "ou=sales,ou=users,dc=example,dc=com", SearchScope.OBJECT, "(uid=*)", 0, 0, 0, 0 );
+ verifyCounts( "ou=sales,ou=users,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=*)", 2, 2, 2, 2 );
+ verifyCounts( "ou=sales,ou=users,dc=example,dc=com", SearchScope.SUBTREE, "(uid=*)", 2, 2, 2, 2 );
+
+ verifyResults( "ou=sales,ou=users,dc=example,dc=com", SearchScope.SUBTREE, "(uid=*)",
+ AliasDerefMode.DEREF_IN_SEARCHING, "uid=user1,ou=sales,ou=users,dc=example,dc=com",
+ "uid=user2,ou=sales,ou=users,dc=example,dc=com" );
+ }
+
+
+ /**
+ * Test proper dereferencing of descendant of aliases.
+ *
+ * @throws Exception
+ */
+ @Ignore("fixme")
+ @Test
+ public void testDerefDescendantOfAlias() throws Exception
+ {
+ verifyResults( "ou=sales,ou=people,dc=example,dc=com", SearchScope.OBJECT, "(objectClass=*)",
+ AliasDerefMode.DEREF_FINDING_BASE_OBJ, "ou=sales,ou=users,dc=example,dc=com" );
+
+ verifyResults( "cn=deputy,uid=user1,ou=managers,dc=example,dc=com", SearchScope.OBJECT,
+ "(objectClass=inetOrgPerson)", AliasDerefMode.DEREF_FINDING_BASE_OBJ,
+ "uid=user2,ou=sales,ou=users,dc=example,dc=com" );
+
+ // test to avoid loops
+ try
+ {
+ verifyResults( "cn=nonexisting,uid=user1,ou=managers,dc=example,dc=com", SearchScope.OBJECT,
+ "(objectClass=inetOrgPerson)", AliasDerefMode.DEREF_FINDING_BASE_OBJ );
+ fail();
+ }
+ catch ( LdapNoSuchObjectException e )
+ {
+ // expected
+ }
+ }
+
+
+ /**
+ * Test dereferencing to branch sibling. Search ou=engineering which is an alias to ou=sales.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testOuEngineering() throws Exception
+ {
+ verifyCounts( "ou=engineering,ou=users,dc=example,dc=com", SearchScope.OBJECT, "(uid=user1)", 0, 0, 0, 0 );
+ verifyCounts( "ou=engineering,ou=users,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user1)", 1, 1, 1, 1 );
+ verifyCounts( "ou=engineering,ou=users,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)", 1, 1, 1, 1 );
+
+ // not dereferenced -> ou=engineering
+ verifyResults( "ou=engineering,ou=users,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user1)",
+ AliasDerefMode.NEVER_DEREF_ALIASES, "uid=user1,ou=engineering,ou=users,dc=example,dc=com" );
+ verifyResults( "ou=engineering,ou=users,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)",
+ AliasDerefMode.NEVER_DEREF_ALIASES, "uid=user1,ou=engineering,ou=users,dc=example,dc=com" );
+ // not dereferenced -> ou=engineering
+ verifyResults( "ou=engineering,ou=users,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user1)",
+ AliasDerefMode.DEREF_FINDING_BASE_OBJ, "uid=user1,ou=engineering,ou=users,dc=example,dc=com" );
+ verifyResults( "ou=engineering,ou=users,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)",
+ AliasDerefMode.DEREF_FINDING_BASE_OBJ, "uid=user1,ou=engineering,ou=users,dc=example,dc=com" );
+ // dereferenced -> ou=sales
+ verifyResults( "ou=engineering,ou=users,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user1)",
+ AliasDerefMode.DEREF_IN_SEARCHING, "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+ verifyResults( "ou=engineering,ou=users,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)",
+ AliasDerefMode.DEREF_IN_SEARCHING, "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+ // dereferenced -> ou=sales
+ verifyResults( "ou=engineering,ou=users,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user1)",
+ AliasDerefMode.DEREF_ALWAYS, "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+ verifyResults( "ou=engineering,ou=users,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)",
+ AliasDerefMode.DEREF_ALWAYS, "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+ }
+
+
+ /**
+ * Test dereferencing to another partition.
+ *
+ * @throws Exception
+ */
+ @Ignore("not implemented")
+ @Test
+ public void testOuHr() throws Exception
+ {
+ verifyCounts( "ou=hr,ou=users,dc=example,dc=com", SearchScope.OBJECT, "(uid=*)", 0, 0, 0, 0 );
+ verifyCounts( "ou=hr,ou=users,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=*)", 0, 2, 0, 2 );
+ verifyCounts( "ou=hr,ou=users,dc=example,dc=com", SearchScope.SUBTREE, "(uid=*)", 0, 2, 0, 2 );
+
+ verifyResults( "ou=hr,ou=users,dc=example,dc=com", SearchScope.SUBTREE, "(uid=*)", AliasDerefMode.DEREF_ALWAYS,
+ "uid=userA,ou=human resources,ou=users,o=acme", "uid=userB,ou=human resources,ou=users,o=acme" );
+ }
+
+
+ /**
+ * Test dereferencing to leaf sibling.
+ *
+ * @throws Exception
+ */
+ @Ignore("not implemented")
+ @Test
+ public void testUidFoobar() throws Exception
+ {
+ verifyCounts( "uid=foobar,ou=engineering,ou=users,dc=example,dc=com", SearchScope.OBJECT,
+ "(objectClass=person)", 0, 1, 0, 1 );
+ verifyCounts( "uid=foobar,ou=engineering,ou=users,dc=example,dc=com", SearchScope.ONELEVEL,
+ "(objectClass=person)", 0, 0, 0, 1 );
+ verifyCounts( "uid=foobar,ou=engineering,ou=users,dc=example,dc=com", SearchScope.SUBTREE,
+ "(objectClass=person)", 0, 1, 0, 1 );
+
+ // cn=deputy,uid=user3 -> uid=user3
+ verifyResults( "uid=foobar,ou=engineering,ou=users,dc=example,dc=com", SearchScope.ONELEVEL,
+ "(objectClass=person)", AliasDerefMode.DEREF_ALWAYS, "uid=user3,ou=engineering,ou=users,dc=example,dc=com" );
+ }
+
+
+ /**
+ * Test dereferencing of chained alias
+ * uid=user1,ou=managers,dc=example,dc=com ->
+ * uid=user1,ou=engineering,ou=users,dc=example,dc=com ->
+ * uid=user1,ou=sales,ou=users,dc=example,dc=com
+ *
+ * @throws Exception
+ */
+ @Ignore("not implemented")
+ @Test
+ public void testUidUser1OuManager() throws Exception
+ {
+ verifyCounts( "uid=user1,ou=managers,dc=example,dc=com", SearchScope.OBJECT, "(uid=user1)", 1, 1, 0, 1 );
+ verifyCounts( "uid=user1,ou=managers,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user1)", 0, 0, 0, 0 );
+ verifyCounts( "uid=user1,ou=managers,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)", 1, 1, 0, 1 );
+
+ verifyResults( "uid=user1,ou=managers,dc=example,dc=com", SearchScope.OBJECT, "(uid=user1)",
+ AliasDerefMode.NEVER_DEREF_ALIASES, "uid=user1,ou=managers,dc=example,dc=com" );
+ verifyResults( "uid=user1,ou=managers,dc=example,dc=com", SearchScope.OBJECT, "(uid=user1)",
+ AliasDerefMode.DEREF_FINDING_BASE_OBJ, "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+ verifyResults( "uid=user1,ou=managers,dc=example,dc=com", SearchScope.OBJECT, "(uid=user1)",
+ AliasDerefMode.DEREF_IN_SEARCHING );
+ verifyResults( "uid=user1,ou=managers,dc=example,dc=com", SearchScope.OBJECT, "(uid=user1)",
+ AliasDerefMode.DEREF_ALWAYS, "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+
+ verifyResults( "uid=user1,ou=managers,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)",
+ AliasDerefMode.NEVER_DEREF_ALIASES, "uid=user1,ou=managers,dc=example,dc=com" );
+ verifyResults( "uid=user1,ou=managers,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)",
+ AliasDerefMode.DEREF_FINDING_BASE_OBJ, "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+ verifyResults( "uid=user1,ou=managers,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)",
+ AliasDerefMode.DEREF_IN_SEARCHING );
+ verifyResults( "uid=user1,ou=managers,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user1)",
+ AliasDerefMode.DEREF_ALWAYS, "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+ }
+
+
+ @Test
+ public void testCnDeputy() throws Exception
+ {
+ verifyCounts( "cn=deputy,uid=user2,ou=sales,ou=users,dc=example,dc=com", SearchScope.OBJECT, "(objectClass=*)",
+ 1, 1, 1, 1 );
+ verifyResults( "cn=deputy,uid=user2,ou=sales,ou=users,dc=example,dc=com", SearchScope.OBJECT,
+ "(objectClass=*)", AliasDerefMode.NEVER_DEREF_ALIASES,
+ "cn=deputy,uid=user2,ou=sales,ou=users,dc=example,dc=com" );
+ verifyResults( "cn=deputy,uid=user2,ou=sales,ou=users,dc=example,dc=com", SearchScope.OBJECT,
+ "(objectClass=*)", AliasDerefMode.DEREF_FINDING_BASE_OBJ, "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+ verifyResults( "cn=deputy,uid=user2,ou=sales,ou=users,dc=example,dc=com", SearchScope.OBJECT,
+ "(objectClass=*)", AliasDerefMode.DEREF_IN_SEARCHING,
+ "cn=deputy,uid=user2,ou=sales,ou=users,dc=example,dc=com" );
+ verifyResults( "cn=deputy,uid=user2,ou=sales,ou=users,dc=example,dc=com", SearchScope.OBJECT,
+ "(objectClass=*)", AliasDerefMode.DEREF_ALWAYS, "uid=user1,ou=sales,ou=users,dc=example,dc=com" );
+
+ // should not cause infinite loops
+ verifyCounts( "cn=deputy,uid=user2,ou=sales,ou=users,dc=example,dc=com", SearchScope.ONELEVEL,
+ "(objectClass=*)", 0, 2, 0, 1 );
+ verifyCounts( "cn=deputy,uid=user2,ou=sales,ou=users,dc=example,dc=com", SearchScope.SUBTREE,
+ "(objectClass=*)", 1, 4, 0, 4 );
+ }
+
+
+ /**
+ * Search uid=user3,ou=engineering,ou=users,dc=example,dc=com.
+ *
+ * @throws Exception
+ */
+ @Ignore("fixme")
+ @Test
+ public void testOuUser3_Loop() throws Exception
+ {
+ verifyCounts( "uid=user3,ou=engineering,ou=users,dc=example,dc=com", SearchScope.OBJECT, "(uid=user3)", 1, 1,
+ 1, 1 );
+ verifyCounts( "uid=user3,ou=engineering,ou=users,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user3)", 0, 0,
+ 1, 1 );
+ verifyCounts( "uid=user3,ou=engineering,ou=users,dc=example,dc=com", SearchScope.SUBTREE, "(uid=user3)", 1, 1,
+ 1, 1 );
+
+ verifyResults( "uid=user3,ou=engineering,ou=users,dc=example,dc=com", SearchScope.ONELEVEL, "(uid=user3)",
+ AliasDerefMode.DEREF_IN_SEARCHING, "uid=user3,ou=engineering,ou=users,dc=example,dc=com" );
+ }
+
+
+ @Ignore("fixme")
+ @Test
+ public void testCnDeputyOuUser3_Loop() throws Exception
+ {
+ verifyCounts( "cn=deputy,uid=user3,ou=engineering,ou=users,dc=example,dc=com", SearchScope.OBJECT,
+ "(uid=user3)", 0, 1, 0, 1 );
+ verifyCounts( "cn=deputy,uid=user3,ou=engineering,ou=users,dc=example,dc=com", SearchScope.ONELEVEL,
+ "(uid=user3)", 0, 0, 0, 1 );
+ verifyCounts( "cn=deputy,uid=user3,ou=engineering,ou=users,dc=example,dc=com", SearchScope.SUBTREE,
+ "(uid=user3)", 0, 1, 0, 1 );
+ }
+
+
+ @Ignore
+ @Test
+ public void testCursorNextPrevWithReset() throws Exception
+ {
+ try
+ {
+ DN base = new DN( "dc=example,dc=com" );
+ SearchScope scope = SearchScope.SUBTREE;
+ ExprNode exprNode = FilterParser.parse( "(objectClass=*)" );
+ AliasDerefMode aliasDerefMode = AliasDerefMode.DEREF_ALWAYS;
+ EntryFilteringCursor cursor = service.getAdminSession()
+ .search( base, scope, exprNode, aliasDerefMode, null );
+
+ // advancing the cursor forward and backward must give the same result
+ for ( int count = 1; count < 20; count++ )
+ {
+ cursor.beforeFirst();
+
+ List<String> nextResults = new ArrayList<String>();
+ while ( nextResults.size() < count && cursor.next() )
+ {
+ nextResults.add( cursor.get().getDn().getName() );
+ }
+
+ cursor.next();
+
+ List<String> prevResults = new ArrayList<String>();
+ while ( cursor.previous() )
+ {
+ prevResults.add( 0, cursor.get().getDn().getName() );
+ }
+
+ assertEquals( nextResults.size(), prevResults.size() );
+ assertEquals( nextResults, prevResults );
+ }
+ }
+ catch ( UnsupportedOperationException e )
+ {
+ LOG.warn( "Partition doesn't support next/previous test" );
+ }
+ }
+
+
+ @Ignore
+ @Test
+ public void testCursorPrevNext() throws Exception
+ {
+ try
+ {
+ DN base = new DN( "dc=example,dc=com" );
+ SearchScope scope = SearchScope.SUBTREE;
+ ExprNode exprNode = FilterParser.parse( "(objectClass=*)" );
+ AliasDerefMode aliasDerefMode = AliasDerefMode.DEREF_ALWAYS;
+ EntryFilteringCursor cursor = service.getAdminSession()
+ .search( base, scope, exprNode, aliasDerefMode, null );
+
+ // advancing the cursor backward and forward must give the same result
+ for ( int count = 1; count < 20; count++ )
+ {
+ cursor.afterLast();
+
+ List<String> prevResults = new ArrayList<String>();
+ while ( prevResults.size() < count && cursor.previous() )
+ {
+ prevResults.add( cursor.get().getDn().getName() );
+ }
+
+ cursor.previous();
+
+ List<String> nextResults = new ArrayList<String>();
+ while ( cursor.next() )
+ {
+ nextResults.add( 0, cursor.get().getDn().getName() );
+ }
+
+ assertEquals( nextResults.size(), prevResults.size() );
+ assertEquals( nextResults, prevResults );
+ }
+ }
+ catch ( UnsupportedOperationException e )
+ {
+ LOG.warn( "Partition doesn't support previous/next test" );
+ }
+ }
+
+
+ private void verifyResults( String base, SearchScope scope, String filter, AliasDerefMode aliasDerefMode,
+ String... expectedResults ) throws Exception
+ {
+ List<String> result = search( base, scope, filter, aliasDerefMode );
+ assertEquals( expectedResults.length, result.size() );
+ for ( String expected : expectedResults )
+ {
+ assertTrue( result.contains( expected ) );
+ }
+ }
+
+
+ /**
+ * Performs a search for each alias dereferencing mode and checks the search result count.
+ *
+ * @param base the search base to use
+ * @param scope the search scope to use
+ * @param filter the search filter to use
+ * @param neverCount the expected result count for AliasDerefMode.NEVER_DEREF_ALIASES
+ * @param findCount the expected result count for AliasDerefMode.DEREF_FINDING_BASE_OBJ
+ * @param searchCount the expected result count for AliasDerefMode.DEREF_IN_SEARCHING
+ * @param alwaysCount the expected result count for AliasDerefMode.DEREF_ALWAYS
+ * @throws Exception
+ */
+ private void verifyCounts( String base, SearchScope scope, String filter, int neverCount, int findCount,
+ int searchCount, int alwaysCount ) throws Exception
+ {
+ List<String> results1 = search( base, scope, filter, AliasDerefMode.NEVER_DEREF_ALIASES );
+ assertEquals( neverCount, results1.size() );
+
+ List<String> results2 = search( base, scope, filter, AliasDerefMode.DEREF_FINDING_BASE_OBJ );
+ assertEquals( findCount, results2.size() );
+
+ List<String> results3 = search( base, scope, filter, AliasDerefMode.DEREF_IN_SEARCHING );
+ assertEquals( searchCount, results3.size() );
+
+ List<String> results4 = search( base, scope, filter, AliasDerefMode.DEREF_ALWAYS );
+ assertEquals( alwaysCount, results4.size() );
+ }
+
+
+ /**
+ * Performs a search and returns the search results DNs.
+ *
+ * @param base the search base to use
+ * @param scope the search scope to use
+ * @param filter the search filter to use
+ * @param aliasDerefMode the alias dereferencing mode to use
+ * @return the list of search results DNs
+ * @throws Exception
+ */
+ private List<String> search( String base, SearchScope scope, String filter, AliasDerefMode aliasDerefMode )
+ throws Exception
+ {
+ List<String> nextResults = new ArrayList<String>();
+
+ ExprNode exprNode = FilterParser.parse( filter );
+ EntryFilteringCursor cursor = service.getAdminSession().search( new DN( base ), scope, exprNode,
+ aliasDerefMode, null );
+ cursor.beforeFirst();
+ while ( cursor.next() )
+ {
+ nextResults.add( cursor.get().getDn().getName() );
+ }
+
+ try
+ {
+ List<String> prevResults = new ArrayList<String>();
+ cursor.afterLast();
+ while ( cursor.previous() )
+ {
+ prevResults.add( 0, cursor.get().getDn().getName() );
+ }
+
+ assertEquals( nextResults.size(), prevResults.size() );
+ assertEquals( nextResults, prevResults );
+ }
+ catch ( UnsupportedOperationException e )
+ {
+ LOG.warn( "Partition doesn't support previous test" );
+ }
+
+ return nextResults;
+ }
+
+}
\ No newline at end of file
Modified: directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/suites/StockCoreISuite.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/suites/StockCoreISuite.java?rev=940280&r1=940279&r2=940280&view=diff
==============================================================================
--- directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/suites/StockCoreISuite.java (original)
+++ directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/suites/StockCoreISuite.java Sun May 2 18:01:54 2010
@@ -55,6 +55,7 @@ import org.apache.directory.server.core.
import org.apache.directory.server.core.operations.modify.ModifyAddIT;
import org.apache.directory.server.core.operations.modify.ModifyDelIT;
import org.apache.directory.server.core.operations.modify.ModifyMultipleChangesIT;
+import org.apache.directory.server.core.operations.search.AliasSearchIT;
import org.apache.directory.server.core.operations.search.DIRSERVER759IT;
import org.apache.directory.server.core.operations.search.SearchIT;
import org.apache.directory.server.core.partition.PartitionIT;
@@ -107,6 +108,7 @@ import org.junit.runners.Suite;
ExtensibleObjectIT.class,
RFC2713IT.class,
RootDSEIT.class,
+ AliasSearchIT.class,
SearchIT.class,
UniqueMemberIT.class,
PreferencesIT.class,
Added: directory/apacheds/trunk/core-integ/src/test/resources/AliasSearchIT.ldif
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-integ/src/test/resources/AliasSearchIT.ldif?rev=940280&view=auto
==============================================================================
--- directory/apacheds/trunk/core-integ/src/test/resources/AliasSearchIT.ldif (added)
+++ directory/apacheds/trunk/core-integ/src/test/resources/AliasSearchIT.ldif Sun May 2 18:01:54 2010
@@ -0,0 +1,210 @@
+dn: dc=example,dc=com
+objectClass: domain
+objectClass: top
+dc: example
+
+dn: ou=users,dc=example,dc=com
+objectClass: organizationalUnit
+objectClass: top
+ou: users
+
+dn: ou=engineering,ou=users,dc=example,dc=com
+objectClass: organizationalUnit
+objectClass: top
+ou: engineering
+
+dn: uid=user3,ou=engineering,ou=users,dc=example,dc=com
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+objectClass: person
+objectClass: top
+uid: user3
+cn: User 3
+sn: 3
+givenName: User
+
+dn: ou=sales,ou=users,dc=example,dc=com
+objectClass: organizationalUnit
+objectClass: top
+ou: sales
+
+dn: uid=user1,ou=sales,ou=users,dc=example,dc=com
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+objectClass: person
+objectClass: top
+uid: user1
+cn: User 1
+sn: 1
+givenName: User
+
+dn: ou=subscriptions,uid=user1,ou=sales,ou=users,dc=example,dc=com
+objectClass: organizationalUnit
+objectClass: top
+ou: subscriptions
+
+dn: uid=user2,ou=sales,ou=users,dc=example,dc=com
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+objectClass: person
+objectClass: top
+uid: user2
+cn: User 2
+sn: 2
+givenName: User
+
+dn: ou=subscriptions,uid=user2,ou=sales,ou=users,dc=example,dc=com
+objectClass: organizationalUnit
+objectClass: top
+ou: subscriptions
+
+dn: ou=managers,dc=example,dc=com
+objectClass: organizationalUnit
+objectClass: top
+ou: managers
+
+
+dn: ou=newsfeeds,dc=example,dc=com
+objectClass: organizationalUnit
+objectClass: top
+ou: bookmarks
+
+dn: cn=feed1,ou=newsfeeds,dc=example,dc=com
+objectClass: document
+objectClass: top
+cn: feed1
+documentIdentifier: http://www.heise.de/newsticker/heise-atom.xml
+
+dn: cn=feed2,ou=newsfeeds,dc=example,dc=com
+objectClass: document
+objectClass: top
+cn: feed2
+documentIdentifier: http://www.heise.de/newsticker/heise-atom.xml
+
+dn: cn=feed3,ou=newsfeeds,dc=example,dc=com
+objectClass: document
+objectClass: top
+cn: feed3
+documentIdentifier: http://www.heise.de/newsticker/heise-atom.xml
+
+
+dn: ou=people,dc=example,dc=com
+objectClass: extensibleObject
+objectClass: alias
+ou: people
+aliasedObjectName: ou=users,dc=example,dc=com
+description: alias to sibling (branch)
+
+#dn: ou=all,ou=users,dc=example,dc=com
+#objectClass: extensibleObject
+#objectClass: alias
+#ou: all
+#aliasedObjectName: dc=example,dc=com
+#description: alias to context entry, extends search base to all + loop!
+
+dn: uid=foobar,ou=engineering,ou=users,dc=example,dc=com
+objectClass: extensibleObject
+objectClass: alias
+uid: foobar
+aliasedObjectName: uid=user3,ou=engineering,ou=users,dc=example,dc=com
+description: alias to sibling (leaf)
+
+dn: uid=user1,ou=engineering,ou=users,dc=example,dc=com
+objectClass: extensibleObject
+objectClass: alias
+uid: user1
+aliasedObjectName: uid=user1,ou=sales,ou=users,dc=example,dc=com
+description: alias to cousin
+
+dn: cn=feed1,ou=subscriptions,uid=user1,ou=sales,ou=users,dc=example,dc=com
+objectClass: extensibleObject
+objectClass: alias
+cn: feed1
+aliasedObjectName: cn=feed1,ou=newsfeeds,dc=example,dc=com
+description: alias to parent
+
+dn: cn=feed1,ou=subscriptions,uid=user2,ou=sales,ou=users,dc=example,dc=com
+objectClass: extensibleObject
+objectClass: alias
+cn: feed1
+aliasedObjectName: cn=feed1,ou=newsfeeds,dc=example,dc=com
+description: alias to parent
+
+dn: cn=feed2,ou=subscriptions,uid=user2,ou=sales,ou=users,dc=example,dc=com
+objectClass: extensibleObject
+objectClass: alias
+cn: feed2
+aliasedObjectName: cn=feed2,ou=newsfeeds,dc=example,dc=com
+description: alias to parent
+
+dn: uid=user1,ou=managers,dc=example,dc=com
+objectClass: extensibleObject
+objectClass: alias
+uid: user1
+aliasedObjectName: uid=user1,ou=sales,ou=users,dc=example,dc=com
+description: alias
+#aliasedObjectName: uid=user1,ou=engineering,ou=users,dc=example,dc=com
+#description: chained alias
+
+dn: cn=deputy,uid=user1,ou=sales,ou=users,dc=example,dc=com
+objectClass: extensibleObject
+objectClass: alias
+cn: deputy
+aliasedObjectName: uid=user2,ou=sales,ou=users,dc=example,dc=com
+description: alias to parent's sibling, builds an indirect loop!
+
+#dn: cn=deputy,uid=user3,ou=engineering,ou=users,dc=example,dc=com
+#objectClass: extensibleObject
+#objectClass: alias
+#cn: deputy
+#aliasedObjectName: uid=user3,ou=engineering,ou=users,dc=example,dc=com
+#description: alias to parent, builds a direct loop!
+
+dn: cn=deputy,uid=user2,ou=sales,ou=users,dc=example,dc=com
+objectClass: extensibleObject
+objectClass: alias
+cn: deputy
+aliasedObjectName: uid=user1,ou=sales,ou=users,dc=example,dc=com
+description: alias to parent's sibling, builds an indirect loop!
+
+#dn: ou=hr,ou=users,dc=example,dc=com
+#objectClass: extensibleObject
+#objectClass: alias
+#ou: hr
+#aliasedObjectName: ou=human resources,ou=users,o=acme
+#description: alias to another partition
+
+#dn: o=acme
+#objectClass: organization
+#objectClass: top
+#o: acme
+
+#dn: ou=users,o=acme
+#objectClass: organizationalUnit
+#objectClass: top
+#ou: users
+
+#dn: ou=human resources,ou=users,o=acme
+#objectClass: organizationalUnit
+#objectClass: top
+#ou: human resources
+
+#dn: uid=userA,ou=human resources,ou=users,o=acme
+#objectClass: inetOrgPerson
+#objectClass: organizationalPerson
+#objectClass: person
+#objectClass: top
+#uid: userA
+#cn: User A
+#sn: A
+#givenName: User
+
+#dn: uid=userB,ou=human resources,ou=users,o=acme
+#objectClass: inetOrgPerson
+#objectClass: organizationalPerson
+#objectClass: person
+#objectClass: top
+#uid: userB
+#cn: User B
+#sn: B
+#givenName: User