Why should one use the string comparison assertions?
Ignore the fact that there's a STRING
in the name and use CU_ASSERT_NSTRING_EQUAL(actual, expected, count). Specifically in your case, the assertions might be
//Assert that the arrays are the same size.
//If not, they can't have deep equality.
CU_ASSERT_EQUAL(sizeof(arr1), sizeof(arr2));
//Now assert byte-by-byte equality
//for the size of both arrays
CU_ASSERT_NSTRING_EQUAL(arr1, arr2, sizeof(arr1));
Looking at the documentation, you can see that the semantic meaning of CU_ASSERT_NSTRING_EQUAL is "assert that 1st count chars of actual and expected are the same." Recall that a char
is just a byte in memory. The fact that you interpret the bytes at &arr1
through &arr + (1 * sizeof(uchar))
as unsigned characters notwithstanding, string comparison is done by incrementing across the characters one by one and checking their byte value. For CU_ASSERT_STRING_EQUAL(actual, expected)
this occurs until a null byte is encountered because that's how strings are terminated. For CU_ASSERT_NSTRING_EQUAL(actual, expected, count)
, a size is passed because you want to inspect count
-bytes, regardless of whether a null byte is encountered or not. The types in the array might be larger than a char
, but it doesn't matter. Underneath, they're still just a fixed number of bytes contiguously located in memory.
Note that this only works if you can tell the unit test framework the size of the object to inspect. This requires either inspecting the object using sizeof()
, or knowing the size of the object and having a pointer to the object (recall that sizeof()
a pointer is always the same, regardless of the size of the object pointed-to). For an object which is dynamically-sized, this might not be possible.
But will iterating across the array still work?
Maybe. But you'll need to have an assertion for every index. Again, this will only work if you know the size of the array at compile time (i.e. arrays whose space is acquired by malloc
and are located on the heap will have unknown sizes at compile time, and therefore a for-loop of CU_ASSERT_EQUAL
assertions won't work). In your case, here's what such a thing might look like
//Assert that the arrays are the same size
//If not, they can't have deep equality.
CU_ASSERT_EQUAL(sizeof(arr1), sizeof(arr2));
//Now assert index-by-index equality
for (size_t i=0; i < sizeof(arr1) / sizeof(uchar); i++)
CU_ASSERT_EQUAL(arr1[i], arr2[i]);
The problem is that your suite will quickly become filled with assertions for large arrays. You don't want to know each element in the array that doesn't match... you want to know that any element in the array doesn't match. As soon as CU_ASSERT_NSTRING_EQUAL
finds a non-match, the test fails. This is not the case for a loop of CU_ASSERT_EQUAL
assertions. Since the CUnit assertions are implemented as macros, there's no return value to inspect such that you could break out of the loop. And even if you did a separate non-assertion comparison, you'd still leave the trail of assertions that did complete prior to the first non-matching index.