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


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.nio.ByteBuffer;
import java.util.Arrays;

import com.mycila.junit.concurrent.Concurrency;
import com.mycila.junit.concurrent.ConcurrentJunitRunner;

import org.apache.directory.api.asn1.DecoderException;
import org.apache.directory.api.ldap.codec.controls.search.pagedSearch.PagedResultsDecorator;
import org.apache.directory.api.ldap.codec.osgi.AbstractCodecServiceTest;
import org.apache.directory.api.ldap.model.message.controls.PagedResults;
import org.apache.directory.api.util.Strings;
import org.junit.Test;
import org.junit.runner.RunWith;


/**
 * Test the PagedSearchControlTest codec
 * 
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
@RunWith(ConcurrentJunitRunner.class)
@Concurrency()
public class PagedSearchControlTest extends AbstractCodecServiceTest
{
    /**
     * Test encoding of a PagedSearchControl.
     */
    @Test
    public void testEncodePagedSearchControl() throws Exception
    {
        ByteBuffer bb = ByteBuffer.allocate( 0x0B );
        bb.put( new byte[]
            {
                0x30, 0x09, // realSearchControlValue ::= SEQUENCE {
                0x02,
                0x01,
                0x20, // size INTEGER,
                0x04,
                0x04,
                't',
                'e',
                's',
                't' // cookie OCTET STRING,
        } );
        bb.flip();

        PagedResultsDecorator decorator = new PagedResultsDecorator( codec );

        PagedResults pagedSearch = ( PagedResults ) decorator.decode( bb.array() );

        assertEquals( 32, pagedSearch.getSize() );
        assertTrue( Arrays.equals( Strings.getBytesUtf8( "test" ),
            pagedSearch.getCookie() ) );

        bb.flip();

        PagedResultsDecorator ctrl = new PagedResultsDecorator( codec );
        ctrl.setSize( 32 );
        ctrl.setCookie( Strings.getBytesUtf8( "test" ) );

        ByteBuffer buffer = ctrl.encode( ByteBuffer.allocate( ctrl.computeLength() ) );
        String decoded = Strings.dumpBytes( buffer.array() );
        String expected = Strings.dumpBytes( bb.array() );
        assertEquals( expected, decoded );
    }


    /**
     * Test the decoding of a PagedSearchControl with no cookie
     */
    @Test(expected = DecoderException.class)
    public void testDecodePagedSearchRequestNoCookie() throws Exception
    {
        ByteBuffer bb = ByteBuffer.allocate( 0x05 );
        bb.put( new byte[]
            {
                0x30, 0x03, // realSearchControlValue ::= SEQUENCE {
                0x02,
                0x01,
                0x20 // size INTEGER,
        } );
        bb.flip();

        PagedResultsDecorator decorator = new PagedResultsDecorator( codec );

        decorator.decode( bb.array() );
    }


    /**
     * Test the decoding of a PagedSearchControl with no size
     */
    @Test(expected = DecoderException.class)
    public void testDecodePagedSearchRequestNoSize() throws Exception
    {
        ByteBuffer bb = ByteBuffer.allocate( 0x08 );
        bb.put( new byte[]
            {
                0x30, 0x06, // realSearchControlValue ::= SEQUENCE {
                0x04,
                0x04,
                't',
                'e',
                's',
                't' // cookie OCTET STRING,
        } );
        bb.flip();

        PagedResultsDecorator decorator = new PagedResultsDecorator( codec );

        decorator.decode( bb.array() );
    }


    /**
     * Test the decoding of a PagedSearchControl with no size  and no cookie
     */
    @Test(expected = DecoderException.class)
    public void testDecodePagedSearchRequestNoSizeNoCookie() throws Exception
    {
        ByteBuffer bb = ByteBuffer.allocate( 0x02 );
        bb.put( new byte[]
            {
                0x30, 0x00, // realSearchControlValue ::= SEQUENCE 
            } );
        bb.flip();

        PagedResultsDecorator decorator = new PagedResultsDecorator( codec );

        decorator.decode( bb.array() );
    }


    /**
     * Test encoding of a PagedSearchControl with a negative size
     */
    @Test
    public void testEncodePagedSearchControlNegativeSize() throws Exception
    {
        ByteBuffer bb = ByteBuffer.allocate( 0x0b );
        bb.put( new byte[]
            {
                0x30, 0x09, // realSearchControlValue ::= SEQUENCE {
                0x02,
                0x01,
                ( byte ) 0xFF, // size INTEGER,
                0x04,
                0x04,
                't',
                'e',
                's',
                't' // cookie OCTET STRING,
        } );
        bb.flip();

        PagedResultsDecorator decorator = new PagedResultsDecorator( codec );

        PagedResults pagedSearch = ( PagedResults ) decorator.decode( bb.array() );

        assertEquals( Integer.MAX_VALUE, pagedSearch.getSize() );
        assertTrue( Arrays.equals( Strings.getBytesUtf8( "test" ),
            pagedSearch.getCookie() ) );

        bb.flip();

        PagedResultsDecorator ctrl = new PagedResultsDecorator( codec );
        ctrl.setSize( -1 );
        ctrl.setCookie( Strings.getBytesUtf8( "test" ) );

        ByteBuffer buffer = ctrl.encode( ByteBuffer.allocate( ctrl.computeLength() ) );
        String decoded = Strings.dumpBytes( buffer.array() );
        String expected = Strings.dumpBytes( bb.array() );
        assertEquals( expected, decoded );
    }


    /**
     * Test encoding of a PagedSearchControl with a empty size
     */
    @Test(expected = DecoderException.class)
    public void testEncodePagedSearchControlEmptySize() throws Exception
    {
        ByteBuffer bb = ByteBuffer.allocate( 0x0a );
        bb.put( new byte[]
            {
                0x30, 0x08, // realSearchControlValue ::= SEQUENCE {
                0x02,
                0x00, // size INTEGER,
                0x04,
                0x04,
                't',
                'e',
                's',
                't' // cookie OCTET STRING,
        } );
        bb.flip();

        PagedResultsDecorator decorator = new PagedResultsDecorator( codec );

        decorator.decode( bb.array() );
    }


    /**
     * Test encoding of a PagedSearchControl with a empty cookie
     */
    @Test
    public void testEncodePagedSearchControlEmptyCookie() throws Exception
    {
        ByteBuffer bb = ByteBuffer.allocate( 0x07 );
        bb.put( new byte[]
            {
                0x30, 0x05, // realSearchControlValue ::= SEQUENCE {
                0x02,
                0x01,
                0x20, // size INTEGER,
                0x04,
                0x00 // cookie OCTET STRING,
        } );
        bb.flip();

        PagedResultsDecorator decorator = new PagedResultsDecorator( codec );

        PagedResults pagedSearch = ( PagedResults ) decorator.decode( bb.array() );

        assertEquals( 32, pagedSearch.getSize() );
        assertNull( pagedSearch.getCookie() );

        PagedResultsDecorator ctrl = new PagedResultsDecorator( codec );
        ctrl.setSize( 32 );
        ctrl.setCookie( null );

        ByteBuffer buffer = ctrl.encode( ByteBuffer.allocate( ctrl.computeLength() ) );
        String decoded = Strings.dumpBytes( buffer.array() );
        String expected = Strings.dumpBytes( bb.array() );
        assertEquals( expected, decoded );
    }
}