Skip to content

Conversation

eljonny
Copy link
Owner

@eljonny eljonny commented Feb 20, 2025

new branch to handle #8 since the other branch got super far behind main.

@eljonny eljonny self-assigned this Feb 20, 2025
@eljonny eljonny linked an issue Feb 20, 2025 that may be closed by this pull request
Copy link

github-actions bot commented Feb 20, 2025

⚡ Static analysis result ⚡

🔴 cppcheck found 23 issues! Click here to see details.

static constexpr const char* nullAssertionMessage = "Null assertion failed!";
bool null = ptr == nullptr;
if (!null) {
return logTestFailure(
"", "",

!Line: 304 - style: The scope of the variable 'nullAssertionMessage' can be reduced. [variableScope]

static constexpr const char* notNullAssertionMessage = "Not Null assertion failed!";
bool notNull = ptr != nullptr;
if (!notNull) {
return logTestFailure(
"", "",

!Line: 324 - style: The scope of the variable 'notNullAssertionMessage' can be reduced. [variableScope]

void clearStdoutCapture ();
/**
* @brief Clears the captured output from std::clog.
*
* This can be used for checking sections of output based on

!Line: 199 - performance: inconclusive: Technically the member function 'TestCPP::TestCase::clearStdoutCapture' can be static (but you may consider moving to unnamed namespace). [functionStatic]

!Line: 461 - note: Technically the member function 'TestCPP::TestCase::clearStdoutCapture' can be static (but you may consider moving to unnamed namespace).
!Line: 199 - note: Technically the member function 'TestCPP::TestCase::clearStdoutCapture' can be static (but you may consider moving to unnamed namespace).

void clearLogCapture ();
/**
* @brief Clears the captured output from stderr.
*
* This can be used for checking sections of output based on

!Line: 207 - performance: inconclusive: Technically the member function 'TestCPP::TestCase::clearLogCapture' can be static (but you may consider moving to unnamed namespace). [functionStatic]

!Line: 467 - note: Technically the member function 'TestCPP::TestCase::clearLogCapture' can be static (but you may consider moving to unnamed namespace).
!Line: 207 - note: Technically the member function 'TestCPP::TestCase::clearLogCapture' can be static (but you may consider moving to unnamed namespace).

void clearStderrCapture ();
/**
* @brief Check the argument against what is captured from
* stdout using the configured comparison mode.
* @param against The value to check the captured output against

!Line: 215 - performance: inconclusive: Technically the member function 'TestCPP::TestCase::clearStderrCapture' can be static (but you may consider moving to unnamed namespace). [functionStatic]

!Line: 473 - note: Technically the member function 'TestCPP::TestCase::clearStderrCapture' can be static (but you may consider moving to unnamed namespace).
!Line: 215 - note: Technically the member function 'TestCPP::TestCase::clearStderrCapture' can be static (but you may consider moving to unnamed namespace).

void logFailure (ostream& out, string& reason);
/**
* @brief If a test encounters an error while running, this
* function will be called to log the test error.
* @param failureMessage The error message from the test that
* should be logged.

!Line: 292 - style: inconclusive: Technically the member function 'TestCPP::TestCase::logFailure' can be const. [functionConst]

!Line: 292 - note: Technically the member function 'TestCPP::TestCase::logFailure' can be const.
!Line: 292 - note: Technically the member function 'TestCPP::TestCase::logFailure' can be const.

this->outCompareOption(std::move(o.option));
this->setNotifyPassed(std::move(o.notifyTestPassed));
this->pass = std::move(o.pass);
this->lastRunTime = std::move(o.lastRunTime);

!Line: 171 - error: Exception thrown in function declared not to throw exceptions. [throwInNoexceptFunction]

this->outCompareOption(std::move(rhs.option));
this->setNotifyPassed(std::move(rhs.notifyTestPassed));
this->pass = std::move(rhs.pass);
this->lastRunTime = std::move(rhs.lastRunTime);

!Line: 262 - error: Exception thrown in function declared not to throw exceptions. [throwInNoexceptFunction]

TestCase::TestCase (TestObjName&& name,
function<void()> testFn,
bool msg,
bool captureOut, bool captureLog,
bool captureErr,
TestCase::TestCaseOutCompareOptions opt)

!Line: 114 - style: inconclusive: Function 'TestCase' argument 1 names different: declaration 'testName' definition 'name'. [funcArgNamesDifferent]

!Line: 132 - note: Function 'TestCase' argument 1 names different: declaration 'testName' definition 'name'.
!Line: 114 - note: Function 'TestCase' argument 1 names different: declaration 'testName' definition 'name'.

function<void()> testFn,
bool msg,
bool captureOut, bool captureLog,
bool captureErr,
TestCase::TestCaseOutCompareOptions opt)
{

!Line: 115 - style: inconclusive: Function 'TestCase' argument 2 names different: declaration 'test' definition 'testFn'. [funcArgNamesDifferent]

!Line: 133 - note: Function 'TestCase' argument 2 names different: declaration 'test' definition 'testFn'.
!Line: 115 - note: Function 'TestCase' argument 2 names different: declaration 'test' definition 'testFn'.

bool msg,
bool captureOut, bool captureLog,
bool captureErr,
TestCase::TestCaseOutCompareOptions opt)
{
this->notifyTestPassed = msg;

!Line: 116 - style: inconclusive: Function 'TestCase' argument 3 names different: declaration 'testPassedMessage' definition 'msg'. [funcArgNamesDifferent]

!Line: 134 - note: Function 'TestCase' argument 3 names different: declaration 'testPassedMessage' definition 'msg'.
!Line: 116 - note: Function 'TestCase' argument 3 names different: declaration 'testPassedMessage' definition 'msg'.

void TestCase::logTestFailure (string reason) {
unique_ptr<ostream> logStream = nullptr;
if (this->clogOriginal.get() != nullptr) {
logStream = unique_ptr<ostream>(
new ostream(this->clogOriginal.get().get())

!Line: 304 - style: inconclusive: Function 'logTestFailure' argument 1 names different: declaration 'failureMessage' definition 'reason'. [funcArgNamesDifferent]

!Line: 299 - note: Function 'logTestFailure' argument 1 names different: declaration 'failureMessage' definition 'reason'.
!Line: 304 - note: Function 'logTestFailure' argument 1 names different: declaration 'failureMessage' definition 'reason'.

void TestCase::setNotifyPassed (bool notify) {
this->notifyTestPassed = notify;
}
void TestCase::captureStdout () {
if (TestCase::stdoutCaptureCasesConstructed ==

!Line: 371 - style: inconclusive: Function 'setNotifyPassed' argument 1 names different: declaration 'shouldNotify' definition 'notify'. [funcArgNamesDifferent]

!Line: 180 - note: Function 'setNotifyPassed' argument 1 names different: declaration 'shouldNotify' definition 'notify'.
!Line: 371 - note: Function 'setNotifyPassed' argument 1 names different: declaration 'shouldNotify' definition 'notify'.

TestCase::TestCase (TestCase& o) {
this->outCompareOption(o.option);
this->setNotifyPassed(o.notifyTestPassed);
this->pass = o.pass;
this->lastRunTime = o.lastRunTime;

!Line: 145 - style: Parameter 'o' can be declared as reference to const [constParameterReference]

TestCase& TestCase::operator= (TestCase& rhs) {
this->outCompareOption(rhs.option);
this->setNotifyPassed(rhs.notifyTestPassed);
this->pass = rhs.pass;
this->lastRunTime = rhs.lastRunTime;

!Line: 234 - style: Parameter 'rhs' can be declared as reference to const [constParameterReference]

void TestCase::logFailure(ostream& out, string& reason) {
out << fixed;
out << setprecision(TCPPNum::TIME_PRECISION);
out << TCPPStr::TEST << this->testName << TCPPStr::FAIL
<< TCPPStr::PARENL
<< static_cast<double>(this->lastRunTime)/

!Line: 292 - style: Parameter 'reason' can be declared as reference to const [constParameterReference]

TestSuite (TestObjName&& suiteName,
typename enable_if<sizeof...(TestType) == 0>::type)
{
this->testSuitePassedMessage = true;
this->setSuiteName(std::move(suiteName));
this->tests = vector<TestCase>();

!Line: 80 - warning: Member variable 'TestSuite::lastRunSucceeded' is not initialized in the constructor. [uninitMemberVar]

TestSuite (TestObjName&& suiteName,
typename enable_if<sizeof...(TestType) == 0>::type)
{
this->testSuitePassedMessage = true;
this->setSuiteName(std::move(suiteName));
this->tests = vector<TestCase>();

!Line: 80 - warning: Member variable 'TestSuite::lastRunSuccessCount' is not initialized in the constructor. [uninitMemberVar]

TestSuite (TestObjName&& suiteName,
typename enable_if<sizeof...(TestType) == 0>::type)
{
this->testSuitePassedMessage = true;
this->setSuiteName(std::move(suiteName));
this->tests = vector<TestCase>();

!Line: 80 - warning: Member variable 'TestSuite::lastRunFailCount' is not initialized in the constructor. [uninitMemberVar]

TestSuite (TestObjName&& suiteName,
typename enable_if<sizeof...(TestType) == 0>::type)
{
this->testSuitePassedMessage = true;
this->setSuiteName(std::move(suiteName));
this->tests = vector<TestCase>();

!Line: 80 - warning: Member variable 'TestSuite::totalRuntime' is not initialized in the constructor. [uninitMemberVar]

inline addTests () { }
/**
* @brief Add one or more tests at once to the test suite.
* @param test The first test to add.
* @param tests The rest of the tests to add.

!Line: 117 - performance: inconclusive: Technically the member function 'TestCPP::TestSuite::addTests' can be static (but you may consider moving to unnamed namespace). [functionStatic]

unsigned getLastRunFailCount ();
/**
* @brief Run all tests in the test suite.
*/
void run ();

!Line: 153 - style: inconclusive: Technically the member function 'TestCPP::TestSuite::getLastRunFailCount' can be const. [functionConst]

!Line: 73 - note: Technically the member function 'TestCPP::TestSuite::getLastRunFailCount' can be const.
!Line: 153 - note: Technically the member function 'TestCPP::TestSuite::getLastRunFailCount' can be const.

const string& getName ();
/**
* @brief Output the test object name to the specified stream.
* @param s The stream to output to.
* @param tcName The test object name object.

!Line: 81 - style: inconclusive: Technically the member function 'TestCPP::TestObjName::getName' can be const. [functionConst]

!Line: 59 - note: Technically the member function 'TestCPP::TestObjName::getName' can be const.
!Line: 81 - note: Technically the member function 'TestCPP::TestObjName::getName' can be const.

🔴 clang-tidy found 146 issues! Click here to see details.

static constexpr const char * SP = " ";
static constexpr const char * START_RUN =
"Starting run of test ";
static constexpr const char * SUITE = "Suite ";
static constexpr const char * SUITE_TESTS_PASSED =
" suite tests passed!";

!Line: 88 - error: variable name 'SP' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]

TestObjName (const char* name);
/**
* @brief Get the encapsulated name for the TestCPP object that
* holds this object.
* @return The name of the TestCPP object that this object

!Line: 73 - error: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [hicpp-explicit-conversions,-warnings-as-errors]

const string& getName ();
/**
* @brief Output the test object name to the specified stream.
* @param s The stream to output to.
* @param tcName The test object name object.

!Line: 81 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

friend std::ostream& operator<< (
std::ostream& s,
TestObjName& tcName
);
private:

!Line: 89 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

std::ostream& s,
TestObjName& tcName
);
private:
string testCaseName;

!Line: 90 - error: parameter name 's' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]

template <class T> class no_destroy {
alignas(T) unsigned char data[sizeof(T)];
public:
template <class... Ts> no_destroy(Ts&&... ts) { new (data) T(std::forward<Ts>(ts)...); }
T& get() { return *reinterpret_cast<T*>(data); }
};

!Line: 106 - error: constructor does not initialize these fields: data [cppcoreguidelines-pro-type-member-init,hicpp-member-init,-warnings-as-errors]

alignas(T) unsigned char data[sizeof(T)];
public:
template <class... Ts> no_destroy(Ts&&... ts) { new (data) T(std::forward<Ts>(ts)...); }
T& get() { return *reinterpret_cast<T*>(data); }
};

!Line: 107 - error: do not declare C-style arrays, use std::array<> instead [cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,-warnings-as-errors]

template <class... Ts> no_destroy(Ts&&... ts) { new (data) T(std::forward<Ts>(ts)...); }
T& get() { return *reinterpret_cast<T*>(data); }
};
/**
* @brief Log a message that will only be output when debug

!Line: 109 - error: constructor does not initialize these fields: data [cppcoreguidelines-pro-type-member-init,hicpp-member-init,-warnings-as-errors]

template <class... Ts> no_destroy(Ts&&... ts) { new (data) T(std::forward<Ts>(ts)...); }
T& get() { return *reinterpret_cast<T*>(data); }
};
/**
* @brief Log a message that will only be output when debug

!Line: 109 - error: constructors that are callable with a single argument must be marked explicit to avoid unintentional implicit conversions [hicpp-explicit-conversions,-warnings-as-errors]

template <class... Ts> no_destroy(Ts&&... ts) { new (data) T(std::forward<Ts>(ts)...); }
T& get() { return *reinterpret_cast<T*>(data); }
};
/**
* @brief Log a message that will only be output when debug

!Line: 109 - error: parameter name 'ts' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]

T& get() { return *reinterpret_cast<T*>(data); }
};
/**
* @brief Log a message that will only be output when debug
* logging is enabled.

!Line: 110 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

T& get() { return *reinterpret_cast<T*>(data); }
};
/**
* @brief Log a message that will only be output when debug
* logging is enabled.

!Line: 110 - error: do not use reinterpret_cast [cppcoreguidelines-pro-type-reinterpret-cast,-warnings-as-errors]

bool stringContains (const string& source,
const string& contains);
/**
* @brief Safely converts unsigned integer values to signed.
* @param toCast The unsigned value to convert.

!Line: 136 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

int unsignedToSigned(unsigned toCast);
}
}
#endif

!Line: 144 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

if (name) {
this->testCaseName = name;
}
else {
throw TestCPPException(TCPPStr::NVTN);
}

!Line: 51 - error: implicit conversion 'const char *' -> 'bool' [readability-implicit-bool-conversion,-warnings-as-errors]

const string& TestObjName::getName () {
return this->testCaseName;
}
std::ostream& operator<< (
std::ostream& s,

!Line: 59 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

std::ostream& operator<< (
std::ostream& s,
TestObjName& tcName
)
{
s << tcName.getName();

!Line: 63 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

std::ostream& s,
TestObjName& tcName
)
{
s << tcName.getName();
return s;

!Line: 64 - error: parameter name 's' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]

clog << endl;
}
#endif
}
bool stringContains(const string& source,

!Line: 78 - error: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]

bool stringContains(const string& source,
const string& contains)
{
return source.find(contains) != string::npos;
}

!Line: 83 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

int unsignedToSigned(unsigned toCast) {
if (toCast <= INT_MAX) {
return static_cast<int>(toCast);
}
if (toCast >= static_cast<unsigned>(INT_MIN)) {

!Line: 89 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

#include <iostream>
#include "internal/TestCPPExceptions.h"
#ifdef TESTCPP_STACKTRACE_ENABLED
#include <boost/stacktrace.hpp>

!Line: 28 - error: included header iostream is not used directly [misc-include-cleaner,-warnings-as-errors]

using std::string;
using std::runtime_error;
namespace TestCPP {
TestCPPException::TestCPPException (const char * msg) :

!Line: 37 - error: no header providing "std::string" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::runtime_error;
namespace TestCPP {
TestCPPException::TestCPPException (const char * msg) :
runtime_error(msg)

!Line: 38 - error: no header providing "std::runtime_error" is directly included [misc-include-cleaner,-warnings-as-errors]

TestCPPException(std::move(msg))
{
#ifdef TESTCPP_STACKTRACE_ENABLED
clog << boost::stacktrace::stacktrace();
#endif
}

!Line: 66 - error: std::move of the const variable 'msg' has no effect or make the variable non-const [hicpp-move-const-arg,performance-move-const-arg,-warnings-as-errors]

!Line: 49 - note: consider changing the 1st parameter of 'TestCPPException' from 'const string &&' (aka 'const basic_string<char> &&') to 'const string &'

TestCPPException(std::move(msg))
{
#ifdef TESTCPP_STACKTRACE_ENABLED
clog << boost::stacktrace::stacktrace();
#endif
}

!Line: 66 - error: no header providing "std::move" is directly included [misc-include-cleaner,-warnings-as-errors]

if (err.size()) {
throw TestFailedException(std::move(err));
}
}
/**

!Line: 84 - error: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty,-warnings-as-errors]

throw TestFailedException(std::move(err));
}
}
/**
* @brief Check that something is not equivalent to something

!Line: 85 - error: std::move of the const variable 'err' has no effect or make the variable non-const [hicpp-move-const-arg,performance-move-const-arg,-warnings-as-errors]

!Line: 98 - note: consider changing the 1st parameter of 'TestFailedException' from 'const string &&' (aka 'const basic_string<char> &&') to 'const string &'

if (err.size()) {
throw TestFailedException(std::move(err));
}
}
/**

!Line: 110 - error: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty,-warnings-as-errors]

throw TestFailedException(std::move(err));
}
}
/**
* @brief Check that a pointer is null.

!Line: 111 - error: std::move of the const variable 'err' has no effect or make the variable non-const [hicpp-move-const-arg,performance-move-const-arg,-warnings-as-errors]

!Line: 98 - note: consider changing the 1st parameter of 'TestFailedException' from 'const string &&' (aka 'const basic_string<char> &&') to 'const string &'

if (err.size()) {
throw TestFailedException(std::move(err));
}
}
/**

!Line: 131 - error: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty,-warnings-as-errors]

throw TestFailedException(std::move(err));
}
}
/**
* @brief Check that a pointer is non-null.

!Line: 132 - error: std::move of the const variable 'err' has no effect or make the variable non-const [hicpp-move-const-arg,performance-move-const-arg,-warnings-as-errors]

!Line: 98 - note: consider changing the 1st parameter of 'TestFailedException' from 'const string &&' (aka 'const basic_string<char> &&') to 'const string &'

if (err.size()) {
throw TestFailedException(std::move(err));
}
}
/**

!Line: 152 - error: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty,-warnings-as-errors]

throw TestFailedException(std::move(err));
}
}
/**
* @brief Verify that a function throws something.

!Line: 153 - error: std::move of the const variable 'err' has no effect or make the variable non-const [hicpp-move-const-arg,performance-move-const-arg,-warnings-as-errors]

!Line: 98 - note: consider changing the 1st parameter of 'TestFailedException' from 'const string &&' (aka 'const basic_string<char> &&') to 'const string &'

static const string logTestFailure(
T1 expectationValue, T2 actual,
const string& assertionTypeMessage,
const string& failureMessage,
const bool logValues
)

!Line: 243 - error: return type 'const string' (aka 'const basic_string<char>') is 'const'-qualified at the top level, which may reduce code readability without improving const correctness [readability-const-return-type,-warnings-as-errors]

static const string logTestFailure(
T1 expectationValue, T2 actual,
const string& assertionTypeMessage,
const string& failureMessage,
const bool logValues
)

!Line: 243 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

err << assertionTypeMessage << endl;
err << failureMessage << endl;
if (logValues) {
err << "Expectation value: <" << expectationValue << ">"
<< endl;

!Line: 252 - error: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]

err << failureMessage << endl;
if (logValues) {
err << "Expectation value: <" << expectationValue << ">"
<< endl;
err << "Actual: <" << actual << ">" << endl;

!Line: 253 - error: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]

static const string checkEquals(
T1 expected, T2 actual,
const string& failureMessage
)
{
if (expected != actual) {

!Line: 265 - error: return type 'const string' (aka 'const basic_string<char>') is 'const'-qualified at the top level, which may reduce code readability without improving const correctness [readability-const-return-type,-warnings-as-errors]

static const string checkEquals(
T1 expected, T2 actual,
const string& failureMessage
)
{
if (expected != actual) {

!Line: 265 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

static const string checkNotEquals(
T1 shouldNotBe, T2 actual,
const string& failureMessage
)
{
if (shouldNotBe == actual) {

!Line: 282 - error: return type 'const string' (aka 'const basic_string<char>') is 'const'-qualified at the top level, which may reduce code readability without improving const correctness [readability-const-return-type,-warnings-as-errors]

static const string checkNotEquals(
T1 shouldNotBe, T2 actual,
const string& failureMessage
)
{
if (shouldNotBe == actual) {

!Line: 282 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

static const string checkNull(
T ptr,
const string& failureMessage
)
{
static constexpr const char* nullAssertionMessage = "Null assertion failed!";

!Line: 299 - error: return type 'const string' (aka 'const basic_string<char>') is 'const'-qualified at the top level, which may reduce code readability without improving const correctness [readability-const-return-type,-warnings-as-errors]

static const string checkNull(
T ptr,
const string& failureMessage
)
{
static constexpr const char* nullAssertionMessage = "Null assertion failed!";

!Line: 299 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

static const string checkNotNull(
T ptr,
const string& failureMessage
)
{
static constexpr const char* notNullAssertionMessage = "Not Null assertion failed!";

!Line: 319 - error: return type 'const string' (aka 'const basic_string<char>') is 'const'-qualified at the top level, which may reduce code readability without improving const correctness [readability-const-return-type,-warnings-as-errors]

static const string checkNotNull(
T ptr,
const string& failureMessage
)
{
static constexpr const char* notNullAssertionMessage = "Not Null assertion failed!";

!Line: 319 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

const string TestCPP::Assertions::checkEquals<const char*, const char*>(
const char* expected, const char* actual,
const string& failureMessage
);
template<>

!Line: 389 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

const string TestCPP::Assertions::checkNotEquals<const char*, const char*>(
const char* shouldNotBe, const char* actual,
const string& failureMessage
);
#endif

!Line: 395 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

using std::clog;
using std::current_exception;
using std::endl;
using std::exception;
using std::exception_ptr;
using std::function;

!Line: 30 - error: no header providing "std::clog" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::current_exception;
using std::endl;
using std::exception;
using std::exception_ptr;
using std::function;
using std::rethrow_exception;

!Line: 31 - error: no header providing "std::current_exception" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::exception;
using std::exception_ptr;
using std::function;
using std::rethrow_exception;
using std::string;
using std::stringstream;

!Line: 33 - error: no header providing "std::exception" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::exception_ptr;
using std::function;
using std::rethrow_exception;
using std::string;
using std::stringstream;

!Line: 34 - error: no header providing "std::__exception_ptr::exception_ptr" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::rethrow_exception;
using std::string;
using std::stringstream;
namespace TestCPP {

!Line: 36 - error: no header providing "std::rethrow_exception" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::string;
using std::stringstream;
namespace TestCPP {
template<>

!Line: 37 - error: no header providing "std::string" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::stringstream;
namespace TestCPP {
template<>
const string Assertions::checkEquals<const char*, const char*>(

!Line: 38 - error: no header providing "std::stringstream" is directly included [misc-include-cleaner,-warnings-as-errors]

const string Assertions::checkEquals<const char*, const char*>(
const char* expected, const char* actual,
const string& failureMessage
)
{
if (strcmp(expected, actual)) {

!Line: 43 - error: return type 'const string' (aka 'const basic_string<char>') is 'const'-qualified at the top level, which may reduce code readability without improving const correctness [readability-const-return-type,-warnings-as-errors]

const string Assertions::checkEquals<const char*, const char*>(
const char* expected, const char* actual,
const string& failureMessage
)
{
if (strcmp(expected, actual)) {

!Line: 43 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

if (strcmp(expected, actual)) {
return logTestFailure(
expected, actual,
equivalenceAssertionMessage,
failureMessage,
true

!Line: 48 - error: function 'strcmp' is called without explicitly comparing result [bugprone-suspicious-string-compare,-warnings-as-errors]

if (strcmp(expected, actual)) {
return logTestFailure(
expected, actual,
equivalenceAssertionMessage,
failureMessage,
true

!Line: 48 - error: no header providing "strcmp" is directly included [misc-include-cleaner,-warnings-as-errors]

if (strcmp(expected, actual)) {
return logTestFailure(
expected, actual,
equivalenceAssertionMessage,
failureMessage,
true

!Line: 48 - error: implicit conversion 'int' -> 'bool' [readability-implicit-bool-conversion,-warnings-as-errors]

const string Assertions::checkNotEquals<const char*, const char*>(
const char* shouldNotBe, const char* actual,
const string& failureMessage
)
{
if (!strcmp(shouldNotBe, actual)) {

!Line: 60 - error: return type 'const string' (aka 'const basic_string<char>') is 'const'-qualified at the top level, which may reduce code readability without improving const correctness [readability-const-return-type,-warnings-as-errors]

const string Assertions::checkNotEquals<const char*, const char*>(
const char* shouldNotBe, const char* actual,
const string& failureMessage
)
{
if (!strcmp(shouldNotBe, actual)) {

!Line: 60 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

if (!strcmp(shouldNotBe, actual)) {
return logTestFailure(
shouldNotBe, actual,
nonequivalenceAssertionMessage,
failureMessage,
true

!Line: 65 - error: implicit conversion 'int' -> 'bool' [readability-implicit-bool-conversion,-warnings-as-errors]

if (err.size()) {
throw TestFailedException(std::move(err));
}
}
template<>

!Line: 83 - error: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty,-warnings-as-errors]

if (err.size()) {
throw TestFailedException(std::move(err));
}
}
template<>

!Line: 83 - error: implicit conversion 'size_type' (aka 'unsigned long') -> 'bool' [readability-implicit-bool-conversion,-warnings-as-errors]

throw TestFailedException(std::move(err));
}
}
template<>
void Assertions::assertNotEquals<const char*, const char*>(

!Line: 84 - error: std::move of the const variable 'err' has no effect or make the variable non-const [hicpp-move-const-arg,performance-move-const-arg,-warnings-as-errors]

!Line: 98 - note: consider changing the 1st parameter of 'TestFailedException' from 'const string &&' (aka 'const basic_string<char> &&') to 'const string &'

throw TestFailedException(std::move(err));
}
}
template<>
void Assertions::assertNotEquals<const char*, const char*>(

!Line: 84 - error: no header providing "std::move" is directly included [misc-include-cleaner,-warnings-as-errors]

if (err.size()) {
throw TestFailedException(std::move(err));
}
}
void Assertions::assertThrows (

!Line: 96 - error: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty,-warnings-as-errors]

if (err.size()) {
throw TestFailedException(std::move(err));
}
}
void Assertions::assertThrows (

!Line: 96 - error: implicit conversion 'size_type' (aka 'unsigned long') -> 'bool' [readability-implicit-bool-conversion,-warnings-as-errors]

throw TestFailedException(std::move(err));
}
}
void Assertions::assertThrows (
function<void()> shouldThrow,

!Line: 97 - error: std::move of the const variable 'err' has no effect or make the variable non-const [hicpp-move-const-arg,performance-move-const-arg,-warnings-as-errors]

!Line: 98 - note: consider changing the 1st parameter of 'TestFailedException' from 'const string &&' (aka 'const basic_string<char> &&') to 'const string &'

function<void()> shouldThrow,
const string& failureMessage
)
{
try {
shouldThrow();

!Line: 102 - error: the parameter 'shouldThrow' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param,-warnings-as-errors]

exception_ptr eptr = current_exception();
if (eptr) {
try {
rethrow_exception(eptr);
}

!Line: 110 - error: variable 'eptr' of type 'exception_ptr' can be declared 'const' [misc-const-correctness,-warnings-as-errors]

<< endl;
}
}
else {
clog << "Something was thrown, not sure what." << endl
<< "This satisfies the assertion, so no failure is"

!Line: 119 - error: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]

clog << "Something was thrown, not sure what." << endl
<< "This satisfies the assertion, so no failure is"
<< " present. "
<< TestFailedException("Unknown thrown object").
what();
}

!Line: 123 - error: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]

throw TestFailedException(std::move(failureMessage));
}
void Assertions::assertNoThrows (
function<void()> shouldNotThrow,
const string& failureMessage

!Line: 133 - error: std::move of the const variable 'failureMessage' has no effect or make the variable non-const [hicpp-move-const-arg,performance-move-const-arg,-warnings-as-errors]

!Line: 98 - note: consider changing the 1st parameter of 'TestFailedException' from 'const string &&' (aka 'const basic_string<char> &&') to 'const string &'

function<void()> shouldNotThrow,
const string& failureMessage
)
{
try {
shouldNotThrow();

!Line: 137 - error: the parameter 'shouldNotThrow' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param,-warnings-as-errors]

throw TestFailedException(std::move(failureMessage));
}
}
void Assertions::assertTrue (
bool condition,

!Line: 145 - error: std::move of the const variable 'failureMessage' has no effect or make the variable non-const [hicpp-move-const-arg,performance-move-const-arg,-warnings-as-errors]

!Line: 98 - note: consider changing the 1st parameter of 'TestFailedException' from 'const string &&' (aka 'const basic_string<char> &&') to 'const string &'

if (err.size()) {
throw TestFailedException(std::move(err));
}
}
}

!Line: 164 - error: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty,-warnings-as-errors]

if (err.size()) {
throw TestFailedException(std::move(err));
}
}
}

!Line: 164 - error: implicit conversion 'size_type' (aka 'unsigned long') -> 'bool' [readability-implicit-bool-conversion,-warnings-as-errors]

throw TestFailedException(std::move(err));
}
}
}
void Assertions::assertFalse (

!Line: 165 - error: std::move of the const variable 'err' has no effect or make the variable non-const [hicpp-move-const-arg,performance-move-const-arg,-warnings-as-errors]

!Line: 98 - note: consider changing the 1st parameter of 'TestFailedException' from 'const string &&' (aka 'const basic_string<char> &&') to 'const string &'

if (err.size()) {
throw TestFailedException(std::move(err));
}
}
}

!Line: 185 - error: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty,-warnings-as-errors]

if (err.size()) {
throw TestFailedException(std::move(err));
}
}
}

!Line: 185 - error: implicit conversion 'size_type' (aka 'unsigned long') -> 'bool' [readability-implicit-bool-conversion,-warnings-as-errors]

throw TestFailedException(std::move(err));
}
}
}
[[noreturn]] void Assertions::fail(string failureMessage) {

!Line: 186 - error: std::move of the const variable 'err' has no effect or make the variable non-const [hicpp-move-const-arg,performance-move-const-arg,-warnings-as-errors]

!Line: 98 - note: consider changing the 1st parameter of 'TestFailedException' from 'const string &&' (aka 'const basic_string<char> &&') to 'const string &'

[[noreturn]] void Assertions::fail(string failureMessage) {
throw TestFailedException(std::move(failureMessage));
}
}

!Line: 191 - error: the parameter 'failureMessage' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param,-warnings-as-errors]

throw TestFailedException(std::move(failureMessage));
}
}

!Line: 192 - error: no header providing "std::move" is directly included [misc-include-cleaner,-warnings-as-errors]

enum TestCaseOutCompareOptions {
CONTAINS,
EXACT
};
/**

!Line: 92 - error: enum 'TestCaseOutCompareOptions' uses a larger base type ('unsigned int', size: 4 bytes) than necessary for its value set, consider using 'std::uint8_t' (1 byte) as the base type to reduce its size [performance-enum-size,-warnings-as-errors]

TestCase (TestCase& o);
/**
* @brief Construct a TestCase by moving all data from another
* TestCase.
* @param o Move everything from this TestCase into the new one.

!Line: 146 - error: parameter name 'o' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]

TestCase (TestCase&& o) noexcept;
/**
* @brief Copy a TestCase into another TestCase.
* @param rhs The test case to copy from.
* @return A reference to the new TestCase copy.

!Line: 153 - error: parameter name 'o' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]

TestCase& operator= (TestCase& rhs);
/**
* @brief Move a TestCase into another TestCase.
* @param rhs Move everything from this TestCase into the new
* one.

!Line: 160 - error: operator=() should take 'TestCase const&', 'TestCase&&' or 'TestCase' [cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator,-warnings-as-errors]

TestCase& operator= (TestCase& rhs);
/**
* @brief Move a TestCase into another TestCase.
* @param rhs Move everything from this TestCase into the new
* one.

!Line: 160 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

TestCase& operator= (TestCase&& rhs) noexcept;
/**
* @brief Destroy a TestCase object.
*/
~TestCase ();

!Line: 169 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

bool checkStdout (const string& against);
/**
* @brief Check the argument against what is captured from
* std::clog using the configured comparison mode.
* @param against The value to check the captured output against

!Line: 224 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

bool checkLog (const string& against);
/**
* @brief Check the argument against what is captured from
* stderr using the configured comparison mode.
* @param against The value to check the captured output against

!Line: 233 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

bool checkStderr (const string& against);
/**
* @brief Run the test case.
* @return True if the test ran successfully, false otherwise.
*/

!Line: 243 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

bool go ();
/**
* @brief Returns the duration of the last run in nanoseconds.
* @return The duration of the last run of this TestCase in
* nanoseconds.

!Line: 249 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

long long getLastRuntime () const;
private:
bool notifyTestPassed = false;
bool pass = false;
bool stdoutCaptured = false;

!Line: 256 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

bool checkOutput (const string& source, const string& against);
static atomic_int stdoutCaptureCasesConstructed;
static atomic_int logCaptureCasesConstructed;
static atomic_int stderrCaptureCasesConstructed;
static atomic_int stdoutCaptureCasesDestroyed;

!Line: 315 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

static nanoseconds duration (F func, Args&&... args)
{
auto start = system_clock::now();
func(forward<Args>(args)...);
return duration_cast<nanoseconds>(
system_clock::now() - start

!Line: 345 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

TestSuite (TestObjName&& suiteName,
typename enable_if<sizeof...(TestType) == 0>::type)
{
this->testSuitePassedMessage = true;
this->setSuiteName(std::move(suiteName));
this->tests = vector<TestCase>();

!Line: 80 - error: constructor does not initialize these fields: lastRunSucceeded, lastRunSuccessCount, lastRunFailCount, totalRuntime [cppcoreguidelines-pro-type-member-init,hicpp-member-init,-warnings-as-errors]

typename enable_if<sizeof...(TestType) == 0>::type)
{
this->testSuitePassedMessage = true;
this->setSuiteName(std::move(suiteName));
this->tests = vector<TestCase>();
}

!Line: 81 - error: all parameters should be named in a function [hicpp-named-parameter,readability-named-parameter,-warnings-as-errors]

this->testSuitePassedMessage = true;
this->setSuiteName(std::move(suiteName));
this->tests = vector<TestCase>();
}
/**

!Line: 83 - error: 'testSuitePassedMessage' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer,-warnings-as-errors]

TestSuite (TestObjName&& suiteName, TestType ...tests) {
this->testSuitePassedMessage = true;
this->setSuiteName(std::move(suiteName));
this->tests = vector<TestCase>();
this->addTests(tests...);

!Line: 93 - error: constructor does not initialize these fields: lastRunSucceeded, lastRunSuccessCount, lastRunFailCount, totalRuntime [cppcoreguidelines-pro-type-member-init,hicpp-member-init,-warnings-as-errors]

TestSuite (TestObjName&& suiteName, TestType ...tests) {
this->testSuitePassedMessage = true;
this->setSuiteName(std::move(suiteName));
this->tests = vector<TestCase>();
this->addTests(tests...);

!Line: 93 - error: constructors that are callable with a single argument must be marked explicit to avoid unintentional implicit conversions [hicpp-explicit-conversions,-warnings-as-errors]

this->testSuitePassedMessage = true;
this->setSuiteName(std::move(suiteName));
this->tests = vector<TestCase>();
this->addTests(tests...);
}

!Line: 94 - error: 'testSuitePassedMessage' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer,-warnings-as-errors]

inline addTests () { }
/**
* @brief Add one or more tests at once to the test suite.
* @param test The first test to add.
* @param tests The rest of the tests to add.

!Line: 117 - error: function 'addTests' has inline specifier but is implicitly inlined [readability-redundant-inline-specifier,-warnings-as-errors]

inline addTests () { }
/**
* @brief Add one or more tests at once to the test suite.
* @param test The first test to add.
* @param tests The rest of the tests to add.

!Line: 117 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

unsigned getLastRunFailCount ();
/**
* @brief Run all tests in the test suite.
*/
void run ();

!Line: 153 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

using std::cerr;
using std::clog;
using std::cout;
using std::endl;
using std::exception;
using std::fixed;

!Line: 36 - error: no header providing "std::cerr" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::clog;
using std::cout;
using std::endl;
using std::exception;
using std::fixed;
using std::function;

!Line: 37 - error: no header providing "std::clog" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::cout;
using std::endl;
using std::exception;
using std::fixed;
using std::function;
using std::invalid_argument;

!Line: 38 - error: using decl 'cout' is unused [misc-unused-using-decls,-warnings-as-errors]

!Line: 38 - note: remove the using

using std::exception;
using std::fixed;
using std::function;
using std::invalid_argument;
using std::ostream;
using std::rethrow_exception;

!Line: 40 - error: no header providing "std::exception" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::fixed;
using std::function;
using std::invalid_argument;
using std::ostream;
using std::rethrow_exception;
using std::runtime_error;

!Line: 41 - error: no header providing "std::fixed" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::invalid_argument;
using std::ostream;
using std::rethrow_exception;
using std::runtime_error;
using std::setprecision;
using std::string;

!Line: 43 - error: using decl 'invalid_argument' is unused [misc-unused-using-decls,-warnings-as-errors]

!Line: 43 - note: remove the using

using std::ostream;
using std::rethrow_exception;
using std::runtime_error;
using std::setprecision;
using std::string;
using std::tuple;

!Line: 44 - error: no header providing "std::ostream" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::rethrow_exception;
using std::runtime_error;
using std::setprecision;
using std::string;
using std::tuple;

!Line: 45 - error: no header providing "std::rethrow_exception" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::rethrow_exception;
using std::runtime_error;
using std::setprecision;
using std::string;
using std::tuple;

!Line: 45 - error: using decl 'rethrow_exception' is unused [misc-unused-using-decls,-warnings-as-errors]

!Line: 45 - note: remove the using

using std::runtime_error;
using std::setprecision;
using std::string;
using std::tuple;
using TCPPNum = TestCPP::TestCPPCommon::Nums;

!Line: 46 - error: no header providing "std::runtime_error" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::runtime_error;
using std::setprecision;
using std::string;
using std::tuple;
using TCPPNum = TestCPP::TestCPPCommon::Nums;

!Line: 46 - error: using decl 'runtime_error' is unused [misc-unused-using-decls,-warnings-as-errors]

!Line: 46 - note: remove the using

using std::string;
using std::tuple;
using TCPPNum = TestCPP::TestCPPCommon::Nums;
using TCPPStr = TestCPP::TestCPPCommon::Strings;

!Line: 48 - error: no header providing "std::string" is directly included [misc-include-cleaner,-warnings-as-errors]

void TestSuite::setSuiteName (TestObjName&& testSuiteName) {
this->suiteName = std::move(testSuiteName);
}
unsigned TestSuite::getLastRunFailCount () {
return this->lastRunFailCount;

!Line: 69 - error: no header providing "TestCPP::TestObjName" is directly included [misc-include-cleaner,-warnings-as-errors]

this->suiteName = std::move(testSuiteName);
}
unsigned TestSuite::getLastRunFailCount () {
return this->lastRunFailCount;
}

!Line: 70 - error: no header providing "std::move" is directly included [misc-include-cleaner,-warnings-as-errors]

unsigned TestSuite::getLastRunFailCount () {
return this->lastRunFailCount;
}
void TestSuite::run () {
if (this->tests.size() == 0) {

!Line: 73 - error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]

unsigned TestSuite::getLastRunFailCount () {
return this->lastRunFailCount;
}
void TestSuite::run () {
if (this->tests.size() == 0) {

!Line: 73 - error: method 'getLastRunFailCount' can be made const [readability-make-member-function-const,-warnings-as-errors]

if (this->tests.size() == 0) {
clog << TCPPStr::NTR << endl;
return;
}
this->lastRunSucceeded = true;

!Line: 78 - error: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty,-warnings-as-errors]

clog << TCPPStr::NTR << endl;
return;
}
this->lastRunSucceeded = true;
this->lastRunFailCount = 0;

!Line: 79 - error: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]

clog << endl
<< TCPPStr::START_RUN << TCPPStr::SUITE
<< TCPPStr::APOS << this->suiteName << TCPPStr::APOS
<< endl
<< endl;

!Line: 88 - error: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]

<< endl
<< endl;
for (TestCase test : this->tests) {
bool testPassed = false;
try {

!Line: 91 - error: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]

<< endl;
for (TestCase test : this->tests) {
bool testPassed = false;
try {
testPassed = test.go();

!Line: 92 - error: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]

<< endl;
}
catch (...) {
cerr << TCPPStr::UNK_EXC
<< endl;
}

!Line: 101 - error: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]

<< endl;
}
if (!testPassed) {
this->lastRunFailCount++;

!Line: 105 - error: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]

clog << endl;
if (this->testSuitePassedMessage &&
this->lastRunFailCount == 0) {
clog << TCPPStr::ALL << TCPPStr::APOS << this->suiteName
<< TCPPStr::APOS << TCPPStr::SUITE_TESTS_PASSED

!Line: 122 - error: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]

<< endl;
}
double suiteRuntimeElapsed = static_cast<double>(
this->totalRuntime)/TCPPNum::NANOS_IN_SEC;

!Line: 128 - error: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]

