mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
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.
This commit is contained in:
parent
0241b2b97e
commit
cd09ea0c4a
4 changed files with 46 additions and 13 deletions
|
@ -14,6 +14,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
#include "test.hh"
|
#include "test.hh"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "libdecomp.hh"
|
#include "libdecomp.hh"
|
||||||
|
|
||||||
vector<UnitTest *> UnitTest::tests;
|
vector<UnitTest *> UnitTest::tests;
|
||||||
|
@ -21,7 +24,8 @@ vector<UnitTest *> UnitTest::tests;
|
||||||
/// Run all the tests unless a non-empty set of names is passed in.
|
/// Run all the tests unless a non-empty set of names is passed in.
|
||||||
/// In which case, only the named tests in the set are run.
|
/// In which case, only the named tests in the set are run.
|
||||||
/// \param testNames is the set of names
|
/// \param testNames is the set of names
|
||||||
void UnitTest::run(set<string> &testNames)
|
/// \return number of failed tests
|
||||||
|
int UnitTest::run(set<string> &testNames)
|
||||||
|
|
||||||
{
|
{
|
||||||
int total = 0;
|
int total = 0;
|
||||||
|
@ -42,6 +46,7 @@ void UnitTest::run(set<string> &testNames)
|
||||||
}
|
}
|
||||||
std::cerr << "==============================" << std::endl;
|
std::cerr << "==============================" << std::endl;
|
||||||
std::cerr << passed << "/" << total << " tests passed." << std::endl;
|
std::cerr << passed << "/" << total << " tests passed." << std::endl;
|
||||||
|
return total - passed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create list of the absolute path of all tests to be run
|
/// 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>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief This function performs a saturating add on two numbers where the
|
||||||
|
/// result is to be used as an exit code for a CLI application.
|
||||||
|
///
|
||||||
|
/// \param current The current return code
|
||||||
|
/// \param add A number to add to the current return code
|
||||||
|
/// \return A number that can be used as an exit code up to 255.
|
||||||
|
int add_exit_code(int current, int add) {
|
||||||
|
const int CLAMP = 255;
|
||||||
|
int ret = current + add;
|
||||||
|
if (current < 0 || // Sanity checks
|
||||||
|
current > CLAMP ||
|
||||||
|
ret < current || // Can only happen due to overflow
|
||||||
|
ret > CLAMP) { // Check clamp value
|
||||||
|
ret = CLAMP; // Set to max exit code
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
bool runUnitTests = true;
|
bool runUnitTests = true;
|
||||||
bool runDataTests = true;
|
bool runDataTests = true;
|
||||||
|
@ -85,7 +108,7 @@ int main(int argc, char **argv) {
|
||||||
set<string> dataTestNames;
|
set<string> dataTestNames;
|
||||||
string dirname("../datatests");
|
string dirname("../datatests");
|
||||||
string sleighdirname("../../../../../../..");
|
string sleighdirname("../../../../../../..");
|
||||||
if (argc > 0) {
|
while (argc > 0) {
|
||||||
string command(argv[0]);
|
string command(argv[0]);
|
||||||
if (command == "-path") {
|
if (command == "-path") {
|
||||||
dirname = argv[1];
|
dirname = argv[1];
|
||||||
|
@ -109,30 +132,39 @@ int main(int argc, char **argv) {
|
||||||
argv += 1;
|
argv += 1;
|
||||||
argc -= 1;
|
argc -= 1;
|
||||||
}
|
}
|
||||||
}
|
else if (command == "unittests") {
|
||||||
if (argc > 0) {
|
|
||||||
string command(argv[0]);
|
|
||||||
if (command == "unittests") {
|
|
||||||
runUnitTests = true;
|
runUnitTests = true;
|
||||||
runDataTests = false; // Run only unit tests
|
runDataTests = false; // Run only unit tests
|
||||||
unitTestNames.insert(argv + 1,argv + argc);
|
unitTestNames.insert(argv + 1,argv + argc);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (command == "datatests") {
|
else if (command == "datatests") {
|
||||||
runUnitTests = false; // Run only data-tests
|
runUnitTests = false; // Run only data-tests
|
||||||
runDataTests = true;
|
runDataTests = true;
|
||||||
dataTestNames.insert(argv + 1,argv + argc);
|
dataTestNames.insert(argv + 1,argv + argc);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cout << "USAGE: ghidra_test [-path <datatestdir>] [[unittests|datatests] [testname1 testname2 ...]]" << endl;
|
cout << "USAGE: ghidra_test [-usesleighenv] [-sleighpath <sleighdir>] [-path <datatestdir>] [[unittests|datatests] [testname1 testname2 ...]]" << endl;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
startDecompilerLibrary(sleighdirname.c_str());
|
startDecompilerLibrary(sleighdirname.c_str());
|
||||||
if (runUnitTests)
|
|
||||||
UnitTest::run(unitTestNames);
|
// Keep track of failed tests as return code to indicate failures, clamped at
|
||||||
|
// max exit code value in add_exit_code
|
||||||
|
int failedTests = 0;
|
||||||
|
if (runUnitTests) {
|
||||||
|
int errors = UnitTest::run(unitTestNames);
|
||||||
|
failedTests = add_exit_code(failedTests, errors);
|
||||||
|
}
|
||||||
if (runDataTests) {
|
if (runDataTests) {
|
||||||
vector<string> testFiles;
|
vector<string> testFiles;
|
||||||
gatherDataTests(dirname,dataTestNames,testFiles);
|
gatherDataTests(dirname,dataTestNames,testFiles);
|
||||||
cout << endl << endl;
|
cout << endl << endl;
|
||||||
FunctionTestCollection::runTestFiles(testFiles,cout);
|
int errors = FunctionTestCollection::runTestFiles(testFiles,cout);
|
||||||
|
failedTests = add_exit_code(failedTests, errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return failedTests;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ struct UnitTest {
|
||||||
tests.push_back(this);
|
tests.push_back(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void run(std::set<std::string> &testNames); ///< Run all the instantiated tests
|
static int run(std::set<std::string> &testNames); ///< Run all the instantiated tests
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -304,7 +304,7 @@ void FunctionTestCollection::runTests(list<string> &lateStream)
|
||||||
/// Run through all XML files in the given list, processing each in turn.
|
/// Run through all XML files in the given list, processing each in turn.
|
||||||
/// \param testFiles is the given list of test files
|
/// \param testFiles is the given list of test files
|
||||||
/// \param s is the output stream to print results to
|
/// \param s is the output stream to print results to
|
||||||
void FunctionTestCollection::runTestFiles(const vector<string> &testFiles,ostream &s)
|
int FunctionTestCollection::runTestFiles(const vector<string> &testFiles,ostream &s)
|
||||||
|
|
||||||
{
|
{
|
||||||
int4 totalTestsApplied = 0;
|
int4 totalTestsApplied = 0;
|
||||||
|
@ -344,4 +344,5 @@ void FunctionTestCollection::runTestFiles(const vector<string> &testFiles,ostrea
|
||||||
if (iter == failures.end()) break;
|
if (iter == failures.end()) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return totalTestsApplied - totalTestsSucceeded;
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ public:
|
||||||
void restoreXml(DocumentStorage &store,const Element *el); ///< Load tests from a \<decompilertest> tag.
|
void restoreXml(DocumentStorage &store,const Element *el); ///< Load tests from a \<decompilertest> tag.
|
||||||
void restoreXmlOldForm(DocumentStorage &store,const Element *el); ///< Load tests from \<binaryimage> tag.
|
void restoreXmlOldForm(DocumentStorage &store,const Element *el); ///< Load tests from \<binaryimage> tag.
|
||||||
void runTests(list<string> &lateStream); ///< Run the script and perform the tests
|
void runTests(list<string> &lateStream); ///< Run the script and perform the tests
|
||||||
static void runTestFiles(const vector<string> &testFiles,ostream &s); ///< Run tests for each listed file
|
static int runTestFiles(const vector<string> &testFiles,ostream &s); ///< Run tests for each listed file
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue