Files
test/source/blender/blenlib/tests/BLI_virtual_array_test.cc
Jacques Lucke ba62e20af6 BLI: make some spans default constructible
`GSpan` and spans based on virtual arrays were not default constructible
before, which made them hard to use sometimes. It's generally fine for
spans to be empty.

The main thing the keep in mind is that the type pointer in `GSpan` may
be null now. Generally, code receiving spans as input can assume that
the type is not-null, but sometimes that may be valid. The old #type() method
that returned a reference to the type still exists. It asserts when the
type is null.
2022-07-07 19:19:18 +02:00

259 lines
7.2 KiB
C++

/* SPDX-License-Identifier: Apache-2.0 */
#include "BLI_array.hh"
#include "BLI_generic_virtual_array.hh"
#include "BLI_strict_flags.h"
#include "BLI_vector.hh"
#include "BLI_vector_set.hh"
#include "BLI_virtual_array.hh"
#include "testing/testing.h"
namespace blender::tests {
TEST(virtual_array, Span)
{
std::array<int, 5> data = {3, 4, 5, 6, 7};
VArray<int> varray = VArray<int>::ForSpan(data);
EXPECT_EQ(varray.size(), 5);
EXPECT_EQ(varray.get(0), 3);
EXPECT_EQ(varray.get(4), 7);
EXPECT_TRUE(varray.is_span());
EXPECT_FALSE(varray.is_single());
EXPECT_EQ(varray.get_internal_span().data(), data.data());
}
TEST(virtual_array, Single)
{
VArray<int> varray = VArray<int>::ForSingle(10, 4);
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray.get(0), 10);
EXPECT_EQ(varray.get(3), 10);
EXPECT_FALSE(varray.is_span());
EXPECT_TRUE(varray.is_single());
}
TEST(virtual_array, Array)
{
Array<int> array = {1, 2, 3, 5, 8};
{
VArray<int> varray = VArray<int>::ForContainer(array);
EXPECT_EQ(varray.size(), 5);
EXPECT_EQ(varray[0], 1);
EXPECT_EQ(varray[2], 3);
EXPECT_EQ(varray[3], 5);
EXPECT_TRUE(varray.is_span());
}
{
VArray<int> varray = VArray<int>::ForContainer(std::move(array));
EXPECT_EQ(varray.size(), 5);
EXPECT_EQ(varray[0], 1);
EXPECT_EQ(varray[2], 3);
EXPECT_EQ(varray[3], 5);
EXPECT_TRUE(varray.is_span());
}
{
VArray<int> varray = VArray<int>::ForContainer(array); /* NOLINT: bugprone-use-after-move */
EXPECT_TRUE(varray.is_empty());
}
}
TEST(virtual_array, Vector)
{
Vector<int> vector = {9, 8, 7, 6};
VArray<int> varray = VArray<int>::ForContainer(std::move(vector));
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[0], 9);
EXPECT_EQ(varray[3], 6);
}
TEST(virtual_array, StdVector)
{
std::vector<int> vector = {5, 6, 7, 8};
VArray<int> varray = VArray<int>::ForContainer(std::move(vector));
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[0], 5);
EXPECT_EQ(varray[1], 6);
}
TEST(virtual_array, StdArray)
{
std::array<int, 4> array = {2, 3, 4, 5};
VArray<int> varray = VArray<int>::ForContainer(std::move(array));
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[0], 2);
EXPECT_EQ(varray[1], 3);
}
TEST(virtual_array, VectorSet)
{
VectorSet<int> vector_set = {5, 3, 7, 3, 3, 5, 1};
VArray<int> varray = VArray<int>::ForContainer(std::move(vector_set));
EXPECT_TRUE(vector_set.is_empty()); /* NOLINT: bugprone-use-after-move. */
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[0], 5);
EXPECT_EQ(varray[1], 3);
EXPECT_EQ(varray[2], 7);
EXPECT_EQ(varray[3], 1);
}
TEST(virtual_array, Func)
{
auto func = [](int64_t index) { return (int)(index * index); };
VArray<int> varray = VArray<int>::ForFunc(10, func);
EXPECT_EQ(varray.size(), 10);
EXPECT_EQ(varray[0], 0);
EXPECT_EQ(varray[3], 9);
EXPECT_EQ(varray[9], 81);
}
TEST(virtual_array, AsSpan)
{
auto func = [](int64_t index) { return (int)(10 * index); };
VArray<int> func_varray = VArray<int>::ForFunc(10, func);
VArraySpan span_varray{func_varray};
EXPECT_EQ(span_varray.size(), 10);
Span<int> span = span_varray;
EXPECT_EQ(span.size(), 10);
EXPECT_EQ(span[0], 0);
EXPECT_EQ(span[3], 30);
EXPECT_EQ(span[6], 60);
}
static int get_x(const std::array<int, 3> &item)
{
return item[0];
}
static void set_x(std::array<int, 3> &item, int value)
{
item[0] = value;
}
TEST(virtual_array, DerivedSpan)
{
Vector<std::array<int, 3>> vector;
vector.append({3, 4, 5});
vector.append({1, 1, 1});
{
VArray<int> varray = VArray<int>::ForDerivedSpan<std::array<int, 3>, get_x>(vector);
EXPECT_EQ(varray.size(), 2);
EXPECT_EQ(varray[0], 3);
EXPECT_EQ(varray[1], 1);
}
{
VMutableArray<int> varray =
VMutableArray<int>::ForDerivedSpan<std::array<int, 3>, get_x, set_x>(vector);
EXPECT_EQ(varray.size(), 2);
EXPECT_EQ(varray[0], 3);
EXPECT_EQ(varray[1], 1);
varray.set(0, 10);
varray.set(1, 20);
EXPECT_EQ(vector[0][0], 10);
EXPECT_EQ(vector[1][0], 20);
}
}
TEST(virtual_array, MutableToImmutable)
{
std::array<int, 4> array = {4, 2, 6, 4};
{
VMutableArray<int> mutable_varray = VMutableArray<int>::ForSpan(array);
VArray<int> varray = mutable_varray;
EXPECT_TRUE(varray.is_span());
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[1], 2);
EXPECT_EQ(mutable_varray.size(), 4);
}
{
VMutableArray<int> mutable_varray = VMutableArray<int>::ForSpan(array);
EXPECT_EQ(mutable_varray.size(), 4);
VArray<int> varray = std::move(mutable_varray);
EXPECT_TRUE(varray.is_span());
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[1], 2);
EXPECT_EQ(mutable_varray.size(), 0); /* NOLINT: bugprone-use-after-move */
}
{
VArray<int> varray = VMutableArray<int>::ForSpan(array);
EXPECT_TRUE(varray.is_span());
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[1], 2);
}
}
TEST(virtual_array, MaterializeCompressed)
{
{
std::array<int, 10> array = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90};
VArray<int> varray = VArray<int>::ForSpan(array);
std::array<int, 3> compressed_array;
varray.materialize_compressed({3, 6, 7}, compressed_array);
EXPECT_EQ(compressed_array[0], 30);
EXPECT_EQ(compressed_array[1], 60);
EXPECT_EQ(compressed_array[2], 70);
varray.materialize_compressed_to_uninitialized({2, 8, 9}, compressed_array);
EXPECT_EQ(compressed_array[0], 20);
EXPECT_EQ(compressed_array[1], 80);
EXPECT_EQ(compressed_array[2], 90);
}
{
VArray<int> varray = VArray<int>::ForSingle(4, 10);
std::array<int, 3> compressed_array;
varray.materialize_compressed({2, 6, 7}, compressed_array);
EXPECT_EQ(compressed_array[0], 4);
EXPECT_EQ(compressed_array[1], 4);
EXPECT_EQ(compressed_array[2], 4);
compressed_array.fill(0);
varray.materialize_compressed_to_uninitialized({0, 1, 2}, compressed_array);
EXPECT_EQ(compressed_array[0], 4);
EXPECT_EQ(compressed_array[1], 4);
EXPECT_EQ(compressed_array[2], 4);
}
{
VArray<int> varray = VArray<int>::ForFunc(10, [](const int64_t i) { return (int)(i * i); });
std::array<int, 3> compressed_array;
varray.materialize_compressed({5, 7, 8}, compressed_array);
EXPECT_EQ(compressed_array[0], 25);
EXPECT_EQ(compressed_array[1], 49);
EXPECT_EQ(compressed_array[2], 64);
varray.materialize_compressed_to_uninitialized({1, 2, 3}, compressed_array);
EXPECT_EQ(compressed_array[0], 1);
EXPECT_EQ(compressed_array[1], 4);
EXPECT_EQ(compressed_array[2], 9);
}
}
TEST(virtual_array, EmptySpanWrapper)
{
{
VArray<int> varray;
VArraySpan<int> span1 = varray;
EXPECT_TRUE(span1.is_empty());
VArraySpan<int> span2 = std::move(span1);
EXPECT_TRUE(span2.is_empty());
}
{
VMutableArray<int> varray;
MutableVArraySpan<int> span1 = varray;
EXPECT_TRUE(span1.is_empty());
MutableVArraySpan<int> span2 = std::move(span1);
EXPECT_TRUE(span2.is_empty());
}
{
GVArray varray;
GVArraySpan span1 = varray;
EXPECT_TRUE(span1.is_empty());
GVArraySpan span2 = std::move(span1);
EXPECT_TRUE(span2.is_empty());
}
{
GVMutableArray varray;
GMutableVArraySpan span1 = varray;
EXPECT_TRUE(span1.is_empty());
GMutableVArraySpan span2 = std::move(span1);
EXPECT_TRUE(span2.is_empty());
}
}
} // namespace blender::tests