1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 // This is the base::span unit test from Chromium, with small modifications.
16 // Modifications are noted with "Pigweed:" comments.
17 //
18 // Original file:
19 // https://chromium.googlesource.com/chromium/src/+/ef71f9c29f0dc6eddae474879c4ca5232ca93a6c/base/containers/span_unittest.cc
20 //
21 // In order to minimize changes from the original, this file does NOT fully
22 // adhere to Pigweed's style guide.
23
24 // NOLINTBEGIN(modernize-unary-static-assert)
25
26 #include "pw_span/span.h"
27
28 #include <algorithm>
29 #include <cstdint>
30 #include <cstring>
31 #include <memory>
32 #include <string>
33 #include <type_traits>
34 #include <vector>
35
36 #include "pw_polyfill/standard.h"
37 #include "pw_unit_test/framework.h"
38
39 // Pigweed: gMock matchers are not yet supported.
40 #if 0
41 using ::testing::ElementsAre;
42 using ::testing::Eq;
43 using ::testing::Pointwise;
44 #endif // 0
45
46 namespace pw {
47 namespace {
48
49 // constexpr implementation of std::equal's 4 argument overload.
50 template <class InputIterator1, class InputIterator2>
constexpr_equal(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2)51 constexpr bool constexpr_equal(InputIterator1 first1,
52 InputIterator1 last1,
53 InputIterator2 first2,
54 InputIterator2 last2) {
55 for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
56 if (*first1 != *first2)
57 return false;
58 }
59
60 return first1 == last1 && first2 == last2;
61 }
62
63 } // namespace
64
65 #ifdef __cpp_deduction_guides
66
TEST(SpanTest,DeductionGuides_MutableArray)67 TEST(SpanTest, DeductionGuides_MutableArray) {
68 char array[] = {'a', 'b', 'c', 'd', '\0'};
69
70 auto the_span = span(array);
71 static_assert(the_span.extent == 5u);
72 static_assert(the_span.size() == 5u);
73
74 the_span[0] = '!';
75 EXPECT_STREQ(the_span.data(), "!bcd");
76 }
77
TEST(SpanTest,DeductionGuides_ConstArray)78 TEST(SpanTest, DeductionGuides_ConstArray) {
79 static constexpr char array[] = {'a', 'b', 'c', 'd', '\0'};
80
81 constexpr auto the_span = span(array);
82 static_assert(the_span.extent == 5u);
83 static_assert(the_span.size() == 5u);
84
85 EXPECT_STREQ(the_span.data(), "abcd");
86 }
87
TEST(SpanTest,DeductionGuides_MutableStdArray)88 TEST(SpanTest, DeductionGuides_MutableStdArray) {
89 std::array<char, 5> array{'a', 'b', 'c', 'd'};
90
91 auto the_span = span(array);
92 static_assert(the_span.extent == 5u);
93 static_assert(the_span.size() == 5u);
94
95 the_span[0] = '?';
96 EXPECT_STREQ(the_span.data(), "?bcd");
97 }
98
TEST(SpanTest,DeductionGuides_ConstStdArray)99 TEST(SpanTest, DeductionGuides_ConstStdArray) {
100 static constexpr std::array<char, 5> array{'a', 'b', 'c', 'd'};
101
102 constexpr auto the_span = span(array);
103 static_assert(the_span.extent == 5u);
104 static_assert(the_span.size() == 5u);
105
106 EXPECT_STREQ(the_span.data(), "abcd");
107 }
108
TEST(SpanTest,DeductionGuides_MutableContainerWithConstElements)109 TEST(SpanTest, DeductionGuides_MutableContainerWithConstElements) {
110 std::string_view string("Hello");
111 auto the_span = span<const char>(string);
112 static_assert(the_span.extent == dynamic_extent);
113
114 EXPECT_STREQ("Hello", the_span.data());
115 EXPECT_EQ(5u, the_span.size());
116 }
117
TEST(SpanTest,DeductionGuides_MutableContainerWithMutableElements)118 TEST(SpanTest, DeductionGuides_MutableContainerWithMutableElements) {
119 std::string string("Hello");
120 auto the_span = span(string);
121 static_assert(the_span.extent == dynamic_extent);
122
123 EXPECT_EQ(5u, the_span.size());
124 the_span[1] = 'a';
125 EXPECT_STREQ(the_span.data(), string.data());
126 EXPECT_STREQ("Hallo", the_span.data());
127 }
128
129 #endif // __cpp_deduction_guides
130
131 class MutableStringView {
132 public:
133 using element_type = char;
134 using value_type = char;
135 using size_type = size_t;
136 using difference_type = ptrdiff_t;
137 using pointer = char*;
138 using reference = char&;
139 using iterator = char*;
140 using const_iterator = const char*;
141 using reverse_iterator = std::reverse_iterator<iterator>;
142 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
143
MutableStringView(char * str)144 MutableStringView(char* str) : data_(str, std::strlen(str)) {}
145
operator [](size_type index) const146 char& operator[](size_type index) const { return data_[index]; }
data() const147 pointer data() const { return data_.data(); }
size() const148 size_type size() const { return data_.size(); }
begin() const149 iterator begin() const { return data_.data(); }
end() const150 iterator end() const { return data_.data() + size(); }
151
152 private:
153 span<char> data_;
154 };
155
156 #ifdef __cpp_deduction_guides
157
TEST(SpanTest,DeductionGuides_ConstContainerWithMutableElements)158 TEST(SpanTest, DeductionGuides_ConstContainerWithMutableElements) {
159 char data[] = "54321";
160 MutableStringView view(data);
161
162 auto the_span = span(view);
163 static_assert(the_span.extent == dynamic_extent);
164
165 EXPECT_EQ(5u, the_span.size());
166 view[2] = '?';
167 EXPECT_STREQ("54?21", the_span.data());
168 EXPECT_STREQ("54?21", data);
169 }
170
TEST(SpanTest,DeductionGuides_ConstContainerWithMutableValueType)171 TEST(SpanTest, DeductionGuides_ConstContainerWithMutableValueType) {
172 const std::string string("Hello");
173 auto the_span = span(string);
174 static_assert(the_span.extent == dynamic_extent);
175
176 EXPECT_EQ(5u, the_span.size());
177 EXPECT_STREQ("Hello", the_span.data());
178 }
179
TEST(SpanTest,DeductionGuides_ConstContainerWithConstElements)180 TEST(SpanTest, DeductionGuides_ConstContainerWithConstElements) {
181 const std::string_view string("Hello");
182 auto the_span = span(string);
183 static_assert(the_span.extent == dynamic_extent);
184
185 EXPECT_EQ(5u, the_span.size());
186 EXPECT_STREQ("Hello", the_span.data());
187 }
188
TEST(SpanTest,DeductionGuides_FromTemporary_ContainerWithConstElements)189 TEST(SpanTest, DeductionGuides_FromTemporary_ContainerWithConstElements) {
190 auto the_span = span(std::string_view("Hello"));
191 static_assert(the_span.extent == dynamic_extent);
192
193 EXPECT_EQ(5u, the_span.size());
194 EXPECT_STREQ("Hello", the_span.data());
195 }
196
TEST(SpanTest,DeductionGuides_FromReference)197 TEST(SpanTest, DeductionGuides_FromReference) {
198 std::array<int, 5> array{1, 3, 5, 7, 9};
199 std::array<int, 5>& array_ref = array;
200
201 auto the_span = span(array_ref);
202 static_assert(the_span.extent == 5);
203
204 for (unsigned i = 0; i < array.size(); ++i) {
205 ASSERT_EQ(array[i], the_span[i]);
206 }
207 }
208
TEST(SpanTest,DeductionGuides_FromConstReference)209 TEST(SpanTest, DeductionGuides_FromConstReference) {
210 std::string_view string = "yo!";
211 const std::string_view string_ref = string;
212
213 auto the_span = span(string_ref);
214 static_assert(the_span.extent == dynamic_extent);
215
216 EXPECT_EQ(string, the_span.data());
217 }
218
219 #endif // __cpp_deduction_guides
220
TEST(SpanTest,DefaultConstructor)221 TEST(SpanTest, DefaultConstructor) {
222 span<int> dynamic_span;
223 EXPECT_EQ(nullptr, dynamic_span.data());
224 EXPECT_EQ(0u, dynamic_span.size());
225
226 constexpr span<int, 0> static_span;
227 static_assert(nullptr == static_span.data(), "");
228 static_assert(static_span.empty(), "");
229 }
230
TEST(SpanTest,ConstructFromDataAndSize)231 TEST(SpanTest, ConstructFromDataAndSize) {
232 constexpr span<int> empty_span(static_cast<int*>(nullptr), 0);
233 EXPECT_TRUE(empty_span.empty());
234 EXPECT_EQ(nullptr, empty_span.data());
235
236 std::vector<int> vector = {1, 1, 2, 3, 5, 8};
237
238 span<int> dynamic_span(vector.data(), vector.size());
239 EXPECT_EQ(vector.data(), dynamic_span.data());
240 EXPECT_EQ(vector.size(), dynamic_span.size());
241
242 for (size_t i = 0; i < dynamic_span.size(); ++i)
243 EXPECT_EQ(vector[i], dynamic_span[i]);
244
245 span<int, 6> static_span(vector.data(), vector.size());
246 EXPECT_EQ(vector.data(), static_span.data());
247 EXPECT_EQ(vector.size(), static_span.size());
248
249 for (size_t i = 0; i < static_span.size(); ++i)
250 EXPECT_EQ(vector[i], static_span[i]);
251 }
252
TEST(SpanTest,ConstructFromPointerPair)253 TEST(SpanTest, ConstructFromPointerPair) {
254 constexpr span<int> empty_span(static_cast<int*>(nullptr),
255 static_cast<int*>(nullptr));
256 EXPECT_TRUE(empty_span.empty());
257 EXPECT_EQ(nullptr, empty_span.data());
258
259 std::vector<int> vector = {1, 1, 2, 3, 5, 8};
260
261 span<int> dynamic_span(vector.data(), vector.data() + vector.size() / 2);
262 EXPECT_EQ(vector.data(), dynamic_span.data());
263 EXPECT_EQ(vector.size() / 2, dynamic_span.size());
264
265 for (size_t i = 0; i < dynamic_span.size(); ++i)
266 EXPECT_EQ(vector[i], dynamic_span[i]);
267
268 span<int, 3> static_span(vector.data(), vector.data() + vector.size() / 2);
269 EXPECT_EQ(vector.data(), static_span.data());
270 EXPECT_EQ(vector.size() / 2, static_span.size());
271
272 for (size_t i = 0; i < static_span.size(); ++i)
273 EXPECT_EQ(vector[i], static_span[i]);
274 }
275
TEST(SpanTest,AllowedConversionsFromStdArray)276 TEST(SpanTest, AllowedConversionsFromStdArray) {
277 // In the following assertions we use std::is_convertible_v<From, To>, which
278 // for non-void types is equivalent to checking whether the following
279 // expression is well-formed:
280 //
281 // T obj = std::declval<From>();
282 //
283 // In particular we are checking whether From is implicitly convertible to To,
284 // which also implies that To is explicitly constructible from From.
285 static_assert(
286 std::is_convertible<std::array<int, 3>&, span<int>>::value,
287 "Error: l-value reference to std::array<int> should be convertible to "
288 "span<int> with dynamic extent.");
289 static_assert(
290 std::is_convertible<std::array<int, 3>&, span<int, 3>>::value,
291 "Error: l-value reference to std::array<int> should be convertible to "
292 "span<int> with the same static extent.");
293 static_assert(
294 std::is_convertible<std::array<int, 3>&, span<const int>>::value,
295 "Error: l-value reference to std::array<int> should be convertible to "
296 "span<const int> with dynamic extent.");
297 static_assert(
298 std::is_convertible<std::array<int, 3>&, span<const int, 3>>::value,
299 "Error: l-value reference to std::array<int> should be convertible to "
300 "span<const int> with the same static extent.");
301 static_assert(
302 std::is_convertible<const std::array<int, 3>&, span<const int>>::value,
303 "Error: const l-value reference to std::array<int> should be "
304 "convertible to span<const int> with dynamic extent.");
305 static_assert(
306 std::is_convertible<const std::array<int, 3>&, span<const int, 3>>::value,
307 "Error: const l-value reference to std::array<int> should be convertible "
308 "to span<const int> with the same static extent.");
309 static_assert(
310 std::is_convertible<std::array<const int, 3>&, span<const int>>::value,
311 "Error: l-value reference to std::array<const int> should be "
312 "convertible to span<const int> with dynamic extent.");
313 static_assert(
314 std::is_convertible<std::array<const int, 3>&, span<const int, 3>>::value,
315 "Error: l-value reference to std::array<const int> should be convertible "
316 "to span<const int> with the same static extent.");
317 static_assert(
318 std::is_convertible<const std::array<const int, 3>&,
319 span<const int>>::value,
320 "Error: const l-value reference to std::array<const int> should be "
321 "convertible to span<const int> with dynamic extent.");
322 static_assert(
323 std::is_convertible<const std::array<const int, 3>&,
324 span<const int, 3>>::value,
325 "Error: const l-value reference to std::array<const int> should be "
326 "convertible to span<const int> with the same static extent.");
327 }
328
TEST(SpanTest,DisallowedConstructionsFromStdArray)329 TEST(SpanTest, DisallowedConstructionsFromStdArray) {
330 // In the following assertions we use !std::is_constructible_v<T, Args>, which
331 // is equivalent to checking whether the following expression is malformed:
332 //
333 // T obj(std::declval<Args>()...);
334 //
335 // In particular we are checking that T is not explicitly constructible from
336 // Args, which also implies that T is not implicitly constructible from Args
337 // as well.
338 static_assert(
339 !std::is_constructible<span<int>, const std::array<int, 3>&>::value,
340 "Error: span<int> with dynamic extent should not be constructible "
341 "from const l-value reference to std::array<int>");
342
343 static_assert(
344 !std::is_constructible<span<int>, std::array<const int, 3>&>::value,
345 "Error: span<int> with dynamic extent should not be constructible "
346 "from l-value reference to std::array<const int>");
347
348 static_assert(
349 !std::is_constructible<span<int>, const std::array<const int, 3>&>::value,
350 "Error: span<int> with dynamic extent should not be constructible "
351 "const from l-value reference to std::array<const int>");
352
353 static_assert(
354 !std::is_constructible<span<int, 2>, std::array<int, 3>&>::value,
355 "Error: span<int> with static extent should not be constructible "
356 "from l-value reference to std::array<int> with different extent");
357
358 static_assert(
359 !std::is_constructible<span<int, 4>, std::array<int, 3>&>::value,
360 "Error: span<int> with dynamic extent should not be constructible "
361 "from l-value reference to std::array<int> with different extent");
362
363 static_assert(
364 !std::is_constructible<span<int>, std::array<bool, 3>&>::value,
365 "Error: span<int> with dynamic extent should not be constructible "
366 "from l-value reference to std::array<bool>");
367 }
368
TEST(SpanTest,ConstructFromConstexprArray)369 TEST(SpanTest, ConstructFromConstexprArray) {
370 static constexpr int kArray[] = {5, 4, 3, 2, 1};
371
372 constexpr span<const int> dynamic_span(kArray);
373 static_assert(kArray == dynamic_span.data(), "");
374 static_assert(std::size(kArray) == dynamic_span.size(), "");
375
376 static_assert(kArray[0] == dynamic_span[0], "");
377 static_assert(kArray[1] == dynamic_span[1], "");
378 static_assert(kArray[2] == dynamic_span[2], "");
379 static_assert(kArray[3] == dynamic_span[3], "");
380 static_assert(kArray[4] == dynamic_span[4], "");
381
382 constexpr span<const int, std::size(kArray)> static_span(kArray);
383 static_assert(kArray == static_span.data(), "");
384 static_assert(std::size(kArray) == static_span.size(), "");
385
386 static_assert(kArray[0] == static_span[0], "");
387 static_assert(kArray[1] == static_span[1], "");
388 static_assert(kArray[2] == static_span[2], "");
389 static_assert(kArray[3] == static_span[3], "");
390 static_assert(kArray[4] == static_span[4], "");
391 }
392
TEST(SpanTest,ConstructFromArray)393 TEST(SpanTest, ConstructFromArray) {
394 int array[] = {5, 4, 3, 2, 1};
395
396 span<const int> const_span(array);
397 EXPECT_EQ(array, const_span.data());
398 EXPECT_EQ(std::size(array), const_span.size());
399 for (size_t i = 0; i < const_span.size(); ++i)
400 EXPECT_EQ(array[i], const_span[i]);
401
402 span<int> dynamic_span(array);
403 EXPECT_EQ(array, dynamic_span.data());
404 EXPECT_EQ(std::size(array), dynamic_span.size());
405 for (size_t i = 0; i < dynamic_span.size(); ++i)
406 EXPECT_EQ(array[i], dynamic_span[i]);
407
408 span<int, std::size(array)> static_span(array);
409 EXPECT_EQ(array, static_span.data());
410 EXPECT_EQ(std::size(array), static_span.size());
411 for (size_t i = 0; i < static_span.size(); ++i)
412 EXPECT_EQ(array[i], static_span[i]);
413 }
414
TEST(SpanTest,ConstructFromStdArray)415 TEST(SpanTest, ConstructFromStdArray) {
416 // Note: Constructing a constexpr span from a constexpr std::array does not
417 // work prior to C++17 due to non-constexpr std::array::data.
418 std::array<int, 5> array = {{5, 4, 3, 2, 1}};
419
420 span<const int> const_span(array);
421 EXPECT_EQ(array.data(), const_span.data());
422 EXPECT_EQ(array.size(), const_span.size());
423 for (size_t i = 0; i < const_span.size(); ++i)
424 EXPECT_EQ(array[i], const_span[i]);
425
426 span<int> dynamic_span(array);
427 EXPECT_EQ(array.data(), dynamic_span.data());
428 EXPECT_EQ(array.size(), dynamic_span.size());
429 for (size_t i = 0; i < dynamic_span.size(); ++i)
430 EXPECT_EQ(array[i], dynamic_span[i]);
431
432 span<int, std::size(array)> static_span(array);
433 EXPECT_EQ(array.data(), static_span.data());
434 EXPECT_EQ(array.size(), static_span.size());
435 for (size_t i = 0; i < static_span.size(); ++i)
436 EXPECT_EQ(array[i], static_span[i]);
437 }
438
439 #if PW_CXX_STANDARD_IS_SUPPORTED(17)
440
TEST(SpanTest,ConstructFromInitializerList)441 TEST(SpanTest, ConstructFromInitializerList) {
442 std::initializer_list<int> il = {1, 1, 2, 3, 5, 8};
443
444 span<const int> const_span(il);
445 EXPECT_EQ(il.begin(), const_span.data());
446 EXPECT_EQ(il.size(), const_span.size());
447
448 for (size_t i = 0; i < const_span.size(); ++i)
449 EXPECT_EQ(il.begin()[i], const_span[i]);
450
451 span<const int, 6> static_span(il.begin(), il.end());
452 EXPECT_EQ(il.begin(), static_span.data());
453 EXPECT_EQ(il.size(), static_span.size());
454
455 for (size_t i = 0; i < static_span.size(); ++i)
456 EXPECT_EQ(il.begin()[i], static_span[i]);
457 }
458
TEST(SpanTest,ConstructFromStdString)459 TEST(SpanTest, ConstructFromStdString) {
460 std::string str = "foobar";
461
462 span<const char> const_span(str);
463 EXPECT_EQ(str.data(), const_span.data());
464 EXPECT_EQ(str.size(), const_span.size());
465
466 for (size_t i = 0; i < const_span.size(); ++i)
467 EXPECT_EQ(str[i], const_span[i]);
468
469 span<char> dynamic_span(str);
470 EXPECT_EQ(str.data(), dynamic_span.data());
471 EXPECT_EQ(str.size(), dynamic_span.size());
472
473 for (size_t i = 0; i < dynamic_span.size(); ++i)
474 EXPECT_EQ(str[i], dynamic_span[i]);
475
476 span<char, 6> static_span(data(str), str.size());
477 EXPECT_EQ(str.data(), static_span.data());
478 EXPECT_EQ(str.size(), static_span.size());
479
480 for (size_t i = 0; i < static_span.size(); ++i)
481 EXPECT_EQ(str[i], static_span[i]);
482 }
483
484 #endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
485
TEST(SpanTest,ConstructFromConstContainer)486 TEST(SpanTest, ConstructFromConstContainer) {
487 const std::vector<int> vector = {1, 1, 2, 3, 5, 8};
488
489 span<const int> const_span(vector);
490 EXPECT_EQ(vector.data(), const_span.data());
491 EXPECT_EQ(vector.size(), const_span.size());
492
493 for (size_t i = 0; i < const_span.size(); ++i)
494 EXPECT_EQ(vector[i], const_span[i]);
495
496 span<const int, 6> static_span(vector.data(), vector.size());
497 EXPECT_EQ(vector.data(), static_span.data());
498 EXPECT_EQ(vector.size(), static_span.size());
499
500 for (size_t i = 0; i < static_span.size(); ++i)
501 EXPECT_EQ(vector[i], static_span[i]);
502 }
503
TEST(SpanTest,ConstructFromContainer)504 TEST(SpanTest, ConstructFromContainer) {
505 std::vector<int> vector = {1, 1, 2, 3, 5, 8};
506
507 span<const int> const_span(vector);
508 EXPECT_EQ(vector.data(), const_span.data());
509 EXPECT_EQ(vector.size(), const_span.size());
510
511 for (size_t i = 0; i < const_span.size(); ++i)
512 EXPECT_EQ(vector[i], const_span[i]);
513
514 span<int> dynamic_span(vector);
515 EXPECT_EQ(vector.data(), dynamic_span.data());
516 EXPECT_EQ(vector.size(), dynamic_span.size());
517
518 for (size_t i = 0; i < dynamic_span.size(); ++i)
519 EXPECT_EQ(vector[i], dynamic_span[i]);
520
521 span<int, 6> static_span(vector.data(), vector.size());
522 EXPECT_EQ(vector.data(), static_span.data());
523 EXPECT_EQ(vector.size(), static_span.size());
524
525 for (size_t i = 0; i < static_span.size(); ++i)
526 EXPECT_EQ(vector[i], static_span[i]);
527 }
528
529 #if 0
530
531 // Pigweed: gMock matchers are not yet supported.
532 TEST(SpanTest, ConvertNonConstIntegralToConst) {
533 std::vector<int> vector = {1, 1, 2, 3, 5, 8};
534
535 span<int> int_span(vector.data(), vector.size());
536 span<const int> const_span(int_span);
537 EXPECT_EQ(int_span.size(), const_span.size());
538
539 EXPECT_THAT(const_span, Pointwise(Eq(), int_span));
540
541 span<int, 6> static_int_span(vector.data(), vector.size());
542 span<const int, 6> static_const_span(static_int_span);
543 EXPECT_THAT(static_const_span, Pointwise(Eq(), static_int_span));
544 }
545
546 // Pigweed: gMock matchers are not yet supported.
547 TEST(SpanTest, ConvertNonConstPointerToConst) {
548 auto a = std::make_unique<int>(11);
549 auto b = std::make_unique<int>(22);
550 auto c = std::make_unique<int>(33);
551 std::vector<int*> vector = {a.get(), b.get(), c.get()};
552
553 span<int*> non_const_pointer_span(vector);
554 EXPECT_THAT(non_const_pointer_span, Pointwise(Eq(), vector));
555 span<int* const> const_pointer_span(non_const_pointer_span);
556 EXPECT_THAT(const_pointer_span, Pointwise(Eq(), non_const_pointer_span));
557 // Note: no test for conversion from span<int> to span<const int*>, since that
558 // would imply a conversion from int** to const int**, which is unsafe.
559 //
560 // Note: no test for conversion from span<int*> to span<const int* const>,
561 // due to CWG Defect 330:
562 // http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#330
563
564 span<int*, 3> static_non_const_pointer_span(vector.data(), vector.size());
565 EXPECT_THAT(static_non_const_pointer_span, Pointwise(Eq(), vector));
566 span<int* const, 3> static_const_pointer_span(static_non_const_pointer_span);
567 EXPECT_THAT(static_const_pointer_span,
568 Pointwise(Eq(), static_non_const_pointer_span));
569 }
570
571 // Pigweed: This test does not work on platforms where int32_t is long int.
572 TEST(SpanTest, ConvertBetweenEquivalentTypes) {
573 std::vector<int32_t> vector = {2, 4, 8, 16, 32};
574
575 span<int32_t> int32_t_span(vector);
576 span<int> converted_span(int32_t_span);
577 EXPECT_EQ(int32_t_span.data(), converted_span.data());
578 EXPECT_EQ(int32_t_span.size(), converted_span.size());
579
580 span<int32_t, 5> static_int32_t_span(vector.data(), vector.size());
581 span<int, 5> static_converted_span(static_int32_t_span);
582 EXPECT_EQ(static_int32_t_span.data(), static_converted_span.data());
583 EXPECT_EQ(static_int32_t_span.size(), static_converted_span.size());
584 }
585
586 #endif // 0
587
TEST(SpanTest,TemplatedFirst)588 TEST(SpanTest, TemplatedFirst) {
589 static constexpr int array[] = {1, 2, 3};
590 constexpr span<const int, 3> span(array);
591
592 {
593 constexpr auto subspan = span.first<0>();
594 static_assert(span.data() == subspan.data(), "");
595 static_assert(subspan.empty(), "");
596 static_assert(0u == decltype(subspan)::extent, "");
597 }
598
599 {
600 constexpr auto subspan = span.first<1>();
601 static_assert(span.data() == subspan.data(), "");
602 static_assert(1u == subspan.size(), "");
603 static_assert(1u == decltype(subspan)::extent, "");
604 static_assert(1 == subspan[0], "");
605 }
606
607 {
608 constexpr auto subspan = span.first<2>();
609 static_assert(span.data() == subspan.data(), "");
610 static_assert(2u == subspan.size(), "");
611 static_assert(2u == decltype(subspan)::extent, "");
612 static_assert(1 == subspan[0], "");
613 static_assert(2 == subspan[1], "");
614 }
615
616 {
617 constexpr auto subspan = span.first<3>();
618 static_assert(span.data() == subspan.data(), "");
619 static_assert(3u == subspan.size(), "");
620 static_assert(3u == decltype(subspan)::extent, "");
621 static_assert(1 == subspan[0], "");
622 static_assert(2 == subspan[1], "");
623 static_assert(3 == subspan[2], "");
624 }
625 }
626
TEST(SpanTest,TemplatedLast)627 TEST(SpanTest, TemplatedLast) {
628 static constexpr int array[] = {1, 2, 3};
629 constexpr span<const int, 3> span(array);
630
631 {
632 constexpr auto subspan = span.last<0>();
633 static_assert(span.data() + 3 == subspan.data(), "");
634 static_assert(subspan.empty(), "");
635 static_assert(0u == decltype(subspan)::extent, "");
636 }
637
638 {
639 constexpr auto subspan = span.last<1>();
640 static_assert(span.data() + 2 == subspan.data(), "");
641 static_assert(1u == subspan.size(), "");
642 static_assert(1u == decltype(subspan)::extent, "");
643 static_assert(3 == subspan[0], "");
644 }
645
646 {
647 constexpr auto subspan = span.last<2>();
648 static_assert(span.data() + 1 == subspan.data(), "");
649 static_assert(2u == subspan.size(), "");
650 static_assert(2u == decltype(subspan)::extent, "");
651 static_assert(2 == subspan[0], "");
652 static_assert(3 == subspan[1], "");
653 }
654
655 {
656 constexpr auto subspan = span.last<3>();
657 static_assert(span.data() == subspan.data(), "");
658 static_assert(3u == subspan.size(), "");
659 static_assert(3u == decltype(subspan)::extent, "");
660 static_assert(1 == subspan[0], "");
661 static_assert(2 == subspan[1], "");
662 static_assert(3 == subspan[2], "");
663 }
664 }
665
TEST(SpanTest,TemplatedSubspan)666 TEST(SpanTest, TemplatedSubspan) {
667 static constexpr int array[] = {1, 2, 3};
668 constexpr span<const int, 3> span(array);
669
670 {
671 constexpr auto subspan = span.subspan<0>();
672 static_assert(span.data() == subspan.data(), "");
673 static_assert(3u == subspan.size(), "");
674 static_assert(3u == decltype(subspan)::extent, "");
675 static_assert(1 == subspan[0], "");
676 static_assert(2 == subspan[1], "");
677 static_assert(3 == subspan[2], "");
678 }
679
680 {
681 constexpr auto subspan = span.subspan<1>();
682 static_assert(span.data() + 1 == subspan.data(), "");
683 static_assert(2u == subspan.size(), "");
684 static_assert(2u == decltype(subspan)::extent, "");
685 static_assert(2 == subspan[0], "");
686 static_assert(3 == subspan[1], "");
687 }
688
689 {
690 constexpr auto subspan = span.subspan<2>();
691 static_assert(span.data() + 2 == subspan.data(), "");
692 static_assert(1u == subspan.size(), "");
693 static_assert(1u == decltype(subspan)::extent, "");
694 static_assert(3 == subspan[0], "");
695 }
696
697 {
698 constexpr auto subspan = span.subspan<3>();
699 static_assert(span.data() + 3 == subspan.data(), "");
700 static_assert(subspan.empty(), "");
701 static_assert(0u == decltype(subspan)::extent, "");
702 }
703
704 {
705 constexpr auto subspan = span.subspan<0, 0>();
706 static_assert(span.data() == subspan.data(), "");
707 static_assert(subspan.empty(), "");
708 static_assert(0u == decltype(subspan)::extent, "");
709 }
710
711 {
712 constexpr auto subspan = span.subspan<1, 0>();
713 static_assert(span.data() + 1 == subspan.data(), "");
714 static_assert(subspan.empty(), "");
715 static_assert(0u == decltype(subspan)::extent, "");
716 }
717
718 {
719 constexpr auto subspan = span.subspan<2, 0>();
720 static_assert(span.data() + 2 == subspan.data(), "");
721 static_assert(subspan.empty(), "");
722 static_assert(0u == decltype(subspan)::extent, "");
723 }
724
725 {
726 constexpr auto subspan = span.subspan<0, 1>();
727 static_assert(span.data() == subspan.data(), "");
728 static_assert(1u == subspan.size(), "");
729 static_assert(1u == decltype(subspan)::extent, "");
730 static_assert(1 == subspan[0], "");
731 }
732
733 {
734 constexpr auto subspan = span.subspan<1, 1>();
735 static_assert(span.data() + 1 == subspan.data(), "");
736 static_assert(1u == subspan.size(), "");
737 static_assert(1u == decltype(subspan)::extent, "");
738 static_assert(2 == subspan[0], "");
739 }
740
741 {
742 constexpr auto subspan = span.subspan<2, 1>();
743 static_assert(span.data() + 2 == subspan.data(), "");
744 static_assert(1u == subspan.size(), "");
745 static_assert(1u == decltype(subspan)::extent, "");
746 static_assert(3 == subspan[0], "");
747 }
748
749 {
750 constexpr auto subspan = span.subspan<0, 2>();
751 static_assert(span.data() == subspan.data(), "");
752 static_assert(2u == subspan.size(), "");
753 static_assert(2u == decltype(subspan)::extent, "");
754 static_assert(1 == subspan[0], "");
755 static_assert(2 == subspan[1], "");
756 }
757
758 {
759 constexpr auto subspan = span.subspan<1, 2>();
760 static_assert(span.data() + 1 == subspan.data(), "");
761 static_assert(2u == subspan.size(), "");
762 static_assert(2u == decltype(subspan)::extent, "");
763 static_assert(2 == subspan[0], "");
764 static_assert(3 == subspan[1], "");
765 }
766
767 {
768 constexpr auto subspan = span.subspan<0, 3>();
769 static_assert(span.data() == subspan.data(), "");
770 static_assert(3u == subspan.size(), "");
771 static_assert(3u == decltype(subspan)::extent, "");
772 static_assert(1 == subspan[0], "");
773 static_assert(2 == subspan[1], "");
774 static_assert(3 == subspan[2], "");
775 }
776 }
777
TEST(SpanTest,SubscriptedBeginIterator)778 TEST(SpanTest, SubscriptedBeginIterator) {
779 int array[] = {1, 2, 3};
780 span<const int> const_span(array);
781 for (size_t i = 0; i < const_span.size(); ++i)
782 EXPECT_EQ(array[i], const_span.begin()[i]);
783
784 span<int> mutable_span(array);
785 for (size_t i = 0; i < mutable_span.size(); ++i)
786 EXPECT_EQ(array[i], mutable_span.begin()[i]);
787 }
788
TEST(SpanTest,TemplatedFirstOnDynamicSpan)789 TEST(SpanTest, TemplatedFirstOnDynamicSpan) {
790 int array[] = {1, 2, 3};
791 span<const int> span(array);
792
793 {
794 auto subspan = span.first<0>();
795 EXPECT_EQ(span.data(), subspan.data());
796 EXPECT_EQ(0u, subspan.size());
797 static_assert(0u == decltype(subspan)::extent, "");
798 }
799
800 {
801 auto subspan = span.first<1>();
802 EXPECT_EQ(span.data(), subspan.data());
803 EXPECT_EQ(1u, subspan.size());
804 static_assert(1u == decltype(subspan)::extent, "");
805 EXPECT_EQ(1, subspan[0]);
806 }
807
808 {
809 auto subspan = span.first<2>();
810 EXPECT_EQ(span.data(), subspan.data());
811 EXPECT_EQ(2u, subspan.size());
812 static_assert(2u == decltype(subspan)::extent, "");
813 EXPECT_EQ(1, subspan[0]);
814 EXPECT_EQ(2, subspan[1]);
815 }
816
817 {
818 auto subspan = span.first<3>();
819 EXPECT_EQ(span.data(), subspan.data());
820 EXPECT_EQ(3u, subspan.size());
821 static_assert(3u == decltype(subspan)::extent, "");
822 EXPECT_EQ(1, subspan[0]);
823 EXPECT_EQ(2, subspan[1]);
824 EXPECT_EQ(3, subspan[2]);
825 }
826 }
827
TEST(SpanTest,TemplatedLastOnDynamicSpan)828 TEST(SpanTest, TemplatedLastOnDynamicSpan) {
829 int array[] = {1, 2, 3};
830 span<int> span(array);
831
832 {
833 auto subspan = span.last<0>();
834 EXPECT_EQ(span.data() + 3, subspan.data());
835 EXPECT_EQ(0u, subspan.size());
836 static_assert(0u == decltype(subspan)::extent, "");
837 }
838
839 {
840 auto subspan = span.last<1>();
841 EXPECT_EQ(span.data() + 2, subspan.data());
842 EXPECT_EQ(1u, subspan.size());
843 static_assert(1u == decltype(subspan)::extent, "");
844 EXPECT_EQ(3, subspan[0]);
845 }
846
847 {
848 auto subspan = span.last<2>();
849 EXPECT_EQ(span.data() + 1, subspan.data());
850 EXPECT_EQ(2u, subspan.size());
851 static_assert(2u == decltype(subspan)::extent, "");
852 EXPECT_EQ(2, subspan[0]);
853 EXPECT_EQ(3, subspan[1]);
854 }
855
856 {
857 auto subspan = span.last<3>();
858 EXPECT_EQ(span.data(), subspan.data());
859 EXPECT_EQ(3u, subspan.size());
860 static_assert(3u == decltype(subspan)::extent, "");
861 EXPECT_EQ(1, subspan[0]);
862 EXPECT_EQ(2, subspan[1]);
863 EXPECT_EQ(3, subspan[2]);
864 }
865 }
866
TEST(SpanTest,TemplatedSubspanFromDynamicSpan)867 TEST(SpanTest, TemplatedSubspanFromDynamicSpan) {
868 int array[] = {1, 2, 3};
869 span<int, 3> span(array);
870
871 {
872 auto subspan = span.subspan<0>();
873 EXPECT_EQ(span.data(), subspan.data());
874 static_assert(3u == decltype(subspan)::extent, "");
875 EXPECT_EQ(3u, subspan.size());
876 EXPECT_EQ(1, subspan[0]);
877 EXPECT_EQ(2, subspan[1]);
878 EXPECT_EQ(3, subspan[2]);
879 }
880
881 {
882 auto subspan = span.subspan<1>();
883 EXPECT_EQ(span.data() + 1, subspan.data());
884 EXPECT_EQ(2u, subspan.size());
885 static_assert(2u == decltype(subspan)::extent, "");
886 EXPECT_EQ(2, subspan[0]);
887 EXPECT_EQ(3, subspan[1]);
888 }
889
890 {
891 auto subspan = span.subspan<2>();
892 EXPECT_EQ(span.data() + 2, subspan.data());
893 EXPECT_EQ(1u, subspan.size());
894 static_assert(1u == decltype(subspan)::extent, "");
895 EXPECT_EQ(3, subspan[0]);
896 }
897
898 {
899 auto subspan = span.subspan<3>();
900 EXPECT_EQ(span.data() + 3, subspan.data());
901 EXPECT_EQ(0u, subspan.size());
902 static_assert(0u == decltype(subspan)::extent, "");
903 }
904
905 {
906 auto subspan = span.subspan<0, 0>();
907 EXPECT_EQ(span.data(), subspan.data());
908 EXPECT_EQ(0u, subspan.size());
909 static_assert(0u == decltype(subspan)::extent, "");
910 }
911
912 {
913 auto subspan = span.subspan<1, 0>();
914 EXPECT_EQ(span.data() + 1, subspan.data());
915 EXPECT_EQ(0u, subspan.size());
916 static_assert(0u == decltype(subspan)::extent, "");
917 }
918
919 {
920 auto subspan = span.subspan<2, 0>();
921 EXPECT_EQ(span.data() + 2, subspan.data());
922 EXPECT_EQ(0u, subspan.size());
923 static_assert(0u == decltype(subspan)::extent, "");
924 }
925
926 {
927 auto subspan = span.subspan<0, 1>();
928 EXPECT_EQ(span.data(), subspan.data());
929 EXPECT_EQ(1u, subspan.size());
930 static_assert(1u == decltype(subspan)::extent, "");
931 EXPECT_EQ(1, subspan[0]);
932 }
933
934 {
935 auto subspan = span.subspan<1, 1>();
936 EXPECT_EQ(span.data() + 1, subspan.data());
937 EXPECT_EQ(1u, subspan.size());
938 static_assert(1u == decltype(subspan)::extent, "");
939 EXPECT_EQ(2, subspan[0]);
940 }
941
942 {
943 auto subspan = span.subspan<2, 1>();
944 EXPECT_EQ(span.data() + 2, subspan.data());
945 EXPECT_EQ(1u, subspan.size());
946 static_assert(1u == decltype(subspan)::extent, "");
947 EXPECT_EQ(3, subspan[0]);
948 }
949
950 {
951 auto subspan = span.subspan<0, 2>();
952 EXPECT_EQ(span.data(), subspan.data());
953 EXPECT_EQ(2u, subspan.size());
954 static_assert(2u == decltype(subspan)::extent, "");
955 EXPECT_EQ(1, subspan[0]);
956 EXPECT_EQ(2, subspan[1]);
957 }
958
959 {
960 auto subspan = span.subspan<1, 2>();
961 EXPECT_EQ(span.data() + 1, subspan.data());
962 EXPECT_EQ(2u, subspan.size());
963 static_assert(2u == decltype(subspan)::extent, "");
964 EXPECT_EQ(2, subspan[0]);
965 EXPECT_EQ(3, subspan[1]);
966 }
967
968 {
969 auto subspan = span.subspan<0, 3>();
970 EXPECT_EQ(span.data(), subspan.data());
971 EXPECT_EQ(3u, subspan.size());
972 static_assert(3u == decltype(subspan)::extent, "");
973 EXPECT_EQ(1, subspan[0]);
974 EXPECT_EQ(2, subspan[1]);
975 EXPECT_EQ(3, subspan[2]);
976 }
977 }
978
TEST(SpanTest,First)979 TEST(SpanTest, First) {
980 int array[] = {1, 2, 3};
981 span<int> span(array);
982
983 {
984 auto subspan = span.first(0);
985 EXPECT_EQ(span.data(), subspan.data());
986 EXPECT_EQ(0u, subspan.size());
987 }
988
989 {
990 auto subspan = span.first(1);
991 EXPECT_EQ(span.data(), subspan.data());
992 EXPECT_EQ(1u, subspan.size());
993 EXPECT_EQ(1, subspan[0]);
994 }
995
996 {
997 auto subspan = span.first(2);
998 EXPECT_EQ(span.data(), subspan.data());
999 EXPECT_EQ(2u, subspan.size());
1000 EXPECT_EQ(1, subspan[0]);
1001 EXPECT_EQ(2, subspan[1]);
1002 }
1003
1004 {
1005 auto subspan = span.first(3);
1006 EXPECT_EQ(span.data(), subspan.data());
1007 EXPECT_EQ(3u, subspan.size());
1008 EXPECT_EQ(1, subspan[0]);
1009 EXPECT_EQ(2, subspan[1]);
1010 EXPECT_EQ(3, subspan[2]);
1011 }
1012 }
1013
TEST(SpanTest,Last)1014 TEST(SpanTest, Last) {
1015 int array[] = {1, 2, 3};
1016 span<int> span(array);
1017
1018 {
1019 auto subspan = span.last(0);
1020 EXPECT_EQ(span.data() + 3, subspan.data());
1021 EXPECT_EQ(0u, subspan.size());
1022 }
1023
1024 {
1025 auto subspan = span.last(1);
1026 EXPECT_EQ(span.data() + 2, subspan.data());
1027 EXPECT_EQ(1u, subspan.size());
1028 EXPECT_EQ(3, subspan[0]);
1029 }
1030
1031 {
1032 auto subspan = span.last(2);
1033 EXPECT_EQ(span.data() + 1, subspan.data());
1034 EXPECT_EQ(2u, subspan.size());
1035 EXPECT_EQ(2, subspan[0]);
1036 EXPECT_EQ(3, subspan[1]);
1037 }
1038
1039 {
1040 auto subspan = span.last(3);
1041 EXPECT_EQ(span.data(), subspan.data());
1042 EXPECT_EQ(3u, subspan.size());
1043 EXPECT_EQ(1, subspan[0]);
1044 EXPECT_EQ(2, subspan[1]);
1045 EXPECT_EQ(3, subspan[2]);
1046 }
1047 }
1048
TEST(SpanTest,Subspan)1049 TEST(SpanTest, Subspan) {
1050 int array[] = {1, 2, 3};
1051 span<int> span(array);
1052
1053 {
1054 auto subspan = span.subspan(0);
1055 EXPECT_EQ(span.data(), subspan.data());
1056 EXPECT_EQ(3u, subspan.size());
1057 EXPECT_EQ(1, subspan[0]);
1058 EXPECT_EQ(2, subspan[1]);
1059 EXPECT_EQ(3, subspan[2]);
1060 }
1061
1062 {
1063 auto subspan = span.subspan(1);
1064 EXPECT_EQ(span.data() + 1, subspan.data());
1065 EXPECT_EQ(2u, subspan.size());
1066 EXPECT_EQ(2, subspan[0]);
1067 EXPECT_EQ(3, subspan[1]);
1068 }
1069
1070 {
1071 auto subspan = span.subspan(2);
1072 EXPECT_EQ(span.data() + 2, subspan.data());
1073 EXPECT_EQ(1u, subspan.size());
1074 EXPECT_EQ(3, subspan[0]);
1075 }
1076
1077 {
1078 auto subspan = span.subspan(3);
1079 EXPECT_EQ(span.data() + 3, subspan.data());
1080 EXPECT_EQ(0u, subspan.size());
1081 }
1082
1083 {
1084 auto subspan = span.subspan(0, 0);
1085 EXPECT_EQ(span.data(), subspan.data());
1086 EXPECT_EQ(0u, subspan.size());
1087 }
1088
1089 {
1090 auto subspan = span.subspan(1, 0);
1091 EXPECT_EQ(span.data() + 1, subspan.data());
1092 EXPECT_EQ(0u, subspan.size());
1093 }
1094
1095 {
1096 auto subspan = span.subspan(2, 0);
1097 EXPECT_EQ(span.data() + 2, subspan.data());
1098 EXPECT_EQ(0u, subspan.size());
1099 }
1100
1101 {
1102 auto subspan = span.subspan(0, 1);
1103 EXPECT_EQ(span.data(), subspan.data());
1104 EXPECT_EQ(1u, subspan.size());
1105 EXPECT_EQ(1, subspan[0]);
1106 }
1107
1108 {
1109 auto subspan = span.subspan(1, 1);
1110 EXPECT_EQ(span.data() + 1, subspan.data());
1111 EXPECT_EQ(1u, subspan.size());
1112 EXPECT_EQ(2, subspan[0]);
1113 }
1114
1115 {
1116 auto subspan = span.subspan(2, 1);
1117 EXPECT_EQ(span.data() + 2, subspan.data());
1118 EXPECT_EQ(1u, subspan.size());
1119 EXPECT_EQ(3, subspan[0]);
1120 }
1121
1122 {
1123 auto subspan = span.subspan(0, 2);
1124 EXPECT_EQ(span.data(), subspan.data());
1125 EXPECT_EQ(2u, subspan.size());
1126 EXPECT_EQ(1, subspan[0]);
1127 EXPECT_EQ(2, subspan[1]);
1128 }
1129
1130 {
1131 auto subspan = span.subspan(1, 2);
1132 EXPECT_EQ(span.data() + 1, subspan.data());
1133 EXPECT_EQ(2u, subspan.size());
1134 EXPECT_EQ(2, subspan[0]);
1135 EXPECT_EQ(3, subspan[1]);
1136 }
1137
1138 {
1139 auto subspan = span.subspan(0, 3);
1140 EXPECT_EQ(span.data(), subspan.data());
1141 EXPECT_EQ(span.size(), subspan.size());
1142 EXPECT_EQ(1, subspan[0]);
1143 EXPECT_EQ(2, subspan[1]);
1144 EXPECT_EQ(3, subspan[2]);
1145 }
1146 }
1147
TEST(SpanTest,Size)1148 TEST(SpanTest, Size) {
1149 {
1150 span<int> span;
1151 EXPECT_EQ(0u, span.size());
1152 }
1153
1154 {
1155 int array[] = {1, 2, 3};
1156 span<int> span(array);
1157 EXPECT_EQ(3u, span.size());
1158 }
1159 }
1160
TEST(SpanTest,SizeBytes)1161 TEST(SpanTest, SizeBytes) {
1162 {
1163 span<int> span;
1164 EXPECT_EQ(0u, span.size_bytes());
1165 }
1166
1167 {
1168 int array[] = {1, 2, 3};
1169 span<int> span(array);
1170 EXPECT_EQ(3u * sizeof(int), span.size_bytes());
1171 }
1172 }
1173
TEST(SpanTest,Empty)1174 TEST(SpanTest, Empty) {
1175 {
1176 span<int> span;
1177 EXPECT_TRUE(span.empty());
1178 }
1179
1180 {
1181 int array[] = {1, 2, 3};
1182 span<int> span(array);
1183 EXPECT_FALSE(span.empty());
1184 }
1185 }
1186
TEST(SpanTest,OperatorAt)1187 TEST(SpanTest, OperatorAt) {
1188 static constexpr int kArray[] = {1, 6, 1, 8, 0};
1189 constexpr span<const int> span(kArray);
1190
1191 static_assert(&kArray[0] == &span[0],
1192 "span[0] does not refer to the same element as kArray[0]");
1193 static_assert(&kArray[1] == &span[1],
1194 "span[1] does not refer to the same element as kArray[1]");
1195 static_assert(&kArray[2] == &span[2],
1196 "span[2] does not refer to the same element as kArray[2]");
1197 static_assert(&kArray[3] == &span[3],
1198 "span[3] does not refer to the same element as kArray[3]");
1199 static_assert(&kArray[4] == &span[4],
1200 "span[4] does not refer to the same element as kArray[4]");
1201 }
1202
TEST(SpanTest,Front)1203 TEST(SpanTest, Front) {
1204 static constexpr int kArray[] = {1, 6, 1, 8, 0};
1205 constexpr span<const int> span(kArray);
1206 static_assert(&kArray[0] == &span.front(),
1207 "span.front() does not refer to the same element as kArray[0]");
1208 }
1209
TEST(SpanTest,Back)1210 TEST(SpanTest, Back) {
1211 static constexpr int kArray[] = {1, 6, 1, 8, 0};
1212 constexpr span<const int> span(kArray);
1213 static_assert(&kArray[4] == &span.back(),
1214 "span.back() does not refer to the same element as kArray[4]");
1215 }
1216
1217 // Pigweed: This test uses gMock features not yet supported in Pigweed.
1218 #if 0
1219 TEST(SpanTest, Iterator) {
1220 static constexpr int kArray[] = {1, 6, 1, 8, 0};
1221 constexpr span<const int> span(kArray);
1222
1223 std::vector<int> results;
1224 for (int i : span)
1225 results.emplace_back(i);
1226 EXPECT_THAT(results, ElementsAre(1, 6, 1, 8, 0));
1227 }
1228 #endif // 0
1229
TEST(SpanTest,ConstexprIterator)1230 TEST(SpanTest, ConstexprIterator) {
1231 static constexpr int kArray[] = {1, 6, 1, 8, 0};
1232 constexpr span<const int> span(kArray);
1233
1234 static_assert(
1235 constexpr_equal(
1236 std::begin(kArray), std::end(kArray), span.begin(), span.end()),
1237 "");
1238 static_assert(1 == span.begin()[0], "");
1239 // Pigweed: These tests assume an iterator object, but Pigweed's span uses a
1240 // simple pointer.
1241 #if 0
1242 static_assert(1 == *(span.begin() += 0), "");
1243 static_assert(6 == *(span.begin() += 1), "");
1244
1245 static_assert(1 == *((span.begin() + 1) -= 1), "");
1246 static_assert(6 == *((span.begin() + 1) -= 0), "");
1247 #endif // 0
1248 }
1249
TEST(SpanTest,ReverseIterator)1250 TEST(SpanTest, ReverseIterator) {
1251 static constexpr int kArray[] = {1, 6, 1, 8, 0};
1252 constexpr span<const int> span(kArray);
1253
1254 EXPECT_TRUE(std::equal(
1255 std::rbegin(kArray), std::rend(kArray), span.rbegin(), span.rend()));
1256 EXPECT_TRUE(std::equal(std::crbegin(kArray),
1257 std::crend(kArray),
1258 std::crbegin(span),
1259 std::crend(span)));
1260 }
1261
1262 // Pigweed: These are tests for make_span, which is not included in Pigweed's
1263 // implementation, since class template deduction is available.
1264 #if 0
1265 TEST(SpanTest, AsBytes) {
1266 {
1267 constexpr int kArray[] = {2, 3, 5, 7, 11, 13};
1268 span<const uint8_t, sizeof(kArray)> bytes_span =
1269 as_bytes(make_span(kArray));
1270 EXPECT_EQ(reinterpret_cast<const uint8_t*>(kArray), bytes_span.data());
1271 EXPECT_EQ(sizeof(kArray), bytes_span.size());
1272 EXPECT_EQ(bytes_span.size(), bytes_span.size_bytes());
1273 }
1274
1275 {
1276 std::vector<int> vec = {1, 1, 2, 3, 5, 8};
1277 span<int> mutable_span(vec);
1278 span<const uint8_t> bytes_span = as_bytes(mutable_span);
1279 EXPECT_EQ(reinterpret_cast<const uint8_t*>(vec.data()), bytes_span.data());
1280 EXPECT_EQ(sizeof(int) * vec.size(), bytes_span.size());
1281 EXPECT_EQ(bytes_span.size(), bytes_span.size_bytes());
1282 }
1283 }
1284
1285 TEST(SpanTest, AsWritableBytes) {
1286 std::vector<int> vec = {1, 1, 2, 3, 5, 8};
1287 span<int> mutable_span(vec);
1288 span<uint8_t> writable_bytes_span = as_writable_bytes(mutable_span);
1289 EXPECT_EQ(reinterpret_cast<uint8_t*>(vec.data()), writable_bytes_span.data());
1290 EXPECT_EQ(sizeof(int) * vec.size(), writable_bytes_span.size());
1291 EXPECT_EQ(writable_bytes_span.size(), writable_bytes_span.size_bytes());
1292
1293 // Set the first entry of vec to zero while writing through the span.
1294 std::fill(writable_bytes_span.data(),
1295 writable_bytes_span.data() + sizeof(int), 0);
1296 EXPECT_EQ(0, vec[0]);
1297 }
1298
1299 TEST(SpanTest, MakeSpanFromDataAndSize) {
1300 int* nullint = nullptr;
1301 auto empty_span = make_span(nullint, 0);
1302 EXPECT_TRUE(empty_span.empty());
1303 EXPECT_EQ(nullptr, empty_span.data());
1304
1305 std::vector<int> vector = {1, 1, 2, 3, 5, 8};
1306 span<int> expected_span(vector.data(), vector.size());
1307 auto made_span = make_span(vector.data(), vector.size());
1308 EXPECT_EQ(expected_span.data(), made_span.data());
1309 EXPECT_EQ(expected_span.size(), made_span.size());
1310 static_assert(decltype(made_span)::extent == dynamic_extent, "");
1311 static_assert(
1312 std::is_same<decltype(expected_span), decltype(made_span)>::value,
1313 "the type of made_span differs from expected_span!");
1314 }
1315
1316 TEST(SpanTest, MakeSpanFromPointerPair) {
1317 int* nullint = nullptr;
1318 auto empty_span = make_span(nullint, nullint);
1319 EXPECT_TRUE(empty_span.empty());
1320 EXPECT_EQ(nullptr, empty_span.data());
1321
1322 std::vector<int> vector = {1, 1, 2, 3, 5, 8};
1323 span<int> expected_span(vector.data(), vector.size());
1324 auto made_span = make_span(vector.data(), vector.data() + vector.size());
1325 EXPECT_EQ(expected_span.data(), made_span.data());
1326 EXPECT_EQ(expected_span.size(), made_span.size());
1327 static_assert(decltype(made_span)::extent == dynamic_extent, "");
1328 static_assert(
1329 std::is_same<decltype(expected_span), decltype(made_span)>::value,
1330 "the type of made_span differs from expected_span!");
1331 }
1332
1333 TEST(SpanTest, MakeSpanFromConstexprArray) {
1334 static constexpr int kArray[] = {1, 2, 3, 4, 5};
1335 constexpr span<const int, 5> expected_span(kArray);
1336 constexpr auto made_span = make_span(kArray);
1337 EXPECT_EQ(expected_span.data(), made_span.data());
1338 EXPECT_EQ(expected_span.size(), made_span.size());
1339 static_assert(decltype(made_span)::extent == 5, "");
1340 static_assert(
1341 std::is_same<decltype(expected_span), decltype(made_span)>::value,
1342 "the type of made_span differs from expected_span!");
1343 }
1344
1345 TEST(SpanTest, MakeSpanFromStdArray) {
1346 const std::array<int, 5> kArray = {{1, 2, 3, 4, 5}};
1347 span<const int, 5> expected_span(kArray);
1348 auto made_span = make_span(kArray);
1349 EXPECT_EQ(expected_span.data(), made_span.data());
1350 EXPECT_EQ(expected_span.size(), made_span.size());
1351 static_assert(decltype(made_span)::extent == 5, "");
1352 static_assert(
1353 std::is_same<decltype(expected_span), decltype(made_span)>::value,
1354 "the type of made_span differs from expected_span!");
1355 }
1356
1357 TEST(SpanTest, MakeSpanFromConstContainer) {
1358 const std::vector<int> vector = {-1, -2, -3, -4, -5};
1359 span<const int> expected_span(vector);
1360 auto made_span = make_span(vector);
1361 EXPECT_EQ(expected_span.data(), made_span.data());
1362 EXPECT_EQ(expected_span.size(), made_span.size());
1363 static_assert(decltype(made_span)::extent == dynamic_extent, "");
1364 static_assert(
1365 std::is_same<decltype(expected_span), decltype(made_span)>::value,
1366 "the type of made_span differs from expected_span!");
1367 }
1368
1369 TEST(SpanTest, MakeStaticSpanFromConstContainer) {
1370 const std::vector<int> vector = {-1, -2, -3, -4, -5};
1371 span<const int, 5> expected_span(vector.data(), vector.size());
1372 auto made_span = make_span<5>(vector);
1373 EXPECT_EQ(expected_span.data(), made_span.data());
1374 EXPECT_EQ(expected_span.size(), made_span.size());
1375 static_assert(decltype(made_span)::extent == 5, "");
1376 static_assert(
1377 std::is_same<decltype(expected_span), decltype(made_span)>::value,
1378 "the type of made_span differs from expected_span!");
1379 }
1380
1381 TEST(SpanTest, MakeSpanFromContainer) {
1382 std::vector<int> vector = {-1, -2, -3, -4, -5};
1383 span<int> expected_span(vector);
1384 auto made_span = make_span(vector);
1385 EXPECT_EQ(expected_span.data(), made_span.data());
1386 EXPECT_EQ(expected_span.size(), made_span.size());
1387 static_assert(decltype(made_span)::extent == dynamic_extent, "");
1388 static_assert(
1389 std::is_same<decltype(expected_span), decltype(made_span)>::value,
1390 "the type of made_span differs from expected_span!");
1391 }
1392
1393 TEST(SpanTest, MakeStaticSpanFromContainer) {
1394 std::vector<int> vector = {-1, -2, -3, -4, -5};
1395 span<int, 5> expected_span(vector.data(), vector.size());
1396 auto made_span = make_span<5>(vector);
1397 EXPECT_EQ(expected_span.data(), make_span<5>(vector).data());
1398 EXPECT_EQ(expected_span.size(), make_span<5>(vector).size());
1399 static_assert(decltype(make_span<5>(vector))::extent == 5, "");
1400 static_assert(
1401 std::is_same<decltype(expected_span), decltype(made_span)>::value,
1402 "the type of made_span differs from expected_span!");
1403 }
1404
1405 TEST(SpanTest, MakeStaticSpanFromConstexprContainer) {
1406 constexpr StringPiece str = "Hello, World";
1407 constexpr auto made_span = make_span<12>(str);
1408 static_assert(str.data() == made_span.data(), "Error: data() does not match");
1409 static_assert(str.size() == made_span.size(), "Error: size() does not match");
1410 static_assert(std::is_same<decltype(str)::value_type,
1411 decltype(made_span)::value_type>::value,
1412 "Error: value_type does not match");
1413 static_assert(str.size() == decltype(made_span)::extent,
1414 "Error: extent does not match");
1415 }
1416
1417 TEST(SpanTest, MakeSpanFromRValueContainer) {
1418 std::vector<int> vector = {-1, -2, -3, -4, -5};
1419 span<const int> expected_span(vector);
1420 // Note: While static_cast<T&&>(foo) is effectively just a fancy spelling of
1421 // std::move(foo), make_span does not actually take ownership of the passed in
1422 // container. Writing it this way makes it more obvious that we simply care
1423 // about the right behavour when passing rvalues.
1424 auto made_span = make_span(static_cast<std::vector<int>&&>(vector));
1425 EXPECT_EQ(expected_span.data(), made_span.data());
1426 EXPECT_EQ(expected_span.size(), made_span.size());
1427 static_assert(decltype(made_span)::extent == dynamic_extent, "");
1428 static_assert(
1429 std::is_same<decltype(expected_span), decltype(made_span)>::value,
1430 "the type of made_span differs from expected_span!");
1431 }
1432
1433 TEST(SpanTest, MakeStaticSpanFromRValueContainer) {
1434 std::vector<int> vector = {-1, -2, -3, -4, -5};
1435 span<const int, 5> expected_span(vector.data(), vector.size());
1436 // Note: While static_cast<T&&>(foo) is effectively just a fancy spelling of
1437 // std::move(foo), make_span does not actually take ownership of the passed in
1438 // container. Writing it this way makes it more obvious that we simply care
1439 // about the right behavour when passing rvalues.
1440 auto made_span = make_span<5>(static_cast<std::vector<int>&&>(vector));
1441 EXPECT_EQ(expected_span.data(), made_span.data());
1442 EXPECT_EQ(expected_span.size(), made_span.size());
1443 static_assert(decltype(made_span)::extent == 5, "");
1444 static_assert(
1445 std::is_same<decltype(expected_span), decltype(made_span)>::value,
1446 "the type of made_span differs from expected_span!");
1447 }
1448
1449 TEST(SpanTest, MakeSpanFromDynamicSpan) {
1450 static constexpr int kArray[] = {1, 2, 3, 4, 5};
1451 constexpr span<const int> expected_span(kArray);
1452 constexpr auto made_span = make_span(expected_span);
1453 static_assert(std::is_same<decltype(expected_span)::element_type,
1454 decltype(made_span)::element_type>::value,
1455 "make_span(span) should have the same element_type as span");
1456
1457 static_assert(expected_span.data() == made_span.data(),
1458 "make_span(span) should have the same data() as span");
1459
1460 static_assert(expected_span.size() == made_span.size(),
1461 "make_span(span) should have the same size() as span");
1462
1463 static_assert(decltype(made_span)::extent == decltype(expected_span)::extent,
1464 "make_span(span) should have the same extent as span");
1465
1466 static_assert(
1467 std::is_same<decltype(expected_span), decltype(made_span)>::value,
1468 "the type of made_span differs from expected_span!");
1469 }
1470
1471 TEST(SpanTest, MakeSpanFromStaticSpan) {
1472 static constexpr int kArray[] = {1, 2, 3, 4, 5};
1473 constexpr span<const int, 5> expected_span(kArray);
1474 constexpr auto made_span = make_span(expected_span);
1475 static_assert(std::is_same<decltype(expected_span)::element_type,
1476 decltype(made_span)::element_type>::value,
1477 "make_span(span) should have the same element_type as span");
1478
1479 static_assert(expected_span.data() == made_span.data(),
1480 "make_span(span) should have the same data() as span");
1481
1482 static_assert(expected_span.size() == made_span.size(),
1483 "make_span(span) should have the same size() as span");
1484
1485 static_assert(decltype(made_span)::extent == decltype(expected_span)::extent,
1486 "make_span(span) should have the same extent as span");
1487
1488 static_assert(
1489 std::is_same<decltype(expected_span), decltype(made_span)>::value,
1490 "the type of made_span differs from expected_span!");
1491 }
1492 #endif // 0
1493
TEST(SpanTest,EnsureConstexprGoodness)1494 TEST(SpanTest, EnsureConstexprGoodness) {
1495 static constexpr int kArray[] = {5, 4, 3, 2, 1};
1496 constexpr span<const int> constexpr_span(kArray);
1497 const size_t size = 2;
1498
1499 const size_t start = 1;
1500 constexpr span<const int> subspan =
1501 constexpr_span.subspan(start, start + size);
1502 for (size_t i = 0; i < subspan.size(); ++i)
1503 EXPECT_EQ(kArray[start + i], subspan[i]);
1504
1505 constexpr span<const int> firsts = constexpr_span.first(size);
1506 for (size_t i = 0; i < firsts.size(); ++i)
1507 EXPECT_EQ(kArray[i], firsts[i]);
1508
1509 constexpr span<const int> lasts = constexpr_span.last(size);
1510 for (size_t i = 0; i < lasts.size(); ++i) {
1511 const size_t j = (std::size(kArray) - size) + i;
1512 EXPECT_EQ(kArray[j], lasts[i]);
1513 }
1514
1515 constexpr int item = constexpr_span[size];
1516 EXPECT_EQ(kArray[size], item);
1517 }
1518
1519 #if 0
1520
1521 // Pigweed: Death tests are not yet supported.
1522 TEST(SpanTest, OutOfBoundsDeath) {
1523 constexpr span<int, 0> kEmptySpan;
1524 ASSERT_DEATH_IF_SUPPORTED(kEmptySpan[0], "");
1525 ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.first(1), "");
1526 ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.last(1), "");
1527 ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.subspan(1), "");
1528
1529 constexpr span<int> kEmptyDynamicSpan;
1530 ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan[0], "");
1531 ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.front(), "");
1532 ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.first(1), "");
1533 ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.last(1), "");
1534 ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.back(), "");
1535 ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.subspan(1), "");
1536
1537 static constexpr int kArray[] = {0, 1, 2};
1538 constexpr span<const int> kNonEmptyDynamicSpan(kArray);
1539 EXPECT_EQ(3U, kNonEmptyDynamicSpan.size());
1540 ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan[4], "");
1541 ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.subspan(10), "");
1542 ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.subspan(1, 7), "");
1543 }
1544
1545 // Pigweed: These tests use CheckedContiguousConstIterator, which isn't used in
1546 // Pigweed's version.
1547 TEST(SpanTest, IteratorIsRangeMoveSafe) {
1548 static constexpr int kArray[] = {1, 6, 1, 8, 0};
1549 const size_t kNumElements = 5;
1550 constexpr span<const int> span(kArray);
1551
1552 static constexpr int kOverlappingStartIndexes[] = {-4, 0, 3, 4};
1553 static constexpr int kNonOverlappingStartIndexes[] = {-7, -5, 5, 7};
1554
1555 // Overlapping ranges.
1556 for (const int dest_start_index : kOverlappingStartIndexes) {
1557 EXPECT_FALSE(CheckedContiguousIterator<const int>::IsRangeMoveSafe(
1558 span.begin(), span.end(),
1559 CheckedContiguousIterator<const int>(
1560 span.data() + dest_start_index,
1561 span.data() + dest_start_index + kNumElements)));
1562 EXPECT_FALSE(CheckedContiguousConstIterator<const int>::IsRangeMoveSafe(
1563 std::cbegin(span), std::cend(span),
1564 CheckedContiguousConstIterator<const int>(
1565 span.data() + dest_start_index,
1566 span.data() + dest_start_index + kNumElements)));
1567 }
1568
1569 // Non-overlapping ranges.
1570 for (const int dest_start_index : kNonOverlappingStartIndexes) {
1571 EXPECT_TRUE(CheckedContiguousIterator<const int>::IsRangeMoveSafe(
1572 span.begin(), span.end(),
1573 CheckedContiguousIterator<const int>(
1574 span.data() + dest_start_index,
1575 span.data() + dest_start_index + kNumElements)));
1576 EXPECT_TRUE(CheckedContiguousConstIterator<const int>::IsRangeMoveSafe(
1577 std::cbegin(span), std::cend(span),
1578 CheckedContiguousConstIterator<const int>(
1579 span.data() + dest_start_index,
1580 span.data() + dest_start_index + kNumElements)));
1581 }
1582
1583 // IsRangeMoveSafe is true if the length to be moved is 0.
1584 EXPECT_TRUE(CheckedContiguousIterator<const int>::IsRangeMoveSafe(
1585 span.begin(), span.begin(),
1586 CheckedContiguousIterator<const int>(span.data(), span.data())));
1587 EXPECT_TRUE(CheckedContiguousConstIterator<const int>::IsRangeMoveSafe(
1588 std::cbegin(span), std::cbegin(span),
1589 CheckedContiguousConstIterator<const int>(span.data(), span.data())));
1590
1591 // IsRangeMoveSafe is false if end < begin.
1592 EXPECT_FALSE(CheckedContiguousIterator<const int>::IsRangeMoveSafe(
1593 span.end(), span.begin(),
1594 CheckedContiguousIterator<const int>(span.data(), span.data())));
1595 EXPECT_FALSE(CheckedContiguousConstIterator<const int>::IsRangeMoveSafe(
1596 std::cend(span), std::cbegin(span),
1597 CheckedContiguousConstIterator<const int>(span.data(), span.data())));
1598 }
1599
1600 // Pigweed: gMock matchers are not yet supported.
1601 TEST(SpanTest, Sort) {
1602 int array[] = {5, 4, 3, 2, 1};
1603
1604 span<int> dynamic_span = array;
1605 std::sort(dynamic_span.begin(), dynamic_span.end());
1606 EXPECT_THAT(array, ElementsAre(1, 2, 3, 4, 5));
1607 std::sort(dynamic_span.rbegin(), dynamic_span.rend());
1608 EXPECT_THAT(array, ElementsAre(5, 4, 3, 2, 1));
1609
1610 span<int, 5> static_span = array;
1611 std::sort(static_span.rbegin(), static_span.rend(), std::greater<>());
1612 EXPECT_THAT(array, ElementsAre(1, 2, 3, 4, 5));
1613 std::sort(static_span.begin(), static_span.end(), std::greater<>());
1614 EXPECT_THAT(array, ElementsAre(5, 4, 3, 2, 1));
1615 }
1616 #endif // 0
1617
TEST(SpanTest,SpanExtentConversions)1618 TEST(SpanTest, SpanExtentConversions) {
1619 // Statically checks that various conversions between spans of dynamic and
1620 // static extent are possible or not.
1621
1622 // This test fails with the real C++20 std::span, so skip it.
1623 // static_assert(
1624 // !std::is_constructible<span<int, 0>, span<int>>::value,
1625 // "Error: static span should not be constructible from dynamic span");
1626
1627 static_assert(!std::is_constructible<span<int, 2>, span<int, 1>>::value,
1628 "Error: static span should not be constructible from static "
1629 "span with different extent");
1630
1631 static_assert(std::is_convertible<span<int, 0>, span<int>>::value,
1632 "Error: static span should be convertible to dynamic span");
1633
1634 static_assert(std::is_convertible<span<int>, span<int>>::value,
1635 "Error: dynamic span should be convertible to dynamic span");
1636
1637 static_assert(std::is_convertible<span<int, 2>, span<int, 2>>::value,
1638 "Error: static span should be convertible to static span");
1639 }
1640
TEST(SpanTest,IteratorConversions)1641 TEST(SpanTest, IteratorConversions) {
1642 static_assert(std::is_convertible<span<int>::iterator,
1643 span<const int>::iterator>::value,
1644 "Error: iterator should be convertible to const iterator");
1645
1646 static_assert(!std::is_convertible<span<const int>::iterator,
1647 span<int>::iterator>::value,
1648 "Error: const iterator should not be convertible to iterator");
1649 }
1650
1651 // NOLINTEND(modernize-unary-static-assert)
1652
1653 } // namespace pw
1654