Skip to content

Conversation

eljonny
Copy link
Owner

@eljonny eljonny commented Feb 17, 2025

Closes #16

Break down build arguments into groups into their own CMake files.
Same with linking arguments.
Start building out CMakePresets.
Remove CMakeSettings.
Move "included" files into the CMakePresets.json file since having the include block didn't work like I thought it would.
CMakePresets is now modified such that:
 - there are buildPresets that correspond to all configurationPresets,
    so the proper base native tool options are applied to all relevant
    configurations when running a build in VS or on the command line
 - issues are addressed
 - added descriptions/names where missing
 - made presets hidden where appropriate so they don't show up in the
    VS build configurations menu, and so they can't be referenced when
    the cmake tool is invoked on the command line

Fixed an issue in BuildTypeHandling.cmake where when building with
 ClangCL for running clang-tidy on Windows with (or without) VS, it was
 selecting MSVC++ tool options instead of GCC/Clang tool options since
 it is indeed running an MSBuild build, but the underlying toolchain is
 ClangCL

Added some whitespace where it seemed to make it easier to read.

Added the following gcc/clang switches:
 -Wno-c++98-compat - Because there are C++11 and greater features that
  conflict with C++98 compatibility, but that's ok because the project
  is only intended to be built with C++11 or newer

 -Wno-c++98-compat-pedantic - Same reason as for Wno-c++98-compat

 -Wno-covered-switch-default - Clang was giving me some confusing
   results... keep the default: case in my switch, and it would output
   this from -Wcovered-switch-default:
    error : default label in switch which covers all enumeration values
     [-Werror,-Wcovered-switch-default]
  Then in rewriting it so there's no default: case but basically works
   the same way, Clang would output this from -Wswitch-default:
    error : 'switch' missing 'default' label [-Werror,-Wswitch-default]
  So I go look it up and find this gem on SE-SoftwareEngineering-design:
    https://lnkd.in/gg8d7U2T
  I opted for defensive programming, as I usually do, left the default:
   case in the switch, and added -Wno-covered-switch-default to my
   build.
  It seems like it's probably the most correct thing to do... at risk
   of having an extremely weird (read: improbable) situation where
   disabling this warning would cause me to miss a bug.
  I think it's more likely that there would be a bug as a result of not
   having a default case to handle erroneous values since enums in
   C/C++ are not strongly-typed (a la Java).
  I'm not using -Weverything, so I find it odd that there are clashes
   in warnings, but it was an interesting exercise to work through this
   issue.
  I would much rather have -Wswitch-default enabled, because that can
   catch some really nasty issues; this is just a weird pedantic
   annoyance, where the default: case is for "just in case" because of
   the lack of type checking, as I mentioned already.
  I did not find arguments on StackOverflow very compelling that argued
   against a default case when all known explicitly-defined cases are
   covered; since enums are value-based types, they can hold any value
   of the underlying type, which the compiler might or might not warn
   about/catch; the collection of known cases is typically a very tiny
   subset of the set of all possible values (4+ billion with the
   default underlying int type), so there should be an escape hatch for
   if the programmer knowningly or unknowingly ventures outside those
   explicitly-defined cases, where it would make sense to do so and a
   sensible default can be used or an error/exception can be generated,
   instead of just crashing the host application with no information
   about why there was a crash; I didn't want to use an assert because
   the values can change and are not tied explicitly to the symbols, so
   an assert could easily be broken.
Fixed documentation - wrong parameter name, @return on a constructor
Fixed not explicitly specifying that the fail function never returns a
 value with [[noreturn]] even though it's void
Fix problematic names of constants
No need to have unsigned long long when std::chrono::nanoseconds.
 count() returns long long, as implicit conversions can cause
 unexpected problems.
Fix std::move being unqualified in a whole bunch of places; remove
 using std::move where it is no longer needed because std::move is
 supposed to be qualified.
Specify explicitly that auto-destructors are not to be created and used
 with stream buffer and string stream pointers, because these
 "exit-destructors" can cause segfaults because the type destructor
 handles dismantling and destroying these unique_ptr objects.
Refactoring problematic names of constants.
Fixed missing EOF newlines.
Fixed implicitly casting INT_MIN to unsigned.
Clang-Tidy configuration and .clang-tidy file:
 - Disable *-use-nullptr clang-tidy checks because they are broken on
    Windows in the Visual Studio 2022-provided Clang builds, as
    evidenced by the following issues I discovered in researching why
    clang-tidy was failing with an ACCESS_VIOLATION (0xc0000005) error:
  > https://developercommunity.visualstudio.com/t/clang-tidy-terminates-with-Exception-Cod/10822069?pageSize=15&sort=active&openOnly=false&closedOnly=false&topics=repos
  > llvm/llvm-project#53778
 - Set FormatStyle to none so clang-tidy doesn't auto-format files,
    that is not what I want
 - Added HeaderFilterRegex that includes all headers, then added
    ExcludeHeaderFilterRegex to exclude the external headers (boost)
 - Added WarningsAsErrors * to treat all warnings as errors
 - Added SystemHeaders false so all system headers are excluded from
    analysis
 - Added ExtraArgs:
  > -Iinclude so library headers are discovered and included in
     analysis
  > -I3rdparty/include so boost headers are discovered and properly
     excluded from analysis
 - Now formatted as JSON so its format is more obvious without the
    weird opening/closing 3-character strings that indicate YAML but
    cause issues.

