aboutsummaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/mkunit.cpp34
-rw-r--r--src/tools/rununits.cpp186
2 files changed, 217 insertions, 3 deletions
diff --git a/src/tools/mkunit.cpp b/src/tools/mkunit.cpp
index f6ea669..5711c42 100644
--- a/src/tools/mkunit.cpp
+++ b/src/tools/mkunit.cpp
@@ -42,6 +42,7 @@ enum TokType
42 tokTest, 42 tokTest,
43 tokChar, 43 tokChar,
44 tokBlock, 44 tokBlock,
45 tokCleanup,
45 tokEof 46 tokEof
46}; 47};
47 48
@@ -54,6 +55,7 @@ Bu::Formatter &operator<<( Bu::Formatter &f, TokType t )
54 case tokTest: return f << "tokTest"; 55 case tokTest: return f << "tokTest";
55 case tokChar: return f << "tokChar"; 56 case tokChar: return f << "tokChar";
56 case tokBlock: return f << "tokBlock"; 57 case tokBlock: return f << "tokBlock";
58 case tokCleanup: return f << "tokCleanup";
57 case tokEof: return f << "tokEof"; 59 case tokEof: return f << "tokEof";
58 } 60 }
59 61
@@ -193,6 +195,8 @@ public:
193 { 195 {
194 if( sTok == "test" ) 196 if( sTok == "test" )
195 return tokTest; 197 return tokTest;
198 else if( sTok == "cleanup" )
199 return tokCleanup;
196 else 200 else
197 { 201 {
198 v = sTok; 202 v = sTok;
@@ -361,6 +365,15 @@ public:
361 s.lTest.append( t ); 365 s.lTest.append( t );
362 } 366 }
363 break; 367 break;
368
369 case tokCleanup:
370 {
371 if( nextToken( v, sWs, iL, iC ) != tokBlock )
372 throw Bu::ExceptionBase("%d:%d: Expected "
373 "{...} block.",
374 iL, iC );
375 }
376 break;
364 377
365 case tokChar: 378 case tokChar:
366 if( v.get<char>() == '}' ) 379 if( v.get<char>() == '}' )
@@ -438,7 +451,7 @@ public:
438 for( TestList::iterator i = s.lTest.begin(); i; i++ ) 451 for( TestList::iterator i = s.lTest.begin(); i; i++ )
439 { 452 {
440 f << "\t\tadd( static_cast<Bu::UnitSuite::Test>(" 453 f << "\t\tadd( static_cast<Bu::UnitSuite::Test>("
441 "&" << sClass << "::" << (*i).sName << "), \"" 454 "&" << sClass << "::_test_" << (*i).sName << "), \""
442 << (*i).sName << "\", Bu::UnitSuite::" 455 << (*i).sName << "\", Bu::UnitSuite::"
443 "expectPass );" << f.nl; 456 "expectPass );" << f.nl;
444 } 457 }
@@ -481,9 +494,24 @@ public:
481 "{...} block.", 494 "{...} block.",
482 iL, iC ); 495 iL, iC );
483 496
484 f << "\tvoid " << t.sName << "()" 497 f << "void _test_" << t.sName << "()"
498 << f.nl << "#line " << iL
499 << " \"" << sIn << "\"" << f.nl << " "
500 << v << f.nl;
501 }
502 break;
503
504 case tokCleanup:
505 {
506 fOut.write( sWs );
507 if( nextToken( v, sWs, iL, iC ) != tokBlock )
508 throw Bu::ExceptionBase("%d:%d: Expected "
509 "{...} block.",
510 iL, iC );
511
512 f << "void cleanup()"
485 << f.nl << "#line " << iL 513 << f.nl << "#line " << iL
486 << " \"" << sIn << "\"" << f.nl 514 << " \"" << sIn << "\"" << f.nl << " "
487 << v << f.nl; 515 << v << f.nl;
488 } 516 }
489 break; 517 break;
diff --git a/src/tools/rununits.cpp b/src/tools/rununits.cpp
new file mode 100644
index 0000000..769d3ab
--- /dev/null
+++ b/src/tools/rununits.cpp
@@ -0,0 +1,186 @@
1#include <bu/sio.h>
2#include <bu/json.h>
3#include <bu/process.h>
4#include <bu/optparser.h>
5#include <bu/blob.h>
6#include <bu/blobbuilder.h>
7
8#include <sys/types.h>
9#include <dirent.h>
10
11Bu::Blob getSuiteName( const Bu::Blob &bSuiteExec )
12{
13 Bu::Process proc(
14 Bu::Process::StdOut,
15 bSuiteExec.getData(),
16 bSuiteExec.getData(),
17 "--print-name",
18 NULL
19 );
20
21 Bu::String sResult = proc.readAll().trimWhitespace();
22 Bu::Blob bRet( sResult.getStr(), sResult.getSize() );
23 return bRet;
24}
25
26Bu::Json *runSuite( const Bu::Blob &bSuiteExec )
27{
28 Bu::Process proc(
29 Bu::Process::StdOut,
30 bSuiteExec.getData(),
31 bSuiteExec.getData(),
32 "--interop",
33 NULL
34 );
35 Bu::BlobBuilder bbReport;
36 while( proc.isRunning() )
37 {
38 int iRead = 0;
39 char dRead[4096];
40 iRead = proc.read( dRead, 4096 );
41 if( iRead > 0 )
42 {
43 bbReport.append( dRead, iRead );
44 }
45 }
46 Bu::Json *pReport = new Bu::Json();
47 pReport->parse( bbReport.getBlob() );
48 return pReport;
49}
50
51typedef Bu::List<Bu::Blob> BlobList;
52
53BlobList getSuitePaths( const Bu::Blob &bDir )
54{
55 BlobList lPaths;
56 DIR *dir = opendir( bDir.getData() );
57 if( dir == NULL )
58 {
59 Bu::println("Could not open directory: %1").arg( bDir );
60 return lPaths;
61 }
62 struct dirent *de = NULL;
63 while( (de = readdir( dir )) != NULL )
64 {
65 if( de->d_type != DT_REG )
66 continue;
67
68 Bu::BlobBuilder bbPath;
69 bbPath.append( bDir );
70 bbPath.append("/");
71 bbPath.append( de->d_name );
72 Bu::Blob bPath = bbPath.getBlob();
73 if( access( bPath.getData(), X_OK ) != 0 )
74 continue;
75
76 lPaths.append( bPath );
77 }
78 closedir( dir );
79
80 return lPaths;
81}
82
83int main( int /*argc*/, char * /*argv*/[] )
84{
85 Bu::Blob bDir("unit");
86 BlobList lPaths = getSuitePaths( bDir );
87
88 int iNumLen = Bu::String("%1").arg( lPaths.getSize() ).end().getSize();
89 int iMaxSuiteName = 0;
90 Bu::Hash<Bu::Blob, Bu::Blob> hName;
91 for( BlobList::iterator i = lPaths.begin(); i; i++ )
92 {
93 Bu::Blob bSuiteName = getSuiteName( *i );
94 if( iMaxSuiteName < bSuiteName.getSize() )
95 iMaxSuiteName = bSuiteName.getSize();
96 hName.insert( *i, bSuiteName );
97 }
98
99 Bu::List<Bu::Json *> lReport;
100
101 int iTest = 0;
102 for( BlobList::iterator i = lPaths.begin(); i; i++ )
103 {
104 iTest++;
105 Bu::Blob bSuiteName = hName.get( *i );
106 Bu::print("\rRunning test suite [%1/%2]: %3")
107 .arg( iTest, Bu::Fmt().width( iNumLen ).right() )
108 .arg( lPaths.getSize(), Bu::Fmt().width( iNumLen ) )
109 .arg( bSuiteName, Bu::Fmt().width( iMaxSuiteName ).fill(' ').left() );
110 Bu::sio << Bu::sio.flush;
111
112 Bu::Json *pReport = runSuite( (*i) );
113 int iUnexpected = 0;
114 int iTotal = 0;
115 iTotal = (*pReport)["tests"].getSize();
116 for( int j = 0; j < iTotal; j++ )
117 {
118 if( !((*pReport)["tests"][j]["expected"].getString() ==
119 (*pReport)["tests"][j]["result"].getString()) )
120 {
121 iUnexpected++;
122 }
123 }
124 if( iUnexpected == 0 )
125 {
126 delete pReport;
127 }
128 else
129 {
130 lReport.append( pReport );
131 }
132 }
133 Bu::println("\rCompleted %1 unit test suites.%2")
134 .arg( lPaths.getSize(), Bu::Fmt().width( iNumLen ) )
135 .arg( Bu::Blob(""), Bu::Fmt().width( iMaxSuiteName ).fill(' ').left() );
136
137 if( lReport.getSize() == 0 )
138 {
139 Bu::println("\nNothing unexpected in unit tests.");
140 }
141 else
142 {
143 for( Bu::List<Bu::Json *>::iterator i = lReport.begin(); i; i++ )
144 {
145 Bu::println("\nUnexpected results in: %1")
146 .arg( (**i)["suite"].getString().get() );
147
148 for( Bu::Json::iterator iTest = (**i)["tests"].begin();
149 iTest; iTest++ )
150 {
151 if( (**iTest)["expected"].getString() ==
152 (**iTest)["result"].getString() )
153 {
154 continue;
155 }
156
157 Bu::println(" %1: unexpected %2")
158 .arg( (**iTest)["name"].getString().get() )
159 .arg( (**iTest)["result"].getString().get() );
160 if( (**iTest).has("fail") )
161 {
162 if( (**iTest)["fail"].has("action") )
163 {
164 Bu::println(" unitTest( %1 );")
165 .arg( (**iTest)["fail"]["action"].getString().get() );
166 Bu::println(" at %1:%2")
167 .arg( (**iTest)["fail"]["file"].getString().get() )
168 .arg( (int)(**iTest)["fail"]["line"].getNumber() );
169 }
170 else if( (**iTest)["fail"].has("what") )
171 {
172 Bu::println(" Unexpected exception: %1")
173 .arg( (**iTest)["fail"]["what"].getString().get() );
174 }
175 }
176 else
177 {
178 Bu::println(" No further details.");
179 }
180 }
181 delete *i;
182 }
183 }
184
185 return 0;
186}