xref: /aosp_15_r20/external/pigweed/pw_log/proto_utils_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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 #include "pw_log/proto_utils.h"
16 
17 #include "pw_bytes/span.h"
18 #include "pw_containers/algorithm.h"
19 #include "pw_log/levels.h"
20 #include "pw_log/proto/log.pwpb.h"
21 #include "pw_protobuf/bytes_utils.h"
22 #include "pw_protobuf/decoder.h"
23 #include "pw_unit_test/framework.h"
24 
25 namespace pw::log {
26 namespace {
27 
VerifyTokenizedLogEntry(pw::protobuf::Decoder & entry_decoder,pw::log_tokenized::Metadata expected_metadata,ConstByteSpan expected_tokenized_data,const int64_t expected_timestamp,ConstByteSpan expected_thread_name)28 void VerifyTokenizedLogEntry(pw::protobuf::Decoder& entry_decoder,
29                              pw::log_tokenized::Metadata expected_metadata,
30                              ConstByteSpan expected_tokenized_data,
31                              const int64_t expected_timestamp,
32                              ConstByteSpan expected_thread_name) {
33   ConstByteSpan tokenized_data;
34   EXPECT_TRUE(entry_decoder.Next().ok());  // message [tokenized]
35   EXPECT_EQ(entry_decoder.FieldNumber(),
36             static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kMessage));
37   EXPECT_TRUE(entry_decoder.ReadBytes(&tokenized_data).ok());
38   EXPECT_TRUE(std::memcmp(tokenized_data.data(),
39                           expected_tokenized_data.data(),
40                           expected_tokenized_data.size()) == 0);
41 
42   uint32_t line_level;
43   EXPECT_TRUE(entry_decoder.Next().ok());  // line_level
44   EXPECT_EQ(entry_decoder.FieldNumber(),
45             static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kLineLevel));
46   EXPECT_TRUE(entry_decoder.ReadUint32(&line_level).ok());
47 
48   uint32_t line_number;
49   uint8_t level;
50   std::tie(line_number, level) = UnpackLineLevel(line_level);
51   EXPECT_EQ(expected_metadata.level(), level);
52   EXPECT_EQ(expected_metadata.line_number(), line_number);
53 
54   if (expected_metadata.flags() != 0) {
55     uint32_t flags;
56     EXPECT_TRUE(entry_decoder.Next().ok());  // flags
57     EXPECT_EQ(entry_decoder.FieldNumber(),
58               static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kFlags));
59     EXPECT_TRUE(entry_decoder.ReadUint32(&flags).ok());
60     EXPECT_EQ(expected_metadata.flags(), flags);
61   }
62 
63   int64_t timestamp;
64   EXPECT_TRUE(entry_decoder.Next().ok());  // timestamp
65   EXPECT_TRUE(
66       entry_decoder.FieldNumber() ==
67           static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kTimestamp) ||
68       entry_decoder.FieldNumber() ==
69           static_cast<uint32_t>(
70               log::pwpb::LogEntry::Fields::kTimeSinceLastEntry));
71   EXPECT_TRUE(entry_decoder.ReadInt64(&timestamp).ok());
72   EXPECT_EQ(expected_timestamp, timestamp);
73 
74   if (expected_metadata.module() != 0) {
75     EXPECT_TRUE(entry_decoder.Next().ok());  // module name
76     EXPECT_EQ(entry_decoder.FieldNumber(),
77               static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kModule));
78     const Result<uint32_t> module =
79         protobuf::DecodeBytesToUint32(entry_decoder);
80     ASSERT_TRUE(module.ok());
81     EXPECT_EQ(expected_metadata.module(), module.value());
82   }
83 
84   if (!expected_thread_name.empty()) {
85     ConstByteSpan tokenized_thread_name;
86     EXPECT_TRUE(entry_decoder.Next().ok());  // thread [tokenized]
87     EXPECT_EQ(entry_decoder.FieldNumber(),
88               static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kThread));
89     EXPECT_TRUE(entry_decoder.ReadBytes(&tokenized_thread_name).ok());
90     EXPECT_TRUE(std::memcmp(tokenized_thread_name.data(),
91                             expected_thread_name.data(),
92                             expected_thread_name.size()) == 0);
93   }
94 }
95 
VerifyLogEntry(pw::protobuf::Decoder & entry_decoder,int expected_level,unsigned int expected_flags,std::string_view expected_module,std::string_view expected_thread_name,std::string_view expected_file_name,int expected_line_number,int64_t expected_ticks_since_epoch,std::string_view expected_message)96 void VerifyLogEntry(pw::protobuf::Decoder& entry_decoder,
97                     int expected_level,
98                     unsigned int expected_flags,
99                     std::string_view expected_module,
100                     std::string_view expected_thread_name,
101                     std::string_view expected_file_name,
102                     int expected_line_number,
103                     int64_t expected_ticks_since_epoch,
104                     std::string_view expected_message) {
105   std::string_view message;
106   EXPECT_TRUE(entry_decoder.Next().ok());  // message
107   EXPECT_EQ(entry_decoder.FieldNumber(),
108             static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kMessage));
109   EXPECT_TRUE(entry_decoder.ReadString(&message).ok());
110   EXPECT_TRUE(pw::containers::Equal(message, expected_message));
111 
112   uint32_t line_level;
113   EXPECT_TRUE(entry_decoder.Next().ok());  // line_level
114   EXPECT_EQ(entry_decoder.FieldNumber(),
115             static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kLineLevel));
116   EXPECT_TRUE(entry_decoder.ReadUint32(&line_level).ok());
117   uint32_t line_number;
118   uint8_t level;
119   std::tie(line_number, level) = UnpackLineLevel(line_level);
120   EXPECT_EQ(static_cast<unsigned int>(expected_line_number), line_number);
121   EXPECT_EQ(expected_level, level);
122 
123   if (expected_flags != 0) {
124     uint32_t flags;
125     EXPECT_TRUE(entry_decoder.Next().ok());  // flags
126     EXPECT_EQ(entry_decoder.FieldNumber(),
127               static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kFlags));
128     EXPECT_TRUE(entry_decoder.ReadUint32(&flags).ok());
129     EXPECT_EQ(expected_flags, flags);
130   }
131 
132   int64_t timestamp;
133   EXPECT_TRUE(entry_decoder.Next().ok());  // timestamp
134   EXPECT_TRUE(
135       entry_decoder.FieldNumber() ==
136           static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kTimestamp) ||
137       entry_decoder.FieldNumber() ==
138           static_cast<uint32_t>(
139               log::pwpb::LogEntry::Fields::kTimeSinceLastEntry));
140   EXPECT_TRUE(entry_decoder.ReadInt64(&timestamp).ok());
141   EXPECT_EQ(expected_ticks_since_epoch, timestamp);
142 
143   if (!expected_module.empty()) {
144     std::string_view module_name;
145     EXPECT_TRUE(entry_decoder.Next().ok());  // module
146     EXPECT_EQ(entry_decoder.FieldNumber(),
147               static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kModule));
148     EXPECT_TRUE(entry_decoder.ReadString(&module_name).ok());
149     EXPECT_TRUE(pw::containers::Equal(module_name, expected_module));
150   }
151 
152   if (!expected_file_name.empty()) {
153     std::string_view file_name;
154     EXPECT_TRUE(entry_decoder.Next().ok());  // file
155     EXPECT_EQ(entry_decoder.FieldNumber(),
156               static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kFile));
157     EXPECT_TRUE(entry_decoder.ReadString(&file_name).ok());
158     EXPECT_TRUE(pw::containers::Equal(file_name, expected_file_name));
159   }
160 
161   if (!expected_thread_name.empty()) {
162     std::string_view thread_name;
163     EXPECT_TRUE(entry_decoder.Next().ok());  // file
164     EXPECT_EQ(entry_decoder.FieldNumber(),
165               static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kThread));
166     EXPECT_TRUE(entry_decoder.ReadString(&thread_name).ok());
167     EXPECT_TRUE(pw::containers::Equal(thread_name, expected_thread_name));
168   }
169 }
170 
TEST(UtilsTest,LineLevelPacking)171 TEST(UtilsTest, LineLevelPacking) {
172   constexpr uint8_t kExpectedLevel = PW_LOG_LEVEL_ERROR;
173   constexpr uint32_t kExpectedLine = 1234567;
174   constexpr uint32_t kExpectedLineLevel =
175       (kExpectedLine << PW_LOG_LEVEL_BITS) |
176       (kExpectedLevel & PW_LOG_LEVEL_BITMASK);
177 
178   EXPECT_EQ(kExpectedLineLevel, PackLineLevel(kExpectedLine, kExpectedLevel));
179 }
180 
TEST(UtilsTest,LineLevelUnpacking)181 TEST(UtilsTest, LineLevelUnpacking) {
182   constexpr uint8_t kExpectedLevel = PW_LOG_LEVEL_ERROR;
183   constexpr uint32_t kExpectedLine = 1234567;
184   constexpr uint32_t kExpectedLineLevel =
185       (kExpectedLine << PW_LOG_LEVEL_BITS) |
186       (kExpectedLevel & PW_LOG_LEVEL_BITMASK);
187 
188   uint32_t line_number;
189   uint8_t level;
190   std::tie(line_number, level) = UnpackLineLevel(kExpectedLineLevel);
191 
192   EXPECT_EQ(kExpectedLine, line_number);
193   EXPECT_EQ(kExpectedLevel, level);
194 }
195 
TEST(UtilsTest,LineLevelPackAndUnpack)196 TEST(UtilsTest, LineLevelPackAndUnpack) {
197   constexpr uint8_t kExpectedLevel = PW_LOG_LEVEL_ERROR;
198   constexpr uint32_t kExpectedLine = 1234567;
199 
200   uint32_t line_number;
201   uint8_t level;
202   std::tie(line_number, level) =
203       UnpackLineLevel(PackLineLevel(kExpectedLine, kExpectedLevel));
204 
205   EXPECT_EQ(kExpectedLine, line_number);
206   EXPECT_EQ(kExpectedLevel, level);
207 }
208 
TEST(UtilsTest,EncodeTokenizedLog)209 TEST(UtilsTest, EncodeTokenizedLog) {
210   constexpr std::byte kTokenizedData[1] = {std::byte(0x01)};
211   constexpr int64_t kExpectedTimestamp = 1;
212   constexpr std::byte kExpectedThreadName[1] = {std::byte(0x02)};
213   std::byte encode_buffer[32];
214 
215   pw::log_tokenized::Metadata metadata =
216       pw::log_tokenized::Metadata::Set<1, 2, 3, 4>();
217 
218   Result<ConstByteSpan> result = EncodeTokenizedLog(metadata,
219                                                     kTokenizedData,
220                                                     kExpectedTimestamp,
221                                                     kExpectedThreadName,
222                                                     encode_buffer);
223   EXPECT_TRUE(result.ok());
224 
225   pw::protobuf::Decoder log_decoder(result.value());
226   VerifyTokenizedLogEntry(log_decoder,
227                           metadata,
228                           kTokenizedData,
229                           kExpectedTimestamp,
230                           kExpectedThreadName);
231 
232   result = EncodeTokenizedLog(metadata,
233                               reinterpret_cast<const uint8_t*>(kTokenizedData),
234                               sizeof(kTokenizedData),
235                               kExpectedTimestamp,
236                               kExpectedThreadName,
237                               encode_buffer);
238   EXPECT_TRUE(result.ok());
239 
240   log_decoder.Reset(result.value());
241   VerifyTokenizedLogEntry(log_decoder,
242                           metadata,
243                           kTokenizedData,
244                           kExpectedTimestamp,
245                           kExpectedThreadName);
246 }
247 
TEST(UtilsTest,EncodeTokenizedLog_EmptyFlags)248 TEST(UtilsTest, EncodeTokenizedLog_EmptyFlags) {
249   constexpr std::byte kTokenizedData[1] = {std::byte(0x01)};
250   constexpr int64_t kExpectedTimestamp = 1;
251   constexpr std::byte kExpectedThreadName[1] = {std::byte(0x02)};
252   std::byte encode_buffer[32];
253 
254   // Create an empty flags set.
255   pw::log_tokenized::Metadata metadata =
256       pw::log_tokenized::Metadata::Set<1, 2, 0, 4>();
257 
258   Result<ConstByteSpan> result = EncodeTokenizedLog(metadata,
259                                                     kTokenizedData,
260                                                     kExpectedTimestamp,
261                                                     kExpectedThreadName,
262                                                     encode_buffer);
263   EXPECT_TRUE(result.ok());
264 
265   pw::protobuf::Decoder log_decoder(result.value());
266   VerifyTokenizedLogEntry(log_decoder,
267                           metadata,
268                           kTokenizedData,
269                           kExpectedTimestamp,
270                           kExpectedThreadName);
271 }
272 
TEST(UtilsTest,EncodeTokenizedLog_InsufficientSpace)273 TEST(UtilsTest, EncodeTokenizedLog_InsufficientSpace) {
274   constexpr std::byte kTokenizedData[1] = {std::byte(0x01)};
275   constexpr int64_t kExpectedTimestamp = 1;
276   constexpr std::byte kExpectedThreadName[1] = {std::byte(0x02)};
277   std::byte encode_buffer[1];
278 
279   pw::log_tokenized::Metadata metadata =
280       pw::log_tokenized::Metadata::Set<1, 2, 3, 4>();
281 
282   Result<ConstByteSpan> result = EncodeTokenizedLog(metadata,
283                                                     kTokenizedData,
284                                                     kExpectedTimestamp,
285                                                     kExpectedThreadName,
286                                                     encode_buffer);
287   EXPECT_TRUE(result.status().IsResourceExhausted());
288 }
289 
TEST(UtilsTest,EncodeLog)290 TEST(UtilsTest, EncodeLog) {
291   constexpr int kExpectedLevel = PW_LOG_LEVEL_INFO;
292   constexpr unsigned int kExpectedFlags = 2;
293   constexpr std::string_view kExpectedModule("TST");
294   constexpr std::string_view kExpectedThread("thread");
295   constexpr std::string_view kExpectedFile("proto_test.cc");
296   constexpr int kExpectedLine = 14;
297   constexpr int64_t kExpectedTimestamp = 1;
298   constexpr std::string_view kExpectedMessage("msg");
299   std::byte encode_buffer[64];
300 
301   Result<ConstByteSpan> result = EncodeLog(kExpectedLevel,
302                                            kExpectedFlags,
303                                            kExpectedModule,
304                                            kExpectedThread,
305                                            kExpectedFile,
306                                            kExpectedLine,
307                                            kExpectedTimestamp,
308                                            kExpectedMessage,
309                                            encode_buffer);
310   EXPECT_TRUE(result.ok());
311 
312   pw::protobuf::Decoder log_decoder(result.value());
313   VerifyLogEntry(log_decoder,
314                  kExpectedLevel,
315                  kExpectedFlags,
316                  kExpectedModule,
317                  kExpectedThread,
318                  kExpectedFile,
319                  kExpectedLine,
320                  kExpectedTimestamp,
321                  kExpectedMessage);
322 }
323 
TEST(UtilsTest,EncodeLog_EmptyFlags)324 TEST(UtilsTest, EncodeLog_EmptyFlags) {
325   constexpr int kExpectedLevel = PW_LOG_LEVEL_INFO;
326   constexpr unsigned int kExpectedFlags = 0;
327   constexpr std::string_view kExpectedModule("TST");
328   constexpr std::string_view kExpectedThread("thread");
329   constexpr std::string_view kExpectedFile("proto_test.cc");
330   constexpr int kExpectedLine = 14;
331   constexpr int64_t kExpectedTimestamp = 1;
332   constexpr std::string_view kExpectedMessage("msg");
333   std::byte encode_buffer[64];
334 
335   Result<ConstByteSpan> result = EncodeLog(kExpectedLevel,
336                                            kExpectedFlags,
337                                            kExpectedModule,
338                                            kExpectedThread,
339                                            kExpectedFile,
340                                            kExpectedLine,
341                                            kExpectedTimestamp,
342                                            kExpectedMessage,
343                                            encode_buffer);
344   EXPECT_TRUE(result.ok());
345 
346   pw::protobuf::Decoder log_decoder(result.value());
347   VerifyLogEntry(log_decoder,
348                  kExpectedLevel,
349                  kExpectedFlags,
350                  kExpectedModule,
351                  kExpectedThread,
352                  kExpectedFile,
353                  kExpectedLine,
354                  kExpectedTimestamp,
355                  kExpectedMessage);
356 }
357 
TEST(UtilsTest,EncodeLog_EmptyFile)358 TEST(UtilsTest, EncodeLog_EmptyFile) {
359   constexpr int kExpectedLevel = PW_LOG_LEVEL_INFO;
360   constexpr unsigned int kExpectedFlags = 0;
361   constexpr std::string_view kExpectedModule("TST");
362   constexpr std::string_view kExpectedThread("thread");
363   constexpr std::string_view kExpectedFile;
364   constexpr int kExpectedLine = 14;
365   constexpr int64_t kExpectedTimestamp = 1;
366   constexpr std::string_view kExpectedMessage("msg");
367   std::byte encode_buffer[64];
368 
369   Result<ConstByteSpan> result = EncodeLog(kExpectedLevel,
370                                            kExpectedFlags,
371                                            kExpectedModule,
372                                            kExpectedThread,
373                                            kExpectedFile,
374                                            kExpectedLine,
375                                            kExpectedTimestamp,
376                                            kExpectedMessage,
377                                            encode_buffer);
378   EXPECT_TRUE(result.ok());
379 
380   pw::protobuf::Decoder log_decoder(result.value());
381   VerifyLogEntry(log_decoder,
382                  kExpectedLevel,
383                  kExpectedFlags,
384                  kExpectedModule,
385                  kExpectedThread,
386                  kExpectedFile,
387                  kExpectedLine,
388                  kExpectedTimestamp,
389                  kExpectedMessage);
390 }
391 
TEST(UtilsTest,EncodeLog_EmptyModule)392 TEST(UtilsTest, EncodeLog_EmptyModule) {
393   constexpr int kExpectedLevel = PW_LOG_LEVEL_INFO;
394   constexpr unsigned int kExpectedFlags = 3;
395   constexpr std::string_view kExpectedModule;
396   constexpr std::string_view kExpectedThread("thread");
397   constexpr std::string_view kExpectedFile("test.cc");
398   constexpr int kExpectedLine = 14;
399   constexpr int64_t kExpectedTimestamp = 1;
400   constexpr std::string_view kExpectedMessage("msg");
401   std::byte encode_buffer[64];
402 
403   Result<ConstByteSpan> result = EncodeLog(kExpectedLevel,
404                                            kExpectedFlags,
405                                            kExpectedModule,
406                                            kExpectedThread,
407                                            kExpectedFile,
408                                            kExpectedLine,
409                                            kExpectedTimestamp,
410                                            kExpectedMessage,
411                                            encode_buffer);
412   EXPECT_TRUE(result.ok());
413 
414   pw::protobuf::Decoder log_decoder(result.value());
415   VerifyLogEntry(log_decoder,
416                  kExpectedLevel,
417                  kExpectedFlags,
418                  kExpectedModule,
419                  kExpectedThread,
420                  kExpectedFile,
421                  kExpectedLine,
422                  kExpectedTimestamp,
423                  kExpectedMessage);
424 }
425 
TEST(UtilsTest,EncodeLog_EmptyThread)426 TEST(UtilsTest, EncodeLog_EmptyThread) {
427   constexpr int kExpectedLevel = PW_LOG_LEVEL_INFO;
428   constexpr unsigned int kExpectedFlags = 2;
429   constexpr std::string_view kExpectedModule("TST");
430   constexpr std::string_view kExpectedThread;
431   constexpr std::string_view kExpectedFile("proto_test.cc");
432   constexpr int kExpectedLine = 14;
433   constexpr int64_t kExpectedTimestamp = 1;
434   constexpr std::string_view kExpectedMessage("msg");
435   std::byte encode_buffer[64];
436 
437   Result<ConstByteSpan> result = EncodeLog(kExpectedLevel,
438                                            kExpectedFlags,
439                                            kExpectedModule,
440                                            kExpectedThread,
441                                            kExpectedFile,
442                                            kExpectedLine,
443                                            kExpectedTimestamp,
444                                            kExpectedMessage,
445                                            encode_buffer);
446   EXPECT_TRUE(result.ok());
447 
448   pw::protobuf::Decoder log_decoder(result.value());
449   VerifyLogEntry(log_decoder,
450                  kExpectedLevel,
451                  kExpectedFlags,
452                  kExpectedModule,
453                  kExpectedThread,
454                  kExpectedFile,
455                  kExpectedLine,
456                  kExpectedTimestamp,
457                  kExpectedMessage);
458 }
459 
TEST(UtilsTest,EncodeLog_EmptyMessage)460 TEST(UtilsTest, EncodeLog_EmptyMessage) {
461   constexpr int kExpectedLevel = PW_LOG_LEVEL_INFO;
462   constexpr unsigned int kExpectedFlags = 0;
463   constexpr std::string_view kExpectedModule;
464   constexpr std::string_view kExpectedThread;
465   constexpr std::string_view kExpectedFile;
466   constexpr int kExpectedLine = 14;
467   constexpr int64_t kExpectedTimestamp = 1;
468   constexpr std::string_view kExpectedMessage;
469   std::byte encode_buffer[64];
470 
471   Result<ConstByteSpan> result = EncodeLog(kExpectedLevel,
472                                            kExpectedFlags,
473                                            kExpectedModule,
474                                            kExpectedThread,
475                                            kExpectedFile,
476                                            kExpectedLine,
477                                            kExpectedTimestamp,
478                                            kExpectedMessage,
479                                            encode_buffer);
480 
481   EXPECT_TRUE(result.status().IsInvalidArgument());
482 }
483 
TEST(UtilsTest,EncodeLog_InsufficientSpace)484 TEST(UtilsTest, EncodeLog_InsufficientSpace) {
485   constexpr int kExpectedLevel = PW_LOG_LEVEL_INFO;
486   constexpr unsigned int kExpectedFlags = 0;
487   constexpr std::string_view kExpectedModule;
488   constexpr std::string_view kExpectedThread;
489   constexpr std::string_view kExpectedFile;
490   constexpr int kExpectedLine = 14;
491   constexpr int64_t kExpectedTimestamp = 1;
492   constexpr std::string_view kExpectedMessage("msg");
493   std::byte encode_buffer[1];
494 
495   Result<ConstByteSpan> result = EncodeLog(kExpectedLevel,
496                                            kExpectedFlags,
497                                            kExpectedModule,
498                                            kExpectedThread,
499                                            kExpectedFile,
500                                            kExpectedLine,
501                                            kExpectedTimestamp,
502                                            kExpectedMessage,
503                                            encode_buffer);
504 
505   EXPECT_TRUE(result.status().IsResourceExhausted());
506 }
507 
508 }  // namespace
509 }  // namespace pw::log
510