Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/mfbt/tests/gtest/TestSpan.cpp
Line
Count
Source (jump to first uncovered line)
1
///////////////////////////////////////////////////////////////////////////////
2
//
3
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
4
//
5
// This code is licensed under the MIT License (MIT).
6
//
7
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
10
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
11
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
12
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
13
// THE SOFTWARE.
14
//
15
///////////////////////////////////////////////////////////////////////////////
16
17
// Adapted from https://github.com/Microsoft/GSL/blob/3819df6e378ffccf0e29465afe99c3b324c2aa70/tests/Span_tests.cpp
18
19
#include "gtest/gtest.h"
20
21
#include "mozilla/Span.h"
22
23
#include "nsString.h"
24
#include "nsTArray.h"
25
#include "mozilla/Range.h"
26
#include "mozilla/TypeTraits.h"
27
28
#define SPAN_TEST(name) TEST(SpanTest, name)
29
#define CHECK_THROW(a, b)
30
31
using namespace std;
32
using namespace mozilla;
33
34
static_assert(IsConvertible<Range<int>, Span<const int>>::value,
35
              "Range should convert into const");
36
static_assert(IsConvertible<Range<const int>, Span<const int>>::value,
37
              "const Range should convert into const");
38
static_assert(!IsConvertible<Range<const int>, Span<int>>::value,
39
              "Range should not drop const in conversion");
40
static_assert(IsConvertible<Span<int>, Range<const int>>::value,
41
              "Span should convert into const");
42
static_assert(IsConvertible<Span<const int>, Range<const int>>::value,
43
              "const Span should convert into const");
44
static_assert(!IsConvertible<Span<const int>, Range<int>>::value,
45
              "Span should not drop const in conversion");
46
static_assert(IsConvertible<Span<const int>, Span<const int>>::value,
47
              "const Span should convert into const");
48
static_assert(IsConvertible<Span<int>, Span<const int>>::value,
49
              "Span should convert into const");
50
static_assert(!IsConvertible<Span<const int>, Span<int>>::value,
51
              "Span should not drop const in conversion");
52
static_assert(IsConvertible<const nsTArray<int>, Span<const int>>::value,
53
              "const nsTArray should convert into const");
54
static_assert(IsConvertible<nsTArray<int>, Span<const int>>::value,
55
              "nsTArray should convert into const");
56
static_assert(!IsConvertible<const nsTArray<int>, Span<int>>::value,
57
              "nsTArray should not drop const in conversion");
58
static_assert(IsConvertible<nsTArray<const int>, Span<const int>>::value,
59
              "nsTArray should convert into const");
60
static_assert(!IsConvertible<nsTArray<const int>, Span<int>>::value,
61
              "nsTArray should not drop const in conversion");
62
63
/**
64
 * Rust slice-compatible nullptr replacement value.
65
 */
66
#define SLICE_CONST_INT_PTR reinterpret_cast<const int*>(alignof(const int))
67
68
/**
69
 * Rust slice-compatible nullptr replacement value.
70
 */
71
#define SLICE_INT_PTR reinterpret_cast<int*>(alignof(int))
72
73
/**
74
 * Rust slice-compatible nullptr replacement value.
75
 */
76
#define SLICE_CONST_INT_PTR_PTR reinterpret_cast<const int**>(alignof(const int*))
77
78
/**
79
 * Rust slice-compatible nullptr replacement value.
80
 */
81
#define SLICE_INT_PTR_PTR reinterpret_cast<int**>(alignof(int *))
82
83
namespace {
84
struct BaseClass
85
{
86
};
87
struct DerivedClass : BaseClass
88
{
89
};
90
}
91
92
void
93
AssertSpanOfThreeInts(Span<const int> s)
94
0
{
95
0
  ASSERT_EQ(s.size(), 3U);
96
0
  ASSERT_EQ(s[0], 1);
97
0
  ASSERT_EQ(s[1], 2);
98
0
  ASSERT_EQ(s[2], 3);
99
0
}
100
101
void
102
AssertSpanOfThreeChars(Span<const char> s)
103
0
{
104
0
  ASSERT_EQ(s.size(), 3U);
105
0
  ASSERT_EQ(s[0], 'a');
106
0
  ASSERT_EQ(s[1], 'b');
107
0
  ASSERT_EQ(s[2], 'c');
108
0
}
109
110
void
111
AssertSpanOfThreeChar16s(Span<const char16_t> s)
112
0
{
113
0
  ASSERT_EQ(s.size(), 3U);
114
0
  ASSERT_EQ(s[0], 'a');
115
0
  ASSERT_EQ(s[1], 'b');
116
0
  ASSERT_EQ(s[2], 'c');
117
0
}
118
119
void
120
AssertSpanOfThreeCharsViaString(const nsACString& aStr)
121
0
{
122
0
  AssertSpanOfThreeChars(aStr);
123
0
}
124
125
void
126
AssertSpanOfThreeChar16sViaString(const nsAString& aStr)
127
0
{
128
0
  AssertSpanOfThreeChar16s(aStr);
129
0
}
130
131
SPAN_TEST(default_constructor)
132
0
{
133
0
  {
134
0
    Span<int> s;
135
0
    ASSERT_EQ(s.Length(), 0U);
136
0
    ASSERT_EQ(s.data(), SLICE_INT_PTR);
137
0
138
0
    Span<const int> cs;
139
0
    ASSERT_EQ(cs.Length(), 0U);
140
0
    ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR);
141
0
  }
142
0
143
0
  {
144
0
    Span<int, 0> s;
145
0
    ASSERT_EQ(s.Length(), 0U);
146
0
    ASSERT_EQ(s.data(), SLICE_INT_PTR);
147
0
148
0
    Span<const int, 0> cs;
149
0
    ASSERT_EQ(cs.Length(), 0U);
150
0
    ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR);
151
0
  }
152
0
153
0
  {
154
#ifdef CONFIRM_COMPILATION_ERRORS
155
    Span<int, 1> s;
156
    ASSERT_EQ(s.Length(), 1U);
157
    ASSERT_EQ(s.data(), SLICE_INT_PTR); // explains why it can't compile
158
#endif
159
  }
160
0
161
0
  {
162
0
    Span<int> s{};
163
0
    ASSERT_EQ(s.Length(), 0U);
164
0
    ASSERT_EQ(s.data(), SLICE_INT_PTR);
165
0
166
0
    Span<const int> cs{};
167
0
    ASSERT_EQ(cs.Length(), 0U);
168
0
    ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR);
169
0
  }
170
0
}
171
172
SPAN_TEST(size_optimization)
173
0
{
174
0
  {
175
0
    Span<int> s;
176
0
    ASSERT_EQ(sizeof(s), sizeof(int*) + sizeof(size_t));
177
0
  }
178
0
179
0
  {
180
0
    Span<int, 0> s;
181
0
    ASSERT_EQ(sizeof(s), sizeof(int*));
182
0
  }
183
0
}
184
185
SPAN_TEST(from_nullptr_constructor)
186
0
{
187
0
  {
188
0
    Span<int> s = nullptr;
189
0
    ASSERT_EQ(s.Length(), 0U);
190
0
    ASSERT_EQ(s.data(), SLICE_INT_PTR);
191
0
192
0
    Span<const int> cs = nullptr;
193
0
    ASSERT_EQ(cs.Length(), 0U);
194
0
    ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR);
195
0
  }
196
0
197
0
  {
198
0
    Span<int, 0> s = nullptr;
199
0
    ASSERT_EQ(s.Length(), 0U);
200
0
    ASSERT_EQ(s.data(), SLICE_INT_PTR);
201
0
202
0
    Span<const int, 0> cs = nullptr;
203
0
    ASSERT_EQ(cs.Length(), 0U);
204
0
    ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR);
205
0
  }
206
0
207
0
  {
208
#ifdef CONFIRM_COMPILATION_ERRORS
209
    Span<int, 1> s = nullptr;
210
    ASSERT_EQ(s.Length(), 1U);
211
    ASSERT_EQ(s.data(), SLICE_INT_PTR); // explains why it can't compile
212
#endif
213
  }
214
0
215
0
  {
216
0
    Span<int> s{ nullptr };
217
0
    ASSERT_EQ(s.Length(), 0U);
218
0
    ASSERT_EQ(s.data(), SLICE_INT_PTR);
219
0
220
0
    Span<const int> cs{ nullptr };
221
0
    ASSERT_EQ(cs.Length(), 0U);
222
0
    ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR);
223
0
  }
224
0
225
0
  {
226
0
    Span<int*> s{ nullptr };
227
0
    ASSERT_EQ(s.Length(), 0U);
228
0
    ASSERT_EQ(s.data(), SLICE_INT_PTR_PTR);
229
0
230
0
    Span<const int*> cs{ nullptr };
231
0
    ASSERT_EQ(cs.Length(), 0U);
232
0
    ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR_PTR);
233
0
  }
234
0
}
235
236
SPAN_TEST(from_nullptr_length_constructor)
237
0
{
238
0
  {
239
0
    Span<int> s{ nullptr, static_cast<Span<int>::index_type>(0) };
240
0
    ASSERT_EQ(s.Length(), 0U);
241
0
    ASSERT_EQ(s.data(), SLICE_INT_PTR);
242
0
243
0
    Span<const int> cs{ nullptr, static_cast<Span<int>::index_type>(0) };
244
0
    ASSERT_EQ(cs.Length(), 0U);
245
0
    ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR);
246
0
  }
247
0
248
0
  {
249
0
    Span<int, 0> s{ nullptr, static_cast<Span<int>::index_type>(0) };
250
0
    ASSERT_EQ(s.Length(), 0U);
251
0
    ASSERT_EQ(s.data(), SLICE_INT_PTR);
252
0
253
0
    Span<const int, 0> cs{ nullptr, static_cast<Span<int>::index_type>(0) };
254
0
    ASSERT_EQ(cs.Length(), 0U);
255
0
    ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR);
256
0
  }
257
0
258
#if 0
259
        {
260
            auto workaround_macro = []() { Span<int, 1> s{ nullptr, static_cast<Span<int>::index_type>(0) }; };
261
            CHECK_THROW(workaround_macro(), fail_fast);
262
        }
263
264
        {
265
            auto workaround_macro = []() { Span<int> s{nullptr, 1}; };
266
            CHECK_THROW(workaround_macro(), fail_fast);
267
268
            auto const_workaround_macro = []() { Span<const int> cs{nullptr, 1}; };
269
            CHECK_THROW(const_workaround_macro(), fail_fast);
270
        }
271
272
        {
273
            auto workaround_macro = []() { Span<int, 0> s{nullptr, 1}; };
274
            CHECK_THROW(workaround_macro(), fail_fast);
275
276
            auto const_workaround_macro = []() { Span<const int, 0> s{nullptr, 1}; };
277
            CHECK_THROW(const_workaround_macro(), fail_fast);
278
        }
