blob: e556aa49446831a534ba844ca4f81c7731096529 [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
Primiano Tuccid52e6272018-04-06 19:06:53 +020094 size_t GetNumPendingFlushes() {
Primiano Tucci9754d0d2018-09-15 12:41:46 +010095 return tracing_session()->pending_flushes.size();
96 }
97
98 void WaitForNextSyncMarker() {
99 tracing_session()->last_snapshot_time = base::TimeMillis(0);
100 static int attempt = 0;
101 while (tracing_session()->last_snapshot_time == base::TimeMillis(0)) {
102 auto checkpoint_name = "wait_snapshot_" + std::to_string(attempt++);
103 auto timer_expired = task_runner.CreateCheckpoint(checkpoint_name);
104 task_runner.PostDelayedTask([timer_expired] { timer_expired(); }, 1);
105 task_runner.RunUntilCheckpoint(checkpoint_name);
106 }
Primiano Tuccid52e6272018-04-06 19:06:53 +0200107 }
108
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000109 base::TestTaskRunner task_runner;
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100110 std::unique_ptr<TracingServiceImpl> svc;
Sami Kyostila06487a22018-02-27 13:48:38 +0000111};
112
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100113TEST_F(TracingServiceImplTest, RegisterAndUnregister) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200114 std::unique_ptr<MockProducer> mock_producer_1 = CreateMockProducer();
115 std::unique_ptr<MockProducer> mock_producer_2 = CreateMockProducer();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000116
Primiano Tuccidca727d2018-04-04 11:31:55 +0200117 mock_producer_1->Connect(svc.get(), "mock_producer_1", 123u /* uid */);
118 mock_producer_2->Connect(svc.get(), "mock_producer_2", 456u /* uid */);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000119
120 ASSERT_EQ(2u, svc->num_producers());
Primiano Tuccidca727d2018-04-04 11:31:55 +0200121 ASSERT_EQ(mock_producer_1->endpoint(), svc->GetProducer(1));
122 ASSERT_EQ(mock_producer_2->endpoint(), svc->GetProducer(2));
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200123 ASSERT_EQ(123u, GetProducerUid(1));
124 ASSERT_EQ(456u, GetProducerUid(2));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000125
Primiano Tuccidca727d2018-04-04 11:31:55 +0200126 mock_producer_1->RegisterDataSource("foo");
127 mock_producer_2->RegisterDataSource("bar");
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000128
Primiano Tuccidca727d2018-04-04 11:31:55 +0200129 mock_producer_1->UnregisterDataSource("foo");
130 mock_producer_2->UnregisterDataSource("bar");
Primiano Tucci9daa4832018-03-28 23:28:17 +0100131
Primiano Tuccidca727d2018-04-04 11:31:55 +0200132 mock_producer_1.reset();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000133 ASSERT_EQ(1u, svc->num_producers());
134 ASSERT_EQ(nullptr, svc->GetProducer(1));
135
Primiano Tuccidca727d2018-04-04 11:31:55 +0200136 mock_producer_2.reset();
137 ASSERT_EQ(nullptr, svc->GetProducer(2));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000138
139 ASSERT_EQ(0u, svc->num_producers());
140}
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100141
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100142TEST_F(TracingServiceImplTest, EnableAndDisableTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200143 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
144 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000145
Primiano Tuccidca727d2018-04-04 11:31:55 +0200146 std::unique_ptr<MockProducer> producer = CreateMockProducer();
147 producer->Connect(svc.get(), "mock_producer");
148 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000149
Sami Kyostila06487a22018-02-27 13:48:38 +0000150 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200151 trace_config.add_buffers()->set_size_kb(128);
Sami Kyostila06487a22018-02-27 13:48:38 +0000152 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200153 ds_config->set_name("data_source");
154 consumer->EnableTracing(trace_config);
Sami Kyostila06487a22018-02-27 13:48:38 +0000155
Primiano Tuccidca727d2018-04-04 11:31:55 +0200156 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100157 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200158 producer->WaitForDataSourceStart("data_source");
159
Primiano Tucci674076d2018-10-01 10:41:09 +0100160 // Calling StartTracing() should be a noop (% a DLOG statement) because the
161 // trace config didn't have the |deferred_start| flag set.
162 consumer->StartTracing();
163
Primiano Tuccidca727d2018-04-04 11:31:55 +0200164 consumer->DisableTracing();
165 producer->WaitForDataSourceStop("data_source");
166 consumer->WaitForTracingDisabled();
Sami Kyostila06487a22018-02-27 13:48:38 +0000167}
168
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100169TEST_F(TracingServiceImplTest, LockdownMode) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200170 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
171 consumer->Connect(svc.get());
172
173 std::unique_ptr<MockProducer> producer = CreateMockProducer();
174 producer->Connect(svc.get(), "mock_producer_sameuid", geteuid());
175 producer->RegisterDataSource("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000176
177 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200178 trace_config.add_buffers()->set_size_kb(128);
179 auto* ds_config = trace_config.add_data_sources()->mutable_config();
180 ds_config->set_name("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000181 trace_config.set_lockdown_mode(
182 TraceConfig::LockdownModeOperation::LOCKDOWN_SET);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200183 consumer->EnableTracing(trace_config);
184
185 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100186 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200187 producer->WaitForDataSourceStart("data_source");
188
189 std::unique_ptr<MockProducer> producer_otheruid = CreateMockProducer();
190 auto x = svc->ConnectProducer(producer_otheruid.get(), geteuid() + 1,
191 "mock_producer_ouid");
192 EXPECT_CALL(*producer_otheruid, OnConnect()).Times(0);
Florian Mayer61c55482018-03-06 14:43:54 +0000193 task_runner.RunUntilIdle();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200194 Mock::VerifyAndClearExpectations(producer_otheruid.get());
Florian Mayer61c55482018-03-06 14:43:54 +0000195
Primiano Tuccidca727d2018-04-04 11:31:55 +0200196 consumer->DisableTracing();
197 consumer->FreeBuffers();
198 producer->WaitForDataSourceStop("data_source");
199 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000200
201 trace_config.set_lockdown_mode(
202 TraceConfig::LockdownModeOperation::LOCKDOWN_CLEAR);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200203 consumer->EnableTracing(trace_config);
Primiano Tucci674076d2018-10-01 10:41:09 +0100204 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200205 producer->WaitForDataSourceStart("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000206
Primiano Tuccidca727d2018-04-04 11:31:55 +0200207 std::unique_ptr<MockProducer> producer_otheruid2 = CreateMockProducer();
208 producer_otheruid->Connect(svc.get(), "mock_producer_ouid2", geteuid() + 1);
Florian Mayer61c55482018-03-06 14:43:54 +0000209
Primiano Tuccidca727d2018-04-04 11:31:55 +0200210 consumer->DisableTracing();
211 producer->WaitForDataSourceStop("data_source");
212 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000213}
214
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100215TEST_F(TracingServiceImplTest, DisconnectConsumerWhileTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200216 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
217 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000218
Primiano Tuccidca727d2018-04-04 11:31:55 +0200219 std::unique_ptr<MockProducer> producer = CreateMockProducer();
220 producer->Connect(svc.get(), "mock_producer");
221 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000222
Primiano Tuccidca727d2018-04-04 11:31:55 +0200223 TraceConfig trace_config;
224 trace_config.add_buffers()->set_size_kb(128);
225 auto* ds_config = trace_config.add_data_sources()->mutable_config();
226 ds_config->set_name("data_source");
227 consumer->EnableTracing(trace_config);
228
229 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100230 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200231 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000232
233 // Disconnecting the consumer while tracing should trigger data source
234 // teardown.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200235 consumer.reset();
236 producer->WaitForDataSourceStop("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000237}
238
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100239TEST_F(TracingServiceImplTest, ReconnectProducerWhileTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200240 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
241 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000242
Primiano Tuccidca727d2018-04-04 11:31:55 +0200243 std::unique_ptr<MockProducer> producer = CreateMockProducer();
244 producer->Connect(svc.get(), "mock_producer");
245 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000246
Sami Kyostila06487a22018-02-27 13:48:38 +0000247 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200248 trace_config.add_buffers()->set_size_kb(128);
Sami Kyostila06487a22018-02-27 13:48:38 +0000249 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200250 ds_config->set_name("data_source");
251 consumer->EnableTracing(trace_config);
Sami Kyostila06487a22018-02-27 13:48:38 +0000252
Primiano Tuccidca727d2018-04-04 11:31:55 +0200253 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100254 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200255 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000256
Primiano Tuccidca727d2018-04-04 11:31:55 +0200257 // Disconnecting and reconnecting a producer with a matching data source.
258 // The Producer should see that data source getting enabled again.
259 producer.reset();
260 producer = CreateMockProducer();
261 producer->Connect(svc.get(), "mock_producer_2");
262 producer->RegisterDataSource("data_source");
263 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100264 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200265 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000266}
267
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100268TEST_F(TracingServiceImplTest, ProducerIDWrapping) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200269 std::vector<std::unique_ptr<MockProducer>> producers;
270 producers.push_back(nullptr);
Primiano Tucci081d46a2018-02-28 11:09:43 +0000271
Primiano Tuccidca727d2018-04-04 11:31:55 +0200272 auto connect_producer_and_get_id = [&producers,
273 this](const std::string& name) {
274 producers.emplace_back(CreateMockProducer());
275 producers.back()->Connect(svc.get(), "mock_producer_" + name);
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200276 return *last_producer_id();
Primiano Tucci081d46a2018-02-28 11:09:43 +0000277 };
278
279 // Connect producers 1-4.
280 for (ProducerID i = 1; i <= 4; i++)
Primiano Tuccidca727d2018-04-04 11:31:55 +0200281 ASSERT_EQ(i, connect_producer_and_get_id(std::to_string(i)));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000282
283 // Disconnect producers 1,3.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200284 producers[1].reset();
285 producers[3].reset();
Primiano Tucci081d46a2018-02-28 11:09:43 +0000286
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200287 *last_producer_id() = kMaxProducerID - 1;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200288 ASSERT_EQ(kMaxProducerID, connect_producer_and_get_id("maxid"));
289 ASSERT_EQ(1u, connect_producer_and_get_id("1_again"));
290 ASSERT_EQ(3u, connect_producer_and_get_id("3_again"));
291 ASSERT_EQ(5u, connect_producer_and_get_id("5"));
292 ASSERT_EQ(6u, connect_producer_and_get_id("6"));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000293}
294
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000295// Note: file_write_period_ms is set to a large enough to have exactly one flush
296// of the tracing buffers (and therefore at most one synchronization section),
297// unless the test runs unrealistically slowly, or the implementation of the
298// tracing snapshot packets changes.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100299TEST_F(TracingServiceImplTest, WriteIntoFileAndStopOnMaxSize) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200300 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
301 consumer->Connect(svc.get());
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100302
Primiano Tuccidca727d2018-04-04 11:31:55 +0200303 std::unique_ptr<MockProducer> producer = CreateMockProducer();
304 producer->Connect(svc.get(), "mock_producer");
305 producer->RegisterDataSource("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100306
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100307 TraceConfig trace_config;
308 trace_config.add_buffers()->set_size_kb(4096);
309 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200310 ds_config->set_name("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100311 ds_config->set_target_buffer(0);
312 trace_config.set_write_into_file(true);
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000313 trace_config.set_file_write_period_ms(100000); // 100s
314 const uint64_t kMaxFileSize = 1024;
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100315 trace_config.set_max_file_size_bytes(kMaxFileSize);
316 base::TempFile tmp_file = base::TempFile::Create();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200317 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
318
319 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100320 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccidca727d2018-04-04 11:31:55 +0200321 producer->WaitForDataSourceStart("data_source");
322
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000323 static const int kNumPreamblePackets = 4;
324 static const int kNumTestPackets = 10;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200325 static const char kPayload[] = "1234567890abcdef-";
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100326
327 std::unique_ptr<TraceWriter> writer =
Primiano Tuccidca727d2018-04-04 11:31:55 +0200328 producer->CreateTraceWriter("data_source");
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000329 // Tracing service will emit a preamble of packets (a synchronization section,
330 // followed by a tracing config packet). The preamble and these test packets
331 // should fit within kMaxFileSize.
332 for (int i = 0; i < kNumTestPackets; i++) {
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100333 auto tp = writer->NewTracePacket();
334 std::string payload(kPayload);
335 payload.append(std::to_string(i));
336 tp->set_for_testing()->set_str(payload.c_str(), payload.size());
337 }
338
339 // Finally add a packet that overflows kMaxFileSize. This should cause the
340 // implicit stop of the trace and should *not* be written in the trace.
341 {
342 auto tp = writer->NewTracePacket();
343 char big_payload[kMaxFileSize] = "BIG!";
344 tp->set_for_testing()->set_str(big_payload, sizeof(big_payload));
345 }
346 writer->Flush();
347 writer.reset();
348
Primiano Tuccidca727d2018-04-04 11:31:55 +0200349 consumer->DisableTracing();
350 producer->WaitForDataSourceStop("data_source");
351 consumer->WaitForTracingDisabled();
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100352
353 // Verify the contents of the file.
354 std::string trace_raw;
355 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
356 protos::Trace trace;
357 ASSERT_TRUE(trace.ParseFromString(trace_raw));
Ryan Savitskicc28cbf2018-11-09 22:55:12 +0000358
359 ASSERT_EQ(trace.packet_size(), kNumPreamblePackets + kNumTestPackets);
360 for (int i = 0; i < kNumTestPackets; i++) {
361 const protos::TracePacket& tp = trace.packet(kNumPreamblePackets + i);
362 ASSERT_EQ(kPayload + std::to_string(i++), tp.for_testing().str());
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100363 }
Primiano Tuccidca727d2018-04-04 11:31:55 +0200364}
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100365
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200366// Test the logic that allows the trace config to set the shm total size and
367// page size from the trace config. Also check that, if the config doesn't
368// specify a value we fall back on the hint provided by the producer.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100369TEST_F(TracingServiceImplTest, ProducerShmAndPageSizeOverriddenByTraceConfig) {
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200370 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
371 consumer->Connect(svc.get());
372 const size_t kConfigPageSizesKb[] = /****/ {16, 16, 4, 0, 16, 8, 3, 4096, 4};
373 const size_t kExpectedPageSizesKb[] = /**/ {16, 16, 4, 4, 16, 8, 4, 64, 4};
374
375 const size_t kConfigSizesKb[] = /**/ {0, 16, 0, 20, 32, 7, 0, 96, 4096000};
376 const size_t kHintSizesKb[] = /****/ {0, 0, 16, 32, 16, 0, 7, 96, 4096000};
377 const size_t kExpectedSizesKb[] = {
378 kDefaultShmSizeKb, // Both hint and config are 0, use default.
379 16, // Hint is 0, use config.
380 16, // Config is 0, use hint.
381 20, // Hint is takes precedence over the config.
382 32, // Ditto, even if config is higher than hint.
383 kDefaultShmSizeKb, // Config is invalid and hint is 0, use default.
384 kDefaultShmSizeKb, // Config is 0 and hint is invalid, use default.
385 kDefaultShmSizeKb, // 96 KB isn't a multiple of the page size (64 KB).
386 kMaxShmSizeKb // Too big, cap at kMaxShmSize.
387 };
388
389 const size_t kNumProducers = base::ArraySize(kHintSizesKb);
390 std::unique_ptr<MockProducer> producer[kNumProducers];
391 for (size_t i = 0; i < kNumProducers; i++) {
392 auto name = "mock_producer_" + std::to_string(i);
393 producer[i] = CreateMockProducer();
394 producer[i]->Connect(svc.get(), name, geteuid(), kHintSizesKb[i] * 1024);
395 producer[i]->RegisterDataSource("data_source");
396 }
397
398 TraceConfig trace_config;
399 trace_config.add_buffers()->set_size_kb(128);
400 auto* ds_config = trace_config.add_data_sources()->mutable_config();
401 ds_config->set_name("data_source");
402 for (size_t i = 0; i < kNumProducers; i++) {
403 auto* producer_config = trace_config.add_producers();
404 producer_config->set_producer_name("mock_producer_" + std::to_string(i));
Primiano Tucci3cbb10a2018-04-10 17:52:40 +0100405 producer_config->set_shm_size_kb(static_cast<uint32_t>(kConfigSizesKb[i]));
406 producer_config->set_page_size_kb(
407 static_cast<uint32_t>(kConfigPageSizesKb[i]));
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200408 }
409
410 consumer->EnableTracing(trace_config);
411 size_t actual_shm_sizes_kb[kNumProducers]{};
412 size_t actual_page_sizes_kb[kNumProducers]{};
413 for (size_t i = 0; i < kNumProducers; i++) {
414 producer[i]->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100415 producer[i]->WaitForDataSourceSetup("data_source");
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200416 actual_shm_sizes_kb[i] =
417 producer[i]->endpoint()->shared_memory()->size() / 1024;
418 actual_page_sizes_kb[i] =
419 producer[i]->endpoint()->shared_buffer_page_size_kb();
420 }
Primiano Tucci674076d2018-10-01 10:41:09 +0100421 for (size_t i = 0; i < kNumProducers; i++) {
422 producer[i]->WaitForDataSourceStart("data_source");
423 }
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200424 ASSERT_THAT(actual_page_sizes_kb, ElementsAreArray(kExpectedPageSizesKb));
425 ASSERT_THAT(actual_shm_sizes_kb, ElementsAreArray(kExpectedSizesKb));
426}
427
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100428TEST_F(TracingServiceImplTest, ExplicitFlush) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200429 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
430 consumer->Connect(svc.get());
431
432 std::unique_ptr<MockProducer> producer = CreateMockProducer();
433 producer->Connect(svc.get(), "mock_producer");
434 producer->RegisterDataSource("data_source");
435
436 TraceConfig trace_config;
437 trace_config.add_buffers()->set_size_kb(128);
438 auto* ds_config = trace_config.add_data_sources()->mutable_config();
439 ds_config->set_name("data_source");
440
441 consumer->EnableTracing(trace_config);
442 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100443 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccid52e6272018-04-06 19:06:53 +0200444 producer->WaitForDataSourceStart("data_source");
445
446 std::unique_ptr<TraceWriter> writer =
447 producer->CreateTraceWriter("data_source");
448 {
449 auto tp = writer->NewTracePacket();
450 tp->set_for_testing()->set_str("payload");
451 }
452
453 auto flush_request = consumer->Flush();
454 producer->WaitForFlush(writer.get());
455 ASSERT_TRUE(flush_request.WaitForReply());
456
457 consumer->DisableTracing();
458 producer->WaitForDataSourceStop("data_source");
459 consumer->WaitForTracingDisabled();
460 EXPECT_THAT(
461 consumer->ReadBuffers(),
462 Contains(Property(&protos::TracePacket::for_testing,
463 Property(&protos::TestEvent::str, Eq("payload")))));
464}
465
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100466TEST_F(TracingServiceImplTest, ImplicitFlushOnTimedTraces) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200467 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
468 consumer->Connect(svc.get());
469
470 std::unique_ptr<MockProducer> producer = CreateMockProducer();
471 producer->Connect(svc.get(), "mock_producer");
472 producer->RegisterDataSource("data_source");
473
474 TraceConfig trace_config;
475 trace_config.add_buffers()->set_size_kb(128);
476 auto* ds_config = trace_config.add_data_sources()->mutable_config();
477 ds_config->set_name("data_source");
478 trace_config.set_duration_ms(1);
479
480 consumer->EnableTracing(trace_config);
481 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100482 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccid52e6272018-04-06 19:06:53 +0200483 producer->WaitForDataSourceStart("data_source");
484
485 std::unique_ptr<TraceWriter> writer =
486 producer->CreateTraceWriter("data_source");
487 {
488 auto tp = writer->NewTracePacket();
489 tp->set_for_testing()->set_str("payload");
490 }
491
492 producer->WaitForFlush(writer.get());
493
494 producer->WaitForDataSourceStop("data_source");
495 consumer->WaitForTracingDisabled();
496
497 EXPECT_THAT(
498 consumer->ReadBuffers(),
499 Contains(Property(&protos::TracePacket::for_testing,
500 Property(&protos::TestEvent::str, Eq("payload")))));
501}
502
503// Tests the monotonic semantic of flush request IDs, i.e., once a producer
504// acks flush request N, all flush requests <= N are considered successful and
505// acked to the consumer.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100506TEST_F(TracingServiceImplTest, BatchFlushes) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200507 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
508 consumer->Connect(svc.get());
509
510 std::unique_ptr<MockProducer> producer = CreateMockProducer();
511 producer->Connect(svc.get(), "mock_producer");
512 producer->RegisterDataSource("data_source");
513
514 TraceConfig trace_config;
515 trace_config.add_buffers()->set_size_kb(128);
516 auto* ds_config = trace_config.add_data_sources()->mutable_config();
517 ds_config->set_name("data_source");
518
519 consumer->EnableTracing(trace_config);
520 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100521 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccid52e6272018-04-06 19:06:53 +0200522 producer->WaitForDataSourceStart("data_source");
523
524 std::unique_ptr<TraceWriter> writer =
525 producer->CreateTraceWriter("data_source");
526 {
527 auto tp = writer->NewTracePacket();
528 tp->set_for_testing()->set_str("payload");
529 }
530
531 auto flush_req_1 = consumer->Flush();
532 auto flush_req_2 = consumer->Flush();
533 auto flush_req_3 = consumer->Flush();
534
535 // We'll deliberately let the 4th flush request timeout. Use a lower timeout
536 // to keep test time short.
537 auto flush_req_4 = consumer->Flush(/*timeout_ms=*/10);
538 ASSERT_EQ(4u, GetNumPendingFlushes());
539
540 // Make the producer reply only to the 3rd flush request.
541 testing::InSequence seq;
542 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 1.
543 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 2.
544 producer->WaitForFlush(writer.get()); // Will reply only to flush id == 3.
545 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 4.
546
547 // Even if the producer explicily replied only to flush ID == 3, all the
548 // previous flushed < 3 should be implicitly acked.
549 ASSERT_TRUE(flush_req_1.WaitForReply());
550 ASSERT_TRUE(flush_req_2.WaitForReply());
551 ASSERT_TRUE(flush_req_3.WaitForReply());
552
553 // At this point flush id == 4 should still be pending and should fail because
554 // of reaching its timeout.
Primiano Tuccid52e6272018-04-06 19:06:53 +0200555 ASSERT_FALSE(flush_req_4.WaitForReply());
556
557 consumer->DisableTracing();
558 producer->WaitForDataSourceStop("data_source");
559 consumer->WaitForTracingDisabled();
560 EXPECT_THAT(
561 consumer->ReadBuffers(),
562 Contains(Property(&protos::TracePacket::for_testing,
563 Property(&protos::TestEvent::str, Eq("payload")))));
564}
565
Primiano Tuccicaa57802018-11-25 11:07:07 +0000566TEST_F(TracingServiceImplTest, PeriodicFlush) {
567 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
568 consumer->Connect(svc.get());
569
570 std::unique_ptr<MockProducer> producer = CreateMockProducer();
571 producer->Connect(svc.get(), "mock_producer");
572 producer->RegisterDataSource("data_source");
573
574 TraceConfig trace_config;
575 trace_config.add_buffers()->set_size_kb(128);
576 trace_config.set_flush_period_ms(1);
577 auto* ds_config = trace_config.add_data_sources()->mutable_config();
578 ds_config->set_name("data_source");
579
580 consumer->EnableTracing(trace_config);
581 producer->WaitForTracingSetup();
582 producer->WaitForDataSourceSetup("data_source");
583 producer->WaitForDataSourceStart("data_source");
584
585 std::unique_ptr<TraceWriter> writer =
586 producer->CreateTraceWriter("data_source");
587
588 const int kNumFlushes = 3;
589 auto checkpoint = task_runner.CreateCheckpoint("all_flushes_done");
590 int flushes_seen = 0;
591 EXPECT_CALL(*producer, Flush(_, _, _))
592 .WillRepeatedly(Invoke([&producer, &writer, &flushes_seen, checkpoint](
593 FlushRequestID flush_req_id,
594 const DataSourceInstanceID*, size_t) {
595 {
596 auto tp = writer->NewTracePacket();
597 char payload[32];
598 sprintf(payload, "f_%d", flushes_seen);
599 tp->set_for_testing()->set_str(payload);
600 }
601 writer->Flush();
602 producer->endpoint()->NotifyFlushComplete(flush_req_id);
603 if (++flushes_seen == kNumFlushes)
604 checkpoint();
605 }));
606 task_runner.RunUntilCheckpoint("all_flushes_done");
607
608 consumer->DisableTracing();
609 producer->WaitForDataSourceStop("data_source");
610 consumer->WaitForTracingDisabled();
611 auto trace_packets = consumer->ReadBuffers();
612 for (int i = 0; i < kNumFlushes; i++) {
613 EXPECT_THAT(trace_packets,
614 Contains(Property(&protos::TracePacket::for_testing,
615 Property(&protos::TestEvent::str,
616 Eq("f_" + std::to_string(i))))));
617 }
618}
619
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100620// Creates a tracing session where some of the data sources set the
621// |will_notify_on_stop| flag and checks that the OnTracingDisabled notification
622// to the consumer is delayed until the acks are received.
623TEST_F(TracingServiceImplTest, OnTracingDisabledWaitsForDataSourceStopAcks) {
624 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
625 consumer->Connect(svc.get());
626
627 std::unique_ptr<MockProducer> producer = CreateMockProducer();
628 producer->Connect(svc.get(), "mock_producer");
629 producer->RegisterDataSource("ds_will_ack_1", /*ack_stop=*/true);
630 producer->RegisterDataSource("ds_wont_ack");
631 producer->RegisterDataSource("ds_will_ack_2", /*ack_stop=*/true);
632
633 TraceConfig trace_config;
634 trace_config.add_buffers()->set_size_kb(128);
635 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack_1");
636 trace_config.add_data_sources()->mutable_config()->set_name("ds_wont_ack");
637 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack_2");
638 trace_config.set_duration_ms(1);
639
640 consumer->EnableTracing(trace_config);
641 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100642
643 producer->WaitForDataSourceSetup("ds_will_ack_1");
644 producer->WaitForDataSourceSetup("ds_wont_ack");
645 producer->WaitForDataSourceSetup("ds_will_ack_2");
646
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100647 producer->WaitForDataSourceStart("ds_will_ack_1");
648 producer->WaitForDataSourceStart("ds_wont_ack");
649 producer->WaitForDataSourceStart("ds_will_ack_2");
650
651 std::unique_ptr<TraceWriter> writer =
652 producer->CreateTraceWriter("ds_wont_ack");
653 producer->WaitForFlush(writer.get());
654
655 DataSourceInstanceID id1 = producer->GetDataSourceInstanceId("ds_will_ack_1");
656 DataSourceInstanceID id2 = producer->GetDataSourceInstanceId("ds_will_ack_2");
657
658 producer->WaitForDataSourceStop("ds_will_ack_1");
659 producer->WaitForDataSourceStop("ds_wont_ack");
660 producer->WaitForDataSourceStop("ds_will_ack_2");
661
662 producer->endpoint()->NotifyDataSourceStopped(id1);
663 producer->endpoint()->NotifyDataSourceStopped(id2);
664
665 // Wait for at most half of the service timeout, so that this test fails if
666 // the service falls back on calling the OnTracingDisabled() because some of
667 // the expected acks weren't received.
668 consumer->WaitForTracingDisabled(
669 TracingServiceImpl::kDataSourceStopTimeoutMs / 2);
670}
671
Oystein Eftevaagf250e1c2018-08-23 16:10:52 -0700672// Creates a tracing session where a second data source
673// is added while the service is waiting for DisableTracing
674// acks; the service should not enable the new datasource
675// and should not hit any asserts when the consumer is
676// subsequently destroyed.
677TEST_F(TracingServiceImplTest, OnDataSourceAddedWhilePendingDisableAcks) {
678 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
679 consumer->Connect(svc.get());
680
681 std::unique_ptr<MockProducer> producer = CreateMockProducer();
682 producer->Connect(svc.get(), "mock_producer");
683 producer->RegisterDataSource("ds_will_ack", /*ack_stop=*/true);
684
685 TraceConfig trace_config;
686 trace_config.add_buffers()->set_size_kb(128);
687 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack");
688 trace_config.add_data_sources()->mutable_config()->set_name("ds_wont_ack");
689
690 consumer->EnableTracing(trace_config);
691 producer->WaitForTracingSetup();
692
693 consumer->DisableTracing();
694
695 producer->RegisterDataSource("ds_wont_ack");
696
697 consumer.reset();
698}
699
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100700// Similar to OnTracingDisabledWaitsForDataSourceStopAcks, but deliberately
701// skips the ack and checks that the service invokes the OnTracingDisabled()
702// after the timeout.
703TEST_F(TracingServiceImplTest, OnTracingDisabledCalledAnywaysInCaseOfTimeout) {
704 svc->override_data_source_test_timeout_ms_for_testing = 1;
705 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
706 consumer->Connect(svc.get());
707
708 std::unique_ptr<MockProducer> producer = CreateMockProducer();
709 producer->Connect(svc.get(), "mock_producer");
710 producer->RegisterDataSource("data_source", /*ack_stop=*/true);
711
712 TraceConfig trace_config;
713 trace_config.add_buffers()->set_size_kb(128);
714 trace_config.add_data_sources()->mutable_config()->set_name("data_source");
715 trace_config.set_duration_ms(1);
716
717 consumer->EnableTracing(trace_config);
718 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100719 producer->WaitForDataSourceSetup("data_source");
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100720 producer->WaitForDataSourceStart("data_source");
721
722 std::unique_ptr<TraceWriter> writer =
723 producer->CreateTraceWriter("data_source");
724 producer->WaitForFlush(writer.get());
725
726 producer->WaitForDataSourceStop("data_source");
727 consumer->WaitForTracingDisabled();
728}
729
Primiano Tucci03de28f2018-08-01 11:29:46 +0100730// Tests the session_id logic. Two data sources in the same tracing session
731// should see the same session id.
732TEST_F(TracingServiceImplTest, SessionId) {
733 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
734 consumer->Connect(svc.get());
735
736 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
737 producer1->Connect(svc.get(), "mock_producer1");
738 producer1->RegisterDataSource("ds_1A");
739 producer1->RegisterDataSource("ds_1B");
740
741 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
742 producer2->Connect(svc.get(), "mock_producer2");
743 producer2->RegisterDataSource("ds_2A");
744
745 testing::InSequence seq;
746 TracingSessionID last_session_id = 0;
747 for (int i = 0; i < 3; i++) {
748 TraceConfig trace_config;
749 trace_config.add_buffers()->set_size_kb(128);
750 trace_config.add_data_sources()->mutable_config()->set_name("ds_1A");
751 trace_config.add_data_sources()->mutable_config()->set_name("ds_1B");
752 trace_config.add_data_sources()->mutable_config()->set_name("ds_2A");
753 trace_config.set_duration_ms(1);
754
755 consumer->EnableTracing(trace_config);
756
757 if (i == 0)
758 producer1->WaitForTracingSetup();
Primiano Tucci03de28f2018-08-01 11:29:46 +0100759
Primiano Tucci674076d2018-10-01 10:41:09 +0100760 producer1->WaitForDataSourceSetup("ds_1A");
761 producer1->WaitForDataSourceSetup("ds_1B");
Primiano Tucci03de28f2018-08-01 11:29:46 +0100762 if (i == 0)
763 producer2->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100764 producer2->WaitForDataSourceSetup("ds_2A");
765
766 producer1->WaitForDataSourceStart("ds_1A");
767 producer1->WaitForDataSourceStart("ds_1B");
Primiano Tucci03de28f2018-08-01 11:29:46 +0100768 producer2->WaitForDataSourceStart("ds_2A");
769
770 auto* ds1 = producer1->GetDataSourceInstance("ds_1A");
771 auto* ds2 = producer1->GetDataSourceInstance("ds_1B");
772 auto* ds3 = producer2->GetDataSourceInstance("ds_2A");
773 ASSERT_EQ(ds1->session_id, ds2->session_id);
774 ASSERT_EQ(ds1->session_id, ds3->session_id);
775 ASSERT_NE(ds1->session_id, last_session_id);
776 last_session_id = ds1->session_id;
777
778 auto writer1 = producer1->CreateTraceWriter("ds_1A");
779 producer1->WaitForFlush(writer1.get());
780
781 auto writer2 = producer2->CreateTraceWriter("ds_2A");
782 producer2->WaitForFlush(writer2.get());
783
784 producer1->WaitForDataSourceStop("ds_1A");
785 producer1->WaitForDataSourceStop("ds_1B");
786 producer2->WaitForDataSourceStop("ds_2A");
787 consumer->WaitForTracingDisabled();
788 consumer->FreeBuffers();
789 }
790}
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100791
792// Writes a long trace and then tests that the trace parsed in partitions
793// derived by the synchronization markers is identical to the whole trace parsed
794// in one go.
795TEST_F(TracingServiceImplTest, ResynchronizeTraceStreamUsingSyncMarker) {
796 // Setup tracing.
797 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
798 consumer->Connect(svc.get());
799 std::unique_ptr<MockProducer> producer = CreateMockProducer();
800 producer->Connect(svc.get(), "mock_producer");
801 producer->RegisterDataSource("data_source");
802 TraceConfig trace_config;
803 trace_config.add_buffers()->set_size_kb(4096);
804 auto* ds_config = trace_config.add_data_sources()->mutable_config();
805 ds_config->set_name("data_source");
806 trace_config.set_write_into_file(true);
807 trace_config.set_file_write_period_ms(1);
808 base::TempFile tmp_file = base::TempFile::Create();
809 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
810 producer->WaitForTracingSetup();
Primiano Tucci674076d2018-10-01 10:41:09 +0100811 producer->WaitForDataSourceSetup("data_source");
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100812 producer->WaitForDataSourceStart("data_source");
813
814 // Write some variable length payload, waiting for sync markers every now
815 // and then.
816 const int kNumMarkers = 5;
817 auto writer = producer->CreateTraceWriter("data_source");
818 for (int i = 1; i <= 100; i++) {
819 std::string payload(i, 'A' + (i % 25));
820 writer->NewTracePacket()->set_for_testing()->set_str(payload.c_str());
821 if (i % (100 / kNumMarkers) == 0) {
822 writer->Flush();
823 WaitForNextSyncMarker();
824 }
825 }
826 writer->Flush();
827 writer.reset();
828 consumer->DisableTracing();
829 producer->WaitForDataSourceStop("data_source");
830 consumer->WaitForTracingDisabled();
831
832 std::string trace_raw;
833 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
834
835 const auto kMarkerSize = sizeof(TracingServiceImpl::kSyncMarker);
836 const std::string kSyncMarkerStr(
837 reinterpret_cast<const char*>(TracingServiceImpl::kSyncMarker),
838 kMarkerSize);
839
840 // Read back the trace in partitions derived from the marker.
841 // The trace should look like this:
842 // [uid, marker] [event] [event] [uid, marker] [event] [event]
843 size_t num_markers = 0;
844 size_t start = 0;
845 size_t end = 0;
846 protos::Trace merged_trace;
847 for (size_t pos = 0; pos != std::string::npos; start = end) {
848 pos = trace_raw.find(kSyncMarkerStr, pos + 1);
849 num_markers++;
850 end = (pos == std::string::npos) ? trace_raw.size() : pos + kMarkerSize;
851 int size = static_cast<int>(end - start);
852 ASSERT_GT(size, 0);
853 protos::Trace trace_partition;
854 ASSERT_TRUE(trace_partition.ParseFromArray(trace_raw.data() + start, size));
855 merged_trace.MergeFrom(trace_partition);
856 }
Lalit Maganti9bdc7ce2018-09-17 15:25:11 +0100857 EXPECT_GE(num_markers, static_cast<size_t>(kNumMarkers));
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100858
859 protos::Trace whole_trace;
860 ASSERT_TRUE(whole_trace.ParseFromString(trace_raw));
861
862 ASSERT_EQ(whole_trace.packet_size(), merged_trace.packet_size());
863 EXPECT_EQ(whole_trace.SerializeAsString(), merged_trace.SerializeAsString());
864}
865
Primiano Tucci674076d2018-10-01 10:41:09 +0100866// Creates a tracing session with |deferred_start| and checks that data sources
867// are started only after calling StartTracing().
868TEST_F(TracingServiceImplTest, DeferredStart) {
869 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
870 consumer->Connect(svc.get());
871
872 std::unique_ptr<MockProducer> producer = CreateMockProducer();
873 producer->Connect(svc.get(), "mock_producer");
874
875 // Create two data sources but enable only one of them.
876 producer->RegisterDataSource("ds_1");
877 producer->RegisterDataSource("ds_2");
878
879 TraceConfig trace_config;
880 trace_config.add_buffers()->set_size_kb(128);
881 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
882 trace_config.set_deferred_start(true);
883 trace_config.set_duration_ms(1);
884
885 consumer->EnableTracing(trace_config);
886 producer->WaitForTracingSetup();
887
888 producer->WaitForDataSourceSetup("ds_1");
889
890 // Make sure we don't get unexpected DataSourceStart() notifications yet.
891 task_runner.RunUntilIdle();
892
893 consumer->StartTracing();
894
895 producer->WaitForDataSourceStart("ds_1");
896
897 auto writer1 = producer->CreateTraceWriter("ds_1");
898 producer->WaitForFlush(writer1.get());
899
900 producer->WaitForDataSourceStop("ds_1");
901 consumer->WaitForTracingDisabled();
902}
903
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000904} // namespace perfetto