1 /*
2 * Copyright (C) 2022 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 "perfetto/tracing/internal/interceptor_trace_writer.h"
18
19 #include "perfetto/tracing/interceptor.h"
20 #include "test/gtest_and_gmock.h"
21
22 namespace perfetto {
23 namespace internal {
24 namespace {
25
26 using ::testing::AllOf;
27 using ::testing::Field;
28 using ::testing::HasSubstr;
29 using ::testing::InSequence;
30 using ::testing::Invoke;
31 using ::testing::IsNull;
32 using ::testing::MockFunction;
33 using ::testing::Not;
34 using ::testing::NotNull;
35
36 constexpr uint32_t kInstanceIndex = 42;
37
38 } // namespace
39
40 class InterceptorTraceWriterTest : public testing::Test {
41 protected:
42 using TracePacketCallbackArgs = InterceptorBase::TracePacketCallbackArgs;
43 using ThreadLocalState = InterceptorBase::ThreadLocalState;
44 using MockTracePacketCallback = MockFunction<void(TracePacketCallbackArgs)>;
45
InterceptorTraceWriterTest()46 InterceptorTraceWriterTest()
47 : tls_ptr_(new ThreadLocalState()),
48 tw_(std::unique_ptr<ThreadLocalState>(tls_ptr_),
49 TracePacketCallback,
50 &dss_,
51 kInstanceIndex) {}
52
SetUp()53 void SetUp() override {
54 static_trace_packet_callback_ = &trace_packet_callback_;
55 }
56
TearDown()57 void TearDown() override { static_trace_packet_callback_ = nullptr; }
58
TracePacketCallback(InterceptorBase::TracePacketCallbackArgs args)59 static void TracePacketCallback(
60 InterceptorBase::TracePacketCallbackArgs args) {
61 ASSERT_THAT(static_trace_packet_callback_, NotNull());
62 static_trace_packet_callback_->Call(args);
63 }
64
65 MockTracePacketCallback trace_packet_callback_;
66 static MockTracePacketCallback* static_trace_packet_callback_;
67
68 ThreadLocalState* tls_ptr_;
69 DataSourceStaticState dss_;
70 InterceptorTraceWriter tw_;
71 };
72
73 InterceptorTraceWriterTest::MockTracePacketCallback*
74 InterceptorTraceWriterTest::static_trace_packet_callback_;
75
TEST_F(InterceptorTraceWriterTest,TracePacketCallbackParams)76 TEST_F(InterceptorTraceWriterTest, TracePacketCallbackParams) {
77 EXPECT_CALL(trace_packet_callback_,
78 Call(AllOf(Field(&TracePacketCallbackArgs::instance_index,
79 kInstanceIndex),
80 Field(&TracePacketCallbackArgs::static_state, &dss_),
81 Field(&TracePacketCallbackArgs::tls, tls_ptr_))))
82 .Times(1);
83
84 tw_.NewTracePacket();
85 tw_.Flush();
86 }
87
TEST_F(InterceptorTraceWriterTest,NewTracePacketAutomaticallyAddedFields)88 TEST_F(InterceptorTraceWriterTest, NewTracePacketAutomaticallyAddedFields) {
89 std::string first_packet;
90 std::string second_packet;
91 EXPECT_CALL(trace_packet_callback_, Call)
92 .WillOnce(Invoke([&](TracePacketCallbackArgs args) {
93 first_packet = args.packet_data.ToStdString();
94 }))
95 .WillOnce(Invoke([&](TracePacketCallbackArgs args) {
96 second_packet = args.packet_data.ToStdString();
97 }));
98
99 tw_.NewTracePacket();
100 tw_.NewTracePacket();
101 tw_.Flush();
102
103 protos::pbzero::TracePacket::Decoder first(first_packet);
104 protos::pbzero::TracePacket::Decoder second(second_packet);
105 EXPECT_TRUE(first.has_trusted_packet_sequence_id());
106 EXPECT_TRUE(second.has_trusted_packet_sequence_id());
107 EXPECT_EQ(first.trusted_packet_sequence_id(),
108 second.trusted_packet_sequence_id());
109 }
110
TEST_F(InterceptorTraceWriterTest,NewTracePacketLargePacket)111 TEST_F(InterceptorTraceWriterTest, NewTracePacketLargePacket) {
112 size_t first_packet_size;
113 size_t second_packet_size;
114 EXPECT_CALL(trace_packet_callback_, Call)
115 .WillOnce(Invoke([&](TracePacketCallbackArgs args) {
116 first_packet_size = args.packet_data.size;
117 }))
118 .WillOnce(Invoke([&](TracePacketCallbackArgs args) {
119 second_packet_size = args.packet_data.size;
120 }));
121
122 tw_.NewTracePacket();
123 {
124 auto msg = tw_.NewTracePacket();
125 std::vector<uint8_t> large(20000u, 0);
126 msg->AppendRawProtoBytes(large.data(), large.size());
127 }
128 tw_.Flush();
129
130 EXPECT_EQ(second_packet_size, first_packet_size + 20000u);
131 }
132
TEST_F(InterceptorTraceWriterTest,NewTracePacketTakeWriterLargePacket)133 TEST_F(InterceptorTraceWriterTest, NewTracePacketTakeWriterLargePacket) {
134 size_t first_packet_size;
135 size_t second_packet_size;
136 EXPECT_CALL(trace_packet_callback_, Call)
137 .WillOnce(Invoke([&](TracePacketCallbackArgs args) {
138 first_packet_size = args.packet_data.size;
139 }))
140 .WillOnce(Invoke([&](TracePacketCallbackArgs args) {
141 second_packet_size = args.packet_data.size;
142 }));
143
144 tw_.NewTracePacket();
145 tw_.FinishTracePacket();
146
147 protozero::ScatteredStreamWriter* writer =
148 tw_.NewTracePacket().TakeStreamWriter();
149 std::vector<uint8_t> large(20000u, 0);
150 writer->WriteBytes(large.data(), large.size());
151 tw_.FinishTracePacket();
152 tw_.Flush();
153
154 EXPECT_EQ(second_packet_size, first_packet_size + 20000u);
155 }
156
TEST_F(InterceptorTraceWriterTest,MixManualTakeAndMessage)157 TEST_F(InterceptorTraceWriterTest, MixManualTakeAndMessage) {
158 std::string content1 = "AAAAA";
159 std::string content2 = "BBBBB";
160 std::string content3 = "CCCCC";
161 EXPECT_CALL(trace_packet_callback_, Call)
162 .WillOnce(Invoke([&](TracePacketCallbackArgs args) {
163 std::string data = args.packet_data.ToStdString();
164 EXPECT_THAT(data, HasSubstr(content1));
165 EXPECT_THAT(data, Not(HasSubstr(content2)));
166 EXPECT_THAT(data, Not(HasSubstr(content3)));
167 }))
168 .WillOnce(Invoke([&](TracePacketCallbackArgs args) {
169 std::string data = args.packet_data.ToStdString();
170 EXPECT_THAT(data, Not(HasSubstr(content1)));
171 EXPECT_THAT(data, HasSubstr(content2));
172 EXPECT_THAT(data, Not(HasSubstr(content3)));
173 }))
174 .WillOnce(Invoke([&](TracePacketCallbackArgs args) {
175 std::string data = args.packet_data.ToStdString();
176 EXPECT_THAT(data, Not(HasSubstr(content1)));
177 EXPECT_THAT(data, Not(HasSubstr(content2)));
178 EXPECT_THAT(data, HasSubstr(content3));
179 }));
180
181 protozero::ScatteredStreamWriter* writer =
182 tw_.NewTracePacket().TakeStreamWriter();
183 writer->WriteBytes(reinterpret_cast<const uint8_t*>(content1.data()),
184 content1.size());
185 tw_.FinishTracePacket();
186 {
187 auto msg = tw_.NewTracePacket();
188 msg->AppendRawProtoBytes(reinterpret_cast<const uint8_t*>(content2.data()),
189 content2.size());
190 }
191 writer = tw_.NewTracePacket().TakeStreamWriter();
192 writer->WriteBytes(reinterpret_cast<const uint8_t*>(content3.data()),
193 content3.size());
194 tw_.FinishTracePacket();
195
196 tw_.Flush();
197 }
198
TEST_F(InterceptorTraceWriterTest,FlushCallback)199 TEST_F(InterceptorTraceWriterTest, FlushCallback) {
200 MockFunction<void()> flush_cb;
201
202 InSequence seq;
203 EXPECT_CALL(trace_packet_callback_, Call).Times(1);
204 EXPECT_CALL(flush_cb, Call).Times(1);
205
206 tw_.NewTracePacket();
207 tw_.Flush(flush_cb.AsStdFunction());
208 }
209
210 } // namespace internal
211 } // namespace perfetto
212