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