// vim: syntax=cpp /* * Copyright (C) 2007-2010 Xagasoft, All rights reserved. * * This file is part of the libbu++ library and is released under the * terms of the license contained in the file LICENSE. */ #include "bu/fstring.h" #include "bu/file.h" #include "bu/myriad.h" #include "bu/myriadstream.h" #include "bu/array.h" #include "bu/sio.h" #include using namespace Bu; suite Myriad { test setSize { FString sFileName("myriad-XXXXXXX"); File fMyriad = tempFile( sFileName ); Myriad m( fMyriad ); m.initialize( 64 ); MyriadStream ms = m.openStream( m.createStream() ); ms.setSize( 150 ); ms.setPos( 145 ); char stuff[10]; unitTest( ms.read( stuff, 10 ) == 5 ); ms.setSize( 12 ); unitTest( ms.read( stuff, 10 ) == 0 ); unitTest( ms.write( "hello", 5 ) == 5 ); unitTest( ms.tell() == 17 ); ms.setSize( 500 ); unitTest( ms.tell() == 17 ); } void addBlock( Stream &s, bool bAppend=true ) { if( bAppend ) s.setPosEnd( 0 ); int iSize = (random()%1016)+8; s.write( &iSize, 4 ); char *buf = new char[iSize-8]; for( int j = 0; j < iSize-8; j++ ) { buf[j] = (j+iSize)%256; } s.write( buf, iSize-8 ); delete[] buf; iSize = ~iSize; s.write( &iSize, 4 ); } void verifyBlock( Stream &s ) { int iSize, iInv; if( s.read( &iSize, 4 ) == 0 ) return; if( iSize < 8 || iSize > 1024 ) throw ExceptionBase("Read bad data, %d", iSize ); char *buf = new char[iSize-8]; if( s.read( buf, iSize-8 ) < (size_t)iSize-8 ) { delete[] buf; throw ExceptionBase("Block failed verify (insuffient block data)."); } for( int j = 0; j < iSize-8; j++ ) { if( buf[j] != (char)((j+iSize)%256) ) { char b = buf[j]; delete[] buf; throw ExceptionBase("Block failed computed data verify (%02X==%02X).", b, (char)((j+iSize)%256) ); } } delete[] buf; if( s.read( &iInv, 4 ) < 4 ) throw ExceptionBase("Block failed verify (insufficient data)."); if( iInv != ~iSize ) throw ExceptionBase("Block failed inversion verify."); } void verifyStream( Stream &s ) { s.setPos( 0 ); while( !s.isEos() ) verifyBlock( s ); } test stressGrow { FString sFileName("myriad-XXXXXXX"); File fMyriad = tempFile( sFileName ); Myriad m( fMyriad ); m.initialize( 64 ); Array aStreams; for( int j = 0; j < 5; j++ ) { aStreams.append( m.createStream() ); } srandom( 512 ); for( int j = 0; j < 2500; j++ ) { switch( random()%5 ) { case 0: aStreams.append( m.createStream() ); break; case 1: if( aStreams.getSize() > 0 ) { int iStream = random()%aStreams.getSize(); { MyriadStream ms = m.openStream( aStreams[iStream] ); verifyStream( ms ); } m.deleteStream( aStreams[iStream] ); Array::iterator i = aStreams.begin(); for( int k = 0; k < iStream; k++ ) i++; aStreams.erase( i ); } break; default: if( aStreams.getSize() == 0 ) { aStreams.append( m.createStream() ); } { int iStream = random()%aStreams.getSize(); MyriadStream ms = m.openStream( aStreams[iStream] ); addBlock( ms ); verifyStream( ms ); } break; } } for( Array::iterator i = aStreams.begin(); i; i++ ) { MyriadStream ms = m.openStream( *i ); verifyStream( ms ); } } test stressTruncate { FString sFileName("myriad-XXXXXXX"); File fMyriad = tempFile( sFileName ); Myriad m( fMyriad ); m.initialize( 64 ); Array aStream; for( int j = 0; j < 5; j++ ) { aStream.append( m.createStream() ); } srandom( 1024 ); char b; for( int iter = 0; iter < 2500; iter++ ) { for( Array::iterator i = aStream.begin(); i; i++ ) { MyriadStream ms = m.openStream( *i ); addBlock( ms, false ); ms.setSize( ms.tell() ); unitTest( ms.read( &b, 1 ) == 0 ); ms.setPos( 0 ); verifyBlock( ms ); unitTest( ms.read( &b, 1 ) == 0 ); } } } }