1 // Copyright 2020 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 mostly a compile test to verify that the log backend is able to
16 // compile the constructs promised by the logging facade; and that when run,
17 // there is no crash.
18 //
19 // TODO: b/235289499 - Add verification of the actually logged statements.
20
21 // clang-format off
22 #define PW_LOG_MODULE_NAME "TST"
23 #define PW_LOG_LEVEL PW_LOG_LEVEL_DEBUG
24 #include "pw_log/log.h"
25 #include "pw_log/short.h"
26 #include "pw_log/shorter.h"
27 // clang-format on
28
29 #include "pw_unit_test/framework.h"
30
31 namespace {
32
33 // TODO: b/235291136 - Test unsigned integer logging (32 and 64 bit); test
34 // pointer logging.
35
LoggingFromFunction()36 void LoggingFromFunction() { PW_LOG_INFO("From a function!"); }
37
38 const int N = 3;
39
TEST(BasicLog,DebugLevel)40 TEST(BasicLog, DebugLevel) {
41 PW_LOG_DEBUG("This log statement should be at DEBUG level; no args");
42 for (int i = 0; i < N; ++i) {
43 PW_LOG_DEBUG("Counting: %d", i);
44 }
45 PW_LOG_DEBUG("Here is a string: %s; with another string %s", "foo", "bar");
46 }
47
TEST(BasicLog,InfoLevel)48 TEST(BasicLog, InfoLevel) {
49 PW_LOG_INFO("This log statement should be at INFO level; no args");
50 for (int i = 0; i < N; ++i) {
51 PW_LOG_INFO("Counting: %d", i);
52 }
53 PW_LOG_INFO("Here is a string: %s; with another string %s", "foo", "bar");
54 }
55
TEST(BasicLog,WarnLevel)56 TEST(BasicLog, WarnLevel) {
57 PW_LOG_WARN("This log statement should be at WARN level; no args");
58 for (int i = 0; i < N; ++i) {
59 PW_LOG_WARN("Counting: %d", i);
60 }
61 PW_LOG_WARN("Here is a string: %s; with another string %s", "foo", "bar");
62 }
63
TEST(BasicLog,ErrorLevel)64 TEST(BasicLog, ErrorLevel) {
65 PW_LOG_ERROR("This log statement should be at ERROR level; no args");
66 for (int i = 0; i < N; ++i) {
67 PW_LOG_ERROR("Counting: %d", i);
68 }
69 PW_LOG_ERROR("Here is a string: %s; with another string %s", "foo", "bar");
70 }
71
TEST(BasicLog,CriticalLevel)72 TEST(BasicLog, CriticalLevel) {
73 PW_LOG_CRITICAL("Critical, emergency log. Device should not reboot");
74 }
75
TEST(BasicLog,ManualLevel)76 TEST(BasicLog, ManualLevel) {
77 PW_LOG(PW_LOG_LEVEL_DEBUG,
78 PW_LOG_LEVEL,
79 PW_LOG_MODULE_NAME,
80 0,
81 "A manual DEBUG-level message");
82 PW_LOG(PW_LOG_LEVEL_DEBUG,
83 PW_LOG_LEVEL,
84 PW_LOG_MODULE_NAME,
85 1,
86 "A manual DEBUG-level message; with a flag");
87
88 PW_LOG(PW_LOG_LEVEL_INFO,
89 PW_LOG_LEVEL,
90 PW_LOG_MODULE_NAME,
91 0,
92 "A manual INFO-level message");
93 PW_LOG(PW_LOG_LEVEL_INFO,
94 PW_LOG_LEVEL,
95 PW_LOG_MODULE_NAME,
96 1,
97 "A manual INFO-level message; with a flag");
98
99 PW_LOG(PW_LOG_LEVEL_WARN,
100 PW_LOG_LEVEL,
101 PW_LOG_MODULE_NAME,
102 0,
103 "A manual WARN-level message");
104 PW_LOG(PW_LOG_LEVEL_WARN,
105 PW_LOG_LEVEL,
106 PW_LOG_MODULE_NAME,
107 1,
108 "A manual WARN-level message; with a flag");
109
110 PW_LOG(PW_LOG_LEVEL_ERROR,
111 PW_LOG_LEVEL,
112 PW_LOG_MODULE_NAME,
113 0,
114 "A manual ERROR-level message");
115 PW_LOG(PW_LOG_LEVEL_ERROR,
116 PW_LOG_LEVEL,
117 PW_LOG_MODULE_NAME,
118 1,
119 "A manual ERROR-level message; with a flag");
120
121 PW_LOG(PW_LOG_LEVEL_CRITICAL,
122 PW_LOG_LEVEL,
123 PW_LOG_MODULE_NAME,
124 0,
125 "A manual CRITICAL-level message");
126 PW_LOG(PW_LOG_LEVEL_CRITICAL,
127 PW_LOG_LEVEL,
128 PW_LOG_MODULE_NAME,
129 1,
130 "A manual CRITICAL-level message; with a flag");
131 }
132
TEST(BasicLog,FromAFunction)133 TEST(BasicLog, FromAFunction) { LoggingFromFunction(); }
134
TEST(BasicLog,CustomLogLevels)135 TEST(BasicLog, CustomLogLevels) {
136 // Log levels other than the standard ones work; what each backend does is
137 // implementation defined.
138 PW_LOG(0, PW_LOG_LEVEL, "", 0, "Custom log level: 0");
139 PW_LOG(1, PW_LOG_LEVEL, "", 0, "Custom log level: 1");
140 PW_LOG(2, PW_LOG_LEVEL, "", 0, "Custom log level: 2");
141 PW_LOG(3, PW_LOG_LEVEL, "", 0, "Custom log level: 3");
142 PW_LOG(100, PW_LOG_LEVEL, "", 0, "Custom log level: 100");
143 }
144
145 #define TEST_FAILED_LOG "IF THIS MESSAGE WAS LOGGED, THE TEST FAILED"
146
TEST(BasicLog,FilteringByLevel)147 TEST(BasicLog, FilteringByLevel) {
148 #undef PW_LOG_SKIP_LOGS_WITH_LEVEL_LT
149 #define PW_LOG_SKIP_LOGS_WITH_LEVEL_LT PW_LOG_LEVEL_ERROR
150
151 PW_LOG_DEBUG(TEST_FAILED_LOG);
152 PW_LOG_INFO(TEST_FAILED_LOG);
153 PW_LOG_WARN(TEST_FAILED_LOG);
154
155 PW_LOG_ERROR("This log should appear as error status (and that's good)");
156
157 #undef PW_LOG_SKIP_LOGS_WITH_LEVEL_LT
158 #define PW_LOG_SKIP_LOGS_WITH_LEVEL_LT 0
159 }
160
TEST(BasicLog,FilteringByFlags)161 TEST(BasicLog, FilteringByFlags) {
162 #undef PW_LOG_SKIP_LOGS_WITH_FLAGS
163 #define PW_LOG_SKIP_LOGS_WITH_FLAGS 1
164
165 // Flag is set so these should all get zapped.
166 PW_LOG(
167 PW_LOG_LEVEL_INFO, PW_LOG_LEVEL, PW_LOG_MODULE_NAME, 1, TEST_FAILED_LOG);
168 PW_LOG(
169 PW_LOG_LEVEL_ERROR, PW_LOG_LEVEL, PW_LOG_MODULE_NAME, 1, TEST_FAILED_LOG);
170
171 // However, a different flag bit should still log.
172 PW_LOG(PW_LOG_LEVEL_INFO,
173 PW_LOG_LEVEL,
174 PW_LOG_MODULE_NAME,
175 1 << 1,
176 "This flagged log is intended to appear");
177 PW_LOG(PW_LOG_LEVEL_ERROR,
178 PW_LOG_LEVEL,
179 PW_LOG_MODULE_NAME,
180 1 << 1,
181 "This flagged log is intended to appear");
182
183 #undef PW_LOG_SKIP_LOGS_WITH_FLAGS
184 #define PW_LOG_SKIP_LOGS_WITH_FLAGS 0
185 }
186
TEST(BasicLog,ChangingTheModuleName)187 TEST(BasicLog, ChangingTheModuleName) {
188 #undef PW_LOG_MODULE_NAME
189 #define PW_LOG_MODULE_NAME "PQR"
190 PW_LOG_INFO("This has a custom module name");
191 PW_LOG_INFO("So does this");
192 }
193
TEST(BasicLog,ShortNames)194 TEST(BasicLog, ShortNames) {
195 LOG(PW_LOG_LEVEL_INFO, PW_LOG_LEVEL, PW_LOG_MODULE_NAME, 0, "Shrt lg");
196 LOG_DEBUG("A debug log: %d", 1);
197 LOG_INFO("An info log: %d", 2);
198 LOG_WARN("A warning log: %d", 3);
199 LOG_ERROR("An error log: %d", 4);
200 LOG_CRITICAL("A critical log: %d", 4);
201 }
202
TEST(BasicLog,UltraShortNames)203 TEST(BasicLog, UltraShortNames) {
204 LOG(PW_LOG_LEVEL_INFO, PW_LOG_LEVEL, PW_LOG_MODULE_NAME, 0, "Shrt lg");
205 DBG("A debug log: %d", 1);
206 INF("An info log: %d", 2);
207 WRN("A warning log: %d", 3);
208 ERR("An error log: %d", 4);
209 CRT("A critical log: %d", 4);
210 }
211
212 extern "C" void BasicLogTestPlainC();
213
TEST(BasicLog,FromPlainC)214 TEST(BasicLog, FromPlainC) { BasicLogTestPlainC(); }
215
216 // Test that adding to the format string compiles correctly. If PW_COMMA_ARGS is
217 // used in PW_LOG_INFO and the other wrappers in pw_log/log.h, then these
218 // functions tests fail to compile, because the arguments end up out-of-order.
219
220 #undef PW_LOG
221 #define PW_LOG(level, verbosity, module, flags, message, ...) \
222 DoNothingFakeFunction(module, \
223 "%d/%d/%d: incoming transmission [" message "]", \
224 level, \
225 __LINE__, \
226 flags PW_COMMA_ARGS(__VA_ARGS__))
227
228 void DoNothingFakeFunction(const char*, const char*, ...)
229 PW_PRINTF_FORMAT(2, 3);
230
DoNothingFakeFunction(const char *,const char *,...)231 void DoNothingFakeFunction(const char*, const char*, ...) {}
232
TEST(CustomFormatString,DebugLevel)233 TEST(CustomFormatString, DebugLevel) {
234 PW_LOG_DEBUG("This log statement should be at DEBUG level; no args");
235 for (int i = 0; i < N; ++i) {
236 PW_LOG_DEBUG("Counting: %d", i);
237 }
238 PW_LOG_DEBUG("Here is a string: %s; with another string %s", "foo", "bar");
239 }
240
TEST(CustomFormatString,InfoLevel)241 TEST(CustomFormatString, InfoLevel) {
242 PW_LOG_INFO("This log statement should be at INFO level; no args");
243 for (int i = 0; i < N; ++i) {
244 PW_LOG_INFO("Counting: %d", i);
245 }
246 PW_LOG_INFO("Here is a string: %s; with another string %s", "foo", "bar");
247 }
248
TEST(CustomFormatString,WarnLevel)249 TEST(CustomFormatString, WarnLevel) {
250 PW_LOG_WARN("This log statement should be at WARN level; no args");
251 for (int i = 0; i < N; ++i) {
252 PW_LOG_WARN("Counting: %d", i);
253 }
254 PW_LOG_WARN("Here is a string: %s; with another string %s", "foo", "bar");
255 }
256
TEST(CustomFormatString,ErrorLevel)257 TEST(CustomFormatString, ErrorLevel) {
258 PW_LOG_ERROR("This log statement should be at ERROR level; no args");
259 for (int i = 0; i < N; ++i) {
260 PW_LOG_ERROR("Counting: %d", i);
261 }
262 PW_LOG_ERROR("Here is a string: %s; with another string %s", "foo", "bar");
263 }
264
TEST(CustomFormatString,CriticalLevel)265 TEST(CustomFormatString, CriticalLevel) {
266 PW_LOG_CRITICAL("Critical, emergency log. Device should not reboot");
267 }
268
269 } // namespace
270