blob: cbf2da6d7ac6c8bede80f038562984e8e5060509 [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 Secklerf3f524b2018-12-13 09:09:34 +000034#include "src/tracing/core/trace_writer_impl.h"
Primiano Tuccidca727d2018-04-04 11:31:55 +020035#include "src/tracing/test/mock_consumer.h"
36#include "src/tracing/test/mock_producer.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000037#include "src/tracing/test/test_shared_memory.h"
38
Primiano Tucci2ffd1a52018-03-27 01:01:30 +010039#include "perfetto/trace/test_event.pbzero.h"
40#include "perfetto/trace/trace.pb.h"
Primiano Tuccidca727d2018-04-04 11:31:55 +020041#include "perfetto/trace/trace_packet.pb.h"
Primiano Tucci2ffd1a52018-03-27 01:01:30 +010042#include "perfetto/trace/trace_packet.pbzero.h"
43
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000044using ::testing::_;
Primiano Tuccidca727d2018-04-04 11:31:55 +020045using ::testing::Contains;
Primiano Tucci1a1951d2018-04-04 21:08:16 +020046using ::testing::ElementsAreArray;
Primiano Tuccidca727d2018-04-04 11:31:55 +020047using ::testing::Eq;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000048using ::testing::InSequence;
Primiano Tucci081d46a2018-02-28 11:09:43 +000049using ::testing::Invoke;
Primiano Tuccidca727d2018-04-04 11:31:55 +020050using ::testing::InvokeWithoutArgs;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000051using ::testing::Mock;
Eric Secklerdd0ad102018-12-06 11:32:04 +000052using ::testing::Not;
Primiano Tuccidca727d2018-04-04 11:31:55 +020053using ::testing::Property;
54using ::testing::StrictMock;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000055
Primiano Tuccidca727d2018-04-04 11:31:55 +020056namespace perfetto {
Sami Kyostila32e0b542018-02-14 08:55:43 +000057
Primiano Tucci1a1951d2018-04-04 21:08:16 +020058namespace {
Florian Mayer6a1a4d52018-06-08 16:47:07 +010059constexpr size_t kDefaultShmSizeKb = TracingServiceImpl::kDefaultShmSize / 1024;
60constexpr size_t kMaxShmSizeKb = TracingServiceImpl::kMaxShmSize / 1024;
Primiano Tucci1a1951d2018-04-04 21:08:16 +020061} // namespace
62
Florian Mayer6a1a4d52018-06-08 16:47:07 +010063class TracingServiceImplTest : public testing::Test {
Sami Kyostila06487a22018-02-27 13:48:38 +000064 public:
Florian Mayer6a1a4d52018-06-08 16:47:07 +010065 TracingServiceImplTest() {
Sami Kyostila06487a22018-02-27 13:48:38 +000066 auto shm_factory =
67 std::unique_ptr<SharedMemory::Factory>(new TestSharedMemory::Factory());
Florian Mayer6a1a4d52018-06-08 16:47:07 +010068 svc.reset(static_cast<TracingServiceImpl*>(
69 TracingService::CreateInstance(std::move(shm_factory), &task_runner)
Sami Kyostila06487a22018-02-27 13:48:38 +000070 .release()));
Primiano Tucci9754d0d2018-09-15 12:41:46 +010071 svc->min_write_period_ms_ = 1;
Sami Kyostila06487a22018-02-27 13:48:38 +000072 }
73
Primiano Tuccidca727d2018-04-04 11:31:55 +020074 std::unique_ptr<MockProducer> CreateMockProducer() {
75 return std::unique_ptr<MockProducer>(
76 new StrictMock<MockProducer>(&task_runner));
77 }
78
79 std::unique_ptr<MockConsumer> CreateMockConsumer() {
80 return std::unique_ptr<MockConsumer>(
81 new StrictMock<MockConsumer>(&task_runner));
82 }
83
Primiano Tucci1a1951d2018-04-04 21:08:16 +020084 ProducerID* last_producer_id() { return &svc->last_producer_id_; }
85
86 uid_t GetProducerUid(ProducerID producer_id) {
87 return svc->GetProducer(producer_id)->uid_;
88 }
89
Primiano Tucci9754d0d2018-09-15 12:41:46 +010090 TracingServiceImpl::TracingSession* tracing_session() {
91 auto* session = svc->GetTracingSession(svc->last_tracing_session_id_);
92 EXPECT_NE(nullptr, session);
93 return session;
94 }
95
Eric Seckler6dc23592018-11-30 10:59:06 +000096 const std::set<BufferID>& GetAllowedTargetBuffers(ProducerID producer_id) {
97 return svc->GetProducer(producer_id)->allowed_target_buffers_;
98 }
99
Eric Secklerf3f524b2018-12-13 09:09:34 +0000100 const std::map<WriterID, BufferID>& GetWriters(ProducerID producer_id) {
101 return svc->GetProducer(producer_id)->writers_;
102 }
103
Primiano Tuccid52e6272018-04-06 19:06:53 +0200104 size_t GetNumPendingFlushes() {
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100105 return tracing_session()->pending_flushes.size();
106 }
107
108 void WaitForNextSyncMarker() {
109 tracing_session()->last_snapshot_time = base::TimeMillis(0);
110 static int attempt = 0;
111 while (tracing_session()->last_snapshot_time == base::TimeMillis(0)) {
112 auto checkpoint_name = "wait_snapshot_" + std::to_string(attempt++);
113 auto timer_expired = task_runner.CreateCheckpoint(checkpoint_name);
114 task_runner.PostDelayedTask([timer_expired] { timer_expired(); }, 1);
115 task_runner.RunUntilCheckpoint(checkpoint_name);
116 }
Primiano Tuccid52e6272018-04-06 19:06:53 +0200117 }
118
Eric Secklerf3f524b2018-12-13 09:09:34 +0000119 void WaitForTraceWritersChanged(ProducerID producer_id) {
120 static int i = 0;
121 auto checkpoint_name = "writers_changed_" + std::to_string(producer_id) +
122 "_" + std::to_string(i++);
123 auto writers_changed = task_runner.CreateCheckpoint(checkpoint_name);
124 auto writers = GetWriters(producer_id);
125 std::function<void()> task;
126 task = [&task, writers, writers_changed, producer_id, this]() {
127 if (writers != GetWriters(producer_id)) {
128 writers_changed();
129 return;
130 }
131 task_runner.PostDelayedTask(task, 1);
132 };
133 task_runner.PostDelayedTask(task, 1);
134 task_runner.RunUntilCheckpoint(checkpoint_name);
135 }
136
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000137 base::TestTaskRunner task_runner;
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100138 std::unique_ptr<TracingServiceImpl> svc;
Sami Kyostila06487a22018-02-27 13:48:38 +0000139};
140
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100141TEST_F(TracingServiceImplTest, RegisterAndUnregister) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200142 std::unique_ptr<MockProducer> mock_producer_1 = CreateMockProducer();
143 std::unique_ptr<MockProducer> mock_producer_2 = CreateMockProducer();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000144
Primiano Tuccidca727d2018-04-04 11:31:55 +0200145 mock_producer_1->Connect(svc.get(), "mock_producer_1", 123u /* uid */);
146 mock_producer_2->Connect(svc.get(), "mock_producer_2", 456u /* uid */);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000147
148 ASSERT_EQ(2u, svc->num_producers());
Primiano Tuccidca727d2018-04-04 11:31:55 +0200149 ASSERT_EQ(mock_producer_1->endpoint(), svc->GetProducer(1));
150 ASSERT_EQ(mock_producer_2->endpoint(), svc->GetProducer(2));
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200151 ASSERT_EQ(123u, GetProducerUid(1));
152 ASSERT_EQ(456u, GetProducerUid(2));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000153
Primiano Tuccidca727d2018-04-04 11:31:55 +0200154 mock_producer_1->RegisterDataSource("foo");
155 mock_producer_2->RegisterDataSource("bar");
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000156
Primiano Tuccidca727d2018-04-04 11:31:55 +0200157 mock_producer_1->UnregisterDataSource("foo");
158 mock_producer_2->UnregisterDataSource("bar");
Primiano Tucci9daa4832018-03-28 23:28:17 +0100159
Primiano Tuccidca727d2018-04-04 11:31:55 +0200160 mock_producer_1.reset();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000161 ASSERT_EQ(1u, svc->num_producers());
162 ASSERT_EQ(nullptr, svc->GetProducer(1));
163
Primiano Tuccidca727d2018-04-04 11:31:55 +0200164 mock_producer_2.reset();
165 ASSERT_EQ(nullptr, svc->GetProducer(2));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000166
167 ASSERT_EQ(0u, svc->num_producers());
168}
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100169
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100170TEST_F(TracingServiceImplTest, EnableAndDisableTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200171 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
172 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000173
Primiano Tuccidca727d2018-04-04 11:31:55 +0200174 std::unique_ptr<MockProducer> producer = CreateMockProducer();
175 producer->Connect(svc.get(), "mock_producer");
176 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000177
Sami Kyostila06487a22018-02-27 13:48:38 +0000178 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200179 trace_config.add_buffers()->set_size_kb(128);
Sami Kyostila06487a22018-02-27 13:48:38 +0000180 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200181 ds_config->set_name("data_source");
182 consumer->EnableTracing(trace_config);
Sami Kyostila06487a22018-02-27 13:48:38 +0000183
Primiano Tuccidca727d2018-04-04 11:31:55 +0200184 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100185 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200186 producer->WaitForDataSourceStart("data_source");
187
Primiano Tucci674076d2018-10-01 10:41:09 +0100188 // Calling StartTracing() should be a noop (% a DLOG statement) because the
189 // trace config didn't have the |deferred_start| flag set.
190 consumer->StartTracing();
191
Primiano Tuccidca727d2018-04-04 11:31:55 +0200192 consumer->DisableTracing();
193 producer->WaitForDataSourceStop("data_source");
194 consumer->WaitForTracingDisabled();
Sami Kyostila06487a22018-02-27 13:48:38 +0000195}
196
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100197TEST_F(TracingServiceImplTest, LockdownMode) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200198 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
199 consumer->Connect(svc.get());
200
201 std::unique_ptr<MockProducer> producer = CreateMockProducer();
202 producer->Connect(svc.get(), "mock_producer_sameuid", geteuid());
203 producer->RegisterDataSource("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000204
205 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200206 trace_config.add_buffers()->set_size_kb(128);
207 auto* ds_config = trace_config.add_data_sources()->mutable_config();
208 ds_config->set_name("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000209 trace_config.set_lockdown_mode(
210 TraceConfig::LockdownModeOperation::LOCKDOWN_SET);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200211 consumer->EnableTracing(trace_config);
212
213 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100214 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200215 producer->WaitForDataSourceStart("data_source");
216
217 std::unique_ptr<MockProducer> producer_otheruid = CreateMockProducer();
218 auto x = svc->ConnectProducer(producer_otheruid.get(), geteuid() + 1,
219 "mock_producer_ouid");
220 EXPECT_CALL(*producer_otheruid, OnConnect()).Times(0);
Florian Mayer61c55482018-03-06 14:43:54 +0000221 task_runner.RunUntilIdle();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200222 Mock::VerifyAndClearExpectations(producer_otheruid.get());
Florian Mayer61c55482018-03-06 14:43:54 +0000223
Primiano Tuccidca727d2018-04-04 11:31:55 +0200224 consumer->DisableTracing();
225 consumer->FreeBuffers();
226 producer->WaitForDataSourceStop("data_source");
227 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000228
229 trace_config.set_lockdown_mode(
230 TraceConfig::LockdownModeOperation::LOCKDOWN_CLEAR);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200231 consumer->EnableTracing(trace_config);
Primiano Tucci674076d2018-10-01 10:41:09 +0100232 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200233 producer->WaitForDataSourceStart("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000234
Primiano Tuccidca727d2018-04-04 11:31:55 +0200235 std::unique_ptr<MockProducer> producer_otheruid2 = CreateMockProducer();
236 producer_otheruid->Connect(svc.get(), "mock_producer_ouid2", geteuid() + 1);
Florian Mayer61c55482018-03-06 14:43:54 +0000237
Primiano Tuccidca727d2018-04-04 11:31:55 +0200238 consumer->DisableTracing();
239 producer->WaitForDataSourceStop("data_source");
240 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000241}
242
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100243TEST_F(TracingServiceImplTest, DisconnectConsumerWhileTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200244 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
245 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000246
Primiano Tuccidca727d2018-04-04 11:31:55 +0200247 std::unique_ptr<MockProducer> producer = CreateMockProducer();
248 producer->Connect(svc.get(), "mock_producer");
249 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000250
Primiano Tuccidca727d2018-04-04 11:31:55 +0200251 TraceConfig trace_config;
252 trace_config.add_buffers()->set_size_kb(128);
253 auto* ds_config = trace_config.add_data_sources()->mutable_config();
254 ds_config->set_name("data_source");
255 consumer->EnableTracing(trace_config);
256
257 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100258 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200259 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000260
261 // Disconnecting the consumer while tracing should trigger data source
262 // teardown.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200263 consumer.reset();
264 producer->WaitForDataSourceStop("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000265}
266
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100267TEST_F(TracingServiceImplTest, ReconnectProducerWhileTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200268 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
269 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000270
Primiano Tuccidca727d2018-04-04 11:31:55 +0200271 std::unique_ptr<MockProducer> producer = CreateMockProducer();
272 producer->Connect(svc.get(), "mock_producer");
273 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000274
Sami Kyostila06487a22018-02-27 13:48:38 +0000275 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200276 trace_config.add_buffers()->set_size_kb(128);
Sami Kyostila06487a22018-02-27 13:48:38 +0000277 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200278 ds_config->set_name("data_source");
279 consumer->EnableTracing(trace_config);
Sami Kyostila06487a22018-02-27 13:48:38 +0000280
Primiano Tuccidca727d2018-04-04 11:31:55 +0200281 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100282 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200283 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000284
Primiano Tuccidca727d2018-04-04 11:31:55 +0200285 // Disconnecting and reconnecting a producer with a matching data source.
286 // The Producer should see that data source getting enabled again.
287 producer.reset();
288 producer = CreateMockProducer();
289 producer->Connect(svc.get(), "mock_producer_2");
290 producer->RegisterDataSource("data_source");
291 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100292 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200293 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000294}
295
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100296TEST_F(TracingServiceImplTest, ProducerIDWrapping) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200297 std::vector<std::unique_ptr<MockProducer>> producers;
298 producers.push_back(nullptr);
Primiano Tucci081d46a2018-02-28 11:09:43 +0000299
Primiano Tuccidca727d2018-04-04 11:31:55 +0200300 auto connect_producer_and_get_id = [&producers,
301 this](const std::string& name) {
302 producers.emplace_back(CreateMockProducer());
303 producers.back()->Connect(svc.get(), "mock_producer_" + name);
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200304 return *last_producer_id();
Primiano Tucci081d46a2018-02-28 11:09:43 +0000305 };
306
307 // Connect producers 1-4.
308 for (ProducerID i = 1; i <= 4; i++)
Primiano Tuccidca727d2018-04-04 11:31:55 +0200309 ASSERT_EQ(i, connect_producer_and_get_id(std::to_string(i)));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000310
311 // Disconnect producers 1,3.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200312 producers[1].reset();
313 producers[3].reset();
Primiano Tucci081d46a2018-02-28 11:09:43 +0000314
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200315 *last_producer_id() = kMaxProducerID - 1;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200316 ASSERT_EQ(kMaxProducerID, connect_producer_and_get_id("maxid"));
317 ASSERT_EQ(1u, connect_producer_and_get_id("1_again"));
318 ASSERT_EQ(3u, connect_producer_and_get_id("3_again"));
319 ASSERT_EQ(5u, connect_producer_and_get_id("5"));
320 ASSERT_EQ(6u, connect_producer_and_get_id("6"));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000321}
322
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000323// Note: file_write_period_ms is set to a large enough to have exactly one flush
324// of the tracing buffers (and therefore at most one synchronization section),
325// unless the test runs unrealistically slowly, or the implementation of the
326// tracing snapshot packets changes.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100327TEST_F(TracingServiceImplTest, WriteIntoFileAndStopOnMaxSize) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200328 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
329 consumer->Connect(svc.get());
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100330
Primiano Tuccidca727d2018-04-04 11:31:55 +0200331 std::unique_ptr<MockProducer> producer = CreateMockProducer();
332 producer->Connect(svc.get(), "mock_producer");
333 producer->RegisterDataSource("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100334
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100335 TraceConfig trace_config;
336 trace_config.add_buffers()->set_size_kb(4096);
337 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200338 ds_config->set_name("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100339 ds_config->set_target_buffer(0);
340 trace_config.set_write_into_file(true);
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000341 trace_config.set_file_write_period_ms(100000); // 100s
342 const uint64_t kMaxFileSize = 1024;
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100343 trace_config.set_max_file_size_bytes(kMaxFileSize);
344 base::TempFile tmp_file = base::TempFile::Create();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200345 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
346
347 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100348 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200349 producer->WaitForDataSourceStart("data_source");
350
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000351 static const int kNumPreamblePackets = 4;
352 static const int kNumTestPackets = 10;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200353 static const char kPayload[] = "1234567890abcdef-";
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100354
355 std::unique_ptr<TraceWriter> writer =
Primiano Tuccidca727d2018-04-04 11:31:55 +0200356 producer->CreateTraceWriter("data_source");
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000357 // Tracing service will emit a preamble of packets (a synchronization section,
358 // followed by a tracing config packet). The preamble and these test packets
359 // should fit within kMaxFileSize.
360 for (int i = 0; i < kNumTestPackets; i++) {
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100361 auto tp = writer->NewTracePacket();
362 std::string payload(kPayload);
363 payload.append(std::to_string(i));
364 tp->set_for_testing()->set_str(payload.c_str(), payload.size());
365 }
366
367 // Finally add a packet that overflows kMaxFileSize. This should cause the
368 // implicit stop of the trace and should *not* be written in the trace.
369 {
370 auto tp = writer->NewTracePacket();
371 char big_payload[kMaxFileSize] = "BIG!";
372 tp->set_for_testing()->set_str(big_payload, sizeof(big_payload));
373 }
374 writer->Flush();
375 writer.reset();
376
Primiano Tuccidca727d2018-04-04 11:31:55 +0200377 consumer->DisableTracing();
378 producer->WaitForDataSourceStop("data_source");
379 consumer->WaitForTracingDisabled();
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100380
381 // Verify the contents of the file.
382 std::string trace_raw;
383 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
384 protos::Trace trace;
385 ASSERT_TRUE(trace.ParseFromString(trace_raw));
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000386
387 ASSERT_EQ(trace.packet_size(), kNumPreamblePackets + kNumTestPackets);
388 for (int i = 0; i < kNumTestPackets; i++) {
389 const protos::TracePacket& tp = trace.packet(kNumPreamblePackets + i);
390 ASSERT_EQ(kPayload + std::to_string(i++), tp.for_testing().str());
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100391 }
Primiano Tuccidca727d2018-04-04 11:31:55 +0200392}
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100393
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200394// Test the logic that allows the trace config to set the shm total size and
395// page size from the trace config. Also check that, if the config doesn't
396// specify a value we fall back on the hint provided by the producer.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100397TEST_F(TracingServiceImplTest, ProducerShmAndPageSizeOverriddenByTraceConfig) {
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200398 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
399 consumer->Connect(svc.get());
400 const size_t kConfigPageSizesKb[] = /****/ {16, 16, 4, 0, 16, 8, 3, 4096, 4};
401 const size_t kExpectedPageSizesKb[] = /**/ {16, 16, 4, 4, 16, 8, 4, 64, 4};
402
403 const size_t kConfigSizesKb[] = /**/ {0, 16, 0, 20, 32, 7, 0, 96, 4096000};
404 const size_t kHintSizesKb[] = /****/ {0, 0, 16, 32, 16, 0, 7, 96, 4096000};
405 const size_t kExpectedSizesKb[] = {
406 kDefaultShmSizeKb, // Both hint and config are 0, use default.
407 16, // Hint is 0, use config.
408 16, // Config is 0, use hint.
409 20, // Hint is takes precedence over the config.
410 32, // Ditto, even if config is higher than hint.
411 kDefaultShmSizeKb, // Config is invalid and hint is 0, use default.
412 kDefaultShmSizeKb, // Config is 0 and hint is invalid, use default.
413 kDefaultShmSizeKb, // 96 KB isn't a multiple of the page size (64 KB).
414 kMaxShmSizeKb // Too big, cap at kMaxShmSize.
415 };
416
417 const size_t kNumProducers = base::ArraySize(kHintSizesKb);
418 std::unique_ptr<MockProducer> producer[kNumProducers];
419 for (size_t i = 0; i < kNumProducers; i++) {
420 auto name = "mock_producer_" + std::to_string(i);
421 producer[i] = CreateMockProducer();
422 producer[i]->Connect(svc.get(), name, geteuid(), kHintSizesKb[i] * 1024);
423 producer[i]->RegisterDataSource("data_source");
424 }
425
426 TraceConfig trace_config;
427 trace_config.add_buffers()->set_size_kb(128);
428 auto* ds_config = trace_config.add_data_sources()->mutable_config();
429 ds_config->set_name("data_source");
430 for (size_t i = 0; i < kNumProducers; i++) {
431 auto* producer_config = trace_config.add_producers();
432 producer_config->set_producer_name("mock_producer_" + std::to_string(i));
Primiano Tucci3cbb10a2018-04-10 17:52:40 +0100433 producer_config->set_shm_size_kb(static_cast<uint32_t>(kConfigSizesKb[i]));
434 producer_config->set_page_size_kb(
435 static_cast<uint32_t>(kConfigPageSizesKb[i]));
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200436 }
437
438 consumer->EnableTracing(trace_config);
439 size_t actual_shm_sizes_kb[kNumProducers]{};
440 size_t actual_page_sizes_kb[kNumProducers]{};
441 for (size_t i = 0; i < kNumProducers; i++) {
442 producer[i]->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100443 producer[i]->WaitForDataSourceSetup("data_source");
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200444 actual_shm_sizes_kb[i] =
445 producer[i]->endpoint()->shared_memory()->size() / 1024;
446 actual_page_sizes_kb[i] =
447 producer[i]->endpoint()->shared_buffer_page_size_kb();
448 }
Primiano Tucci674076d2018-10-01 10:41:09 +0100449 for (size_t i = 0; i < kNumProducers; i++) {
450 producer[i]->WaitForDataSourceStart("data_source");
451 }
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200452 ASSERT_THAT(actual_page_sizes_kb, ElementsAreArray(kExpectedPageSizesKb));
453 ASSERT_THAT(actual_shm_sizes_kb, ElementsAreArray(kExpectedSizesKb));
454}
455
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100456TEST_F(TracingServiceImplTest, ExplicitFlush) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200457 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
458 consumer->Connect(svc.get());
459
460 std::unique_ptr<MockProducer> producer = CreateMockProducer();
461 producer->Connect(svc.get(), "mock_producer");
462 producer->RegisterDataSource("data_source");
463
464 TraceConfig trace_config;
465 trace_config.add_buffers()->set_size_kb(128);
466 auto* ds_config = trace_config.add_data_sources()->mutable_config();
467 ds_config->set_name("data_source");
468
469 consumer->EnableTracing(trace_config);
470 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100471 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccid52e6272018-04-06 19:06:53 +0200472 producer->WaitForDataSourceStart("data_source");
473
474 std::unique_ptr<TraceWriter> writer =
475 producer->CreateTraceWriter("data_source");
476 {
477 auto tp = writer->NewTracePacket();
478 tp->set_for_testing()->set_str("payload");
479 }
480
481 auto flush_request = consumer->Flush();
482 producer->WaitForFlush(writer.get());
483 ASSERT_TRUE(flush_request.WaitForReply());
484
485 consumer->DisableTracing();
486 producer->WaitForDataSourceStop("data_source");
487 consumer->WaitForTracingDisabled();
488 EXPECT_THAT(
489 consumer->ReadBuffers(),
490 Contains(Property(&protos::TracePacket::for_testing,
491 Property(&protos::TestEvent::str, Eq("payload")))));
492}
493
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100494TEST_F(TracingServiceImplTest, ImplicitFlushOnTimedTraces) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200495 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
496 consumer->Connect(svc.get());
497
498 std::unique_ptr<MockProducer> producer = CreateMockProducer();
499 producer->Connect(svc.get(), "mock_producer");
500 producer->RegisterDataSource("data_source");
501
502 TraceConfig trace_config;
503 trace_config.add_buffers()->set_size_kb(128);
504 auto* ds_config = trace_config.add_data_sources()->mutable_config();
505 ds_config->set_name("data_source");
506 trace_config.set_duration_ms(1);
507
508 consumer->EnableTracing(trace_config);
509 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100510 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccid52e6272018-04-06 19:06:53 +0200511 producer->WaitForDataSourceStart("data_source");
512
513 std::unique_ptr<TraceWriter> writer =
514 producer->CreateTraceWriter("data_source");
515 {
516 auto tp = writer->NewTracePacket();
517 tp->set_for_testing()->set_str("payload");
518 }
519
520 producer->WaitForFlush(writer.get());
521
522 producer->WaitForDataSourceStop("data_source");
523 consumer->WaitForTracingDisabled();
524
525 EXPECT_THAT(
526 consumer->ReadBuffers(),
527 Contains(Property(&protos::TracePacket::for_testing,
528 Property(&protos::TestEvent::str, Eq("payload")))));
529}
530
531// Tests the monotonic semantic of flush request IDs, i.e., once a producer
532// acks flush request N, all flush requests <= N are considered successful and
533// acked to the consumer.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100534TEST_F(TracingServiceImplTest, BatchFlushes) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200535 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
536 consumer->Connect(svc.get());
537
538 std::unique_ptr<MockProducer> producer = CreateMockProducer();
539 producer->Connect(svc.get(), "mock_producer");
540 producer->RegisterDataSource("data_source");
541
542 TraceConfig trace_config;
543 trace_config.add_buffers()->set_size_kb(128);
544 auto* ds_config = trace_config.add_data_sources()->mutable_config();
545 ds_config->set_name("data_source");
546
547 consumer->EnableTracing(trace_config);
548 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100549 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccid52e6272018-04-06 19:06:53 +0200550 producer->WaitForDataSourceStart("data_source");
551
552 std::unique_ptr<TraceWriter> writer =
553 producer->CreateTraceWriter("data_source");
554 {
555 auto tp = writer->NewTracePacket();
556 tp->set_for_testing()->set_str("payload");
557 }
558
559 auto flush_req_1 = consumer->Flush();
560 auto flush_req_2 = consumer->Flush();
561 auto flush_req_3 = consumer->Flush();
562
563 // We'll deliberately let the 4th flush request timeout. Use a lower timeout
564 // to keep test time short.
565 auto flush_req_4 = consumer->Flush(/*timeout_ms=*/10);
566 ASSERT_EQ(4u, GetNumPendingFlushes());
567
568 // Make the producer reply only to the 3rd flush request.
569 testing::InSequence seq;
570 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 1.
571 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 2.
572 producer->WaitForFlush(writer.get()); // Will reply only to flush id == 3.
573 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 4.
574
575 // Even if the producer explicily replied only to flush ID == 3, all the
576 // previous flushed < 3 should be implicitly acked.
577 ASSERT_TRUE(flush_req_1.WaitForReply());
578 ASSERT_TRUE(flush_req_2.WaitForReply());
579 ASSERT_TRUE(flush_req_3.WaitForReply());
580
581 // At this point flush id == 4 should still be pending and should fail because
582 // of reaching its timeout.
Primiano Tuccid52e6272018-04-06 19:06:53 +0200583 ASSERT_FALSE(flush_req_4.WaitForReply());
584
585 consumer->DisableTracing();
586 producer->WaitForDataSourceStop("data_source");
587 consumer->WaitForTracingDisabled();
588 EXPECT_THAT(
589 consumer->ReadBuffers(),
590 Contains(Property(&protos::TracePacket::for_testing,
591 Property(&protos::TestEvent::str, Eq("payload")))));
592}
593
Primiano Tuccicaa57802018-11-25 11:07:07 +0000594TEST_F(TracingServiceImplTest, PeriodicFlush) {
595 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
596 consumer->Connect(svc.get());
597
598 std::unique_ptr<MockProducer> producer = CreateMockProducer();
599 producer->Connect(svc.get(), "mock_producer");
600 producer->RegisterDataSource("data_source");
601
602 TraceConfig trace_config;
603 trace_config.add_buffers()->set_size_kb(128);
604 trace_config.set_flush_period_ms(1);
605 auto* ds_config = trace_config.add_data_sources()->mutable_config();
606 ds_config->set_name("data_source");
607
608 consumer->EnableTracing(trace_config);
609 producer->WaitForTracingSetup();
610 producer->WaitForDataSourceSetup("data_source");
611 producer->WaitForDataSourceStart("data_source");
612
613 std::unique_ptr<TraceWriter> writer =
614 producer->CreateTraceWriter("data_source");
615
616 const int kNumFlushes = 3;
617 auto checkpoint = task_runner.CreateCheckpoint("all_flushes_done");
618 int flushes_seen = 0;
619 EXPECT_CALL(*producer, Flush(_, _, _))
620 .WillRepeatedly(Invoke([&producer, &writer, &flushes_seen, checkpoint](
621 FlushRequestID flush_req_id,
622 const DataSourceInstanceID*, size_t) {
623 {
624 auto tp = writer->NewTracePacket();
625 char payload[32];
626 sprintf(payload, "f_%d", flushes_seen);
627 tp->set_for_testing()->set_str(payload);
628 }
629 writer->Flush();
630 producer->endpoint()->NotifyFlushComplete(flush_req_id);
631 if (++flushes_seen == kNumFlushes)
632 checkpoint();
633 }));
634 task_runner.RunUntilCheckpoint("all_flushes_done");
635
636 consumer->DisableTracing();
637 producer->WaitForDataSourceStop("data_source");
638 consumer->WaitForTracingDisabled();
639 auto trace_packets = consumer->ReadBuffers();
640 for (int i = 0; i < kNumFlushes; i++) {
641 EXPECT_THAT(trace_packets,
642 Contains(Property(&protos::TracePacket::for_testing,
643 Property(&protos::TestEvent::str,
644 Eq("f_" + std::to_string(i))))));
645 }
646}
647
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100648// Creates a tracing session where some of the data sources set the
649// |will_notify_on_stop| flag and checks that the OnTracingDisabled notification
650// to the consumer is delayed until the acks are received.
651TEST_F(TracingServiceImplTest, OnTracingDisabledWaitsForDataSourceStopAcks) {
652 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
653 consumer->Connect(svc.get());
654
655 std::unique_ptr<MockProducer> producer = CreateMockProducer();
656 producer->Connect(svc.get(), "mock_producer");
657 producer->RegisterDataSource("ds_will_ack_1", /*ack_stop=*/true);
658 producer->RegisterDataSource("ds_wont_ack");
659 producer->RegisterDataSource("ds_will_ack_2", /*ack_stop=*/true);
660
661 TraceConfig trace_config;
662 trace_config.add_buffers()->set_size_kb(128);
663 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack_1");
664 trace_config.add_data_sources()->mutable_config()->set_name("ds_wont_ack");
665 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack_2");
666 trace_config.set_duration_ms(1);
667
668 consumer->EnableTracing(trace_config);
669 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100670
671 producer->WaitForDataSourceSetup("ds_will_ack_1");
672 producer->WaitForDataSourceSetup("ds_wont_ack");
673 producer->WaitForDataSourceSetup("ds_will_ack_2");
674
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100675 producer->WaitForDataSourceStart("ds_will_ack_1");
676 producer->WaitForDataSourceStart("ds_wont_ack");
677 producer->WaitForDataSourceStart("ds_will_ack_2");
678
679 std::unique_ptr<TraceWriter> writer =
680 producer->CreateTraceWriter("ds_wont_ack");
681 producer->WaitForFlush(writer.get());
682
683 DataSourceInstanceID id1 = producer->GetDataSourceInstanceId("ds_will_ack_1");
684 DataSourceInstanceID id2 = producer->GetDataSourceInstanceId("ds_will_ack_2");
685
686 producer->WaitForDataSourceStop("ds_will_ack_1");
687 producer->WaitForDataSourceStop("ds_wont_ack");
688 producer->WaitForDataSourceStop("ds_will_ack_2");
689
690 producer->endpoint()->NotifyDataSourceStopped(id1);
691 producer->endpoint()->NotifyDataSourceStopped(id2);
692
693 // Wait for at most half of the service timeout, so that this test fails if
694 // the service falls back on calling the OnTracingDisabled() because some of
695 // the expected acks weren't received.
696 consumer->WaitForTracingDisabled(
697 TracingServiceImpl::kDataSourceStopTimeoutMs / 2);
698}
699
Oystein Eftevaagf250e1c2018-08-23 16:10:52 -0700700// Creates a tracing session where a second data source
701// is added while the service is waiting for DisableTracing
702// acks; the service should not enable the new datasource
703// and should not hit any asserts when the consumer is
704// subsequently destroyed.
705TEST_F(TracingServiceImplTest, OnDataSourceAddedWhilePendingDisableAcks) {
706 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
707 consumer->Connect(svc.get());
708
709 std::unique_ptr<MockProducer> producer = CreateMockProducer();
710 producer->Connect(svc.get(), "mock_producer");
711 producer->RegisterDataSource("ds_will_ack", /*ack_stop=*/true);
712
713 TraceConfig trace_config;
714 trace_config.add_buffers()->set_size_kb(128);
715 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack");
716 trace_config.add_data_sources()->mutable_config()->set_name("ds_wont_ack");
717
718 consumer->EnableTracing(trace_config);
719 producer->WaitForTracingSetup();
720
721 consumer->DisableTracing();
722
723 producer->RegisterDataSource("ds_wont_ack");
724
725 consumer.reset();
726}
727
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100728// Similar to OnTracingDisabledWaitsForDataSourceStopAcks, but deliberately
729// skips the ack and checks that the service invokes the OnTracingDisabled()
730// after the timeout.
731TEST_F(TracingServiceImplTest, OnTracingDisabledCalledAnywaysInCaseOfTimeout) {
732 svc->override_data_source_test_timeout_ms_for_testing = 1;
733 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
734 consumer->Connect(svc.get());
735
736 std::unique_ptr<MockProducer> producer = CreateMockProducer();
737 producer->Connect(svc.get(), "mock_producer");
738 producer->RegisterDataSource("data_source", /*ack_stop=*/true);
739
740 TraceConfig trace_config;
741 trace_config.add_buffers()->set_size_kb(128);
742 trace_config.add_data_sources()->mutable_config()->set_name("data_source");
743 trace_config.set_duration_ms(1);
744
745 consumer->EnableTracing(trace_config);
746 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100747 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100748 producer->WaitForDataSourceStart("data_source");
749
750 std::unique_ptr<TraceWriter> writer =
751 producer->CreateTraceWriter("data_source");
752 producer->WaitForFlush(writer.get());
753
754 producer->WaitForDataSourceStop("data_source");
755 consumer->WaitForTracingDisabled();
756}
757
Primiano Tucci03de28f2018-08-01 11:29:46 +0100758// Tests the session_id logic. Two data sources in the same tracing session
759// should see the same session id.
760TEST_F(TracingServiceImplTest, SessionId) {
761 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
762 consumer->Connect(svc.get());
763
764 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
765 producer1->Connect(svc.get(), "mock_producer1");
766 producer1->RegisterDataSource("ds_1A");
767 producer1->RegisterDataSource("ds_1B");
768
769 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
770 producer2->Connect(svc.get(), "mock_producer2");
771 producer2->RegisterDataSource("ds_2A");
772
773 testing::InSequence seq;
774 TracingSessionID last_session_id = 0;
775 for (int i = 0; i < 3; i++) {
776 TraceConfig trace_config;
777 trace_config.add_buffers()->set_size_kb(128);
778 trace_config.add_data_sources()->mutable_config()->set_name("ds_1A");
779 trace_config.add_data_sources()->mutable_config()->set_name("ds_1B");
780 trace_config.add_data_sources()->mutable_config()->set_name("ds_2A");
781 trace_config.set_duration_ms(1);
782
783 consumer->EnableTracing(trace_config);
784
785 if (i == 0)
786 producer1->WaitForTracingSetup();
Primiano Tucci03de28f2018-08-01 11:29:46 +0100787
Primiano Tucci674076d2018-10-01 10:41:09 +0100788 producer1->WaitForDataSourceSetup("ds_1A");
789 producer1->WaitForDataSourceSetup("ds_1B");
Primiano Tucci03de28f2018-08-01 11:29:46 +0100790 if (i == 0)
791 producer2->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100792 producer2->WaitForDataSourceSetup("ds_2A");
793
794 producer1->WaitForDataSourceStart("ds_1A");
795 producer1->WaitForDataSourceStart("ds_1B");
Primiano Tucci03de28f2018-08-01 11:29:46 +0100796 producer2->WaitForDataSourceStart("ds_2A");
797
798 auto* ds1 = producer1->GetDataSourceInstance("ds_1A");
799 auto* ds2 = producer1->GetDataSourceInstance("ds_1B");
800 auto* ds3 = producer2->GetDataSourceInstance("ds_2A");
801 ASSERT_EQ(ds1->session_id, ds2->session_id);
802 ASSERT_EQ(ds1->session_id, ds3->session_id);
803 ASSERT_NE(ds1->session_id, last_session_id);
804 last_session_id = ds1->session_id;
805
806 auto writer1 = producer1->CreateTraceWriter("ds_1A");
807 producer1->WaitForFlush(writer1.get());
808
809 auto writer2 = producer2->CreateTraceWriter("ds_2A");
810 producer2->WaitForFlush(writer2.get());
811
812 producer1->WaitForDataSourceStop("ds_1A");
813 producer1->WaitForDataSourceStop("ds_1B");
814 producer2->WaitForDataSourceStop("ds_2A");
815 consumer->WaitForTracingDisabled();
816 consumer->FreeBuffers();
817 }
818}
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100819
820// Writes a long trace and then tests that the trace parsed in partitions
821// derived by the synchronization markers is identical to the whole trace parsed
822// in one go.
823TEST_F(TracingServiceImplTest, ResynchronizeTraceStreamUsingSyncMarker) {
824 // Setup tracing.
825 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
826 consumer->Connect(svc.get());
827 std::unique_ptr<MockProducer> producer = CreateMockProducer();
828 producer->Connect(svc.get(), "mock_producer");
829 producer->RegisterDataSource("data_source");
830 TraceConfig trace_config;
831 trace_config.add_buffers()->set_size_kb(4096);
832 auto* ds_config = trace_config.add_data_sources()->mutable_config();
833 ds_config->set_name("data_source");
834 trace_config.set_write_into_file(true);
835 trace_config.set_file_write_period_ms(1);
836 base::TempFile tmp_file = base::TempFile::Create();
837 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
838 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100839 producer->WaitForDataSourceSetup("data_source");
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100840 producer->WaitForDataSourceStart("data_source");
841
842 // Write some variable length payload, waiting for sync markers every now
843 // and then.
844 const int kNumMarkers = 5;
845 auto writer = producer->CreateTraceWriter("data_source");
846 for (int i = 1; i <= 100; i++) {
Florian Mayereff98042018-12-10 17:44:44 +0000847 std::string payload(static_cast<size_t>(i), 'A' + (i % 25));
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100848 writer->NewTracePacket()->set_for_testing()->set_str(payload.c_str());
849 if (i % (100 / kNumMarkers) == 0) {
850 writer->Flush();
851 WaitForNextSyncMarker();
852 }
853 }
854 writer->Flush();
855 writer.reset();
856 consumer->DisableTracing();
857 producer->WaitForDataSourceStop("data_source");
858 consumer->WaitForTracingDisabled();
859
860 std::string trace_raw;
861 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
862
863 const auto kMarkerSize = sizeof(TracingServiceImpl::kSyncMarker);
864 const std::string kSyncMarkerStr(
865 reinterpret_cast<const char*>(TracingServiceImpl::kSyncMarker),
866 kMarkerSize);
867
868 // Read back the trace in partitions derived from the marker.
869 // The trace should look like this:
870 // [uid, marker] [event] [event] [uid, marker] [event] [event]
871 size_t num_markers = 0;
872 size_t start = 0;
873 size_t end = 0;
874 protos::Trace merged_trace;
875 for (size_t pos = 0; pos != std::string::npos; start = end) {
876 pos = trace_raw.find(kSyncMarkerStr, pos + 1);
877 num_markers++;
878 end = (pos == std::string::npos) ? trace_raw.size() : pos + kMarkerSize;
879 int size = static_cast<int>(end - start);
880 ASSERT_GT(size, 0);
881 protos::Trace trace_partition;
882 ASSERT_TRUE(trace_partition.ParseFromArray(trace_raw.data() + start, size));
883 merged_trace.MergeFrom(trace_partition);
884 }
Lalit Maganti9bdc7ce2018-09-17 15:25:11 +0100885 EXPECT_GE(num_markers, static_cast<size_t>(kNumMarkers));
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100886
887 protos::Trace whole_trace;
888 ASSERT_TRUE(whole_trace.ParseFromString(trace_raw));
889
890 ASSERT_EQ(whole_trace.packet_size(), merged_trace.packet_size());
891 EXPECT_EQ(whole_trace.SerializeAsString(), merged_trace.SerializeAsString());
892}
893
Primiano Tucci674076d2018-10-01 10:41:09 +0100894// Creates a tracing session with |deferred_start| and checks that data sources
895// are started only after calling StartTracing().
896TEST_F(TracingServiceImplTest, DeferredStart) {
897 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
898 consumer->Connect(svc.get());
899
900 std::unique_ptr<MockProducer> producer = CreateMockProducer();
901 producer->Connect(svc.get(), "mock_producer");
902
903 // Create two data sources but enable only one of them.
904 producer->RegisterDataSource("ds_1");
905 producer->RegisterDataSource("ds_2");
906
907 TraceConfig trace_config;
908 trace_config.add_buffers()->set_size_kb(128);
909 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
910 trace_config.set_deferred_start(true);
911 trace_config.set_duration_ms(1);
912
913 consumer->EnableTracing(trace_config);
914 producer->WaitForTracingSetup();
915
916 producer->WaitForDataSourceSetup("ds_1");
917
918 // Make sure we don't get unexpected DataSourceStart() notifications yet.
919 task_runner.RunUntilIdle();
920
921 consumer->StartTracing();
922
923 producer->WaitForDataSourceStart("ds_1");
924
925 auto writer1 = producer->CreateTraceWriter("ds_1");
926 producer->WaitForFlush(writer1.get());
927
928 producer->WaitForDataSourceStop("ds_1");
929 consumer->WaitForTracingDisabled();
930}
931
Eric Seckler6dc23592018-11-30 10:59:06 +0000932TEST_F(TracingServiceImplTest, AllowedBuffers) {
933 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
934 consumer->Connect(svc.get());
935
936 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
937 producer1->Connect(svc.get(), "mock_producer1");
938 ProducerID producer1_id = *last_producer_id();
939 producer1->RegisterDataSource("data_source1");
940 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
941 producer2->Connect(svc.get(), "mock_producer2");
942 ProducerID producer2_id = *last_producer_id();
943 producer2->RegisterDataSource("data_source2.1");
944 producer2->RegisterDataSource("data_source2.2");
945 producer2->RegisterDataSource("data_source2.3");
946
947 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer1_id));
948 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer2_id));
949
950 TraceConfig trace_config;
951 trace_config.add_buffers()->set_size_kb(128);
952 trace_config.add_buffers()->set_size_kb(128);
953 trace_config.add_buffers()->set_size_kb(128);
954 auto* ds_config1 = trace_config.add_data_sources()->mutable_config();
955 ds_config1->set_name("data_source1");
956 ds_config1->set_target_buffer(0);
957 auto* ds_config21 = trace_config.add_data_sources()->mutable_config();
958 ds_config21->set_name("data_source2.1");
959 ds_config21->set_target_buffer(1);
960 auto* ds_config22 = trace_config.add_data_sources()->mutable_config();
961 ds_config22->set_name("data_source2.2");
962 ds_config22->set_target_buffer(2);
963 auto* ds_config23 = trace_config.add_data_sources()->mutable_config();
964 ds_config23->set_name("data_source2.3");
965 ds_config23->set_target_buffer(2); // same buffer as data_source2.2.
966 consumer->EnableTracing(trace_config);
967
Primiano Tucci2abd1152018-12-03 17:00:02 +0100968 ASSERT_EQ(3u, tracing_session()->num_buffers());
Eric Seckler6dc23592018-11-30 10:59:06 +0000969 std::set<BufferID> expected_buffers_producer1 = {
970 tracing_session()->buffers_index[0]};
971 std::set<BufferID> expected_buffers_producer2 = {
972 tracing_session()->buffers_index[1], tracing_session()->buffers_index[2]};
973 EXPECT_EQ(expected_buffers_producer1, GetAllowedTargetBuffers(producer1_id));
974 EXPECT_EQ(expected_buffers_producer2, GetAllowedTargetBuffers(producer2_id));
975
976 producer1->WaitForTracingSetup();
977 producer1->WaitForDataSourceSetup("data_source1");
978
979 producer2->WaitForTracingSetup();
980 producer2->WaitForDataSourceSetup("data_source2.1");
981 producer2->WaitForDataSourceSetup("data_source2.2");
982 producer2->WaitForDataSourceSetup("data_source2.3");
983
984 producer1->WaitForDataSourceStart("data_source1");
985 producer2->WaitForDataSourceStart("data_source2.1");
986 producer2->WaitForDataSourceStart("data_source2.2");
987 producer2->WaitForDataSourceStart("data_source2.3");
988
989 producer2->UnregisterDataSource("data_source2.3");
990 producer2->WaitForDataSourceStop("data_source2.3");
991
992 // Should still be allowed to write to buffers 1 (data_source2.1) and 2
993 // (data_source2.2).
994 EXPECT_EQ(expected_buffers_producer2, GetAllowedTargetBuffers(producer2_id));
995
996 // Calling StartTracing() should be a noop (% a DLOG statement) because the
997 // trace config didn't have the |deferred_start| flag set.
998 consumer->StartTracing();
999
1000 consumer->DisableTracing();
1001 producer1->WaitForDataSourceStop("data_source1");
1002 producer2->WaitForDataSourceStop("data_source2.1");
1003 producer2->WaitForDataSourceStop("data_source2.2");
1004 consumer->WaitForTracingDisabled();
1005
1006 consumer->FreeBuffers();
1007 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer1_id));
1008 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer2_id));
1009}
1010
Eric Seckler6aa9ece2018-12-06 16:40:12 +00001011#if !PERFETTO_DCHECK_IS_ON()
Eric Secklerdd0ad102018-12-06 11:32:04 +00001012TEST_F(TracingServiceImplTest, CommitToForbiddenBufferIsDiscarded) {
1013 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1014 consumer->Connect(svc.get());
1015
1016 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1017 producer->Connect(svc.get(), "mock_producer");
1018 ProducerID producer_id = *last_producer_id();
1019 producer->RegisterDataSource("data_source");
1020
1021 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer_id));
1022
1023 TraceConfig trace_config;
1024 trace_config.add_buffers()->set_size_kb(128);
1025 trace_config.add_buffers()->set_size_kb(128);
1026 auto* ds_config = trace_config.add_data_sources()->mutable_config();
1027 ds_config->set_name("data_source");
1028 ds_config->set_target_buffer(0);
1029 consumer->EnableTracing(trace_config);
1030
1031 ASSERT_EQ(2u, tracing_session()->num_buffers());
1032 std::set<BufferID> expected_buffers = {tracing_session()->buffers_index[0]};
1033 EXPECT_EQ(expected_buffers, GetAllowedTargetBuffers(producer_id));
1034
1035 producer->WaitForTracingSetup();
1036 producer->WaitForDataSourceSetup("data_source");
1037 producer->WaitForDataSourceStart("data_source");
1038
1039 // Calling StartTracing() should be a noop (% a DLOG statement) because the
1040 // trace config didn't have the |deferred_start| flag set.
1041 consumer->StartTracing();
1042
1043 // Try to write to the correct buffer.
1044 std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter(
1045 tracing_session()->buffers_index[0]);
1046 {
1047 auto tp = writer->NewTracePacket();
1048 tp->set_for_testing()->set_str("good_payload");
1049 }
1050
1051 auto flush_request = consumer->Flush();
1052 producer->WaitForFlush(writer.get());
1053 ASSERT_TRUE(flush_request.WaitForReply());
1054
1055 // Try to write to the wrong buffer.
1056 writer = producer->endpoint()->CreateTraceWriter(
1057 tracing_session()->buffers_index[1]);
1058 {
1059 auto tp = writer->NewTracePacket();
1060 tp->set_for_testing()->set_str("bad_payload");
1061 }
1062
1063 flush_request = consumer->Flush();
1064 producer->WaitForFlush(writer.get());
1065 ASSERT_TRUE(flush_request.WaitForReply());
1066
1067 consumer->DisableTracing();
1068 producer->WaitForDataSourceStop("data_source");
1069 consumer->WaitForTracingDisabled();
1070
1071 auto packets = consumer->ReadBuffers();
1072 EXPECT_THAT(packets, Contains(Property(&protos::TracePacket::for_testing,
1073 Property(&protos::TestEvent::str,
1074 Eq("good_payload")))));
1075 EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
1076 Property(&protos::TestEvent::str,
1077 Eq("bad_payload"))))));
1078
1079 consumer->FreeBuffers();
1080 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer_id));
1081}
Eric Seckler6aa9ece2018-12-06 16:40:12 +00001082#endif // !PERFETTO_DCHECK_IS_ON()
Eric Secklerdd0ad102018-12-06 11:32:04 +00001083
Eric Secklerf3f524b2018-12-13 09:09:34 +00001084TEST_F(TracingServiceImplTest, RegisterAndUnregisterTraceWriter) {
1085 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1086 consumer->Connect(svc.get());
1087
1088 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1089 producer->Connect(svc.get(), "mock_producer");
1090 ProducerID producer_id = *last_producer_id();
1091 producer->RegisterDataSource("data_source");
1092
1093 EXPECT_TRUE(GetWriters(producer_id).empty());
1094
1095 TraceConfig trace_config;
1096 trace_config.add_buffers()->set_size_kb(128);
1097 auto* ds_config = trace_config.add_data_sources()->mutable_config();
1098 ds_config->set_name("data_source");
1099 ds_config->set_target_buffer(0);
1100 consumer->EnableTracing(trace_config);
1101
1102 producer->WaitForTracingSetup();
1103 producer->WaitForDataSourceSetup("data_source");
1104 producer->WaitForDataSourceStart("data_source");
1105
1106 // Calling StartTracing() should be a noop (% a DLOG statement) because the
1107 // trace config didn't have the |deferred_start| flag set.
1108 consumer->StartTracing();
1109
1110 // Creating the trace writer should register it with the service.
1111 std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter(
1112 tracing_session()->buffers_index[0]);
1113
1114 WaitForTraceWritersChanged(producer_id);
1115
1116 std::map<WriterID, BufferID> expected_writers;
1117 expected_writers[writer->writer_id()] = tracing_session()->buffers_index[0];
1118 EXPECT_EQ(expected_writers, GetWriters(producer_id));
1119
1120 // Verify writing works.
1121 {
1122 auto tp = writer->NewTracePacket();
1123 tp->set_for_testing()->set_str("payload");
1124 }
1125
1126 auto flush_request = consumer->Flush();
1127 producer->WaitForFlush(writer.get());
1128 ASSERT_TRUE(flush_request.WaitForReply());
1129
1130 // Destroying the writer should unregister it.
1131 writer.reset();
1132 WaitForTraceWritersChanged(producer_id);
1133 EXPECT_TRUE(GetWriters(producer_id).empty());
1134
1135 consumer->DisableTracing();
1136 producer->WaitForDataSourceStop("data_source");
1137 consumer->WaitForTracingDisabled();
1138
1139 auto packets = consumer->ReadBuffers();
1140 EXPECT_THAT(packets, Contains(Property(
1141 &protos::TracePacket::for_testing,
1142 Property(&protos::TestEvent::str, Eq("payload")))));
1143}
1144
Primiano Tucci4f9b6d72017-12-05 20:59:16 +00001145} // namespace perfetto