Blender V5.0
BLI_vector_set_test.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
6#include "BLI_vector_set.hh"
7
8#include "testing/testing.h"
9
10#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
11
12namespace blender::tests {
13
14TEST(vector_set, DefaultConstructor)
15{
17 EXPECT_EQ(set.size(), 0);
18 EXPECT_TRUE(set.is_empty());
19}
20
21TEST(vector_set, InitializerListConstructor_WithoutDuplicates)
22{
23 VectorSet<int> set = {1, 4, 5};
24 EXPECT_EQ(set.size(), 3);
25 EXPECT_EQ(set[0], 1);
26 EXPECT_EQ(set[1], 4);
27 EXPECT_EQ(set[2], 5);
28 VectorSet<int> set_bigger_than_inline = {1, 4, 5, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19};
29 EXPECT_EQ(set_bigger_than_inline.size(), 14);
30 EXPECT_EQ(set_bigger_than_inline[0], 1);
31 EXPECT_EQ(set_bigger_than_inline[1], 4);
32 EXPECT_EQ(set_bigger_than_inline[2], 5);
33 EXPECT_EQ(set_bigger_than_inline.as_span().last(), 19);
34}
35
36TEST(vector_set, InitializerListConstructor_WithDuplicates)
37{
38 VectorSet<int> set = {1, 3, 3, 2, 1, 5};
39 EXPECT_EQ(set.size(), 4);
40 EXPECT_EQ(set[0], 1);
41 EXPECT_EQ(set[1], 3);
42 EXPECT_EQ(set[2], 2);
43 EXPECT_EQ(set[3], 5);
44}
45
46TEST(vector_set, Copy)
47{
48 VectorSet<int> set1 = {1, 2, 3};
49 VectorSet<int> set2 = set1;
50 EXPECT_EQ(set1.size(), 3);
51 EXPECT_EQ(set2.size(), 3);
52 EXPECT_EQ(set1.index_of(2), 1);
53 EXPECT_EQ(set2.index_of(2), 1);
54}
55
56TEST(vector_set, CopyAssignment)
57{
58 VectorSet<int> set1 = {1, 2, 3};
59 VectorSet<int> set2 = {};
60 set2 = set1;
61 EXPECT_EQ(set1.size(), 3);
62 EXPECT_EQ(set2.size(), 3);
63 EXPECT_EQ(set1.index_of(2), 1);
64 EXPECT_EQ(set2.index_of(2), 1);
65}
66
67TEST(vector_set, Move)
68{
69 {
70 VectorSet<int> set1 = {1, 2, 3};
71 VectorSet<int> set2 = std::move(set1);
72 EXPECT_EQ(set1.size(), 0); /* NOLINT: bugprone-use-after-move */
73 EXPECT_EQ(set2.size(), 3);
74 }
75 {
76 VectorSet<int, 24> set1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
77 VectorSet<int> set2 = std::move(set1);
78 EXPECT_EQ(set1.size(), 0); /* NOLINT: bugprone-use-after-move */
79 EXPECT_EQ(set2.size(), 9);
80 }
81}
82
83TEST(vector_set, MoveNonInline)
84{
85 VectorSet<int> set1 = {1, 2, 3, 5, 1, 6, 7, 8, 1, 4, 57, 8, 7, 34, 57, 8, 1231};
86 VectorSet<int> set2 = std::move(set1);
87 EXPECT_EQ(set1.size(), 0); /* NOLINT: bugprone-use-after-move */
88 EXPECT_EQ(set2.size(), 11);
89}
90
91TEST(vector_set, MoveAssignment)
92{
93 VectorSet<int> set1 = {1, 2, 3};
94 VectorSet<int> set2 = {};
95 set2 = std::move(set1);
96 EXPECT_EQ(set1.size(), 0); /* NOLINT: bugprone-use-after-move */
97 EXPECT_EQ(set2.size(), 3);
98}
99
100TEST(vector_set, AddNewIncreasesSize)
101{
102 VectorSet<int> set;
103 EXPECT_TRUE(set.is_empty());
104 EXPECT_EQ(set.size(), 0);
105 set.add(5);
106 EXPECT_FALSE(set.is_empty());
107 EXPECT_EQ(set.size(), 1);
108}
109
110TEST(vector_set, AddExistingDoesNotIncreaseSize)
111{
112 VectorSet<int> set;
113 EXPECT_EQ(set.size(), 0);
114 EXPECT_TRUE(set.add(5));
115 EXPECT_EQ(set.size(), 1);
116 EXPECT_FALSE(set.add(5));
117 EXPECT_EQ(set.size(), 1);
118}
119
120TEST(vector_set, Index)
121{
122 VectorSet<int> set = {3, 6, 4};
123 EXPECT_EQ(set.index_of(6), 1);
124 EXPECT_EQ(set.index_of(3), 0);
125 EXPECT_EQ(set.index_of(4), 2);
126}
127
128TEST(vector_set, IndexTry)
129{
130 VectorSet<int> set = {3, 6, 4};
131 EXPECT_EQ(set.index_of_try(5), -1);
132 EXPECT_EQ(set.index_of_try(3), 0);
133 EXPECT_EQ(set.index_of_try(6), 1);
134 EXPECT_EQ(set.index_of_try(2), -1);
135}
136
137TEST(vector_set, RemoveContained)
138{
139 VectorSet<int> set = {4, 5, 6, 7};
140 EXPECT_EQ(set.size(), 4);
141 set.remove_contained(5);
142 EXPECT_EQ(set.size(), 3);
143 EXPECT_EQ(set[0], 4);
144 EXPECT_EQ(set[1], 7);
145 EXPECT_EQ(set[2], 6);
146 set.remove_contained(6);
147 EXPECT_EQ(set.size(), 2);
148 EXPECT_EQ(set[0], 4);
149 EXPECT_EQ(set[1], 7);
150 set.remove_contained(4);
151 EXPECT_EQ(set.size(), 1);
152 EXPECT_EQ(set[0], 7);
153 set.remove_contained(7);
154 EXPECT_EQ(set.size(), 0);
155}
156
157TEST(vector_set, RemoveIf)
158{
160 for (const int64_t i : IndexRange(100)) {
161 set.add(i * i);
162 }
163 const int64_t removed = set.remove_if([](const int64_t key) { return key % 2 == 0; });
164 EXPECT_EQ(set.size() + removed, 100);
165 for (const int64_t i : IndexRange(100)) {
166 EXPECT_EQ(set.contains(i * i), i % 2 == 1);
167 }
168}
169
170TEST(vector_set, AddMultipleTimes)
171{
172 VectorSet<int> set;
173 for (int i = 0; i < 100; i++) {
174 EXPECT_FALSE(set.contains(i * 13));
175 set.add(i * 12);
176 set.add(i * 13);
177 EXPECT_TRUE(set.contains(i * 13));
178 }
179}
180
181TEST(vector_set, UniquePtrValue)
182{
184 set.add_new(std::make_unique<int>());
185 set.add(std::make_unique<int>());
186 set.index_of_try(std::make_unique<int>());
187 std::unique_ptr<int> value = set.pop();
188 UNUSED_VARS(value);
189}
190
191TEST(vector_set, Remove)
192{
193 VectorSet<int> set;
194 EXPECT_TRUE(set.add(5));
195 EXPECT_TRUE(set.contains(5));
196 EXPECT_FALSE(set.remove(6));
197 EXPECT_TRUE(set.contains(5));
198 EXPECT_TRUE(set.remove(5));
199 EXPECT_FALSE(set.contains(5));
200 EXPECT_FALSE(set.remove(5));
201 EXPECT_FALSE(set.contains(5));
202}
203
204TEST(vector_set, SpanConstructorExceptions)
205{
206 std::array<ExceptionThrower, 5> array = {1, 2, 3, 4, 5};
207 array[3].throw_during_copy = true;
209
210 EXPECT_ANY_THROW({ VectorSet<ExceptionThrower> set(span); });
211}
212
213TEST(vector_set, CopyConstructorExceptions)
214{
215 VectorSet<ExceptionThrower> set = {1, 2, 3, 4, 5};
216 set[3].throw_during_copy = true;
217
218 EXPECT_ANY_THROW({ VectorSet<ExceptionThrower> set_copy(set); });
219}
220
221TEST(vector_set, MoveConstructorExceptions)
222{
223 VectorSet<ExceptionThrower> set = {1, 2, 3, 4, 5};
224 set[3].throw_during_copy = true;
225 set[3].throw_during_move = true;
226 /* Currently never throws on move, because values are separately allocated. */
227 VectorSet<ExceptionThrower> set_moved(std::move(set));
228 EXPECT_EQ(set.size(), 0); /* NOLINT: bugprone-use-after-move */
229 set.add_multiple({4, 5, 6, 7, 8});
230 EXPECT_EQ(set.size(), 5);
231}
232
233TEST(vector_set, AddNewExceptions)
234{
236 ExceptionThrower value;
237 value.throw_during_copy = true;
238 EXPECT_ANY_THROW({ set.add_new(value); });
239 EXPECT_EQ(set.size(), 0);
240 EXPECT_ANY_THROW({ set.add_new(value); });
241 EXPECT_EQ(set.size(), 0);
242}
243
244TEST(vector_set, AddExceptions)
245{
247 ExceptionThrower value;
248 value.throw_during_copy = true;
249 EXPECT_ANY_THROW({ set.add(value); });
250 EXPECT_EQ(set.size(), 0);
251 EXPECT_ANY_THROW({ set.add(value); });
252 EXPECT_EQ(set.size(), 0);
253}
254
255TEST(vector_set, ReserveExceptions)
256{
258 set.add_multiple({1, 2, 3, 4, 5});
259 set[2].throw_during_move = true;
260 EXPECT_ANY_THROW({ set.reserve(100); });
261}
262
263TEST(vector_set, PopExceptions)
264{
265 VectorSet<ExceptionThrower> set = {1, 2, 3};
266 set.as_span().last().throw_during_move = true;
267 EXPECT_EQ(set.size(), 3);
268 EXPECT_ANY_THROW({ set.pop(); }); /* NOLINT: bugprone-throw-keyword-missing */
269 EXPECT_EQ(set.size(), 3);
270 set.add(10);
271 EXPECT_EQ(set.size(), 4);
272}
273
274TEST(vector_set, IndexOfOrAdd)
275{
276 VectorSet<int> set;
277 EXPECT_EQ(set.index_of_or_add(3), 0);
278 EXPECT_EQ(set.index_of_or_add(3), 0);
279 EXPECT_EQ(set.index_of_or_add(2), 1);
280 EXPECT_EQ(set.index_of_or_add(0), 2);
281 EXPECT_EQ(set.index_of_or_add(2), 1);
282 EXPECT_EQ(set.index_of_or_add(3), 0);
283 EXPECT_EQ(set.index_of_or_add(5), 3);
284 EXPECT_EQ(set.index_of_or_add(8), 4);
285 EXPECT_EQ(set.index_of_or_add(5), 3);
286}
287
288TEST(vector_set, Clear)
289{
290 VectorSet<int> set = {4, 6, 2, 4};
291 EXPECT_EQ(set.size(), 3);
292 set.clear();
293 EXPECT_EQ(set.size(), 0);
294 set.add_multiple({4, 1, 6, 8, 3, 6, 9, 3});
295 EXPECT_EQ(set.size(), 6);
296 set.clear();
297 EXPECT_EQ(set.size(), 0);
298}
299
300TEST(vector_set, LookupKey)
301{
303 set.add("a");
304 set.add("b");
305 set.add("c");
306 EXPECT_EQ(set.lookup_key("a"), "a");
307 EXPECT_EQ(set.lookup_key_as("c"), "c");
308 EXPECT_EQ(set.lookup_key_ptr_as("d"), nullptr);
309 EXPECT_EQ(set.lookup_key_ptr_as("b")->size(), 1);
310 EXPECT_EQ(set.lookup_key_ptr("a"), set.lookup_key_ptr_as("a"));
311 EXPECT_EQ(set.lookup_key_default("d", "default"), "default");
312 EXPECT_EQ(set.lookup_key_default("c", "default"), "c");
313}
314
315TEST(vector_set, GrowWhenEmpty)
316{
317 /* Tests that the internal keys array is freed correctly when growing an empty set. */
318 VectorSet<int> set;
319 set.add(4);
320 set.remove(4);
321 EXPECT_TRUE(set.is_empty());
322 set.reserve(100);
323}
324
325TEST(vector_set, ExtractVector)
326{
327 VectorSet<int> set;
328 set.add_multiple({5, 2, 7, 4, 8, 5, 4, 5});
329 EXPECT_EQ(set.size(), 5);
330 const int *data_ptr = set.data();
331
332 Vector<int> vec = set.extract_vector();
333 EXPECT_EQ(vec.size(), 5);
334 EXPECT_EQ(vec.data(), data_ptr);
335 EXPECT_TRUE(set.is_empty());
336}
337
338TEST(vector_set, ExtractVectorInline)
339{
341 set.add_multiple({5, 2, 7, 4, 8, 5, 4, 5});
342 EXPECT_EQ(set.size(), 5);
343
344 Vector<int> vec = set.extract_vector();
345 EXPECT_EQ(vec.size(), 5);
346 EXPECT_EQ(vec[2], 7);
347 EXPECT_TRUE(set.is_empty());
348}
349
350TEST(vector_set, ExtractVectorInlineExceptions)
351{
353 set.add_multiple({5, 2, 7, 4, 8, 5, 4, 5});
354 set[3].throw_during_copy = true;
355 set[3].throw_during_move = true;
356 EXPECT_EQ(set.size(), 5);
357
358 EXPECT_ANY_THROW({ Vector<ExceptionThrower> vec = set.extract_vector(); });
359 EXPECT_EQ(set.size(), 5);
360}
361
362TEST(vector_set, ExtractVectorEmpty)
363{
364 VectorSet<int> set;
365 Vector<int> vec = set.extract_vector();
366 EXPECT_TRUE(vec.is_empty());
367}
368
370{
371 struct ThingWithID {
372 int a;
373 std::string b;
374 int c;
375 };
376 struct ThingGetter {
377 StringRef operator()(const ThingWithID &value) const
378 {
379 return value.b;
380 }
381 };
383 set.add_new(ThingWithID{0, "test", 54});
384 EXPECT_TRUE(set.contains_as("test"));
385 set.add_new(ThingWithID{4333, "other", 2});
386 EXPECT_EQ(set.size(), 2);
387 set.add(ThingWithID{3333, "test", 27});
388 EXPECT_EQ(set.size(), 2);
389
390 /* Add more elements than the inline capacity. */
392 larger_set.add_new(ThingWithID{12, "test", 9});
393 EXPECT_EQ(larger_set.index_of_as("test"), 0);
394 larger_set.add_new(ThingWithID{123, "other", 8});
395 larger_set.add(ThingWithID{1234, "test", 7});
396 larger_set.add_new(ThingWithID{12345, "test_2", 6});
397 larger_set.add_new(ThingWithID{123456, "test_4", 5});
398 larger_set.add_new(ThingWithID{1234567, "test_5", 4});
399 EXPECT_EQ(larger_set.index_of_as("test_4"), 3);
400 larger_set.add_new(ThingWithID{12345678, "test_6", 3});
401 EXPECT_TRUE(larger_set.size() == 6);
402}
403
404TEST(vector_set, CustomIDVectorSetMove)
405{
406
407 struct ThingWithID {
408 int a;
409 std::string b;
410 int c;
411 };
412 struct ThingGetter {
413 StringRef operator()(const std::unique_ptr<ThingWithID> &value) const
414 {
415 return value->b;
416 }
417 };
419 set.add(std::make_unique<ThingWithID>(ThingWithID{1, "hug", 2}));
420 set.add(std::make_unique<ThingWithID>(ThingWithID{2, "a", 2}));
421 set.add(std::make_unique<ThingWithID>(ThingWithID{3, "bug", 4}));
422 auto set_new = std::move(set);
423 EXPECT_EQ(set.size(), 0); /* NOLINT: bugprone-use-after-move */
424 EXPECT_EQ(set_new.size(), 3);
425}
426
427namespace {
428struct KeyWithData {
429 int key;
430 std::string data;
431
432 KeyWithData(int key, std::string data) : key(key), data(data) {}
433 KeyWithData(const StringRef data) : key(0), data(data) {}
434
435 uint64_t hash() const
436 {
437 return uint64_t(this->key);
438 }
439
440 friend bool operator==(const KeyWithData &a, const KeyWithData &b)
441 {
442 return a.key == b.key;
443 }
444};
445} // namespace
446
447TEST(vector_set, AddOverwrite)
448{
450 EXPECT_TRUE(set.add_overwrite(KeyWithData{1, "a"}));
451 EXPECT_EQ(set.size(), 1);
452 EXPECT_EQ(set[0].data, "a");
453 EXPECT_FALSE(set.add(KeyWithData{1, "b"}));
454 EXPECT_EQ(set.size(), 1);
455 EXPECT_EQ(set[0].data, "a");
456 EXPECT_EQ(set.lookup_key(KeyWithData{1, "_"}).data, "a");
457 EXPECT_FALSE(set.add_overwrite(KeyWithData{1, "c"}));
458 EXPECT_EQ(set.size(), 1);
459 EXPECT_EQ(set[0].data, "c");
460 EXPECT_EQ(set.lookup_key(KeyWithData{1, "_"}).data, "c");
461
462 const KeyWithData key{2, "d"};
463 EXPECT_TRUE(set.add_overwrite(key));
464 EXPECT_EQ(set.size(), 2);
465 EXPECT_EQ(set[0].data, "c");
466 EXPECT_EQ(set[1].data, "d");
467 EXPECT_EQ(set.lookup_key(key).data, "d");
468}
469
470TEST(vector_set, LookupDefault)
471{
473 EXPECT_TRUE(set.add(KeyWithData{1, "b"}));
474 EXPECT_TRUE(set.add(KeyWithData{423, "s"}));
475 EXPECT_TRUE(set.add(KeyWithData{2, "t"}));
476 KeyWithData default_key{1, "default"};
477 EXPECT_EQ(set.lookup_key_default(KeyWithData{1221, "3"}, default_key), default_key);
478 KeyWithData other_s{0, "testing"};
479 EXPECT_EQ(set.lookup_key_default(KeyWithData{2398745, "fffff"}, StringRef("testing")), other_s);
480 EXPECT_EQ(set.lookup_key_default(KeyWithData{1, "s"}, StringRef("testing")), set[0]);
481 EXPECT_EQ(set.lookup_key_default(KeyWithData{2, "t"}, {1, "default"}), set[2]);
482}
483
484} // namespace blender::tests
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
#define UNUSED_VARS(...)
BMesh const char void * data
long long int int64_t
unsigned long long int uint64_t
SIMD_FORCE_INLINE btVector3 operator()(const btVector3 &x) const
Return the transform of the vector.
Definition btTransform.h:90
int64_t index_of_try(const Key &key) const
const Key & lookup_key_as(const ForwardKey &key) const
bool contains_as(const ForwardKey &key) const
const Key * data() const
bool remove(const Key &key)
bool add(const Key &key)
int64_t index_of_as(const ForwardKey &key) const
const Key * lookup_key_ptr(const Key &key) const
int64_t index_of_or_add(const Key &key)
const Key & lookup_key(const Key &key) const
const Key * lookup_key_ptr_as(const ForwardKey &key) const
Key lookup_key_default(const Key &key, const Key &default_value) const
void reserve(const int64_t n)
void add_multiple(Span< Key > keys)
int64_t size() const
bool add_overwrite(const Key &key)
int64_t index_of(const Key &key) const
bool contains(const Key &key) const
int64_t remove_if(Predicate &&predicate)
Span< Key > as_span() const
void add_new(const Key &key)
void remove_contained(const Key &key)
int64_t size() const
bool is_empty() const
static bool operator==(const Type1 &a, const Type1 &b)
TEST(blf_load, load)
Definition BLF_tests.cc:34
VectorSet< T, InlineBufferCapacity, DefaultProbingStrategy, CustomIDHash< T, GetIDFn >, CustomIDEqual< T, GetIDFn > > CustomIDVectorSet
#define hash
Definition noise_c.cc:154
i
Definition text_draw.cc:230