Alexander Timin | 5a99b5c | 2021-05-11 22:48:07 +0000 | [diff] [blame] | 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/proto_to_args_parser.h" |
| 18 | |
| 19 | #include "perfetto/ext/base/string_view.h" |
| 20 | #include "perfetto/protozero/scattered_heap_buffer.h" |
Primiano Tucci | 3264b59 | 2021-11-08 18:20:51 +0000 | [diff] [blame^] | 21 | #include "perfetto/trace_processor/trace_blob.h" |
| 22 | #include "perfetto/trace_processor/trace_blob_view.h" |
Alexander Timin | 5a99b5c | 2021-05-11 22:48:07 +0000 | [diff] [blame] | 23 | #include "protos/perfetto/common/descriptor.pbzero.h" |
| 24 | #include "protos/perfetto/trace/track_event/source_location.pbzero.h" |
| 25 | #include "src/protozero/test/example_proto/test_messages.pbzero.h" |
| 26 | #include "src/trace_processor/test_messages.descriptor.h" |
Alexander Timin | 97d8785 | 2021-05-17 18:01:33 +0000 | [diff] [blame] | 27 | #include "src/trace_processor/util/interned_message_view.h" |
Alexander Timin | 5a99b5c | 2021-05-11 22:48:07 +0000 | [diff] [blame] | 28 | #include "test/gtest_and_gmock.h" |
| 29 | |
| 30 | #include <sstream> |
| 31 | |
| 32 | namespace perfetto { |
| 33 | namespace trace_processor { |
| 34 | namespace util { |
| 35 | namespace { |
| 36 | |
| 37 | constexpr size_t kChunkSize = 42; |
| 38 | |
Alexander Timin | 45123b7 | 2021-05-21 14:53:52 +0000 | [diff] [blame] | 39 | protozero::ConstChars ToChars(const char* str) { |
| 40 | return protozero::ConstChars{str, strlen(str)}; |
| 41 | } |
Alexander Timin | 5a99b5c | 2021-05-11 22:48:07 +0000 | [diff] [blame] | 42 | |
| 43 | class ProtoToArgsParserTest : public ::testing::Test, |
| 44 | public ProtoToArgsParser::Delegate { |
| 45 | protected: |
| 46 | ProtoToArgsParserTest() {} |
| 47 | |
| 48 | const std::vector<std::string>& args() const { return args_; } |
| 49 | |
Alexander Timin | 99653b1 | 2021-05-11 22:50:00 +0000 | [diff] [blame] | 50 | void AddInternedSourceLocation(uint64_t iid, TraceBlobView data) { |
| 51 | interned_source_locations_[iid] = std::unique_ptr<InternedMessageView>( |
| 52 | new InternedMessageView(std::move(data))); |
| 53 | } |
| 54 | |
Alexander Timin | 5a99b5c | 2021-05-11 22:48:07 +0000 | [diff] [blame] | 55 | private: |
| 56 | using Key = ProtoToArgsParser::Key; |
| 57 | |
| 58 | void AddInteger(const Key& key, int64_t value) override { |
| 59 | std::stringstream ss; |
| 60 | ss << key.flat_key << " " << key.key << " " << value; |
| 61 | args_.push_back(ss.str()); |
| 62 | } |
| 63 | |
| 64 | void AddUnsignedInteger(const Key& key, uint64_t value) override { |
| 65 | std::stringstream ss; |
| 66 | ss << key.flat_key << " " << key.key << " " << value; |
| 67 | args_.push_back(ss.str()); |
| 68 | } |
| 69 | |
| 70 | void AddString(const Key& key, const protozero::ConstChars& value) override { |
| 71 | std::stringstream ss; |
| 72 | ss << key.flat_key << " " << key.key << " " << value.ToStdString(); |
| 73 | args_.push_back(ss.str()); |
| 74 | } |
| 75 | |
| 76 | void AddDouble(const Key& key, double value) override { |
| 77 | std::stringstream ss; |
| 78 | ss << key.flat_key << " " << key.key << " " << value; |
| 79 | args_.push_back(ss.str()); |
| 80 | } |
| 81 | |
| 82 | void AddPointer(const Key& key, const void* value) override { |
| 83 | std::stringstream ss; |
| 84 | ss << key.flat_key << " " << key.key << " " << std::hex |
| 85 | << reinterpret_cast<uintptr_t>(value) << std::dec; |
| 86 | args_.push_back(ss.str()); |
| 87 | } |
| 88 | |
| 89 | void AddBoolean(const Key& key, bool value) override { |
| 90 | std::stringstream ss; |
| 91 | ss << key.flat_key << " " << key.key << " " << (value ? "true" : "false"); |
| 92 | args_.push_back(ss.str()); |
| 93 | } |
| 94 | |
Alexander Timin | 97d8785 | 2021-05-17 18:01:33 +0000 | [diff] [blame] | 95 | bool AddJson(const Key& key, const protozero::ConstChars& value) override { |
Alexander Timin | 5a99b5c | 2021-05-11 22:48:07 +0000 | [diff] [blame] | 96 | std::stringstream ss; |
| 97 | ss << key.flat_key << " " << key.key << " " << std::hex |
| 98 | << value.ToStdString() << std::dec; |
| 99 | args_.push_back(ss.str()); |
Alexander Timin | 97d8785 | 2021-05-17 18:01:33 +0000 | [diff] [blame] | 100 | return true; |
Alexander Timin | 5a99b5c | 2021-05-11 22:48:07 +0000 | [diff] [blame] | 101 | } |
| 102 | |
Alexander Timin | 7677825 | 2021-10-04 13:24:46 +0000 | [diff] [blame] | 103 | void AddNull(const Key& key) override { |
| 104 | std::stringstream ss; |
| 105 | ss << key.flat_key << " " << key.key << " [NULL]"; |
| 106 | args_.push_back(ss.str()); |
| 107 | } |
| 108 | |
Alexander Timin | 97d8785 | 2021-05-17 18:01:33 +0000 | [diff] [blame] | 109 | size_t GetArrayEntryIndex(const std::string&) final { return 0; } |
| 110 | |
| 111 | size_t IncrementArrayEntryIndex(const std::string&) final { return 0; } |
| 112 | |
Alexander Timin | 99653b1 | 2021-05-11 22:50:00 +0000 | [diff] [blame] | 113 | InternedMessageView* GetInternedMessageView(uint32_t field_id, |
| 114 | uint64_t iid) override { |
| 115 | if (field_id != protos::pbzero::InternedData::kSourceLocationsFieldNumber) |
| 116 | return nullptr; |
| 117 | return interned_source_locations_.at(iid).get(); |
| 118 | } |
| 119 | |
Alexander Timin | 5a99b5c | 2021-05-11 22:48:07 +0000 | [diff] [blame] | 120 | std::vector<std::string> args_; |
Alexander Timin | 99653b1 | 2021-05-11 22:50:00 +0000 | [diff] [blame] | 121 | std::map<uint64_t, std::unique_ptr<InternedMessageView>> |
| 122 | interned_source_locations_; |
Alexander Timin | 5a99b5c | 2021-05-11 22:48:07 +0000 | [diff] [blame] | 123 | }; |
| 124 | |
| 125 | TEST_F(ProtoToArgsParserTest, EnsureTestMessageProtoParses) { |
| 126 | DescriptorPool pool; |
| 127 | auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(), |
| 128 | kTestMessagesDescriptor.size()); |
| 129 | ProtoToArgsParser parser(pool); |
| 130 | EXPECT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: " |
| 131 | << status.message(); |
| 132 | } |
| 133 | |
| 134 | TEST_F(ProtoToArgsParserTest, BasicSingleLayerProto) { |
| 135 | using namespace protozero::test::protos::pbzero; |
| 136 | protozero::HeapBuffered<EveryField> msg{kChunkSize, kChunkSize}; |
| 137 | msg->set_field_int32(-1); |
| 138 | msg->set_field_int64(-333123456789ll); |
| 139 | msg->set_field_uint32(600); |
| 140 | msg->set_field_uint64(333123456789ll); |
| 141 | msg->set_field_sint32(-5); |
| 142 | msg->set_field_sint64(-9000); |
| 143 | msg->set_field_fixed32(12345); |
| 144 | msg->set_field_fixed64(444123450000ll); |
| 145 | msg->set_field_sfixed32(-69999); |
| 146 | msg->set_field_sfixed64(-200); |
| 147 | msg->set_field_double(0.5555); |
| 148 | msg->set_field_bool(true); |
| 149 | msg->set_small_enum(SmallEnum::TO_BE); |
| 150 | msg->set_signed_enum(SignedEnum::NEGATIVE); |
| 151 | msg->set_big_enum(BigEnum::BEGIN); |
| 152 | msg->set_nested_enum(EveryField::PONG); |
| 153 | msg->set_field_float(3.14f); |
| 154 | msg->set_field_string("FizzBuzz"); |
| 155 | msg->add_repeated_int32(1); |
| 156 | msg->add_repeated_int32(-1); |
| 157 | msg->add_repeated_int32(100); |
| 158 | msg->add_repeated_int32(2000000); |
| 159 | |
| 160 | auto binary_proto = msg.SerializeAsArray(); |
| 161 | |
| 162 | DescriptorPool pool; |
| 163 | auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(), |
| 164 | kTestMessagesDescriptor.size()); |
| 165 | ProtoToArgsParser parser(pool); |
| 166 | ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: " |
| 167 | << status.message(); |
| 168 | |
| 169 | status = parser.ParseMessage( |
| 170 | protozero::ConstBytes{binary_proto.data(), binary_proto.size()}, |
| 171 | ".protozero.test.protos.EveryField", nullptr, *this); |
| 172 | |
| 173 | EXPECT_TRUE(status.ok()) |
| 174 | << "InternProtoFieldsIntoArgsTable failed with error: " |
| 175 | << status.message(); |
| 176 | |
| 177 | EXPECT_THAT( |
| 178 | args(), |
| 179 | testing::ElementsAre( |
| 180 | "field_int32 field_int32 -1", "field_int64 field_int64 -333123456789", |
| 181 | "field_uint32 field_uint32 600", |
| 182 | "field_uint64 field_uint64 333123456789", |
| 183 | "field_sint32 field_sint32 -5", "field_sint64 field_sint64 -9000", |
| 184 | "field_fixed32 field_fixed32 12345", |
| 185 | "field_fixed64 field_fixed64 444123450000", |
| 186 | "field_sfixed32 field_sfixed32 -69999", |
| 187 | "field_sfixed64 field_sfixed64 -200", |
| 188 | "field_double field_double 0.5555", "field_bool field_bool true", |
| 189 | "small_enum small_enum TO_BE", "signed_enum signed_enum NEGATIVE", |
| 190 | "big_enum big_enum BEGIN", "nested_enum nested_enum PONG", |
| 191 | "field_float field_float 3.14", "field_string field_string FizzBuzz", |
| 192 | "repeated_int32 repeated_int32[0] 1", |
| 193 | "repeated_int32 repeated_int32[1] -1", |
| 194 | "repeated_int32 repeated_int32[2] 100", |
| 195 | "repeated_int32 repeated_int32[3] 2000000")); |
| 196 | } |
| 197 | |
| 198 | TEST_F(ProtoToArgsParserTest, NestedProto) { |
| 199 | using namespace protozero::test::protos::pbzero; |
| 200 | protozero::HeapBuffered<NestedA> msg{kChunkSize, kChunkSize}; |
| 201 | msg->set_super_nested()->set_value_c(3); |
| 202 | |
| 203 | auto binary_proto = msg.SerializeAsArray(); |
| 204 | |
| 205 | DescriptorPool pool; |
| 206 | auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(), |
| 207 | kTestMessagesDescriptor.size()); |
| 208 | ProtoToArgsParser parser(pool); |
| 209 | ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: " |
| 210 | << status.message(); |
| 211 | |
| 212 | status = parser.ParseMessage( |
| 213 | protozero::ConstBytes{binary_proto.data(), binary_proto.size()}, |
| 214 | ".protozero.test.protos.NestedA", nullptr, *this); |
| 215 | EXPECT_TRUE(status.ok()) |
| 216 | << "InternProtoFieldsIntoArgsTable failed with error: " |
| 217 | << status.message(); |
| 218 | EXPECT_THAT(args(), testing::ElementsAre( |
| 219 | "super_nested.value_c super_nested.value_c 3")); |
| 220 | } |
| 221 | |
| 222 | TEST_F(ProtoToArgsParserTest, CamelCaseFieldsProto) { |
| 223 | using namespace protozero::test::protos::pbzero; |
| 224 | protozero::HeapBuffered<CamelCaseFields> msg{kChunkSize, kChunkSize}; |
| 225 | msg->set_barbaz(true); |
| 226 | msg->set_moomoo(true); |
| 227 | msg->set___bigbang(true); |
| 228 | |
| 229 | auto binary_proto = msg.SerializeAsArray(); |
| 230 | |
| 231 | DescriptorPool pool; |
| 232 | auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(), |
| 233 | kTestMessagesDescriptor.size()); |
| 234 | ProtoToArgsParser parser(pool); |
| 235 | ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: " |
| 236 | << status.message(); |
| 237 | |
| 238 | status = parser.ParseMessage( |
| 239 | protozero::ConstBytes{binary_proto.data(), binary_proto.size()}, |
| 240 | ".protozero.test.protos.CamelCaseFields", nullptr, *this); |
| 241 | EXPECT_TRUE(status.ok()) |
| 242 | << "InternProtoFieldsIntoArgsTable failed with error: " |
| 243 | << status.message(); |
| 244 | EXPECT_THAT(args(), |
| 245 | testing::ElementsAre("barBaz barBaz true", "MooMoo MooMoo true", |
| 246 | "__bigBang __bigBang true")); |
| 247 | } |
| 248 | |
| 249 | TEST_F(ProtoToArgsParserTest, NestedProtoParsingOverrideHandled) { |
| 250 | using namespace protozero::test::protos::pbzero; |
| 251 | protozero::HeapBuffered<NestedA> msg{kChunkSize, kChunkSize}; |
| 252 | msg->set_super_nested()->set_value_c(3); |
| 253 | |
| 254 | auto binary_proto = msg.SerializeAsArray(); |
| 255 | |
| 256 | DescriptorPool pool; |
| 257 | auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(), |
| 258 | kTestMessagesDescriptor.size()); |
| 259 | ProtoToArgsParser parser(pool); |
| 260 | ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: " |
| 261 | << status.message(); |
| 262 | |
Alexander Timin | 45123b7 | 2021-05-21 14:53:52 +0000 | [diff] [blame] | 263 | parser.AddParsingOverrideForField( |
Alexander Timin | 5a99b5c | 2021-05-11 22:48:07 +0000 | [diff] [blame] | 264 | "super_nested.value_c", |
| 265 | [](const protozero::Field& field, ProtoToArgsParser::Delegate& writer) { |
| 266 | EXPECT_EQ(field.type(), protozero::proto_utils::ProtoWireType::kVarInt); |
| 267 | std::string key = "super_nested.value_b.replaced"; |
| 268 | writer.AddInteger({key, key}, field.as_int32()); |
| 269 | // We've handled this field by adding the desired args. |
| 270 | return base::OkStatus(); |
| 271 | }); |
| 272 | |
| 273 | status = parser.ParseMessage( |
| 274 | protozero::ConstBytes{binary_proto.data(), binary_proto.size()}, |
| 275 | ".protozero.test.protos.NestedA", nullptr, *this); |
| 276 | EXPECT_TRUE(status.ok()) |
| 277 | << "InternProtoFieldsIntoArgsTable failed with error: " |
| 278 | << status.message(); |
| 279 | EXPECT_THAT( |
| 280 | args(), |
| 281 | testing::ElementsAre( |
| 282 | "super_nested.value_b.replaced super_nested.value_b.replaced 3")); |
| 283 | } |
| 284 | |
| 285 | TEST_F(ProtoToArgsParserTest, NestedProtoParsingOverrideSkipped) { |
| 286 | using namespace protozero::test::protos::pbzero; |
| 287 | protozero::HeapBuffered<NestedA> msg{kChunkSize, kChunkSize}; |
| 288 | msg->set_super_nested()->set_value_c(3); |
| 289 | |
| 290 | auto binary_proto = msg.SerializeAsArray(); |
| 291 | |
| 292 | DescriptorPool pool; |
| 293 | auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(), |
| 294 | kTestMessagesDescriptor.size()); |
| 295 | ProtoToArgsParser parser(pool); |
| 296 | ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: " |
| 297 | << status.message(); |
| 298 | |
Alexander Timin | 45123b7 | 2021-05-21 14:53:52 +0000 | [diff] [blame] | 299 | parser.AddParsingOverrideForField( |
Alexander Timin | 5a99b5c | 2021-05-11 22:48:07 +0000 | [diff] [blame] | 300 | "super_nested.value_c", |
| 301 | [](const protozero::Field& field, ProtoToArgsParser::Delegate&) { |
| 302 | static int val = 0; |
| 303 | ++val; |
| 304 | EXPECT_EQ(1, val); |
| 305 | EXPECT_EQ(field.type(), protozero::proto_utils::ProtoWireType::kVarInt); |
| 306 | return base::nullopt; |
| 307 | }); |
| 308 | |
| 309 | status = parser.ParseMessage( |
| 310 | protozero::ConstBytes{binary_proto.data(), binary_proto.size()}, |
| 311 | ".protozero.test.protos.NestedA", nullptr, *this); |
| 312 | EXPECT_TRUE(status.ok()) |
| 313 | << "InternProtoFieldsIntoArgsTable failed with error: " |
| 314 | << status.message(); |
| 315 | EXPECT_THAT(args(), testing::ElementsAre( |
| 316 | "super_nested.value_c super_nested.value_c 3")); |
| 317 | } |
| 318 | |
Alexander Timin | 99653b1 | 2021-05-11 22:50:00 +0000 | [diff] [blame] | 319 | TEST_F(ProtoToArgsParserTest, LookingUpInternedStateParsingOverride) { |
| 320 | using namespace protozero::test::protos::pbzero; |
| 321 | // The test proto, we will use |value_c| as the source_location iid. |
| 322 | protozero::HeapBuffered<NestedA> msg{kChunkSize, kChunkSize}; |
| 323 | msg->set_super_nested()->set_value_c(3); |
| 324 | auto binary_proto = msg.SerializeAsArray(); |
| 325 | |
| 326 | // The interned source location. |
| 327 | protozero::HeapBuffered<protos::pbzero::SourceLocation> src_loc{kChunkSize, |
| 328 | kChunkSize}; |
| 329 | const uint64_t kIid = 3; |
| 330 | src_loc->set_iid(kIid); |
| 331 | src_loc->set_file_name("test_file_name"); |
| 332 | // We need to update sequence_state to point to it. |
| 333 | auto binary_data = src_loc.SerializeAsArray(); |
| 334 | std::unique_ptr<uint8_t[]> buffer(new uint8_t[binary_data.size()]); |
| 335 | for (size_t i = 0; i < binary_data.size(); ++i) { |
| 336 | buffer.get()[i] = binary_data[i]; |
| 337 | } |
Primiano Tucci | 3264b59 | 2021-11-08 18:20:51 +0000 | [diff] [blame^] | 338 | TraceBlob blob = |
| 339 | TraceBlob::TakeOwnership(std::move(buffer), binary_data.size()); |
| 340 | AddInternedSourceLocation(kIid, TraceBlobView(std::move(blob))); |
Alexander Timin | 99653b1 | 2021-05-11 22:50:00 +0000 | [diff] [blame] | 341 | |
| 342 | DescriptorPool pool; |
| 343 | auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(), |
| 344 | kTestMessagesDescriptor.size()); |
| 345 | ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: " |
| 346 | << status.message(); |
| 347 | |
| 348 | ProtoToArgsParser parser(pool); |
| 349 | // Now we override the behaviour of |value_c| so we can expand the iid into |
| 350 | // multiple args rows. |
Alexander Timin | 45123b7 | 2021-05-21 14:53:52 +0000 | [diff] [blame] | 351 | parser.AddParsingOverrideForField( |
Alexander Timin | 99653b1 | 2021-05-11 22:50:00 +0000 | [diff] [blame] | 352 | "super_nested.value_c", |
| 353 | [](const protozero::Field& field, ProtoToArgsParser::Delegate& delegate) |
| 354 | -> base::Optional<base::Status> { |
| 355 | auto* decoder = delegate.GetInternedMessage( |
| 356 | protos::pbzero::InternedData::kSourceLocations, field.as_uint64()); |
| 357 | if (!decoder) { |
| 358 | // Lookup failed fall back on default behaviour. |
| 359 | return base::nullopt; |
| 360 | } |
| 361 | delegate.AddString(ProtoToArgsParser::Key("file_name"), |
| 362 | protozero::ConstChars{"file", 4}); |
| 363 | delegate.AddInteger(ProtoToArgsParser::Key("line_number"), 2); |
| 364 | return base::OkStatus(); |
| 365 | }); |
| 366 | |
| 367 | status = parser.ParseMessage( |
| 368 | protozero::ConstBytes{binary_proto.data(), binary_proto.size()}, |
| 369 | ".protozero.test.protos.NestedA", nullptr, *this); |
| 370 | EXPECT_TRUE(status.ok()) |
| 371 | << "InternProtoFieldsIntoArgsTable failed with error: " |
| 372 | << status.message(); |
| 373 | EXPECT_THAT(args(), testing::ElementsAre("file_name file_name file", |
| 374 | "line_number line_number 2")); |
| 375 | } |
| 376 | |
Alexander Timin | 45123b7 | 2021-05-21 14:53:52 +0000 | [diff] [blame] | 377 | TEST_F(ProtoToArgsParserTest, OverrideForType) { |
| 378 | using namespace protozero::test::protos::pbzero; |
| 379 | protozero::HeapBuffered<NestedA> msg{kChunkSize, kChunkSize}; |
| 380 | msg->set_super_nested()->set_value_c(3); |
| 381 | |
| 382 | auto binary_proto = msg.SerializeAsArray(); |
| 383 | |
| 384 | DescriptorPool pool; |
| 385 | auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(), |
| 386 | kTestMessagesDescriptor.size()); |
| 387 | ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: " |
| 388 | << status.message(); |
| 389 | |
| 390 | ProtoToArgsParser parser(pool); |
| 391 | |
| 392 | parser.AddParsingOverrideForType( |
| 393 | ".protozero.test.protos.NestedA.NestedB.NestedC", |
| 394 | [](ProtoToArgsParser::ScopedNestedKeyContext&, |
| 395 | const protozero::ConstBytes&, Delegate& delegate) { |
| 396 | delegate.AddInteger(ProtoToArgsParser::Key("arg"), 42); |
| 397 | return base::OkStatus(); |
| 398 | }); |
| 399 | |
| 400 | status = parser.ParseMessage( |
| 401 | protozero::ConstBytes{binary_proto.data(), binary_proto.size()}, |
| 402 | ".protozero.test.protos.NestedA", nullptr, *this); |
| 403 | EXPECT_TRUE(status.ok()) |
| 404 | << "InternProtoFieldsIntoArgsTable failed with error: " |
| 405 | << status.message(); |
| 406 | EXPECT_THAT(args(), testing::ElementsAre("arg arg 42")); |
| 407 | } |
| 408 | |
| 409 | TEST_F(ProtoToArgsParserTest, FieldOverrideTakesPrecedence) { |
| 410 | using namespace protozero::test::protos::pbzero; |
| 411 | protozero::HeapBuffered<NestedA> msg{kChunkSize, kChunkSize}; |
| 412 | msg->set_super_nested()->set_value_c(3); |
| 413 | |
| 414 | auto binary_proto = msg.SerializeAsArray(); |
| 415 | |
| 416 | DescriptorPool pool; |
| 417 | auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(), |
| 418 | kTestMessagesDescriptor.size()); |
| 419 | ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: " |
| 420 | << status.message(); |
| 421 | |
| 422 | ProtoToArgsParser parser(pool); |
| 423 | |
| 424 | parser.AddParsingOverrideForField( |
| 425 | "super_nested", |
| 426 | [](const protozero::Field&, ProtoToArgsParser::Delegate& writer) { |
| 427 | writer.AddString(ProtoToArgsParser::Key("arg"), |
| 428 | ToChars("override-for-field")); |
| 429 | return base::OkStatus(); |
| 430 | }); |
| 431 | |
| 432 | parser.AddParsingOverrideForType( |
| 433 | ".protozero.test.protos.NestedA.NestedB.NestedC", |
| 434 | [](ProtoToArgsParser::ScopedNestedKeyContext&, |
| 435 | const protozero::ConstBytes&, Delegate& delegate) { |
| 436 | delegate.AddString(ProtoToArgsParser::Key("arg"), |
| 437 | ToChars("override-for-type")); |
| 438 | return base::OkStatus(); |
| 439 | }); |
| 440 | |
| 441 | status = parser.ParseMessage( |
| 442 | protozero::ConstBytes{binary_proto.data(), binary_proto.size()}, |
| 443 | ".protozero.test.protos.NestedA", nullptr, *this); |
| 444 | EXPECT_TRUE(status.ok()) |
| 445 | << "InternProtoFieldsIntoArgsTable failed with error: " |
| 446 | << status.message(); |
| 447 | EXPECT_THAT(args(), testing::ElementsAre("arg arg override-for-field")); |
| 448 | } |
| 449 | |
Alexander Timin | 7677825 | 2021-10-04 13:24:46 +0000 | [diff] [blame] | 450 | TEST_F(ProtoToArgsParserTest, EmptyMessage) { |
| 451 | using namespace protozero::test::protos::pbzero; |
| 452 | protozero::HeapBuffered<NestedA> msg{kChunkSize, kChunkSize}; |
| 453 | msg->set_super_nested(); |
| 454 | |
| 455 | auto binary_proto = msg.SerializeAsArray(); |
| 456 | |
| 457 | DescriptorPool pool; |
| 458 | auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(), |
| 459 | kTestMessagesDescriptor.size()); |
| 460 | ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: " |
| 461 | << status.message(); |
| 462 | |
| 463 | ProtoToArgsParser parser(pool); |
| 464 | status = parser.ParseMessage( |
| 465 | protozero::ConstBytes{binary_proto.data(), binary_proto.size()}, |
| 466 | ".protozero.test.protos.NestedA", nullptr, *this); |
| 467 | EXPECT_TRUE(status.ok()) |
| 468 | << "InternProtoFieldsIntoArgsTable failed with error: " |
| 469 | << status.message(); |
| 470 | EXPECT_THAT(args(), testing::ElementsAre("super_nested super_nested [NULL]")); |
| 471 | } |
| 472 | |
Alexander Timin | 5a99b5c | 2021-05-11 22:48:07 +0000 | [diff] [blame] | 473 | } // namespace |
| 474 | } // namespace util |
| 475 | } // namespace trace_processor |
| 476 | } // namespace perfetto |