/* 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 data = {3, 4, 5, 6, 7}; VArray varray = VArray::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 varray = VArray::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 array = {1, 2, 3, 5, 8}; { VArray varray = VArray::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 varray = VArray::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 varray = VArray::ForContainer(array); /* NOLINT: bugprone-use-after-move */ EXPECT_TRUE(varray.is_empty()); } } TEST(virtual_array, Vector) { Vector vector = {9, 8, 7, 6}; VArray varray = VArray::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 vector = {5, 6, 7, 8}; VArray varray = VArray::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 array = {2, 3, 4, 5}; VArray varray = VArray::ForContainer(std::move(array)); EXPECT_EQ(varray.size(), 4); EXPECT_EQ(varray[0], 2); EXPECT_EQ(varray[1], 3); } TEST(virtual_array, VectorSet) { VectorSet vector_set = {5, 3, 7, 3, 3, 5, 1}; VArray varray = VArray::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 varray = VArray::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 func_varray = VArray::ForFunc(10, func); VArraySpan span_varray{func_varray}; EXPECT_EQ(span_varray.size(), 10); Span 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 &item) { return item[0]; } static void set_x(std::array &item, int value) { item[0] = value; } TEST(virtual_array, DerivedSpan) { Vector> vector; vector.append({3, 4, 5}); vector.append({1, 1, 1}); { VArray varray = VArray::ForDerivedSpan, get_x>(vector); EXPECT_EQ(varray.size(), 2); EXPECT_EQ(varray[0], 3); EXPECT_EQ(varray[1], 1); } { VMutableArray varray = VMutableArray::ForDerivedSpan, 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 array = {4, 2, 6, 4}; { VMutableArray mutable_varray = VMutableArray::ForSpan(array); VArray 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 mutable_varray = VMutableArray::ForSpan(array); EXPECT_EQ(mutable_varray.size(), 4); VArray 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 varray = VMutableArray::ForSpan(array); EXPECT_TRUE(varray.is_span()); EXPECT_EQ(varray.size(), 4); EXPECT_EQ(varray[1], 2); } } TEST(virtual_array, MaterializeCompressed) { { std::array array = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90}; VArray varray = VArray::ForSpan(array); std::array 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 varray = VArray::ForSingle(4, 10); std::array 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 varray = VArray::ForFunc(10, [](const int64_t i) { return int(i * i); }); std::array 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 varray; VArraySpan span1 = varray; EXPECT_TRUE(span1.is_empty()); VArraySpan span2 = std::move(span1); EXPECT_TRUE(span2.is_empty()); } { VMutableArray varray; MutableVArraySpan span1 = varray; EXPECT_TRUE(span1.is_empty()); MutableVArraySpan 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