Serenity Operating System
1/*
2 * Copyright (c) 2020-2021, the SerenityOS developers.
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibTest/TestCase.h>
8
9#include <AK/TypeList.h>
10
11#define STATIC_EXPECT_EQ(lhs, rhs) \
12 static_assert(IsSame<lhs, rhs>, "");
13
14#define STATIC_EXPECT_FALSE(Expression) \
15 static_assert(!Expression, "");
16
17#define STATIC_EXPECT_TRUE(Expression) \
18 static_assert(Expression, "");
19
20#define EXPECT_TRAIT_TRUE(trait, ...) \
21 for_each_type<TypeList<__VA_ARGS__>>([]<typename T>(TypeWrapper<T>) { \
22 STATIC_EXPECT_TRUE(trait<T>); \
23 })
24
25#define EXPECT_TRAIT_FALSE(trait, ...) \
26 for_each_type<TypeList<__VA_ARGS__>>([]<typename T>(TypeWrapper<T>) { \
27 STATIC_EXPECT_FALSE(trait<T>); \
28 })
29
30#define EXPECT_EQ_WITH_TRAIT(trait, ListA, ListB) \
31 for_each_type_zipped<ListA, ListB>([]<typename A, typename B>(TypeWrapper<A>, TypeWrapper<B>) { \
32 STATIC_EXPECT_EQ(trait<A>, B); \
33 })
34
35#define EXPECT_VARIADIC_TRAIT_TRUE(trait, ...) \
36 static_assert(trait<__VA_ARGS__>)
37
38#define EXPECT_VARIADIC_TRAIT_FALSE(trait, ...) \
39 static_assert(!trait<__VA_ARGS__>)
40
41enum class Enummer : u8 {
42 Dummy
43};
44
45TEST_CASE(FundamentalTypeClassification)
46{
47 EXPECT_TRAIT_TRUE(IsVoid, void);
48 EXPECT_TRAIT_FALSE(IsVoid, int, Empty, nullptr_t);
49
50 EXPECT_TRAIT_TRUE(IsNullPointer, nullptr_t);
51 EXPECT_TRAIT_FALSE(IsNullPointer, void, int, Empty, decltype(0));
52
53 EXPECT_TRAIT_TRUE(IsFloatingPoint, float, double, long double);
54 EXPECT_TRAIT_FALSE(IsFloatingPoint, int, Empty, nullptr_t, void);
55
56 EXPECT_TRAIT_TRUE(IsArithmetic, float, double, long double, bool, size_t);
57 EXPECT_TRAIT_TRUE(IsArithmetic, char, signed char, unsigned char, char8_t, char16_t, char32_t);
58 EXPECT_TRAIT_TRUE(IsArithmetic, short, int, long, long long);
59 EXPECT_TRAIT_TRUE(IsArithmetic, unsigned short, unsigned int, unsigned long, unsigned long long);
60
61 EXPECT_TRAIT_FALSE(IsArithmetic, void, nullptr_t, Empty);
62
63 EXPECT_TRAIT_TRUE(IsFundamental, void, nullptr_t);
64 EXPECT_TRAIT_TRUE(IsFundamental, float, double, long double, bool, size_t);
65 EXPECT_TRAIT_TRUE(IsFundamental, char, signed char, unsigned char, char8_t, char16_t, char32_t);
66 EXPECT_TRAIT_TRUE(IsFundamental, short, int, long, long long);
67 EXPECT_TRAIT_TRUE(IsFundamental, unsigned short, unsigned int, unsigned long, unsigned long long);
68
69 EXPECT_TRAIT_FALSE(IsFundamental, Empty, int*, int&);
70
71 EXPECT_TRAIT_FALSE(IsSigned, unsigned);
72 EXPECT_TRAIT_FALSE(IsSigned, unsigned short);
73 EXPECT_TRAIT_FALSE(IsSigned, unsigned char);
74 EXPECT_TRAIT_FALSE(IsSigned, unsigned long);
75 EXPECT_TRAIT_TRUE(IsSigned, int);
76 EXPECT_TRAIT_TRUE(IsSigned, short);
77 EXPECT_TRAIT_TRUE(IsSigned, long);
78
79 EXPECT_TRAIT_TRUE(IsUnsigned, unsigned);
80 EXPECT_TRAIT_TRUE(IsUnsigned, unsigned short);
81 EXPECT_TRAIT_TRUE(IsUnsigned, unsigned char);
82 EXPECT_TRAIT_TRUE(IsUnsigned, unsigned long);
83 EXPECT_TRAIT_FALSE(IsUnsigned, int);
84 EXPECT_TRAIT_FALSE(IsUnsigned, short);
85 EXPECT_TRAIT_FALSE(IsUnsigned, long);
86
87 EXPECT_TRAIT_TRUE(IsEnum, Enummer);
88 EXPECT_TRAIT_FALSE(IsEnum, Empty);
89 EXPECT_TRAIT_FALSE(IsEnum, int);
90 EXPECT_TRAIT_FALSE(IsEnum, void);
91 EXPECT_TRAIT_FALSE(IsEnum, nullptr_t);
92}
93
94TEST_CASE(AddConst)
95{
96 // clang-format off
97 using NoConstList = TypeList<int, const int, Empty, const Empty>;
98 using YesConstList = TypeList<const int, const int, const Empty, const Empty>;
99 // clang-format on
100
101 EXPECT_EQ_WITH_TRAIT(AddConst, NoConstList, YesConstList);
102}
103
104TEST_CASE(UnderlyingType)
105{
106 using Type = UnderlyingType<Enummer>;
107
108 STATIC_EXPECT_EQ(Type, u8);
109}
110
111TEST_CASE(RemoveCVReference)
112{
113 using TestTypeList = TypeList<int, int&, int const&, int volatile&, int const volatile&, int&&, int const&&, int volatile&&, int const volatile&&>;
114 using ResultTypeList = TypeList<int, int, int, int, int, int, int, int, int>;
115
116 EXPECT_EQ_WITH_TRAIT(RemoveCVReference, TestTypeList, ResultTypeList);
117}
118
119TEST_CASE(AddReference)
120{
121 STATIC_EXPECT_EQ(AddLvalueReference<int>, int&);
122 STATIC_EXPECT_EQ(AddLvalueReference<int&>, int&);
123 STATIC_EXPECT_EQ(AddLvalueReference<int&&>, int&);
124
125 STATIC_EXPECT_EQ(AddRvalueReference<int>, int&&);
126 STATIC_EXPECT_EQ(AddRvalueReference<int&>, int&);
127 STATIC_EXPECT_EQ(AddRvalueReference<int&&>, int&&);
128
129 STATIC_EXPECT_EQ(AddLvalueReference<void>, void);
130}
131
132TEST_CASE(IsConvertible)
133{
134 struct A {
135 };
136 struct B {
137 B(A);
138 };
139 struct C {
140 A a;
141 operator A() { return a; };
142 };
143 struct D {
144 };
145
146 EXPECT_VARIADIC_TRAIT_TRUE(IsConvertible, A, B);
147 EXPECT_VARIADIC_TRAIT_FALSE(IsConvertible, B, A);
148 EXPECT_VARIADIC_TRAIT_TRUE(IsConvertible, C, A);
149 EXPECT_VARIADIC_TRAIT_FALSE(IsConvertible, A, C);
150 EXPECT_VARIADIC_TRAIT_FALSE(IsConvertible, D, A);
151 EXPECT_VARIADIC_TRAIT_FALSE(IsConvertible, A, D);
152}
153
154TEST_CASE(IsAssignable)
155{
156 EXPECT_VARIADIC_TRAIT_FALSE(IsAssignable, int, int);
157 EXPECT_VARIADIC_TRAIT_TRUE(IsAssignable, int&, int);
158 EXPECT_VARIADIC_TRAIT_FALSE(IsAssignable, int, void);
159
160 struct A {
161 };
162 EXPECT_TRAIT_TRUE(IsCopyAssignable, A);
163 EXPECT_TRAIT_TRUE(IsTriviallyCopyAssignable, A);
164 EXPECT_TRAIT_TRUE(IsMoveAssignable, A);
165 EXPECT_TRAIT_TRUE(IsTriviallyMoveAssignable, A);
166
167 struct B {
168 B& operator=(B const&) { return *this; }
169 B& operator=(B&&) { return *this; }
170 };
171 EXPECT_TRAIT_TRUE(IsCopyAssignable, B);
172 EXPECT_TRAIT_FALSE(IsTriviallyCopyAssignable, B);
173 EXPECT_TRAIT_TRUE(IsMoveAssignable, B);
174 EXPECT_TRAIT_FALSE(IsTriviallyMoveAssignable, B);
175
176 struct C {
177 C& operator=(C const&) = delete;
178 C& operator=(C&&) = delete;
179 };
180 EXPECT_TRAIT_FALSE(IsCopyAssignable, C);
181 EXPECT_TRAIT_FALSE(IsTriviallyCopyAssignable, C);
182 EXPECT_TRAIT_FALSE(IsMoveAssignable, C);
183 EXPECT_TRAIT_FALSE(IsTriviallyMoveAssignable, C);
184}
185
186TEST_CASE(IsConstructible)
187{
188 struct A {
189 };
190 EXPECT_TRAIT_TRUE(IsCopyConstructible, A);
191 EXPECT_TRAIT_TRUE(IsTriviallyCopyConstructible, A);
192 EXPECT_TRAIT_TRUE(IsMoveConstructible, A);
193 EXPECT_TRAIT_TRUE(IsTriviallyMoveConstructible, A);
194
195 struct B {
196 B(B const&)
197 {
198 }
199 B(B&&)
200 {
201 }
202 };
203 EXPECT_TRAIT_TRUE(IsCopyConstructible, B);
204 EXPECT_TRAIT_FALSE(IsTriviallyCopyConstructible, B);
205 EXPECT_TRAIT_TRUE(IsMoveConstructible, B);
206 EXPECT_TRAIT_FALSE(IsTriviallyMoveConstructible, B);
207
208 struct C {
209 C(C const&) = delete;
210 C(C&&) = delete;
211 };
212 EXPECT_TRAIT_FALSE(IsCopyConstructible, C);
213 EXPECT_TRAIT_FALSE(IsTriviallyCopyConstructible, C);
214 EXPECT_TRAIT_FALSE(IsMoveConstructible, C);
215 EXPECT_TRAIT_FALSE(IsTriviallyMoveConstructible, C);
216
217 struct D {
218 D(int);
219 };
220 EXPECT_VARIADIC_TRAIT_TRUE(IsConstructible, D, int);
221 EXPECT_VARIADIC_TRAIT_TRUE(IsConstructible, D, char);
222 EXPECT_VARIADIC_TRAIT_FALSE(IsConstructible, D, char const*);
223 EXPECT_VARIADIC_TRAIT_FALSE(IsConstructible, D, void);
224}
225
226TEST_CASE(IsDestructible)
227{
228 struct A {
229 };
230 EXPECT_TRAIT_TRUE(IsDestructible, A);
231 EXPECT_TRAIT_TRUE(IsTriviallyDestructible, A);
232 struct B {
233 ~B()
234 {
235 }
236 };
237 EXPECT_TRAIT_TRUE(IsDestructible, B);
238 EXPECT_TRAIT_FALSE(IsTriviallyDestructible, B);
239 struct C {
240 ~C() = delete;
241 };
242 EXPECT_TRAIT_FALSE(IsDestructible, C);
243 EXPECT_TRAIT_FALSE(IsTriviallyDestructible, C);
244}
245
246TEST_CASE(CommonType)
247{
248 using TCommon0 = CommonType<int, float, char>;
249 EXPECT_VARIADIC_TRAIT_TRUE(IsSame, TCommon0, float);
250
251 using TCommon1 = CommonType<int, int, int, char>;
252 EXPECT_VARIADIC_TRAIT_TRUE(IsSame, TCommon1, int);
253
254 struct Foo {
255 };
256 using TCommon2 = CommonType<Foo, Foo, Foo>;
257 EXPECT_VARIADIC_TRAIT_TRUE(IsSame, TCommon2, Foo);
258
259 struct Bar {
260 operator Foo();
261 };
262 using TCommon3 = CommonType<Bar, Foo, Bar>;
263 EXPECT_VARIADIC_TRAIT_TRUE(IsSame, TCommon3, Foo);
264}