Skip to content

Commit 54c01cf

Browse files
authored
testrunner: added options -n (no summary) and -d (dry run) / added script to run test cases separately / adjusted some tests (#6049)
This script runs each test case separately so we can uncover cases where it depends on left-over data on the previous one. `CTest` is only running the fixtures separately so that does not.
1 parent 260ae3c commit 54c01cf

16 files changed

+167
-123
lines changed

test/fixture.cpp

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ bool TestFixture::prepareTest(const char testname[])
106106
} else {
107107
std::cout << classname << "::" << mTestname << std::endl;
108108
}
109-
return true;
109+
return !dry_run;
110110
}
111111
return false;
112112
}
@@ -301,8 +301,25 @@ void TestFixture::assertThrowFail(const char * const filename, const unsigned in
301301
void TestFixture::assertNoThrowFail(const char * const filename, const unsigned int linenr) const
302302
{
303303
++fails_counter;
304+
305+
std::string ex_msg;
306+
307+
try {
308+
// cppcheck-suppress rethrowNoCurrentException
309+
throw;
310+
}
311+
catch (const InternalError& e) {
312+
ex_msg = e.errorMessage;
313+
}
314+
catch (const std::exception& e) {
315+
ex_msg = e.what();
316+
}
317+
catch (...) {
318+
ex_msg = "unknown exception";
319+
}
320+
304321
errmsg << getLocationStr(filename, linenr) << ": Assertion failed. "
305-
<< "Unexpected exception was thrown" << std::endl << "_____" << std::endl;
322+
<< "Unexpected exception was thrown: " << ex_msg << std::endl << "_____" << std::endl;
306323

307324
}
308325

@@ -323,7 +340,9 @@ void TestFixture::printHelp()
323340
"\n"
324341
"Options:\n"
325342
" -q Do not print the test cases that have run.\n"
326-
" -h, --help Print this help.\n";
343+
" -h, --help Print this help.\n"
344+
" -n Print no summaries.\n"
345+
" -d Do not execute the tests.\n";
327346
}
328347

329348
void TestFixture::run(const std::string &str)
@@ -355,6 +374,7 @@ void TestFixture::run(const std::string &str)
355374
void TestFixture::processOptions(const options& args)
356375
{
357376
quiet_tests = args.quiet();
377+
dry_run = args.dry_run();
358378
exename = args.exe();
359379
}
360380

@@ -378,15 +398,19 @@ std::size_t TestFixture::runTests(const options& args)
378398
}
379399
}
380400

381-
std::cout << "\n\nTesting Complete\nNumber of tests: " << countTests << std::endl;
382-
std::cout << "Number of todos: " << todos_counter;
383-
if (succeeded_todos_counter > 0)
384-
std::cout << " (" << succeeded_todos_counter << " succeeded)";
385-
std::cout << std::endl;
401+
if (args.summary() && !args.dry_run()) {
402+
std::cout << "\n\nTesting Complete\nNumber of tests: " << countTests << std::endl;
403+
std::cout << "Number of todos: " << todos_counter;
404+
if (succeeded_todos_counter > 0)
405+
std::cout << " (" << succeeded_todos_counter << " succeeded)";
406+
std::cout << std::endl;
407+
}
386408
// calling flush here, to do all output before the error messages (in case the output is buffered)
387409
std::cout.flush();
388410

389-
std::cerr << "Tests failed: " << fails_counter << std::endl << std::endl;
411+
if (args.summary() && !args.dry_run()) {
412+
std::cerr << "Tests failed: " << fails_counter << std::endl << std::endl;
413+
}
390414
std::cerr << errmsg.str();
391415

392416
std::cerr.flush();

