Skip to content

Commit

Permalink
Add new assertion SPANS_ARE_EQUAL
Browse files Browse the repository at this point in the history
  • Loading branch information
NeilJustice committed Sep 22, 2024
1 parent e8c890f commit 1a84923
Show file tree
Hide file tree
Showing 3 changed files with 235 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CppcheckSuppressions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ internalAstError:*
missingIncludeSystem:*
normalCheckLevelMaxBranches:*
nullPointer:*
returnDanglingLifetime:ZenUnitAndMetalMock\ZenUnit.h:3548
returnDanglingLifetime:*
unusedFunction:*
useStlAlgorithm:*
78 changes: 78 additions & 0 deletions ZenUnitAndMetalMock/ZenUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,10 @@ Example ZenUnit command line arguments:
ZenUnit::SETS_ARE_EQUAL_Defined(expectedSet, #expectedSet, actualSet, #actualSet, \
ZENUNIT_FILELINE, ZENUNIT_VA_ARGS_TEXT(__VA_ARGS__), ##__VA_ARGS__)

// Asserts that two std::spans<T> have equal sizes and equal elements according to ARE_EQUAL(expectedElement, actualElement) assertions.
#define SPANS_ARE_EQUAL(expectedSpan, actualSpan, ...) \
ZenUnit::SPANS_ARE_EQUAL_Defined(expectedSpan, #expectedSpan, actualSpan, #actualSpan, ZENUNIT_FILELINE)

// Asserts that the elements of expectedMap are equal to the elements of actualMap according to ARE_EQUAL(expectedElement, actualElement) assertions.
#define MAPS_ARE_EQUAL(expectedMap, actualMap, ...) \
ZenUnit::MAPS_ARE_EQUAL_Defined(expectedMap, #expectedMap, actualMap, #actualMap, \
Expand Down Expand Up @@ -4216,6 +4220,70 @@ namespace ZenUnit
throw anomaly;
}

template<typename T>
NOINLINE void SPANS_ARE_EQUAL_ThrowAnomaly(
const Anomaly& becauseAnomaly,
const std::span<T>& expectedSpan, const char* expectedSpanText,
const std::span<T>& actualSpan, const char* actualSpanText,
FilePathLineNumber filePathLineNumber)
{
const std::string toStringedExpectedSpan = ToStringer::ToString(expectedSpan);
const std::string toStringedActualSpan = ToStringer::ToString(actualSpan);
const Anomaly anomaly(
"SPANS_ARE_EQUAL",
expectedSpanText,
actualSpanText,
"",
"",
becauseAnomaly,
toStringedExpectedSpan,
toStringedActualSpan,
ExpectedActualFormat::Fields, filePathLineNumber);
throw anomaly;
}

template<typename T>
void SPANS_ARE_EQUAL_Defined(
const std::span<T>& expectedSpan, const char* expectedSpanText,
const std::span<T>& actualSpan, const char* actualSpanText,
FilePathLineNumber filePathLineNumber)
{
try
{
ARE_EQUAL(expectedSpan.size(), actualSpan.size());
}
catch (const Anomaly& becauseAnomaly)
{
SPANS_ARE_EQUAL_ThrowAnomaly(
becauseAnomaly,
expectedSpan, expectedSpanText,
actualSpan, actualSpanText,
filePathLineNumber);
}
const size_t expectedSpanSize = expectedSpan.size();
constexpr size_t IEqualsSignLength = 2;
constexpr size_t SizeTMaxValueLength = 21; // strlen("18446744073709551615")
char indexMessage[IEqualsSignLength + SizeTMaxValueLength]{ "i=" };
for (size_t i = 0; i < expectedSpanSize; ++i)
{
const T& ithExpectedElement = expectedSpan[i];
const T& ithActualElement = actualSpan[i];
WriteIntegerToCharArray(i, indexMessage + IEqualsSignLength);
try
{
ARE_EQUAL(ithExpectedElement, ithActualElement, indexMessage);
}
catch (const Anomaly& becauseAnomaly)
{
SPANS_ARE_EQUAL_ThrowAnomaly(
becauseAnomaly,
expectedSpan, expectedSpanText,
actualSpan, actualSpanText,
filePathLineNumber);
}
}
}

template<
template<typename...>
class IndexableType,
Expand Down Expand Up @@ -7435,6 +7503,16 @@ or change TEST(TestName) to TESTNXN(TestName, ...), where N can be 1 through 10,
}
};

template<typename T>
class Printer<std::span<T>>
{
public:
static void Print(std::ostream& os, const std::span<T>& sp)
{
PrintCollection(os, sp);
}
};