Added hidden windows-specific presets that are intended to be inherited
 so the descendant presets will have the proper toolchain loaded; these
 are new to the presets here and have the toolchainFile property
 defined so as to load a toolchain from the cmake/toolchains location.
There are ancestor toolchain presets defined for MSVC and ClangCL.
ClangCL is only used for running clang-tidy analysis on Windows with
 the VS-packaged LLVM distribution.
Split MSVC ancestor toolchain presets into stacktrace-enabled and no-
 stacktrace variants.
Set CMAKE_SYSTEM_PROCESSOR so the toolchain scripts select the proper
 toolchain tools.
Changed all VS-specific names, descriptions, and display names to be
 architecture-specific and also either Windows- or MSVC-specific,
 depending on context.
Add CMAKE_C_FLAGS, CMAKE_CXX_FLAGS, and CMAKE_EXE_LINKER_FLAGS where
 appropriate and necessary, particularly where static code analysis is
 to be run.
Fix nativeToolOptions since we're now using Ninja instead of MSBuild.
Moved nativeToolOptions in code analysis buildPresets to CMAKE_C_FLAGS
 and CMAKE_CXX_FLAGS in the corresponding configurePresets, because
 these are cl arguments, not MSBuild/Ninja arguments.
Added buildPresets for clang-tidy configurePresets.
Added an EOF newline.

Added toolchain files since we're no longer using MSBuild, courtesy of
 https://github.com/MarkSchofield/WindowsToolchain, with some great
 CMake toolchain files; thank you @MarkSchofield; awesome work, they
 work wonderfully:
 - cmake/toolchains/VSWhere.cmake
 - cmake/toolchains/Windows.Clang.toolchain.cmake
 - cmake/toolchains/Windows.Kits.cmake
 - cmake/toolchains/Windows.MSVC.toolchain.cmake
These are referenced through CMakePresets.json and are loaded such that
 the build has all the necessary tools.

Fixed find_program for clang-tidy so it is now NO_CACHE.
Fixed CLANG_TIDY_COMMAND such that it now uses the --config-file
 parameter, so all configurations are loaded through that instead of
 specified on the command line; added cache string description, and
 force-load the new value.

Ignore the global-constructors warnings, as explained in the comment
 in the CMake files that define the GCC/Clang build flags for different
 configurations; this only applies to Clang until this issue gets
 resolved: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71482
Noted in GCCCoverage.cmake for if/when that ref issue gets resolved.

Add /external:anglebrackets, /external:W0, and in the case where
 stacktraces are enabled /external:I3rdparty/include, so warnings in
 these external headers are ignored.
Removed warning suppressions that are now unnecessary because warnings
 in external headers (boost, system headers) are now ignored thanks to
 the above CL parameters:
 - /wd4625
  > Implicitly-deleted copy constructors.
 - /wd4626
  > Implicitly-deleted copy assignment operators.
 - /wd4668
  > Undefined preprocessor macros in the Windows SDK internal headers.
 - /wd5026
  > Implicitly-deleted move constructors.
 - /wd5027
  > Implicitly-deleted move assignment operators.
 - /wd5039
  > Windows SDK functions that are passed to extern 'C' APIs that are
     not marked as noexcept.
Added /nologo so if CMake doesn't configure the build to have it, it
 will be there.
Added /Zi to the debug build ensuring all debug information is
 generated.
/FS to avoid file locking issues.
Added explicit exception handling enablement in MSVC to fix issues with
 noexcept generating warnings because there's no exception handling
 mode specified: /EHscr for Debug (adds noexcept runtime checks with
 the r), and /EHsc for Release (no runtime noexcept checks).
Added runtime checks to Debug (/RTC1) so running the debug build can
 catch issues during testing or give more information if there's user
 code that is causing an issue inside the library.
Make sure that if we are running an MSVC analysis build, and a ruleset
 file is explicitly selected, that we add the standard location for
 built-in ruleset files with /analyze:rulesetdirectory and the
 VS_INSTALLATION_PATH specified by the toolchain.
CMake for some reason automatically adds /RTC1 to Release builds, which
 causes compilation to fail because /RTC1 and /O2 are incompatible, so
 the build generator now manually removes the RTC flags from release
 build compilation commands.
@eljonny eljonny self-assigned this Feb 17, 2025
Copy link

github-actions bot commented Feb 17, 2025

⚡ Static analysis result ⚡

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