test/fixture.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class TestFixture : public ErrorLogger {
5959
std::string exename;
6060
std::string testToRun;
6161
bool quiet_tests{};
62+
bool dry_run{};
6263

6364
virtual void run() = 0;
6465

@@ -255,6 +256,8 @@ class TestFixture : public ErrorLogger {
255256

256257
std::ostringstream errout;
257258

259+
const Settings settingsDefault;
260+
258261
private:
259262
std::ostringstream mOutput;
260263

@@ -276,7 +279,9 @@ class TestFixture : public ErrorLogger {
276279
#define ASSERT( CONDITION ) if (!assert_(__FILE__, __LINE__, (CONDITION))) return
277280
#define ASSERT_LOC( CONDITION, FILE_, LINE_ ) assert_(FILE_, LINE_, (CONDITION))
278281
#define CHECK_EQUALS( EXPECTED, ACTUAL ) assertEquals(__FILE__, __LINE__, (EXPECTED), (ACTUAL))
279-
#define ASSERT_EQUALS( EXPECTED, ACTUAL ) if (!assertEquals(__FILE__, __LINE__, (EXPECTED), (ACTUAL))) return
282+
// *INDENT-OFF*
283+
#define ASSERT_EQUALS( EXPECTED, ACTUAL ) do { try { if (!assertEquals(__FILE__, __LINE__, (EXPECTED), (ACTUAL))) return; } catch (...) { assertNoThrowFail(__FILE__, __LINE__); } } while (false)
284+
// *INDENT-ON*
280285
#define ASSERT_EQUALS_WITHOUT_LINENUMBERS( EXPECTED, ACTUAL ) assertEqualsWithoutLineNumbers(__FILE__, __LINE__, EXPECTED, ACTUAL)
281286
#define ASSERT_EQUALS_DOUBLE( EXPECTED, ACTUAL, TOLERANCE ) assertEqualsDouble(__FILE__, __LINE__, EXPECTED, ACTUAL, TOLERANCE)
282287
#define ASSERT_EQUALS_MSG( EXPECTED, ACTUAL, MSG ) assertEquals(__FILE__, __LINE__, EXPECTED, ACTUAL, MSG)

test/options.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ options::options(int argc, const char* const argv[])
2020
: mWhichTests(argv + 1, argv + argc)
2121
,mQuiet(mWhichTests.count("-q") != 0)
2222
,mHelp(mWhichTests.count("-h") != 0 || mWhichTests.count("--help"))
23+
,mSummary(mWhichTests.count("-n") == 0)
24+
,mDryRun(mWhichTests.count("-d") != 0)
2325
,mExe(argv[0])
2426
{
2527
for (std::set<std::string>::const_iterator it = mWhichTests.cbegin(); it != mWhichTests.cend();) {
@@ -44,6 +46,16 @@ bool options::help() const
4446
return mHelp;
4547
}
4648

49+
bool options::summary() const
50+
{
51+
return mSummary;
52+
}
53+
54+
bool options::dry_run() const
55+
{
56+
return mDryRun;
57+
}
58+
4759
const std::set<std::string>& options::which_test() const
4860
{
4961
return mWhichTests;

test/options.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ class options {
3333
bool quiet() const;
3434
/** Print help. */
3535
bool help() const;
36+
/** Print summary. */
37+
bool summary() const;
38+
/** Perform dry run. */
39+
bool dry_run() const;
3640
/** Which test should be run. Empty string means 'all tests' */
3741
const std::set<std::string>& which_test() const;
3842

@@ -46,6 +50,8 @@ class options {
4650
std::set<std::string> mWhichTests;
4751
const bool mQuiet;
4852
const bool mHelp;
53+
const bool mSummary;
54+
const bool mDryRun;
4955
std::string mExe;
5056
};
5157

test/scripts/testrunner-single.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
3+
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
4+
5+
if [ -n "$1" ]; then
6+
testrunner_bin=$1
7+
else
8+
make -s -C "$SCRIPT_DIR/../.." -j"$(nproc)" testrunner # CXXFLAGS="-g -O2 -w -DHAVE_BOOST"
9+
testrunner_bin=$SCRIPT_DIR/../../testrunner
10+
fi
11+
12+
ec=0
13+
14+
tests=$($testrunner_bin -d | cut -d'(' -f2 | cut -d')' -f1)
15+
for test in $tests; do
16+
$testrunner_bin -n "$test" || ec=1
17+
done
18+
19+
exit $ec

test/testastutils.cpp

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,7 @@ class TestAstUtils : public TestFixture {
9292

9393
#define findLambdaStartToken(code) findLambdaStartToken_(code, __FILE__, __LINE__)
9494
bool findLambdaStartToken_(const char code[], const char* file, int line) {
95-
const Settings settings;
96-
Tokenizer tokenizer(settings, this);
95+
Tokenizer tokenizer(settingsDefault, this);
9796
std::istringstream istr(code);
9897
ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line);
9998
const Token * const tokStart = (::findLambdaStartToken)(tokenizer.list.back());
@@ -125,8 +124,7 @@ class TestAstUtils : public TestFixture {
125124

126125
#define isNullOperand(code) isNullOperand_(code, __FILE__, __LINE__)
127126
bool isNullOperand_(const char code[], const char* file, int line) {
128-
const Settings settings;
129-
Tokenizer tokenizer(settings, this);
127+
Tokenizer tokenizer(settingsDefault, this);
130128
std::istringstream istr(code);
131129
ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line);
132130
return (::isNullOperand)(tokenizer.tokens());
@@ -147,8 +145,7 @@ class TestAstUtils : public TestFixture {
147145

148146
#define isReturnScope(code, offset) isReturnScope_(code, offset, __FILE__, __LINE__)
149147
bool isReturnScope_(const char code[], int offset, const char* file, int line) {
150-
const Settings settings;
151-
Tokenizer tokenizer(settings, this);
148+
Tokenizer tokenizer(settingsDefault, this);
152149
std::istringstream istr(code);
153150
ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line);
154151
const Token * const tok = (offset < 0)
@@ -178,9 +175,8 @@ class TestAstUtils : public TestFixture {
178175

179176
#define isSameExpression(...) isSameExpression_(__FILE__, __LINE__, __VA_ARGS__)
180177
bool isSameExpression_(const char* file, int line, const char code[], const char tokStr1[], const char tokStr2[], bool cpp) {
181-
const Settings settings;
182178
Library library;
183-
Tokenizer tokenizer(settings, this);
179+
Tokenizer tokenizer(settingsDefault, this);
184180
std::istringstream istr(code);
185181
ASSERT_LOC(tokenizer.tokenize(istr, cpp ? "test.cpp" : "test.c"), file, line);
186182
const Token * const tok1 = Token::findsimplematch(tokenizer.tokens(), tokStr1, strlen(tokStr1));
@@ -228,13 +224,12 @@ class TestAstUtils : public TestFixture {
228224

229225
#define isVariableChanged(code, startPattern, endPattern) isVariableChanged_(code, startPattern, endPattern, __FILE__, __LINE__)
230226
bool isVariableChanged_(const char code[], const char startPattern[], const char endPattern[], const char* file, int line) {
231-
const Settings settings;
232-
Tokenizer tokenizer(settings, this);
227+
Tokenizer tokenizer(settingsDefault, this);
233228
std::istringstream istr(code);
234229
ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line);
235230
const Token * const tok1 = Token::findsimplematch(tokenizer.tokens(), startPattern, strlen(startPattern));
236231
const Token * const tok2 = Token::findsimplematch(tokenizer.tokens(), endPattern, strlen(endPattern));
237-
return (isVariableChanged)(tok1, tok2, 1, false, &settings, /*cpp*/ true);
232+
return (isVariableChanged)(tok1, tok2, 1, false, &settingsDefault, /*cpp*/ true);
238233
}
239234

240235
void isVariableChangedTest() {
@@ -263,14 +258,13 @@ class TestAstUtils : public TestFixture {
263258

264259
#define isVariableChangedByFunctionCall(code, pattern, inconclusive) isVariableChangedByFunctionCall_(code, pattern, inconclusive, __FILE__, __LINE__)
265260
bool isVariableChangedByFunctionCall_(const char code[], const char pattern[], bool *inconclusive, const char* file, int line) {
266-
const Settings settings;
267-
Tokenizer tokenizer(settings, this);
261+
Tokenizer tokenizer(settingsDefault, this);
268262
std::istringstream istr(code);
269263
ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line);
270264
const Token * const argtok = Token::findmatch(tokenizer.tokens(), pattern);
271265
ASSERT_LOC(argtok, file, line);
272266
int indirect = (argtok->variable() && argtok->variable()->isArray());
273-
return (isVariableChangedByFunctionCall)(argtok, indirect, &settings, inconclusive);
267+
return (isVariableChangedByFunctionCall)(argtok, indirect, &settingsDefault, inconclusive);
274268
}
275269

276270
void isVariableChangedByFunctionCallTest() {
@@ -438,8 +432,7 @@ class TestAstUtils : public TestFixture {
438432

439433
#define nextAfterAstRightmostLeaf(code, parentPattern, rightPattern) nextAfterAstRightmostLeaf_(code, parentPattern, rightPattern, __FILE__, __LINE__)
440434
bool nextAfterAstRightmostLeaf_(const char code[], const char parentPattern[], const char rightPattern[], const char* file, int line) {
441-
const Settings settings;
442-
Tokenizer tokenizer(settings, this);
435+
Tokenizer tokenizer(settingsDefault, this);
443436
std::istringstream istr(code);
444437
ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line);
445438
const Token * tok = Token::findsimplematch(tokenizer.tokens(), parentPattern, strlen(parentPattern));
@@ -463,8 +456,7 @@ class TestAstUtils : public TestFixture {
463456
enum class Result {False, True, Fail};
464457

465458
Result isUsedAsBool(const char code[], const char pattern[]) {
466-
const Settings settings;
467-
Tokenizer tokenizer(settings, this);
459+
Tokenizer tokenizer(settingsDefault, this);
468460
std::istringstream istr(code);
469461
if (!tokenizer.tokenize(istr, "test.cpp"))
470462
return Result::Fail;

test/testbufferoverrun.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3451,9 +3451,7 @@ class TestBufferOverrun : public TestFixture {
34513451
"test.cpp:2:note:Assign p, buffer with size 10\n"
34523452
"test.cpp:3:note:Buffer overrun\n", errout.str());
34533453

3454-
// TODO: need to reset this but it breaks other tests
3455-
(void)settingsOld;
3456-
//settings0 = settingsOld;
3454+
settings0 = settingsOld;
34573455
}
34583456

34593457
void buffer_overrun_bailoutIfSwitch() {
@@ -3805,7 +3803,7 @@ class TestBufferOverrun : public TestFixture {
38053803
" std::string hi = \"hi\" + val;\n"
38063804
" std::cout << hi << std::endl;\n"
38073805
"}\n");
3808-
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (portability) Undefined behaviour, pointer arithmetic '\"hi\"+val' is out of bounds.\n", errout.str());
3806+
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour, pointer arithmetic '\"hi\"+val' is out of bounds.\n", errout.str());
38093807

38103808
check("void f(const char* s, int len) {\n" // #11026
38113809
" const char* end = s + len;\n"
@@ -4053,14 +4051,14 @@ class TestBufferOverrun : public TestFixture {
40534051
" for (int i = 0; i < 3; i++)\n"
40544052
" a[i] = NULL;\n"
40554053
"}");
4056-
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Array 'a[2]' accessed at index 2, which is out of bounds.\n", errout.str());
4054+
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2]' accessed at index 2, which is out of bounds.\n", errout.str());
40574055

40584056
check("void f() {\n"
40594057
" int **a = new int*[2];\n"
40604058
" for (int i = 0; i < 3; i++)\n"
40614059
" a[i] = NULL;\n"
40624060
"}");
4063-
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Array 'a[2]' accessed at index 2, which is out of bounds.\n", errout.str());
4061+
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2]' accessed at index 2, which is out of bounds.\n", errout.str());
40644062
}
40654063

40664064
// statically allocated buffer
@@ -5136,7 +5134,7 @@ class TestBufferOverrun : public TestFixture {
51365134
" int* p = new int[d];\n"
51375135
" return p;\n"
51385136
"}\n");
5139-
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3] -> [test.cpp:5]: (warning, inconclusive) Memory allocation size is negative.\n", errout.str());
5137+
ASSERT_EQUALS("[test.cpp:5]: (warning, inconclusive) Memory allocation size is negative.\n", errout.str());
51405138
}
51415139

51425140
void negativeArraySize() {

test/testclass.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8945,21 +8945,20 @@ class TestClass : public TestFixture {
89458945

89468946

89478947
void ctu(const std::vector<std::string> &code) {
8948-
const Settings settings;
89498948
Check &check = getCheck<CheckClass>();
89508949

89518950
// getFileInfo
89528951
std::list<Check::FileInfo*> fileInfo;
89538952
for (const std::string& c: code) {
8954-
Tokenizer tokenizer(settings, this);
8953+
Tokenizer tokenizer(settingsDefault, this);
89558954
std::istringstream istr(c);
89568955
ASSERT(tokenizer.tokenize(istr, (std::to_string(fileInfo.size()) + ".cpp").c_str()));
8957-
fileInfo.push_back(check.getFileInfo(&tokenizer, &settings));
8956+
fileInfo.push_back(check.getFileInfo(&tokenizer, &settingsDefault));
89588957
}
89598958

89608959
// Check code..
89618960
errout.str("");
8962-
check.analyseWholeProgram(nullptr, fileInfo, settings, *this);
8961+
check.analyseWholeProgram(nullptr, fileInfo, settingsDefault, *this);
89638962

89648963
while (!fileInfo.empty()) {
89658964
delete fileInfo.back();

test/testmemleak.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@
2727
#include <list>
2828
#include <sstream> // IWYU pragma: keep
2929

30-
class TestMemleakInClass;
31-
class TestMemleakNoVar;
32-
class TestMemleakStructMember;
33-
34-
3530
class TestMemleak : private TestFixture {
3631
public:
3732
TestMemleak() : TestFixture("TestMemleak") {}

test/testnullpointer.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4147,8 +4147,7 @@ class TestNullPointer : public TestFixture {
41474147
}
41484148

41494149
void functioncalllibrary() {
4150-
const Settings settings1;
4151-
Tokenizer tokenizer(settings1,this);
4150+
Tokenizer tokenizer(settingsDefault,this);
41524151
std::istringstream code("void f() { int a,b,c; x(a,b,c); }");
41534152
ASSERT_EQUALS(true, tokenizer.tokenize(code, "test.c"));
41544153
const Token *xtok = Token::findsimplematch(tokenizer.tokens(), "x");

0 commit comments

Comments
 (0)