From a0c6e974a3393642bda80fed5bce464a6c6cf2ec Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 25 May 2010 02:29:05 +0000 Subject: We now have a portable tempfile function, cool, it compiles on windows. Fixed a bug in Socket, it wasn't closing the socket in all exception cases. Also fixed a few things in the unit test framework, going to add some more helpers soon. --- src/file.cpp | 39 ++++++++++++++++----- src/socket.cpp | 11 ++++-- src/unit/myriad.unit | 3 +- src/unitsuite.cpp | 95 ++++++++++++++++++++++++++++++++++------------------ src/unitsuite.h | 4 ++- 5 files changed, 106 insertions(+), 46 deletions(-) diff --git a/src/file.cpp b/src/file.cpp index a0c3fd8..0566ee8 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -12,6 +12,7 @@ #include #include #include // for mkstemp +#include #include "bu/config.h" @@ -189,21 +190,41 @@ void Bu::File::setBlocking( bool bBlocking ) Bu::File Bu::File::tempFile( Bu::FString &sName ) { -#ifndef WIN32 - int afh_d = mkstemp( sName.getStr() ); + uint32_t iX; + iX = time( NULL ) + getpid(); + int iXes; + for( iXes = sName.getSize()-1; iXes >= 0; iXes-- ) + { + if( sName[iXes] != 'X' ) + break; + } + iXes++; + if( iXes == sName.getSize() ) + throw Bu::ExceptionBase("Invalid temporary filename template."); + for( int iter = 0; iter < 100; iter++ ) + { + for( int j = iXes; j < sName.getSize(); j++ ) + { + iX = (1103515245 * iX + 12345); + sName[j] = ('A'+(iX%26)) | ((iX&0x1000)?(0x20):(0)); + } - return Bu::File( afh_d ); -#else - return Bu::File( sName, Bu::File::Write|Bu::File::Create ); -#endif + try + { + return Bu::File( sName, Bu::File::Read|Bu::File::Write + |Bu::File::Create|Bu::File::Exclusive ); + } catch(...) { } + } + throw Bu::FileException("Failed to create unique temporary file after 100" + " iterations."); } void Bu::File::setSize( long iSize ) { -#ifndef WIN32 - ftruncate( fd, iSize ); +#ifdef WIN32 + chsize( fd, iSize ); #else -#warning Bu::File::setSize not implemented on this platform + ftruncate( fd, iSize ); #endif } diff --git a/src/socket.cpp b/src/socket.cpp index 41e0763..696db1e 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -77,6 +77,7 @@ Bu::Socket::Socket( const Bu::FString &sAddr, int nPort, int nTimeout ) : if( (ret = bu_getaddrinfo( sAddr.getStr(), ibuf, &aiHints, &pAddr )) != 0 ) { + close(); throw Bu::SocketException("Couldn't resolve hostname %s (%s).\n", sAddr.getStr(), bu_gai_strerror(ret)); } @@ -151,7 +152,11 @@ size_t Bu::Socket::read( void *pBuf, size_t nBytes ) FD_SET(nSocket, &rfds); struct timeval tv = {0, 0}; if( bu_select( nSocket+1, &rfds, NULL, NULL, &tv ) < 0 ) - throw SocketException( SocketException::cRead, strerror(errno) ); + { + int iErr = errno; + close(); + throw SocketException( SocketException::cRead, strerror(iErr) ); + } if( FD_ISSET( nSocket, &rfds ) || bBlocking ) { int nRead = TEMP_FAILURE_RETRY( @@ -176,7 +181,9 @@ size_t Bu::Socket::read( void *pBuf, size_t nBytes ) } if( errno == EAGAIN ) return 0; - throw SocketException( SocketException::cRead, strerror(errno) ); + int iErr = errno; + close(); + throw SocketException( SocketException::cRead, strerror(iErr) ); #endif } return nRead; diff --git a/src/unit/myriad.unit b/src/unit/myriad.unit index cf861a3..ed121cc 100644 --- a/src/unit/myriad.unit +++ b/src/unit/myriad.unit @@ -76,8 +76,7 @@ suite Myriad { FString sFileName("myriad-XXXXXXX"); - tempFile( sFileName ); - File fMyriad( sFileName, File::WriteNew|File::Read ); + File fMyriad = tempFile( sFileName ); Myriad m( fMyriad ); m.initialize( 64 ); diff --git a/src/unitsuite.cpp b/src/unitsuite.cpp index 51cca10..711b9b5 100644 --- a/src/unitsuite.cpp +++ b/src/unitsuite.cpp @@ -7,16 +7,21 @@ #include "bu/unitsuite.h" #include "bu/file.h" +#include "bu/sio.h" + +using namespace Bu; #include Bu::UnitSuite::UnitSuite() : - iOptions( 0 ) + iOptions( 0 ), + iNameWidth( 0 ) { } Bu::UnitSuite::UnitSuite( int iOptions ) : - iOptions( iOptions ) + iOptions( iOptions ), + iNameWidth( 0 ) { } @@ -33,37 +38,46 @@ int Bu::UnitSuite::run( int /*argc*/, char * /*argv */ [] ) int iUFail = 0; for( TestList::iterator i = lTests.begin(); i != lTests.end(); i++ ) { - printf("%s: ", i->sName.getStr() ); - fflush( stdout ); + sio << Fmt( iNameWidth+3, Fmt::Left ).fill('.') << i->sName + << sio.flush; try { (this->*(i->fTest))(); switch( i->eExpect ) { - case expectPass: printf("expected pass.\n"); iEPass++; break; - case expectFail: printf("unexpected pass.\n"); iUPass++; break; + case expectPass: + sio << "pass." << sio.nl; + iEPass++; + break; + + case expectFail: + sio << "unexpected pass." << sio.nl; + iUPass++; + break; } } catch( Failed &e ) { switch( i->eExpect ) { - case expectPass: printf("unexpected "); iUFail++; break; - case expectFail: printf("expected "); iEFail++; break; + case expectPass: + sio << "unexpected "; + iUFail++; + break; + + case expectFail: + sio << "expected "; + iEFail++; + break; } if( e.bFile ) { - printf("fail in unitTest(%s). (%s:%d)\n", - e.str.getStr(), - e.sFile.getStr(), - e.nLine - ); + sio << "fail in unitTest(" << e.str << "). (" << e.sFile + << ":" << e.nLine << ")." << sio.nl; } else { - printf("fail in unitTest(%s).\n", - e.str.getStr() - ); + sio << "fail in unitTest(" << e.str << ")." << sio.nl; } if( (iOptions & optStopOnError) ) @@ -73,10 +87,17 @@ int Bu::UnitSuite::run( int /*argc*/, char * /*argv */ [] ) { switch( i->eExpect ) { - case expectPass: printf("unexpected "); iUFail++; break; - case expectFail: printf("expected "); iEFail++; break; + case expectPass: + sio << "unexpected "; + iUFail++; + break; + + case expectFail: + sio << "expected "; + iEFail++; + break; } - printf("fail with unknown exception. what: %s\n", e.what() ); + sio << "fail with unknown exception. what: " << e.what() << sio.nl; if( (iOptions & optStopOnError) ) return 0; @@ -85,25 +106,32 @@ int Bu::UnitSuite::run( int /*argc*/, char * /*argv */ [] ) { switch( i->eExpect ) { - case expectPass: printf("unexpected "); iUFail++; break; - case expectFail: printf("expected "); iEFail++; break; + case expectPass: + sio << "unexpected "; + iUFail++; + break; + + case expectFail: + sio << "expected "; + iEFail++; + break; } - printf("fail with external exception.\n"); + sio << "fail with external exception." << sio.nl; if( (iOptions & optStopOnError) ) return 0; } } - printf("\nReport:\n" - "\tTotal tests run: %ld\n" - "\tExpected passes: %d\n" - "\tExpected failures: %d\n" - "\tUnexpected passes: %d\n" - "\tUnexpected failures: %d\n\n", - lTests.getSize(), iEPass, iEFail, iUPass, iUFail ); + sio << sio.nl + << "Report:" << sio.nl + << "\tTotal tests run: " << lTests.getSize() << sio.nl + << "\tExpected passes: " << iEPass << sio.nl + << "\tExpected failures: " << iEFail << sio.nl + << "\tUnexpected passes: " << iUPass << sio.nl + << "\tUnexpected failures: " << iUFail << sio.nl << sio.nl; if( iUPass == 0 && iUFail == 0 ) - printf("\tNothing unexpected.\n\n"); + sio << "\tNothing unexpected." << sio.nl << sio.nl; for( StrList::iterator i = lFileCleanup.begin(); i; i++ ) { @@ -113,10 +141,11 @@ int Bu::UnitSuite::run( int /*argc*/, char * /*argv */ [] ) return 0; } -void Bu::UnitSuite::tempFile( Bu::FString &sFileName ) +Bu::File Bu::UnitSuite::tempFile( Bu::FString &sFileName ) { - Bu::File::tempFile( sFileName ); + Bu::File f = Bu::File::tempFile( sFileName ); lFileCleanup.append( sFileName ); + return f; } void Bu::UnitSuite::add( Test fTest, const Bu::FString &sName, Expect e ) @@ -133,6 +162,8 @@ void Bu::UnitSuite::add( Test fTest, const Bu::FString &sName, Expect e ) } ti.fTest = fTest; lTests.append( ti ); + if( iNameWidth < ti.sName.getSize() ) + iNameWidth = ti.sName.getSize(); } void Bu::UnitSuite::setName( const FString &sName ) diff --git a/src/unitsuite.h b/src/unitsuite.h index 7d026c2..74aac6f 100644 --- a/src/unitsuite.h +++ b/src/unitsuite.h @@ -11,6 +11,7 @@ #include #include "bu/list.h" #include "fstring.h" +#include "bu/file.h" namespace Bu { @@ -61,7 +62,7 @@ namespace Bu int run( int argc=0, char *argv[]=NULL ); - void tempFile( Bu::FString &sFileName ); + Bu::File tempFile( Bu::FString &sFileName ); typedef void (UnitSuite::*Test)(); @@ -110,6 +111,7 @@ namespace Bu typedef Bu::List StrList; StrList lFileCleanup; + int iNameWidth; }; } -- cgit v1.2.3