/*
 *  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.api.ldap.codec.add;


import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

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

import org.apache.directory.api.asn1.DecoderException;
import org.apache.directory.api.asn1.EncoderException;
import org.apache.directory.api.asn1.ber.Asn1Decoder;
import org.apache.directory.api.asn1.util.Asn1Buffer;
import org.apache.directory.api.ldap.codec.api.LdapEncoder;
import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
import org.apache.directory.api.ldap.codec.api.ResponseCarryingException;
import org.apache.directory.api.ldap.codec.osgi.AbstractCodecServiceTest;
import org.apache.directory.api.ldap.model.entry.Attribute;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.entry.Value;
import org.apache.directory.api.ldap.model.message.AddRequest;
import org.apache.directory.api.ldap.model.message.AddRequestImpl;
import org.apache.directory.api.ldap.model.message.AddResponseImpl;
import org.apache.directory.api.ldap.model.message.Control;
import org.apache.directory.api.ldap.model.message.Message;
import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
import org.apache.directory.api.ldap.model.message.controls.ManageDsaIT;
import org.apache.directory.api.ldap.model.message.controls.ManageDsaITImpl;
import org.apache.directory.api.util.Strings;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode;

/**
 * Test the AddRequest codec
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
@Execution(ExecutionMode.CONCURRENT)
public class AddRequestTest extends AbstractCodecServiceTest
{
    /**
     * Test the decoding of a AddRequest
     * @throws EncoderException
     */
    @Test
    public void testDecodeAddRequestSuccess() throws DecoderException, EncoderException
    {
        ByteBuffer stream = ByteBuffer.allocate( 0x59 );

        stream.put( new byte[]
            {
                0x30, 0x57,                 // LDAPMessage ::= SEQUENCE {
                  0x02, 0x01, 0x01,         // messageID MessageID
                  0x68, 0x52,               // CHOICE { ..., addRequest AddRequest, ...
                                            // AddRequest ::= [APPLICATION 8] SEQUENCE {
                                            // entry LDAPDN,
                    0x04, 0x20,
                      'c', 'n', '=', 't', 'e', 's', 't', 'M', 'o', 'd', 'i', 'f', 'y',
                      ',', 'o', 'u', '=', 'u', 's', 'e', 'r', 's', ',',
                      'o', 'u', '=', 's', 'y', 's', 't', 'e', 'm',
                                            // attributes AttributeList }
                    0x30, 0x2E,             // AttributeList ::= SEQUENCE OF SEQUENCE {
                      0x30, 0x0c,           // attribute 1
                        0x04, 0x01,         // type AttributeDescription,
                          'l',
                        0x31, 0x07,         // vals SET OF AttributeValue }
                          0x04, 0x05,
                            'P', 'a', 'r', 'i', 's',
                      0x30, 0x1E,           // attribute 2
                        0x04, 0x05,         // type AttributeDescription,
                          'a', 't', 't', 'r', 's',
                        0x31, 0x15,         // vals SET OF AttributeValue }
                          0x04, 0x05,
                            't', 'e', 's', 't', '1',
                          0x04, 0x05,
                            't', 'e', 's', 't', '2',
                          0x04, 0x05,
                            't', 'e', 's', 't', '3'
            } );

        Strings.dumpBytes( stream.array() );
        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<AddRequest> container = new LdapMessageContainer<>( codec );

        // Decode a AddRequest message
        Asn1Decoder.decode( stream, container );

        AddRequest addRequest = container.getMessage();

        // Check the decoded message
        assertEquals( 1, addRequest.getMessageId() );
        assertEquals( "cn=testModify,ou=users,ou=system", addRequest.getEntryDn().toString() );

        Entry entry = addRequest.getEntry();

        assertEquals( 2, entry.size() );

        Set<String> expectedTypes = new HashSet<String>();

        expectedTypes.add( "l" );
        expectedTypes.add( "attrs" );

        Map<String, Set<String>> typesVals = new HashMap<String, Set<String>>();

        Set<String> lVal1 = new HashSet<String>();
        lVal1.add( "Paris" );
        typesVals.put( "l", lVal1 );

        Set<String> lVal2 = new HashSet<String>();
        lVal2.add( "test1" );
        lVal2.add( "test2" );
        lVal2.add( "test3" );
        typesVals.put( "attrs", lVal2 );

        Attribute attribute = entry.get( "l" );

        assertTrue( expectedTypes.contains( Strings.toLowerCaseAscii( attribute.getId() ) ) );

        Set<String> vals = typesVals.get( Strings.toLowerCaseAscii( attribute.getId() ) );

        for ( Value value : attribute )
        {
            assertTrue( vals.contains( value.getString() ) );

            vals.remove( value.getString() );
        }

        attribute = entry.get( "attrs" );

        assertTrue( expectedTypes.contains( Strings.toLowerCaseAscii( attribute.getId() ) ) );

        vals = typesVals.get( Strings.toLowerCaseAscii( attribute.getId() ) );

        for ( Value value : attribute )
        {
            assertTrue( vals.contains( value.getString() ) );

            vals.remove( value.getString() );
        }

        // Check encode reverse
        Asn1Buffer buffer = new Asn1Buffer();

        AddRequest request = new AddRequestImpl();
        request.setEntry( addRequest.getEntry() );
        request.setMessageId( addRequest.getMessageId() );

        LdapEncoder.encodeMessage( buffer, codec, request );

        assertArrayEquals( stream.array(), buffer.getBytes().array() );
    }


    /**
     * Test the decoding of a AddRequest with a null body
     */
    @Test
    public void testDecodeAddRequestNullBody() throws DecoderException
    {

        ByteBuffer stream = ByteBuffer.allocate( 0x07 );

        stream.put( new byte[]
            {
                0x30, 0x05,             // LDAPMessage ::= SEQUENCE {
                  0x02, 0x01, 0x01,     // messageID MessageID
                  0x68, 0x00            // CHOICE { ..., addRequest AddRequest, ...
            } );

        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<AddRequest> container = new LdapMessageContainer<>( codec );

        // Decode a AddRequest message
        assertThrows( DecoderException.class, ( ) ->
        {
            Asn1Decoder.decode( stream, container );
        } );
    }


    /**
     * Test the decoding of a AddRequest with a null entry
     */
    @Test
    public void testDecodeAddRequestNullEntry() throws DecoderException
    {
        ByteBuffer stream = ByteBuffer.allocate( 0x39 );

        stream.put( new byte[]
            {
                0x30, 0x37,                     // LDAPMessage ::= SEQUENCE {
                  0x02, 0x01, 0x01,             // messageID MessageID
                  0x68, 0x26,                   // CHOICE { ..., addRequest AddRequest, ...
                                                // AddRequest ::= [APPLICATION 8] SEQUENCE {
                    0x04, 0x00,                 // entry LDAPDN,
                                                // attributes AttributeList }
                    0x30, 0x2E,                 // AttributeList ::= SEQUENCE OF SEQUENCE {
                      0x30, 0x0c,               // attribute 1
                        0x04, 0x01,
                          'l',                  // type AttributeDescription,
                        0x31, 0x07,             // vals SET OF AttributeValue }
                          0x04, 0x05,
                            'P', 'a', 'r', 'i', 's',
                      0x30, 0x1E,               // attribute 2
                        0x04, 0x05,             // type AttributeDescription,
                          'a', 't', 't', 'r', 's',
                        0x31, 0x15,             // vals SET OF AttributeValue }
                          0x04, 0x05,
                            't', 'e', 's', 't', '1',
                          0x04, 0x05,
                            't', 'e', 's', 't', '2',
                          0x04, 0x05,
                            't', 'e', 's', 't', '3'
            } );

        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<AddRequest> container = new LdapMessageContainer<>( codec );

        // Decode a AddRequest message
        assertThrows( DecoderException.class, ( ) ->
        {
            try
            {
                Asn1Decoder.decode( stream, container );
            }
            catch ( DecoderException de )
            {
                assertTrue( de instanceof ResponseCarryingException );
                Message response = ( ( ResponseCarryingException ) de ).getResponse();
                assertTrue( response instanceof AddResponseImpl );
                assertEquals( ResultCodeEnum.NAMING_VIOLATION, ( ( AddResponseImpl ) response ).getLdapResult()
                    .getResultCode() );
    
                throw de;
            }
        } );
    }


    /**
     * Test the decoding of a AddRequest
     */
    @Test
    public void testDecodeAddRequestbadDN() throws DecoderException
    {
        ByteBuffer stream = ByteBuffer.allocate( 0x59 );

        stream.put( new byte[]
            {
                0x30, 0x57,                     // LDAPMessage ::= SEQUENCE {
                  0x02, 0x01, 0x01,             // messageID MessageID
                  0x68, 0x52,                   // CHOICE { ..., addRequest AddRequest, ...
                                                // AddRequest ::= [APPLICATION 8] SEQUENCE {
                    0x04, 0x20,                 // entry LDAPDN,
                      'c', 'n', ':', 't', 'e', 's', 't', 'M', 'o', 'd', 'i', 'f', 'y',
                      ',', 'o', 'u', '=', 'u', 's', 'e', 'r', 's', ',',
                      'o', 'u', '=', 's', 'y', 's', 't', 'e', 'm',
                                                // attributes AttributeList }
                    0x30, 0x2E,                 // AttributeList ::= SEQUENCE OF SEQUENCE {
                      0x30, 0x0c,               // attribute 1
                        0x04, 0x01,
                         'l',                   // type AttributeDescription,
                      0x31, 0x07,               // vals SET OF AttributeValue }
                        0x04, 0x05,
                          'P', 'a', 'r', 'i', 's',
                    0x30, 0x1E,                 // attribute 2
                      0x04, 0x05,               // type AttributeDescription,
                        'a', 't', 't', 'r', 's',
                      0x31, 0x15,               // vals SET OF AttributeValue }
                        0x04, 0x05,
                          't', 'e', 's', 't', '1',
                        0x04, 0x05,
                          't', 'e', 's', 't', '2',
                        0x04, 0x05,
                          't', 'e', 's', 't', '3'
            } );

        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<AddRequest> container = new LdapMessageContainer<>( codec );

        // Decode a AddRequest message
        assertThrows( DecoderException.class, ( ) ->
        {
            try
            {
                Asn1Decoder.decode( stream, container );
            }
            catch ( DecoderException de )
            {
                assertTrue( de instanceof ResponseCarryingException );
                Message response = ( ( ResponseCarryingException ) de ).getResponse();
                assertTrue( response instanceof AddResponseImpl );
                assertEquals( ResultCodeEnum.INVALID_DN_SYNTAX, ( ( AddResponseImpl ) response ).getLdapResult()
                    .getResultCode() );
    
                throw de;
            }
        } );
    }


    /**
     * Test the decoding of a AddRequest with a null attributeList
     */
    @Test
    public void testDecodeAddRequestNullAttributes() throws DecoderException
    {
        ByteBuffer stream = ByteBuffer.allocate( 0x2B );

        stream.put( new byte[]
            {
                0x30, 0x29,                 // LDAPMessage ::= SEQUENCE {
                  0x02, 0x01, 0x01,         // messageID MessageID
                  0x68, 0x24,               // CHOICE { ..., addRequest AddRequest, ...
                                            // AddRequest ::= [APPLICATION 8] SEQUENCE {
                    0x04, 0x20,             // entry LDAPDN,
                      'c', 'n', '=', 't', 'e', 's', 't', 'M', 'o', 'd', 'i', 'f', 'y',
                      ',', 'o', 'u', '=', 'u', 's', 'e', 'r', 's', ',',
                      'o', 'u', '=', 's', 'y', 's', 't', 'e', 'm',
                                            // attributes AttributeList }
                    0x30, 0x00              // AttributeList ::= SEQUENCE OF SEQUENCE {
            } );

        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<AddRequest> container = new LdapMessageContainer<>( codec );

        // Decode a AddRequest message
        assertThrows( DecoderException.class, ( ) ->
        {
            Asn1Decoder.decode( stream, container );
        } );
    }


    /**
     * Test the decoding of a AddRequest with a empty attributeList
     */
    @Test
    public void testDecodeAddRequestNullAttributeList() throws DecoderException
    {
        ByteBuffer stream = ByteBuffer.allocate( 0x2D );

        stream.put( new byte[]
            {
                0x30, 0x2B,                 // LDAPMessage ::= SEQUENCE {
                  0x02, 0x01, 0x01,         // messageID MessageID
                  0x68, 0x26,               // CHOICE { ..., addRequest AddRequest, ...
                                            // AddRequest ::= [APPLICATION 8] SEQUENCE {
                    0x04, 0x20,             // entry LDAPDN,
                      'c', 'n', '=', 't', 'e', 's', 't', 'M', 'o', 'd', 'i', 'f', 'y',
                      ',', 'o', 'u', '=', 'u', 's', 'e', 'r', 's', ',',
                      'o', 'u', '=', 's', 'y', 's', 't', 'e', 'm',
                                            // attributes AttributeList }
                    0x30, 0x02,             // AttributeList ::= SEQUENCE OF SEQUENCE {
                      0x30, 0x00
            } );

        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<AddRequest> container = new LdapMessageContainer<>( codec );

        // Decode a AddRequest message
        assertThrows( DecoderException.class, ( ) ->
        {
            Asn1Decoder.decode( stream, container );
        } );
    }


    /**
     * Test the decoding of a AddRequest with a empty attributeList
     */
    @Test
    public void testDecodeAddRequestNullType() throws DecoderException
    {
        ByteBuffer stream = ByteBuffer.allocate( 0x2F );

        stream.put( new byte[]
            {
                0x30, 0x2D,                 // LDAPMessage ::= SEQUENCE {
                  0x02, 0x01, 0x01,         // messageID MessageID
                  0x68, 0x28,               // CHOICE { ..., addRequest AddRequest, ...
                                            // AddRequest ::= [APPLICATION 8] SEQUENCE {
                    0x04, 0x20,             // entry LDAPDN,
                      'c', 'n', '=', 't', 'e', 's', 't', 'M', 'o', 'd', 'i', 'f', 'y',
                      ',', 'o', 'u', '=', 'u', 's', 'e', 'r', 's', ',',
                      'o', 'u', '=', 's', 'y', 's', 't', 'e', 'm',
                                            // attributes AttributeList }
                    0x30, 0x04,             // AttributeList ::= SEQUENCE OF SEQUENCE {
                      0x30, 0x02,           // attribute 1
                        0x04, 0x00          // type AttributeDescription,
            } );

        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<AddRequest> container = new LdapMessageContainer<>( codec );

        // Decode a AddRequest message
        assertThrows( DecoderException.class, ( ) ->
        {
            try
            {
                Asn1Decoder.decode( stream, container );
            }
            catch ( DecoderException de )
            {
                assertTrue( de instanceof ResponseCarryingException );
                Message response = ( ( ResponseCarryingException ) de ).getResponse();
                assertTrue( response instanceof AddResponseImpl );
                assertEquals( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, ( ( AddResponseImpl ) response ).getLdapResult()
                    .getResultCode() );
    
                throw de;
            }
        } );
    }


    /**
     * Test the decoding of a AddRequest with a empty attributeList
     */
    @Test
    public void testDecodeAddRequestNoVals() throws DecoderException
    {
        ByteBuffer stream = ByteBuffer.allocate( 0x30 );

        stream.put( new byte[]
            {
                0x30, 0x2E,                 // LDAPMessage ::= SEQUENCE {
                  0x02, 0x01, 0x01,         // messageID MessageID
                  0x68, 0x29,               // CHOICE { ..., addRequest AddRequest, ...
                                            // AddRequest ::= [APPLICATION 8] SEQUENCE {
                    0x04, 0x20,             // entry LDAPDN,
                      'c', 'n', '=', 't', 'e', 's', 't', 'M', 'o', 'd', 'i', 'f', 'y',
                      ',', 'o', 'u', '=', 'u', 's', 'e', 'r', 's', ',',
                      'o', 'u', '=', 's', 'y', 's', 't', 'e', 'm',
                                            // attributes AttributeList }
                    0x30, 0x05,             // AttributeList ::= SEQUENCE OF SEQUENCE {
                      0x30, 0x03,           // attribute 1
                        0x04, 0x01,         // type AttributeDescription,
                          'A'
            } );

        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<AddRequest> container = new LdapMessageContainer<>( codec );

        // Decode a AddRequest message
        assertThrows( DecoderException.class, ( ) ->
        {
            Asn1Decoder.decode( stream, container );
        } );
    }


    /**
     * Test the decoding of a AddRequest with a empty attributeList
     */
    @Test
    public void testDecodeAddRequestNullVals() throws DecoderException
    {
        ByteBuffer stream = ByteBuffer.allocate( 0x32 );

        stream.put( new byte[]
            {
                0x30, 0x30,                     // LDAPMessage ::= SEQUENCE {
                  0x02, 0x01, 0x01,             // messageID MessageID
                  0x68, 0x2B,                   // CHOICE { ..., addRequest AddRequest, ...
                                                // AddRequest ::= [APPLICATION 8] SEQUENCE {
                    0x04, 0x20,                 // entry LDAPDN,
                      'c', 'n', '=', 't', 'e', 's', 't', 'M', 'o', 'd', 'i', 'f', 'y',
                      ',', 'o', 'u', '=', 'u', 's', 'e', 'r', 's', ',',
                      'o', 'u', '=', 's', 'y', 's', 't', 'e', 'm',
                                                // attributes AttributeList }
                    0x30, 0x07,                 // AttributeList ::= SEQUENCE OF SEQUENCE {
                      0x30, 0x05,               // attribute 1
                        0x04, 0x01,             // type AttributeDescription,
                          'A',
                        0x31, 0x00
            } );

        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<AddRequest> container = new LdapMessageContainer<>( codec );

        // Decode a AddRequest message
        assertThrows( DecoderException.class, ( ) ->
        {
            Asn1Decoder.decode( stream, container );
        } );
    }


    /**
     * Test the decoding of a AddRequest with a empty attributeList
     */
    @Test
    public void testDecodeAddRequestEmptyAttributeValue() throws DecoderException, EncoderException
    {
        ByteBuffer stream = ByteBuffer.allocate( 0x34 );

        stream.put( new byte[]
            {
                0x30, 0x32,                     // LDAPMessage ::= SEQUENCE {
                  0x02, 0x01, 0x01,             // messageID MessageID
                  0x68, 0x2D,                   // CHOICE { ..., addRequest AddRequest, ...
                                                // AddRequest ::= [APPLICATION 8] SEQUENCE {
                    0x04, 0x20,                 // entry LDAPDN,
                      'c', 'n', '=', 't', 'e', 's', 't', 'M', 'o', 'd', 'i', 'f', 'y',
                      ',', 'o', 'u', '=', 'u', 's', 'e', 'r', 's', ',',
                      'o', 'u', '=', 's', 'y', 's', 't', 'e', 'm',
                                                // attributes AttributeList }
                    0x30, 0x09,                 // AttributeList ::= SEQUENCE OF SEQUENCE {
                      0x30, 0x07,               // attribute 1
                        0x04, 0x01,
                          'l',                  // type AttributeDescription,
                        0x31, 0x02,
                          0x04, 0x00
            } );

        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<AddRequest> container = new LdapMessageContainer<>( codec );

        // Decode a AddRequest message
        Asn1Decoder.decode( stream, container );

        AddRequest addRequest = container.getMessage();

        // Check the decoded message
        assertEquals( 1, addRequest.getMessageId() );
        assertEquals( "cn=testModify,ou=users,ou=system", addRequest.getEntryDn().toString() );

        Entry entry = addRequest.getEntry();

        assertEquals( 1, entry.size() );

        Attribute attribute = entry.get( "l" );

        assertEquals( "l", Strings.toLowerCaseAscii( attribute.getId() ) );

        for ( Value value : attribute )
        {
            assertEquals( "", value.getString() );
        }

        // Check encode reverse
        Asn1Buffer buffer = new Asn1Buffer();

        AddRequest request = new AddRequestImpl();
        request.setEntry( addRequest.getEntry() );
        request.setMessageId( addRequest.getMessageId() );

        LdapEncoder.encodeMessage( buffer, codec, request );

        assertArrayEquals( stream.array(), buffer.getBytes().array() );
    }


    /**
     * Test the decoding of a AddRequest with a empty attributeList and a
     * control
     */
    @Test
    public void testDecodeAddRequestEmptyAttributeValueWithControl() throws  DecoderException, EncoderException
    {
        ByteBuffer stream = ByteBuffer.allocate( 0x51 );

        stream.put( new byte[]
            {
                0x30, 0x4F, // LDAPMessage ::= SEQUENCE {
                  0x02, 0x01, 0x01, // messageID MessageID
                  0x68, 0x2D, // CHOICE { ..., addRequest AddRequest, ...
                    // AddRequest ::= [APPLICATION 8] SEQUENCE {
                    // entry LDAPDN,
                    0x04, 0x20,
                      'c', 'n', '=', 't', 'e', 's', 't', 'M', 'o', 'd', 'i', 'f', 'y',
                      ',', 'o', 'u', '=', 'u', 's', 'e', 'r', 's', ',',
                      'o', 'u', '=', 's', 'y', 's', 't', 'e', 'm',
                    // attributes AttributeList }
                    0x30, 0x09, // AttributeList ::= SEQUENCE OF SEQUENCE {
                      0x30, 0x07, // attribute 1
                        0x04, 0x01,
                          'l', // type AttributeDescription,
                      0x31, 0x02,
                        0x04, 0x00,
                    ( byte ) 0xA0, 0x1B, // A control (ManageDsaIT)
                      0x30, 0x19,
                        0x04, 0x17,
                          '2', '.', '1', '6', '.', '8', '4', '0', '.', '1',  '.', '1', '1', '3', '7', '3', '0',
                          '.', '3', '.', '4', '.', '2'
            } );

        stream.flip();

        // Allocate a LdapMessage Container
        LdapMessageContainer<AddRequest> container = new LdapMessageContainer<>( codec );

        // Decode a AddRequest message
        Asn1Decoder.decode( stream, container );

        AddRequest addRequest = container.getMessage();

        // Check the decoded message
        assertEquals( 1, addRequest.getMessageId() );
        assertEquals( "cn=testModify,ou=users,ou=system", addRequest.getEntryDn().toString() );

        Entry entry = addRequest.getEntry();

        assertEquals( 1, entry.size() );

        Attribute attribute = entry.get( "l" );

        assertEquals( "l", Strings.toLowerCaseAscii( attribute.getId() ) );

        for ( Value value : attribute )
        {
            assertEquals( "", value.getString() );
        }

        // Check the Control
        Map<String, Control> controls = addRequest.getControls();

        assertEquals( 1, controls.size() );

        assertTrue( addRequest.hasControl( "2.16.840.1.113730.3.4.2" ) );

        Control control = controls.get( "2.16.840.1.113730.3.4.2" );
        assertTrue( control instanceof ManageDsaIT );
        assertEquals( "2.16.840.1.113730.3.4.2", control.getOid() );

        // Check encode reverse
        Asn1Buffer buffer = new Asn1Buffer();

        AddRequest request = new AddRequestImpl();
        request.setEntry( addRequest.getEntry() );
        request.setMessageId( addRequest.getMessageId() );
        request.addControl( new ManageDsaITImpl() );

        LdapEncoder.encodeMessage( buffer, codec, request );

        assertArrayEquals( stream.array(), buffer.getBytes().array() );
        
        // Check encode reverse
        Asn1Buffer asn1Buffer = new Asn1Buffer();

        AddRequest request2 = new AddRequestImpl();
        request2.setEntry( addRequest.getEntry() );
        request2.setMessageId( addRequest.getMessageId() );
        request2.addControl( new ManageDsaITImpl() );

        LdapEncoder.encodeMessage( asn1Buffer, codec, request2 );

        assertArrayEquals( stream.array(), asn1Buffer.getBytes().array() );
    }
}