template<typename TKey, typename TValue, typename LessComparator, typename Allocator>
class Printer<std::map<TKey, TValue, LessComparator, Allocator>>
{
Expand Down
156 changes: 156 additions & 0 deletions ZenUnitUtilsAndAssertionTests/Assertions/SPANS_ARE_EQUALTests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#include "pch.h"

namespace ZenUnit
{
template<typename T>
TEMPLATE_TESTS(SPANS_ARE_EQUALTests, T)
AFACT(ConstEmptySpans_DoesNothing)
AFACT(NonConstEmptySpans_DoesNothing)
AFACT(ConstNonEmptySpans_AllElementsEqual_DoesNothing)
AFACT(ConstNonEmptySpans_SizesAreNotEqual_ThrowsAnomaly)
AFACT(ConstNonEmptySpans_SizesAreEqual_ElementsAreNotEqual_ThrowsAnomaly__TestCase1)
AFACT(ConstNonEmptySpans_SizesAreEqual_ElementsAreNotEqual_ThrowsAnomaly__TestCase2)
AFACT(NonConstNonEmptySpans_SizesAreEqual_ElementsAreNotEqual_ThrowsAnomaly)
EVIDENCE

const string TypeName = *Type::GetName<T>();
const string _constSpanTypeName = *Type::GetName<span<const T>>();
const string _nonConstSpanTypeName = *Type::GetName<span<T>>();

TEST(ConstEmptySpans_DoesNothing)
{
const span<const T> expectedSpan;
const span<const T> actualSpan;
SPANS_ARE_EQUAL(expectedSpan, actualSpan);
}

TEST(NonConstEmptySpans_DoesNothing)
{
const span<T> expectedSpan;
const span<T> actualSpan;
SPANS_ARE_EQUAL(expectedSpan, actualSpan);
}

TEST(ConstNonEmptySpans_AllElementsEqual_DoesNothing)
{
const vector<T> expectedElements{ 1, 2, 3 };
const vector<T> actualElements{ 1, 2, 3 };

const span<const T> expectedSpan = expectedElements;
const span<const T> actualSpan = actualElements;
SPANS_ARE_EQUAL(expectedSpan, actualSpan);
}

TEST(ConstNonEmptySpans_SizesAreNotEqual_ThrowsAnomaly)
{
const vector<T> expectedElements;
const vector<T> actualElements{ 1 };

const span<const T> expectedSpan = expectedElements;
const span<const T> actualSpan = actualElements;

THROWS_EXCEPTION(SPANS_ARE_EQUAL(expectedSpan, actualSpan),
Anomaly, TestUtil::NewlineConcat("",
" Failed: SPANS_ARE_EQUAL(expectedSpan, actualSpan)",
"Expected: " + _constSpanTypeName + " (size 0):",
"{",
"}",
" Actual: " + _constSpanTypeName + " (size 1):",
"{",
" 1",
"}",
" Because: ARE_EQUAL(expectedSpan.size(), actualSpan.size()) failed",
"Expected: 0",
" Actual: 1",
"File.cpp(1)",
"File.cpp(1)"));
}

TEST(ConstNonEmptySpans_SizesAreEqual_ElementsAreNotEqual_ThrowsAnomaly__TestCase1)
{
const vector<T> expectedElements{ 0 };
const vector<T> actualElements{ 1 };

const span<const T> expectedSpan = expectedElements;
const span<const T> actualSpan = actualElements;

THROWS_EXCEPTION(SPANS_ARE_EQUAL(expectedSpan, actualSpan),
Anomaly, TestUtil::NewlineConcat("",
" Failed: SPANS_ARE_EQUAL(expectedSpan, actualSpan)",
"Expected: " + _constSpanTypeName + " (size 1):",
"{",
" 0",
"}",
" Actual: " + _constSpanTypeName + " (size 1):",
"{",
" 1",
"}",
" Because: ARE_EQUAL(ithExpectedElement, ithActualElement, indexMessage) failed",
"Expected: 0",
" Actual: 1",
" Message: \"i=0\"",
"File.cpp(1)",
"File.cpp(1)"));
}

TEST(ConstNonEmptySpans_SizesAreEqual_ElementsAreNotEqual_ThrowsAnomaly__TestCase2)
{
const vector<T> expectedElements{ 0, 1, 20 };
const vector<T> actualElements{ 0, 1, 30 };

const span<const T> expectedSpan = expectedElements;
const span<const T> actualSpan = actualElements;

THROWS_EXCEPTION(SPANS_ARE_EQUAL(expectedSpan, actualSpan),
Anomaly, TestUtil::NewlineConcat("",
" Failed: SPANS_ARE_EQUAL(expectedSpan, actualSpan)",
"Expected: " + _constSpanTypeName + " (size 3):",
"{",
" 0,",
" 1,",
" 20",
"}",
" Actual: " + _constSpanTypeName + " (size 3):",
"{",
" 0,",
" 1,",
" 30",
"}",
" Because: ARE_EQUAL(ithExpectedElement, ithActualElement, indexMessage) failed",
"Expected: 20",
" Actual: 30",
" Message: \"i=2\"",
"File.cpp(1)",
"File.cpp(1)"));
}

TEST(NonConstNonEmptySpans_SizesAreEqual_ElementsAreNotEqual_ThrowsAnomaly)
{
vector<T> expectedElements{ 0 };
vector<T> actualElements{ 1 };

const span<T> expectedSpan = expectedElements;
const span<T> actualSpan = actualElements;

THROWS_EXCEPTION(SPANS_ARE_EQUAL(expectedSpan, actualSpan),
Anomaly, TestUtil::NewlineConcat("",
" Failed: SPANS_ARE_EQUAL(expectedSpan, actualSpan)",
"Expected: " + _nonConstSpanTypeName + " (size 1):",
"{",
" 0",
"}",
" Actual: " + _nonConstSpanTypeName + " (size 1):",
"{",
" 1",
"}",
" Because: ARE_EQUAL(ithExpectedElement, ithActualElement, indexMessage) failed",
"Expected: 0",
" Actual: 1",
" Message: \"i=0\"",
"File.cpp(1)",
"File.cpp(1)"));
}

RUN_TEMPLATE_TESTS(SPANS_ARE_EQUALTests, int)
THEN_RUN_TEMPLATE_TESTS(SPANS_ARE_EQUALTests, unsigned long long)
}

0 comments on commit 1a84923

Please sign in to comment.