1 // Copyright 2021 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 #define PW_LOG_MODULE_NAME "log module name!"
16
17 // Configure the module so that the test runs against known values.
18 #undef PW_LOG_TOKENIZED_LEVEL_BITS
19 #undef PW_LOG_TOKENIZED_MODULE_BITS
20 #undef PW_LOG_TOKENIZED_FLAG_BITS
21 #undef PW_LOG_TOKENIZED_LINE_BITS
22
23 #define PW_LOG_TOKENIZED_LEVEL_BITS 3
24 #define PW_LOG_TOKENIZED_MODULE_BITS 16
25 #define PW_LOG_TOKENIZED_FLAG_BITS 2
26 #define PW_LOG_TOKENIZED_LINE_BITS 11
27
28 #include "pw_log_tokenized/log_tokenized.h"
29
30 #include "pw_log_tokenized/base64.h"
31 #include "pw_log_tokenized_private/test_utils.h"
32 #include "pw_unit_test/framework.h"
33
34 namespace pw::log_tokenized {
35 namespace {
36
TEST(LogTokenized,FormatString_LogModuleName)37 TEST(LogTokenized, FormatString_LogModuleName) {
38 PW_LOG_TOKENIZED_TO_GLOBAL_HANDLER_WITH_PAYLOAD(
39 63, PW_LOG_MODULE_NAME, 1023, "hello %d", 1);
40 EXPECT_STREQ(last_log.format_string,
41 "■msg♦hello %d■module♦log module name!■file♦" __FILE__);
42 }
43
TEST(LogTokenized,FormatString_OtherModuleNames)44 TEST(LogTokenized, FormatString_OtherModuleNames) {
45 PW_LOG_TOKENIZED_TO_GLOBAL_HANDLER_WITH_PAYLOAD(1, "", 1, "goodbye");
46 EXPECT_STREQ(last_log.format_string, "■msg♦goodbye■module♦■file♦" __FILE__);
47
48 PW_LOG_TOKENIZED_TO_GLOBAL_HANDLER_WITH_PAYLOAD(
49 63, "OTHER MODULE!", 123, "goodbye");
50 EXPECT_STREQ(last_log.format_string,
51 "■msg♦goodbye■module♦OTHER MODULE!■file♦" __FILE__);
52 }
53
54 constexpr uintptr_t kModuleToken =
55 PW_TOKENIZER_STRING_TOKEN(PW_LOG_MODULE_NAME) &
56 ((1u << PW_LOG_TOKENIZED_MODULE_BITS) - 1);
57
TEST(LogTokenized,Base64)58 TEST(LogTokenized, Base64) {
59 constexpr uint8_t kBinary[6]{1, 2, 3, 4, 5, 6};
60 constexpr const char* kBase64Expected = "$AQIDBAUG"; // calculated in Python
61
62 InlineBasicString result_1 = PrefixedBase64Encode(as_bytes(span(kBinary)));
63 EXPECT_EQ(result_1, kBase64Expected);
64 EXPECT_EQ(result_1.capacity(), kBase64EncodedBufferSizeBytes);
65
66 InlineBasicString result_2 = PrefixedBase64Encode(kBinary, sizeof(kBinary));
67 EXPECT_EQ(result_2, kBase64Expected);
68
69 InlineBasicString result_3 = PrefixedBase64Encode(
70 reinterpret_cast<const std::byte*>(kBinary), sizeof(kBinary));
71 EXPECT_EQ(result_3, kBase64Expected);
72 }
73
TEST(LogTokenized,LogMetadata_LevelTooLarge_Clamps)74 TEST(LogTokenized, LogMetadata_LevelTooLarge_Clamps) {
75 auto check_metadata = [] {
76 Metadata metadata = Metadata(last_log.metadata);
77 EXPECT_EQ(metadata.level(), 7u);
78 EXPECT_EQ(metadata.flags(), 0u);
79 EXPECT_EQ(metadata.module(), kModuleToken);
80 EXPECT_EQ(metadata.line_number(), 1000u);
81 };
82
83 #line 1000
84 PW_LOG_TOKENIZED_TO_GLOBAL_HANDLER_WITH_PAYLOAD(8, PW_LOG_MODULE_NAME, 0, "");
85 check_metadata();
86
87 pw_log_tokenized_Test_LogMetadata_LevelTooLarge_Clamps();
88 check_metadata();
89 }
90
TEST(LogTokenized,LogMetadata_TooManyFlags_Truncates)91 TEST(LogTokenized, LogMetadata_TooManyFlags_Truncates) {
92 auto check_metadata = [] {
93 Metadata metadata = Metadata(last_log.metadata);
94 EXPECT_EQ(metadata.level(), 1u);
95 EXPECT_EQ(metadata.flags(), 0b11u);
96 EXPECT_EQ(metadata.module(), kModuleToken);
97 EXPECT_EQ(metadata.line_number(), 1100u);
98 };
99
100 // Keep statements on a single line, since GCC and Clang disagree about which
101 // line number to assign to multi-line macros.
102 // clang-format off
103 #line 1100
104 PW_LOG_TOKENIZED_TO_GLOBAL_HANDLER_WITH_PAYLOAD(1, PW_LOG_MODULE_NAME, 0xFFFFFFFF, "hello");
105 // clang-format on
106 check_metadata();
107
108 pw_log_tokenized_Test_LogMetadata_TooManyFlags_Truncates();
109 check_metadata();
110 }
111
TEST(LogTokenized,LogMetadata_VariousValues)112 TEST(LogTokenized, LogMetadata_VariousValues) {
113 auto check_metadata = [] {
114 Metadata metadata = Metadata(last_log.metadata);
115 EXPECT_EQ(metadata.level(), 6u);
116 EXPECT_EQ(metadata.flags(), 3u);
117 EXPECT_EQ(metadata.module(), kModuleToken);
118 EXPECT_EQ(last_log.arg_count, 1u);
119 EXPECT_EQ(metadata.line_number(), 1200u);
120 };
121
122 // clang-format off
123 #line 1200
124 PW_LOG_TOKENIZED_TO_GLOBAL_HANDLER_WITH_PAYLOAD(6, PW_LOG_MODULE_NAME, 3, "hello%s", "?");
125 // clang-format on
126 check_metadata();
127
128 pw_log_tokenized_Test_LogMetadata_LogMetadata_VariousValues();
129 check_metadata();
130 }
131
TEST(LogTokenized,LogMetadata_Zero)132 TEST(LogTokenized, LogMetadata_Zero) {
133 auto check_metadata = [] {
134 Metadata metadata = Metadata(last_log.metadata);
135 EXPECT_EQ(metadata.level(), 0u);
136 EXPECT_EQ(metadata.flags(), 0u);
137 EXPECT_EQ(metadata.module(), kModuleToken);
138 EXPECT_EQ(last_log.arg_count, 0u);
139 EXPECT_EQ(metadata.line_number(), 1300u);
140 };
141
142 #line 1300
143 PW_LOG_TOKENIZED_TO_GLOBAL_HANDLER_WITH_PAYLOAD(0, PW_LOG_MODULE_NAME, 0, "");
144 check_metadata();
145
146 pw_log_tokenized_Test_LogMetadata_LogMetadata_Zero();
147 check_metadata();
148 }
149
TEST(LogTokenized,LogMetadata_MaxValues)150 TEST(LogTokenized, LogMetadata_MaxValues) {
151 #line 2047
152 PW_LOG_TOKENIZED_TO_GLOBAL_HANDLER_WITH_PAYLOAD(7, "name", 3, "hello %d", 1);
153
154 Metadata metadata = Metadata(last_log.metadata);
155 EXPECT_EQ(metadata.line_number(), 2047u);
156 EXPECT_EQ(metadata.level(), 7u);
157 EXPECT_EQ(metadata.flags(), 3u);
158 EXPECT_EQ(metadata.module(),
159 PW_TOKENIZER_STRING_TOKEN("name") &
160 ((1u << PW_LOG_TOKENIZED_MODULE_BITS) - 1));
161 EXPECT_EQ(last_log.arg_count, 1u);
162 }
163
TEST(LogTokenized,LogMetadata_LineNumberTooLarge_IsZero)164 TEST(LogTokenized, LogMetadata_LineNumberTooLarge_IsZero) {
165 #line 2048 // At 11 bits, the largest representable line is 2047
166 PW_LOG_TOKENIZED_TO_GLOBAL_HANDLER_WITH_PAYLOAD(
167 7, PW_LOG_MODULE_NAME, 3, "hello %d", 1);
168 EXPECT_EQ(Metadata(last_log.metadata).line_number(), 0u);
169
170 #line 2049
171 PW_LOG_TOKENIZED_TO_GLOBAL_HANDLER_WITH_PAYLOAD(
172 7, PW_LOG_MODULE_NAME, 3, "hello %d", 1);
173 EXPECT_EQ(Metadata(last_log.metadata).line_number(), 0u);
174
175 #line 99999
176 PW_LOG_TOKENIZED_TO_GLOBAL_HANDLER_WITH_PAYLOAD(
177 7, PW_LOG_MODULE_NAME, 3, "hello %d", 1);
178 EXPECT_EQ(Metadata(last_log.metadata).line_number(), 0u);
179 }
180
181 } // namespace
182 } // namespace pw::log_tokenized
183