string failureMessage = "Arguments are not equivalent!"
)
{
if (expected != actual) {
stringstream err;

!Line: 78 - performance: Function parameter 'failureMessage' should be passed by const reference. [passedByValue]

string failureMessage = "Arguments are equivalent!"
)
{
if (expected == actual) {
stringstream err;

!Line: 109 - performance: Function parameter 'failureMessage' should be passed by const reference. [passedByValue]

string failureMessage = "Object is not null!"
)
{
bool null = ptr == nullptr;
if (!null) {

!Line: 136 - performance: Function parameter 'failureMessage' should be passed by const reference. [passedByValue]

string failureMessage = "Object is null!"
)
{
bool notNull = ptr != nullptr;
if (!notNull) {

!Line: 163 - performance: Function parameter 'failureMessage' should be passed by const reference. [passedByValue]

string failureMessage
)
{
if (!condition) {
stringstream err;

!Line: 92 - performance: Function parameter 'failureMessage' should be passed by const reference. [passedByValue]

string failureMessage
)
{
if (condition) {
stringstream err;

!Line: 107 - performance: Function parameter 'failureMessage' should be passed by const reference. [passedByValue]

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]

bool TestCase::checkStdout (string against) {
return checkOutput(TestCase::stdoutBuffer.get()->str(),
against);
}
bool TestCase::checkLog (string against) {

!Line: 479 - performance: Function parameter 'against' should be passed by const reference. [passedByValue]

bool TestCase::checkLog (string against) {
return checkOutput(TestCase::clogBuffer.get()->str(),
against);
}
bool TestCase::checkStderr (string against) {

!Line: 484 - performance: Function parameter 'against' should be passed by const reference. [passedByValue]

bool TestCase::checkStderr (string against) {
return checkOutput(TestCase::stderrBuffer.get()->str(),
against);
}
bool TestCase::checkOutput (string source, string against)

!Line: 489 - performance: Function parameter 'against' should be passed by const reference. [passedByValue]

bool TestCase::checkOutput (string source, string against)
{
switch (this->option) {
case EXACT:
if (source == against) {
return true;

!Line: 494 - performance: Function parameter 'source' should be passed by const reference. [passedByValue]

bool TestCase::checkOutput (string source, string against)
{
switch (this->option) {
case EXACT:
if (source == against) {
return true;

!Line: 494 - performance: Function parameter 'against' should be passed by const reference. [passedByValue]

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]


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

TestCPP/.clang-tidy

Lines 4 to 9 in ac88b62

"ExcludeHeaderFilterRegex": "boost/.*",
"WarningsAsErrors": "*",
"FormatStyle": "none",
"SystemHeaders": false,
"ExtraArgs": [
"-Iinclude",

!Line: 4 - error: unknown key 'ExcludeHeaderFilterRegex'

using std::clog;
using std::string;
using std::runtime_error;
namespace TestCPP {

!Line: 36 - warning: using decl 'clog' is unused [misc-unused-using-decls]

!Line: 36 - note: remove the using

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

!Line: 37 - warning: no header providing "std::string" is directly included [misc-include-cleaner]

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

!Line: 38 - warning: no header providing "std::runtime_error" is directly included [misc-include-cleaner]

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

!Line: 50 - warning: passing result of std::move() as a const reference argument; no move will actually happen [hicpp-move-const-arg,performance-move-const-arg]

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

!Line: 50 - warning: no header providing "std::move" is directly included [misc-include-cleaner]

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

!Line: 30 - warning: no header providing "std::clog" is directly included [misc-include-cleaner]

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

!Line: 31 - warning: no header providing "std::current_exception" is directly included [misc-include-cleaner]

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

!Line: 33 - warning: no header providing "std::exception" is directly included [misc-include-cleaner]

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

!Line: 34 - warning: no header providing "std::__exception_ptr::exception_ptr" is directly included [misc-include-cleaner]

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

!Line: 36 - warning: no header providing "std::rethrow_exception" is directly included [misc-include-cleaner]

using std::string;
using std::stringstream;
namespace TestCPP {
void Assertions::assertThrows (

!Line: 37 - warning: no header providing "std::string" is directly included [misc-include-cleaner]

using std::stringstream;
namespace TestCPP {
void Assertions::assertThrows (
function<void()> shouldThrow,

!Line: 38 - warning: no header providing "std::stringstream" is directly included [misc-include-cleaner]

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

!Line: 43 - warning: 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]

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

!Line: 51 - warning: variable 'eptr' of type 'exception_ptr' can be declared 'const' [misc-const-correctness]

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

!Line: 60 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

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

!Line: 64 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

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

!Line: 74 - warning: no header providing "std::move" is directly included [misc-include-cleaner]

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

!Line: 78 - warning: 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]

string failureMessage
)
{
if (!condition) {
stringstream err;

!Line: 92 - warning: 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]

err << "Boolean Truth assertion failed!" << endl;
err << failureMessage << endl;
throw TestFailedException(err.str());
}
}

!Line: 98 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

err << failureMessage << endl;
throw TestFailedException(err.str());
}
}

!Line: 99 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

string failureMessage
)
{
if (condition) {
stringstream err;

!Line: 107 - warning: 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]

err << "Boolean False assertion failed!" << endl;
err << failureMessage << endl;
throw TestFailedException(err.str());
}
}

!Line: 113 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

err << failureMessage << endl;
throw TestFailedException(err.str());
}
}

!Line: 114 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

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

!Line: 51 - warning: implicit conversion 'const char *' -> 'bool' [readability-implicit-bool-conversion]

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

!Line: 59 - warning: use a trailing return type for this function [modernize-use-trailing-return-type]

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

!Line: 63 - warning: use a trailing return type for this function [modernize-use-trailing-return-type]

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

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

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

!Line: 78 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

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

!Line: 83 - warning: use a trailing return type for this function [modernize-use-trailing-return-type]

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

!Line: 89 - warning: use a trailing return type for this function [modernize-use-trailing-return-type]

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

!Line: 36 - warning: no header providing "std::cerr" is directly included [misc-include-cleaner]

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

!Line: 37 - warning: no header providing "std::clog" is directly included [misc-include-cleaner]

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

!Line: 38 - warning: using decl 'cout' is unused [misc-unused-using-decls]

!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 - warning: no header providing "std::exception" is directly included [misc-include-cleaner]

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

!Line: 41 - warning: no header providing "std::fixed" is directly included [misc-include-cleaner]

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

!Line: 43 - warning: using decl 'invalid_argument' is unused [misc-unused-using-decls]

!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 - warning: no header providing "std::ostream" is directly included [misc-include-cleaner]

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

!Line: 45 - warning: no header providing "std::rethrow_exception" is directly included [misc-include-cleaner]

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

!Line: 45 - warning: using decl 'rethrow_exception' is unused [misc-unused-using-decls]

!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 - warning: no header providing "std::runtime_error" is directly included [misc-include-cleaner]

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

!Line: 46 - warning: using decl 'runtime_error' is unused [misc-unused-using-decls]

!Line: 46 - note: remove the using

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

!Line: 48 - warning: no header providing "std::string" is directly included [misc-include-cleaner]

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

!Line: 69 - warning: no header providing "TestCPP::TestObjName" is directly included [misc-include-cleaner]

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

!Line: 70 - warning: no header providing "std::move" is directly included [misc-include-cleaner]

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

!Line: 73 - warning: use a trailing return type for this function [modernize-use-trailing-return-type]

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

!Line: 73 - warning: method 'getLastRunFailCount' can be made const [readability-make-member-function-const]

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

!Line: 78 - warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]

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

!Line: 79 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

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

!Line: 88 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

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

!Line: 91 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

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

!Line: 92 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

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

!Line: 101 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

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

!Line: 105 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

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

!Line: 122 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

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

!Line: 128 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

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

!Line: 131 - warning: variable 'suiteRuntimeElapsed' of type 'double' can be declared 'const' [misc-const-correctness]

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

!Line: 142 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

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

!Line: 151 - warning: rvalue reference parameter 'test' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]

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

!Line: 164 - warning: rvalue reference parameter 'test' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]

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

!Line: 131 - warning: function 'TestCPP::TestCase::TestCase' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]

!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 - warning: function 'TestCPP::TestCase::logTestFailure' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]

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

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

!Line: 45 - warning: no header providing "std::cerr" is directly included [misc-include-cleaner]

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

!Line: 46 - warning: no header providing "std::clog" is directly included [misc-include-cleaner]

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

!Line: 47 - warning: no header providing "std::cout" is directly included [misc-include-cleaner]

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

!Line: 49 - warning: no header providing "std::exception" is directly included [misc-include-cleaner]

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

!Line: 50 - warning: no header providing "std::fixed" is directly included [misc-include-cleaner]

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

!Line: 52 - warning: using decl 'invalid_argument' is unused [misc-unused-using-decls]

!Line: 52 - note: remove the using

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

!Line: 53 - warning: no header providing "std::rethrow_exception" is directly included [misc-include-cleaner]

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

!Line: 53 - warning: using decl 'rethrow_exception' is unused [misc-unused-using-decls]

!Line: 53 - note: remove the using

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

!Line: 54 - warning: no header providing "std::runtime_error" is directly included [misc-include-cleaner]

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

!Line: 54 - warning: using decl 'runtime_error' is unused [misc-unused-using-decls]

!Line: 54 - note: remove the using

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

!Line: 56 - warning: no header providing "std::string" is directly included [misc-include-cleaner]

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

!Line: 57 - warning: using decl 'tuple' is unused [misc-unused-using-decls]

!Line: 57 - note: remove the using

atomic_int TestCase::stdoutCaptureCasesConstructed;
atomic_int TestCase::logCaptureCasesConstructed;
atomic_int TestCase::stderrCaptureCasesConstructed;
atomic_int TestCase::stdoutCaptureCasesDestroyed;
atomic_int TestCase::logCaptureCasesDestroyed;
atomic_int TestCase::stderrCaptureCasesDestroyed;

!Line: 64 - warning: no header providing "atomic_int" is directly included [misc-include-cleaner]

TestCase::stdoutBuffer =
no_destroy<unique_ptr<stringstream, void(*)(stringstream*)>>(
unique_ptr<stringstream, void(*)(stringstream*)>(
nullptr, [](stringstream*){}
)
);

!Line: 72 - warning: initialization of 'stdoutBuffer' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]

!Line: 109 - note: possibly throwing constructor declared here

TestCase::clogBuffer =
no_destroy<unique_ptr<stringstream, void(*)(stringstream*)>>(
unique_ptr<stringstream, void(*)(stringstream*)>(
nullptr, [](stringstream*){}
)
);

!Line: 79 - warning: initialization of 'clogBuffer' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]

!Line: 109 - note: possibly throwing constructor declared here

TestCase::stderrBuffer =
no_destroy<unique_ptr<stringstream, void(*)(stringstream*)>>(
unique_ptr<stringstream, void(*)(stringstream*)>(
nullptr, [](stringstream*){}
)
);

!Line: 86 - warning: initialization of 'stderrBuffer' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]

!Line: 109 - note: possibly throwing constructor declared here

TestCase::stdoutOriginal =
no_destroy<unique_ptr<streambuf, void(*)(streambuf*)>>(
unique_ptr<streambuf, void(*)(streambuf*)>(
nullptr, [](streambuf*){}
)
);

!Line: 93 - warning: initialization of 'stdoutOriginal' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]

