/** \file
 *
 *  Contains unit tests for the StrIOStream class
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */

#ifndef _STRIOSTREAM_TEST_H_
#define _STRIOSTREAM_TEST_H_

#include "StrIOStream.h"

#include <cxxtest/TestSuite.h>

/**
 *  Unit tests for StrIOStream class
 *
 *  \ingroup io
 */
class StrIOStream_Test : public CxxTest::TestSuite
{
public:

    // dummy test
    void testWrite( void )
    {
        Str str;
        StrIOStream strIOStream( str );
        strIOStream << "Hello";
        TS_ASSERT_EQUALS( str, "Hello" );
        TS_ASSERT_EQUALS( strIOStream.bytesWritten(), 5U );

        strIOStream.write( " Worldly", 6 );
        TS_ASSERT_EQUALS( str, "Hello World" );
        TS_ASSERT_EQUALS( strIOStream.bytesWritten(), 6U );
    }

    void testWriteUShortCompact( void )
    {
        Str str;
        StrIOStream strIOStream( str );
        unsigned short foo( ( ( '<' >> 2 ) << 8 ) | ( 'E' >> 2 ) );
        strIOStream.writeUShortCompact( foo );
        TS_ASSERT_EQUALS( str, "E<" );

        str = Str::EMPTY_STR;
        unsigned short bar( '*' >> 1 | 1 );
        strIOStream.writeUShortCompact( bar );
        TS_ASSERT_EQUALS( str, "*" );

    }

    void testUShortCompactAll( void )
    {
        Str str;
        StrIOStream strIOStream( str );
        for( int i = 0; i < 65535; ++i )
        {
            unsigned short val = i;
            strIOStream.writeUShortCompact( val );
            unsigned short newVal;
            strIOStream.readUShortCompact( newVal );
            TS_ASSERT_EQUALS( val, newVal );
            strIOStream.clear();
        }
    }

    void testLongLongCompact( void )
    {
        const int nValues = 16;
        long long values[nValues] = { -0x1234567812345678LL,
                                      -0x12345678123456LL,
                                      -0x123456781234LL,
                                      -0x1234567812LL,
                                      -0x12345678LL,
                                      -0x123456LL,
                                      -0x1234LL,
                                      -0x12LL,
                                      0x12LL,
                                      0x1234LL,
                                      0x123456LL,
                                      0x12345678LL,
                                      0x1234567812LL,
                                      0x123456781234LL,
                                      0x12345678123456LL,
                                      0x1234567812345678LL,
                                    };

        Str str;
        StrIOStream strIOStream( str );
        for( int i = 0; i < nValues; ++i )
        {
            long long value = values[i];
            long long newValue;
            for( int i = 0; i < 63; ++i )
            {
                strIOStream.clear();
                strIOStream.writeLongLongCompact( value );
                strIOStream.readLongLongCompact( newValue );
                TS_ASSERT_EQUALS( value, newValue );
                value = ( value << 1 ) | ( ( value >> 63 ) & 0x01LL );
            }
        }
    }

    void testLongLongCompactShift( void )
    {
        const int nValues = 63;
        long long value = 01LL;

        Str str;
        StrIOStream strIOStream( str );
        for( int i = 0; i < nValues; ++i )
        {
            long long val = ( value << i );
            strIOStream.writeLongLongCompact( val );
            long long newVal;
            strIOStream.readLongLongCompact( newVal );
            TS_ASSERT_EQUALS( val, newVal );
            strIOStream.clear();
        }

        for( int i = 0; i < nValues; ++i )
        {
            long long val = -( value << i );
            strIOStream.writeLongLongCompact( val );
            long long newVal;
            strIOStream.readLongLongCompact( newVal );
            TS_ASSERT_EQUALS( val, newVal );
            strIOStream.clear();
        }
    }

    void testRead( void )
    {
        Str str( "Hello World" );
        StrIOStream strIOStream( str );
        char buffer[16];

        strIOStream.read( buffer, 5 );
        TS_ASSERT_SAME_DATA( buffer, "Hello", 5 );
        TS_ASSERT_EQUALS( strIOStream.bytesRead(), 5U );

        strIOStream.read( buffer, 20 );
        TS_ASSERT_SAME_DATA( buffer, " World", 6 );
        TS_ASSERT_EQUALS( strIOStream.bytesRead(), 6U );


    }

    void testReadUntil( void )
    {
        Str str( "Hello World" );
        StrIOStream strIOStream( str );
        char buffer[16];

        strIOStream.readUntil( buffer, 11, 'o' );
        TS_ASSERT_SAME_DATA( buffer, "Hello", 6 );
        TS_ASSERT_EQUALS( strIOStream.bytesRead(), 5U );

        strIOStream.readUntil( buffer, 6, '~' );
        TS_ASSERT_SAME_DATA( buffer, " World", 6 );
        TS_ASSERT_EQUALS( strIOStream.bytesRead(), 6U );

    }

};

#endif // _STRIOSTREAM_TEST_H
