blob: 01c6bc56ffb4a00fcf98684dafb07cbfa5fa267a [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/tokenize.h"
16
17#include <cinttypes>
18#include <cstdint>
19#include <cstring>
20#include <iterator>
21
22#include "gtest/gtest.h"
Wyatt Heplereb020a12020-10-28 14:01:51 -070023#include "pw_tokenizer/hash.h"
Wyatt Hepler80c6ee52020-01-03 09:54:58 -080024#include "pw_tokenizer_private/tokenize_test.h"
25#include "pw_varint/varint.h"
26
27namespace pw::tokenizer {
28namespace {
29
Wyatt Hepler80c6ee52020-01-03 09:54:58 -080030// Constructs an array with the hashed string followed by the provided bytes.
31template <uint8_t... kData, size_t kSize>
32constexpr auto ExpectedData(const char (&format)[kSize]) {
Wyatt Heplereb020a12020-10-28 14:01:51 -070033 const uint32_t value = Hash(format);
Wyatt Hepler80c6ee52020-01-03 09:54:58 -080034 return std::array<uint8_t, sizeof(uint32_t) + sizeof...(kData)>{
35 static_cast<uint8_t>(value & 0xff),
36 static_cast<uint8_t>(value >> 8 & 0xff),
37 static_cast<uint8_t>(value >> 16 & 0xff),
38 static_cast<uint8_t>(value >> 24 & 0xff),
39 kData...};
40}
41
Wyatt Hepler7e587232020-08-28 07:51:29 -070042TEST(TokenizeString, EmptyString_IsZero) {
Wyatt Hepler7a5e4d62020-08-31 08:39:16 -070043 constexpr pw_tokenizer_Token token = PW_TOKENIZE_STRING("");
Wyatt Hepler80c6ee52020-01-03 09:54:58 -080044 EXPECT_EQ(0u, token);
45}
46
Wyatt Hepler7e587232020-08-28 07:51:29 -070047TEST(TokenizeString, String_MatchesHash) {
Wyatt Hepler80c6ee52020-01-03 09:54:58 -080048 constexpr uint32_t token = PW_TOKENIZE_STRING("[:-)");
Wyatt Heplereb020a12020-10-28 14:01:51 -070049 EXPECT_EQ(Hash("[:-)"), token);
Wyatt Hepler80c6ee52020-01-03 09:54:58 -080050}
51
52constexpr uint32_t kGlobalToken = PW_TOKENIZE_STRING(">:-[]");
53
Wyatt Hepler7e587232020-08-28 07:51:29 -070054TEST(TokenizeString, GlobalVariable_MatchesHash) {
Wyatt Heplereb020a12020-10-28 14:01:51 -070055 EXPECT_EQ(Hash(">:-[]"), kGlobalToken);
Wyatt Hepler80c6ee52020-01-03 09:54:58 -080056}
57
Wyatt Hepler7e587232020-08-28 07:51:29 -070058struct TokenizedWithinClass {
59 static constexpr uint32_t kThisToken = PW_TOKENIZE_STRING("???");
60};
61
Wyatt Heplereb020a12020-10-28 14:01:51 -070062static_assert(Hash("???") == TokenizedWithinClass::kThisToken);
Wyatt Hepler7e587232020-08-28 07:51:29 -070063
64TEST(TokenizeString, ClassMember_MatchesHash) {
Wyatt Heplereb020a12020-10-28 14:01:51 -070065 EXPECT_EQ(Hash("???"), TokenizedWithinClass().kThisToken);
Wyatt Hepler7e587232020-08-28 07:51:29 -070066}
67
68// Use a function with a shorter name to test tokenizing __func__ and
69// __PRETTY_FUNCTION__.
70//
71// WARNING: This function might cause errors for compilers other than GCC and
72// clang. It relies on two GCC/clang extensions:
73//
74// 1 - The __PRETTY_FUNCTION__ C++ function name variable.
75// 2 - __func__ as a static constexpr array instead of static const. See
76// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66639 for background.
77//
78void TestName() {
79 constexpr uint32_t function_hash = PW_TOKENIZE_STRING(__func__);
Wyatt Heplereb020a12020-10-28 14:01:51 -070080 EXPECT_EQ(pw::tokenizer::Hash(__func__), function_hash);
Wyatt Hepler7e587232020-08-28 07:51:29 -070081
82 // Check the non-standard __PRETTY_FUNCTION__ name.
83 constexpr uint32_t pretty_function = PW_TOKENIZE_STRING(__PRETTY_FUNCTION__);
Wyatt Heplereb020a12020-10-28 14:01:51 -070084 EXPECT_EQ(pw::tokenizer::Hash(__PRETTY_FUNCTION__), pretty_function);
Wyatt Hepler7e587232020-08-28 07:51:29 -070085}
86
87TEST(TokenizeString, FunctionName) { TestName(); }
88
89TEST(TokenizeString, Array) {
90 constexpr char array[] = "won-won-won-wonderful";
91
92 const uint32_t array_hash = PW_TOKENIZE_STRING(array);
Wyatt Heplereb020a12020-10-28 14:01:51 -070093 EXPECT_EQ(Hash(array), array_hash);
94}
95
96TEST(TokenizeString, NullInString) {
97 // Use PW_TOKENIZER_STRING_TOKEN to avoid emitting strings with NUL into the
98 // ELF file. The CSV database format does not support NUL.
99 constexpr char nulls[32] = {};
100 static_assert(Hash(nulls) == PW_TOKENIZER_STRING_TOKEN(nulls));
101 static_assert(PW_TOKENIZER_STRING_TOKEN(nulls) != 0u);
102
103 static_assert(PW_TOKENIZER_STRING_TOKEN("\0") == Hash("\0"));
104 static_assert(PW_TOKENIZER_STRING_TOKEN("\0") != Hash(""));
105
106 static_assert(PW_TOKENIZER_STRING_TOKEN("abc\0def") == Hash("abc\0def"));
107
108 static_assert(Hash("abc\0def") != Hash("abc\0def\0"));
Wyatt Hepler7e587232020-08-28 07:51:29 -0700109}
110
Keir Mierle42f41f72020-08-05 00:15:56 -0700111// Verify that we can tokenize multiple strings from one source line.
Wyatt Heplereb020a12020-10-28 14:01:51 -0700112#define THREE_FOR_ONE(first, second, third) \
113 [[maybe_unused]] constexpr uint32_t token_1 = \
114 PW_TOKENIZE_STRING_DOMAIN("TEST_DOMAIN", first); \
115 [[maybe_unused]] constexpr uint32_t token_2 = \
116 PW_TOKENIZE_STRING_DOMAIN("TEST_DOMAIN", second); \
117 [[maybe_unused]] constexpr uint32_t token_3 = \
118 PW_TOKENIZE_STRING_DOMAIN("TEST_DOMAIN", third);
Keir Mierle42f41f72020-08-05 00:15:56 -0700119
Wyatt Hepler7e587232020-08-28 07:51:29 -0700120TEST(TokenizeString, MultipleTokenizationsInOneMacroExpansion) {
Keir Mierle42f41f72020-08-05 00:15:56 -0700121 // This verifies that we can safely tokenize multiple times in a single macro
122 // expansion. This can be useful when for example a name and description are
123 // both tokenized after being passed into a macro.
124 //
125 // This test only verifies that this compiles correctly; it does not test
126 // that the tokenizations make it to the final token database.
127 THREE_FOR_ONE("hello", "yes", "something");
128}
129
Wyatt Hepler80c6ee52020-01-03 09:54:58 -0800130class TokenizeToBuffer : public ::testing::Test {
131 public:
132 TokenizeToBuffer() : buffer_{} {}
133
134 protected:
135 uint8_t buffer_[64];
136};
137
138TEST_F(TokenizeToBuffer, Integer64) {
139 size_t message_size = 14;
140 PW_TOKENIZE_TO_BUFFER(
141 buffer_,
142 &message_size,
143 "%" PRIu64,
144 static_cast<uint64_t>(0x55555555'55555555ull)); // 0xAAAAAAAA'AAAAAAAA
145
146 // Pattern becomes 10101010'11010101'10101010 ...
147 constexpr std::array<uint8_t, 14> expected =
148 ExpectedData<0xAA, 0xD5, 0xAA, 0xD5, 0xAA, 0xD5, 0xAA, 0xD5, 0xAA, 0x01>(
149 "%" PRIu64);
150 ASSERT_EQ(expected.size(), message_size);
151 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
152}
153
154TEST_F(TokenizeToBuffer, Integer64Overflow) {
155 size_t message_size;
156
157 for (size_t size = 4; size < 20; ++size) {
158 message_size = size;
159
160 PW_TOKENIZE_TO_BUFFER(
161 buffer_,
162 &message_size,
163 "%" PRIx64,
164 static_cast<uint64_t>(std::numeric_limits<int64_t>::min()));
165
166 if (size < 14) {
167 constexpr std::array<uint8_t, 4> empty = ExpectedData("%" PRIx64);
168 ASSERT_EQ(sizeof(uint32_t), message_size);
169 EXPECT_EQ(std::memcmp(empty.data(), &buffer_, empty.size()), 0);
170
171 // Make sure nothing was written past the end of the buffer.
172 EXPECT_TRUE(std::all_of(&buffer_[size], std::end(buffer_), [](uint8_t v) {
173 return v == '\0';
174 }));
175 } else {
176 constexpr std::array<uint8_t, 14> expected =
177 ExpectedData<0xff,
178 0xff,
179 0xff,
180 0xff,
181 0xff,
182 0xff,
183 0xff,
184 0xff,
185 0xff,
186 0x01>("%" PRIx64);
187 ASSERT_EQ(expected.size(), message_size);
188 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
189 }
190 }
191}
192
193TEST_F(TokenizeToBuffer, IntegerNegative) {
194 size_t message_size = 9;
195 PW_TOKENIZE_TO_BUFFER(
196 buffer_, &message_size, "%" PRId32, std::numeric_limits<int32_t>::min());
197
198 // 0x8000'0000 -zig-zag-> 0xff'ff'ff'ff'0f
199 constexpr std::array<uint8_t, 9> expected =
200 ExpectedData<0xff, 0xff, 0xff, 0xff, 0x0f>("%" PRId32);
201 ASSERT_EQ(expected.size(), message_size);
202 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
203}
204
205TEST_F(TokenizeToBuffer, IntegerMin) {
206 size_t message_size = 9;
207 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "%d", -1);
208
209 constexpr std::array<uint8_t, 5> expected = ExpectedData<0x01>("%d");
210 ASSERT_EQ(expected.size(), message_size);
211 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
212}
213
214TEST_F(TokenizeToBuffer, IntegerDoesntFit) {
215 size_t message_size = 8;
216 PW_TOKENIZE_TO_BUFFER(
217 buffer_, &message_size, "%" PRId32, std::numeric_limits<int32_t>::min());
218
219 constexpr std::array<uint8_t, 4> expected = ExpectedData<>("%" PRId32);
220 ASSERT_EQ(expected.size(), message_size);
221 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
222}
223
224TEST_F(TokenizeToBuffer, String) {
225 size_t message_size = sizeof(buffer_);
226
227 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
228 constexpr std::array<uint8_t, 10> expected =
229 ExpectedData<5, '5', '4', '3', '2', '!'>("The answer is: %s");
230
231 ASSERT_EQ(expected.size(), message_size);
232 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
233}
234
235TEST_F(TokenizeToBuffer, String_BufferTooSmall_TruncatesAndSetsTopStatusBit) {
236 size_t message_size = 8;
237 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
238
239 constexpr std::array<uint8_t, 8> truncated_1 =
240 ExpectedData<0x83, '5', '4', '3'>("The answer is: %s");
241
242 ASSERT_EQ(truncated_1.size(), message_size);
243 EXPECT_EQ(std::memcmp(truncated_1.data(), buffer_, truncated_1.size()), 0);
244}
245
246TEST_F(TokenizeToBuffer, String_TwoBytesLeft_TruncatesToOneCharacter) {
247 size_t message_size = 6;
248 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
249
250 constexpr std::array<uint8_t, 6> truncated_2 =
251 ExpectedData<0x81, '5'>("The answer is: %s");
252
253 ASSERT_EQ(truncated_2.size(), message_size);
254 EXPECT_EQ(std::memcmp(truncated_2.data(), buffer_, truncated_2.size()), 0);
255}
256
257TEST_F(TokenizeToBuffer, String_OneByteLeft_OnlyWritesTruncatedStatusByte) {
258 size_t message_size = 5;
259 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
260
261 std::array<uint8_t, 5> result = ExpectedData<0x80>("The answer is: %s");
262 ASSERT_EQ(result.size(), message_size);
263 EXPECT_EQ(std::memcmp(result.data(), buffer_, result.size()), 0);
264}
265
266TEST_F(TokenizeToBuffer, EmptyString_OneByteLeft_EncodesCorrectly) {
267 size_t message_size = 5;
268 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "");
269
270 std::array<uint8_t, 5> result = ExpectedData<0>("The answer is: %s");
271 ASSERT_EQ(result.size(), message_size);
272 EXPECT_EQ(std::memcmp(result.data(), buffer_, result.size()), 0);
273}
274
275TEST_F(TokenizeToBuffer, String_ZeroBytesLeft_WritesNothing) {
276 size_t message_size = 4;
277 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
278
279 constexpr std::array<uint8_t, 4> empty = ExpectedData<>("The answer is: %s");
280 ASSERT_EQ(empty.size(), message_size);
281 EXPECT_EQ(std::memcmp(empty.data(), buffer_, empty.size()), 0);
282}
283
Wyatt Hepler7e587232020-08-28 07:51:29 -0700284TEST_F(TokenizeToBuffer, Array) {
285 static constexpr char array[] = "1234";
286 size_t message_size = 4;
287 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, array);
288
289 constexpr std::array<uint8_t, 4> result = ExpectedData<>("1234");
290 ASSERT_EQ(result.size(), message_size);
291 EXPECT_EQ(std::memcmp(result.data(), buffer_, result.size()), 0);
292}
293
Wyatt Hepler80c6ee52020-01-03 09:54:58 -0800294TEST_F(TokenizeToBuffer, NullptrString_EncodesNull) {
295 char* string = nullptr;
296 size_t message_size = 9;
297 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", string);
298
299 std::array<uint8_t, 9> result =
300 ExpectedData<4, 'N', 'U', 'L', 'L'>("The answer is: %s");
301 ASSERT_EQ(result.size(), message_size);
302 EXPECT_EQ(std::memcmp(result.data(), buffer_, result.size()), 0);
303}
304
305TEST_F(TokenizeToBuffer, NullptrString_BufferTooSmall_EncodesTruncatedNull) {
306 char* string = nullptr;
307 size_t message_size = 6;
308 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", string);
309
310 std::array<uint8_t, 6> result = ExpectedData<0x81, 'N'>("The answer is: %s");
311 ASSERT_EQ(result.size(), message_size);
312 EXPECT_EQ(std::memcmp(result.data(), buffer_, result.size()), 0);
313}
314
Wyatt Heplerd58eef92020-05-08 10:39:56 -0700315TEST_F(TokenizeToBuffer, Domain_String) {
316 size_t message_size = sizeof(buffer_);
317
318 PW_TOKENIZE_TO_BUFFER_DOMAIN(
319 "TEST_DOMAIN", buffer_, &message_size, "The answer was: %s", "5432!");
320 constexpr std::array<uint8_t, 10> expected =
321 ExpectedData<5, '5', '4', '3', '2', '!'>("The answer was: %s");
322
323 ASSERT_EQ(expected.size(), message_size);
324 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
325}
326
Wyatt Hepler80c6ee52020-01-03 09:54:58 -0800327TEST_F(TokenizeToBuffer, TruncateArgs) {
328 // Args that can't fit are dropped completely
329 size_t message_size = 6;
330 PW_TOKENIZE_TO_BUFFER(buffer_,
331 &message_size,
332 "%u %d",
333 static_cast<uint8_t>(0b0010'1010u),
334 0xffffff);
335
336 constexpr std::array<uint8_t, 5> expected =
337 ExpectedData<0b0101'0100u>("%u %d");
338 ASSERT_EQ(expected.size(), message_size);
339 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
340}
341
342TEST_F(TokenizeToBuffer, NoRoomForToken) {
343 // Nothing is written if there isn't room for the token.
344 std::memset(buffer_, '$', sizeof(buffer_));
345 auto is_untouched = [](uint8_t v) { return v == '$'; };
346
347 size_t message_size = 3;
348 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer: \"%s\"", "5432!");
349 EXPECT_EQ(0u, message_size);
350 EXPECT_TRUE(std::all_of(buffer_, std::end(buffer_), is_untouched));
351
352 message_size = 2;
353 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "Jello, world!");
354 EXPECT_EQ(0u, message_size);
355 EXPECT_TRUE(std::all_of(buffer_, std::end(buffer_), is_untouched));
356
357 message_size = 1;
358 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "Jello!");
359 EXPECT_EQ(0u, message_size);
360 EXPECT_TRUE(std::all_of(buffer_, std::end(buffer_), is_untouched));
361
362 message_size = 0;
363 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "Jello?");
364 EXPECT_EQ(0u, message_size);
365 EXPECT_TRUE(std::all_of(buffer_, std::end(buffer_), is_untouched));
366}
367
368TEST_F(TokenizeToBuffer, C_StringShortFloat) {
369 size_t size = sizeof(buffer_);
Wyatt Hepler7a5e4d62020-08-31 08:39:16 -0700370 pw_tokenizer_ToBufferTest_StringShortFloat(buffer_, &size);
Wyatt Hepler80c6ee52020-01-03 09:54:58 -0800371 constexpr std::array<uint8_t, 11> expected = // clang-format off
372 ExpectedData<1, '1', // string '1'
373 3, // -2 (zig-zag encoded)
374 0x00, 0x00, 0x40, 0x40 // 3.0 in floating point
375 >(TEST_FORMAT_STRING_SHORT_FLOAT);
376 ASSERT_EQ(expected.size(), size); // clang-format on
377 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
378}
379
380TEST_F(TokenizeToBuffer, C_SequentialZigZag) {
381 size_t size = sizeof(buffer_);
Wyatt Hepler7a5e4d62020-08-31 08:39:16 -0700382 pw_tokenizer_ToBufferTest_SequentialZigZag(buffer_, &size);
Wyatt Hepler80c6ee52020-01-03 09:54:58 -0800383 constexpr std::array<uint8_t, 18> expected =
384 ExpectedData<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13>(
385 TEST_FORMAT_SEQUENTIAL_ZIG_ZAG);
386
387 ASSERT_EQ(expected.size(), size);
388 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
389}
390
391TEST_F(TokenizeToBuffer, C_Overflow) {
392 std::memset(buffer_, '$', sizeof(buffer_));
393
394 {
395 size_t size = 7;
Wyatt Hepler7a5e4d62020-08-31 08:39:16 -0700396 pw_tokenizer_ToBufferTest_Requires8(buffer_, &size);
Wyatt Hepler80c6ee52020-01-03 09:54:58 -0800397 constexpr std::array<uint8_t, 7> expected =
398 ExpectedData<2, 'h', 'i'>(TEST_FORMAT_REQUIRES_8);
399 ASSERT_EQ(expected.size(), size);
400 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
401 EXPECT_EQ(buffer_[7], '$');
402 }
403
404 {
405 size_t size = 8;
Wyatt Hepler7a5e4d62020-08-31 08:39:16 -0700406 pw_tokenizer_ToBufferTest_Requires8(buffer_, &size);
Wyatt Hepler80c6ee52020-01-03 09:54:58 -0800407 constexpr std::array<uint8_t, 8> expected =
408 ExpectedData<2, 'h', 'i', 13>(TEST_FORMAT_REQUIRES_8);
409 ASSERT_EQ(expected.size(), size);
410 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
411 EXPECT_EQ(buffer_[8], '$');
412 }
413}
414
415// Test fixture for callback and global handler. Both of these need a global
416// message buffer. To keep the message buffers separate, template this on the
417// derived class type.
418template <typename Impl>
419class GlobalMessage : public ::testing::Test {
420 public:
421 static void SetMessage(const uint8_t* message, size_t size) {
422 ASSERT_LE(size, sizeof(message_));
423 std::memcpy(message_, message, size);
424 message_size_bytes_ = size;
425 }
426
427 protected:
428 GlobalMessage() {
429 std::memset(message_, 0, sizeof(message_));
430 message_size_bytes_ = 0;
431 }
432
433 static uint8_t message_[256];
434 static size_t message_size_bytes_;
435};
436
437template <typename Impl>
438uint8_t GlobalMessage<Impl>::message_[256] = {};
439template <typename Impl>
440size_t GlobalMessage<Impl>::message_size_bytes_ = 0;
441
442class TokenizeToCallback : public GlobalMessage<TokenizeToCallback> {};
443
444TEST_F(TokenizeToCallback, Variety) {
445 PW_TOKENIZE_TO_CALLBACK(
446 SetMessage, "%s there are %x (%.2f) of them%c", "Now", 2u, 2.0f, '.');
447 const auto expected = // clang-format off
448 ExpectedData<3, 'N', 'o', 'w', // string "Now"
449 0x04, // unsigned 2 (zig-zag encoded)
450 0x00, 0x00, 0x00, 0x40, // float 2.0
451 0x5C // char '.' (0x2E, zig-zag encoded)
452 >("%s there are %x (%.2f) of them%c");
453 // clang-format on
454 ASSERT_EQ(expected.size(), message_size_bytes_);
455 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
456}
457
458TEST_F(TokenizeToCallback, Strings) {
459 PW_TOKENIZE_TO_CALLBACK(SetMessage, "The answer is: %s", "5432!");
460 constexpr std::array<uint8_t, 10> expected =
461 ExpectedData<5, '5', '4', '3', '2', '!'>("The answer is: %s");
462 ASSERT_EQ(expected.size(), message_size_bytes_);
463 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
464}
465
Wyatt Heplerd58eef92020-05-08 10:39:56 -0700466TEST_F(TokenizeToCallback, Domain_Strings) {
467 PW_TOKENIZE_TO_CALLBACK_DOMAIN(
468 "TEST_DOMAIN", SetMessage, "The answer is: %s", "5432!");
469 constexpr std::array<uint8_t, 10> expected =
470 ExpectedData<5, '5', '4', '3', '2', '!'>("The answer is: %s");
471 ASSERT_EQ(expected.size(), message_size_bytes_);
472 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
473}
474
Wyatt Hepler80c6ee52020-01-03 09:54:58 -0800475TEST_F(TokenizeToCallback, C_SequentialZigZag) {
Wyatt Hepler7a5e4d62020-08-31 08:39:16 -0700476 pw_tokenizer_ToCallbackTest_SequentialZigZag(SetMessage);
Wyatt Hepler80c6ee52020-01-03 09:54:58 -0800477
478 constexpr std::array<uint8_t, 18> expected =
479 ExpectedData<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13>(
480 TEST_FORMAT_SEQUENTIAL_ZIG_ZAG);
481 ASSERT_EQ(expected.size(), message_size_bytes_);
482 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
483}
484
Wyatt Heplereb020a12020-10-28 14:01:51 -0700485// Hijack an internal macro to capture the tokenizer domain.
486#undef _PW_TOKENIZER_RECORD_ORIGINAL_STRING
487#define _PW_TOKENIZER_RECORD_ORIGINAL_STRING(token, domain, string) \
488 tokenizer_domain = domain; \
Wyatt Heplerd58eef92020-05-08 10:39:56 -0700489 string_literal = string
490
491TEST_F(TokenizeToBuffer, Domain_Default) {
492 const char* tokenizer_domain = nullptr;
493 const char* string_literal = nullptr;
494
495 size_t message_size = sizeof(buffer_);
496
497 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
498
499 EXPECT_STREQ(tokenizer_domain, PW_TOKENIZER_DEFAULT_DOMAIN);
500 EXPECT_STREQ(string_literal, "The answer is: %s");
501}
502
503TEST_F(TokenizeToBuffer, Domain_Specified) {
504 const char* tokenizer_domain = nullptr;
505 const char* string_literal = nullptr;
506
507 size_t message_size = sizeof(buffer_);
508
509 PW_TOKENIZE_TO_BUFFER_DOMAIN(
510 "._.", buffer_, &message_size, "The answer is: %s", "5432!");
511
512 EXPECT_STREQ(tokenizer_domain, "._.");
513 EXPECT_STREQ(string_literal, "The answer is: %s");
514}
515
516TEST_F(TokenizeToCallback, Domain_Default) {
517 const char* tokenizer_domain = nullptr;
518 const char* string_literal = nullptr;
519
520 PW_TOKENIZE_TO_CALLBACK(SetMessage, "The answer is: %s", "5432!");
521
522 EXPECT_STREQ(tokenizer_domain, PW_TOKENIZER_DEFAULT_DOMAIN);
523 EXPECT_STREQ(string_literal, "The answer is: %s");
524}
525
526TEST_F(TokenizeToCallback, Domain_Specified) {
527 const char* tokenizer_domain = nullptr;
528 const char* string_literal = nullptr;
529
530 PW_TOKENIZE_TO_CALLBACK_DOMAIN(
531 "ThisIsTheDomain", SetMessage, "The answer is: %s", "5432!");
532
533 EXPECT_STREQ(tokenizer_domain, "ThisIsTheDomain");
534 EXPECT_STREQ(string_literal, "The answer is: %s");
535}
536
Wyatt Hepler80c6ee52020-01-03 09:54:58 -0800537} // namespace
538} // namespace pw::tokenizer