2008-12-18 22:28:57 +01:00
|
|
|
/*
|
2009-01-21 21:04:20 +01:00
|
|
|
* Cppcheck - A tool for static C/C++ code analysis
|
2023-01-28 10:16:34 +01:00
|
|
|
* Copyright (C) 2007-2023 Cppcheck team.
|
2008-12-18 22:28:57 +01:00
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2009-09-27 17:08:31 +02:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2008-12-18 22:28:57 +01:00
|
|
|
*/
|
|
|
|
|
2023-01-27 08:18:32 +01:00
|
|
|
#include "fixture.h"
|
2017-05-27 04:33:47 +02:00
|
|
|
|
2023-10-05 19:04:06 +02:00
|
|
|
#include "cppcheck.h"
|
2023-02-24 21:46:07 +01:00
|
|
|
#include "errortypes.h"
|
2010-09-26 05:29:23 +02:00
|
|
|
#include "options.h"
|
2015-11-29 10:49:10 +01:00
|
|
|
#include "redirect.h"
|
2008-12-18 22:28:57 +01:00
|
|
|
|
2023-10-09 10:07:20 +02:00
|
|
|
#include <algorithm>
|
2016-01-08 11:59:02 +01:00
|
|
|
#include <cstdio>
|
2021-07-10 20:14:38 +02:00
|
|
|
#include <cctype>
|
2023-02-24 21:46:07 +01:00
|
|
|
#include <exception>
|
2008-12-18 22:28:57 +01:00
|
|
|
#include <iostream>
|
2023-08-02 10:36:17 +02:00
|
|
|
#include <set>
|
2022-08-19 18:23:15 +02:00
|
|
|
#include <sstream>
|
2017-05-27 04:33:47 +02:00
|
|
|
#include <string>
|
2008-12-18 22:28:57 +01:00
|
|
|
|
2023-11-26 14:04:35 +01:00
|
|
|
#include "xml.h"
|
2023-05-04 10:31:05 +02:00
|
|
|
|
2008-12-18 22:28:57 +01:00
|
|
|
/**
|
|
|
|
* TestRegistry
|
|
|
|
**/
|
2021-02-27 04:33:16 +01:00
|
|
|
namespace {
|
2021-03-02 10:48:37 +01:00
|
|
|
struct CompareFixtures {
|
|
|
|
bool operator()(const TestFixture* lhs, const TestFixture* rhs) const {
|
|
|
|
return lhs->classname < rhs->classname;
|
|
|
|
}
|
|
|
|
};
|
2021-02-27 04:33:16 +01:00
|
|
|
}
|
2021-01-05 17:51:32 +01:00
|
|
|
using TestSet = std::set<TestFixture*, CompareFixtures>;
|
2023-11-16 15:49:41 +01:00
|
|
|
namespace {
|
|
|
|
class TestRegistry {
|
|
|
|
TestSet _tests;
|
|
|
|
public:
|
2018-04-04 20:51:47 +02:00
|
|
|
|
2023-11-16 15:49:41 +01:00
|
|
|
static TestRegistry &theInstance() {
|
|
|
|
static TestRegistry testreg;
|
|
|
|
return testreg;
|
|
|
|
}
|
2008-12-18 22:28:57 +01:00
|
|
|
|
2023-11-16 15:49:41 +01:00
|
|
|
void addTest(TestFixture *t) {
|
|
|
|
_tests.insert(t);
|
|
|
|
}
|
2008-12-18 22:28:57 +01:00
|
|
|
|
2023-11-16 15:49:41 +01:00
|
|
|
const TestSet &tests() const {
|
|
|
|
return _tests;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2008-12-18 22:28:57 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* TestFixture
|
|
|
|
**/
|
|
|
|
|
|
|
|
std::ostringstream TestFixture::errmsg;
|
2021-08-07 20:51:18 +02:00
|
|
|
unsigned int TestFixture::countTests;
|
2008-12-18 22:28:57 +01:00
|
|
|
|
2012-07-08 23:39:46 +02:00
|
|
|
std::size_t TestFixture::fails_counter = 0;
|
|
|
|
std::size_t TestFixture::todos_counter = 0;
|
|
|
|
std::size_t TestFixture::succeeded_todos_counter = 0;
|
2009-07-18 14:08:10 +02:00
|
|
|
|
2017-10-30 10:57:03 +01:00
|
|
|
TestFixture::TestFixture(const char * const _name)
|
2023-08-08 11:05:02 +02:00
|
|
|
: classname(_name)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
|
|
|
TestRegistry::theInstance().addTest(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-02 20:20:07 +02:00
|
|
|
bool TestFixture::prepareTest(const char testname[])
|
2008-12-17 20:18:39 +01:00
|
|
|
{
|
2018-08-11 11:40:48 +02:00
|
|
|
mVerbose = false;
|
|
|
|
mTemplateFormat.clear();
|
|
|
|
mTemplateLocation.clear();
|
2023-10-05 19:04:06 +02:00
|
|
|
CppCheck::resetTimerResults();
|
2018-08-11 11:40:48 +02:00
|
|
|
|
2023-08-12 21:43:12 +02:00
|
|
|
prepareTestInternal();
|
|
|
|
|
2014-08-02 20:20:07 +02:00
|
|
|
// Check if tests should be executed
|
2011-10-13 20:53:06 +02:00
|
|
|
if (testToRun.empty() || testToRun == testname) {
|
2014-08-02 20:20:07 +02:00
|
|
|
// Tests will be executed - prepare them
|
2018-12-21 13:55:24 +01:00
|
|
|
mTestname = testname;
|
2009-01-01 23:22:28 +01:00
|
|
|
++countTests;
|
2011-10-13 20:53:06 +02:00
|
|
|
if (quiet_tests) {
|
2014-08-02 20:20:07 +02:00
|
|
|
std::putchar('.'); // Use putchar to write through redirection of std::cout/cerr
|
2014-08-05 13:22:40 +02:00
|
|
|
std::fflush(stdout);
|
2011-10-13 20:53:06 +02:00
|
|
|
} else {
|
2023-03-04 12:05:17 +01:00
|
|
|
std::cout << classname << "::" << mTestname << std::endl;
|
2010-09-26 05:29:23 +02:00
|
|
|
}
|
2008-12-17 20:18:39 +01:00
|
|
|
return true;
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
2008-12-17 20:18:39 +01:00
|
|
|
return false;
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
|
|
|
|
2023-11-25 21:12:24 +01:00
|
|
|
void TestFixture::teardownTest()
|
|
|
|
{
|
|
|
|
teardownTestInternal();
|
2023-12-06 22:01:00 +01:00
|
|
|
|
|
|
|
// TODO: enable
|
|
|
|
/*
|
|
|
|
{
|
|
|
|
const std::string s = errout.str();
|
|
|
|
if (!s.empty())
|
|
|
|
throw std::runtime_error("unconsumed ErrorLogger err: " + s);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
const std::string s = output_str();
|
|
|
|
if (!s.empty())
|
|
|
|
throw std::runtime_error("unconsumed ErrorLogger out: " + s);
|
|
|
|
}
|
2023-11-25 21:12:24 +01:00
|
|
|
}
|
|
|
|
|
2018-12-21 13:55:24 +01:00
|
|
|
std::string TestFixture::getLocationStr(const char * const filename, const unsigned int linenr) const
|
|
|
|
{
|
2021-02-27 04:33:16 +01:00
|
|
|
return std::string(filename) + ':' + std::to_string(linenr) + '(' + classname + "::" + mTestname + ')';
|
2018-12-21 13:55:24 +01:00
|
|
|
}
|
|
|
|
|
2011-12-20 20:05:47 +01:00
|
|
|
static std::string writestr(const std::string &str, bool gccStyle = false)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
|
|
|
std::ostringstream ostr;
|
2011-12-20 20:05:47 +01:00
|
|
|
if (gccStyle)
|
|
|
|
ostr << '\"';
|
2022-12-20 20:32:16 +01:00
|
|
|
for (std::string::const_iterator i = str.cbegin(); i != str.cend(); ++i) {
|
2011-12-20 20:05:47 +01:00
|
|
|
if (*i == '\n') {
|
2008-12-18 22:28:57 +01:00
|
|
|
ostr << "\\n";
|
2011-12-20 20:05:47 +01:00
|
|
|
if ((i+1) != str.end() && !gccStyle)
|
|
|
|
ostr << std::endl;
|
|
|
|
} else if (*i == '\t')
|
2008-12-18 22:28:57 +01:00
|
|
|
ostr << "\\t";
|
2011-12-20 20:05:47 +01:00
|
|
|
else if (*i == '\"')
|
2008-12-18 22:28:57 +01:00
|
|
|
ostr << "\\\"";
|
2021-07-10 20:14:38 +02:00
|
|
|
else if (std::isprint(static_cast<unsigned char>(*i)))
|
2011-12-20 20:05:47 +01:00
|
|
|
ostr << *i;
|
2021-07-10 20:14:38 +02:00
|
|
|
else
|
|
|
|
ostr << "\\x" << std::hex << short{*i};
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
2011-12-20 20:05:47 +01:00
|
|
|
if (!str.empty() && !gccStyle)
|
|
|
|
ostr << std::endl;
|
|
|
|
else if (gccStyle)
|
|
|
|
ostr << '\"';
|
2008-12-18 22:28:57 +01:00
|
|
|
return ostr.str();
|
|
|
|
}
|
|
|
|
|
2019-09-16 06:34:45 +02:00
|
|
|
bool TestFixture::assert_(const char * const filename, const unsigned int linenr, const bool condition) const
|
2010-04-15 18:37:51 +02:00
|
|
|
{
|
2011-10-13 20:53:06 +02:00
|
|
|
if (!condition) {
|
2010-04-15 18:37:51 +02:00
|
|
|
++fails_counter;
|
2018-12-21 13:55:24 +01:00
|
|
|
errmsg << getLocationStr(filename, linenr) << ": Assertion failed." << std::endl << "_____" << std::endl;
|
2010-04-15 18:37:51 +02:00
|
|
|
}
|
2019-09-16 06:34:45 +02:00
|
|
|
return condition;
|
2010-04-15 18:37:51 +02:00
|
|
|
}
|
|
|
|
|
2021-02-23 08:19:05 +01:00
|
|
|
void TestFixture::assertEqualsFailed(const char* const filename, const unsigned int linenr, const std::string& expected, const std::string& actual, const std::string& msg) const
|
|
|
|
{
|
|
|
|
++fails_counter;
|
|
|
|
errmsg << getLocationStr(filename, linenr) << ": Assertion failed. " << std::endl
|
2021-02-24 21:47:16 +01:00
|
|
|
<< "Expected: " << std::endl
|
|
|
|
<< writestr(expected) << std::endl
|
|
|
|
<< "Actual: " << std::endl
|
|
|
|
<< writestr(actual) << std::endl;
|
2021-02-23 08:19:05 +01:00
|
|
|
if (!msg.empty())
|
|
|
|
errmsg << "Hint:" << std::endl << msg << std::endl;
|
|
|
|
errmsg << "_____" << std::endl;
|
|
|
|
}
|
|
|
|
|
2019-09-16 06:34:45 +02:00
|
|
|
bool TestFixture::assertEquals(const char * const filename, const unsigned int linenr, const std::string &expected, const std::string &actual, const std::string &msg) const
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
2011-10-13 20:53:06 +02:00
|
|
|
if (expected != actual) {
|
2021-02-23 08:19:05 +01:00
|
|
|
assertEqualsFailed(filename, linenr, expected, actual, msg);
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
2019-09-16 06:34:45 +02:00
|
|
|
return expected == actual;
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
2017-10-05 23:03:13 +02:00
|
|
|
|
2022-03-02 07:46:47 +01:00
|
|
|
std::string TestFixture::deleteLineNumber(const std::string &message)
|
2017-10-05 23:03:13 +02:00
|
|
|
{
|
|
|
|
std::string result(message);
|
|
|
|
// delete line number in "...:NUMBER:..."
|
|
|
|
std::string::size_type pos = 0;
|
|
|
|
while ((pos = result.find(':', pos)) != std::string::npos) {
|
|
|
|
// get number
|
|
|
|
if (pos + 1 == result.find_first_of("0123456789", pos + 1)) {
|
2022-10-02 07:12:40 +02:00
|
|
|
const std::string::size_type after = result.find_first_not_of("0123456789", pos + 1);
|
2022-07-28 22:53:59 +02:00
|
|
|
if (after != std::string::npos
|
2017-10-05 23:01:42 +02:00
|
|
|
&& result.at(after) == ':') {
|
2017-10-05 23:03:13 +02:00
|
|
|
// erase NUMBER
|
|
|
|
result.erase(pos + 1, after - pos - 1);
|
|
|
|
pos = after;
|
|
|
|
} else {
|
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-10-30 10:57:03 +01:00
|
|
|
void TestFixture::assertEqualsWithoutLineNumbers(const char * const filename, const unsigned int linenr, const std::string &expected, const std::string &actual, const std::string &msg) const
|
2017-10-05 23:03:13 +02:00
|
|
|
{
|
2017-10-10 23:43:50 +02:00
|
|
|
assertEquals(filename, linenr, deleteLineNumber(expected), deleteLineNumber(actual), msg);
|
2017-10-05 23:03:13 +02:00
|
|
|
}
|
|
|
|
|
2019-09-16 06:34:45 +02:00
|
|
|
bool TestFixture::assertEquals(const char * const filename, const unsigned int linenr, const char expected[], const std::string& actual, const std::string &msg) const
|
2015-06-28 12:34:08 +02:00
|
|
|
{
|
2019-09-16 06:34:45 +02:00
|
|
|
return assertEquals(filename, linenr, std::string(expected), actual, msg);
|
2015-06-28 12:34:08 +02:00
|
|
|
}
|
2019-09-16 06:34:45 +02:00
|
|
|
bool TestFixture::assertEquals(const char * const filename, const unsigned int linenr, const char expected[], const char actual[], const std::string &msg) const
|
2015-06-28 12:34:08 +02:00
|
|
|
{
|
2019-09-16 06:34:45 +02:00
|
|
|
return assertEquals(filename, linenr, std::string(expected), std::string(actual), msg);
|
2015-06-28 12:34:08 +02:00
|
|
|
}
|
2019-09-16 06:34:45 +02:00
|
|
|
bool TestFixture::assertEquals(const char * const filename, const unsigned int linenr, const std::string& expected, const char actual[], const std::string &msg) const
|
2015-06-28 12:34:08 +02:00
|
|
|
{
|
2019-09-16 06:34:45 +02:00
|
|
|
return assertEquals(filename, linenr, expected, std::string(actual), msg);
|
2015-06-28 12:34:08 +02:00
|
|
|
}
|
|
|
|
|
2019-09-16 06:34:45 +02:00
|
|
|
bool TestFixture::assertEquals(const char * const filename, const unsigned int linenr, const long long expected, const long long actual, const std::string &msg) const
|
2015-07-01 19:15:27 +02:00
|
|
|
{
|
2017-03-08 15:16:19 +01:00
|
|
|
if (expected != actual) {
|
2023-01-16 22:05:33 +01:00
|
|
|
assertEquals(filename, linenr, std::to_string(expected), std::to_string(actual), msg);
|
2017-03-08 15:16:19 +01:00
|
|
|
}
|
2019-09-16 06:34:45 +02:00
|
|
|
return expected == actual;
|
2015-07-01 19:15:27 +02:00
|
|
|
}
|
|
|
|
|
2017-10-30 10:57:03 +01:00
|
|
|
void TestFixture::assertEqualsDouble(const char * const filename, const unsigned int linenr, const double expected, const double actual, const double tolerance, const std::string &msg) const
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
2017-10-10 22:40:49 +02:00
|
|
|
if (expected < (actual - tolerance) || expected > (actual + tolerance)) {
|
2017-03-08 15:16:19 +01:00
|
|
|
std::ostringstream ostr1;
|
|
|
|
ostr1 << expected;
|
|
|
|
std::ostringstream ostr2;
|
|
|
|
ostr2 << actual;
|
|
|
|
assertEquals(filename, linenr, ostr1.str(), ostr2.str(), msg);
|
|
|
|
}
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
|
|
|
|
2017-10-30 10:57:03 +01:00
|
|
|
void TestFixture::todoAssertEquals(const char * const filename, const unsigned int linenr,
|
2011-01-30 12:54:19 +01:00
|
|
|
const std::string &wanted,
|
|
|
|
const std::string ¤t,
|
2012-08-01 20:54:55 +02:00
|
|
|
const std::string &actual) const
|
2010-01-29 18:49:07 +01:00
|
|
|
{
|
2011-10-13 20:53:06 +02:00
|
|
|
if (wanted == actual) {
|
2018-12-21 13:55:24 +01:00
|
|
|
errmsg << getLocationStr(filename, linenr) << ": Assertion succeeded unexpectedly. "
|
2017-01-29 15:41:26 +01:00
|
|
|
<< "Result: " << writestr(wanted, true) << std::endl << "_____" << std::endl;
|
|
|
|
|
2011-12-20 20:05:47 +01:00
|
|
|
++succeeded_todos_counter;
|
2011-10-13 20:53:06 +02:00
|
|
|
} else {
|
2011-12-20 20:05:47 +01:00
|
|
|
assertEquals(filename, linenr, current, actual);
|
2010-01-29 18:49:07 +01:00
|
|
|
++todos_counter;
|
2010-09-26 05:29:23 +02:00
|
|
|
}
|
2010-01-29 18:49:07 +01:00
|
|
|
}
|
|
|
|
|
2021-02-24 22:05:23 +01:00
|
|
|
void TestFixture::todoAssertEquals(const char* const filename, const unsigned int linenr,
|
|
|
|
const char wanted[],
|
|
|
|
const char current[],
|
|
|
|
const std::string& actual) const
|
|
|
|
{
|
|
|
|
todoAssertEquals(filename, linenr, std::string(wanted), std::string(current), actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-30 10:57:03 +01:00
|
|
|
void TestFixture::todoAssertEquals(const char * const filename, const unsigned int linenr, const long long wanted, const long long current, const long long actual) const
|
2010-01-29 18:49:07 +01:00
|
|
|
{
|
2023-01-16 22:05:33 +01:00
|
|
|
todoAssertEquals(filename, linenr, std::to_string(wanted), std::to_string(current), std::to_string(actual));
|
2010-01-29 18:49:07 +01:00
|
|
|
}
|
|
|
|
|
2017-10-30 10:57:03 +01:00
|
|
|
void TestFixture::assertThrow(const char * const filename, const unsigned int linenr) const
|
2016-04-22 06:02:54 +02:00
|
|
|
{
|
|
|
|
++fails_counter;
|
2018-12-21 13:55:24 +01:00
|
|
|
errmsg << getLocationStr(filename, linenr) << ": Assertion succeeded. "
|
2017-01-29 15:41:26 +01:00
|
|
|
<< "The expected exception was thrown" << std::endl << "_____" << std::endl;
|
|
|
|
|
2016-04-22 06:02:54 +02:00
|
|
|
}
|
|
|
|
|
2017-10-30 10:57:03 +01:00
|
|
|
void TestFixture::assertThrowFail(const char * const filename, const unsigned int linenr) const
|
2009-04-27 21:29:03 +02:00
|
|
|
{
|
2009-07-18 14:08:10 +02:00
|
|
|
++fails_counter;
|
2018-12-21 13:55:24 +01:00
|
|
|
errmsg << getLocationStr(filename, linenr) << ": Assertion failed. "
|
2017-01-29 15:41:26 +01:00
|
|
|
<< "The expected exception was not thrown" << std::endl << "_____" << std::endl;
|
|
|
|
|
2009-04-27 21:29:03 +02:00
|
|
|
}
|
|
|
|
|
2017-10-30 10:57:03 +01:00
|
|
|
void TestFixture::assertNoThrowFail(const char * const filename, const unsigned int linenr) const
|
2016-07-26 12:15:55 +02:00
|
|
|
{
|
|
|
|
++fails_counter;
|
2018-12-21 13:55:24 +01:00
|
|
|
errmsg << getLocationStr(filename, linenr) << ": Assertion failed. "
|
2017-01-29 15:41:26 +01:00
|
|
|
<< "Unexpected exception was thrown" << std::endl << "_____" << std::endl;
|
|
|
|
|
2016-07-26 12:15:55 +02:00
|
|
|
}
|
|
|
|
|
2019-03-02 08:06:23 +01:00
|
|
|
void TestFixture::printHelp()
|
|
|
|
{
|
|
|
|
std::cout << "Testrunner - run Cppcheck tests\n"
|
2021-08-07 20:51:18 +02:00
|
|
|
"\n"
|
|
|
|
"Syntax:\n"
|
|
|
|
" testrunner [OPTIONS] [TestClass::TestCase...]\n"
|
|
|
|
" run all test cases:\n"
|
|
|
|
" testrunner\n"
|
|
|
|
" run all test cases in TestClass:\n"
|
|
|
|
" testrunner TestClass\n"
|
|
|
|
" run TestClass::TestCase:\n"
|
|
|
|
" testrunner TestClass::TestCase\n"
|
|
|
|
" run all test cases in TestClass1 and TestClass2::TestCase:\n"
|
|
|
|
" testrunner TestClass1 TestClass2::TestCase\n"
|
|
|
|
"\n"
|
|
|
|
"Options:\n"
|
|
|
|
" -q Do not print the test cases that have run.\n"
|
|
|
|
" -h, --help Print this help.\n";
|
2019-03-02 08:06:23 +01:00
|
|
|
}
|
|
|
|
|
2008-12-17 20:18:39 +01:00
|
|
|
void TestFixture::run(const std::string &str)
|
2008-12-19 22:15:06 +01:00
|
|
|
{
|
|
|
|
testToRun = str;
|
2023-02-24 21:46:07 +01:00
|
|
|
try {
|
|
|
|
if (quiet_tests) {
|
|
|
|
std::cout << '\n' << classname << ':';
|
2023-03-04 12:05:17 +01:00
|
|
|
SUPPRESS;
|
2023-02-24 21:46:07 +01:00
|
|
|
run();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
run();
|
|
|
|
}
|
|
|
|
catch (const InternalError& e) {
|
|
|
|
++fails_counter;
|
2023-03-04 12:05:17 +01:00
|
|
|
errmsg << classname << "::" << mTestname << " - InternalError: " << e.errorMessage << std::endl;
|
2023-02-24 21:46:07 +01:00
|
|
|
}
|
|
|
|
catch (const std::exception& error) {
|
|
|
|
++fails_counter;
|
2023-03-04 12:05:17 +01:00
|
|
|
errmsg << classname << "::" << mTestname << " - Exception: " << error.what() << std::endl;
|
2023-02-24 21:46:07 +01:00
|
|
|
}
|
|
|
|
catch (...) {
|
|
|
|
++fails_counter;
|
2023-03-04 12:05:17 +01:00
|
|
|
errmsg << classname << "::" << mTestname << " - Unknown exception" << std::endl;
|
2023-02-24 21:46:07 +01:00
|
|
|
}
|
2008-12-17 20:18:39 +01:00
|
|
|
}
|
2008-12-18 22:28:57 +01:00
|
|
|
|
2010-09-26 05:29:23 +02:00
|
|
|
void TestFixture::processOptions(const options& args)
|
|
|
|
{
|
|
|
|
quiet_tests = args.quiet();
|
2021-07-08 21:21:35 +02:00
|
|
|
exename = args.exe();
|
2010-09-26 05:29:23 +02:00
|
|
|
}
|
|
|
|
|
2012-07-08 23:39:46 +02:00
|
|
|
std::size_t TestFixture::runTests(const options& args)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
|
|
|
countTests = 0;
|
|
|
|
errmsg.str("");
|
|
|
|
|
2019-04-30 21:01:18 +02:00
|
|
|
for (std::string classname : args.which_test()) {
|
2019-03-26 20:28:40 +01:00
|
|
|
std::string testname;
|
|
|
|
if (classname.find("::") != std::string::npos) {
|
|
|
|
testname = classname.substr(classname.find("::") + 2);
|
|
|
|
classname.erase(classname.find("::"));
|
|
|
|
}
|
2008-12-18 22:28:57 +01:00
|
|
|
|
2019-04-30 21:01:18 +02:00
|
|
|
for (TestFixture * test : TestRegistry::theInstance().tests()) {
|
2019-03-26 20:28:40 +01:00
|
|
|
if (classname.empty() || test->classname == classname) {
|
|
|
|
test->processOptions(args);
|
|
|
|
test->run(testname);
|
|
|
|
}
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-20 20:05:47 +01:00
|
|
|
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;
|
2010-05-13 22:14:29 +02:00
|
|
|
// calling flush here, to do all output before the error messages (in case the output is buffered)
|
|
|
|
std::cout.flush();
|
2008-12-18 22:28:57 +01:00
|
|
|
|
2011-12-20 20:05:47 +01:00
|
|
|
std::cerr << "Tests failed: " << fails_counter << std::endl << std::endl;
|
2008-12-18 22:28:57 +01:00
|
|
|
std::cerr << errmsg.str();
|
2014-01-12 12:44:24 +01:00
|
|
|
|
2010-05-13 22:14:29 +02:00
|
|
|
std::cerr.flush();
|
2023-03-26 15:13:07 +02:00
|
|
|
return fails_counter + succeeded_todos_counter;
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
|
|
|
|
2022-09-27 20:03:25 +02:00
|
|
|
void TestFixture::reportOut(const std::string & outmsg, Color /*c*/)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
2023-12-06 22:01:00 +01:00
|
|
|
mOutput << outmsg << std::endl;
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
2009-02-01 19:00:47 +01:00
|
|
|
|
2020-05-23 07:16:49 +02:00
|
|
|
void TestFixture::reportErr(const ErrorMessage &msg)
|
2009-02-01 19:00:47 +01:00
|
|
|
{
|
2023-12-18 18:26:23 +01:00
|
|
|
if (msg.severity == Severity::internal)
|
2023-08-29 12:00:52 +02:00
|
|
|
return;
|
2018-08-11 11:40:48 +02:00
|
|
|
const std::string errormessage(msg.toString(mVerbose, mTemplateFormat, mTemplateLocation));
|
2023-12-06 22:01:00 +01:00
|
|
|
// TODO: remove the unique error handling?
|
2010-10-24 18:26:59 +02:00
|
|
|
if (errout.str().find(errormessage) == std::string::npos)
|
|
|
|
errout << errormessage << std::endl;
|
2009-02-01 19:00:47 +01:00
|
|
|
}
|
2023-03-04 09:02:35 +01:00
|
|
|
|
|
|
|
void TestFixture::setTemplateFormat(const std::string &templateFormat)
|
|
|
|
{
|
|
|
|
if (templateFormat == "multiline") {
|
|
|
|
mTemplateFormat = "{file}:{line}:{severity}:{message}";
|
|
|
|
mTemplateLocation = "{file}:{line}:note:{info}";
|
|
|
|
}
|
|
|
|
else if (templateFormat == "simple") {
|
|
|
|
mTemplateFormat = "{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]";
|
|
|
|
mTemplateLocation = "";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mTemplateFormat = templateFormat;
|
|
|
|
mTemplateLocation = "";
|
|
|
|
}
|
|
|
|
}
|
2023-05-02 11:48:24 +02:00
|
|
|
|
|
|
|
TestFixture::SettingsBuilder& TestFixture::SettingsBuilder::library(const char lib[]) {
|
2023-08-09 12:43:55 +02:00
|
|
|
if (REDUNDANT_CHECK && std::find(settings.libraries.cbegin(), settings.libraries.cend(), lib) != settings.libraries.cend())
|
|
|
|
throw std::runtime_error("redundant setting: libraries (" + std::string(lib) + ")");
|
2023-05-02 11:48:24 +02:00
|
|
|
// TODO: exename is not yet set
|
|
|
|
LOAD_LIB_2_EXE(settings.library, lib, fixture.exename.c_str());
|
|
|
|
// strip extension
|
|
|
|
std::string lib_s(lib);
|
|
|
|
const std::string ext(".cfg");
|
|
|
|
const auto pos = lib_s.find(ext);
|
|
|
|
if (pos != std::string::npos)
|
|
|
|
lib_s.erase(pos, ext.size());
|
|
|
|
settings.libraries.emplace_back(lib_s);
|
|
|
|
return *this;
|
|
|
|
}
|
2023-05-02 15:54:19 +02:00
|
|
|
|
2023-10-13 16:02:04 +02:00
|
|
|
TestFixture::SettingsBuilder& TestFixture::SettingsBuilder::platform(Platform::Type type)
|
2023-05-02 15:54:19 +02:00
|
|
|
{
|
2023-10-13 16:02:04 +02:00
|
|
|
const std::string platformStr = Platform::toString(type);
|
2023-08-09 12:43:55 +02:00
|
|
|
|
2023-09-11 11:08:23 +02:00
|
|
|
if (REDUNDANT_CHECK && settings.platform.type == type)
|
|
|
|
throw std::runtime_error("redundant setting: platform (" + platformStr + ")");
|
2023-08-09 12:43:55 +02:00
|
|
|
|
2023-05-02 15:54:19 +02:00
|
|
|
std::string errstr;
|
|
|
|
// TODO: exename is not yet set
|
|
|
|
if (!settings.platform.set(platformStr, errstr, {fixture.exename}))
|
|
|
|
throw std::runtime_error("platform '" + platformStr + "' not found");
|
|
|
|
return *this;
|
|
|
|
}
|
2023-05-04 10:31:05 +02:00
|
|
|
|
|
|
|
TestFixture::SettingsBuilder& TestFixture::SettingsBuilder::libraryxml(const char xmldata[], std::size_t len)
|
|
|
|
{
|
|
|
|
tinyxml2::XMLDocument doc;
|
|
|
|
if (tinyxml2::XML_SUCCESS != doc.Parse(xmldata, len))
|
|
|
|
throw std::runtime_error("loading XML data failed");
|
|
|
|
if (settings.library.load(doc).errorcode != Library::ErrorCode::OK)
|
|
|
|
throw std::runtime_error("loading library XML failed");
|
|
|
|
return *this;
|
|
|
|
}
|