Blender V5.0
BLI_span_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
7#include "BLI_span.hh"
8#include "BLI_vector.hh"
9
10#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
11
12namespace blender::tests {
13
14TEST(span, FromSmallVector)
15{
16 Vector<int> a = {1, 2, 3};
17 Span<int> a_span = a;
18 EXPECT_EQ(a_span.size(), 3);
19 EXPECT_EQ(a_span[0], 1);
20 EXPECT_EQ(a_span[1], 2);
21 EXPECT_EQ(a_span[2], 3);
22}
23
24TEST(span, AddConstToPointer)
25{
26 int a = 0;
27 std::vector<int *> vec = {&a};
28 Span<int *> span = vec;
29 Span<const int *> const_span = span;
30 EXPECT_EQ(const_span.size(), 1);
31}
32
33TEST(span, IsReferencing)
34{
35 int array[] = {3, 5, 8};
37 EXPECT_EQ(span.size(), 3);
38 EXPECT_EQ(span[1], 5);
39 array[1] = 10;
40 EXPECT_EQ(span[1], 10);
41}
42
43TEST(span, DropBack)
44{
45 Vector<int> a = {4, 5, 6, 7};
46 auto slice = Span<int>(a).drop_back(2);
47 EXPECT_EQ(slice.size(), 2);
48 EXPECT_EQ(slice[0], 4);
49 EXPECT_EQ(slice[1], 5);
50}
51
52TEST(span, DropBackAll)
53{
54 Vector<int> a = {4, 5, 6, 7};
55 auto slice = Span<int>(a).drop_back(a.size());
56 EXPECT_EQ(slice.size(), 0);
57}
58
59TEST(span, DropFront)
60{
61 Vector<int> a = {4, 5, 6, 7};
62 auto slice = Span<int>(a).drop_front(1);
63 EXPECT_EQ(slice.size(), 3);
64 EXPECT_EQ(slice[0], 5);
65 EXPECT_EQ(slice[1], 6);
66 EXPECT_EQ(slice[2], 7);
67}
68
69TEST(span, DropFrontLargeN)
70{
71 Vector<int> a = {1, 2, 3, 4, 5};
72 Span<int> slice1 = Span<int>(a).drop_front(100);
74 EXPECT_TRUE(slice1.is_empty());
75 EXPECT_TRUE(slice2.is_empty());
76}
77
78TEST(span, DropFrontAll)
79{
80 Vector<int> a = {4, 5, 6, 7};
81 auto slice = Span<int>(a).drop_front(a.size());
82 EXPECT_EQ(slice.size(), 0);
83}
84
85TEST(span, TakeFront)
86{
87 Vector<int> a = {4, 5, 6, 7};
88 auto slice = Span<int>(a).take_front(2);
89 EXPECT_EQ(slice.size(), 2);
90 EXPECT_EQ(slice[0], 4);
91 EXPECT_EQ(slice[1], 5);
92}
93
94TEST(span, TakeFrontLargeN)
95{
96 Vector<int> a = {4, 5, 6, 7};
97 Span<int> slice1 = Span<int>(a).take_front(100);
99 EXPECT_EQ(slice1.size(), 4);
100 EXPECT_EQ(slice2.size(), 4);
101}
102
103TEST(span, TakeBack)
104{
105 Vector<int> a = {5, 6, 7, 8};
106 auto slice = Span<int>(a).take_back(2);
107 EXPECT_EQ(slice.size(), 2);
108 EXPECT_EQ(slice[0], 7);
109 EXPECT_EQ(slice[1], 8);
110}
111
112TEST(span, TakeBackLargeN)
113{
114 Vector<int> a = {3, 4, 5, 6};
115 Span<int> slice1 = Span<int>(a).take_back(100);
117 EXPECT_EQ(slice1.size(), 4);
118 EXPECT_EQ(slice2.size(), 4);
119}
120
121TEST(span, Slice)
122{
123 Vector<int> a = {4, 5, 6, 7};
124 auto slice = Span<int>(a).slice(1, 2);
125 EXPECT_EQ(slice.size(), 2);
126 EXPECT_EQ(slice[0], 5);
127 EXPECT_EQ(slice[1], 6);
128}
129
130TEST(span, SliceEmpty)
131{
132 Vector<int> a = {4, 5, 6, 7};
133 auto slice = Span<int>(a).slice(2, 0);
134 EXPECT_EQ(slice.size(), 0);
135}
136
137TEST(span, SliceRange)
138{
139 Vector<int> a = {1, 2, 3, 4, 5};
140 auto slice = Span<int>(a).slice(IndexRange(2, 2));
141 EXPECT_EQ(slice.size(), 2);
142 EXPECT_EQ(slice[0], 3);
143 EXPECT_EQ(slice[1], 4);
144}
145
146TEST(span, SliceLargeN)
147{
148 Vector<int> a = {1, 2, 3, 4, 5};
149 Span<int> slice1 = Span<int>(a).slice_safe(3, 100);
150 MutableSpan<int> slice2 = MutableSpan<int>(a).slice_safe(3, 100);
151 EXPECT_EQ(slice1.size(), 2);
152 EXPECT_EQ(slice2.size(), 2);
153 EXPECT_EQ(slice1[0], 4);
154 EXPECT_EQ(slice2[0], 4);
155 EXPECT_EQ(slice1[1], 5);
156 EXPECT_EQ(slice2[1], 5);
157}
158
159TEST(span, Contains)
160{
161 Vector<int> a = {4, 5, 6, 7};
162 Span<int> a_span = a;
163 EXPECT_TRUE(a_span.contains(4));
164 EXPECT_TRUE(a_span.contains(5));
165 EXPECT_TRUE(a_span.contains(6));
166 EXPECT_TRUE(a_span.contains(7));
167 EXPECT_FALSE(a_span.contains(3));
168 EXPECT_FALSE(a_span.contains(8));
169}
170
171TEST(mutable_span, Contains)
172{
173 Vector<int> a = {4, 5, 6, 7};
174 MutableSpan<int> a_span = a;
175 EXPECT_TRUE(a_span.contains(4));
176 EXPECT_TRUE(a_span.contains(5));
177 EXPECT_TRUE(a_span.contains(6));
178 EXPECT_TRUE(a_span.contains(7));
179 EXPECT_FALSE(a_span.contains(3));
180 EXPECT_FALSE(a_span.contains(8));
181}
182
183TEST(span, Count)
184{
185 Vector<int> a = {2, 3, 4, 3, 3, 2, 2, 2, 2};
186 Span<int> a_span = a;
187 EXPECT_EQ(a_span.count(1), 0);
188 EXPECT_EQ(a_span.count(2), 5);
189 EXPECT_EQ(a_span.count(3), 3);
190 EXPECT_EQ(a_span.count(4), 1);
191 EXPECT_EQ(a_span.count(5), 0);
192}
193
195{
196 EXPECT_EQ(span.size(), 4);
197 EXPECT_EQ(span[0], 3);
198 EXPECT_EQ(span[1], 6);
199 EXPECT_EQ(span[2], 8);
200 EXPECT_EQ(span[3], 9);
201}
202
203TEST(span, FromInitializerList)
204{
205 test_ref_from_initializer_list({3, 6, 8, 9});
206}
207
208TEST(span, FromVector)
209{
210 std::vector<int> a = {1, 2, 3, 4};
211 Span<int> a_span(a);
212 EXPECT_EQ(a_span.size(), 4);
213 EXPECT_EQ(a_span[0], 1);
214 EXPECT_EQ(a_span[1], 2);
215 EXPECT_EQ(a_span[2], 3);
216 EXPECT_EQ(a_span[3], 4);
217}
218
219TEST(span, FromArray)
220{
221 std::array<int, 2> a = {5, 6};
222 Span<int> a_span(a);
223 EXPECT_EQ(a_span.size(), 2);
224 EXPECT_EQ(a_span[0], 5);
225 EXPECT_EQ(a_span[1], 6);
226}
227
228TEST(span, Fill)
229{
230 std::array<int, 5> a = {4, 5, 6, 7, 8};
231 MutableSpan<int> a_span(a);
232 a_span.fill(1);
233 EXPECT_EQ(a[0], 1);
234 EXPECT_EQ(a[1], 1);
235 EXPECT_EQ(a[2], 1);
236 EXPECT_EQ(a[3], 1);
237 EXPECT_EQ(a[4], 1);
238}
239
240TEST(span, FillIndices)
241{
242 std::array<int, 5> a = {0, 0, 0, 0, 0};
243 MutableSpan<int> a_span(a);
244 a_span.fill_indices(Span({0, 2, 3}), 1);
245 EXPECT_EQ(a[0], 1);
246 EXPECT_EQ(a[1], 0);
247 EXPECT_EQ(a[2], 1);
248 EXPECT_EQ(a[3], 1);
249 EXPECT_EQ(a[4], 0);
250}
251
252TEST(span, SizeInBytes)
253{
254 std::array<int, 10> a{};
255 Span<int> a_span(a);
256 EXPECT_EQ(a_span.size_in_bytes(), int64_t(sizeof(a)));
257 EXPECT_EQ(a_span.size_in_bytes(), 40);
258}
259
260TEST(span, FirstLast)
261{
262 std::array<int, 4> a = {6, 7, 8, 9};
263 Span<int> a_span(a);
264 EXPECT_EQ(a_span.first(), 6);
265 EXPECT_EQ(a_span.last(), 9);
266 EXPECT_EQ(a_span.last(1), 8);
267 EXPECT_EQ(a_span.last(2), 7);
268}
269
270TEST(span, FirstLast_OneElement)
271{
272 int a = 3;
273 Span<int> a_span(&a, 1);
274 EXPECT_EQ(a_span.first(), 3);
275 EXPECT_EQ(a_span.last(), 3);
276 EXPECT_EQ(a_span.last(0), 3);
277}
278
279TEST(span, ContainsPtr)
280{
281 std::array<int, 3> a = {5, 6, 7};
282 int other = 10;
283 Span<int> a_span(a);
284 EXPECT_TRUE(a_span.contains_ptr(&a[0] + 0));
285 EXPECT_TRUE(a_span.contains_ptr(&a[0] + 1));
286 EXPECT_TRUE(a_span.contains_ptr(&a[0] + 2));
287 EXPECT_FALSE(a_span.contains_ptr(&a[0] + 3));
288 int *ptr_before = reinterpret_cast<int *>(uintptr_t(a.data()) - 1);
289 EXPECT_FALSE(a_span.contains_ptr(ptr_before));
290 EXPECT_FALSE(a_span.contains_ptr(&other));
291}
292
293TEST(span, FirstIndex)
294{
295 std::array<int, 5> a = {4, 5, 4, 2, 5};
296 Span<int> a_span(a);
297
298 EXPECT_EQ(a_span.first_index(4), 0);
299 EXPECT_EQ(a_span.first_index(5), 1);
300 EXPECT_EQ(a_span.first_index(2), 3);
301}
302
303TEST(span, CastSameSize)
304{
305 int value = 0;
306 std::array<int *, 4> a = {&value, nullptr, nullptr, nullptr};
307 Span<int *> a_span = a;
308 Span<float *> new_a_span = a_span.cast<float *>();
309
310 EXPECT_EQ(a_span.size(), 4);
311 EXPECT_EQ(new_a_span.size(), 4);
312
313 EXPECT_EQ(a_span[0], &value);
314 EXPECT_EQ(new_a_span[0], (float *)&value);
315}
316
317TEST(span, CastSmallerSize)
318{
319 std::array<uint32_t, 4> a = {3, 4, 5, 6};
320 Span<uint32_t> a_span = a;
321 Span<uint16_t> new_a_span = a_span.cast<uint16_t>();
322
323 EXPECT_EQ(a_span.size(), 4);
324 EXPECT_EQ(new_a_span.size(), 8);
325}
326
327TEST(span, CastLargerSize)
328{
329 std::array<uint16_t, 4> a = {4, 5, 6, 7};
330 Span<uint16_t> a_span = a;
331 Span<uint32_t> new_a_span = a_span.cast<uint32_t>();
332
333 EXPECT_EQ(a_span.size(), 4);
334 EXPECT_EQ(new_a_span.size(), 2);
335}
336
337TEST(span, VoidPointerSpan)
338{
339 int a;
340 float b;
341 double c;
342
343 auto func1 = [](Span<void *> span) { EXPECT_EQ(span.size(), 3); };
344 func1({&a, &b, &c});
345}
346
347TEST(span, CopyFrom)
348{
349 std::array<int, 4> src = {5, 6, 7, 8};
350 std::array<int, 4> dst = {1, 2, 3, 4};
351
352 EXPECT_EQ(dst[2], 3);
353 MutableSpan(dst).copy_from(src);
354 EXPECT_EQ(dst[0], 5);
355 EXPECT_EQ(dst[1], 6);
356 EXPECT_EQ(dst[2], 7);
357 EXPECT_EQ(dst[3], 8);
358}
359
360TEST(span, ReverseIterator)
361{
362 std::array<int, 4> src = {4, 5, 6, 7};
363 Span<int> span = src;
364 Vector<int> reversed_vec;
365
366 for (auto it = span.rbegin(); it != span.rend(); ++it) {
367 reversed_vec.append(*it);
368 }
369 EXPECT_EQ(reversed_vec.size(), 4);
370 EXPECT_EQ_SPAN<int>(reversed_vec, Span({7, 6, 5, 4}));
371}
372
373TEST(span, ReverseMutableSpan)
374{
375 std::array<int, 0> src0 = {};
376 MutableSpan<int> span0 = src0;
377 span0.reverse();
378 EXPECT_EQ_SPAN<int>(span0, Span<int>({}));
379
380 std::array<int, 1> src1 = {4};
381 MutableSpan<int> span1 = src1;
382 span1.reverse();
383 EXPECT_EQ_SPAN<int>(span1, Span({4}));
384
385 std::array<int, 2> src2 = {4, 5};
386 MutableSpan<int> span2 = src2;
387 span2.reverse();
388 EXPECT_EQ_SPAN<int>(span2, Span({5, 4}));
389
390 std::array<int, 5> src5 = {4, 5, 6, 7, 8};
391 MutableSpan<int> span5 = src5;
392 span5.reverse();
393 EXPECT_EQ_SPAN<int>(span5, Span({8, 7, 6, 5, 4}));
394}
395
396TEST(span, MutableReverseIterator)
397{
398 std::array<int, 4> src = {4, 5, 6, 7};
399 MutableSpan<int> span = src;
400 Vector<int> reversed_vec;
401
402 for (auto it = span.rbegin(); it != span.rend(); ++it) {
403 reversed_vec.append(*it);
404 *it += 10;
405 }
406 EXPECT_EQ(reversed_vec.size(), 4);
407 EXPECT_EQ_SPAN<int>(reversed_vec, Span({7, 6, 5, 4}));
408 EXPECT_EQ_SPAN<int>(src, Span({14, 15, 16, 17}));
409}
410
411TEST(span, Constexpr)
412{
413 static constexpr std::array<int, 3> src = {3, 2, 1};
414 constexpr Span<int> span(src);
415 BLI_STATIC_ASSERT(span[2] == 1, "");
416 BLI_STATIC_ASSERT(span.size() == 3, "");
417 BLI_STATIC_ASSERT(span.slice(1, 2).size() == 2, "");
419
420 std::integral_constant<bool, span.first_index(1) == 2> ic;
421 BLI_STATIC_ASSERT(ic.value, "");
422
423 EXPECT_EQ(span.slice(1, 2).size(), 2);
424}
425
426TEST(span, ImplicitConversions)
427{
428 BLI_STATIC_ASSERT((std::is_convertible_v<MutableSpan<int>, Span<int>>), "");
429 BLI_STATIC_ASSERT((std::is_convertible_v<Span<int *>, Span<const int *>>), "");
430 BLI_STATIC_ASSERT((std::is_convertible_v<MutableSpan<int *>, Span<int *>>), "");
431 BLI_STATIC_ASSERT((std::is_convertible_v<MutableSpan<int *>, Span<const int *>>), "");
433 BLI_STATIC_ASSERT((!std::is_convertible_v<MutableSpan<const int *>, MutableSpan<int *>>), "");
434 BLI_STATIC_ASSERT((!std::is_convertible_v<Span<const int *>, Span<int *>>), "");
435 BLI_STATIC_ASSERT((!std::is_convertible_v<Span<int *>, MutableSpan<const int *>>), "");
436}
437
438TEST(span, Comparison)
439{
440 std::array<int, 3> a = {3, 4, 5};
441 std::array<int, 4> b = {3, 4, 5, 6};
442
443 EXPECT_FALSE(Span(a) == Span(b));
444 EXPECT_FALSE(Span(b) == Span(a));
445 EXPECT_TRUE(Span(a) == Span(b).take_front(3));
446 EXPECT_TRUE(Span(a) == Span(a));
447 EXPECT_TRUE(Span(b) == Span(b));
448
449 EXPECT_TRUE(Span(a) != Span(b));
450 EXPECT_TRUE(Span(b) != Span(a));
451 EXPECT_FALSE(Span(a) != Span(b).take_front(3));
452 EXPECT_FALSE(Span(a) != Span(a));
453}
454
455} // namespace blender::tests
#define BLI_STATIC_ASSERT(a, msg)
Definition BLI_assert.h:83
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
#define ARRAY_SIZE(arr)
long long int int64_t
constexpr int64_t size() const
Definition BLI_span.hh:493
constexpr bool contains(const T &value) const
Definition BLI_span.hh:715
constexpr std::reverse_iterator< T * > rbegin() const
Definition BLI_span.hh:553
constexpr bool is_empty() const
Definition BLI_span.hh:509
constexpr MutableSpan take_back(const int64_t n) const
Definition BLI_span.hh:640
constexpr void fill(const T &value) const
Definition BLI_span.hh:517
constexpr MutableSpan slice_safe(const int64_t start, const int64_t size) const
Definition BLI_span.hh:590
constexpr MutableSpan drop_front(const int64_t n) const
Definition BLI_span.hh:607
constexpr void reverse() const
Definition BLI_span.hh:650
constexpr std::reverse_iterator< T * > rend() const
Definition BLI_span.hh:557
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:739
constexpr void fill_indices(Span< IndexT > indices, const T &value) const
Definition BLI_span.hh:526
constexpr MutableSpan take_front(const int64_t n) const
Definition BLI_span.hh:629
constexpr Span drop_front(int64_t n) const
Definition BLI_span.hh:171
Span< NewT > constexpr cast() const
Definition BLI_span.hh:418
constexpr Span slice_safe(const int64_t start, const int64_t size) const
Definition BLI_span.hh:154
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:137
constexpr int64_t size_in_bytes() const
Definition BLI_span.hh:268
constexpr std::reverse_iterator< const T * > rend() const
Definition BLI_span.hh:233
constexpr std::reverse_iterator< const T * > rbegin() const
Definition BLI_span.hh:229
constexpr Span take_back(int64_t n) const
Definition BLI_span.hh:204
constexpr Span drop_back(int64_t n) const
Definition BLI_span.hh:182
constexpr int64_t count(const T &value) const
Definition BLI_span.hh:300
constexpr const T & first() const
Definition BLI_span.hh:315
constexpr bool has_duplicates__linear_search() const
Definition BLI_span.hh:336
constexpr int64_t first_index(const T &search_value) const
Definition BLI_span.hh:377
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr const T & last(const int64_t n=0) const
Definition BLI_span.hh:325
constexpr Span take_front(int64_t n) const
Definition BLI_span.hh:193
constexpr bool is_empty() const
Definition BLI_span.hh:260
constexpr bool contains(const T &value) const
Definition BLI_span.hh:277
constexpr bool contains_ptr(const T *ptr) const
Definition BLI_span.hh:291
int64_t size() const
void append(const T &value)
static void test_ref_from_initializer_list(Span< int > span)
TEST(blf_load, load)
Definition BLF_tests.cc:34