1// Copyright 2016 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <inttypes.h>
6#include <limits.h>
7#include <signal.h>
8#include <stdint.h>
9#include <wchar.h>
10
11#include <fbl/type_support.h>
12#include <unittest/unittest.h>
13
14// stdint.h defines the following types:
15// Fixed width types:
16// int8_t
17// int16_t
18// int32_t
19// int64_t
20// uint8_t
21// uint16_t
22// uint32_t
23// uint64_t
24
25// Minimum width types:
26// int_least8_t
27// int_least16_t
28// int_least32_t
29// int_least64_t
30// uint_least8_t
31// uint_least16_t
32// uint_least32_t
33// uint_least64_t
34
35// Fast minimum width types:
36// int_fast8_t
37// int_fast16_t
38// int_fast32_t
39// int_fast64_t
40// uint_fast8_t
41// uint_fast16_t
42// uint_fast32_t
43// uint_fast64_t
44
45// Pointer-sized types:
46// intptr_t
47// uintptr_t
48
49// Maximum-width types:
50// intmax_t
51// uintmax_t
52
53// stddef.h defines the following types:
54// ptrdiff_t
55// size_t
56// wchar_t
57
58// signal.h defines the following type:
59// sig_atomic_t
60
61// Test sizes.
62static_assert(CHAR_BIT == 8, "");
63
64static_assert(sizeof(int8_t) == 1, "");
65static_assert(sizeof(int16_t) == 2, "");
66static_assert(sizeof(int32_t) == 4, "");
67static_assert(sizeof(int64_t) == 8, "");
68static_assert(sizeof(uint8_t) == 1, "");
69static_assert(sizeof(uint16_t) == 2, "");
70static_assert(sizeof(uint32_t) == 4, "");
71static_assert(sizeof(uint64_t) == 8, "");
72
73static_assert(sizeof(int_least8_t) >= 1, "");
74static_assert(sizeof(int_least16_t) >= 2, "");
75static_assert(sizeof(int_least32_t) >= 4, "");
76static_assert(sizeof(int_least64_t) >= 8, "");
77static_assert(sizeof(uint_least8_t) >= 1, "");
78static_assert(sizeof(uint_least16_t) >= 2, "");
79static_assert(sizeof(uint_least32_t) >= 4, "");
80static_assert(sizeof(uint_least64_t) >= 8, "");
81
82static_assert(sizeof(int_fast8_t) >= 1, "");
83static_assert(sizeof(int_fast16_t) >= 2, "");
84static_assert(sizeof(int_fast32_t) >= 4, "");
85static_assert(sizeof(int_fast64_t) >= 8, "");
86static_assert(sizeof(uint_fast8_t) >= 1, "");
87static_assert(sizeof(uint_fast16_t) >= 2, "");
88static_assert(sizeof(uint_fast32_t) >= 4, "");
89static_assert(sizeof(uint_fast64_t) >= 8, "");
90
91static_assert(sizeof(intptr_t) == sizeof(void*), "");
92static_assert(sizeof(uintptr_t) == sizeof(void*), "");
93
94static_assert(sizeof(intmax_t) == 8, "");
95static_assert(sizeof(uintmax_t) == 8, "");
96
97static_assert(sizeof(ptrdiff_t) == sizeof(void*), "");
98static_assert(sizeof(size_t) == sizeof(void*), "");
99
100// No interesting guarantees can be made about the sizes of these:
101// wchar_t
102// sig_atomic_t
103
104// Check maximums.
105#define CHECK_MAX_TYPE(type, TYPE, max_t, MAX) \
106    ((max_t)TYPE##_MAX == (MAX >> (CHAR_BIT * (sizeof(max_t) - sizeof(type)))))
107
108#define CHECK_MAX_UNSIGNED(type, TYPE) CHECK_MAX_TYPE(type, TYPE, uintmax_t, UINTMAX_MAX)
109#define CHECK_MAX_SIGNED(type, TYPE) CHECK_MAX_TYPE(type, TYPE, intmax_t, INTMAX_MAX)
110
111#define CHECK_MAX(type, TYPE) static_assert(fbl::is_signed<type>::value ? CHECK_MAX_SIGNED(type, TYPE) : CHECK_MAX_UNSIGNED(type, TYPE), "");
112
113CHECK_MAX(int8_t, INT8);
114CHECK_MAX(int16_t, INT16);
115CHECK_MAX(int32_t, INT32);
116CHECK_MAX(int64_t, INT64);
117CHECK_MAX(uint8_t, UINT8);
118CHECK_MAX(uint16_t, UINT16);
119CHECK_MAX(uint32_t, UINT32);
120CHECK_MAX(uint64_t, UINT64);
121
122CHECK_MAX(int_least8_t, INT_LEAST8);
123CHECK_MAX(int_least16_t, INT_LEAST16);
124CHECK_MAX(int_least32_t, INT_LEAST32);
125CHECK_MAX(int_least64_t, INT_LEAST64);
126CHECK_MAX(uint_least8_t, UINT_LEAST8);
127CHECK_MAX(uint_least16_t, UINT_LEAST16);
128CHECK_MAX(uint_least32_t, UINT_LEAST32);
129CHECK_MAX(uint_least64_t, UINT_LEAST64);
130
131CHECK_MAX(int_fast8_t, INT_FAST8);
132CHECK_MAX(int_fast16_t, INT_FAST16);
133CHECK_MAX(int_fast32_t, INT_FAST32);
134CHECK_MAX(int_fast64_t, INT_FAST64);
135CHECK_MAX(uint_fast8_t, UINT_FAST8);
136CHECK_MAX(uint_fast16_t, UINT_FAST16);
137CHECK_MAX(uint_fast32_t, UINT_FAST32);
138CHECK_MAX(uint_fast64_t, UINT_FAST64);
139
140CHECK_MAX(intptr_t, INTPTR);
141CHECK_MAX(uintptr_t, UINTPTR);
142
143CHECK_MAX(intmax_t, INTMAX);
144CHECK_MAX(uintmax_t, UINTMAX);
145
146CHECK_MAX(ptrdiff_t, PTRDIFF);
147CHECK_MAX(size_t, SIZE);
148CHECK_MAX(wchar_t, WCHAR);
149
150CHECK_MAX(sig_atomic_t, SIG_ATOMIC);
151
152// Check minimums.
153#define CHECK_MIN_TYPE(type, TYPE)                                   \
154    ((intmax_t)TYPE##_MIN == (INTMAX_MIN >> (CHAR_BIT * (sizeof(intmax_t) - sizeof(type)))))
155
156#define CHECK_MIN(type, TYPE) static_assert(CHECK_MIN_TYPE(type, TYPE), "")
157
158CHECK_MIN(int8_t, INT8);
159CHECK_MIN(int16_t, INT16);
160CHECK_MIN(int32_t, INT32);
161CHECK_MIN(int64_t, INT64);
162
163CHECK_MIN(int_least8_t, INT_LEAST8);
164CHECK_MIN(int_least16_t, INT_LEAST16);
165CHECK_MIN(int_least32_t, INT_LEAST32);
166CHECK_MIN(int_least64_t, INT_LEAST64);
167
168CHECK_MIN(int_fast8_t, INT_FAST8);
169CHECK_MIN(int_fast16_t, INT_FAST16);
170CHECK_MIN(int_fast32_t, INT_FAST32);
171CHECK_MIN(int_fast64_t, INT_FAST64);
172
173CHECK_MIN(intptr_t, INTPTR);
174
175CHECK_MIN(intmax_t, INTMAX);
176
177CHECK_MIN(ptrdiff_t, PTRDIFF);
178static_assert(fbl::is_signed<wchar_t>::value ? CHECK_MIN_TYPE(wchar_t, WCHAR) : (WCHAR_MIN == 0), "");
179
180static_assert(fbl::is_signed<sig_atomic_t>::value ? CHECK_MIN_TYPE(sig_atomic_t, SIG_ATOMIC) : (SIG_ATOMIC_MIN == 0), "");
181
182// The INTN_C and UINTN_C macros expand into integer constants
183// "corresponding to the type int_leastN_t" and "uint_leastN_t"
184// respectively.
185
186static_assert(INT8_C(0) == fbl::integral_constant<int_least8_t, 0>::value, "");
187static_assert(INT8_C(-0x7f - 1) == fbl::integral_constant<int_least8_t, -0x7f - 1>::value, "");
188static_assert(INT8_C(0x7f) == fbl::integral_constant<int_least8_t, 0x7f>::value, "");
189
190static_assert(INT16_C(0) == fbl::integral_constant<int_least16_t, 0>::value, "");
191static_assert(INT16_C(-0x7fff - 1) == fbl::integral_constant<int_least16_t, -0x7fff - 1>::value, "");
192static_assert(INT16_C(0x7fff) == fbl::integral_constant<int_least16_t, 0x7fff>::value, "");
193
194static_assert(INT32_C(0) == fbl::integral_constant<int_least32_t, 0>::value, "");
195static_assert(INT32_C(-0x7fffffff - 1) == fbl::integral_constant<int_least32_t, -0x7fffffff - 1>::value, "");
196static_assert(INT32_C(0x7fffffff) == fbl::integral_constant<int_least32_t, 0x7fffffff>::value, "");
197
198static_assert(INT64_C(0) == fbl::integral_constant<int_least64_t, 0>::value, "");
199static_assert(INT64_C(-0x7fffffffffffffff - 1) == fbl::integral_constant<int_least64_t, -0x7fffffffffffffff - 1>::value, "");
200static_assert(INT64_C(0x7fffffffffffffff) == fbl::integral_constant<int_least64_t, 0x7fffffffffffffff>::value, "");
201
202
203static_assert(UINT8_C(0) == fbl::integral_constant<uint_least8_t, 0>::value, "");
204static_assert(UINT8_C(0xff) == fbl::integral_constant<uint_least8_t, 0xff>::value, "");
205
206static_assert(UINT16_C(0) == fbl::integral_constant<uint_least16_t, 0>::value, "");
207static_assert(UINT16_C(0xffff) == fbl::integral_constant<uint_least16_t, 0xffff>::value, "");
208
209static_assert(UINT32_C(0) == fbl::integral_constant<uint_least32_t, 0>::value, "");
210static_assert(UINT32_C(0xffffffff) == fbl::integral_constant<uint_least32_t, 0xffffffff>::value, "");
211
212static_assert(UINT64_C(0) == fbl::integral_constant<uint_least64_t, 0>::value, "");
213static_assert(UINT64_C(0xffffffffffffffff) == fbl::integral_constant<uint_least64_t, 0xffffffffffffffff>::value, "");
214
215
216// Unlike the above, the INTMAX_C and UINTMAX_C macros explicitly
217// produce values of type intmax_t and uintmax_t respectively, not
218// just compatible values.
219
220static_assert(fbl::is_same<intmax_t, decltype(INTMAX_C(0))>::value, "");
221static_assert(fbl::is_same<intmax_t, decltype(INTMAX_C(-0x7fffffffffffffff - 1))>::value, "");
222static_assert(fbl::is_same<intmax_t, decltype(INTMAX_C(0x7fffffffffffffff))>::value, "");
223static_assert(INTMAX_C(0) == fbl::integral_constant<intmax_t, 0>::value, "");
224static_assert(INTMAX_C(-0xffffffffffffffff - 1) == fbl::integral_constant<intmax_t, -0xffffffffffffffff - 1>::value, "");
225static_assert(INTMAX_C(0x7fffffffffffffff) == fbl::integral_constant<intmax_t, 0x7fffffffffffffff>::value, "");
226
227static_assert(fbl::is_same<uintmax_t, decltype(UINTMAX_C(0))>::value, "");
228static_assert(fbl::is_same<uintmax_t, decltype(UINTMAX_C(0xffffffffffffffff))>::value, "");
229static_assert(UINTMAX_C(0) == fbl::integral_constant<uintmax_t, 0>::value, "");
230static_assert(UINTMAX_C(0xffffffffffffffff) == fbl::integral_constant<uintmax_t, 0xffffffffffffffff>::value, "");
231
232
233// Check PRI* and SCN* format strings.
234#define LAST(fmt) (fmt[strlen(fmt) - 1])
235
236// Signed format specifiers.
237#define CHECK_d(fmt) EXPECT_EQ(LAST(fmt), 'd', "incorrect format specifier")
238#define CHECK_i(fmt) EXPECT_EQ(LAST(fmt), 'i', "incorrect format specifier")
239
240// Unsigned format specifiers. Note that X is only used by printf, and
241// not also by scanf.
242#define CHECK_o(fmt) EXPECT_EQ(LAST(fmt), 'o', "incorrect format specifier")
243#define CHECK_u(fmt) EXPECT_EQ(LAST(fmt), 'u', "incorrect format specifier")
244#define CHECK_x(fmt) EXPECT_EQ(LAST(fmt), 'x', "incorrect format specifier")
245#define CHECK_X(fmt) EXPECT_EQ(LAST(fmt), 'X', "incorrect format specifier")
246
247#define CHECK_FORMAT_STRINGS(pri, scn, pcheck, scheck, type, max) do { \
248        pcheck(pri);                                                    \
249        scheck(scn);                                                    \
250        char buf[256] = {0};                                            \
251        ASSERT_GT(snprintf(buf, sizeof(buf), "%" pri, (type)max), 1); \
252        type n = (type)0;                                               \
253        ASSERT_EQ(sscanf(buf, "%" scn, &n), 1);                     \
254        ASSERT_EQ(n, max);                                          \
255    } while (0)
256
257#define CHECK_SIGNED_FORMATS(size, type, max) do {                      \
258        CHECK_FORMAT_STRINGS(PRId ## size, SCNd ## size, CHECK_d, CHECK_d, type, max); \
259        CHECK_FORMAT_STRINGS(PRIi ## size, SCNi ## size, CHECK_i, CHECK_i, type, max); \
260    } while (0)
261
262// Since X is not used by scanf (only x), the last line has PRIX but
263// SCNx (upper and lower case).
264#define CHECK_UNSIGNED_FORMATS(size, type, max) do {                    \
265        CHECK_FORMAT_STRINGS(PRIo ## size, SCNo ## size, CHECK_o, CHECK_o, type, max); \
266        CHECK_FORMAT_STRINGS(PRIu ## size, SCNu ## size, CHECK_u, CHECK_u, type, max); \
267        CHECK_FORMAT_STRINGS(PRIx ## size, SCNx ## size, CHECK_x, CHECK_x, type, max); \
268        CHECK_FORMAT_STRINGS(PRIX ## size, SCNx ## size, CHECK_X, CHECK_x, type, max); \
269    } while (0)
270
271#define CHECK_FORMATS(size, type, max) do {             \
272        if (fbl::is_signed<type>::value) {             \
273            CHECK_SIGNED_FORMATS(size, type, max);      \
274        } else {                                        \
275            CHECK_UNSIGNED_FORMATS(size, type, max);    \
276        }                                               \
277    } while (0)
278
279static bool check_format_specifiers(void) {
280    BEGIN_TEST;
281
282    CHECK_FORMATS(8, int8_t, INT8_MAX);
283    CHECK_FORMATS(16, int16_t, INT16_MAX);
284    CHECK_FORMATS(32, int32_t, INT32_MAX);
285    CHECK_FORMATS(64, int64_t, INT64_MAX);
286    CHECK_FORMATS(8, uint8_t, UINT8_MAX);
287    CHECK_FORMATS(16, uint16_t, UINT16_MAX);
288    CHECK_FORMATS(32, uint32_t, UINT32_MAX);
289    CHECK_FORMATS(64, uint64_t, UINT64_MAX);
290
291    CHECK_FORMATS(FAST8, int_fast8_t, INT_FAST8_MAX);
292    CHECK_FORMATS(FAST16, int_fast16_t, INT_FAST16_MAX);
293    CHECK_FORMATS(FAST32, int_fast32_t, INT_FAST32_MAX);
294    CHECK_FORMATS(FAST64, int_fast64_t, INT_FAST64_MAX);
295    CHECK_FORMATS(FAST8, uint_fast8_t, UINT_FAST8_MAX);
296    CHECK_FORMATS(FAST16, uint_fast16_t, UINT_FAST16_MAX);
297    CHECK_FORMATS(FAST32, uint_fast32_t, UINT_FAST32_MAX);
298    CHECK_FORMATS(FAST64, uint_fast64_t, UINT_FAST64_MAX);
299
300    CHECK_FORMATS(LEAST8, int_least8_t, INT_LEAST8_MAX);
301    CHECK_FORMATS(LEAST16, int_least16_t, INT_LEAST16_MAX);
302    CHECK_FORMATS(LEAST32, int_least32_t, INT_LEAST32_MAX);
303    CHECK_FORMATS(LEAST64, int_least64_t, INT_LEAST64_MAX);
304    CHECK_FORMATS(LEAST8, uint_least8_t, UINT_LEAST8_MAX);
305    CHECK_FORMATS(LEAST16, uint_least16_t, UINT_LEAST16_MAX);
306    CHECK_FORMATS(LEAST32, uint_least32_t, UINT_LEAST32_MAX);
307    CHECK_FORMATS(LEAST64, uint_least64_t, UINT_LEAST64_MAX);
308
309    CHECK_FORMATS(PTR, intptr_t, INTPTR_MAX);
310    CHECK_FORMATS(PTR, uintptr_t, UINTPTR_MAX);
311
312    // Note that these are definined in addition to %j
313    CHECK_FORMATS(MAX, intmax_t, INTMAX_MAX);
314    CHECK_FORMATS(MAX, uintmax_t, UINTMAX_MAX);
315
316    // ptrdiff_t is simply %t.
317    // size_t is simply %z.
318    // wchar_t is simply %sl.
319
320    // No particular format specifier or macro is defined for sig_atomic_t.
321
322    END_TEST;
323}
324
325BEGIN_TEST_CASE(format_specifiers)
326RUN_TEST(check_format_specifiers)
327END_TEST_CASE(format_specifiers)
328
329int main(int argc, char** argv) {
330    return unittest_run_all_tests(argc, argv) ? 0 : -1;
331}
332