etl/test/UnitTest++/Checks.h
John Wellbelove 574e041485 #675 Compilation error in optional.h line 405
Changes for compatibility with C++20

Restore C++17 unit test compatibility
2023-03-15 10:28:55 +00:00

310 lines
12 KiB
C++

#ifndef UNITTEST_CHECKS_H
#define UNITTEST_CHECKS_H
#if defined(__GNUC__) && !defined(__clang__) && !defined(__llvm__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
#endif
#if defined(__clang__) || defined(__llvm__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wsign-compare"
#endif
#include "Config.h"
#include "TestResults.h"
#include "MemoryOutStream.h"
#include<iomanip>
namespace UnitTest {
template< typename Value >
bool Check(Value const& value)
{
return !!value; // doing double negative to avoid silly VS warnings
}
template< typename Value >
bool CheckFalse(Value const& value)
{
return !value;
}
#if __cplusplus >= 202002L
template< typename Expected, typename Actual >
std::enable_if_t<!(std::is_same_v<wchar_t, std::remove_cvref_t<std::remove_pointer_t<Expected>>> || std::is_same_v<wchar_t, std::remove_cvref_t<std::remove_pointer_t<Actual>>> ||
std::is_same_v<char8_t, std::remove_cvref_t<std::remove_pointer_t<Expected>>> || std::is_same_v<char8_t, std::remove_cvref_t<std::remove_pointer_t<Actual>>> ||
std::is_same_v<char16_t, std::remove_cvref_t<std::remove_pointer_t<Expected>>> || std::is_same_v<char16_t, std::remove_cvref_t<std::remove_pointer_t<Actual>>> ||
std::is_same_v<char32_t, std::remove_cvref_t<std::remove_pointer_t<Expected>>> || std::is_same_v<char32_t, std::remove_cvref_t<std::remove_pointer_t<Actual>>>), void>
CheckEqual(TestResults& results, Expected const& expected, Actual const& actual, TestDetails const& details)
{
if (!(expected == actual))
{
UnitTest::MemoryOutStream stream;
stream << "Expected " << expected << " but was " << actual;
results.OnTestFailure(details, stream.GetText());
}
}
template< typename Expected, typename Actual >
std::enable_if_t<(std::is_same_v<wchar_t, std::remove_cvref_t<std::remove_pointer_t<Expected>>> || std::is_same_v<wchar_t, std::remove_cvref_t<std::remove_pointer_t<Actual>>> ||
std::is_same_v<char8_t, std::remove_cvref_t<std::remove_pointer_t<Expected>>> || std::is_same_v<char8_t, std::remove_cvref_t<std::remove_pointer_t<Actual>>> ||
std::is_same_v<char16_t, std::remove_cvref_t<std::remove_pointer_t<Expected>>> || std::is_same_v<char16_t, std::remove_cvref_t<std::remove_pointer_t<Actual>>> ||
std::is_same_v<char32_t, std::remove_cvref_t<std::remove_pointer_t<Expected>>> || std::is_same_v<char32_t, std::remove_cvref_t<std::remove_pointer_t<Actual>>>), void>
CheckEqual(TestResults& results, Expected const& expected, Actual const& actual, TestDetails const& details)
{
if (!(expected == actual))
{
using int_type_expected = std::char_traits<Expected>::int_type;
using int_type_actual = std::char_traits<Actual>::int_type;
UnitTest::MemoryOutStream stream;
stream << "Expected " << int_type_expected(expected) << " but was " << int_type_actual(actual);
results.OnTestFailure(details, stream.GetText());
}
}
#else
template< typename Expected, typename Actual >
void CheckEqual(TestResults& results, Expected const& expected, Actual const& actual, TestDetails const& details)
{
if (!(expected == actual))
{
UnitTest::MemoryOutStream stream;
stream << "Expected " << expected << " but was " << actual;
results.OnTestFailure(details, stream.GetText());
}
}
#endif
template< typename Expected, typename Actual >
void CheckEqualHex(TestResults& results, Expected const& expected, Actual const& actual, TestDetails const& details)
{
if (!(expected == actual))
{
UnitTest::MemoryOutStream stream;
stream << std::hex << std::uppercase << std::setfill('0') << "Expected 0x" << std::setw(2 * sizeof(Expected)) << expected << " but was 0x" << std::setw(2 * sizeof(Actual)) << actual;
results.OnTestFailure(details, stream.GetText());
}
}
template< typename Expected, typename Actual >
void CheckNotEqual(TestResults& results, Expected const& expected, Actual const& actual, TestDetails const& details)
{
if (expected == actual)
{
UnitTest::MemoryOutStream stream;
stream << "Expected not equal, but both values are" << actual;
results.OnTestFailure(details, stream.GetText());
}
}
template< typename Expected, typename Actual >
void CheckNotEqualHex(TestResults& results, Expected const& expected, Actual const& actual, TestDetails const& details)
{
if (expected == actual)
{
UnitTest::MemoryOutStream stream;
stream << std::hex << std::uppercase << std::setfill('0') << std::setw(2 * sizeof(Actual)) << "Expected not equal, but both values are " << actual;
results.OnTestFailure(details, stream.GetText());
}
}
UNITTEST_LINKAGE void CheckEqual(TestResults& results, char const* expected, char const* actual, TestDetails const& details);
UNITTEST_LINKAGE void CheckEqual(TestResults& results, char* expected, char* actual, TestDetails const& details);
UNITTEST_LINKAGE void CheckEqual(TestResults& results, char* expected, char const* actual, TestDetails const& details);
UNITTEST_LINKAGE void CheckEqual(TestResults& results, char const* expected, char* actual, TestDetails const& details);
template< typename Expected, typename Actual, typename Tolerance >
bool AreClose(Expected const& expected, Actual const& actual, Tolerance const& tolerance)
{
return (actual >= (expected - tolerance)) && (actual <= (expected + tolerance));
}
template< typename Expected, typename Actual, typename Tolerance >
void CheckClose(TestResults& results, Expected const& expected, Actual const& actual, Tolerance const& tolerance,
TestDetails const& details)
{
if (!AreClose(expected, actual, tolerance))
{
UnitTest::MemoryOutStream stream;
stream << "Expected " << expected << " +/- " << tolerance << " but was " << actual;
results.OnTestFailure(details, stream.GetText());
}
}
#if __cplusplus >= 202002L
template< typename Expected, typename Actual >
void CheckArrayEqual(TestResults& results, Expected const& expected, Actual const& actual,
size_t const count, TestDetails const& details)
{
bool equal = true;
for (size_t i = 0; i < count; ++i)
equal &= (expected[i] == actual[i]);
if (!equal)
{
UnitTest::MemoryOutStream stream;
stream << "Expected [ ";
using expected_type = std::remove_cvref_t<decltype(expected[0])>;
using actual_type = std::remove_cvref_t<decltype(actual[0])>;
if constexpr (std::is_same_v<wchar_t, expected_type> || std::is_same_v<wchar_t, actual_type> ||
std::is_same_v<char8_t, expected_type> || std::is_same_v<char8_t, actual_type> ||
std::is_same_v<char16_t, expected_type> || std::is_same_v<char16_t, actual_type> ||
std::is_same_v<char32_t, expected_type> || std::is_same_v<char32_t, actual_type>)
{
using int_type_expected = std::char_traits<expected_type>::int_type;
using int_type_actual = std::char_traits<actual_type>::int_type;
for (size_t expectedIndex = 0; expectedIndex < count; ++expectedIndex)
stream << int_type_expected(expected[expectedIndex]) << " ";
stream << "] but was [ ";
for (size_t actualIndex = 0; actualIndex < count; ++actualIndex)
stream << int_type_actual(actual[actualIndex]) << " ";
stream << "]";
}
else
{
for (size_t expectedIndex = 0; expectedIndex < count; ++expectedIndex)
stream << expected[expectedIndex] << " ";
stream << "] but was [ ";
for (size_t actualIndex = 0; actualIndex < count; ++actualIndex)
stream << actual[actualIndex] << " ";
stream << "]";
}
results.OnTestFailure(details, stream.GetText());
}
}
#else
template< typename Expected, typename Actual >
void CheckArrayEqual(TestResults& results, Expected const& expected, Actual const& actual,
size_t const count, TestDetails const& details)
{
bool equal = true;
for (size_t i = 0; i < count; ++i)
equal &= (expected[i] == actual[i]);
if (!equal)
{
UnitTest::MemoryOutStream stream;
stream << "Expected [ ";
for (size_t expectedIndex = 0; expectedIndex < count; ++expectedIndex)
stream << expected[expectedIndex] << " ";
stream << "] but was [ ";
for (size_t actualIndex = 0; actualIndex < count; ++actualIndex)
stream << actual[actualIndex] << " ";
stream << "]";
results.OnTestFailure(details, stream.GetText());
}
}
#endif
template< typename Expected, typename Actual, typename Tolerance >
bool ArrayAreClose(Expected const& expected, Actual const& actual, size_t const count, Tolerance const& tolerance)
{
bool equal = true;
for (size_t i = 0; i < count; ++i)
equal &= AreClose(expected[i], actual[i], tolerance);
return equal;
}
template< typename Expected, typename Actual, typename Tolerance >
void CheckArrayClose(TestResults& results, Expected const& expected, Actual const& actual,
size_t const count, Tolerance const& tolerance, TestDetails const& details)
{
bool equal = ArrayAreClose(expected, actual, count, tolerance);
if (!equal)
{
UnitTest::MemoryOutStream stream;
stream << "Expected [ ";
for (size_t expectedIndex = 0; expectedIndex < count; ++expectedIndex)
stream << expected[expectedIndex] << " ";
stream << "] +/- " << tolerance << " but was [ ";
for (size_t actualIndex = 0; actualIndex < count; ++actualIndex)
stream << actual[actualIndex] << " ";
stream << "]";
results.OnTestFailure(details, stream.GetText());
}
}
template< typename Expected, typename Actual, typename Tolerance >
void CheckArray2DClose(TestResults& results, Expected const& expected, Actual const& actual,
size_t const rows, size_t const columns, Tolerance const& tolerance, TestDetails const& details)
{
bool equal = true;
for (size_t i = 0; i < rows; ++i)
equal &= ArrayAreClose(expected[i], actual[i], columns, tolerance);
if (!equal)
{
UnitTest::MemoryOutStream stream;
stream << "Expected [ ";
for (size_t expectedRow = 0; expectedRow < rows; ++expectedRow)
{
stream << "[ ";
for (size_t expectedColumn = 0; expectedColumn < columns; ++expectedColumn)
stream << expected[expectedRow][expectedColumn] << " ";
stream << "] ";
}
stream << "] +/- " << tolerance << " but was [ ";
for (size_t actualRow = 0; actualRow < rows; ++actualRow)
{
stream << "[ ";
for (size_t actualColumn = 0; actualColumn < columns; ++actualColumn)
stream << actual[actualRow][actualColumn] << " ";
stream << "] ";
}
stream << "]";
results.OnTestFailure(details, stream.GetText());
}
}
}
#if defined(__GNUC__) && !defined(__clang__) && !defined(__llvm__)
#pragma GCC diagnostic pop
#endif
#if defined(__clang__) || defined(__llvm__)
#pragma clang diagnostic pop
#endif
#endif