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
|
2010-04-13 21:23:17 +02:00
|
|
|
* Copyright (C) 2007-2010 Daniel Marjamäki and 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
|
|
|
*/
|
|
|
|
|
|
|
|
#include "testsuite.h"
|
2010-09-26 05:29:23 +02:00
|
|
|
#include "options.h"
|
2008-12-18 22:28:57 +01:00
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <list>
|
|
|
|
|
|
|
|
std::ostringstream errout;
|
2010-04-06 21:13:23 +02:00
|
|
|
std::ostringstream output;
|
2008-12-18 22:28:57 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* TestRegistry
|
|
|
|
**/
|
|
|
|
|
|
|
|
class TestRegistry
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
std::list<TestFixture *> _tests;
|
|
|
|
|
|
|
|
public:
|
|
|
|
static TestRegistry &theInstance()
|
|
|
|
{
|
|
|
|
static TestRegistry testreg;
|
|
|
|
return testreg;
|
|
|
|
}
|
|
|
|
|
2009-01-05 16:49:57 +01:00
|
|
|
void addTest(TestFixture *t)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
2009-01-05 16:49:57 +01:00
|
|
|
_tests.push_back(t);
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const std::list<TestFixture *> &tests() const
|
|
|
|
{
|
|
|
|
return _tests;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* TestFixture
|
|
|
|
**/
|
|
|
|
|
|
|
|
std::ostringstream TestFixture::errmsg;
|
|
|
|
unsigned int TestFixture::countTests;
|
|
|
|
|
2009-07-18 14:08:10 +02:00
|
|
|
size_t TestFixture::fails_counter = 0;
|
2010-01-29 18:49:07 +01:00
|
|
|
size_t TestFixture::todos_counter = 0;
|
2009-07-18 14:08:10 +02:00
|
|
|
|
2010-09-26 05:29:23 +02:00
|
|
|
TestFixture::TestFixture(const std::string &_name)
|
|
|
|
:classname(_name)
|
|
|
|
,gcc_style_errors(false)
|
|
|
|
,quiet_tests(false)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
|
|
|
TestRegistry::theInstance().addTest(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool TestFixture::runTest(const char testname[])
|
2008-12-17 20:18:39 +01:00
|
|
|
{
|
2010-04-02 07:30:58 +02:00
|
|
|
if (testToRun.empty() || testToRun == testname)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
2009-01-01 23:22:28 +01:00
|
|
|
++countTests;
|
2010-09-26 05:29:23 +02:00
|
|
|
if (quiet_tests)
|
|
|
|
{
|
|
|
|
std::cout << '.';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::cout << classname << "::" << testname << "\n";
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2009-01-05 16:49:57 +01:00
|
|
|
static std::string writestr(const std::string &str)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
|
|
|
std::ostringstream ostr;
|
|
|
|
ostr << "\"";
|
2010-04-02 07:30:58 +02:00
|
|
|
for (unsigned int i = 0; i < str.length(); ++i)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
|
|
|
char ch = str[i];
|
2010-04-02 07:30:58 +02:00
|
|
|
if (ch == '\n')
|
2008-12-18 22:28:57 +01:00
|
|
|
ostr << "\\n";
|
2010-04-02 07:30:58 +02:00
|
|
|
else if (ch == '\t')
|
2008-12-18 22:28:57 +01:00
|
|
|
ostr << "\\t";
|
2010-04-02 07:30:58 +02:00
|
|
|
else if (ch == '\"')
|
2008-12-18 22:28:57 +01:00
|
|
|
ostr << "\\\"";
|
|
|
|
else
|
|
|
|
ostr << std::string(1, ch);
|
|
|
|
}
|
|
|
|
ostr << "\"";
|
|
|
|
return ostr.str();
|
|
|
|
}
|
|
|
|
|
2010-12-27 21:19:48 +01:00
|
|
|
void TestFixture::assert_(const char *filename, int linenr, bool condition)
|
2010-04-15 18:37:51 +02:00
|
|
|
{
|
|
|
|
if (!condition)
|
|
|
|
{
|
|
|
|
++fails_counter;
|
2010-09-26 05:29:23 +02:00
|
|
|
if (gcc_style_errors)
|
|
|
|
{
|
|
|
|
errmsg << filename << ':' << linenr << ": Assertion failed." << std::endl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
errmsg << "Assertion failed in " << filename << " at line " << linenr << std::endl;
|
|
|
|
}
|
2010-04-15 18:37:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-13 22:14:29 +02:00
|
|
|
void TestFixture::assertEquals(const char *filename, int linenr, const std::string &expected, const std::string &actual, const std::string &msg)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
2010-04-02 07:30:58 +02:00
|
|
|
if (expected != actual)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
2009-07-18 14:08:10 +02:00
|
|
|
++fails_counter;
|
2010-09-26 05:29:23 +02:00
|
|
|
if (gcc_style_errors)
|
|
|
|
{
|
|
|
|
errmsg << filename << ':' << linenr << ": Assertion failed. "
|
|
|
|
<< "Expected: "
|
|
|
|
<< writestr(expected)
|
|
|
|
<< ". Actual: "
|
|
|
|
<< writestr(actual)
|
|
|
|
<< "."
|
|
|
|
<< std::endl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
errmsg << "Assertion failed in " << filename << " at line " << linenr << std::endl
|
|
|
|
<< "Expected:" << std::endl
|
|
|
|
<< writestr(expected) << std::endl
|
|
|
|
<< "Actual:" << std::endl
|
|
|
|
<< writestr(actual) << std::endl;
|
|
|
|
}
|
2010-05-14 18:40:37 +02:00
|
|
|
if (!msg.empty())
|
|
|
|
{
|
|
|
|
errmsg << msg << std::endl;
|
2010-05-13 22:14:29 +02:00
|
|
|
}
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-13 22:14:29 +02:00
|
|
|
void TestFixture::assertEquals(const char *filename, int linenr, double expected, double actual, const std::string &msg)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
|
|
|
std::ostringstream ostr1;
|
|
|
|
ostr1 << expected;
|
|
|
|
std::ostringstream ostr2;
|
|
|
|
ostr2 << actual;
|
2010-05-13 22:14:29 +02:00
|
|
|
assertEquals(filename, linenr, ostr1.str(), ostr2.str(), msg);
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
|
|
|
|
2010-01-29 18:49:07 +01:00
|
|
|
void TestFixture::todoAssertEquals(const char *filename, int linenr, const std::string &expected, const std::string &actual)
|
|
|
|
{
|
2010-04-02 07:30:58 +02:00
|
|
|
if (expected == actual)
|
2010-09-26 05:29:23 +02:00
|
|
|
{
|
2010-01-29 18:49:07 +01:00
|
|
|
assertEquals(filename, linenr, "TODO assertion", "The assertion succeeded");
|
2010-09-26 05:29:23 +02:00
|
|
|
}
|
2010-01-29 18:49:07 +01:00
|
|
|
else
|
2010-09-26 05:29:23 +02:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
void TestFixture::todoAssertEquals(const char *filename, int linenr, unsigned int expected, unsigned int actual)
|
|
|
|
{
|
|
|
|
std::ostringstream ostr1;
|
|
|
|
ostr1 << expected;
|
|
|
|
std::ostringstream ostr2;
|
|
|
|
ostr2 << actual;
|
|
|
|
todoAssertEquals(filename, linenr, ostr1.str(), ostr2.str());
|
|
|
|
}
|
|
|
|
|
2009-04-27 21:29:03 +02:00
|
|
|
void TestFixture::assertThrowFail(const char *filename, int linenr)
|
|
|
|
{
|
2009-07-18 14:08:10 +02:00
|
|
|
++fails_counter;
|
2010-09-26 05:29:23 +02:00
|
|
|
if (gcc_style_errors)
|
|
|
|
{
|
|
|
|
errmsg << filename << ':' << linenr << " Assertion failed. "
|
|
|
|
<< "The expected exception was not thrown" << std::endl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
errmsg << "Assertion failed in " << filename << " at line " << linenr << std::endl
|
|
|
|
<< "The expected exception was not thrown" << std::endl;
|
|
|
|
}
|
2009-04-27 21:29:03 +02:00
|
|
|
}
|
|
|
|
|
2008-12-18 22:28:57 +01:00
|
|
|
void TestFixture::printTests()
|
|
|
|
{
|
|
|
|
const std::list<TestFixture *> &tests = TestRegistry::theInstance().tests();
|
|
|
|
|
2010-04-02 07:30:58 +02:00
|
|
|
for (std::list<TestFixture *>::const_iterator it = tests.begin(); it != tests.end(); ++it)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
|
|
|
std::cout << (*it)->classname << std::endl;
|
|
|
|
}
|
|
|
|
}
|
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;
|
2010-09-26 05:29:23 +02:00
|
|
|
if (quiet_tests)
|
|
|
|
{
|
|
|
|
std::cout << '\n' << classname << ':';
|
|
|
|
}
|
2008-12-19 22:15:06 +01:00
|
|
|
run();
|
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();
|
|
|
|
gcc_style_errors = args.gcc_style_errors();
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t TestFixture::runTests(const options& args)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
2010-09-26 05:29:23 +02:00
|
|
|
std::string classname(args.which_test());
|
2008-12-18 22:28:57 +01:00
|
|
|
std::string testname("");
|
2010-04-02 07:30:58 +02:00
|
|
|
if (classname.find("::") != std::string::npos)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
2009-01-05 16:49:57 +01:00
|
|
|
testname = classname.substr(classname.find("::") + 2);
|
|
|
|
classname.erase(classname.find("::"));
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
countTests = 0;
|
|
|
|
errmsg.str("");
|
|
|
|
|
|
|
|
const std::list<TestFixture *> &tests = TestRegistry::theInstance().tests();
|
|
|
|
|
2010-04-02 07:30:58 +02:00
|
|
|
for (std::list<TestFixture *>::const_iterator it = tests.begin(); it != tests.end(); ++it)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
2010-04-02 07:30:58 +02:00
|
|
|
if (classname.empty() || (*it)->classname == classname)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
2010-09-26 05:29:23 +02:00
|
|
|
(*it)->processOptions(args);
|
2008-12-17 20:18:39 +01:00
|
|
|
(*it)->run(testname);
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::cout << "\n\nTesting Complete\nNumber of tests: " << countTests << "\n";
|
2010-01-29 18:49:07 +01:00
|
|
|
std::cout << "Number of todos: " << todos_counter << "\n";
|
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
|
|
|
|
2010-05-13 22:14:29 +02:00
|
|
|
std::cerr << "Tests failed: " << fails_counter << "\n";
|
2008-12-18 22:28:57 +01:00
|
|
|
std::cerr << errmsg.str();
|
2010-05-13 22:14:29 +02:00
|
|
|
std::cerr.flush();
|
2009-07-18 14:08:10 +02:00
|
|
|
return fails_counter;
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
|
|
|
|
2009-12-13 17:18:27 +01:00
|
|
|
void TestFixture::reportOut(const std::string & outmsg)
|
2008-12-18 22:28:57 +01:00
|
|
|
{
|
2010-04-06 21:13:23 +02:00
|
|
|
output << outmsg << std::endl;
|
2008-12-18 22:28:57 +01:00
|
|
|
}
|
2009-02-01 19:00:47 +01:00
|
|
|
|
2009-02-10 22:51:52 +01:00
|
|
|
void TestFixture::reportErr(const ErrorLogger::ErrorMessage &msg)
|
2009-02-01 19:00:47 +01:00
|
|
|
{
|
2010-11-11 19:54:43 +01:00
|
|
|
const std::string errormessage(msg.toString(false));
|
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
|
|
|
}
|