/*
 *  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 org.apache.directory.server.core.integ.IntegrationUtils.getAdminConnection;
import static org.apache.directory.server.core.integ.IntegrationUtils.getRootContext;
import static org.apache.directory.server.core.integ.IntegrationUtils.getSystemContext;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InvalidSearchFilterException;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapContext;

import org.apache.directory.api.ldap.model.constants.JndiPropertyConstants;
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.cursor.EntryCursor;
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.entry.StringValue;
import org.apache.directory.api.ldap.model.entry.Value;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.filter.ExprNode;
import org.apache.directory.api.ldap.model.filter.GreaterEqNode;
import org.apache.directory.api.ldap.model.filter.LessEqNode;
import org.apache.directory.api.ldap.model.ldif.LdifUtils;
import org.apache.directory.api.ldap.model.message.AliasDerefMode;
import org.apache.directory.api.ldap.model.message.SearchScope;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.ldap.model.schema.AttributeType;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.server.core.annotations.ApplyLdifs;
import org.apache.directory.server.core.annotations.CreateDS;
import org.apache.directory.server.core.annotations.LoadSchema;
import org.apache.directory.server.core.api.LdapCoreSessionConnection;
import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
import org.apache.directory.server.core.integ.FrameworkRunner;
import org.apache.directory.server.core.integ.IntegrationUtils;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;


/**
 * Tests the search() methods of the provider.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
@RunWith(FrameworkRunner.class)
@CreateDS(name = "SearchDS",
    loadedSchemas =
        { @LoadSchema(name = "nis", enabled = true) })
@ApplyLdifs(
    {
        "dn: m-oid=2.2.0, ou=attributeTypes, cn=apachemeta, ou=schema",
        "objectclass: metaAttributeType",
        "objectclass: metaTop",
        "objectclass: top",
        "m-oid: 2.2.0",
        "m-name: integerAttribute",
        "m-description: the precursor for all integer attributes",
        "m-equality: integerMatch",
        "m-ordering: integerOrderingMatch",
        "m-syntax: 1.3.6.1.4.1.1466.115.121.1.27",
        "m-length: 0",
        "",
        "dn: ou=testing00,ou=system",
        "objectClass: top",
        "objectClass: organizationalUnit",
        "objectClass: extensibleObject",
        "ou: testing00",
        "integerAttribute: 0",
        "",
        "dn: ou=testing01,ou=system",
        "objectClass: top",
        "objectClass: organizationalUnit",
        "objectClass: extensibleObject",
        "ou: testing01",
        "integerAttribute: 1",
        "",
        "dn: ou=testing02,ou=system",
        "objectClass: top",
        "objectClass: organizationalUnit",
        "objectClass: extensibleObject",
        "ou: testing02",
        "integerAttribute: 2",
        "",
        "dn: ou=testing03,ou=system",
        "objectClass: top",
        "objectClass: organizationalUnit",
        "objectClass: extensibleObject",
        "ou: testing03",
        "integerAttribute: 3",
        "",
        "dn: ou=testing04,ou=system",
        "objectClass: top",
        "objectClass: organizationalUnit",
        "objectClass: extensibleObject",
        "ou: testing04",
        "integerAttribute: 4",
        "",
        "dn: ou=testing05,ou=system",
        "objectClass: top",
        "objectClass: organizationalUnit",
        "objectClass: extensibleObject",
        "ou: testing05",
        "integerAttribute: 5",
        "",
        "dn: ou=subtest,ou=testing01,ou=system",
        "objectClass: top",
        "objectClass: organizationalUnit",
        "ou: subtest",
        "",
        "dn: cn=Heather Nova, ou=system",
        "objectClass: top",
        "objectClass: person",
        "cn: Heather Nova",
        "sn: Nova",
        "telephoneNumber: 1 801 555 1212 ",
        "",
        "dn: cn=with-dn, ou=system",
        "objectClass: top",
        "objectClass: person",
        "objectClass: organizationalPerson",
        "objectClass: inetorgPerson",
        "cn: singer",
        "sn: manager",
        "telephoneNumber: 1 801 555 1212 ",
        "manager: cn=Heather Nova, ou=system",
        "",
        "dn: cn=testGroup0,ou=groups,ou=system",
        "objectClass: top",
        "objectClass: posixGroup",
        "cn: testGroup0",
        "gidNumber: 0",
        "",
        "dn: cn=testGroup1,ou=groups,ou=system",
        "objectClass: top",
        "objectClass: posixGroup",
        "cn: testGroup1",
        "gidNumber: 1",
        "",
        "dn: cn=testGroup2,ou=groups,ou=system",
        "objectClass: top",
        "objectClass: posixGroup",
        "cn: testGroup2",
        "gidNumber: 2",
        "",
        "dn: cn=testGroup4,ou=groups,ou=system",
        "objectClass: top",
        "objectClass: posixGroup",
        "cn: testGroup4",
        "gidNumber: 4",
        "",
        "dn: cn=testGroup5,ou=groups,ou=system",
        "objectClass: top",
        "objectClass: posixGroup",
        "cn: testGroup5",
        "gidNumber: 5" })
public class SearchIT extends AbstractLdapTestUnit
{
    private static final String RDN = "cn=Heather Nova";
    private static final String FILTER = "(objectclass=*)";

    public static LdapContext sysRoot;


    /**
     * @param sysRoot the system root to add entries to
     * @throws NamingException on errors
     */
    @Before
    public void init() throws Exception
    {
        sysRoot = getSystemContext( getService() );
    }


    @Test
    public void testSearchOneLevel() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(ou=*)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 9, map.size() );
        assertTrue( map.containsKey( "ou=testing00,ou=system" ) );
        assertTrue( map.containsKey( "ou=testing01,ou=system" ) );
        assertTrue( map.containsKey( "ou=testing02,ou=system" ) );
    }


    @Test
    public void testSearchSubTreeLevel() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );

        HashMap<String, Attributes> map = new HashMap<String, Attributes>();
        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(ou=*)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect", 14, map.size() );
        assertTrue( map.containsKey( "ou=system" ) );
        assertTrue( map.containsKey( "ou=testing00,ou=system" ) );
        assertTrue( map.containsKey( "ou=testing01,ou=system" ) );
        assertTrue( map.containsKey( "ou=testing02,ou=system" ) );
        assertTrue( map.containsKey( "ou=subtest,ou=testing01,ou=system" ) );
    }


    @Test
    public void testSearchSubTreeLevelNoAttributes() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );
        controls.setReturningAttributes( new String[]
            { "1.1" } );

        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );

        HashMap<String, Attributes> map = new HashMap<String, Attributes>();
        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(ou=testing02)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect", 1, map.size() );
        assertTrue( map.containsKey( "ou=testing02,ou=system" ) );
        Attributes attrs = map.get( "ou=testing02,ou=system" );
        assertEquals( 0, attrs.size() );
    }


    @Test
    public void testSearchSubstringSubTreeLevel() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );

        HashMap<String, Attributes> map = new HashMap<String, Attributes>();
        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(objectClass=organ*)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        // 16 because it also matches organizationalPerson which the admin is
        assertEquals( "Expected number of results returned was incorrect", 17, map.size() );
        assertTrue( map.containsKey( "ou=system" ) );
        assertTrue( map.containsKey( "ou=configuration,ou=system" ) );
        assertTrue( map.containsKey( "ou=interceptors,ou=configuration,ou=system" ) );
        assertTrue( map.containsKey( "ou=partitions,ou=configuration,ou=system" ) );
        assertTrue( map.containsKey( "ou=services,ou=configuration,ou=system" ) );
        assertTrue( map.containsKey( "ou=groups,ou=system" ) );
        assertTrue( map.containsKey( "ou=testing00,ou=system" ) );
        assertTrue( map.containsKey( "ou=testing01,ou=system" ) );
        assertTrue( map.containsKey( "ou=subtest,ou=testing01,ou=system" ) );
        assertTrue( map.containsKey( "ou=testing02,ou=system" ) );
        assertTrue( map.containsKey( "ou=users,ou=system" ) );
        assertTrue( map.containsKey( "prefNodeName=sysPrefRoot,ou=system" ) );
        assertTrue( map.containsKey( "uid=admin,ou=system" ) );
    }


    /**
     * Tests to make sure undefined attributes in filter assertions are pruned and do not
     * result in exceptions.
     */
    @Test
    public void testBogusAttributeInSearchFilter() throws Exception
    {
        boolean oldSetAllowAnnonymousAccess = getService().isAllowAnonymousAccess();
        getService().setAllowAnonymousAccess( true );

        SearchControls cons = new SearchControls();
        NamingEnumeration<SearchResult> e = sysRoot.search( "", "(bogusAttribute=abc123)", cons );
        assertNotNull( e );

        e.close();

        e = sysRoot.search( "", "(!(bogusAttribute=abc123))", cons );
        assertNotNull( e );
        assertFalse( e.hasMore() );

        e.close();

        e = sysRoot.search( "", "(|(bogusAttribute=abc123)(bogusAttribute=abc123))", cons );
        assertNotNull( e );
        assertFalse( e.hasMore() );

        e.close();

        e = sysRoot.search( "", "(|(bogusAttribute=abc123)(ou=abc123))", cons );
        assertNotNull( e );
        assertFalse( e.hasMore() );

        e.close();

        e = sysRoot.search( "", "(OBJECTclass=*)", cons );
        assertNotNull( e );
        assertTrue( e.hasMore() );

        e.close();

        e = sysRoot.search( "", "(objectclass=*)", cons );
        assertNotNull( e );

        e.close();

        getService().setAllowAnonymousAccess( oldSetAllowAnnonymousAccess );
    }


    @Test
    public void testSearchFilterArgs() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(|(ou={0})(ou={1}))", new Object[]
            { "testing00", "testing01" }, controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 2, map.size() );
        assertTrue( map.containsKey( "ou=testing00,ou=system" ) );
        assertTrue( map.containsKey( "ou=testing01,ou=system" ) );
    }


    @Test
    public void testFilterExpansion0() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );

        HashMap<String, Attributes> map = new HashMap<String, Attributes>();
        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(name=testing00)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "size of results", 1, map.size() );
        assertTrue( "contains ou=testing00,ou=system", map.containsKey( "ou=testing00,ou=system" ) );
    }


    @Test
    public void testFilterExpansion1() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );

        HashMap<String, Attributes> map = new HashMap<String, Attributes>();
        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(name=*)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "size of results", 23, map.size() );
        assertTrue( "contains ou=testing00,ou=system", map.containsKey( "ou=testing00,ou=system" ) );
        assertTrue( "contains ou=testing01,ou=system", map.containsKey( "ou=testing01,ou=system" ) );
        assertTrue( "contains ou=testing02,ou=system", map.containsKey( "ou=testing01,ou=system" ) );
        assertTrue( "contains ou=configuration,ou=system", map.containsKey( "ou=configuration,ou=system" ) );
        assertTrue( "contains ou=groups,ou=system", map.containsKey( "ou=groups,ou=system" ) );
        assertTrue( "contains ou=interceptors,ou=configuration,ou=system", map
            .containsKey( "ou=interceptors,ou=configuration,ou=system" ) );
        assertTrue( "contains ou=partitions,ou=configuration,ou=system", map
            .containsKey( "ou=partitions,ou=configuration,ou=system" ) );
        assertTrue( "contains ou=services,ou=configuration,ou=system", map
            .containsKey( "ou=services,ou=configuration,ou=system" ) );
        assertTrue( "contains ou=subtest,ou=testing01,ou=system", map.containsKey( "ou=subtest,ou=testing01,ou=system" ) );
        assertTrue( "contains ou=system", map.containsKey( "ou=system" ) );
        assertTrue( "contains ou=users,ou=system", map.containsKey( "ou=users,ou=system" ) );
        assertTrue( "contains uid=admin,ou=system", map.containsKey( "uid=admin,ou=system" ) );
        assertTrue( "contains cn=administrators,ou=groups,ou=system", map
            .containsKey( "cn=Administrators,ou=groups,ou=system" ) );
    }


    @Test
    public void testFilterExpansion2() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );

        HashMap<String, Attributes> map = new HashMap<String, Attributes>();
        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(|(name=testing00)(name=testing01))", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "size of results", 2, map.size() );
        assertTrue( "contains ou=testing00,ou=system", map.containsKey( "ou=testing00,ou=system" ) );
        assertTrue( "contains ou=testing01,ou=system", map.containsKey( "ou=testing01,ou=system" ) );
    }


    @Test
    public void testFilterExpansion4() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );

        HashMap<String, Attributes> map = new HashMap<String, Attributes>();
        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(name=testing*)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "size of results", 6, map.size() );
        assertTrue( "contains ou=testing00,ou=system", map.containsKey( "ou=testing00,ou=system" ) );
        assertTrue( "contains ou=testing01,ou=system", map.containsKey( "ou=testing01,ou=system" ) );
        assertTrue( "contains ou=testing02,ou=system", map.containsKey( "ou=testing02,ou=system" ) );
        assertTrue( "contains ou=testing03,ou=system", map.containsKey( "ou=testing03,ou=system" ) );
        assertTrue( "contains ou=testing04,ou=system", map.containsKey( "ou=testing04,ou=system" ) );
        assertTrue( "contains ou=testing05,ou=system", map.containsKey( "ou=testing05,ou=system" ) );
    }


    @Test
    public void testFilterExpansion5() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );

        HashMap<String, Attributes> map = new HashMap<String, Attributes>();
        String filter = "(|(2.5.4.11.1=testing*)(2.5.4.54=testing*)(2.5.4.10=testing*)"
            + "(2.5.4.6=testing*)(2.5.4.43=testing*)(2.5.4.7.1=testing*)(2.5.4.10.1=testing*)"
            + "(2.5.4.44=testing*)(2.5.4.11=testing*)(2.5.4.4=testing*)(2.5.4.8.1=testing*)"
            + "(2.5.4.12=testing*)(1.3.6.1.4.1.18060.0.4.1.2.3=testing*)"
            + "(2.5.4.7=testing*)(2.5.4.3=testing*)(2.5.4.8=testing*)(2.5.4.42=testing*))";
        NamingEnumeration<SearchResult> list = sysRoot.search( "", filter, controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "size of results", 6, map.size() );
        assertTrue( "contains ou=testing00,ou=system", map.containsKey( "ou=testing00,ou=system" ) );
        assertTrue( "contains ou=testing01,ou=system", map.containsKey( "ou=testing01,ou=system" ) );
        assertTrue( "contains ou=testing02,ou=system", map.containsKey( "ou=testing02,ou=system" ) );
        assertTrue( "contains ou=testing03,ou=system", map.containsKey( "ou=testing03,ou=system" ) );
        assertTrue( "contains ou=testing04,ou=system", map.containsKey( "ou=testing04,ou=system" ) );
        assertTrue( "contains ou=testing05,ou=system", map.containsKey( "ou=testing05,ou=system" ) );
    }


    @Test
    public void testOpAttrDenormalizationOff() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );
        controls.setReturningAttributes( new String[]
            { "creatorsName" } );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(ou=testing00)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 1, map.size() );
        assertTrue( map.containsKey( "ou=testing00,ou=system" ) );
        Attributes attrs = map.get( "ou=testing00,ou=system" );
        assertEquals( "normalized creator's name", "0.9.2342.19200300.100.1.1=admin,2.5.4.11=system", attrs.get(
            "creatorsName" ).get() );
    }


    @Test
    public void testOpAttrDenormalizationOn() throws Exception
    {
        getService().setDenormalizeOpAttrsEnabled( true );
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );
        controls.setReturningAttributes( new String[]
            { "creatorsName" } );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(ou=testing00)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 1, map.size() );
        assertTrue( map.containsKey( "ou=testing00,ou=system" ) );
        Attributes attrs = map.get( "ou=testing00,ou=system" );
        assertEquals( "normalized creator's name", "uid=admin,ou=system", attrs.get( "creatorsName" ).get() );
    }


    /**
     * Creation of required attributes of a person entry.
     *
     * @param cn the commonName of the person
     * @param sn the surName of the person
     * @return the attributes of a new person entry
     */
    protected Attributes getPersonAttributes( String sn, String cn ) throws LdapException
    {
        Attributes attributes = LdifUtils.createJndiAttributes( "objectClass: top", "objectClass: top",
            "objectClass: person", "cn", cn, "sn", sn );

        return attributes;
    }


    @Test
    public void testBinaryAttributesInFilter() throws Exception
    {
        byte[] certData = new byte[]
            { 0x34, 0x56, 0x4e, 0x5f };

        // First let's add a some binary data representing a userCertificate
        Attributes attrs = getPersonAttributes( "Bush", "Kate Bush" );
        attrs.put( "userCertificate", certData );

        Attribute objectClasses = attrs.get( "objectClass" );
        objectClasses.add( "strongAuthenticationUser" );

        sysRoot.createSubcontext( "cn=Kate Bush", attrs );

        // Search for kate by cn first
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        NamingEnumeration<SearchResult> enm = sysRoot.search( "", "(cn=Kate Bush)", controls );
        assertTrue( enm.hasMore() );
        SearchResult sr = enm.next();
        assertNotNull( sr );
        assertFalse( enm.hasMore() );

        enm.close();

        assertEquals( "cn=Kate Bush,ou=system", sr.getName() );

        enm = sysRoot.search( "", "(userCertificate=\\34\\56\\4E\\5F)", controls );
        assertTrue( enm.hasMore() );
        sr = enm.next();
        assertNotNull( sr );
        assertFalse( enm.hasMore() );
        assertEquals( "cn=Kate Bush,ou=system", sr.getName() );

        enm.close();
    }


    @Test
    public void testSearchOperationalAttr() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );
        controls.setReturningAttributes( new String[]
            { "+" } );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(ou=testing01)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 1, map.size() );

        Attributes attrs = map.get( "ou=testing01,ou=system" );

        assertNotNull( attrs.get( "createTimestamp" ) );
        assertNotNull( attrs.get( "creatorsName" ) );
        assertNull( attrs.get( "objectClass" ) );
        assertNull( attrs.get( "ou" ) );
    }


    @Test
    public void testSearchUserAttr() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );
        controls.setReturningAttributes( new String[]
            { "*" } );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(ou=testing01)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 1, map.size() );

        Attributes attrs = map.get( "ou=testing01,ou=system" );

        assertNotNull( attrs.get( "objectClass" ) );
        assertNotNull( attrs.get( "ou" ) );
        assertNull( attrs.get( "createTimestamp" ) );
        assertNull( attrs.get( "creatorsName" ) );
    }


    @Test
    public void testSearchUserAttrAndOpAttr() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );
        controls.setReturningAttributes( new String[]
            { "*", "creatorsName" } );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(ou=testing01)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 1, map.size() );

        Attributes attrs = map.get( "ou=testing01,ou=system" );

        assertNotNull( attrs.get( "objectClass" ) );
        assertNotNull( attrs.get( "ou" ) );
        assertNotNull( attrs.get( "creatorsName" ) );
        assertNull( attrs.get( "createTimestamp" ) );
    }


    @Test
    public void testSearchUserAttrAndNoAttr() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );
        controls.setReturningAttributes( new String[]
            { "1.1", "ou" } );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(ou=testing01)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 1, map.size() );

        Attributes attrs = map.get( "ou=testing01,ou=system" );

        assertNull( attrs.get( "objectClass" ) );
        assertNotNull( attrs.get( "ou" ) );
        assertNull( attrs.get( "creatorsName" ) );
        assertNull( attrs.get( "createTimestamp" ) );
    }


    @Test
    public void testSearchNoAttr() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );
        controls.setReturningAttributes( new String[]
            { "1.1" } );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(ou=testing01)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 1, map.size() );

        Attributes attrs = map.get( "ou=testing01,ou=system" );

        assertNull( attrs.get( "objectClass" ) );
        assertNull( attrs.get( "ou" ) );
        assertNull( attrs.get( "creatorsName" ) );
        assertNull( attrs.get( "createTimestamp" ) );
    }


    @Test
    public void testSearchAllAttr() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );
        controls.setReturningAttributes( new String[]
            { "+", "*" } );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(ou=testing01)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 1, map.size() );

        Attributes attrs = map.get( "ou=testing01,ou=system" );

        assertNotNull( attrs.get( "createTimestamp" ) );
        assertNotNull( attrs.get( "creatorsName" ) );
        assertNotNull( attrs.get( "objectClass" ) );
        assertNotNull( attrs.get( "ou" ) );
    }


    /**
     * Search an entry and fetch an attribute with unknown option
     * @throws NamingException if there are errors
     */
    @Test
    @Ignore("We don't support options")
    public void testSearchFetchNonExistingAttributeOption() throws Exception
    {
        SearchControls ctls = new SearchControls();
        ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
        ctls.setReturningAttributes( new String[]
            { "cn", "sn;unknownOption", "badAttr" } );

        NamingEnumeration<SearchResult> result = sysRoot.search( RDN, FILTER, ctls );

        if ( result.hasMore() )
        {
            SearchResult entry = result.next();
            Attributes attrs = entry.getAttributes();
            Attribute cn = attrs.get( "cn" );

            assertNotNull( cn );
            assertEquals( "Heather Nova", cn.get().toString() );

            Attribute sn = attrs.get( "sn" );
            assertNull( sn );
        }
        else
        {
            fail( "entry " + RDN + " not found" );
        }

        result.close();
    }


    /**
     * Search an entry and fetch an attribute and all its subtypes
     * @throws NamingException if there are errors
     */
    @Test
    public void testSearchFetchAttributeAndSubTypes() throws Exception
    {
        SearchControls ctls = new SearchControls();
        ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
        ctls.setReturningAttributes( new String[]
            { "name" } );

        NamingEnumeration<SearchResult> result = sysRoot.search( RDN, FILTER, ctls );

        if ( result.hasMore() )
        {
            SearchResult entry = result.next();
            Attributes attrs = entry.getAttributes();

            // We should have get cn and sn only
            assertEquals( 2, attrs.size() );

            // Check CN
            Attribute cn = attrs.get( "cn" );

            assertNotNull( cn );
            assertEquals( "Heather Nova", cn.get().toString() );

            // Assert SN
            Attribute sn = attrs.get( "sn" );
            assertNotNull( sn );
            assertEquals( "Nova", sn.get().toString() );
        }
        else
        {
            fail( "entry " + RDN + " not found" );
        }

        result.close();
    }


    /**
     * Search an entry and fetch an attribute with twice the same attributeType
     * @throws NamingException if there are errors
     */
    @Test
    public void testSearchFetchTwiceSameAttribute() throws Exception
    {
        SearchControls ctls = new SearchControls();
        ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
        ctls.setReturningAttributes( new String[]
            { "cn", "cn" } );

        NamingEnumeration<SearchResult> result = sysRoot.search( RDN, FILTER, ctls );

        if ( result.hasMore() )
        {
            SearchResult entry = result.next();
            Attributes attrs = entry.getAttributes();
            Attribute cn = attrs.get( "cn" );

            assertNotNull( cn );
            assertEquals( "Heather Nova", cn.get().toString() );
        }
        else
        {
            fail( "entry " + RDN + " not found" );
        }

        result.close();
    }


    // this one is failing because it returns the admin user twice: count = 15
    //    public void testFilterExpansion3() throws Exception
    //    {
    //        SearchControls controls = new SearchControls();
    //        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
    //        controls.setDerefLinkFlag( false );
    //        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES );
    //
    //        List map = new ArrayList();
    //        NamingEnumeration list = sysRoot.search( "", "(name=*)", controls );
    //        while ( list.hasMore() )
    //        {
    //            SearchResult result = ( SearchResult ) list.next();
    //            map.add( result.getName() );
    //        }
    //        assertEquals( "size of results", 14, map.size() );
    //        assertTrue( "contains ou=testing00,ou=system", map.contains( "ou=testing00,ou=system" ) );
    //        assertTrue( "contains ou=testing01,ou=system", map.contains( "ou=testing01,ou=system" ) );
    //        assertTrue( "contains ou=testing02,ou=system", map.contains( "ou=testing01,ou=system" ) );
    //        assertTrue( "contains uid=akarasulu,ou=users,ou=system", map.contains( "uid=akarasulu,ou=users,ou=system" ) );
    //        assertTrue( "contains ou=configuration,ou=system", map.contains( "ou=configuration,ou=system" ) );
    //        assertTrue( "contains ou=groups,ou=system", map.contains( "ou=groups,ou=system" ) );
    //        assertTrue( "contains ou=interceptors,ou=configuration,ou=system", map.contains( "ou=interceptors,ou=configuration,ou=system" ) );
    //        assertTrue( "contains ou=partitions,ou=configuration,ou=system", map.contains( "ou=partitions,ou=configuration,ou=system" ) );
    //        assertTrue( "contains ou=services,ou=configuration,ou=system", map.contains( "ou=services,ou=configuration,ou=system" ) );
    //        assertTrue( "contains ou=subtest,ou=testing01,ou=system", map.contains( "ou=subtest,ou=testing01,ou=system" ) );
    //        assertTrue( "contains ou=system", map.contains( "ou=system" ) );
    //        assertTrue( "contains ou=users,ou=system", map.contains( "ou=users,ou=system" ) );
    //        assertTrue( "contains uid=admin,ou=system", map.contains( "uid=admin,ou=system" ) );
    //        assertTrue( "contains cn=administrators,ou=groups,ou=system", map.contains( "cn=administrators,ou=groups,ou=system" ) );
    //    }

    /**
     *  Convenience method that performs a one level search using the
     *  specified filter returning their DNs as Strings in a set.
     *
     * @param controls the search controls
     * @param filter the filter expression
     * @return the set of groups
     * @throws NamingException if there are problems conducting the search
     */
    public Set<String> searchGroups( String filter, SearchControls controls ) throws Exception
    {
        if ( controls == null )
        {
            controls = new SearchControls();
        }

        Set<String> results = new HashSet<String>();
        NamingEnumeration<SearchResult> list = getSystemContext( getService() ).search( "ou=groups", filter, controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            results.add( result.getName() );
        }

        list.close();

        return results;
    }


    /**
     *  Convenience method that performs a one level search using the
     *  specified filter returning their DNs as Strings in a set.
     *
     * @param filter the filter expression
     * @return the set of group names
     * @throws NamingException if there are problems conducting the search
     */
    public Set<String> searchGroups( String filter ) throws Exception
    {
        return searchGroups( filter, null );
    }


    /**
     *  Convenience method that performs a one level search using the
     *  specified filter returning their DNs as Strings in a set.
     *
     * @param controls the search controls
     * @return the set of groups
     * @throws NamingException if there are problems conducting the search
     */
    public Set<String> searchRevisions( String filter ) throws Exception
    {
        SearchControls controls = new SearchControls();

        Set<String> results = new HashSet<String>();
        NamingEnumeration<SearchResult> list = getSystemContext( getService() ).search( "", filter, controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            results.add( result.getName() );
        }

        list.close();

        return results;
    }


    /**
     *  Convenience method that performs a one level search using the
     *  specified filter returning their DNs as Strings in a set.
     *
     * @param controls the search controls
     * @param filter the filter expression
     * @return the set of groups
     * @throws NamingException if there are problems conducting the search
     */
    private Set<String> searchUnits( String filter, SearchControls controls ) throws Exception
    {
        if ( controls == null )
        {
            controls = new SearchControls();
        }

        Set<String> results = new HashSet<String>();
        NamingEnumeration<SearchResult> list = getSystemContext( getService() ).search( "", filter, controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            results.add( result.getName() );
        }

        list.close();

        return results;
    }


    @Test
    public void testSetup() throws Exception
    {
        Set<String> results = searchGroups( "(objectClass=posixGroup)" );
        assertTrue( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );
    }


    @Test
    public void testLessThanSearch() throws Exception
    {
        Set<String> results = searchGroups( "(gidNumber<=5)" );
        assertTrue( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );

        results = searchGroups( "(gidNumber<=4)" );
        assertTrue( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );

        results = searchGroups( "(gidNumber<=3)" );
        assertTrue( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );

        results = searchGroups( "(gidNumber<=0)" );
        assertTrue( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );

        results = searchGroups( "(gidNumber<=-1)" );
        assertFalse( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );
    }


    @Test
    public void testGreaterThanSearch() throws Exception
    {
        Set<String> results = searchGroups( "(gidNumber>=0)" );
        assertTrue( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );

        results = searchGroups( "(gidNumber>=1)" );
        assertFalse( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );

        results = searchGroups( "(gidNumber>=3)" );
        assertFalse( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );

        results = searchGroups( "(gidNumber>=6)" );
        assertFalse( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );
    }


    @Test
    public void testNotOperator() throws Exception
    {
        Set<String> results = searchGroups( "(!(gidNumber=4))" );
        assertTrue( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );
    }


    @Test
    public void testNotOperatorSubtree() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );

        Set<String> results = searchGroups( "(!(gidNumber=4))", controls );
        assertTrue( results.contains( "cn=testGroup0,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup1,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup2,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup3,ou=groups,ou=system" ) );
        assertFalse( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
        assertTrue( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );
    }


    @Test
    public void testSearchWithEscapedCharsInFilter() throws Exception
    {
        // Create entry cn=Sid Vicious, ou=system
        Attributes vicious = LdifUtils.createJndiAttributes( "objectClass: top", "objectClass: person",
            "cn: Sid Vicious",
            "sn: Vicious", "description: (sex*pis\\tols)" );

        DirContext ctx = sysRoot.createSubcontext( "cn=Sid Vicious", vicious );
        assertNotNull( ctx );

        ctx = ( DirContext ) sysRoot.lookup( "cn=Sid Vicious" );
        assertNotNull( ctx );

        Attributes attributes = ctx.getAttributes( "" );

        assertEquals( "(sex*pis\\tols)", attributes.get( "description" ).get() );

        // Now, search for the description
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );

        controls.setReturningAttributes( new String[]
            { "*" } );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot
            .search( "", "(description=\\28sex\\2Apis\\5Ctols\\29)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 1, map.size() );

        Attributes attrs = map.get( "cn=Sid Vicious,ou=system" );

        assertNotNull( attrs.get( "objectClass" ) );
        assertNotNull( attrs.get( "cn" ) );
    }


    @Test
    public void testSubstringSearchWithEscapedCharsInFilter() throws Exception
    {
        // Create entry cn=Sid Vicious, ou=system
        Attributes vicious = LdifUtils.createJndiAttributes( "objectClass: top", "objectClass: person",
            "cn: Sid Vicious",
            "sn: Vicious", "description: (sex*pis\\tols)" );

        DirContext ctx = sysRoot.createSubcontext( "cn=Sid Vicious", vicious );
        assertNotNull( ctx );

        ctx = ( DirContext ) sysRoot.lookup( "cn=Sid Vicious" );
        assertNotNull( ctx );

        Attributes attributes = ctx.getAttributes( "" );

        assertEquals( "(sex*pis\\tols)", attributes.get( "description" ).get() );

        // Now, search for the description
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );
        controls.setReturningAttributes( new String[]
            { "*" } );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );

        String[] filters = new String[]
            { "(description=*\\28*)", "(description=*\\29*)", "(description=*\\2A*)", "(description=*\\5C*)" };

        for ( String filter : filters )
        {
            HashMap<String, Attributes> map = new HashMap<String, Attributes>();
            NamingEnumeration<SearchResult> list = sysRoot.search( "", filter, controls );

            while ( list.hasMore() )
            {
                SearchResult result = list.next();
                map.put( result.getName(), result.getAttributes() );
            }

            list.close();

            assertEquals( "Expected number of results returned was incorrect!", 1, map.size() );

            Attributes attrs = map.get( "cn=Sid Vicious,ou=system" );

            assertNotNull( attrs.get( "objectClass" ) );
            assertNotNull( attrs.get( "cn" ) );
        }
    }


    @Test
    public void testSubstringSearchWithEscapedAsterisksInFilter_DIRSERVER_1181() throws Exception
    {
        Attributes vicious = LdifUtils.createJndiAttributes( "objectClass: top", "objectClass: person", "cn: x*y*z*",
            "sn: x*y*z*", "description: (sex*pis\\tols)" );

        sysRoot.createSubcontext( "cn=x*y*z*", vicious );

        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setReturningAttributes( new String[]
            { "cn" } );
        NamingEnumeration<SearchResult> res;

        res = sysRoot.search( "", "(cn=*x\\2Ay\\2Az\\2A*)", controls );
        assertTrue( res.hasMore() );
        assertEquals( "x*y*z*", res.next().getAttributes().get( "cn" ).get() );
        assertFalse( res.hasMore() );

        res.close();

        res = sysRoot.search( "", "(cn=*{0}*)", new String[]
            { "x*y*z*" }, controls );
        assertTrue( res.hasMore() );
        assertEquals( "x*y*z*", res.next().getAttributes().get( "cn" ).get() );
        assertFalse( res.hasMore() );

        res.close();
    }


    /**
     * Test a search with a bad filter : there is a missing closing ')'
     */
    @Test
    public void testBadFilter() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );

        try
        {
            sysRoot.search( "", "(|(name=testing00)(name=testing01)", controls );
            fail();
        }
        catch ( InvalidSearchFilterException isfe )
        {
            assertTrue( true );
        }
    }


    /**
     * Search operation with a base Dn with quotes
     * Commented as it's not valid by RFC 5514
    @Test
    public void testSearchWithQuotesInBase() throws NamingException
    {
        LdapContext sysRoot = getSystemContext( getService() );
        createData( sysRoot );
    
        SearchControls ctls = new SearchControls();
        ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
        String filter = "(cn=Tori Amos)";
        ctls.setReturningAttributes( new String[]
            { "cn", "cn" } );
    
        // Search for cn="Tori Amos" (with quotes)
        String base = "cn=\"Tori Amos\"";
    
        try {
            // Check entry
            NamingEnumeration<SearchResult> result = sysRoot.search( base, filter, ctls );
            assertTrue( result.hasMore() );
    
            while ( result.hasMore() )
            {
                SearchResult sr = result.next();
                Attributes attrs = sr.getAttributes();
                Attribute sn = attrs.get( "cn" );
                assertNotNull(sn);
                assertTrue( sn.contains( "Amos" ) );
            }
        } catch (Exception e)
        {
            fail( e.getMessage() );
        }
    }
    */

    /**
    * Added to test correct comparison of integer attribute types when searching.
    * testGreaterThanSearch and testLesserThanSearch fail to detect the problem using values less than 10.
    * Ref. DIRSERVER-1296
    *
    * @throws Exception
    */
    @Test
    public void testIntegerComparison() throws Exception
    {
        Set<String> results = searchUnits( "(&(objectClass=organizationalUnit)(integerAttribute<=2))", null );
        assertTrue( results.contains( "ou=testing00,ou=system" ) );
        assertTrue( results.contains( "ou=testing01,ou=system" ) );
        assertTrue( results.contains( "ou=testing02,ou=system" ) );
        assertFalse( results.contains( "ou=testing03,ou=system" ) );
        assertFalse( results.contains( "ou=testing04,ou=system" ) );
        assertFalse( results.contains( "ou=testing05,ou=system" ) );
    }


    /**
     * Added to test correct comparison of integer attribute types when searching.
     * testGreaterThanSearch and testLesserThanSearch fail to detect the problem using values less than 10.
     * Ref. DIRSERVER-1296
     *
     * @throws Exception
     */
    @Test
    public void testIntegerComparison2() throws Exception
    {
        Set<String> results = searchUnits( "(&(objectClass=organizationalUnit)(integerAttribute>=3))", null );
        assertFalse( results.contains( "ou=testing00,ou=system" ) );
        assertFalse( results.contains( "ou=testing01,ou=system" ) );
        assertFalse( results.contains( "ou=testing02,ou=system" ) );
        assertTrue( results.contains( "ou=testing03,ou=system" ) );
        assertTrue( results.contains( "ou=testing04,ou=system" ) );
        assertTrue( results.contains( "ou=testing05,ou=system" ) );
    }


    /**
     * Added to test correct comparison of integer attribute types when searching.
     * testGreaterThanSearch and testLesserThanSearch fail to detect the problem using values less than 10.
     * Ref. DIRSERVER-1296
     *
     * @throws Exception
     */
    @Test
    public void testIntegerComparison3() throws Exception
    {
        Set<String> results = searchUnits( "(&(objectClass=organizationalUnit)(integerAttribute<=42))", null );
        assertTrue( results.contains( "ou=testing00,ou=system" ) );
        assertTrue( results.contains( "ou=testing01,ou=system" ) );
        assertTrue( results.contains( "ou=testing02,ou=system" ) );
        assertTrue( results.contains( "ou=testing03,ou=system" ) );
        assertTrue( results.contains( "ou=testing04,ou=system" ) );
        assertTrue( results.contains( "ou=testing05,ou=system" ) );
    }


    /**
     * Added to test correct comparison of integer attribute types when searching.
     * testGreaterThanSearch and testLesserThanSearch fail to detect the problem using values less than 10.
     * Ref. DIRSERVER-1296
     *
     * @throws Exception
     */
    @Test
    public void testIntegerComparison4() throws Exception
    {
        Set<String> results = searchUnits(
            "(&(objectClass=organizationalUnit)(|(integerAttribute<=1)(integerAttribute>=5)))", null );
        assertTrue( results.contains( "ou=testing00,ou=system" ) );
        assertTrue( results.contains( "ou=testing01,ou=system" ) );
        assertFalse( results.contains( "ou=testing02,ou=system" ) );
        assertFalse( results.contains( "ou=testing03,ou=system" ) );
        assertFalse( results.contains( "ou=testing04,ou=system" ) );
        assertTrue( results.contains( "ou=testing05,ou=system" ) );
    }


    @Test
    public void testSearchTelephoneNumber() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );

        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(telephoneNumber=18015551212)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 2, map.size() );
        assertTrue( map.containsKey( "cn=Heather Nova, ou=system" ) || map.containsKey( "cn=Heather Nova,ou=system" ) );
    }


    @Test
    public void testSearchDN() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );

        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(manager=cn=Heather Nova, ou=system)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect", 1, map.size() );
        assertTrue( map.containsKey( "cn=with-dn, ou=system" ) || map.containsKey( "cn=with-dn,ou=system" ) );
    }


    @Test
    public void testComplexFilter() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );

        // Create an entry which does not match
        Attributes attrs = LdifUtils.createJndiAttributes( "objectClass: top", "objectClass: groupOfUniqueNames",
            "cn: testGroup3", "uniqueMember: uid=admin,ou=system" );

        getSystemContext( getService() ).createSubcontext( "cn=testGroup3,ou=groups", attrs );

        HashMap<String, Attributes> map = new HashMap<String, Attributes>();
        String filter = "(|(&(|(2.5.4.0=posixgroup)(2.5.4.0=groupofuniquenames)(2.5.4.0=groupofnames)(2.5.4.0=group))(!(|(2.5.4.50=uid=admin,ou=system)(2.5.4.31=0.9.2342.19200300.100.1.1=admin,2.5.4.11=system))))(objectClass=referral))";
        NamingEnumeration<SearchResult> list = sysRoot.search( "", filter, controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "size of results", 5, map.size() );
        assertTrue( map.containsKey( "cn=testGroup0,ou=groups,ou=system" ) );
        assertTrue( map.containsKey( "cn=testGroup1,ou=groups,ou=system" ) );
        assertTrue( map.containsKey( "cn=testGroup2,ou=groups,ou=system" ) );
        assertTrue( map.containsKey( "cn=testGroup4,ou=groups,ou=system" ) );
        assertTrue( map.containsKey( "cn=testGroup5,ou=groups,ou=system" ) );
        assertFalse( map.containsKey( "cn=testGroup3,ou=groups,ou=system" ) );
    }


    /**
     *  NO attributes should be returned
     */
    @Test
    public void testSearchTypesOnlyAndNoAttr() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );
        controls.setReturningAttributes( new String[]
            { "1.1" } );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        sysRoot.addToEnvironment( "java.naming.ldap.typesOnly", "true" );

        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(ou=testing01)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 1, map.size() );

        Attributes attrs = map.get( "ou=testing01,ou=system" );

        assertEquals( 0, attrs.size() );
    }


    /**
     * operational attributes with no values must be returned
     */
    @Test
    public void testSearchTypesOnlyWithNoAttrAndOperationalAttr() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );
        controls.setReturningAttributes( new String[]
            { "1.1", "+" } );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        sysRoot.addToEnvironment( "java.naming.ldap.typesOnly", "true" );

        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(ou=testing01)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 1, map.size() );

        Attributes attrs = map.get( "ou=testing01,ou=system" );

        assertNotNull( attrs.get( SchemaConstants.ENTRY_UUID_AT ) );
        assertNotNull( attrs.get( SchemaConstants.CREATORS_NAME_AT ) );

        assertEquals( 0, attrs.get( SchemaConstants.ENTRY_UUID_AT ).size() );
        assertEquals( 0, attrs.get( SchemaConstants.CREATORS_NAME_AT ).size() );
    }


    /**
     * all user attributes with no values must be returned
     */
    @Test
    public void testSearchTypesOnlyWithNullReturnAttr() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        sysRoot.addToEnvironment( "java.naming.ldap.typesOnly", "true" );

        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(ou=testing01)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 1, map.size() );

        Attributes attrs = map.get( "ou=testing01,ou=system" );

        assertNotNull( attrs.get( SchemaConstants.OU_AT ) );
        assertNotNull( attrs.get( "integerAttribute" ) );

        assertEquals( 0, attrs.get( SchemaConstants.OU_AT ).size() );
        assertEquals( 0, attrs.get( "integerAttribute" ).size() );

        assertNull( attrs.get( SchemaConstants.ENTRY_UUID_AT ) );
        assertNull( attrs.get( SchemaConstants.CREATORS_NAME_AT ) );
    }


    @Test
    public void testSearchEmptyDNWithOneLevelScope() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );

        LdapContext nullRootCtx = getRootContext( getService() );

        NamingEnumeration<SearchResult> list = nullRootCtx.search( "", "(objectClass=*)", controls );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( 2, map.size() );

        assertTrue( map.containsKey( "ou=system" ) );
        assertTrue( map.containsKey( "ou=schema" ) );
    }


    @Test
    public void testSearchEmptyDNWithSubLevelScope() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );

        LdapContext nullRootCtx = getRootContext( getService() );

        NamingEnumeration<SearchResult> list = nullRootCtx.search( "", "(objectClass=organizationalUnit)", controls );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertTrue( map.size() > 2 );

        assertTrue( map.containsKey( "ou=system" ) );
        assertTrue( map.containsKey( "ou=schema" ) );
    }


    @Test
    public void testSearchEmptyDNWithObjectScopeAndNoObjectClassPresenceFilter() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.OBJECT_SCOPE );
        controls.setDerefLinkFlag( false );

        LdapContext nullRootCtx = getRootContext( getService() );

        NamingEnumeration<SearchResult> list = nullRootCtx.search( "", "(objectClass=domain)", controls );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( 0, map.size() );

        assertFalse( map.containsKey( "ou=system" ) );
        assertFalse( map.containsKey( "ou=schema" ) );
    }


    @Test
    public void testSearchRootDSE() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.OBJECT_SCOPE );
        controls.setDerefLinkFlag( false );
        controls.setReturningAttributes( new String[]
            { "*", "+" } );

        LdapContext nullRootCtx = getRootContext( getService() );

        NamingEnumeration<SearchResult> list = nullRootCtx.search( "", "(objectClass=*)", controls );
        Attributes rootDse = null;

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            rootDse = result.getAttributes();
        }

        list.close();

        assertNotNull( rootDse );

        assertEquals( 10, rootDse.size() );
        assertNotNull( rootDse.get( "objectClass" ) );
        assertNotNull( rootDse.get( "entryUUID" ) );
        assertNotNull( rootDse.get( "namingContexts" ) );
        assertNotNull( rootDse.get( "subschemaSubentry" ) );
        assertNotNull( rootDse.get( "supportedControl" ) );
        assertNotNull( rootDse.get( "supportedExtension" ) );
        assertNotNull( rootDse.get( "supportedFeatures" ) );
        assertNotNull( rootDse.get( "supportedLDAPVersion" ) );
        assertNotNull( rootDse.get( "vendorName" ) );
        assertNotNull( rootDse.get( "vendorVersion" ) );
    }


    @Test
    public void testSearchEmptyDNWithOneLevelScopeAndNoObjectClassPresenceFilter() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );

        LdapContext nullRootCtx = getRootContext( getService() );

        NamingEnumeration<SearchResult> list = nullRootCtx.search( "", "(cn=*)", controls );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( 0, map.size() );

        assertFalse( map.containsKey( "ou=system" ) );
        assertFalse( map.containsKey( "ou=schema" ) );
    }


    @Test
    public void testCsnLessEqualitySearch() throws Exception
    {
        LdapConnection connection = IntegrationUtils.getAdminConnection( getService() );

        Dn dn = new Dn( "cn=testLowerCsnAdd,ou=system" );
        Entry entry = new DefaultEntry( dn );
        entry.add( "objectClass", SchemaConstants.PERSON_OC );
        entry.add( "cn", "testLowerCsnAdd_cn" );
        entry.add( "sn", "testLowerCsnAdd_sn" );

        connection.add( entry );

        // add an entry to have a entry with higher CSN value
        Dn dn2 = new Dn( "cn=testHigherCsnAdd,ou=system" );
        Entry entry2 = new DefaultEntry( dn2,
            "objectClass :person",
            "cn: testHigherCsnAdd_cn",
            "sn: testHigherCsnAdd_sn" );

        connection.add( entry2 );

        entry = connection.lookup( dn.getName(), "+" );
        entry2 = connection.lookup( dn2.getName(), "+" );

        String lowerCsn = entry.get( "entryCsn" ).getString();
        String higherCsn = entry2.get( "entryCsn" ).getString();

        // usecases
        // 1.1 Less than or Equal ( with the lower csn value)
        testUseCases( lowerCsn, new String[]
            { lowerCsn }, connection, 1 );

        // 1.2 Less than or equals with a highest csn value
        testUseCases( higherCsn, new String[]
            { higherCsn, lowerCsn }, connection, 1 );

        // 2.1 Greater than or Equal ( with the highest csn value )
        testUseCases( higherCsn, new String[]
            { higherCsn }, connection, 2 );

        // 2.2 Greater than or Equal ( with lower csn value )
        testUseCases( lowerCsn, new String[]
            { higherCsn, lowerCsn }, connection, 2 );
    }


    private void testUseCases( String filterCsnVal, String[] expectedCsns, LdapConnection connection, int useCaseNum )
        throws Exception
    {
        Value<String> val = new StringValue( filterCsnVal );
        AttributeType entryCsnAt = getService().getSchemaManager().getAttributeType( SchemaConstants.ENTRY_CSN_AT );
        ExprNode filter = null;

        if ( useCaseNum == 1 )
        {
            filter = new LessEqNode( entryCsnAt, val );
        }
        else if ( useCaseNum == 2 )
        {
            filter = new GreaterEqNode( entryCsnAt, val );
        }

        Entry loadedEntry = null;

        Set<String> csnSet = new HashSet<String>( expectedCsns.length );
        EntryCursor cursor = connection.search( "ou=system", filter.toString(), SearchScope.ONELEVEL, "*", "+" );

        while ( cursor.next() )
        {
            loadedEntry = cursor.get();
            csnSet.add( loadedEntry.get( SchemaConstants.ENTRY_CSN_AT ).getString() );
        }

        cursor.close();

        assertTrue( csnSet.size() >= expectedCsns.length );

        for ( String csn : expectedCsns )
        {
            assertTrue( csnSet.contains( csn ) );
        }
    }


    @Test
    public void testSearchFilterWithBadAttributeType() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(|(badAttr={0})(ou={1}))", new Object[]
            { "testing00", "testing01" }, controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 1, map.size() );
        assertTrue( map.containsKey( "ou=testing01,ou=system" ) );
    }


    @Test
    public void testSearchFilterBadAttributeType() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setDerefLinkFlag( false );
        sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES, AliasDerefMode.NEVER_DEREF_ALIASES
            .getJndiValue() );
        HashMap<String, Attributes> map = new HashMap<String, Attributes>();

        NamingEnumeration<SearchResult> list = sysRoot.search( "", "(badAttr=*)", controls );

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            map.put( result.getName(), result.getAttributes() );
        }

        list.close();

        assertEquals( "Expected number of results returned was incorrect!", 0, map.size() );
    }


    @Test
    public void testSearchRootDSESubtree() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );
        controls.setReturningAttributes( new String[]
            { "*", "+" } );

        LdapContext nullRootCtx = getRootContext( getService() );

        NamingEnumeration<SearchResult> list = nullRootCtx.search( "", "(ou=testing01)", controls );
        Attributes rootDse = null;

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            rootDse = result.getAttributes();
        }

        list.close();

        assertNotNull( rootDse );
    }


    @Test
    public void testSearchOrGidNumber() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setDerefLinkFlag( false );
        controls.setReturningAttributes( new String[]
            { "*", "+" } );

        LdapContext nullRootCtx = getRootContext( getService() );

        NamingEnumeration<SearchResult> list = nullRootCtx.search( "", "(|(&(objectclass=posixGroup)(|(gidnumber=1)(gidnumber=1)))(objectClass=posixGroupp))", controls );
        Attributes rootDse = null;

        while ( list.hasMore() )
        {
            SearchResult result = list.next();
            rootDse = result.getAttributes();
        }

        list.close();

        assertNotNull( rootDse );
    }
    
    
    /**
     * Test for DIRSERVER-1922
     */
    @Test
    public void testNotEvaluator() throws Exception
    {
        LdapConnection con = new LdapCoreSessionConnection( service.getAdminSession() );

        EntryCursor cursor = con.search( "ou=groups,ou=system", "(!(gidNumber=00001))", SearchScope.ONELEVEL, SchemaConstants.ALL_ATTRIBUTES_ARRAY );

        int count = 0;
        while ( cursor.next() )
        {
            count++;
        }
        
        cursor.close();
        
        assertEquals( 5, count );
    }

    
    /**
     * DIRSERVER-1961
     *
     * @throws Exception
     */
    @Test
    public void testSearchRootDSEOneLevel() throws Exception
    {
        LdapConnection conn = getAdminConnection( service );

        EntryCursor cursor = conn.search( "ou=schema", "(|(objectClass=*)(cn=x))", SearchScope.OBJECT, "*" );

        assertTrue( cursor.next() );
        cursor.close();

        cursor = conn.search( "ou=schema", "(objectClass=person)", SearchScope.OBJECT, "*" );

        assertFalse( cursor.next() );
        cursor.close();

        cursor = conn.search( "", "(objectClass=person)", SearchScope.ONELEVEL, "*" );

        assertFalse( cursor.next() );
        cursor.close();
        
        cursor = conn.search( "", "(objectClass=person)", SearchScope.SUBTREE, "*" );
        int count = 0;
        while( cursor.next() )
        {
            count++;
        }
        
        assertEquals(3, count);
        cursor.close();
    }
}
