/*
 *  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.operations.search;


import static org.apache.directory.server.integ.ServerIntegrationUtils.getAdminConnection;
import static org.apache.directory.server.integ.ServerIntegrationUtils.getWiredContext;
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.Arrays;
import java.util.HashSet;
import java.util.Set;

import javax.naming.InvalidNameException;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapContext;

import org.apache.directory.junit.tools.MultiThreadedMultiInvoker;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.apache.directory.server.annotations.CreateLdapServer;
import org.apache.directory.server.annotations.CreateTransport;
import org.apache.directory.server.core.annotations.ApplyLdifs;
import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
import org.apache.directory.server.core.integ.FrameworkRunner;
import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
import org.apache.directory.shared.ldap.model.cursor.Cursor;
import org.apache.directory.shared.ldap.model.cursor.EntryCursor;
import org.apache.directory.shared.ldap.model.entry.DefaultEntry;
import org.apache.directory.shared.ldap.model.entry.Entry;
import org.apache.directory.shared.ldap.model.exception.LdapException;
import org.apache.directory.shared.ldap.model.message.Control;
import org.apache.directory.shared.ldap.model.message.Response;
import org.apache.directory.shared.ldap.model.message.SearchRequest;
import org.apache.directory.shared.ldap.model.message.SearchRequestImpl;
import org.apache.directory.shared.ldap.model.message.SearchScope;
import org.apache.directory.shared.ldap.model.message.controls.Subentries;
import org.apache.directory.shared.ldap.model.message.controls.SubentriesImpl;
import org.apache.directory.shared.ldap.model.name.Dn;
import org.apache.directory.shared.ldap.util.JndiUtils;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;


/**
 * Testcase with different modify operations on a person entry. Each includes a
 * single add op only. Created to demonstrate DIREVE-241 ("Adding an already
 * existing attribute value with a modify operation does not cause an error.").
 * 
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
@RunWith(FrameworkRunner.class)
@CreateLdapServer(transports =
    { @CreateTransport(protocol = "LDAP") })
@ApplyLdifs(
    {

        // Entry # 0
        "dn: cn=Kate Bush,ou=system",
        "objectClass: person",
        "objectClass: organizationalPerson",
        "objectClass: inetOrgPerson",
        "objectClass: strongAuthenticationUser",
        "objectClass: top",
        "userCertificate:: NFZOXw==",
        "cn: Kate Bush",
        "description: this is a person",
        "sn: Bush",
        "jpegPhoto:: /9j/4AAQSkZJRgABAQEASABIAAD/4QAWRXhpZgAATU0AKgAAAAgAAAAAAAD//gAX",
        " Q3JlYXRlZCB3aXRoIFRoZSBHSU1Q/9sAQwAQCwwODAoQDg0OEhEQExgoGhgWFhgxIyUdKDozPTw",
        " 5Mzg3QEhcTkBEV0U3OFBtUVdfYmdoZz5NcXlwZHhcZWdj/9sAQwEREhIYFRgvGhovY0I4QmNjY2",
        " NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Nj/8AAEQgAAQABA",
        " wEiAAIRAQMRAf/EABUAAQEAAAAAAAAAAAAAAAAAAAAF/8QAFBABAAAAAAAAAAAAAAAAAAAAAP/E",
        " ABUBAQEAAAAAAAAAAAAAAAAAAAUG/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8",
        " AigC14//Z",

        // Entry # 2
        "dn: cn=Tori Amos,ou=system",
        "objectClass: person",
        "objectClass: organizationalPerson",
        "objectClass: inetOrgPerson",
        "objectClass: strongAuthenticationUser",
        "objectClass: top",
        "userCertificate:: NFZOXw==",
        "cn: Tori Amos",
        "description: an American singer-songwriter",
        "sn: Amos",
        "jpegPhoto:: /9j/4AAQSkZJRgABAQEASABIAAD/4QAWRXhpZgAATU0AKgAAAAgAAAAAAAD//gAX",
        " Q3JlYXRlZCB3aXRoIFRoZSBHSU1Q/9sAQwAQCwwODAoQDg0OEhEQExgoGhgWFhgxIyUdKDozPTw",
        " 5Mzg3QEhcTkBEV0U3OFBtUVdfYmdoZz5NcXlwZHhcZWdj/9sAQwEREhIYFRgvGhovY0I4QmNjY2",
        " NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Nj/8AAEQgAAQABA",
        " wEiAAIRAQMRAf/EABUAAQEAAAAAAAAAAAAAAAAAAAAF/8QAFBABAAAAAAAAAAAAAAAAAAAAAP/E",
        " ABUBAQEAAAAAAAAAAAAAAAAAAAUG/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8",
        " AigC14//Z",

        // Entry # 3
        "dn: cn=Rolling-Stones,ou=system",
        "objectClass: person",
        "objectClass: organizationalPerson",
        "objectClass: inetOrgPerson",
        "objectClass: strongAuthenticationUser",
        "objectClass: top",
        "userCertificate:: NFZOXw==",
        "cn: Rolling-Stones",
        "description: an English singer-songwriter",
        "sn: Jagger",
        "jpegPhoto:: /9j/4AAQSkZJRgABAQEASABIAAD/4QAWRXhpZgAATU0AKgAAAAgAAAAAAAD//gAX",
        " Q3JlYXRlZCB3aXRoIFRoZSBHSU1Q/9sAQwAQCwwODAoQDg0OEhEQExgoGhgWFhgxIyUdKDozPTw",
        " 5Mzg3QEhcTkBEV0U3OFBtUVdfYmdoZz5NcXlwZHhcZWdj/9sAQwEREhIYFRgvGhovY0I4QmNjY2",
        " NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Nj/8AAEQgAAQABA",
        " wEiAAIRAQMRAf/EABUAAQEAAAAAAAAAAAAAAAAAAAAF/8QAFBABAAAAAAAAAAAAAAAAAAAAAP/E",
        " ABUBAQEAAAAAAAAAAAAAAAAAAAUG/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8",
        " AigC14//Z",

        // Entry # 4
        "dn: cn=Heather Nova,ou=system",
        "objectClass: person",
        "objectClass: organizationalPerson",
        "objectClass: inetOrgPerson",
        "objectClass: strongAuthenticationUser",
        "objectClass: top",
        "userCertificate:: NFZOXw==",
        "cn: Heather Nova",
        "sn: Nova",
        "jpegPhoto:: /9j/4AAQSkZJRgABAQEASABIAAD/4QAWRXhpZgAATU0AKgAAAAgAAAAAAAD//gAX",
        " Q3JlYXRlZCB3aXRoIFRoZSBHSU1Q/9sAQwAQCwwODAoQDg0OEhEQExgoGhgWFhgxIyUdKDozPTw",
        " 5Mzg3QEhcTkBEV0U3OFBtUVdfYmdoZz5NcXlwZHhcZWdj/9sAQwEREhIYFRgvGhovY0I4QmNjY2",
        " NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Nj/8AAEQgAAQABA",
        " wEiAAIRAQMRAf/EABUAAQEAAAAAAAAAAAAAAAAAAAAF/8QAFBABAAAAAAAAAAAAAAAAAAAAAP/E",
        " ABUBAQEAAAAAAAAAAAAAAAAAAAUG/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8",
        " AigC14//Z",

        // Entry #5
        "dn: cn=Janis Joplin,ou=system",
        "objectClass: person",
        "objectClass: organizationalPerson",
        "objectClass: inetOrgPerson",
        "objectClass: top",
        "objectClass: strongAuthenticationUser",
        "cn: Janis Joplin",
        "sn: Joplin",
        "userCertificate:: ",

        // Entry #6
        "dn: cn=Kim Wilde,ou=system",
        "objectClass: person",
        "objectClass: top",
        "cn: Kim Wilde",
        "sn: Wilde",
        "description: an American singer-songwriter+sexy blond"

})
public class SearchIT extends AbstractLdapTestUnit
{
    @Rule
    public MultiThreadedMultiInvoker i = new MultiThreadedMultiInvoker( MultiThreadedMultiInvoker.NOT_THREADSAFE );
    private static final String BASE = "ou=system";
    
    //public static LdapServer getLdapServer();
    
    private static final String RDN = "cn=Tori Amos";
    private static final String RDN2 = "cn=Rolling-Stones";
    private static final String HEATHER_RDN = "cn=Heather Nova";
    private static final String FILTER = "(objectclass=*)";
    
    private static final byte[] JPEG = new byte[]
        { ( byte ) 0xff, ( byte ) 0xd8, ( byte ) 0xff, ( byte ) 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
            0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, ( byte ) 0xff, ( byte ) 0xe1, 0x00, 0x16, 0x45, 0x78, 0x69,
            0x66, 0x00, 0x00, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            ( byte ) 0xff, ( byte ) 0xfe, 0x00, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74,
            0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, ( byte ) 0xff, ( byte ) 0xdb, 0x00, 0x43, 0x00,
            0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18,
            0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48,
            0x5c, 0x4e, 0x40, 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e,
            0x4d, 0x71, 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63, ( byte ) 0xff, ( byte ) 0xdb, 0x00, 0x43, 0x01,
            0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, 0x63, 0x63,
            0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
            0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
            0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, ( byte ) 0xff, ( byte ) 0xc0, 0x00, 0x11, 0x08,
            0x00, 0x01, 0x00, 0x01, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, ( byte ) 0xff,
            ( byte ) 0xc4, 0x00, 0x15, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x05, ( byte ) 0xff, ( byte ) 0xc4, 0x00, 0x14, 0x10, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ( byte ) 0xff, ( byte ) 0xc4,
            0x00, 0x15, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x05, 0x06, ( byte ) 0xff, ( byte ) 0xc4, 0x00, 0x14, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ( byte ) 0xff, ( byte ) 0xda, 0x00, 0x0c, 0x03,
            0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, ( byte ) 0x8a, 0x00, ( byte ) 0xb5, ( byte ) 0xe3,
            ( byte ) 0xff, ( byte ) 0xd9, };
    
    
    /**
     * Creation of required attributes of a person entry.
     */
    private Attributes getPersonAttributes( String sn, String cn )
    {
        Attributes attributes = new BasicAttributes( true );
        Attribute attribute = new BasicAttribute( "objectClass" );
        attribute.add( "top" );
        attribute.add( "person" );
        attribute.add( "organizationalPerson" );
        attribute.add( "inetOrgPerson" );
        attributes.put( attribute );
        attributes.put( "cn", cn );
        attributes.put( "sn", sn );
        attributes.put( "jpegPhoto", JPEG );
    
        return attributes;
    }
    
    
    private void checkForAttributes( Attributes attrs, String[] attrNames )
    {
        for ( String attrName : attrNames )
        {
            assertNotNull( "Check if attr " + attrName + " is present", attrs.get( attrName ) );
        }
    }
    
    
    /**
     * For DIRSERVER-715 and part of DIRSERVER-169.  May include other tests
     * for binary attribute based searching.
     */
    @Test
    public void testSearchByBinaryAttribute() throws Exception
    {
        DirContext ctx = ( DirContext ) getWiredContext( getLdapServer() ).lookup( BASE );
        byte[] certData = new byte[]
            { 0x34, 0x56, 0x4e, 0x5f };
    
        // Search for kate by cn first
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        NamingEnumeration<SearchResult> enm = ctx.search( "", "(cn=Kate Bush)", controls );
        assertTrue( enm.hasMore() );
        SearchResult sr = enm.next();
        assertNotNull( sr );
        assertFalse( enm.hasMore() );
        assertEquals( "cn=Kate Bush", sr.getName() );
    
        enm = ctx.search( "", "(&(cn=Kate Bush)(userCertificate={0}))", new Object[]
            { certData }, controls );
        assertTrue( enm.hasMore() );
        sr = enm.next();
        assertNotNull( sr );
        assertFalse( enm.hasMore() );
        assertEquals( "cn=Kate Bush", sr.getName() );
    
        enm = ctx.search( "", "(userCertificate=\\34\\56\\4E\\5F)", controls );
        assertTrue( enm.hasMore() );
        int count = 0;
        Set<String> expected = new HashSet<String>();
        expected.add( "cn=Kate Bush" );
        expected.add( "cn=Tori Amos" );
        expected.add( "cn=Rolling-Stones" );
        expected.add( "cn=Heather Nova" );
    
        while ( enm.hasMore() )
        {
            count++;
            sr = enm.next();
            assertNotNull( sr );
    
            assertTrue( expected.contains( sr.getName() ) );
            expected.remove( sr.getName() );
        }
    
        assertEquals( 4, count );
        assertFalse( enm.hasMore() );
        assertEquals( 0, expected.size() );
    }
    
    
    @Test
    public void testSearch() throws Exception
    {
        LdapContext ctx = getWiredContext( getLdapServer() );
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.OBJECT_SCOPE );
        controls.setTimeLimit( 10 );
    
        try
        {
            ctx.search( "myBadDN", "(objectClass=*)", controls );
    
            fail(); // We should get an exception here
        }
        catch ( InvalidNameException ine )
        {
            // Expected.
        }
        catch ( NamingException ne )
        {
            fail();
        }
        catch ( Exception e )
        {
            fail();
        }
    
        try
        {
            controls = new SearchControls();
            controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
            controls.setTimeLimit( 10 );
    
            NamingEnumeration<SearchResult> result = ctx.search( "ou=system", "(objectClass=*)", controls );
    
            assertTrue( result.hasMore() );
        }
        catch ( InvalidNameException ine )
        {
            fail();
            // Expected.
        }
        catch ( NamingException ne )
        {
            fail();
        }
    }
    
    
    /**
     * Performs a single level search from ou=system base and
     * returns the set of DNs found.
     */
    private Set<String> search( String filter ) throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        NamingEnumeration<SearchResult> ii = ctx.search( "", filter, controls );
    
        // collect all results
        HashSet<String> results = new HashSet<String>();
        while ( ii.hasMore() )
        {
            SearchResult result = ii.next();
            results.add( result.getName() );
        }
    
        return results;
    }
    
    
    @Test
    public void testDirserver635() throws Exception
    {
        // -------------------------------------------------------------------
        Set<String> results = search( "(|(cn=Kate*)(cn=Tori*))" );
        assertEquals( "returned size of results", 2, results.size() );
        assertTrue( "contains cn=Tori Amos", results.contains( "cn=Tori Amos" ) );
        assertTrue( "contains cn=Kate Bush", results.contains( "cn=Kate Bush" ) );
    
        // -------------------------------------------------------------------
        results = search( "(|(cn=*Amos)(cn=Kate*))" );
        assertEquals( "returned size of results", 2, results.size() );
        assertTrue( "contains cn=Tori Amos", results.contains( "cn=Tori Amos" ) );
        assertTrue( "contains cn=Kate Bush", results.contains( "cn=Kate Bush" ) );
    
        // -------------------------------------------------------------------
        results = search( "(|(cn=Kate Bush)(cn=Tori*))" );
        assertEquals( "returned size of results", 2, results.size() );
        assertTrue( "contains cn=Tori Amos", results.contains( "cn=Tori Amos" ) );
        assertTrue( "contains cn=Kate Bush", results.contains( "cn=Kate Bush" ) );
    
        // -------------------------------------------------------------------
        results = search( "(|(cn=*Amos))" );
        assertEquals( "returned size of results", 1, results.size() );
        assertTrue( "contains cn=Tori Amos", results.contains( "cn=Tori Amos" ) );
    }
    
    
    /**
     * Search operation with a base Dn which contains a BER encoded value.
     */
    @Test
    public void testSearchWithBackslashEscapedBase() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        // create additional entry
        Attributes attributes = this.getPersonAttributes( "Ferry", "Bryan Ferry" );
        ctx.createSubcontext( "sn=Ferry", attributes );
    
        SearchControls sctls = new SearchControls();
        sctls.setSearchScope( SearchControls.OBJECT_SCOPE );
        String filter = "(cn=Bryan Ferry)";
    
        // sn=Ferry with BEROctetString values
        String base = "sn=\\46\\65\\72\\72\\79";
    
        try
        {
            // Check entry
            NamingEnumeration<SearchResult> enm = ctx.search( base, filter, sctls );
            assertTrue( enm.hasMore() );
            while ( enm.hasMore() )
            {
                SearchResult sr = enm.next();
                Attributes attrs = sr.getAttributes();
                Attribute sn = attrs.get( "sn" );
                assertNotNull( sn );
                assertTrue( sn.contains( "Ferry" ) );
            }
        }
        catch ( Exception e )
        {
            fail( e.getMessage() );
        }
    }
    
    
    /**
     * Add a new attribute to a person entry.
     * 
     * @throws LdapException
     */
    @Test
    public void testSearchValue() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        // Setting up search controls for compare op
        SearchControls ctls = new SearchControls();
        ctls.setReturningAttributes( new String[]
            { "*" } ); // no attributes
        ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
    
        // Search for all entries
        NamingEnumeration<SearchResult> results = ctx.search( RDN, "(cn=*)", ctls );
        assertTrue( results.hasMore() );
    
        results = ctx.search( RDN2, "(cn=*)", ctls );
        assertTrue( results.hasMore() );
    
        // Search for all entries ending by Amos
        results = ctx.search( RDN, "(cn=*Amos)", ctls );
        assertTrue( results.hasMore() );
    
        results = ctx.search( RDN2, "(cn=*Amos)", ctls );
        assertFalse( results.hasMore() );
    
        // Search for all entries ending by amos
        results = ctx.search( RDN, "(cn=*amos)", ctls );
        assertTrue( results.hasMore() );
    
        results = ctx.search( RDN2, "(cn=*amos)", ctls );
        assertFalse( results.hasMore() );
    
        // Search for all entries starting by Tori
        results = ctx.search( RDN, "(cn=Tori*)", ctls );
        assertTrue( results.hasMore() );
    
        results = ctx.search( RDN2, "(cn=Tori*)", ctls );
        assertFalse( results.hasMore() );
    
        // Search for all entries starting by tori
        results = ctx.search( RDN, "(cn=tori*)", ctls );
        assertTrue( results.hasMore() );
    
        results = ctx.search( RDN2, "(cn=tori*)", ctls );
        assertFalse( results.hasMore() );
    
        // Search for all entries containing ori
        results = ctx.search( RDN, "(cn=*ori*)", ctls );
        assertTrue( results.hasMore() );
    
        results = ctx.search( RDN2, "(cn=*ori*)", ctls );
        assertFalse( results.hasMore() );
    
        // Search for all entries containing o and i
        results = ctx.search( RDN, "(cn=*o*i*)", ctls );
        assertTrue( results.hasMore() );
    
        results = ctx.search( RDN2, "(cn=*o*i*)", ctls );
        assertTrue( results.hasMore() );
    
        // Search for all entries containing o, space and o
        results = ctx.search( RDN, "(cn=*o* *o*)", ctls );
        assertTrue( results.hasMore() );
    
        results = ctx.search( RDN2, "(cn=*o* *o*)", ctls );
        assertFalse( results.hasMore() );
    
        results = ctx.search( RDN2, "(cn=*o*-*o*)", ctls );
        assertTrue( results.hasMore() );
    
        // Search for all entries starting by To and containing A
        results = ctx.search( RDN, "(cn=To*A*)", ctls );
        assertTrue( results.hasMore() );
    
        results = ctx.search( RDN2, "(cn=To*A*)", ctls );
        assertFalse( results.hasMore() );
    
        // Search for all entries ending by os and containing ri
        results = ctx.search( RDN, "(cn=*ri*os)", ctls );
        assertTrue( results.hasMore() );
    
        results = ctx.search( RDN2, "(cn=*ri*os)", ctls );
        assertFalse( results.hasMore() );
    }
    
    
    /**
     * Search operation with a base Dn with quotes
     *
    @Test
    public void testSearchWithQuotesInBase() throws NamingException {
    
        SearchControls sctls = new SearchControls();
        sctls.setSearchScope(SearchControls.OBJECT_SCOPE);
        String filter = "(cn=Tori Amos)";
    
        // cn="Tori Amos" (with quotes)
        String base = "cn=\"Tori Amos\"";
    
        try {
            // Check entry
            NamingEnumeration<SearchResult> enm = ctx.search( base, filter, sctls );
            assertTrue( enm.hasMore() );
            
            while ( enm.hasMore() ) {
                SearchResult sr = enm.next();
                Attributes attrs = sr.getAttributes();
                Attribute sn = attrs.get("sn");
                assertNotNull(sn);
                assertTrue( sn.contains( "Amos" ) );
            }
        } catch (Exception e) {
            fail( e.getMessage() );
        }
    }
    
    
    /**
     * Tests for <a href="http://issues.apache.org/jira/browse/DIRSERVER-645">
     * DIRSERVER-645<\a>: Wrong search FILTER evaluation with AND
     * operator and undefined operands.
     */
    @Test
    public void testUndefinedAvaInBranchFilters() throws Exception
    {
        // -------------------------------------------------------------------
        Set<String> results = search( "(|(sn=Bush)(numberOfOctaves=4))" );
        assertEquals( "returned size of results", 1, results.size() );
        assertTrue( "contains cn=Kate Bush", results.contains( "cn=Kate Bush" ) );
    
        // if numberOfOctaves is undefined then this whole FILTER is undefined
        results = search( "(&(sn=Bush)(numberOfOctaves=4))" );
        assertEquals( "returned size of results", 0, results.size() );
    }
    
    
    @Test
    public void testSearchSchema() throws Exception
    {
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.OBJECT_SCOPE );
        controls.setReturningAttributes( new String[]
            { "objectClasses" } );
    
        LdapContext ctx = getWiredContext( getLdapServer() );
    
        NamingEnumeration<SearchResult> results = ctx.search( "cn=schema", "objectClass=subschema", controls );
        assertTrue( results.hasMore() );
        SearchResult result = results.next();
        assertNotNull( result );
        assertFalse( results.hasMore() );
    
        NamingEnumeration<? extends Attribute> attrs = result.getAttributes().getAll();
    
        while ( attrs.hasMoreElements() )
        {
            Attribute attr = attrs.next();
            String ID = attr.getID();
            assertEquals( "objectClasses", ID );
        }
    
        assertNotNull( result.getAttributes().get( "objectClasses" ) );
        assertEquals( 1, result.getAttributes().size() );
    }
    
    
    /**
     * Creates an access decorator subentry under ou=system whose subtree covers
     * the entire naming context.
     *
     * @param cn the common name and rdn for the subentry
     * @param subtree the subtreeSpecification for the subentry
     * @param aciItem the prescriptive ACI attribute value
     * @throws NamingException if there is a problem creating the subentry
     */
    private void createAccessControlSubentry( String cn, String subtree, String aciItem ) throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        DirContext adminCtx = ctx;
    
        // modify ou=system to be an AP for an A/C AA if it is not already
        Attributes ap = adminCtx.getAttributes( "", new String[]
            { "administrativeRole" } );
        Attribute administrativeRole = ap.get( "administrativeRole" );
        if ( administrativeRole == null || !administrativeRole.contains( "accessControlSpecificArea" ) )
        {
            Attributes changes = new BasicAttributes( "administrativeRole", "accessControlSpecificArea", true );
            adminCtx.modifyAttributes( "", DirContext.ADD_ATTRIBUTE, changes );
        }
    
        // now add the A/C subentry below ou=system
        Attributes subentry = new BasicAttributes( "cn", cn, true );
        Attribute objectClass = new BasicAttribute( "objectClass" );
        subentry.put( objectClass );
        objectClass.add( "top" );
        objectClass.add( SchemaConstants.SUBENTRY_OC );
        objectClass.add( "accessControlSubentry" );
        subentry.put( "subtreeSpecification", subtree );
        subentry.put( "prescriptiveACI", aciItem );
        adminCtx.createSubcontext( "cn=" + cn, subentry );
    }
    
    
    /**
     * Test case to demonstrate DIRSERVER-705 ("object class top missing in search
     * result, if scope is base and attribute objectClass is requested explicitly").
     */
    @Test
    public void testAddWithObjectclasses() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        SearchControls ctls = new SearchControls();
        ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
        ctls.setReturningAttributes( new String[]
            { "objectclass" } );
        String filter = "(objectclass=*)";
        String rdn = "cn=Kim Wilde";
    
        NamingEnumeration<SearchResult> result = ctx.search( rdn, filter, ctls );
    
        if ( result.hasMore() )
        {
            SearchResult entry = result.next();
            Attributes heatherReloaded = entry.getAttributes();
            Attribute loadedOcls = heatherReloaded.get( "objectClass" );
            assertNotNull( loadedOcls );
            assertTrue( loadedOcls.contains( "person" ) );
            assertTrue( loadedOcls.contains( "top" ) );
        }
        else
        {
            fail( "entry " + rdn + " not found" );
        }
    
        ctx.destroySubcontext( rdn );
    }
    
    
    /**
     * Test case to demonstrate DIRSERVER-705 ("object class top missing in search
     * result, if scope is base and attribute objectClass is requested explicitly").
     */
    @Test
    public void testAddWithMissingObjectclasses() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        String rdn = "cn=Kate Bush";
        SearchControls ctls = new SearchControls();
        ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
        ctls.setReturningAttributes( new String[]
            { "objectclass" } );
        String filter = "(objectclass=*)";
    
        NamingEnumeration<SearchResult> result = ctx.search( rdn, filter, ctls );
        if ( result.hasMore() )
        {
            SearchResult entry = result.next();
            Attributes kateReloaded = entry.getAttributes();
            Attribute loadedOcls = kateReloaded.get( "objectClass" );
            assertNotNull( loadedOcls );
            assertTrue( loadedOcls.contains( "top" ) );
            assertTrue( loadedOcls.contains( "person" ) );
            assertTrue( loadedOcls.contains( "organizationalPerson" ) );
    
        }
        else
        {
            fail( "entry " + rdn + " not found" );
        }
    
        ctx.destroySubcontext( rdn );
    }
    
    
    @Test
    public void testSubentryControl() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        // create a real access decorator subentry
        createAccessControlSubentry( "anyBodyAdd", "{}", "{ " + "  identificationTag \"addAci\", "
            + "  precedence 14, " + "  authenticationLevel none, " + "  itemOrUserFirst userFirst: " + "  { "
            + "    userClasses " + "    { " + "      allUsers " + "    }, " + "    userPermissions " + "    { "
            + "      { " + "        protectedItems " + "        { " + "          entry, allUserAttributeTypesAndValues"
            + "        }, " + "        grantsAndDenials " + "        { " + "          grantAdd, grantBrowse "
            + "        } " + "      } " + "    } " + "  } " + "}" );
    
        // prepare the subentry decorator to make the subentry visible
        Subentries ctl = new SubentriesImpl();
        ctl.setVisibility( true );
        Control[] reqControls = new Control[]
            { ctl };
        SearchControls searchControls = new SearchControls();
        searchControls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
    
        ctx.setRequestControls( JndiUtils.toJndiControls( getLdapServer().getDirectoryService().getLdapCodecService(),
            reqControls ) );
        NamingEnumeration<SearchResult> enm = ctx.search( "", "(objectClass=*)", searchControls );
        Set<String> results = new HashSet<String>();
    
        while ( enm.hasMore() )
        {
            SearchResult result = enm.next();
            results.add( result.getName() );
        }
    
        assertEquals( "expected results size of", 1, results.size() );
        assertTrue( results.contains( "cn=anyBodyAdd" ) );
    }
    
    
    /**
     * Create a person entry with multivalued Rdn and check its content. This
     * testcase was created to demonstrate DIRSERVER-628.
     */
    @Test
    public void testMultiValuedRdnContent() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        Attributes attrs = getPersonAttributes( "Bush", "Kate Bush" );
        String rdn = "cn=Kate Bush+sn=Bush";
        ctx.createSubcontext( rdn, attrs );
    
        SearchControls sctls = new SearchControls();
        sctls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        String filter = "(sn=Bush)";
        String base = "";
    
        NamingEnumeration<SearchResult> enm = ctx.search( base, filter, sctls );
        while ( enm.hasMore() )
        {
            SearchResult sr = enm.next();
            attrs = sr.getAttributes();
            Attribute cn = sr.getAttributes().get( "cn" );
            assertNotNull( cn );
            assertTrue( cn.contains( "Kate Bush" ) );
            Attribute sn = sr.getAttributes().get( "sn" );
            assertNotNull( sn );
            assertTrue( sn.contains( "Bush" ) );
        }
    
        ctx.destroySubcontext( rdn );
    }
    
    
    /**
     * Create a person entry with multivalued Rdn and check its name.
     */
    @Test
    public void testMultiValuedRdnName() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        Attributes attrs = getPersonAttributes( "Bush", "Kate Bush" );
        String rdn = "cn=Kate Bush+sn=Bush";
        DirContext entry = ctx.createSubcontext( rdn, attrs );
        String nameInNamespace = entry.getNameInNamespace();
    
        SearchControls sctls = new SearchControls();
        sctls.setSearchScope( SearchControls.OBJECT_SCOPE );
        String filter = "(sn=Bush)";
    
        NamingEnumeration<SearchResult> enm = ctx.search( rdn, filter, sctls );
        
        if ( enm.hasMore() )
        {
            SearchResult sr = enm.next();
            assertNotNull( sr );
            assertEquals( "Name in namespace", nameInNamespace, sr.getNameInNamespace() );
        }
        else
        {
            fail( "Entry not found:" + nameInNamespace );
        }
        
        enm.close();

        // Now search with the sn=Bush+cn=Kate Bush RDN
        String mixedRdn = "sn=Bush+cn=Kate Bush";
        
        enm = ctx.search( mixedRdn, filter, sctls );
        
        if ( enm.hasMore() )
        {
            SearchResult sr = enm.next();
            assertNotNull( sr );
            Dn expectedDn = new Dn( nameInNamespace ).getParent().add( mixedRdn );
            
            assertEquals( "Name in namespace", expectedDn, sr.getNameInNamespace() );
        }
        else
        {
            fail( "Entry not found:" + nameInNamespace );
        }

        ctx.destroySubcontext( rdn );
    }
    
    
    @Test
    public void testSearchJpeg() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        NamingEnumeration<SearchResult> res = ctx.search( "", "(cn=Tori*)", controls );
    
        // collect all results
        while ( res.hasMore() )
        {
            SearchResult result = res.next();
    
            Attributes attrs = result.getAttributes();
    
            NamingEnumeration<? extends Attribute> all = attrs.getAll();
    
            while ( all.hasMoreElements() )
            {
                Attribute attr = all.next();
    
                if ( "jpegPhoto".equalsIgnoreCase( attr.getID() ) )
                {
                    byte[] jpegVal = ( byte[] ) attr.get();
    
                    assertTrue( Arrays.equals( jpegVal, JPEG ) );
                }
            }
        }
    }
    
    
    @Test
    public void testSearchOID() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        NamingEnumeration<SearchResult> res = ctx.search( "", "(2.5.4.3=Tori*)", controls );
    
        // ensure that the entry "cn=Tori Amos" was found
        assertTrue( res.hasMore() );
    
        SearchResult result = res.next();
    
        // ensure that result is not null
        assertNotNull( result );
    
        String rdn = result.getName();
    
        // ensure that the entry "cn=Tori Amos" was found
        assertEquals( "cn=Tori Amos", rdn );
    
        // ensure that no other value was found
        assertFalse( res.hasMore() );
    }
    
    
    @Test
    public void testSearchAttrCN() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setReturningAttributes( new String[]
            { "cn" } );
    
        NamingEnumeration<SearchResult> res = ctx.search( "", "(commonName=Tori*)", controls );
    
        assertTrue( res.hasMore() );
    
        SearchResult result = res.next();
    
        // ensure that result is not null
        assertNotNull( result );
    
        Attributes attrs = result.getAttributes();
    
        // ensure the one and only attribute is "cn"
        assertEquals( 1, attrs.size() );
        assertNotNull( attrs.get( "cn" ) );
        assertEquals( 1, attrs.get( "cn" ).size() );
        assertEquals( "Tori Amos", attrs.get( "cn" ).get() );
    }
    
    
    @Test
    public void testSearchAttrName() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setReturningAttributes( new String[]
            { "name" } );
    
        NamingEnumeration<SearchResult> res = ctx.search( "", "(commonName=Tori*)", controls );
    
        assertTrue( res.hasMore() );
    
        SearchResult result = res.next();
    
        // ensure that result is not null
        assertNotNull( result );
    
        Attributes attrs = result.getAttributes();
    
        // ensure that "cn" and "sn" are returned
        assertEquals( 2, attrs.size() );
        assertNotNull( attrs.get( "cn" ) );
        assertEquals( 1, attrs.get( "cn" ).size() );
        assertEquals( "Tori Amos", attrs.get( "cn" ).get() );
        assertNotNull( attrs.get( "sn" ) );
        assertEquals( 1, attrs.get( "sn" ).size() );
        assertEquals( "Amos", attrs.get( "sn" ).get() );
    }
    
    
    @Test
    public void testSearchAttrCommonName() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setReturningAttributes( new String[]
            { "commonName" } );
    
        NamingEnumeration<SearchResult> res = ctx.search( "", "(commonName=Tori*)", controls );
    
        assertTrue( res.hasMore() );
    
        SearchResult result = res.next();
    
        // ensure that result is not null
        assertNotNull( result );
    
        Attributes attrs = result.getAttributes();
    
        // requested attribute was "commonName", but ADS returns "cn".
        //       Other servers do the following:
        //       - OpenLDAP: also return "cn"
        //       - Siemens DirX: return "commonName"
        //       - Sun Directory 5.2: return "commonName"
        // ensure the one and only attribute is "cn"
        assertEquals( 1, attrs.size() );
        assertNotNull( attrs.get( "cn" ) );
        assertEquals( 1, attrs.get( "cn" ).size() );
        assertEquals( "Tori Amos", attrs.get( "cn" ).get() );
    }
    
    
    @Test
    public void testSearchAttrOID() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setReturningAttributes( new String[]
            { "2.5.4.3" } );
    
        NamingEnumeration<SearchResult> res = ctx.search( "", "(commonName=Tori*)", controls );
    
        assertTrue( res.hasMore() );
    
        SearchResult result = res.next();
    
        // ensure that result is not null
        assertNotNull( result );
    
        Attributes attrs = result.getAttributes();
    
        // requested attribute was "2.5.4.3", but ADS returns "cn".
        //       Other servers do the following:
        //       - OpenLDAP: also return "cn"
        //       - Siemens DirX: also return "cn"
        //       - Sun Directory 5.2: return "2.5.4.3"
        // ensure the one and only attribute is "cn"
        assertEquals( 1, attrs.size() );
        assertNotNull( attrs.get( "cn" ) );
        assertEquals( 1, attrs.get( "cn" ).size() );
        assertEquals( "Tori Amos", attrs.get( "cn" ).get() );
    }
    
    
    @Test
    public void testSearchAttrC_L() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        // create administrative area
        Attributes aaAttrs = new BasicAttributes( true );
        Attribute aaObjectClass = new BasicAttribute( "objectClass" );
        aaObjectClass.add( "top" );
        aaObjectClass.add( "organizationalUnit" );
        aaObjectClass.add( "extensibleObject" );
        aaAttrs.put( aaObjectClass );
        aaAttrs.put( "ou", "Collective Area" );
        aaAttrs.put( "administrativeRole", "collectiveAttributeSpecificArea" );
        DirContext aaCtx = ctx.createSubcontext( "ou=Collective Area", aaAttrs );
    
        // create subentry
        Attributes subentry = new BasicAttributes( true );
        Attribute objectClass = new BasicAttribute( "objectClass" );
        objectClass.add( "top" );
        objectClass.add( SchemaConstants.SUBENTRY_OC );
        objectClass.add( "collectiveAttributeSubentry" );
        subentry.put( objectClass );
        subentry.put( "c-l", "Munich" );
        subentry.put( "cn", "Collective Subentry" );
        subentry.put( "subtreeSpecification", "{ }" );
        aaCtx.createSubcontext( "cn=Collective Subentry", subentry );
    
        // create real enty
        Attributes attributes = this.getPersonAttributes( "Bush", "Kate Bush" );
        aaCtx.createSubcontext( "cn=Kate Bush", attributes );
    
        // search
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setReturningAttributes( new String[]
            { "c-l" } );
    
        NamingEnumeration<SearchResult> res = aaCtx.search( "", "(cn=Kate Bush)", controls );
    
        assertTrue( res.hasMore() );
    
        SearchResult result = res.next();
    
        // ensure that result is not null
        assertNotNull( result );
    
        Attributes attrs = result.getAttributes();
    
        // ensure the one and only attribute is "c-l"
        assertEquals( 1, attrs.size() );
        assertNotNull( attrs.get( "c-l" ) );
        assertEquals( 1, attrs.get( "c-l" ).size() );
        assertEquals( "Munich", attrs.get( "c-l" ).get() );
    }
    
    
    @Test
    public void testSearchUsersAttrs() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setReturningAttributes( new String[]
            { "*" } );
    
        NamingEnumeration<SearchResult> res = ctx.search( "", "(commonName=Tori Amos)", controls );
    
        assertTrue( res.hasMore() );
    
        SearchResult result = res.next();
    
        // ensure that result is not null
        assertNotNull( result );
    
        Attributes attrs = result.getAttributes();
    
        // ensure that all user attributes are returned
        assertEquals( 6, attrs.size() );
        assertNotNull( attrs.get( "cn" ) );
        assertNotNull( attrs.get( "sn" ) );
        assertNotNull( attrs.get( "objectClass" ) );
        assertNotNull( attrs.get( "jpegPhoto" ) );
        assertNotNull( attrs.get( "description" ) );
        assertNotNull( attrs.get( "userCertificate" ) );
        assertNull( attrs.get( "createtimestamp" ) );
        assertNull( attrs.get( "creatorsname" ) );
    }
    
    
    @Test
    public void testSearchOperationalAttrs() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setReturningAttributes( new String[]
            { "+" } );
    
        NamingEnumeration<SearchResult> res = ctx.search( "", "(commonName=Tori Amos)", controls );
    
        assertTrue( res.hasMore() );
    
        SearchResult result = res.next();
    
        // ensure that result is not null
        assertNotNull( result );
    
        Attributes attrs = result.getAttributes();
    
        // ensure that all operational attributes are returned
        // and no user attributes
        assertEquals( 5, attrs.size() );
        assertNull( attrs.get( "cn" ) );
        assertNull( attrs.get( "sn" ) );
        assertNull( attrs.get( "objectClass" ) );
        assertNull( attrs.get( "jpegPhoto" ) );
        assertNull( attrs.get( "description" ) );
        assertNotNull( attrs.get( "createtimestamp" ) );
        assertNotNull( attrs.get( "creatorsname" ) );
        assertNotNull( attrs.get( "entryuuid" ) );
        assertNotNull( attrs.get( "entrycsn" ) );
    }
    
    
    @Test
    public void testSearchAllAttrs() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setReturningAttributes( new String[]
            { "+", "*" } );
    
        NamingEnumeration<SearchResult> res = ctx.search( "", "(commonName=Tori Amos)", controls );
    
        assertTrue( res.hasMore() );
    
        SearchResult result = res.next();
    
        // ensure that result is not null
        assertNotNull( result );
    
        Attributes attrs = result.getAttributes();
    
        // ensure that all user attributes are returned
        assertEquals( 11, attrs.size() );
        assertNotNull( attrs.get( "cn" ) );
        assertNotNull( attrs.get( "sn" ) );
        assertNotNull( attrs.get( "objectClass" ) );
        assertNotNull( attrs.get( "jpegPhoto" ) );
        assertNotNull( attrs.get( "userCertificate" ) );
        assertNotNull( attrs.get( "description" ) );
        assertNotNull( attrs.get( "createtimestamp" ) );
        assertNotNull( attrs.get( "creatorsname" ) );
        assertNotNull( attrs.get( "entryuuid" ) );
        assertNotNull( attrs.get( "entrycsn" ) );
    }
    
    
    @Test
    public void testSearchBadDN() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
    
        try
        {
            ctx.search( "cn=admin", "(objectClass=*)", controls );
        }
        catch ( NameNotFoundException nnfe )
        {
            assertTrue( true );
        }
    }
    
    
    @Test
    public void testSearchInvalidDN() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
    
        try
        {
            ctx.search( "myBadDN", "(objectClass=*)", controls );
            fail();
        }
        catch ( NamingException ne )
        {
            assertTrue( true );
        }
    }
    
    
    /**
     * Check if operational attributes are present, if "+" is requested.
     */
    @Test
    public void testSearchOperationalAttributes() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
        SearchControls ctls = new SearchControls();
    
        ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
        ctls.setReturningAttributes( new String[]
            { "+" } );
    
        NamingEnumeration<SearchResult> result = ctx.search( HEATHER_RDN, FILTER, ctls );
    
        if ( result.hasMore() )
        {
            SearchResult entry = result.next();
    
            String[] opAttrNames =
                { "creatorsName", "createTimestamp" };
    
            checkForAttributes( entry.getAttributes(), opAttrNames );
        }
        else
        {
            fail( "entry " + HEATHER_RDN + " not found" );
        }
    
        result.close();
    }
    
    
    /**
     * Check if user attributes are present, if "*" is requested.
     */
    @Test
    public void testSearchUserAttributes() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
        SearchControls ctls = new SearchControls();
    
        ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
        ctls.setReturningAttributes( new String[]
            { "*" } );
    
        NamingEnumeration<SearchResult> result = ctx.search( HEATHER_RDN, FILTER, ctls );
    
        if ( result.hasMore() )
        {
            SearchResult entry = result.next();
    
            String[] userAttrNames =
                { "objectClass", "sn", "cn" };
    
            checkForAttributes( entry.getAttributes(), userAttrNames );
        }
        else
        {
            fail( "entry " + HEATHER_RDN + " not found" );
        }
    
        result.close();
    }
    
    
    /**
     * Check if no error occurs if " " is requested.
     */
    @Test
    public void testSearchUserAttributes_Space() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
        SearchControls ctls = new SearchControls();
    
        ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
        ctls.setReturningAttributes( new String[]
            { " " } );
    
        NamingEnumeration<SearchResult> result = ctx.search( HEATHER_RDN, FILTER, ctls );
        result.close();
    }
    
    
    /**
     * Check if no error occurs if "" is requested.
     */
    @Test
    public void testSearchUserAttributes_EmptyAttrs() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
        SearchControls ctls = new SearchControls();
    
        ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
        ctls.setReturningAttributes( new String[]
            { "" } );
    
        NamingEnumeration<SearchResult> result = ctx.search( HEATHER_RDN, FILTER, ctls );
        result.close();
    }
    
    
    /**
     * Check if no error occurs if "" is requested.
     */
    @Test
    public void testSearchUserAttributes_NullAttrs() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
        SearchControls ctls = new SearchControls();
    
        ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
        ctls.setReturningAttributes( new String[0] );
    
        NamingEnumeration<SearchResult> result = ctx.search( HEATHER_RDN, FILTER, ctls );
        result.close();
    }
    
    
    /**
     * Check if user and operational attributes are present, if both "*" and "+" are requested.
     */
    @Test
    public void testSearchOperationalAndUserAttributes() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
        SearchControls ctls = new SearchControls();
    
        ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
        ctls.setReturningAttributes( new String[]
            { "+", "*" } );
    
        String[] userAttrNames =
            { "objectClass", "sn", "cn" };
    
        String[] opAttrNames =
            { "creatorsName", "createTimestamp" };
    
        NamingEnumeration<SearchResult> result = ctx.search( HEATHER_RDN, FILTER, ctls );
    
        if ( result.hasMore() )
        {
            SearchResult entry = result.next();
            Attributes attrs = entry.getAttributes();
    
            assertNotNull( attrs );
    
            checkForAttributes( attrs, userAttrNames );
            checkForAttributes( attrs, opAttrNames );
        }
        else
        {
            fail( "entry " + HEATHER_RDN + " not found" );
        }
    
        result.close();
    
        ctls.setReturningAttributes( new String[]
            { "*", "+" } );
    
        result = ctx.search( HEATHER_RDN, FILTER, ctls );
    
        if ( result.hasMore() )
        {
            SearchResult entry = result.next();
            Attributes attrs = entry.getAttributes();
    
            assertNotNull( attrs );
    
            checkForAttributes( attrs, userAttrNames );
            checkForAttributes( attrs, opAttrNames );
        }
        else
        {
            fail( "entry " + HEATHER_RDN + " not found" );
        }
    
        result.close();
    }
    
    
    @Test
    public void testSubstringSearchWithEscapedCharsInFilter() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        Attributes attrs = new BasicAttributes( "objectClass", "inetOrgPerson", true );
        attrs.get( "objectClass" ).add( "organizationalPerson" );
        attrs.get( "objectClass" ).add( "person" );
        attrs.put( "givenName", "Jim" );
        attrs.put( "sn", "Bean" );
        attrs.put( "cn", "jimbean" );
        attrs.put( "description", "(sex*pis\\tols)" );
        ctx.createSubcontext( "cn=jimbean", attrs );
    
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setReturningAttributes( new String[]
            { "cn" } );
    
        String[] filters = new String[]
            { "(description=*\\28*)", "(description=*\\29*)", "(description=*\\2A*)", "(description=*\\5C*)" };
        for ( String filter : filters )
        {
            NamingEnumeration<SearchResult> res = ctx.search( "", filter, controls );
            assertTrue( res.hasMore() );
            SearchResult result = res.next();
            assertNotNull( result );
            attrs = result.getAttributes();
            assertEquals( 1, attrs.size() );
            assertNotNull( attrs.get( "cn" ) );
            assertEquals( 1, attrs.get( "cn" ).size() );
            assertEquals( "jimbean", attrs.get( "cn" ).get() );
            assertFalse( res.hasMore() );
        }
    }
    
    
    /**
     * Test for DIRSERVER-1180 where search hangs when an invalid a substring
     * expression missing an any field is used in a filter: i.e. (cn=**).
     * 
     * @see https://issues.apache.org/jira/browse/DIRSERVER-1180
     */
    @Test
    public void testMissingAnyInSubstring_DIRSERVER_1180() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
        Attributes attrs = new BasicAttributes( "objectClass", "inetOrgPerson", true );
        attrs.get( "objectClass" ).add( "organizationalPerson" );
        attrs.get( "objectClass" ).add( "person" );
        attrs.put( "givenName", "Jim" );
        attrs.put( "sn", "Bean" );
        attrs.put( "cn", "jimbean" );
    
        ctx.createSubcontext( "cn=jimbean", attrs );
    
        try
        {
            ctx.search( "", "(cn=**)", new SearchControls() );
            fail();
        }
        catch ( Exception e )
        {
            assertTrue( true );
        }
    }
    
    
    @Test
    public void testSubstringSearchWithEscapedAsterisksInFilter_DIRSERVER_1181() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        Attributes vicious = new BasicAttributes( true );
        Attribute ocls = new BasicAttribute( "objectClass" );
        ocls.add( "top" );
        ocls.add( "person" );
        vicious.put( ocls );
        vicious.put( "cn", "x*y*z*" );
        vicious.put( "sn", "x*y*z*" );
        ctx.createSubcontext( "cn=x*y*z*", vicious );
    
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
        controls.setReturningAttributes( new String[]
            { "cn" } );
        NamingEnumeration<SearchResult> res;
    
        res = ctx.search( "", "(cn=*x\\2Ay\\2Az\\2A*)", controls );
        assertTrue( res.hasMore() );
        assertEquals( "x*y*z*", res.next().getAttributes().get( "cn" ).get() );
        assertFalse( res.hasMore() );
    
        res = ctx.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() );
    }
    
    
    /**
     * Test for DIRSERVER-1347: Unicode characters in filter value.
     */
    @Test
    public void testUnicodeFilter_DIRSERVER_1347() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
    
        Attributes groupOfNames = new BasicAttributes( true );
        Attribute groupOfNamesOC = new BasicAttribute( "objectClass" );
        groupOfNamesOC.add( "top" );
        groupOfNamesOC.add( "groupOfNames" );
        groupOfNames.put( groupOfNamesOC );
        groupOfNames.put( "cn", "groupOfNames" );
        Attribute member = new BasicAttribute( "member" );
        member.add( "uid=test,ou=system" );
        member.add( "uid=r\u00e9dacteur1,ou=system" );
        groupOfNames.put( member );
        ctx.createSubcontext( "cn=groupOfNames", groupOfNames );
    
        Attributes groupOfUniqueNames = new BasicAttributes( true );
        Attribute groupOfUniqueNamesOC = new BasicAttribute( "objectClass" );
        groupOfUniqueNamesOC.add( "top" );
        groupOfUniqueNamesOC.add( "groupOfUniqueNames" );
        groupOfUniqueNames.put( groupOfUniqueNamesOC );
        groupOfUniqueNames.put( "cn", "groupOfUniqueNames" );
        Attribute uniqueMember = new BasicAttribute( "uniqueMember" );
        uniqueMember.add( "uid=test,ou=system" );
        uniqueMember.add( "uid=r\u00e9dacteur1,ou=system" );
        groupOfUniqueNames.put( uniqueMember );
        ctx.createSubcontext( "cn=groupOfUniqueNames", groupOfUniqueNames );
    
        SearchControls controls = new SearchControls();
        NamingEnumeration<SearchResult> res;
    
        // search with unicode filter value
        res = ctx.search( "", "(member=uid=r\u00e9dacteur1,ou=system)", controls );
        assertTrue( res.hasMore() );
        assertEquals( "groupOfNames", res.next().getAttributes().get( "cn" ).get() );
        assertFalse( res.hasMore() );
    
        // search with escaped filter value
        res = ctx.search( "", "(member=uid=r\\c3\\a9dacteur1,ou=system)", controls );
        assertTrue( res.hasMore() );
        assertEquals( "groupOfNames", res.next().getAttributes().get( "cn" ).get() );
        assertFalse( res.hasMore() );
    
        // search with unicode filter value
        res = ctx.search( "", "(uniqueMember=uid=r\u00e9dacteur1,ou=system)", controls );
        assertTrue( res.hasMore() );
        assertEquals( "groupOfUniqueNames", res.next().getAttributes().get( "cn" ).get() );
        assertFalse( res.hasMore() );
    
        // search with escaped filter value
        res = ctx.search( "", "(uniqueMember=uid=r\\c3\\a9dacteur1,ou=system)", controls );
        assertTrue( res.hasMore() );
        assertEquals( "groupOfUniqueNames", res.next().getAttributes().get( "cn" ).get() );
        assertFalse( res.hasMore() );
    }
    
    
    /**
     * Check if no user attributes are present, if "1.1" is requested.
     */
    @Test
    public void testSearchUserAttributes_1_1() throws Exception
    {
        LdapContext ctx = ( LdapContext ) getWiredContext( getLdapServer() ).lookup( BASE );
        SearchControls ctls = new SearchControls();
    
        ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
        ctls.setReturningAttributes( new String[]
            { "1.1" } );
    
        NamingEnumeration<SearchResult> result = ctx.search( HEATHER_RDN, FILTER, ctls );
    
        if ( result.hasMore() )
        {
            SearchResult entry = result.next();
            assertEquals( "No user attributes expected when requesting attribute 1.1", 0, entry.getAttributes().size() );
        }
        else
        {
            fail( "entry " + HEATHER_RDN + " not found" );
        }
    
        result.close();
    }
    
    
    /**
     * test an abandonned search request.
     */
    @Test
    public void testAbandonnedRequest() throws Exception
    {
        LdapConnection asyncCnx = new LdapNetworkConnection( "localhost", getLdapServer().getPort() );
        EntryCursor cursor = null;
    
        try
        {
            // Use the client API as JNDI cannot be used to do a search without
            // first binding. (hmmm, even client API won't allow searching without binding)
            asyncCnx.bind( "uid=admin,ou=system", "secret" );
    
            // First, add 1000 entries in the server
            for ( int i = 0; i < 1000; i++ )
            {
                String dn = "cn=user" + i + "," + BASE;
                Entry kate = new DefaultEntry( dn );
    
                kate.add( "objectclass", "top", "person" );
                kate.add( "sn", "Bush" );
                kate.add( "cn", "user" + i );
    
                asyncCnx.add( kate );
            }
    
            // Searches for all the entries in ou=system
            cursor = asyncCnx.search( "ou=system", "(ObjectClass=*)", SearchScope.SUBTREE, "*" );
    
            // Now loop on all the elements found, and abandon after 10 elements returned
            int count = 0;
    
            while ( cursor.next() )
            {
                count++;
    
                if ( count == 10 )
                {
                    // the message ID = 1 bind op + 1000 add ops + 1 search op
                    asyncCnx.abandon( 1002 );
                }
            }
    
            assertEquals( 10, count );
        }
        catch ( LdapException e )
        {
            e.printStackTrace();
            fail( "Should not have caught exception." );
        }
        finally
        {
            asyncCnx.unBind();
            asyncCnx.close();
            cursor.close();
        }
    }
    
    
    @Test
    public void testSearchSubstringWithPlus() throws Exception
    {
        LdapContext ctx = getWiredContext( getLdapServer() );
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setTimeLimit( 10 );
    
        NamingEnumeration<SearchResult> result = ctx.search( "ou=system", "(description=*+*)", controls );
    
        assertTrue( result.hasMore() );
    
        SearchResult entry = result.next();
    
        assertEquals( "Kim Wilde", entry.getAttributes().get( "cn" ).get() );
    }
    
    
    @Test
    public void testSearchSizeLimit() throws Exception
    {
        long sizeLimit = 7;
        LdapConnection connection = getAdminConnection( getLdapServer() );
        SearchRequest req = new org.apache.directory.shared.ldap.model.message.SearchRequestImpl();
        req.setBase( new Dn( "ou=system" ) );
        req.setFilter( "(ou=*)" );
        req.setScope( SearchScope.SUBTREE );
        req.setSizeLimit( sizeLimit );
    
        Cursor<Response> cursor = connection.search( req );
        long i = 0;
    
        // Equivalent to : while ( cursor.next() )
        for ( Response response : cursor )
        {
            ++i;
        }
        
        cursor.close();
    
        assertEquals( sizeLimit, i );
        connection.close();
    }
    
    
    @Test
    @Ignore("This test is failing because of the timing issue. Note that the SearchHandler handles time based searches correctly, this is just the below test's problem")
    public void testSearchTimeLimit() throws Exception, InterruptedException
    {
        LdapConnection connection = getAdminConnection( getLdapServer() );
        SearchRequest req = new SearchRequestImpl();
        req.setBase( new Dn( "ou=schema" ) );
        req.setFilter( "(objectClass=*)" );
        req.setScope( SearchScope.SUBTREE );
    
        Cursor<Response> cursor = connection.search( req );
        int count = 0;
    
        while ( cursor.next() )
        {
            ++count;
        }
    
        cursor.close();
    
        req.setTimeLimit( 1 );
        cursor = connection.search( req );
        int newCount = 0;
    
        while ( cursor.next() )
        {
            ++newCount;
        }
    
        assertTrue( newCount < count );
        connection.close();
    }
    
    
    @Test
    public void testSearchComplexFilter() throws Exception
    {
        LdapContext ctx = getWiredContext( getLdapServer() );
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.OBJECT_SCOPE );
        controls.setTimeLimit( 10 );
    
        NamingEnumeration<SearchResult> result = ctx.search( "cn=Kim Wilde,ou=system",
            "(&(&(ObjectClass=person)(!(ObjectClass=strongAuthenticationUser))(sn=Wilde)))", controls );
    
        assertTrue( result.hasMore() );
        SearchResult sr = result.next();
        assertNotNull( sr );
        assertEquals( "Kim Wilde", sr.getAttributes().get( "cn" ).get() );
    
        // Now check with another version of the filter
        result = ctx.search( "cn=Kim Wilde,ou=system",
            "(&(sn=Wilde)(&(objectClass=person)(!(objectClass=strongAuthenticationUser))))", controls );
    
        assertTrue( result.hasMore() );
        sr = result.next();
        assertNotNull( sr );
        assertEquals( "Kim Wilde", sr.getAttributes().get( "cn" ).get() );
    }
}
