@@ -21,7 +21,8 @@ vector<UnitTest *> UnitTest::tests;
21
21
// / Run all the tests unless a non-empty set of names is passed in.
22
22
// / In which case, only the named tests in the set are run.
23
23
// / \param testNames is the set of names
24
- void UnitTest::run (set<string> &testNames)
24
+ // / \return number of failed tests
25
+ int UnitTest::run (set<string> &testNames)
25
26
26
27
{
27
28
int total = 0 ;
@@ -42,6 +43,7 @@ void UnitTest::run(set<string> &testNames)
42
43
}
43
44
std::cerr << " ==============================" << std::endl;
44
45
std::cerr << passed << " /" << total << " tests passed." << std::endl;
46
+ return total - passed;
45
47
}
46
48
47
49
// / Create list of the absolute path of all tests to be run
@@ -75,6 +77,24 @@ void gatherDataTests(const string &dirname,set<string> &testNames,vector<string>
75
77
}
76
78
}
77
79
80
+ // / \brief This function performs a saturating add on two numbers where the
81
+ // / result is to be used as an exit code for a CLI application.
82
+ // /
83
+ // / \param current The current return code
84
+ // / \param add A number to add to the current return code
85
+ // / \return A number that can be used as an exit code up to 255.
86
+ int add_exit_code (int current, int add) {
87
+ const int CLAMP = 255 ;
88
+ int ret = current + add;
89
+ if (current < 0 || // Sanity checks
90
+ current > CLAMP ||
91
+ ret < current || // Can only happen due to overflow
92
+ ret > CLAMP) { // Check clamp value
93
+ ret = CLAMP; // Set to max exit code
94
+ }
95
+ return ret;
96
+ }
97
+
78
98
int main (int argc, char **argv) {
79
99
bool runUnitTests = true ;
80
100
bool runDataTests = true ;
@@ -85,7 +105,7 @@ int main(int argc, char **argv) {
85
105
set<string> dataTestNames;
86
106
string dirname (" ../datatests" );
87
107
string sleighdirname (" ../../../../../../.." );
88
- if (argc > 0 ) {
108
+ while (argc > 0 ) {
89
109
string command (argv[0 ]);
90
110
if (command == " -path" ) {
91
111
dirname = argv[1 ];
@@ -109,30 +129,39 @@ int main(int argc, char **argv) {
109
129
argv += 1 ;
110
130
argc -= 1 ;
111
131
}
112
- }
113
- if (argc > 0 ) {
114
- string command (argv[0 ]);
115
- if (command == " unittests" ) {
132
+ else if (command == " unittests" ) {
116
133
runUnitTests = true ;
117
134
runDataTests = false ; // Run only unit tests
118
135
unitTestNames.insert (argv + 1 ,argv + argc);
136
+ break ;
119
137
}
120
138
else if (command == " datatests" ) {
121
139
runUnitTests = false ; // Run only data-tests
122
140
runDataTests = true ;
123
141
dataTestNames.insert (argv + 1 ,argv + argc);
142
+ break ;
124
143
}
125
144
else {
126
- cout << " USAGE: ghidra_test [-path <datatestdir>] [[unittests|datatests] [testname1 testname2 ...]]" << endl;
145
+ cout << " USAGE: ghidra_test [-usesleighenv] [-sleighpath <sleighdir>] [-path <datatestdir>] [[unittests|datatests] [testname1 testname2 ...]]" << endl;
146
+ return -1 ;
127
147
}
128
148
}
129
149
startDecompilerLibrary (sleighdirname.c_str ());
130
- if (runUnitTests)
131
- UnitTest::run (unitTestNames);
150
+
151
+ // Keep track of failed tests as return code to indicate failures, clamped at
152
+ // max exit code value in add_exit_code
153
+ int failedTests = 0 ;
154
+ if (runUnitTests) {
155
+ int errors = UnitTest::run (unitTestNames);
156
+ failedTests = add_exit_code (failedTests, errors);
157
+ }
132
158
if (runDataTests) {
133
159
vector<string> testFiles;
134
160
gatherDataTests (dirname,dataTestNames,testFiles);
135
161
cout << endl << endl;
136
- FunctionTestCollection::runTestFiles (testFiles,cout);
162
+ int errors = FunctionTestCollection::runTestFiles (testFiles,cout);
163
+ failedTests = add_exit_code (failedTests, errors);
137
164
}
165
+
166
+ return failedTests;
138
167
}
0 commit comments