|  | /* | 
|  | * Copyright (C) 2021 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | #include "perfetto/tracing/traced_proto.h" | 
|  |  | 
|  | #include "perfetto/test/traced_value_test_support.h" | 
|  | #include "perfetto/tracing/track_event.h" | 
|  | #include "protos/perfetto/trace/test_event.gen.h" | 
|  | #include "protos/perfetto/trace/test_event.pb.h" | 
|  | #include "protos/perfetto/trace/test_event.pbzero.h" | 
|  | #include "protos/perfetto/trace/track_event/track_event.gen.h" | 
|  | #include "protos/perfetto/trace/track_event/track_event.pb.h" | 
|  | #include "test/gtest_and_gmock.h" | 
|  |  | 
|  | namespace perfetto { | 
|  |  | 
|  | class TracedProtoTest : public ::testing::Test { | 
|  | public: | 
|  | TracedProtoTest() : context_(track_event_.get(), &incremental_state_) {} | 
|  |  | 
|  | EventContext& context() { return context_; } | 
|  |  | 
|  | private: | 
|  | protozero::HeapBuffered<protos::pbzero::TrackEvent> track_event_; | 
|  | internal::TrackEventIncrementalState incremental_state_; | 
|  | EventContext context_; | 
|  | }; | 
|  |  | 
|  | using TestPayload = protos::pbzero::TestEvent::TestPayload; | 
|  |  | 
|  | TEST_F(TracedProtoTest, SingleInt) { | 
|  | protozero::HeapBuffered<TestPayload> event; | 
|  | WriteIntoTracedProto(context().Wrap(event.get()), TestPayload::kSingleInt, | 
|  | 42); | 
|  |  | 
|  | protos::TestEvent::TestPayload result; | 
|  | result.ParseFromString(event.SerializeAsString()); | 
|  | EXPECT_TRUE(result.has_single_int()); | 
|  | EXPECT_EQ(result.single_int(), 42); | 
|  | } | 
|  |  | 
|  | TEST_F(TracedProtoTest, RepeatedInt) { | 
|  | protozero::HeapBuffered<TestPayload> event; | 
|  | WriteIntoTracedProto(context().Wrap(event.get()), TestPayload::kRepeatedInts, | 
|  | std::vector<int>{1, 2, 3}); | 
|  |  | 
|  | protos::TestEvent::TestPayload result; | 
|  | result.ParseFromString(event.SerializeAsString()); | 
|  | EXPECT_THAT(result.repeated_ints(), ::testing::ElementsAre(1, 2, 3)); | 
|  | } | 
|  |  | 
|  | TEST_F(TracedProtoTest, SingleString) { | 
|  | protozero::HeapBuffered<TestPayload> event; | 
|  | WriteIntoTracedProto(context().Wrap(event.get()), TestPayload::kSingleString, | 
|  | "foo"); | 
|  |  | 
|  | protos::TestEvent::TestPayload result; | 
|  | result.ParseFromString(event.SerializeAsString()); | 
|  | EXPECT_TRUE(result.has_single_string()); | 
|  | EXPECT_EQ(result.single_string(), "foo"); | 
|  | } | 
|  |  | 
|  | TEST_F(TracedProtoTest, RepeatedString) { | 
|  | protozero::HeapBuffered<TestPayload> event; | 
|  | WriteIntoTracedProto(context().Wrap(event.get()), TestPayload::kStr, | 
|  | std::vector<std::string>{"foo", "bar"}); | 
|  |  | 
|  | protos::TestEvent::TestPayload result; | 
|  | result.ParseFromString(event.SerializeAsString()); | 
|  | EXPECT_THAT(result.str(), ::testing::ElementsAre("foo", "bar")); | 
|  | } | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | struct Foo { | 
|  | void WriteIntoTrace(TracedProto<TestPayload> message) const { | 
|  | message->set_single_int(42); | 
|  |  | 
|  | auto dict = std::move(message).AddDebugAnnotations(); | 
|  | dict.Add("arg", "value"); | 
|  | } | 
|  | }; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | TEST_F(TracedProtoTest, SingleNestedMessage) { | 
|  | protozero::HeapBuffered<protos::pbzero::TestEvent> event; | 
|  | WriteIntoTracedProto(context().Wrap(event.get()), | 
|  | protos::pbzero::TestEvent::kPayload, Foo()); | 
|  |  | 
|  | protos::TestEvent result; | 
|  | result.ParseFromString(event.SerializeAsString()); | 
|  | EXPECT_EQ(result.payload().single_int(), 42); | 
|  | } | 
|  |  | 
|  | TEST_F(TracedProtoTest, RepeatedNestedMessage) { | 
|  | protozero::HeapBuffered<TestPayload> event; | 
|  | WriteIntoTracedProto(context().Wrap(event.get()), TestPayload::kNested, | 
|  | std::vector<Foo>{Foo(), Foo()}); | 
|  |  | 
|  | protos::TestEvent::TestPayload result; | 
|  | result.ParseFromString(event.SerializeAsString()); | 
|  | EXPECT_EQ(result.nested_size(), 2); | 
|  | EXPECT_EQ(result.nested(0).single_int(), 42); | 
|  | EXPECT_EQ(result.nested(1).single_int(), 42); | 
|  | } | 
|  |  | 
|  | TEST_F(TracedProtoTest, WriteDebugAnnotations) { | 
|  | protozero::HeapBuffered<protos::pbzero::TestEvent> event; | 
|  | WriteIntoTracedProto(context().Wrap(event.get()), | 
|  | protos::pbzero::TestEvent::kPayload, Foo()); | 
|  |  | 
|  | protos::TestEvent result; | 
|  | result.ParseFromString(event.SerializeAsString()); | 
|  |  | 
|  | protos::DebugAnnotation dict; | 
|  | for (const auto& annotation : result.payload().debug_annotations()) { | 
|  | *dict.add_dict_entries() = annotation; | 
|  | } | 
|  |  | 
|  | EXPECT_EQ(internal::DebugAnnotationToString(dict.SerializeAsString()), | 
|  | "{arg:value}"); | 
|  | } | 
|  |  | 
|  | }  // namespace perfetto |