blob: cf3b22b5b09922ae7b499a56a2d25a32a9772868 [file] [log] [blame]
Wyatt Hepler80c6ee52020-01-03 09:54:58 -08001// Copyright 2020 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15#include "pw_tokenizer/internal/argument_types.h"
16
17#include <cstddef>
18
19#include "gtest/gtest.h"
20#include "pw_preprocessor/concat.h"
21#include "pw_tokenizer_private/argument_types_test.h"
22
23namespace pw::tokenizer {
24namespace {
25
26struct DummyType {};
27
28// Check each relevant type mapping.
29#define CHECK_TYPE(c_type, enum_type) \
30 static_assert(_PW_VARARGS_TYPE((c_type)0) == enum_type, \
31 #c_type " should map to " #enum_type)
32
33// integral
34// clang-format off
35CHECK_TYPE(bool, PW_TOKENIZER_ARG_TYPE_INT);
36CHECK_TYPE(char, PW_TOKENIZER_ARG_TYPE_INT);
37CHECK_TYPE(signed char, PW_TOKENIZER_ARG_TYPE_INT);
38CHECK_TYPE(unsigned char, PW_TOKENIZER_ARG_TYPE_INT);
39CHECK_TYPE(short, PW_TOKENIZER_ARG_TYPE_INT);
40CHECK_TYPE(unsigned short, PW_TOKENIZER_ARG_TYPE_INT);
41CHECK_TYPE(int, PW_TOKENIZER_ARG_TYPE_INT);
42CHECK_TYPE(unsigned int, PW_TOKENIZER_ARG_TYPE_INT);
43CHECK_TYPE(long, _PW_TOKENIZER_SELECT_INT_TYPE(long));
44CHECK_TYPE(unsigned long, _PW_TOKENIZER_SELECT_INT_TYPE(unsigned long));
45CHECK_TYPE(long long, PW_TOKENIZER_ARG_TYPE_INT64);
46CHECK_TYPE(unsigned long long, PW_TOKENIZER_ARG_TYPE_INT64);
47
48// floating point
49CHECK_TYPE(float, PW_TOKENIZER_ARG_TYPE_DOUBLE);
50CHECK_TYPE(double, PW_TOKENIZER_ARG_TYPE_DOUBLE);
51CHECK_TYPE(long double, PW_TOKENIZER_ARG_TYPE_DOUBLE);
52
53// strings
54CHECK_TYPE(char*, PW_TOKENIZER_ARG_TYPE_STRING);
55CHECK_TYPE(const char*, PW_TOKENIZER_ARG_TYPE_STRING);
56
57// pointers (which should map to the appropriate sized integer)
58CHECK_TYPE(void*, _PW_TOKENIZER_SELECT_INT_TYPE(void*));
59CHECK_TYPE(const void*, _PW_TOKENIZER_SELECT_INT_TYPE(void*));
60CHECK_TYPE(signed char*, _PW_TOKENIZER_SELECT_INT_TYPE(void*));
61CHECK_TYPE(unsigned char*, _PW_TOKENIZER_SELECT_INT_TYPE(void*));
62CHECK_TYPE(int*, _PW_TOKENIZER_SELECT_INT_TYPE(void*));
63CHECK_TYPE(long long*, _PW_TOKENIZER_SELECT_INT_TYPE(void*));
64CHECK_TYPE(DummyType*, _PW_TOKENIZER_SELECT_INT_TYPE(void*));
65
66// nullptr
67CHECK_TYPE(std::nullptr_t, _PW_TOKENIZER_SELECT_INT_TYPE(void*));
68static_assert(_PW_VARARGS_TYPE(nullptr) ==
69 _PW_TOKENIZER_SELECT_INT_TYPE(void*));
70
71// clang-format on
72
73// Define a macro that generates expected values for tests. This works with
74// either 4-bit or 6-bit argument counts (for encoding types in a uint32_t or
75// uint64_t).
76#define PACKED_TYPES(...) \
77 ((PW_CONCAT(0b, __VA_ARGS__, u) << PW_TOKENIZER_TYPE_COUNT_SIZE_BITS) | \
Wyatt Hepler5191f582020-08-24 09:26:23 -070078 PW_MACRO_ARG_COUNT(__VA_ARGS__))
Wyatt Hepler80c6ee52020-01-03 09:54:58 -080079
80// Test this test macro for both uint32_t and uint64_t.
81#if PW_TOKENIZER_CFG_ARG_TYPES_SIZE_BYTES == 4
82
83static_assert(PACKED_TYPES(00) == 0b00'0001u);
84static_assert(PACKED_TYPES(11) == 0b11'0001u);
85static_assert(PACKED_TYPES(01, 10) == 0b0110'0010u);
86static_assert(PACKED_TYPES(11, 01, 10) == 0b110110'0011u);
87static_assert(PACKED_TYPES(11, 10, 01, 00) == 0b11'10'01'00'0100u);
88
89#elif PW_TOKENIZER_CFG_ARG_TYPES_SIZE_BYTES == 8
90
91static_assert(PACKED_TYPES(00) == 0b00'000001u);
92static_assert(PACKED_TYPES(11) == 0b11'000001u);
93static_assert(PACKED_TYPES(01, 10) == 0b0110'000010u);
94static_assert(PACKED_TYPES(11, 01, 10) == 0b110110'000011u);
95static_assert(PACKED_TYPES(11, 10, 01, 00) == 0b11'10'01'00'000100u);
96
97#else
98
99#error "Unsupported value for PW_TOKENIZER_CFG_ARG_TYPES_SIZE_BYTES"
100
101#endif // PW_TOKENIZER_CFG_ARG_TYPES_SIZE_BYTES
102
103#define SOME_OTHER_MACRO(...) PW_TOKENIZER_ARG_TYPES(__VA_ARGS__)
104
105TEST(ArgumentTypes, Empty) {
106 static_assert(PW_TOKENIZER_ARG_TYPES() == 0u);
107 static_assert(PW_TOKENIZER_ARG_TYPES(/* nothing here */) == 0u);
108 static_assert(SOME_OTHER_MACRO() == 0u);
109 static_assert(SOME_OTHER_MACRO(/* nothing here */) == 0u);
110}
111
112TEST(ArgumentTypes, Int32) {
113 static_assert(PW_TOKENIZER_ARG_TYPES(0) == PACKED_TYPES(00));
114 static_assert(PW_TOKENIZER_ARG_TYPES('a') == PACKED_TYPES(00));
115 static_assert(PW_TOKENIZER_ARG_TYPES(u'X') == PACKED_TYPES(00));
116 static_assert(PW_TOKENIZER_ARG_TYPES(static_cast<uint16_t>(1)) ==
117 PACKED_TYPES(00));
118}
119
120TEST(ArgumentTypes, Int64) {
121 static_assert(PW_TOKENIZER_ARG_TYPES(-123ll) == PACKED_TYPES(01));
122 static_assert(PW_TOKENIZER_ARG_TYPES(123ull) == PACKED_TYPES(01));
123 static_assert(PW_TOKENIZER_ARG_TYPES(static_cast<uint64_t>(1)) ==
124 PACKED_TYPES(01));
125}
126
127TEST(ArgumentTypes, Double) {
128 static_assert(PW_TOKENIZER_ARG_TYPES(1.0) == PACKED_TYPES(10));
129 static_assert(PW_TOKENIZER_ARG_TYPES(5.0f) == PACKED_TYPES(10));
130 float number = 9;
131 static_assert(PW_TOKENIZER_ARG_TYPES(number) == PACKED_TYPES(10));
132}
133
134TEST(ArgumentTypes, String) {
135 static_assert(PW_TOKENIZER_ARG_TYPES("string") == PACKED_TYPES(11));
136 const char buffer[2] = {'a', 'b'};
137 static_assert(PW_TOKENIZER_ARG_TYPES(buffer) == PACKED_TYPES(11));
138 char mutable_buffer[8] = {};
139 static_assert(PW_TOKENIZER_ARG_TYPES(mutable_buffer) == PACKED_TYPES(11));
140 char character = 'a';
141 static_assert(PW_TOKENIZER_ARG_TYPES(&character) == PACKED_TYPES(11));
142}
143
144TEST(ArgumentTypes, Pointer) {
145 static const bool some_data[8] = {};
146
147 // For 32-bit systems, non-string pointers show up as int32.
148 static_assert(sizeof(void*) != sizeof(int32_t) ||
149 PACKED_TYPES(00) == PW_TOKENIZER_ARG_TYPES(nullptr));
150 static_assert(sizeof(void*) != sizeof(int32_t) ||
151 PACKED_TYPES(00) ==
152 PW_TOKENIZER_ARG_TYPES(static_cast<void*>(nullptr)));
153 static_assert(sizeof(void*) != sizeof(int32_t) ||
154 PACKED_TYPES(00) == PW_TOKENIZER_ARG_TYPES(some_data));
155
156 // For 64-bit systems, non-string pointers show up as int64.
157 static_assert(sizeof(void*) != sizeof(int64_t) ||
158 PACKED_TYPES(01) == PW_TOKENIZER_ARG_TYPES(nullptr));
159 static_assert(sizeof(void*) != sizeof(int64_t) ||
160 PACKED_TYPES(01) ==
161 PW_TOKENIZER_ARG_TYPES(static_cast<void*>(nullptr)));
162 static_assert(sizeof(void*) != sizeof(int64_t) ||
163 PACKED_TYPES(01) == PW_TOKENIZER_ARG_TYPES(some_data));
164}
165
166TEST(ArgumentTypes, TwoArgs) {
167 static_assert(PW_TOKENIZER_ARG_TYPES(-100, 1000) == PACKED_TYPES(00, 00));
168 static_assert(PW_TOKENIZER_ARG_TYPES(-100, 10ll) == PACKED_TYPES(01, 00));
169 static_assert(PW_TOKENIZER_ARG_TYPES(-100, 1.0f) == PACKED_TYPES(10, 00));
170 static_assert(PW_TOKENIZER_ARG_TYPES(-100, "hi") == PACKED_TYPES(11, 00));
171
172 static_assert(PW_TOKENIZER_ARG_TYPES(1ull, 1000) == PACKED_TYPES(00, 01));
173 static_assert(PW_TOKENIZER_ARG_TYPES(1ull, 10ll) == PACKED_TYPES(01, 01));
174 static_assert(PW_TOKENIZER_ARG_TYPES(1ull, 1.0f) == PACKED_TYPES(10, 01));
175 static_assert(PW_TOKENIZER_ARG_TYPES(1ull, "hi") == PACKED_TYPES(11, 01));
176
177 static_assert(PW_TOKENIZER_ARG_TYPES(9.0f, 1000) == PACKED_TYPES(00, 10));
178 static_assert(PW_TOKENIZER_ARG_TYPES(9.0f, 10ll) == PACKED_TYPES(01, 10));
179 static_assert(PW_TOKENIZER_ARG_TYPES(9.0f, 1.0f) == PACKED_TYPES(10, 10));
180 static_assert(PW_TOKENIZER_ARG_TYPES(9.0f, "hi") == PACKED_TYPES(11, 10));
181
182 static_assert(PW_TOKENIZER_ARG_TYPES("!!", 1000) == PACKED_TYPES(00, 11));
183 static_assert(PW_TOKENIZER_ARG_TYPES("!!", 10ll) == PACKED_TYPES(01, 11));
184 static_assert(PW_TOKENIZER_ARG_TYPES("!!", 1.0f) == PACKED_TYPES(10, 11));
185 static_assert(PW_TOKENIZER_ARG_TYPES("!!", "hi") == PACKED_TYPES(11, 11));
186}
187
188TEST(ArgumentTypes, MultipleArgs) {
189 // clang-format off
Wyatt Heplerbcf07352021-04-05 14:44:30 -0700190 static_assert(PW_TOKENIZER_ARG_TYPES(1) == 1);
191 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2) == 2);
192 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3) == 3);
193 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4) == 4);
194 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5) == 5);
195 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6) == 6);
196 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7) == 7);
197 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8) == 8);
198 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9) == 9);
199 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) == 10);
200 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) == 11);
201 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) == 12);
202 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13) == 13);
203 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14) == 14);
Wyatt Hepler80c6ee52020-01-03 09:54:58 -0800204
205#if PW_TOKENIZER_CFG_ARG_TYPES_SIZE_BYTES >= 8
Wyatt Heplerbcf07352021-04-05 14:44:30 -0700206 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14) == 14);
207 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) == 15);
208 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) == 16);
209 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17) == 17);
210 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18) == 18);
211 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19) == 19);
212 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20) == 20);
213 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21) == 21);
214 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22) == 22);
215 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23) == 23);
216 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24) == 24);
217 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25) == 25);
218 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26) == 26);
219 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27) == 27);
220 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28) == 28);
221 static_assert(PW_TOKENIZER_ARG_TYPES(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29) == 29);
Wyatt Hepler80c6ee52020-01-03 09:54:58 -0800222#endif // PW_TOKENIZER_CFG_ARG_TYPES_SIZE_BYTES
223 // clang-format on
224}
225
226// The ArgumentTypesFromC test suite tests the arguments types macro in C. The
227// pw_Test* functions are defined in argument_types_c_test.c
228TEST(ArgumentTypesFromC, NoArgs) {
229 EXPECT_EQ(0b0000u, pw_TestTokenizerNoArgs());
230}
231
232TEST(ArgumentTypesFromC, OneArg_Int32) {
233 EXPECT_EQ(PACKED_TYPES(00), pw_TestTokenizerChar());
234 EXPECT_EQ(PACKED_TYPES(00), pw_TestTokenizerUint8());
235 EXPECT_EQ(PACKED_TYPES(00), pw_TestTokenizerUint16());
236 EXPECT_EQ(PACKED_TYPES(00), pw_TestTokenizerInt32());
237}
238
239TEST(ArgumentTypesFromC, OneArg_Int64) {
240 EXPECT_EQ(PACKED_TYPES(01), pw_TestTokenizerInt64());
241 EXPECT_EQ(PACKED_TYPES(01), pw_TestTokenizerUint64());
242}
243
244TEST(ArgumentTypesFromC, OneArg_Float) {
245 EXPECT_EQ(PACKED_TYPES(10), pw_TestTokenizerFloat());
246 EXPECT_EQ(PACKED_TYPES(10), pw_TestTokenizerDouble());
247}
248
249TEST(ArgumentTypesFromC, OneArg_String) {
250 EXPECT_EQ(PACKED_TYPES(11), pw_TestTokenizerString());
251 EXPECT_EQ(PACKED_TYPES(11), pw_TestTokenizerMutableString());
252}
253
254TEST(ArgumentTypesFromC, MultipleArgs) {
255 EXPECT_EQ(PACKED_TYPES(10, 00), pw_TestTokenizerIntFloat());
256 EXPECT_EQ(PACKED_TYPES(00, 01), pw_TestTokenizerUint64Char());
257 EXPECT_EQ(PACKED_TYPES(11, 11), pw_TestTokenizerStringString());
258 EXPECT_EQ(PACKED_TYPES(00, 00), pw_TestTokenizerUint16Int());
259 EXPECT_EQ(PACKED_TYPES(11, 10), pw_TestTokenizerFloatString());
260}
261
262TEST(ArgumentTypesFromC, Pointers) {
263 if constexpr (sizeof(void*) == sizeof(int32_t)) {
264 EXPECT_EQ(PACKED_TYPES(00), pw_TestTokenizerNull());
265 EXPECT_EQ(PACKED_TYPES(00), pw_TestTokenizerPointer());
266 EXPECT_EQ(PACKED_TYPES(00, 00), pw_TestTokenizerPointerPointer());
267 } else { // 64-bit system
268 EXPECT_EQ(PACKED_TYPES(01), pw_TestTokenizerNull());
269 EXPECT_EQ(PACKED_TYPES(01), pw_TestTokenizerPointer());
270 EXPECT_EQ(PACKED_TYPES(01, 01), pw_TestTokenizerPointerPointer());
271 }
272}
273
274} // namespace
275} // namespace pw::tokenizer