!Line: 109 - note: possibly throwing constructor declared here

TestCase::clogOriginal =
no_destroy<unique_ptr<streambuf, void(*)(streambuf*)>>(
unique_ptr<streambuf, void(*)(streambuf*)>(
nullptr, [](streambuf*){}
)
);

!Line: 100 - warning: initialization of 'clogOriginal' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]

!Line: 109 - note: possibly throwing constructor declared here

TestCase::stderrOriginal =
no_destroy<unique_ptr<streambuf, void(*)(streambuf*)>>(
unique_ptr<streambuf, void(*)(streambuf*)>(
nullptr, [](streambuf*){}
)
);

!Line: 107 - warning: initialization of 'stderrOriginal' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]

!Line: 109 - note: possibly throwing constructor declared here

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

!Line: 114 - warning: rvalue reference parameter 'name' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]

this->notifyTestPassed = msg;
this->test = testFn;
this->testName = name;
if (captureOut) {

!Line: 121 - warning: 'notifyTestPassed' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]

this->test = testFn;
this->testName = name;
if (captureOut) {
captureStdout();

!Line: 122 - warning: 'test' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]

this->test = testFn;
this->testName = name;
if (captureOut) {
captureStdout();

!Line: 122 - warning: parameter 'testFn' is passed by value and only copied once; consider moving it to avoid unnecessary copies [performance-unnecessary-value-param]

this->testName = name;
if (captureOut) {
captureStdout();
}
if (captureLog) {

!Line: 124 - warning: 'testName' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]

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

!Line: 145 - warning: parameter name 'o' is too short, expected at least 3 characters [readability-identifier-length]

this->pass = o.pass;
this->lastRunTime = o.lastRunTime;
this->stdoutCaptured = o.stdoutCaptured;
this->clogCaptured = o.clogCaptured;
this->stderrCaptured = o.stderrCaptured;

!Line: 149 - warning: 'pass' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]

