blob: 56cc2c9c54db64ad043d8312b06e240b851f0153 [file] [log] [blame]
Primiano Tucci53589332017-12-19 11:31:13 +01001/*
2 * Copyright (C) 2017 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
Primiano Tucci53589332017-12-19 11:31:13 +010017#include <inttypes.h>
Primiano Tucci2ffd1a52018-03-27 01:01:30 +010018#include <unistd.h>
Primiano Tucci53589332017-12-19 11:31:13 +010019
Primiano Tucci2c5488f2019-06-01 03:27:28 +010020#include "perfetto/ext/base/temp_file.h"
21#include "perfetto/ext/tracing/core/consumer.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010022#include "perfetto/ext/tracing/core/producer.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010023#include "perfetto/ext/tracing/core/trace_packet.h"
24#include "perfetto/ext/tracing/core/trace_stats.h"
25#include "perfetto/ext/tracing/core/trace_writer.h"
26#include "perfetto/ext/tracing/ipc/consumer_ipc_client.h"
27#include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
28#include "perfetto/ext/tracing/ipc/service_ipc_host.h"
Primiano Tucci0f9e0222019-06-05 09:36:41 +010029#include "perfetto/tracing/core/data_source_config.h"
30#include "perfetto/tracing/core/data_source_descriptor.h"
31#include "perfetto/tracing/core/trace_config.h"
Primiano Tucci53589332017-12-19 11:31:13 +010032#include "src/base/test/test_task_runner.h"
33#include "src/ipc/test/test_socket.h"
Eric Seckler062ed502019-05-23 09:02:57 +010034#include "src/tracing/core/tracing_service_impl.h"
Primiano Tucci919ca1e2019-08-21 20:26:58 +020035#include "test/gtest_and_gmock.h"
Primiano Tucci53589332017-12-19 11:31:13 +010036
Primiano Tucci355b8c82019-08-29 08:37:51 +020037#include "protos/perfetto/config/trace_config.pb.h"
38#include "protos/perfetto/trace/test_event.pbzero.h"
39#include "protos/perfetto/trace/trace.pb.h"
40#include "protos/perfetto/trace/trace_packet.pb.h"
41#include "protos/perfetto/trace/trace_packet.pbzero.h"
Primiano Tucci53589332017-12-19 11:31:13 +010042
43namespace perfetto {
44namespace {
45
46using testing::Invoke;
47using testing::InvokeWithoutArgs;
48using testing::_;
49
50constexpr char kProducerSockName[] = TEST_SOCK_NAME("tracing_test-producer");
51constexpr char kConsumerSockName[] = TEST_SOCK_NAME("tracing_test-consumer");
52
Ryan Savitskibdaa9622019-05-13 10:55:32 +010053// TODO(rsavitski): consider using src/tracing/test/mock_producer.h.
Primiano Tucci53589332017-12-19 11:31:13 +010054class MockProducer : public Producer {
55 public:
56 ~MockProducer() override {}
57
58 // Producer implementation.
59 MOCK_METHOD0(OnConnect, void());
60 MOCK_METHOD0(OnDisconnect, void());
Primiano Tucci674076d2018-10-01 10:41:09 +010061 MOCK_METHOD2(SetupDataSource,
62 void(DataSourceInstanceID, const DataSourceConfig&));
Primiano Tucciafb72b52018-09-25 09:37:24 +010063 MOCK_METHOD2(StartDataSource,
Primiano Tucci53589332017-12-19 11:31:13 +010064 void(DataSourceInstanceID, const DataSourceConfig&));
Primiano Tucciafb72b52018-09-25 09:37:24 +010065 MOCK_METHOD1(StopDataSource, void(DataSourceInstanceID));
Sami Kyostila32e0b542018-02-14 08:55:43 +000066 MOCK_METHOD0(uid, uid_t());
Primiano Tuccidca727d2018-04-04 11:31:55 +020067 MOCK_METHOD0(OnTracingSetup, void());
Primiano Tuccid52e6272018-04-06 19:06:53 +020068 MOCK_METHOD3(Flush,
69 void(FlushRequestID, const DataSourceInstanceID*, size_t));
Ryan Savitskibdaa9622019-05-13 10:55:32 +010070 MOCK_METHOD2(ClearIncrementalState,
71 void(const DataSourceInstanceID*, size_t));
Primiano Tucci53589332017-12-19 11:31:13 +010072};
73
74class MockConsumer : public Consumer {
75 public:
76 ~MockConsumer() override {}
77
78 // Producer implementation.
79 MOCK_METHOD0(OnConnect, void());
80 MOCK_METHOD0(OnDisconnect, void());
Primiano Tuccidca727d2018-04-04 11:31:55 +020081 MOCK_METHOD0(OnTracingDisabled, void());
Primiano Tucci3324dfc2017-12-20 14:35:58 +010082 MOCK_METHOD2(OnTracePackets, void(std::vector<TracePacket>*, bool));
Primiano Tucci9ba1d842018-12-20 17:31:04 +010083 MOCK_METHOD1(OnDetach, void(bool));
84 MOCK_METHOD2(OnAttach, void(bool, const TraceConfig&));
Eric Secklereaf29ed2019-01-23 09:53:55 +000085 MOCK_METHOD2(OnTraceStats, void(bool, const TraceStats&));
Eric Seckler7b0c9452019-03-18 13:14:36 +000086 MOCK_METHOD1(OnObservableEvents, void(const ObservableEvents&));
Primiano Tucci3324dfc2017-12-20 14:35:58 +010087
88 // Workaround, gmock doesn't support yet move-only types, passing a pointer.
89 void OnTraceData(std::vector<TracePacket> packets, bool has_more) {
90 OnTracePackets(&packets, has_more);
91 }
Primiano Tucci53589332017-12-19 11:31:13 +010092};
93
Primiano Tucci5e33cad2018-04-30 14:41:25 +010094void CheckTraceStats(const protos::TracePacket& packet) {
95 EXPECT_TRUE(packet.has_trace_stats());
Oystein Eftevaagbb6e5662018-05-01 14:01:57 -070096 EXPECT_GE(packet.trace_stats().producers_seen(), 1u);
97 EXPECT_EQ(1u, packet.trace_stats().producers_connected());
98 EXPECT_EQ(1u, packet.trace_stats().data_sources_registered());
99 EXPECT_EQ(1u, packet.trace_stats().tracing_sessions());
100 EXPECT_EQ(1u, packet.trace_stats().total_buffers());
Primiano Tucci5e33cad2018-04-30 14:41:25 +0100101 EXPECT_EQ(1, packet.trace_stats().buffer_stats_size());
102
103 const auto& buf_stats = packet.trace_stats().buffer_stats(0);
Oystein Eftevaagbb6e5662018-05-01 14:01:57 -0700104 EXPECT_GT(buf_stats.bytes_written(), 0u);
105 EXPECT_GT(buf_stats.chunks_written(), 0u);
106 EXPECT_EQ(0u, buf_stats.chunks_overwritten());
Stephen Nuskod13fdf82019-01-15 11:22:58 +0000107 EXPECT_EQ(0u, buf_stats.chunks_rewritten());
108 EXPECT_EQ(0u, buf_stats.chunks_committed_out_of_order());
Oystein Eftevaagbb6e5662018-05-01 14:01:57 -0700109 EXPECT_EQ(0u, buf_stats.write_wrap_count());
110 EXPECT_EQ(0u, buf_stats.patches_failed());
111 EXPECT_EQ(0u, buf_stats.readaheads_failed());
112 EXPECT_EQ(0u, buf_stats.abi_violations());
Primiano Tucci5e33cad2018-04-30 14:41:25 +0100113}
114
Eric Seckler062ed502019-05-23 09:02:57 +0100115} // namespace
116
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100117class TracingIntegrationTest : public ::testing::Test {
118 public:
119 void SetUp() override {
120 DESTROY_TEST_SOCK(kProducerSockName);
121 DESTROY_TEST_SOCK(kConsumerSockName);
122 task_runner_.reset(new base::TestTaskRunner());
123
124 // Create the service host.
125 svc_ = ServiceIPCHost::CreateInstance(task_runner_.get());
126 svc_->Start(kProducerSockName, kConsumerSockName);
127
128 // Create and connect a Producer.
129 producer_endpoint_ = ProducerIPCClient::Connect(
Primiano Tucci578d7842018-03-29 15:27:05 +0100130 kProducerSockName, &producer_, "perfetto.mock_producer",
Eric Seckler062ed502019-05-23 09:02:57 +0100131 task_runner_.get(), GetProducerSMBScrapingMode());
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100132 auto on_producer_connect =
133 task_runner_->CreateCheckpoint("on_producer_connect");
134 EXPECT_CALL(producer_, OnConnect()).WillOnce(Invoke(on_producer_connect));
135 task_runner_->RunUntilCheckpoint("on_producer_connect");
136
137 // Register a data source.
138 DataSourceDescriptor ds_desc;
139 ds_desc.set_name("perfetto.test");
Primiano Tucci9daa4832018-03-28 23:28:17 +0100140 producer_endpoint_->RegisterDataSource(ds_desc);
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100141
142 // Create and connect a Consumer.
143 consumer_endpoint_ = ConsumerIPCClient::Connect(
144 kConsumerSockName, &consumer_, task_runner_.get());
145 auto on_consumer_connect =
146 task_runner_->CreateCheckpoint("on_consumer_connect");
147 EXPECT_CALL(consumer_, OnConnect()).WillOnce(Invoke(on_consumer_connect));
148 task_runner_->RunUntilCheckpoint("on_consumer_connect");
149
150 ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&producer_));
151 ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&consumer_));
152 }
153
154 void TearDown() override {
155 // Destroy the service and check that both Producer and Consumer see an
156 // OnDisconnect() call.
157
158 auto on_producer_disconnect =
159 task_runner_->CreateCheckpoint("on_producer_disconnect");
160 EXPECT_CALL(producer_, OnDisconnect())
161 .WillOnce(Invoke(on_producer_disconnect));
162
163 auto on_consumer_disconnect =
164 task_runner_->CreateCheckpoint("on_consumer_disconnect");
165 EXPECT_CALL(consumer_, OnDisconnect())
166 .WillOnce(Invoke(on_consumer_disconnect));
167
168 svc_.reset();
169 task_runner_->RunUntilCheckpoint("on_producer_disconnect");
170 task_runner_->RunUntilCheckpoint("on_consumer_disconnect");
171
172 ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&producer_));
173 ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&consumer_));
174
175 task_runner_.reset();
176 DESTROY_TEST_SOCK(kProducerSockName);
177 DESTROY_TEST_SOCK(kConsumerSockName);
178 }
179
Eric Seckler062ed502019-05-23 09:02:57 +0100180 virtual TracingService::ProducerSMBScrapingMode GetProducerSMBScrapingMode() {
181 return TracingService::ProducerSMBScrapingMode::kDefault;
182 }
183
184 void WaitForTraceWritersChanged(ProducerID producer_id) {
185 static int i = 0;
186 auto checkpoint_name = "writers_changed_" + std::to_string(producer_id) +
187 "_" + std::to_string(i++);
188 auto writers_changed = task_runner_->CreateCheckpoint(checkpoint_name);
189 auto writers = GetWriters(producer_id);
190 std::function<void()> task;
191 task = [&task, writers, writers_changed, producer_id, this]() {
192 if (writers != GetWriters(producer_id)) {
193 writers_changed();
194 return;
195 }
196 task_runner_->PostDelayedTask(task, 1);
197 };
198 task_runner_->PostDelayedTask(task, 1);
199 task_runner_->RunUntilCheckpoint(checkpoint_name);
200 }
201
202 const std::map<WriterID, BufferID>& GetWriters(ProducerID producer_id) {
203 return reinterpret_cast<TracingServiceImpl*>(svc_->service())
204 ->GetProducer(producer_id)
205 ->writers_;
206 }
207
208 ProducerID* last_producer_id() {
209 return &reinterpret_cast<TracingServiceImpl*>(svc_->service())
210 ->last_producer_id_;
211 }
212
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100213 std::unique_ptr<base::TestTaskRunner> task_runner_;
214 std::unique_ptr<ServiceIPCHost> svc_;
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100215 std::unique_ptr<TracingService::ProducerEndpoint> producer_endpoint_;
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100216 MockProducer producer_;
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100217 std::unique_ptr<TracingService::ConsumerEndpoint> consumer_endpoint_;
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100218 MockConsumer consumer_;
219};
220
Primiano Tucci53589332017-12-19 11:31:13 +0100221TEST_F(TracingIntegrationTest, WithIPCTransport) {
Primiano Tucci53589332017-12-19 11:31:13 +0100222 // Start tracing.
223 TraceConfig trace_config;
224 trace_config.add_buffers()->set_size_kb(4096 * 10);
225 auto* ds_config = trace_config.add_data_sources()->mutable_config();
226 ds_config->set_name("perfetto.test");
227 ds_config->set_target_buffer(0);
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100228 consumer_endpoint_->EnableTracing(trace_config);
Primiano Tucci53589332017-12-19 11:31:13 +0100229
230 // At this point, the Producer should be asked to turn its data source on.
231 DataSourceInstanceID ds_iid = 0;
Primiano Tucci20d441d2018-01-16 09:25:51 +0000232
233 BufferID global_buf_id = 0;
Primiano Tucci53589332017-12-19 11:31:13 +0100234 auto on_create_ds_instance =
235 task_runner_->CreateCheckpoint("on_create_ds_instance");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200236 EXPECT_CALL(producer_, OnTracingSetup());
Primiano Tucci674076d2018-10-01 10:41:09 +0100237
238 // Store the arguments passed to SetupDataSource() and later check that they
239 // match the ones passed to StartDataSource().
240 DataSourceInstanceID setup_id;
241 perfetto::protos::DataSourceConfig setup_cfg_proto;
242 EXPECT_CALL(producer_, SetupDataSource(_, _))
243 .WillOnce(
244 Invoke([&setup_id, &setup_cfg_proto](DataSourceInstanceID id,
245 const DataSourceConfig& cfg) {
246
247 setup_id = id;
248 cfg.ToProto(&setup_cfg_proto);
249 }));
Primiano Tucciafb72b52018-09-25 09:37:24 +0100250 EXPECT_CALL(producer_, StartDataSource(_, _))
Primiano Tucci53589332017-12-19 11:31:13 +0100251 .WillOnce(
Primiano Tucci674076d2018-10-01 10:41:09 +0100252 Invoke([on_create_ds_instance, &ds_iid, &global_buf_id, &setup_id,
253 &setup_cfg_proto](DataSourceInstanceID id,
254 const DataSourceConfig& cfg) {
255 // id and config should match the ones passed to SetupDataSource.
256 ASSERT_EQ(id, setup_id);
257 perfetto::protos::DataSourceConfig cfg_proto;
258 cfg.ToProto(&cfg_proto);
259 ASSERT_EQ(cfg_proto.SerializeAsString(),
260 setup_cfg_proto.SerializeAsString());
261
Primiano Tucci53589332017-12-19 11:31:13 +0100262 ASSERT_NE(0u, id);
263 ds_iid = id;
264 ASSERT_EQ("perfetto.test", cfg.name());
Primiano Tucci20d441d2018-01-16 09:25:51 +0000265 global_buf_id = static_cast<BufferID>(cfg.target_buffer());
266 ASSERT_NE(0u, global_buf_id);
267 ASSERT_LE(global_buf_id, std::numeric_limits<BufferID>::max());
Primiano Tucci53589332017-12-19 11:31:13 +0100268 on_create_ds_instance();
269 }));
270 task_runner_->RunUntilCheckpoint("on_create_ds_instance");
271
272 // Now let the data source fill some pages within the same task.
273 // Doing so should accumulate a bunch of chunks that will be notified by the
274 // a future task in one batch.
275 std::unique_ptr<TraceWriter> writer =
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100276 producer_endpoint_->CreateTraceWriter(global_buf_id);
Primiano Tucci53589332017-12-19 11:31:13 +0100277 ASSERT_TRUE(writer);
278
279 const size_t kNumPackets = 10;
280 for (size_t i = 0; i < kNumPackets; i++) {
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100281 char buf[16];
Primiano Tucci53589332017-12-19 11:31:13 +0100282 sprintf(buf, "evt_%zu", i);
Sami Kyostila32e0b542018-02-14 08:55:43 +0000283 writer->NewTracePacket()->set_for_testing()->set_str(buf, strlen(buf));
Primiano Tucci53589332017-12-19 11:31:13 +0100284 }
285
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100286 // Allow the service to see the CommitData() before reading back.
Primiano Tucci3e69ed92018-03-14 14:52:29 +0000287 auto on_data_committed = task_runner_->CreateCheckpoint("on_data_committed");
288 writer->Flush(on_data_committed);
289 task_runner_->RunUntilCheckpoint("on_data_committed");
Primiano Tucci53589332017-12-19 11:31:13 +0100290
291 // Read the log buffer.
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100292 consumer_endpoint_->ReadBuffers();
Primiano Tucci53589332017-12-19 11:31:13 +0100293 size_t num_pack_rx = 0;
Sami Kyostilafbccb3c2018-03-21 14:00:47 +0000294 bool saw_clock_snapshot = false;
Sami Kyostila200bd2e2018-03-26 12:24:10 +0100295 bool saw_trace_config = false;
Primiano Tucci5e33cad2018-04-30 14:41:25 +0100296 bool saw_trace_stats = false;
Primiano Tucci53589332017-12-19 11:31:13 +0100297 auto all_packets_rx = task_runner_->CreateCheckpoint("all_packets_rx");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100298 EXPECT_CALL(consumer_, OnTracePackets(_, _))
Primiano Tucci5e33cad2018-04-30 14:41:25 +0100299 .WillRepeatedly(
300 Invoke([&num_pack_rx, all_packets_rx, &trace_config,
301 &saw_clock_snapshot, &saw_trace_config, &saw_trace_stats](
302 std::vector<TracePacket>* packets, bool has_more) {
Oystein Eftevaag4966fdc2018-03-28 10:20:59 -0700303#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
Primiano Tucci5e33cad2018-04-30 14:41:25 +0100304 const int kExpectedMinNumberOfClocks = 1;
Oystein Eftevaag4966fdc2018-03-28 10:20:59 -0700305#else
Primiano Tucci5e33cad2018-04-30 14:41:25 +0100306 const int kExpectedMinNumberOfClocks = 6;
Oystein Eftevaag4966fdc2018-03-28 10:20:59 -0700307#endif
308
Primiano Tucci5e33cad2018-04-30 14:41:25 +0100309 for (auto& encoded_packet : *packets) {
310 protos::TracePacket packet;
311 ASSERT_TRUE(encoded_packet.Decode(&packet));
312 if (packet.has_for_testing()) {
313 char buf[8];
314 sprintf(buf, "evt_%zu", num_pack_rx++);
315 EXPECT_EQ(std::string(buf), packet.for_testing().str());
316 } else if (packet.has_clock_snapshot()) {
317 EXPECT_GE(packet.clock_snapshot().clocks_size(),
318 kExpectedMinNumberOfClocks);
319 saw_clock_snapshot = true;
320 } else if (packet.has_trace_config()) {
321 protos::TraceConfig config_proto;
322 trace_config.ToProto(&config_proto);
323 Slice expected_slice = Slice::Allocate(
324 static_cast<size_t>(config_proto.ByteSize()));
325 config_proto.SerializeWithCachedSizesToArray(
326 expected_slice.own_data());
327 Slice actual_slice = Slice::Allocate(
328 static_cast<size_t>(packet.trace_config().ByteSize()));
329 packet.trace_config().SerializeWithCachedSizesToArray(
330 actual_slice.own_data());
331 EXPECT_EQ(std::string(reinterpret_cast<const char*>(
332 expected_slice.own_data()),
333 expected_slice.size),
334 std::string(reinterpret_cast<const char*>(
335 actual_slice.own_data()),
336 actual_slice.size));
337 saw_trace_config = true;
338 } else if (packet.has_trace_stats()) {
339 saw_trace_stats = true;
340 CheckTraceStats(packet);
341 }
342 }
343 if (!has_more)
344 all_packets_rx();
345 }));
Primiano Tucci53589332017-12-19 11:31:13 +0100346 task_runner_->RunUntilCheckpoint("all_packets_rx");
Primiano Tucci09db8272018-03-08 17:47:47 +0000347 ASSERT_EQ(kNumPackets, num_pack_rx);
Sami Kyostilafbccb3c2018-03-21 14:00:47 +0000348 EXPECT_TRUE(saw_clock_snapshot);
Sami Kyostila200bd2e2018-03-26 12:24:10 +0100349 EXPECT_TRUE(saw_trace_config);
Primiano Tucci5e33cad2018-04-30 14:41:25 +0100350 EXPECT_TRUE(saw_trace_stats);
Primiano Tucci53589332017-12-19 11:31:13 +0100351
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100352 // Disable tracing.
353 consumer_endpoint_->DisableTracing();
Primiano Tucci53589332017-12-19 11:31:13 +0100354
Primiano Tuccidca727d2018-04-04 11:31:55 +0200355 auto on_tracing_disabled =
356 task_runner_->CreateCheckpoint("on_tracing_disabled");
Primiano Tucciafb72b52018-09-25 09:37:24 +0100357 EXPECT_CALL(producer_, StopDataSource(_));
Primiano Tuccidca727d2018-04-04 11:31:55 +0200358 EXPECT_CALL(consumer_, OnTracingDisabled())
359 .WillOnce(Invoke(on_tracing_disabled));
360 task_runner_->RunUntilCheckpoint("on_tracing_disabled");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100361}
Primiano Tucci53589332017-12-19 11:31:13 +0100362
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100363TEST_F(TracingIntegrationTest, WriteIntoFile) {
364 // Start tracing.
365 TraceConfig trace_config;
366 trace_config.add_buffers()->set_size_kb(4096 * 10);
367 auto* ds_config = trace_config.add_data_sources()->mutable_config();
368 ds_config->set_name("perfetto.test");
369 ds_config->set_target_buffer(0);
370 trace_config.set_write_into_file(true);
371 base::TempFile tmp_file = base::TempFile::CreateUnlinked();
372 consumer_endpoint_->EnableTracing(trace_config,
373 base::ScopedFile(dup(tmp_file.fd())));
Primiano Tucci53589332017-12-19 11:31:13 +0100374
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100375 // At this point, the producer_ should be asked to turn its data source on.
376 BufferID global_buf_id = 0;
377 auto on_create_ds_instance =
378 task_runner_->CreateCheckpoint("on_create_ds_instance");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200379 EXPECT_CALL(producer_, OnTracingSetup());
Primiano Tucci674076d2018-10-01 10:41:09 +0100380 EXPECT_CALL(producer_, SetupDataSource(_, _));
Primiano Tucciafb72b52018-09-25 09:37:24 +0100381 EXPECT_CALL(producer_, StartDataSource(_, _))
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100382 .WillOnce(Invoke([on_create_ds_instance, &global_buf_id](
383 DataSourceInstanceID, const DataSourceConfig& cfg) {
384 global_buf_id = static_cast<BufferID>(cfg.target_buffer());
385 on_create_ds_instance();
386 }));
387 task_runner_->RunUntilCheckpoint("on_create_ds_instance");
Primiano Tucci53589332017-12-19 11:31:13 +0100388
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100389 std::unique_ptr<TraceWriter> writer =
390 producer_endpoint_->CreateTraceWriter(global_buf_id);
391 ASSERT_TRUE(writer);
392
393 const size_t kNumPackets = 10;
394 for (size_t i = 0; i < kNumPackets; i++) {
395 char buf[16];
396 sprintf(buf, "evt_%zu", i);
397 writer->NewTracePacket()->set_for_testing()->set_str(buf, strlen(buf));
398 }
399 auto on_data_committed = task_runner_->CreateCheckpoint("on_data_committed");
400 writer->Flush(on_data_committed);
401 task_runner_->RunUntilCheckpoint("on_data_committed");
402
403 // Will disable tracing and will force the buffers to be written into the
404 // file before destroying them.
405 consumer_endpoint_->FreeBuffers();
406
Primiano Tuccidca727d2018-04-04 11:31:55 +0200407 auto on_tracing_disabled =
408 task_runner_->CreateCheckpoint("on_tracing_disabled");
Primiano Tucciafb72b52018-09-25 09:37:24 +0100409 EXPECT_CALL(producer_, StopDataSource(_));
Primiano Tuccidca727d2018-04-04 11:31:55 +0200410 EXPECT_CALL(consumer_, OnTracingDisabled())
411 .WillOnce(Invoke(on_tracing_disabled));
412 task_runner_->RunUntilCheckpoint("on_tracing_disabled");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100413
414 // Check that |tmp_file| contains a valid trace.proto message.
415 ASSERT_EQ(0, lseek(tmp_file.fd(), 0, SEEK_SET));
416 char tmp_buf[1024];
417 ssize_t rsize = read(tmp_file.fd(), tmp_buf, sizeof(tmp_buf));
418 ASSERT_GT(rsize, 0);
419 protos::Trace tmp_trace;
Primiano Tucci3cbb10a2018-04-10 17:52:40 +0100420 ASSERT_TRUE(tmp_trace.ParseFromArray(tmp_buf, static_cast<int>(rsize)));
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100421 size_t num_test_packet = 0;
Hector Dearman685f7522019-03-12 14:28:56 +0000422 size_t num_clock_snapshot_packet = 0;
423 size_t num_system_info_packet = 0;
Primiano Tucci5e33cad2018-04-30 14:41:25 +0100424 bool saw_trace_stats = false;
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100425 for (int i = 0; i < tmp_trace.packet_size(); i++) {
426 const protos::TracePacket& packet = tmp_trace.packet(i);
427 if (packet.has_for_testing()) {
428 ASSERT_EQ("evt_" + std::to_string(num_test_packet++),
429 packet.for_testing().str());
Primiano Tucci5e33cad2018-04-30 14:41:25 +0100430 } else if (packet.has_trace_stats()) {
431 saw_trace_stats = true;
432 CheckTraceStats(packet);
Hector Dearman685f7522019-03-12 14:28:56 +0000433 } else if (packet.has_clock_snapshot()) {
434 num_clock_snapshot_packet++;
435 } else if (packet.has_system_info()) {
436 num_system_info_packet++;
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100437 }
438 }
Primiano Tucci5e33cad2018-04-30 14:41:25 +0100439 ASSERT_TRUE(saw_trace_stats);
Hector Dearman685f7522019-03-12 14:28:56 +0000440 ASSERT_GT(num_clock_snapshot_packet, 0u);
441 ASSERT_GT(num_system_info_packet, 0u);
Primiano Tucci53589332017-12-19 11:31:13 +0100442}
443
Eric Seckler062ed502019-05-23 09:02:57 +0100444class TracingIntegrationTestWithSMBScrapingProducer
445 : public TracingIntegrationTest {
446 public:
447 TracingService::ProducerSMBScrapingMode GetProducerSMBScrapingMode()
448 override {
449 return TracingService::ProducerSMBScrapingMode::kEnabled;
450 }
451};
452
453TEST_F(TracingIntegrationTestWithSMBScrapingProducer, ScrapeOnFlush) {
454 // Start tracing.
455 TraceConfig trace_config;
456 trace_config.add_buffers()->set_size_kb(4096 * 10);
457 auto* ds_config = trace_config.add_data_sources()->mutable_config();
458 ds_config->set_name("perfetto.test");
459 ds_config->set_target_buffer(0);
460 consumer_endpoint_->EnableTracing(trace_config);
461
462 // At this point, the Producer should be asked to turn its data source on.
463
464 BufferID global_buf_id = 0;
465 auto on_create_ds_instance =
466 task_runner_->CreateCheckpoint("on_create_ds_instance");
467 EXPECT_CALL(producer_, OnTracingSetup());
468
469 EXPECT_CALL(producer_, SetupDataSource(_, _));
470 EXPECT_CALL(producer_, StartDataSource(_, _))
471 .WillOnce(Invoke([on_create_ds_instance, &global_buf_id](
472 DataSourceInstanceID, const DataSourceConfig& cfg) {
473 global_buf_id = static_cast<BufferID>(cfg.target_buffer());
474 on_create_ds_instance();
475 }));
476 task_runner_->RunUntilCheckpoint("on_create_ds_instance");
477
478 // Create writer, which will post a task to register the writer with the
479 // service.
480 std::unique_ptr<TraceWriter> writer =
481 producer_endpoint_->CreateTraceWriter(global_buf_id);
482 ASSERT_TRUE(writer);
483
484 // Wait for the writer to be registered.
485 WaitForTraceWritersChanged(*last_producer_id());
486
487 // Write a few trace packets.
488 writer->NewTracePacket()->set_for_testing()->set_str("payload1");
489 writer->NewTracePacket()->set_for_testing()->set_str("payload2");
490 writer->NewTracePacket()->set_for_testing()->set_str("payload3");
491
492 // Ask the service to flush, but don't flush our trace writer. This should
493 // cause our uncommitted SMB chunk to be scraped.
494 auto on_flush_complete = task_runner_->CreateCheckpoint("on_flush_complete");
495 consumer_endpoint_->Flush(5000, [on_flush_complete](bool success) {
496 EXPECT_TRUE(success);
497 on_flush_complete();
498 });
499 EXPECT_CALL(producer_, Flush(_, _, _))
500 .WillOnce(Invoke([this](FlushRequestID flush_req_id,
501 const DataSourceInstanceID*, size_t) {
502 producer_endpoint_->NotifyFlushComplete(flush_req_id);
503 }));
504 task_runner_->RunUntilCheckpoint("on_flush_complete");
505
506 // Read the log buffer. We should only see the first two written trace
507 // packets, because the service can't be sure the last one was written
508 // completely by the trace writer.
509 consumer_endpoint_->ReadBuffers();
510
511 size_t num_test_pack_rx = 0;
512 auto all_packets_rx = task_runner_->CreateCheckpoint("all_packets_rx");
513 EXPECT_CALL(consumer_, OnTracePackets(_, _))
514 .WillRepeatedly(
515 Invoke([&num_test_pack_rx, all_packets_rx](
516 std::vector<TracePacket>* packets, bool has_more) {
517 for (auto& encoded_packet : *packets) {
518 protos::TracePacket packet;
519 ASSERT_TRUE(encoded_packet.Decode(&packet));
520 if (packet.has_for_testing()) {
521 num_test_pack_rx++;
522 }
523 }
524 if (!has_more)
525 all_packets_rx();
526 }));
527 task_runner_->RunUntilCheckpoint("all_packets_rx");
Primiano Tuccifcd67252019-05-28 13:22:32 +0100528 ASSERT_EQ(2u, num_test_pack_rx);
Eric Seckler062ed502019-05-23 09:02:57 +0100529
530 // Disable tracing.
531 consumer_endpoint_->DisableTracing();
532
533 auto on_tracing_disabled =
534 task_runner_->CreateCheckpoint("on_tracing_disabled");
535 EXPECT_CALL(producer_, StopDataSource(_));
536 EXPECT_CALL(consumer_, OnTracingDisabled())
537 .WillOnce(Invoke(on_tracing_disabled));
538 task_runner_->RunUntilCheckpoint("on_tracing_disabled");
539}
540
Primiano Tucci53589332017-12-19 11:31:13 +0100541// TODO(primiano): add tests to cover:
542// - unknown fields preserved end-to-end.
543// - >1 data source.
544// - >1 data consumer sharing the same data source, with different TraceBuffers.
Primiano Tucci20d441d2018-01-16 09:25:51 +0000545// - >1 consumer with > 1 buffer each.
546// - Consumer disconnecting in the middle of a ReadBuffers() call.
547// - Multiple calls to DisableTracing.
548// - Out of order Enable/Disable/FreeBuffers calls.
549// - DisableTracing does actually freeze the buffers.
Primiano Tucci53589332017-12-19 11:31:13 +0100550
Primiano Tucci53589332017-12-19 11:31:13 +0100551} // namespace perfetto