279
#endif
280
0
  {
281
0
    Span<int*> s{ nullptr, static_cast<Span<int>::index_type>(0) };
282
0
    ASSERT_EQ(s.Length(), 0U);
283
0
    ASSERT_EQ(s.data(), SLICE_INT_PTR_PTR);
284
0
285
0
    Span<const int*> cs{ nullptr, static_cast<Span<int>::index_type>(0) };
286
0
    ASSERT_EQ(cs.Length(), 0U);
287
0
    ASSERT_EQ(cs.data(), SLICE_CONST_INT_PTR_PTR);
288
0
  }
289
0
}
290
291
SPAN_TEST(from_pointer_length_constructor)
292
0
{
293
0
  int arr[4] = { 1, 2, 3, 4 };
294
0
295
0
  {
296
0
    Span<int> s{ &arr[0], 2 };
297
0
    ASSERT_EQ(s.Length(), 2U);
298
0
    ASSERT_EQ(s.data(), &arr[0]);
299
0
    ASSERT_EQ(s[0], 1);
300
0
    ASSERT_EQ(s[1], 2);
301
0
  }
302
0
303
0
  {
304
0
    Span<int, 2> s{ &arr[0], 2 };
305
0
    ASSERT_EQ(s.Length(), 2U);
306
0
    ASSERT_EQ(s.data(), &arr[0]);
307
0
    ASSERT_EQ(s[0], 1);
308
0
    ASSERT_EQ(s[1], 2);
309
0
  }
310
0
311
0
  {
312
0
    int* p = nullptr;
313
0
    Span<int> s{ p, static_cast<Span<int>::index_type>(0) };
314
0
    ASSERT_EQ(s.Length(), 0U);
315
0
    ASSERT_EQ(s.data(), SLICE_INT_PTR);
316
0
  }
317
0
318
#if 0
319
        {
320
            int* p = nullptr;
321
            auto workaround_macro = [=]() { Span<int> s{p, 2}; };
322
            CHECK_THROW(workaround_macro(), fail_fast);
323
        }
324
#endif
325
326
0
  {
327
0
    auto s = MakeSpan(&arr[0], 2);
328
0
    ASSERT_EQ(s.Length(), 2U);
329
0
    ASSERT_EQ(s.data(), &arr[0]);
330
0
    ASSERT_EQ(s[0], 1);
331
0
    ASSERT_EQ(s[1], 2);
332
0
  }
333
0
334
0
  {
335
0
    int* p = nullptr;
336
0
    auto s = MakeSpan(p, static_cast<Span<int>::index_type>(0));
337
0
    ASSERT_EQ(s.Length(), 0U);
338
0
    ASSERT_EQ(s.data(), SLICE_INT_PTR);
339
0
  }
340
0
341
#if 0
342
        {
343
            int* p = nullptr;
344
            auto workaround_macro = [=]() { MakeSpan(p, 2); };
345
            CHECK_THROW(workaround_macro(), fail_fast);
346
        }
347
#endif
348
}
349
350
SPAN_TEST(from_pointer_pointer_constructor)
351
0
{
352
0
  int arr[4] = { 1, 2, 3, 4 };
353
0
354
0
  {
355
0
    Span<int> s{ &arr[0], &arr[2] };
356
0
    ASSERT_EQ(s.Length(), 2U);
357
0
    ASSERT_EQ(s.data(), &arr[0]);
358
0
    ASSERT_EQ(s[0], 1);
359
0
    ASSERT_EQ(s[1], 2);
360
0
  }
361
0
362
0
  {
363
0
    Span<int, 2> s{ &arr[0], &arr[2] };
364
0
    ASSERT_EQ(s.Length(), 2U);
365
0
    ASSERT_EQ(s.data(), &arr[0]);
366
0
    ASSERT_EQ(s[0], 1);
367
0
    ASSERT_EQ(s[1], 2);
368
0
  }
369
0
370
0
  {
371
0
    Span<int> s{ &arr[0], &arr[0] };
372
0
    ASSERT_EQ(s.Length(), 0U);
373
0
    ASSERT_EQ(s.data(), &arr[0]);
374
0
  }
375
0
376
0
  {
377
0
    Span<int, 0> s{ &arr[0], &arr[0] };
378
0
    ASSERT_EQ(s.Length(), 0U);
379
0
    ASSERT_EQ(s.data(), &arr[0]);
380
0
  }
381
0
382
0
  // this will fail the std::distance() precondition, which asserts on MSVC debug builds
383
0
  //{
384
0
  //    auto workaround_macro = [&]() { Span<int> s{&arr[1], &arr[0]}; };
385
0
  //    CHECK_THROW(workaround_macro(), fail_fast);
386
0
  //}
387
0
388
0
  // this will fail the std::distance() precondition, which asserts on MSVC debug builds
389
0
  //{
390
0
  //    int* p = nullptr;
391
0
  //    auto workaround_macro = [&]() { Span<int> s{&arr[0], p}; };
392
0
  //    CHECK_THROW(workaround_macro(), fail_fast);
393
0
  //}
394
0
395
0
  {
396
0
    int* p = nullptr;
397
0
    Span<int> s{ p, p };
398
0
    ASSERT_EQ(s.Length(), 0U);
399
0
    ASSERT_EQ(s.data(), SLICE_INT_PTR);
400
0
  }
401
0
402
0
  {
403
0
    int* p = nullptr;
404
0
    Span<int, 0> s{ p, p };
405
0
    ASSERT_EQ(s.Length(), 0U);
406
0
    ASSERT_EQ(s.data(), SLICE_INT_PTR);
407
0
  }
408
0
409
0
  // this will fail the std::distance() precondition, which asserts on MSVC debug builds
410
0
  //{
411
0
  //    int* p = nullptr;
412
0
  //    auto workaround_macro = [&]() { Span<int> s{&arr[0], p}; };
413
0
  //    CHECK_THROW(workaround_macro(), fail_fast);
414
0
  //}
415
0
416
0
  {
417
0
    auto s = MakeSpan(&arr[0], &arr[2]);
418
0
    ASSERT_EQ(s.Length(), 2U);
419
0
    ASSERT_EQ(s.data(), &arr[0]);
420
0
    ASSERT_EQ(s[0], 1);
421
0
    ASSERT_EQ(s[1], 2);
422
0
  }
423
0
424
0
  {
425
0
    auto s = MakeSpan(&arr[0], &arr[0]);
426
0
    ASSERT_EQ(s.Length(), 0U);
427
0
    ASSERT_EQ(s.data(), &arr[0]);
428
0
  }
429
0
430
0
  {
431
0
    int* p = nullptr;
432
0
    auto s = MakeSpan(p, p);
433
0
    ASSERT_EQ(s.Length(), 0U);
434
0
    ASSERT_EQ(s.data(), SLICE_INT_PTR);
435
0
  }
436
0
}
437
438
SPAN_TEST(from_array_constructor)
439
0
{
440
0
  int arr[5] = { 1, 2, 3, 4, 5 };
441
0
442
0
  {
443
0
    Span<int> s{ arr };
444
0
    ASSERT_EQ(s.Length(), 5U);
445
0
    ASSERT_EQ(s.data(), &arr[0]);
446
0
  }
447
0
448
0
  {
449
0
    Span<int, 5> s{ arr };
450
0
    ASSERT_EQ(s.Length(), 5U);
451
0
    ASSERT_EQ(s.data(), &arr[0]);
452
0
  }
453
0
454
0
  int arr2d[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
455
0
456
#ifdef CONFIRM_COMPILATION_ERRORS
457
  {
458
    Span<int, 6> s{ arr };
459
  }
460
461
  {
462
    Span<int, 0> s{ arr };
463
    ASSERT_EQ(s.Length(), 0U);
464
    ASSERT_EQ(s.data(), &arr[0]);
465
  }
466
467
  {
468
    Span<int> s{ arr2d };
469
    ASSERT_EQ(s.Length(), 6U);
470
    ASSERT_EQ(s.data(), &arr2d[0][0]);
471
    ASSERT_EQ(s[0], 1);
472
    ASSERT_EQ(s[5], 6);
473
  }
474
475
  {
476
    Span<int, 0> s{ arr2d };
477
    ASSERT_EQ(s.Length(), 0U);
478
    ASSERT_EQ(s.data(), &arr2d[0][0]);
479
  }
480
481
  {
482
    Span<int, 6> s{ arr2d };
483
  }
484
#endif
485
  {
486
0
    Span<int[3]> s{ &(arr2d[0]), 1 };
487
0
    ASSERT_EQ(s.Length(), 1U);
488
0
    ASSERT_EQ(s.data(), &arr2d[0]);
489
0
  }
490
0
491
0
  int arr3d[2][3][2] = { { { 1, 2 }, { 3, 4 }, { 5, 6 } },
492
0
                         { { 7, 8 }, { 9, 10 }, { 11, 12 } } };
493
0
494
#ifdef CONFIRM_COMPILATION_ERRORS
495
  {
496
    Span<int> s{ arr3d };
497
    ASSERT_EQ(s.Length(), 12U);
498
    ASSERT_EQ(s.data(), &arr3d[0][0][0]);
499
    ASSERT_EQ(s[0], 1);
500
    ASSERT_EQ(s[11], 12);
501
  }
502
503
  {
504
    Span<int, 0> s{ arr3d };
505
    ASSERT_EQ(s.Length(), 0U);
506
    ASSERT_EQ(s.data(), &arr3d[0][0][0]);
507
  }
508
509
  {
510
    Span<int, 11> s{ arr3d };
511
  }
512
513
  {
514
    Span<int, 12> s{ arr3d };
515
    ASSERT_EQ(s.Length(), 12U);
516
    ASSERT_EQ(s.data(), &arr3d[0][0][0]);
517
    ASSERT_EQ(s[0], 1);
518
    ASSERT_EQ(s[5], 6);
519
  }
520
#endif
521
  {
522
0
    Span<int[3][2]> s{ &arr3d[0], 1 };
523
0
    ASSERT_EQ(s.Length(), 1U);
524
0
    ASSERT_EQ(s.data(), &arr3d[0]);
525
0
  }
526
0
527
0
  {
528
0
    auto s = MakeSpan(arr);
529
0
    ASSERT_EQ(s.Length(), 5U);
530
0
    ASSERT_EQ(s.data(), &arr[0]);
531
0
  }
532
0
533
0
  {
534
0
    auto s = MakeSpan(&(arr2d[0]), 1);
535
0
    ASSERT_EQ(s.Length(), 1U);
536
0
    ASSERT_EQ(s.data(), &arr2d[0]);
537
0
  }
538
0
539
0
  {
540
0
    auto s = MakeSpan(&arr3d[0], 1);
541
0
    ASSERT_EQ(s.Length(), 1U);
542
0
    ASSERT_EQ(s.data(), &arr3d[0]);
543
0
  }
544
0
}
545
546
SPAN_TEST(from_dynamic_array_constructor)
547
0
{
548
0
  double(*arr)[3][4] = new double[100][3][4];
549
0
550
0
  {
551
0
    Span<double> s(&arr[0][0][0], 10);
552
0
    ASSERT_EQ(s.Length(), 10U);
553
0
    ASSERT_EQ(s.data(), &arr[0][0][0]);
554
0
  }
555
0
556
0
  {
557
0
    auto s = MakeSpan(&arr[0][0][0], 10);
558
0
    ASSERT_EQ(s.Length(), 10U);
559
0
    ASSERT_EQ(s.data(), &arr[0][0][0]);
560
0
  }
561
0
562
0
  delete[] arr;
563
0
}
564
565
SPAN_TEST(from_std_array_constructor)
566
0
{
567
0
  std::array<int, 4> arr = { { 1, 2, 3, 4 } };
568
0
569
0
  {
570
0
    Span<int> s{ arr };
571
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size()));
572
0
    ASSERT_EQ(s.data(), arr.data());
573
0
574
0
    Span<const int> cs{ arr };
575
0
    ASSERT_EQ(cs.size(), narrow_cast<size_t>(arr.size()));
576
0
    ASSERT_EQ(cs.data(), arr.data());
577
0
  }
