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
path: root/tests
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2020-07-15 15:18:30 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-07-15 15:23:35 +0300
commite8f8c13d4b76ba587ef7cf33370b286d4fbd36bc (patch)
tree371472ae220ad8740b310aaa8f4c5746448302c5 /tests
parent0c062a9e082130212447c2b67e8e16b8a2e622d1 (diff)
parent44bb73e765a6f79bc14a46449368f83e572d8bad (diff)
PointCloud: Initial rendering support for Workbenchtmp-pointcloud-render
Also includes outline overlays. Removes the temp overlay drawing We make the geometry follow camera like billboards this uses less geometry. Currently we use half octahedron for now. Goal would be to use icospheres. This patch also optimize the case when pointcloud has uniform radius. However we should premultiply the radius prop by the default radius beforehand to avoid a multiplication on CPU. Differential Revision: https://developer.blender.org/D8301
Diffstat (limited to 'tests')
-rw-r--r--tests/gtests/blenlib/BLI_array_test.cc13
-rw-r--r--tests/gtests/blenlib/BLI_disjoint_set_test.cc36
-rw-r--r--tests/gtests/blenlib/BLI_ghash_performance_test.cc36
-rw-r--r--tests/gtests/blenlib/BLI_index_mask_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_index_range_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_linear_allocator_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_map_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_math_bits_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_memory_utils_test.cc159
-rw-r--r--tests/gtests/blenlib/BLI_set_test.cc47
-rw-r--r--tests/gtests/blenlib/BLI_span_test.cc12
-rw-r--r--tests/gtests/blenlib/BLI_stack_cxx_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_string_ref_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_vector_set_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_vector_test.cc27
-rw-r--r--tests/gtests/blenlib/CMakeLists.txt2
-rw-r--r--tests/gtests/functions/FN_array_spans_test.cc16
-rw-r--r--tests/gtests/functions/FN_attributes_ref_test.cc16
-rw-r--r--tests/gtests/functions/FN_cpp_type_test.cc46
-rw-r--r--tests/gtests/functions/FN_generic_vector_array_test.cc16
-rw-r--r--tests/gtests/functions/FN_multi_function_network_test.cc16
-rw-r--r--tests/gtests/functions/FN_multi_function_test.cc84
-rw-r--r--tests/gtests/functions/FN_spans_test.cc16
-rw-r--r--tests/gtests/usd/CMakeLists.txt1
-rw-r--r--tests/gtests/usd/object_identifier_test.cc236
-rw-r--r--tests/python/alembic_tests.py57
26 files changed, 701 insertions, 151 deletions
diff --git a/tests/gtests/blenlib/BLI_array_test.cc b/tests/gtests/blenlib/BLI_array_test.cc
index 9c77c69e296..3ff5baf1d94 100644
--- a/tests/gtests/blenlib/BLI_array_test.cc
+++ b/tests/gtests/blenlib/BLI_array_test.cc
@@ -1,3 +1,5 @@
+/* Apache License, Version 2.0 */
+
#include "BLI_array.hh"
#include "BLI_strict_flags.h"
#include "testing/testing.h"
@@ -138,23 +140,22 @@ TEST(array, NoInitializationSizeConstructor)
{
using MyArray = Array<ConstructibleType>;
- AlignedBuffer<sizeof(MyArray), alignof(MyArray)> buffer;
- char *buffer_ptr = (char *)buffer.ptr();
- memset(buffer_ptr, 100, sizeof(MyArray));
+ TypedBuffer<MyArray> buffer;
+ memset(buffer, 100, sizeof(MyArray));
/* Doing this to avoid some compiler optimization. */
for (uint i : IndexRange(sizeof(MyArray))) {
- EXPECT_EQ(buffer_ptr[i], 100);
+ EXPECT_EQ(((char *)buffer.ptr())[i], 100);
}
{
- MyArray &array = *new (buffer.ptr()) MyArray(1, NoInitialization());
+ MyArray &array = *new (buffer) MyArray(1, NoInitialization());
EXPECT_EQ(array[0].value, 100);
array.clear_without_destruct();
array.~Array();
}
{
- MyArray &array = *new (buffer.ptr()) MyArray(1);
+ MyArray &array = *new (buffer) MyArray(1);
EXPECT_EQ(array[0].value, 42);
array.~Array();
}
diff --git a/tests/gtests/blenlib/BLI_disjoint_set_test.cc b/tests/gtests/blenlib/BLI_disjoint_set_test.cc
new file mode 100644
index 00000000000..30503954c62
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_disjoint_set_test.cc
@@ -0,0 +1,36 @@
+/* Apache License, Version 2.0 */
+
+#include "BLI_disjoint_set.hh"
+#include "BLI_strict_flags.h"
+
+#include "testing/testing.h"
+
+namespace blender {
+
+TEST(disjoint_set, Test)
+{
+ DisjointSet disjoint_set(6);
+ EXPECT_FALSE(disjoint_set.in_same_set(1, 2));
+ EXPECT_FALSE(disjoint_set.in_same_set(5, 3));
+ EXPECT_TRUE(disjoint_set.in_same_set(2, 2));
+ EXPECT_EQ(disjoint_set.find_root(3), 3u);
+
+ disjoint_set.join(1, 2);
+
+ EXPECT_TRUE(disjoint_set.in_same_set(1, 2));
+ EXPECT_FALSE(disjoint_set.in_same_set(0, 1));
+
+ disjoint_set.join(3, 4);
+
+ EXPECT_FALSE(disjoint_set.in_same_set(2, 3));
+ EXPECT_TRUE(disjoint_set.in_same_set(3, 4));
+
+ disjoint_set.join(1, 4);
+
+ EXPECT_TRUE(disjoint_set.in_same_set(1, 4));
+ EXPECT_TRUE(disjoint_set.in_same_set(1, 3));
+ EXPECT_TRUE(disjoint_set.in_same_set(2, 4));
+ EXPECT_FALSE(disjoint_set.in_same_set(0, 4));
+}
+
+} // namespace blender
diff --git a/tests/gtests/blenlib/BLI_ghash_performance_test.cc b/tests/gtests/blenlib/BLI_ghash_performance_test.cc
index 1002ff7d2df..201598869e8 100644
--- a/tests/gtests/blenlib/BLI_ghash_performance_test.cc
+++ b/tests/gtests/blenlib/BLI_ghash_performance_test.cc
@@ -535,42 +535,6 @@ static void int2_ghash_tests(GHash *ghash, const char *id, const unsigned int nb
printf("========== ENDED %s ==========\n\n", id);
}
-TEST(ghash, Int2GHash2000)
-{
- GHash *ghash = BLI_ghash_new(
- BLI_ghashutil_uinthash_v2_p, BLI_ghashutil_uinthash_v2_cmp, __func__);
-
- int2_ghash_tests(ghash, "Int2GHash - GHash - 2000", 2000);
-}
-
-#ifdef GHASH_RUN_BIG
-TEST(ghash, Int2GHash20000000)
-{
- GHash *ghash = BLI_ghash_new(
- BLI_ghashutil_uinthash_v2_p, BLI_ghashutil_uinthash_v2_cmp, __func__);
-
- int2_ghash_tests(ghash, "Int2GHash - GHash - 20000000", 20000000);
-}
-#endif
-
-TEST(ghash, Int2Murmur2a2000)
-{
- GHash *ghash = BLI_ghash_new(
- BLI_ghashutil_uinthash_v2_p_murmur, BLI_ghashutil_uinthash_v2_cmp, __func__);
-
- int2_ghash_tests(ghash, "Int2GHash - Murmur - 2000", 2000);
-}
-
-#ifdef GHASH_RUN_BIG
-TEST(ghash, Int2Murmur2a20000000)
-{
- GHash *ghash = BLI_ghash_new(
- BLI_ghashutil_uinthash_v2_p_murmur, BLI_ghashutil_uinthash_v2_cmp, __func__);
-
- int2_ghash_tests(ghash, "Int2GHash - Murmur - 20000000", 20000000);
-}
-#endif
-
/* MultiSmall: create and manipulate a lot of very small ghashes
* (90% < 10 items, 9% < 100 items, 1% < 1000 items). */
diff --git a/tests/gtests/blenlib/BLI_index_mask_test.cc b/tests/gtests/blenlib/BLI_index_mask_test.cc
index 50b32be6364..6d9b7c70ab2 100644
--- a/tests/gtests/blenlib/BLI_index_mask_test.cc
+++ b/tests/gtests/blenlib/BLI_index_mask_test.cc
@@ -1,3 +1,5 @@
+/* Apache License, Version 2.0 */
+
#include "BLI_index_mask.hh"
#include "testing/testing.h"
diff --git a/tests/gtests/blenlib/BLI_index_range_test.cc b/tests/gtests/blenlib/BLI_index_range_test.cc
index e484da5ef42..0f4fb7ef03b 100644
--- a/tests/gtests/blenlib/BLI_index_range_test.cc
+++ b/tests/gtests/blenlib/BLI_index_range_test.cc
@@ -1,3 +1,5 @@
+/* Apache License, Version 2.0 */
+
#include "BLI_index_range.hh"
#include "BLI_strict_flags.h"
#include "BLI_vector.hh"
diff --git a/tests/gtests/blenlib/BLI_linear_allocator_test.cc b/tests/gtests/blenlib/BLI_linear_allocator_test.cc
index bbea4c1239f..7ef9d433a4d 100644
--- a/tests/gtests/blenlib/BLI_linear_allocator_test.cc
+++ b/tests/gtests/blenlib/BLI_linear_allocator_test.cc
@@ -1,3 +1,5 @@
+/* Apache License, Version 2.0 */
+
#include "BLI_linear_allocator.hh"
#include "BLI_strict_flags.h"
#include "testing/testing.h"
diff --git a/tests/gtests/blenlib/BLI_map_test.cc b/tests/gtests/blenlib/BLI_map_test.cc
index 3b72795d36f..4fb97c40e86 100644
--- a/tests/gtests/blenlib/BLI_map_test.cc
+++ b/tests/gtests/blenlib/BLI_map_test.cc
@@ -1,3 +1,5 @@
+/* Apache License, Version 2.0 */
+
#include "BLI_map.hh"
#include "BLI_rand.h"
#include "BLI_set.hh"
diff --git a/tests/gtests/blenlib/BLI_math_bits_test.cc b/tests/gtests/blenlib/BLI_math_bits_test.cc
index 9baa471cf48..4fa4809beed 100644
--- a/tests/gtests/blenlib/BLI_math_bits_test.cc
+++ b/tests/gtests/blenlib/BLI_math_bits_test.cc
@@ -1,3 +1,5 @@
+/* Apache License, Version 2.0 */
+
#include "BLI_math_bits.h"
#include "testing/testing.h"
#include <iostream>
diff --git a/tests/gtests/blenlib/BLI_memory_utils_test.cc b/tests/gtests/blenlib/BLI_memory_utils_test.cc
new file mode 100644
index 00000000000..b99db5c5eca
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_memory_utils_test.cc
@@ -0,0 +1,159 @@
+/* Apache License, Version 2.0 */
+
+#include "BLI_float3.hh"
+#include "BLI_memory_utils.hh"
+#include "BLI_strict_flags.h"
+#include "testing/testing.h"
+
+namespace blender {
+
+struct MyValue {
+ static inline int alive = 0;
+
+ MyValue()
+ {
+ if (alive == 15) {
+ throw std::exception();
+ }
+
+ alive++;
+ }
+
+ MyValue(const MyValue &other)
+ {
+ if (alive == 15) {
+ throw std::exception();
+ }
+
+ alive++;
+ }
+
+ ~MyValue()
+ {
+ alive--;
+ }
+};
+
+TEST(memory_utils, DefaultConstructN_ActuallyCallsConstructor)
+{
+ constexpr int amount = 10;
+ TypedBuffer<MyValue, amount> buffer;
+
+ EXPECT_EQ(MyValue::alive, 0);
+ default_construct_n(buffer.ptr(), amount);
+ EXPECT_EQ(MyValue::alive, amount);
+ destruct_n(buffer.ptr(), amount);
+ EXPECT_EQ(MyValue::alive, 0);
+}
+
+TEST(memory_utils, DefaultConstructN_StrongExceptionSafety)
+{
+ constexpr int amount = 20;
+ TypedBuffer<MyValue, amount> buffer;
+
+ EXPECT_EQ(MyValue::alive, 0);
+ EXPECT_THROW(default_construct_n(buffer.ptr(), amount), std::exception);
+ EXPECT_EQ(MyValue::alive, 0);
+}
+
+TEST(memory_utils, UninitializedCopyN_ActuallyCopies)
+{
+ constexpr int amount = 5;
+ TypedBuffer<MyValue, amount> buffer1;
+ TypedBuffer<MyValue, amount> buffer2;
+
+ EXPECT_EQ(MyValue::alive, 0);
+ default_construct_n(buffer1.ptr(), amount);
+ EXPECT_EQ(MyValue::alive, amount);
+ uninitialized_copy_n(buffer1.ptr(), amount, buffer2.ptr());
+ EXPECT_EQ(MyValue::alive, 2 * amount);
+ destruct_n(buffer1.ptr(), amount);
+ EXPECT_EQ(MyValue::alive, amount);
+ destruct_n(buffer2.ptr(), amount);
+ EXPECT_EQ(MyValue::alive, 0);
+}
+
+TEST(memory_utils, UninitializedCopyN_StrongExceptionSafety)
+{
+ constexpr int amount = 10;
+ TypedBuffer<MyValue, amount> buffer1;
+ TypedBuffer<MyValue, amount> buffer2;
+
+ EXPECT_EQ(MyValue::alive, 0);
+ default_construct_n(buffer1.ptr(), amount);
+ EXPECT_EQ(MyValue::alive, amount);
+ EXPECT_THROW(uninitialized_copy_n(buffer1.ptr(), amount, buffer2.ptr()), std::exception);
+ EXPECT_EQ(MyValue::alive, amount);
+ destruct_n(buffer1.ptr(), amount);
+ EXPECT_EQ(MyValue::alive, 0);
+}
+
+TEST(memory_utils, UninitializedFillN_ActuallyCopies)
+{
+ constexpr int amount = 10;
+ TypedBuffer<MyValue, amount> buffer;
+
+ EXPECT_EQ(MyValue::alive, 0);
+ {
+ MyValue value;
+ EXPECT_EQ(MyValue::alive, 1);
+ uninitialized_fill_n(buffer.ptr(), amount, value);
+ EXPECT_EQ(MyValue::alive, 1 + amount);
+ destruct_n(buffer.ptr(), amount);
+ EXPECT_EQ(MyValue::alive, 1);
+ }
+ EXPECT_EQ(MyValue::alive, 0);
+}
+
+TEST(memory_utils, UninitializedFillN_StrongExceptionSafety)
+{
+ constexpr int amount = 20;
+ TypedBuffer<MyValue, amount> buffer;
+
+ EXPECT_EQ(MyValue::alive, 0);
+ {
+ MyValue value;
+ EXPECT_EQ(MyValue::alive, 1);
+ EXPECT_THROW(uninitialized_fill_n(buffer.ptr(), amount, value), std::exception);
+ EXPECT_EQ(MyValue::alive, 1);
+ }
+ EXPECT_EQ(MyValue::alive, 0);
+}
+
+class TestBaseClass {
+ virtual void mymethod(){};
+};
+
+class TestChildClass : public TestBaseClass {
+ void mymethod() override
+ {
+ }
+};
+
+static_assert(is_convertible_pointer_v<int *, int *>);
+static_assert(is_convertible_pointer_v<int *, const int *>);
+static_assert(is_convertible_pointer_v<int *, int *const>);
+static_assert(is_convertible_pointer_v<int *, const int *const>);
+static_assert(!is_convertible_pointer_v<const int *, int *>);
+static_assert(!is_convertible_pointer_v<int, int *>);
+static_assert(!is_convertible_pointer_v<int *, int>);
+static_assert(is_convertible_pointer_v<TestBaseClass *, const TestBaseClass *>);
+static_assert(!is_convertible_pointer_v<const TestBaseClass *, TestBaseClass *>);
+static_assert(is_convertible_pointer_v<TestChildClass *, TestBaseClass *>);
+static_assert(!is_convertible_pointer_v<TestBaseClass *, TestChildClass *>);
+static_assert(is_convertible_pointer_v<const TestChildClass *, const TestBaseClass *>);
+static_assert(!is_convertible_pointer_v<TestBaseClass, const TestChildClass *>);
+static_assert(!is_convertible_pointer_v<float3, float *>);
+static_assert(!is_convertible_pointer_v<float *, float3>);
+static_assert(!is_convertible_pointer_v<int **, int *>);
+static_assert(!is_convertible_pointer_v<int *, int **>);
+static_assert(is_convertible_pointer_v<int **, int **>);
+static_assert(is_convertible_pointer_v<const int **, const int **>);
+static_assert(!is_convertible_pointer_v<const int **, int **>);
+static_assert(!is_convertible_pointer_v<int *const *, int **>);
+static_assert(!is_convertible_pointer_v<int *const *const, int **>);
+static_assert(is_convertible_pointer_v<int **, int **const>);
+static_assert(is_convertible_pointer_v<int **, int *const *>);
+static_assert(is_convertible_pointer_v<int **, int const *const *>);
+
+} // namespace blender
diff --git a/tests/gtests/blenlib/BLI_set_test.cc b/tests/gtests/blenlib/BLI_set_test.cc
index ac78eb786df..189f0c1b134 100644
--- a/tests/gtests/blenlib/BLI_set_test.cc
+++ b/tests/gtests/blenlib/BLI_set_test.cc
@@ -1,3 +1,5 @@
+/* Apache License, Version 2.0 */
+
#include <set>
#include <unordered_set>
@@ -403,6 +405,51 @@ TEST(set, IntrusiveIntKey)
EXPECT_TRUE(set.remove(4));
}
+struct MyKeyType {
+ uint32_t key;
+ int32_t attached_data;
+
+ uint32_t hash() const
+ {
+ return key;
+ }
+
+ friend bool operator==(const MyKeyType &a, const MyKeyType &b)
+ {
+ return a.key == b.key;
+ }
+};
+
+TEST(set, LookupKey)
+{
+ Set<MyKeyType> set;
+ set.add({1, 10});
+ set.add({2, 20});
+ EXPECT_EQ(set.lookup_key({1, 30}).attached_data, 10);
+ EXPECT_EQ(set.lookup_key({2, 0}).attached_data, 20);
+}
+
+TEST(set, LookupKeyDefault)
+{
+ Set<MyKeyType> set;
+ set.add({1, 10});
+ set.add({2, 20});
+
+ MyKeyType fallback{5, 50};
+ EXPECT_EQ(set.lookup_key_default({1, 66}, fallback).attached_data, 10);
+ EXPECT_EQ(set.lookup_key_default({4, 40}, fallback).attached_data, 50);
+}
+
+TEST(set, LookupKeyPtr)
+{
+ Set<MyKeyType> set;
+ set.add({1, 10});
+ set.add({2, 20});
+ EXPECT_EQ(set.lookup_key_ptr({1, 50})->attached_data, 10);
+ EXPECT_EQ(set.lookup_key_ptr({2, 50})->attached_data, 20);
+ EXPECT_EQ(set.lookup_key_ptr({3, 50}), nullptr);
+}
+
/**
* Set this to 1 to activate the benchmark. It is disabled by default, because it prints a lot.
*/
diff --git a/tests/gtests/blenlib/BLI_span_test.cc b/tests/gtests/blenlib/BLI_span_test.cc
index 375cb694b7b..ccc63fd80eb 100644
--- a/tests/gtests/blenlib/BLI_span_test.cc
+++ b/tests/gtests/blenlib/BLI_span_test.cc
@@ -1,3 +1,5 @@
+/* Apache License, Version 2.0 */
+
#include "BLI_span.hh"
#include "BLI_strict_flags.h"
#include "BLI_vector.hh"
@@ -283,4 +285,14 @@ TEST(span, CastLargerSize)
EXPECT_EQ(new_a_span.size(), 2u);
}
+TEST(span, VoidPointerSpan)
+{
+ int a;
+ float b;
+ double c;
+
+ auto func1 = [](Span<void *> span) { EXPECT_EQ(span.size(), 3u); };
+ func1({&a, &b, &c});
+}
+
} // namespace blender
diff --git a/tests/gtests/blenlib/BLI_stack_cxx_test.cc b/tests/gtests/blenlib/BLI_stack_cxx_test.cc
index b59ac1f7ec1..c8433b4fd87 100644
--- a/tests/gtests/blenlib/BLI_stack_cxx_test.cc
+++ b/tests/gtests/blenlib/BLI_stack_cxx_test.cc
@@ -1,3 +1,5 @@
+/* Apache License, Version 2.0 */
+
#include "BLI_stack.hh"
#include "BLI_strict_flags.h"
#include "BLI_vector.hh"
diff --git a/tests/gtests/blenlib/BLI_string_ref_test.cc b/tests/gtests/blenlib/BLI_string_ref_test.cc
index 1f84b8577b4..0d1880229c7 100644
--- a/tests/gtests/blenlib/BLI_string_ref_test.cc
+++ b/tests/gtests/blenlib/BLI_string_ref_test.cc
@@ -1,3 +1,5 @@
+/* Apache License, Version 2.0 */
+
#include "BLI_strict_flags.h"
#include "BLI_string_ref.hh"
#include "BLI_vector.hh"
diff --git a/tests/gtests/blenlib/BLI_vector_set_test.cc b/tests/gtests/blenlib/BLI_vector_set_test.cc
index 982081f4b4c..3c3b4d55959 100644
--- a/tests/gtests/blenlib/BLI_vector_set_test.cc
+++ b/tests/gtests/blenlib/BLI_vector_set_test.cc
@@ -1,3 +1,5 @@
+/* Apache License, Version 2.0 */
+
#include "BLI_strict_flags.h"
#include "BLI_vector_set.hh"
#include "testing/testing.h"
diff --git a/tests/gtests/blenlib/BLI_vector_test.cc b/tests/gtests/blenlib/BLI_vector_test.cc
index ea4711ca015..25435739a43 100644
--- a/tests/gtests/blenlib/BLI_vector_test.cc
+++ b/tests/gtests/blenlib/BLI_vector_test.cc
@@ -1,3 +1,5 @@
+/* Apache License, Version 2.0 */
+
#include "BLI_strict_flags.h"
#include "BLI_vector.hh"
#include "testing/testing.h"
@@ -57,6 +59,18 @@ TEST(vector, InitializerListConstructor)
EXPECT_EQ(vec[3], 6);
}
+TEST(vector, ConvertingConstructor)
+{
+ std::array<float, 5> values = {5.4f, 7.3f, -8.1f, 5.0f, 0.0f};
+ Vector<int> vec = values;
+ EXPECT_EQ(vec.size(), 5u);
+ EXPECT_EQ(vec[0], 5);
+ EXPECT_EQ(vec[1], 7);
+ EXPECT_EQ(vec[2], -8);
+ EXPECT_EQ(vec[3], 5);
+ EXPECT_EQ(vec[4], 0);
+}
+
struct TestListValue {
TestListValue *next, *prev;
int value;
@@ -499,7 +513,7 @@ class TypeConstructMock {
{
}
- TypeConstructMock(TypeConstructMock &&other) : move_constructed(true)
+ TypeConstructMock(TypeConstructMock &&other) noexcept : move_constructed(true)
{
}
@@ -513,7 +527,7 @@ class TypeConstructMock {
return *this;
}
- TypeConstructMock &operator=(TypeConstructMock &&other)
+ TypeConstructMock &operator=(TypeConstructMock &&other) noexcept
{
if (this == &other) {
return *this;
@@ -637,4 +651,13 @@ TEST(vector, OveralignedValues)
}
}
+TEST(vector, ConstructVoidPointerVector)
+{
+ int a;
+ float b;
+ double c;
+ Vector<void *> vec = {&a, &b, &c};
+ EXPECT_EQ(vec.size(), 3u);
+}
+
} // namespace blender
diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt
index ba493b22b42..496fe44234e 100644
--- a/tests/gtests/blenlib/CMakeLists.txt
+++ b/tests/gtests/blenlib/CMakeLists.txt
@@ -43,6 +43,7 @@ BLENDER_TEST(BLI_array "bf_blenlib")
BLENDER_TEST(BLI_array_store "bf_blenlib")
BLENDER_TEST(BLI_array_utils "bf_blenlib")
BLENDER_TEST(BLI_delaunay_2d "bf_blenlib")
+BLENDER_TEST(BLI_disjoint_set "bf_blenlib")
BLENDER_TEST(BLI_edgehash "bf_blenlib")
BLENDER_TEST(BLI_expr_pylike_eval "bf_blenlib")
BLENDER_TEST(BLI_ghash "bf_blenlib")
@@ -63,6 +64,7 @@ BLENDER_TEST(BLI_math_geom "bf_blenlib")
BLENDER_TEST(BLI_math_matrix "bf_blenlib")
BLENDER_TEST(BLI_math_vector "bf_blenlib")
BLENDER_TEST(BLI_memiter "bf_blenlib")
+BLENDER_TEST(BLI_memory_utils "bf_blenlib")
BLENDER_TEST(BLI_path_util "${BLI_path_util_extra_libs}")
BLENDER_TEST(BLI_polyfill_2d "bf_blenlib")
BLENDER_TEST(BLI_set "bf_blenlib")
diff --git a/tests/gtests/functions/FN_array_spans_test.cc b/tests/gtests/functions/FN_array_spans_test.cc
index fa483ebf0f8..988d48fa452 100644
--- a/tests/gtests/functions/FN_array_spans_test.cc
+++ b/tests/gtests/functions/FN_array_spans_test.cc
@@ -1,18 +1,4 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
+/* Apache License, Version 2.0 */
#include "testing/testing.h"
diff --git a/tests/gtests/functions/FN_attributes_ref_test.cc b/tests/gtests/functions/FN_attributes_ref_test.cc
index eda4592d214..1c05bb930db 100644
--- a/tests/gtests/functions/FN_attributes_ref_test.cc
+++ b/tests/gtests/functions/FN_attributes_ref_test.cc
@@ -1,18 +1,4 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
+/* Apache License, Version 2.0 */
#include "BLI_float3.hh"
#include "FN_attributes_ref.hh"
diff --git a/tests/gtests/functions/FN_cpp_type_test.cc b/tests/gtests/functions/FN_cpp_type_test.cc
index f6ae0877ed1..da5ce3416ce 100644
--- a/tests/gtests/functions/FN_cpp_type_test.cc
+++ b/tests/gtests/functions/FN_cpp_type_test.cc
@@ -1,22 +1,9 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
+/* Apache License, Version 2.0 */
#include "testing/testing.h"
#include "FN_cpp_type.hh"
+#include "FN_cpp_types.hh"
namespace blender::fn {
@@ -50,7 +37,7 @@ struct TestType {
other.value = copy_constructed_from_value;
}
- TestType(TestType &&other)
+ TestType(TestType &&other) noexcept
{
value = move_constructed_value;
other.value = move_constructed_from_value;
@@ -63,12 +50,28 @@ struct TestType {
return *this;
}
- TestType &operator=(TestType &&other)
+ TestType &operator=(TestType &&other) noexcept
{
value = move_assigned_value;
other.value = move_assigned_from_value;
return *this;
}
+
+ friend std::ostream &operator<<(std::ostream &stream, const TestType &value)
+ {
+ stream << value.value;
+ return stream;
+ }
+
+ friend bool operator==(const TestType &a, const TestType &b)
+ {
+ return false;
+ }
+
+ uint32_t hash() const
+ {
+ return 0;
+ }
};
MAKE_CPP_TYPE(TestType, TestType)
@@ -305,4 +308,13 @@ TEST(cpp_type, FillUninitialized)
EXPECT_EQ(buffer2[9], 0);
}
+TEST(cpp_type, DebugPrint)
+{
+ int value = 42;
+ std::stringstream ss;
+ CPPType_int32.debug_print((void *)&value, ss);
+ std::string text = ss.str();
+ EXPECT_EQ(text, "42");
+}
+
} // namespace blender::fn
diff --git a/tests/gtests/functions/FN_generic_vector_array_test.cc b/tests/gtests/functions/FN_generic_vector_array_test.cc
index 3308913a72e..7ce7b543218 100644
--- a/tests/gtests/functions/FN_generic_vector_array_test.cc
+++ b/tests/gtests/functions/FN_generic_vector_array_test.cc
@@ -1,18 +1,4 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
+/* Apache License, Version 2.0 */
#include "FN_cpp_types.hh"
#include "FN_generic_vector_array.hh"
diff --git a/tests/gtests/functions/FN_multi_function_network_test.cc b/tests/gtests/functions/FN_multi_function_network_test.cc
index 07068aecdb6..5507733c8be 100644
--- a/tests/gtests/functions/FN_multi_function_network_test.cc
+++ b/tests/gtests/functions/FN_multi_function_network_test.cc
@@ -1,18 +1,4 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
+/* Apache License, Version 2.0 */
#include "testing/testing.h"
diff --git a/tests/gtests/functions/FN_multi_function_test.cc b/tests/gtests/functions/FN_multi_function_test.cc
index 07dffeeb948..8cc8f91a300 100644
--- a/tests/gtests/functions/FN_multi_function_test.cc
+++ b/tests/gtests/functions/FN_multi_function_test.cc
@@ -1,18 +1,4 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
+/* Apache License, Version 2.0 */
#include "testing/testing.h"
@@ -329,4 +315,72 @@ TEST(multi_function, CustomMF_Constant)
EXPECT_EQ(outputs[3], 42);
}
+TEST(multi_function, CustomMF_GenericConstant)
+{
+ int value = 42;
+ CustomMF_GenericConstant fn{CPPType_int32, (const void *)&value};
+ EXPECT_EQ(fn.param_name(0), "42");
+
+ Array<int> outputs(4, 0);
+
+ MFParamsBuilder params(fn, outputs.size());
+ params.add_uninitialized_single_output(outputs.as_mutable_span());
+
+ MFContextBuilder context;
+
+ fn.call({0, 1, 2}, params, context);
+
+ EXPECT_EQ(outputs[0], 42);
+ EXPECT_EQ(outputs[1], 42);
+ EXPECT_EQ(outputs[2], 42);
+ EXPECT_EQ(outputs[3], 0);
+}
+
+TEST(multi_function, CustomMF_GenericConstantArray)
+{
+ std::array<int, 4> values = {3, 4, 5, 6};
+ CustomMF_GenericConstantArray fn{GSpan(Span(values))};
+ EXPECT_EQ(fn.param_name(0), "[3, 4, 5, 6, ]");
+
+ GVectorArray g_vector_array{CPPType_int32, 4};
+ GVectorArrayRef<int> vector_array = g_vector_array;
+
+ MFParamsBuilder params(fn, g_vector_array.size());
+ params.add_vector_output(g_vector_array);
+
+ MFContextBuilder context;
+
+ fn.call({1, 2, 3}, params, context);
+
+ EXPECT_EQ(vector_array[0].size(), 0);
+ EXPECT_EQ(vector_array[1].size(), 4);
+ EXPECT_EQ(vector_array[2].size(), 4);
+ EXPECT_EQ(vector_array[3].size(), 4);
+ for (uint i = 1; i < 4; i++) {
+ EXPECT_EQ(vector_array[i][0], 3);
+ EXPECT_EQ(vector_array[i][1], 4);
+ EXPECT_EQ(vector_array[i][2], 5);
+ EXPECT_EQ(vector_array[i][3], 6);
+ }
+}
+
+TEST(multi_function, CustomMF_Convert)
+{
+ CustomMF_Convert<float, int> fn;
+
+ Array<float> inputs = {5.4f, 7.1f, 9.0f};
+ Array<int> outputs(inputs.size(), 0);
+
+ MFParamsBuilder params(fn, inputs.size());
+ params.add_readonly_single_input(inputs.as_span());
+ params.add_uninitialized_single_output(outputs.as_mutable_span());
+
+ MFContextBuilder context;
+ fn.call({0, 2}, params, context);
+
+ EXPECT_EQ(outputs[0], 5);
+ EXPECT_EQ(outputs[1], 0);
+ EXPECT_EQ(outputs[2], 9);
+}
+
} // namespace blender::fn
diff --git a/tests/gtests/functions/FN_spans_test.cc b/tests/gtests/functions/FN_spans_test.cc
index 43deb80ed23..8968d49c082 100644
--- a/tests/gtests/functions/FN_spans_test.cc
+++ b/tests/gtests/functions/FN_spans_test.cc
@@ -1,18 +1,4 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
+/* Apache License, Version 2.0 */
#include "testing/testing.h"
diff --git a/tests/gtests/usd/CMakeLists.txt b/tests/gtests/usd/CMakeLists.txt
index d2bfe5e1306..0caa2fac155 100644
--- a/tests/gtests/usd/CMakeLists.txt
+++ b/tests/gtests/usd/CMakeLists.txt
@@ -67,6 +67,7 @@ get_property(BLENDER_SORTED_LIBS GLOBAL PROPERTY BLENDER_SORTED_LIBS_PROP)
set(SRC
abstract_hierarchy_iterator_test.cc
hierarchy_context_order_test.cc
+ object_identifier_test.cc
)
# TODO(Sybren): re-enable this unit test.
diff --git a/tests/gtests/usd/object_identifier_test.cc b/tests/gtests/usd/object_identifier_test.cc
new file mode 100644
index 00000000000..810d4470260
--- /dev/null
+++ b/tests/gtests/usd/object_identifier_test.cc
@@ -0,0 +1,236 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2019 Blender Foundation.
+ * All rights reserved.
+ */
+#include "IO_abstract_hierarchy_iterator.h"
+
+#include "testing/testing.h"
+
+#include "BLI_utildefines.h"
+
+#include <climits>
+
+namespace blender {
+namespace io {
+
+namespace {
+
+/* Return object pointer for use in tests. This makes it possible to reliably test for
+ * order/equality functions while using hard-coded values for simplicity. */
+Object *fake_pointer(int value)
+{
+ return static_cast<Object *>(POINTER_FROM_INT(value));
+}
+
+/* PersistentID subclass for use in tests, making it easier to construct test values. */
+class TestPersistentID : public PersistentID {
+ public:
+ TestPersistentID(int value0,
+ int value1,
+ int value2,
+ int value3,
+ int value4,
+ int value5,
+ int value6,
+ int value7)
+ {
+ persistent_id_[0] = value0;
+ persistent_id_[1] = value1;
+ persistent_id_[2] = value2;
+ persistent_id_[3] = value3;
+ persistent_id_[4] = value4;
+ persistent_id_[5] = value5;
+ persistent_id_[6] = value6;
+ persistent_id_[7] = value7;
+ }
+ TestPersistentID(int value0, int value1, int value2)
+ : TestPersistentID(value0, value1, value2, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX)
+ {
+ }
+ TestPersistentID(int value0, int value1) : TestPersistentID(value0, value1, INT_MAX)
+ {
+ }
+ explicit TestPersistentID(int value0) : TestPersistentID(value0, INT_MAX)
+ {
+ }
+};
+
+/* ObjectIdentifier subclass for use in tests, making it easier to construct test values. */
+class TestObjectIdentifier : public ObjectIdentifier {
+ public:
+ TestObjectIdentifier(Object *object, Object *duplicated_by, const PersistentID &persistent_id)
+ : ObjectIdentifier(object, duplicated_by, persistent_id)
+ {
+ }
+};
+
+} // namespace
+
+class ObjectIdentifierOrderTest : public testing::Test {
+};
+
+TEST_F(ObjectIdentifierOrderTest, graph_root)
+{
+ ObjectIdentifier id_root_1 = ObjectIdentifier::for_graph_root();
+ ObjectIdentifier id_root_2 = ObjectIdentifier::for_graph_root();
+ EXPECT_TRUE(id_root_1 == id_root_2);
+ EXPECT_FALSE(id_root_1 < id_root_2);
+ EXPECT_FALSE(id_root_2 < id_root_1);
+
+ ObjectIdentifier id_a = ObjectIdentifier::for_real_object(fake_pointer(1));
+ EXPECT_FALSE(id_root_1 == id_a);
+ EXPECT_TRUE(id_root_1 < id_a);
+ EXPECT_FALSE(id_a < id_root_1);
+
+ ObjectIdentifier id_accidental_root = ObjectIdentifier::for_real_object(nullptr);
+ EXPECT_TRUE(id_root_1 == id_accidental_root);
+ EXPECT_FALSE(id_root_1 < id_accidental_root);
+ EXPECT_FALSE(id_accidental_root < id_root_1);
+}
+
+TEST_F(ObjectIdentifierOrderTest, real_objects)
+{
+ ObjectIdentifier id_a = ObjectIdentifier::for_real_object(fake_pointer(1));
+ ObjectIdentifier id_b = ObjectIdentifier::for_real_object(fake_pointer(2));
+ EXPECT_FALSE(id_a == id_b);
+ EXPECT_TRUE(id_a < id_b);
+}
+
+TEST_F(ObjectIdentifierOrderTest, duplicated_objects)
+{
+ ObjectIdentifier id_real_a = ObjectIdentifier::for_real_object(fake_pointer(1));
+ TestObjectIdentifier id_dupli_a(fake_pointer(1), fake_pointer(2), TestPersistentID(0));
+ TestObjectIdentifier id_dupli_b(fake_pointer(1), fake_pointer(3), TestPersistentID(0));
+ TestObjectIdentifier id_different_dupli_b(fake_pointer(1), fake_pointer(3), TestPersistentID(1));
+
+ EXPECT_FALSE(id_real_a == id_dupli_a);
+ EXPECT_FALSE(id_dupli_a == id_dupli_b);
+ EXPECT_TRUE(id_real_a < id_dupli_a);
+ EXPECT_TRUE(id_real_a < id_dupli_b);
+ EXPECT_TRUE(id_dupli_a < id_dupli_b);
+ EXPECT_TRUE(id_dupli_a < id_different_dupli_b);
+
+ EXPECT_FALSE(id_dupli_b == id_different_dupli_b);
+ EXPECT_FALSE(id_dupli_a == id_different_dupli_b);
+ EXPECT_TRUE(id_dupli_b < id_different_dupli_b);
+ EXPECT_FALSE(id_different_dupli_b < id_dupli_b);
+}
+
+TEST_F(ObjectIdentifierOrderTest, behaviour_as_map_keys)
+{
+ ObjectIdentifier id_root = ObjectIdentifier::for_graph_root();
+ ObjectIdentifier id_another_root = ObjectIdentifier::for_graph_root();
+ ObjectIdentifier id_real_a = ObjectIdentifier::for_real_object(fake_pointer(1));
+ TestObjectIdentifier id_dupli_a(fake_pointer(1), fake_pointer(2), TestPersistentID(0));
+ TestObjectIdentifier id_dupli_b(fake_pointer(1), fake_pointer(3), TestPersistentID(0));
+ AbstractHierarchyIterator::ExportGraph graph;
+
+ /* This inserts the keys with default values. */
+ graph[id_root];
+ graph[id_real_a];
+ graph[id_dupli_a];
+ graph[id_dupli_b];
+ graph[id_another_root];
+
+ EXPECT_EQ(4, graph.size());
+
+ graph.erase(id_another_root);
+ EXPECT_EQ(3, graph.size());
+
+ TestObjectIdentifier id_another_dupli_b(fake_pointer(1), fake_pointer(3), TestPersistentID(0));
+ graph.erase(id_another_dupli_b);
+ EXPECT_EQ(2, graph.size());
+}
+
+TEST_F(ObjectIdentifierOrderTest, map_copy_and_update)
+{
+ ObjectIdentifier id_root = ObjectIdentifier::for_graph_root();
+ ObjectIdentifier id_real_a = ObjectIdentifier::for_real_object(fake_pointer(1));
+ TestObjectIdentifier id_dupli_a(fake_pointer(1), fake_pointer(2), TestPersistentID(0));
+ TestObjectIdentifier id_dupli_b(fake_pointer(1), fake_pointer(3), TestPersistentID(0));
+ TestObjectIdentifier id_dupli_c(fake_pointer(1), fake_pointer(3), TestPersistentID(1));
+ AbstractHierarchyIterator::ExportGraph graph;
+
+ /* This inserts the keys with default values. */
+ graph[id_root];
+ graph[id_real_a];
+ graph[id_dupli_a];
+ graph[id_dupli_b];
+ graph[id_dupli_c];
+ EXPECT_EQ(5, graph.size());
+
+ AbstractHierarchyIterator::ExportGraph graph_copy = graph;
+ EXPECT_EQ(5, graph_copy.size());
+
+ // Updating a value in a copy should not update the original.
+ HierarchyContext ctx1;
+ HierarchyContext ctx2;
+ ctx1.object = fake_pointer(1);
+ ctx2.object = fake_pointer(2);
+
+ graph_copy[id_root].insert(&ctx1);
+ EXPECT_EQ(0, graph[id_root].size());
+
+ // Deleting a key in the copy should not update the original.
+ graph_copy.erase(id_dupli_c);
+ EXPECT_EQ(4, graph_copy.size());
+ EXPECT_EQ(5, graph.size());
+}
+
+class PersistentIDTest : public testing::Test {
+};
+
+TEST_F(PersistentIDTest, is_from_same_instancer)
+{
+ PersistentID child_id_a = TestPersistentID(42, 327);
+ PersistentID child_id_b = TestPersistentID(17, 327);
+ PersistentID child_id_c = TestPersistentID(17);
+
+ EXPECT_TRUE(child_id_a.is_from_same_instancer_as(child_id_b));
+ EXPECT_FALSE(child_id_a.is_from_same_instancer_as(child_id_c));
+}
+
+TEST_F(PersistentIDTest, instancer_id)
+{
+ PersistentID child_id = TestPersistentID(42, 327);
+
+ PersistentID expect_instancer_id = TestPersistentID(327);
+ EXPECT_EQ(expect_instancer_id, child_id.instancer_pid());
+
+ PersistentID empty_id;
+ EXPECT_EQ(empty_id, child_id.instancer_pid().instancer_pid());
+
+ EXPECT_LT(child_id, expect_instancer_id);
+ EXPECT_LT(expect_instancer_id, empty_id);
+}
+
+TEST_F(PersistentIDTest, as_object_name_suffix)
+{
+ EXPECT_EQ("", PersistentID().as_object_name_suffix());
+ EXPECT_EQ("47", TestPersistentID(47).as_object_name_suffix());
+ EXPECT_EQ("327-47", TestPersistentID(47, 327).as_object_name_suffix());
+ EXPECT_EQ("42-327-47", TestPersistentID(47, 327, 42).as_object_name_suffix());
+
+ EXPECT_EQ("7-6-5-4-3-2-1-0", TestPersistentID(0, 1, 2, 3, 4, 5, 6, 7).as_object_name_suffix());
+
+ EXPECT_EQ("0-0-0", TestPersistentID(0, 0, 0).as_object_name_suffix());
+ EXPECT_EQ("0-0", TestPersistentID(0, 0).as_object_name_suffix());
+ EXPECT_EQ("-3--2--1", TestPersistentID(-1, -2, -3).as_object_name_suffix());
+}
+
+} // namespace io
+} // namespace blender
diff --git a/tests/python/alembic_tests.py b/tests/python/alembic_tests.py
index 5f8113729c3..66545dc85c7 100644
--- a/tests/python/alembic_tests.py
+++ b/tests/python/alembic_tests.py
@@ -243,6 +243,63 @@ class DupliGroupExportTest(AbstractAlembicTest):
2.0, 3.0, 0.0, 1.0]
)
+ @with_tempdir
+ def test_multiple_duplicated_hierarchies(self, tempdir: pathlib.Path):
+ abc = tempdir / "multiple-duplicated-hierarchies.abc"
+ script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1)" % abc.as_posix()
+ self.run_blender('multiple-duplicated-hierarchies.blend', script)
+
+ # This is the expected hierarchy:
+ # ABC
+ # `--Triangle
+ # |--Triangle
+ # |--Empty-1
+ # | `--Pole-1-0
+ # | |--Pole
+ # | `--Block-1-1
+ # | `--Block
+ # |--Empty
+ # | `--Pole-0
+ # | |--Pole
+ # | `--Block-1
+ # | `--Block
+ # |--Empty-2
+ # | `--Pole-2-0
+ # | |--Pole
+ # | `--Block-2-1
+ # | `--Block
+ # `--Empty-0
+ # `--Pole-0-0
+ # |--Pole
+ # `--Block-0-1
+ # `--Block
+
+ # Now check the resulting Alembic file.
+ xform = self.abcprop(abc, '/Triangle/Empty-1/Pole-1-0/Block-1-1/.xform')
+ self.assertEqual(1, xform['.inherits'])
+ self.assertAlmostEqualFloatArray(
+ xform['.vals'],
+ [1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 2.0, 0.0, 1.0]
+ )
+
+ # If the property can be gotten, the hierarchy is okay. No need to actually check each xform.
+ self.abcprop(abc, '/Triangle/.xform')
+ self.abcprop(abc, '/Triangle/Empty-1/.xform')
+ self.abcprop(abc, '/Triangle/Empty-1/Pole-1-0/.xform')
+ self.abcprop(abc, '/Triangle/Empty-1/Pole-1-0/Block-1-1/.xform')
+ self.abcprop(abc, '/Triangle/Empty/.xform')
+ self.abcprop(abc, '/Triangle/Empty/Pole-0/.xform')
+ self.abcprop(abc, '/Triangle/Empty/Pole-0/Block-1/.xform')
+ self.abcprop(abc, '/Triangle/Empty-2/.xform')
+ self.abcprop(abc, '/Triangle/Empty-2/Pole-2-0/.xform')
+ self.abcprop(abc, '/Triangle/Empty-2/Pole-2-0/Block-2-1/.xform')
+ self.abcprop(abc, '/Triangle/Empty-0/.xform')
+ self.abcprop(abc, '/Triangle/Empty-0/Pole-0-0/.xform')
+ self.abcprop(abc, '/Triangle/Empty-0/Pole-0-0/Block-0-1/.xform')
+
class CurveExportTest(AbstractAlembicTest):
@with_tempdir