From 54c01cff1a55d2dbdf1686da325d2f6c9dd2bbbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Wed, 6 Mar 2024 14:14:49 +0100 Subject: [PATCH] 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. --- test/fixture.cpp | 42 ++++++++++++++++++------ test/fixture.h | 7 +++- test/options.cpp | 12 +++++++ test/options.h | 6 ++++ test/scripts/testrunner-single.sh | 19 +++++++++++ test/testastutils.cpp | 28 ++++++---------- test/testbufferoverrun.cpp | 12 +++---- test/testclass.cpp | 7 ++-- test/testmemleak.cpp | 5 --- test/testnullpointer.cpp | 3 +- test/testoptions.cpp | 14 ++++++++ test/testsummaries.cpp | 3 +- test/testtoken.cpp | 13 ++++---- test/testtokenize.cpp | 51 ++++++++++++----------------- test/testtokenrange.cpp | 14 ++++---- test/testtype.cpp | 54 ++++++++++++++----------------- 16 files changed, 167 insertions(+), 123 deletions(-) create mode 100755 test/scripts/testrunner-single.sh diff --git a/test/fixture.cpp b/test/fixture.cpp index 71281e3fa60..30acf65935f 100644 --- a/test/fixture.cpp +++ b/test/fixture.cpp @@ -106,7 +106,7 @@ bool TestFixture::prepareTest(const char testname[]) } else { std::cout << classname << "::" << mTestname << std::endl; } - return true; + return !dry_run; } return false; } @@ -301,8 +301,25 @@ void TestFixture::assertThrowFail(const char * const filename, const unsigned in void TestFixture::assertNoThrowFail(const char * const filename, const unsigned int linenr) const { ++fails_counter; + + std::string ex_msg; + + try { + // cppcheck-suppress rethrowNoCurrentException + throw; + } + catch (const InternalError& e) { + ex_msg = e.errorMessage; + } + catch (const std::exception& e) { + ex_msg = e.what(); + } + catch (...) { + ex_msg = "unknown exception"; + } + errmsg << getLocationStr(filename, linenr) << ": Assertion failed. " - << "Unexpected exception was thrown" << std::endl << "_____" << std::endl; + << "Unexpected exception was thrown: " << ex_msg << std::endl << "_____" << std::endl; } @@ -323,7 +340,9 @@ void TestFixture::printHelp() "\n" "Options:\n" " -q Do not print the test cases that have run.\n" - " -h, --help Print this help.\n"; + " -h, --help Print this help.\n" + " -n Print no summaries.\n" + " -d Do not execute the tests.\n"; } void TestFixture::run(const std::string &str) @@ -355,6 +374,7 @@ void TestFixture::run(const std::string &str) void TestFixture::processOptions(const options& args) { quiet_tests = args.quiet(); + dry_run = args.dry_run(); exename = args.exe(); } @@ -378,15 +398,19 @@ std::size_t TestFixture::runTests(const options& args) } } - std::cout << "\n\nTesting Complete\nNumber of tests: " << countTests << std::endl; - std::cout << "Number of todos: " << todos_counter; - if (succeeded_todos_counter > 0) - std::cout << " (" << succeeded_todos_counter << " succeeded)"; - std::cout << std::endl; + if (args.summary() && !args.dry_run()) { + std::cout << "\n\nTesting Complete\nNumber of tests: " << countTests << std::endl; + std::cout << "Number of todos: " << todos_counter; + if (succeeded_todos_counter > 0) + std::cout << " (" << succeeded_todos_counter << " succeeded)"; + std::cout << std::endl; + } // calling flush here, to do all output before the error messages (in case the output is buffered) std::cout.flush(); - std::cerr << "Tests failed: " << fails_counter << std::endl << std::endl; + if (args.summary() && !args.dry_run()) { + std::cerr << "Tests failed: " << fails_counter << std::endl << std::endl; + } std::cerr << errmsg.str(); std::cerr.flush(); diff --git a/test/fixture.h b/test/fixture.h index d2ec804f41d..e151e520ed8 100644 --- a/test/fixture.h +++ b/test/fixture.h @@ -59,6 +59,7 @@ class TestFixture : public ErrorLogger { std::string exename; std::string testToRun; bool quiet_tests{}; + bool dry_run{}; virtual void run() = 0; @@ -255,6 +256,8 @@ class TestFixture : public ErrorLogger { std::ostringstream errout; + const Settings settingsDefault; + private: std::ostringstream mOutput; @@ -276,7 +279,9 @@ class TestFixture : public ErrorLogger { #define ASSERT( CONDITION ) if (!assert_(__FILE__, __LINE__, (CONDITION))) return #define ASSERT_LOC( CONDITION, FILE_, LINE_ ) assert_(FILE_, LINE_, (CONDITION)) #define CHECK_EQUALS( EXPECTED, ACTUAL ) assertEquals(__FILE__, __LINE__, (EXPECTED), (ACTUAL)) -#define ASSERT_EQUALS( EXPECTED, ACTUAL ) if (!assertEquals(__FILE__, __LINE__, (EXPECTED), (ACTUAL))) return +// *INDENT-OFF* +#define ASSERT_EQUALS( EXPECTED, ACTUAL ) do { try { if (!assertEquals(__FILE__, __LINE__, (EXPECTED), (ACTUAL))) return; } catch (...) { assertNoThrowFail(__FILE__, __LINE__); } } while (false) +// *INDENT-ON* #define ASSERT_EQUALS_WITHOUT_LINENUMBERS( EXPECTED, ACTUAL ) assertEqualsWithoutLineNumbers(__FILE__, __LINE__, EXPECTED, ACTUAL) #define ASSERT_EQUALS_DOUBLE( EXPECTED, ACTUAL, TOLERANCE ) assertEqualsDouble(__FILE__, __LINE__, EXPECTED, ACTUAL, TOLERANCE) #define ASSERT_EQUALS_MSG( EXPECTED, ACTUAL, MSG ) assertEquals(__FILE__, __LINE__, EXPECTED, ACTUAL, MSG) diff --git a/test/options.cpp b/test/options.cpp index d835d14e21c..0444c9e1696 100644 --- a/test/options.cpp +++ b/test/options.cpp @@ -20,6 +20,8 @@ options::options(int argc, const char* const argv[]) : mWhichTests(argv + 1, argv + argc) ,mQuiet(mWhichTests.count("-q") != 0) ,mHelp(mWhichTests.count("-h") != 0 || mWhichTests.count("--help")) + ,mSummary(mWhichTests.count("-n") == 0) + ,mDryRun(mWhichTests.count("-d") != 0) ,mExe(argv[0]) { for (std::set::const_iterator it = mWhichTests.cbegin(); it != mWhichTests.cend();) { @@ -44,6 +46,16 @@ bool options::help() const return mHelp; } +bool options::summary() const +{ + return mSummary; +} + +bool options::dry_run() const +{ + return mDryRun; +} + const std::set& options::which_test() const { return mWhichTests; diff --git a/test/options.h b/test/options.h index bdde6a1d4bc..4aa83c10270 100644 --- a/test/options.h +++ b/test/options.h @@ -33,6 +33,10 @@ class options { bool quiet() const; /** Print help. */ bool help() const; + /** Print summary. */ + bool summary() const; + /** Perform dry run. */ + bool dry_run() const; /** Which test should be run. Empty string means 'all tests' */ const std::set& which_test() const; @@ -46,6 +50,8 @@ class options { std::set mWhichTests; const bool mQuiet; const bool mHelp; + const bool mSummary; + const bool mDryRun; std::string mExe; }; diff --git a/test/scripts/testrunner-single.sh b/test/scripts/testrunner-single.sh new file mode 100755 index 00000000000..072779a2730 --- /dev/null +++ b/test/scripts/testrunner-single.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +if [ -n "$1" ]; then + testrunner_bin=$1 +else + make -s -C "$SCRIPT_DIR/../.." -j"$(nproc)" testrunner # CXXFLAGS="-g -O2 -w -DHAVE_BOOST" + testrunner_bin=$SCRIPT_DIR/../../testrunner +fi + +ec=0 + +tests=$($testrunner_bin -d | cut -d'(' -f2 | cut -d')' -f1) +for test in $tests; do + $testrunner_bin -n "$test" || ec=1 +done + +exit $ec diff --git a/test/testastutils.cpp b/test/testastutils.cpp index 1a42749be35..e2b518519a8 100644 --- a/test/testastutils.cpp +++ b/test/testastutils.cpp @@ -92,8 +92,7 @@ class TestAstUtils : public TestFixture { #define findLambdaStartToken(code) findLambdaStartToken_(code, __FILE__, __LINE__) bool findLambdaStartToken_(const char code[], const char* file, int line) { - const Settings settings; - Tokenizer tokenizer(settings, this); + Tokenizer tokenizer(settingsDefault, this); std::istringstream istr(code); ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line); const Token * const tokStart = (::findLambdaStartToken)(tokenizer.list.back()); @@ -125,8 +124,7 @@ class TestAstUtils : public TestFixture { #define isNullOperand(code) isNullOperand_(code, __FILE__, __LINE__) bool isNullOperand_(const char code[], const char* file, int line) { - const Settings settings; - Tokenizer tokenizer(settings, this); + Tokenizer tokenizer(settingsDefault, this); std::istringstream istr(code); ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line); return (::isNullOperand)(tokenizer.tokens()); @@ -147,8 +145,7 @@ class TestAstUtils : public TestFixture { #define isReturnScope(code, offset) isReturnScope_(code, offset, __FILE__, __LINE__) bool isReturnScope_(const char code[], int offset, const char* file, int line) { - const Settings settings; - Tokenizer tokenizer(settings, this); + Tokenizer tokenizer(settingsDefault, this); std::istringstream istr(code); ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line); const Token * const tok = (offset < 0) @@ -178,9 +175,8 @@ class TestAstUtils : public TestFixture { #define isSameExpression(...) isSameExpression_(__FILE__, __LINE__, __VA_ARGS__) bool isSameExpression_(const char* file, int line, const char code[], const char tokStr1[], const char tokStr2[], bool cpp) { - const Settings settings; Library library; - Tokenizer tokenizer(settings, this); + Tokenizer tokenizer(settingsDefault, this); std::istringstream istr(code); ASSERT_LOC(tokenizer.tokenize(istr, cpp ? "test.cpp" : "test.c"), file, line); const Token * const tok1 = Token::findsimplematch(tokenizer.tokens(), tokStr1, strlen(tokStr1)); @@ -228,13 +224,12 @@ class TestAstUtils : public TestFixture { #define isVariableChanged(code, startPattern, endPattern) isVariableChanged_(code, startPattern, endPattern, __FILE__, __LINE__) bool isVariableChanged_(const char code[], const char startPattern[], const char endPattern[], const char* file, int line) { - const Settings settings; - Tokenizer tokenizer(settings, this); + Tokenizer tokenizer(settingsDefault, this); std::istringstream istr(code); ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line); const Token * const tok1 = Token::findsimplematch(tokenizer.tokens(), startPattern, strlen(startPattern)); const Token * const tok2 = Token::findsimplematch(tokenizer.tokens(), endPattern, strlen(endPattern)); - return (isVariableChanged)(tok1, tok2, 1, false, &settings, /*cpp*/ true); + return (isVariableChanged)(tok1, tok2, 1, false, &settingsDefault, /*cpp*/ true); } void isVariableChangedTest() { @@ -263,14 +258,13 @@ class TestAstUtils : public TestFixture { #define isVariableChangedByFunctionCall(code, pattern, inconclusive) isVariableChangedByFunctionCall_(code, pattern, inconclusive, __FILE__, __LINE__) bool isVariableChangedByFunctionCall_(const char code[], const char pattern[], bool *inconclusive, const char* file, int line) { - const Settings settings; - Tokenizer tokenizer(settings, this); + Tokenizer tokenizer(settingsDefault, this); std::istringstream istr(code); ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line); const Token * const argtok = Token::findmatch(tokenizer.tokens(), pattern); ASSERT_LOC(argtok, file, line); int indirect = (argtok->variable() && argtok->variable()->isArray()); - return (isVariableChangedByFunctionCall)(argtok, indirect, &settings, inconclusive); + return (isVariableChangedByFunctionCall)(argtok, indirect, &settingsDefault, inconclusive); } void isVariableChangedByFunctionCallTest() { @@ -438,8 +432,7 @@ class TestAstUtils : public TestFixture { #define nextAfterAstRightmostLeaf(code, parentPattern, rightPattern) nextAfterAstRightmostLeaf_(code, parentPattern, rightPattern, __FILE__, __LINE__) bool nextAfterAstRightmostLeaf_(const char code[], const char parentPattern[], const char rightPattern[], const char* file, int line) { - const Settings settings; - Tokenizer tokenizer(settings, this); + Tokenizer tokenizer(settingsDefault, this); std::istringstream istr(code); ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line); const Token * tok = Token::findsimplematch(tokenizer.tokens(), parentPattern, strlen(parentPattern)); @@ -463,8 +456,7 @@ class TestAstUtils : public TestFixture { enum class Result {False, True, Fail}; Result isUsedAsBool(const char code[], const char pattern[]) { - const Settings settings; - Tokenizer tokenizer(settings, this); + Tokenizer tokenizer(settingsDefault, this); std::istringstream istr(code); if (!tokenizer.tokenize(istr, "test.cpp")) return Result::Fail; diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index f1995a222c6..e4fb223871c 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -3451,9 +3451,7 @@ class TestBufferOverrun : public TestFixture { "test.cpp:2:note:Assign p, buffer with size 10\n" "test.cpp:3:note:Buffer overrun\n", errout.str()); - // TODO: need to reset this but it breaks other tests - (void)settingsOld; - //settings0 = settingsOld; + settings0 = settingsOld; } void buffer_overrun_bailoutIfSwitch() { @@ -3805,7 +3803,7 @@ class TestBufferOverrun : public TestFixture { " std::string hi = \"hi\" + val;\n" " std::cout << hi << std::endl;\n" "}\n"); - ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (portability) Undefined behaviour, pointer arithmetic '\"hi\"+val' is out of bounds.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour, pointer arithmetic '\"hi\"+val' is out of bounds.\n", errout.str()); check("void f(const char* s, int len) {\n" // #11026 " const char* end = s + len;\n" @@ -4053,14 +4051,14 @@ class TestBufferOverrun : public TestFixture { " for (int i = 0; i < 3; i++)\n" " a[i] = NULL;\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Array 'a[2]' accessed at index 2, which is out of bounds.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2]' accessed at index 2, which is out of bounds.\n", errout.str()); check("void f() {\n" " int **a = new int*[2];\n" " for (int i = 0; i < 3; i++)\n" " a[i] = NULL;\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Array 'a[2]' accessed at index 2, which is out of bounds.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2]' accessed at index 2, which is out of bounds.\n", errout.str()); } // statically allocated buffer @@ -5136,7 +5134,7 @@ class TestBufferOverrun : public TestFixture { " int* p = new int[d];\n" " return p;\n" "}\n"); - ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3] -> [test.cpp:5]: (warning, inconclusive) Memory allocation size is negative.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:5]: (warning, inconclusive) Memory allocation size is negative.\n", errout.str()); } void negativeArraySize() { diff --git a/test/testclass.cpp b/test/testclass.cpp index f0ffab38135..1fdf11a9ae4 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -8945,21 +8945,20 @@ class TestClass : public TestFixture { void ctu(const std::vector &code) { - const Settings settings; Check &check = getCheck(); // getFileInfo std::list fileInfo; for (const std::string& c: code) { - Tokenizer tokenizer(settings, this); + Tokenizer tokenizer(settingsDefault, this); std::istringstream istr(c); ASSERT(tokenizer.tokenize(istr, (std::to_string(fileInfo.size()) + ".cpp").c_str())); - fileInfo.push_back(check.getFileInfo(&tokenizer, &settings)); + fileInfo.push_back(check.getFileInfo(&tokenizer, &settingsDefault)); } // Check code.. errout.str(""); - check.analyseWholeProgram(nullptr, fileInfo, settings, *this); + check.analyseWholeProgram(nullptr, fileInfo, settingsDefault, *this); while (!fileInfo.empty()) { delete fileInfo.back(); diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index eada4036faf..607bf30f942 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -27,11 +27,6 @@ #include #include // IWYU pragma: keep -class TestMemleakInClass; -class TestMemleakNoVar; -class TestMemleakStructMember; - - class TestMemleak : private TestFixture { public: TestMemleak() : TestFixture("TestMemleak") {} diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index 5f76195af10..a64ef06f85b 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -4147,8 +4147,7 @@ class TestNullPointer : public TestFixture { } void functioncalllibrary() { - const Settings settings1; - Tokenizer tokenizer(settings1,this); + Tokenizer tokenizer(settingsDefault,this); std::istringstream code("void f() { int a,b,c; x(a,b,c); }"); ASSERT_EQUALS(true, tokenizer.tokenize(code, "test.c")); const Token *xtok = Token::findsimplematch(tokenizer.tokens(), "x"); diff --git a/test/testoptions.cpp b/test/testoptions.cpp index f03f183db9e..dde97517d51 100644 --- a/test/testoptions.cpp +++ b/test/testoptions.cpp @@ -43,6 +43,8 @@ class TestOptions : public TestFixture { TEST_CASE(multiple_testcases); TEST_CASE(multiple_testcases_ignore_duplicates); TEST_CASE(invalid_switches); + TEST_CASE(summary); + TEST_CASE(dry_run); } @@ -121,6 +123,18 @@ class TestOptions : public TestFixture { ASSERT(expected == args.which_test()); ASSERT_EQUALS(true, args.quiet()); } + + void summary() const { + const char* argv[] = {"./test_runner", "TestClass::TestMethod", "-n"}; + options args(sizeof argv / sizeof argv[0], argv); + ASSERT_EQUALS(false, args.summary()); + } + + void dry_run() const { + const char* argv[] = {"./test_runner", "TestClass::TestMethod", "-d"}; + options args(sizeof argv / sizeof argv[0], argv); + ASSERT_EQUALS(true, args.dry_run()); + } }; REGISTER_TEST(TestOptions) diff --git a/test/testsummaries.cpp b/test/testsummaries.cpp index ecaa893d687..158f6106ee4 100644 --- a/test/testsummaries.cpp +++ b/test/testsummaries.cpp @@ -44,8 +44,7 @@ class TestSummaries : public TestFixture { errout.str(""); // tokenize.. - const Settings settings; - Tokenizer tokenizer(settings, this); + Tokenizer tokenizer(settingsDefault, this); std::istringstream istr(code); ASSERT_LOC(tokenizer.tokenize(istr, filename), file, line); return Summaries::create(&tokenizer, ""); diff --git a/test/testtoken.cpp b/test/testtoken.cpp index 1a75ccc3084..1478f524ee5 100644 --- a/test/testtoken.cpp +++ b/test/testtoken.cpp @@ -39,8 +39,7 @@ class TestToken : public TestFixture { } private: - const Settings settings; - /*const*/ TokenList list{&settings}; + /*const*/ TokenList list{&settingsDefault}; std::vector arithmeticalOps; std::vector logicalOps; @@ -143,7 +142,7 @@ class TestToken : public TestFixture { #define MatchCheck(...) MatchCheck_(__FILE__, __LINE__, __VA_ARGS__) bool MatchCheck_(const char* file, int line, const std::string& code, const std::string& pattern, unsigned int varid = 0) { - Tokenizer tokenizer(settings, this); + Tokenizer tokenizer(settingsDefault, this); std::istringstream istr(";" + code + ";"); try { ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line); @@ -440,16 +439,16 @@ class TestToken : public TestFixture { Token tok(tokensFrontBack); tok.str("\"\""); - ASSERT_EQUALS(sizeof(""), Token::getStrSize(&tok, settings)); + ASSERT_EQUALS(sizeof(""), Token::getStrSize(&tok, settingsDefault)); tok.str("\"abc\""); - ASSERT_EQUALS(sizeof("abc"), Token::getStrSize(&tok, settings)); + ASSERT_EQUALS(sizeof("abc"), Token::getStrSize(&tok, settingsDefault)); tok.str("\"\\0abc\""); - ASSERT_EQUALS(sizeof("\0abc"), Token::getStrSize(&tok, settings)); + ASSERT_EQUALS(sizeof("\0abc"), Token::getStrSize(&tok, settingsDefault)); tok.str("\"\\\\\""); - ASSERT_EQUALS(sizeof("\\"), Token::getStrSize(&tok, settings)); + ASSERT_EQUALS(sizeof("\\"), Token::getStrSize(&tok, settingsDefault)); } void strValue() const { diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 57d87c2e9a0..33fb3228954 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -944,14 +944,13 @@ class TestTokenizer : public TestFixture { } { - const Settings s; ASSERT_EQUALS("; template < typename T , u_int uBAR = 0 >\n" "class Foo {\n" "public:\n" "void FooBar ( ) {\n" "new ( uBAR ? uBAR : sizeof ( T ) ) T ;\n" "}\n" - "} ;", tokenizeAndStringify(code, s)); + "} ;", tokenizeAndStringify(code, settingsDefault)); } } @@ -991,33 +990,25 @@ class TestTokenizer : public TestFixture { // #4725 - ^{} void simplifyAsm2() { - ASSERT_THROW(ASSERT_EQUALS("void f ( ) { asm ( \"^{}\" ) ; }", tokenizeAndStringify("void f() { ^{} }")), InternalError); - ASSERT_THROW(ASSERT_EQUALS("void f ( ) { x ( asm ( \"^{}\" ) ) ; }", tokenizeAndStringify("void f() { x(^{}); }")), InternalError); - ASSERT_THROW(ASSERT_EQUALS("void f ( ) { foo ( A ( ) , asm ( \"^{bar();}\" ) ) ; }", tokenizeAndStringify("void f() { foo(A(), ^{ bar(); }); }")), InternalError); - ASSERT_THROW(ASSERT_EQUALS("int f0 ( Args args ) { asm ( \"asm(\"return^{returnsizeof...(Args);}()\")+^{returnsizeof...(args);}()\" )\n" - "2:\n" - "|\n" - "5:\n" - "6: ;\n" - "} ;", tokenizeAndStringify("int f0(Args args) {\n" - " return ^{\n" - " return sizeof...(Args);\n" - " }() + ^ {\n" - " return sizeof...(args);\n" - " }();\n" - "};")), InternalError); - ASSERT_THROW(ASSERT_EQUALS("int ( ^ block ) ( void ) = asm ( \"^{staticinttest=0;returntest;}\" )\n\n\n;", - tokenizeAndStringify("int(^block)(void) = ^{\n" - " static int test = 0;\n" - " return test;\n" - "};")), InternalError); - - ASSERT_THROW(ASSERT_EQUALS("; return f ( a [ b = c ] , asm ( \"^{}\" ) ) ;", - tokenizeAndStringify("; return f(a[b=c],^{});")), InternalError); // #7185 + ASSERT_THROW_EQUALS(tokenizeAndStringify("void f() { ^{} }"), InternalError, "syntax error"); + ASSERT_THROW_EQUALS(tokenizeAndStringify("void f() { x(^{}); }"), InternalError, "syntax error"); + ASSERT_THROW_EQUALS(tokenizeAndStringify("void f() { foo(A(), ^{ bar(); }); }"), InternalError, "syntax error"); + ASSERT_THROW_EQUALS(tokenizeAndStringify("int f0(Args args) {\n" + " return ^{\n" + " return sizeof...(Args);\n" + " }() + ^ {\n" + " return sizeof...(args);\n" + " }();\n" + "};"), InternalError, "syntax error"); + ASSERT_THROW_EQUALS(tokenizeAndStringify("int(^block)(void) = ^{\n" + " static int test = 0;\n" + " return test;\n" + "};"), InternalError, "syntax error"); + + ASSERT_THROW_EQUALS(tokenizeAndStringify("; return f(a[b=c],^{});"), InternalError, "syntax error: keyword 'return' is not allowed in global scope"); // #7185 ASSERT_EQUALS("{ return f ( asm ( \"^(void){somecode}\" ) ) ; }", tokenizeAndStringify("{ return f(^(void){somecode}); }")); - ASSERT_THROW(ASSERT_EQUALS("; asm ( \"a?(b?(c,asm(\"^{}\")):0):^{}\" ) ;", - tokenizeAndStringify(";a?(b?(c,^{}):0):^{};")), InternalError); + ASSERT_THROW_EQUALS(tokenizeAndStringify(";a?(b?(c,^{}):0):^{};"), InternalError, "syntax error"); ASSERT_EQUALS("template < typename T > " "CImg < T > operator| ( const char * const expression , const CImg < T > & img ) { " "return img | expression ; " @@ -7679,8 +7670,7 @@ class TestTokenizer : public TestFixture { "a = reinterpret_cast(x);\n" "a = static_cast(x);\n"; - const Settings settings; - Tokenizer tokenizer(settings, this); + Tokenizer tokenizer(settingsDefault, this); std::istringstream istr(code); ASSERT(tokenizer.tokenize(istr, "test.cpp")); @@ -7818,8 +7808,7 @@ class TestTokenizer : public TestFixture { void cpp11init() { #define testIsCpp11init(...) testIsCpp11init_(__FILE__, __LINE__, __VA_ARGS__) auto testIsCpp11init_ = [this](const char* file, int line, const char* code, const char* find, TokenImpl::Cpp11init expected) { - const Settings settings; - Tokenizer tokenizer(settings, this); + Tokenizer tokenizer(settingsDefault, this); std::istringstream istr(code); ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line); diff --git a/test/testtokenrange.cpp b/test/testtokenrange.cpp index d1d51d8fb4b..dee15b918c6 100644 --- a/test/testtokenrange.cpp +++ b/test/testtokenrange.cpp @@ -36,8 +36,6 @@ class TestTokenRange : public TestFixture { TestTokenRange() : TestFixture("TestTokenRange") {} private: - const Settings settings; - void run() override { TEST_CASE(enumerationToEnd); TEST_CASE(untilHelperToEnd); @@ -72,21 +70,21 @@ class TestTokenRange : public TestFixture { void enumerationToEnd() const { std::istringstream istr("void a(){} void main(){ if(true){a();} }"); - TokenList tokenList(&settings); + TokenList tokenList(&settingsDefault); tokenList.createTokens(istr, "test.cpp"); ASSERT_EQUALS("", testTokenRange(ConstTokenRange{ tokenList.front(), nullptr }, tokenList.front(), nullptr)); } void untilHelperToEnd() const { std::istringstream istr("void a(){} void main(){ if(true){a();} }"); - TokenList tokenList(&settings); + TokenList tokenList(&settingsDefault); tokenList.createTokens(istr, "test.cpp"); ASSERT_EQUALS("", testTokenRange(tokenList.front()->until(nullptr), tokenList.front(), nullptr)); } void untilHelperPartWay() const { std::istringstream istr("void a(){} void main(){ if(true){a();} }"); - TokenList tokenList(&settings); + TokenList tokenList(&settingsDefault); tokenList.createTokens(istr, "test.cpp"); const Token* start = tokenList.front()->tokAt(4); const Token* end = start->tokAt(8); @@ -95,7 +93,7 @@ class TestTokenRange : public TestFixture { void partialEnumeration() const { std::istringstream istr("void a(){} void main(){ if(true){a();} }"); - TokenList tokenList(&settings); + TokenList tokenList(&settingsDefault); tokenList.createTokens(istr, "test.cpp"); const Token* start = tokenList.front()->tokAt(4); const Token* end = tokenList.front()->tokAt(10); @@ -103,7 +101,7 @@ class TestTokenRange : public TestFixture { } void scopeExample() const { - Tokenizer tokenizer(settings); + Tokenizer tokenizer(settingsDefault); std::istringstream sample("void a(){} void main(){ if(true){a();} }"); ASSERT(tokenizer.tokenize(sample, "test.cpp")); @@ -119,7 +117,7 @@ class TestTokenRange : public TestFixture { void exampleAlgorithms() const { std::istringstream istr("void a(){} void main(){ if(true){a();} }"); - TokenList tokenList(&settings); + TokenList tokenList(&settingsDefault); tokenList.createTokens(istr, "test.cpp"); ConstTokenRange range{ tokenList.front(), nullptr }; ASSERT_EQUALS(true, std::all_of(range.begin(), range.end(), [](const Token*) { diff --git a/test/testtype.cpp b/test/testtype.cpp index 882754b6547..dbc2998befe 100644 --- a/test/testtype.cpp +++ b/test/testtype.cpp @@ -86,7 +86,6 @@ class TestType : public TestFixture { } void checkTooBigShift_Unix32() { - const Settings settings0; const Settings settings = settingsBuilder().platform(Platform::Type::Unix32).build(); // unsigned types getting promoted to int sizeof(int) = 4 bytes @@ -186,7 +185,7 @@ class TestType : public TestFixture { // #7266: C++, shift in macro check("void f(unsigned int x) {\n" " UINFO(x << 1234);\n" - "}", settings0); + "}", settingsDefault); ASSERT_EQUALS("", errout.str()); // #8640 @@ -196,7 +195,7 @@ class TestType : public TestFixture { " constexpr const int shift[1] = {32};\n" " constexpr const int ret = a << shift[0];\n" // shift too many bits " return ret;\n" - "}", settings0); + "}", settingsDefault); ASSERT_EQUALS("[test.cpp:5]: (error) Shifting 32-bit value by 32 bits is undefined behaviour\n" "[test.cpp:5]: (error) Signed integer overflow for expression 'a< 32)\n" " return 0;\n" " return rm>> k;\n" - "}", settings0); + "}", settingsDefault); ASSERT_EQUALS( "[test.cpp:4] -> [test.cpp:6]: (warning) Shifting signed 32-bit value by 31 bits is undefined behaviour. See condition at line 4.\n", errout.str()); @@ -219,7 +218,7 @@ class TestType : public TestFixture { " return 0;\n" " else\n" " return rm>> k;\n" - "}", settings0); + "}", settingsDefault); ASSERT_EQUALS( "[test.cpp:4] -> [test.cpp:7]: (warning) Shifting signed 32-bit value by 31 bits is undefined behaviour. See condition at line 4.\n", errout.str()); @@ -231,20 +230,20 @@ class TestType : public TestFixture { " return 0;\n" " else\n" " return rm>> k;\n" - "}", settings0); + "}", settingsDefault); ASSERT_EQUALS("", errout.str()); check("static long long f(int x, long long y) {\n" " if (x >= 64)\n" " return 0;\n" " return -(y << (x-1));\n" - "}", settings0); + "}", settingsDefault); ASSERT_EQUALS("", errout.str()); check("bool f() {\n" " std::ofstream outfile;\n" " outfile << vec_points[0](0) << static_cast(d) << ' ';\n" - "}", settings0); + "}", settingsDefault); ASSERT_EQUALS("", errout.str()); check("void f(unsigned b, int len, unsigned char rem) {\n" // #10773 @@ -255,7 +254,7 @@ class TestType : public TestFixture { " if (bits == 512)\n" " len -= 8;\n" " }\n" - "}\n", settings0); + "}\n", settingsDefault); ASSERT_EQUALS("", errout.str()); } @@ -305,12 +304,11 @@ class TestType : public TestFixture { } void signConversion() { - const Settings settings0; const Settings settings = settingsBuilder().platform(Platform::Type::Unix64).build(); - check("x = -4 * (unsigned)y;", settings0); + check("x = -4 * (unsigned)y;", settingsDefault); ASSERT_EQUALS("[test.cpp:1]: (warning) Expression '-4' has a negative value. That is converted to an unsigned value and used in an unsigned calculation.\n", errout.str()); - check("x = (unsigned)y * -4;", settings0); + check("x = (unsigned)y * -4;", settingsDefault); ASSERT_EQUALS("[test.cpp:1]: (warning) Expression '-4' has a negative value. That is converted to an unsigned value and used in an unsigned calculation.\n", errout.str()); check("unsigned int dostuff(int x) {\n" // x is signed @@ -322,7 +320,7 @@ class TestType : public TestFixture { check("unsigned int f1(signed int x, unsigned int y) {" // x is signed " return x * y;\n" "}\n" - "void f2() { f1(-4,4); }", settings0); + "void f2() { f1(-4,4); }", settingsDefault); ASSERT_EQUALS( "[test.cpp:1]: (warning) Expression 'x' can have a negative value. That is converted to an unsigned value and used in an unsigned calculation.\n", errout.str()); @@ -330,7 +328,7 @@ class TestType : public TestFixture { check("unsigned int f1(int x) {" " return x * 5U;\n" "}\n" - "void f2() { f1(-4); }", settings0); + "void f2() { f1(-4); }", settingsDefault); ASSERT_EQUALS( "[test.cpp:1]: (warning) Expression 'x' can have a negative value. That is converted to an unsigned value and used in an unsigned calculation.\n", errout.str()); @@ -338,19 +336,19 @@ class TestType : public TestFixture { check("unsigned int f1(int x) {" // #6168: FP for inner calculation " return 5U * (1234 - x);\n" // <- signed subtraction, x is not sign converted "}\n" - "void f2() { f1(-4); }", settings0); + "void f2() { f1(-4); }", settingsDefault); ASSERT_EQUALS("", errout.str()); // Don't warn for + and - check("void f1(int x) {" " a = x + 5U;\n" "}\n" - "void f2() { f1(-4); }", settings0); + "void f2() { f1(-4); }", settingsDefault); ASSERT_EQUALS("", errout.str()); check("size_t foo(size_t x) {\n" " return -2 * x;\n" - "}", settings0); + "}", settingsDefault); ASSERT_EQUALS("[test.cpp:2]: (warning) Expression '-2' has a negative value. That is converted to an unsigned value and used in an unsigned calculation.\n", errout.str()); } @@ -453,48 +451,46 @@ class TestType : public TestFixture { } void checkFloatToIntegerOverflow() { - const Settings settings; - check("x = (int)1E100;", settings); + check("x = (int)1E100;", settingsDefault); ASSERT_EQUALS("[test.cpp:1]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout.str())); check("void f(void) {\n" " return (int)1E100;\n" - "}", settings); + "}", settingsDefault); ASSERT_EQUALS("[test.cpp:2]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout.str())); check("void f(void) {\n" " return (int)-1E100;\n" - "}", settings); + "}", settingsDefault); ASSERT_EQUALS("[test.cpp:2]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout.str())); check("void f(void) {\n" " return (short)1E6;\n" - "}", settings); + "}", settingsDefault); ASSERT_EQUALS("[test.cpp:2]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout.str())); check("void f(void) {\n" " return (unsigned char)256.0;\n" - "}", settings); + "}", settingsDefault); ASSERT_EQUALS("[test.cpp:2]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout.str())); check("void f(void) {\n" " return (unsigned char)255.5;\n" - "}", settings); + "}", settingsDefault); ASSERT_EQUALS("", removeFloat(errout.str())); check("void f(void) {\n" " char c = 1234.5;\n" - "}", settings); + "}", settingsDefault); ASSERT_EQUALS("[test.cpp:2]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout.str())); check("char f(void) {\n" " return 1234.5;\n" - "}", settings); + "}", settingsDefault); ASSERT_EQUALS("[test.cpp:2]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout.str())); } void integerOverflow() { // #11794 - const Settings settings; // TODO: needs to use preprocessing production code simplecpp::DUI dui; dui.std = "c++11"; @@ -511,14 +507,14 @@ class TestType : public TestFixture { "int f()\n" "{\n" " fun(INT_MIN);\n" - "}", settings, "test.cpp", dui); + "}", settingsDefault, "test.cpp", dui); ASSERT_EQUALS("[test.cpp:3]: (error) Signed integer overflow for expression '-x'.\n", errout.str()); checkP("void f() {\n" // #8399 " int32_t i = INT32_MAX;\n" " i << 1;\n" " i << 2;\n" - "}", settings, "test.cpp", dui); + "}", settingsDefault, "test.cpp", dui); ASSERT_EQUALS("[test.cpp:4]: (error) Signed integer overflow for expression 'i<<2'.\n", errout.str()); } };