578
0
579
0
  {
580
0
    Span<int, 4> s{ arr };
581
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size()));
582
0
    ASSERT_EQ(s.data(), arr.data());
583
0
584
0
    Span<const int, 4> cs{ arr };
585
0
    ASSERT_EQ(cs.size(), narrow_cast<size_t>(arr.size()));
586
0
    ASSERT_EQ(cs.data(), arr.data());
587
0
  }
588
0
589
#ifdef CONFIRM_COMPILATION_ERRORS
590
  {
591
    Span<int, 2> s{ arr };
592
    ASSERT_EQ(s.size(), 2U);
593
    ASSERT_EQ(s.data(), arr.data());
594
595
    Span<const int, 2> cs{ arr };
596
    ASSERT_EQ(cs.size(), 2U);
597
    ASSERT_EQ(cs.data(), arr.data());
598
  }
599
600
  {
601
    Span<int, 0> s{ arr };
602
    ASSERT_EQ(s.size(), 0U);
603
    ASSERT_EQ(s.data(), arr.data());
604
605
    Span<const int, 0> cs{ arr };
606
    ASSERT_EQ(cs.size(), 0U);
607
    ASSERT_EQ(cs.data(), arr.data());
608
  }
609
610
  {
611
    Span<int, 5> s{ arr };
612
  }
613
614
  {
615
    auto get_an_array = []() -> std::array<int, 4> { return { 1, 2, 3, 4 }; };
616
    auto take_a_Span = [](Span<int> s) { static_cast<void>(s); };
617
    // try to take a temporary std::array
618
    take_a_Span(get_an_array());
619
  }
620
#endif
621
622
0
  {
623
0
    auto get_an_array = []() -> std::array<int, 4> {
624
0
      return { { 1, 2, 3, 4 } };
625
0
    };
626
0
    auto take_a_Span = [](Span<const int> s) { static_cast<void>(s); };
627
0
    // try to take a temporary std::array
628
0
    take_a_Span(get_an_array());
629
0
  }
630
0
631
0
  {
632
0
    auto s = MakeSpan(arr);
633
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size()));
634
0
    ASSERT_EQ(s.data(), arr.data());
635
0
  }
636
0
}
637
638
SPAN_TEST(from_const_std_array_constructor)
639
0
{
640
0
  const std::array<int, 4> arr = { { 1, 2, 3, 4 } };
641
0
642
0
  {
643
0
    Span<const int> s{ arr };
644
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size()));
645
0
    ASSERT_EQ(s.data(), arr.data());
646
0
  }
647
0
648
0
  {
649
0
    Span<const int, 4> s{ arr };
650
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size()));
651
0
    ASSERT_EQ(s.data(), arr.data());
652
0
  }
653
0
654
#ifdef CONFIRM_COMPILATION_ERRORS
655
  {
656
    Span<const int, 2> s{ arr };
657
    ASSERT_EQ(s.size(), 2U);
658
    ASSERT_EQ(s.data(), arr.data());
659
  }
660
661
  {
662
    Span<const int, 0> s{ arr };
663
    ASSERT_EQ(s.size(), 0U);
664
    ASSERT_EQ(s.data(), arr.data());
665
  }
666
667
  {
668
    Span<const int, 5> s{ arr };
669
  }
670
#endif
671
672
0
  {
673
0
    auto get_an_array = []() -> const std::array<int, 4> {
674
0
      return { { 1, 2, 3, 4 } };
675
0
    };
676
0
    auto take_a_Span = [](Span<const int> s) { static_cast<void>(s); };
677
0
    // try to take a temporary std::array
678
0
    take_a_Span(get_an_array());
679
0
  }
680
0
681
0
  {
682
0
    auto s = MakeSpan(arr);
683
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size()));
684
0
    ASSERT_EQ(s.data(), arr.data());
685
0
  }
686
0
}
687
688
SPAN_TEST(from_std_array_const_constructor)
689
0
{
690
0
  std::array<const int, 4> arr = { { 1, 2, 3, 4 } };
691
0
692
0
  {
693
0
    Span<const int> s{ arr };
694
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size()));
695
0
    ASSERT_EQ(s.data(), arr.data());
696
0
  }
697
0
698
0
  {
699
0
    Span<const int, 4> s{ arr };
700
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size()));
701
0
    ASSERT_EQ(s.data(), arr.data());
702
0
  }
703
0
704
#ifdef CONFIRM_COMPILATION_ERRORS
705
  {
706
    Span<const int, 2> s{ arr };
707
    ASSERT_EQ(s.size(), 2U);
708
    ASSERT_EQ(s.data(), arr.data());
709
  }
710
711
  {
712
    Span<const int, 0> s{ arr };
713
    ASSERT_EQ(s.size(), 0U);
714
    ASSERT_EQ(s.data(), arr.data());
715
  }
716
717
  {
718
    Span<const int, 5> s{ arr };
719
  }
720
721
  {
722
    Span<int, 4> s{ arr };
723
  }
724
#endif
725
726
0
  {
727
0
    auto s = MakeSpan(arr);
728
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.size()));
729
0
    ASSERT_EQ(s.data(), arr.data());
730
0
  }
731
0
}
732
733
SPAN_TEST(from_mozilla_array_constructor)
734
0
{
735
0
  mozilla::Array<int, 4> arr(1, 2, 3, 4);
736
0
737
0
  {
738
0
    Span<int> s{ arr };
739
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin()));
740
0
    ASSERT_EQ(s.data(), &arr[0]);
741
0
742
0
    Span<const int> cs{ arr };
743
0
    ASSERT_EQ(cs.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin()));
744
0
    ASSERT_EQ(cs.data(), &arr[0]);
745
0
  }
746
0
747
0
  {
748
0
    Span<int, 4> s{ arr };
749
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin()));
750
0
    ASSERT_EQ(s.data(), &arr[0]);
751
0
752
0
    Span<const int, 4> cs{ arr };
753
0
    ASSERT_EQ(cs.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin()));
754
0
    ASSERT_EQ(cs.data(), &arr[0]);
755
0
  }
756
0
757
#ifdef CONFIRM_COMPILATION_ERRORS
758
  {
759
    Span<int, 2> s{ arr };
760
    ASSERT_EQ(s.size(), 2U);
761
    ASSERT_EQ(s.data(), &arr[0]);
762
763
    Span<const int, 2> cs{ arr };
764
    ASSERT_EQ(cs.size(), 2U);
765
    ASSERT_EQ(cs.data(), &arr[0]);
766
  }
767
768
  {
769
    Span<int, 0> s{ arr };
770
    ASSERT_EQ(s.size(), 0U);
771
    ASSERT_EQ(s.data(), &arr[0]);
772
773
    Span<const int, 0> cs{ arr };
774
    ASSERT_EQ(cs.size(), 0U);
775
    ASSERT_EQ(cs.data(), &arr[0]);
776
  }
777
778
  {
779
    Span<int, 5> s{ arr };
780
  }
781
782
  {
783
    auto get_an_array = []() -> mozilla::Array<int, 4> {
784
      return { 1, 2, 3, 4 };
785
    };
786
    auto take_a_Span = [](Span<int> s) { static_cast<void>(s); };
787
    // try to take a temporary mozilla::Array
788
    take_a_Span(get_an_array());
789
  }
790
#endif
791
792
0
  {
793
0
    auto get_an_array = []() -> mozilla::Array<int, 4> {
794
0
      return { 1, 2, 3, 4 };
795
0
    };
796
0
    auto take_a_Span = [](Span<const int> s) { static_cast<void>(s); };
797
0
    // try to take a temporary mozilla::Array
798
0
    take_a_Span(get_an_array());
799
0
  }
800
0
801
0
  {
802
0
    auto s = MakeSpan(arr);
803
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin()));
804
0
    ASSERT_EQ(s.data(), &arr[0]);
805
0
  }
806
0
}
807
808
SPAN_TEST(from_const_mozilla_array_constructor)
809
0
{
810
0
  const mozilla::Array<int, 4> arr(1, 2, 3, 4);
811
0
812
0
  {
813
0
    Span<const int> s{ arr };
814
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin()));
815
0
    ASSERT_EQ(s.data(), &arr[0]);
816
0
  }
817
0
818
0
  {
819
0
    Span<const int, 4> s{ arr };
820
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin()));
821
0
    ASSERT_EQ(s.data(), &arr[0]);
822
0
  }
823
0
824
#ifdef CONFIRM_COMPILATION_ERRORS
825
  {
826
    Span<const int, 2> s{ arr };
827
    ASSERT_EQ(s.size(), 2U);
828
    ASSERT_EQ(s.data(), &arr[0]);
829
  }
830
831
  {
832
    Span<const int, 0> s{ arr };
833
    ASSERT_EQ(s.size(), 0U);
834
    ASSERT_EQ(s.data(), &arr[0]);
835
  }
836
837
  {
838
    Span<const int, 5> s{ arr };
839
  }
840
#endif
841
842
#if 0
843
  {
844
    auto get_an_array = []() -> const mozilla::Array<int, 4> {
845
      return { 1, 2, 3, 4 };
846
    };
847
    auto take_a_Span = [](Span<const int> s) { static_cast<void>(s); };
848
    // try to take a temporary mozilla::Array
849
    take_a_Span(get_an_array());
850
  }
851
#endif
852
853
0
  {
854
0
    auto s = MakeSpan(arr);
855
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin()));
856
0
    ASSERT_EQ(s.data(), &arr[0]);
857
0
  }
858
0
}
859
860
SPAN_TEST(from_mozilla_array_const_constructor)
861
0
{
862
0
  mozilla::Array<const int, 4> arr(1, 2, 3, 4);
863
0
864
0
  {
865
0
    Span<const int> s{ arr };
866
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin()));
867
0
    ASSERT_EQ(s.data(), &arr[0]);
