Skip to content

Commit cd09ea0

Browse files
ekilmercaheckman
authored andcommitted
Fixes CLI argument parsing
Accept more than one option for specifying test paths. Support non-zero exit code when tests fail Return a non-zero exit code (saturated to max value 255, even if more than 255 tests fail) indicating number of failed tests. This is helpful when running in a script (like in CI) to detect failures instead of detecting failures through manual visual inspection of output text.
1 parent 0241b2b commit cd09ea0

File tree

4 files changed

+46
-13
lines changed

4 files changed

+46
-13
lines changed

Ghidra/Features/Decompiler/src/decompile/cpp/test.cc

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,18 @@
1414
* limitations under the License.
1515
*/
1616
#include "test.hh"
17+
18+
#include <algorithm>
19+
1720
#include "libdecomp.hh"
1821

1922
vector<UnitTest *> UnitTest::tests;
2023

2124
/// Run all the tests unless a non-empty set of names is passed in.
2225
/// In which case, only the named tests in the set are run.
2326
/// \param testNames is the set of names
24-
void UnitTest::run(set<string> &testNames)
27+
/// \return number of failed tests
28+
int UnitTest::run(set<string> &testNames)
2529

2630
{
2731
int total = 0;
@@ -42,6 +46,7 @@ void UnitTest::run(set<string> &testNames)
4246
}
4347
std::cerr << "==============================" << std::endl;
4448
std::cerr << passed << "/" << total << " tests passed." << std::endl;
49+
return total - passed;
4550
}
4651

4752
/// Create list of the absolute path of all tests to be run
@@ -75,6 +80,24 @@ void gatherDataTests(const string &dirname,set<string> &testNames,vector<string>
7580
}
7681
}
7782

83+
/// \brief This function performs a saturating add on two numbers where the
84+
/// result is to be used as an exit code for a CLI application.
85+
///
86+
/// \param current The current return code
87+
/// \param add A number to add to the current return code
88+
/// \return A number that can be used as an exit code up to 255.
89+
int add_exit_code(int current, int add) {
90+
const int CLAMP = 255;
91+
int ret = current + add;
92+
if (current < 0 || // Sanity checks
93+
current > CLAMP ||
94+
ret < current || // Can only happen due to overflow
95+
ret > CLAMP) { // Check clamp value
96+
ret = CLAMP; // Set to max exit code
97+
}
98+
return ret;
99+
}
100+
78101
int main(int argc, char **argv) {
79102
bool runUnitTests = true;
80103
bool runDataTests = true;
@@ -85,7 +108,7 @@ int main(int argc, char **argv) {
85108
set<string> dataTestNames;
86109
string dirname("../datatests");
87110
string sleighdirname("../../../../../../..");
88-
if (argc > 0) {
111+
while (argc > 0) {
89112
string command(argv[0]);
90113
if (command == "-path") {
91114
dirname = argv[1];
@@ -109,30 +132,39 @@ int main(int argc, char **argv) {
109132
argv += 1;
110133
argc -= 1;
111134
}
112-
}
113-
if (argc > 0) {
114-
string command(argv[0]);
115-
if (command == "unittests") {
135+
else if (command == "unittests") {
116136
runUnitTests = true;
117137
runDataTests = false; // Run only unit tests
118138
unitTestNames.insert(argv + 1,argv + argc);
139+
break;
119140
}
120141
else if (command == "datatests") {
121142
runUnitTests = false; // Run only data-tests
122143
runDataTests = true;
123144
dataTestNames.insert(argv + 1,argv + argc);
145+
break;
124146
}
125147
else {
126-
cout << "USAGE: ghidra_test [-path <datatestdir>] [[unittests|datatests] [testname1 testname2 ...]]" << endl;
148+
cout << "USAGE: ghidra_test [-usesleighenv] [-sleighpath <sleighdir>] [-path <datatestdir>] [[unittests|datatests] [testname1 testname2 ...]]" << endl;
149+
return -1;
127150
}
128151
}
129152
startDecompilerLibrary(sleighdirname.c_str());
130-
if (runUnitTests)
131-
UnitTest::run(unitTestNames);
153+
154+
// Keep track of failed tests as return code to indicate failures, clamped at
155+
// max exit code value in add_exit_code
156+
int failedTests = 0;
157+
if (runUnitTests) {
158+
int errors = UnitTest::run(unitTestNames);
159+
failedTests = add_exit_code(failedTests, errors);
160+
}
132161
if (runDataTests) {
133162
vector<string> testFiles;
134163
gatherDataTests(dirname,dataTestNames,testFiles);
135164
cout << endl << endl;
136-
FunctionTestCollection::runTestFiles(testFiles,cout);
165+
int errors = FunctionTestCollection::runTestFiles(testFiles,cout);
166+
failedTests = add_exit_code(failedTests, errors);
137167
}
168+
169+
return failedTests;
138170
}

Ghidra/Features/Decompiler/src/decompile/cpp/test.hh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ struct UnitTest {
5454
tests.push_back(this);
5555
}
5656

57-
static void run(std::set<std::string> &testNames); ///< Run all the instantiated tests
57+
static int run(std::set<std::string> &testNames); ///< Run all the instantiated tests
5858
};
5959

6060

Ghidra/Features/Decompiler/src/decompile/cpp/testfunction.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ void FunctionTestCollection::runTests(list<string> &lateStream)
304304
/// Run through all XML files in the given list, processing each in turn.
305305
/// \param testFiles is the given list of test files
306306
/// \param s is the output stream to print results to
307-
void FunctionTestCollection::runTestFiles(const vector<string> &testFiles,ostream &s)
307+
int FunctionTestCollection::runTestFiles(const vector<string> &testFiles,ostream &s)
308308

309309
{
310310
int4 totalTestsApplied = 0;
@@ -344,4 +344,5 @@ void FunctionTestCollection::runTestFiles(const vector<string> &testFiles,ostrea
344344
if (iter == failures.end()) break;
345345
}
346346
}
347+
return totalTestsApplied - totalTestsSucceeded;
347348
}

Ghidra/Features/Decompiler/src/decompile/cpp/testfunction.hh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public:
9191
void restoreXml(DocumentStorage &store,const Element *el); ///< Load tests from a \<decompilertest> tag.
9292
void restoreXmlOldForm(DocumentStorage &store,const Element *el); ///< Load tests from \<binaryimage> tag.
9393
void runTests(list<string> &lateStream); ///< Run the script and perform the tests
94-
static void runTestFiles(const vector<string> &testFiles,ostream &s); ///< Run tests for each listed file
94+
static int runTestFiles(const vector<string> &testFiles,ostream &s); ///< Run tests for each listed file
9595
};
9696

9797
#endif

0 commit comments

Comments
 (0)