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
260 lines
5.9 KiB
C++
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
|