868
0
  }
869
0
870
0
  {
871
0
    Span<const int, 4> s{ arr };
872
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin()));
873
0
    ASSERT_EQ(s.data(), &arr[0]);
874
0
  }
875
0
876
#ifdef CONFIRM_COMPILATION_ERRORS
877
  {
878
    Span<const int, 2> s{ arr };
879
    ASSERT_EQ(s.size(), 2U);
880
    ASSERT_EQ(s.data(), &arr[0]);
881
  }
882
883
  {
884
    Span<const int, 0> s{ arr };
885
    ASSERT_EQ(s.size(), 0U);
886
    ASSERT_EQ(s.data(), &arr[0]);
887
  }
888
889
  {
890
    Span<const int, 5> s{ arr };
891
  }
892
893
  {
894
    Span<int, 4> s{ arr };
895
  }
896
#endif
897
898
0
  {
899
0
    auto s = MakeSpan(arr);
900
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(arr.cend() - arr.cbegin()));
901
0
    ASSERT_EQ(s.data(), &arr[0]);
902
0
  }
903
0
}
904
905
SPAN_TEST(from_container_constructor)
906
0
{
907
0
  std::vector<int> v = { 1, 2, 3 };
908
0
  const std::vector<int> cv = v;
909
0
910
0
  {
911
0
    AssertSpanOfThreeInts(v);
912
0
913
0
    Span<int> s{ v };
914
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(v.size()));
915
0
    ASSERT_EQ(s.data(), v.data());
916
0
917
0
    Span<const int> cs{ v };
918
0
    ASSERT_EQ(cs.size(), narrow_cast<size_t>(v.size()));
919
0
    ASSERT_EQ(cs.data(), v.data());
920
0
  }
921
0
922
0
  std::string str = "hello";
923
0
  const std::string cstr = "hello";
924
0
925
0
  {
926
#ifdef CONFIRM_COMPILATION_ERRORS
927
    Span<char> s{ str };
928
    ASSERT_EQ(s.size(), narrow_cast<size_t>(str.size()));
929
    ASSERT_EQ(s.data(), str.data());
930
#endif
931
    Span<const char> cs{ str };
932
0
    ASSERT_EQ(cs.size(), narrow_cast<size_t>(str.size()));
933
0
    ASSERT_EQ(cs.data(), str.data());
934
0
  }
935
0
936
0
  {
937
#ifdef CONFIRM_COMPILATION_ERRORS
938
    Span<char> s{ cstr };
939
#endif
940
    Span<const char> cs{ cstr };
941
0
    ASSERT_EQ(cs.size(), narrow_cast<size_t>(cstr.size()));
942
0
    ASSERT_EQ(cs.data(), cstr.data());
943
0
  }
944
0
945
0
  {
946
#ifdef CONFIRM_COMPILATION_ERRORS
947
    auto get_temp_vector = []() -> std::vector<int> { return {}; };
948
    auto use_Span = [](Span<int> s) { static_cast<void>(s); };
949
    use_Span(get_temp_vector());
950
#endif
951
  }
952
0
953
0
  {
954
0
    auto get_temp_vector = []() -> std::vector<int> { return {}; };
955
0
    auto use_Span = [](Span<const int> s) { static_cast<void>(s); };
956
0
    use_Span(get_temp_vector());
957
0
  }
958
0
959
0
  {
960
#ifdef CONFIRM_COMPILATION_ERRORS
961
    auto get_temp_string = []() -> std::string { return {}; };
962
    auto use_Span = [](Span<char> s) { static_cast<void>(s); };
963
    use_Span(get_temp_string());
964
#endif
965
  }
966
0
967
0
  {
968
0
    auto get_temp_string = []() -> std::string { return {}; };
969
0
    auto use_Span = [](Span<const char> s) { static_cast<void>(s); };
970
0
    use_Span(get_temp_string());
971
0
  }
972
0
973
0
  {
974
#ifdef CONFIRM_COMPILATION_ERRORS
975
    auto get_temp_vector = []() -> const std::vector<int> { return {}; };
976
    auto use_Span = [](Span<const char> s) { static_cast<void>(s); };
977
    use_Span(get_temp_vector());
978
#endif
979
  }
980
0
981
0
  {
982
0
    auto get_temp_string = []() -> const std::string { return {}; };
983
0
    auto use_Span = [](Span<const char> s) { static_cast<void>(s); };
984
0
    use_Span(get_temp_string());
985
0
  }
986
0
987
0
  {
988
#ifdef CONFIRM_COMPILATION_ERRORS
989
    std::map<int, int> m;
990
    Span<int> s{ m };
991
#endif
992
  }
993
0
994
0
  {
995
0
    auto s = MakeSpan(v);
996
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(v.size()));
997
0
    ASSERT_EQ(s.data(), v.data());
998
0
999
0
    auto cs = MakeSpan(cv);
1000
0
    ASSERT_EQ(cs.size(), narrow_cast<size_t>(cv.size()));
1001
0
    ASSERT_EQ(cs.data(), cv.data());
1002
0
  }
1003
0
}
1004
1005
SPAN_TEST(from_xpcom_collections)
1006
0
{
1007
0
  {
1008
0
    nsTArray<int> v;
1009
0
    v.AppendElement(1);
1010
0
    v.AppendElement(2);
1011
0
    v.AppendElement(3);
1012
0
1013
0
    AssertSpanOfThreeInts(v);
1014
0
1015
0
    Span<int> s{ v };
1016
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length()));
1017
0
    ASSERT_EQ(s.data(), v.Elements());
1018
0
    ASSERT_EQ(s[2], 3);
1019
0
1020
0
    Span<const int> cs{ v };
1021
0
    ASSERT_EQ(cs.size(), narrow_cast<size_t>(v.Length()));
1022
0
    ASSERT_EQ(cs.data(), v.Elements());
1023
0
    ASSERT_EQ(cs[2], 3);
1024
0
  }
1025
0
  {
1026
0
    nsTArray<int> v;
1027
0
    v.AppendElement(1);
1028
0
    v.AppendElement(2);
1029
0
    v.AppendElement(3);
1030
0
1031
0
    AssertSpanOfThreeInts(v);
1032
0
1033
0
    auto s = MakeSpan(v);
1034
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length()));
1035
0
    ASSERT_EQ(s.data(), v.Elements());
1036
0
    ASSERT_EQ(s[2], 3);
1037
0
  }
1038
0
  {
1039
0
    AutoTArray<int, 5> v;
1040
0
    v.AppendElement(1);
1041
0
    v.AppendElement(2);
1042
0
    v.AppendElement(3);
1043
0
1044
0
    AssertSpanOfThreeInts(v);
1045
0
1046
0
    Span<int> s{ v };
1047
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length()));
1048
0
    ASSERT_EQ(s.data(), v.Elements());
1049
0
    ASSERT_EQ(s[2], 3);
1050
0
1051
0
    Span<const int> cs{ v };
1052
0
    ASSERT_EQ(cs.size(), narrow_cast<size_t>(v.Length()));
1053
0
    ASSERT_EQ(cs.data(), v.Elements());
1054
0
    ASSERT_EQ(cs[2], 3);
1055
0
  }
1056
0
  {
1057
0
    AutoTArray<int, 5> v;
1058
0
    v.AppendElement(1);
1059
0
    v.AppendElement(2);
1060
0
    v.AppendElement(3);
1061
0
1062
0
    AssertSpanOfThreeInts(v);
1063
0
1064
0
    auto s = MakeSpan(v);
1065
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length()));
1066
0
    ASSERT_EQ(s.data(), v.Elements());
1067
0
    ASSERT_EQ(s[2], 3);
1068
0
  }
1069
0
  {
1070
0
    FallibleTArray<int> v;
1071
0
    *(v.AppendElement(fallible)) = 1;
1072
0
    *(v.AppendElement(fallible)) = 2;
1073
0
    *(v.AppendElement(fallible)) = 3;
1074
0
1075
0
    AssertSpanOfThreeInts(v);
1076
0
1077
0
    Span<int> s{ v };
1078
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length()));
1079
0
    ASSERT_EQ(s.data(), v.Elements());
1080
0
    ASSERT_EQ(s[2], 3);
1081
0
1082
0
    Span<const int> cs{ v };
1083
0
    ASSERT_EQ(cs.size(), narrow_cast<size_t>(v.Length()));
1084
0
    ASSERT_EQ(cs.data(), v.Elements());
1085
0
    ASSERT_EQ(cs[2], 3);
1086
0
  }
1087
0
  {
1088
0
    FallibleTArray<int> v;
1089
0
    *(v.AppendElement(fallible)) = 1;
1090
0
    *(v.AppendElement(fallible)) = 2;
1091
0
    *(v.AppendElement(fallible)) = 3;
1092
0
1093
0
    AssertSpanOfThreeInts(v);
1094
0
1095
0
    auto s = MakeSpan(v);
1096
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length()));
1097
0
    ASSERT_EQ(s.data(), v.Elements());
1098
0
    ASSERT_EQ(s[2], 3);
1099
0
  }
1100
0
  {
1101
0
    nsAutoString str;
1102
0
    str.AssignLiteral("abc");
1103
0
1104
0
    AssertSpanOfThreeChar16s(str);
1105
0
    AssertSpanOfThreeChar16sViaString(str);
1106
0
1107
0
    Span<char16_t> s{ str };
1108
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(str.Length()));
1109
0
    ASSERT_EQ(s.data(), str.BeginWriting());
1110
0
    ASSERT_EQ(s[2], 'c');
1111
0
1112
0
    Span<const char16_t> cs{ str };
1113
0
    ASSERT_EQ(cs.size(), narrow_cast<size_t>(str.Length()));
1114
0
    ASSERT_EQ(cs.data(), str.BeginReading());
1115
0
    ASSERT_EQ(cs[2], 'c');
1116
0
  }
1117
0
  {
1118
0
    nsAutoString str;
1119
0
    str.AssignLiteral("abc");
1120
0
1121
0
    AssertSpanOfThreeChar16s(str);
1122
0
    AssertSpanOfThreeChar16sViaString(str);
1123
0
1124
0
    auto s = MakeSpan(str);
1125
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(str.Length()));
1126
0
    ASSERT_EQ(s.data(), str.BeginWriting());
1127
0
    ASSERT_EQ(s[2], 'c');
1128
0
  }
1129
0
  {
1130
0
    nsAutoCString str;
1131
0
    str.AssignLiteral("abc");
1132
0
1133
0
    AssertSpanOfThreeChars(str);
1134
0
    AssertSpanOfThreeCharsViaString(str);
1135
0
1136
0
    Span<uint8_t> s{ str };
1137
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(str.Length()));
1138
0
    ASSERT_EQ(s.data(), reinterpret_cast<uint8_t*>(str.BeginWriting()));
1139
0
    ASSERT_EQ(s[2], 'c');
