blob: 2368c6d82542578d24e10cdb5966f1bba5b1d3c7 [file] [log] [blame]
// 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";
}