tomwalters@570: /* tomwalters@570: oscpack -- Open Sound Control packet manipulation library tomwalters@570: http://www.audiomulch.com/~rossb/oscpack tomwalters@570: tomwalters@570: Copyright (c) 2004-2005 Ross Bencina tomwalters@570: tomwalters@570: Permission is hereby granted, free of charge, to any person obtaining tomwalters@570: a copy of this software and associated documentation files tomwalters@570: (the "Software"), to deal in the Software without restriction, tomwalters@570: including without limitation the rights to use, copy, modify, merge, tomwalters@570: publish, distribute, sublicense, and/or sell copies of the Software, tomwalters@570: and to permit persons to whom the Software is furnished to do so, tomwalters@570: subject to the following conditions: tomwalters@570: tomwalters@570: The above copyright notice and this permission notice shall be tomwalters@570: included in all copies or substantial portions of the Software. tomwalters@570: tomwalters@570: Any person wishing to distribute modifications to the Software is tomwalters@570: requested to send the modifications to the original developer so that tomwalters@570: they can be incorporated into the canonical version. tomwalters@570: tomwalters@570: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, tomwalters@570: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF tomwalters@570: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. tomwalters@570: IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR tomwalters@570: ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF tomwalters@570: CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION tomwalters@570: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tomwalters@570: */ tomwalters@570: #include "OscUnitTests.h" tomwalters@570: tomwalters@570: #include tomwalters@570: #include tomwalters@570: tomwalters@570: #include "osc/OscReceivedElements.h" tomwalters@570: #include "osc/OscPrintReceivedElements.h" tomwalters@570: #include "osc/OscOutboundPacketStream.h" tomwalters@570: tomwalters@570: tomwalters@570: namespace osc{ tomwalters@570: tomwalters@570: static int passCount_=0, failCount_=0; tomwalters@570: tomwalters@570: void PrintTestSummary() tomwalters@570: { tomwalters@570: std::cout << (passCount_+failCount_) << " tests run, " << passCount_ << " passed, " << failCount_ << " failed.\n"; tomwalters@570: } tomwalters@570: tomwalters@570: void pass_equality( const char *slhs, const char *srhs, const char *file, int line ) tomwalters@570: { tomwalters@570: ++passCount_; tomwalters@570: std::cout << file << "(" << line << "): PASSED : " << slhs << " == " << srhs << "\n"; tomwalters@570: } tomwalters@570: tomwalters@570: void fail_equality( const char *slhs, const char *srhs, const char *file, int line ) tomwalters@570: { tomwalters@570: ++failCount_; tomwalters@570: std::cout << file << "(" << line << "): FAILED : " << slhs << " != " << srhs << "\n"; tomwalters@570: } tomwalters@570: tomwalters@570: template tomwalters@570: void assertEqual_( const T& lhs, const T& rhs, const char *slhs, const char *srhs, const char *file, int line ) tomwalters@570: { tomwalters@570: if( lhs == rhs ) tomwalters@570: pass_equality( slhs, srhs, file, line ); tomwalters@570: else tomwalters@570: fail_equality( slhs, srhs, file, line ); tomwalters@570: } tomwalters@570: tomwalters@570: template tomwalters@570: void assertEqual_( const T* lhs, const T* rhs, const char *slhs, const char *srhs, const char *file, int line ) tomwalters@570: { tomwalters@570: if( lhs == rhs ) tomwalters@570: pass_equality( slhs, srhs, file, line ); tomwalters@570: else tomwalters@570: fail_equality( slhs, srhs, file, line ); tomwalters@570: } tomwalters@570: tomwalters@570: template <> tomwalters@570: void assertEqual_( const char* lhs, const char* rhs, const char *slhs, const char *srhs, const char *file, int line ) tomwalters@570: { tomwalters@570: if( strcmp( lhs, rhs ) == 0 ) tomwalters@570: pass_equality( slhs, srhs, file, line ); tomwalters@570: else tomwalters@570: fail_equality( slhs, srhs, file, line ); tomwalters@570: } tomwalters@570: tomwalters@570: tomwalters@570: #define assertEqual( a, b ) assertEqual_( (a), (b), #a, #b, __FILE__, __LINE__ ) tomwalters@570: tomwalters@570: //--------------------------------------------------------------------------- tomwalters@570: char * AllocateAligned4( unsigned long size ) tomwalters@570: { tomwalters@570: char *s = new char[ size + 4 ]; //allocate on stack to get 4 byte alignment tomwalters@570: return (char*)((long)(s-1) & (~0x03L)) + 4; tomwalters@570: } tomwalters@570: tomwalters@570: // allocate a 4 byte aligned copy of s tomwalters@570: char * NewMessageBuffer( const char *s, unsigned long length ) tomwalters@570: { tomwalters@570: char *p = AllocateAligned4( length ); tomwalters@570: memcpy( p, s, length ); tomwalters@570: return p; tomwalters@570: } tomwalters@570: tomwalters@570: void test1() tomwalters@570: { tomwalters@570: const char s[] = "/test\0\0\0,fiT\0\0\0\0\0\0\0\0\0\0\0A"; tomwalters@570: char *buffer = NewMessageBuffer( s, sizeof(s)-1 ); tomwalters@570: tomwalters@570: // test argument iterator interface tomwalters@570: bool unexpectedExceptionCaught = false; tomwalters@570: try{ tomwalters@570: ReceivedMessage m( ReceivedPacket(buffer, sizeof(s)-1) ); tomwalters@570: tomwalters@570: assertEqual( strcmp( m.AddressPattern(), "/test" ), 0 ); tomwalters@570: assertEqual( strcmp( m.TypeTags(), "fiT" ), 0 ); tomwalters@570: tomwalters@570: ReceivedMessage::const_iterator i = m.ArgumentsBegin(); tomwalters@570: ++i; tomwalters@570: ++i; tomwalters@570: ++i; tomwalters@570: assertEqual( i, m.ArgumentsEnd() ); tomwalters@570: tomwalters@570: i = m.ArgumentsBegin(); tomwalters@570: float f = (i++)->AsFloat(); tomwalters@570: (void)f; tomwalters@570: int n = (i++)->AsInt32(); tomwalters@570: (void)n; tomwalters@570: bool b = (i++)->AsBool(); tomwalters@570: (void)b; tomwalters@570: tomwalters@570: i = m.ArgumentsBegin(); tomwalters@570: bool exceptionThrown = false; tomwalters@570: try{ tomwalters@570: int n = (i++)->AsInt32(); tomwalters@570: (void)n; tomwalters@570: }catch( Exception& ){ tomwalters@570: exceptionThrown = true; tomwalters@570: } tomwalters@570: assertEqual( exceptionThrown, true ); tomwalters@570: tomwalters@570: }catch( Exception& e ){ tomwalters@570: std::cout << "unexpected exception: " << e.what() << "\n"; tomwalters@570: unexpectedExceptionCaught = true; tomwalters@570: } tomwalters@570: assertEqual( unexpectedExceptionCaught, false ); tomwalters@570: tomwalters@570: tomwalters@570: // test argument stream interface tomwalters@570: unexpectedExceptionCaught = false; tomwalters@570: try{ tomwalters@570: ReceivedMessage m( ReceivedPacket(buffer, sizeof(s)-1) ); tomwalters@570: ReceivedMessageArgumentStream args = m.ArgumentStream(); tomwalters@570: assertEqual( args.Eos(), false ); tomwalters@570: tomwalters@570: float f; tomwalters@570: long n; tomwalters@570: bool b; tomwalters@570: args >> f >> n >> b; tomwalters@570: tomwalters@570: (void) f; tomwalters@570: (void) n; tomwalters@570: (void) b; tomwalters@570: tomwalters@570: assertEqual( args.Eos(), true ); tomwalters@570: tomwalters@570: }catch( Exception& e ){ tomwalters@570: std::cout << "unexpected exception: " << e.what() << "\n"; tomwalters@570: unexpectedExceptionCaught = true; tomwalters@570: } tomwalters@570: assertEqual( unexpectedExceptionCaught, false ); tomwalters@570: } tomwalters@570: tomwalters@570: //--------------------------------------------------------------------------- tomwalters@570: tomwalters@570: tomwalters@570: #define TEST2_PRINT( ss )\ tomwalters@570: {\ tomwalters@570: const char s[] = ss;\ tomwalters@570: ReceivedPacket p( NewMessageBuffer( s, sizeof(s)-1 ), sizeof(s)-1 ); \ tomwalters@570: ReceivedMessage m( p );\ tomwalters@570: std::cout << m << "\n";\ tomwalters@570: } tomwalters@570: tomwalters@570: void test2() tomwalters@570: { tomwalters@570: bool unexpectedExceptionCaught = false; tomwalters@570: try{ tomwalters@570: // 012301230 1 2 3 tomwalters@570: TEST2_PRINT( "/no_args\0\0\0\0" ); tomwalters@570: tomwalters@570: // 012301230 1 2 3 01 2 3 tomwalters@570: TEST2_PRINT( "/no_args\0\0\0\0,\0\0\0" ); tomwalters@570: tomwalters@570: // 01230123 012 3 0 1 2 3 tomwalters@570: TEST2_PRINT( "/an_int\0,i\0\0\0\0\0A" ); tomwalters@570: // 012301230 1 2 3 012 3 0 1 2 3 tomwalters@570: TEST2_PRINT( "/a_float\0\0\0\0,f\0\0\0\0\0\0" ); tomwalters@570: // 0123012301 2 3 012 3 012301230123 tomwalters@570: TEST2_PRINT( "/a_string\0\0\0,s\0\0hello world\0" ); tomwalters@570: // 01230123 012 3 0 1 2 3 0 1 2 3 tomwalters@570: TEST2_PRINT( "/a_blob\0,b\0\0\0\0\0\x4\x0\x1\x2\x3" ); tomwalters@570: tomwalters@570: // 0123012301 2 3 012 3 0 1 2 3 0 1 2 3 tomwalters@570: TEST2_PRINT( "/an_int64\0\0\0,h\0\0\0\0\0\0\0\0\0\x1" ); tomwalters@570: // 01230123012 3 012 3 0 1 2 3 0 1 2 3 tomwalters@570: TEST2_PRINT( "/a_timetag\0\0,t\0\0\0\0\0\0\0\0\0\x1" ); tomwalters@570: // 0123012301 2 3 012 3 0 1 2 3 0 1 2 3 tomwalters@570: TEST2_PRINT( "/a_double\0\0\0,d\0\0\0\0\0\0\0\0\0\0" ); tomwalters@570: // 0123012301 2 3 012 3 012301230123 tomwalters@570: TEST2_PRINT( "/a_symbol\0\0\0,S\0\0hello world\0" ); tomwalters@570: // 01230123 012 3 0 1 2 3 tomwalters@570: TEST2_PRINT( "/a_char\0,c\0\0\0\0\0A" ); tomwalters@570: // 012301230 1 2 3 012 3 0 1 2 3 tomwalters@570: TEST2_PRINT( "/a_color\0\0\0\0,r\0\0\0\0\0\0" ); tomwalters@570: // 012301230123012 3 012 3 0 1 2 3 tomwalters@570: TEST2_PRINT( "/a_midimessage\0\0,m\0\0\0\0\0\0" ); tomwalters@570: // 01230123 012 3 tomwalters@570: TEST2_PRINT( "/a_bool\0,T\0\0" ); tomwalters@570: // 01230123 012 3 tomwalters@570: TEST2_PRINT( "/a_bool\0,F\0\0" ); tomwalters@570: // 01230 1 2 3 012 3 tomwalters@570: TEST2_PRINT( "/Nil\0\0\0\0,N\0\0" ); tomwalters@570: // 01230 1 2 3 012 3 tomwalters@570: TEST2_PRINT( "/Inf\0\0\0\0,I\0\0" ); tomwalters@570: tomwalters@570: TEST2_PRINT( "/test\0\0\0,fiT\0\0\0\0\0\0\0\0\0\0\0A" ); tomwalters@570: tomwalters@570: bool exceptionThrown = false; tomwalters@570: try{ tomwalters@570: TEST2_PRINT( "/a_char\0,x\0\0\0\0\0A" ); // unknown type tag 'x' tomwalters@570: }catch( Exception& ){ tomwalters@570: exceptionThrown = true; tomwalters@570: } tomwalters@570: assertEqual( exceptionThrown, true ); tomwalters@570: tomwalters@570: }catch( Exception& e ){ tomwalters@570: std::cout << "unexpected exception: " << e.what() << "\n"; tomwalters@570: unexpectedExceptionCaught = true; tomwalters@570: } tomwalters@570: assertEqual( unexpectedExceptionCaught, false ); tomwalters@570: } tomwalters@570: tomwalters@570: //----------------------------------------------------------------------- tomwalters@570: tomwalters@570: // pack a message and then unpack it and check that the result is the same tomwalters@570: // also print each message tomwalters@570: // repeat the process inside a bundle tomwalters@570: tomwalters@570: #define TEST_PACK_UNPACK0( addressPattern, argument, value, recieveGetter ) \ tomwalters@570: { \ tomwalters@570: memset( buffer, 0x74, bufferSize ); \ tomwalters@570: OutboundPacketStream ps( buffer, bufferSize ); \ tomwalters@570: ps << BeginMessage( addressPattern ) \ tomwalters@570: << argument \ tomwalters@570: << EndMessage;\ tomwalters@570: assertEqual( ps.IsReady(), true );\ tomwalters@570: ReceivedMessage m( ReceivedPacket(ps.Data(), ps.Size()) );\ tomwalters@570: std::cout << m << "\n";\ tomwalters@570: assertEqual( m.ArgumentsBegin()-> recieveGetter () , value );\ tomwalters@570: } \ tomwalters@570: { \ tomwalters@570: memset( buffer, 0x74, bufferSize ); \ tomwalters@570: OutboundPacketStream ps( buffer, bufferSize ); \ tomwalters@570: ps << BeginBundle( 1234 ) \ tomwalters@570: << BeginMessage( addressPattern ) \ tomwalters@570: << argument \ tomwalters@570: << EndMessage \ tomwalters@570: << EndBundle;\ tomwalters@570: assertEqual( ps.IsReady(), true );\ tomwalters@570: ReceivedBundle b( ReceivedPacket(ps.Data(), ps.Size()) );\ tomwalters@570: ReceivedMessage m( *b.ElementsBegin() );\ tomwalters@570: std::cout << m << "\n";\ tomwalters@570: assertEqual( m.ArgumentsBegin()-> recieveGetter () , value );\ tomwalters@570: } tomwalters@570: tomwalters@570: #define TEST_PACK_UNPACK( addressPattern, argument, type, recieveGetter ) \ tomwalters@570: { \ tomwalters@570: memset( buffer, 0x74, bufferSize ); \ tomwalters@570: OutboundPacketStream ps( buffer, bufferSize ); \ tomwalters@570: ps << BeginMessage( addressPattern ) \ tomwalters@570: << argument \ tomwalters@570: << EndMessage;\ tomwalters@570: assertEqual( ps.IsReady(), true );\ tomwalters@570: ReceivedMessage m( ReceivedPacket(ps.Data(), ps.Size()) );\ tomwalters@570: std::cout << m << "\n";\ tomwalters@570: assertEqual( m.ArgumentsBegin()-> recieveGetter () , ( type ) argument );\ tomwalters@570: } \ tomwalters@570: { \ tomwalters@570: memset( buffer, 0x74, bufferSize ); \ tomwalters@570: OutboundPacketStream ps( buffer, bufferSize ); \ tomwalters@570: ps << BeginBundle( 1234 ) \ tomwalters@570: << BeginMessage( addressPattern ) \ tomwalters@570: << argument \ tomwalters@570: << EndMessage \ tomwalters@570: << EndBundle;\ tomwalters@570: assertEqual( ps.IsReady(), true );\ tomwalters@570: ReceivedBundle b( ReceivedPacket(ps.Data(), ps.Size()) );\ tomwalters@570: ReceivedMessage m( *b.ElementsBegin() );\ tomwalters@570: std::cout << m << "\n";\ tomwalters@570: assertEqual( m.ArgumentsBegin()-> recieveGetter () , ( type ) argument );\ tomwalters@570: } tomwalters@570: tomwalters@570: void test3() tomwalters@570: { tomwalters@570: int bufferSize = 1000; tomwalters@570: char *buffer = AllocateAligned4( bufferSize ); tomwalters@570: tomwalters@570: // single message tests tomwalters@570: // empty message tomwalters@570: { tomwalters@570: memset( buffer, 0x74, bufferSize ); tomwalters@570: OutboundPacketStream ps( buffer, bufferSize ); tomwalters@570: ps << BeginMessage( "/no_arguments" ) tomwalters@570: << EndMessage; tomwalters@570: assertEqual( ps.IsReady(), true ); tomwalters@570: ReceivedMessage m( ReceivedPacket(ps.Data(), ps.Size()) ); tomwalters@570: std::cout << m << "\n";\ tomwalters@570: } tomwalters@570: tomwalters@570: TEST_PACK_UNPACK( "/a_bool", true, bool, AsBool ); tomwalters@570: TEST_PACK_UNPACK( "/a_bool", false, bool, AsBool ); tomwalters@570: TEST_PACK_UNPACK( "/a_bool", (bool)1, bool, AsBool ); tomwalters@570: tomwalters@570: TEST_PACK_UNPACK0( "/nil", Nil, true, IsNil ); tomwalters@570: TEST_PACK_UNPACK0( "/inf", Infinitum, true, IsInfinitum ); tomwalters@570: tomwalters@570: TEST_PACK_UNPACK( "/an_int", (int32)1234, int32, AsInt32 ); tomwalters@570: tomwalters@570: TEST_PACK_UNPACK( "/a_float", 3.1415926f, float, AsFloat ); tomwalters@570: tomwalters@570: TEST_PACK_UNPACK( "/a_char", 'c', char, AsChar ); tomwalters@570: tomwalters@570: TEST_PACK_UNPACK( "/an_rgba_color", RgbaColor(0x22334455), uint32, AsRgbaColor ); tomwalters@570: tomwalters@570: TEST_PACK_UNPACK( "/a_midi_message", MidiMessage(0x7F), uint32, AsMidiMessage ); tomwalters@570: tomwalters@570: TEST_PACK_UNPACK( "/an_int64", (int64)(0xFFFFFFFF), int64, AsInt64 ); tomwalters@570: tomwalters@570: TEST_PACK_UNPACK( "/a_time_tag", TimeTag(0xFFFFFFFF), uint64, AsTimeTag ); tomwalters@570: tomwalters@570: TEST_PACK_UNPACK( "/a_double", (double)3.1415926, double, AsDouble ); tomwalters@570: tomwalters@570: // blob tomwalters@570: { tomwalters@570: char blobData[] = "abcd"; tomwalters@570: memset( buffer, 0x74, bufferSize ); tomwalters@570: OutboundPacketStream ps( buffer, bufferSize ); tomwalters@570: ps << BeginMessage( "/a_blob" ) tomwalters@570: << Blob( blobData, 4 ) tomwalters@570: << EndMessage; tomwalters@570: assertEqual( ps.IsReady(), true ); tomwalters@570: ReceivedMessage m( ReceivedPacket(ps.Data(), ps.Size()) ); tomwalters@570: std::cout << m << "\n"; tomwalters@570: tomwalters@570: const void *value; tomwalters@570: unsigned long size; tomwalters@570: m.ArgumentsBegin()->AsBlob( value, size ); tomwalters@570: assertEqual( size, (unsigned long)4 ); tomwalters@570: assertEqual( (memcmp( value, blobData, 4 ) == 0), true ); tomwalters@570: } tomwalters@570: tomwalters@570: tomwalters@570: TEST_PACK_UNPACK( "/a_string", "hello world", const char*, AsString ); tomwalters@570: tomwalters@570: TEST_PACK_UNPACK( "/a_symbol", Symbol("foobar"), const char*, AsSymbol ); tomwalters@570: tomwalters@570: tomwalters@570: // nested bundles, and multiple messages in bundles... tomwalters@570: tomwalters@570: { tomwalters@570: memset( buffer, 0x74, bufferSize ); tomwalters@570: OutboundPacketStream ps( buffer, bufferSize ); tomwalters@570: ps << BeginBundle() tomwalters@570: << BeginMessage( "/message_one" ) << 1 << 2 << 3 << 4 << EndMessage tomwalters@570: << BeginMessage( "/message_two" ) << 1 << 2 << 3 << 4 << EndMessage tomwalters@570: << BeginMessage( "/message_three" ) << 1 << 2 << 3 << 4 << EndMessage tomwalters@570: << BeginMessage( "/message_four" ) << 1 << 2 << 3 << 4 << EndMessage tomwalters@570: << EndBundle; tomwalters@570: assertEqual( ps.IsReady(), true ); tomwalters@570: ReceivedBundle b( ReceivedPacket(ps.Data(), ps.Size()) ); tomwalters@570: std::cout << b << "\n"; tomwalters@570: } tomwalters@570: } tomwalters@570: tomwalters@570: tomwalters@570: void RunUnitTests() tomwalters@570: { tomwalters@570: test1(); tomwalters@570: test2(); tomwalters@570: test3(); tomwalters@570: PrintTestSummary(); tomwalters@570: } tomwalters@570: tomwalters@570: } // namespace osc tomwalters@570: tomwalters@570: tomwalters@570: #ifndef NO_OSC_TEST_MAIN tomwalters@570: tomwalters@570: int main(int argc, char* argv[]) tomwalters@570: { tomwalters@570: (void)argc; tomwalters@570: (void)argv; tomwalters@570: tomwalters@570: osc::RunUnitTests(); tomwalters@570: } tomwalters@570: tomwalters@570: #endif