1140
0
1141
0
    Span<const uint8_t> cs{ str };
1142
0
    ASSERT_EQ(cs.size(), narrow_cast<size_t>(str.Length()));
1143
0
    ASSERT_EQ(cs.data(), reinterpret_cast<const uint8_t*>(str.BeginReading()));
1144
0
    ASSERT_EQ(cs[2], 'c');
1145
0
  }
1146
0
  {
1147
0
    nsAutoCString str;
1148
0
    str.AssignLiteral("abc");
1149
0
1150
0
    AssertSpanOfThreeChars(str);
1151
0
    AssertSpanOfThreeCharsViaString(str);
1152
0
1153
0
    auto s = MakeSpan(str);
1154
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(str.Length()));
1155
0
    ASSERT_EQ(s.data(), str.BeginWriting());
1156
0
    ASSERT_EQ(s[2], 'c');
1157
0
  }
1158
0
  {
1159
0
    nsTArray<int> v;
1160
0
    v.AppendElement(1);
1161
0
    v.AppendElement(2);
1162
0
    v.AppendElement(3);
1163
0
1164
0
    Range<int> r(v.Elements(), v.Length());
1165
0
1166
0
    AssertSpanOfThreeInts(r);
1167
0
1168
0
    Span<int> s{ r };
1169
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length()));
1170
0
    ASSERT_EQ(s.data(), v.Elements());
1171
0
    ASSERT_EQ(s[2], 3);
1172
0
1173
0
    Span<const int> cs{ r };
1174
0
    ASSERT_EQ(cs.size(), narrow_cast<size_t>(v.Length()));
1175
0
    ASSERT_EQ(cs.data(), v.Elements());
1176
0
    ASSERT_EQ(cs[2], 3);
1177
0
  }
1178
0
  {
1179
0
    nsTArray<int> v;
1180
0
    v.AppendElement(1);
1181
0
    v.AppendElement(2);
1182
0
    v.AppendElement(3);
1183
0
1184
0
    Range<int> r(v.Elements(), v.Length());
1185
0
1186
0
    AssertSpanOfThreeInts(r);
1187
0
1188
0
    auto s = MakeSpan(r);
1189
0
    ASSERT_EQ(s.size(), narrow_cast<size_t>(v.Length()));
1190
0
    ASSERT_EQ(s.data(), v.Elements());
1191
0
    ASSERT_EQ(s[2], 3);
1192
0
  }
