diff options
author | Mike Buland <eichlan@xagasoft.com> | 2010-05-25 02:29:05 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2010-05-25 02:29:05 +0000 |
commit | a0c6e974a3393642bda80fed5bce464a6c6cf2ec (patch) | |
tree | 30e3098bb9a4da43bf5f94bd1e1944e070144615 /src | |
parent | ecc191f590f76584a14c9c51727412b0b7b3086e (diff) | |
download | libbu++-a0c6e974a3393642bda80fed5bce464a6c6cf2ec.tar.gz libbu++-a0c6e974a3393642bda80fed5bce464a6c6cf2ec.tar.bz2 libbu++-a0c6e974a3393642bda80fed5bce464a6c6cf2ec.tar.xz libbu++-a0c6e974a3393642bda80fed5bce464a6c6cf2ec.zip |
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.
Diffstat (limited to '')
-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 | ||