xref: /aosp_15_r20/external/pigweed/pw_tokenizer/tokenize_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2020 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker #include "pw_tokenizer/tokenize.h"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include <cinttypes>
18*61c4878aSAndroid Build Coastguard Worker #include <cstdint>
19*61c4878aSAndroid Build Coastguard Worker #include <cstring>
20*61c4878aSAndroid Build Coastguard Worker #include <iterator>
21*61c4878aSAndroid Build Coastguard Worker #include <limits>
22*61c4878aSAndroid Build Coastguard Worker 
23*61c4878aSAndroid Build Coastguard Worker #include "pw_tokenizer/hash.h"
24*61c4878aSAndroid Build Coastguard Worker #include "pw_tokenizer_private/tokenize_test.h"
25*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
26*61c4878aSAndroid Build Coastguard Worker #include "pw_varint/varint.h"
27*61c4878aSAndroid Build Coastguard Worker 
28*61c4878aSAndroid Build Coastguard Worker namespace pw::tokenizer {
29*61c4878aSAndroid Build Coastguard Worker namespace {
30*61c4878aSAndroid Build Coastguard Worker 
31*61c4878aSAndroid Build Coastguard Worker // Constructs an array with the hashed string followed by the provided bytes.
32*61c4878aSAndroid Build Coastguard Worker template <uint8_t... kData, size_t kSize>
ExpectedData(const char (& format)[kSize],uint32_t token_mask=std::numeric_limits<uint32_t>::max ())33*61c4878aSAndroid Build Coastguard Worker constexpr auto ExpectedData(
34*61c4878aSAndroid Build Coastguard Worker     const char (&format)[kSize],
35*61c4878aSAndroid Build Coastguard Worker     uint32_t token_mask = std::numeric_limits<uint32_t>::max()) {
36*61c4878aSAndroid Build Coastguard Worker   const uint32_t value = Hash(format) & token_mask;
37*61c4878aSAndroid Build Coastguard Worker   return std::array<uint8_t, sizeof(uint32_t) + sizeof...(kData)>{
38*61c4878aSAndroid Build Coastguard Worker       static_cast<uint8_t>(value & 0xff),
39*61c4878aSAndroid Build Coastguard Worker       static_cast<uint8_t>(value >> 8 & 0xff),
40*61c4878aSAndroid Build Coastguard Worker       static_cast<uint8_t>(value >> 16 & 0xff),
41*61c4878aSAndroid Build Coastguard Worker       static_cast<uint8_t>(value >> 24 & 0xff),
42*61c4878aSAndroid Build Coastguard Worker       kData...};
43*61c4878aSAndroid Build Coastguard Worker }
44*61c4878aSAndroid Build Coastguard Worker 
TEST(TokenizeString,EmptyString_IsZero)45*61c4878aSAndroid Build Coastguard Worker TEST(TokenizeString, EmptyString_IsZero) {
46*61c4878aSAndroid Build Coastguard Worker   constexpr pw_tokenizer_Token token = PW_TOKENIZE_STRING("");
47*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(0u, token);
48*61c4878aSAndroid Build Coastguard Worker }
49*61c4878aSAndroid Build Coastguard Worker 
TEST(TokenizeString,String_MatchesHash)50*61c4878aSAndroid Build Coastguard Worker TEST(TokenizeString, String_MatchesHash) {
51*61c4878aSAndroid Build Coastguard Worker   constexpr uint32_t token = PW_TOKENIZE_STRING("[:-)");
52*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Hash("[:-)"), token);
53*61c4878aSAndroid Build Coastguard Worker }
54*61c4878aSAndroid Build Coastguard Worker 
TEST(TokenizeString,String_MatchesHashExpr)55*61c4878aSAndroid Build Coastguard Worker TEST(TokenizeString, String_MatchesHashExpr) {
56*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Hash("[:-)"), PW_TOKENIZE_STRING_EXPR("[:-)"));
57*61c4878aSAndroid Build Coastguard Worker }
58*61c4878aSAndroid Build Coastguard Worker 
TEST(TokenizeString,ExpressionWithStringVariable)59*61c4878aSAndroid Build Coastguard Worker TEST(TokenizeString, ExpressionWithStringVariable) {
60*61c4878aSAndroid Build Coastguard Worker   constexpr char kTestString[] = "test";
61*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Hash(kTestString), PW_TOKENIZE_STRING_EXPR(kTestString));
62*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Hash(kTestString),
63*61c4878aSAndroid Build Coastguard Worker             PW_TOKENIZE_STRING_DOMAIN_EXPR("TEST_DOMAIN", kTestString));
64*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(
65*61c4878aSAndroid Build Coastguard Worker       Hash(kTestString) & 0xAAAAAAAA,
66*61c4878aSAndroid Build Coastguard Worker       PW_TOKENIZE_STRING_MASK_EXPR("TEST_DOMAIN", 0xAAAAAAAA, kTestString));
67*61c4878aSAndroid Build Coastguard Worker }
68*61c4878aSAndroid Build Coastguard Worker 
69*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kGlobalToken = PW_TOKENIZE_STRING(">:-[]");
70*61c4878aSAndroid Build Coastguard Worker 
TEST(TokenizeString,GlobalVariable_MatchesHash)71*61c4878aSAndroid Build Coastguard Worker TEST(TokenizeString, GlobalVariable_MatchesHash) {
72*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Hash(">:-[]"), kGlobalToken);
73*61c4878aSAndroid Build Coastguard Worker }
74*61c4878aSAndroid Build Coastguard Worker 
75*61c4878aSAndroid Build Coastguard Worker struct TokenizedWithinClass {
76*61c4878aSAndroid Build Coastguard Worker   static constexpr uint32_t kThisToken = PW_TOKENIZE_STRING("???");
77*61c4878aSAndroid Build Coastguard Worker };
78*61c4878aSAndroid Build Coastguard Worker 
79*61c4878aSAndroid Build Coastguard Worker static_assert(Hash("???") == TokenizedWithinClass::kThisToken);
80*61c4878aSAndroid Build Coastguard Worker 
TEST(TokenizeString,ClassMember_MatchesHash)81*61c4878aSAndroid Build Coastguard Worker TEST(TokenizeString, ClassMember_MatchesHash) {
82*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Hash("???"), TokenizedWithinClass().kThisToken);
83*61c4878aSAndroid Build Coastguard Worker }
84*61c4878aSAndroid Build Coastguard Worker 
TEST(TokenizeString,WithinNonCapturingLambda)85*61c4878aSAndroid Build Coastguard Worker TEST(TokenizeString, WithinNonCapturingLambda) {
86*61c4878aSAndroid Build Coastguard Worker   uint32_t non_capturing_lambda = [] {
87*61c4878aSAndroid Build Coastguard Worker     return PW_TOKENIZE_STRING("Lambda!");
88*61c4878aSAndroid Build Coastguard Worker   }();
89*61c4878aSAndroid Build Coastguard Worker 
90*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Hash("Lambda!"), non_capturing_lambda);
91*61c4878aSAndroid Build Coastguard Worker }
92*61c4878aSAndroid Build Coastguard Worker 
TEST(TokenizeString,WithinCapturingLambda)93*61c4878aSAndroid Build Coastguard Worker TEST(TokenizeString, WithinCapturingLambda) {
94*61c4878aSAndroid Build Coastguard Worker   bool executed_lambda = false;
95*61c4878aSAndroid Build Coastguard Worker   uint32_t capturing_lambda = [&executed_lambda] {
96*61c4878aSAndroid Build Coastguard Worker     if (executed_lambda) {
97*61c4878aSAndroid Build Coastguard Worker       return PW_TOKENIZE_STRING("Never should be returned!");
98*61c4878aSAndroid Build Coastguard Worker     }
99*61c4878aSAndroid Build Coastguard Worker     executed_lambda = true;
100*61c4878aSAndroid Build Coastguard Worker     return PW_TOKENIZE_STRING("Capturing lambda!");
101*61c4878aSAndroid Build Coastguard Worker   }();
102*61c4878aSAndroid Build Coastguard Worker 
103*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(executed_lambda);
104*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Hash("Capturing lambda!"), capturing_lambda);
105*61c4878aSAndroid Build Coastguard Worker }
106*61c4878aSAndroid Build Coastguard Worker 
TEST(TokenizeString,Mask)107*61c4878aSAndroid Build Coastguard Worker TEST(TokenizeString, Mask) {
108*61c4878aSAndroid Build Coastguard Worker   [[maybe_unused]] constexpr uint32_t token = PW_TOKENIZE_STRING("(O_o)");
109*61c4878aSAndroid Build Coastguard Worker   [[maybe_unused]] constexpr uint32_t masked_1 =
110*61c4878aSAndroid Build Coastguard Worker       PW_TOKENIZE_STRING_MASK("domain", 0xAAAAAAAA, "(O_o)");
111*61c4878aSAndroid Build Coastguard Worker   [[maybe_unused]] constexpr uint32_t masked_2 =
112*61c4878aSAndroid Build Coastguard Worker       PW_TOKENIZE_STRING_MASK("domain", 0x55555555, "(O_o)");
113*61c4878aSAndroid Build Coastguard Worker   [[maybe_unused]] constexpr uint32_t masked_3 =
114*61c4878aSAndroid Build Coastguard Worker       PW_TOKENIZE_STRING_MASK("domain", 0xFFFF0000, "(O_o)");
115*61c4878aSAndroid Build Coastguard Worker 
116*61c4878aSAndroid Build Coastguard Worker   static_assert(token != masked_1 && token != masked_2 && token != masked_3);
117*61c4878aSAndroid Build Coastguard Worker   static_assert(masked_1 != masked_2 && masked_2 != masked_3);
118*61c4878aSAndroid Build Coastguard Worker   static_assert((token & 0xAAAAAAAA) == masked_1);
119*61c4878aSAndroid Build Coastguard Worker   static_assert((token & 0x55555555) == masked_2);
120*61c4878aSAndroid Build Coastguard Worker   static_assert((token & 0xFFFF0000) == masked_3);
121*61c4878aSAndroid Build Coastguard Worker }
122*61c4878aSAndroid Build Coastguard Worker 
TEST(TokenizeString,MaskExpr)123*61c4878aSAndroid Build Coastguard Worker TEST(TokenizeString, MaskExpr) {
124*61c4878aSAndroid Build Coastguard Worker   uint32_t token = PW_TOKENIZE_STRING("(O_o)");
125*61c4878aSAndroid Build Coastguard Worker   uint32_t masked_1 =
126*61c4878aSAndroid Build Coastguard Worker       PW_TOKENIZE_STRING_MASK_EXPR("domain", 0xAAAAAAAA, "(O_o)");
127*61c4878aSAndroid Build Coastguard Worker   uint32_t masked_2 =
128*61c4878aSAndroid Build Coastguard Worker       PW_TOKENIZE_STRING_MASK_EXPR("domain", 0x55555555, "(O_o)");
129*61c4878aSAndroid Build Coastguard Worker   uint32_t masked_3 =
130*61c4878aSAndroid Build Coastguard Worker       PW_TOKENIZE_STRING_MASK_EXPR("domain", 0xFFFF0000, "(O_o)");
131*61c4878aSAndroid Build Coastguard Worker 
132*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(token != masked_1 && token != masked_2 && token != masked_3);
133*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(masked_1 != masked_2 && masked_2 != masked_3);
134*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE((token & 0xAAAAAAAA) == masked_1);
135*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE((token & 0x55555555) == masked_2);
136*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE((token & 0xFFFF0000) == masked_3);
137*61c4878aSAndroid Build Coastguard Worker }
138*61c4878aSAndroid Build Coastguard Worker 
139*61c4878aSAndroid Build Coastguard Worker // Use a function with a shorter name to test tokenizing __func__ and
140*61c4878aSAndroid Build Coastguard Worker // __PRETTY_FUNCTION__.
141*61c4878aSAndroid Build Coastguard Worker //
142*61c4878aSAndroid Build Coastguard Worker // WARNING: This function might cause errors for compilers other than GCC and
143*61c4878aSAndroid Build Coastguard Worker // clang. It relies on two GCC/clang extensions:
144*61c4878aSAndroid Build Coastguard Worker //
145*61c4878aSAndroid Build Coastguard Worker //   1 - The __PRETTY_FUNCTION__ C++ function name variable.
146*61c4878aSAndroid Build Coastguard Worker //   2 - __func__ as a static constexpr array instead of static const. See
147*61c4878aSAndroid Build Coastguard Worker //       https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66639 for background.
148*61c4878aSAndroid Build Coastguard Worker //
TestName()149*61c4878aSAndroid Build Coastguard Worker void TestName() {
150*61c4878aSAndroid Build Coastguard Worker   constexpr uint32_t function_hash = PW_TOKENIZE_STRING(__func__);
151*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(pw::tokenizer::Hash(__func__), function_hash);
152*61c4878aSAndroid Build Coastguard Worker 
153*61c4878aSAndroid Build Coastguard Worker   // Check the non-standard __PRETTY_FUNCTION__ name.
154*61c4878aSAndroid Build Coastguard Worker   constexpr uint32_t pretty_function = PW_TOKENIZE_STRING(__PRETTY_FUNCTION__);
155*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(pw::tokenizer::Hash(__PRETTY_FUNCTION__), pretty_function);
156*61c4878aSAndroid Build Coastguard Worker }
157*61c4878aSAndroid Build Coastguard Worker 
TEST(TokenizeString,FunctionName)158*61c4878aSAndroid Build Coastguard Worker TEST(TokenizeString, FunctionName) { TestName(); }
159*61c4878aSAndroid Build Coastguard Worker 
TEST(TokenizeString,Array)160*61c4878aSAndroid Build Coastguard Worker TEST(TokenizeString, Array) {
161*61c4878aSAndroid Build Coastguard Worker   constexpr char array[] = "won-won-won-wonderful";
162*61c4878aSAndroid Build Coastguard Worker 
163*61c4878aSAndroid Build Coastguard Worker   const uint32_t array_hash = PW_TOKENIZE_STRING(array);
164*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(Hash(array), array_hash);
165*61c4878aSAndroid Build Coastguard Worker }
166*61c4878aSAndroid Build Coastguard Worker 
TEST(TokenizeString,NullInString)167*61c4878aSAndroid Build Coastguard Worker TEST(TokenizeString, NullInString) {
168*61c4878aSAndroid Build Coastguard Worker   // Use PW_TOKENIZER_STRING_TOKEN to avoid emitting strings with NUL into the
169*61c4878aSAndroid Build Coastguard Worker   // ELF file. The CSV database format does not support NUL.
170*61c4878aSAndroid Build Coastguard Worker   constexpr char nulls[32] = {};
171*61c4878aSAndroid Build Coastguard Worker   static_assert(Hash(nulls) == PW_TOKENIZER_STRING_TOKEN(nulls));
172*61c4878aSAndroid Build Coastguard Worker   static_assert(PW_TOKENIZER_STRING_TOKEN(nulls) != 0u);
173*61c4878aSAndroid Build Coastguard Worker 
174*61c4878aSAndroid Build Coastguard Worker   static_assert(PW_TOKENIZER_STRING_TOKEN("\0") == Hash("\0"));
175*61c4878aSAndroid Build Coastguard Worker   static_assert(PW_TOKENIZER_STRING_TOKEN("\0") != Hash(""));
176*61c4878aSAndroid Build Coastguard Worker 
177*61c4878aSAndroid Build Coastguard Worker   static_assert(PW_TOKENIZER_STRING_TOKEN("abc\0def") == Hash("abc\0def"));
178*61c4878aSAndroid Build Coastguard Worker 
179*61c4878aSAndroid Build Coastguard Worker   static_assert(Hash("abc\0def") != Hash("abc\0def\0"));
180*61c4878aSAndroid Build Coastguard Worker }
181*61c4878aSAndroid Build Coastguard Worker 
182*61c4878aSAndroid Build Coastguard Worker // Verify that we can tokenize multiple strings from one source line.
183*61c4878aSAndroid Build Coastguard Worker #define THREE_FOR_ONE(first, second, third)             \
184*61c4878aSAndroid Build Coastguard Worker   [[maybe_unused]] constexpr uint32_t token_1 =         \
185*61c4878aSAndroid Build Coastguard Worker       PW_TOKENIZE_STRING_DOMAIN("TEST_DOMAIN", first);  \
186*61c4878aSAndroid Build Coastguard Worker   [[maybe_unused]] constexpr uint32_t token_2 =         \
187*61c4878aSAndroid Build Coastguard Worker       PW_TOKENIZE_STRING_DOMAIN("TEST_DOMAIN", second); \
188*61c4878aSAndroid Build Coastguard Worker   [[maybe_unused]] constexpr uint32_t token_3 =         \
189*61c4878aSAndroid Build Coastguard Worker       PW_TOKENIZE_STRING_DOMAIN("TEST_DOMAIN", third);
190*61c4878aSAndroid Build Coastguard Worker 
TEST(TokenizeString,MultipleTokenizationsInOneMacroExpansion)191*61c4878aSAndroid Build Coastguard Worker TEST(TokenizeString, MultipleTokenizationsInOneMacroExpansion) {
192*61c4878aSAndroid Build Coastguard Worker   // This verifies that we can safely tokenize multiple times in a single macro
193*61c4878aSAndroid Build Coastguard Worker   // expansion. This can be useful when for example a name and description are
194*61c4878aSAndroid Build Coastguard Worker   // both tokenized after being passed into a macro.
195*61c4878aSAndroid Build Coastguard Worker   //
196*61c4878aSAndroid Build Coastguard Worker   // This test only verifies that this compiles correctly; it does not test
197*61c4878aSAndroid Build Coastguard Worker   // that the tokenizations make it to the final token database.
198*61c4878aSAndroid Build Coastguard Worker   THREE_FOR_ONE("hello", "yes", "something");
199*61c4878aSAndroid Build Coastguard Worker }
200*61c4878aSAndroid Build Coastguard Worker 
201*61c4878aSAndroid Build Coastguard Worker // Verify that we can tokenize multiple strings from one source line.
202*61c4878aSAndroid Build Coastguard Worker #define THREE_FOR_ONE_EXPR(first, second, third)             \
203*61c4878aSAndroid Build Coastguard Worker   [[maybe_unused]] uint32_t token_1 =                        \
204*61c4878aSAndroid Build Coastguard Worker       PW_TOKENIZE_STRING_DOMAIN_EXPR("TEST_DOMAIN", first);  \
205*61c4878aSAndroid Build Coastguard Worker   [[maybe_unused]] uint32_t token_2 =                        \
206*61c4878aSAndroid Build Coastguard Worker       PW_TOKENIZE_STRING_DOMAIN_EXPR("TEST_DOMAIN", second); \
207*61c4878aSAndroid Build Coastguard Worker   [[maybe_unused]] uint32_t token_3 =                        \
208*61c4878aSAndroid Build Coastguard Worker       PW_TOKENIZE_STRING_DOMAIN_EXPR("TEST_DOMAIN", third);
209*61c4878aSAndroid Build Coastguard Worker 
TEST(TokenizeString,MultipleTokenizationsInOneMacroExpansionExpr)210*61c4878aSAndroid Build Coastguard Worker TEST(TokenizeString, MultipleTokenizationsInOneMacroExpansionExpr) {
211*61c4878aSAndroid Build Coastguard Worker   // This verifies that we can safely tokenize multiple times in a single macro
212*61c4878aSAndroid Build Coastguard Worker   // expansion. This can be useful when for example a name and description are
213*61c4878aSAndroid Build Coastguard Worker   // both tokenized after being passed into a macro.
214*61c4878aSAndroid Build Coastguard Worker   //
215*61c4878aSAndroid Build Coastguard Worker   // This test only verifies that this compiles correctly; it does not test
216*61c4878aSAndroid Build Coastguard Worker   // that the tokenizations make it to the final token database.
217*61c4878aSAndroid Build Coastguard Worker   THREE_FOR_ONE_EXPR("hello", "yes", "something");
218*61c4878aSAndroid Build Coastguard Worker }
219*61c4878aSAndroid Build Coastguard Worker 
220*61c4878aSAndroid Build Coastguard Worker class TokenizeToBuffer : public ::testing::Test {
221*61c4878aSAndroid Build Coastguard Worker  public:
TokenizeToBuffer()222*61c4878aSAndroid Build Coastguard Worker   TokenizeToBuffer() : buffer_{} {}
223*61c4878aSAndroid Build Coastguard Worker 
224*61c4878aSAndroid Build Coastguard Worker  protected:
225*61c4878aSAndroid Build Coastguard Worker   uint8_t buffer_[64];
226*61c4878aSAndroid Build Coastguard Worker };
227*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,Integer64)228*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, Integer64) {
229*61c4878aSAndroid Build Coastguard Worker   size_t message_size = 14;
230*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(
231*61c4878aSAndroid Build Coastguard Worker       buffer_,
232*61c4878aSAndroid Build Coastguard Worker       &message_size,
233*61c4878aSAndroid Build Coastguard Worker       "%" PRIu64,
234*61c4878aSAndroid Build Coastguard Worker       static_cast<uint64_t>(0x55555555'55555555ull));  // 0xAAAAAAAA'AAAAAAAA
235*61c4878aSAndroid Build Coastguard Worker 
236*61c4878aSAndroid Build Coastguard Worker   // Pattern becomes 10101010'11010101'10101010 ...
237*61c4878aSAndroid Build Coastguard Worker   constexpr std::array<uint8_t, 14> expected =
238*61c4878aSAndroid Build Coastguard Worker       ExpectedData<0xAA, 0xD5, 0xAA, 0xD5, 0xAA, 0xD5, 0xAA, 0xD5, 0xAA, 0x01>(
239*61c4878aSAndroid Build Coastguard Worker           "%" PRIu64);
240*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(expected.size(), message_size);
241*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
242*61c4878aSAndroid Build Coastguard Worker }
243*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,Integer64Overflow)244*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, Integer64Overflow) {
245*61c4878aSAndroid Build Coastguard Worker   size_t message_size;
246*61c4878aSAndroid Build Coastguard Worker 
247*61c4878aSAndroid Build Coastguard Worker   for (size_t size = 4; size < 20; ++size) {
248*61c4878aSAndroid Build Coastguard Worker     message_size = size;
249*61c4878aSAndroid Build Coastguard Worker 
250*61c4878aSAndroid Build Coastguard Worker     PW_TOKENIZE_TO_BUFFER(
251*61c4878aSAndroid Build Coastguard Worker         buffer_,
252*61c4878aSAndroid Build Coastguard Worker         &message_size,
253*61c4878aSAndroid Build Coastguard Worker         "%" PRIx64,
254*61c4878aSAndroid Build Coastguard Worker         static_cast<uint64_t>(std::numeric_limits<int64_t>::min()));
255*61c4878aSAndroid Build Coastguard Worker 
256*61c4878aSAndroid Build Coastguard Worker     if (size < 14) {
257*61c4878aSAndroid Build Coastguard Worker       constexpr std::array<uint8_t, 4> empty = ExpectedData("%" PRIx64);
258*61c4878aSAndroid Build Coastguard Worker       ASSERT_EQ(sizeof(uint32_t), message_size);
259*61c4878aSAndroid Build Coastguard Worker       EXPECT_EQ(std::memcmp(empty.data(), &buffer_, empty.size()), 0);
260*61c4878aSAndroid Build Coastguard Worker 
261*61c4878aSAndroid Build Coastguard Worker       // Make sure nothing was written past the end of the buffer.
262*61c4878aSAndroid Build Coastguard Worker       EXPECT_TRUE(std::all_of(&buffer_[size], std::end(buffer_), [](uint8_t v) {
263*61c4878aSAndroid Build Coastguard Worker         return v == '\0';
264*61c4878aSAndroid Build Coastguard Worker       }));
265*61c4878aSAndroid Build Coastguard Worker     } else {
266*61c4878aSAndroid Build Coastguard Worker       constexpr std::array<uint8_t, 14> expected =
267*61c4878aSAndroid Build Coastguard Worker           ExpectedData<0xff,
268*61c4878aSAndroid Build Coastguard Worker                        0xff,
269*61c4878aSAndroid Build Coastguard Worker                        0xff,
270*61c4878aSAndroid Build Coastguard Worker                        0xff,
271*61c4878aSAndroid Build Coastguard Worker                        0xff,
272*61c4878aSAndroid Build Coastguard Worker                        0xff,
273*61c4878aSAndroid Build Coastguard Worker                        0xff,
274*61c4878aSAndroid Build Coastguard Worker                        0xff,
275*61c4878aSAndroid Build Coastguard Worker                        0xff,
276*61c4878aSAndroid Build Coastguard Worker                        0x01>("%" PRIx64);
277*61c4878aSAndroid Build Coastguard Worker       ASSERT_EQ(expected.size(), message_size);
278*61c4878aSAndroid Build Coastguard Worker       EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
279*61c4878aSAndroid Build Coastguard Worker     }
280*61c4878aSAndroid Build Coastguard Worker   }
281*61c4878aSAndroid Build Coastguard Worker }
282*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,IntegerNegative)283*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, IntegerNegative) {
284*61c4878aSAndroid Build Coastguard Worker   size_t message_size = 9;
285*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(
286*61c4878aSAndroid Build Coastguard Worker       buffer_, &message_size, "%" PRId32, std::numeric_limits<int32_t>::min());
287*61c4878aSAndroid Build Coastguard Worker 
288*61c4878aSAndroid Build Coastguard Worker   // 0x8000'0000 -zig-zag-> 0xff'ff'ff'ff'0f
289*61c4878aSAndroid Build Coastguard Worker   constexpr std::array<uint8_t, 9> expected =
290*61c4878aSAndroid Build Coastguard Worker       ExpectedData<0xff, 0xff, 0xff, 0xff, 0x0f>("%" PRId32);
291*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(expected.size(), message_size);
292*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
293*61c4878aSAndroid Build Coastguard Worker }
294*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,IntegerMin)295*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, IntegerMin) {
296*61c4878aSAndroid Build Coastguard Worker   size_t message_size = 9;
297*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "%d", -1);
298*61c4878aSAndroid Build Coastguard Worker 
299*61c4878aSAndroid Build Coastguard Worker   constexpr std::array<uint8_t, 5> expected = ExpectedData<0x01>("%d");
300*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(expected.size(), message_size);
301*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
302*61c4878aSAndroid Build Coastguard Worker }
303*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,IntegerDoesntFit)304*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, IntegerDoesntFit) {
305*61c4878aSAndroid Build Coastguard Worker   size_t message_size = 8;
306*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(
307*61c4878aSAndroid Build Coastguard Worker       buffer_, &message_size, "%" PRId32, std::numeric_limits<int32_t>::min());
308*61c4878aSAndroid Build Coastguard Worker 
309*61c4878aSAndroid Build Coastguard Worker   constexpr std::array<uint8_t, 4> expected = ExpectedData<>("%" PRId32);
310*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(expected.size(), message_size);
311*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
312*61c4878aSAndroid Build Coastguard Worker }
313*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,String)314*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, String) {
315*61c4878aSAndroid Build Coastguard Worker   size_t message_size = sizeof(buffer_);
316*61c4878aSAndroid Build Coastguard Worker 
317*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
318*61c4878aSAndroid Build Coastguard Worker   constexpr std::array<uint8_t, 10> expected =
319*61c4878aSAndroid Build Coastguard Worker       ExpectedData<5, '5', '4', '3', '2', '!'>("The answer is: %s");
320*61c4878aSAndroid Build Coastguard Worker 
321*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(expected.size(), message_size);
322*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
323*61c4878aSAndroid Build Coastguard Worker }
324*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,String_BufferTooSmall_TruncatesAndSetsTopStatusBit)325*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, String_BufferTooSmall_TruncatesAndSetsTopStatusBit) {
326*61c4878aSAndroid Build Coastguard Worker   size_t message_size = 8;
327*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
328*61c4878aSAndroid Build Coastguard Worker 
329*61c4878aSAndroid Build Coastguard Worker   constexpr std::array<uint8_t, 8> truncated_1 =
330*61c4878aSAndroid Build Coastguard Worker       ExpectedData<0x83, '5', '4', '3'>("The answer is: %s");
331*61c4878aSAndroid Build Coastguard Worker 
332*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(truncated_1.size(), message_size);
333*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(truncated_1.data(), buffer_, truncated_1.size()), 0);
334*61c4878aSAndroid Build Coastguard Worker }
335*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,String_TwoBytesLeft_TruncatesToOneCharacter)336*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, String_TwoBytesLeft_TruncatesToOneCharacter) {
337*61c4878aSAndroid Build Coastguard Worker   size_t message_size = 6;
338*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
339*61c4878aSAndroid Build Coastguard Worker 
340*61c4878aSAndroid Build Coastguard Worker   constexpr std::array<uint8_t, 6> truncated_2 =
341*61c4878aSAndroid Build Coastguard Worker       ExpectedData<0x81, '5'>("The answer is: %s");
342*61c4878aSAndroid Build Coastguard Worker 
343*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(truncated_2.size(), message_size);
344*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(truncated_2.data(), buffer_, truncated_2.size()), 0);
345*61c4878aSAndroid Build Coastguard Worker }
346*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,String_OneByteLeft_OnlyWritesTruncatedStatusByte)347*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, String_OneByteLeft_OnlyWritesTruncatedStatusByte) {
348*61c4878aSAndroid Build Coastguard Worker   size_t message_size = 5;
349*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
350*61c4878aSAndroid Build Coastguard Worker 
351*61c4878aSAndroid Build Coastguard Worker   std::array<uint8_t, 5> result = ExpectedData<0x80>("The answer is: %s");
352*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(result.size(), message_size);
353*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), buffer_, result.size()), 0);
354*61c4878aSAndroid Build Coastguard Worker }
355*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,EmptyString_OneByteLeft_EncodesCorrectly)356*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, EmptyString_OneByteLeft_EncodesCorrectly) {
357*61c4878aSAndroid Build Coastguard Worker   size_t message_size = 5;
358*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "");
359*61c4878aSAndroid Build Coastguard Worker 
360*61c4878aSAndroid Build Coastguard Worker   std::array<uint8_t, 5> result = ExpectedData<0>("The answer is: %s");
361*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(result.size(), message_size);
362*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), buffer_, result.size()), 0);
363*61c4878aSAndroid Build Coastguard Worker }
364*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,String_ZeroBytesLeft_WritesNothing)365*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, String_ZeroBytesLeft_WritesNothing) {
366*61c4878aSAndroid Build Coastguard Worker   size_t message_size = 4;
367*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
368*61c4878aSAndroid Build Coastguard Worker 
369*61c4878aSAndroid Build Coastguard Worker   constexpr std::array<uint8_t, 4> empty = ExpectedData<>("The answer is: %s");
370*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(empty.size(), message_size);
371*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(empty.data(), buffer_, empty.size()), 0);
372*61c4878aSAndroid Build Coastguard Worker }
373*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,Array)374*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, Array) {
375*61c4878aSAndroid Build Coastguard Worker   static constexpr char array[] = "1234";
376*61c4878aSAndroid Build Coastguard Worker   size_t message_size = 4;
377*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, array);
378*61c4878aSAndroid Build Coastguard Worker 
379*61c4878aSAndroid Build Coastguard Worker   constexpr std::array<uint8_t, 4> result = ExpectedData<>("1234");
380*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(result.size(), message_size);
381*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), buffer_, result.size()), 0);
382*61c4878aSAndroid Build Coastguard Worker }
383*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,NullptrString_EncodesNull)384*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, NullptrString_EncodesNull) {
385*61c4878aSAndroid Build Coastguard Worker   char* string = nullptr;
386*61c4878aSAndroid Build Coastguard Worker   size_t message_size = 9;
387*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", string);
388*61c4878aSAndroid Build Coastguard Worker 
389*61c4878aSAndroid Build Coastguard Worker   std::array<uint8_t, 9> result =
390*61c4878aSAndroid Build Coastguard Worker       ExpectedData<4, 'N', 'U', 'L', 'L'>("The answer is: %s");
391*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(result.size(), message_size);
392*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), buffer_, result.size()), 0);
393*61c4878aSAndroid Build Coastguard Worker }
394*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,NullptrString_BufferTooSmall_EncodesTruncatedNull)395*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, NullptrString_BufferTooSmall_EncodesTruncatedNull) {
396*61c4878aSAndroid Build Coastguard Worker   char* string = nullptr;
397*61c4878aSAndroid Build Coastguard Worker   size_t message_size = 6;
398*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", string);
399*61c4878aSAndroid Build Coastguard Worker 
400*61c4878aSAndroid Build Coastguard Worker   std::array<uint8_t, 6> result = ExpectedData<0x81, 'N'>("The answer is: %s");
401*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(result.size(), message_size);
402*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(result.data(), buffer_, result.size()), 0);
403*61c4878aSAndroid Build Coastguard Worker }
404*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,Domain_String)405*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, Domain_String) {
406*61c4878aSAndroid Build Coastguard Worker   size_t message_size = sizeof(buffer_);
407*61c4878aSAndroid Build Coastguard Worker 
408*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER_DOMAIN(
409*61c4878aSAndroid Build Coastguard Worker       "TEST_DOMAIN", buffer_, &message_size, "The answer was: %s", "5432!");
410*61c4878aSAndroid Build Coastguard Worker   constexpr std::array<uint8_t, 10> expected =
411*61c4878aSAndroid Build Coastguard Worker       ExpectedData<5, '5', '4', '3', '2', '!'>("The answer was: %s");
412*61c4878aSAndroid Build Coastguard Worker 
413*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(expected.size(), message_size);
414*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
415*61c4878aSAndroid Build Coastguard Worker }
416*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,Mask)417*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, Mask) {
418*61c4878aSAndroid Build Coastguard Worker   size_t message_size = sizeof(buffer_);
419*61c4878aSAndroid Build Coastguard Worker 
420*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER_MASK("TEST_DOMAIN",
421*61c4878aSAndroid Build Coastguard Worker                              0x0000FFFF,
422*61c4878aSAndroid Build Coastguard Worker                              buffer_,
423*61c4878aSAndroid Build Coastguard Worker                              &message_size,
424*61c4878aSAndroid Build Coastguard Worker                              "The answer was: %s",
425*61c4878aSAndroid Build Coastguard Worker                              "5432!");
426*61c4878aSAndroid Build Coastguard Worker   constexpr std::array<uint8_t, 10> expected =
427*61c4878aSAndroid Build Coastguard Worker       ExpectedData<5, '5', '4', '3', '2', '!'>("The answer was: %s",
428*61c4878aSAndroid Build Coastguard Worker                                                0x0000FFFF);
429*61c4878aSAndroid Build Coastguard Worker 
430*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(expected.size(), message_size);
431*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
432*61c4878aSAndroid Build Coastguard Worker }
433*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,TruncateArgs)434*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, TruncateArgs) {
435*61c4878aSAndroid Build Coastguard Worker   // Args that can't fit are dropped completely
436*61c4878aSAndroid Build Coastguard Worker   size_t message_size = 6;
437*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_,
438*61c4878aSAndroid Build Coastguard Worker                         &message_size,
439*61c4878aSAndroid Build Coastguard Worker                         "%u %d",
440*61c4878aSAndroid Build Coastguard Worker                         static_cast<uint8_t>(0b0010'1010u),
441*61c4878aSAndroid Build Coastguard Worker                         0xffffff);
442*61c4878aSAndroid Build Coastguard Worker 
443*61c4878aSAndroid Build Coastguard Worker   constexpr std::array<uint8_t, 5> expected =
444*61c4878aSAndroid Build Coastguard Worker       ExpectedData<0b0101'0100u>("%u %d");
445*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(expected.size(), message_size);
446*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
447*61c4878aSAndroid Build Coastguard Worker }
448*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,NoRoomForToken)449*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, NoRoomForToken) {
450*61c4878aSAndroid Build Coastguard Worker   // Nothing is written if there isn't room for the token.
451*61c4878aSAndroid Build Coastguard Worker   std::memset(buffer_, '$', sizeof(buffer_));
452*61c4878aSAndroid Build Coastguard Worker   auto is_untouched = [](uint8_t v) { return v == '$'; };
453*61c4878aSAndroid Build Coastguard Worker 
454*61c4878aSAndroid Build Coastguard Worker   size_t message_size = 3;
455*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer: \"%s\"", "5432!");
456*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(0u, message_size);
457*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(std::all_of(buffer_, std::end(buffer_), is_untouched));
458*61c4878aSAndroid Build Coastguard Worker 
459*61c4878aSAndroid Build Coastguard Worker   message_size = 2;
460*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "Jello, world!");
461*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(0u, message_size);
462*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(std::all_of(buffer_, std::end(buffer_), is_untouched));
463*61c4878aSAndroid Build Coastguard Worker 
464*61c4878aSAndroid Build Coastguard Worker   message_size = 1;
465*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "Jello!");
466*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(0u, message_size);
467*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(std::all_of(buffer_, std::end(buffer_), is_untouched));
468*61c4878aSAndroid Build Coastguard Worker 
469*61c4878aSAndroid Build Coastguard Worker   message_size = 0;
470*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "Jello?");
471*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(0u, message_size);
472*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(std::all_of(buffer_, std::end(buffer_), is_untouched));
473*61c4878aSAndroid Build Coastguard Worker }
474*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,CharArray)475*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, CharArray) {
476*61c4878aSAndroid Build Coastguard Worker   size_t message_size = sizeof(buffer_);
477*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, __func__);
478*61c4878aSAndroid Build Coastguard Worker   constexpr auto expected = ExpectedData(__func__);
479*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(expected.size(), message_size);
480*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
481*61c4878aSAndroid Build Coastguard Worker }
482*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,C_StringShortFloat)483*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, C_StringShortFloat) {
484*61c4878aSAndroid Build Coastguard Worker   size_t size = sizeof(buffer_);
485*61c4878aSAndroid Build Coastguard Worker   pw_tokenizer_ToBufferTest_StringShortFloat(buffer_, &size);
486*61c4878aSAndroid Build Coastguard Worker   constexpr std::array<uint8_t, 11> expected =  // clang-format off
487*61c4878aSAndroid Build Coastguard Worker       ExpectedData<1, '1',                 // string '1'
488*61c4878aSAndroid Build Coastguard Worker                    3,                      // -2 (zig-zag encoded)
489*61c4878aSAndroid Build Coastguard Worker                    0x00, 0x00, 0x40, 0x40  // 3.0 in floating point
490*61c4878aSAndroid Build Coastguard Worker                    >(TEST_FORMAT_STRING_SHORT_FLOAT);
491*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(expected.size(), size);  // clang-format on
492*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
493*61c4878aSAndroid Build Coastguard Worker }
494*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,C_SequentialZigZag)495*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, C_SequentialZigZag) {
496*61c4878aSAndroid Build Coastguard Worker   size_t size = sizeof(buffer_);
497*61c4878aSAndroid Build Coastguard Worker   pw_tokenizer_ToBufferTest_SequentialZigZag(buffer_, &size);
498*61c4878aSAndroid Build Coastguard Worker   constexpr std::array<uint8_t, 18> expected =
499*61c4878aSAndroid Build Coastguard Worker       ExpectedData<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13>(
500*61c4878aSAndroid Build Coastguard Worker           TEST_FORMAT_SEQUENTIAL_ZIG_ZAG);
501*61c4878aSAndroid Build Coastguard Worker 
502*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(expected.size(), size);
503*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
504*61c4878aSAndroid Build Coastguard Worker }
505*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,C_Overflow)506*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, C_Overflow) {
507*61c4878aSAndroid Build Coastguard Worker   std::memset(buffer_, '$', sizeof(buffer_));
508*61c4878aSAndroid Build Coastguard Worker 
509*61c4878aSAndroid Build Coastguard Worker   {
510*61c4878aSAndroid Build Coastguard Worker     size_t size = 7;
511*61c4878aSAndroid Build Coastguard Worker     pw_tokenizer_ToBufferTest_Requires8(buffer_, &size);
512*61c4878aSAndroid Build Coastguard Worker     constexpr std::array<uint8_t, 7> expected =
513*61c4878aSAndroid Build Coastguard Worker         ExpectedData<2, 'h', 'i'>(TEST_FORMAT_REQUIRES_8);
514*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(expected.size(), size);
515*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
516*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(buffer_[7], '$');
517*61c4878aSAndroid Build Coastguard Worker   }
518*61c4878aSAndroid Build Coastguard Worker 
519*61c4878aSAndroid Build Coastguard Worker   {
520*61c4878aSAndroid Build Coastguard Worker     size_t size = 8;
521*61c4878aSAndroid Build Coastguard Worker     pw_tokenizer_ToBufferTest_Requires8(buffer_, &size);
522*61c4878aSAndroid Build Coastguard Worker     constexpr std::array<uint8_t, 8> expected =
523*61c4878aSAndroid Build Coastguard Worker         ExpectedData<2, 'h', 'i', 13>(TEST_FORMAT_REQUIRES_8);
524*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(expected.size(), size);
525*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
526*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(buffer_[8], '$');
527*61c4878aSAndroid Build Coastguard Worker   }
528*61c4878aSAndroid Build Coastguard Worker }
529*61c4878aSAndroid Build Coastguard Worker 
530*61c4878aSAndroid Build Coastguard Worker #define MACRO_THAT_CALLS_ANOTHER_MACRO(action) ANOTHER_MACRO(action)
531*61c4878aSAndroid Build Coastguard Worker 
532*61c4878aSAndroid Build Coastguard Worker #define ANOTHER_MACRO(action) action
533*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,AsArgumentToAnotherMacro)534*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, AsArgumentToAnotherMacro) {
535*61c4878aSAndroid Build Coastguard Worker   size_t message_size = sizeof(buffer_);
536*61c4878aSAndroid Build Coastguard Worker   MACRO_THAT_CALLS_ANOTHER_MACRO(
537*61c4878aSAndroid Build Coastguard Worker       PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, __func__));
538*61c4878aSAndroid Build Coastguard Worker   constexpr auto expected = ExpectedData(__func__);
539*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(expected.size(), message_size);
540*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(std::memcmp(expected.data(), buffer_, expected.size()), 0);
541*61c4878aSAndroid Build Coastguard Worker }
542*61c4878aSAndroid Build Coastguard Worker 
543*61c4878aSAndroid Build Coastguard Worker #undef MACRO_THAT_CALLS_ANOTHER_MACRO
544*61c4878aSAndroid Build Coastguard Worker #undef ANOTHER_MACRO
545*61c4878aSAndroid Build Coastguard Worker 
546*61c4878aSAndroid Build Coastguard Worker // Hijack an internal macro to capture the tokenizer domain.
547*61c4878aSAndroid Build Coastguard Worker #undef PW_TOKENIZER_DEFINE_TOKEN
548*61c4878aSAndroid Build Coastguard Worker #define PW_TOKENIZER_DEFINE_TOKEN(token, domain, string) \
549*61c4878aSAndroid Build Coastguard Worker   tokenizer_domain = domain;                             \
550*61c4878aSAndroid Build Coastguard Worker   string_literal = string
551*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,Domain_Default)552*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, Domain_Default) {
553*61c4878aSAndroid Build Coastguard Worker   const char* tokenizer_domain = nullptr;
554*61c4878aSAndroid Build Coastguard Worker   const char* string_literal = nullptr;
555*61c4878aSAndroid Build Coastguard Worker 
556*61c4878aSAndroid Build Coastguard Worker   size_t message_size = sizeof(buffer_);
557*61c4878aSAndroid Build Coastguard Worker 
558*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER(buffer_, &message_size, "The answer is: %s", "5432!");
559*61c4878aSAndroid Build Coastguard Worker 
560*61c4878aSAndroid Build Coastguard Worker   EXPECT_STREQ(tokenizer_domain, PW_TOKENIZER_DEFAULT_DOMAIN);
561*61c4878aSAndroid Build Coastguard Worker   EXPECT_STREQ(string_literal, "The answer is: %s");
562*61c4878aSAndroid Build Coastguard Worker }
563*61c4878aSAndroid Build Coastguard Worker 
TEST_F(TokenizeToBuffer,Domain_Specified)564*61c4878aSAndroid Build Coastguard Worker TEST_F(TokenizeToBuffer, Domain_Specified) {
565*61c4878aSAndroid Build Coastguard Worker   const char* tokenizer_domain = nullptr;
566*61c4878aSAndroid Build Coastguard Worker   const char* string_literal = nullptr;
567*61c4878aSAndroid Build Coastguard Worker 
568*61c4878aSAndroid Build Coastguard Worker   size_t message_size = sizeof(buffer_);
569*61c4878aSAndroid Build Coastguard Worker 
570*61c4878aSAndroid Build Coastguard Worker   PW_TOKENIZE_TO_BUFFER_DOMAIN(
571*61c4878aSAndroid Build Coastguard Worker       "._.", buffer_, &message_size, "The answer is: %s", "5432!");
572*61c4878aSAndroid Build Coastguard Worker 
573*61c4878aSAndroid Build Coastguard Worker   EXPECT_STREQ(tokenizer_domain, "._.");
574*61c4878aSAndroid Build Coastguard Worker   EXPECT_STREQ(string_literal, "The answer is: %s");
575*61c4878aSAndroid Build Coastguard Worker }
576*61c4878aSAndroid Build Coastguard Worker 
577*61c4878aSAndroid Build Coastguard Worker #undef PW_TOKENIZER_DEFINE_TOKEN
578*61c4878aSAndroid Build Coastguard Worker #define PW_TOKENIZER_DEFINE_TOKEN(token, domain, string)                   \
579*61c4878aSAndroid Build Coastguard Worker   static_assert(false,                                                     \
580*61c4878aSAndroid Build Coastguard Worker                 "The internal PW_TOKENIZER_DEFINE_TOKEN was "              \
581*61c4878aSAndroid Build Coastguard Worker                 "repurposed earlier in this test! The macro or any macro " \
582*61c4878aSAndroid Build Coastguard Worker                 "that calls it cannot be used here!")
583*61c4878aSAndroid Build Coastguard Worker 
584*61c4878aSAndroid Build Coastguard Worker }  // namespace
585*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::tokenizer
586