/*
 *   Copyright 2005 The Apache Software Foundation
 *
 *   Licensed 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.asn1new.ldap;

import junit.framework.TestCase;
import junit.framework.Assert;
import org.apache.ldap.common.message.spi.Provider;
import org.apache.ldap.common.message.*;
import org.apache.asn1new.ldap.pojo.SearchResultDone;
import org.apache.asn1new.ldap.pojo.LdapMessage;
import org.apache.asn1new.ldap.pojo.Control;

import java.io.ByteArrayInputStream;
import java.util.Arrays;
import java.util.Iterator;
import java.nio.ByteBuffer;

/**
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class TwixProviderTest extends TestCase
{
    public void testSearchResultDoneWithNoControl()
    {
        byte[] asn1BER = new byte[]
        {
            0x30, 0x0c,
                0x02, 0x01, 0x06, // messageID
                0x65, 0x07,
                    0x0a, 0x01, 0x00, // LDAPResult: success
                    0x04, 0x00,   // matchedDN
                    0x04, 0x00,   // errorMessage
        };

        Provider twixProvider = TwixProvider.getProvider();

        // test the decoder
        Object message = twixProvider.getDecoder( null )
            .decode( null, new ByteArrayInputStream(asn1BER) );
        Assert.assertTrue( message instanceof LdapMessage );
        LdapMessage ldapMessage = (LdapMessage) message;
        Assert.assertEquals( 6, ldapMessage.getMessageId() );

        SearchResultDone searchDoneMessage = ldapMessage.getSearchResultDone();
        Assert.assertNotNull( searchDoneMessage );
        Assert.assertEquals( 0, searchDoneMessage.getLdapResult().getResultCode() );
        Assert.assertEquals( "", searchDoneMessage.getLdapResult().getMatchedDN() );
        Assert.assertEquals( "", searchDoneMessage.getLdapResult().getErrorMessage() );

        Assert.assertNull( ldapMessage.getControls() );

        try
        {
            ldapMessage.addControl( null );
        }
        catch (NullPointerException ex)
        {
            Assert.fail("Got null pointer exception when calling LdapMessage.addControl()");
        }
    }

    public void testSearchResultDoneWithControls()
    {
        byte[] asn1BER = new byte[]
        {
            0x30, 0x35,
                0x02, 0x01, 0x06, // messageID
                0x65, 0x07,
                    0x0a, 0x01, 0x00, // LDAPResult: success
                    0x04, 0x00,   // matchedDN
                    0x04, 0x00,   // errorMessage
                (byte)0xa0, 0x27, // controls
                    0x30, 0x25,
                        0x04, 0x16,
                            0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x31,
                                    0x33, 0x35, 0x35, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x33,
                                    0x31, 0x39, // control oid: 1.2.840.113556.1.4.319
                        0x04, 0x0b, 0x30, 0x09, 0x02, 0x01, 0x00, 0x04, 0x04, 0x4d, 0x00, 0x00, 0x00 // control value
        };

        Provider twixProvider = TwixProvider.getProvider();

        // test the decoder
        Object message = twixProvider.getDecoder( null )
            .decode( null, new ByteArrayInputStream(asn1BER) );
        Assert.assertTrue( message instanceof LdapMessage );
        LdapMessage ldapMessage = (LdapMessage) message;
        Assert.assertEquals( 6, ldapMessage.getMessageId() );

        SearchResultDone searchDoneMessage = ldapMessage.getSearchResultDone();
        Assert.assertNotNull( searchDoneMessage );
        Assert.assertEquals( 0, searchDoneMessage.getLdapResult().getResultCode() );
        Assert.assertEquals( "", searchDoneMessage.getLdapResult().getMatchedDN() );
        Assert.assertEquals( "", searchDoneMessage.getLdapResult().getErrorMessage() );

        Assert.assertEquals( 1, ldapMessage.getControls().size() );
        // this is a constant in Java 5 API
        String pagedResultsControlOID = "1.2.840.113556.1.4.319";
        Control pagedResultsControl = ldapMessage.getControls( 0 );
        Assert.assertEquals( pagedResultsControlOID, pagedResultsControl.getControlType() );
        Assert.assertFalse( pagedResultsControl.getCriticality() );
        Assert.assertNotNull( pagedResultsControl.getControlValue() );

        // test the encoder
        ByteBuffer buff =
            twixProvider.getEncoder().encodeBlocking( ldapMessage );
        Assert.assertTrue( Arrays.equals( asn1BER, buff.array() ) );
    }

    public void testSearchRequestWithControls()
    {
        byte[] asn1BER = new byte[]
        {
            0x30, 0x64,
                0x02, 0x01, 0x04, // messageID
                0x63, 0x33,
                    0x04, 0x13,
                        0x64, 0x63, 0x3d, 0x6d, 0x79, 0x2d, 0x64, 0x6f, 0x6d, 0x61,
                                0x69, 0x6e, 0x2c, 0x64, 0x63, 0x3d, 0x63, 0x6f, 0x6d, // baseObject: dc=my-domain,dc=com
                    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,
                        0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, // filter: (objectClass=*)
                    0x30, 0x00,
                (byte)0xa0, 0x2a, // controls
                    0x30, 0x28,
                        0x04, 0x16,
                            0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x31,
                                    0x33, 0x35, 0x35, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x33,
                                    0x31, 0x39, // control oid: 1.2.840.113556.1.4.319
                        0x01, 0x01, (byte)0xff, // criticality: true
                        0x04, 0x0b,
                            0x30, 0x09, 0x02, 0x01, 0x02, 0x04, 0x04, 0x47, 0x00, 0x00, 0x00, // value: pageSize=2
        };

        Provider twixProvider = TwixProvider.getProvider();
        Object message = twixProvider.getDecoder( null )
            .decode( null, new ByteArrayInputStream(asn1BER) );
        Assert.assertTrue( message instanceof LdapMessage );
        LdapMessage ldapMessage = (LdapMessage) message;

        // test the transformer
        Message snickerLdapMessage =
            twixProvider.getTransformer().transform( ldapMessage );
        Assert.assertEquals( 4, snickerLdapMessage.getMessageId() );
        Assert.assertEquals( 1, snickerLdapMessage.getControls().size() );
        Iterator controlIterator =
            snickerLdapMessage.getControls().iterator();
        org.apache.ldap.common.message.Control snickersControl =
            (org.apache.ldap.common.message.Control)controlIterator.next();
        Assert.assertNotNull( snickersControl.getEncodedValue() );
        Assert.assertTrue( snickersControl.getEncodedValue().length > 0 );
    }

    public void testTransformerTransformingSnickersMessage()
    {
        SearchResponseDoneImpl snickerMessage = new SearchResponseDoneImpl( 6 );
        LdapResultImpl ldapResult = new LdapResultImpl( null );
        ldapResult.setErrorMessage( "" );
        ldapResult.setMatchedDn( "" );
        ldapResult.setResultCode( ResultCodeEnum.SUCCESS );
        snickerMessage.setLdapResult( ldapResult );
        snickerMessage.add(new ControlImpl()
        {
            public String getID()
            {
                return "1.2";
            }
            public byte[] getEncodedValue()
            {
                return null;
            }
        });

        // test the transformer
        Provider twixProvider = TwixProvider.getProvider();
        Object twixMessage =
            twixProvider.getTransformer().transform( snickerMessage );
        Assert.assertTrue( twixMessage instanceof LdapMessage );
        LdapMessage ldapMessage = (LdapMessage) twixMessage;
        Assert.assertEquals( 6, ldapMessage.getMessageId() );

        SearchResultDone searchDoneMessage = ldapMessage.getSearchResultDone();
        Assert.assertNotNull( searchDoneMessage );
        Assert.assertEquals( 0, searchDoneMessage.getLdapResult().getResultCode() );
        Assert.assertEquals( "", searchDoneMessage.getLdapResult().getMatchedDN() );
        Assert.assertEquals( "", searchDoneMessage.getLdapResult().getErrorMessage() );

        Assert.assertNotNull( ldapMessage.getControls() );
        Assert.assertEquals( 1, ldapMessage.getControls().size() );
        Control pagedResultsControl = ldapMessage.getControls( 0 );
        Assert.assertEquals( "1.2", pagedResultsControl.getControlType() );
    }
}
