diff options
author | Mike Buland <eichlan@xagasoft.com> | 2023-08-09 13:00:44 -0700 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2023-08-09 13:00:44 -0700 |
commit | 7fbaf6242fb8371d226f7980849261826e329f98 (patch) | |
tree | b43f923de35f9b0c8c686e000cbfca83ec9fa070 /src | |
parent | 9fc845c1746a83afc4e847895913851576945000 (diff) | |
download | libbu++-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.
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/rununits.cpp | 100 |
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 | ||
12 | typedef Bu::List<Bu::Blob> BlobList; | ||
13 | |||
11 | Bu::Blob getSuiteName( const Bu::Blob &bSuiteExec ) | 14 | Bu::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 | ||
26 | Bu::Json *runSuite( const Bu::Blob &bSuiteExec ) | 29 | Bu::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 | ||
51 | typedef Bu::List<Bu::Blob> BlobList; | ||
52 | |||
53 | BlobList getSuitePaths( const Bu::Blob &bDir ) | 70 | BlobList 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 | ||
83 | int main( int /*argc*/, char * /*argv*/[] ) | 100 | int 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; |