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