blob: 73ffaabbb552d184f6b2da99395a5bbd429368c8 [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"
23#include "pw_tokenizer/pw_tokenizer_65599_fixed_length_hash.h"
24#include "pw_tokenizer_private/tokenize_test.h"
25#include "pw_varint/varint.h"
26
27namespace pw::tokenizer {
28namespace {
29
30// The hash to use for this test. This makes sure the strings are shorter than
31// the configured max length to ensure this test works with any reasonable
32// configuration.
33template <size_t kSize>
34constexpr uint32_t TestHash(const char (&string)[kSize]) {
35 constexpr unsigned kTestHashLength = 48;
36 static_assert(kTestHashLength <= PW_TOKENIZER_CFG_HASH_LENGTH);
37 static_assert(kSize <= kTestHashLength + 1);
38 return PwTokenizer65599FixedLengthHash(std::string_view(string, kSize - 1),
39 kTestHashLength);
40}
41
42// Constructs an array with the hashed string followed by the provided bytes.
43template <uint8_t... kData, size_t kSize>
44constexpr auto ExpectedData(const char (&format)[kSize]) {
45 const uint32_t value = TestHash(format);
46 return std::array<uint8_t, sizeof(uint32_t) + sizeof...(kData)>{
47 static_cast<uint8_t>(value & 0xff),
48 static_cast<uint8_t>(value >> 8 & 0xff),
49 static_cast<uint8_t>(value >> 16 & 0xff),
50 static_cast<uint8_t>(value >> 24 & 0xff),
51 kData...};
52}
53
54TEST(TokenizeStringLiteral, EmptyString_IsZero) {
55 constexpr pw_TokenizerStringToken token = PW_TOKENIZE_STRING("");
56 EXPECT_EQ(0u, token);
57}
58
59TEST(TokenizeStringLiteral, String_MatchesHash) {
60 constexpr uint32_t token = PW_TOKENIZE_STRING("[:-)");
61 EXPECT_EQ(TestHash("[:-)"), token);
62}
63
64constexpr uint32_t kGlobalToken = PW_TOKENIZE_STRING(">:-[]");
65
66TEST(TokenizeStringLiteral, GlobalVariable_MatchesHash) {
67 EXPECT_EQ(TestHash(">:-[]"), kGlobalToken);
68}
69
70class TokenizeToBuffer : public ::testing::Test {
71 public:
72 TokenizeToBuffer() : buffer_{} {}
73
74 protected:
75 uint8_t buffer_[64];
76};
77
78TEST_F(TokenizeToBuffer, Integer64) {
79 size_t message_size = 14;
80 PW_TOKENIZE_TO_BUFFER(
81 buffer_,
82 &message_size,
83 "%" PRIu64,
84 static_cast<uint64_t>(0x55555555'55555555ull)); // 0xAAAAAAAA'AAAAAAAA
85
86 // Pattern becomes 10101010'11010101'10101010 ...
87 constexpr std::array<uint8_t, 14> expected =
88 ExpectedData<0xAA, 0xD5, 0xAA, 0xD5, 0xAA, 0xD5, 0xAA, 0xD5, 0xAA, 0x01>(
89 "%" PRIu64);
90 ASSERT_EQ(expected.size(), message_size);
91 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
92}
93
94TEST_F(TokenizeToBuffer, Integer64Overflow) {
95 size_t message_size;
96
97 for (size_t size = 4; size < 20; ++size) {
98 message_size = size;
99
100 PW_TOKENIZE_TO_BUFFER(
101 buffer_,
102 &message_size,
103 "%" PRIx64,
104 static_cast<uint64_t>(std::numeric_limits<int64_t>::min()));
105
106 if (size < 14) {
107 constexpr std::array<uint8_t, 4> empty = ExpectedData("%" PRIx64);
108 ASSERT_EQ(sizeof(uint32_t), message_size);
109 EXPECT_EQ(std::memcmp(empty.data(), &buffer_, empty.size()), 0);
110
111 // Make sure nothing was written past the end of the buffer.
112 EXPECT_TRUE(std::all_of(&buffer_[size], std::end(buffer_), [](uint8_t v) {
113 return v == '\0';
114 }));
115 } else {
116 constexpr std::array<uint8_t, 14> expected =
117 ExpectedData<0xff,
118 0xff,
119 0xff,
120 0xff,
121 0xff,
122 0xff,
123 0xff,
124 0xff,
125 0xff,
126 0x01>("%" PRIx64);
127 ASSERT_EQ(expected.size(), message_size);
128 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
129 }
130 }
131}
132
133TEST_F(TokenizeToBuffer, IntegerNegative) {
134 size_t message_size = 9;
135 PW_TOKENIZE_TO_BUFFER(
136 buffer_, &message_size, "%" PRId32, std::numeric_limits<int32_t>::min());
137
138 // 0x8000'0000 -zig-zag-> 0xff'ff'ff'ff'0f
139 constexpr std::array<uint8_t, 9> expected =
140 ExpectedData<0xff, 0xff, 0xff, 0xff, 0x0f>("%" PRId32);
141 ASSERT_EQ(expected.size(), message_size);
142 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
143}
144
145TEST_F(TokenizeToBuffer, IntegerMin) {
146 size_t message_size = 9;
147 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "%d", -1);
148
149 constexpr std::array<uint8_t, 5> expected = ExpectedData<0x01>("%d");
150 ASSERT_EQ(expected.size(), message_size);
151 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
152}
153
154TEST_F(TokenizeToBuffer, IntegerDoesntFit) {
155 size_t message_size = 8;
156 PW_TOKENIZE_TO_BUFFER(
157 buffer_, &message_size, "%" PRId32, std::numeric_limits<int32_t>::min());
158
159 constexpr std::array<uint8_t, 4> expected = ExpectedData<>("%" PRId32);
160 ASSERT_EQ(expected.size(), message_size);
161 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
162}
163
164TEST_F(TokenizeToBuffer, String) {
165 size_t message_size = sizeof(buffer_);
166
167 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
168 constexpr std::array<uint8_t, 10> expected =
169 ExpectedData<5, '5', '4', '3', '2', '!'>("The answer is: %s");
170
171 ASSERT_EQ(expected.size(), message_size);
172 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
173}
174
175TEST_F(TokenizeToBuffer, String_BufferTooSmall_TruncatesAndSetsTopStatusBit) {
176 size_t message_size = 8;
177 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
178
179 constexpr std::array<uint8_t, 8> truncated_1 =
180 ExpectedData<0x83, '5', '4', '3'>("The answer is: %s");
181
182 ASSERT_EQ(truncated_1.size(), message_size);
183 EXPECT_EQ(std::memcmp(truncated_1.data(), buffer_, truncated_1.size()), 0);
184}
185
186TEST_F(TokenizeToBuffer, String_TwoBytesLeft_TruncatesToOneCharacter) {
187 size_t message_size = 6;
188 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
189
190 constexpr std::array<uint8_t, 6> truncated_2 =
191 ExpectedData<0x81, '5'>("The answer is: %s");
192
193 ASSERT_EQ(truncated_2.size(), message_size);
194 EXPECT_EQ(std::memcmp(truncated_2.data(), buffer_, truncated_2.size()), 0);
195}
196
197TEST_F(TokenizeToBuffer, String_OneByteLeft_OnlyWritesTruncatedStatusByte) {
198 size_t message_size = 5;
199 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
200
201 std::array<uint8_t, 5> result = ExpectedData<0x80>("The answer is: %s");
202 ASSERT_EQ(result.size(), message_size);
203 EXPECT_EQ(std::memcmp(result.data(), buffer_, result.size()), 0);
204}
205
206TEST_F(TokenizeToBuffer, EmptyString_OneByteLeft_EncodesCorrectly) {
207 size_t message_size = 5;
208 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "");
209
210 std::array<uint8_t, 5> result = ExpectedData<0>("The answer is: %s");
211 ASSERT_EQ(result.size(), message_size);
212 EXPECT_EQ(std::memcmp(result.data(), buffer_, result.size()), 0);
213}
214
215TEST_F(TokenizeToBuffer, String_ZeroBytesLeft_WritesNothing) {
216 size_t message_size = 4;
217 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
218
219 constexpr std::array<uint8_t, 4> empty = ExpectedData<>("The answer is: %s");
220 ASSERT_EQ(empty.size(), message_size);
221 EXPECT_EQ(std::memcmp(empty.data(), buffer_, empty.size()), 0);
222}
223
224TEST_F(TokenizeToBuffer, NullptrString_EncodesNull) {
225 char* string = nullptr;
226 size_t message_size = 9;
227 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", string);
228
229 std::array<uint8_t, 9> result =
230 ExpectedData<4, 'N', 'U', 'L', 'L'>("The answer is: %s");
231 ASSERT_EQ(result.size(), message_size);
232 EXPECT_EQ(std::memcmp(result.data(), buffer_, result.size()), 0);
233}
234
235TEST_F(TokenizeToBuffer, NullptrString_BufferTooSmall_EncodesTruncatedNull) {
236 char* string = nullptr;
237 size_t message_size = 6;
238 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", string);
239
240 std::array<uint8_t, 6> result = ExpectedData<0x81, 'N'>("The answer is: %s");
241 ASSERT_EQ(result.size(), message_size);
242 EXPECT_EQ(std::memcmp(result.data(), buffer_, result.size()), 0);
243}
244
245TEST_F(TokenizeToBuffer, TruncateArgs) {
246 // Args that can't fit are dropped completely
247 size_t message_size = 6;
248 PW_TOKENIZE_TO_BUFFER(buffer_,
249 &message_size,
250 "%u %d",
251 static_cast<uint8_t>(0b0010'1010u),
252 0xffffff);
253
254 constexpr std::array<uint8_t, 5> expected =
255 ExpectedData<0b0101'0100u>("%u %d");
256 ASSERT_EQ(expected.size(), message_size);
257 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
258}
259
260TEST_F(TokenizeToBuffer, NoRoomForToken) {
261 // Nothing is written if there isn't room for the token.
262 std::memset(buffer_, '$', sizeof(buffer_));
263 auto is_untouched = [](uint8_t v) { return v == '$'; };
264
265 size_t message_size = 3;
266 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer: \"%s\"", "5432!");
267 EXPECT_EQ(0u, message_size);
268 EXPECT_TRUE(std::all_of(buffer_, std::end(buffer_), is_untouched));
269
270 message_size = 2;
271 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "Jello, world!");
272 EXPECT_EQ(0u, message_size);
273 EXPECT_TRUE(std::all_of(buffer_, std::end(buffer_), is_untouched));
274
275 message_size = 1;
276 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "Jello!");
277 EXPECT_EQ(0u, message_size);
278 EXPECT_TRUE(std::all_of(buffer_, std::end(buffer_), is_untouched));
279
280 message_size = 0;
281 PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "Jello?");
282 EXPECT_EQ(0u, message_size);
283 EXPECT_TRUE(std::all_of(buffer_, std::end(buffer_), is_untouched));
284}
285
286TEST_F(TokenizeToBuffer, C_StringShortFloat) {
287 size_t size = sizeof(buffer_);
288 pw_TokenizeToBufferTest_StringShortFloat(buffer_, &size);
289 constexpr std::array<uint8_t, 11> expected = // clang-format off
290 ExpectedData<1, '1', // string '1'
291 3, // -2 (zig-zag encoded)
292 0x00, 0x00, 0x40, 0x40 // 3.0 in floating point
293 >(TEST_FORMAT_STRING_SHORT_FLOAT);
294 ASSERT_EQ(expected.size(), size); // clang-format on
295 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
296}
297
298TEST_F(TokenizeToBuffer, C_SequentialZigZag) {
299 size_t size = sizeof(buffer_);
300 pw_TokenizeToBufferTest_SequentialZigZag(buffer_, &size);
301 constexpr std::array<uint8_t, 18> expected =
302 ExpectedData<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13>(
303 TEST_FORMAT_SEQUENTIAL_ZIG_ZAG);
304
305 ASSERT_EQ(expected.size(), size);
306 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
307}
308
309TEST_F(TokenizeToBuffer, C_Overflow) {
310 std::memset(buffer_, '$', sizeof(buffer_));
311
312 {
313 size_t size = 7;
314 pw_TokenizeToBufferTest_Requires8(buffer_, &size);
315 constexpr std::array<uint8_t, 7> expected =
316 ExpectedData<2, 'h', 'i'>(TEST_FORMAT_REQUIRES_8);
317 ASSERT_EQ(expected.size(), size);
318 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
319 EXPECT_EQ(buffer_[7], '$');
320 }
321
322 {
323 size_t size = 8;
324 pw_TokenizeToBufferTest_Requires8(buffer_, &size);
325 constexpr std::array<uint8_t, 8> expected =
326 ExpectedData<2, 'h', 'i', 13>(TEST_FORMAT_REQUIRES_8);
327 ASSERT_EQ(expected.size(), size);
328 EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
329 EXPECT_EQ(buffer_[8], '$');
330 }
331}
332
333// Test fixture for callback and global handler. Both of these need a global
334// message buffer. To keep the message buffers separate, template this on the
335// derived class type.
336template <typename Impl>
337class GlobalMessage : public ::testing::Test {
338 public:
339 static void SetMessage(const uint8_t* message, size_t size) {
340 ASSERT_LE(size, sizeof(message_));
341 std::memcpy(message_, message, size);
342 message_size_bytes_ = size;
343 }
344
345 protected:
346 GlobalMessage() {
347 std::memset(message_, 0, sizeof(message_));
348 message_size_bytes_ = 0;
349 }
350
351 static uint8_t message_[256];
352 static size_t message_size_bytes_;
353};
354
355template <typename Impl>
356uint8_t GlobalMessage<Impl>::message_[256] = {};
357template <typename Impl>
358size_t GlobalMessage<Impl>::message_size_bytes_ = 0;
359
360class TokenizeToCallback : public GlobalMessage<TokenizeToCallback> {};
361
362TEST_F(TokenizeToCallback, Variety) {
363 PW_TOKENIZE_TO_CALLBACK(
364 SetMessage, "%s there are %x (%.2f) of them%c", "Now", 2u, 2.0f, '.');
365 const auto expected = // clang-format off
366 ExpectedData<3, 'N', 'o', 'w', // string "Now"
367 0x04, // unsigned 2 (zig-zag encoded)
368 0x00, 0x00, 0x00, 0x40, // float 2.0
369 0x5C // char '.' (0x2E, zig-zag encoded)
370 >("%s there are %x (%.2f) of them%c");
371 // clang-format on
372 ASSERT_EQ(expected.size(), message_size_bytes_);
373 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
374}
375
376TEST_F(TokenizeToCallback, Strings) {
377 PW_TOKENIZE_TO_CALLBACK(SetMessage, "The answer is: %s", "5432!");
378 constexpr std::array<uint8_t, 10> expected =
379 ExpectedData<5, '5', '4', '3', '2', '!'>("The answer is: %s");
380 ASSERT_EQ(expected.size(), message_size_bytes_);
381 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
382}
383
384TEST_F(TokenizeToCallback, C_SequentialZigZag) {
385 pw_TokenizeToCallbackTest_SequentialZigZag(SetMessage);
386
387 constexpr std::array<uint8_t, 18> expected =
388 ExpectedData<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13>(
389 TEST_FORMAT_SEQUENTIAL_ZIG_ZAG);
390 ASSERT_EQ(expected.size(), message_size_bytes_);
391 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
392}
393
394#if PW_TOKENIZER_CFG_ENABLE_TOKENIZE_TO_GLOBAL_HANDLER
395
396class TokenizeToGlobalHandler : public GlobalMessage<TokenizeToGlobalHandler> {
397};
398
399TEST_F(TokenizeToGlobalHandler, Variety) {
400 PW_TOKENIZE_TO_GLOBAL_HANDLER("%x%lld%1.2f%s", 0, 0ll, -0.0, "");
401 const auto expected =
402 ExpectedData<0, 0, 0x00, 0x00, 0x00, 0x80, 0>("%x%lld%1.2f%s");
403 ASSERT_EQ(expected.size(), message_size_bytes_);
404 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
405}
406
407TEST_F(TokenizeToGlobalHandler, Strings) {
408 PW_TOKENIZE_TO_GLOBAL_HANDLER("The answer is: %s", "5432!");
409 constexpr std::array<uint8_t, 10> expected =
410 ExpectedData<5, '5', '4', '3', '2', '!'>("The answer is: %s");
411 ASSERT_EQ(expected.size(), message_size_bytes_);
412 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
413}
414
415TEST_F(TokenizeToGlobalHandler, C_SequentialZigZag) {
416 pw_TokenizeToGlobalHandlerTest_SequentialZigZag();
417
418 constexpr std::array<uint8_t, 18> expected =
419 ExpectedData<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13>(
420 TEST_FORMAT_SEQUENTIAL_ZIG_ZAG);
421 ASSERT_EQ(expected.size(), message_size_bytes_);
422 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
423}
424
425extern "C" void pw_TokenizerHandleEncodedMessage(const uint8_t* encoded_message,
426 size_t size_bytes) {
427 TokenizeToGlobalHandler::SetMessage(encoded_message, size_bytes);
428}
429
430#endif // PW_TOKENIZER_CFG_ENABLE_TOKENIZE_TO_GLOBAL_HANDLER
431
432#if PW_TOKENIZER_CFG_ENABLE_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD
433
434class TokenizeToGlobalHandlerWithPayload
435 : public GlobalMessage<TokenizeToGlobalHandlerWithPayload> {
436 public:
437 static void SetPayload(pw_TokenizerPayload payload) {
438 payload_ = reinterpret_cast<intptr_t>(payload);
439 }
440
441 protected:
442 TokenizeToGlobalHandlerWithPayload() { payload_ = {}; }
443
444 static intptr_t payload_;
445};
446
447intptr_t TokenizeToGlobalHandlerWithPayload::payload_;
448
449TEST_F(TokenizeToGlobalHandlerWithPayload, Variety) {
450 ASSERT_NE(payload_, 123);
451
452 const auto expected =
453 ExpectedData<0, 0, 0x00, 0x00, 0x00, 0x80, 0>("%x%lld%1.2f%s");
454
455 PW_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD(
456 reinterpret_cast<pw_TokenizerPayload>(123),
457 "%x%lld%1.2f%s",
458 0,
459 0ll,
460 -0.0,
461 "");
462 ASSERT_EQ(expected.size(), message_size_bytes_);
463 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
464 EXPECT_EQ(payload_, 123);
465
466 PW_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD(
467 reinterpret_cast<pw_TokenizerPayload>(-543),
468 "%x%lld%1.2f%s",
469 0,
470 0ll,
471 -0.0,
472 "");
473 ASSERT_EQ(expected.size(), message_size_bytes_);
474 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
475 EXPECT_EQ(payload_, -543);
476}
477
478TEST_F(TokenizeToGlobalHandlerWithPayload, Strings) {
479 constexpr std::array<uint8_t, 10> expected =
480 ExpectedData<5, '5', '4', '3', '2', '!'>("The answer is: %s");
481
482 PW_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD(
483 reinterpret_cast<pw_TokenizerPayload>(5432),
484 "The answer is: %s",
485 "5432!");
486
487 ASSERT_EQ(expected.size(), message_size_bytes_);
488 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
489 EXPECT_EQ(payload_, 5432);
490
491 PW_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD({}, "The answer is: %s", "5432!");
492
493 ASSERT_EQ(expected.size(), message_size_bytes_);
494 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
495 EXPECT_EQ(payload_, 0);
496}
497
498struct Foo {
499 unsigned char a;
500 bool b;
501};
502
503TEST_F(TokenizeToGlobalHandlerWithPayload, PointerToStack) {
504 Foo foo{254u, true};
505
506 PW_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD(
507 reinterpret_cast<pw_TokenizerPayload>(&foo), "Boring!");
508
509 constexpr auto expected = ExpectedData("Boring!");
510 static_assert(expected.size() == 4);
511 ASSERT_EQ(expected.size(), message_size_bytes_);
512 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
513
514 Foo* payload_foo = reinterpret_cast<Foo*>(payload_);
515 ASSERT_EQ(&foo, payload_foo);
516 EXPECT_EQ(payload_foo->a, 254u);
517 EXPECT_TRUE(payload_foo->b);
518}
519
520TEST_F(TokenizeToGlobalHandlerWithPayload, C_SequentialZigZag) {
521 pw_TokenizeToGlobalHandlerWithPayloadTest_SequentialZigZag();
522
523 constexpr std::array<uint8_t, 18> expected =
524 ExpectedData<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13>(
525 TEST_FORMAT_SEQUENTIAL_ZIG_ZAG);
526 ASSERT_EQ(expected.size(), message_size_bytes_);
527 EXPECT_EQ(std::memcmp(expected.data(), message_, expected.size()), 0);
528 EXPECT_EQ(payload_, 600613);
529}
530
531extern "C" void pw_TokenizerHandleEncodedMessageWithPayload(
532 pw_TokenizerPayload payload,
533 const uint8_t* encoded_message,
534 size_t size_bytes) {
535 TokenizeToGlobalHandlerWithPayload::SetMessage(encoded_message, size_bytes);
536 TokenizeToGlobalHandlerWithPayload::SetPayload(payload);
537}
538
539#endif // PW_TOKENIZER_CFG_ENABLE_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD
540
541} // namespace
542} // namespace pw::tokenizer