aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2023-08-09 13:00:44 -0700
committerMike Buland <eichlan@xagasoft.com>2023-08-09 13:00:44 -0700
commit7fbaf6242fb8371d226f7980849261826e329f98 (patch)
treeb43f923de35f9b0c8c686e000cbfca83ec9fa070
parent9fc845c1746a83afc4e847895913851576945000 (diff)
downloadlibbu++-7fbaf6242fb8371d226f7980849261826e329f98.tar.gz
libbu++-7fbaf6242fb8371d226f7980849261826e329f98.tar.bz2
libbu++-7fbaf6242fb8371d226f7980849261826e329f98.tar.xz
libbu++-7fbaf6242fb8371d226f7980849261826e329f98.zip
rununits now tracks status and has options.
When we encounter unexpected test results it logs them to a status file, subsequent runs without other options will only re-run the tests that had unexpected results, updating the status file as you go. When all tests are returning expected results again then the status file is deleted and the next run will process all tests again. Of course, the --all parameter will force it to run all tests and ignore the current status.
-rw-r--r--src/tools/rununits.cpp100
1 files changed, 92 insertions, 8 deletions
diff --git a/src/tools/rununits.cpp b/src/tools/rununits.cpp
index 769d3ab..ee847d3 100644
--- a/src/tools/rununits.cpp
+++ b/src/tools/rununits.cpp
@@ -4,10 +4,13 @@
4#include <bu/optparser.h> 4#include <bu/optparser.h>
5#include <bu/blob.h> 5#include <bu/blob.h>
6#include <bu/blobbuilder.h> 6#include <bu/blobbuilder.h>
7#include <bu/file.h>
7 8
8#include <sys/types.h> 9#include <sys/types.h>
9#include <dirent.h> 10#include <dirent.h>
10 11
12typedef Bu::List<Bu::Blob> BlobList;
13
11Bu::Blob getSuiteName( const Bu::Blob &bSuiteExec ) 14Bu::Blob getSuiteName( const Bu::Blob &bSuiteExec )
12{ 15{
13 Bu::Process proc( 16 Bu::Process proc(
@@ -23,14 +26,29 @@ Bu::Blob getSuiteName( const Bu::Blob &bSuiteExec )
23 return bRet; 26 return bRet;
24} 27}
25 28
26Bu::Json *runSuite( const Bu::Blob &bSuiteExec ) 29Bu::Json *runSuite( const Bu::Blob &bSuiteExec, Bu::Json *pSuiteStatus=NULL )
27{ 30{
31 BlobList lCmd;
32 lCmd.append( bSuiteExec );
33 lCmd.append( "--interop" );
34 if( pSuiteStatus != NULL )
35 {
36 for( Bu::Json::iterator i = (*pSuiteStatus)["tests"].begin(); i; i++ )
37 {
38 lCmd.append( (**i)["name"].getString().get() );
39 }
40 }
41 char **argv = new char*[lCmd.getSize()+1];
42 int j = 0;
43 for( BlobList::iterator i = lCmd.begin(); i; j++, i++ )
44 {
45 argv[j] = (*i).getData();
46 }
47 argv[lCmd.getSize()] = NULL;
28 Bu::Process proc( 48 Bu::Process proc(
29 Bu::Process::StdOut, 49 Bu::Process::StdOut,
30 bSuiteExec.getData(), 50 bSuiteExec.getData(),
31 bSuiteExec.getData(), 51 argv
32 "--interop",
33 NULL
34 ); 52 );
35 Bu::BlobBuilder bbReport; 53 Bu::BlobBuilder bbReport;
36 while( proc.isRunning() ) 54 while( proc.isRunning() )
@@ -43,13 +61,12 @@ Bu::Json *runSuite( const Bu::Blob &bSuiteExec )
43 bbReport.append( dRead, iRead ); 61 bbReport.append( dRead, iRead );
44 } 62 }
45 } 63 }
64 delete[] argv;
46 Bu::Json *pReport = new Bu::Json(); 65 Bu::Json *pReport = new Bu::Json();
47 pReport->parse( bbReport.getBlob() ); 66 pReport->parse( bbReport.getBlob() );
48 return pReport; 67 return pReport;
49} 68}
50 69
51typedef Bu::List<Bu::Blob> BlobList;
52
53BlobList getSuitePaths( const Bu::Blob &bDir ) 70BlobList getSuitePaths( const Bu::Blob &bDir )
54{ 71{
55 BlobList lPaths; 72 BlobList lPaths;
@@ -80,10 +97,54 @@ BlobList getSuitePaths( const Bu::Blob &bDir )
80 return lPaths; 97 return lPaths;
81} 98}
82 99
83int main( int /*argc*/, char * /*argv*/[] ) 100int main( int argc, char *argv[] )
84{ 101{
85 Bu::Blob bDir("unit"); 102 Bu::Blob bDir("unit");
103 bool bAll = false;
104 bool bHasStatus = false;
105 Bu::Json jsLastStatus;
106
107 Bu::OptParser options;
108 options.addOption( bDir, 'p', "path", "Directory to look for unit tests.");
109 options.addOption( bAll, 'a', "all", "Execute all tests, ignoring state.");
110 options.setOverride("all", "true");
111 options.addHelpOption();
112 options.parse( argc, argv );
113
114 if( !bAll )
115 {
116 try
117 {
118 Bu::String sData =
119 Bu::File("rununits.status.json", Bu::File::Read )
120 .readAll();
121 jsLastStatus.parse( sData );
122 bHasStatus = true;
123 Bu::println("Current status loaded, created: %1")
124 .arg( jsLastStatus["date"].getString().get() );
125 }
126 catch(...)
127 {
128 }
129 }
130
86 BlobList lPaths = getSuitePaths( bDir ); 131 BlobList lPaths = getSuitePaths( bDir );
132 Bu::Hash<Bu::Blob, Bu::Json *> hStatusSuitesByPath;
133
134 if( bHasStatus )
135 {
136 BlobList lNewPaths;
137 for( Bu::Json::iterator i = jsLastStatus["suites"].begin(); i; i++ )
138 {
139 hStatusSuitesByPath.insert( (**i)["path"].getString().get(), (*i) );
140 }
141 for( BlobList::iterator i = lPaths.begin(); i; i++ )
142 {
143 if( hStatusSuitesByPath.has( *i ) )
144 lNewPaths.append( *i );
145 }
146 lPaths = lNewPaths;
147 }
87 148
88 int iNumLen = Bu::String("%1").arg( lPaths.getSize() ).end().getSize(); 149 int iNumLen = Bu::String("%1").arg( lPaths.getSize() ).end().getSize();
89 int iMaxSuiteName = 0; 150 int iMaxSuiteName = 0;
@@ -109,7 +170,13 @@ int main( int /*argc*/, char * /*argv*/[] )
109 .arg( bSuiteName, Bu::Fmt().width( iMaxSuiteName ).fill(' ').left() ); 170 .arg( bSuiteName, Bu::Fmt().width( iMaxSuiteName ).fill(' ').left() );
110 Bu::sio << Bu::sio.flush; 171 Bu::sio << Bu::sio.flush;
111 172
112 Bu::Json *pReport = runSuite( (*i) ); 173 Bu::Json *pSuiteStatus = NULL;
174 if( bHasStatus )
175 {
176 pSuiteStatus = hStatusSuitesByPath.get( *i );
177 }
178 Bu::Json *pReport = runSuite( (*i), pSuiteStatus );
179 pReport->insert("path", *i );
113 int iUnexpected = 0; 180 int iUnexpected = 0;
114 int iTotal = 0; 181 int iTotal = 0;
115 iTotal = (*pReport)["tests"].getSize(); 182 iTotal = (*pReport)["tests"].getSize();
@@ -137,13 +204,23 @@ int main( int /*argc*/, char * /*argv*/[] )
137 if( lReport.getSize() == 0 ) 204 if( lReport.getSize() == 0 )
138 { 205 {
139 Bu::println("\nNothing unexpected in unit tests."); 206 Bu::println("\nNothing unexpected in unit tests.");
207 unlink("rununits.status.json");
140 } 208 }
141 else 209 else
142 { 210 {
211 Bu::Json jStatus( Bu::Json::Object );
212
213 time_t tNow = time( NULL );
214 jStatus.insert("date", Bu::String(ctime( &tNow )).trimWhitespace() );
215 jStatus.insertArray("suites");
143 for( Bu::List<Bu::Json *>::iterator i = lReport.begin(); i; i++ ) 216 for( Bu::List<Bu::Json *>::iterator i = lReport.begin(); i; i++ )
144 { 217 {
145 Bu::println("\nUnexpected results in: %1") 218 Bu::println("\nUnexpected results in: %1")
146 .arg( (**i)["suite"].getString().get() ); 219 .arg( (**i)["suite"].getString().get() );
220 Bu::Json &jStSuite = jStatus["suites"].appendObject();
221 jStSuite.insert("name", (**i)["suite"].getString() );
222 jStSuite.insert("path", (**i)["path"].getString() );
223 Bu::Json &jStTests = jStSuite.insertArray("tests");
147 224
148 for( Bu::Json::iterator iTest = (**i)["tests"].begin(); 225 for( Bu::Json::iterator iTest = (**i)["tests"].begin();
149 iTest; iTest++ ) 226 iTest; iTest++ )
@@ -153,6 +230,10 @@ int main( int /*argc*/, char * /*argv*/[] )
153 { 230 {
154 continue; 231 continue;
155 } 232 }
233 Bu::Json &jsTest = jStTests.appendObject();
234 jsTest.insert("name", (**iTest)["name"].getString() );
235 jsTest.insert("result", (**iTest)["result"].getString() );
236 jsTest.insert("expected", (**iTest)["expected"].getString() );
156 237
157 Bu::println(" %1: unexpected %2") 238 Bu::println(" %1: unexpected %2")
158 .arg( (**iTest)["name"].getString().get() ) 239 .arg( (**iTest)["name"].getString().get() )
@@ -180,6 +261,9 @@ int main( int /*argc*/, char * /*argv*/[] )
180 } 261 }
181 delete *i; 262 delete *i;
182 } 263 }
264
265 Bu::File("rununits.status.json", Bu::File::WriteNew )
266 .write( jStatus.toString() );
183 } 267 }
184 268
185 return 0; 269 return 0;