double suiteRuntimeElapsed = static_cast<double>(
this->totalRuntime)/TCPPNum::NANOS_IN_SEC;
clog << fixed;
clog << setprecision(0);
clog << TCPPStr::FINISHED_SUITE << TCPPStr::APOS

!Line: 131 - error: variable 'suiteRuntimeElapsed' of type 'double' can be declared 'const' [misc-const-correctness,-warnings-as-errors]

<< endl;
}
/**
* @brief Add a test to this test suite.
*

!Line: 142 - error: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]

void TestSuite::addTest (TestCase&& test) {
this->tests.emplace_back(test);
}
/**
* @brief Add a test to this test suite.

!Line: 151 - error: rvalue reference parameter 'test' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved,-warnings-as-errors]

function<void()>>&& test) {
this->tests.emplace_back(
std::get<0>(test),
std::get<1>(test),
this->testSuitePassedMessage
);

!Line: 164 - error: rvalue reference parameter 'test' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved,-warnings-as-errors]

TestCase (
TestObjName&& testName,
function<void()> test,
bool testPassedMessage = true,
bool captureOut = false,
bool captureLog = false,

!Line: 131 - error: function 'TestCPP::TestCase::TestCase' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name,-warnings-as-errors]

!Line: 114 - note: the definition seen here
!Line: 131 - note: differing parameters are named here: ('testPassedMessage'), in definition: ('msg')

void logTestFailure (string failureMessage);
/**
* @brief Internal test run controller.
*/
void runTest ();
/**

!Line: 299 - error: function 'TestCPP::TestCase::logTestFailure' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name,-warnings-as-errors]

!Line: 304 - note: the definition seen here
!Line: 299 - note: differing parameters are named here: ('failureMessage'), in definition: ('reason')

static nanoseconds duration (F func, Args&&... args)
{
auto start = system_clock::now();
func(forward<Args>(args)...);
return duration_cast<nanoseconds>(
system_clock::now() - start

!Line: 345 - error: the parameter 'func' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param,-warnings-as-errors]

template <class... Ts> no_destroy(Ts&&... ts) { new (data) T(std::forward<Ts>(ts)...); }
T& get() { return *reinterpret_cast<T*>(data); }
};
/**
* @brief Log a message that will only be output when debug

!Line: 109 - error: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay,-warnings-as-errors]

using std::cerr;
using std::clog;
using std::cout;
using std::endl;
using std::exception;
using std::fixed;

!Line: 45 - error: no header providing "std::cerr" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::clog;
using std::cout;
using std::endl;
using std::exception;
using std::fixed;
using std::function;

!Line: 46 - error: no header providing "std::clog" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::cout;
using std::endl;
using std::exception;
using std::fixed;
using std::function;
using std::invalid_argument;

!Line: 47 - error: no header providing "std::cout" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::exception;
using std::fixed;
using std::function;
using std::invalid_argument;
using std::rethrow_exception;
using std::runtime_error;

!Line: 49 - error: no header providing "std::exception" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::fixed;
using std::function;
using std::invalid_argument;
using std::rethrow_exception;
using std::runtime_error;
using std::setprecision;

!Line: 50 - error: no header providing "std::fixed" is directly included [misc-include-cleaner,-warnings-as-errors]

using std::invalid_argument;
using std::rethrow_exception;
using std::runtime_error;
using std::setprecision;
using std::string;
using std::tuple;

!Line: 52 - error: using decl 'invalid_argument' is unused [misc-unused-using-decls,-warnings-as-errors]

!Line: 52 - note: remove the using

!Maximum character count per GitHub comment has been reached! Not all warnings/errors has been parsed!

@eljonny eljonny marked this pull request as draft February 20, 2025 07:33
Copy link

codecov bot commented Feb 20, 2025

Codecov Report

Attention: Patch coverage is 95.94595% with 3 lines in your changes missing coverage. Please review.

Project coverage is 84.69%. Comparing base (6bb387d) to head (efd470f).
Report is 13 commits behind head on main.

✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/TestCPPAssertions.cpp 93.10% 0 Missing and 2 partials ⚠️
include/internal/TestCPPAssertions.h 97.36% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #27      +/-   ##
==========================================
+ Coverage   75.17%   84.69%   +9.51%     
==========================================
  Files          10       10              
  Lines         423      477      +54     
  Branches       47       60      +13     
==========================================
+ Hits          318      404      +86     
+ Misses        101       66      -35     
- Partials        4        7       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

There were a number of areas affected by the performance::passedByValue
 issue, these also show up repeatedly in clang-tidy, so this should
 resolve some of those issues as well.

Closes #8.
All the tests pass.

There was an instance of a using statement that should have been
 wrapped in the adjacent conditional preprocessor directive, this has
 been corrected.
This should resolve at least one instance of the clang-tidy warning
 misc-unused-using-decls as reported in #45.
Added tests for the following functions:
* checkStdout
* checkStderr

This is to increase patch coverage for #27.

Formatted some lines.
@eljonny eljonny added this to the 0.3-release milestone Feb 26, 2025
@eljonny eljonny added the static-analysis An issue related to a static analysis result label Feb 26, 2025
Fixed the order of GH Actions workflows.
Added flawfinder and infer to the list of static analysis tools.
Added that debug and release are also taken into consideration for presets.
Updated the vcpkg and conan sections to more acurately reflect status.
Split the Features section into Current and Planned.
Added a long list of new assertions I plan on adding to the library.
The CMake build now includes all required sections for
 TestCPP_Exceptions_test, which is the addition of the Exceptions test
 suite to the build.
Now a TestCPP_Exceptions_test executable is created and linked in.

Added a test suite for TestCPPExceptions.
This included adding the following files:
 - test/include/Exceptions/ExceptionsTests.h
   - Test declarations
 - test/include/Exceptions/ExceptionsSuite.h
   - Creation of test suite
 - test/src/Exceptions/ExceptionsTests.cpp
   - Implementation of tests
 - test/src/TestCPPExceptionsMain.cpp
   - Implementation of suite runner
The only things that really needed to happen here were:
 - Test constructor variants
 - Make sure the constructors don't throw when given sane output

Additional behavior to check:
 - What does it do with negative testing?

If everything is good with CI after I push this I'll add some negative
 testing.

In Assertions, assertEquals did not work correctly with C Strings.
I added a template specialization that fixes this... I have a feeling
 this is going to need to happen in other cases as well, though I don't
 yet know what.
Most of the assertions have a common failure logging pattern, which
 should be consolidated into a common function call path.
Devise a return value system that will work for all test failures that
 log details of the test failure, where they share a common output
 format.
This is all of them except fail, assertThrows, and assertNoThrows.
Basically if there is content in the error string, it will throw the
 failure exception causing the test to fail.

Finish fixing #94 by implementing the template specialization for const
 char* for assertNotEquals.
Use C++11 way of creating literal empty strings.
Stop suppressing MSVC warning 4514, because those functions being
 removed via optimization (why they are being removed by the optimizer
 in Debug builds, I do not know, that should not have been happening)
 should not be removed.
For some reason it seems like the warning-disable flag for this
 specific warning was not being applied anyways, even though it should
 have been the way the CMake build was implemented; the flag is not
 longer in the CMake build.
Those template specializations need to be there; they may not be
 referenced by a library function, but it's a static function that will
 be accessed by library consumers, it's not intended to be used by the
 library itself.
I had to create extern instantiations to make sure the compiler kept
 the template specialization defined in the cpp file.
With the template specialization implementations being in the header
 file, they were being removed by the optimizer even with optimizations
 disabled in the debug build, which was super weird.
This appears to only be an issue with MSVC, which is also a little
 weird.

For #27 this should address all the issues but there's more coverage
 that needs to be improved to make the patch coverage acceptable.

Other fixes:
 - checkNull, checkNotNull, checkEquals, checkNotEquals, and
    logTestFailure now return values (copies) instead of references,
    and everything has been refactored to reflect this.
 - Moved definitions of the template specializations of assertEquals,
    assertNotEquals, checkEquals, and checkNotEquals to the cpp file.
 - Explicit template specializations that are only declarations are
    supposed to be in the global scope, according to research about
    some warnings I saw from clang, so they are moved out of the
    TestCPP namespace into the global scope. It appears this is the
    applicable section of the C++11 standard:
   - 14.7.3 clause 8 seems the most applicable
   - 14.7.3 clause 2 is referenced on the below post and seems to be a
      part of why this is the way it is as well:
     - https://forums.oracle.com/ords/apexds/post/explicit-specialization-is-not-allowed-in-the-current-scope-8848
   - C++11 standard Reference:
     - https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf
Increase patch coverage where it was lacking for #27, #94, and #8.
Added new tests so all assertions are now covered, and added negative
 testing for all assertions.

Restructure Assertions test files so there's a paradigm for adding
 new assertion categories.
Updated CMake build to take this into account.
I have confirmed the issues on the list I'm removing here are fixed
 per the cppcheck run local and on the PR CI run.

Added additional clang-tidy warnings: clang-diagnostics-*.
@eljonny eljonny marked this pull request as ready for review February 28, 2025 08:27
@eljonny eljonny merged commit be603a2 into main Feb 28, 2025
41 of 42 checks passed
eljonny added a commit that referenced this pull request Feb 28, 2025
Added tests for the following functions:
* checkStdout
* checkStderr

This is to increase patch coverage for #27.

Formatted some lines.
eljonny added a commit that referenced this pull request Feb 28, 2025
Stop suppressing MSVC warning 4514, because those functions being
 removed via optimization (why they are being removed by the optimizer
 in Debug builds, I do not know, that should not have been happening)
 should not be removed.
For some reason it seems like the warning-disable flag for this
 specific warning was not being applied anyways, even though it should
 have been the way the CMake build was implemented; the flag is not
 longer in the CMake build.
Those template specializations need to be there; they may not be
 referenced by a library function, but it's a static function that will
 be accessed by library consumers, it's not intended to be used by the
 library itself.
I had to create extern instantiations to make sure the compiler kept
 the template specialization defined in the cpp file.
With the template specialization implementations being in the header
 file, they were being removed by the optimizer even with optimizations
 disabled in the debug build, which was super weird.
This appears to only be an issue with MSVC, which is also a little
 weird.

For #27 this should address all the issues but there's more coverage
 that needs to be improved to make the patch coverage acceptable.

Other fixes:
 - checkNull, checkNotNull, checkEquals, checkNotEquals, and
    logTestFailure now return values (copies) instead of references,
    and everything has been refactored to reflect this.
 - Moved definitions of the template specializations of assertEquals,
    assertNotEquals, checkEquals, and checkNotEquals to the cpp file.
 - Explicit template specializations that are only declarations are
    supposed to be in the global scope, according to research about
    some warnings I saw from clang, so they are moved out of the
    TestCPP namespace into the global scope. It appears this is the
    applicable section of the C++11 standard:
   - 14.7.3 clause 8 seems the most applicable
   - 14.7.3 clause 2 is referenced on the below post and seems to be a
      part of why this is the way it is as well:
     - https://forums.oracle.com/ords/apexds/post/explicit-specialization-is-not-allowed-in-the-current-scope-8848
   - C++11 standard Reference:
     - https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf
eljonny added a commit that referenced this pull request Feb 28, 2025
Increase patch coverage where it was lacking for #27, #94, and #8.
Added new tests so all assertions are now covered, and added negative
 testing for all assertions.

Restructure Assertions test files so there's a paradigm for adding
 new assertion categories.
Updated CMake build to take this into account.
@eljonny eljonny deleted the fix-cppcheck-performance-passedbyvalue branch February 28, 2025 08:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

static-analysis An issue related to a static analysis result

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug - assertEquals and the converse function assertNotEquals does not work properly for C strings Fix CPPCheck issues - Argument is passed by value

1 participant