1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // span_unittests.cpp: Unit tests for the TSpan class.
7 //
8 
9 #include "Common.h"
10 
11 #include <gtest/gtest.h>
12 
13 using namespace angle;
14 
15 namespace
16 {
17 
18 using Span                                      = sh::TSpan<const unsigned int>;
19 constexpr size_t kSpanDataSize                  = 16;
20 constexpr unsigned int kSpanData[kSpanDataSize] = {0, 1, 2,  3,  4,  5,  6,  7,
21                                                    8, 9, 10, 11, 12, 13, 14, 15};
22 
23 // Test that comparing spans work
TEST(SpanTest,Comparison)24 TEST(SpanTest, Comparison)
25 {
26     // Duplicate data to make sure comparison is being done on values (and not addresses).
27     constexpr unsigned int kSpanDataDup[kSpanDataSize] = {0, 1, 2,  3,  4,  5,  6,  7,
28                                                           8, 9, 10, 11, 12, 13, 14, 15};
29 
30     // Don't use ASSERT_EQ at first because the == is more hidden
31     ASSERT_TRUE(Span() == Span(kSpanData, 0));
32     ASSERT_TRUE(Span(kSpanData + 3, 4) != Span(kSpanDataDup + 5, 4));
33 
34     // Check ASSERT_EQ and ASSERT_NE work correctly
35     ASSERT_EQ(Span(kSpanData, kSpanDataSize), Span(kSpanDataDup, kSpanDataSize));
36     ASSERT_NE(Span(kSpanData, kSpanDataSize - 1), Span(kSpanDataDup + 1, kSpanDataSize - 1));
37     ASSERT_NE(Span(kSpanData, kSpanDataSize), Span(kSpanDataDup, kSpanDataSize - 1));
38     ASSERT_NE(Span(kSpanData, kSpanDataSize - 1), Span(kSpanDataDup, kSpanDataSize));
39     ASSERT_NE(Span(kSpanData, 0), Span(kSpanDataDup, 1));
40     ASSERT_NE(Span(kSpanData, 1), Span(kSpanDataDup, 0));
41 }
42 
43 // Test indexing
TEST(SpanTest,Indexing)44 TEST(SpanTest, Indexing)
45 {
46     constexpr Span sp(kSpanData, kSpanDataSize);
47 
48     for (size_t i = 0; i < kSpanDataSize; ++i)
49     {
50         ASSERT_EQ(sp[i], i);
51     }
52 
53     unsigned int storage[kSpanDataSize] = {};
54     sh::TSpan<unsigned int> writableSpan(storage, kSpanDataSize);
55 
56     for (size_t i = 0; i < kSpanDataSize; ++i)
57     {
58         writableSpan[i] = i;
59     }
60     for (size_t i = 0; i < kSpanDataSize; ++i)
61     {
62         ASSERT_EQ(writableSpan[i], i);
63     }
64     for (size_t i = 0; i < kSpanDataSize; ++i)
65     {
66         ASSERT_EQ(storage[i], i);
67     }
68 }
69 
70 // Test for the various constructors
TEST(SpanTest,Constructors)71 TEST(SpanTest, Constructors)
72 {
73     // Default constructor
74     {
75         Span sp;
76         ASSERT_TRUE(sp.size() == 0);
77         ASSERT_TRUE(sp.empty());
78     }
79 
80     // Constexpr construct from pointer
81     {
82         constexpr Span sp(kSpanData, kSpanDataSize);
83         ASSERT_EQ(sp.data(), kSpanData);
84         ASSERT_EQ(sp.size(), kSpanDataSize);
85         ASSERT_FALSE(sp.empty());
86     }
87 
88     // Copy constructor and copy assignment
89     {
90         Span sp(kSpanData, kSpanDataSize);
91         Span sp2(sp);
92         Span sp3;
93 
94         ASSERT_EQ(sp, sp2);
95         ASSERT_EQ(sp2.data(), kSpanData);
96         ASSERT_EQ(sp2.size(), kSpanDataSize);
97         ASSERT_FALSE(sp2.empty());
98 
99         sp3 = sp;
100 
101         ASSERT_EQ(sp, sp3);
102         ASSERT_EQ(sp3.data(), kSpanData);
103         ASSERT_EQ(sp3.size(), kSpanDataSize);
104         ASSERT_FALSE(sp3.empty());
105     }
106 }
107 
108 // Test accessing the data directly
TEST(SpanTest,DataAccess)109 TEST(SpanTest, DataAccess)
110 {
111     constexpr Span sp(kSpanData, kSpanDataSize);
112     const unsigned int *data = sp.data();
113 
114     for (size_t i = 0; i < kSpanDataSize; ++i)
115     {
116         ASSERT_EQ(data[i], i);
117     }
118 }
119 
120 // Test front and back
TEST(SpanTest,FrontAndBack)121 TEST(SpanTest, FrontAndBack)
122 {
123     constexpr Span sp(kSpanData, kSpanDataSize);
124     ASSERT_TRUE(sp.front() == 0);
125     ASSERT_EQ(sp.back(), kSpanDataSize - 1);
126 }
127 
128 // Test begin and end
TEST(SpanTest,BeginAndEnd)129 TEST(SpanTest, BeginAndEnd)
130 {
131     constexpr Span sp(kSpanData, kSpanDataSize);
132 
133     size_t currentIndex = 0;
134     for (unsigned int value : sp)
135     {
136         ASSERT_EQ(value, currentIndex);
137         ++currentIndex;
138     }
139 }
140 
141 // Test reverse begin and end
TEST(SpanTest,RbeginAndRend)142 TEST(SpanTest, RbeginAndRend)
143 {
144     constexpr Span sp(kSpanData, kSpanDataSize);
145 
146     size_t currentIndex = 0;
147     for (auto iter = sp.rbegin(); iter != sp.rend(); ++iter)
148     {
149         ASSERT_EQ(*iter, kSpanDataSize - 1 - currentIndex);
150         ++currentIndex;
151     }
152 }
153 
154 // Test first and last
TEST(SpanTest,FirstAndLast)155 TEST(SpanTest, FirstAndLast)
156 {
157     constexpr Span sp(kSpanData, kSpanDataSize);
158     constexpr size_t kSplitSize = kSpanDataSize / 4;
159     constexpr Span first        = sp.first(kSplitSize);
160     constexpr Span last         = sp.last(kSplitSize);
161 
162     ASSERT_EQ(first, Span(kSpanData, kSplitSize));
163     ASSERT_EQ(first.data(), kSpanData);
164     ASSERT_EQ(first.size(), kSplitSize);
165 
166     ASSERT_EQ(last, Span(kSpanData + kSpanDataSize - kSplitSize, kSplitSize));
167     ASSERT_EQ(last.data(), kSpanData + kSpanDataSize - kSplitSize);
168     ASSERT_EQ(last.size(), kSplitSize);
169 }
170 
171 // Test subspan
TEST(SpanTest,Subspan)172 TEST(SpanTest, Subspan)
173 {
174     constexpr Span sp(kSpanData, kSpanDataSize);
175     constexpr size_t kSplitOffset = kSpanDataSize / 4;
176     constexpr size_t kSplitSize   = kSpanDataSize / 2;
177     constexpr Span subspan        = sp.subspan(kSplitOffset, kSplitSize);
178 
179     ASSERT_EQ(subspan, Span(kSpanData + kSplitOffset, kSplitSize));
180     ASSERT_EQ(subspan.data(), kSpanData + kSplitOffset);
181     ASSERT_EQ(subspan.size(), kSplitSize);
182 }
183 
184 }  // anonymous namespace
185