blob: c679c5239334c17274cf8ef9b788027a4c17cff3 [file] [log] [blame]
Primiano Tucci4f9b6d72017-12-05 20:59:16 +00001/*
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
Florian Mayer6a1a4d52018-06-08 16:47:07 +010017#include "src/tracing/core/tracing_service_impl.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000018
19#include <string.h>
20
21#include "gmock/gmock.h"
22#include "gtest/gtest.h"
Primiano Tucci2ffd1a52018-03-27 01:01:30 +010023#include "perfetto/base/file_utils.h"
24#include "perfetto/base/temp_file.h"
Primiano Tucci1a1951d2018-04-04 21:08:16 +020025#include "perfetto/base/utils.h"
Sami Kyostila06487a22018-02-27 13:48:38 +000026#include "perfetto/tracing/core/consumer.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000027#include "perfetto/tracing/core/data_source_config.h"
28#include "perfetto/tracing/core/data_source_descriptor.h"
29#include "perfetto/tracing/core/producer.h"
30#include "perfetto/tracing/core/shared_memory.h"
Sami Kyostila06487a22018-02-27 13:48:38 +000031#include "perfetto/tracing/core/trace_packet.h"
Primiano Tucci2ffd1a52018-03-27 01:01:30 +010032#include "perfetto/tracing/core/trace_writer.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000033#include "src/base/test/test_task_runner.h"
Eric Secklera01e28a2019-01-08 11:21:04 +000034#include "src/tracing/core/shared_memory_arbiter_impl.h"
Eric Secklerf3f524b2018-12-13 09:09:34 +000035#include "src/tracing/core/trace_writer_impl.h"
Primiano Tuccidca727d2018-04-04 11:31:55 +020036#include "src/tracing/test/mock_consumer.h"
37#include "src/tracing/test/mock_producer.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000038#include "src/tracing/test/test_shared_memory.h"
39
Primiano Tucci2ffd1a52018-03-27 01:01:30 +010040#include "perfetto/trace/test_event.pbzero.h"
41#include "perfetto/trace/trace.pb.h"
Primiano Tuccidca727d2018-04-04 11:31:55 +020042#include "perfetto/trace/trace_packet.pb.h"
Primiano Tucci2ffd1a52018-03-27 01:01:30 +010043#include "perfetto/trace/trace_packet.pbzero.h"
44
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000045using ::testing::_;
Primiano Tuccidca727d2018-04-04 11:31:55 +020046using ::testing::Contains;
Primiano Tucci1a1951d2018-04-04 21:08:16 +020047using ::testing::ElementsAreArray;
Primiano Tuccidca727d2018-04-04 11:31:55 +020048using ::testing::Eq;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000049using ::testing::InSequence;
Primiano Tucci081d46a2018-02-28 11:09:43 +000050using ::testing::Invoke;
Primiano Tuccidca727d2018-04-04 11:31:55 +020051using ::testing::InvokeWithoutArgs;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000052using ::testing::Mock;
Eric Secklerdd0ad102018-12-06 11:32:04 +000053using ::testing::Not;
Primiano Tuccidca727d2018-04-04 11:31:55 +020054using ::testing::Property;
55using ::testing::StrictMock;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000056
Primiano Tuccidca727d2018-04-04 11:31:55 +020057namespace perfetto {
Sami Kyostila32e0b542018-02-14 08:55:43 +000058
Primiano Tucci1a1951d2018-04-04 21:08:16 +020059namespace {
Florian Mayer6a1a4d52018-06-08 16:47:07 +010060constexpr size_t kDefaultShmSizeKb = TracingServiceImpl::kDefaultShmSize / 1024;
61constexpr size_t kMaxShmSizeKb = TracingServiceImpl::kMaxShmSize / 1024;
Primiano Tucci1a1951d2018-04-04 21:08:16 +020062} // namespace
63
Florian Mayer6a1a4d52018-06-08 16:47:07 +010064class TracingServiceImplTest : public testing::Test {
Sami Kyostila06487a22018-02-27 13:48:38 +000065 public:
Florian Mayer6a1a4d52018-06-08 16:47:07 +010066 TracingServiceImplTest() {
Sami Kyostila06487a22018-02-27 13:48:38 +000067 auto shm_factory =
68 std::unique_ptr<SharedMemory::Factory>(new TestSharedMemory::Factory());
Florian Mayer6a1a4d52018-06-08 16:47:07 +010069 svc.reset(static_cast<TracingServiceImpl*>(
70 TracingService::CreateInstance(std::move(shm_factory), &task_runner)
Sami Kyostila06487a22018-02-27 13:48:38 +000071 .release()));
Primiano Tucci9754d0d2018-09-15 12:41:46 +010072 svc->min_write_period_ms_ = 1;
Sami Kyostila06487a22018-02-27 13:48:38 +000073 }
74
Primiano Tuccidca727d2018-04-04 11:31:55 +020075 std::unique_ptr<MockProducer> CreateMockProducer() {
76 return std::unique_ptr<MockProducer>(
77 new StrictMock<MockProducer>(&task_runner));
78 }
79
80 std::unique_ptr<MockConsumer> CreateMockConsumer() {
81 return std::unique_ptr<MockConsumer>(
82 new StrictMock<MockConsumer>(&task_runner));
83 }
84
Primiano Tucci1a1951d2018-04-04 21:08:16 +020085 ProducerID* last_producer_id() { return &svc->last_producer_id_; }
86
87 uid_t GetProducerUid(ProducerID producer_id) {
88 return svc->GetProducer(producer_id)->uid_;
89 }
90
Primiano Tucci9754d0d2018-09-15 12:41:46 +010091 TracingServiceImpl::TracingSession* tracing_session() {
92 auto* session = svc->GetTracingSession(svc->last_tracing_session_id_);
93 EXPECT_NE(nullptr, session);
94 return session;
95 }
96
Eric Seckler6dc23592018-11-30 10:59:06 +000097 const std::set<BufferID>& GetAllowedTargetBuffers(ProducerID producer_id) {
98 return svc->GetProducer(producer_id)->allowed_target_buffers_;
99 }
100
Eric Secklerf3f524b2018-12-13 09:09:34 +0000101 const std::map<WriterID, BufferID>& GetWriters(ProducerID producer_id) {
102 return svc->GetProducer(producer_id)->writers_;
103 }
104
Eric Secklera01e28a2019-01-08 11:21:04 +0000105 std::unique_ptr<SharedMemoryArbiterImpl> TakeShmemArbiterForProducer(
106 ProducerID producer_id) {
107 return std::move(svc->GetProducer(producer_id)->inproc_shmem_arbiter_);
108 }
109
Primiano Tuccid52e6272018-04-06 19:06:53 +0200110 size_t GetNumPendingFlushes() {
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100111 return tracing_session()->pending_flushes.size();
112 }
113
114 void WaitForNextSyncMarker() {
115 tracing_session()->last_snapshot_time = base::TimeMillis(0);
116 static int attempt = 0;
117 while (tracing_session()->last_snapshot_time == base::TimeMillis(0)) {
118 auto checkpoint_name = "wait_snapshot_" + std::to_string(attempt++);
119 auto timer_expired = task_runner.CreateCheckpoint(checkpoint_name);
120 task_runner.PostDelayedTask([timer_expired] { timer_expired(); }, 1);
121 task_runner.RunUntilCheckpoint(checkpoint_name);
122 }
Primiano Tuccid52e6272018-04-06 19:06:53 +0200123 }
124
Eric Secklerf3f524b2018-12-13 09:09:34 +0000125 void WaitForTraceWritersChanged(ProducerID producer_id) {
126 static int i = 0;
127 auto checkpoint_name = "writers_changed_" + std::to_string(producer_id) +
128 "_" + std::to_string(i++);
129 auto writers_changed = task_runner.CreateCheckpoint(checkpoint_name);
130 auto writers = GetWriters(producer_id);
131 std::function<void()> task;
132 task = [&task, writers, writers_changed, producer_id, this]() {
133 if (writers != GetWriters(producer_id)) {
134 writers_changed();
135 return;
136 }
137 task_runner.PostDelayedTask(task, 1);
138 };
139 task_runner.PostDelayedTask(task, 1);
140 task_runner.RunUntilCheckpoint(checkpoint_name);
141 }
142
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000143 base::TestTaskRunner task_runner;
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100144 std::unique_ptr<TracingServiceImpl> svc;
Sami Kyostila06487a22018-02-27 13:48:38 +0000145};
146
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100147TEST_F(TracingServiceImplTest, RegisterAndUnregister) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200148 std::unique_ptr<MockProducer> mock_producer_1 = CreateMockProducer();
149 std::unique_ptr<MockProducer> mock_producer_2 = CreateMockProducer();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000150
Primiano Tuccidca727d2018-04-04 11:31:55 +0200151 mock_producer_1->Connect(svc.get(), "mock_producer_1", 123u /* uid */);
152 mock_producer_2->Connect(svc.get(), "mock_producer_2", 456u /* uid */);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000153
154 ASSERT_EQ(2u, svc->num_producers());
Primiano Tuccidca727d2018-04-04 11:31:55 +0200155 ASSERT_EQ(mock_producer_1->endpoint(), svc->GetProducer(1));
156 ASSERT_EQ(mock_producer_2->endpoint(), svc->GetProducer(2));
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200157 ASSERT_EQ(123u, GetProducerUid(1));
158 ASSERT_EQ(456u, GetProducerUid(2));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000159
Primiano Tuccidca727d2018-04-04 11:31:55 +0200160 mock_producer_1->RegisterDataSource("foo");
161 mock_producer_2->RegisterDataSource("bar");
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000162
Primiano Tuccidca727d2018-04-04 11:31:55 +0200163 mock_producer_1->UnregisterDataSource("foo");
164 mock_producer_2->UnregisterDataSource("bar");
Primiano Tucci9daa4832018-03-28 23:28:17 +0100165
Primiano Tuccidca727d2018-04-04 11:31:55 +0200166 mock_producer_1.reset();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000167 ASSERT_EQ(1u, svc->num_producers());
168 ASSERT_EQ(nullptr, svc->GetProducer(1));
169
Primiano Tuccidca727d2018-04-04 11:31:55 +0200170 mock_producer_2.reset();
171 ASSERT_EQ(nullptr, svc->GetProducer(2));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000172
173 ASSERT_EQ(0u, svc->num_producers());
174}
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100175
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100176TEST_F(TracingServiceImplTest, EnableAndDisableTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200177 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
178 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000179
Primiano Tuccidca727d2018-04-04 11:31:55 +0200180 std::unique_ptr<MockProducer> producer = CreateMockProducer();
181 producer->Connect(svc.get(), "mock_producer");
182 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000183
Sami Kyostila06487a22018-02-27 13:48:38 +0000184 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200185 trace_config.add_buffers()->set_size_kb(128);
Sami Kyostila06487a22018-02-27 13:48:38 +0000186 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200187 ds_config->set_name("data_source");
188 consumer->EnableTracing(trace_config);
Sami Kyostila06487a22018-02-27 13:48:38 +0000189
Primiano Tuccidca727d2018-04-04 11:31:55 +0200190 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100191 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200192 producer->WaitForDataSourceStart("data_source");
193
Primiano Tucci674076d2018-10-01 10:41:09 +0100194 // Calling StartTracing() should be a noop (% a DLOG statement) because the
195 // trace config didn't have the |deferred_start| flag set.
196 consumer->StartTracing();
197
Primiano Tuccidca727d2018-04-04 11:31:55 +0200198 consumer->DisableTracing();
199 producer->WaitForDataSourceStop("data_source");
200 consumer->WaitForTracingDisabled();
Sami Kyostila06487a22018-02-27 13:48:38 +0000201}
202
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100203TEST_F(TracingServiceImplTest, LockdownMode) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200204 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
205 consumer->Connect(svc.get());
206
207 std::unique_ptr<MockProducer> producer = CreateMockProducer();
208 producer->Connect(svc.get(), "mock_producer_sameuid", geteuid());
209 producer->RegisterDataSource("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000210
211 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200212 trace_config.add_buffers()->set_size_kb(128);
213 auto* ds_config = trace_config.add_data_sources()->mutable_config();
214 ds_config->set_name("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000215 trace_config.set_lockdown_mode(
216 TraceConfig::LockdownModeOperation::LOCKDOWN_SET);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200217 consumer->EnableTracing(trace_config);
218
219 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100220 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200221 producer->WaitForDataSourceStart("data_source");
222
223 std::unique_ptr<MockProducer> producer_otheruid = CreateMockProducer();
224 auto x = svc->ConnectProducer(producer_otheruid.get(), geteuid() + 1,
225 "mock_producer_ouid");
226 EXPECT_CALL(*producer_otheruid, OnConnect()).Times(0);
Florian Mayer61c55482018-03-06 14:43:54 +0000227 task_runner.RunUntilIdle();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200228 Mock::VerifyAndClearExpectations(producer_otheruid.get());
Florian Mayer61c55482018-03-06 14:43:54 +0000229
Primiano Tuccidca727d2018-04-04 11:31:55 +0200230 consumer->DisableTracing();
231 consumer->FreeBuffers();
232 producer->WaitForDataSourceStop("data_source");
233 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000234
235 trace_config.set_lockdown_mode(
236 TraceConfig::LockdownModeOperation::LOCKDOWN_CLEAR);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200237 consumer->EnableTracing(trace_config);
Primiano Tucci674076d2018-10-01 10:41:09 +0100238 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200239 producer->WaitForDataSourceStart("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000240
Primiano Tuccidca727d2018-04-04 11:31:55 +0200241 std::unique_ptr<MockProducer> producer_otheruid2 = CreateMockProducer();
242 producer_otheruid->Connect(svc.get(), "mock_producer_ouid2", geteuid() + 1);
Florian Mayer61c55482018-03-06 14:43:54 +0000243
Primiano Tuccidca727d2018-04-04 11:31:55 +0200244 consumer->DisableTracing();
245 producer->WaitForDataSourceStop("data_source");
246 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000247}
248
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100249TEST_F(TracingServiceImplTest, DisconnectConsumerWhileTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200250 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
251 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000252
Primiano Tuccidca727d2018-04-04 11:31:55 +0200253 std::unique_ptr<MockProducer> producer = CreateMockProducer();
254 producer->Connect(svc.get(), "mock_producer");
255 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000256
Primiano Tuccidca727d2018-04-04 11:31:55 +0200257 TraceConfig trace_config;
258 trace_config.add_buffers()->set_size_kb(128);
259 auto* ds_config = trace_config.add_data_sources()->mutable_config();
260 ds_config->set_name("data_source");
261 consumer->EnableTracing(trace_config);
262
263 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100264 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200265 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000266
267 // Disconnecting the consumer while tracing should trigger data source
268 // teardown.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200269 consumer.reset();
270 producer->WaitForDataSourceStop("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000271}
272
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100273TEST_F(TracingServiceImplTest, ReconnectProducerWhileTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200274 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
275 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000276
Primiano Tuccidca727d2018-04-04 11:31:55 +0200277 std::unique_ptr<MockProducer> producer = CreateMockProducer();
278 producer->Connect(svc.get(), "mock_producer");
279 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000280
Sami Kyostila06487a22018-02-27 13:48:38 +0000281 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200282 trace_config.add_buffers()->set_size_kb(128);
Sami Kyostila06487a22018-02-27 13:48:38 +0000283 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200284 ds_config->set_name("data_source");
285 consumer->EnableTracing(trace_config);
Sami Kyostila06487a22018-02-27 13:48:38 +0000286
Primiano Tuccidca727d2018-04-04 11:31:55 +0200287 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100288 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200289 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000290
Primiano Tuccidca727d2018-04-04 11:31:55 +0200291 // Disconnecting and reconnecting a producer with a matching data source.
292 // The Producer should see that data source getting enabled again.
293 producer.reset();
294 producer = CreateMockProducer();
295 producer->Connect(svc.get(), "mock_producer_2");
296 producer->RegisterDataSource("data_source");
297 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100298 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200299 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000300}
301
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100302TEST_F(TracingServiceImplTest, ProducerIDWrapping) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200303 std::vector<std::unique_ptr<MockProducer>> producers;
304 producers.push_back(nullptr);
Primiano Tucci081d46a2018-02-28 11:09:43 +0000305
Primiano Tuccidca727d2018-04-04 11:31:55 +0200306 auto connect_producer_and_get_id = [&producers,
307 this](const std::string& name) {
308 producers.emplace_back(CreateMockProducer());
309 producers.back()->Connect(svc.get(), "mock_producer_" + name);
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200310 return *last_producer_id();
Primiano Tucci081d46a2018-02-28 11:09:43 +0000311 };
312
313 // Connect producers 1-4.
314 for (ProducerID i = 1; i <= 4; i++)
Primiano Tuccidca727d2018-04-04 11:31:55 +0200315 ASSERT_EQ(i, connect_producer_and_get_id(std::to_string(i)));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000316
317 // Disconnect producers 1,3.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200318 producers[1].reset();
319 producers[3].reset();
Primiano Tucci081d46a2018-02-28 11:09:43 +0000320
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200321 *last_producer_id() = kMaxProducerID - 1;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200322 ASSERT_EQ(kMaxProducerID, connect_producer_and_get_id("maxid"));
323 ASSERT_EQ(1u, connect_producer_and_get_id("1_again"));
324 ASSERT_EQ(3u, connect_producer_and_get_id("3_again"));
325 ASSERT_EQ(5u, connect_producer_and_get_id("5"));
326 ASSERT_EQ(6u, connect_producer_and_get_id("6"));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000327}
328
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000329// Note: file_write_period_ms is set to a large enough to have exactly one flush
330// of the tracing buffers (and therefore at most one synchronization section),
331// unless the test runs unrealistically slowly, or the implementation of the
332// tracing snapshot packets changes.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100333TEST_F(TracingServiceImplTest, WriteIntoFileAndStopOnMaxSize) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200334 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
335 consumer->Connect(svc.get());
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100336
Primiano Tuccidca727d2018-04-04 11:31:55 +0200337 std::unique_ptr<MockProducer> producer = CreateMockProducer();
338 producer->Connect(svc.get(), "mock_producer");
339 producer->RegisterDataSource("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100340
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100341 TraceConfig trace_config;
342 trace_config.add_buffers()->set_size_kb(4096);
343 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200344 ds_config->set_name("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100345 ds_config->set_target_buffer(0);
346 trace_config.set_write_into_file(true);
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000347 trace_config.set_file_write_period_ms(100000); // 100s
348 const uint64_t kMaxFileSize = 1024;
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100349 trace_config.set_max_file_size_bytes(kMaxFileSize);
350 base::TempFile tmp_file = base::TempFile::Create();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200351 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
352
353 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100354 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200355 producer->WaitForDataSourceStart("data_source");
356
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000357 static const int kNumPreamblePackets = 4;
358 static const int kNumTestPackets = 10;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200359 static const char kPayload[] = "1234567890abcdef-";
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100360
361 std::unique_ptr<TraceWriter> writer =
Primiano Tuccidca727d2018-04-04 11:31:55 +0200362 producer->CreateTraceWriter("data_source");
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000363 // Tracing service will emit a preamble of packets (a synchronization section,
364 // followed by a tracing config packet). The preamble and these test packets
365 // should fit within kMaxFileSize.
366 for (int i = 0; i < kNumTestPackets; i++) {
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100367 auto tp = writer->NewTracePacket();
368 std::string payload(kPayload);
369 payload.append(std::to_string(i));
370 tp->set_for_testing()->set_str(payload.c_str(), payload.size());
371 }
372
373 // Finally add a packet that overflows kMaxFileSize. This should cause the
374 // implicit stop of the trace and should *not* be written in the trace.
375 {
376 auto tp = writer->NewTracePacket();
377 char big_payload[kMaxFileSize] = "BIG!";
378 tp->set_for_testing()->set_str(big_payload, sizeof(big_payload));
379 }
380 writer->Flush();
381 writer.reset();
382
Primiano Tuccidca727d2018-04-04 11:31:55 +0200383 consumer->DisableTracing();
384 producer->WaitForDataSourceStop("data_source");
385 consumer->WaitForTracingDisabled();
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100386
387 // Verify the contents of the file.
388 std::string trace_raw;
389 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
390 protos::Trace trace;
391 ASSERT_TRUE(trace.ParseFromString(trace_raw));
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000392
393 ASSERT_EQ(trace.packet_size(), kNumPreamblePackets + kNumTestPackets);
394 for (int i = 0; i < kNumTestPackets; i++) {
395 const protos::TracePacket& tp = trace.packet(kNumPreamblePackets + i);
396 ASSERT_EQ(kPayload + std::to_string(i++), tp.for_testing().str());
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100397 }
Primiano Tuccidca727d2018-04-04 11:31:55 +0200398}
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100399
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200400// Test the logic that allows the trace config to set the shm total size and
401// page size from the trace config. Also check that, if the config doesn't
402// specify a value we fall back on the hint provided by the producer.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100403TEST_F(TracingServiceImplTest, ProducerShmAndPageSizeOverriddenByTraceConfig) {
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200404 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
405 consumer->Connect(svc.get());
406 const size_t kConfigPageSizesKb[] = /****/ {16, 16, 4, 0, 16, 8, 3, 4096, 4};
407 const size_t kExpectedPageSizesKb[] = /**/ {16, 16, 4, 4, 16, 8, 4, 64, 4};
408
409 const size_t kConfigSizesKb[] = /**/ {0, 16, 0, 20, 32, 7, 0, 96, 4096000};
410 const size_t kHintSizesKb[] = /****/ {0, 0, 16, 32, 16, 0, 7, 96, 4096000};
411 const size_t kExpectedSizesKb[] = {
412 kDefaultShmSizeKb, // Both hint and config are 0, use default.
413 16, // Hint is 0, use config.
414 16, // Config is 0, use hint.
415 20, // Hint is takes precedence over the config.
416 32, // Ditto, even if config is higher than hint.
417 kDefaultShmSizeKb, // Config is invalid and hint is 0, use default.
418 kDefaultShmSizeKb, // Config is 0 and hint is invalid, use default.
419 kDefaultShmSizeKb, // 96 KB isn't a multiple of the page size (64 KB).
420 kMaxShmSizeKb // Too big, cap at kMaxShmSize.
421 };
422
423 const size_t kNumProducers = base::ArraySize(kHintSizesKb);
424 std::unique_ptr<MockProducer> producer[kNumProducers];
425 for (size_t i = 0; i < kNumProducers; i++) {
426 auto name = "mock_producer_" + std::to_string(i);
427 producer[i] = CreateMockProducer();
428 producer[i]->Connect(svc.get(), name, geteuid(), kHintSizesKb[i] * 1024);
429 producer[i]->RegisterDataSource("data_source");
430 }
431
432 TraceConfig trace_config;
433 trace_config.add_buffers()->set_size_kb(128);
434 auto* ds_config = trace_config.add_data_sources()->mutable_config();
435 ds_config->set_name("data_source");
436 for (size_t i = 0; i < kNumProducers; i++) {
437 auto* producer_config = trace_config.add_producers();
438 producer_config->set_producer_name("mock_producer_" + std::to_string(i));
Primiano Tucci3cbb10a2018-04-10 17:52:40 +0100439 producer_config->set_shm_size_kb(static_cast<uint32_t>(kConfigSizesKb[i]));
440 producer_config->set_page_size_kb(
441 static_cast<uint32_t>(kConfigPageSizesKb[i]));
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200442 }
443
444 consumer->EnableTracing(trace_config);
445 size_t actual_shm_sizes_kb[kNumProducers]{};
446 size_t actual_page_sizes_kb[kNumProducers]{};
447 for (size_t i = 0; i < kNumProducers; i++) {
448 producer[i]->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100449 producer[i]->WaitForDataSourceSetup("data_source");
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200450 actual_shm_sizes_kb[i] =
451 producer[i]->endpoint()->shared_memory()->size() / 1024;
452 actual_page_sizes_kb[i] =
453 producer[i]->endpoint()->shared_buffer_page_size_kb();
454 }
Primiano Tucci674076d2018-10-01 10:41:09 +0100455 for (size_t i = 0; i < kNumProducers; i++) {
456 producer[i]->WaitForDataSourceStart("data_source");
457 }
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200458 ASSERT_THAT(actual_page_sizes_kb, ElementsAreArray(kExpectedPageSizesKb));
459 ASSERT_THAT(actual_shm_sizes_kb, ElementsAreArray(kExpectedSizesKb));
460}
461
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100462TEST_F(TracingServiceImplTest, ExplicitFlush) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200463 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
464 consumer->Connect(svc.get());
465
466 std::unique_ptr<MockProducer> producer = CreateMockProducer();
467 producer->Connect(svc.get(), "mock_producer");
468 producer->RegisterDataSource("data_source");
469
470 TraceConfig trace_config;
471 trace_config.add_buffers()->set_size_kb(128);
472 auto* ds_config = trace_config.add_data_sources()->mutable_config();
473 ds_config->set_name("data_source");
474
475 consumer->EnableTracing(trace_config);
476 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100477 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccid52e6272018-04-06 19:06:53 +0200478 producer->WaitForDataSourceStart("data_source");
479
480 std::unique_ptr<TraceWriter> writer =
481 producer->CreateTraceWriter("data_source");
482 {
483 auto tp = writer->NewTracePacket();
484 tp->set_for_testing()->set_str("payload");
485 }
486
487 auto flush_request = consumer->Flush();
488 producer->WaitForFlush(writer.get());
489 ASSERT_TRUE(flush_request.WaitForReply());
490
491 consumer->DisableTracing();
492 producer->WaitForDataSourceStop("data_source");
493 consumer->WaitForTracingDisabled();
494 EXPECT_THAT(
495 consumer->ReadBuffers(),
496 Contains(Property(&protos::TracePacket::for_testing,
497 Property(&protos::TestEvent::str, Eq("payload")))));
498}
499
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100500TEST_F(TracingServiceImplTest, ImplicitFlushOnTimedTraces) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200501 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
502 consumer->Connect(svc.get());
503
504 std::unique_ptr<MockProducer> producer = CreateMockProducer();
505 producer->Connect(svc.get(), "mock_producer");
506 producer->RegisterDataSource("data_source");
507
508 TraceConfig trace_config;
509 trace_config.add_buffers()->set_size_kb(128);
510 auto* ds_config = trace_config.add_data_sources()->mutable_config();
511 ds_config->set_name("data_source");
512 trace_config.set_duration_ms(1);
513
514 consumer->EnableTracing(trace_config);
515 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100516 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccid52e6272018-04-06 19:06:53 +0200517 producer->WaitForDataSourceStart("data_source");
518
519 std::unique_ptr<TraceWriter> writer =
520 producer->CreateTraceWriter("data_source");
521 {
522 auto tp = writer->NewTracePacket();
523 tp->set_for_testing()->set_str("payload");
524 }
525
526 producer->WaitForFlush(writer.get());
527
528 producer->WaitForDataSourceStop("data_source");
529 consumer->WaitForTracingDisabled();
530
531 EXPECT_THAT(
532 consumer->ReadBuffers(),
533 Contains(Property(&protos::TracePacket::for_testing,
534 Property(&protos::TestEvent::str, Eq("payload")))));
535}
536
537// Tests the monotonic semantic of flush request IDs, i.e., once a producer
538// acks flush request N, all flush requests <= N are considered successful and
539// acked to the consumer.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100540TEST_F(TracingServiceImplTest, BatchFlushes) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200541 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
542 consumer->Connect(svc.get());
543
544 std::unique_ptr<MockProducer> producer = CreateMockProducer();
545 producer->Connect(svc.get(), "mock_producer");
546 producer->RegisterDataSource("data_source");
547
548 TraceConfig trace_config;
549 trace_config.add_buffers()->set_size_kb(128);
550 auto* ds_config = trace_config.add_data_sources()->mutable_config();
551 ds_config->set_name("data_source");
552
553 consumer->EnableTracing(trace_config);
554 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100555 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccid52e6272018-04-06 19:06:53 +0200556 producer->WaitForDataSourceStart("data_source");
557
558 std::unique_ptr<TraceWriter> writer =
559 producer->CreateTraceWriter("data_source");
560 {
561 auto tp = writer->NewTracePacket();
562 tp->set_for_testing()->set_str("payload");
563 }
564
565 auto flush_req_1 = consumer->Flush();
566 auto flush_req_2 = consumer->Flush();
567 auto flush_req_3 = consumer->Flush();
568
569 // We'll deliberately let the 4th flush request timeout. Use a lower timeout
570 // to keep test time short.
571 auto flush_req_4 = consumer->Flush(/*timeout_ms=*/10);
572 ASSERT_EQ(4u, GetNumPendingFlushes());
573
574 // Make the producer reply only to the 3rd flush request.
575 testing::InSequence seq;
Eric Secklera01e28a2019-01-08 11:21:04 +0000576 producer->WaitForFlush(nullptr, /*reply=*/false); // Do NOT reply to flush 1.
577 producer->WaitForFlush(nullptr, /*reply=*/false); // Do NOT reply to flush 2.
578 producer->WaitForFlush(writer.get()); // Reply only to flush 3.
579 producer->WaitForFlush(nullptr, /*reply=*/false); // Do NOT reply to flush 4.
Primiano Tuccid52e6272018-04-06 19:06:53 +0200580
581 // Even if the producer explicily replied only to flush ID == 3, all the
582 // previous flushed < 3 should be implicitly acked.
583 ASSERT_TRUE(flush_req_1.WaitForReply());
584 ASSERT_TRUE(flush_req_2.WaitForReply());
585 ASSERT_TRUE(flush_req_3.WaitForReply());
586
587 // At this point flush id == 4 should still be pending and should fail because
588 // of reaching its timeout.
Primiano Tuccid52e6272018-04-06 19:06:53 +0200589 ASSERT_FALSE(flush_req_4.WaitForReply());
590
591 consumer->DisableTracing();
592 producer->WaitForDataSourceStop("data_source");
593 consumer->WaitForTracingDisabled();
594 EXPECT_THAT(
595 consumer->ReadBuffers(),
596 Contains(Property(&protos::TracePacket::for_testing,
597 Property(&protos::TestEvent::str, Eq("payload")))));
598}
599
Primiano Tuccicaa57802018-11-25 11:07:07 +0000600TEST_F(TracingServiceImplTest, PeriodicFlush) {
601 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
602 consumer->Connect(svc.get());
603
604 std::unique_ptr<MockProducer> producer = CreateMockProducer();
605 producer->Connect(svc.get(), "mock_producer");
606 producer->RegisterDataSource("data_source");
607
608 TraceConfig trace_config;
609 trace_config.add_buffers()->set_size_kb(128);
610 trace_config.set_flush_period_ms(1);
611 auto* ds_config = trace_config.add_data_sources()->mutable_config();
612 ds_config->set_name("data_source");
613
614 consumer->EnableTracing(trace_config);
615 producer->WaitForTracingSetup();
616 producer->WaitForDataSourceSetup("data_source");
617 producer->WaitForDataSourceStart("data_source");
618
619 std::unique_ptr<TraceWriter> writer =
620 producer->CreateTraceWriter("data_source");
621
622 const int kNumFlushes = 3;
623 auto checkpoint = task_runner.CreateCheckpoint("all_flushes_done");
624 int flushes_seen = 0;
625 EXPECT_CALL(*producer, Flush(_, _, _))
626 .WillRepeatedly(Invoke([&producer, &writer, &flushes_seen, checkpoint](
627 FlushRequestID flush_req_id,
628 const DataSourceInstanceID*, size_t) {
629 {
630 auto tp = writer->NewTracePacket();
631 char payload[32];
632 sprintf(payload, "f_%d", flushes_seen);
633 tp->set_for_testing()->set_str(payload);
634 }
635 writer->Flush();
636 producer->endpoint()->NotifyFlushComplete(flush_req_id);
637 if (++flushes_seen == kNumFlushes)
638 checkpoint();
639 }));
640 task_runner.RunUntilCheckpoint("all_flushes_done");
641
642 consumer->DisableTracing();
643 producer->WaitForDataSourceStop("data_source");
644 consumer->WaitForTracingDisabled();
645 auto trace_packets = consumer->ReadBuffers();
646 for (int i = 0; i < kNumFlushes; i++) {
647 EXPECT_THAT(trace_packets,
648 Contains(Property(&protos::TracePacket::for_testing,
649 Property(&protos::TestEvent::str,
650 Eq("f_" + std::to_string(i))))));
651 }
652}
653
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100654// Creates a tracing session where some of the data sources set the
655// |will_notify_on_stop| flag and checks that the OnTracingDisabled notification
656// to the consumer is delayed until the acks are received.
657TEST_F(TracingServiceImplTest, OnTracingDisabledWaitsForDataSourceStopAcks) {
658 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
659 consumer->Connect(svc.get());
660
661 std::unique_ptr<MockProducer> producer = CreateMockProducer();
662 producer->Connect(svc.get(), "mock_producer");
663 producer->RegisterDataSource("ds_will_ack_1", /*ack_stop=*/true);
664 producer->RegisterDataSource("ds_wont_ack");
665 producer->RegisterDataSource("ds_will_ack_2", /*ack_stop=*/true);
666
667 TraceConfig trace_config;
668 trace_config.add_buffers()->set_size_kb(128);
669 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack_1");
670 trace_config.add_data_sources()->mutable_config()->set_name("ds_wont_ack");
671 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack_2");
672 trace_config.set_duration_ms(1);
673
674 consumer->EnableTracing(trace_config);
675 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100676
677 producer->WaitForDataSourceSetup("ds_will_ack_1");
678 producer->WaitForDataSourceSetup("ds_wont_ack");
679 producer->WaitForDataSourceSetup("ds_will_ack_2");
680
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100681 producer->WaitForDataSourceStart("ds_will_ack_1");
682 producer->WaitForDataSourceStart("ds_wont_ack");
683 producer->WaitForDataSourceStart("ds_will_ack_2");
684
685 std::unique_ptr<TraceWriter> writer =
686 producer->CreateTraceWriter("ds_wont_ack");
687 producer->WaitForFlush(writer.get());
688
689 DataSourceInstanceID id1 = producer->GetDataSourceInstanceId("ds_will_ack_1");
690 DataSourceInstanceID id2 = producer->GetDataSourceInstanceId("ds_will_ack_2");
691
692 producer->WaitForDataSourceStop("ds_will_ack_1");
693 producer->WaitForDataSourceStop("ds_wont_ack");
694 producer->WaitForDataSourceStop("ds_will_ack_2");
695
696 producer->endpoint()->NotifyDataSourceStopped(id1);
697 producer->endpoint()->NotifyDataSourceStopped(id2);
698
699 // Wait for at most half of the service timeout, so that this test fails if
700 // the service falls back on calling the OnTracingDisabled() because some of
701 // the expected acks weren't received.
702 consumer->WaitForTracingDisabled(
703 TracingServiceImpl::kDataSourceStopTimeoutMs / 2);
704}
705
Oystein Eftevaagf250e1c2018-08-23 16:10:52 -0700706// Creates a tracing session where a second data source
707// is added while the service is waiting for DisableTracing
708// acks; the service should not enable the new datasource
709// and should not hit any asserts when the consumer is
710// subsequently destroyed.
711TEST_F(TracingServiceImplTest, OnDataSourceAddedWhilePendingDisableAcks) {
712 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
713 consumer->Connect(svc.get());
714
715 std::unique_ptr<MockProducer> producer = CreateMockProducer();
716 producer->Connect(svc.get(), "mock_producer");
717 producer->RegisterDataSource("ds_will_ack", /*ack_stop=*/true);
718
719 TraceConfig trace_config;
720 trace_config.add_buffers()->set_size_kb(128);
721 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack");
722 trace_config.add_data_sources()->mutable_config()->set_name("ds_wont_ack");
723
724 consumer->EnableTracing(trace_config);
725 producer->WaitForTracingSetup();
726
727 consumer->DisableTracing();
728
729 producer->RegisterDataSource("ds_wont_ack");
730
731 consumer.reset();
732}
733
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100734// Similar to OnTracingDisabledWaitsForDataSourceStopAcks, but deliberately
735// skips the ack and checks that the service invokes the OnTracingDisabled()
736// after the timeout.
737TEST_F(TracingServiceImplTest, OnTracingDisabledCalledAnywaysInCaseOfTimeout) {
738 svc->override_data_source_test_timeout_ms_for_testing = 1;
739 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
740 consumer->Connect(svc.get());
741
742 std::unique_ptr<MockProducer> producer = CreateMockProducer();
743 producer->Connect(svc.get(), "mock_producer");
744 producer->RegisterDataSource("data_source", /*ack_stop=*/true);
745
746 TraceConfig trace_config;
747 trace_config.add_buffers()->set_size_kb(128);
748 trace_config.add_data_sources()->mutable_config()->set_name("data_source");
749 trace_config.set_duration_ms(1);
750
751 consumer->EnableTracing(trace_config);
752 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100753 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100754 producer->WaitForDataSourceStart("data_source");
755
756 std::unique_ptr<TraceWriter> writer =
757 producer->CreateTraceWriter("data_source");
758 producer->WaitForFlush(writer.get());
759
760 producer->WaitForDataSourceStop("data_source");
761 consumer->WaitForTracingDisabled();
762}
763
Primiano Tucci03de28f2018-08-01 11:29:46 +0100764// Tests the session_id logic. Two data sources in the same tracing session
765// should see the same session id.
766TEST_F(TracingServiceImplTest, SessionId) {
767 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
768 consumer->Connect(svc.get());
769
770 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
771 producer1->Connect(svc.get(), "mock_producer1");
772 producer1->RegisterDataSource("ds_1A");
773 producer1->RegisterDataSource("ds_1B");
774
775 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
776 producer2->Connect(svc.get(), "mock_producer2");
777 producer2->RegisterDataSource("ds_2A");
778
779 testing::InSequence seq;
780 TracingSessionID last_session_id = 0;
781 for (int i = 0; i < 3; i++) {
782 TraceConfig trace_config;
783 trace_config.add_buffers()->set_size_kb(128);
784 trace_config.add_data_sources()->mutable_config()->set_name("ds_1A");
785 trace_config.add_data_sources()->mutable_config()->set_name("ds_1B");
786 trace_config.add_data_sources()->mutable_config()->set_name("ds_2A");
787 trace_config.set_duration_ms(1);
788
789 consumer->EnableTracing(trace_config);
790
791 if (i == 0)
792 producer1->WaitForTracingSetup();
Primiano Tucci03de28f2018-08-01 11:29:46 +0100793
Primiano Tucci674076d2018-10-01 10:41:09 +0100794 producer1->WaitForDataSourceSetup("ds_1A");
795 producer1->WaitForDataSourceSetup("ds_1B");
Primiano Tucci03de28f2018-08-01 11:29:46 +0100796 if (i == 0)
797 producer2->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100798 producer2->WaitForDataSourceSetup("ds_2A");
799
800 producer1->WaitForDataSourceStart("ds_1A");
801 producer1->WaitForDataSourceStart("ds_1B");
Primiano Tucci03de28f2018-08-01 11:29:46 +0100802 producer2->WaitForDataSourceStart("ds_2A");
803
804 auto* ds1 = producer1->GetDataSourceInstance("ds_1A");
805 auto* ds2 = producer1->GetDataSourceInstance("ds_1B");
806 auto* ds3 = producer2->GetDataSourceInstance("ds_2A");
807 ASSERT_EQ(ds1->session_id, ds2->session_id);
808 ASSERT_EQ(ds1->session_id, ds3->session_id);
809 ASSERT_NE(ds1->session_id, last_session_id);
810 last_session_id = ds1->session_id;
811
812 auto writer1 = producer1->CreateTraceWriter("ds_1A");
813 producer1->WaitForFlush(writer1.get());
814
815 auto writer2 = producer2->CreateTraceWriter("ds_2A");
816 producer2->WaitForFlush(writer2.get());
817
818 producer1->WaitForDataSourceStop("ds_1A");
819 producer1->WaitForDataSourceStop("ds_1B");
820 producer2->WaitForDataSourceStop("ds_2A");
821 consumer->WaitForTracingDisabled();
822 consumer->FreeBuffers();
823 }
824}
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100825
826// Writes a long trace and then tests that the trace parsed in partitions
827// derived by the synchronization markers is identical to the whole trace parsed
828// in one go.
829TEST_F(TracingServiceImplTest, ResynchronizeTraceStreamUsingSyncMarker) {
830 // Setup tracing.
831 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
832 consumer->Connect(svc.get());
833 std::unique_ptr<MockProducer> producer = CreateMockProducer();
834 producer->Connect(svc.get(), "mock_producer");
835 producer->RegisterDataSource("data_source");
836 TraceConfig trace_config;
837 trace_config.add_buffers()->set_size_kb(4096);
838 auto* ds_config = trace_config.add_data_sources()->mutable_config();
839 ds_config->set_name("data_source");
840 trace_config.set_write_into_file(true);
841 trace_config.set_file_write_period_ms(1);
842 base::TempFile tmp_file = base::TempFile::Create();
843 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
844 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100845 producer->WaitForDataSourceSetup("data_source");
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100846 producer->WaitForDataSourceStart("data_source");
847
848 // Write some variable length payload, waiting for sync markers every now
849 // and then.
850 const int kNumMarkers = 5;
851 auto writer = producer->CreateTraceWriter("data_source");
852 for (int i = 1; i <= 100; i++) {
Florian Mayereff98042018-12-10 17:44:44 +0000853 std::string payload(static_cast<size_t>(i), 'A' + (i % 25));
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100854 writer->NewTracePacket()->set_for_testing()->set_str(payload.c_str());
855 if (i % (100 / kNumMarkers) == 0) {
856 writer->Flush();
857 WaitForNextSyncMarker();
858 }
859 }
860 writer->Flush();
861 writer.reset();
862 consumer->DisableTracing();
863 producer->WaitForDataSourceStop("data_source");
864 consumer->WaitForTracingDisabled();
865
866 std::string trace_raw;
867 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
868
869 const auto kMarkerSize = sizeof(TracingServiceImpl::kSyncMarker);
870 const std::string kSyncMarkerStr(
871 reinterpret_cast<const char*>(TracingServiceImpl::kSyncMarker),
872 kMarkerSize);
873
874 // Read back the trace in partitions derived from the marker.
875 // The trace should look like this:
876 // [uid, marker] [event] [event] [uid, marker] [event] [event]
877 size_t num_markers = 0;
878 size_t start = 0;
879 size_t end = 0;
880 protos::Trace merged_trace;
881 for (size_t pos = 0; pos != std::string::npos; start = end) {
882 pos = trace_raw.find(kSyncMarkerStr, pos + 1);
883 num_markers++;
884 end = (pos == std::string::npos) ? trace_raw.size() : pos + kMarkerSize;
885 int size = static_cast<int>(end - start);
886 ASSERT_GT(size, 0);
887 protos::Trace trace_partition;
888 ASSERT_TRUE(trace_partition.ParseFromArray(trace_raw.data() + start, size));
889 merged_trace.MergeFrom(trace_partition);
890 }
Lalit Maganti9bdc7ce2018-09-17 15:25:11 +0100891 EXPECT_GE(num_markers, static_cast<size_t>(kNumMarkers));
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100892
893 protos::Trace whole_trace;
894 ASSERT_TRUE(whole_trace.ParseFromString(trace_raw));
895
896 ASSERT_EQ(whole_trace.packet_size(), merged_trace.packet_size());
897 EXPECT_EQ(whole_trace.SerializeAsString(), merged_trace.SerializeAsString());
898}
899
Primiano Tucci674076d2018-10-01 10:41:09 +0100900// Creates a tracing session with |deferred_start| and checks that data sources
901// are started only after calling StartTracing().
902TEST_F(TracingServiceImplTest, DeferredStart) {
903 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
904 consumer->Connect(svc.get());
905
906 std::unique_ptr<MockProducer> producer = CreateMockProducer();
907 producer->Connect(svc.get(), "mock_producer");
908
909 // Create two data sources but enable only one of them.
910 producer->RegisterDataSource("ds_1");
911 producer->RegisterDataSource("ds_2");
912
913 TraceConfig trace_config;
914 trace_config.add_buffers()->set_size_kb(128);
915 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
916 trace_config.set_deferred_start(true);
917 trace_config.set_duration_ms(1);
918
919 consumer->EnableTracing(trace_config);
920 producer->WaitForTracingSetup();
921
922 producer->WaitForDataSourceSetup("ds_1");
923
924 // Make sure we don't get unexpected DataSourceStart() notifications yet.
925 task_runner.RunUntilIdle();
926
927 consumer->StartTracing();
928
929 producer->WaitForDataSourceStart("ds_1");
930
931 auto writer1 = producer->CreateTraceWriter("ds_1");
932 producer->WaitForFlush(writer1.get());
933
934 producer->WaitForDataSourceStop("ds_1");
935 consumer->WaitForTracingDisabled();
936}
937
Eric Seckler6dc23592018-11-30 10:59:06 +0000938TEST_F(TracingServiceImplTest, AllowedBuffers) {
939 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
940 consumer->Connect(svc.get());
941
942 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
943 producer1->Connect(svc.get(), "mock_producer1");
944 ProducerID producer1_id = *last_producer_id();
945 producer1->RegisterDataSource("data_source1");
946 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
947 producer2->Connect(svc.get(), "mock_producer2");
948 ProducerID producer2_id = *last_producer_id();
949 producer2->RegisterDataSource("data_source2.1");
950 producer2->RegisterDataSource("data_source2.2");
951 producer2->RegisterDataSource("data_source2.3");
952
953 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer1_id));
954 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer2_id));
955
956 TraceConfig trace_config;
957 trace_config.add_buffers()->set_size_kb(128);
958 trace_config.add_buffers()->set_size_kb(128);
959 trace_config.add_buffers()->set_size_kb(128);
960 auto* ds_config1 = trace_config.add_data_sources()->mutable_config();
961 ds_config1->set_name("data_source1");
962 ds_config1->set_target_buffer(0);
963 auto* ds_config21 = trace_config.add_data_sources()->mutable_config();
964 ds_config21->set_name("data_source2.1");
965 ds_config21->set_target_buffer(1);
966 auto* ds_config22 = trace_config.add_data_sources()->mutable_config();
967 ds_config22->set_name("data_source2.2");
968 ds_config22->set_target_buffer(2);
969 auto* ds_config23 = trace_config.add_data_sources()->mutable_config();
970 ds_config23->set_name("data_source2.3");
971 ds_config23->set_target_buffer(2); // same buffer as data_source2.2.
972 consumer->EnableTracing(trace_config);
973
Primiano Tucci2abd1152018-12-03 17:00:02 +0100974 ASSERT_EQ(3u, tracing_session()->num_buffers());
Eric Seckler6dc23592018-11-30 10:59:06 +0000975 std::set<BufferID> expected_buffers_producer1 = {
976 tracing_session()->buffers_index[0]};
977 std::set<BufferID> expected_buffers_producer2 = {
978 tracing_session()->buffers_index[1], tracing_session()->buffers_index[2]};
979 EXPECT_EQ(expected_buffers_producer1, GetAllowedTargetBuffers(producer1_id));
980 EXPECT_EQ(expected_buffers_producer2, GetAllowedTargetBuffers(producer2_id));
981
982 producer1->WaitForTracingSetup();
983 producer1->WaitForDataSourceSetup("data_source1");
984
985 producer2->WaitForTracingSetup();
986 producer2->WaitForDataSourceSetup("data_source2.1");
987 producer2->WaitForDataSourceSetup("data_source2.2");
988 producer2->WaitForDataSourceSetup("data_source2.3");
989
990 producer1->WaitForDataSourceStart("data_source1");
991 producer2->WaitForDataSourceStart("data_source2.1");
992 producer2->WaitForDataSourceStart("data_source2.2");
993 producer2->WaitForDataSourceStart("data_source2.3");
994
995 producer2->UnregisterDataSource("data_source2.3");
996 producer2->WaitForDataSourceStop("data_source2.3");
997
998 // Should still be allowed to write to buffers 1 (data_source2.1) and 2
999 // (data_source2.2).
1000 EXPECT_EQ(expected_buffers_producer2, GetAllowedTargetBuffers(producer2_id));
1001
1002 // Calling StartTracing() should be a noop (% a DLOG statement) because the
1003 // trace config didn't have the |deferred_start| flag set.
1004 consumer->StartTracing();
1005
1006 consumer->DisableTracing();
1007 producer1->WaitForDataSourceStop("data_source1");
1008 producer2->WaitForDataSourceStop("data_source2.1");
1009 producer2->WaitForDataSourceStop("data_source2.2");
1010 consumer->WaitForTracingDisabled();
1011
1012 consumer->FreeBuffers();
1013 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer1_id));
1014 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer2_id));
1015}
1016
Eric Seckler6aa9ece2018-12-06 16:40:12 +00001017#if !PERFETTO_DCHECK_IS_ON()
Eric Secklerdd0ad102018-12-06 11:32:04 +00001018TEST_F(TracingServiceImplTest, CommitToForbiddenBufferIsDiscarded) {
1019 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1020 consumer->Connect(svc.get());
1021
1022 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1023 producer->Connect(svc.get(), "mock_producer");
1024 ProducerID producer_id = *last_producer_id();
1025 producer->RegisterDataSource("data_source");
1026
1027 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer_id));
1028
1029 TraceConfig trace_config;
1030 trace_config.add_buffers()->set_size_kb(128);
1031 trace_config.add_buffers()->set_size_kb(128);
1032 auto* ds_config = trace_config.add_data_sources()->mutable_config();
1033 ds_config->set_name("data_source");
1034 ds_config->set_target_buffer(0);
1035 consumer->EnableTracing(trace_config);
1036
1037 ASSERT_EQ(2u, tracing_session()->num_buffers());
1038 std::set<BufferID> expected_buffers = {tracing_session()->buffers_index[0]};
1039 EXPECT_EQ(expected_buffers, GetAllowedTargetBuffers(producer_id));
1040
1041 producer->WaitForTracingSetup();
1042 producer->WaitForDataSourceSetup("data_source");
1043 producer->WaitForDataSourceStart("data_source");
1044
1045 // Calling StartTracing() should be a noop (% a DLOG statement) because the
1046 // trace config didn't have the |deferred_start| flag set.
1047 consumer->StartTracing();
1048
1049 // Try to write to the correct buffer.
1050 std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter(
1051 tracing_session()->buffers_index[0]);
1052 {
1053 auto tp = writer->NewTracePacket();
1054 tp->set_for_testing()->set_str("good_payload");
1055 }
1056
1057 auto flush_request = consumer->Flush();
1058 producer->WaitForFlush(writer.get());
1059 ASSERT_TRUE(flush_request.WaitForReply());
1060
1061 // Try to write to the wrong buffer.
1062 writer = producer->endpoint()->CreateTraceWriter(
1063 tracing_session()->buffers_index[1]);
1064 {
1065 auto tp = writer->NewTracePacket();
1066 tp->set_for_testing()->set_str("bad_payload");
1067 }
1068
1069 flush_request = consumer->Flush();
1070 producer->WaitForFlush(writer.get());
1071 ASSERT_TRUE(flush_request.WaitForReply());
1072
1073 consumer->DisableTracing();
1074 producer->WaitForDataSourceStop("data_source");
1075 consumer->WaitForTracingDisabled();
1076
1077 auto packets = consumer->ReadBuffers();
1078 EXPECT_THAT(packets, Contains(Property(&protos::TracePacket::for_testing,
1079 Property(&protos::TestEvent::str,
1080 Eq("good_payload")))));
1081 EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
1082 Property(&protos::TestEvent::str,
1083 Eq("bad_payload"))))));
1084
1085 consumer->FreeBuffers();
1086 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer_id));
1087}
Eric Seckler6aa9ece2018-12-06 16:40:12 +00001088#endif // !PERFETTO_DCHECK_IS_ON()
Eric Secklerdd0ad102018-12-06 11:32:04 +00001089
Eric Secklerf3f524b2018-12-13 09:09:34 +00001090TEST_F(TracingServiceImplTest, RegisterAndUnregisterTraceWriter) {
1091 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1092 consumer->Connect(svc.get());
1093
1094 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1095 producer->Connect(svc.get(), "mock_producer");
1096 ProducerID producer_id = *last_producer_id();
1097 producer->RegisterDataSource("data_source");
1098
1099 EXPECT_TRUE(GetWriters(producer_id).empty());
1100
1101 TraceConfig trace_config;
1102 trace_config.add_buffers()->set_size_kb(128);
1103 auto* ds_config = trace_config.add_data_sources()->mutable_config();
1104 ds_config->set_name("data_source");
1105 ds_config->set_target_buffer(0);
1106 consumer->EnableTracing(trace_config);
1107
1108 producer->WaitForTracingSetup();
1109 producer->WaitForDataSourceSetup("data_source");
1110 producer->WaitForDataSourceStart("data_source");
1111
1112 // Calling StartTracing() should be a noop (% a DLOG statement) because the
1113 // trace config didn't have the |deferred_start| flag set.
1114 consumer->StartTracing();
1115
1116 // Creating the trace writer should register it with the service.
1117 std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter(
1118 tracing_session()->buffers_index[0]);
1119
1120 WaitForTraceWritersChanged(producer_id);
1121
1122 std::map<WriterID, BufferID> expected_writers;
1123 expected_writers[writer->writer_id()] = tracing_session()->buffers_index[0];
1124 EXPECT_EQ(expected_writers, GetWriters(producer_id));
1125
1126 // Verify writing works.
1127 {
1128 auto tp = writer->NewTracePacket();
1129 tp->set_for_testing()->set_str("payload");
1130 }
1131
1132 auto flush_request = consumer->Flush();
1133 producer->WaitForFlush(writer.get());
1134 ASSERT_TRUE(flush_request.WaitForReply());
1135
1136 // Destroying the writer should unregister it.
1137 writer.reset();
1138 WaitForTraceWritersChanged(producer_id);
1139 EXPECT_TRUE(GetWriters(producer_id).empty());
1140
1141 consumer->DisableTracing();
1142 producer->WaitForDataSourceStop("data_source");
1143 consumer->WaitForTracingDisabled();
1144
1145 auto packets = consumer->ReadBuffers();
1146 EXPECT_THAT(packets, Contains(Property(
1147 &protos::TracePacket::for_testing,
1148 Property(&protos::TestEvent::str, Eq("payload")))));
1149}
1150
Eric Secklera01e28a2019-01-08 11:21:04 +00001151TEST_F(TracingServiceImplTest, ScrapeBuffersOnFlush) {
1152 svc->SetSMBScrapingEnabled(true);
1153
1154 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1155 consumer->Connect(svc.get());
1156
1157 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1158 producer->Connect(svc.get(), "mock_producer");
1159 ProducerID producer_id = *last_producer_id();
1160 producer->RegisterDataSource("data_source");
1161
1162 TraceConfig trace_config;
1163 trace_config.add_buffers()->set_size_kb(128);
1164 auto* ds_config = trace_config.add_data_sources()->mutable_config();
1165 ds_config->set_name("data_source");
1166 ds_config->set_target_buffer(0);
1167 consumer->EnableTracing(trace_config);
1168
1169 producer->WaitForTracingSetup();
1170 producer->WaitForDataSourceSetup("data_source");
1171 producer->WaitForDataSourceStart("data_source");
1172
1173 // Calling StartTracing() should be a noop (% a DLOG statement) because the
1174 // trace config didn't have the |deferred_start| flag set.
1175 consumer->StartTracing();
1176
1177 std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter(
1178 tracing_session()->buffers_index[0]);
1179 WaitForTraceWritersChanged(producer_id);
1180
1181 // Write a few trace packets.
1182 writer->NewTracePacket()->set_for_testing()->set_str("payload1");
1183 writer->NewTracePacket()->set_for_testing()->set_str("payload2");
1184 writer->NewTracePacket()->set_for_testing()->set_str("payload3");
1185
1186 // Flush but don't actually flush the chunk from TraceWriter.
1187 auto flush_request = consumer->Flush();
1188 producer->WaitForFlush(nullptr, /*reply=*/true);
1189 ASSERT_TRUE(flush_request.WaitForReply());
1190
1191 // Chunk with the packets should have been scraped. The service can't know
1192 // whether the last packet was completed, so shouldn't read it.
1193 auto packets = consumer->ReadBuffers();
1194 EXPECT_THAT(packets, Contains(Property(
1195 &protos::TracePacket::for_testing,
1196 Property(&protos::TestEvent::str, Eq("payload1")))));
1197 EXPECT_THAT(packets, Contains(Property(
1198 &protos::TracePacket::for_testing,
1199 Property(&protos::TestEvent::str, Eq("payload2")))));
1200 EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
1201 Property(&protos::TestEvent::str,
1202 Eq("payload3"))))));
1203
1204 // Write some more packets.
1205 writer->NewTracePacket()->set_for_testing()->set_str("payload4");
1206 writer->NewTracePacket()->set_for_testing()->set_str("payload5");
1207
1208 // Don't reply to flush, causing a timeout. This should scrape again.
1209 flush_request = consumer->Flush(/*timeout=*/100);
1210 producer->WaitForFlush(nullptr, /*reply=*/false);
1211 ASSERT_FALSE(flush_request.WaitForReply());
1212
1213 // Chunk with the packets should have been scraped again, overriding the
1214 // original one. Again, the last packet should be ignored and the first two
1215 // should not be read twice.
1216 packets = consumer->ReadBuffers();
1217 EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
1218 Property(&protos::TestEvent::str,
1219 Eq("payload1"))))));
1220 EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
1221 Property(&protos::TestEvent::str,
1222 Eq("payload2"))))));
1223 EXPECT_THAT(packets, Contains(Property(
1224 &protos::TracePacket::for_testing,
1225 Property(&protos::TestEvent::str, Eq("payload3")))));
1226 EXPECT_THAT(packets, Contains(Property(
1227 &protos::TracePacket::for_testing,
1228 Property(&protos::TestEvent::str, Eq("payload4")))));
1229 EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
1230 Property(&protos::TestEvent::str,
1231 Eq("payload5"))))));
1232
1233 consumer->DisableTracing();
1234 producer->WaitForDataSourceStop("data_source");
1235 consumer->WaitForTracingDisabled();
1236}
1237
1238// Test scraping on producer disconnect.
1239TEST_F(TracingServiceImplTest, ScrapeBuffersOnProducerDisconnect) {
1240 svc->SetSMBScrapingEnabled(true);
1241
1242 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1243 consumer->Connect(svc.get());
1244
1245 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1246 producer->Connect(svc.get(), "mock_producer");
1247 ProducerID producer_id = *last_producer_id();
1248 producer->RegisterDataSource("data_source");
1249
1250 TraceConfig trace_config;
1251 trace_config.add_buffers()->set_size_kb(128);
1252 auto* ds_config = trace_config.add_data_sources()->mutable_config();
1253 ds_config->set_name("data_source");
1254 ds_config->set_target_buffer(0);
1255 consumer->EnableTracing(trace_config);
1256
1257 producer->WaitForTracingSetup();
1258 producer->WaitForDataSourceSetup("data_source");
1259 producer->WaitForDataSourceStart("data_source");
1260
1261 // Calling StartTracing() should be a noop (% a DLOG statement) because the
1262 // trace config didn't have the |deferred_start| flag set.
1263 consumer->StartTracing();
1264
1265 std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter(
1266 tracing_session()->buffers_index[0]);
1267 WaitForTraceWritersChanged(producer_id);
1268
1269 // Write a few trace packets.
1270 writer->NewTracePacket()->set_for_testing()->set_str("payload1");
1271 writer->NewTracePacket()->set_for_testing()->set_str("payload2");
1272 writer->NewTracePacket()->set_for_testing()->set_str("payload3");
1273
1274 // Disconnect the producer without committing the chunk. This should cause a
1275 // scrape of the SMB. Avoid destroying the ShmemArbiter until writer is
1276 // destroyed.
1277 auto shmem_arbiter = TakeShmemArbiterForProducer(producer_id);
1278 producer.reset();
1279
1280 // Chunk with the packets should have been scraped. The service can't know
1281 // whether the last packet was completed, so shouldn't read it.
1282 auto packets = consumer->ReadBuffers();
1283 EXPECT_THAT(packets, Contains(Property(
1284 &protos::TracePacket::for_testing,
1285 Property(&protos::TestEvent::str, Eq("payload1")))));
1286 EXPECT_THAT(packets, Contains(Property(
1287 &protos::TracePacket::for_testing,
1288 Property(&protos::TestEvent::str, Eq("payload2")))));
1289 EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
1290 Property(&protos::TestEvent::str,
1291 Eq("payload3"))))));
1292
1293 // Cleanup writer without causing a crash because the producer already went
1294 // away.
1295 static_cast<TraceWriterImpl*>(writer.get())->ResetChunkForTesting();
1296 writer.reset();
1297 shmem_arbiter.reset();
1298
1299 consumer->DisableTracing();
1300 consumer->WaitForTracingDisabled();
1301}
1302
1303TEST_F(TracingServiceImplTest, ScrapeBuffersOnDisable) {
1304 svc->SetSMBScrapingEnabled(true);
1305
1306 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1307 consumer->Connect(svc.get());
1308
1309 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1310 producer->Connect(svc.get(), "mock_producer");
1311 ProducerID producer_id = *last_producer_id();
1312 producer->RegisterDataSource("data_source");
1313
1314 TraceConfig trace_config;
1315 trace_config.add_buffers()->set_size_kb(128);
1316 auto* ds_config = trace_config.add_data_sources()->mutable_config();
1317 ds_config->set_name("data_source");
1318 ds_config->set_target_buffer(0);
1319 consumer->EnableTracing(trace_config);
1320
1321 producer->WaitForTracingSetup();
1322 producer->WaitForDataSourceSetup("data_source");
1323 producer->WaitForDataSourceStart("data_source");
1324
1325 // Calling StartTracing() should be a noop (% a DLOG statement) because the
1326 // trace config didn't have the |deferred_start| flag set.
1327 consumer->StartTracing();
1328
1329 std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter(
1330 tracing_session()->buffers_index[0]);
1331 WaitForTraceWritersChanged(producer_id);
1332
1333 // Write a few trace packets.
1334 writer->NewTracePacket()->set_for_testing()->set_str("payload1");
1335 writer->NewTracePacket()->set_for_testing()->set_str("payload2");
1336 writer->NewTracePacket()->set_for_testing()->set_str("payload3");
1337
1338 consumer->DisableTracing();
1339 producer->WaitForDataSourceStop("data_source");
1340 consumer->WaitForTracingDisabled();
1341
1342 // Chunk with the packets should have been scraped. The service can't know
1343 // whether the last packet was completed, so shouldn't read it.
1344 auto packets = consumer->ReadBuffers();
1345 EXPECT_THAT(packets, Contains(Property(
1346 &protos::TracePacket::for_testing,
1347 Property(&protos::TestEvent::str, Eq("payload1")))));
1348 EXPECT_THAT(packets, Contains(Property(
1349 &protos::TracePacket::for_testing,
1350 Property(&protos::TestEvent::str, Eq("payload2")))));
1351 EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
1352 Property(&protos::TestEvent::str,
1353 Eq("payload3"))))));
1354}
1355
Primiano Tucci4f9b6d72017-12-05 20:59:16 +00001356} // namespace perfetto