blob: accb28cf1a28f61a934828e344604698fc72dd10 [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;
Eric Secklerdd0ad102018-12-06 11:32:04 +000051using ::testing::Not;
Primiano Tuccidca727d2018-04-04 11:31:55 +020052using ::testing::Property;
53using ::testing::StrictMock;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000054
Primiano Tuccidca727d2018-04-04 11:31:55 +020055namespace perfetto {
Sami Kyostila32e0b542018-02-14 08:55:43 +000056
Primiano Tucci1a1951d2018-04-04 21:08:16 +020057namespace {
Florian Mayer6a1a4d52018-06-08 16:47:07 +010058constexpr size_t kDefaultShmSizeKb = TracingServiceImpl::kDefaultShmSize / 1024;
59constexpr size_t kMaxShmSizeKb = TracingServiceImpl::kMaxShmSize / 1024;
Primiano Tucci1a1951d2018-04-04 21:08:16 +020060} // namespace
61
Florian Mayer6a1a4d52018-06-08 16:47:07 +010062class TracingServiceImplTest : public testing::Test {
Sami Kyostila06487a22018-02-27 13:48:38 +000063 public:
Florian Mayer6a1a4d52018-06-08 16:47:07 +010064 TracingServiceImplTest() {
Sami Kyostila06487a22018-02-27 13:48:38 +000065 auto shm_factory =
66 std::unique_ptr<SharedMemory::Factory>(new TestSharedMemory::Factory());
Florian Mayer6a1a4d52018-06-08 16:47:07 +010067 svc.reset(static_cast<TracingServiceImpl*>(
68 TracingService::CreateInstance(std::move(shm_factory), &task_runner)
Sami Kyostila06487a22018-02-27 13:48:38 +000069 .release()));
Primiano Tucci9754d0d2018-09-15 12:41:46 +010070 svc->min_write_period_ms_ = 1;
Sami Kyostila06487a22018-02-27 13:48:38 +000071 }
72
Primiano Tuccidca727d2018-04-04 11:31:55 +020073 std::unique_ptr<MockProducer> CreateMockProducer() {
74 return std::unique_ptr<MockProducer>(
75 new StrictMock<MockProducer>(&task_runner));
76 }
77
78 std::unique_ptr<MockConsumer> CreateMockConsumer() {
79 return std::unique_ptr<MockConsumer>(
80 new StrictMock<MockConsumer>(&task_runner));
81 }
82
Primiano Tucci1a1951d2018-04-04 21:08:16 +020083 ProducerID* last_producer_id() { return &svc->last_producer_id_; }
84
85 uid_t GetProducerUid(ProducerID producer_id) {
86 return svc->GetProducer(producer_id)->uid_;
87 }
88
Primiano Tucci9754d0d2018-09-15 12:41:46 +010089 TracingServiceImpl::TracingSession* tracing_session() {
90 auto* session = svc->GetTracingSession(svc->last_tracing_session_id_);
91 EXPECT_NE(nullptr, session);
92 return session;
93 }
94
Eric Seckler6dc23592018-11-30 10:59:06 +000095 const std::set<BufferID>& GetAllowedTargetBuffers(ProducerID producer_id) {
96 return svc->GetProducer(producer_id)->allowed_target_buffers_;
97 }
98
Primiano Tuccid52e6272018-04-06 19:06:53 +020099 size_t GetNumPendingFlushes() {
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100100 return tracing_session()->pending_flushes.size();
101 }
102
103 void WaitForNextSyncMarker() {
104 tracing_session()->last_snapshot_time = base::TimeMillis(0);
105 static int attempt = 0;
106 while (tracing_session()->last_snapshot_time == base::TimeMillis(0)) {
107 auto checkpoint_name = "wait_snapshot_" + std::to_string(attempt++);
108 auto timer_expired = task_runner.CreateCheckpoint(checkpoint_name);
109 task_runner.PostDelayedTask([timer_expired] { timer_expired(); }, 1);
110 task_runner.RunUntilCheckpoint(checkpoint_name);
111 }
Primiano Tuccid52e6272018-04-06 19:06:53 +0200112 }
113
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000114 base::TestTaskRunner task_runner;
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100115 std::unique_ptr<TracingServiceImpl> svc;
Sami Kyostila06487a22018-02-27 13:48:38 +0000116};
117
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100118TEST_F(TracingServiceImplTest, RegisterAndUnregister) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200119 std::unique_ptr<MockProducer> mock_producer_1 = CreateMockProducer();
120 std::unique_ptr<MockProducer> mock_producer_2 = CreateMockProducer();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000121
Primiano Tuccidca727d2018-04-04 11:31:55 +0200122 mock_producer_1->Connect(svc.get(), "mock_producer_1", 123u /* uid */);
123 mock_producer_2->Connect(svc.get(), "mock_producer_2", 456u /* uid */);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000124
125 ASSERT_EQ(2u, svc->num_producers());
Primiano Tuccidca727d2018-04-04 11:31:55 +0200126 ASSERT_EQ(mock_producer_1->endpoint(), svc->GetProducer(1));
127 ASSERT_EQ(mock_producer_2->endpoint(), svc->GetProducer(2));
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200128 ASSERT_EQ(123u, GetProducerUid(1));
129 ASSERT_EQ(456u, GetProducerUid(2));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000130
Primiano Tuccidca727d2018-04-04 11:31:55 +0200131 mock_producer_1->RegisterDataSource("foo");
132 mock_producer_2->RegisterDataSource("bar");
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000133
Primiano Tuccidca727d2018-04-04 11:31:55 +0200134 mock_producer_1->UnregisterDataSource("foo");
135 mock_producer_2->UnregisterDataSource("bar");
Primiano Tucci9daa4832018-03-28 23:28:17 +0100136
Primiano Tuccidca727d2018-04-04 11:31:55 +0200137 mock_producer_1.reset();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000138 ASSERT_EQ(1u, svc->num_producers());
139 ASSERT_EQ(nullptr, svc->GetProducer(1));
140
Primiano Tuccidca727d2018-04-04 11:31:55 +0200141 mock_producer_2.reset();
142 ASSERT_EQ(nullptr, svc->GetProducer(2));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000143
144 ASSERT_EQ(0u, svc->num_producers());
145}
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100146
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100147TEST_F(TracingServiceImplTest, EnableAndDisableTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200148 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
149 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000150
Primiano Tuccidca727d2018-04-04 11:31:55 +0200151 std::unique_ptr<MockProducer> producer = CreateMockProducer();
152 producer->Connect(svc.get(), "mock_producer");
153 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000154
Sami Kyostila06487a22018-02-27 13:48:38 +0000155 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200156 trace_config.add_buffers()->set_size_kb(128);
Sami Kyostila06487a22018-02-27 13:48:38 +0000157 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200158 ds_config->set_name("data_source");
159 consumer->EnableTracing(trace_config);
Sami Kyostila06487a22018-02-27 13:48:38 +0000160
Primiano Tuccidca727d2018-04-04 11:31:55 +0200161 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100162 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200163 producer->WaitForDataSourceStart("data_source");
164
Primiano Tucci674076d2018-10-01 10:41:09 +0100165 // Calling StartTracing() should be a noop (% a DLOG statement) because the
166 // trace config didn't have the |deferred_start| flag set.
167 consumer->StartTracing();
168
Primiano Tuccidca727d2018-04-04 11:31:55 +0200169 consumer->DisableTracing();
170 producer->WaitForDataSourceStop("data_source");
171 consumer->WaitForTracingDisabled();
Sami Kyostila06487a22018-02-27 13:48:38 +0000172}
173
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100174TEST_F(TracingServiceImplTest, LockdownMode) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200175 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
176 consumer->Connect(svc.get());
177
178 std::unique_ptr<MockProducer> producer = CreateMockProducer();
179 producer->Connect(svc.get(), "mock_producer_sameuid", geteuid());
180 producer->RegisterDataSource("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000181
182 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200183 trace_config.add_buffers()->set_size_kb(128);
184 auto* ds_config = trace_config.add_data_sources()->mutable_config();
185 ds_config->set_name("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000186 trace_config.set_lockdown_mode(
187 TraceConfig::LockdownModeOperation::LOCKDOWN_SET);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200188 consumer->EnableTracing(trace_config);
189
190 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100191 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200192 producer->WaitForDataSourceStart("data_source");
193
194 std::unique_ptr<MockProducer> producer_otheruid = CreateMockProducer();
195 auto x = svc->ConnectProducer(producer_otheruid.get(), geteuid() + 1,
196 "mock_producer_ouid");
197 EXPECT_CALL(*producer_otheruid, OnConnect()).Times(0);
Florian Mayer61c55482018-03-06 14:43:54 +0000198 task_runner.RunUntilIdle();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200199 Mock::VerifyAndClearExpectations(producer_otheruid.get());
Florian Mayer61c55482018-03-06 14:43:54 +0000200
Primiano Tuccidca727d2018-04-04 11:31:55 +0200201 consumer->DisableTracing();
202 consumer->FreeBuffers();
203 producer->WaitForDataSourceStop("data_source");
204 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000205
206 trace_config.set_lockdown_mode(
207 TraceConfig::LockdownModeOperation::LOCKDOWN_CLEAR);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200208 consumer->EnableTracing(trace_config);
Primiano Tucci674076d2018-10-01 10:41:09 +0100209 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200210 producer->WaitForDataSourceStart("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000211
Primiano Tuccidca727d2018-04-04 11:31:55 +0200212 std::unique_ptr<MockProducer> producer_otheruid2 = CreateMockProducer();
213 producer_otheruid->Connect(svc.get(), "mock_producer_ouid2", geteuid() + 1);
Florian Mayer61c55482018-03-06 14:43:54 +0000214
Primiano Tuccidca727d2018-04-04 11:31:55 +0200215 consumer->DisableTracing();
216 producer->WaitForDataSourceStop("data_source");
217 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000218}
219
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100220TEST_F(TracingServiceImplTest, DisconnectConsumerWhileTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200221 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
222 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000223
Primiano Tuccidca727d2018-04-04 11:31:55 +0200224 std::unique_ptr<MockProducer> producer = CreateMockProducer();
225 producer->Connect(svc.get(), "mock_producer");
226 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000227
Primiano Tuccidca727d2018-04-04 11:31:55 +0200228 TraceConfig trace_config;
229 trace_config.add_buffers()->set_size_kb(128);
230 auto* ds_config = trace_config.add_data_sources()->mutable_config();
231 ds_config->set_name("data_source");
232 consumer->EnableTracing(trace_config);
233
234 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100235 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200236 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000237
238 // Disconnecting the consumer while tracing should trigger data source
239 // teardown.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200240 consumer.reset();
241 producer->WaitForDataSourceStop("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000242}
243
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100244TEST_F(TracingServiceImplTest, ReconnectProducerWhileTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200245 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
246 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000247
Primiano Tuccidca727d2018-04-04 11:31:55 +0200248 std::unique_ptr<MockProducer> producer = CreateMockProducer();
249 producer->Connect(svc.get(), "mock_producer");
250 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000251
Sami Kyostila06487a22018-02-27 13:48:38 +0000252 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200253 trace_config.add_buffers()->set_size_kb(128);
Sami Kyostila06487a22018-02-27 13:48:38 +0000254 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200255 ds_config->set_name("data_source");
256 consumer->EnableTracing(trace_config);
Sami Kyostila06487a22018-02-27 13:48:38 +0000257
Primiano Tuccidca727d2018-04-04 11:31:55 +0200258 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100259 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200260 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000261
Primiano Tuccidca727d2018-04-04 11:31:55 +0200262 // Disconnecting and reconnecting a producer with a matching data source.
263 // The Producer should see that data source getting enabled again.
264 producer.reset();
265 producer = CreateMockProducer();
266 producer->Connect(svc.get(), "mock_producer_2");
267 producer->RegisterDataSource("data_source");
268 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100269 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200270 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000271}
272
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100273TEST_F(TracingServiceImplTest, ProducerIDWrapping) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200274 std::vector<std::unique_ptr<MockProducer>> producers;
275 producers.push_back(nullptr);
Primiano Tucci081d46a2018-02-28 11:09:43 +0000276
Primiano Tuccidca727d2018-04-04 11:31:55 +0200277 auto connect_producer_and_get_id = [&producers,
278 this](const std::string& name) {
279 producers.emplace_back(CreateMockProducer());
280 producers.back()->Connect(svc.get(), "mock_producer_" + name);
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200281 return *last_producer_id();
Primiano Tucci081d46a2018-02-28 11:09:43 +0000282 };
283
284 // Connect producers 1-4.
285 for (ProducerID i = 1; i <= 4; i++)
Primiano Tuccidca727d2018-04-04 11:31:55 +0200286 ASSERT_EQ(i, connect_producer_and_get_id(std::to_string(i)));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000287
288 // Disconnect producers 1,3.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200289 producers[1].reset();
290 producers[3].reset();
Primiano Tucci081d46a2018-02-28 11:09:43 +0000291
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200292 *last_producer_id() = kMaxProducerID - 1;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200293 ASSERT_EQ(kMaxProducerID, connect_producer_and_get_id("maxid"));
294 ASSERT_EQ(1u, connect_producer_and_get_id("1_again"));
295 ASSERT_EQ(3u, connect_producer_and_get_id("3_again"));
296 ASSERT_EQ(5u, connect_producer_and_get_id("5"));
297 ASSERT_EQ(6u, connect_producer_and_get_id("6"));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000298}
299
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000300// Note: file_write_period_ms is set to a large enough to have exactly one flush
301// of the tracing buffers (and therefore at most one synchronization section),
302// unless the test runs unrealistically slowly, or the implementation of the
303// tracing snapshot packets changes.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100304TEST_F(TracingServiceImplTest, WriteIntoFileAndStopOnMaxSize) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200305 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
306 consumer->Connect(svc.get());
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100307
Primiano Tuccidca727d2018-04-04 11:31:55 +0200308 std::unique_ptr<MockProducer> producer = CreateMockProducer();
309 producer->Connect(svc.get(), "mock_producer");
310 producer->RegisterDataSource("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100311
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100312 TraceConfig trace_config;
313 trace_config.add_buffers()->set_size_kb(4096);
314 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200315 ds_config->set_name("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100316 ds_config->set_target_buffer(0);
317 trace_config.set_write_into_file(true);
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000318 trace_config.set_file_write_period_ms(100000); // 100s
319 const uint64_t kMaxFileSize = 1024;
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100320 trace_config.set_max_file_size_bytes(kMaxFileSize);
321 base::TempFile tmp_file = base::TempFile::Create();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200322 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
323
324 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100325 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200326 producer->WaitForDataSourceStart("data_source");
327
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000328 static const int kNumPreamblePackets = 4;
329 static const int kNumTestPackets = 10;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200330 static const char kPayload[] = "1234567890abcdef-";
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100331
332 std::unique_ptr<TraceWriter> writer =
Primiano Tuccidca727d2018-04-04 11:31:55 +0200333 producer->CreateTraceWriter("data_source");
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000334 // Tracing service will emit a preamble of packets (a synchronization section,
335 // followed by a tracing config packet). The preamble and these test packets
336 // should fit within kMaxFileSize.
337 for (int i = 0; i < kNumTestPackets; i++) {
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100338 auto tp = writer->NewTracePacket();
339 std::string payload(kPayload);
340 payload.append(std::to_string(i));
341 tp->set_for_testing()->set_str(payload.c_str(), payload.size());
342 }
343
344 // Finally add a packet that overflows kMaxFileSize. This should cause the
345 // implicit stop of the trace and should *not* be written in the trace.
346 {
347 auto tp = writer->NewTracePacket();
348 char big_payload[kMaxFileSize] = "BIG!";
349 tp->set_for_testing()->set_str(big_payload, sizeof(big_payload));
350 }
351 writer->Flush();
352 writer.reset();
353
Primiano Tuccidca727d2018-04-04 11:31:55 +0200354 consumer->DisableTracing();
355 producer->WaitForDataSourceStop("data_source");
356 consumer->WaitForTracingDisabled();
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100357
358 // Verify the contents of the file.
359 std::string trace_raw;
360 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
361 protos::Trace trace;
362 ASSERT_TRUE(trace.ParseFromString(trace_raw));
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000363
364 ASSERT_EQ(trace.packet_size(), kNumPreamblePackets + kNumTestPackets);
365 for (int i = 0; i < kNumTestPackets; i++) {
366 const protos::TracePacket& tp = trace.packet(kNumPreamblePackets + i);
367 ASSERT_EQ(kPayload + std::to_string(i++), tp.for_testing().str());
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100368 }
Primiano Tuccidca727d2018-04-04 11:31:55 +0200369}
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100370
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200371// Test the logic that allows the trace config to set the shm total size and
372// page size from the trace config. Also check that, if the config doesn't
373// specify a value we fall back on the hint provided by the producer.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100374TEST_F(TracingServiceImplTest, ProducerShmAndPageSizeOverriddenByTraceConfig) {
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200375 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
376 consumer->Connect(svc.get());
377 const size_t kConfigPageSizesKb[] = /****/ {16, 16, 4, 0, 16, 8, 3, 4096, 4};
378 const size_t kExpectedPageSizesKb[] = /**/ {16, 16, 4, 4, 16, 8, 4, 64, 4};
379
380 const size_t kConfigSizesKb[] = /**/ {0, 16, 0, 20, 32, 7, 0, 96, 4096000};
381 const size_t kHintSizesKb[] = /****/ {0, 0, 16, 32, 16, 0, 7, 96, 4096000};
382 const size_t kExpectedSizesKb[] = {
383 kDefaultShmSizeKb, // Both hint and config are 0, use default.
384 16, // Hint is 0, use config.
385 16, // Config is 0, use hint.
386 20, // Hint is takes precedence over the config.
387 32, // Ditto, even if config is higher than hint.
388 kDefaultShmSizeKb, // Config is invalid and hint is 0, use default.
389 kDefaultShmSizeKb, // Config is 0 and hint is invalid, use default.
390 kDefaultShmSizeKb, // 96 KB isn't a multiple of the page size (64 KB).
391 kMaxShmSizeKb // Too big, cap at kMaxShmSize.
392 };
393
394 const size_t kNumProducers = base::ArraySize(kHintSizesKb);
395 std::unique_ptr<MockProducer> producer[kNumProducers];
396 for (size_t i = 0; i < kNumProducers; i++) {
397 auto name = "mock_producer_" + std::to_string(i);
398 producer[i] = CreateMockProducer();
399 producer[i]->Connect(svc.get(), name, geteuid(), kHintSizesKb[i] * 1024);
400 producer[i]->RegisterDataSource("data_source");
401 }
402
403 TraceConfig trace_config;
404 trace_config.add_buffers()->set_size_kb(128);
405 auto* ds_config = trace_config.add_data_sources()->mutable_config();
406 ds_config->set_name("data_source");
407 for (size_t i = 0; i < kNumProducers; i++) {
408 auto* producer_config = trace_config.add_producers();
409 producer_config->set_producer_name("mock_producer_" + std::to_string(i));
Primiano Tucci3cbb10a2018-04-10 17:52:40 +0100410 producer_config->set_shm_size_kb(static_cast<uint32_t>(kConfigSizesKb[i]));
411 producer_config->set_page_size_kb(
412 static_cast<uint32_t>(kConfigPageSizesKb[i]));
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200413 }
414
415 consumer->EnableTracing(trace_config);
416 size_t actual_shm_sizes_kb[kNumProducers]{};
417 size_t actual_page_sizes_kb[kNumProducers]{};
418 for (size_t i = 0; i < kNumProducers; i++) {
419 producer[i]->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100420 producer[i]->WaitForDataSourceSetup("data_source");
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200421 actual_shm_sizes_kb[i] =
422 producer[i]->endpoint()->shared_memory()->size() / 1024;
423 actual_page_sizes_kb[i] =
424 producer[i]->endpoint()->shared_buffer_page_size_kb();
425 }
Primiano Tucci674076d2018-10-01 10:41:09 +0100426 for (size_t i = 0; i < kNumProducers; i++) {
427 producer[i]->WaitForDataSourceStart("data_source");
428 }
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200429 ASSERT_THAT(actual_page_sizes_kb, ElementsAreArray(kExpectedPageSizesKb));
430 ASSERT_THAT(actual_shm_sizes_kb, ElementsAreArray(kExpectedSizesKb));
431}
432
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100433TEST_F(TracingServiceImplTest, ExplicitFlush) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200434 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
435 consumer->Connect(svc.get());
436
437 std::unique_ptr<MockProducer> producer = CreateMockProducer();
438 producer->Connect(svc.get(), "mock_producer");
439 producer->RegisterDataSource("data_source");
440
441 TraceConfig trace_config;
442 trace_config.add_buffers()->set_size_kb(128);
443 auto* ds_config = trace_config.add_data_sources()->mutable_config();
444 ds_config->set_name("data_source");
445
446 consumer->EnableTracing(trace_config);
447 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100448 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccid52e6272018-04-06 19:06:53 +0200449 producer->WaitForDataSourceStart("data_source");
450
451 std::unique_ptr<TraceWriter> writer =
452 producer->CreateTraceWriter("data_source");
453 {
454 auto tp = writer->NewTracePacket();
455 tp->set_for_testing()->set_str("payload");
456 }
457
458 auto flush_request = consumer->Flush();
459 producer->WaitForFlush(writer.get());
460 ASSERT_TRUE(flush_request.WaitForReply());
461
462 consumer->DisableTracing();
463 producer->WaitForDataSourceStop("data_source");
464 consumer->WaitForTracingDisabled();
465 EXPECT_THAT(
466 consumer->ReadBuffers(),
467 Contains(Property(&protos::TracePacket::for_testing,
468 Property(&protos::TestEvent::str, Eq("payload")))));
469}
470
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100471TEST_F(TracingServiceImplTest, ImplicitFlushOnTimedTraces) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200472 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
473 consumer->Connect(svc.get());
474
475 std::unique_ptr<MockProducer> producer = CreateMockProducer();
476 producer->Connect(svc.get(), "mock_producer");
477 producer->RegisterDataSource("data_source");
478
479 TraceConfig trace_config;
480 trace_config.add_buffers()->set_size_kb(128);
481 auto* ds_config = trace_config.add_data_sources()->mutable_config();
482 ds_config->set_name("data_source");
483 trace_config.set_duration_ms(1);
484
485 consumer->EnableTracing(trace_config);
486 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100487 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccid52e6272018-04-06 19:06:53 +0200488 producer->WaitForDataSourceStart("data_source");
489
490 std::unique_ptr<TraceWriter> writer =
491 producer->CreateTraceWriter("data_source");
492 {
493 auto tp = writer->NewTracePacket();
494 tp->set_for_testing()->set_str("payload");
495 }
496
497 producer->WaitForFlush(writer.get());
498
499 producer->WaitForDataSourceStop("data_source");
500 consumer->WaitForTracingDisabled();
501
502 EXPECT_THAT(
503 consumer->ReadBuffers(),
504 Contains(Property(&protos::TracePacket::for_testing,
505 Property(&protos::TestEvent::str, Eq("payload")))));
506}
507
508// Tests the monotonic semantic of flush request IDs, i.e., once a producer
509// acks flush request N, all flush requests <= N are considered successful and
510// acked to the consumer.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100511TEST_F(TracingServiceImplTest, BatchFlushes) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200512 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
513 consumer->Connect(svc.get());
514
515 std::unique_ptr<MockProducer> producer = CreateMockProducer();
516 producer->Connect(svc.get(), "mock_producer");
517 producer->RegisterDataSource("data_source");
518
519 TraceConfig trace_config;
520 trace_config.add_buffers()->set_size_kb(128);
521 auto* ds_config = trace_config.add_data_sources()->mutable_config();
522 ds_config->set_name("data_source");
523
524 consumer->EnableTracing(trace_config);
525 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100526 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccid52e6272018-04-06 19:06:53 +0200527 producer->WaitForDataSourceStart("data_source");
528
529 std::unique_ptr<TraceWriter> writer =
530 producer->CreateTraceWriter("data_source");
531 {
532 auto tp = writer->NewTracePacket();
533 tp->set_for_testing()->set_str("payload");
534 }
535
536 auto flush_req_1 = consumer->Flush();
537 auto flush_req_2 = consumer->Flush();
538 auto flush_req_3 = consumer->Flush();
539
540 // We'll deliberately let the 4th flush request timeout. Use a lower timeout
541 // to keep test time short.
542 auto flush_req_4 = consumer->Flush(/*timeout_ms=*/10);
543 ASSERT_EQ(4u, GetNumPendingFlushes());
544
545 // Make the producer reply only to the 3rd flush request.
546 testing::InSequence seq;
547 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 1.
548 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 2.
549 producer->WaitForFlush(writer.get()); // Will reply only to flush id == 3.
550 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 4.
551
552 // Even if the producer explicily replied only to flush ID == 3, all the
553 // previous flushed < 3 should be implicitly acked.
554 ASSERT_TRUE(flush_req_1.WaitForReply());
555 ASSERT_TRUE(flush_req_2.WaitForReply());
556 ASSERT_TRUE(flush_req_3.WaitForReply());
557
558 // At this point flush id == 4 should still be pending and should fail because
559 // of reaching its timeout.
Primiano Tuccid52e6272018-04-06 19:06:53 +0200560 ASSERT_FALSE(flush_req_4.WaitForReply());
561
562 consumer->DisableTracing();
563 producer->WaitForDataSourceStop("data_source");
564 consumer->WaitForTracingDisabled();
565 EXPECT_THAT(
566 consumer->ReadBuffers(),
567 Contains(Property(&protos::TracePacket::for_testing,
568 Property(&protos::TestEvent::str, Eq("payload")))));
569}
570
Primiano Tuccicaa57802018-11-25 11:07:07 +0000571TEST_F(TracingServiceImplTest, PeriodicFlush) {
572 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
573 consumer->Connect(svc.get());
574
575 std::unique_ptr<MockProducer> producer = CreateMockProducer();
576 producer->Connect(svc.get(), "mock_producer");
577 producer->RegisterDataSource("data_source");
578
579 TraceConfig trace_config;
580 trace_config.add_buffers()->set_size_kb(128);
581 trace_config.set_flush_period_ms(1);
582 auto* ds_config = trace_config.add_data_sources()->mutable_config();
583 ds_config->set_name("data_source");
584
585 consumer->EnableTracing(trace_config);
586 producer->WaitForTracingSetup();
587 producer->WaitForDataSourceSetup("data_source");
588 producer->WaitForDataSourceStart("data_source");
589
590 std::unique_ptr<TraceWriter> writer =
591 producer->CreateTraceWriter("data_source");
592
593 const int kNumFlushes = 3;
594 auto checkpoint = task_runner.CreateCheckpoint("all_flushes_done");
595 int flushes_seen = 0;
596 EXPECT_CALL(*producer, Flush(_, _, _))
597 .WillRepeatedly(Invoke([&producer, &writer, &flushes_seen, checkpoint](
598 FlushRequestID flush_req_id,
599 const DataSourceInstanceID*, size_t) {
600 {
601 auto tp = writer->NewTracePacket();
602 char payload[32];
603 sprintf(payload, "f_%d", flushes_seen);
604 tp->set_for_testing()->set_str(payload);
605 }
606 writer->Flush();
607 producer->endpoint()->NotifyFlushComplete(flush_req_id);
608 if (++flushes_seen == kNumFlushes)
609 checkpoint();
610 }));
611 task_runner.RunUntilCheckpoint("all_flushes_done");
612
613 consumer->DisableTracing();
614 producer->WaitForDataSourceStop("data_source");
615 consumer->WaitForTracingDisabled();
616 auto trace_packets = consumer->ReadBuffers();
617 for (int i = 0; i < kNumFlushes; i++) {
618 EXPECT_THAT(trace_packets,
619 Contains(Property(&protos::TracePacket::for_testing,
620 Property(&protos::TestEvent::str,
621 Eq("f_" + std::to_string(i))))));
622 }
623}
624
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100625// Creates a tracing session where some of the data sources set the
626// |will_notify_on_stop| flag and checks that the OnTracingDisabled notification
627// to the consumer is delayed until the acks are received.
628TEST_F(TracingServiceImplTest, OnTracingDisabledWaitsForDataSourceStopAcks) {
629 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
630 consumer->Connect(svc.get());
631
632 std::unique_ptr<MockProducer> producer = CreateMockProducer();
633 producer->Connect(svc.get(), "mock_producer");
634 producer->RegisterDataSource("ds_will_ack_1", /*ack_stop=*/true);
635 producer->RegisterDataSource("ds_wont_ack");
636 producer->RegisterDataSource("ds_will_ack_2", /*ack_stop=*/true);
637
638 TraceConfig trace_config;
639 trace_config.add_buffers()->set_size_kb(128);
640 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack_1");
641 trace_config.add_data_sources()->mutable_config()->set_name("ds_wont_ack");
642 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack_2");
643 trace_config.set_duration_ms(1);
644
645 consumer->EnableTracing(trace_config);
646 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100647
648 producer->WaitForDataSourceSetup("ds_will_ack_1");
649 producer->WaitForDataSourceSetup("ds_wont_ack");
650 producer->WaitForDataSourceSetup("ds_will_ack_2");
651
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100652 producer->WaitForDataSourceStart("ds_will_ack_1");
653 producer->WaitForDataSourceStart("ds_wont_ack");
654 producer->WaitForDataSourceStart("ds_will_ack_2");
655
656 std::unique_ptr<TraceWriter> writer =
657 producer->CreateTraceWriter("ds_wont_ack");
658 producer->WaitForFlush(writer.get());
659
660 DataSourceInstanceID id1 = producer->GetDataSourceInstanceId("ds_will_ack_1");
661 DataSourceInstanceID id2 = producer->GetDataSourceInstanceId("ds_will_ack_2");
662
663 producer->WaitForDataSourceStop("ds_will_ack_1");
664 producer->WaitForDataSourceStop("ds_wont_ack");
665 producer->WaitForDataSourceStop("ds_will_ack_2");
666
667 producer->endpoint()->NotifyDataSourceStopped(id1);
668 producer->endpoint()->NotifyDataSourceStopped(id2);
669
670 // Wait for at most half of the service timeout, so that this test fails if
671 // the service falls back on calling the OnTracingDisabled() because some of
672 // the expected acks weren't received.
673 consumer->WaitForTracingDisabled(
674 TracingServiceImpl::kDataSourceStopTimeoutMs / 2);
675}
676
Oystein Eftevaagf250e1c2018-08-23 16:10:52 -0700677// Creates a tracing session where a second data source
678// is added while the service is waiting for DisableTracing
679// acks; the service should not enable the new datasource
680// and should not hit any asserts when the consumer is
681// subsequently destroyed.
682TEST_F(TracingServiceImplTest, OnDataSourceAddedWhilePendingDisableAcks) {
683 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
684 consumer->Connect(svc.get());
685
686 std::unique_ptr<MockProducer> producer = CreateMockProducer();
687 producer->Connect(svc.get(), "mock_producer");
688 producer->RegisterDataSource("ds_will_ack", /*ack_stop=*/true);
689
690 TraceConfig trace_config;
691 trace_config.add_buffers()->set_size_kb(128);
692 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack");
693 trace_config.add_data_sources()->mutable_config()->set_name("ds_wont_ack");
694
695 consumer->EnableTracing(trace_config);
696 producer->WaitForTracingSetup();
697
698 consumer->DisableTracing();
699
700 producer->RegisterDataSource("ds_wont_ack");
701
702 consumer.reset();
703}
704
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100705// Similar to OnTracingDisabledWaitsForDataSourceStopAcks, but deliberately
706// skips the ack and checks that the service invokes the OnTracingDisabled()
707// after the timeout.
708TEST_F(TracingServiceImplTest, OnTracingDisabledCalledAnywaysInCaseOfTimeout) {
709 svc->override_data_source_test_timeout_ms_for_testing = 1;
710 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
711 consumer->Connect(svc.get());
712
713 std::unique_ptr<MockProducer> producer = CreateMockProducer();
714 producer->Connect(svc.get(), "mock_producer");
715 producer->RegisterDataSource("data_source", /*ack_stop=*/true);
716
717 TraceConfig trace_config;
718 trace_config.add_buffers()->set_size_kb(128);
719 trace_config.add_data_sources()->mutable_config()->set_name("data_source");
720 trace_config.set_duration_ms(1);
721
722 consumer->EnableTracing(trace_config);
723 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100724 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100725 producer->WaitForDataSourceStart("data_source");
726
727 std::unique_ptr<TraceWriter> writer =
728 producer->CreateTraceWriter("data_source");
729 producer->WaitForFlush(writer.get());
730
731 producer->WaitForDataSourceStop("data_source");
732 consumer->WaitForTracingDisabled();
733}
734
Primiano Tucci03de28f2018-08-01 11:29:46 +0100735// Tests the session_id logic. Two data sources in the same tracing session
736// should see the same session id.
737TEST_F(TracingServiceImplTest, SessionId) {
738 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
739 consumer->Connect(svc.get());
740
741 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
742 producer1->Connect(svc.get(), "mock_producer1");
743 producer1->RegisterDataSource("ds_1A");
744 producer1->RegisterDataSource("ds_1B");
745
746 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
747 producer2->Connect(svc.get(), "mock_producer2");
748 producer2->RegisterDataSource("ds_2A");
749
750 testing::InSequence seq;
751 TracingSessionID last_session_id = 0;
752 for (int i = 0; i < 3; i++) {
753 TraceConfig trace_config;
754 trace_config.add_buffers()->set_size_kb(128);
755 trace_config.add_data_sources()->mutable_config()->set_name("ds_1A");
756 trace_config.add_data_sources()->mutable_config()->set_name("ds_1B");
757 trace_config.add_data_sources()->mutable_config()->set_name("ds_2A");
758 trace_config.set_duration_ms(1);
759
760 consumer->EnableTracing(trace_config);
761
762 if (i == 0)
763 producer1->WaitForTracingSetup();
Primiano Tucci03de28f2018-08-01 11:29:46 +0100764
Primiano Tucci674076d2018-10-01 10:41:09 +0100765 producer1->WaitForDataSourceSetup("ds_1A");
766 producer1->WaitForDataSourceSetup("ds_1B");
Primiano Tucci03de28f2018-08-01 11:29:46 +0100767 if (i == 0)
768 producer2->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100769 producer2->WaitForDataSourceSetup("ds_2A");
770
771 producer1->WaitForDataSourceStart("ds_1A");
772 producer1->WaitForDataSourceStart("ds_1B");
Primiano Tucci03de28f2018-08-01 11:29:46 +0100773 producer2->WaitForDataSourceStart("ds_2A");
774
775 auto* ds1 = producer1->GetDataSourceInstance("ds_1A");
776 auto* ds2 = producer1->GetDataSourceInstance("ds_1B");
777 auto* ds3 = producer2->GetDataSourceInstance("ds_2A");
778 ASSERT_EQ(ds1->session_id, ds2->session_id);
779 ASSERT_EQ(ds1->session_id, ds3->session_id);
780 ASSERT_NE(ds1->session_id, last_session_id);
781 last_session_id = ds1->session_id;
782
783 auto writer1 = producer1->CreateTraceWriter("ds_1A");
784 producer1->WaitForFlush(writer1.get());
785
786 auto writer2 = producer2->CreateTraceWriter("ds_2A");
787 producer2->WaitForFlush(writer2.get());
788
789 producer1->WaitForDataSourceStop("ds_1A");
790 producer1->WaitForDataSourceStop("ds_1B");
791 producer2->WaitForDataSourceStop("ds_2A");
792 consumer->WaitForTracingDisabled();
793 consumer->FreeBuffers();
794 }
795}
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100796
797// Writes a long trace and then tests that the trace parsed in partitions
798// derived by the synchronization markers is identical to the whole trace parsed
799// in one go.
800TEST_F(TracingServiceImplTest, ResynchronizeTraceStreamUsingSyncMarker) {
801 // Setup tracing.
802 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
803 consumer->Connect(svc.get());
804 std::unique_ptr<MockProducer> producer = CreateMockProducer();
805 producer->Connect(svc.get(), "mock_producer");
806 producer->RegisterDataSource("data_source");
807 TraceConfig trace_config;
808 trace_config.add_buffers()->set_size_kb(4096);
809 auto* ds_config = trace_config.add_data_sources()->mutable_config();
810 ds_config->set_name("data_source");
811 trace_config.set_write_into_file(true);
812 trace_config.set_file_write_period_ms(1);
813 base::TempFile tmp_file = base::TempFile::Create();
814 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
815 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100816 producer->WaitForDataSourceSetup("data_source");
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100817 producer->WaitForDataSourceStart("data_source");
818
819 // Write some variable length payload, waiting for sync markers every now
820 // and then.
821 const int kNumMarkers = 5;
822 auto writer = producer->CreateTraceWriter("data_source");
823 for (int i = 1; i <= 100; i++) {
Florian Mayereff98042018-12-10 17:44:44 +0000824 std::string payload(static_cast<size_t>(i), 'A' + (i % 25));
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100825 writer->NewTracePacket()->set_for_testing()->set_str(payload.c_str());
826 if (i % (100 / kNumMarkers) == 0) {
827 writer->Flush();
828 WaitForNextSyncMarker();
829 }
830 }
831 writer->Flush();
832 writer.reset();
833 consumer->DisableTracing();
834 producer->WaitForDataSourceStop("data_source");
835 consumer->WaitForTracingDisabled();
836
837 std::string trace_raw;
838 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
839
840 const auto kMarkerSize = sizeof(TracingServiceImpl::kSyncMarker);
841 const std::string kSyncMarkerStr(
842 reinterpret_cast<const char*>(TracingServiceImpl::kSyncMarker),
843 kMarkerSize);
844
845 // Read back the trace in partitions derived from the marker.
846 // The trace should look like this:
847 // [uid, marker] [event] [event] [uid, marker] [event] [event]
848 size_t num_markers = 0;
849 size_t start = 0;
850 size_t end = 0;
851 protos::Trace merged_trace;
852 for (size_t pos = 0; pos != std::string::npos; start = end) {
853 pos = trace_raw.find(kSyncMarkerStr, pos + 1);
854 num_markers++;
855 end = (pos == std::string::npos) ? trace_raw.size() : pos + kMarkerSize;
856 int size = static_cast<int>(end - start);
857 ASSERT_GT(size, 0);
858 protos::Trace trace_partition;
859 ASSERT_TRUE(trace_partition.ParseFromArray(trace_raw.data() + start, size));
860 merged_trace.MergeFrom(trace_partition);
861 }
Lalit Maganti9bdc7ce2018-09-17 15:25:11 +0100862 EXPECT_GE(num_markers, static_cast<size_t>(kNumMarkers));
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100863
864 protos::Trace whole_trace;
865 ASSERT_TRUE(whole_trace.ParseFromString(trace_raw));
866
867 ASSERT_EQ(whole_trace.packet_size(), merged_trace.packet_size());
868 EXPECT_EQ(whole_trace.SerializeAsString(), merged_trace.SerializeAsString());
869}
870
Primiano Tucci674076d2018-10-01 10:41:09 +0100871// Creates a tracing session with |deferred_start| and checks that data sources
872// are started only after calling StartTracing().
873TEST_F(TracingServiceImplTest, DeferredStart) {
874 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
875 consumer->Connect(svc.get());
876
877 std::unique_ptr<MockProducer> producer = CreateMockProducer();
878 producer->Connect(svc.get(), "mock_producer");
879
880 // Create two data sources but enable only one of them.
881 producer->RegisterDataSource("ds_1");
882 producer->RegisterDataSource("ds_2");
883
884 TraceConfig trace_config;
885 trace_config.add_buffers()->set_size_kb(128);
886 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
887 trace_config.set_deferred_start(true);
888 trace_config.set_duration_ms(1);
889
890 consumer->EnableTracing(trace_config);
891 producer->WaitForTracingSetup();
892
893 producer->WaitForDataSourceSetup("ds_1");
894
895 // Make sure we don't get unexpected DataSourceStart() notifications yet.
896 task_runner.RunUntilIdle();
897
898 consumer->StartTracing();
899
900 producer->WaitForDataSourceStart("ds_1");
901
902 auto writer1 = producer->CreateTraceWriter("ds_1");
903 producer->WaitForFlush(writer1.get());
904
905 producer->WaitForDataSourceStop("ds_1");
906 consumer->WaitForTracingDisabled();
907}
908
Eric Seckler6dc23592018-11-30 10:59:06 +0000909TEST_F(TracingServiceImplTest, AllowedBuffers) {
910 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
911 consumer->Connect(svc.get());
912
913 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
914 producer1->Connect(svc.get(), "mock_producer1");
915 ProducerID producer1_id = *last_producer_id();
916 producer1->RegisterDataSource("data_source1");
917 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
918 producer2->Connect(svc.get(), "mock_producer2");
919 ProducerID producer2_id = *last_producer_id();
920 producer2->RegisterDataSource("data_source2.1");
921 producer2->RegisterDataSource("data_source2.2");
922 producer2->RegisterDataSource("data_source2.3");
923
924 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer1_id));
925 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer2_id));
926
927 TraceConfig trace_config;
928 trace_config.add_buffers()->set_size_kb(128);
929 trace_config.add_buffers()->set_size_kb(128);
930 trace_config.add_buffers()->set_size_kb(128);
931 auto* ds_config1 = trace_config.add_data_sources()->mutable_config();
932 ds_config1->set_name("data_source1");
933 ds_config1->set_target_buffer(0);
934 auto* ds_config21 = trace_config.add_data_sources()->mutable_config();
935 ds_config21->set_name("data_source2.1");
936 ds_config21->set_target_buffer(1);
937 auto* ds_config22 = trace_config.add_data_sources()->mutable_config();
938 ds_config22->set_name("data_source2.2");
939 ds_config22->set_target_buffer(2);
940 auto* ds_config23 = trace_config.add_data_sources()->mutable_config();
941 ds_config23->set_name("data_source2.3");
942 ds_config23->set_target_buffer(2); // same buffer as data_source2.2.
943 consumer->EnableTracing(trace_config);
944
Primiano Tucci2abd1152018-12-03 17:00:02 +0100945 ASSERT_EQ(3u, tracing_session()->num_buffers());
Eric Seckler6dc23592018-11-30 10:59:06 +0000946 std::set<BufferID> expected_buffers_producer1 = {
947 tracing_session()->buffers_index[0]};
948 std::set<BufferID> expected_buffers_producer2 = {
949 tracing_session()->buffers_index[1], tracing_session()->buffers_index[2]};
950 EXPECT_EQ(expected_buffers_producer1, GetAllowedTargetBuffers(producer1_id));
951 EXPECT_EQ(expected_buffers_producer2, GetAllowedTargetBuffers(producer2_id));
952
953 producer1->WaitForTracingSetup();
954 producer1->WaitForDataSourceSetup("data_source1");
955
956 producer2->WaitForTracingSetup();
957 producer2->WaitForDataSourceSetup("data_source2.1");
958 producer2->WaitForDataSourceSetup("data_source2.2");
959 producer2->WaitForDataSourceSetup("data_source2.3");
960
961 producer1->WaitForDataSourceStart("data_source1");
962 producer2->WaitForDataSourceStart("data_source2.1");
963 producer2->WaitForDataSourceStart("data_source2.2");
964 producer2->WaitForDataSourceStart("data_source2.3");
965
966 producer2->UnregisterDataSource("data_source2.3");
967 producer2->WaitForDataSourceStop("data_source2.3");
968
969 // Should still be allowed to write to buffers 1 (data_source2.1) and 2
970 // (data_source2.2).
971 EXPECT_EQ(expected_buffers_producer2, GetAllowedTargetBuffers(producer2_id));
972
973 // Calling StartTracing() should be a noop (% a DLOG statement) because the
974 // trace config didn't have the |deferred_start| flag set.
975 consumer->StartTracing();
976
977 consumer->DisableTracing();
978 producer1->WaitForDataSourceStop("data_source1");
979 producer2->WaitForDataSourceStop("data_source2.1");
980 producer2->WaitForDataSourceStop("data_source2.2");
981 consumer->WaitForTracingDisabled();
982
983 consumer->FreeBuffers();
984 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer1_id));
985 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer2_id));
986}
987
Eric Seckler6aa9ece2018-12-06 16:40:12 +0000988#if !PERFETTO_DCHECK_IS_ON()
Eric Secklerdd0ad102018-12-06 11:32:04 +0000989TEST_F(TracingServiceImplTest, CommitToForbiddenBufferIsDiscarded) {
990 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
991 consumer->Connect(svc.get());
992
993 std::unique_ptr<MockProducer> producer = CreateMockProducer();
994 producer->Connect(svc.get(), "mock_producer");
995 ProducerID producer_id = *last_producer_id();
996 producer->RegisterDataSource("data_source");
997
998 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer_id));
999
1000 TraceConfig trace_config;
1001 trace_config.add_buffers()->set_size_kb(128);
1002 trace_config.add_buffers()->set_size_kb(128);
1003 auto* ds_config = trace_config.add_data_sources()->mutable_config();
1004 ds_config->set_name("data_source");
1005 ds_config->set_target_buffer(0);
1006 consumer->EnableTracing(trace_config);
1007
1008 ASSERT_EQ(2u, tracing_session()->num_buffers());
1009 std::set<BufferID> expected_buffers = {tracing_session()->buffers_index[0]};
1010 EXPECT_EQ(expected_buffers, GetAllowedTargetBuffers(producer_id));
1011
1012 producer->WaitForTracingSetup();
1013 producer->WaitForDataSourceSetup("data_source");
1014 producer->WaitForDataSourceStart("data_source");
1015
1016 // Calling StartTracing() should be a noop (% a DLOG statement) because the
1017 // trace config didn't have the |deferred_start| flag set.
1018 consumer->StartTracing();
1019
1020 // Try to write to the correct buffer.
1021 std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter(
1022 tracing_session()->buffers_index[0]);
1023 {
1024 auto tp = writer->NewTracePacket();
1025 tp->set_for_testing()->set_str("good_payload");
1026 }
1027
1028 auto flush_request = consumer->Flush();
1029 producer->WaitForFlush(writer.get());
1030 ASSERT_TRUE(flush_request.WaitForReply());
1031
1032 // Try to write to the wrong buffer.
1033 writer = producer->endpoint()->CreateTraceWriter(
1034 tracing_session()->buffers_index[1]);
1035 {
1036 auto tp = writer->NewTracePacket();
1037 tp->set_for_testing()->set_str("bad_payload");
1038 }
1039
1040 flush_request = consumer->Flush();
1041 producer->WaitForFlush(writer.get());
1042 ASSERT_TRUE(flush_request.WaitForReply());
1043
1044 consumer->DisableTracing();
1045 producer->WaitForDataSourceStop("data_source");
1046 consumer->WaitForTracingDisabled();
1047
1048 auto packets = consumer->ReadBuffers();
1049 EXPECT_THAT(packets, Contains(Property(&protos::TracePacket::for_testing,
1050 Property(&protos::TestEvent::str,
1051 Eq("good_payload")))));
1052 EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
1053 Property(&protos::TestEvent::str,
1054 Eq("bad_payload"))))));
1055
1056 consumer->FreeBuffers();
1057 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer_id));
1058}
Eric Seckler6aa9ece2018-12-06 16:40:12 +00001059#endif // !PERFETTO_DCHECK_IS_ON()
Eric Secklerdd0ad102018-12-06 11:32:04 +00001060
Primiano Tucci4f9b6d72017-12-05 20:59:16 +00001061} // namespace perfetto