this->lastRunTime = o.lastRunTime;
this->stdoutCaptured = o.stdoutCaptured;
this->clogCaptured = o.clogCaptured;
this->stderrCaptured = o.stderrCaptured;

!Line: 150 - warning: 'lastRunTime' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]

this->stdoutCaptured = o.stdoutCaptured;
this->clogCaptured = o.clogCaptured;
this->stderrCaptured = o.stderrCaptured;
if (this->stdoutCaptured) {
captureStdout();

!Line: 152 - warning: 'stdoutCaptured' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]

this->clogCaptured = o.clogCaptured;
this->stderrCaptured = o.stderrCaptured;
if (this->stdoutCaptured) {
captureStdout();
}

!Line: 153 - warning: 'clogCaptured' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]

this->stderrCaptured = o.stderrCaptured;
if (this->stdoutCaptured) {
captureStdout();
}
if (this->clogCaptured) {

!Line: 154 - warning: 'stderrCaptured' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]

TestCase::TestCase (TestCase&& o) noexcept {
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: 170 - warning: an exception may be thrown in function 'TestCase' which should not throw exceptions [bugprone-exception-escape]

TestCase::TestCase (TestCase&& o) noexcept {
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: 170 - warning: parameter name 'o' is too short, expected at least 3 characters [readability-identifier-length]

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 - warning: std::move of the expression of the trivially-copyable type 'TestCaseOutCompareOptions' has no effect; remove std::move() [hicpp-move-const-arg,performance-move-const-arg]

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 - warning: no header providing "std::move" is directly included [misc-include-cleaner]

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

!Line: 172 - warning: std::move of the expression of the trivially-copyable type 'bool' has no effect; remove std::move() [hicpp-move-const-arg,performance-move-const-arg]

this->pass = std::move(o.pass);
this->lastRunTime = std::move(o.lastRunTime);
this->stdoutCaptured = std::move(o.stdoutCaptured);
this->clogCaptured = std::move(o.clogCaptured);
this->stderrCaptured = std::move(o.stderrCaptured);

!Line: 174 - warning: 'pass' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]

this->pass = std::move(o.pass);
this->lastRunTime = std::move(o.lastRunTime);
this->stdoutCaptured = std::move(o.stdoutCaptured);
this->clogCaptured = std::move(o.clogCaptured);
this->stderrCaptured = std::move(o.stderrCaptured);

!Line: 174 - warning: std::move of the expression of the trivially-copyable type 'bool' has no effect; remove std::move() [hicpp-move-const-arg,performance-move-const-arg]

this->lastRunTime = std::move(o.lastRunTime);
this->stdoutCaptured = std::move(o.stdoutCaptured);
this->clogCaptured = std::move(o.clogCaptured);
this->stderrCaptured = std::move(o.stderrCaptured);

!Line: 175 - warning: 'lastRunTime' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]

