xref: /aosp_15_r20/external/pigweed/pw_log_rpc/test_utils.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2022 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker #include "pw_log_rpc_private/test_utils.h"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include <cstdint>
18*61c4878aSAndroid Build Coastguard Worker 
19*61c4878aSAndroid Build Coastguard Worker #include "pw_bytes/span.h"
20*61c4878aSAndroid Build Coastguard Worker #include "pw_containers/vector.h"
21*61c4878aSAndroid Build Coastguard Worker #include "pw_log/log.h"
22*61c4878aSAndroid Build Coastguard Worker #include "pw_log/proto/log.pwpb.h"
23*61c4878aSAndroid Build Coastguard Worker #include "pw_log_tokenized/metadata.h"
24*61c4878aSAndroid Build Coastguard Worker #include "pw_protobuf/bytes_utils.h"
25*61c4878aSAndroid Build Coastguard Worker #include "pw_protobuf/decoder.h"
26*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
27*61c4878aSAndroid Build Coastguard Worker 
28*61c4878aSAndroid Build Coastguard Worker namespace pw::log_rpc {
29*61c4878aSAndroid Build Coastguard Worker namespace {
VerifyOptionallyTokenizedField(protobuf::Decoder & entry_decoder,log::pwpb::LogEntry::Fields field_number,ConstByteSpan expected_data)30*61c4878aSAndroid Build Coastguard Worker void VerifyOptionallyTokenizedField(protobuf::Decoder& entry_decoder,
31*61c4878aSAndroid Build Coastguard Worker                                     log::pwpb::LogEntry::Fields field_number,
32*61c4878aSAndroid Build Coastguard Worker                                     ConstByteSpan expected_data) {
33*61c4878aSAndroid Build Coastguard Worker   if (expected_data.empty()) {
34*61c4878aSAndroid Build Coastguard Worker     return;
35*61c4878aSAndroid Build Coastguard Worker   }
36*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan tokenized_data;
37*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(entry_decoder.Next(), OkStatus());
38*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(entry_decoder.FieldNumber(), static_cast<uint32_t>(field_number));
39*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(entry_decoder.ReadBytes(&tokenized_data), OkStatus());
40*61c4878aSAndroid Build Coastguard Worker   std::string_view data_as_string(
41*61c4878aSAndroid Build Coastguard Worker       reinterpret_cast<const char*>(tokenized_data.data()),
42*61c4878aSAndroid Build Coastguard Worker       tokenized_data.size());
43*61c4878aSAndroid Build Coastguard Worker   std::string_view expected_data_as_string(
44*61c4878aSAndroid Build Coastguard Worker       reinterpret_cast<const char*>(expected_data.data()),
45*61c4878aSAndroid Build Coastguard Worker       expected_data.size());
46*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(data_as_string, expected_data_as_string);
47*61c4878aSAndroid Build Coastguard Worker }
48*61c4878aSAndroid Build Coastguard Worker }  // namespace
49*61c4878aSAndroid Build Coastguard Worker 
50*61c4878aSAndroid Build Coastguard Worker // Unpacks a `LogEntry` proto buffer to compare it with the expected data and
51*61c4878aSAndroid Build Coastguard Worker // updates the total drop count found.
VerifyLogEntry(protobuf::Decoder & entry_decoder,const TestLogEntry & expected_entry,uint32_t & drop_count_out)52*61c4878aSAndroid Build Coastguard Worker void VerifyLogEntry(protobuf::Decoder& entry_decoder,
53*61c4878aSAndroid Build Coastguard Worker                     const TestLogEntry& expected_entry,
54*61c4878aSAndroid Build Coastguard Worker                     uint32_t& drop_count_out) {
55*61c4878aSAndroid Build Coastguard Worker   VerifyOptionallyTokenizedField(entry_decoder,
56*61c4878aSAndroid Build Coastguard Worker                                  log::pwpb::LogEntry::Fields::kMessage,
57*61c4878aSAndroid Build Coastguard Worker                                  expected_entry.tokenized_data);
58*61c4878aSAndroid Build Coastguard Worker   if (expected_entry.metadata.level()) {
59*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(entry_decoder.Next(), OkStatus());
60*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(entry_decoder.FieldNumber(),
61*61c4878aSAndroid Build Coastguard Worker               static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kLineLevel));
62*61c4878aSAndroid Build Coastguard Worker     uint32_t line_level;
63*61c4878aSAndroid Build Coastguard Worker     ASSERT_TRUE(entry_decoder.ReadUint32(&line_level).ok());
64*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(expected_entry.metadata.level(),
65*61c4878aSAndroid Build Coastguard Worker               line_level & PW_LOG_LEVEL_BITMASK);
66*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(expected_entry.metadata.line_number(),
67*61c4878aSAndroid Build Coastguard Worker               (line_level & ~PW_LOG_LEVEL_BITMASK) >> PW_LOG_LEVEL_BITS);
68*61c4878aSAndroid Build Coastguard Worker   }
69*61c4878aSAndroid Build Coastguard Worker   if (expected_entry.metadata.flags()) {
70*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(entry_decoder.Next(), OkStatus());
71*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(entry_decoder.FieldNumber(),
72*61c4878aSAndroid Build Coastguard Worker               static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kFlags));
73*61c4878aSAndroid Build Coastguard Worker     uint32_t flags;
74*61c4878aSAndroid Build Coastguard Worker     ASSERT_TRUE(entry_decoder.ReadUint32(&flags).ok());
75*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(expected_entry.metadata.flags(), flags);
76*61c4878aSAndroid Build Coastguard Worker   }
77*61c4878aSAndroid Build Coastguard Worker   if (expected_entry.timestamp) {
78*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(entry_decoder.Next(), OkStatus());
79*61c4878aSAndroid Build Coastguard Worker     ASSERT_TRUE(
80*61c4878aSAndroid Build Coastguard Worker         entry_decoder.FieldNumber() ==
81*61c4878aSAndroid Build Coastguard Worker             static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kTimestamp) ||
82*61c4878aSAndroid Build Coastguard Worker         entry_decoder.FieldNumber() ==
83*61c4878aSAndroid Build Coastguard Worker             static_cast<uint32_t>(
84*61c4878aSAndroid Build Coastguard Worker                 log::pwpb::LogEntry::Fields::kTimeSinceLastEntry));
85*61c4878aSAndroid Build Coastguard Worker     int64_t timestamp;
86*61c4878aSAndroid Build Coastguard Worker     ASSERT_TRUE(entry_decoder.ReadInt64(&timestamp).ok());
87*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(expected_entry.timestamp, timestamp);
88*61c4878aSAndroid Build Coastguard Worker   }
89*61c4878aSAndroid Build Coastguard Worker   if (expected_entry.dropped) {
90*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(entry_decoder.Next(), OkStatus());
91*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(entry_decoder.FieldNumber(),
92*61c4878aSAndroid Build Coastguard Worker               static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kDropped));
93*61c4878aSAndroid Build Coastguard Worker     uint32_t dropped = 0;
94*61c4878aSAndroid Build Coastguard Worker     ASSERT_TRUE(entry_decoder.ReadUint32(&dropped).ok());
95*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(expected_entry.dropped, dropped);
96*61c4878aSAndroid Build Coastguard Worker     drop_count_out += dropped;
97*61c4878aSAndroid Build Coastguard Worker   }
98*61c4878aSAndroid Build Coastguard Worker   if (expected_entry.metadata.module()) {
99*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(entry_decoder.Next(), OkStatus());
100*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(entry_decoder.FieldNumber(),
101*61c4878aSAndroid Build Coastguard Worker               static_cast<uint32_t>(log::pwpb::LogEntry::Fields::kModule));
102*61c4878aSAndroid Build Coastguard Worker     const Result<uint32_t> module =
103*61c4878aSAndroid Build Coastguard Worker         protobuf::DecodeBytesToUint32(entry_decoder);
104*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(module.status(), OkStatus());
105*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(expected_entry.metadata.module(), module.value());
106*61c4878aSAndroid Build Coastguard Worker   }
107*61c4878aSAndroid Build Coastguard Worker   VerifyOptionallyTokenizedField(
108*61c4878aSAndroid Build Coastguard Worker       entry_decoder, log::pwpb::LogEntry::Fields::kFile, expected_entry.file);
109*61c4878aSAndroid Build Coastguard Worker   VerifyOptionallyTokenizedField(entry_decoder,
110*61c4878aSAndroid Build Coastguard Worker                                  log::pwpb::LogEntry::Fields::kThread,
111*61c4878aSAndroid Build Coastguard Worker                                  expected_entry.thread);
112*61c4878aSAndroid Build Coastguard Worker }
113*61c4878aSAndroid Build Coastguard Worker 
114*61c4878aSAndroid Build Coastguard Worker // Compares an encoded LogEntry's fields against the expected sequence ID and
115*61c4878aSAndroid Build Coastguard Worker // LogEntries, and updates the total entry and drop counts. Starts comparing at
116*61c4878aSAndroid Build Coastguard Worker // `expected_entries[entries_count_out]`. `expected_entries` must be in the same
117*61c4878aSAndroid Build Coastguard Worker // order that messages were added to the MultiSink.
VerifyLogEntries(protobuf::Decoder & entries_decoder,const Vector<TestLogEntry> & expected_entries,uint32_t expected_first_entry_sequence_id,size_t & entries_count_out,uint32_t & drop_count_out)118*61c4878aSAndroid Build Coastguard Worker void VerifyLogEntries(protobuf::Decoder& entries_decoder,
119*61c4878aSAndroid Build Coastguard Worker                       const Vector<TestLogEntry>& expected_entries,
120*61c4878aSAndroid Build Coastguard Worker                       uint32_t expected_first_entry_sequence_id,
121*61c4878aSAndroid Build Coastguard Worker                       size_t& entries_count_out,
122*61c4878aSAndroid Build Coastguard Worker                       uint32_t& drop_count_out) {
123*61c4878aSAndroid Build Coastguard Worker   size_t entry_index = entries_count_out;
124*61c4878aSAndroid Build Coastguard Worker   while (entries_decoder.Next().ok()) {
125*61c4878aSAndroid Build Coastguard Worker     if (static_cast<log::pwpb::LogEntries::Fields>(
126*61c4878aSAndroid Build Coastguard Worker             entries_decoder.FieldNumber()) ==
127*61c4878aSAndroid Build Coastguard Worker         log::pwpb::LogEntries::Fields::kEntries) {
128*61c4878aSAndroid Build Coastguard Worker       ConstByteSpan entry;
129*61c4878aSAndroid Build Coastguard Worker       EXPECT_EQ(entries_decoder.ReadBytes(&entry), OkStatus());
130*61c4878aSAndroid Build Coastguard Worker       protobuf::Decoder entry_decoder(entry);
131*61c4878aSAndroid Build Coastguard Worker       if (expected_entries.empty()) {
132*61c4878aSAndroid Build Coastguard Worker         break;
133*61c4878aSAndroid Build Coastguard Worker       }
134*61c4878aSAndroid Build Coastguard Worker 
135*61c4878aSAndroid Build Coastguard Worker       ASSERT_LT(entry_index, expected_entries.size());
136*61c4878aSAndroid Build Coastguard Worker 
137*61c4878aSAndroid Build Coastguard Worker       // Keep track of entries and drops respective counts.
138*61c4878aSAndroid Build Coastguard Worker       uint32_t current_drop_count = 0;
139*61c4878aSAndroid Build Coastguard Worker       VerifyLogEntry(
140*61c4878aSAndroid Build Coastguard Worker           entry_decoder, expected_entries[entry_index], current_drop_count);
141*61c4878aSAndroid Build Coastguard Worker       ++entry_index;
142*61c4878aSAndroid Build Coastguard Worker       drop_count_out += current_drop_count;
143*61c4878aSAndroid Build Coastguard Worker       if (current_drop_count == 0) {
144*61c4878aSAndroid Build Coastguard Worker         ++entries_count_out;
145*61c4878aSAndroid Build Coastguard Worker       }
146*61c4878aSAndroid Build Coastguard Worker     } else if (static_cast<log::pwpb::LogEntries::Fields>(
147*61c4878aSAndroid Build Coastguard Worker                    entries_decoder.FieldNumber()) ==
148*61c4878aSAndroid Build Coastguard Worker                log::pwpb::LogEntries::Fields::kFirstEntrySequenceId) {
149*61c4878aSAndroid Build Coastguard Worker       uint32_t first_entry_sequence_id = 0;
150*61c4878aSAndroid Build Coastguard Worker       EXPECT_EQ(entries_decoder.ReadUint32(&first_entry_sequence_id),
151*61c4878aSAndroid Build Coastguard Worker                 OkStatus());
152*61c4878aSAndroid Build Coastguard Worker       EXPECT_EQ(expected_first_entry_sequence_id, first_entry_sequence_id);
153*61c4878aSAndroid Build Coastguard Worker     }
154*61c4878aSAndroid Build Coastguard Worker   }
155*61c4878aSAndroid Build Coastguard Worker }
156*61c4878aSAndroid Build Coastguard Worker 
CountLogEntries(protobuf::Decoder & entries_decoder)157*61c4878aSAndroid Build Coastguard Worker size_t CountLogEntries(protobuf::Decoder& entries_decoder) {
158*61c4878aSAndroid Build Coastguard Worker   size_t entries_found = 0;
159*61c4878aSAndroid Build Coastguard Worker   while (entries_decoder.Next().ok()) {
160*61c4878aSAndroid Build Coastguard Worker     if (static_cast<log::pwpb::LogEntries::Fields>(
161*61c4878aSAndroid Build Coastguard Worker             entries_decoder.FieldNumber()) ==
162*61c4878aSAndroid Build Coastguard Worker         log::pwpb::LogEntries::Fields::kEntries) {
163*61c4878aSAndroid Build Coastguard Worker       ++entries_found;
164*61c4878aSAndroid Build Coastguard Worker     }
165*61c4878aSAndroid Build Coastguard Worker   }
166*61c4878aSAndroid Build Coastguard Worker   return entries_found;
167*61c4878aSAndroid Build Coastguard Worker }
168*61c4878aSAndroid Build Coastguard Worker 
169*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::log_rpc
170