xref: /aosp_15_r20/external/pigweed/pw_tokenizer/tokenize_c99_test.c (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2023 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 // This is a test of using pw_tokenizer in C99. It can be compiled outside of
16 // the GN build by adding a main() function that calls RunTestAndReturnPassed()
17 // and invoking the compiler as follows:
18 /*
19   gcc -std=c99 -Wall -Wextra \
20       -Ipw_assert/public \
21       -Ipw_assert/print_and_abort_check_public_overrides \
22       -Ipw_containers/public \
23       -Ipw_polyfill/public \
24       -Ipw_preprocessor/public \
25       -Ipw_tokenizer/public \
26       -Ipw_varint/public \
27       pw_tokenizer/tokenize_c99_test.c \
28       pw_varint/varint_c.c \
29       pw_containers/inline_var_len_entry_queue.c
30  */
31 
32 #include <inttypes.h>
33 #include <stdarg.h>
34 #include <stdint.h>
35 #include <string.h>
36 
37 #include "pw_containers/inline_var_len_entry_queue.h"
38 #include "pw_tokenizer/encode_args.h"
39 #include "pw_tokenizer/tokenize.h"
40 #include "pw_varint/varint.h"
41 
42 static_assert(__STDC_VERSION__ == 199901L,
43               "This test should be compiled with -std=c99.");
44 
45 PW_VARIABLE_LENGTH_ENTRY_QUEUE_DECLARE(buffer, 256);
46 
47 // Encodes a tokenized message with any number of int arguments.
TokenizeIntegersOnly(uint32_t token,int arg_count,...)48 static void TokenizeIntegersOnly(uint32_t token, int arg_count, ...) {
49   va_list args;
50   va_start(args, arg_count);
51 
52   // Encode the tokenized log to a temporary buffer.
53   uint8_t encoded[32];
54   memcpy(encoded, &token, sizeof(token));
55 
56   size_t index = sizeof(token);
57 
58   for (int i = 0; i < arg_count; ++i) {
59     // Encode each int argument.
60     int argument = va_arg(args, uint32_t);
61 
62     // Encode the argument to the buffer
63     index += pw_tokenizer_EncodeInt(
64         argument, &encoded[index], sizeof(encoded) - index);
65   }
66 
67   // Write the encoded log to the ring buffer
68   pw_InlineVarLenEntryQueue_PushOverwrite(buffer, encoded, index);
69 
70   va_end(args);
71 }
72 
73 // Tokenization macro that only handles int arguments.
74 #define TOKENIZE_INTS(format, ...)                             \
75   do {                                                         \
76     PW_TOKENIZE_FORMAT_STRING_ANY_ARG_COUNT(                   \
77         "tokenize_c99_test", UINT32_MAX, format, __VA_ARGS__); \
78     TokenizeIntegersOnly(_pw_tokenizer_token,                  \
79                          PW_FUNCTION_ARG_COUNT(__VA_ARGS__)    \
80                              PW_COMMA_ARGS(__VA_ARGS__));      \
81   } while (0)
82 
83 // C version of the ASSERT_EQ macro that returns a string version of the failing
84 // line.
85 #define ASSERT_EQ(lhs, rhs)                                     \
86   if ((lhs) != (rhs)) {                                         \
87     return FILE_LINE ": ASSERT_EQ(" #lhs ", " #rhs ") failed!"; \
88   }
89 
90 #define FILE_LINE __FILE__ ":" STRINGIFY(__LINE__)
91 #define STRINGIFY(x) _STRINGIFY(x)
92 #define _STRINGIFY(x) #x
93 
94 // This test tokenize a few strings with arguments and checks the contents.
95 // It is called from tokenize_c99_test_entry_point.cc.
RunTestAndReturnPassed(void)96 const char* RunTestAndReturnPassed(void) {
97   TOKENIZE_INTS("Tokenize this with no arguments!");
98   TOKENIZE_INTS("One arg, one byte: %x", -1);
99   TOKENIZE_INTS("One arg, 5 bytes: %ld", (long)INT32_MAX);
100   TOKENIZE_INTS("Three args, 4 bytes: %d %d %d", 1, 63, 128);
101 
102   ASSERT_EQ(pw_InlineVarLenEntryQueue_Size(buffer), 4u);
103 
104   pw_InlineVarLenEntryQueue_Iterator it =
105       pw_InlineVarLenEntryQueue_Begin(buffer);
106   pw_InlineVarLenEntryQueue_Entry entry =
107       pw_InlineVarLenEntryQueue_GetEntry(&it);
108 
109   ASSERT_EQ(entry.size_1, sizeof(uint32_t) + 0);
110   ASSERT_EQ(entry.size_2, 0u);
111 
112   pw_InlineVarLenEntryQueue_Iterator_Advance(&it);
113   entry = pw_InlineVarLenEntryQueue_GetEntry(&it);
114   ASSERT_EQ(entry.size_1, sizeof(uint32_t) + 1);
115   ASSERT_EQ(entry.size_2, 0u);
116 
117   pw_InlineVarLenEntryQueue_Iterator_Advance(&it);
118   entry = pw_InlineVarLenEntryQueue_GetEntry(&it);
119   ASSERT_EQ(entry.size_1, sizeof(uint32_t) + 5);
120   ASSERT_EQ(entry.size_2, 0u);
121 
122   pw_InlineVarLenEntryQueue_Iterator_Advance(&it);
123   entry = pw_InlineVarLenEntryQueue_GetEntry(&it);
124   ASSERT_EQ(entry.size_1, sizeof(uint32_t) + 4);
125   ASSERT_EQ(entry.size_2, 0u);
126 
127   pw_InlineVarLenEntryQueue_Iterator_Advance(&it);
128   pw_InlineVarLenEntryQueue_Iterator end =
129       pw_InlineVarLenEntryQueue_End(buffer);
130   ASSERT_EQ(pw_InlineVarLenEntryQueue_Iterator_Equal(&it, &end), true);
131 
132   return "passed";
133 }
134