Skip to content

Commit 1fba72c

Browse files
committed
test(span): add more tests for span
Signed-off-by: Yuming He <ComixHe1895@outlook.com>
1 parent e2e30b9 commit 1fba72c

1 file changed

Lines changed: 208 additions & 11 deletions

File tree

tests/ll-box-ut/src/span_test.cpp

Lines changed: 208 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <linyaps_box/utils/span.h>
88

99
#include <array>
10+
#include <cstring>
1011
#include <vector>
1112

1213
namespace utils = linyaps_box::utils;
@@ -28,7 +29,6 @@ TEST(SpanAt, OutOfRangeThrows)
2829
const utils::span<int> s(arr);
2930

3031
EXPECT_THROW(std::ignore = s.at(3), std::out_of_range);
31-
EXPECT_THROW(std::ignore = s.at(100), std::out_of_range);
3232
}
3333

3434
TEST(SpanAt, EmptySpanThrows)
@@ -55,16 +55,7 @@ TEST(SpanAt, ConstSpanReadsCorrectly)
5555
EXPECT_EQ(s.at(1), 6);
5656
}
5757

58-
TEST(SpanAt, BoundaryIndex)
59-
{
60-
std::array arr = { 99 };
61-
const utils::span<int> s(arr);
62-
63-
EXPECT_EQ(s.at(0), 99);
64-
EXPECT_THROW(std::ignore = s.at(1), std::out_of_range);
65-
}
66-
67-
TEST(SpanAt, SubspanAt)
58+
TEST(Subspan, Offset)
6859
{
6960
std::array raw{ 0, 1, 2, 3, 4 };
7061
auto s = utils::span<int>(raw).subspan(1, 3);
@@ -73,3 +64,209 @@ TEST(SpanAt, SubspanAt)
7364
EXPECT_EQ(s.at(2), 3);
7465
EXPECT_THROW(std::ignore = s.at(3), std::out_of_range);
7566
}
67+
68+
// P1976R2: fixed-size span construction from dynamic-size range should be explicit.
69+
// Single-argument constructors are tested via is_convertible_v (which requires implicit
70+
// conversion). Two-argument constructors (ptr,count) and (first,last) are tested via runtime
71+
// positive tests.
72+
static_assert(std::is_convertible_v<std::vector<int> &, utils::span<int>>,
73+
"dynamic span from container should be implicit");
74+
static_assert(!std::is_convertible_v<std::vector<int> &, utils::span<int, 3>>,
75+
"fixed span from container should be explicit");
76+
77+
static_assert(std::is_convertible_v<utils::span<int> &, utils::span<const int>>,
78+
"dynamic→dynamic span should be implicit");
79+
static_assert(!std::is_convertible_v<utils::span<int> &, utils::span<const int, 5>>,
80+
"dynamic→fixed span should be explicit");
81+
static_assert(std::is_convertible_v<utils::span<int, 5> &, utils::span<const int, 5>>,
82+
"fixed→fixed (matching) span should be implicit");
83+
static_assert(std::is_convertible_v<utils::span<int, 5> &, utils::span<const int>>,
84+
"fixed→dynamic span should be implicit");
85+
86+
static_assert(std::is_convertible_v<int (&)[5], utils::span<int>>,
87+
"dynamic span from c-array should be implicit");
88+
static_assert(std::is_convertible_v<int (&)[5], utils::span<int, 5>>,
89+
"fixed span from c-array (matching extent) should be implicit");
90+
static_assert(std::is_convertible_v<std::array<int, 5> &, utils::span<int, 5>>,
91+
"fixed span from std::array (matching extent) should be implicit");
92+
static_assert(std::is_convertible_v<const std::array<int, 5> &, utils::span<const int, 5>>,
93+
"fixed span from const std::array (matching extent) should be implicit");
94+
95+
static_assert(std::is_default_constructible_v<utils::span<int>>,
96+
"dynamic span should be default-constructible");
97+
static_assert(!std::is_default_constructible_v<utils::span<int, 5>>,
98+
"fixed non-zero span should NOT be default-constructible");
99+
100+
TEST(SpanConstructorExplicit, PtrCountDynamic)
101+
{
102+
const std::vector<int> data{ 1, 2, 3 };
103+
const utils::span<const int> s(data.data(), 3);
104+
EXPECT_EQ(s.size(), 3);
105+
EXPECT_EQ(s[0], 1);
106+
EXPECT_EQ(s[2], 3);
107+
}
108+
109+
TEST(SpanConstructorExplicit, FirstLastDynamic)
110+
{
111+
const std::vector<int> data{ 1, 2, 3, 4 };
112+
const utils::span<const int> s(data.cbegin(), data.cend());
113+
EXPECT_EQ(s.size(), 4);
114+
EXPECT_EQ(s[0], 1);
115+
EXPECT_EQ(s[3], 4);
116+
}
117+
118+
TEST(SpanConstructorExplicit, ContainerFixedExplicit)
119+
{
120+
const std::vector<int> v{ 1, 2, 3 };
121+
auto s = utils::span<const int, 3>(v);
122+
EXPECT_EQ(s.size(), 3);
123+
EXPECT_EQ(s[0], 1);
124+
EXPECT_EQ(s[2], 3);
125+
}
126+
127+
TEST(SpanConstructorExplicit, ConvertingSpanFixedToDynamic)
128+
{
129+
std::array arr{ 1, 2, 3 };
130+
const utils::span<const int, 3> fixed(arr);
131+
const utils::span<const int> dyn(fixed);
132+
EXPECT_EQ(dyn.size(), 3);
133+
EXPECT_EQ(dyn[0], 1);
134+
}
135+
136+
TEST(SpanConstructorExplicit, ConvertingSpanDynamicToFixed)
137+
{
138+
std::vector<int> arr{ 1, 2, 3 };
139+
const utils::span<const int> dyn(arr);
140+
auto fixed = utils::span<const int, 3>(dyn);
141+
EXPECT_EQ(fixed.size(), 3);
142+
EXPECT_EQ(fixed[0], 1);
143+
}
144+
145+
TEST(SpanConstructorExplicit, ItCountDynamic)
146+
{
147+
const std::vector<int> data{ 10, 20, 30 };
148+
const utils::span<const int> s(data.cbegin(), 2);
149+
EXPECT_EQ(s.size(), 2);
150+
EXPECT_EQ(s[0], 10);
151+
EXPECT_EQ(s[1], 20);
152+
}
153+
154+
TEST(SpanConstructorExplicit, ItEndFixedExplicit)
155+
{
156+
const std::vector<int> data{ 1, 2, 3 };
157+
const utils::span<const int, 3> s(data.cbegin(), data.cend());
158+
EXPECT_EQ(s.size(), 3);
159+
EXPECT_EQ(s[0], 1);
160+
EXPECT_EQ(s[2], 3);
161+
}
162+
163+
TEST(SpanConstructorExplicit, ItCountFixedExplicit)
164+
{
165+
const std::vector<int> data{ 5, 6, 7 };
166+
const utils::span<const int, 3> s(data.cbegin(), 3);
167+
EXPECT_EQ(s.size(), 3);
168+
EXPECT_EQ(s[0], 5);
169+
EXPECT_EQ(s[2], 7);
170+
}
171+
172+
TEST(SpanCTAD, CArray)
173+
{
174+
int arr[] = { 1, 2, 3 }; // NOLINT
175+
const utils::span s(arr);
176+
EXPECT_EQ(s.size(), 3);
177+
EXPECT_EQ(s[0], 1);
178+
EXPECT_EQ(s[2], 3);
179+
static_assert(decltype(s)::extent == 3);
180+
}
181+
182+
TEST(SpanCTAD, StdArray)
183+
{
184+
std::array arr{ 10, 20 };
185+
const utils::span s(arr);
186+
EXPECT_EQ(s.size(), 2);
187+
EXPECT_EQ(s[0], 10);
188+
static_assert(decltype(s)::extent == 2);
189+
}
190+
191+
TEST(SpanCTAD, ConstStdArray)
192+
{
193+
const std::array arr{ 1, 2, 3, 4 };
194+
const utils::span s(arr);
195+
EXPECT_EQ(s.size(), 4);
196+
EXPECT_EQ(s[3], 4);
197+
static_assert(decltype(s)::extent == 4);
198+
}
199+
200+
TEST(SpanCTAD, ItCount)
201+
{
202+
std::vector<int> v{ 5, 5, 5 };
203+
const utils::span s(v.begin(), 2);
204+
EXPECT_EQ(s.size(), 2);
205+
EXPECT_EQ(s[0], 5);
206+
static_assert(decltype(s)::extent == utils::dynamic_extent);
207+
}
208+
209+
TEST(SpanCTAD, ItEnd)
210+
{
211+
const std::vector<int> v{ 7, 8, 9 };
212+
const utils::span s(v.cbegin(), v.cend());
213+
EXPECT_EQ(s.size(), 3);
214+
EXPECT_EQ(s[2], 9);
215+
static_assert(decltype(s)::extent == utils::dynamic_extent);
216+
}
217+
218+
namespace {
219+
220+
template <typename T, typename = void>
221+
struct has_as_bytes : std::false_type
222+
{
223+
};
224+
225+
template <typename T>
226+
struct has_as_bytes<T, std::void_t<decltype(utils::as_bytes(std::declval<utils::span<T>>()))>>
227+
: std::true_type
228+
{
229+
};
230+
231+
template <typename T, typename = void>
232+
struct has_as_writable_bytes : std::false_type
233+
{
234+
};
235+
236+
template <typename T>
237+
struct has_as_writable_bytes<
238+
T,
239+
std::void_t<decltype(utils::as_writable_bytes(std::declval<utils::span<T>>()))>> : std::true_type
240+
{
241+
};
242+
243+
} // anonymous namespace
244+
245+
static_assert(has_as_bytes<int>::value, "as_bytes should accept int");
246+
static_assert(has_as_bytes<const int>::value, "as_bytes should accept const int");
247+
static_assert(!has_as_bytes<volatile int>::value, "as_bytes should reject volatile");
248+
static_assert(has_as_writable_bytes<int>::value, "as_writable_bytes should accept int");
249+
static_assert(!has_as_writable_bytes<const int>::value, "as_writable_bytes should reject const");
250+
static_assert(!has_as_writable_bytes<volatile int>::value,
251+
"as_writable_bytes should reject volatile");
252+
253+
TEST(SpanBytes, AsBytes)
254+
{
255+
const std::array arr{ 0x01020304, 0x05060708 };
256+
const utils::span s(arr);
257+
auto bytes = utils::as_bytes(s);
258+
EXPECT_EQ(bytes.size(), sizeof(arr));
259+
EXPECT_EQ(bytes.data(), reinterpret_cast<const std::byte *>(s.data()));
260+
}
261+
262+
TEST(SpanBytes, AsWritableBytes)
263+
{
264+
std::array arr{ 0x01020304 };
265+
const utils::span s(arr);
266+
auto bytes = utils::as_writable_bytes(s);
267+
EXPECT_EQ(bytes.size(), sizeof(int));
268+
memset(bytes.data(), 0, sizeof(int));
269+
EXPECT_EQ(arr[0], 0);
270+
bytes[0] = std::byte(1);
271+
EXPECT_EQ(arr[0], 1);
272+
}

0 commit comments

Comments
 (0)