blob: 812a91b0e77597d200c85d14c8fc5264f2439b68 [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"
Primiano Tuccidca727d2018-04-04 11:31:55 +020034#include "src/tracing/test/mock_consumer.h"
35#include "src/tracing/test/mock_producer.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000036#include "src/tracing/test/test_shared_memory.h"
37
Primiano Tucci2ffd1a52018-03-27 01:01:30 +010038#include "perfetto/trace/test_event.pbzero.h"
39#include "perfetto/trace/trace.pb.h"
Primiano Tuccidca727d2018-04-04 11:31:55 +020040#include "perfetto/trace/trace_packet.pb.h"
Primiano Tucci2ffd1a52018-03-27 01:01:30 +010041#include "perfetto/trace/trace_packet.pbzero.h"
42
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000043using ::testing::_;
Primiano Tuccidca727d2018-04-04 11:31:55 +020044using ::testing::Contains;
Primiano Tucci1a1951d2018-04-04 21:08:16 +020045using ::testing::ElementsAreArray;
Primiano Tuccidca727d2018-04-04 11:31:55 +020046using ::testing::Eq;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000047using ::testing::InSequence;
Primiano Tucci081d46a2018-02-28 11:09:43 +000048using ::testing::Invoke;
Primiano Tuccidca727d2018-04-04 11:31:55 +020049using ::testing::InvokeWithoutArgs;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000050using ::testing::Mock;
Primiano Tuccidca727d2018-04-04 11:31:55 +020051using ::testing::Property;
52using ::testing::StrictMock;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000053
Primiano Tuccidca727d2018-04-04 11:31:55 +020054namespace perfetto {
Sami Kyostila32e0b542018-02-14 08:55:43 +000055
Primiano Tucci1a1951d2018-04-04 21:08:16 +020056namespace {
Florian Mayer6a1a4d52018-06-08 16:47:07 +010057constexpr size_t kDefaultShmSizeKb = TracingServiceImpl::kDefaultShmSize / 1024;
58constexpr size_t kMaxShmSizeKb = TracingServiceImpl::kMaxShmSize / 1024;
Primiano Tucci1a1951d2018-04-04 21:08:16 +020059} // namespace
60
Florian Mayer6a1a4d52018-06-08 16:47:07 +010061class TracingServiceImplTest : public testing::Test {
Sami Kyostila06487a22018-02-27 13:48:38 +000062 public:
Florian Mayer6a1a4d52018-06-08 16:47:07 +010063 TracingServiceImplTest() {
Sami Kyostila06487a22018-02-27 13:48:38 +000064 auto shm_factory =
65 std::unique_ptr<SharedMemory::Factory>(new TestSharedMemory::Factory());
Florian Mayer6a1a4d52018-06-08 16:47:07 +010066 svc.reset(static_cast<TracingServiceImpl*>(
67 TracingService::CreateInstance(std::move(shm_factory), &task_runner)
Sami Kyostila06487a22018-02-27 13:48:38 +000068 .release()));
Primiano Tucci9754d0d2018-09-15 12:41:46 +010069 svc->min_write_period_ms_ = 1;
Sami Kyostila06487a22018-02-27 13:48:38 +000070 }
71
Primiano Tuccidca727d2018-04-04 11:31:55 +020072 std::unique_ptr<MockProducer> CreateMockProducer() {
73 return std::unique_ptr<MockProducer>(
74 new StrictMock<MockProducer>(&task_runner));
75 }
76
77 std::unique_ptr<MockConsumer> CreateMockConsumer() {
78 return std::unique_ptr<MockConsumer>(
79 new StrictMock<MockConsumer>(&task_runner));
80 }
81
Primiano Tucci1a1951d2018-04-04 21:08:16 +020082 ProducerID* last_producer_id() { return &svc->last_producer_id_; }
83
84 uid_t GetProducerUid(ProducerID producer_id) {
85 return svc->GetProducer(producer_id)->uid_;
86 }
87
Primiano Tucci9754d0d2018-09-15 12:41:46 +010088 TracingServiceImpl::TracingSession* tracing_session() {
89 auto* session = svc->GetTracingSession(svc->last_tracing_session_id_);
90 EXPECT_NE(nullptr, session);
91 return session;
92 }
93
Eric Seckler6dc23592018-11-30 10:59:06 +000094 const std::set<BufferID>& GetAllowedTargetBuffers(ProducerID producer_id) {
95 return svc->GetProducer(producer_id)->allowed_target_buffers_;
96 }
97
Primiano Tuccid52e6272018-04-06 19:06:53 +020098 size_t GetNumPendingFlushes() {
Primiano Tucci9754d0d2018-09-15 12:41:46 +010099 return tracing_session()->pending_flushes.size();
100 }
101
102 void WaitForNextSyncMarker() {
103 tracing_session()->last_snapshot_time = base::TimeMillis(0);
104 static int attempt = 0;
105 while (tracing_session()->last_snapshot_time == base::TimeMillis(0)) {
106 auto checkpoint_name = "wait_snapshot_" + std::to_string(attempt++);
107 auto timer_expired = task_runner.CreateCheckpoint(checkpoint_name);
108 task_runner.PostDelayedTask([timer_expired] { timer_expired(); }, 1);
109 task_runner.RunUntilCheckpoint(checkpoint_name);
110 }
Primiano Tuccid52e6272018-04-06 19:06:53 +0200111 }
112
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000113 base::TestTaskRunner task_runner;
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100114 std::unique_ptr<TracingServiceImpl> svc;
Sami Kyostila06487a22018-02-27 13:48:38 +0000115};
116
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100117TEST_F(TracingServiceImplTest, RegisterAndUnregister) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200118 std::unique_ptr<MockProducer> mock_producer_1 = CreateMockProducer();
119 std::unique_ptr<MockProducer> mock_producer_2 = CreateMockProducer();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000120
Primiano Tuccidca727d2018-04-04 11:31:55 +0200121 mock_producer_1->Connect(svc.get(), "mock_producer_1", 123u /* uid */);
122 mock_producer_2->Connect(svc.get(), "mock_producer_2", 456u /* uid */);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000123
124 ASSERT_EQ(2u, svc->num_producers());
Primiano Tuccidca727d2018-04-04 11:31:55 +0200125 ASSERT_EQ(mock_producer_1->endpoint(), svc->GetProducer(1));
126 ASSERT_EQ(mock_producer_2->endpoint(), svc->GetProducer(2));
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200127 ASSERT_EQ(123u, GetProducerUid(1));
128 ASSERT_EQ(456u, GetProducerUid(2));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000129
Primiano Tuccidca727d2018-04-04 11:31:55 +0200130 mock_producer_1->RegisterDataSource("foo");
131 mock_producer_2->RegisterDataSource("bar");
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000132
Primiano Tuccidca727d2018-04-04 11:31:55 +0200133 mock_producer_1->UnregisterDataSource("foo");
134 mock_producer_2->UnregisterDataSource("bar");
Primiano Tucci9daa4832018-03-28 23:28:17 +0100135
Primiano Tuccidca727d2018-04-04 11:31:55 +0200136 mock_producer_1.reset();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000137 ASSERT_EQ(1u, svc->num_producers());
138 ASSERT_EQ(nullptr, svc->GetProducer(1));
139
Primiano Tuccidca727d2018-04-04 11:31:55 +0200140 mock_producer_2.reset();
141 ASSERT_EQ(nullptr, svc->GetProducer(2));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000142
143 ASSERT_EQ(0u, svc->num_producers());
144}
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100145
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100146TEST_F(TracingServiceImplTest, EnableAndDisableTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200147 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
148 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000149
Primiano Tuccidca727d2018-04-04 11:31:55 +0200150 std::unique_ptr<MockProducer> producer = CreateMockProducer();
151 producer->Connect(svc.get(), "mock_producer");
152 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000153
Sami Kyostila06487a22018-02-27 13:48:38 +0000154 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200155 trace_config.add_buffers()->set_size_kb(128);
Sami Kyostila06487a22018-02-27 13:48:38 +0000156 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200157 ds_config->set_name("data_source");
158 consumer->EnableTracing(trace_config);
Sami Kyostila06487a22018-02-27 13:48:38 +0000159
Primiano Tuccidca727d2018-04-04 11:31:55 +0200160 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100161 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200162 producer->WaitForDataSourceStart("data_source");
163
Primiano Tucci674076d2018-10-01 10:41:09 +0100164 // Calling StartTracing() should be a noop (% a DLOG statement) because the
165 // trace config didn't have the |deferred_start| flag set.
166 consumer->StartTracing();
167
Primiano Tuccidca727d2018-04-04 11:31:55 +0200168 consumer->DisableTracing();
169 producer->WaitForDataSourceStop("data_source");
170 consumer->WaitForTracingDisabled();
Sami Kyostila06487a22018-02-27 13:48:38 +0000171}
172
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100173TEST_F(TracingServiceImplTest, LockdownMode) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200174 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
175 consumer->Connect(svc.get());
176
177 std::unique_ptr<MockProducer> producer = CreateMockProducer();
178 producer->Connect(svc.get(), "mock_producer_sameuid", geteuid());
179 producer->RegisterDataSource("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000180
181 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200182 trace_config.add_buffers()->set_size_kb(128);
183 auto* ds_config = trace_config.add_data_sources()->mutable_config();
184 ds_config->set_name("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000185 trace_config.set_lockdown_mode(
186 TraceConfig::LockdownModeOperation::LOCKDOWN_SET);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200187 consumer->EnableTracing(trace_config);
188
189 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100190 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200191 producer->WaitForDataSourceStart("data_source");
192
193 std::unique_ptr<MockProducer> producer_otheruid = CreateMockProducer();
194 auto x = svc->ConnectProducer(producer_otheruid.get(), geteuid() + 1,
195 "mock_producer_ouid");
196 EXPECT_CALL(*producer_otheruid, OnConnect()).Times(0);
Florian Mayer61c55482018-03-06 14:43:54 +0000197 task_runner.RunUntilIdle();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200198 Mock::VerifyAndClearExpectations(producer_otheruid.get());
Florian Mayer61c55482018-03-06 14:43:54 +0000199
Primiano Tuccidca727d2018-04-04 11:31:55 +0200200 consumer->DisableTracing();
201 consumer->FreeBuffers();
202 producer->WaitForDataSourceStop("data_source");
203 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000204
205 trace_config.set_lockdown_mode(
206 TraceConfig::LockdownModeOperation::LOCKDOWN_CLEAR);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200207 consumer->EnableTracing(trace_config);
Primiano Tucci674076d2018-10-01 10:41:09 +0100208 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200209 producer->WaitForDataSourceStart("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000210
Primiano Tuccidca727d2018-04-04 11:31:55 +0200211 std::unique_ptr<MockProducer> producer_otheruid2 = CreateMockProducer();
212 producer_otheruid->Connect(svc.get(), "mock_producer_ouid2", geteuid() + 1);
Florian Mayer61c55482018-03-06 14:43:54 +0000213
Primiano Tuccidca727d2018-04-04 11:31:55 +0200214 consumer->DisableTracing();
215 producer->WaitForDataSourceStop("data_source");
216 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000217}
218
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100219TEST_F(TracingServiceImplTest, DisconnectConsumerWhileTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200220 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
221 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000222
Primiano Tuccidca727d2018-04-04 11:31:55 +0200223 std::unique_ptr<MockProducer> producer = CreateMockProducer();
224 producer->Connect(svc.get(), "mock_producer");
225 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000226
Primiano Tuccidca727d2018-04-04 11:31:55 +0200227 TraceConfig trace_config;
228 trace_config.add_buffers()->set_size_kb(128);
229 auto* ds_config = trace_config.add_data_sources()->mutable_config();
230 ds_config->set_name("data_source");
231 consumer->EnableTracing(trace_config);
232
233 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100234 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200235 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000236
237 // Disconnecting the consumer while tracing should trigger data source
238 // teardown.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200239 consumer.reset();
240 producer->WaitForDataSourceStop("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000241}
242
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100243TEST_F(TracingServiceImplTest, ReconnectProducerWhileTracing) {
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
Sami Kyostila06487a22018-02-27 13:48:38 +0000251 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200252 trace_config.add_buffers()->set_size_kb(128);
Sami Kyostila06487a22018-02-27 13:48:38 +0000253 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200254 ds_config->set_name("data_source");
255 consumer->EnableTracing(trace_config);
Sami Kyostila06487a22018-02-27 13:48:38 +0000256
Primiano Tuccidca727d2018-04-04 11:31:55 +0200257 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
Primiano Tuccidca727d2018-04-04 11:31:55 +0200261 // Disconnecting and reconnecting a producer with a matching data source.
262 // The Producer should see that data source getting enabled again.
263 producer.reset();
264 producer = CreateMockProducer();
265 producer->Connect(svc.get(), "mock_producer_2");
266 producer->RegisterDataSource("data_source");
267 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100268 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200269 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000270}
271
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100272TEST_F(TracingServiceImplTest, ProducerIDWrapping) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200273 std::vector<std::unique_ptr<MockProducer>> producers;
274 producers.push_back(nullptr);
Primiano Tucci081d46a2018-02-28 11:09:43 +0000275
Primiano Tuccidca727d2018-04-04 11:31:55 +0200276 auto connect_producer_and_get_id = [&producers,
277 this](const std::string& name) {
278 producers.emplace_back(CreateMockProducer());
279 producers.back()->Connect(svc.get(), "mock_producer_" + name);
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200280 return *last_producer_id();
Primiano Tucci081d46a2018-02-28 11:09:43 +0000281 };
282
283 // Connect producers 1-4.
284 for (ProducerID i = 1; i <= 4; i++)
Primiano Tuccidca727d2018-04-04 11:31:55 +0200285 ASSERT_EQ(i, connect_producer_and_get_id(std::to_string(i)));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000286
287 // Disconnect producers 1,3.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200288 producers[1].reset();
289 producers[3].reset();
Primiano Tucci081d46a2018-02-28 11:09:43 +0000290
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200291 *last_producer_id() = kMaxProducerID - 1;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200292 ASSERT_EQ(kMaxProducerID, connect_producer_and_get_id("maxid"));
293 ASSERT_EQ(1u, connect_producer_and_get_id("1_again"));
294 ASSERT_EQ(3u, connect_producer_and_get_id("3_again"));
295 ASSERT_EQ(5u, connect_producer_and_get_id("5"));
296 ASSERT_EQ(6u, connect_producer_and_get_id("6"));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000297}
298
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000299// Note: file_write_period_ms is set to a large enough to have exactly one flush
300// of the tracing buffers (and therefore at most one synchronization section),
301// unless the test runs unrealistically slowly, or the implementation of the
302// tracing snapshot packets changes.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100303TEST_F(TracingServiceImplTest, WriteIntoFileAndStopOnMaxSize) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200304 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
305 consumer->Connect(svc.get());
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100306
Primiano Tuccidca727d2018-04-04 11:31:55 +0200307 std::unique_ptr<MockProducer> producer = CreateMockProducer();
308 producer->Connect(svc.get(), "mock_producer");
309 producer->RegisterDataSource("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100310
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100311 TraceConfig trace_config;
312 trace_config.add_buffers()->set_size_kb(4096);
313 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200314 ds_config->set_name("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100315 ds_config->set_target_buffer(0);
316 trace_config.set_write_into_file(true);
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000317 trace_config.set_file_write_period_ms(100000); // 100s
318 const uint64_t kMaxFileSize = 1024;
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100319 trace_config.set_max_file_size_bytes(kMaxFileSize);
320 base::TempFile tmp_file = base::TempFile::Create();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200321 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
322
323 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100324 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200325 producer->WaitForDataSourceStart("data_source");
326
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000327 static const int kNumPreamblePackets = 4;
328 static const int kNumTestPackets = 10;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200329 static const char kPayload[] = "1234567890abcdef-";
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100330
331 std::unique_ptr<TraceWriter> writer =
Primiano Tuccidca727d2018-04-04 11:31:55 +0200332 producer->CreateTraceWriter("data_source");
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000333 // Tracing service will emit a preamble of packets (a synchronization section,
334 // followed by a tracing config packet). The preamble and these test packets
335 // should fit within kMaxFileSize.
336 for (int i = 0; i < kNumTestPackets; i++) {
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100337 auto tp = writer->NewTracePacket();
338 std::string payload(kPayload);
339 payload.append(std::to_string(i));
340 tp->set_for_testing()->set_str(payload.c_str(), payload.size());
341 }
342
343 // Finally add a packet that overflows kMaxFileSize. This should cause the
344 // implicit stop of the trace and should *not* be written in the trace.
345 {
346 auto tp = writer->NewTracePacket();
347 char big_payload[kMaxFileSize] = "BIG!";
348 tp->set_for_testing()->set_str(big_payload, sizeof(big_payload));
349 }
350 writer->Flush();
351 writer.reset();
352
Primiano Tuccidca727d2018-04-04 11:31:55 +0200353 consumer->DisableTracing();
354 producer->WaitForDataSourceStop("data_source");
355 consumer->WaitForTracingDisabled();
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100356
357 // Verify the contents of the file.
358 std::string trace_raw;
359 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
360 protos::Trace trace;
361 ASSERT_TRUE(trace.ParseFromString(trace_raw));
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000362
363 ASSERT_EQ(trace.packet_size(), kNumPreamblePackets + kNumTestPackets);
364 for (int i = 0; i < kNumTestPackets; i++) {
365 const protos::TracePacket& tp = trace.packet(kNumPreamblePackets + i);
366 ASSERT_EQ(kPayload + std::to_string(i++), tp.for_testing().str());
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100367 }
Primiano Tuccidca727d2018-04-04 11:31:55 +0200368}
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100369
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200370// Test the logic that allows the trace config to set the shm total size and
371// page size from the trace config. Also check that, if the config doesn't
372// specify a value we fall back on the hint provided by the producer.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100373TEST_F(TracingServiceImplTest, ProducerShmAndPageSizeOverriddenByTraceConfig) {
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200374 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
375 consumer->Connect(svc.get());
376 const size_t kConfigPageSizesKb[] = /****/ {16, 16, 4, 0, 16, 8, 3, 4096, 4};
377 const size_t kExpectedPageSizesKb[] = /**/ {16, 16, 4, 4, 16, 8, 4, 64, 4};
378
379 const size_t kConfigSizesKb[] = /**/ {0, 16, 0, 20, 32, 7, 0, 96, 4096000};
380 const size_t kHintSizesKb[] = /****/ {0, 0, 16, 32, 16, 0, 7, 96, 4096000};
381 const size_t kExpectedSizesKb[] = {
382 kDefaultShmSizeKb, // Both hint and config are 0, use default.
383 16, // Hint is 0, use config.
384 16, // Config is 0, use hint.
385 20, // Hint is takes precedence over the config.
386 32, // Ditto, even if config is higher than hint.
387 kDefaultShmSizeKb, // Config is invalid and hint is 0, use default.
388 kDefaultShmSizeKb, // Config is 0 and hint is invalid, use default.
389 kDefaultShmSizeKb, // 96 KB isn't a multiple of the page size (64 KB).
390 kMaxShmSizeKb // Too big, cap at kMaxShmSize.
391 };
392
393 const size_t kNumProducers = base::ArraySize(kHintSizesKb);
394 std::unique_ptr<MockProducer> producer[kNumProducers];
395 for (size_t i = 0; i < kNumProducers; i++) {
396 auto name = "mock_producer_" + std::to_string(i);
397 producer[i] = CreateMockProducer();
398 producer[i]->Connect(svc.get(), name, geteuid(), kHintSizesKb[i] * 1024);
399 producer[i]->RegisterDataSource("data_source");
400 }
401
402 TraceConfig trace_config;
403 trace_config.add_buffers()->set_size_kb(128);
404 auto* ds_config = trace_config.add_data_sources()->mutable_config();
405 ds_config->set_name("data_source");
406 for (size_t i = 0; i < kNumProducers; i++) {
407 auto* producer_config = trace_config.add_producers();
408 producer_config->set_producer_name("mock_producer_" + std::to_string(i));
Primiano Tucci3cbb10a2018-04-10 17:52:40 +0100409 producer_config->set_shm_size_kb(static_cast<uint32_t>(kConfigSizesKb[i]));
410 producer_config->set_page_size_kb(
411 static_cast<uint32_t>(kConfigPageSizesKb[i]));
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200412 }
413
414 consumer->EnableTracing(trace_config);
415 size_t actual_shm_sizes_kb[kNumProducers]{};
416 size_t actual_page_sizes_kb[kNumProducers]{};
417 for (size_t i = 0; i < kNumProducers; i++) {
418 producer[i]->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100419 producer[i]->WaitForDataSourceSetup("data_source");
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200420 actual_shm_sizes_kb[i] =
421 producer[i]->endpoint()->shared_memory()->size() / 1024;
422 actual_page_sizes_kb[i] =
423 producer[i]->endpoint()->shared_buffer_page_size_kb();
424 }
Primiano Tucci674076d2018-10-01 10:41:09 +0100425 for (size_t i = 0; i < kNumProducers; i++) {
426 producer[i]->WaitForDataSourceStart("data_source");
427 }
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200428 ASSERT_THAT(actual_page_sizes_kb, ElementsAreArray(kExpectedPageSizesKb));
429 ASSERT_THAT(actual_shm_sizes_kb, ElementsAreArray(kExpectedSizesKb));
430}
431
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100432TEST_F(TracingServiceImplTest, ExplicitFlush) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200433 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
434 consumer->Connect(svc.get());
435
436 std::unique_ptr<MockProducer> producer = CreateMockProducer();
437 producer->Connect(svc.get(), "mock_producer");
438 producer->RegisterDataSource("data_source");
439
440 TraceConfig trace_config;
441 trace_config.add_buffers()->set_size_kb(128);
442 auto* ds_config = trace_config.add_data_sources()->mutable_config();
443 ds_config->set_name("data_source");
444
445 consumer->EnableTracing(trace_config);
446 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100447 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccid52e6272018-04-06 19:06:53 +0200448 producer->WaitForDataSourceStart("data_source");
449
450 std::unique_ptr<TraceWriter> writer =
451 producer->CreateTraceWriter("data_source");
452 {
453 auto tp = writer->NewTracePacket();
454 tp->set_for_testing()->set_str("payload");
455 }
456
457 auto flush_request = consumer->Flush();
458 producer->WaitForFlush(writer.get());
459 ASSERT_TRUE(flush_request.WaitForReply());
460
461 consumer->DisableTracing();
462 producer->WaitForDataSourceStop("data_source");
463 consumer->WaitForTracingDisabled();
464 EXPECT_THAT(
465 consumer->ReadBuffers(),
466 Contains(Property(&protos::TracePacket::for_testing,
467 Property(&protos::TestEvent::str, Eq("payload")))));
468}
469
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100470TEST_F(TracingServiceImplTest, ImplicitFlushOnTimedTraces) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200471 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
472 consumer->Connect(svc.get());
473
474 std::unique_ptr<MockProducer> producer = CreateMockProducer();
475 producer->Connect(svc.get(), "mock_producer");
476 producer->RegisterDataSource("data_source");
477
478 TraceConfig trace_config;
479 trace_config.add_buffers()->set_size_kb(128);
480 auto* ds_config = trace_config.add_data_sources()->mutable_config();
481 ds_config->set_name("data_source");
482 trace_config.set_duration_ms(1);
483
484 consumer->EnableTracing(trace_config);
485 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100486 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccid52e6272018-04-06 19:06:53 +0200487 producer->WaitForDataSourceStart("data_source");
488
489 std::unique_ptr<TraceWriter> writer =
490 producer->CreateTraceWriter("data_source");
491 {
492 auto tp = writer->NewTracePacket();
493 tp->set_for_testing()->set_str("payload");
494 }
495
496 producer->WaitForFlush(writer.get());
497
498 producer->WaitForDataSourceStop("data_source");
499 consumer->WaitForTracingDisabled();
500
501 EXPECT_THAT(
502 consumer->ReadBuffers(),
503 Contains(Property(&protos::TracePacket::for_testing,
504 Property(&protos::TestEvent::str, Eq("payload")))));
505}
506
507// Tests the monotonic semantic of flush request IDs, i.e., once a producer
508// acks flush request N, all flush requests <= N are considered successful and
509// acked to the consumer.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100510TEST_F(TracingServiceImplTest, BatchFlushes) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200511 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
512 consumer->Connect(svc.get());
513
514 std::unique_ptr<MockProducer> producer = CreateMockProducer();
515 producer->Connect(svc.get(), "mock_producer");
516 producer->RegisterDataSource("data_source");
517
518 TraceConfig trace_config;
519 trace_config.add_buffers()->set_size_kb(128);
520 auto* ds_config = trace_config.add_data_sources()->mutable_config();
521 ds_config->set_name("data_source");
522
523 consumer->EnableTracing(trace_config);
524 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100525 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccid52e6272018-04-06 19:06:53 +0200526 producer->WaitForDataSourceStart("data_source");
527
528 std::unique_ptr<TraceWriter> writer =
529 producer->CreateTraceWriter("data_source");
530 {
531 auto tp = writer->NewTracePacket();
532 tp->set_for_testing()->set_str("payload");
533 }
534
535 auto flush_req_1 = consumer->Flush();
536 auto flush_req_2 = consumer->Flush();
537 auto flush_req_3 = consumer->Flush();
538
539 // We'll deliberately let the 4th flush request timeout. Use a lower timeout
540 // to keep test time short.
541 auto flush_req_4 = consumer->Flush(/*timeout_ms=*/10);
542 ASSERT_EQ(4u, GetNumPendingFlushes());
543
544 // Make the producer reply only to the 3rd flush request.
545 testing::InSequence seq;
546 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 1.
547 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 2.
548 producer->WaitForFlush(writer.get()); // Will reply only to flush id == 3.
549 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 4.
550
551 // Even if the producer explicily replied only to flush ID == 3, all the
552 // previous flushed < 3 should be implicitly acked.
553 ASSERT_TRUE(flush_req_1.WaitForReply());
554 ASSERT_TRUE(flush_req_2.WaitForReply());
555 ASSERT_TRUE(flush_req_3.WaitForReply());
556
557 // At this point flush id == 4 should still be pending and should fail because
558 // of reaching its timeout.
Primiano Tuccid52e6272018-04-06 19:06:53 +0200559 ASSERT_FALSE(flush_req_4.WaitForReply());
560
561 consumer->DisableTracing();
562 producer->WaitForDataSourceStop("data_source");
563 consumer->WaitForTracingDisabled();
564 EXPECT_THAT(
565 consumer->ReadBuffers(),
566 Contains(Property(&protos::TracePacket::for_testing,
567 Property(&protos::TestEvent::str, Eq("payload")))));
568}
569
Primiano Tuccicaa57802018-11-25 11:07:07 +0000570TEST_F(TracingServiceImplTest, PeriodicFlush) {
571 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
572 consumer->Connect(svc.get());
573
574 std::unique_ptr<MockProducer> producer = CreateMockProducer();
575 producer->Connect(svc.get(), "mock_producer");
576 producer->RegisterDataSource("data_source");
577
578 TraceConfig trace_config;
579 trace_config.add_buffers()->set_size_kb(128);
580 trace_config.set_flush_period_ms(1);
581 auto* ds_config = trace_config.add_data_sources()->mutable_config();
582 ds_config->set_name("data_source");
583
584 consumer->EnableTracing(trace_config);
585 producer->WaitForTracingSetup();
586 producer->WaitForDataSourceSetup("data_source");
587 producer->WaitForDataSourceStart("data_source");
588
589 std::unique_ptr<TraceWriter> writer =
590 producer->CreateTraceWriter("data_source");
591
592 const int kNumFlushes = 3;
593 auto checkpoint = task_runner.CreateCheckpoint("all_flushes_done");
594 int flushes_seen = 0;
595 EXPECT_CALL(*producer, Flush(_, _, _))
596 .WillRepeatedly(Invoke([&producer, &writer, &flushes_seen, checkpoint](
597 FlushRequestID flush_req_id,
598 const DataSourceInstanceID*, size_t) {
599 {
600 auto tp = writer->NewTracePacket();
601 char payload[32];
602 sprintf(payload, "f_%d", flushes_seen);
603 tp->set_for_testing()->set_str(payload);
604 }
605 writer->Flush();
606 producer->endpoint()->NotifyFlushComplete(flush_req_id);
607 if (++flushes_seen == kNumFlushes)
608 checkpoint();
609 }));
610 task_runner.RunUntilCheckpoint("all_flushes_done");
611
612 consumer->DisableTracing();
613 producer->WaitForDataSourceStop("data_source");
614 consumer->WaitForTracingDisabled();
615 auto trace_packets = consumer->ReadBuffers();
616 for (int i = 0; i < kNumFlushes; i++) {
617 EXPECT_THAT(trace_packets,
618 Contains(Property(&protos::TracePacket::for_testing,
619 Property(&protos::TestEvent::str,
620 Eq("f_" + std::to_string(i))))));
621 }
622}
623
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100624// Creates a tracing session where some of the data sources set the
625// |will_notify_on_stop| flag and checks that the OnTracingDisabled notification
626// to the consumer is delayed until the acks are received.
627TEST_F(TracingServiceImplTest, OnTracingDisabledWaitsForDataSourceStopAcks) {
628 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
629 consumer->Connect(svc.get());
630
631 std::unique_ptr<MockProducer> producer = CreateMockProducer();
632 producer->Connect(svc.get(), "mock_producer");
633 producer->RegisterDataSource("ds_will_ack_1", /*ack_stop=*/true);
634 producer->RegisterDataSource("ds_wont_ack");
635 producer->RegisterDataSource("ds_will_ack_2", /*ack_stop=*/true);
636
637 TraceConfig trace_config;
638 trace_config.add_buffers()->set_size_kb(128);
639 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack_1");
640 trace_config.add_data_sources()->mutable_config()->set_name("ds_wont_ack");
641 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack_2");
642 trace_config.set_duration_ms(1);
643
644 consumer->EnableTracing(trace_config);
645 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100646
647 producer->WaitForDataSourceSetup("ds_will_ack_1");
648 producer->WaitForDataSourceSetup("ds_wont_ack");
649 producer->WaitForDataSourceSetup("ds_will_ack_2");
650
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100651 producer->WaitForDataSourceStart("ds_will_ack_1");
652 producer->WaitForDataSourceStart("ds_wont_ack");
653 producer->WaitForDataSourceStart("ds_will_ack_2");
654
655 std::unique_ptr<TraceWriter> writer =
656 producer->CreateTraceWriter("ds_wont_ack");
657 producer->WaitForFlush(writer.get());
658
659 DataSourceInstanceID id1 = producer->GetDataSourceInstanceId("ds_will_ack_1");
660 DataSourceInstanceID id2 = producer->GetDataSourceInstanceId("ds_will_ack_2");
661
662 producer->WaitForDataSourceStop("ds_will_ack_1");
663 producer->WaitForDataSourceStop("ds_wont_ack");
664 producer->WaitForDataSourceStop("ds_will_ack_2");
665
666 producer->endpoint()->NotifyDataSourceStopped(id1);
667 producer->endpoint()->NotifyDataSourceStopped(id2);
668
669 // Wait for at most half of the service timeout, so that this test fails if
670 // the service falls back on calling the OnTracingDisabled() because some of
671 // the expected acks weren't received.
672 consumer->WaitForTracingDisabled(
673 TracingServiceImpl::kDataSourceStopTimeoutMs / 2);
674}
675
Oystein Eftevaagf250e1c2018-08-23 16:10:52 -0700676// Creates a tracing session where a second data source
677// is added while the service is waiting for DisableTracing
678// acks; the service should not enable the new datasource
679// and should not hit any asserts when the consumer is
680// subsequently destroyed.
681TEST_F(TracingServiceImplTest, OnDataSourceAddedWhilePendingDisableAcks) {
682 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
683 consumer->Connect(svc.get());
684
685 std::unique_ptr<MockProducer> producer = CreateMockProducer();
686 producer->Connect(svc.get(), "mock_producer");
687 producer->RegisterDataSource("ds_will_ack", /*ack_stop=*/true);
688
689 TraceConfig trace_config;
690 trace_config.add_buffers()->set_size_kb(128);
691 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack");
692 trace_config.add_data_sources()->mutable_config()->set_name("ds_wont_ack");
693
694 consumer->EnableTracing(trace_config);
695 producer->WaitForTracingSetup();
696
697 consumer->DisableTracing();
698
699 producer->RegisterDataSource("ds_wont_ack");
700
701 consumer.reset();
702}
703
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100704// Similar to OnTracingDisabledWaitsForDataSourceStopAcks, but deliberately
705// skips the ack and checks that the service invokes the OnTracingDisabled()
706// after the timeout.
707TEST_F(TracingServiceImplTest, OnTracingDisabledCalledAnywaysInCaseOfTimeout) {
708 svc->override_data_source_test_timeout_ms_for_testing = 1;
709 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
710 consumer->Connect(svc.get());
711
712 std::unique_ptr<MockProducer> producer = CreateMockProducer();
713 producer->Connect(svc.get(), "mock_producer");
714 producer->RegisterDataSource("data_source", /*ack_stop=*/true);
715
716 TraceConfig trace_config;
717 trace_config.add_buffers()->set_size_kb(128);
718 trace_config.add_data_sources()->mutable_config()->set_name("data_source");
719 trace_config.set_duration_ms(1);
720
721 consumer->EnableTracing(trace_config);
722 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100723 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100724 producer->WaitForDataSourceStart("data_source");
725
726 std::unique_ptr<TraceWriter> writer =
727 producer->CreateTraceWriter("data_source");
728 producer->WaitForFlush(writer.get());
729
730 producer->WaitForDataSourceStop("data_source");
731 consumer->WaitForTracingDisabled();
732}
733
Primiano Tucci03de28f2018-08-01 11:29:46 +0100734// Tests the session_id logic. Two data sources in the same tracing session
735// should see the same session id.
736TEST_F(TracingServiceImplTest, SessionId) {
737 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
738 consumer->Connect(svc.get());
739
740 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
741 producer1->Connect(svc.get(), "mock_producer1");
742 producer1->RegisterDataSource("ds_1A");
743 producer1->RegisterDataSource("ds_1B");
744
745 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
746 producer2->Connect(svc.get(), "mock_producer2");
747 producer2->RegisterDataSource("ds_2A");
748
749 testing::InSequence seq;
750 TracingSessionID last_session_id = 0;
751 for (int i = 0; i < 3; i++) {
752 TraceConfig trace_config;
753 trace_config.add_buffers()->set_size_kb(128);
754 trace_config.add_data_sources()->mutable_config()->set_name("ds_1A");
755 trace_config.add_data_sources()->mutable_config()->set_name("ds_1B");
756 trace_config.add_data_sources()->mutable_config()->set_name("ds_2A");
757 trace_config.set_duration_ms(1);
758
759 consumer->EnableTracing(trace_config);
760
761 if (i == 0)
762 producer1->WaitForTracingSetup();
Primiano Tucci03de28f2018-08-01 11:29:46 +0100763
Primiano Tucci674076d2018-10-01 10:41:09 +0100764 producer1->WaitForDataSourceSetup("ds_1A");
765 producer1->WaitForDataSourceSetup("ds_1B");
Primiano Tucci03de28f2018-08-01 11:29:46 +0100766 if (i == 0)
767 producer2->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100768 producer2->WaitForDataSourceSetup("ds_2A");
769
770 producer1->WaitForDataSourceStart("ds_1A");
771 producer1->WaitForDataSourceStart("ds_1B");
Primiano Tucci03de28f2018-08-01 11:29:46 +0100772 producer2->WaitForDataSourceStart("ds_2A");
773
774 auto* ds1 = producer1->GetDataSourceInstance("ds_1A");
775 auto* ds2 = producer1->GetDataSourceInstance("ds_1B");
776 auto* ds3 = producer2->GetDataSourceInstance("ds_2A");
777 ASSERT_EQ(ds1->session_id, ds2->session_id);
778 ASSERT_EQ(ds1->session_id, ds3->session_id);
779 ASSERT_NE(ds1->session_id, last_session_id);
780 last_session_id = ds1->session_id;
781
782 auto writer1 = producer1->CreateTraceWriter("ds_1A");
783 producer1->WaitForFlush(writer1.get());
784
785 auto writer2 = producer2->CreateTraceWriter("ds_2A");
786 producer2->WaitForFlush(writer2.get());
787
788 producer1->WaitForDataSourceStop("ds_1A");
789 producer1->WaitForDataSourceStop("ds_1B");
790 producer2->WaitForDataSourceStop("ds_2A");
791 consumer->WaitForTracingDisabled();
792 consumer->FreeBuffers();
793 }
794}
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100795
796// Writes a long trace and then tests that the trace parsed in partitions
797// derived by the synchronization markers is identical to the whole trace parsed
798// in one go.
799TEST_F(TracingServiceImplTest, ResynchronizeTraceStreamUsingSyncMarker) {
800 // Setup tracing.
801 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
802 consumer->Connect(svc.get());
803 std::unique_ptr<MockProducer> producer = CreateMockProducer();
804 producer->Connect(svc.get(), "mock_producer");
805 producer->RegisterDataSource("data_source");
806 TraceConfig trace_config;
807 trace_config.add_buffers()->set_size_kb(4096);
808 auto* ds_config = trace_config.add_data_sources()->mutable_config();
809 ds_config->set_name("data_source");
810 trace_config.set_write_into_file(true);
811 trace_config.set_file_write_period_ms(1);
812 base::TempFile tmp_file = base::TempFile::Create();
813 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
814 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100815 producer->WaitForDataSourceSetup("data_source");
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100816 producer->WaitForDataSourceStart("data_source");
817
818 // Write some variable length payload, waiting for sync markers every now
819 // and then.
820 const int kNumMarkers = 5;
821 auto writer = producer->CreateTraceWriter("data_source");
822 for (int i = 1; i <= 100; i++) {
823 std::string payload(i, 'A' + (i % 25));
824 writer->NewTracePacket()->set_for_testing()->set_str(payload.c_str());
825 if (i % (100 / kNumMarkers) == 0) {
826 writer->Flush();
827 WaitForNextSyncMarker();
828 }
829 }
830 writer->Flush();
831 writer.reset();
832 consumer->DisableTracing();
833 producer->WaitForDataSourceStop("data_source");
834 consumer->WaitForTracingDisabled();
835
836 std::string trace_raw;
837 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
838
839 const auto kMarkerSize = sizeof(TracingServiceImpl::kSyncMarker);
840 const std::string kSyncMarkerStr(
841 reinterpret_cast<const char*>(TracingServiceImpl::kSyncMarker),
842 kMarkerSize);
843
844 // Read back the trace in partitions derived from the marker.
845 // The trace should look like this:
846 // [uid, marker] [event] [event] [uid, marker] [event] [event]
847 size_t num_markers = 0;
848 size_t start = 0;
849 size_t end = 0;
850 protos::Trace merged_trace;
851 for (size_t pos = 0; pos != std::string::npos; start = end) {
852 pos = trace_raw.find(kSyncMarkerStr, pos + 1);
853 num_markers++;
854 end = (pos == std::string::npos) ? trace_raw.size() : pos + kMarkerSize;
855 int size = static_cast<int>(end - start);
856 ASSERT_GT(size, 0);
857 protos::Trace trace_partition;
858 ASSERT_TRUE(trace_partition.ParseFromArray(trace_raw.data() + start, size));
859 merged_trace.MergeFrom(trace_partition);
860 }
Lalit Maganti9bdc7ce2018-09-17 15:25:11 +0100861 EXPECT_GE(num_markers, static_cast<size_t>(kNumMarkers));
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100862
863 protos::Trace whole_trace;
864 ASSERT_TRUE(whole_trace.ParseFromString(trace_raw));
865
866 ASSERT_EQ(whole_trace.packet_size(), merged_trace.packet_size());
867 EXPECT_EQ(whole_trace.SerializeAsString(), merged_trace.SerializeAsString());
868}
869
Primiano Tucci674076d2018-10-01 10:41:09 +0100870// Creates a tracing session with |deferred_start| and checks that data sources
871// are started only after calling StartTracing().
872TEST_F(TracingServiceImplTest, DeferredStart) {
873 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
874 consumer->Connect(svc.get());
875
876 std::unique_ptr<MockProducer> producer = CreateMockProducer();
877 producer->Connect(svc.get(), "mock_producer");
878
879 // Create two data sources but enable only one of them.
880 producer->RegisterDataSource("ds_1");
881 producer->RegisterDataSource("ds_2");
882
883 TraceConfig trace_config;
884 trace_config.add_buffers()->set_size_kb(128);
885 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
886 trace_config.set_deferred_start(true);
887 trace_config.set_duration_ms(1);
888
889 consumer->EnableTracing(trace_config);
890 producer->WaitForTracingSetup();
891
892 producer->WaitForDataSourceSetup("ds_1");
893
894 // Make sure we don't get unexpected DataSourceStart() notifications yet.
895 task_runner.RunUntilIdle();
896
897 consumer->StartTracing();
898
899 producer->WaitForDataSourceStart("ds_1");
900
901 auto writer1 = producer->CreateTraceWriter("ds_1");
902 producer->WaitForFlush(writer1.get());
903
904 producer->WaitForDataSourceStop("ds_1");
905 consumer->WaitForTracingDisabled();
906}
907
Eric Seckler6dc23592018-11-30 10:59:06 +0000908TEST_F(TracingServiceImplTest, AllowedBuffers) {
909 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
910 consumer->Connect(svc.get());
911
912 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
913 producer1->Connect(svc.get(), "mock_producer1");
914 ProducerID producer1_id = *last_producer_id();
915 producer1->RegisterDataSource("data_source1");
916 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
917 producer2->Connect(svc.get(), "mock_producer2");
918 ProducerID producer2_id = *last_producer_id();
919 producer2->RegisterDataSource("data_source2.1");
920 producer2->RegisterDataSource("data_source2.2");
921 producer2->RegisterDataSource("data_source2.3");
922
923 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer1_id));
924 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer2_id));
925
926 TraceConfig trace_config;
927 trace_config.add_buffers()->set_size_kb(128);
928 trace_config.add_buffers()->set_size_kb(128);
929 trace_config.add_buffers()->set_size_kb(128);
930 auto* ds_config1 = trace_config.add_data_sources()->mutable_config();
931 ds_config1->set_name("data_source1");
932 ds_config1->set_target_buffer(0);
933 auto* ds_config21 = trace_config.add_data_sources()->mutable_config();
934 ds_config21->set_name("data_source2.1");
935 ds_config21->set_target_buffer(1);
936 auto* ds_config22 = trace_config.add_data_sources()->mutable_config();
937 ds_config22->set_name("data_source2.2");
938 ds_config22->set_target_buffer(2);
939 auto* ds_config23 = trace_config.add_data_sources()->mutable_config();
940 ds_config23->set_name("data_source2.3");
941 ds_config23->set_target_buffer(2); // same buffer as data_source2.2.
942 consumer->EnableTracing(trace_config);
943
Primiano Tucci2abd1152018-12-03 17:00:02 +0100944 ASSERT_EQ(3u, tracing_session()->num_buffers());
Eric Seckler6dc23592018-11-30 10:59:06 +0000945 std::set<BufferID> expected_buffers_producer1 = {
946 tracing_session()->buffers_index[0]};
947 std::set<BufferID> expected_buffers_producer2 = {
948 tracing_session()->buffers_index[1], tracing_session()->buffers_index[2]};
949 EXPECT_EQ(expected_buffers_producer1, GetAllowedTargetBuffers(producer1_id));
950 EXPECT_EQ(expected_buffers_producer2, GetAllowedTargetBuffers(producer2_id));
951
952 producer1->WaitForTracingSetup();
953 producer1->WaitForDataSourceSetup("data_source1");
954
955 producer2->WaitForTracingSetup();
956 producer2->WaitForDataSourceSetup("data_source2.1");
957 producer2->WaitForDataSourceSetup("data_source2.2");
958 producer2->WaitForDataSourceSetup("data_source2.3");
959
960 producer1->WaitForDataSourceStart("data_source1");
961 producer2->WaitForDataSourceStart("data_source2.1");
962 producer2->WaitForDataSourceStart("data_source2.2");
963 producer2->WaitForDataSourceStart("data_source2.3");
964
965 producer2->UnregisterDataSource("data_source2.3");
966 producer2->WaitForDataSourceStop("data_source2.3");
967
968 // Should still be allowed to write to buffers 1 (data_source2.1) and 2
969 // (data_source2.2).
970 EXPECT_EQ(expected_buffers_producer2, GetAllowedTargetBuffers(producer2_id));
971
972 // Calling StartTracing() should be a noop (% a DLOG statement) because the
973 // trace config didn't have the |deferred_start| flag set.
974 consumer->StartTracing();
975
976 consumer->DisableTracing();
977 producer1->WaitForDataSourceStop("data_source1");
978 producer2->WaitForDataSourceStop("data_source2.1");
979 producer2->WaitForDataSourceStop("data_source2.2");
980 consumer->WaitForTracingDisabled();
981
982 consumer->FreeBuffers();
983 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer1_id));
984 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer2_id));
985}
986
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000987} // namespace perfetto