1 //===- SequenceTest.cpp - Unit tests for a sequence abstraciton -----------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/Sequence.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "gmock/gmock.h"
12 #include "gtest/gtest.h"
19 using testing::ElementsAre
;
20 using testing::IsEmpty
;
24 using detail::canTypeFitValue
;
25 using detail::CheckedInt
;
27 using IntegralTypes
= testing::Types
<uint8_t, // 0
39 template <class T
> class StrongIntTest
: public testing::Test
{};
40 TYPED_TEST_SUITE(StrongIntTest
, IntegralTypes
, );
41 TYPED_TEST(StrongIntTest
, Operations
) {
43 auto Max
= std::numeric_limits
<T
>::max();
44 auto Min
= std::numeric_limits
<T
>::min();
46 // We bail out for types that are not entirely representable within intmax_t.
47 if (!canTypeFitValue
<intmax_t>(Max
) || !canTypeFitValue
<intmax_t>(Min
))
50 // All representable values convert back and forth.
51 EXPECT_EQ(CheckedInt::from(Min
).template to
<T
>(), Min
);
52 EXPECT_EQ(CheckedInt::from(Max
).template to
<T
>(), Max
);
54 // Addition -2, -1, 0, 1, 2.
55 const T Expected
= Max
/ 2;
56 const CheckedInt Actual
= CheckedInt::from(Expected
);
57 EXPECT_EQ((Actual
+ -2).template to
<T
>(), Expected
- 2);
58 EXPECT_EQ((Actual
+ -1).template to
<T
>(), Expected
- 1);
59 EXPECT_EQ((Actual
+ 0).template to
<T
>(), Expected
);
60 EXPECT_EQ((Actual
+ 1).template to
<T
>(), Expected
+ 1);
61 EXPECT_EQ((Actual
+ 2).template to
<T
>(), Expected
+ 2);
64 EXPECT_EQ(Actual
, Actual
);
65 EXPECT_NE(Actual
, Actual
+ 1);
68 EXPECT_EQ(Actual
- Actual
, 0);
69 EXPECT_EQ((Actual
+ 1) - Actual
, 1);
70 EXPECT_EQ(Actual
- (Actual
+ 2), -2);
73 #if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
74 TEST(StrongIntDeathTest
, OutOfBounds
) {
75 // Values above 'INTMAX_MAX' are not representable.
76 EXPECT_DEATH(CheckedInt::from
<uintmax_t>(INTMAX_MAX
+ 1ULL), "Out of bounds");
77 EXPECT_DEATH(CheckedInt::from
<uintmax_t>(UINTMAX_MAX
), "Out of bounds");
78 // Casting to narrower type asserts when out of bounds.
79 EXPECT_DEATH(CheckedInt::from(-1).to
<uint8_t>(), "Out of bounds");
80 EXPECT_DEATH(CheckedInt::from(256).to
<uint8_t>(), "Out of bounds");
81 // Operations leading to intmax_t overflow assert.
82 EXPECT_DEATH(CheckedInt::from(INTMAX_MAX
) + 1, "Out of bounds");
83 EXPECT_DEATH(CheckedInt::from(INTMAX_MIN
) + -1, "Out of bounds");
84 EXPECT_DEATH(CheckedInt::from(INTMAX_MIN
) - CheckedInt::from(INTMAX_MAX
),
89 TEST(SafeIntIteratorTest
, Operations
) {
90 detail::SafeIntIterator
<int, false> Forward(0);
91 detail::SafeIntIterator
<int, true> Reverse(0);
93 const auto SetToZero
= [&]() {
94 Forward
= detail::SafeIntIterator
<int, false>(0);
95 Reverse
= detail::SafeIntIterator
<int, true>(0);
98 // Equality / Comparisons
100 EXPECT_EQ(Forward
, Forward
);
101 EXPECT_LT(Forward
- 1, Forward
);
102 EXPECT_LE(Forward
, Forward
);
103 EXPECT_LE(Forward
- 1, Forward
);
104 EXPECT_GT(Forward
+ 1, Forward
);
105 EXPECT_GE(Forward
, Forward
);
106 EXPECT_GE(Forward
+ 1, Forward
);
108 EXPECT_EQ(Reverse
, Reverse
);
109 EXPECT_LT(Reverse
- 1, Reverse
);
110 EXPECT_LE(Reverse
, Reverse
);
111 EXPECT_LE(Reverse
- 1, Reverse
);
112 EXPECT_GT(Reverse
+ 1, Reverse
);
113 EXPECT_GE(Reverse
, Reverse
);
114 EXPECT_GE(Reverse
+ 1, Reverse
);
118 EXPECT_EQ(*Forward
, 0);
119 EXPECT_EQ(*Reverse
, 0);
123 EXPECT_EQ(Forward
[2], 2);
124 EXPECT_EQ(Reverse
[2], -2);
129 EXPECT_EQ(*Forward
, 1);
131 EXPECT_EQ(*Reverse
, -1);
136 EXPECT_EQ(*Forward
, -1);
138 EXPECT_EQ(*Reverse
, 1);
142 EXPECT_EQ(*(Forward
++), 0);
143 EXPECT_EQ(*Forward
, 1);
144 EXPECT_EQ(*(Reverse
++), 0);
145 EXPECT_EQ(*Reverse
, -1);
149 EXPECT_EQ(*(Forward
--), 0);
150 EXPECT_EQ(*Forward
, -1);
151 EXPECT_EQ(*(Reverse
--), 0);
152 EXPECT_EQ(*Reverse
, 1);
154 // Compound assignment operators
157 EXPECT_EQ(*Forward
, 1);
159 EXPECT_EQ(*Reverse
, -1);
162 EXPECT_EQ(*Forward
, -2);
164 EXPECT_EQ(*Reverse
, 2);
168 EXPECT_EQ(*(Forward
+ 3), 3);
169 EXPECT_EQ(*(Reverse
+ 3), -3);
171 EXPECT_EQ(*(Forward
- 4), -4);
172 EXPECT_EQ(*(Reverse
- 4), 4);
176 EXPECT_EQ(Forward
- Forward
, 0);
177 EXPECT_EQ(Reverse
- Reverse
, 0);
178 EXPECT_EQ((Forward
+ 1) - Forward
, 1);
179 EXPECT_EQ(Forward
- (Forward
+ 1), -1);
180 EXPECT_EQ((Reverse
+ 1) - Reverse
, 1);
181 EXPECT_EQ(Reverse
- (Reverse
+ 1), -1);
184 TEST(SequenceTest
, Iteration
) {
185 EXPECT_THAT(seq(-4, 5), ElementsAre(-4, -3, -2, -1, 0, 1, 2, 3, 4));
186 EXPECT_THAT(reverse(seq(-4, 5)), ElementsAre(4, 3, 2, 1, 0, -1, -2, -3, -4));
188 EXPECT_THAT(seq_inclusive(-4, 5),
189 ElementsAre(-4, -3, -2, -1, 0, 1, 2, 3, 4, 5));
190 EXPECT_THAT(reverse(seq_inclusive(-4, 5)),
191 ElementsAre(5, 4, 3, 2, 1, 0, -1, -2, -3, -4));
194 TEST(SequenceTest
, Distance
) {
195 const auto Forward
= seq(0, 10);
196 EXPECT_EQ(std::distance(Forward
.begin(), Forward
.end()), 10);
197 EXPECT_EQ(std::distance(Forward
.rbegin(), Forward
.rend()), 10);
200 TEST(SequenceTest
, Dereference
) {
201 const auto Forward
= seq(0, 10).begin();
202 EXPECT_EQ(Forward
[0], 0);
203 EXPECT_EQ(Forward
[2], 2);
204 const auto Backward
= seq(0, 10).rbegin();
205 EXPECT_EQ(Backward
[0], 9);
206 EXPECT_EQ(Backward
[2], 7);
209 enum UntypedEnum
{ A
= 3 };
210 enum TypedEnum
: uint32_t { B
= 3 };
213 enum class ScopedEnum
: uint16_t { C
= 3 };
217 enum NestedEnum
{ D
= 4 };
218 enum NestedEnum2
{ E
= 5 };
221 enum NestedEnum3
{ F
= 6 };
222 friend struct llvm::enum_iteration_traits
<NestedEnum3
>;
225 static auto getNestedEnum3() { return NestedEnum3::F
; }
232 template <> struct enum_iteration_traits
<UntypedEnum
> {
233 static constexpr bool is_iterable
= true;
236 template <> struct enum_iteration_traits
<TypedEnum
> {
237 static constexpr bool is_iterable
= true;
240 template <> struct enum_iteration_traits
<X::ScopedEnum
> {
241 static constexpr bool is_iterable
= true;
244 template <> struct enum_iteration_traits
<S::NestedEnum
> {
245 static constexpr bool is_iterable
= true;
248 template <> struct enum_iteration_traits
<S::NestedEnum3
> {
249 static constexpr bool is_iterable
= true;
256 TEST(StrongIntTest
, Enums
) {
257 EXPECT_EQ(CheckedInt::from(A
).to
<UntypedEnum
>(), A
);
258 EXPECT_EQ(CheckedInt::from(B
).to
<TypedEnum
>(), B
);
259 EXPECT_EQ(CheckedInt::from(X::ScopedEnum::C
).to
<X::ScopedEnum
>(),
263 TEST(SequenceTest
, IterableEnums
) {
264 EXPECT_THAT(enum_seq(UntypedEnum::A
, UntypedEnum::A
), IsEmpty());
265 EXPECT_THAT(enum_seq_inclusive(UntypedEnum::A
, UntypedEnum::A
),
266 ElementsAre(UntypedEnum::A
));
268 EXPECT_THAT(enum_seq(TypedEnum::B
, TypedEnum::B
), IsEmpty());
269 EXPECT_THAT(enum_seq_inclusive(TypedEnum::B
, TypedEnum::B
),
270 ElementsAre(TypedEnum::B
));
272 EXPECT_THAT(enum_seq(X::ScopedEnum::C
, X::ScopedEnum::C
), IsEmpty());
273 EXPECT_THAT(enum_seq_inclusive(X::ScopedEnum::C
, X::ScopedEnum::C
),
274 ElementsAre(X::ScopedEnum::C
));
276 EXPECT_THAT(enum_seq_inclusive(S::NestedEnum::D
, S::NestedEnum::D
),
277 ElementsAre(S::NestedEnum::D
));
278 EXPECT_THAT(enum_seq_inclusive(S::getNestedEnum3(), S::getNestedEnum3()),
279 ElementsAre(S::getNestedEnum3()));
282 TEST(SequenceTest
, NonIterableEnums
) {
283 EXPECT_THAT(enum_seq(S::NestedEnum2::E
, S::NestedEnum2::E
,
284 force_iteration_on_noniterable_enum
),
286 EXPECT_THAT(enum_seq_inclusive(S::NestedEnum2::E
, S::NestedEnum2::E
,
287 force_iteration_on_noniterable_enum
),
288 ElementsAre(S::NestedEnum2::E
));
290 // Check that this also works with enums marked as iterable.
291 EXPECT_THAT(enum_seq(UntypedEnum::A
, UntypedEnum::A
,
292 force_iteration_on_noniterable_enum
),
294 EXPECT_THAT(enum_seq_inclusive(UntypedEnum::A
, UntypedEnum::A
,
295 force_iteration_on_noniterable_enum
),
296 ElementsAre(UntypedEnum::A
));