1 // Copyright (C) 206 Jonathan Müller <jonathanmueller.dev@gmail.com>
2 // This file is subject to the license terms in the LICENSE file
3 // found in the top-level directory of this distribution.
4 
5 #include <type_safe/integer.hpp>
6 
7 #include <catch.hpp>
8 
9 #include <sstream>
10 
11 using namespace type_safe;
12 
13 #ifndef TYPE_SAFE_TEST_NO_STATIC_ASSERT
14 static_assert(std::is_standard_layout<integer<int>>::value, "");
15 static_assert(std::is_trivially_copyable<integer<int>>::value, "");
16 // conversion checks
17 static_assert(sizeof(short) < sizeof(int), "");
18 static_assert(std::is_constructible<integer<short>, short>::value, "");
19 static_assert(!std::is_constructible<integer<short>, int>::value, "");
20 static_assert(!std::is_constructible<integer<short>, unsigned short>::value, "");
21 static_assert(!std::is_constructible<integer<unsigned short>, short>::value, "");
22 
23 static_assert(std::is_assignable<integer<short>, short>::value, "");
24 static_assert(!std::is_assignable<integer<short>, int>::value, "");
25 static_assert(!std::is_assignable<integer<short>, unsigned short>::value, "");
26 static_assert(!std::is_assignable<integer<unsigned short>, short>::value, "");
27 
28 static_assert(sizeof(int) < sizeof(long long), "");
29 static_assert(std::is_constructible<integer<int>, int>::value, "");
30 static_assert(std::is_constructible<integer<int>, short>::value, "");
31 static_assert(!std::is_constructible<integer<int>, long long>::value, "");
32 static_assert(!std::is_constructible<integer<int>, unsigned>::value, "");
33 static_assert(!std::is_constructible<integer<unsigned>, int>::value, "");
34 
35 static_assert(std::is_assignable<integer<int>, int>::value, "");
36 static_assert(std::is_assignable<integer<int>, short>::value, "");
37 static_assert(!std::is_assignable<integer<int>, long long>::value, "");
38 static_assert(!std::is_assignable<integer<int>, unsigned>::value, "");
39 static_assert(!std::is_assignable<integer<unsigned>, int>::value, "");
40 #endif
41 
42 TEST_CASE("integer")
43 {
44     using int_t = integer<int>;
45 
46     SECTION("constructor")
47     {
48         int_t a(0);
49         REQUIRE(static_cast<int>(a) == 0);
50         int_t b(32);
51         REQUIRE(static_cast<int>(b) == 32);
52         int_t c(-25);
53         REQUIRE(static_cast<int>(c) == -25);
54     }
55     SECTION("assignment")
56     {
57         int_t a(0);
58         a = 32;
59         REQUIRE(static_cast<int>(a) == 32);
60         a = -25;
61         REQUIRE(static_cast<int>(a) == -25);
62     }
63     SECTION("unary")
64     {
65         int_t a(13);
66         REQUIRE(static_cast<int>(+a) == static_cast<int>(a));
67         REQUIRE(static_cast<int>(-a) == -static_cast<int>(a));
68     }
69     SECTION("increment")
70     {
71         int_t a(0);
72         REQUIRE(static_cast<int>(++a) == 1);
73         REQUIRE(static_cast<int>(a++) == 1);
74         REQUIRE(static_cast<int>(a) == 2);
75     }
76     SECTION("decrement")
77     {
78         int_t a(0);
79         REQUIRE(static_cast<int>(--a) == -1);
80         REQUIRE(static_cast<int>(a--) == -1);
81         REQUIRE(static_cast<int>(a) == -2);
82     }
83     SECTION("addition")
84     {
85         int_t wrapper(0);
86         int   normal(0);
87         REQUIRE(static_cast<int>(wrapper) == normal);
88 
89         wrapper += 5;
90         normal += 5;
91         REQUIRE(static_cast<int>(wrapper) == normal);
92 
93         wrapper += short(5);
94         normal += short(5);
95         REQUIRE(static_cast<int>(wrapper) == normal);
96 
97         wrapper = wrapper + (-23);
98         normal  = normal + (-23);
99         REQUIRE(static_cast<int>(wrapper) == normal);
100 
101         wrapper = 22 + wrapper;
102         normal  = 22 + normal;
103         REQUIRE(static_cast<int>(wrapper) == normal);
104 
105         wrapper = int_t(-4) + wrapper;
106         normal  = (-4) + normal;
107         REQUIRE(static_cast<int>(wrapper) == normal);
108     }
109     SECTION("subtraction")
110     {
111         int_t wrapper(0);
112         int   normal(0);
113         REQUIRE(static_cast<int>(wrapper) == normal);
114 
115         wrapper -= 5;
116         normal -= 5;
117         REQUIRE(static_cast<int>(wrapper) == normal);
118 
119         wrapper -= short(5);
120         normal -= short(5);
121         REQUIRE(static_cast<int>(wrapper) == normal);
122 
123         wrapper = wrapper - (-23);
124         normal  = normal - (-23);
125         REQUIRE(static_cast<int>(wrapper) == normal);
126 
127         wrapper = 22 - wrapper;
128         normal  = 22 - normal;
129         REQUIRE(static_cast<int>(wrapper) == normal);
130 
131         wrapper = int_t(-4) - wrapper;
132         normal  = (-4) - normal;
133         REQUIRE(static_cast<int>(wrapper) == normal);
134     }
135     SECTION("multiplication")
136     {
137         int_t wrapper(1);
138         int   normal(1);
139         REQUIRE(static_cast<int>(wrapper) == normal);
140 
141         wrapper *= 5;
142         normal *= 5;
143         REQUIRE(static_cast<int>(wrapper) == normal);
144 
145         wrapper *= short(5);
146         normal *= short(5);
147         REQUIRE(static_cast<int>(wrapper) == normal);
148 
149         wrapper = wrapper * (-23);
150         normal  = normal * (-23);
151         REQUIRE(static_cast<int>(wrapper) == normal);
152 
153         wrapper = 22 * wrapper;
154         normal  = 22 * normal;
155         REQUIRE(static_cast<int>(wrapper) == normal);
156 
157         wrapper = int_t(-4) * wrapper;
158         normal  = (-4) * normal;
159         REQUIRE(static_cast<int>(wrapper) == normal);
160     }
161     SECTION("division")
162     {
163         int_t wrapper(23 * 25);
164         int   normal(23 * 25);
165         REQUIRE(static_cast<int>(wrapper) == normal);
166 
167         wrapper /= 5;
168         normal /= 5;
169         REQUIRE(static_cast<int>(wrapper) == normal);
170 
171         wrapper /= short(5);
172         normal /= short(5);
173         REQUIRE(static_cast<int>(wrapper) == normal);
174 
175         wrapper = wrapper / (-23);
176         normal  = normal / (-23);
177         REQUIRE(static_cast<int>(wrapper) == normal);
178 
179         wrapper = 22 / wrapper;
180         normal  = 22 / normal;
181         REQUIRE(static_cast<int>(wrapper) == normal);
182 
183         wrapper = int_t(-4) / wrapper;
184         normal  = (-4) / normal;
185         REQUIRE(static_cast<int>(wrapper) == normal);
186     }
187     SECTION("modulo")
188     {
189         int_t wrapper(24 * 6);
190         int   normal(24 * 6);
191         REQUIRE(static_cast<int>(wrapper) == normal);
192 
193         wrapper %= 5;
194         normal %= 5;
195         REQUIRE(static_cast<int>(wrapper) == normal);
196 
197         wrapper %= short(5);
198         normal %= short(5);
199         REQUIRE(static_cast<int>(wrapper) == normal);
200 
201         wrapper = wrapper % (-23);
202         normal  = normal % (-23);
203         REQUIRE(static_cast<int>(wrapper) == normal);
204 
205         wrapper = 22 % wrapper;
206         normal  = 22 % normal;
207         REQUIRE(static_cast<int>(wrapper) == normal);
208 
209         wrapper = int_t(-4) % wrapper;
210         normal  = (-4) % normal;
211         REQUIRE(static_cast<int>(wrapper) == normal);
212     }
213     SECTION("comparison")
214     {
215         // ==
216         REQUIRE(bool(int_t(4) == int_t(4)));
217         REQUIRE(!(int_t(5) == int_t(4)));
218 
219         REQUIRE(bool(4 == int_t(4)));
220         REQUIRE(!(5 == int_t(4)));
221 
222         REQUIRE(bool(int_t(4) == 4));
223         REQUIRE(!(int_t(5) == 4));
224 
225         // !=
226         REQUIRE(bool(int_t(5) != int_t(4)));
227         REQUIRE(!(int_t(4) != int_t(4)));
228 
229         REQUIRE(bool(5 != int_t(4)));
230         REQUIRE(!(4 != int_t(4)));
231 
232         REQUIRE(bool(int_t(5) != 4));
233         REQUIRE(!(int_t(4) != 4));
234 
235         // <
236         REQUIRE(bool(int_t(4) < int_t(5)));
237         REQUIRE(!(int_t(5) < int_t(4)));
238         REQUIRE(!(int_t(4) < int_t(4)));
239 
240         REQUIRE(bool(4 < int_t(5)));
241         REQUIRE(!(5 < int_t(4)));
242         REQUIRE(!(4 < int_t(4)));
243 
244         REQUIRE(bool(int_t(4) < 5));
245         REQUIRE(!(int_t(5) < 4));
246         REQUIRE(!(int_t(4) < 4));
247 
248         // <=
249         REQUIRE(bool(int_t(4) <= int_t(5)));
250         REQUIRE(!(int_t(5) <= int_t(4)));
251         REQUIRE(bool(int_t(4) <= int_t(4)));
252 
253         REQUIRE(bool(4 <= int_t(5)));
254         REQUIRE(!(5 <= int_t(4)));
255         REQUIRE(bool(4 <= int_t(4)));
256 
257         REQUIRE(bool(int_t(4) <= 5));
258         REQUIRE(!(int_t(5) <= 4));
259         REQUIRE(bool(int_t(4) <= 4));
260 
261         // >
262         REQUIRE(bool(int_t(5) > int_t(4)));
263         REQUIRE(!(int_t(4) > int_t(5)));
264         REQUIRE(!(int_t(5) > int_t(5)));
265 
266         REQUIRE(bool(5 > int_t(4)));
267         REQUIRE(!(4 > int_t(5)));
268         REQUIRE(!(5 > int_t(5)));
269 
270         REQUIRE(bool(int_t(5) > 4));
271         REQUIRE(!(int_t(4) > 5));
272         REQUIRE(!(int_t(5) > 5));
273 
274         // >=
275         REQUIRE(bool(int_t(5) >= int_t(4)));
276         REQUIRE(!(int_t(4) >= int_t(5)));
277         REQUIRE(bool(int_t(5) >= int_t(5)));
278 
279         REQUIRE(bool(5 >= int_t(4)));
280         REQUIRE(!(4 >= int_t(5)));
281         REQUIRE(bool(5 >= int_t(5)));
282 
283         REQUIRE(bool(int_t(5) >= 4));
284         REQUIRE(!(int_t(4) >= 5));
285         REQUIRE(bool(int_t(5) >= 5));
286     }
287     SECTION("make_(un)signed")
288     {
289         int_t             a = 5;
290         integer<unsigned> b = make_unsigned(a);
291         REQUIRE(static_cast<unsigned>(b) == 5);
292 
293         b = 125u;
294         a = make_signed(b);
295         REQUIRE(static_cast<int>(a) == 125);
296     }
297     SECTION("i/o")
298     {
299         std::ostringstream out;
300         std::istringstream in("10");
301 
302         int_t i(0);
303         out << i;
304         REQUIRE(out.str() == "0");
305 
306         in >> i;
307         REQUIRE(static_cast<int>(i) == 10);
308     }
309     SECTION("abs")
310     {
311         int               i  = 123;
312         integer<unsigned> ia = type_safe::abs(i);
313         REQUIRE(static_cast<unsigned>(ia) == 123u);
314 
315         i  = -123;
316         ia = type_safe::abs(i);
317         REQUIRE(static_cast<unsigned>(ia) == 123u);
318     }
319     SECTION("signed_to_unsigned")
320     {
321         // From int8_t
322         REQUIRE(!std::is_convertible<integer<int8_t>, integer<uint8_t>>::value);
323         REQUIRE(!std::is_convertible<integer<int8_t>, integer<uint16_t>>::value);
324         REQUIRE(!std::is_convertible<integer<int8_t>, integer<uint32_t>>::value);
325         REQUIRE(!std::is_convertible<integer<int8_t>, integer<uint64_t>>::value);
326 
327         // From int16_t
328         REQUIRE(!std::is_convertible<integer<int16_t>, integer<uint8_t>>::value);
329         REQUIRE(!std::is_convertible<integer<int16_t>, integer<uint16_t>>::value);
330         REQUIRE(!std::is_convertible<integer<int16_t>, integer<uint32_t>>::value);
331         REQUIRE(!std::is_convertible<integer<int16_t>, integer<uint64_t>>::value);
332 
333         // From int32_t
334         REQUIRE(!std::is_convertible<integer<int32_t>, integer<uint8_t>>::value);
335         REQUIRE(!std::is_convertible<integer<int32_t>, integer<uint16_t>>::value);
336         REQUIRE(!std::is_convertible<integer<int32_t>, integer<uint32_t>>::value);
337         REQUIRE(!std::is_convertible<integer<int32_t>, integer<uint64_t>>::value);
338 
339         // From int64_t
340         REQUIRE(!std::is_convertible<integer<int64_t>, integer<uint8_t>>::value);
341         REQUIRE(!std::is_convertible<integer<int64_t>, integer<uint16_t>>::value);
342         REQUIRE(!std::is_convertible<integer<int64_t>, integer<uint32_t>>::value);
343         REQUIRE(!std::is_convertible<integer<int64_t>, integer<uint64_t>>::value);
344     }
345     SECTION("unsigned_to_signed")
346     {
347         // From uint8_t
348         REQUIRE(!std::is_convertible<integer<uint8_t>, integer<int8_t>>::value);
349         REQUIRE(std::is_convertible<integer<uint8_t>, integer<int16_t>>::value);
350         REQUIRE(std::is_convertible<integer<uint8_t>, integer<int32_t>>::value);
351         REQUIRE(std::is_convertible<integer<uint8_t>, integer<int64_t>>::value);
352 
353         // From uint16_t
354         REQUIRE(!std::is_convertible<integer<uint16_t>, integer<int8_t>>::value);
355         REQUIRE(!std::is_convertible<integer<uint16_t>, integer<int16_t>>::value);
356         REQUIRE(std::is_convertible<integer<uint16_t>, integer<int32_t>>::value);
357         REQUIRE(std::is_convertible<integer<uint16_t>, integer<int64_t>>::value);
358 
359         // From uint32_t
360         REQUIRE(!std::is_convertible<integer<uint32_t>, integer<int8_t>>::value);
361         REQUIRE(!std::is_convertible<integer<uint32_t>, integer<int16_t>>::value);
362         REQUIRE(!std::is_convertible<integer<uint32_t>, integer<int32_t>>::value);
363         REQUIRE(std::is_convertible<integer<uint32_t>, integer<int64_t>>::value);
364 
365         // From uint32_t
366         REQUIRE(!std::is_convertible<integer<uint64_t>, integer<int8_t>>::value);
367         REQUIRE(!std::is_convertible<integer<uint64_t>, integer<int16_t>>::value);
368         REQUIRE(!std::is_convertible<integer<uint64_t>, integer<int32_t>>::value);
369         REQUIRE(!std::is_convertible<integer<uint64_t>, integer<int64_t>>::value);
370     }
371     SECTION("signed_to_signed")
372     {
373         // From int8_t
374         REQUIRE(std::is_convertible<integer<int8_t>, integer<int8_t>>::value);
375         REQUIRE(std::is_convertible<integer<int8_t>, integer<int16_t>>::value);
376         REQUIRE(std::is_convertible<integer<int8_t>, integer<int32_t>>::value);
377         REQUIRE(std::is_convertible<integer<int8_t>, integer<int64_t>>::value);
378 
379         // From int16_t
380         REQUIRE(!std::is_convertible<integer<int16_t>, integer<int8_t>>::value);
381         REQUIRE(std::is_convertible<integer<int16_t>, integer<int16_t>>::value);
382         REQUIRE(std::is_convertible<integer<int16_t>, integer<int32_t>>::value);
383         REQUIRE(std::is_convertible<integer<int16_t>, integer<int64_t>>::value);
384 
385         // From int32_t
386         REQUIRE(!std::is_convertible<integer<int32_t>, integer<int8_t>>::value);
387         REQUIRE(!std::is_convertible<integer<int32_t>, integer<int16_t>>::value);
388         REQUIRE(std::is_convertible<integer<int32_t>, integer<int32_t>>::value);
389         REQUIRE(std::is_convertible<integer<int32_t>, integer<int64_t>>::value);
390 
391         // From int64_t
392         REQUIRE(!std::is_convertible<integer<int64_t>, integer<int8_t>>::value);
393         REQUIRE(!std::is_convertible<integer<int64_t>, integer<int16_t>>::value);
394         REQUIRE(!std::is_convertible<integer<int64_t>, integer<int32_t>>::value);
395         REQUIRE(std::is_convertible<integer<int64_t>, integer<int64_t>>::value);
396     }
397     SECTION("unsigned_to_unsigned")
398     {
399         // From uint8_t
400         REQUIRE(std::is_convertible<integer<uint8_t>, integer<uint8_t>>::value);
401         REQUIRE(std::is_convertible<integer<uint8_t>, integer<uint16_t>>::value);
402         REQUIRE(std::is_convertible<integer<uint8_t>, integer<uint32_t>>::value);
403         REQUIRE(std::is_convertible<integer<uint8_t>, integer<uint64_t>>::value);
404 
405         // From uint16_t
406         REQUIRE(!std::is_convertible<integer<uint16_t>, integer<uint8_t>>::value);
407         REQUIRE(std::is_convertible<integer<uint16_t>, integer<uint16_t>>::value);
408         REQUIRE(std::is_convertible<integer<uint16_t>, integer<uint32_t>>::value);
409         REQUIRE(std::is_convertible<integer<uint16_t>, integer<uint64_t>>::value);
410 
411         // From uint32_t
412         REQUIRE(!std::is_convertible<integer<uint32_t>, integer<uint8_t>>::value);
413         REQUIRE(!std::is_convertible<integer<uint32_t>, integer<uint16_t>>::value);
414         REQUIRE(std::is_convertible<integer<uint32_t>, integer<uint32_t>>::value);
415         REQUIRE(std::is_convertible<integer<uint32_t>, integer<uint64_t>>::value);
416 
417         // From uint64_t
418         REQUIRE(!std::is_convertible<integer<uint64_t>, integer<uint8_t>>::value);
419         REQUIRE(!std::is_convertible<integer<uint64_t>, integer<uint16_t>>::value);
420         REQUIRE(!std::is_convertible<integer<uint64_t>, integer<uint32_t>>::value);
421         REQUIRE(std::is_convertible<integer<uint64_t>, integer<uint64_t>>::value);
422     }
423 }
424