diff options
| -rw-r--r-- | src/file.cpp | 39 | ||||
| -rw-r--r-- | src/socket.cpp | 11 | ||||
| -rw-r--r-- | src/unit/myriad.unit | 3 | ||||
| -rw-r--r-- | src/unitsuite.cpp | 95 | ||||
| -rw-r--r-- | 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 @@ | |||
| 12 | #include <fcntl.h> | 12 | #include <fcntl.h> |
| 13 | #include <unistd.h> | 13 | #include <unistd.h> |
| 14 | #include <stdlib.h> // for mkstemp | 14 | #include <stdlib.h> // for mkstemp |
| 15 | #include <time.h> | ||
| 15 | 16 | ||
| 16 | #include "bu/config.h" | 17 | #include "bu/config.h" |
| 17 | 18 | ||
| @@ -189,21 +190,41 @@ void Bu::File::setBlocking( bool bBlocking ) | |||
| 189 | 190 | ||
| 190 | Bu::File Bu::File::tempFile( Bu::FString &sName ) | 191 | Bu::File Bu::File::tempFile( Bu::FString &sName ) |
| 191 | { | 192 | { |
| 192 | #ifndef WIN32 | 193 | uint32_t iX; |
| 193 | int afh_d = mkstemp( sName.getStr() ); | 194 | iX = time( NULL ) + getpid(); |
| 195 | int iXes; | ||
| 196 | for( iXes = sName.getSize()-1; iXes >= 0; iXes-- ) | ||
| 197 | { | ||
| 198 | if( sName[iXes] != 'X' ) | ||
| 199 | break; | ||
| 200 | } | ||
| 201 | iXes++; | ||
| 202 | if( iXes == sName.getSize() ) | ||
| 203 | throw Bu::ExceptionBase("Invalid temporary filename template."); | ||
| 204 | for( int iter = 0; iter < 100; iter++ ) | ||
| 205 | { | ||
| 206 | for( int j = iXes; j < sName.getSize(); j++ ) | ||
| 207 | { | ||
| 208 | iX = (1103515245 * iX + 12345); | ||
| 209 | sName[j] = ('A'+(iX%26)) | ((iX&0x1000)?(0x20):(0)); | ||
| 210 | } | ||
| 194 | 211 | ||
| 195 | return Bu::File( afh_d ); | 212 | try |
| 196 | #else | 213 | { |
| 197 | return Bu::File( sName, Bu::File::Write|Bu::File::Create ); | 214 | return Bu::File( sName, Bu::File::Read|Bu::File::Write |
| 198 | #endif | 215 | |Bu::File::Create|Bu::File::Exclusive ); |
| 216 | } catch(...) { } | ||
| 217 | } | ||
| 218 | throw Bu::FileException("Failed to create unique temporary file after 100" | ||
| 219 | " iterations."); | ||
| 199 | } | 220 | } |
| 200 | 221 | ||
| 201 | void Bu::File::setSize( long iSize ) | 222 | void Bu::File::setSize( long iSize ) |
| 202 | { | 223 | { |
| 203 | #ifndef WIN32 | 224 | #ifdef WIN32 |
| 204 | ftruncate( fd, iSize ); | 225 | chsize( fd, iSize ); |
| 205 | #else | 226 | #else |
| 206 | #warning Bu::File::setSize not implemented on this platform | 227 | ftruncate( fd, iSize ); |
| 207 | #endif | 228 | #endif |
| 208 | } | 229 | } |
| 209 | 230 | ||
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 ) : | |||
| 77 | if( (ret = bu_getaddrinfo( | 77 | if( (ret = bu_getaddrinfo( |
| 78 | sAddr.getStr(), ibuf, &aiHints, &pAddr )) != 0 ) | 78 | sAddr.getStr(), ibuf, &aiHints, &pAddr )) != 0 ) |
| 79 | { | 79 | { |
| 80 | close(); | ||
| 80 | throw Bu::SocketException("Couldn't resolve hostname %s (%s).\n", | 81 | throw Bu::SocketException("Couldn't resolve hostname %s (%s).\n", |
| 81 | sAddr.getStr(), bu_gai_strerror(ret)); | 82 | sAddr.getStr(), bu_gai_strerror(ret)); |
| 82 | } | 83 | } |
| @@ -151,7 +152,11 @@ size_t Bu::Socket::read( void *pBuf, size_t nBytes ) | |||
| 151 | FD_SET(nSocket, &rfds); | 152 | FD_SET(nSocket, &rfds); |
| 152 | struct timeval tv = {0, 0}; | 153 | struct timeval tv = {0, 0}; |
| 153 | if( bu_select( nSocket+1, &rfds, NULL, NULL, &tv ) < 0 ) | 154 | if( bu_select( nSocket+1, &rfds, NULL, NULL, &tv ) < 0 ) |
| 154 | throw SocketException( SocketException::cRead, strerror(errno) ); | 155 | { |
| 156 | int iErr = errno; | ||
| 157 | close(); | ||
| 158 | throw SocketException( SocketException::cRead, strerror(iErr) ); | ||
| 159 | } | ||
| 155 | if( FD_ISSET( nSocket, &rfds ) || bBlocking ) | 160 | if( FD_ISSET( nSocket, &rfds ) || bBlocking ) |
| 156 | { | 161 | { |
| 157 | int nRead = TEMP_FAILURE_RETRY( | 162 | int nRead = TEMP_FAILURE_RETRY( |
| @@ -176,7 +181,9 @@ size_t Bu::Socket::read( void *pBuf, size_t nBytes ) | |||
| 176 | } | 181 | } |
| 177 | if( errno == EAGAIN ) | 182 | if( errno == EAGAIN ) |
| 178 | return 0; | 183 | return 0; |
| 179 | throw SocketException( SocketException::cRead, strerror(errno) ); | 184 | int iErr = errno; |
| 185 | close(); | ||
| 186 | throw SocketException( SocketException::cRead, strerror(iErr) ); | ||
| 180 | #endif | 187 | #endif |
| 181 | } | 188 | } |
| 182 | return nRead; | 189 | 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 | |||
| 76 | { | 76 | { |
| 77 | FString sFileName("myriad-XXXXXXX"); | 77 | FString sFileName("myriad-XXXXXXX"); |
| 78 | 78 | ||
| 79 | tempFile( sFileName ); | 79 | File fMyriad = tempFile( sFileName ); |
| 80 | File fMyriad( sFileName, File::WriteNew|File::Read ); | ||
| 81 | Myriad m( fMyriad ); | 80 | Myriad m( fMyriad ); |
| 82 | m.initialize( 64 ); | 81 | m.initialize( 64 ); |
| 83 | 82 | ||
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 @@ | |||
| 7 | 7 | ||
| 8 | #include "bu/unitsuite.h" | 8 | #include "bu/unitsuite.h" |
| 9 | #include "bu/file.h" | 9 | #include "bu/file.h" |
| 10 | #include "bu/sio.h" | ||
| 11 | |||
| 12 | using namespace Bu; | ||
| 10 | 13 | ||
| 11 | #include <unistd.h> | 14 | #include <unistd.h> |
| 12 | 15 | ||
| 13 | Bu::UnitSuite::UnitSuite() : | 16 | Bu::UnitSuite::UnitSuite() : |
| 14 | iOptions( 0 ) | 17 | iOptions( 0 ), |
| 18 | iNameWidth( 0 ) | ||
| 15 | { | 19 | { |
| 16 | } | 20 | } |
| 17 | 21 | ||
| 18 | Bu::UnitSuite::UnitSuite( int iOptions ) : | 22 | Bu::UnitSuite::UnitSuite( int iOptions ) : |
| 19 | iOptions( iOptions ) | 23 | iOptions( iOptions ), |
| 24 | iNameWidth( 0 ) | ||
| 20 | { | 25 | { |
| 21 | } | 26 | } |
| 22 | 27 | ||
| @@ -33,37 +38,46 @@ int Bu::UnitSuite::run( int /*argc*/, char * /*argv */ [] ) | |||
| 33 | int iUFail = 0; | 38 | int iUFail = 0; |
| 34 | for( TestList::iterator i = lTests.begin(); i != lTests.end(); i++ ) | 39 | for( TestList::iterator i = lTests.begin(); i != lTests.end(); i++ ) |
| 35 | { | 40 | { |
| 36 | printf("%s: ", i->sName.getStr() ); | 41 | sio << Fmt( iNameWidth+3, Fmt::Left ).fill('.') << i->sName |
| 37 | fflush( stdout ); | 42 | << sio.flush; |
| 38 | try | 43 | try |
| 39 | { | 44 | { |
| 40 | (this->*(i->fTest))(); | 45 | (this->*(i->fTest))(); |
| 41 | switch( i->eExpect ) | 46 | switch( i->eExpect ) |
| 42 | { | 47 | { |
| 43 | case expectPass: printf("expected pass.\n"); iEPass++; break; | 48 | case expectPass: |
| 44 | case expectFail: printf("unexpected pass.\n"); iUPass++; break; | 49 | sio << "pass." << sio.nl; |
| 50 | iEPass++; | ||
| 51 | break; | ||
| 52 | |||
| 53 | case expectFail: | ||
| 54 | sio << "unexpected pass." << sio.nl; | ||
| 55 | iUPass++; | ||
| 56 | break; | ||
| 45 | } | 57 | } |
| 46 | } | 58 | } |
| 47 | catch( Failed &e ) | 59 | catch( Failed &e ) |
| 48 | { | 60 | { |
| 49 | switch( i->eExpect ) | 61 | switch( i->eExpect ) |
| 50 | { | 62 | { |
| 51 | case expectPass: printf("unexpected "); iUFail++; break; | 63 | case expectPass: |
| 52 | case expectFail: printf("expected "); iEFail++; break; | 64 | sio << "unexpected "; |
| 65 | iUFail++; | ||
| 66 | break; | ||
| 67 | |||
| 68 | case expectFail: | ||
| 69 | sio << "expected "; | ||
| 70 | iEFail++; | ||
| 71 | break; | ||
| 53 | } | 72 | } |
| 54 | if( e.bFile ) | 73 | if( e.bFile ) |
| 55 | { | 74 | { |
| 56 | printf("fail in unitTest(%s). (%s:%d)\n", | 75 | sio << "fail in unitTest(" << e.str << "). (" << e.sFile |
| 57 | e.str.getStr(), | 76 | << ":" << e.nLine << ")." << sio.nl; |
| 58 | e.sFile.getStr(), | ||
| 59 | e.nLine | ||
| 60 | ); | ||
| 61 | } | 77 | } |
| 62 | else | 78 | else |
| 63 | { | 79 | { |
| 64 | printf("fail in unitTest(%s).\n", | 80 | sio << "fail in unitTest(" << e.str << ")." << sio.nl; |
| 65 | e.str.getStr() | ||
| 66 | ); | ||
| 67 | } | 81 | } |
| 68 | 82 | ||
| 69 | if( (iOptions & optStopOnError) ) | 83 | if( (iOptions & optStopOnError) ) |
| @@ -73,10 +87,17 @@ int Bu::UnitSuite::run( int /*argc*/, char * /*argv */ [] ) | |||
| 73 | { | 87 | { |
| 74 | switch( i->eExpect ) | 88 | switch( i->eExpect ) |
| 75 | { | 89 | { |
| 76 | case expectPass: printf("unexpected "); iUFail++; break; | 90 | case expectPass: |
| 77 | case expectFail: printf("expected "); iEFail++; break; | 91 | sio << "unexpected "; |
| 92 | iUFail++; | ||
| 93 | break; | ||
| 94 | |||
| 95 | case expectFail: | ||
| 96 | sio << "expected "; | ||
| 97 | iEFail++; | ||
| 98 | break; | ||
| 78 | } | 99 | } |
| 79 | printf("fail with unknown exception. what: %s\n", e.what() ); | 100 | sio << "fail with unknown exception. what: " << e.what() << sio.nl; |
| 80 | 101 | ||
| 81 | if( (iOptions & optStopOnError) ) | 102 | if( (iOptions & optStopOnError) ) |
| 82 | return 0; | 103 | return 0; |
| @@ -85,25 +106,32 @@ int Bu::UnitSuite::run( int /*argc*/, char * /*argv */ [] ) | |||
| 85 | { | 106 | { |
| 86 | switch( i->eExpect ) | 107 | switch( i->eExpect ) |
| 87 | { | 108 | { |
| 88 | case expectPass: printf("unexpected "); iUFail++; break; | 109 | case expectPass: |
| 89 | case expectFail: printf("expected "); iEFail++; break; | 110 | sio << "unexpected "; |
| 111 | iUFail++; | ||
| 112 | break; | ||
| 113 | |||
| 114 | case expectFail: | ||
| 115 | sio << "expected "; | ||
| 116 | iEFail++; | ||
| 117 | break; | ||
| 90 | } | 118 | } |
| 91 | printf("fail with external exception.\n"); | 119 | sio << "fail with external exception." << sio.nl; |
| 92 | 120 | ||
| 93 | if( (iOptions & optStopOnError) ) | 121 | if( (iOptions & optStopOnError) ) |
| 94 | return 0; | 122 | return 0; |
| 95 | } | 123 | } |
| 96 | } | 124 | } |
| 97 | 125 | ||
| 98 | printf("\nReport:\n" | 126 | sio << sio.nl |
| 99 | "\tTotal tests run: %ld\n" | 127 | << "Report:" << sio.nl |
| 100 | "\tExpected passes: %d\n" | 128 | << "\tTotal tests run: " << lTests.getSize() << sio.nl |
| 101 | "\tExpected failures: %d\n" | 129 | << "\tExpected passes: " << iEPass << sio.nl |
| 102 | "\tUnexpected passes: %d\n" | 130 | << "\tExpected failures: " << iEFail << sio.nl |
| 103 | "\tUnexpected failures: %d\n\n", | 131 | << "\tUnexpected passes: " << iUPass << sio.nl |
| 104 | lTests.getSize(), iEPass, iEFail, iUPass, iUFail ); | 132 | << "\tUnexpected failures: " << iUFail << sio.nl << sio.nl; |
| 105 | if( iUPass == 0 && iUFail == 0 ) | 133 | if( iUPass == 0 && iUFail == 0 ) |
| 106 | printf("\tNothing unexpected.\n\n"); | 134 | sio << "\tNothing unexpected." << sio.nl << sio.nl; |
| 107 | 135 | ||
| 108 | for( StrList::iterator i = lFileCleanup.begin(); i; i++ ) | 136 | for( StrList::iterator i = lFileCleanup.begin(); i; i++ ) |
| 109 | { | 137 | { |
| @@ -113,10 +141,11 @@ int Bu::UnitSuite::run( int /*argc*/, char * /*argv */ [] ) | |||
| 113 | return 0; | 141 | return 0; |
| 114 | } | 142 | } |
| 115 | 143 | ||
| 116 | void Bu::UnitSuite::tempFile( Bu::FString &sFileName ) | 144 | Bu::File Bu::UnitSuite::tempFile( Bu::FString &sFileName ) |
| 117 | { | 145 | { |
| 118 | Bu::File::tempFile( sFileName ); | 146 | Bu::File f = Bu::File::tempFile( sFileName ); |
| 119 | lFileCleanup.append( sFileName ); | 147 | lFileCleanup.append( sFileName ); |
| 148 | return f; | ||
| 120 | } | 149 | } |
| 121 | 150 | ||
| 122 | void Bu::UnitSuite::add( Test fTest, const Bu::FString &sName, Expect e ) | 151 | 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 ) | |||
| 133 | } | 162 | } |
| 134 | ti.fTest = fTest; | 163 | ti.fTest = fTest; |
| 135 | lTests.append( ti ); | 164 | lTests.append( ti ); |
| 165 | if( iNameWidth < ti.sName.getSize() ) | ||
| 166 | iNameWidth = ti.sName.getSize(); | ||
| 136 | } | 167 | } |
| 137 | 168 | ||
| 138 | void Bu::UnitSuite::setName( const FString &sName ) | 169 | 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 @@ | |||
| 11 | #include <stdint.h> | 11 | #include <stdint.h> |
| 12 | #include "bu/list.h" | 12 | #include "bu/list.h" |
| 13 | #include "fstring.h" | 13 | #include "fstring.h" |
| 14 | #include "bu/file.h" | ||
| 14 | 15 | ||
| 15 | namespace Bu | 16 | namespace Bu |
| 16 | { | 17 | { |
| @@ -61,7 +62,7 @@ namespace Bu | |||
| 61 | 62 | ||
| 62 | int run( int argc=0, char *argv[]=NULL ); | 63 | int run( int argc=0, char *argv[]=NULL ); |
| 63 | 64 | ||
| 64 | void tempFile( Bu::FString &sFileName ); | 65 | Bu::File tempFile( Bu::FString &sFileName ); |
| 65 | 66 | ||
| 66 | typedef void (UnitSuite::*Test)(); | 67 | typedef void (UnitSuite::*Test)(); |
| 67 | 68 | ||
| @@ -110,6 +111,7 @@ namespace Bu | |||
| 110 | 111 | ||
| 111 | typedef Bu::List<Bu::FString> StrList; | 112 | typedef Bu::List<Bu::FString> StrList; |
| 112 | StrList lFileCleanup; | 113 | StrList lFileCleanup; |
| 114 | int iNameWidth; | ||
| 113 | }; | 115 | }; |
| 114 | } | 116 | } |
| 115 | 117 | ||
