Files
test2/source/blender/blenlib/tests/BLI_array_test.cc
Mattias Fredriksson 407dcb39d4 Tests: EXPECT_EQ_SPAN utility macro
Replaces pointer based EXPECT_EQ_ARRAY with EXPECT_EQ_SPAN in most cases
as they already used spans (or span compatible datastructures).
Currently EXPECT_EQ_ARRAY only takes in one size variable and doesn't
compare the  number of elements between arguments (requiring an
additional line to do so).

This should make the code cleaner and safer. Goal is also to promote
the use Spans in new test code.

Pull Request: https://projects.blender.org/blender/blender/pulls/140340
2025-06-16 20:31:00 +02:00

260 lines
5.9 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: Apache-2.0 */
#include "testing/testing.h"
#include "BLI_array.hh"
#include "BLI_exception_safety_test_utils.hh"
#include "BLI_vector.hh"
#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
namespace blender::tests {
TEST(array, DefaultConstructor)
{
Array<int> array;
EXPECT_EQ(array.size(), 0);
EXPECT_TRUE(array.is_empty());
}
TEST(array, SizeConstructor)
{
Array<int> array(5);
EXPECT_EQ(array.size(), 5);
EXPECT_FALSE(array.is_empty());
}
TEST(array, FillConstructor)
{
Array<int> array(5, 8);
EXPECT_EQ(array.size(), 5);
EXPECT_EQ(array[0], 8);
EXPECT_EQ(array[1], 8);
EXPECT_EQ(array[2], 8);
EXPECT_EQ(array[3], 8);
EXPECT_EQ(array[4], 8);
}
TEST(array, InitializerListConstructor)
{
Array<int> array = {4, 5, 6, 7};
EXPECT_EQ(array.size(), 4);
EXPECT_EQ(array[0], 4);
EXPECT_EQ(array[1], 5);
EXPECT_EQ(array[2], 6);
EXPECT_EQ(array[3], 7);
}
TEST(array, SpanConstructor)
{
int stackarray[4] = {6, 7, 8, 9};
Span<int> span(stackarray, ARRAY_SIZE(stackarray));
Array<int> array(span);
EXPECT_EQ(array.size(), 4);
EXPECT_EQ(array[0], 6);
EXPECT_EQ(array[1], 7);
EXPECT_EQ(array[2], 8);
EXPECT_EQ(array[3], 9);
}
TEST(array, CopyConstructor)
{
Array<int> array = {5, 6, 7, 8};
Array<int> new_array(array);
EXPECT_EQ(array.size(), 4);
EXPECT_EQ(new_array.size(), 4);
EXPECT_NE(array.data(), new_array.data());
EXPECT_EQ(new_array[0], 5);
EXPECT_EQ(new_array[1], 6);
EXPECT_EQ(new_array[2], 7);
EXPECT_EQ(new_array[3], 8);
}
TEST(array, MoveConstructor)
{
Array<int> array = {5, 6, 7, 8};
Array<int> new_array(std::move(array));
EXPECT_EQ(array.size(), 0); /* NOLINT: bugprone-use-after-move */
EXPECT_EQ(new_array.size(), 4);
EXPECT_EQ(new_array[0], 5);
EXPECT_EQ(new_array[1], 6);
EXPECT_EQ(new_array[2], 7);
EXPECT_EQ(new_array[3], 8);
}
TEST(array, CopyAssignment)
{
Array<int> array = {1, 2, 3};
Array<int> new_array = {4};
EXPECT_EQ(new_array.size(), 1);
new_array = array;
EXPECT_EQ(new_array.size(), 3);
EXPECT_EQ(array.size(), 3);
EXPECT_NE(array.data(), new_array.data());
EXPECT_EQ(new_array[0], 1);
EXPECT_EQ(new_array[1], 2);
EXPECT_EQ(new_array[2], 3);
}
TEST(array, MoveAssignment)
{
Array<int> array = {1, 2, 3};
Array<int> new_array = {4};
EXPECT_EQ(new_array.size(), 1);
new_array = std::move(array);
EXPECT_EQ(new_array.size(), 3);
EXPECT_EQ(array.size(), 0); /* NOLINT: bugprone-use-after-move */
EXPECT_EQ(new_array[0], 1);
EXPECT_EQ(new_array[1], 2);
EXPECT_EQ(new_array[2], 3);
}
/**
* Tests that the trivially constructible types are not zero-initialized. We do not want that for
* performance reasons.
*/
TEST(array, TrivialTypeSizeConstructor)
{
Array<char, 1> *array = new Array<char, 1>(1);
char *ptr = &(*array)[0];
array->~Array();
const char magic = 42;
*ptr = magic;
EXPECT_EQ(*ptr, magic);
new (array) Array<char, 1>(1);
EXPECT_EQ((*array)[0], magic);
EXPECT_EQ(*ptr, magic);
delete array;
}
struct ConstructibleType {
char value;
ConstructibleType()
{
value = 42;
}
};
TEST(array, NoInitializationSizeConstructor)
{
using MyArray = Array<ConstructibleType>;
TypedBuffer<MyArray> buffer;
memset((void *)&buffer, 100, sizeof(MyArray));
/* Doing this to avoid some compiler optimization. */
for (int64_t i : IndexRange(sizeof(MyArray))) {
EXPECT_EQ(((char *)buffer.ptr())[i], 100);
}
{
MyArray &array = *new (buffer) MyArray(1, NoInitialization());
EXPECT_EQ(array[0].value, 100);
array.clear_without_destruct();
array.~Array();
}
{
MyArray &array = *new (buffer) MyArray(1);
EXPECT_EQ(array[0].value, 42);
array.~Array();
}
}
TEST(array, Fill)
{
Array<int> array(5);
array.fill(3);
EXPECT_EQ(array.size(), 5u);
EXPECT_EQ(array[0], 3);
EXPECT_EQ(array[1], 3);
EXPECT_EQ(array[2], 3);
EXPECT_EQ(array[3], 3);
EXPECT_EQ(array[4], 3);
}
TEST(array, ReverseIterator)
{
Array<int> array = {3, 4, 5, 6};
Vector<int> reversed_vec;
for (auto it = array.rbegin(); it != array.rend(); ++it) {
reversed_vec.append(*it);
*it += 10;
}
EXPECT_EQ_SPAN<int>(reversed_vec, Span({6, 5, 4, 3}));
EXPECT_EQ_SPAN<int>(array, Span({13, 14, 15, 16}));
}
TEST(array, SpanConstructorExceptions)
{
std::array<ExceptionThrower, 4> values;
values[2].throw_during_copy = true;
Span<ExceptionThrower> span{values};
EXPECT_ANY_THROW({ Array<ExceptionThrower> array(span); });
}
TEST(array, SizeValueConstructorExceptions)
{
ExceptionThrower value;
value.throw_during_copy = true;
EXPECT_ANY_THROW({ Array<ExceptionThrower> array(5, value); });
}
TEST(array, MoveConstructorExceptions)
{
Array<ExceptionThrower, 4> array(3);
array[1].throw_during_move = true;
EXPECT_ANY_THROW({ Array<ExceptionThrower> array_copy(std::move(array)); });
}
TEST(array, CopyAssignmentExceptions)
{
Array<ExceptionThrower> array(5);
array[3].throw_during_copy = true;
Array<ExceptionThrower> array_copy(10);
EXPECT_ANY_THROW({ array_copy = array; });
}
TEST(array, MoveAssignmentExceptions)
{
Array<ExceptionThrower, 4> array(4);
array[2].throw_during_move = true;
Array<ExceptionThrower> array_moved(10);
EXPECT_ANY_THROW({ array_moved = std::move(array); });
}
TEST(array, Last)
{
Array<int> array = {5, 7, 8, 9};
EXPECT_EQ(array.last(), 9);
EXPECT_EQ(array.last(1), 8);
array.last() = 1;
EXPECT_EQ(array[3], 1);
EXPECT_EQ(const_cast<const Array<int> &>(array).last(), 1);
EXPECT_EQ(const_cast<const Array<int> &>(array).last(2), 7);
}
TEST(array, Reinitialize)
{
Array<std::string> array = {"hello", "world"};
EXPECT_EQ(array.size(), 2);
EXPECT_EQ(array[1], "world");
array.reinitialize(3);
EXPECT_EQ(array.size(), 3);
EXPECT_EQ(array[0], "");
EXPECT_EQ(array[1], "");
EXPECT_EQ(array[2], "");
array.reinitialize(0);
EXPECT_EQ(array.size(), 0);
}
} // namespace blender::tests