| // Copyright 2023 The Pigweed Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| // use this file except in compliance with the License. You may obtain a copy of |
| // the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| // License for the specific language governing permissions and limitations under |
| // the License. |
| |
| // This is a test of using pw_tokenizer in C99. It can be compiled outside of |
| // the GN build by adding a main() function that calls RunTestAndReturnPassed() |
| // and invoking the compiler as follows: |
| /* |
| gcc -std=c99 -Wall -Wextra \ |
| -Ipw_assert/public \ |
| -Ipw_assert/print_and_abort_check_public_overrides \ |
| -Ipw_containers/public \ |
| -Ipw_polyfill/public \ |
| -Ipw_preprocessor/public \ |
| -Ipw_tokenizer/public \ |
| -Ipw_varint/public \ |
| pw_tokenizer/tokenize_c99_test.c \ |
| pw_varint/varint_c.c \ |
| pw_containers/inline_var_len_entry_queue.c |
| */ |
| |
| #include <inttypes.h> |
| #include <stdarg.h> |
| #include <stdint.h> |
| #include <string.h> |
| |
| #include "pw_containers/inline_var_len_entry_queue.h" |
| #include "pw_tokenizer/encode_args.h" |
| #include "pw_tokenizer/tokenize.h" |
| #include "pw_varint/varint.h" |
| |
| static_assert(__STDC_VERSION__ == 199901L, |
| "This test should be compiled with -std=c99."); |
| |
| PW_VARIABLE_LENGTH_ENTRY_QUEUE_DECLARE(buffer, 256); |
| |
| // Encodes a tokenized message with any number of int arguments. |
| static void TokenizeIntegersOnly(uint32_t token, int arg_count, ...) { |
| va_list args; |
| va_start(args, arg_count); |
| |
| // Encode the tokenized log to a temporary buffer. |
| uint8_t encoded[32]; |
| memcpy(encoded, &token, sizeof(token)); |
| |
| size_t index = sizeof(token); |
| |
| for (int i = 0; i < arg_count; ++i) { |
| // Encode each int argument. |
| int argument = va_arg(args, uint32_t); |
| |
| // Encode the argument to the buffer |
| index += pw_tokenizer_EncodeInt( |
| argument, &encoded[index], sizeof(encoded) - index); |
| } |
| |
| // Write the encoded log to the ring buffer |
| pw_InlineVarLenEntryQueue_PushOverwrite(buffer, encoded, index); |
| |
| va_end(args); |
| } |
| |
| // Tokenization macro that only handles int arguments. |
| #define TOKENIZE_INTS(format, ...) \ |
| do { \ |
| PW_TOKENIZE_FORMAT_STRING_ANY_ARG_COUNT( \ |
| "tokenize_c99_test", UINT32_MAX, format, __VA_ARGS__); \ |
| TokenizeIntegersOnly(_pw_tokenizer_token, \ |
| PW_FUNCTION_ARG_COUNT(__VA_ARGS__) \ |
| PW_COMMA_ARGS(__VA_ARGS__)); \ |
| } while (0) |
| |
| // C version of the ASSERT_EQ macro that returns a string version of the failing |
| // line. |
| #define ASSERT_EQ(lhs, rhs) \ |
| if ((lhs) != (rhs)) { \ |
| return FILE_LINE ": ASSERT_EQ(" #lhs ", " #rhs ") failed!"; \ |
| } |
| |
| #define FILE_LINE __FILE__ ":" STRINGIFY(__LINE__) |
| #define STRINGIFY(x) _STRINGIFY(x) |
| #define _STRINGIFY(x) #x |
| |
| // This test tokenize a few strings with arguments and checks the contents. |
| // It is called from tokenize_c99_test_entry_point.cc. |
| const char* RunTestAndReturnPassed(void) { |
| TOKENIZE_INTS("Tokenize this with no arguments!"); |
| TOKENIZE_INTS("One arg, one byte: %x", -1); |
| TOKENIZE_INTS("One arg, 5 bytes: %ld", (long)INT32_MAX); |
| TOKENIZE_INTS("Three args, 4 bytes: %d %d %d", 1, 63, 128); |
| |
| ASSERT_EQ(pw_InlineVarLenEntryQueue_Size(buffer), 4u); |
| |
| pw_InlineVarLenEntryQueue_Iterator it = |
| pw_InlineVarLenEntryQueue_Begin(buffer); |
| pw_InlineVarLenEntryQueue_Entry entry = |
| pw_InlineVarLenEntryQueue_GetEntry(&it); |
| |
| ASSERT_EQ(entry.size_1, sizeof(uint32_t) + 0); |
| ASSERT_EQ(entry.size_2, 0u); |
| |
| pw_InlineVarLenEntryQueue_Iterator_Advance(&it); |
| entry = pw_InlineVarLenEntryQueue_GetEntry(&it); |
| ASSERT_EQ(entry.size_1, sizeof(uint32_t) + 1); |
| ASSERT_EQ(entry.size_2, 0u); |
| |
| pw_InlineVarLenEntryQueue_Iterator_Advance(&it); |
| entry = pw_InlineVarLenEntryQueue_GetEntry(&it); |
| ASSERT_EQ(entry.size_1, sizeof(uint32_t) + 5); |
| ASSERT_EQ(entry.size_2, 0u); |
| |
| pw_InlineVarLenEntryQueue_Iterator_Advance(&it); |
| entry = pw_InlineVarLenEntryQueue_GetEntry(&it); |
| ASSERT_EQ(entry.size_1, sizeof(uint32_t) + 4); |
| ASSERT_EQ(entry.size_2, 0u); |
| |
| pw_InlineVarLenEntryQueue_Iterator_Advance(&it); |
| pw_InlineVarLenEntryQueue_Iterator end = |
| pw_InlineVarLenEntryQueue_End(buffer); |
| ASSERT_EQ(pw_InlineVarLenEntryQueue_Iterator_Equal(&it, &end), true); |
| |
| return "passed"; |
| } |