Blender V4.3
BLI_linear_allocator_test.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "testing/testing.h"
6
8#include "BLI_rand.hh"
9
10#include "BLI_strict_flags.h" /* Keep last. */
11
12namespace blender::tests {
13
14static bool is_aligned(void *ptr, uint alignment)
15{
16 BLI_assert(is_power_of_2(int(alignment)));
17 return (POINTER_AS_UINT(ptr) & (alignment - 1)) == 0;
18}
19
20TEST(linear_allocator, AllocationAlignment)
21{
22 LinearAllocator<> allocator;
23
24 EXPECT_TRUE(is_aligned(allocator.allocate(10, 4), 4));
25 EXPECT_TRUE(is_aligned(allocator.allocate(10, 4), 4));
26 EXPECT_TRUE(is_aligned(allocator.allocate(10, 4), 4));
27 EXPECT_TRUE(is_aligned(allocator.allocate(10, 8), 8));
28 EXPECT_TRUE(is_aligned(allocator.allocate(10, 4), 4));
29 EXPECT_TRUE(is_aligned(allocator.allocate(10, 16), 16));
30 EXPECT_TRUE(is_aligned(allocator.allocate(10, 4), 4));
31 EXPECT_TRUE(is_aligned(allocator.allocate(10, 64), 64));
32 EXPECT_TRUE(is_aligned(allocator.allocate(10, 64), 64));
33 EXPECT_TRUE(is_aligned(allocator.allocate(10, 8), 8));
34 EXPECT_TRUE(is_aligned(allocator.allocate(10, 128), 128));
35}
36
37TEST(linear_allocator, PackedAllocation)
38{
39 LinearAllocator<> allocator;
41 allocator.provide_buffer(buffer);
42
43 uintptr_t ptr1 = uintptr_t(allocator.allocate(10, 4)); /* 0 - 10 */
44 uintptr_t ptr2 = uintptr_t(allocator.allocate(10, 4)); /* 12 - 22 */
45 uintptr_t ptr3 = uintptr_t(allocator.allocate(8, 32)); /* 32 - 40 */
46 uintptr_t ptr4 = uintptr_t(allocator.allocate(16, 8)); /* 40 - 56 */
47 uintptr_t ptr5 = uintptr_t(allocator.allocate(1, 8)); /* 56 - 57 */
48 uintptr_t ptr6 = uintptr_t(allocator.allocate(1, 4)); /* 60 - 61 */
49 uintptr_t ptr7 = uintptr_t(allocator.allocate(1, 1)); /* 61 - 62 */
50
51 EXPECT_EQ(ptr2 - ptr1, 12); /* 12 - 0 = 12 */
52 EXPECT_EQ(ptr3 - ptr2, 20); /* 32 - 12 = 20 */
53 EXPECT_EQ(ptr4 - ptr3, 8); /* 40 - 32 = 8 */
54 EXPECT_EQ(ptr5 - ptr4, 16); /* 56 - 40 = 16 */
55 EXPECT_EQ(ptr6 - ptr5, 4); /* 60 - 56 = 4 */
56 EXPECT_EQ(ptr7 - ptr6, 1); /* 61 - 60 = 1 */
57}
58
59TEST(linear_allocator, CopyString)
60{
61 LinearAllocator<> allocator;
63 allocator.provide_buffer(buffer);
64
65 StringRefNull ref1 = allocator.copy_string("Hello");
66 StringRefNull ref2 = allocator.copy_string("World");
67
68 EXPECT_EQ(ref1, "Hello");
69 EXPECT_EQ(ref2, "World");
70 EXPECT_EQ(ref2.data() - ref1.data(), 6);
71}
72
73TEST(linear_allocator, AllocateArray)
74{
75 LinearAllocator<> allocator;
76
77 MutableSpan<int> span = allocator.allocate_array<int>(5);
78 EXPECT_EQ(span.size(), 5);
79}
80
81TEST(linear_allocator, Construct)
82{
83 LinearAllocator<> allocator;
84
85 std::array<int, 5> values = {1, 2, 3, 4, 5};
86 Vector<int> *vector = allocator.construct<Vector<int>>(values).release();
87 EXPECT_EQ(vector->size(), 5);
88 EXPECT_EQ((*vector)[3], 4);
89 vector->~Vector();
90}
91
92TEST(linear_allocator, ConstructElementsAndPointerArray)
93{
94 LinearAllocator<> allocator;
95
96 std::array<int, 7> values = {1, 2, 3, 4, 5, 6, 7};
98 5, values);
99
100 EXPECT_EQ(vectors.size(), 5);
101 EXPECT_EQ(vectors[3]->size(), 7);
102 EXPECT_EQ((*vectors[2])[5], 6);
103
104 for (Vector<int> *vector : vectors) {
105 vector->~Vector();
106 }
107}
108
109TEST(linear_allocator, ConstructArrayCopy)
110{
111 LinearAllocator<> allocator;
112
113 Vector<int> values = {1, 2, 3};
114 MutableSpan<int> span1 = allocator.construct_array_copy(values.as_span());
115 MutableSpan<int> span2 = allocator.construct_array_copy(values.as_span());
116 EXPECT_NE(span1.data(), span2.data());
117 EXPECT_EQ(span1.size(), 3);
118 EXPECT_EQ(span2.size(), 3);
119 EXPECT_EQ(span1[1], 2);
120 EXPECT_EQ(span2[2], 3);
121}
122
123TEST(linear_allocator, AllocateLarge)
124{
125 LinearAllocator<> allocator;
126 void *buffer1 = allocator.allocate(1024 * 1024, 8);
127 void *buffer2 = allocator.allocate(1024 * 1024, 8);
128 EXPECT_NE(buffer1, buffer2);
129}
130
131TEST(linear_allocator, ManyAllocations)
132{
133 LinearAllocator<> allocator;
135 for (int i = 0; i < 1000; i++) {
136 int size = rng.get_int32(10000);
137 int alignment = 1 << rng.get_int32(7);
138 void *buffer = allocator.allocate(size, alignment);
139 EXPECT_NE(buffer, nullptr);
140 }
141}
142
143TEST(linear_allocator, ConstructArray)
144{
145 LinearAllocator<> allocator;
146 MutableSpan<std::string> strings = allocator.construct_array<std::string>(4, "hello");
147 EXPECT_EQ(strings[0], "hello");
148 EXPECT_EQ(strings[1], "hello");
149 EXPECT_EQ(strings[2], "hello");
150 EXPECT_EQ(strings[3], "hello");
151 for (std::string &string : strings) {
152 string.~basic_string();
153 }
154}
155
156TEST(linear_allocator, TransferOwnership)
157{
158 LinearAllocator<> main_allocator;
159 MutableSpan<int> values;
160
161 /* Allocate a large buffer that is likely to be given back to the system when freed. This test
162 * essentially only fails by crashing with a segfault. */
163 const int size = 1'000'000;
164 const int value = 42;
165 const int index = 500'000;
166 {
167 LinearAllocator<> nested_allocator;
168 values = nested_allocator.allocate_array<int>(size);
169 values[index] = value;
170 main_allocator.transfer_ownership_from(nested_allocator);
171 }
172 EXPECT_EQ(values[index], value);
173}
174
175} // namespace blender::tests
#define BLI_assert(a)
Definition BLI_assert.h:50
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
unsigned int uint
#define POINTER_AS_UINT(i)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
destruct_ptr< T > construct(Args &&...args)
void provide_buffer(void *buffer, const int64_t size)
MutableSpan< T > allocate_array(int64_t size)
StringRefNull copy_string(StringRef str)
void * allocate(const int64_t size, const int64_t alignment)
MutableSpan< T > construct_array(int64_t size, Args &&...args)
Span< T * > construct_elements_and_pointer_array(int64_t n, Args &&...args)
MutableSpan< T > construct_array_copy(Span< T > src)
void transfer_ownership_from(LinearAllocator<> &other)
constexpr int64_t size() const
Definition BLI_span.hh:494
constexpr T * data() const
Definition BLI_span.hh:540
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr const char * data() const
static bool is_aligned(void *ptr, uint alignment)
TEST(any, DefaultConstructor)
_W64 unsigned int uintptr_t
Definition stdint.h:119
PointerRNA * ptr
Definition wm_files.cc:4126