Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2021-10-14 19:06:18 +0300
committerHans Goudey <h.goudey@me.com>2021-10-14 19:06:18 +0300
commitb42ce0c54cab8ff5f85ca795cc1f0dab4308449b (patch)
treea924f6615cf2f6ae1471311bc359d57a283e33f9 /source/blender/functions/tests
parent5e8775a8da93292a6d8ef0eed3b89dea40c94399 (diff)
Functions: Generic array data structure
Sometimes it's useful to pass around a set of values with a generic type. The virtual array data structures allow this, but they don't have logical ownership. My initial use case for this is as a return type for the functions that interpolate curve attributes to evaluated points, but a need for this data structure has come up in a few other places as well. It also reduced the need for templates. Differential Revision: https://developer.blender.org/D11103
Diffstat (limited to 'source/blender/functions/tests')
-rw-r--r--source/blender/functions/tests/FN_generic_array_test.cc118
1 files changed, 118 insertions, 0 deletions
diff --git a/source/blender/functions/tests/FN_generic_array_test.cc b/source/blender/functions/tests/FN_generic_array_test.cc
new file mode 100644
index 00000000000..417ab479cca
--- /dev/null
+++ b/source/blender/functions/tests/FN_generic_array_test.cc
@@ -0,0 +1,118 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_array.hh"
+
+#include "FN_generic_array.hh"
+
+namespace blender::fn::tests {
+
+TEST(generic_array, TypeConstructor)
+{
+ GArray array(CPPType::get<float>());
+ EXPECT_TRUE(array.data() == nullptr);
+ EXPECT_EQ(array.size(), 0);
+ EXPECT_EQ(array.as_span().typed<float>().size(), 0);
+ EXPECT_TRUE(array.is_empty());
+}
+
+TEST(generic_array, MoveConstructor)
+{
+ GArray array_a(CPPType::get<int32_t>(), (int64_t)10);
+ GMutableSpan span_a = array_a.as_mutable_span();
+ MutableSpan<int32_t> typed_span_a = span_a.typed<int32_t>();
+ typed_span_a.fill(42);
+
+ const GArray array_b = std::move(array_a);
+ Span<int32_t> typed_span_b = array_b.as_span().typed<int32_t>();
+ EXPECT_FALSE(array_b.data() == nullptr);
+ EXPECT_EQ(array_b.size(), 10);
+ EXPECT_EQ(typed_span_b[4], 42);
+
+ /* Make sure the copy constructor cleaned up the original, but it shouldn't clear the type. */
+ EXPECT_TRUE(array_a.data() == nullptr); /* NOLINT: bugprone-use-after-move */
+ EXPECT_EQ(array_a.size(), 0); /* NOLINT: bugprone-use-after-move */
+ EXPECT_TRUE(array_a.is_empty()); /* NOLINT: bugprone-use-after-move */
+ EXPECT_EQ(array_b.type(), array_a.type()); /* NOLINT: bugprone-use-after-move */
+}
+
+TEST(generic_array, CopyConstructor)
+{
+ GArray array_a(CPPType::get<int32_t>(), (int64_t)10);
+ GMutableSpan span_a = array_a.as_mutable_span();
+ MutableSpan<int32_t> typed_span_a = span_a.typed<int32_t>();
+ typed_span_a.fill(42);
+
+ /* From span directly. */
+ const GArray array_b = array_a.as_span();
+ Span<int32_t> typed_span_b = array_b.as_span().typed<int32_t>();
+ EXPECT_FALSE(array_b.data() == nullptr);
+ EXPECT_EQ(array_b.size(), 10);
+ EXPECT_EQ(typed_span_b[4], 42);
+ EXPECT_FALSE(array_a.is_empty());
+
+ /* From array. */
+ const GArray array_c = array_a;
+ Span<int32_t> typed_span_c = array_c.as_span().typed<int32_t>();
+ EXPECT_FALSE(array_c.data() == nullptr);
+ EXPECT_EQ(array_c.size(), 10);
+ EXPECT_EQ(typed_span_c[4], 42);
+ EXPECT_FALSE(array_a.is_empty());
+}
+
+TEST(generic_array, BufferAndSizeConstructor)
+{
+ int32_t *values = (int32_t *)MEM_malloc_arrayN(12, sizeof(int32_t), __func__);
+ void *buffer = (void *)values;
+ GArray array(CPPType::get<int32_t>(), buffer, 4);
+ EXPECT_FALSE(array.data() == nullptr);
+ EXPECT_EQ(array.size(), 4);
+ EXPECT_FALSE(array.is_empty());
+ EXPECT_EQ(array.as_span().typed<int>().size(), 4);
+ EXPECT_EQ(array[0], &values[0]);
+ EXPECT_EQ(array[1], &values[1]);
+ EXPECT_EQ(array[2], &values[2]);
+ EXPECT_EQ(array[3], &values[3]);
+}
+
+TEST(generic_array, Reinitialize)
+{
+ GArray array(CPPType::get<int32_t>(), (int64_t)5);
+ EXPECT_FALSE(array.data() == nullptr);
+ GMutableSpan span = array.as_mutable_span();
+ MutableSpan<int32_t> typed_span = span.typed<int32_t>();
+ typed_span.fill(77);
+ EXPECT_FALSE(typed_span.data() == nullptr);
+ typed_span[2] = 8;
+ EXPECT_EQ(array[2], &typed_span[2]);
+ EXPECT_EQ(typed_span[0], 77);
+ EXPECT_EQ(typed_span[1], 77);
+
+ array.reinitialize(10);
+ EXPECT_EQ(array.size(), 10);
+ span = array.as_mutable_span();
+ EXPECT_EQ(span.size(), 10);
+
+ typed_span = span.typed<int32_t>();
+ EXPECT_FALSE(typed_span.data() == nullptr);
+
+ array.reinitialize(0);
+ EXPECT_EQ(array.size(), 0);
+}
+
+TEST(generic_array, InContainer)
+{
+ blender::Array<GArray<>> arrays;
+ for (GArray<> &array : arrays) {
+ array = GArray(CPPType::get<int32_t>(), (int64_t)5);
+ array.as_mutable_span().typed<int32_t>().fill(55);
+ }
+ for (GArray<> &array : arrays) {
+ EXPECT_EQ(array.as_span().typed<int32_t>()[3], 55);
+ }
+}
+
+} // namespace blender::fn::tests