/*
 *  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.shared.ldap.codec.search;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.mycila.junit.concurrent.Concurrency;
import com.mycila.junit.concurrent.ConcurrentJunitRunner;
import org.apache.directory.shared.asn1.DecoderException;
import org.apache.directory.shared.asn1.EncoderException;
import org.apache.directory.shared.asn1.ber.Asn1Decoder;
import org.apache.directory.shared.asn1.ber.tlv.TLVStateEnum;
import org.apache.directory.shared.ldap.codec.LdapMessageContainer;
import org.apache.directory.shared.ldap.codec.api.ResponseCarryingException;
import org.apache.directory.shared.ldap.codec.controls.search.subentries.SubentriesDecorator;
import org.apache.directory.shared.ldap.codec.decorators.SearchRequestDecorator;
import org.apache.directory.shared.ldap.codec.osgi.AbstractCodecServiceTest;
import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
import org.apache.directory.shared.ldap.model.filter.AndNode;
import org.apache.directory.shared.ldap.model.filter.ApproximateNode;
import org.apache.directory.shared.ldap.model.filter.EqualityNode;
import org.apache.directory.shared.ldap.model.filter.ExprNode;
import org.apache.directory.shared.ldap.model.filter.GreaterEqNode;
import org.apache.directory.shared.ldap.model.filter.LessEqNode;
import org.apache.directory.shared.ldap.model.filter.NotNode;
import org.apache.directory.shared.ldap.model.filter.OrNode;
import org.apache.directory.shared.ldap.model.filter.PresenceNode;
import org.apache.directory.shared.ldap.model.filter.SearchScope;
import org.apache.directory.shared.ldap.model.filter.SubstringNode;
import org.apache.directory.shared.ldap.model.message.AliasDerefMode;
import org.apache.directory.shared.ldap.model.message.Control;
import org.apache.directory.shared.ldap.model.message.Message;
import org.apache.directory.shared.ldap.model.message.ResultCodeEnum;
import org.apache.directory.shared.ldap.model.message.SearchRequest;
import org.apache.directory.shared.ldap.model.message.SearchResultDoneImpl;
import org.apache.directory.shared.ldap.model.message.controls.Subentries;
import org.apache.directory.shared.ldap.model.schema.normalizers.DeepTrimToLowerNormalizer;
import org.apache.directory.shared.ldap.model.schema.normalizers.OidNormalizer;
import org.apache.directory.shared.util.Strings;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;


/**
 * A test case for SearchRequest messages
 * 
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
@RunWith(ConcurrentJunitRunner.class)
@Concurrency()
public class SearchRequestTest extends AbstractCodecServiceTest
{
    /** An oid normalizer map */
    static Map<String, OidNormalizer> oids = new HashMap<String, OidNormalizer>();


    @Before
    public void setUp() throws Exception
    {
        // DC normalizer
        OidNormalizer dcOidNormalizer = new OidNormalizer( "dc", new DeepTrimToLowerNormalizer(
            SchemaConstants.DOMAIN_COMPONENT_AT_OID ) );

        oids.put( "dc", dcOidNormalizer );
        oids.put( "domaincomponent", dcOidNormalizer );
        oids.put( "0.9.2342.19200300.100.1.25", dcOidNormalizer );

        // OU normalizer
        OidNormalizer ouOidNormalizer = new OidNormalizer( "ou", new DeepTrimToLowerNormalizer(
            SchemaConstants.OU_AT_OID ) );

        oids.put( "ou", ouOidNormalizer );
        oids.put( "organizationalUnitName", ouOidNormalizer );
        oids.put( "2.5.4.11", ouOidNormalizer );

        // ObjectClass normalizer
        OidNormalizer objectClassOidNormalizer = new OidNormalizer( "objectClass", new DeepTrimToLowerNormalizer(
            SchemaConstants.OBJECT_CLASS_AT_OID ) );

        oids.put( "objectclass", objectClassOidNormalizer );
        oids.put( "2.5.4.0", objectClassOidNormalizer );
    }


    /**
     * Test the decoding of a SearchRequest with no controls. The search filter
     * is : (&(|(objectclass=top)(ou=contacts))(!(objectclass=ttt)))
     */
    @Test
    public void testDecodeSearchRequestGlobalNoControls()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x90 );
        stream.put( new byte[]
            { 0x30, ( byte ) 0x81,
                ( byte ) 0x8D, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01,
                0x01, // messageID MessageID
                0x63,
                ( byte ) 0x81,
                ( byte ) 0x87, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                // baseObject (0),
                // singleLevel (1),
                // wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                // neverDerefAliases (0),
                // derefInSearching (1),
                // derefFindingBaseObj (2),
                // derefAlways (3) },
                0x02, 0x02, 0x03, ( byte ) 0xE8, // sizeLimit INTEGER (0 .. maxInt), (1000)
                0x02, 0x02, 0x03, ( byte ) 0xE8, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF, // typesOnly  BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x3C, // Filter ::= CHOICE {
                // and [0] SET OF Filter,
                ( byte ) 0xA1, 0x24, // or [1] SET of Filter,
                ( byte ) 0xA3, 0x12, // equalityMatch [3]
                // Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 'o', 'p', ( byte ) 0xA3, 0x0E, // equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x02, 'o', 'u', // attributeDesc AttributeDescription (LDAPString),
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x08, 'c', 'o', 'n', 't', 'a', 'c', 't', 's', ( byte ) 0xA2, 0x14, // not [2] Filter,
                ( byte ) 0xA3, 0x12, // equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 't', 't',
                // attributes AttributeDescriptionList }
                0x30, 0x15, // AttributeDescriptionList ::= SEQUENCE OF
                // AttributeDescription
                0x04, 0x05, 'a', 't', 't', 'r', '0', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '1', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '2' // AttributeDescription ::= LDAPString
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "uid=akarasulu,dc=example,dc=com", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 1000, searchRequest.getSizeLimit() );
        assertEquals( 1000, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (& (...
        ExprNode node = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) node;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();

        // (& (| (...
        assertEquals( 2, andNodes.size() );
        OrNode orFilter = ( OrNode ) andNodes.get( 0 );
        assertNotNull( orFilter );

        // (& (| (obectclass=top) (...
        List<ExprNode> orNodes = orFilter.getChildren();
        assertEquals( 2, orNodes.size() );
        EqualityNode<?> equalityNode = ( EqualityNode<?> ) orNodes.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "objectclass", equalityNode.getAttribute() );
        assertEquals( "top", equalityNode.getValue().getString() );

        // (& (| (objectclass=top) (ou=contacts) ) (...
        equalityNode = ( EqualityNode<?> ) orNodes.get( 1 );
        assertNotNull( equalityNode );

        assertEquals( "ou", equalityNode.getAttribute() );
        assertEquals( "contacts", equalityNode.getValue().getString() );

        // (& (| (objectclass=top) (ou=contacts) ) (! ...
        NotNode notNode = ( NotNode ) andNodes.get( 1 );
        assertNotNull( notNode );

        // (& (| (objectclass=top) (ou=contacts) ) (! (objectclass=ttt) ) )
        equalityNode = ( EqualityNode<?> ) notNode.getFirstChild();
        assertNotNull( equalityNode );

        assertEquals( "objectclass", equalityNode.getAttribute() );
        assertEquals( "ttt", equalityNode.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();

        for ( String attribute : attributes )
        {
            assertNotNull( attribute );
        }

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x90, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x81 ), decodedPdu.substring( 0, 0x81 ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest with no controls. Test the various
     * types of filter : >=, <=, ~= The search filter is :
     * (&(|(objectclass~=top)(ou<=contacts))(!(objectclass>=ttt)))
     */
    @Test
    public void testDecodeSearchRequestCompareFiltersNoControls()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x90 );
        stream.put( new byte[]
            { 0x30, ( byte ) 0x81,
                ( byte ) 0x8D, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01,
                0x01, //     messageID MessageID
                0x63,
                ( byte ) 0x81,
                ( byte ) 0x87, //     CHOICE { ...,
                //         searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04,
                0x1F, //     baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x01, //     scope ENUMERATED {
                //         baseObject   (0),
                //         singleLevel  (1),
                //         wholeSubtree (2) },
                0x0A, 0x01, 0x03, //     derefAliases ENUMERATED {
                //         neverDerefAliases (0),
                //         derefInSearching (1),
                //         derefFindingBaseObj (2),
                //         derefAlways (3) },
                0x02, 0x02, 0x03, ( byte ) 0xE8, //     sizeLimit INTEGER (0 .. maxInt), (1000)
                0x02, 0x02, 0x03, ( byte ) 0xE8, //     timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF, //     typesOnly BOOLEAN, (TRUE)
                //     filter Filter,
                ( byte ) 0xA0, 0x3C, // Filter ::= CHOICE {
                //      and [0] SET OF Filter,
                ( byte ) 0xA1, 0x24, //      or [1] SET of Filter,
                ( byte ) 0xA8, 0x12, //      approxMatch [8]
                // Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x0B, // attributeDesc AttributeDescription (LDAPString),
                'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's', 0x04, 0x03, // attributeDesc AttributeDescription (LDAPString), 
                't', 'o', 'p', ( byte ) 0xA6, 0x0E, // lessOrEqual [3] Assertion,
                0x04, 0x02, // Assertion ::= SEQUENCE {
                'o', 'u', // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x08, // assertionValue AssertionValue (OCTET STRING) } 
                'c', 'o', 'n', 't', 'a', 'c', 't', 's', ( byte ) 0xA2, 0x14, // not [2] Filter,
                ( byte ) 0xA5, 0x12, // greaterOrEqual [5] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x0B, // attributeDesc AttributeDescription (LDAPString), 
                'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's', 0x04, 0x03, 't', 't', 't', // assertionValue AssertionValue (OCTET STRING) }
                // attributes AttributeDescriptionList }
                0x30, 0x15, // AttributeDescriptionList ::= SEQUENCE OF
                // AttributeDescription
                0x04, 0x05, 'a', 't', 't', 'r', '0', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '1', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '2' // AttributeDescription ::= LDAPString
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "uid=akarasulu,dc=example,dc=com", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 1000, searchRequest.getSizeLimit() );
        assertEquals( 1000, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (& (...
        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();

        // (& (| (...
        assertEquals( 2, andNodes.size() );
        OrNode orFilter = ( OrNode ) andNodes.get( 0 );
        assertNotNull( orFilter );

        // (& (| (objectclass~=top) (...
        List<ExprNode> orNodes = orFilter.getChildren();
        assertEquals( 2, orNodes.size() );
        ApproximateNode<?> approxNode = ( ApproximateNode<?> ) orNodes.get( 0 );
        assertNotNull( approxNode );

        assertEquals( "objectclass", approxNode.getAttribute() );
        assertEquals( "top", approxNode.getValue().getString() );

        // (& (| (objectclass~=top) (ou<=contacts) ) (...
        LessEqNode<?> lessOrEqualNode = ( LessEqNode<?> ) orNodes.get( 1 );
        assertNotNull( lessOrEqualNode );

        assertEquals( "ou", lessOrEqualNode.getAttribute() );
        assertEquals( "contacts", lessOrEqualNode.getValue().getString() );

        // (& (| (objectclass~=top) (ou<=contacts) ) (! ...
        NotNode notNode = ( NotNode ) andNodes.get( 1 );
        assertNotNull( notNode );

        // (& (| (objectclass~=top) (ou<=contacts) ) (! (objectclass>=ttt) ) )
        GreaterEqNode<?> greaterOrEqual = ( GreaterEqNode<?> ) notNode.getFirstChild();
        assertNotNull( greaterOrEqual );

        assertEquals( "objectclass", greaterOrEqual.getAttribute() );
        assertEquals( "ttt", greaterOrEqual.getValue().getString() );

        // The attributes
        List<String> attributes = searchRequest.getAttributes();

        for ( String attribute : attributes )
        {
            assertNotNull( attribute );
        }

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x0090, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x81 ), decodedPdu.substring( 0, 0x81 ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest with no controls. Test the present
     * filter : =* The search filter is :
     * (&(|(objectclass=*)(ou=*))(!(objectclass>=ttt)))
     */
    @Test
    public void testDecodeSearchRequestPresentNoControls()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x7B );
        stream.put( new byte[]
            { 0x30,
                0x79, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01,
                0x01, // messageID MessageID
                0x63,
                0x74, // CHOICE { ..., searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x01, // scope
                // ENUMERATED
                // {
                // baseObject (0),
                // singleLevel (1),
                // wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                // neverDerefAliases (0),
                // derefInSearching (1),
                // derefFindingBaseObj (2),
                // derefAlways (3) },
                // sizeLimit INTEGER (0 .. maxInt), (1000)
                0x02, 0x02, 0x03, ( byte ) 0xE8,
                // timeLimit INTEGER (0 .. maxInt), (1000)
                0x02, 0x02, 0x03, ( byte ) 0xE8, 0x01, 0x01, ( byte ) 0xFF, // typesOnly
                // BOOLEAN,
                // (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x29, // Filter ::= CHOICE {
                // and [0] SET OF Filter,
                ( byte ) 0xA1, 0x11, // or [1] SET of Filter,
                ( byte ) 0x87, 0x0B, // present [7] AttributeDescription,
                // AttributeDescription ::= LDAPString
                'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                ( byte ) 0x87, 0x02, 'o', 'u', // present [7]
                // AttributeDescription,
                // AttributeDescription ::= LDAPString
                ( byte ) 0xA2, 0x14, // not [2] Filter,
                ( byte ) 0xA5, 0x12, // greaterOrEqual [5]
                // Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 't', 't',
                // attributes AttributeDescriptionList }
                0x30, 0x15, // AttributeDescriptionList ::= SEQUENCE OF
                // AttributeDescription
                0x04, 0x05, 'a', 't', 't', 'r', '0', // AttributeDescription
                // ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '1', // AttributeDescription
                // ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '2' // AttributeDescription ::=
            // LDAPString
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "uid=akarasulu,dc=example,dc=com", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 1000, searchRequest.getSizeLimit() );
        assertEquals( 1000, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (& (...
        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();

        // (& (| (...
        assertEquals( 2, andNodes.size() );
        OrNode orFilter = ( OrNode ) andNodes.get( 0 );
        assertNotNull( orFilter );

        // (& (| (objectclass=*) (...
        List<ExprNode> orNodes = orFilter.getChildren();
        assertEquals( 2, orNodes.size() );

        PresenceNode presenceNode = ( PresenceNode ) orNodes.get( 0 );
        assertNotNull( presenceNode );

        assertEquals( "objectclass", presenceNode.getAttribute() );

        // (& (| (objectclass=*) (ou=*) ) (...
        presenceNode = ( PresenceNode ) orNodes.get( 1 );
        assertNotNull( presenceNode );

        assertEquals( "ou", presenceNode.getAttribute() );

        // (& (| (objectclass=*) (ou=*) ) (! ...
        NotNode notNode = ( NotNode ) andNodes.get( 1 );
        assertNotNull( notNode );

        // (& (| (objectclass=*) (ou=*) ) (! (objectclass>=ttt) ) )
        GreaterEqNode<?> greaterOrEqual = ( GreaterEqNode<?> ) notNode.getFirstChild();
        assertNotNull( greaterOrEqual );

        assertEquals( "objectclass", greaterOrEqual.getAttribute() );
        assertEquals( "ttt", greaterOrEqual.getValue().getString() );

        // The attributes
        List<String> attributes = searchRequest.getAttributes();

        for ( String attribute : attributes )
        {
            assertNotNull( attribute );
        }

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x7B, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x6C ), decodedPdu.substring( 0, 0x6C ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest with no attributes. The search
     * filter is : (objectclass=*)
     */
    @Test
    public void testDecodeSearchRequestNoAttributes()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x40 );
        stream.put( new byte[]
            { 0x30,
                0x37, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01,
                0x03, // messageID MessageID
                0x63,
                0x32, // CHOICE { ..., searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04,
                0x12, // baseObject LDAPDN,
                'o', 'u', '=', 'u', 's', 'e', 'r', 's', ',', 'o', 'u', '=', 's', 'y', 's', 't', 'e', 'm', 0x0A, 0x01,
                0x00, // scope ENUMERATED {
                // baseObject (0),
                // singleLevel (1),
                // wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                // neverDerefAliases (0),
                // derefInSearching (1),
                // derefFindingBaseObj (2),
                // derefAlways (3) },
                // sizeLimit INTEGER (0 .. maxInt), (infinite)
                0x02, 0x01, 0x00,
                // timeLimit INTEGER (0 .. maxInt), (infinite)
                0x02, 0x01, 0x00, 0x01, 0x01, ( byte ) 0x00, // typesOnly
                // BOOLEAN,
                // (FALSE)
                // filter Filter,
                // Filter ::= CHOICE {
                ( byte ) 0x87, 0x0B, // present [7] AttributeDescription,
                'o', 'b', 'j', 'e', 'c', 't', 'C', 'l', 'a', 's', 's',
                // attributes AttributeDescriptionList }
                0x30, 0x00, // AttributeDescriptionList ::= SEQUENCE OF
                // AttributeDescription
                0x00, 0x00, // Some trailing 00, useless.
                0x00, 0x00, 0x00, 0x00 } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 3, searchRequest.getMessageId() );
        assertEquals( "ou=users,ou=system", searchRequest.getBase().toString() );
        assertEquals( SearchScope.OBJECT, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( false, searchRequest.getTypesOnly() );

        // (objectClass = *)
        ExprNode filter = searchRequest.getFilter();

        PresenceNode presenceNode = ( PresenceNode ) filter;
        assertNotNull( presenceNode );
        assertEquals( "objectClass", presenceNode.getAttribute() );

        // The attributes
        List<String> attributes = searchRequest.getAttributes();

        assertEquals( 0, attributes.size() );

        // Check the encoding
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x39, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu, decodedPdu.substring( 0, decodedPdu.length() - 35 ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest with an empty attribute. The search
     * filter is : (objectclass=*)
     */
    @Test
    public void testDecodeSearchRequestOneEmptyAttribute()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x3F );
        stream.put( new byte[]
            { 0x30,
                0x3D, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01,
                0x03, // messageID MessageID
                0x63,
                0x38, // CHOICE { ..., searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04,
                0x12, // baseObject LDAPDN,
                'o', 'u', '=', 'u', 's', 'e', 'r', 's', ',', 'o', 'u', '=', 's', 'y', 's', 't', 'e', 'm', 0x0A, 0x01,
                0x00, // scope ENUMERATED {
                // baseObject (0),
                // singleLevel (1),
                // wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                // neverDerefAliases (0),
                // derefInSearching (1),
                // derefFindingBaseObj (2),
                // derefAlways (3) },
                // sizeLimit INTEGER (0 .. maxInt), (infinite)
                0x02, 0x01, 0x00, // timeLimit INTEGER (0 .. maxInt), (infinite)
                0x02, 0x01, 0x00, 0x01, 0x01, 0x00, // typesOnly
                // BOOLEAN,
                // (FALSE)
                // filter Filter,
                // Filter ::= CHOICE {
                ( byte ) 0x87, 0x0B, // present [7] AttributeDescription,
                'o', 'b', 'j', 'e', 'c', 't', 'C', 'l', 'a', 's', 's',
                // attributes AttributeDescriptionList }
                0x30, 0x06, // AttributeDescriptionList ::= SEQUENCE OF
                // AttributeDescription
                0x04, 0x02, // Request for sn
                's', 'n', 0x04, 0x00 // Empty attribute
            } );

        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 3, searchRequest.getMessageId() );
        assertEquals( "ou=users,ou=system", searchRequest.getBase().toString() );
        assertEquals( SearchScope.OBJECT, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( false, searchRequest.getTypesOnly() );

        // (objectClass = *)
        ExprNode filter = searchRequest.getFilter();

        PresenceNode presenceNode = ( PresenceNode ) filter;
        assertNotNull( presenceNode );
        assertEquals( "objectClass", presenceNode.getAttribute() );

        // The attributes
        List<String> attributes = searchRequest.getAttributes();

        assertEquals( 1, attributes.size() );
    }


    /**
     * Test the decoding of a SearchRequest with a star and an attribute. The search
     * filter is : (objectclass=*)
     */
    @Test
    public void testDecodeSearchRequestWithStarAndAttr()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x40 );
        stream.put( new byte[]
            { 0x30,
                0x3E, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01,
                0x03, // messageID MessageID
                0x63,
                0x39, // CHOICE { ..., searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04,
                0x12, // baseObject LDAPDN,
                'o', 'u', '=', 'u', 's', 'e', 'r', 's', ',', 'o', 'u', '=', 's', 'y', 's', 't', 'e', 'm', 0x0A, 0x01,
                0x00, // scope ENUMERATED {
                // baseObject (0),
                // singleLevel (1),
                // wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                // neverDerefAliases (0),
                // derefInSearching (1),
                // derefFindingBaseObj (2),
                // derefAlways (3) },
                // sizeLimit INTEGER (0 .. maxInt), (infinite)
                0x02, 0x01, 0x00, // timeLimit INTEGER (0 .. maxInt), (infinite)
                0x02, 0x01, 0x00, 0x01, 0x01, 0x00, // typesOnly
                // BOOLEAN,
                // (FALSE)
                // filter Filter,
                // Filter ::= CHOICE {
                ( byte ) 0x87, 0x0B, // present [7] AttributeDescription,
                'o', 'b', 'j', 'e', 'c', 't', 'C', 'l', 'a', 's', 's',
                // attributes AttributeDescriptionList }
                0x30, 0x07, // AttributeDescriptionList ::= SEQUENCE OF
                // AttributeDescription
                0x04, 0x02, // Request for sn
                's', 'n', 0x04, 0x01, '*' // * attribute
            } );

        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 3, searchRequest.getMessageId() );
        assertEquals( "ou=users,ou=system", searchRequest.getBase().toString() );
        assertEquals( SearchScope.OBJECT, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( false, searchRequest.getTypesOnly() );

        // (objectClass = *)
        ExprNode filter = searchRequest.getFilter();

        PresenceNode presenceNode = ( PresenceNode ) filter;
        assertNotNull( presenceNode );
        assertEquals( "objectClass", presenceNode.getAttribute() );

        // The attributes
        List<String> attributes = searchRequest.getAttributes();

        assertEquals( 2, attributes.size() );
        Set<String> expectedAttrs = new HashSet<String>();
        expectedAttrs.add( "sn" );
        expectedAttrs.add( "*" );

        for ( String attribute : attributes )
        {
            assertTrue( expectedAttrs.contains( attribute ) );
            expectedAttrs.remove( attribute );
        }

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


    /**
     * Tests an search request decode with a simple equality match filter.
     */
    @Test
    public void testDecodeSearchRequestOrFilters()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x96 );
        stream.put( new byte[]
            { 0x30, ( byte ) 0x81, ( byte ) 0x93, 0x02, 0x01,
                0x21,
                0x63,
                ( byte ) 0x81,
                ( byte ) 0x8D, // "dc=example,dc=com"
                0x04, 0x11, 'd', 'c', '=', 'e', 'x', 'a', 'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A,
                0x01, 0x00, 0x0A, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03, 0x01, 0x01,
                ( byte ) 0xFF,
                ( byte ) 0xA1,
                0x52, // ( |
                ( byte ) 0xA3,
                0x10, // ( uid=akarasulu )
                0x04, 0x03, 'u', 'i', 'd', 0x04, 0x09, 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u',
                ( byte ) 0xA3,
                0x09, // ( cn=aok )
                0x04, 0x02, 'c', 'n', 0x04, 0x03, 'a', 'o', 'k', ( byte ) 0xA3,
                0x15, // ( ou=Human Resources )
                0x04, 0x02, 'o', 'u', 0x04, 0x0F, 'H', 'u', 'm', 'a', 'n', ' ', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e',
                's', ( byte ) 0xA3, 0x10, 0x04, 0x01, 'l', // (l=Santa Clara )
                0x04, 0x0B, 'S', 'a', 'n', 't', 'a', ' ', 'C', 'l', 'a', 'r', 'a', ( byte ) 0xA3, 0x0A, // ( cn=abok ))
                0x04, 0x02, 'c', 'n', 0x04, 0x04, 'a', 'b', 'o', 'k', 0x30, 0x15, // Attributes
                0x04, 0x05, 'a', 't', 't', 'r', '0', // attr0
                0x04, 0x05, 'a', 't', 't', 'r', '1', // attr1
                0x04, 0x05, 'a', 't', 't', 'r', '2' // attr2
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 33, searchRequest.getMessageId() );
        assertEquals( "dc=example,dc=com", searchRequest.getBase().toString() );
        assertEquals( SearchScope.OBJECT, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_FINDING_BASE_OBJ, searchRequest.getDerefAliases() );
        assertEquals( 2, searchRequest.getSizeLimit() );
        assertEquals( 3, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (objectclass=t*)
        OrNode orNode = ( OrNode ) searchRequest.getFilter();
        assertNotNull( orNode );
        assertEquals( 5, orNode.getChildren().size() );

        // uid=akarasulu
        EqualityNode<?> equalityNode = ( EqualityNode<?> ) orNode.getChildren().get( 0 );

        assertEquals( "uid", equalityNode.getAttribute() );
        assertEquals( "akarasulu", equalityNode.getValue().getString() );

        // cn=aok
        equalityNode = ( EqualityNode<?> ) orNode.getChildren().get( 1 );

        assertEquals( "cn", equalityNode.getAttribute() );
        assertEquals( "aok", equalityNode.getValue().getString() );

        // ou = Human Resources
        equalityNode = ( EqualityNode<?> ) orNode.getChildren().get( 2 );

        assertEquals( "ou", equalityNode.getAttribute() );
        assertEquals( "Human Resources", equalityNode.getValue().getString() );

        // l=Santa Clara
        equalityNode = ( EqualityNode<?> ) orNode.getChildren().get( 3 );

        assertEquals( "l", equalityNode.getAttribute() );
        assertEquals( "Santa Clara", equalityNode.getValue().getString() );

        // cn=abok
        equalityNode = ( EqualityNode<?> ) orNode.getChildren().get( 4 );

        assertEquals( "cn", equalityNode.getAttribute() );
        assertEquals( "abok", equalityNode.getValue().getString() );

        // The attributes
        List<String> attributes = searchRequest.getAttributes();

        for ( String attribute : attributes )
        {
            assertNotNull( attribute );
        }

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x0096, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x87 ), decodedPdu.substring( 0, 0x87 ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest with controls.
     */
    @Test
    public void testDecodeSearchRequestWithControls()
    {
        byte[] asn1BERJava5 = new byte[]
            { 0x30, 0x7f,
                0x02, 0x01, 0x04, // messageID
                0x63, 0x33,
                  0x04, 0x13, // baseObject
                    'd', 'c', '=', 'm', 'y', '-', 'd', 'o', 'm', 'a', 'i', 'n', ',', 'd', 'c', '=', 'c', 'o', 'm',
                  0x0a, 0x01, 0x02, // scope: subtree
                  0x0a, 0x01, 0x03, // derefAliases: derefAlways
                  0x02, 0x01, 0x00, // sizeLimit: 0
                  0x02, 0x01, 0x00, // timeLimit: 0
                  0x01, 0x01, 0x00, // typesOnly: false
                  ( byte ) 0x87, 0x0b, // Present filter: (objectClass=*)
                    'o', 'b', 'j', 'e', 'c', 't', 'C', 'l', 'a', 's', 's',
                  0x30, 0x00, // Attributes = '*'
                  ( byte ) 0xa0, 0x45, // controls
                    0x30, 0x28,
                      0x04, 0x16, // control
                        '1', '.', '2', '.', '8', '4', '0', '.', 
                        '1', '1', '3', '5', '5', '6', '.', '1', 
                        '.', '4', '.', '3', '1', '9', 
                      0x01, 0x01, ( byte ) 0xff, // criticality: false
                      0x04, 0x0b, 
                        0x30, 0x09, 
                          0x02, 0x01, 0x02, 
                          0x04, 0x04, 0x47, 0x00, 0x00, 0x00, // value: pageSize=2
                    0x30, 0x19, 
                      0x04, 0x17, // control
                        '2', '.', '1', '6', '.', '8', '4', '0', 
                        '.', '1', '.', '1', '1', '3', '7', '3', 
                        '0', '.', '3', '.', '4', '.', '2', 
                        };

        byte[] asn1BERJava6 = new byte[]
           { 0x30, 0x7f,
               0x02, 0x01, 0x04, // messageID
               0x63, 0x33,
                 0x04, 0x13, // baseObject
                   'd', 'c', '=', 'm', 'y', '-', 'd', 'o', 'm', 'a', 'i', 'n', ',', 'd', 'c', '=', 'c', 'o', 'm',
                 0x0a, 0x01, 0x02, // scope: subtree
                 0x0a, 0x01, 0x03, // derefAliases: derefAlways
                 0x02, 0x01, 0x00, // sizeLimit: 0
                 0x02, 0x01, 0x00, // timeLimit: 0
                 0x01, 0x01, 0x00, // typesOnly: false
                 ( byte ) 0x87, 0x0b, // Present filter: (objectClass=*)
                   'o', 'b', 'j', 'e', 'c', 't', 'C', 'l', 'a', 's', 's',
                 0x30, 0x00, // Attributes = '*'
                 ( byte ) 0xa0, 0x45, // controls
                   0x30, 0x19, 
                     0x04, 0x17, // control
                       '2', '.', '1', '6', '.', '8', '4', '0', 
                       '.', '1', '.', '1', '1', '3', '7', '3', 
                       '0', '.', '3', '.', '4', '.', '2', 
                   0x30, 0x28,
                     0x04, 0x16, // control
                       '1', '.', '2', '.', '8', '4', '0', '.', 
                       '1', '1', '3', '5', '5', '6', '.', '1', 
                       '.', '4', '.', '3', '1', '9', 
                     0x01, 0x01, ( byte ) 0xff, // criticality: false
                     0x04, 0x0b, 
                       0x30, 0x09, 
                         0x02, 0x01, 0x02, 
                         0x04, 0x04, 0x47, 0x00, 0x00, 0x00, // value: pageSize=2
                       };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        // For Java6
        ByteBuffer streamJava6 = ByteBuffer.allocate( asn1BERJava6.length );
        streamJava6.put( asn1BERJava6 );
        String decodedPduJava6 = Strings.dumpBytes(streamJava6.array());
        streamJava6.flip();

        // For Java5
        ByteBuffer streamJava5 = ByteBuffer.allocate( asn1BERJava5.length );
        streamJava5.put( asn1BERJava5 );
        String decodedPduJava5 = Strings.dumpBytes(streamJava5.array());

        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( streamJava6, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 4, searchRequest.getMessageId() );
        assertEquals( 2, searchRequest.getControls().size() );

        // this is a constant in Java 5 API
        String pagedResultsControlOID = "1.2.840.113556.1.4.319";
        Control pagedResultsControl = searchRequest.getControl( pagedResultsControlOID );
        assertEquals( pagedResultsControlOID, pagedResultsControl.getOid() );
        assertTrue( pagedResultsControl.isCritical() );

        // this is a constant in Java 5 API
        String manageReferralControlOID = "2.16.840.1.113730.3.4.2";
        Control manageReferralControl = searchRequest.getControl( manageReferralControlOID );
        assertEquals( manageReferralControlOID, manageReferralControl.getOid() );

        assertEquals( "dc=my-domain,dc=com", searchRequest.getBase().toString() );
        assertEquals( SearchScope.SUBTREE, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( false, searchRequest.getTypesOnly() );

        ExprNode filter = searchRequest.getFilter();

        assertTrue( filter instanceof PresenceNode );
        assertEquals( "objectClass", ( ( PresenceNode ) filter ).getAttribute() );

        // Check the encoding
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x81, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());
            
            assertTrue( decodedPduJava5.equals( encodedPdu ) || decodedPduJava6.equals( encodedPdu ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest with no controls but with oid
     * attributes. The search filter is :
     * (&(|(objectclass=top)(2.5.4.11=contacts))(!(organizationalUnitName=ttt)))
     */
    @Test
    public void testDecodeSearchRequestGlobalNoControlsOidAndAlias()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0xA1 );
        stream.put( new byte[]
            {
                0x30,
                ( byte ) 0x81,
                ( byte ) 0x9E, // LDAPMessage ::=SEQUENCE {
                0x02,
                0x01,
                0x01, // messageID MessageID
                0x63,
                ( byte ) 0x81,
                ( byte ) 0x98, // CHOICE { ...,
                // searchRequest
                // SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd',
                'c',
                '=',
                'c',
                'o',
                'm',
                0x0A,
                0x01,
                0x01, // scope
                // ENUMERATED
                // {
                // baseObject (0),
                // singleLevel (1),
                // wholeSubtree (2) },
                0x0A,
                0x01,
                0x03, // derefAliases ENUMERATED {
                // neverDerefAliases (0),
                // derefInSearching (1),
                // derefFindingBaseObj (2),
                // derefAlways (3) },
                // sizeLimit INTEGER (0 .. maxInt), (1000)
                0x02, 0x02, 0x03, ( byte ) 0xE8,
                // timeLimit INTEGER (0 .. maxInt), (1000)
                0x02, 0x02, 0x03,
                ( byte ) 0xE8,
                0x01,
                0x01,
                ( byte ) 0xFF, // typesOnly
                // BOOLEAN,
                // (TRUE)
                // filter Filter,
                ( byte ) 0xA0,
                0x4D, // Filter ::= CHOICE {
                // and [0] SET OF Filter,
                ( byte ) 0xA1,
                0x2A, // or [1] SET of Filter,
                ( byte ) 0xA3,
                0x12, // equalityMatch [3]
                // Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 'o',
                'p',
                ( byte ) 0xA3,
                0x14, // equalityMatch
                // [3]
                // Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x08, '2', '.', '5', '.', '4',
                '.',
                '1',
                '1', // attributeDesc
                // AttributeDescription
                // (LDAPString),
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x08, 'c', 'o', 'n', 't', 'a', 'c',
                't',
                's',
                ( byte ) 0xA2,
                0x1F, // not
                // [2]
                // Filter,
                ( byte ) 0xA3,
                0x1D, // equalityMatch [3]
                // Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x16, 'o', 'r', 'g', 'a', 'n', 'i', 'z', 'a', 't', 'i', 'o', 'n', 'a', 'l', 'U', 'n', 'i', 't',
                'N', 'a', 'm', 'e',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 't', 't',
                // attributes AttributeDescriptionList }
                0x30, 0x15, // AttributeDescriptionList ::= SEQUENCE OF
                // AttributeDescription
                0x04, 0x05, 'a', 't', 't', 'r', '0', // AttributeDescription
                // ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '1', // AttributeDescription
                // ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '2' // AttributeDescription ::=
            // LDAPString
            } );

        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "uid=akarasulu,dc=example,dc=com", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 1000, searchRequest.getSizeLimit() );
        assertEquals( 1000, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (& (...
        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();

        // (& (| (...
        assertEquals( 2, andNodes.size() );
        OrNode orFilter = ( OrNode ) andNodes.get( 0 );
        assertNotNull( orFilter );

        // (& (| (obectclass=top) (...
        List<ExprNode> orNodes = orFilter.getChildren();
        assertEquals( 2, orNodes.size() );
        
        EqualityNode<?> equalityNode = ( EqualityNode<?> ) orNodes.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "objectclass", equalityNode.getAttribute() );
        assertEquals( "top", equalityNode.getValue().getString() );

        // (& (| (objectclass=top) (ou=contacts) ) (...
        equalityNode = ( EqualityNode<?> ) orNodes.get( 1 );
        assertNotNull( equalityNode );

        assertEquals( "2.5.4.11", equalityNode.getAttribute() );
        assertEquals( "contacts", equalityNode.getValue().getString() );

        // (& (| (objectclass=top) (ou=contacts) ) (! ...
        NotNode notNode = ( NotNode ) andNodes.get( 1 );
        assertNotNull( notNode );

        // (& (| (objectclass=top) (ou=contacts) ) (! (objectclass=ttt) ) )
        equalityNode = ( EqualityNode<?> ) notNode.getFirstChild();
        assertNotNull( equalityNode );

        assertEquals( "organizationalUnitName", equalityNode.getAttribute() );
        assertEquals( "ttt", equalityNode.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();

        for ( String attribute : attributes )
        {
            assertNotNull( attribute );
        }

        // We won't check the encoding, as it has changed because of
        // attributes transformations
    }


    /**
     * Test the decoding of a SearchRequest with SubEntry control.
     */
    @Test
    public void testDecodeSearchRequestSubEntryControl()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x5D, 0x02,
                0x01,
                0x04, // messageID
                0x63, 0x33,
                0x04,
                0x13, // baseObject: dc=my-domain,dc=com
                'd', 'c', '=', 'm', 'y', '-', 'd', 'o', 'm', 'a', 'i', 'n', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0a,
                0x01,
                0x02, // scope: subtree
                0x0a, 0x01,
                0x03, // derefAliases: derefAlways
                0x02, 0x01,
                0x00, // sizeLimit: 0
                0x02, 0x01,
                0x00, // timeLimit: 0
                0x01, 0x01,
                0x00, // typesOnly: false
                ( byte ) 0x87,
                0x0b, // filter: (objectClass=*)
                'o', 'b', 'j', 'e', 'c', 't', 'C', 'l', 'a', 's', 's', 0x30, 0x00, ( byte ) 0xa0,
                0x23, // controls
                0x30, 0x21, 0x04, 0x17, '1', '.', '3', '.', '6', '.', '1', '.', '4', '.', '1', '.', '4', '2', '0', '3',
                '.', '1', '.', '1', '0', '.', '1', // SubEntry OID
                0x01, 0x01, ( byte ) 0xFF, // criticality: true
                0x04, 0x03, 0x01, 0x01, ( byte ) 0xFF // SubEntry visibility
            };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 4, searchRequest.getMessageId() );
        assertEquals( 1, searchRequest.getControls().size() );

        // SubEntry Control
        String subEntryControlOID = "1.3.6.1.4.1.4203.1.10.1";
        Control subEntryControl = searchRequest.getControl( subEntryControlOID );
        assertEquals( subEntryControlOID, subEntryControl.getOid() );
        assertTrue( subEntryControl.isCritical() );
        assertTrue( subEntryControl instanceof SubentriesDecorator );
        assertTrue( ( ( Subentries ) ( ( SubentriesDecorator ) subEntryControl ).getDecorated() ).isVisible() );

        assertEquals( "dc=my-domain,dc=com", searchRequest.getBase().toString() );
        assertEquals( SearchScope.SUBTREE, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( false, searchRequest.getTypesOnly() );

        ExprNode filter = searchRequest.getFilter();

        assertTrue( filter instanceof PresenceNode );
        assertEquals( "objectClass", ( ( PresenceNode ) filter ).getAttribute() );

        // Check the encoding
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x5F, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());
            assertEquals( decodedPdu, encodedPdu );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    // Defensive tests
    /**
     * Test the decoding of a SearchRequest with an empty body
     */
    @Test
    public void testDecodeSearchRequestEmptyBody()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x05, 0x02, 0x01, 0x04, // messageID
                0x63, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with an empty baseDN and nothing more
     */
    @Test
    public void testDecodeSearchRequestBaseDnOnly()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x07, 0x02, 0x01, 0x04, // messageID
                0x63, 0x02, 0x04, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with no controls. The search filter
     * is : (&(|(objectclass=top)(ou=contacts))(!(objectclass=ttt)))
     */
    @Test
    public void testDecodeSearchRequestEmptyBaseDnNoControls()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x6F );
        stream.put( new byte[]
            { 0x30, 0x6D, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01, 0x01, // messageID MessageID
                0x63, 0x68, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04, 0x00, // baseObject LDAPDN,
                0x0A, 0x01, 0x01, // scope ENUMERATED {
                // baseObject (0),
                // singleLevel (1),
                // wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                // neverDerefAliases (0),
                // derefInSearching (1),
                // derefFindingBaseObj (2),
                // derefAlways (3) },
                0x02, 0x02, 0x03, ( byte ) 0xE8, // sizeLimit INTEGER (0 .. maxInt), (1000)
                0x02, 0x02, 0x03, ( byte ) 0xE8, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF, // typesOnly  BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x3C, // Filter ::= CHOICE {
                // and [0] SET OF Filter,
                ( byte ) 0xA1, 0x24, // or [1] SET of Filter,
                ( byte ) 0xA3, 0x12, // equalityMatch [3]
                // Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 'o', 'p', ( byte ) 0xA3, 0x0E, // equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x02, 'o', 'u', // attributeDesc AttributeDescription (LDAPString),
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x08, 'c', 'o', 'n', 't', 'a', 'c', 't', 's', ( byte ) 0xA2, 0x14, // not [2] Filter,
                ( byte ) 0xA3, 0x12, // equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 't', 't',
                // attributes AttributeDescriptionList }
                0x30, 0x15, // AttributeDescriptionList ::= SEQUENCE OF
                // AttributeDescription
                0x04, 0x05, 'a', 't', 't', 'r', '0', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '1', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '2' // AttributeDescription ::= LDAPString
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 1000, searchRequest.getSizeLimit() );
        assertEquals( 1000, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (& (...
        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();

        // (& (| (...
        assertEquals( 2, andNodes.size() );
        OrNode orFilter = ( OrNode ) andNodes.get( 0 );
        assertNotNull( orFilter );

        // (& (| (obectclass=top) (...
        List<ExprNode> orNodes = orFilter.getChildren();
        assertEquals( 2, orNodes.size() );
        
        EqualityNode<?> equalityNode = ( EqualityNode<?> ) orNodes.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "objectclass", equalityNode.getAttribute() );
        assertEquals( "top", equalityNode.getValue().getString() );

        // (& (| (objectclass=top) (ou=contacts) ) (...
        equalityNode = ( EqualityNode<?> ) orNodes.get( 1 );
        assertNotNull( equalityNode );

        assertEquals( "ou", equalityNode.getAttribute() );
        assertEquals( "contacts", equalityNode.getValue().getString() );

        // (& (| (objectclass=top) (ou=contacts) ) (! ...
        NotNode notNode = ( NotNode ) andNodes.get( 1 );
        assertNotNull( notNode );

        // (& (| (objectclass=top) (ou=contacts) ) (! (objectclass=ttt) ) )
        equalityNode = ( EqualityNode<?> ) notNode.getFirstChild();
        assertNotNull( equalityNode );

        assertEquals( "objectclass", equalityNode.getAttribute() );
        assertEquals( "ttt", equalityNode.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();

        for ( String attribute : attributes )
        {
            assertNotNull( attribute );
        }

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x6F, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x6F ), decodedPdu.substring( 0, 0x6F ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest with a bad objectBase
     */
    @Test
    public void testDecodeSearchRequestGlobalBadObjectBase()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x90 );
        stream.put( new byte[]
            { 0x30, ( byte ) 0x81,
                ( byte ) 0x8D, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01,
                0x01, // messageID MessageID
                0x63,
                ( byte ) 0x81,
                ( byte ) 0x87, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', ':', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                // baseObject (0),
                // singleLevel (1),
                // wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                // neverDerefAliases (0),
                // derefInSearching (1),
                // derefFindingBaseObj (2),
                // derefAlways (3) },
                0x02, 0x02, 0x03, ( byte ) 0xE8, // sizeLimit INTEGER (0 .. maxInt), (1000)
                0x02, 0x02, 0x03, ( byte ) 0xE8, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF, // typesOnly  BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x3C, // Filter ::= CHOICE {
                // and [0] SET OF Filter,
                ( byte ) 0xA1, 0x24, // or [1] SET of Filter,
                ( byte ) 0xA3, 0x12, // equalityMatch [3]
                // Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 'o', 'p', ( byte ) 0xA3, 0x0E, // equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x02, 'o', 'u', // attributeDesc AttributeDescription (LDAPString),
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x08, 'c', 'o', 'n', 't', 'a', 'c', 't', 's', ( byte ) 0xA2, 0x14, // not [2] Filter,
                ( byte ) 0xA3, 0x12, // equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 't', 't',
                // attributes AttributeDescriptionList }
                0x30, 0x15, // AttributeDescriptionList ::= SEQUENCE OF
                // AttributeDescription
                0x04, 0x05, 'a', 't', 't', 'r', '0', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '1', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '2' // AttributeDescription ::= LDAPString
            } );

        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( de instanceof ResponseCarryingException );
            Message response = ( ( ResponseCarryingException ) de ).getResponse();
            assertTrue( response instanceof SearchResultDoneImpl );
            assertEquals( ResultCodeEnum.INVALID_DN_SYNTAX, ( ( SearchResultDoneImpl ) response ).getLdapResult()
                .getResultCode() );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with an empty scope
     */
    @Test
    public void testDecodeSearchRequestEmptyScope()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x28, 0x02, 0x01,
                0x04, // messageID
                0x63, 0x23, 0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with a bad scope
     */
    @Test
    public void testDecodeSearchRequestGlobalBadScope()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x90 );
        stream.put( new byte[]
            { 0x30, ( byte ) 0x81,
                ( byte ) 0x8D, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01,
                0x01, // messageID MessageID
                0x63,
                ( byte ) 0x81,
                ( byte ) 0x87, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', ':', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x03, // scope ENUMERATED {
                // baseObject (0),
                // singleLevel (1),
                // wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                // neverDerefAliases (0),
                // derefInSearching (1),
                // derefFindingBaseObj (2),
                // derefAlways (3) },
                0x02, 0x02, 0x03, ( byte ) 0xE8, // sizeLimit INTEGER (0 .. maxInt), (1000)
                0x02, 0x02, 0x03, ( byte ) 0xE8, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF, // typesOnly  BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x3C, // Filter ::= CHOICE {
                // and [0] SET OF Filter,
                ( byte ) 0xA1, 0x24, // or [1] SET of Filter,
                ( byte ) 0xA3, 0x12, // equalityMatch [3]
                // Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 'o', 'p', ( byte ) 0xA3, 0x0E, // equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x02, 'o', 'u', // attributeDesc AttributeDescription (LDAPString),
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x08, 'c', 'o', 'n', 't', 'a', 'c', 't', 's', ( byte ) 0xA2, 0x14, // not [2] Filter,
                ( byte ) 0xA3, 0x12, // equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 't', 't',
                // attributes AttributeDescriptionList }
                0x30, 0x15, // AttributeDescriptionList ::= SEQUENCE OF
                // AttributeDescription
                0x04, 0x05, 'a', 't', 't', 'r', '0', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '1', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '2' // AttributeDescription ::= LDAPString
            } );

        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with an empty derefAlias
     */
    @Test
    public void testDecodeSearchRequestEmptyDerefAlias()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x2B, 0x02, 0x01,
                0x04, // messageID
                0x63, 0x26, 0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x00, 0x0A, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with a bad derefAlias
     */
    @Test
    public void testDecodeSearchRequestGlobalBadDerefAlias()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x90 );
        stream.put( new byte[]
            { 0x30, ( byte ) 0x81,
                ( byte ) 0x8D, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01,
                0x01, // messageID MessageID
                0x63,
                ( byte ) 0x81,
                ( byte ) 0x87, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', ':', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                // baseObject (0),
                // singleLevel (1),
                // wholeSubtree (2) },
                0x0A, 0x01, 0x04, // derefAliases ENUMERATED {
                // neverDerefAliases (0),
                // derefInSearching (1),
                // derefFindingBaseObj (2),
                // derefAlways (3) },
                0x02, 0x02, 0x03, ( byte ) 0xE8, // sizeLimit INTEGER (0 .. maxInt), (1000)
                0x02, 0x02, 0x03, ( byte ) 0xE8, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF, // typesOnly  BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x3C, // Filter ::= CHOICE {
                // and [0] SET OF Filter,
                ( byte ) 0xA1, 0x24, // or [1] SET of Filter,
                ( byte ) 0xA3, 0x12, // equalityMatch [3]
                // Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 'o', 'p', ( byte ) 0xA3, 0x0E, // equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x02, 'o', 'u', // attributeDesc AttributeDescription (LDAPString),
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x08, 'c', 'o', 'n', 't', 'a', 'c', 't', 's', ( byte ) 0xA2, 0x14, // not [2] Filter,
                ( byte ) 0xA3, 0x12, // equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 't', 't',
                // attributes AttributeDescriptionList }
                0x30, 0x15, // AttributeDescriptionList ::= SEQUENCE OF
                // AttributeDescription
                0x04, 0x05, 'a', 't', 't', 'r', '0', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '1', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '2' // AttributeDescription ::= LDAPString
            } );

        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with an empty size limit
     */
    @Test
    public void testDecodeSearchRequestEmptySizeLimit()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x2E, 0x02, 0x01,
                0x04, // messageID
                0x63, 0x29, 0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x00, 0x0A, 0x01, 0x00, 0x02, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with a bad sizeLimit
     */
    @Test
    public void testDecodeSearchRequestGlobalBadSizeLimit()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x8F );
        stream.put( new byte[]
            { 0x30, ( byte ) 0x81,
                ( byte ) 0x8C, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01,
                0x01, // messageID MessageID
                0x63,
                ( byte ) 0x81,
                ( byte ) 0x86, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', ':', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                // baseObject (0),
                // singleLevel (1),
                // wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                // neverDerefAliases (0),
                // derefInSearching (1),
                // derefFindingBaseObj (2),
                // derefAlways (3) },
                0x02, 0x01, ( byte ) 0xFF, // sizeLimit INTEGER (0 .. maxInt), (1000)
                0x02, 0x02, 0x03, ( byte ) 0xE8, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF, // typesOnly  BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x3C, // Filter ::= CHOICE {
                // and [0] SET OF Filter,
                ( byte ) 0xA1, 0x24, // or [1] SET of Filter,
                ( byte ) 0xA3, 0x12, // equalityMatch [3]
                // Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 'o', 'p', ( byte ) 0xA3, 0x0E, // equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x02, 'o', 'u', // attributeDesc AttributeDescription (LDAPString),
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x08, 'c', 'o', 'n', 't', 'a', 'c', 't', 's', ( byte ) 0xA2, 0x14, // not [2] Filter,
                ( byte ) 0xA3, 0x12, // equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 't', 't',
                // attributes AttributeDescriptionList }
                0x30, 0x15, // AttributeDescriptionList ::= SEQUENCE OF
                // AttributeDescription
                0x04, 0x05, 'a', 't', 't', 'r', '0', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '1', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '2' // AttributeDescription ::= LDAPString
            } );

        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with an empty time limit
     */
    @Test
    public void testDecodeSearchRequestEmptyTimeLimit()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x31, 0x02,
                0x01,
                0x04, // messageID
                0x63, 0x2C,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x00, 0x0A, 0x01, 0x00, 0x02, 0x01,
                0x00, 0x02, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with a bad timeLimit
     */
    @Test
    public void testDecodeSearchRequestGlobalBadTimeLimit()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x8F );
        stream.put( new byte[]
            { 0x30, ( byte ) 0x81,
                ( byte ) 0x8C, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01,
                0x01, // messageID MessageID
                0x63,
                ( byte ) 0x81,
                ( byte ) 0x86, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', ':', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                // baseObject (0),
                // singleLevel (1),
                // wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                // neverDerefAliases (0),
                // derefInSearching (1),
                // derefFindingBaseObj (2),
                // derefAlways (3) },
                0x02, 0x02, 0x03, ( byte ) 0xE8, // sizeLimit INTEGER (0 .. maxInt), (1000)
                0x02, 0x01, ( byte ) 0xFF, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF, // typesOnly  BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x3C, // Filter ::= CHOICE {
                // and [0] SET OF Filter,
                ( byte ) 0xA1, 0x24, // or [1] SET of Filter,
                ( byte ) 0xA3, 0x12, // equalityMatch [3]
                // Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 'o', 'p', ( byte ) 0xA3, 0x0E, // equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x02, 'o', 'u', // attributeDesc AttributeDescription (LDAPString),
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x08, 'c', 'o', 'n', 't', 'a', 'c', 't', 's', ( byte ) 0xA2, 0x14, // not [2] Filter,
                ( byte ) 0xA3, 0x12, // equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                // attributeDesc AttributeDescription (LDAPString),
                0x04, 0x0B, 'o', 'b', 'j', 'e', 'c', 't', 'c', 'l', 'a', 's', 's',
                // assertionValue AssertionValue (OCTET STRING) }
                0x04, 0x03, 't', 't', 't',
                // attributes AttributeDescriptionList }
                0x30, 0x15, // AttributeDescriptionList ::= SEQUENCE OF
                // AttributeDescription
                0x04, 0x05, 'a', 't', 't', 'r', '0', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '1', // AttributeDescription ::= LDAPString
                0x04, 0x05, 'a', 't', 't', 'r', '2' // AttributeDescription ::= LDAPString
            } );

        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with an empty filter
     */
    @Test
    public void testDecodeSearchRequestEmptyTypeOnly()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x34, 0x02,
                0x01,
                0x04, // messageID
                0x63, 0x2F,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x00, 0x0A, 0x01, 0x00, 0x02, 0x01,
                0x00, 0x02, 0x01, 0x00, 0x01, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with an empty filter
     */
    @Test
    public void testDecodeSearchRequestEmptyFilter()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x37, 0x02,
                0x01,
                0x04, // messageID
                0x63, 0x32,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x00, 0x0A, 0x01, 0x00, 0x02, 0x01,
                0x00, 0x02, 0x01, 0x00, 0x01, 0x01, ( byte ) 0xFF, ( byte ) 0xA0, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with an empty Present filter
     */
    @Test
    public void testDecodeSearchRequestEmptyPresentFilter()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x37, 0x02,
                0x01,
                0x04, // messageID
                0x63, 0x32,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x00, 0x0A, 0x01, 0x00, 0x02, 0x01,
                0x00, 0x02, 0x01, 0x00, 0x01, 0x01, ( byte ) 0xFF, ( byte ) 0x87, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with an empty equalityMatch filter
     */
    @Test
    public void testDecodeSearchRequestEmptyEqualityMatchFilter()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x37, 0x02,
                0x01,
                0x04, // messageID
                0x63, 0x32,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x00, 0x0A, 0x01, 0x00, 0x02, 0x01,
                0x00, 0x02, 0x01, 0x00, 0x01, 0x01, ( byte ) 0xFF, ( byte ) 0xA3, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with an empty greaterOrEqual filter
     */
    @Test
    public void testDecodeSearchRequestEmptyGreaterOrEqualFilter()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x37, 0x02,
                0x01,
                0x04, // messageID
                0x63, 0x32,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x00, 0x0A, 0x01, 0x00, 0x02, 0x01,
                0x00, 0x02, 0x01, 0x00, 0x01, 0x01, ( byte ) 0xFF, ( byte ) 0xA5, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with an empty lessOrEqual filter
     */
    @Test
    public void testDecodeSearchRequestEmptyLessOrEqualFilter()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x37, 0x02,
                0x01,
                0x04, // messageID
                0x63, 0x32,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x00, 0x0A, 0x01, 0x00, 0x02, 0x01,
                0x00, 0x02, 0x01, 0x00, 0x01, 0x01, ( byte ) 0xFF, ( byte ) 0xA6, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with an approxMatch filter
     */
    @Test
    public void testDecodeSearchRequestEmptyApproxMatchFilter()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x37, 0x02,
                0x01,
                0x04, // messageID
                0x63, 0x32,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x00, 0x0A, 0x01, 0x00, 0x02, 0x01,
                0x00, 0x02, 0x01, 0x00, 0x01, 0x01, ( byte ) 0xFF, ( byte ) 0xA8, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with a greaterOrEqual filter and an
     * empty attributeDesc
     */
    @Test
    public void testDecodeSearchRequestEmptyGreaterOrEqualEmptyAttrDesc()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x39, 0x02,
                0x01,
                0x04, // messageID
                0x63, 0x34,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x00, 0x0A, 0x01, 0x00, 0x02, 0x01,
                0x00, 0x02, 0x01, 0x00, 0x01, 0x01, ( byte ) 0xFF, ( byte ) 0xA5, 0x02, 0x04, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with a greaterOrEqual filter and an
     * empty attributeValue, and an empty attribute List
     */
    @Test
    public void testDecodeSearchRequestEmptyGreaterOrEqualEmptyAttrValue()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x41,
                0x02,
                0x01,
                0x04, // messageID
                0x63,
                0x3C,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x01, 0x0A, 0x01, 0x03, 0x02, 0x01,
                0x00, 0x02, 0x01, 0x00, 0x01, 0x01, ( byte ) 0xFF, ( byte ) 0xA5, 0x08, 0x04, 0x04, 't', 'e', 's', 't',
                0x04, 0x00, 0x30, 0x00 // AttributeDescriptionList ::= SEQUENCE
            // OF AttributeDescription
            };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 4, searchRequest.getMessageId() );
        assertEquals( "uid=akarasulu,dc=example,dc=com", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // >=
        GreaterEqNode<?> greaterOrEqual = (GreaterEqNode<?>)searchRequest.getFilter();

        assertNotNull( greaterOrEqual );

        assertEquals( "test", greaterOrEqual.getAttribute() );
        assertEquals( "", greaterOrEqual.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();

        assertEquals( 0, attributes.size() );

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x43, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu, decodedPdu );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest with a greaterOrEqual filter and an
     * empty attributeValue, and an '*' attribute List
     */
    @Test
    public void testDecodeSearchRequestEmptyGreaterOrEqualEmptyAttrValueStar()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x44,
                0x02,
                0x01,
                0x04, // messageID
                0x63,
                0x3F,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x01, 0x0A, 0x01, 0x03, 0x02, 0x01,
                0x00, 0x02, 0x01, 0x00, 0x01, 0x01, ( byte ) 0xFF, ( byte ) 0xA5, 0x08, 0x04, 0x04, 't', 'e', 's', 't',
                0x04, 0x00, 0x30, 0x03, // AttributeDescriptionList ::= SEQUENCE
                // OF AttributeDescription
                0x04, 0x01, '*' };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 4, searchRequest.getMessageId() );
        assertEquals( "uid=akarasulu,dc=example,dc=com", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // >=
        GreaterEqNode<?> greaterOrEqual = (GreaterEqNode<?>)searchRequest.getFilter();

        assertNotNull( greaterOrEqual );

        assertEquals( "test", greaterOrEqual.getAttribute() );
        assertEquals( "", greaterOrEqual.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();

        assertEquals( 1, attributes.size() );
        assertEquals( "*", attributes.get( 0 ) );

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x46, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu, decodedPdu );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest with a greaterOrEqual filter and an
     * empty attributeValue, and an empty attribute List
     */
    @Test
    public void testDecodeSearchRequestEmptyGreaterOrEqualEmptyAttrValueEmpty()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x43,
                0x02,
                0x01,
                0x04, // messageID
                0x63,
                0x3E,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x01, 0x0A, 0x01, 0x03, 0x02, 0x01,
                0x00, 0x02, 0x01, 0x00, 0x01, 0x01, ( byte ) 0xFF, ( byte ) 0xA5, 0x08, 0x04, 0x04, 't', 'e', 's', 't',
                0x04, 0x00, 0x30, 0x02, // AttributeDescriptionList ::= SEQUENCE
                // OF AttributeDescription
                0x04, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 4, searchRequest.getMessageId() );
        assertEquals( "uid=akarasulu,dc=example,dc=com", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // >=
        GreaterEqNode<?> greaterOrEqual = (GreaterEqNode<?>)searchRequest.getFilter();

        assertNotNull( greaterOrEqual );

        assertEquals( "test", greaterOrEqual.getAttribute() );
        assertEquals( "", greaterOrEqual.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();

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


    /**
     * Test the decoding of a SearchRequest with an empty And filter
     */
    @Test
    public void testDecodeSearchRequestEmptyAndFilter()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x3B, 0x02,
                0x01,
                0x04, // messageID
                0x63, 0x36,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x01, 0x0A, 0x01, 0x03, 0x02, 0x01,
                0x00, 0x02, 0x01, 0x00, 0x01, 0x01, ( byte ) 0xFF, ( byte ) 0xA0, 0x00, 0x30, 0x02, // AttributeDescriptionList
                // ::=
                // SEQUENCE
                // OF
                // AttributeDescription
                0x04, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with an empty Or filter
     */
    @Test
    public void testDecodeSearchRequestEmptyOrFilter()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x3B, 0x02,
                0x01,
                0x04, // messageID
                0x63, 0x36,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x01, 0x0A, 0x01, 0x03, 0x02, 0x01,
                0x00, 0x02, 0x01, 0x00, 0x01, 0x01, ( byte ) 0xFF, ( byte ) 0xA1, 0x00, 0x30, 0x02, // AttributeDescriptionList
                // ::=
                // SEQUENCE
                // OF
                // AttributeDescription
                0x04, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with an empty Not filter
     */
    @Test
    public void testDecodeSearchRequestEmptyNotFilter()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x3B, 0x02,
                0x01,
                0x04, // messageID
                0x63, 0x36,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x01, 0x0A, 0x01, 0x03, 0x02, 0x01,
                0x00, 0x02, 0x01, 0x00, 0x01, 0x01, ( byte ) 0xFF, ( byte ) 0xA2, 0x00, 0x30, 0x02, // AttributeDescriptionList
                // ::=
                // SEQUENCE
                // OF
                // AttributeDescription
                0x04, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with a Not filter and an empty And
     * filter
     */
    @Test
    public void testDecodeSearchRequestNotFilterEmptyAndFilter()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x3D,
                0x02,
                0x01,
                0x04, // messageID
                0x63,
                0x38,
                0x04,
                0x1F, // baseObject LDAPDN,
                'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
                'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm', 0x0A, 0x01, 0x01, 0x0A, 0x01, 0x03, 0x02, 0x01,
                0x00, 0x02, 0x01, 0x00, 0x01, 0x01, ( byte ) 0xFF, ( byte ) 0xA2, 0x02, ( byte ) 0xA0, 0x00, 0x30,
                0x02, // AttributeDescriptionList ::= SEQUENCE OF
                // AttributeDescription
                0x04, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            assertTrue( true );
            return;
        }

        fail( "We should not reach this point" );
    }


    /**
     * Test the decoding of a SearchRequest with a greaterOrEqual filter and an
     * empty attributeValue, and an '*' attribute List
     */
    @Test
    public void testDecodeSearchRequestDIRSERVER_651()
    {
        byte[] asn1BER = new byte[]
            { 0x30, 0x60, 0x02, 0x01, 0x02, 0x63, 0x5b, 0x04, 0x0a, 'd', 'c', '=', 'p', 'g', 'p', 'k', 'e', 'y', 's',
                0x0a, 01, 02, 0x0a, 01, 00, 0x02, 01, 00, 0x02, 01, 00, 0x01, 01, 00, ( byte ) 0xa0, 0x3c,
                ( byte ) 0xa4, 0x28, 0x04, 0x09, 'p', 'g', 'p', 'u', 's', 'e', 'r', 'i', 'd', 0x30, 0x1b,
                ( byte ) 0x80, 0x19, 'v', 'g', 'j', 'o', 'k', 'j', 'e', 'v', '@', 'n', 'e', 't', 'c', 'e', 't', 'e',
                'r', 'a', '.', 'c', 'o', 'm', '.', 'm', 'k', ( byte ) 0xa3, 0x10, 0x04, 0x0b, 'p', 'g', 'p', 'd', 'i',
                's', 'a', 'b', 'l', 'e', 'd', 0x04, 0x01, '0', 0x30, 0x00 };

        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( asn1BER.length );
        stream.put( asn1BER );
        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        // Decode a SearchRequest message
        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 2, searchRequest.getMessageId() );
        assertEquals( "dc=pgpkeys", searchRequest.getBase().toString() );
        assertEquals( SearchScope.SUBTREE, searchRequest.getScope() );
        assertEquals( AliasDerefMode.NEVER_DEREF_ALIASES, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( false, searchRequest.getTypesOnly() );

        // And 
        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();
        assertEquals( 2, andNodes.size() );

        SubstringNode substringNode = ( SubstringNode ) andNodes.get( 0 );
        assertNotNull( substringNode );

        assertEquals( "pgpuserid", substringNode.getAttribute() );
        assertEquals( "vgjokjev@netcetera.com.mk", substringNode.getInitial() );
        assertEquals( 0, substringNode.getAny().size() );
        assertEquals( null, substringNode.getFinal() );

        EqualityNode<?> equalityNode = ( EqualityNode<?> ) andNodes.get( 1 );
        assertNotNull( equalityNode );

        assertEquals( "pgpdisabled", equalityNode.getAttribute() );
        assertEquals( "0", equalityNode.getValue().getString() );

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x62, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu, decodedPdu );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest
     * (a=b)
     */
    @Test
    public void testDecodeSearchRequestEq()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x25 );
        stream.put( new byte[]
            { 0x30, 0x23, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01, 0x01, // messageID MessageID
                0x63, 0x1E, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04, 0x03, // baseObject LDAPDN,
                'a', '=', 'b', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                //      baseObject (0),
                //      singleLevel (1),
                //      wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                //      neverDerefAliases (0),
                //      derefInSearching (1),
                //      derefFindingBaseObj (2),
                //      derefAlways (3) },
                0x02, 0x01, 0x00, // sizeLimit INTEGER (0 .. maxInt), (0)
                0x02, 0x01, 0x00, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF,// typesOnly BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA3, 0x06, // Filter ::= CHOICE {
                //      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'a', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'b', //      assertionValue AssertionValue (OCTET STRING) } 
                // attributes AttributeDescriptionList }
                0x30, 0x00, // AttributeDescriptionList ::= SEQUENCE OF AttributeDescription
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "a=b", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (a=b)
        EqualityNode<?> equalityNode = (EqualityNode<?>)searchRequest.getFilter();

        assertNotNull( equalityNode );

        assertEquals( "a", equalityNode.getAttribute() );
        assertEquals( "b", equalityNode.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();
        assertEquals( 0, attributes.size() );

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x25, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x25 ), decodedPdu.substring( 0, 0x25 ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest
     * (&(a=b))
     */
    @Test
    public void testDecodeSearchRequestAndEq()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x27 );
        stream.put( new byte[]
            { 0x30, 0x25, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01, 0x01, // messageID MessageID
                0x63, 0x20, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04, 0x03, // baseObject LDAPDN,
                'a', '=', 'b', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                //      baseObject (0),
                //      singleLevel (1),
                //      wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                //      neverDerefAliases (0),
                //      derefInSearching (1),
                //      derefFindingBaseObj (2),
                //      derefAlways (3) },
                0x02, 0x01, 0x00, // sizeLimit INTEGER (0 .. maxInt), (0)
                0x02, 0x01, 0x00, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF,// typesOnly BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x08, // Filter ::= CHOICE {
                ( byte ) 0xA3, 0x06,
                //      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'a', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'b', //      assertionValue AssertionValue (OCTET STRING) } 
                // attributes AttributeDescriptionList }
                0x30, 0x00, // AttributeDescriptionList ::= SEQUENCE OF AttributeDescription
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "a=b", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (&(...
        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();
        assertEquals( 1, andNodes.size() );

        // (&(a=b))
        EqualityNode<?> equalityNode = (EqualityNode<?>)andNodes.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "a", equalityNode.getAttribute() );
        assertEquals( "b", equalityNode.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();
        assertEquals( 0, attributes.size() );

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x27, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x27 ), decodedPdu.substring( 0, 0x27 ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest
     * (&(a=b)(c=d))
     */
    @Test
    public void testDecodeSearchRequestAndEqEq()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x2F );
        stream.put( new byte[]
            { 0x30, 0x2D, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01, 0x01, // messageID MessageID
                0x63, 0x28, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04, 0x03, // baseObject LDAPDN,
                'a', '=', 'b', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                //      baseObject (0),
                //      singleLevel (1),
                //      wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                //      neverDerefAliases (0),
                //      derefInSearching (1),
                //      derefFindingBaseObj (2),
                //      derefAlways (3) },
                0x02, 0x01, 0x00, // sizeLimit INTEGER (0 .. maxInt), (0)
                0x02, 0x01, 0x00, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF,// typesOnly BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x10, // Filter ::= CHOICE {
                ( byte ) 0xA3, 0x06,
                //      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'a', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'b', //      assertionValue AssertionValue (OCTET STRING) } 
                ( byte ) 0xA3, 0x06,
                //      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'c', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'd', //      assertionValue AssertionValue (OCTET STRING) } 
                // attributes AttributeDescriptionList }
                0x30, 0x00, // AttributeDescriptionList ::= SEQUENCE OF AttributeDescription
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "a=b", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (&(...
        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();
        assertEquals( 2, andNodes.size() );

        // (&(a=b)...
        EqualityNode<?> equalityNode = (EqualityNode<?>)andNodes.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "a", equalityNode.getAttribute() );
        assertEquals( "b", equalityNode.getValue().getString() );

        // (&(a=b)(c=d))
        equalityNode = ( EqualityNode<?> ) andNodes.get( 1 );
        assertNotNull( equalityNode );

        assertEquals( "c", equalityNode.getAttribute() );
        assertEquals( "d", equalityNode.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();
        assertEquals( 0, attributes.size() );

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x2F, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x2F ), decodedPdu.substring( 0, 0x2F ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest
     * (&(&(a=b))
     */
    @Test
    public void testDecodeSearchRequestAndAndEq()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x29 );
        stream.put( new byte[]
            { 0x30, 0x27, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01, 0x01, // messageID MessageID
                0x63, 0x22, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04, 0x03, // baseObject LDAPDN,
                'a', '=', 'b', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                //      baseObject (0),
                //      singleLevel (1),
                //      wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                //      neverDerefAliases (0),
                //      derefInSearching (1),
                //      derefFindingBaseObj (2),
                //      derefAlways (3) },
                0x02, 0x01, 0x00, // sizeLimit INTEGER (0 .. maxInt), (0)
                0x02, 0x01, 0x00, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF,// typesOnly BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x0A, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA0, 0x08, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA3, 0x06,//      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'a', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'b', //      assertionValue AssertionValue (OCTET STRING) } 
                0x30, 0x00, // AttributeDescriptionList ::= SEQUENCE OF AttributeDescription
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "a=b", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (&(...
        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();
        assertEquals( 1, andNodes.size() );

        // (&(&(..
        AndNode andNode2 = ( AndNode ) andNodes.get( 0 );
        assertNotNull( andNode2 );

        List<ExprNode> andNodes2 = andNode2.getChildren();
        assertEquals( 1, andNodes2.size() );

        // (&(&(a=b)))
        EqualityNode<?> equalityNode = ( EqualityNode<?> ) andNodes2.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "a", equalityNode.getAttribute() );
        assertEquals( "b", equalityNode.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();
        assertEquals( 0, attributes.size() );

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x29, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x29 ), decodedPdu.substring( 0, 0x29 ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest
     * (&(&(a=b)(c=d))
     */
    @Test
    public void testDecodeSearchRequestAndAndEqEq()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x31 );
        stream.put( new byte[]
            { 0x30, 0x2F, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01, 0x01, // messageID MessageID
                0x63, 0x2A, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04, 0x03, // baseObject LDAPDN,
                'a', '=', 'b', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                //      baseObject (0),
                //      singleLevel (1),
                //      wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                //      neverDerefAliases (0),
                //      derefInSearching (1),
                //      derefFindingBaseObj (2),
                //      derefAlways (3) },
                0x02, 0x01, 0x00, // sizeLimit INTEGER (0 .. maxInt), (0)
                0x02, 0x01, 0x00, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF,// typesOnly BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x12, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA0, 0x10, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA3, 0x06,
                //      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'a', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'b', //      assertionValue AssertionValue (OCTET STRING) } 
                ( byte ) 0xA3, 0x06,
                //      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'c', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'd', //      assertionValue AssertionValue (OCTET STRING) } 
                0x30, 0x00, // AttributeDescriptionList ::= SEQUENCE OF AttributeDescription
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "a=b", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (&(...
        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();
        assertEquals( 1, andNodes.size() );

        // (&(&(..
        AndNode andNode2 = ( AndNode ) andNodes.get( 0 );
        assertNotNull( andNode2 );

        List<ExprNode> andNodes2 = andNode2.getChildren();
        assertEquals( 2, andNodes2.size() );

        // (&(&(a=b)...
        EqualityNode<?> equalityNode = ( EqualityNode<?> ) andNodes2.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "a", equalityNode.getAttribute() );
        assertEquals( "b", equalityNode.getValue().getString() );

        // (&(&(a=b)(c=d)
        equalityNode = ( EqualityNode<?> ) andNodes2.get( 1 );
        assertNotNull( equalityNode );

        assertEquals( "c", equalityNode.getAttribute() );
        assertEquals( "d", equalityNode.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();
        assertEquals( 0, attributes.size() );

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x31, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x31 ), decodedPdu.substring( 0, 0x31 ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest
     * (&(&(a=b))(c=d))
     */
    @Test
    public void testDecodeSearchRequestAnd_AndEq_Eq()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x31 );
        stream.put( new byte[]
            { 0x30, 0x2F, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01, 0x01, // messageID MessageID
                0x63, 0x2A, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04, 0x03, // baseObject LDAPDN,
                'a', '=', 'b', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                //      baseObject (0),
                //      singleLevel (1),
                //      wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                //      neverDerefAliases (0),
                //      derefInSearching (1),
                //      derefFindingBaseObj (2),
                //      derefAlways (3) },
                0x02, 0x01, 0x00, // sizeLimit INTEGER (0 .. maxInt), (0)
                0x02, 0x01, 0x00, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF,// typesOnly BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x12, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA0, 0x08, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA3, 0x06,//      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'a', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'b', //      assertionValue AssertionValue (OCTET STRING) } 
                ( byte ) 0xA3, 0x06, //      equalityMatch [3] Assertion,
                //      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'c', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'd', //      assertionValue AssertionValue (OCTET STRING) } 
                0x30, 0x00, // AttributeDescriptionList ::= SEQUENCE OF AttributeDescription
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "a=b", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (&(...
        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();
        assertEquals( 2, andNodes.size() );

        // (&(&(..
        AndNode andNode2 = ( AndNode ) andNodes.get( 0 );
        assertNotNull( andNode2 );

        List<ExprNode> andNodes2 = andNode2.getChildren();
        assertEquals( 1, andNodes2.size() );

        // (&(&(a=b))...
        EqualityNode<?> equalityNode = ( EqualityNode<?> ) andNodes2.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "a", equalityNode.getAttribute() );
        assertEquals( "b", equalityNode.getValue().getString() );

        // (&(&(a=b))(c=d))
        equalityNode = ( EqualityNode<?> ) andNodes.get( 1 );
        assertNotNull( equalityNode );

        assertEquals( "c", equalityNode.getAttribute() );
        assertEquals( "d", equalityNode.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();
        assertEquals( 0, attributes.size() );

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x31, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x31 ), decodedPdu.substring( 0, 0x31 ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest
     * (&(&(a=b)(c=d))(e=f))
     */
    @Test
    public void testDecodeSearchRequestAnd_AndEqEq_Eq()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x39 );
        stream.put( new byte[]
            { 0x30, 0x37, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01, 0x01, // messageID MessageID
                0x63, 0x32, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04, 0x03, // baseObject LDAPDN,
                'a', '=', 'b', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                //      baseObject (0),
                //      singleLevel (1),
                //      wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                //      neverDerefAliases (0),
                //      derefInSearching (1),
                //      derefFindingBaseObj (2),
                //      derefAlways (3) },
                0x02, 0x01, 0x00, // sizeLimit INTEGER (0 .. maxInt), (0)
                0x02, 0x01, 0x00, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF,// typesOnly BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x1A, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA0, 0x10, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA3, 0x06,//      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'a', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'b', //      assertionValue AssertionValue (OCTET STRING) } 
                ( byte ) 0xA3, 0x06,//      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'c', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'd', //      assertionValue AssertionValue (OCTET STRING) } 
                ( byte ) 0xA3, 0x06, //      equalityMatch [3] Assertion,
                //      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'e', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'f', //      assertionValue AssertionValue (OCTET STRING) } 
                0x30, 0x00, // AttributeDescriptionList ::= SEQUENCE OF AttributeDescription
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "a=b", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (&(...
        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();
        assertEquals( 2, andNodes.size() );

        // (&(&(..
        AndNode andNode2 = ( AndNode ) andNodes.get( 0 );
        assertNotNull( andNode2 );

        List<ExprNode> andNodes2 = andNode2.getChildren();
        assertEquals( 2, andNodes2.size() );

        // (&(&(a=b)...
        EqualityNode<?> equalityNode = ( EqualityNode<?> ) andNodes2.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "a", equalityNode.getAttribute() );
        assertEquals( "b", equalityNode.getValue().getString() );

        // (&(&(a=b)(c=d)...
        equalityNode = ( EqualityNode<?> ) andNodes2.get( 1 );
        assertNotNull( equalityNode );

        assertEquals( "c", equalityNode.getAttribute() );
        assertEquals( "d", equalityNode.getValue().getString() );

        // (&(&(a=b)(c=d))(e=f))
        equalityNode = ( EqualityNode<?> ) andNodes.get( 1 );
        assertNotNull( equalityNode );


        assertEquals( "e", equalityNode.getAttribute() );
        assertEquals( "f", equalityNode.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();
        assertEquals( 0, attributes.size() );

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x39, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x39 ), decodedPdu.substring( 0, 0x39 ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest
     * (&(a=b)(|(a=b)(c=d)))
     */
    @Test
    public void testDecodeSearchRequestAndEq_OrEqEq()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x39 );
        stream.put( new byte[]
            { 0x30, 0x37, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01, 0x01, // messageID MessageID
                0x63, 0x32, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04, 0x03, // baseObject LDAPDN,
                'a', '=', 'b', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                //      baseObject (0),
                //      singleLevel (1),
                //      wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                //      neverDerefAliases (0),
                //      derefInSearching (1),
                //      derefFindingBaseObj (2),
                //      derefAlways (3) },
                0x02, 0x01, 0x00, // sizeLimit INTEGER (0 .. maxInt), (0)
                0x02, 0x01, 0x00, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF,// typesOnly BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x1A, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA3, 0x06, //      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'a', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'b', //      assertionValue AssertionValue (OCTET STRING) } 
                ( byte ) 0xA1, 0x10, // Filter ::= CHOICE { or             [1] SET OF Filter,
                ( byte ) 0xA3, 0x06,//      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'c', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'd', //      assertionValue AssertionValue (OCTET STRING) } 
                ( byte ) 0xA3, 0x06,//      equalityMatch [3] Assertion,
                //      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'e', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'f', //      assertionValue AssertionValue (OCTET STRING) } 
                0x30, 0x00, // AttributeDescriptionList ::= SEQUENCE OF AttributeDescription
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "a=b", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (&(...
        ExprNode exprNode = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) exprNode;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();
        assertEquals( 2, andNodes.size() );

        // (&(a=b)..
        EqualityNode<?> equalityNode = ( EqualityNode<?> ) andNodes.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "a", equalityNode.getAttribute() );
        assertEquals( "b", equalityNode.getValue().getString() );

        // (&(a=b)(|(...
        OrNode orNode = ( OrNode ) andNodes.get( 1 );
        assertNotNull( orNode );

        List<ExprNode> orNodes = orNode.getChildren();
        assertEquals( 2, orNodes.size() );

        // (&(a=b)(|(c=d)...
        equalityNode = ( EqualityNode<?> ) orNodes.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "c", equalityNode.getAttribute() );
        assertEquals( "d", equalityNode.getValue().getString() );

        // (&(a=b)(|(c=d)(e=f)))
        equalityNode = ( EqualityNode<?> ) orNodes.get( 1 );
        assertNotNull( equalityNode );

        assertEquals( "e", equalityNode.getAttribute() );
        assertEquals( "f", equalityNode.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();
        assertEquals( 0, attributes.size() );

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x39, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x39 ), decodedPdu.substring( 0, 0x39 ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest
     * (&(&(a=b))(&(c=d)))
     */
    @Test
    public void testDecodeSearchRequestAnd_AndEq_AndEq()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x33 );
        stream.put( new byte[]
            { 0x30, 0x31, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01, 0x01, // messageID MessageID
                0x63, 0x2C, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04, 0x03, // baseObject LDAPDN,
                'a', '=', 'b', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                //      baseObject (0),
                //      singleLevel (1),
                //      wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                //      neverDerefAliases (0),
                //      derefInSearching (1),
                //      derefFindingBaseObj (2),
                //      derefAlways (3) },
                0x02, 0x01, 0x00, // sizeLimit INTEGER (0 .. maxInt), (0)
                0x02, 0x01, 0x00, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF,// typesOnly BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x14, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA0, 0x08, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA3, 0x06,//      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'a', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'b', //      assertionValue AssertionValue (OCTET STRING) } 
                ( byte ) 0xA0, 0x08, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA3, 0x06,//      equalityMatch [3] Assertion,
                //      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'c', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'd', //      assertionValue AssertionValue (OCTET STRING) } 
                0x30, 0x00 // AttributeDescriptionList ::= SEQUENCE OF AttributeDescription
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "a=b", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (&(...
        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();
        assertEquals( 2, andNodes.size() );

        // (&(&(..
        AndNode andNode2 = ( AndNode ) andNodes.get( 0 );
        assertNotNull( andNode2 );

        List<ExprNode> andNodes2 = andNode2.getChildren();
        assertEquals( 1, andNodes2.size() );

        // (&(&(a=b)...
        EqualityNode<?> equalityNode = ( EqualityNode<?> ) andNodes2.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "a", equalityNode.getAttribute() );
        assertEquals( "b", equalityNode.getValue().getString() );

        // (&(&(a=b))(&...
        andNode2 = ( AndNode ) andNodes.get( 1 );
        assertNotNull( andNode2 );

        andNodes2 = andNode2.getChildren();
        assertEquals( 1, andNodes2.size() );

        // (&(&(a=b))(&(c=d)))
        equalityNode = ( EqualityNode<?> ) andNodes2.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "c", equalityNode.getAttribute() );
        assertEquals( "d", equalityNode.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();
        assertEquals( 0, attributes.size() );

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x33, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x33 ), decodedPdu.substring( 0, 0x33 ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest
     * (&(&(a=b)(c=d))(&(e=f)))
     */
    @Test
    public void testDecodeSearchRequestAnd_AndEqEq_AndEq()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x3B );
        stream.put( new byte[]
            { 0x30, 0x39, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01, 0x01, // messageID MessageID
                0x63, 0x34, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04, 0x03, // baseObject LDAPDN,
                'a', '=', 'b', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                //      baseObject (0),
                //      singleLevel (1),
                //      wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                //      neverDerefAliases (0),
                //      derefInSearching (1),
                //      derefFindingBaseObj (2),
                //      derefAlways (3) },
                0x02, 0x01, 0x00, // sizeLimit INTEGER (0 .. maxInt), (0)
                0x02, 0x01, 0x00, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF,// typesOnly BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x1C, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA0, 0x10, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA3, 0x06,//      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'a', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'b', //      assertionValue AssertionValue (OCTET STRING) } 
                ( byte ) 0xA3, 0x06,//      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'c', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'd', //      assertionValue AssertionValue (OCTET STRING) } 
                ( byte ) 0xA0, 0x08, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA3, 0x06,//      equalityMatch [3] Assertion,
                //      equalityMatch [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'e', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'f', //      assertionValue AssertionValue (OCTET STRING) } 
                0x30, 0x00 // AttributeDescriptionList ::= SEQUENCE OF AttributeDescription
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "a=b", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (&(...
        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();
        assertEquals( 2, andNodes.size() );

        // (&(&(..
        AndNode andNode2 = ( AndNode ) andNodes.get( 0 );
        assertNotNull( andNode2 );

        List<ExprNode> andNodes2 = andNode2.getChildren();
        assertEquals( 2, andNodes2.size() );

        // (&(&(a=b)...
        EqualityNode<?> equalityNode = ( EqualityNode<?> ) andNodes2.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "a", equalityNode.getAttribute() );
        assertEquals( "b", equalityNode.getValue().getString() );

        // (&(&(a=b)(c=d))...
        equalityNode = ( EqualityNode<?> ) andNodes2.get( 1 );
        assertNotNull( equalityNode );

        assertEquals( "c", equalityNode.getAttribute() );
        assertEquals( "d", equalityNode.getValue().getString() );

        // (&(&(a=b)(c=d))(&...
        andNode2 = ( AndNode ) andNodes.get( 1 );
        assertNotNull( andNode2 );

        andNodes2 = andNode2.getChildren();
        assertEquals( 1, andNodes2.size() );

        // (&(&(a=b)(c=d))(&(e=f)))
        equalityNode = ( EqualityNode<?> ) andNodes2.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "e", equalityNode.getAttribute() );
        assertEquals( "f", equalityNode.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();
        assertEquals( 0, attributes.size() );

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x3B, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x3B ), decodedPdu.substring( 0, 0x3B ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest
     * (&(|(abcdef=*)(ghijkl=*))(!(e>=f)))
     */
    @Test
    public void testDecodeSearchRequestAnd_OrPrPr_NotGEq()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x3B );
        stream.put( new byte[]
            { 0x30, 0x39, // LDAPMessage ::=SEQUENCE {
                0x02, 0x01, 0x01, // messageID MessageID
                0x63, 0x34, // CHOICE { ...,
                // searchRequest SearchRequest, ...
                // SearchRequest ::= APPLICATION[3] SEQUENCE {
                0x04, 0x03, // baseObject LDAPDN,
                'a', '=', 'b', 0x0A, 0x01, 0x01, // scope ENUMERATED {
                //      baseObject (0),
                //      singleLevel (1),
                //      wholeSubtree (2) },
                0x0A, 0x01, 0x03, // derefAliases ENUMERATED {
                //      neverDerefAliases (0),
                //      derefInSearching (1),
                //      derefFindingBaseObj (2),
                //      derefAlways (3) },
                0x02, 0x01, 0x00, // sizeLimit INTEGER (0 .. maxInt), (0)
                0x02, 0x01, 0x00, // timeLimit INTEGER (0 .. maxInt), (1000) 
                0x01, 0x01, ( byte ) 0xFF,// typesOnly BOOLEAN, (TRUE)
                // filter Filter,
                ( byte ) 0xA0, 0x1C, // Filter ::= CHOICE { and             [0] SET OF Filter,
                ( byte ) 0xA1, 0x10, // Filter ::= CHOICE { or             [0] SET OF Filter,
                ( byte ) 0x87, 0x06,// present [7] AttributeDescription,
                'a', 'b', 'c', // AttributeDescription ::= LDAPString
                'd', 'e', 'f', ( byte ) 0x87, 0x06,// present [7] AttributeDescription,
                'g', 'h', 'i', // AttributeDescription ::= LDAPString
                'j', 'k', 'l', ( byte ) 0xA2, 0x08, // Filter ::= CHOICE { not             Filter,
                ( byte ) 0xA5, 0x06,//      greaterOrEqual [3] Assertion,
                // Assertion ::= SEQUENCE {
                0x04, 0x01, 'e', //      attributeDesc AttributeDescription (LDAPString),
                0x04, 0x01, 'f', //      assertionValue AssertionValue (OCTET STRING) } 
                0x30, 0x00 // AttributeDescriptionList ::= SEQUENCE OF AttributeDescription
            } );

        String decodedPdu = Strings.dumpBytes(stream.array());
        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "a=b", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        // (&(...
        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();
        assertEquals( 2, andNodes.size() );

        // (&(|(..
        OrNode orFilter = ( OrNode ) andNodes.get( 0 );
        assertNotNull( orFilter );

        List<ExprNode> orNodes = orFilter.getChildren();
        assertEquals( 2, orNodes.size() );

        // (&(&(abcdef=*)...
        PresenceNode presenceNode = ( PresenceNode ) orNodes.get( 0 );
        assertNotNull( presenceNode );

        assertEquals( "abcdef", presenceNode.getAttribute() );

        // (&(&(abcdef=*)(ghijkl=*))...
        presenceNode = ( PresenceNode ) orNodes.get( 1 );
        assertNotNull( presenceNode );

        assertEquals( "ghijkl", presenceNode.getAttribute() );

        // (&(&(abcdef=*)(ghijkl=*))(&...
        NotNode notNode = ( NotNode ) andNodes.get( 1 );
        assertNotNull( notNode );

        // (&(&(abcdef=*)(ghijkl=*))(&(e>=f)))
        GreaterEqNode<?> greaterEqNode = ( GreaterEqNode<?> ) notNode.getFirstChild();
        assertNotNull( greaterEqNode );

        assertEquals( "e", greaterEqNode.getAttribute() );
        assertEquals( "f", greaterEqNode.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();
        assertEquals( 0, attributes.size() );

        // Check the encoding
        // We won't check the whole PDU, as it may differs because
        // attributes may have been reordered
        try
        {
            ByteBuffer bb = encoder.encodeMessage( searchRequest );

            // Check the length
            assertEquals( 0x3B, bb.limit() );

            String encodedPdu = Strings.dumpBytes(bb.array());

            assertEquals( encodedPdu.substring( 0, 0x3B ), decodedPdu.substring( 0, 0x3B ) );
        }
        catch ( EncoderException ee )
        {
            ee.printStackTrace();
            fail( ee.getMessage() );
        }
    }


    /**
     * Test the decoding of a SearchRequest
     * for rootDSE
     */
    @Test
    public void testDecodeSearchRequestRootDSE()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x33 );
        stream.put( new byte[]
            { 0x30, ( byte ) 0x84, 0x00, 0x00, 0x00, 0x2D, 0x02, 0x01, 0x01, 0x63, ( byte ) 0x84, 0x00, 0x00, 0x00,
                0x24, 0x04, 0x00, 0x0A, 0x01, 0x00, 0x0A, 0x01, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01,
                0x00, ( byte ) 0x87, 0x0B, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x30,
                ( byte ) 0x84, 0x00, 0x00, 0x00, 0x00 } );

        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 1, searchRequest.getMessageId() );
        assertEquals( "", searchRequest.getBase().toString() );
        assertEquals( SearchScope.OBJECT, searchRequest.getScope() );
        assertEquals( AliasDerefMode.NEVER_DEREF_ALIASES, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( false, searchRequest.getTypesOnly() );

        ExprNode filter = searchRequest.getFilter();

        PresenceNode presenceNode = ( PresenceNode ) filter;
        assertNotNull( presenceNode );
        assertEquals( "objectClass", presenceNode.getAttribute() );

        List<String> attributes = searchRequest.getAttributes();
        assertEquals( 0, attributes.size() );
    }


    /**
     * Test the decoding of a SearchRequest with special length (long form)
     * for rootDSE
     */
    @Test
    public void testDecodeSearchRequestDIRSERVER_810()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x6B );
        stream.put( new byte[]
            { 0x30, ( byte ) 0x84, 0x00, 0x00, 0x00, 0x65, 0x02, 0x01, 0x03, 0x63, ( byte ) 0x84, 0x00, 0x00, 0x00,
                0x5c, 0x04, 0x12, 0x6f, 0x75, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79,
                0x73,
                0x74,
                0x65,
                0x6d, // 'ou=users,ou=system'
                0x0a, 0x01, 0x01, 0x0a, 0x01, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x1e, 0x01, 0x01, ( byte ) 0xff,
                ( byte ) 0xa0, ( byte ) 0x84, 0x00, 0x00, 0x00, 0x2d, ( byte ) 0xa3, ( byte ) 0x84, 0x00, 0x00, 0x00,
                0x0e, 0x04, 0x03, 0x75, 0x69, 0x64, 0x04, 0x07, 0x62, 0x75, 0x73, 0x74, 0x65, 0x72,
                0x20, // 'buster ' (with a space at the end)
                ( byte ) 0xa3, ( byte ) 0x84, 0x00, 0x00, 0x00, 0x13, 0x04, 0x0b, 0x73, 0x62, 0x41, 0x74, 0x74, 0x72,
                0x69, 0x62, 0x75, 0x74, 0x65, // sbAttribute
                0x04, 0x04, 0x42, 0x75, 0x79, 0x20, // 'Buy ' (with a space at the end)
                0x30, ( byte ) 0x84, 0x00, 0x00, 0x00, 0x00 } );

        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 3, searchRequest.getMessageId() );
        assertEquals( "ou=users,ou=system", searchRequest.getBase().toString() );
        assertEquals( SearchScope.ONELEVEL, searchRequest.getScope() );
        assertEquals( AliasDerefMode.NEVER_DEREF_ALIASES, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 30, searchRequest.getTimeLimit() );
        assertEquals( true, searchRequest.getTypesOnly() );

        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();
        assertEquals( 2, andNodes.size() );

        // (&(uid=buster)...
        EqualityNode<?> equalityNode = ( EqualityNode<?> ) andNodes.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "uid", equalityNode.getAttribute() );
        assertEquals( "buster ", equalityNode.getValue().getString() );

        // (&(uid=buster)(sbAttribute=Buy))
        equalityNode = ( EqualityNode<?> ) andNodes.get( 1 );
        assertNotNull( equalityNode );

        assertEquals( "sbAttribute", equalityNode.getAttribute() );
        assertEquals( "Buy ", equalityNode.getValue().getString() );

        List<String> attributes = searchRequest.getAttributes();
        assertEquals( 0, attributes.size() );
    }


    /**
     * Test the decoding of a SearchRequest with a complex filter :
     * (&(objectClass=person)(|(cn=Tori*)(sn=Jagger)))
     */
    @Test
    public void testDecodeSearchRequestComplexFilterWithControl()
    {
        Asn1Decoder ldapDecoder = new Asn1Decoder();

        ByteBuffer stream = ByteBuffer.allocate( 0x77 );
        stream.put( new byte[]
            { 0x30,
                0x75, // LdapMessage
                0x02, 0x01,
                0x06, // message Id = 6
                0x63,
                0x53, // SearchRequest
                0x04,
                0x09, // BasDN 'ou=system'
                0x6F, 0x75, 0x3D, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x0A, 0x01,
                0x02, // scope = SUBTREE
                0x0A, 0x01,
                0x03, // derefAlias = 3
                0x02, 0x01,
                0x00, // sizeLimit = none
                0x02, 0x01,
                0x00, // timeLimit = none
                0x01, 0x01,
                0x00, // types only = false
                ( byte ) 0xA0,
                0x35, // AND
                ( byte ) 0xA3,
                0x15, // equals
                0x04,
                0x0B, // 'objectclass'
                0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x04,
                0x06, // 'person'
                0x70, 0x65, 0x72, 0x73, 0x6F, 0x6E, ( byte ) 0xA1,
                0x1C, // OR
                ( byte ) 0xA4,
                0x0C, // substrings : 'cn=Tori*'
                0x04,
                0x02, // 'cn'
                0x63, 0x6E, 0x30,
                0x06, // initial = 'Tori'
                ( byte ) 0x80, 0x04, 0x54, 0x6F, 0x72, 0x69, ( byte ) 0xA3,
                0x0C, // equals
                0x04,
                0x02, // 'sn'
                0x73, 0x6E, 0x04,
                0x06, // 'Jagger'
                0x4A, 0x61, 0x67, 0x67, 0x65, 0x72, 0x30,
                0x00, // Control
                ( byte ) 0xA0, 0x1B, 0x30, 0x19, 0x04, 0x17, '2', '.', '1', '6', '.', '8', '4', '0', '.', '1', '.',
                '1', '1', '3', '7', '3', '0', '.', '3', '.', '4', '.', '2' } );

        stream.flip();

        // Allocate a BindRequest Container
        LdapMessageContainer<SearchRequestDecorator> ldapMessageContainer = 
            new LdapMessageContainer<SearchRequestDecorator>( codec );

        try
        {
            ldapDecoder.decode( stream, ldapMessageContainer );
        }
        catch ( DecoderException de )
        {
            de.printStackTrace();
            fail( de.getMessage() );
        }

        assertEquals( TLVStateEnum.PDU_DECODED, ldapMessageContainer.getState() );

        SearchRequest searchRequest = ldapMessageContainer.getMessage();

        assertEquals( 6, searchRequest.getMessageId() );
        assertEquals( "ou=system", searchRequest.getBase().toString() );
        assertEquals( SearchScope.SUBTREE, searchRequest.getScope() );
        assertEquals( AliasDerefMode.DEREF_ALWAYS, searchRequest.getDerefAliases() );
        assertEquals( 0, searchRequest.getSizeLimit() );
        assertEquals( 0, searchRequest.getTimeLimit() );
        assertEquals( false, searchRequest.getTypesOnly() );

        // (&(...
        ExprNode filter = searchRequest.getFilter();

        AndNode andNode = ( AndNode ) filter;
        assertNotNull( andNode );

        List<ExprNode> andNodes = andNode.getChildren();
        assertEquals( 2, andNodes.size() );

        // (&(objectClass=person)..
        EqualityNode<?> equalityNode = ( EqualityNode<?> ) andNodes.get( 0 );
        assertNotNull( equalityNode );

        assertEquals( "objectClass", equalityNode.getAttribute() );
        assertEquals( "person", equalityNode.getValue().getString() );

        // (&(a=b)(|
        OrNode orNode = ( OrNode ) andNodes.get( 1 );
        assertNotNull( orNode );

        List<ExprNode> orNodes = orNode.getChildren();
        assertEquals( 2, orNodes.size() );

        // (&(a=b)(|(cn=Tori*
        SubstringNode substringNode = ( SubstringNode ) orNodes.get( 0 );
        assertNotNull( substringNode );

        assertEquals( "cn", substringNode.getAttribute() );
        assertEquals( "Tori", substringNode.getInitial() );
        assertEquals( 0, substringNode.getAny().size() );
        assertEquals( null, substringNode.getFinal() );

        // (&(a=b)(|(cn=Tori*)(sn=Jagger)))
        equalityNode = ( EqualityNode<?> ) orNodes.get( 1 );
        assertNotNull( equalityNode );

        assertEquals( "sn", equalityNode.getAttribute() );
        assertEquals( "Jagger", equalityNode.getValue().getString() );
    }
}