1193
0
}
1194
1195
SPAN_TEST(from_cstring)
1196
0
{
1197
0
  {
1198
0
    const char* str = nullptr;
1199
0
    auto cs = MakeStringSpan(str);
1200
0
    ASSERT_EQ(cs.size(), 0U);
1201
0
  }
1202
0
  {
1203
0
    const char* str = "abc";
1204
0
1205
0
    auto cs = MakeStringSpan(str);
1206
0
    ASSERT_EQ(cs.size(), 3U);
1207
0
    ASSERT_EQ(cs.data(), str);
1208
0
    ASSERT_EQ(cs[2], 'c');
1209
0
1210
#ifdef CONFIRM_COMPILATION_ERRORS
1211
    Span<const char> scccl("literal"); // error
1212
1213
    Span<const char> sccel;
1214
    sccel = "literal"; // error
1215
1216
    cs = MakeSpan("literal"); // error
1217
#endif
1218
  }
1219
0
  {
1220
0
    char arr[4] = {'a', 'b', 'c', 0};
1221
0
1222
0
    auto cs = MakeStringSpan(arr);
1223
0
    ASSERT_EQ(cs.size(), 3U);
1224
0
    ASSERT_EQ(cs.data(), arr);
1225
0
    ASSERT_EQ(cs[2], 'c');
1226
0
1227
0
    cs = MakeSpan(arr);
1228
0
    ASSERT_EQ(cs.size(), 4U); // zero terminator is part of the array span.
1229
0
    ASSERT_EQ(cs.data(), arr);
1230
0
    ASSERT_EQ(cs[2], 'c');
1231
0
    ASSERT_EQ(cs[3], '\0'); // zero terminator is part of the array span.
1232
0
1233
#ifdef CONFIRM_COMPILATION_ERRORS
1234
    Span<char> scca(arr); // error
1235
    Span<const char> sccca(arr); // error
1236
1237
    Span<const char> scccea;
1238
    scccea = arr; // error
1239
#endif
1240
  }
1241
0
  {
1242
0
    const char16_t* str = nullptr;
1243
0
    auto cs = MakeStringSpan(str);
1244
0
    ASSERT_EQ(cs.size(), 0U);
1245
0
  }
1246
0
  {
1247
0
    char16_t arr[4] = {'a', 'b', 'c', 0};
1248
0
    const char16_t* str = arr;
1249
0
1250
0
    auto cs = MakeStringSpan(str);
1251
0
    ASSERT_EQ(cs.size(), 3U);
1252
0
    ASSERT_EQ(cs.data(), str);
1253
0
    ASSERT_EQ(cs[2], 'c');
1254
0
1255
0
    cs = MakeStringSpan(arr);
1256
0
    ASSERT_EQ(cs.size(), 3U);
1257
0
    ASSERT_EQ(cs.data(), str);
1258
0
    ASSERT_EQ(cs[2], 'c');
1259
0
1260
0
    cs = MakeSpan(arr);
1261
0
    ASSERT_EQ(cs.size(), 4U); // zero terminator is part of the array span.
1262
0
    ASSERT_EQ(cs.data(), str);
1263
0
    ASSERT_EQ(cs[2], 'c');
1264
0
    ASSERT_EQ(cs[3], '\0'); // zero terminator is part of the array span.
1265
0
1266
#ifdef CONFIRM_COMPILATION_ERRORS
1267
    Span<char16_t> scca(arr); // error
1268
1269
    Span<const char16_t> scccea;
1270
    scccea = arr; // error
1271
1272
    Span<const char16_t> scccl(u"literal"); // error
1273
1274
    Span<const char16_t> *sccel;
1275
    *sccel = u"literal"; // error
1276
1277
    cs = MakeSpan(u"literal"); // error
1278
#endif
1279
  }
1280
0
}
1281
1282
0
SPAN_TEST(from_convertible_Span_constructor){
1283
0
  {
1284
0
    Span<DerivedClass> avd;
1285
0
    Span<const DerivedClass> avcd = avd;
1286
0
    static_cast<void>(avcd);
1287
0
  }
1288
0
1289
0
  {
1290
#ifdef CONFIRM_COMPILATION_ERRORS
1291
  Span<DerivedClass> avd;
1292
  Span<BaseClass> avb = avd;
1293
  static_cast<void>(avb);
1294
#endif
1295
  }
1296
0
1297
#ifdef CONFIRM_COMPILATION_ERRORS
1298
  {
1299
    Span<int> s;
1300
    Span<unsigned int> s2 = s;
1301
    static_cast<void>(s2);
1302
  }
1303
1304
  {
1305
    Span<int> s;
1306
    Span<const unsigned int> s2 = s;
1307
    static_cast<void>(s2);
1308
  }
1309
1310
  {
1311
    Span<int> s;
1312
    Span<short> s2 = s;
1313
    static_cast<void>(s2);
1314
  }
1315
#endif
1316
}
1317
1318
SPAN_TEST(copy_move_and_assignment)
1319
0
{
1320
0
  Span<int> s1;
1321
0
  ASSERT_TRUE(s1.empty());
1322
0
1323
0
  int arr[] = { 3, 4, 5 };
1324
0
1325
0
  Span<const int> s2 = arr;
1326
0
  ASSERT_EQ(s2.Length(), 3U);
1327
0
  ASSERT_EQ(s2.data(), &arr[0]);
1328
0
1329
0
  s2 = s1;
1330
0
  ASSERT_TRUE(s2.empty());
1331
0
1332
0
  auto get_temp_Span = [&]() -> Span<int> { return { &arr[1], 2 }; };
1333
0
  auto use_Span = [&](Span<const int> s) {
1334
0
    ASSERT_EQ(s.Length(), 2U);
1335
0
    ASSERT_EQ(s.data(), &arr[1]);
1336
0
  };
1337
0
  use_Span(get_temp_Span());
1338
0
1339
0
  s1 = get_temp_Span();
1340
0
  ASSERT_EQ(s1.Length(), 2U);
1341
0
  ASSERT_EQ(s1.data(), &arr[1]);
1342
0
}
1343
1344
SPAN_TEST(first)
1345
0
{
1346
0
  int arr[5] = { 1, 2, 3, 4, 5 };
1347
0
1348
0
  {
1349
0
    Span<int, 5> av = arr;
1350
0
    ASSERT_EQ(av.First<2>().Length(), 2U);
1351
0
    ASSERT_EQ(av.First(2).Length(), 2U);
1352
0
  }
1353
0
1354
0
  {
1355
0
    Span<int, 5> av = arr;
1356
0
    ASSERT_EQ(av.First<0>().Length(), 0U);
1357
0
    ASSERT_EQ(av.First(0).Length(), 0U);
1358
0
  }
1359
0
1360
0
  {
1361
0
    Span<int, 5> av = arr;
1362
0
    ASSERT_EQ(av.First<5>().Length(), 5U);
1363
0
    ASSERT_EQ(av.First(5).Length(), 5U);
1364
0
  }
1365
0
1366
#if 0
1367
        {
1368
            Span<int, 5> av = arr;
1369
#ifdef CONFIRM_COMPILATION_ERRORS
1370
            ASSERT_EQ(av.First<6>().Length() , 6U);
1371
            ASSERT_EQ(av.First<-1>().Length() , -1);
1372
#endif
1373
            CHECK_THROW(av.First(6).Length(), fail_fast);
1374
        }
1375
#endif
1376
1377
0
  {
1378
0
    Span<int> av;
1379
0
    ASSERT_EQ(av.First<0>().Length(), 0U);
1380
0
    ASSERT_EQ(av.First(0).Length(), 0U);
1381
0
  }
1382
0
}
1383
1384
SPAN_TEST(last)
1385
0
{
1386
0
  int arr[5] = { 1, 2, 3, 4, 5 };
1387
0
1388
0
  {
1389
0
    Span<int, 5> av = arr;
1390
0
    ASSERT_EQ(av.Last<2>().Length(), 2U);
1391
0
    ASSERT_EQ(av.Last(2).Length(), 2U);
1392
0
  }
1393
0
1394
0
  {
1395
0
    Span<int, 5> av = arr;
1396
0
    ASSERT_EQ(av.Last<0>().Length(), 0U);
1397
0
    ASSERT_EQ(av.Last(0).Length(), 0U);
1398
0
  }
1399
0
1400
0
  {
1401
0
    Span<int, 5> av = arr;
1402
0
    ASSERT_EQ(av.Last<5>().Length(), 5U);
1403
0
    ASSERT_EQ(av.Last(5).Length(), 5U);
1404
0
  }
1405
0
1406
#if 0
1407
        {
1408
            Span<int, 5> av = arr;
1409
#ifdef CONFIRM_COMPILATION_ERRORS
1410
            ASSERT_EQ(av.Last<6>().Length() , 6U);
1411
#endif
1412
            CHECK_THROW(av.Last(6).Length(), fail_fast);
1413
        }
1414
#endif
1415
1416
0
  {
1417
0
    Span<int> av;
1418
0
    ASSERT_EQ(av.Last<0>().Length(), 0U);
1419
0
    ASSERT_EQ(av.Last(0).Length(), 0U);
1420
0
  }
1421
0
}
1422
1423
SPAN_TEST(from_to)
1424
0
{
1425
0
  int arr[5] = { 1, 2, 3, 4, 5 };
1426
0
1427
0
  {
1428
0
    Span<int, 5> av = arr;
1429
0
    ASSERT_EQ(av.From(3).Length(), 2U);
1430
0
    ASSERT_EQ(av.From(2)[1], 4);
1431
0
  }
1432
0
1433
0
  {
1434
0
    Span<int, 5> av = arr;
1435
0
    ASSERT_EQ(av.From(5).Length(), 0U);
1436
0
  }
1437
0
1438
0
  {
1439
0
    Span<int, 5> av = arr;
1440
0
    ASSERT_EQ(av.From(0).Length(), 5U);
1441
0
  }
1442
0
1443
0
  {
1444
0
    Span<int, 5> av = arr;
1445
0
    ASSERT_EQ(av.To(3).Length(), 3U);
1446
0
    ASSERT_EQ(av.To(3)[1], 2);
1447
0
  }
1448
0
1449
0
  {
1450
0
    Span<int, 5> av = arr;
1451
0
    ASSERT_EQ(av.To(0).Length(), 0U);
1452
0
  }
1453
0
1454
0
  {
1455
0
    Span<int, 5> av = arr;
1456
0
    ASSERT_EQ(av.To(5).Length(), 5U);
1457
0
  }
1458
0
1459
0
  {
1460
0
    Span<int, 5> av = arr;
1461
0
    ASSERT_EQ(av.FromTo(1, 4).Length(), 3U);
1462
0
    ASSERT_EQ(av.FromTo(1, 4)[1], 3);
1463
0
  }
1464
0
1465
0
  {
1466
0
    Span<int, 5> av = arr;
1467
0
    ASSERT_EQ(av.FromTo(2, 2).Length(), 0U);
1468
0
  }
1469
0
1470
0
  {
1471
0
    Span<int, 5> av = arr;
1472
0
    ASSERT_EQ(av.FromTo(0, 5).Length(), 5U);
1473
0
  }
1474
0
}
1475
1476
SPAN_TEST(Subspan)
1477
0
{
1478
0
  int arr[5] = { 1, 2, 3, 4, 5 };
1479
0
1480
0
  {
1481
0
    Span<int, 5> av = arr;
1482
0
    ASSERT_EQ((av.Subspan<2, 2>().Length()), 2U);
1483
0
    ASSERT_EQ(av.Subspan(2, 2).Length(), 2U);
1484
0
    ASSERT_EQ(av.Subspan(2, 3).Length(), 3U);
1485
0
  }
1486
0
1487
0
  {
1488
0
    Span<int, 5> av = arr;
1489
0
    ASSERT_EQ((av.Subspan<0, 0>().Length()), 0U);
1490
0
    ASSERT_EQ(av.Subspan(0, 0).Length(), 0U);
1491
0
  }
1492
0
1493
0
  {
1494
0
    Span<int, 5> av = arr;
1495
0
    ASSERT_EQ((av.Subspan<0, 5>().Length()), 5U);
1496
0
    ASSERT_EQ(av.Subspan(0, 5).Length(), 5U);
1497
0
    CHECK_THROW(av.Subspan(0, 6).Length(), fail_fast);
1498
0
    CHECK_THROW(av.Subspan(1, 5).Length(), fail_fast);
1499
0
  }
1500
0
1501
0
  {
1502
0
    Span<int, 5> av = arr;
1503
0
    ASSERT_EQ((av.Subspan<4, 0>().Length()), 0U);
1504
0
    ASSERT_EQ(av.Subspan(4, 0).Length(), 0U);
1505
0
    ASSERT_EQ(av.Subspan(5, 0).Length(), 0U);
1506
0
    CHECK_THROW(av.Subspan(6, 0).Length(), fail_fast);
1507
0
  }
1508
0
1509
0
  {
1510
0
    Span<int> av;
1511
0
    ASSERT_EQ((av.Subspan<0, 0>().Length()), 0U);
1512
0
    ASSERT_EQ(av.Subspan(0, 0).Length(), 0U);
1513
0
    CHECK_THROW((av.Subspan<1, 0>().Length()), fail_fast);
1514
0
  }
1515
0
1516
0
  {
1517
0
    Span<int> av;
1518
0
    ASSERT_EQ(av.Subspan(0).Length(), 0U);
1519
0
    CHECK_THROW(av.Subspan(1).Length(), fail_fast);
1520
0
  }
1521
0
1522
0
  {
1523
0
    Span<int> av = arr;
1524
0
    ASSERT_EQ(av.Subspan(0).Length(), 5U);
1525
0
    ASSERT_EQ(av.Subspan(1).Length(), 4U);
1526
0
    ASSERT_EQ(av.Subspan(4).Length(), 1U);
1527
0
    ASSERT_EQ(av.Subspan(5).Length(), 0U);
1528
0
    CHECK_THROW(av.Subspan(6).Length(), fail_fast);
1529
0
    auto av2 = av.Subspan(1);
1530
0
    for (int i = 0; i < 4; ++i)
1531
0
      ASSERT_EQ(av2[i], i + 2);
1532
0
  }
1533
0
1534
0
  {
1535
0
    Span<int, 5> av = arr;
1536
0
    ASSERT_EQ(av.Subspan(0).Length(), 5U);
1537
0
    ASSERT_EQ(av.Subspan(1).Length(), 4U);
1538
0
    ASSERT_EQ(av.Subspan(4).Length(), 1U);
1539
0
    ASSERT_EQ(av.Subspan(5).Length(), 0U);
1540
0
    CHECK_THROW(av.Subspan(6).Length(), fail_fast);
1541
0
    auto av2 = av.Subspan(1);
1542
0
    for (int i = 0; i < 4; ++i)
1543
0
      ASSERT_EQ(av2[i], i + 2);
1544
0
  }
1545
0
}
1546
1547
SPAN_TEST(at_call)
1548
0
{
1549
0
  int arr[4] = { 1, 2, 3, 4 };
1550
0
1551
0
  {
1552
0
    Span<int> s = arr;
1553
0
    ASSERT_EQ(s.at(0), 1);
1554
0
    CHECK_THROW(s.at(5), fail_fast);
1555
0
  }
1556
0
1557
0
  {
1558
0
    int arr2d[2] = { 1, 6 };
1559
0
    Span<int, 2> s = arr2d;
1560
0
    ASSERT_EQ(s.at(0), 1);
1561
0
    ASSERT_EQ(s.at(1), 6);
1562
0
    CHECK_THROW(s.at(2), fail_fast);
1563
0
  }
1564
0
}
1565
1566
SPAN_TEST(operator_function_call)
1567
0
{
1568
0
  int arr[4] = { 1, 2, 3, 4 };
1569
0
1570
0
  {
1571
0
    Span<int> s = arr;
1572
0
    ASSERT_EQ(s(0), 1);
1573
0
    CHECK_THROW(s(5), fail_fast);
1574
0
  }
1575
0
1576
0
  {
1577
0
    int arr2d[2] = { 1, 6 };
1578
0
    Span<int, 2> s = arr2d;
1579
0
    ASSERT_EQ(s(0), 1);
1580
0
    ASSERT_EQ(s(1), 6);
1581
0
    CHECK_THROW(s(2), fail_fast);
1582
0
  }
1583
0
}
1584
1585
SPAN_TEST(iterator_default_init)
1586
0
{
1587
0
  Span<int>::iterator it1;
1588
0
  Span<int>::iterator it2;
1589
0
  ASSERT_EQ(it1, it2);
1590
0
}
1591
1592
SPAN_TEST(const_iterator_default_init)
1593
0
{
1594
0
  Span<int>::const_iterator it1;
1595
0
  Span<int>::const_iterator it2;
1596
0
  ASSERT_EQ(it1, it2);
1597
0
}
1598
1599
SPAN_TEST(iterator_conversions)
1600
0
{
1601
0
  Span<int>::iterator badIt;
1602
0
  Span<int>::const_iterator badConstIt;
1603
0
  ASSERT_EQ(badIt, badConstIt);
1604
0
1605
0
  int a[] = { 1, 2, 3, 4 };
1606
0
  Span<int> s = a;
1607
0
1608
0
  auto it = s.begin();
1609
0
  auto cit = s.cbegin();
1610
0
1611
0
  ASSERT_EQ(it, cit);
1612
0
  ASSERT_EQ(cit, it);
1613
0
1614
0
  Span<int>::const_iterator cit2 = it;
1615
0
  ASSERT_EQ(cit2, cit);
1616
0
1617
0
  Span<int>::const_iterator cit3 = it + 4;
1618
0
  ASSERT_EQ(cit3, s.cend());
1619
0
}
1620
1621
SPAN_TEST(iterator_comparisons)
1622
0
{
1623
0
  int a[] = { 1, 2, 3, 4 };
1624
0
  {
1625
0
    Span<int> s = a;
1626
0
    Span<int>::iterator it = s.begin();
1627
0
    auto it2 = it + 1;
1628
0
    Span<int>::const_iterator cit = s.cbegin();
1629
0
1630
0
    ASSERT_EQ(it, cit);
1631
0
    ASSERT_EQ(cit, it);
1632
0
    ASSERT_EQ(it, it);
1633
0
    ASSERT_EQ(cit, cit);
1634
0
    ASSERT_EQ(cit, s.begin());
1635
0
    ASSERT_EQ(s.begin(), cit);
1636
0
    ASSERT_EQ(s.cbegin(), cit);
1637
0
    ASSERT_EQ(it, s.begin());
1638
0
    ASSERT_EQ(s.begin(), it);
1639
0
1640
0
    ASSERT_NE(it, it2);
1641
0
    ASSERT_NE(it2, it);
1642
0
    ASSERT_NE(it, s.end());
1643
0
    ASSERT_NE(it2, s.end());
1644
0
    ASSERT_NE(s.end(), it);
1645
0
    ASSERT_NE(it2, cit);
1646
0
    ASSERT_NE(cit, it2);
1647
0
1648
0
    ASSERT_LT(it, it2);
1649
0
    ASSERT_LE(it, it2);
1650
0
    ASSERT_LE(it2, s.end());
1651
0
    ASSERT_LT(it, s.end());
1652
0
    ASSERT_LE(it, cit);
1653
0
    ASSERT_LE(cit, it);
1654
0
    ASSERT_LT(cit, it2);
1655
0
    ASSERT_LE(cit, it2);
1656
0
    ASSERT_LT(cit, s.end());
1657
0
    ASSERT_LE(cit, s.end());
1658
0
1659
0
    ASSERT_GT(it2, it);
1660
0
    ASSERT_GE(it2, it);
1661
0
    ASSERT_GT(s.end(), it2);
1662
0
    ASSERT_GE(s.end(), it2);
1663
0
    ASSERT_GT(it2, cit);
1664
0
    ASSERT_GE(it2, cit);
1665
0
  }
1666
0
}
1667
1668
SPAN_TEST(begin_end)
1669
0
{
1670
0
  {
1671
0
    int a[] = { 1, 2, 3, 4 };
1672
0
    Span<int> s = a;
1673
0
1674
0
    Span<int>::iterator it = s.begin();
1675
0
    Span<int>::iterator it2 = std::begin(s);
1676
0
    ASSERT_EQ(it, it2);
1677
0
1678
0
    it = s.end();
1679
0
    it2 = std::end(s);
1680
0
    ASSERT_EQ(it, it2);
1681
0
  }
1682
0
1683
0
  {
1684
0
    int a[] = { 1, 2, 3, 4 };
1685
0
    Span<int> s = a;
1686
0
1687
0
    auto it = s.begin();
1688
0
    auto first = it;
1689
0
    ASSERT_EQ(it, first);
1690
0
    ASSERT_EQ(*it, 1);
1691
0
1692
0
    auto beyond = s.end();
1693
0
    ASSERT_NE(it, beyond);
1694
0
    CHECK_THROW(*beyond, fail_fast);
1695
0
1696
0
    ASSERT_EQ(beyond - first, 4U);
1697
0
    ASSERT_EQ(first - first, 0U);
1698
0
    ASSERT_EQ(beyond - beyond, 0U);
1699
0
1700
0
    ++it;
1701
0
    ASSERT_EQ(it - first, 1U);
1702
0
    ASSERT_EQ(*it, 2);
1703
0
    *it = 22;
1704
0
    ASSERT_EQ(*it, 22);
1705
0
    ASSERT_EQ(beyond - it, 3U);
1706
0
1707
0
    it = first;
1708
0
    ASSERT_EQ(it, first);
1709
0
    while (it != s.end()) {
1710
0
      *it = 5;
1711
0
      ++it;
1712
0
    }
1713
0
1714
0
    ASSERT_EQ(it, beyond);
1715
0
    ASSERT_EQ(it - beyond, 0U);
1716
0
1717
0
    for (auto& n : s) {
1718
0
      ASSERT_EQ(n, 5);
1719
0
    }
1720
0
  }
1721
0
}
1722
1723
SPAN_TEST(cbegin_cend)
1724
0
{
1725
#if 0
1726
          {
1727
              int a[] = { 1, 2, 3, 4 };
1728
              Span<int> s = a;
1729
1730
              Span<int>::const_iterator cit = s.cbegin();
1731
              Span<int>::const_iterator cit2 = std::cbegin(s);
1732
              ASSERT_EQ(cit , cit2);
1733
1734
              cit = s.cend();
1735
              cit2 = std::cend(s);
1736
              ASSERT_EQ(cit , cit2);
1737
          }
1738
#endif
1739
  {
1740
0
    int a[] = { 1, 2, 3, 4 };
1741
0
    Span<int> s = a;
1742
0
1743
0
    auto it = s.cbegin();
1744
0
    auto first = it;
1745
0
    ASSERT_EQ(it, first);
1746
0
    ASSERT_EQ(*it, 1);
1747
0
1748
0
    auto beyond = s.cend();
1749
0
    ASSERT_NE(it, beyond);
1750
0
    CHECK_THROW(*beyond, fail_fast);
1751
0
1752
0
    ASSERT_EQ(beyond - first, 4U);
1753
0
    ASSERT_EQ(first - first, 0U);
1754
0
    ASSERT_EQ(beyond - beyond, 0U);
1755
0
1756
0
    ++it;
1757
0
    ASSERT_EQ(it - first, 1U);
1758
0
    ASSERT_EQ(*it, 2);
1759
0
    ASSERT_EQ(beyond - it, 3U);
1760
0
1761
0
    int last = 0;
1762
0
    it = first;
1763
0
    ASSERT_EQ(it, first);
1764
0
    while (it != s.cend()) {
1765
0
      ASSERT_EQ(*it, last + 1);
1766
0
1767
0
      last = *it;
1768
0
      ++it;
1769
0
    }
1770
0
1771
0
    ASSERT_EQ(it, beyond);
1772
0
    ASSERT_EQ(it - beyond, 0U);
1773
0
  }
1774
0
}
1775
1776
SPAN_TEST(rbegin_rend)
1777
0
{
1778
0
  {
1779
0
    int a[] = { 1, 2, 3, 4 };
1780
0
    Span<int> s = a;
1781
0
1782
0
    auto it = s.rbegin();
1783
0
    auto first = it;
1784
0
    ASSERT_EQ(it, first);
1785
0
    ASSERT_EQ(*it, 4);
1786
0
1787
0
    auto beyond = s.rend();
1788
0
    ASSERT_NE(it, beyond);
1789
0
    CHECK_THROW(*beyond, fail_fast);
1790
0
1791
0
    ASSERT_EQ(beyond - first, 4U);
1792
0
    ASSERT_EQ(first - first, 0U);
1793
0
    ASSERT_EQ(beyond - beyond, 0U);
1794
0
1795
0
    ++it;
1796
0
    ASSERT_EQ(it - first, 1U);
1797
0
    ASSERT_EQ(*it, 3);
1798
0
    *it = 22;
1799
0
    ASSERT_EQ(*it, 22);
1800
0
    ASSERT_EQ(beyond - it, 3U);
1801
0
1802
0
    it = first;
1803
0
    ASSERT_EQ(it, first);
1804
0
    while (it != s.rend()) {
1805
0
      *it = 5;
1806
0
      ++it;
1807
0
    }
1808
0
1809
0
    ASSERT_EQ(it, beyond);
1810
0
    ASSERT_EQ(it - beyond, 0U);
1811
0
1812
0
    for (auto& n : s) {
1813
0
      ASSERT_EQ(n, 5);
1814
0
    }
1815
0
  }
1816
0
}
1817
1818
SPAN_TEST(crbegin_crend)
1819
0
{
1820
0
  {
1821
0
    int a[] = { 1, 2, 3, 4 };
1822
0
    Span<int> s = a;
1823
0
1824
0
    auto it = s.crbegin();
1825
0
    auto first = it;
1826
0
    ASSERT_EQ(it, first);
1827
0
    ASSERT_EQ(*it, 4);
1828
0
1829
0
    auto beyond = s.crend();
1830
0
    ASSERT_NE(it, beyond);
1831
0
    CHECK_THROW(*beyond, fail_fast);
1832
0
1833
0
    ASSERT_EQ(beyond - first, 4U);
1834
0
    ASSERT_EQ(first - first, 0U);
1835
0
    ASSERT_EQ(beyond - beyond, 0U);
1836
0
1837
0
    ++it;
1838
0
    ASSERT_EQ(it - first, 1U);
1839
0
    ASSERT_EQ(*it, 3);
1840
0
    ASSERT_EQ(beyond - it, 3U);
1841
0
1842
0
    it = first;
1843
0
    ASSERT_EQ(it, first);
1844
0
    int last = 5;
1845
0
    while (it != s.crend()) {
1846
0
      ASSERT_EQ(*it, last - 1);
1847
0
      last = *it;
1848
0
1849
0
      ++it;
1850
0
    }
1851
0
1852
0
    ASSERT_EQ(it, beyond);
1853
0
    ASSERT_EQ(it - beyond, 0U);
1854
0
  }
1855
0
}
1856
1857
SPAN_TEST(comparison_operators)
1858
0
{
1859
0
  {
1860
0
    Span<int> s1 = nullptr;
1861
0
    Span<int> s2 = nullptr;
1862
0
    ASSERT_EQ(s1, s2);
1863
0
    ASSERT_FALSE(s1 != s2);
1864
0
    ASSERT_FALSE(s1 < s2);
1865
0
    ASSERT_LE(s1, s2);
1866
0
    ASSERT_FALSE(s1 > s2);
1867
0
    ASSERT_GE(s1, s2);
1868
0
    ASSERT_EQ(s2, s1);
1869
0
    ASSERT_FALSE(s2 != s1);
1870
0
    ASSERT_FALSE(s2 < s1);
1871
0
    ASSERT_LE(s2, s1);
1872
0
    ASSERT_FALSE(s2 > s1);
1873
0
    ASSERT_GE(s2, s1);
1874
0
  }
1875
0
1876
0
  {
1877
0
    int arr[] = { 2, 1 };
1878
0
    Span<int> s1 = arr;
1879
0
    Span<int> s2 = arr;
1880
0
1881
0
    ASSERT_EQ(s1, s2);
1882
0
    ASSERT_FALSE(s1 != s2);
1883
0
    ASSERT_FALSE(s1 < s2);
1884
0
    ASSERT_LE(s1, s2);
1885
0
    ASSERT_FALSE(s1 > s2);
1886
0
    ASSERT_GE(s1, s2);
1887
0
    ASSERT_EQ(s2, s1);
1888
0
    ASSERT_FALSE(s2 != s1);
1889
0
    ASSERT_FALSE(s2 < s1);
1890
0
    ASSERT_LE(s2, s1);
1891
0
    ASSERT_FALSE(s2 > s1);
1892
0
    ASSERT_GE(s2, s1);
1893
0
  }
1894
0
1895
0
  {
1896
0
    int arr[] = { 2, 1 }; // bigger
1897
0
1898
0
    Span<int> s1 = nullptr;
1899
0
    Span<int> s2 = arr;
1900
0
1901
0
    ASSERT_NE(s1, s2);
1902
0
    ASSERT_NE(s2, s1);
1903
0
    ASSERT_NE(s1, s2);
1904
0
    ASSERT_NE(s2, s1);
1905
0
    ASSERT_LT(s1, s2);
1906
0
    ASSERT_FALSE(s2 < s1);
1907
0
    ASSERT_LE(s1, s2);
1908
0
    ASSERT_FALSE(s2 <= s1);
1909
0
    ASSERT_GT(s2, s1);
1910
0
    ASSERT_FALSE(s1 > s2);
1911
0
    ASSERT_GE(s2, s1);
1912
0
    ASSERT_FALSE(s1 >= s2);
1913
0
  }
1914
0
1915
0
  {
1916
0
    int arr1[] = { 1, 2 };
1917
0
    int arr2[] = { 1, 2 };
1918
0
    Span<int> s1 = arr1;
1919
0
    Span<int> s2 = arr2;
1920
0
1921
0
    ASSERT_EQ(s1, s2);
1922
0
    ASSERT_FALSE(s1 != s2);
1923
0
    ASSERT_FALSE(s1 < s2);
1924
0
    ASSERT_LE(s1, s2);
1925
0
    ASSERT_FALSE(s1 > s2);
1926
0
    ASSERT_GE(s1, s2);
1927
0
    ASSERT_EQ(s2, s1);
1928
0
    ASSERT_FALSE(s2 != s1);
1929
0
    ASSERT_FALSE(s2 < s1);
1930
0
    ASSERT_LE(s2, s1);
1931
0
    ASSERT_FALSE(s2 > s1);
1932
0
    ASSERT_GE(s2, s1);
1933
0
  }
1934
0
1935
0
  {
1936
0
    int arr[] = { 1, 2, 3 };
1937
0
1938
0
    AssertSpanOfThreeInts(arr);
1939
0
1940
0
    Span<int> s1 = { &arr[0], 2 }; // shorter
1941
0
    Span<int> s2 = arr;            // longer
1942
0
1943
0
    ASSERT_NE(s1, s2);
1944
0
    ASSERT_NE(s2, s1);
1945
0
    ASSERT_NE(s1, s2);
1946
0
    ASSERT_NE(s2, s1);
1947
0
    ASSERT_LT(s1, s2);
1948
0
    ASSERT_FALSE(s2 < s1);
1949
0
    ASSERT_LE(s1, s2);
1950
0
    ASSERT_FALSE(s2 <= s1);
1951
0
    ASSERT_GT(s2, s1);
1952
0
    ASSERT_FALSE(s1 > s2);
1953
0
    ASSERT_GE(s2, s1);
1954
0
    ASSERT_FALSE(s1 >= s2);
1955
0
  }
1956
0
1957
0
  {
1958
0
    int arr1[] = { 1, 2 }; // smaller
1959
0
    int arr2[] = { 2, 1 }; // bigger
1960
0
1961
0
    Span<int> s1 = arr1;
1962
0
    Span<int> s2 = arr2;
1963
0
1964
0
    ASSERT_NE(s1, s2);
1965
0
    ASSERT_NE(s2, s1);
1966
0
    ASSERT_NE(s1, s2);
1967
0
    ASSERT_NE(s2, s1);
1968
0
    ASSERT_LT(s1, s2);
1969
0
    ASSERT_FALSE(s2 < s1);
1970
0
    ASSERT_LE(s1, s2);
1971
0
    ASSERT_FALSE(s2 <= s1);
1972
0
    ASSERT_GT(s2, s1);
1973
0
    ASSERT_FALSE(s1 > s2);
1974
0
    ASSERT_GE(s2, s1);
1975
0
    ASSERT_FALSE(s1 >= s2);
1976
0
  }
1977
0
}
1978
1979
SPAN_TEST(as_bytes)
1980
0
{
1981
0
  int a[] = { 1, 2, 3, 4 };
1982
0
1983
0
  {
1984
0
    Span<const int> s = a;
1985
0
    ASSERT_EQ(s.Length(), 4U);
1986
0
    Span<const uint8_t> bs = AsBytes(s);
1987
0
    ASSERT_EQ(static_cast<const void*>(bs.data()),
1988
0
              static_cast<const void*>(s.data()));
1989
0
    ASSERT_EQ(bs.Length(), s.LengthBytes());
1990
0
  }
1991
0
1992
0
  {
1993
0
    Span<int> s;
1994
0
    auto bs = AsBytes(s);
1995
0
    ASSERT_EQ(bs.Length(), s.Length());
1996
0
    ASSERT_EQ(bs.Length(), 0U);
1997
0
    ASSERT_EQ(bs.size_bytes(), 0U);
1998
0
    ASSERT_EQ(static_cast<const void*>(bs.data()),
1999
0
              static_cast<const void*>(s.data()));
2000
0
    ASSERT_EQ(bs.data(), reinterpret_cast<const uint8_t*>(SLICE_INT_PTR));
2001
0
  }
2002
0
2003
0
  {
2004
0
    Span<int> s = a;
2005
0
    auto bs = AsBytes(s);
2006
0
    ASSERT_EQ(static_cast<const void*>(bs.data()),
2007
0
              static_cast<const void*>(s.data()));
2008
0
    ASSERT_EQ(bs.Length(), s.LengthBytes());
2009
0
  }
2010
0
}
2011
2012
SPAN_TEST(as_writable_bytes)
2013
0
{
2014
0
  int a[] = { 1, 2, 3, 4 };
2015
0
2016
0
  {
2017
#ifdef CONFIRM_COMPILATION_ERRORS
2018
    // you should not be able to get writeable bytes for const objects
2019
    Span<const int> s = a;
2020
    ASSERT_EQ(s.Length(), 4U);
2021
    Span<const byte> bs = AsWritableBytes(s);
2022
    ASSERT_EQ(static_cast<void*>(bs.data()), static_cast<void*>(s.data()));
2023
    ASSERT_EQ(bs.Length(), s.LengthBytes());
2024
#endif
2025
  }
2026
0
2027
0
  {
2028
0
    Span<int> s;
2029
0
    auto bs = AsWritableBytes(s);
2030
0
    ASSERT_EQ(bs.Length(), s.Length());
2031
0
    ASSERT_EQ(bs.Length(), 0U);
2032
0
    ASSERT_EQ(bs.size_bytes(), 0U);
2033
0
    ASSERT_EQ(static_cast<void*>(bs.data()), static_cast<void*>(s.data()));
2034
0
    ASSERT_EQ(bs.data(), reinterpret_cast<uint8_t*>(SLICE_INT_PTR));
2035
0
  }
2036
0
2037
0
  {
2038
0
    Span<int> s = a;
2039
0
    auto bs = AsWritableBytes(s);
2040
0
    ASSERT_EQ(static_cast<void*>(bs.data()), static_cast<void*>(s.data()));
2041
0
    ASSERT_EQ(bs.Length(), s.LengthBytes());
2042
0
  }
2043
0
}
2044
2045
SPAN_TEST(fixed_size_conversions)
2046
0
{
2047
0
  int arr[] = { 1, 2, 3, 4 };
2048
0
2049
0
  // converting to an Span from an equal size array is ok
2050
0
  Span<int, 4> s4 = arr;
2051
0
  ASSERT_EQ(s4.Length(), 4U);
2052
0
2053
0
  // converting to dynamic_range is always ok
2054
0
  {
2055
0
    Span<int> s = s4;
2056
0
    ASSERT_EQ(s.Length(), s4.Length());
2057
0
    static_cast<void>(s);
2058
0
  }
2059
0
2060
0
// initialization or assignment to static Span that REDUCES size is NOT ok
2061
#ifdef CONFIRM_COMPILATION_ERRORS
2062
  {
2063
    Span<int, 2> s = arr;
2064
  }
2065
  {
2066
    Span<int, 2> s2 = s4;
2067
    static_cast<void>(s2);
2068
  }
2069
#endif
2070
2071
#if 0
2072
        // even when done dynamically
2073
        {
2074
            Span<int> s = arr;
2075
            auto f = [&]() {
2076
                Span<int, 2> s2 = s;
2077
                static_cast<void>(s2);
2078
            };
2079
            CHECK_THROW(f(), fail_fast);
2080
        }
2081
#endif
2082
2083
0
  // but doing so explicitly is ok
2084
0
2085
0
  // you can convert statically
2086
0
  {
2087
0
    Span<int, 2> s2 = { arr, 2 };
2088
0
    static_cast<void>(s2);
2089
0
  }
2090
0
  {
2091
0
    Span<int, 1> s1 = s4.First<1>();
2092
0
    static_cast<void>(s1);
2093
0
  }
2094
0
2095
0
  // ...or dynamically
2096
0
  {
2097
0
    // NB: implicit conversion to Span<int,1> from Span<int>
2098
0
    Span<int, 1> s1 = s4.First(1);
2099
0
    static_cast<void>(s1);
2100
0
  }
2101
0
2102
#if 0
2103
        // initialization or assignment to static Span that requires size INCREASE is not ok.
2104
        int arr2[2] = {1, 2};
2105
#endif
2106
2107
#ifdef CONFIRM_COMPILATION_ERRORS
2108
  {
2109
    Span<int, 4> s3 = arr2;
2110
  }
2111
  {
2112
    Span<int, 2> s2 = arr2;
2113
    Span<int, 4> s4a = s2;
2114
  }
2115
#endif
2116
2117
#if 0
2118
        {
2119
            auto f = [&]() {
2120
                Span<int, 4> _s4 = {arr2, 2};
2121
                static_cast<void>(_s4);
2122
            };
2123
            CHECK_THROW(f(), fail_fast);
2124
        }
2125
2126
        // this should fail - we are trying to assign a small dynamic Span to a fixed_size larger one
2127
        Span<int> av = arr2;
2128
        auto f = [&]() {
2129
            Span<int, 4> _s4 = av;
2130
            static_cast<void>(_s4);
2131
        };
2132
        CHECK_THROW(f(), fail_fast);
2133
#endif
2134
}
2135
2136
#if 0
2137
    SPAN_TEST(interop_with_std_regex)
