xref: /aosp_15_r20/external/perfetto/src/trace_processor/util/debug_annotation_parser_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/trace_processor/util/debug_annotation_parser.h"
18 
19 #include "perfetto/ext/base/string_view.h"
20 #include "perfetto/protozero/scattered_heap_buffer.h"
21 #include "perfetto/trace_processor/ref_counted.h"
22 #include "perfetto/trace_processor/trace_blob.h"
23 #include "perfetto/trace_processor/trace_blob_view.h"
24 #include "protos/perfetto/common/descriptor.pbzero.h"
25 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
26 #include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
27 #include "protos/perfetto/trace/test_event.pbzero.h"
28 #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
29 #include "protos/perfetto/trace/track_event/source_location.pbzero.h"
30 #include "src/protozero/test/example_proto/test_messages.pbzero.h"
31 #include "src/trace_processor/importers/proto/packet_sequence_state_builder.h"
32 #include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
33 #include "src/trace_processor/storage/trace_storage.h"
34 #include "src/trace_processor/test_messages.descriptor.h"
35 #include "src/trace_processor/types/trace_processor_context.h"
36 #include "src/trace_processor/util/interned_message_view.h"
37 #include "src/trace_processor/util/proto_to_args_parser.h"
38 #include "test/gtest_and_gmock.h"
39 
40 #include <sstream>
41 
42 namespace perfetto {
43 namespace trace_processor {
44 namespace util {
45 namespace {
46 
ParseDebugAnnotation(DebugAnnotationParser & parser,protozero::HeapBuffered<protos::pbzero::DebugAnnotation> & msg,ProtoToArgsParser::Delegate & delegate)47 base::Status ParseDebugAnnotation(
48     DebugAnnotationParser& parser,
49     protozero::HeapBuffered<protos::pbzero::DebugAnnotation>& msg,
50     ProtoToArgsParser::Delegate& delegate) {
51   std::vector<uint8_t> data = msg.SerializeAsArray();
52   return parser.Parse(protozero::ConstBytes{data.data(), data.size()},
53                       delegate);
54 }
55 
56 class DebugAnnotationParserTest : public ::testing::Test,
57                                   public ProtoToArgsParser::Delegate {
58  protected:
DebugAnnotationParserTest()59   DebugAnnotationParserTest() { context_.storage.reset(new TraceStorage()); }
60 
args() const61   const std::vector<std::string>& args() const { return args_; }
62 
InternMessage(uint32_t field_id,TraceBlobView message)63   void InternMessage(uint32_t field_id, TraceBlobView message) {
64     state_builder_.InternMessage(field_id, std::move(message));
65   }
66 
67  private:
68   using Key = ProtoToArgsParser::Key;
69 
AddInteger(const Key & key,int64_t value)70   void AddInteger(const Key& key, int64_t value) override {
71     std::stringstream ss;
72     ss << key.flat_key << " " << key.key << " " << value;
73     args_.push_back(ss.str());
74   }
75 
AddUnsignedInteger(const Key & key,uint64_t value)76   void AddUnsignedInteger(const Key& key, uint64_t value) override {
77     std::stringstream ss;
78     ss << key.flat_key << " " << key.key << " " << value;
79     args_.push_back(ss.str());
80   }
81 
AddString(const Key & key,const protozero::ConstChars & value)82   void AddString(const Key& key, const protozero::ConstChars& value) override {
83     std::stringstream ss;
84     ss << key.flat_key << " " << key.key << " " << value.ToStdString();
85     args_.push_back(ss.str());
86   }
87 
AddString(const Key & key,const std::string & value)88   void AddString(const Key& key, const std::string& value) override {
89     std::stringstream ss;
90     ss << key.flat_key << " " << key.key << " " << value;
91     args_.push_back(ss.str());
92   }
93 
AddDouble(const Key & key,double value)94   void AddDouble(const Key& key, double value) override {
95     std::stringstream ss;
96     ss << key.flat_key << " " << key.key << " " << value;
97     args_.push_back(ss.str());
98   }
99 
AddPointer(const Key & key,const void * value)100   void AddPointer(const Key& key, const void* value) override {
101     std::stringstream ss;
102     ss << key.flat_key << " " << key.key << " " << std::hex
103        << reinterpret_cast<uintptr_t>(value) << std::dec;
104     args_.push_back(ss.str());
105   }
106 
AddBoolean(const Key & key,bool value)107   void AddBoolean(const Key& key, bool value) override {
108     std::stringstream ss;
109     ss << key.flat_key << " " << key.key << " " << (value ? "true" : "false");
110     args_.push_back(ss.str());
111   }
112 
AddJson(const Key & key,const protozero::ConstChars & value)113   bool AddJson(const Key& key, const protozero::ConstChars& value) override {
114     std::stringstream ss;
115     ss << key.flat_key << " " << key.key << " " << std::hex
116        << value.ToStdString() << std::dec;
117     args_.push_back(ss.str());
118     return true;
119   }
120 
AddNull(const Key & key)121   void AddNull(const Key& key) override {
122     std::stringstream ss;
123     ss << key.flat_key << " " << key.key << " [NULL]";
124     args_.push_back(ss.str());
125   }
126 
GetArrayEntryIndex(const std::string & array_key)127   size_t GetArrayEntryIndex(const std::string& array_key) final {
128     return array_indices_[array_key];
129   }
130 
IncrementArrayEntryIndex(const std::string & array_key)131   size_t IncrementArrayEntryIndex(const std::string& array_key) final {
132     return ++array_indices_[array_key];
133   }
134 
GetInternedMessageView(uint32_t field_id,uint64_t iid)135   InternedMessageView* GetInternedMessageView(uint32_t field_id,
136                                               uint64_t iid) override {
137     return state_builder_.current_generation()->GetInternedMessageView(field_id,
138                                                                        iid);
139   }
140 
seq_state()141   PacketSequenceStateGeneration* seq_state() final {
142     return state_builder_.current_generation().get();
143   }
144 
145   std::vector<std::string> args_;
146   std::map<std::string, size_t> array_indices_;
147 
148   TraceProcessorContext context_;
149   PacketSequenceStateBuilder state_builder_{&context_};
150 };
151 
152 // This test checks that in when an array is nested inside a dict which is
153 // nested inside an array which is nested inside a dict, flat keys and non-flat
154 // keys are parsed correctly.
TEST_F(DebugAnnotationParserTest,DeeplyNestedDictsAndArrays)155 TEST_F(DebugAnnotationParserTest, DeeplyNestedDictsAndArrays) {
156   protozero::HeapBuffered<protos::pbzero::DebugAnnotation> msg;
157 
158   msg->set_name("root");
159   auto* dict1 = msg->add_dict_entries();
160   dict1->set_name("k1");
161   auto* array1 = dict1->add_array_values();
162   auto* dict2 = array1->add_dict_entries();
163   dict2->set_name("k2");
164   auto* array2 = dict2->add_array_values();
165   array2->set_int_value(42);
166 
167   DescriptorPool pool;
168   auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(),
169                                               kTestMessagesDescriptor.size());
170   EXPECT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
171                            << status.message();
172 
173   ProtoToArgsParser args_parser(pool);
174   DebugAnnotationParser parser(args_parser);
175 
176   status = ParseDebugAnnotation(parser, msg, *this);
177   EXPECT_TRUE(status.ok()) << "DebugAnnotationParser::Parse failed with error: "
178                            << status.message();
179 
180   EXPECT_THAT(args(), testing::ElementsAre("root.k1.k2 root.k1[0].k2[0] 42"));
181 }
182 
183 // This test checks that array indexes are correctly merged across messages.
TEST_F(DebugAnnotationParserTest,MergeArrays)184 TEST_F(DebugAnnotationParserTest, MergeArrays) {
185   protozero::HeapBuffered<protos::pbzero::DebugAnnotation> msg1;
186   msg1->set_name("root");
187   auto* item1 = msg1->add_array_values();
188   item1->set_int_value(1);
189 
190   protozero::HeapBuffered<protos::pbzero::DebugAnnotation> msg2;
191   msg2->set_name("root");
192   auto* item2 = msg1->add_array_values();
193   item2->set_int_value(2);
194 
195   DescriptorPool pool;
196   ProtoToArgsParser args_parser(pool);
197   DebugAnnotationParser parser(args_parser);
198 
199   base::Status status = ParseDebugAnnotation(parser, msg1, *this);
200   EXPECT_TRUE(status.ok()) << "DebugAnnotationParser::Parse failed with error: "
201                            << status.message();
202 
203   status = ParseDebugAnnotation(parser, msg2, *this);
204   EXPECT_TRUE(status.ok()) << "DebugAnnotationParser::Parse failed with error: "
205                            << status.message();
206 
207   EXPECT_THAT(args(), testing::ElementsAre("root root[0] 1", "root root[1] 2"));
208 }
209 
210 // This test checks that nested empty dictionaries / arrays do not cause array
211 // index to be incremented.
TEST_F(DebugAnnotationParserTest,EmptyArrayIndexIsSkipped)212 TEST_F(DebugAnnotationParserTest, EmptyArrayIndexIsSkipped) {
213   protozero::HeapBuffered<protos::pbzero::DebugAnnotation> msg;
214   msg->set_name("root");
215 
216   msg->add_array_values()->set_int_value(1);
217 
218   // Empty item.
219   msg->add_array_values();
220 
221   msg->add_array_values()->set_int_value(3);
222 
223   // Empty dict.
224   msg->add_array_values()->add_dict_entries()->set_name("key1");
225 
226   auto* nested_dict_entry = msg->add_array_values()->add_dict_entries();
227   nested_dict_entry->set_name("key2");
228   nested_dict_entry->set_string_value("value");
229 
230   msg->add_array_values()->set_int_value(5);
231 
232   DescriptorPool pool;
233   ProtoToArgsParser args_parser(pool);
234   DebugAnnotationParser parser(args_parser);
235 
236   base::Status status = ParseDebugAnnotation(parser, msg, *this);
237   EXPECT_TRUE(status.ok()) << "DebugAnnotationParser::Parse failed with error: "
238                            << status.message();
239 
240   EXPECT_THAT(args(), testing::ElementsAre("root root[0] 1", "root root[1] 3",
241                                            "root.key2 root[3].key2 value",
242                                            "root root[4] 5"));
243 }
244 
TEST_F(DebugAnnotationParserTest,NestedArrays)245 TEST_F(DebugAnnotationParserTest, NestedArrays) {
246   protozero::HeapBuffered<protos::pbzero::DebugAnnotation> msg;
247   msg->set_name("root");
248   auto* item1 = msg->add_array_values();
249   item1->add_array_values()->set_int_value(1);
250   item1->add_array_values()->set_int_value(2);
251   auto* item2 = msg->add_array_values();
252   item2->add_array_values()->set_int_value(3);
253   item2->add_array_values()->set_int_value(4);
254 
255   DescriptorPool pool;
256   ProtoToArgsParser args_parser(pool);
257   DebugAnnotationParser parser(args_parser);
258 
259   base::Status status = ParseDebugAnnotation(parser, msg, *this);
260   EXPECT_TRUE(status.ok()) << "DebugAnnotationParser::Parse failed with error: "
261                            << status.message();
262 
263   EXPECT_THAT(args(),
264               testing::ElementsAre("root root[0][0] 1", "root root[0][1] 2",
265                                    "root root[1][0] 3", "root root[1][1] 4"));
266 }
267 
TEST_F(DebugAnnotationParserTest,TypedMessageInsideUntyped)268 TEST_F(DebugAnnotationParserTest, TypedMessageInsideUntyped) {
269   protozero::HeapBuffered<protos::pbzero::DebugAnnotation> msg;
270   msg->set_name("root");
271 
272   protozero::HeapBuffered<protozero::test::protos::pbzero::EveryField> message;
273   message->set_field_string("value");
274 
275   msg->set_proto_type_name(message->GetName());
276   msg->set_proto_value(message.SerializeAsString());
277 
278   DescriptorPool pool;
279   auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(),
280                                               kTestMessagesDescriptor.size());
281   EXPECT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
282                            << status.message();
283 
284   ProtoToArgsParser args_parser(pool);
285   DebugAnnotationParser parser(args_parser);
286 
287   status = ParseDebugAnnotation(parser, msg, *this);
288   EXPECT_TRUE(status.ok()) << "DebugAnnotationParser::Parse failed with error: "
289                            << status.message();
290 
291   EXPECT_THAT(args(), testing::ElementsAre(
292                           "root.field_string root.field_string value"));
293 }
294 
TEST_F(DebugAnnotationParserTest,InternedString)295 TEST_F(DebugAnnotationParserTest, InternedString) {
296   protozero::HeapBuffered<protos::pbzero::DebugAnnotation> msg;
297   msg->set_name("root");
298 
299   protozero::HeapBuffered<protos::pbzero::InternedString> string;
300   string->set_iid(1);
301   string->set_str("foo");
302   std::vector<uint8_t> data_serialized = string.SerializeAsArray();
303 
304   InternMessage(
305       protos::pbzero::InternedData::kDebugAnnotationStringValuesFieldNumber,
306       TraceBlobView(
307           TraceBlob::CopyFrom(data_serialized.data(), data_serialized.size())));
308 
309   msg->set_string_value_iid(1);
310 
311   DescriptorPool pool;
312   ProtoToArgsParser args_parser(pool);
313   DebugAnnotationParser parser(args_parser);
314 
315   auto status = ParseDebugAnnotation(parser, msg, *this);
316   EXPECT_TRUE(status.ok()) << "DebugAnnotationParser::Parse failed with error: "
317                            << status.message();
318 
319   EXPECT_THAT(args(), testing::ElementsAre("root root foo"));
320 }
321 
322 }  // namespace
323 }  // namespace util
324 }  // namespace trace_processor
325 }  // namespace perfetto
326