aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2010-05-25 02:29:05 +0000
committerMike Buland <eichlan@xagasoft.com>2010-05-25 02:29:05 +0000
commita0c6e974a3393642bda80fed5bce464a6c6cf2ec (patch)
tree30e3098bb9a4da43bf5f94bd1e1944e070144615
parentecc191f590f76584a14c9c51727412b0b7b3086e (diff)
downloadlibbu++-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.
-rw-r--r--src/file.cpp39
-rw-r--r--src/socket.cpp11
-rw-r--r--src/unit/myriad.unit3
-rw-r--r--src/unitsuite.cpp95
-rw-r--r--src/unitsuite.h4
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
190Bu::File Bu::File::tempFile( Bu::FString &sName ) 191Bu::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
201void Bu::File::setSize( long iSize ) 222void 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
12using namespace Bu;
10 13
11#include <unistd.h> 14#include <unistd.h>
12 15
13Bu::UnitSuite::UnitSuite() : 16Bu::UnitSuite::UnitSuite() :
14 iOptions( 0 ) 17 iOptions( 0 ),
18 iNameWidth( 0 )
15{ 19{
16} 20}
17 21
18Bu::UnitSuite::UnitSuite( int iOptions ) : 22Bu::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
116void Bu::UnitSuite::tempFile( Bu::FString &sFileName ) 144Bu::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
122void Bu::UnitSuite::add( Test fTest, const Bu::FString &sName, Expect e ) 151void 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
138void Bu::UnitSuite::setName( const FString &sName ) 169void 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
15namespace Bu 16namespace 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