2138
    {
2139
        char lat[] = { '1', '2', '3', '4', '5', '6', 'E', 'F', 'G' };
2140
        Span<char> s = lat;
2141
        auto f_it = s.begin() + 7;
2142
2143
        std::match_results<Span<char>::iterator> match;
2144
2145
        std::regex_match(s.begin(), s.end(), match, std::regex(".*"));
2146
        ASSERT_EQ(match.ready());
2147
        ASSERT_TRUE(!match.empty());
2148
        ASSERT_TRUE(match[0].matched);
2149
        ASSERT_TRUE(match[0].first , s.begin());
2150
        ASSERT_EQ(match[0].second , s.end());
2151
2152
        std::regex_search(s.begin(), s.end(), match, std::regex("F"));
2153
        ASSERT_TRUE(match.ready());
2154
        ASSERT_TRUE(!match.empty());
2155
        ASSERT_TRUE(match[0].matched);
2156
        ASSERT_EQ(match[0].first , f_it);
2157
        ASSERT_EQ(match[0].second , (f_it + 1));
2158
    }
2159
2160
SPAN_TEST(interop_with_gsl_at)
2161
{
2162
  int arr[5] = { 1, 2, 3, 4, 5 };
2163
  Span<int> s{ arr };
2164
  ASSERT_EQ(at(s, 0) , 1 );
2165
ASSERT_EQ(at(s, 1) , 2U);
2166
}
2167
#endif
2168
2169
SPAN_TEST(default_constructible)
2170
0
{
2171
0
  ASSERT_TRUE((std::is_default_constructible<Span<int>>::value));
2172
0
  ASSERT_TRUE((std::is_default_constructible<Span<int, 0>>::value));
2173
0
  ASSERT_TRUE((!std::is_default_constructible<Span<int, 42>>::value));
2174
0
}