this->lastRunTime = std::move(o.lastRunTime);
this->stdoutCaptured = std::move(o.stdoutCaptured);
this->clogCaptured = std::move(o.clogCaptured);
this->stderrCaptured = std::move(o.stderrCaptured);

!Line: 175 - warning: std::move of the expression of the trivially-copyable type 'long long' has no effect; remove std::move() [hicpp-move-const-arg,performance-move-const-arg]

this->stdoutCaptured = std::move(o.stdoutCaptured);
this->clogCaptured = std::move(o.clogCaptured);
this->stderrCaptured = std::move(o.stderrCaptured);
if (this->stdoutCaptured) {
captureStdout();

!Line: 177 - warning: 'stdoutCaptured' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]

this->stdoutCaptured = std::move(o.stdoutCaptured);
this->clogCaptured = std::move(o.clogCaptured);
this->stderrCaptured = std::move(o.stderrCaptured);
if (this->stdoutCaptured) {
captureStdout();

!Line: 177 - warning: std::move of the expression of the trivially-copyable type 'bool' has no effect; remove std::move() [hicpp-move-const-arg,performance-move-const-arg]

this->clogCaptured = std::move(o.clogCaptured);
this->stderrCaptured = std::move(o.stderrCaptured);
if (this->stdoutCaptured) {
captureStdout();
}

!Line: 178 - warning: 'clogCaptured' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]

this->clogCaptured = std::move(o.clogCaptured);
this->stderrCaptured = std::move(o.stderrCaptured);
if (this->stdoutCaptured) {
captureStdout();
}

!Line: 178 - warning: std::move of the expression of the trivially-copyable type 'bool' has no effect; remove std::move() [hicpp-move-const-arg,performance-move-const-arg]

this->stderrCaptured = std::move(o.stderrCaptured);
if (this->stdoutCaptured) {
captureStdout();
}
if (this->clogCaptured) {

!Line: 179 - warning: 'stderrCaptured' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]

this->stderrCaptured = std::move(o.stderrCaptured);
if (this->stdoutCaptured) {
captureStdout();
}
if (this->clogCaptured) {

!Line: 179 - warning: std::move of the expression of the trivially-copyable type 'bool' has no effect; remove std::move() [hicpp-move-const-arg,performance-move-const-arg]

delete TestCase::stdoutBuffer.get().get();
TestCase::stdoutBuffer.get() = nullptr;
}
TestCase::stdoutCaptureCasesDestroyed += 1;
}

!Line: 202 - warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead [cppcoreguidelines-owning-memory]

!Line: 71 - note: variable declared here

delete TestCase::clogBuffer.get().get();
TestCase::clogBuffer.get() = nullptr;
}
TestCase::logCaptureCasesDestroyed += 1;
}

!Line: 214 - warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead [cppcoreguidelines-owning-memory]

!Line: 78 - note: variable declared here

delete TestCase::stderrBuffer.get().get();
TestCase::stderrBuffer.get() = nullptr;
}
TestCase::stderrCaptureCasesDestroyed += 1;
}

!Line: 226 - warning: deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead [cppcoreguidelines-owning-memory]

!Line: 85 - note: variable declared here

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

!Line: 234 - warning: operator=() should take 'TestCase const&', 'TestCase&&' or 'TestCase' [cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator]

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

!Line: 234 - warning: operator=() does not handle self-assignment properly [cert-oop54-cpp]

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

!Line: 234 - warning: use a trailing return type for this function [modernize-use-trailing-return-type]

TestCase& TestCase::operator= (TestCase&& rhs) noexcept {
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: 261 - warning: an exception may be thrown in function 'operator=' which should not throw exceptions [bugprone-exception-escape]

TestCase& TestCase::operator= (TestCase&& rhs) noexcept {
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: 261 - warning: use a trailing return type for this function [modernize-use-trailing-return-type]

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 - warning: std::move of the expression of the trivially-copyable type 'TestCaseOutCompareOptions' has no effect; remove std::move() [hicpp-move-const-arg,performance-move-const-arg]

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

!Line: 263 - warning: std::move of the expression of the trivially-copyable type 'bool' has no effect; remove std::move() [hicpp-move-const-arg,performance-move-const-arg]

this->pass = std::move(rhs.pass);
this->lastRunTime = std::move(rhs.lastRunTime);
this->stdoutCaptured = std::move(rhs.stdoutCaptured);
this->clogCaptured = std::move(rhs.clogCaptured);
this->stderrCaptured = std::move(rhs.stderrCaptured);

!Line: 265 - warning: std::move of the expression of the trivially-copyable type 'bool' has no effect; remove std::move() [hicpp-move-const-arg,performance-move-const-arg]

this->lastRunTime = std::move(rhs.lastRunTime);
this->stdoutCaptured = std::move(rhs.stdoutCaptured);
this->clogCaptured = std::move(rhs.clogCaptured);
this->stderrCaptured = std::move(rhs.stderrCaptured);

!Line: 266 - warning: std::move of the expression of the trivially-copyable type 'long long' has no effect; remove std::move() [hicpp-move-const-arg,performance-move-const-arg]

this->stdoutCaptured = std::move(rhs.stdoutCaptured);
this->clogCaptured = std::move(rhs.clogCaptured);
this->stderrCaptured = std::move(rhs.stderrCaptured);
if (this->stdoutCaptured) {
captureStdout();

!Line: 268 - warning: std::move of the expression of the trivially-copyable type 'bool' has no effect; remove std::move() [hicpp-move-const-arg,performance-move-const-arg]

this->clogCaptured = std::move(rhs.clogCaptured);
this->stderrCaptured = std::move(rhs.stderrCaptured);
if (this->stdoutCaptured) {
captureStdout();
}

!Line: 269 - warning: std::move of the expression of the trivially-copyable type 'bool' has no effect; remove std::move() [hicpp-move-const-arg,performance-move-const-arg]

this->stderrCaptured = std::move(rhs.stderrCaptured);
if (this->stdoutCaptured) {
captureStdout();
}
if (this->clogCaptured) {

!Line: 270 - warning: std::move of the expression of the trivially-copyable type 'bool' has no effect; remove std::move() [hicpp-move-const-arg,performance-move-const-arg]

long long TestCase::getLastRuntime () const {
return this->lastRunTime;
}
void TestCase::logFailure(ostream& out, string& reason) {
out << fixed;

!Line: 288 - warning: use a trailing return type for this function [modernize-use-trailing-return-type]

<< endl;
out << TCPPStr::REASON_ << reason << endl;
}
void TestCase::logTestFailure (string reason) {
unique_ptr<ostream> logStream = nullptr;

!Line: 300 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

out << TCPPStr::REASON_ << reason << endl;
}
void TestCase::logTestFailure (string reason) {
unique_ptr<ostream> logStream = nullptr;

!Line: 301 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

if (this->clogOriginal.get() != nullptr) {
logStream = unique_ptr<ostream>(
new ostream(this->clogOriginal.get().get())
);
}
else {

!Line: 307 - warning: static member accessed through instance [readability-static-accessed-through-instance]

new ostream(this->clogOriginal.get().get())
);
}
else {
logStream = unique_ptr<ostream>(&clog);
}

!Line: 309 - warning: static member accessed through instance [readability-static-accessed-through-instance]

if (this->clogOriginal.get() != nullptr) {
logStream->flush();
// If someone is looking for something in the message,
// and it's captured, make sure it's there.
logFailure(clog, reason);

!Line: 318 - warning: static member accessed through instance [readability-static-accessed-through-instance]

logStream.release();
logStream.reset();
}
void TestCase::runTest () {
clog << TCPPStr::START_RUN << this->testName << endl;

!Line: 326 - warning: the value returned by this function should not be disregarded; neglecting it may lead to errors [bugprone-unused-return-value]

clog << TCPPStr::START_RUN << this->testName << endl;
this->lastRunTime = duration(this->test).count();
if (this->notifyTestPassed) {
clog << fixed;
clog << setprecision(TCPPNum::TIME_PRECISION);
clog << TCPPStr::TEST << this->testName << TCPPStr::PASS

!Line: 331 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

<< endl;
}
this->pass = true;
}
bool TestCase::go () {

!Line: 341 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

bool TestCase::go () {
try {
runTest();
return true;
}
catch(const char * errorMessage) {

!Line: 346 - warning: use a trailing return type for this function [modernize-use-trailing-return-type]

void TestCase::captureStdout () {
if (TestCase::stdoutCaptureCasesConstructed ==
TestCase::stdoutCaptureCasesDestroyed)
{
TestCase::stdoutCaptureCasesConstructed += 1;
TestCase::stdoutBuffer =

!Line: 375 - warning: method 'captureStdout' can be made static [readability-convert-member-functions-to-static]

void TestCase::captureClog () {
if (TestCase::logCaptureCasesConstructed ==
TestCase::logCaptureCasesDestroyed)
{
TestCase::logCaptureCasesConstructed += 1;
TestCase::clogBuffer =

!Line: 399 - warning: method 'captureClog' can be made static [readability-convert-member-functions-to-static]

void TestCase::captureStdErr () {
if (TestCase::stderrCaptureCasesConstructed ==
TestCase::stderrCaptureCasesDestroyed)
{
TestCase::stderrCaptureCasesConstructed += 1;
TestCase::stderrBuffer =

!Line: 423 - warning: method 'captureStdErr' can be made static [readability-convert-member-functions-to-static]

void TestCase::clearStdoutCapture () {
if (TestCase::stdoutBuffer.get()) {
TestCase::stdoutBuffer.get()->str(string());
}
}

!Line: 461 - warning: method 'clearStdoutCapture' can be made static [readability-convert-member-functions-to-static]

void TestCase::clearLogCapture () {
if (TestCase::clogBuffer.get()) {
TestCase::clogBuffer.get()->str(string());
}
}

!Line: 467 - warning: method 'clearLogCapture' can be made static [readability-convert-member-functions-to-static]

void TestCase::clearStderrCapture () {
if (TestCase::stderrBuffer.get()) {
TestCase::stderrBuffer.get()->str(string());
}
}

!Line: 473 - warning: method 'clearStderrCapture' can be made static [readability-convert-member-functions-to-static]

bool TestCase::checkStdout (string against) {
return checkOutput(TestCase::stdoutBuffer.get()->str(),
against);
}
bool TestCase::checkLog (string against) {

!Line: 479 - warning: use a trailing return type for this function [modernize-use-trailing-return-type]

against);
}
bool TestCase::checkLog (string against) {
return checkOutput(TestCase::clogBuffer.get()->str(),
against);

!Line: 481 - warning: parameter 'against' is passed by value and only copied once; consider moving it to avoid unnecessary copies [performance-unnecessary-value-param]

bool TestCase::checkLog (string against) {
return checkOutput(TestCase::clogBuffer.get()->str(),
against);
}
bool TestCase::checkStderr (string against) {

!Line: 484 - warning: use a trailing return type for this function [modernize-use-trailing-return-type]

against);
}
bool TestCase::checkStderr (string against) {
return checkOutput(TestCase::stderrBuffer.get()->str(),
against);

!Line: 486 - warning: parameter 'against' is passed by value and only copied once; consider moving it to avoid unnecessary copies [performance-unnecessary-value-param]

bool TestCase::checkStderr (string against) {
return checkOutput(TestCase::stderrBuffer.get()->str(),
against);
}
bool TestCase::checkOutput (string source, string against)

!Line: 489 - warning: use a trailing return type for this function [modernize-use-trailing-return-type]

against);
}
bool TestCase::checkOutput (string source, string against)
{
switch (this->option) {

!Line: 491 - warning: parameter 'against' is passed by value and only copied once; consider moving it to avoid unnecessary copies [performance-unnecessary-value-param]

bool TestCase::checkOutput (string source, string against)
{
switch (this->option) {
case EXACT:
if (source == against) {
return true;

!Line: 494 - warning: use a trailing return type for this function [modernize-use-trailing-return-type]

bool TestCase::checkOutput (string source, string against)
{
switch (this->option) {
case EXACT:
if (source == against) {
return true;

!Line: 494 - warning: the parameter 'source' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]

bool TestCase::checkOutput (string source, string against)
{
switch (this->option) {
case EXACT:
if (source == against) {
return true;

!Line: 494 - warning: the parameter 'against' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]

if (this->clogOriginal.get() != nullptr) {
ostream tmp(this->clogOriginal.get().get());
tmp << nomatch.str() << endl;
tmp.flush();
}
else {

!Line: 507 - warning: static member accessed through instance [readability-static-accessed-through-instance]

ostream tmp(this->clogOriginal.get().get());
tmp << nomatch.str() << endl;
tmp.flush();
}
else {
clog << nomatch.str() << endl;

!Line: 508 - warning: static member accessed through instance [readability-static-accessed-through-instance]

tmp << nomatch.str() << endl;
tmp.flush();
}
else {
clog << nomatch.str() << endl;
}

!Line: 509 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

clog << nomatch.str() << endl;
}
return false;
}

!Line: 513 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

if (this->clogOriginal.get() != nullptr) {
ostream tmp(this->clogOriginal.get().get());
tmp << nomatch.str() << endl;
tmp.flush();
}
else {

!Line: 529 - warning: static member accessed through instance [readability-static-accessed-through-instance]

ostream tmp(this->clogOriginal.get().get());
tmp << nomatch.str() << endl;
tmp.flush();
}
else {
clog << nomatch.str() << endl;

!Line: 530 - warning: static member accessed through instance [readability-static-accessed-through-instance]

tmp << nomatch.str() << endl;
tmp.flush();
}
else {
clog << nomatch.str() << endl;
}

!Line: 531 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

clog << nomatch.str() << endl;
}
return false;
}

!Line: 535 - warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]

stringstream re;
re << TCPPStr::UNK_CMP_OPT << this->option;
throw TestCPPException(re.str());
}
}
}

!Line: 542 - warning: variable name 're' is too short, expected at least 3 characters [readability-identifier-length]


Add noexcept to constructors and operators that should not throw
 exceptions.
Apply const to getLastRuntime function.

Add no_destroy template type that replaces the clang::no_destroy
 attribute since it is not implemented in GCC or MSVC.
There are some downsides, but they don't really bother me given the
 types it's applied to and the operations applied to those statics.
For more info, see:
 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1247r0.html
Applied some fixes based on this new level of indirection (calls to
 no_destroy::get).
Copy link

codecov bot commented Feb 17, 2025

Codecov Report

Attention: Patch coverage is 81.63265% with 18 lines in your changes missing coverage. Please review.

Project coverage is 77.46%. Comparing base (6fd733e) to head (ac88b62).
Report is 12 commits behind head on main.

Files with missing lines Patch % Lines
src/TestCPPTestCase.cpp 86.25% 11 Missing ⚠️
src/TestCPPAssertions.cpp 0.00% 4 Missing ⚠️
src/TestCPPExceptions.cpp 0.00% 2 Missing ⚠️
src/TestCPPTestSuite.cpp 85.71% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #17      +/-   ##
==========================================
+ Coverage   77.36%   77.46%   +0.10%     
==========================================
  Files          19       19              
  Lines         561      568       +7     
  Branches       70       70              
==========================================
+ Hits          434      440       +6     
- Misses        110      111       +1     
  Partials       17       17              

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

@eljonny eljonny merged commit b8a52a7 into main Feb 17, 2025
37 of 38 checks passed
@eljonny eljonny deleted the add-cmake-presets branch February 17, 2025 10:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Configure CMake Presets for builds

1 participant