blob: 8787672fb990a4c3d8542ef83d6b114f8920797b [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();
157 producer->WaitForDataSourceStart("data_source");
158
159 consumer->DisableTracing();
160 producer->WaitForDataSourceStop("data_source");
161 consumer->WaitForTracingDisabled();
Sami Kyostila06487a22018-02-27 13:48:38 +0000162}
163
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100164TEST_F(TracingServiceImplTest, LockdownMode) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200165 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
166 consumer->Connect(svc.get());
167
168 std::unique_ptr<MockProducer> producer = CreateMockProducer();
169 producer->Connect(svc.get(), "mock_producer_sameuid", geteuid());
170 producer->RegisterDataSource("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000171
172 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200173 trace_config.add_buffers()->set_size_kb(128);
174 auto* ds_config = trace_config.add_data_sources()->mutable_config();
175 ds_config->set_name("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000176 trace_config.set_lockdown_mode(
177 TraceConfig::LockdownModeOperation::LOCKDOWN_SET);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200178 consumer->EnableTracing(trace_config);
179
180 producer->WaitForTracingSetup();
181 producer->WaitForDataSourceStart("data_source");
182
183 std::unique_ptr<MockProducer> producer_otheruid = CreateMockProducer();
184 auto x = svc->ConnectProducer(producer_otheruid.get(), geteuid() + 1,
185 "mock_producer_ouid");
186 EXPECT_CALL(*producer_otheruid, OnConnect()).Times(0);
Florian Mayer61c55482018-03-06 14:43:54 +0000187 task_runner.RunUntilIdle();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200188 Mock::VerifyAndClearExpectations(producer_otheruid.get());
Florian Mayer61c55482018-03-06 14:43:54 +0000189
Primiano Tuccidca727d2018-04-04 11:31:55 +0200190 consumer->DisableTracing();
191 consumer->FreeBuffers();
192 producer->WaitForDataSourceStop("data_source");
193 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000194
195 trace_config.set_lockdown_mode(
196 TraceConfig::LockdownModeOperation::LOCKDOWN_CLEAR);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200197 consumer->EnableTracing(trace_config);
198 producer->WaitForDataSourceStart("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000199
Primiano Tuccidca727d2018-04-04 11:31:55 +0200200 std::unique_ptr<MockProducer> producer_otheruid2 = CreateMockProducer();
201 producer_otheruid->Connect(svc.get(), "mock_producer_ouid2", geteuid() + 1);
Florian Mayer61c55482018-03-06 14:43:54 +0000202
Primiano Tuccidca727d2018-04-04 11:31:55 +0200203 consumer->DisableTracing();
204 producer->WaitForDataSourceStop("data_source");
205 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000206}
207
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100208TEST_F(TracingServiceImplTest, DisconnectConsumerWhileTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200209 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
210 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000211
Primiano Tuccidca727d2018-04-04 11:31:55 +0200212 std::unique_ptr<MockProducer> producer = CreateMockProducer();
213 producer->Connect(svc.get(), "mock_producer");
214 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000215
Primiano Tuccidca727d2018-04-04 11:31:55 +0200216 TraceConfig trace_config;
217 trace_config.add_buffers()->set_size_kb(128);
218 auto* ds_config = trace_config.add_data_sources()->mutable_config();
219 ds_config->set_name("data_source");
220 consumer->EnableTracing(trace_config);
221
222 producer->WaitForTracingSetup();
223 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000224
225 // Disconnecting the consumer while tracing should trigger data source
226 // teardown.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200227 consumer.reset();
228 producer->WaitForDataSourceStop("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000229}
230
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100231TEST_F(TracingServiceImplTest, ReconnectProducerWhileTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200232 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
233 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000234
Primiano Tuccidca727d2018-04-04 11:31:55 +0200235 std::unique_ptr<MockProducer> producer = CreateMockProducer();
236 producer->Connect(svc.get(), "mock_producer");
237 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000238
Sami Kyostila06487a22018-02-27 13:48:38 +0000239 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200240 trace_config.add_buffers()->set_size_kb(128);
Sami Kyostila06487a22018-02-27 13:48:38 +0000241 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200242 ds_config->set_name("data_source");
243 consumer->EnableTracing(trace_config);
Sami Kyostila06487a22018-02-27 13:48:38 +0000244
Primiano Tuccidca727d2018-04-04 11:31:55 +0200245 producer->WaitForTracingSetup();
246 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000247
Primiano Tuccidca727d2018-04-04 11:31:55 +0200248 // Disconnecting and reconnecting a producer with a matching data source.
249 // The Producer should see that data source getting enabled again.
250 producer.reset();
251 producer = CreateMockProducer();
252 producer->Connect(svc.get(), "mock_producer_2");
253 producer->RegisterDataSource("data_source");
254 producer->WaitForTracingSetup();
255 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000256}
257
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100258TEST_F(TracingServiceImplTest, ProducerIDWrapping) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200259 std::vector<std::unique_ptr<MockProducer>> producers;
260 producers.push_back(nullptr);
Primiano Tucci081d46a2018-02-28 11:09:43 +0000261
Primiano Tuccidca727d2018-04-04 11:31:55 +0200262 auto connect_producer_and_get_id = [&producers,
263 this](const std::string& name) {
264 producers.emplace_back(CreateMockProducer());
265 producers.back()->Connect(svc.get(), "mock_producer_" + name);
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200266 return *last_producer_id();
Primiano Tucci081d46a2018-02-28 11:09:43 +0000267 };
268
269 // Connect producers 1-4.
270 for (ProducerID i = 1; i <= 4; i++)
Primiano Tuccidca727d2018-04-04 11:31:55 +0200271 ASSERT_EQ(i, connect_producer_and_get_id(std::to_string(i)));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000272
273 // Disconnect producers 1,3.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200274 producers[1].reset();
275 producers[3].reset();
Primiano Tucci081d46a2018-02-28 11:09:43 +0000276
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200277 *last_producer_id() = kMaxProducerID - 1;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200278 ASSERT_EQ(kMaxProducerID, connect_producer_and_get_id("maxid"));
279 ASSERT_EQ(1u, connect_producer_and_get_id("1_again"));
280 ASSERT_EQ(3u, connect_producer_and_get_id("3_again"));
281 ASSERT_EQ(5u, connect_producer_and_get_id("5"));
282 ASSERT_EQ(6u, connect_producer_and_get_id("6"));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000283}
284
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100285TEST_F(TracingServiceImplTest, WriteIntoFileAndStopOnMaxSize) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200286 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
287 consumer->Connect(svc.get());
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100288
Primiano Tuccidca727d2018-04-04 11:31:55 +0200289 std::unique_ptr<MockProducer> producer = CreateMockProducer();
290 producer->Connect(svc.get(), "mock_producer");
291 producer->RegisterDataSource("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100292
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100293 TraceConfig trace_config;
294 trace_config.add_buffers()->set_size_kb(4096);
295 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200296 ds_config->set_name("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100297 ds_config->set_target_buffer(0);
298 trace_config.set_write_into_file(true);
299 trace_config.set_file_write_period_ms(1);
300 const uint64_t kMaxFileSize = 512;
301 trace_config.set_max_file_size_bytes(kMaxFileSize);
302 base::TempFile tmp_file = base::TempFile::Create();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200303 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
304
305 producer->WaitForTracingSetup();
306 producer->WaitForDataSourceStart("data_source");
307
308 static const char kPayload[] = "1234567890abcdef-";
309 static const int kNumPackets = 10;
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100310
311 std::unique_ptr<TraceWriter> writer =
Primiano Tuccidca727d2018-04-04 11:31:55 +0200312 producer->CreateTraceWriter("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100313 // All these packets should fit within kMaxFileSize.
314 for (int i = 0; i < kNumPackets; i++) {
315 auto tp = writer->NewTracePacket();
316 std::string payload(kPayload);
317 payload.append(std::to_string(i));
318 tp->set_for_testing()->set_str(payload.c_str(), payload.size());
319 }
320
321 // Finally add a packet that overflows kMaxFileSize. This should cause the
322 // implicit stop of the trace and should *not* be written in the trace.
323 {
324 auto tp = writer->NewTracePacket();
325 char big_payload[kMaxFileSize] = "BIG!";
326 tp->set_for_testing()->set_str(big_payload, sizeof(big_payload));
327 }
328 writer->Flush();
329 writer.reset();
330
Primiano Tuccidca727d2018-04-04 11:31:55 +0200331 consumer->DisableTracing();
332 producer->WaitForDataSourceStop("data_source");
333 consumer->WaitForTracingDisabled();
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100334
335 // Verify the contents of the file.
336 std::string trace_raw;
337 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
338 protos::Trace trace;
339 ASSERT_TRUE(trace.ParseFromString(trace_raw));
340 ASSERT_GE(trace.packet_size(), kNumPackets);
341 int num_testing_packet = 0;
342 for (int i = 0; i < trace.packet_size(); i++) {
343 const protos::TracePacket& tp = trace.packet(i);
344 if (!tp.has_for_testing())
345 continue;
346 ASSERT_EQ(kPayload + std::to_string(num_testing_packet++),
347 tp.for_testing().str());
348 }
Primiano Tuccidca727d2018-04-04 11:31:55 +0200349}
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100350
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200351// Test the logic that allows the trace config to set the shm total size and
352// page size from the trace config. Also check that, if the config doesn't
353// specify a value we fall back on the hint provided by the producer.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100354TEST_F(TracingServiceImplTest, ProducerShmAndPageSizeOverriddenByTraceConfig) {
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200355 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
356 consumer->Connect(svc.get());
357 const size_t kConfigPageSizesKb[] = /****/ {16, 16, 4, 0, 16, 8, 3, 4096, 4};
358 const size_t kExpectedPageSizesKb[] = /**/ {16, 16, 4, 4, 16, 8, 4, 64, 4};
359
360 const size_t kConfigSizesKb[] = /**/ {0, 16, 0, 20, 32, 7, 0, 96, 4096000};
361 const size_t kHintSizesKb[] = /****/ {0, 0, 16, 32, 16, 0, 7, 96, 4096000};
362 const size_t kExpectedSizesKb[] = {
363 kDefaultShmSizeKb, // Both hint and config are 0, use default.
364 16, // Hint is 0, use config.
365 16, // Config is 0, use hint.
366 20, // Hint is takes precedence over the config.
367 32, // Ditto, even if config is higher than hint.
368 kDefaultShmSizeKb, // Config is invalid and hint is 0, use default.
369 kDefaultShmSizeKb, // Config is 0 and hint is invalid, use default.
370 kDefaultShmSizeKb, // 96 KB isn't a multiple of the page size (64 KB).
371 kMaxShmSizeKb // Too big, cap at kMaxShmSize.
372 };
373
374 const size_t kNumProducers = base::ArraySize(kHintSizesKb);
375 std::unique_ptr<MockProducer> producer[kNumProducers];
376 for (size_t i = 0; i < kNumProducers; i++) {
377 auto name = "mock_producer_" + std::to_string(i);
378 producer[i] = CreateMockProducer();
379 producer[i]->Connect(svc.get(), name, geteuid(), kHintSizesKb[i] * 1024);
380 producer[i]->RegisterDataSource("data_source");
381 }
382
383 TraceConfig trace_config;
384 trace_config.add_buffers()->set_size_kb(128);
385 auto* ds_config = trace_config.add_data_sources()->mutable_config();
386 ds_config->set_name("data_source");
387 for (size_t i = 0; i < kNumProducers; i++) {
388 auto* producer_config = trace_config.add_producers();
389 producer_config->set_producer_name("mock_producer_" + std::to_string(i));
Primiano Tucci3cbb10a2018-04-10 17:52:40 +0100390 producer_config->set_shm_size_kb(static_cast<uint32_t>(kConfigSizesKb[i]));
391 producer_config->set_page_size_kb(
392 static_cast<uint32_t>(kConfigPageSizesKb[i]));
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200393 }
394
395 consumer->EnableTracing(trace_config);
396 size_t actual_shm_sizes_kb[kNumProducers]{};
397 size_t actual_page_sizes_kb[kNumProducers]{};
398 for (size_t i = 0; i < kNumProducers; i++) {
399 producer[i]->WaitForTracingSetup();
400 producer[i]->WaitForDataSourceStart("data_source");
401 actual_shm_sizes_kb[i] =
402 producer[i]->endpoint()->shared_memory()->size() / 1024;
403 actual_page_sizes_kb[i] =
404 producer[i]->endpoint()->shared_buffer_page_size_kb();
405 }
406 ASSERT_THAT(actual_page_sizes_kb, ElementsAreArray(kExpectedPageSizesKb));
407 ASSERT_THAT(actual_shm_sizes_kb, ElementsAreArray(kExpectedSizesKb));
408}
409
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100410TEST_F(TracingServiceImplTest, ExplicitFlush) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200411 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
412 consumer->Connect(svc.get());
413
414 std::unique_ptr<MockProducer> producer = CreateMockProducer();
415 producer->Connect(svc.get(), "mock_producer");
416 producer->RegisterDataSource("data_source");
417
418 TraceConfig trace_config;
419 trace_config.add_buffers()->set_size_kb(128);
420 auto* ds_config = trace_config.add_data_sources()->mutable_config();
421 ds_config->set_name("data_source");
422
423 consumer->EnableTracing(trace_config);
424 producer->WaitForTracingSetup();
425 producer->WaitForDataSourceStart("data_source");
426
427 std::unique_ptr<TraceWriter> writer =
428 producer->CreateTraceWriter("data_source");
429 {
430 auto tp = writer->NewTracePacket();
431 tp->set_for_testing()->set_str("payload");
432 }
433
434 auto flush_request = consumer->Flush();
435 producer->WaitForFlush(writer.get());
436 ASSERT_TRUE(flush_request.WaitForReply());
437
438 consumer->DisableTracing();
439 producer->WaitForDataSourceStop("data_source");
440 consumer->WaitForTracingDisabled();
441 EXPECT_THAT(
442 consumer->ReadBuffers(),
443 Contains(Property(&protos::TracePacket::for_testing,
444 Property(&protos::TestEvent::str, Eq("payload")))));
445}
446
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100447TEST_F(TracingServiceImplTest, ImplicitFlushOnTimedTraces) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200448 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
449 consumer->Connect(svc.get());
450
451 std::unique_ptr<MockProducer> producer = CreateMockProducer();
452 producer->Connect(svc.get(), "mock_producer");
453 producer->RegisterDataSource("data_source");
454
455 TraceConfig trace_config;
456 trace_config.add_buffers()->set_size_kb(128);
457 auto* ds_config = trace_config.add_data_sources()->mutable_config();
458 ds_config->set_name("data_source");
459 trace_config.set_duration_ms(1);
460
461 consumer->EnableTracing(trace_config);
462 producer->WaitForTracingSetup();
463 producer->WaitForDataSourceStart("data_source");
464
465 std::unique_ptr<TraceWriter> writer =
466 producer->CreateTraceWriter("data_source");
467 {
468 auto tp = writer->NewTracePacket();
469 tp->set_for_testing()->set_str("payload");
470 }
471
472 producer->WaitForFlush(writer.get());
473
474 producer->WaitForDataSourceStop("data_source");
475 consumer->WaitForTracingDisabled();
476
477 EXPECT_THAT(
478 consumer->ReadBuffers(),
479 Contains(Property(&protos::TracePacket::for_testing,
480 Property(&protos::TestEvent::str, Eq("payload")))));
481}
482
483// Tests the monotonic semantic of flush request IDs, i.e., once a producer
484// acks flush request N, all flush requests <= N are considered successful and
485// acked to the consumer.
Florian Mayer6a1a4d52018-06-08 16:47:07 +0100486TEST_F(TracingServiceImplTest, BatchFlushes) {
Primiano Tuccid52e6272018-04-06 19:06:53 +0200487 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
488 consumer->Connect(svc.get());
489
490 std::unique_ptr<MockProducer> producer = CreateMockProducer();
491 producer->Connect(svc.get(), "mock_producer");
492 producer->RegisterDataSource("data_source");
493
494 TraceConfig trace_config;
495 trace_config.add_buffers()->set_size_kb(128);
496 auto* ds_config = trace_config.add_data_sources()->mutable_config();
497 ds_config->set_name("data_source");
498
499 consumer->EnableTracing(trace_config);
500 producer->WaitForTracingSetup();
501 producer->WaitForDataSourceStart("data_source");
502
503 std::unique_ptr<TraceWriter> writer =
504 producer->CreateTraceWriter("data_source");
505 {
506 auto tp = writer->NewTracePacket();
507 tp->set_for_testing()->set_str("payload");
508 }
509
510 auto flush_req_1 = consumer->Flush();
511 auto flush_req_2 = consumer->Flush();
512 auto flush_req_3 = consumer->Flush();
513
514 // We'll deliberately let the 4th flush request timeout. Use a lower timeout
515 // to keep test time short.
516 auto flush_req_4 = consumer->Flush(/*timeout_ms=*/10);
517 ASSERT_EQ(4u, GetNumPendingFlushes());
518
519 // Make the producer reply only to the 3rd flush request.
520 testing::InSequence seq;
521 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 1.
522 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 2.
523 producer->WaitForFlush(writer.get()); // Will reply only to flush id == 3.
524 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 4.
525
526 // Even if the producer explicily replied only to flush ID == 3, all the
527 // previous flushed < 3 should be implicitly acked.
528 ASSERT_TRUE(flush_req_1.WaitForReply());
529 ASSERT_TRUE(flush_req_2.WaitForReply());
530 ASSERT_TRUE(flush_req_3.WaitForReply());
531
532 // At this point flush id == 4 should still be pending and should fail because
533 // of reaching its timeout.
Primiano Tuccid52e6272018-04-06 19:06:53 +0200534 ASSERT_FALSE(flush_req_4.WaitForReply());
535
536 consumer->DisableTracing();
537 producer->WaitForDataSourceStop("data_source");
538 consumer->WaitForTracingDisabled();
539 EXPECT_THAT(
540 consumer->ReadBuffers(),
541 Contains(Property(&protos::TracePacket::for_testing,
542 Property(&protos::TestEvent::str, Eq("payload")))));
543}
544
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100545// Creates a tracing session where some of the data sources set the
546// |will_notify_on_stop| flag and checks that the OnTracingDisabled notification
547// to the consumer is delayed until the acks are received.
548TEST_F(TracingServiceImplTest, OnTracingDisabledWaitsForDataSourceStopAcks) {
549 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
550 consumer->Connect(svc.get());
551
552 std::unique_ptr<MockProducer> producer = CreateMockProducer();
553 producer->Connect(svc.get(), "mock_producer");
554 producer->RegisterDataSource("ds_will_ack_1", /*ack_stop=*/true);
555 producer->RegisterDataSource("ds_wont_ack");
556 producer->RegisterDataSource("ds_will_ack_2", /*ack_stop=*/true);
557
558 TraceConfig trace_config;
559 trace_config.add_buffers()->set_size_kb(128);
560 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack_1");
561 trace_config.add_data_sources()->mutable_config()->set_name("ds_wont_ack");
562 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack_2");
563 trace_config.set_duration_ms(1);
564
565 consumer->EnableTracing(trace_config);
566 producer->WaitForTracingSetup();
567 producer->WaitForDataSourceStart("ds_will_ack_1");
568 producer->WaitForDataSourceStart("ds_wont_ack");
569 producer->WaitForDataSourceStart("ds_will_ack_2");
570
571 std::unique_ptr<TraceWriter> writer =
572 producer->CreateTraceWriter("ds_wont_ack");
573 producer->WaitForFlush(writer.get());
574
575 DataSourceInstanceID id1 = producer->GetDataSourceInstanceId("ds_will_ack_1");
576 DataSourceInstanceID id2 = producer->GetDataSourceInstanceId("ds_will_ack_2");
577
578 producer->WaitForDataSourceStop("ds_will_ack_1");
579 producer->WaitForDataSourceStop("ds_wont_ack");
580 producer->WaitForDataSourceStop("ds_will_ack_2");
581
582 producer->endpoint()->NotifyDataSourceStopped(id1);
583 producer->endpoint()->NotifyDataSourceStopped(id2);
584
585 // Wait for at most half of the service timeout, so that this test fails if
586 // the service falls back on calling the OnTracingDisabled() because some of
587 // the expected acks weren't received.
588 consumer->WaitForTracingDisabled(
589 TracingServiceImpl::kDataSourceStopTimeoutMs / 2);
590}
591
Oystein Eftevaagf250e1c2018-08-23 16:10:52 -0700592// Creates a tracing session where a second data source
593// is added while the service is waiting for DisableTracing
594// acks; the service should not enable the new datasource
595// and should not hit any asserts when the consumer is
596// subsequently destroyed.
597TEST_F(TracingServiceImplTest, OnDataSourceAddedWhilePendingDisableAcks) {
598 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
599 consumer->Connect(svc.get());
600
601 std::unique_ptr<MockProducer> producer = CreateMockProducer();
602 producer->Connect(svc.get(), "mock_producer");
603 producer->RegisterDataSource("ds_will_ack", /*ack_stop=*/true);
604
605 TraceConfig trace_config;
606 trace_config.add_buffers()->set_size_kb(128);
607 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack");
608 trace_config.add_data_sources()->mutable_config()->set_name("ds_wont_ack");
609
610 consumer->EnableTracing(trace_config);
611 producer->WaitForTracingSetup();
612
613 consumer->DisableTracing();
614
615 producer->RegisterDataSource("ds_wont_ack");
616
617 consumer.reset();
618}
619
Primiano Tuccibaeecf12018-07-25 12:02:20 +0100620// Similar to OnTracingDisabledWaitsForDataSourceStopAcks, but deliberately
621// skips the ack and checks that the service invokes the OnTracingDisabled()
622// after the timeout.
623TEST_F(TracingServiceImplTest, OnTracingDisabledCalledAnywaysInCaseOfTimeout) {
624 svc->override_data_source_test_timeout_ms_for_testing = 1;
625 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
626 consumer->Connect(svc.get());
627
628 std::unique_ptr<MockProducer> producer = CreateMockProducer();
629 producer->Connect(svc.get(), "mock_producer");
630 producer->RegisterDataSource("data_source", /*ack_stop=*/true);
631
632 TraceConfig trace_config;
633 trace_config.add_buffers()->set_size_kb(128);
634 trace_config.add_data_sources()->mutable_config()->set_name("data_source");
635 trace_config.set_duration_ms(1);
636
637 consumer->EnableTracing(trace_config);
638 producer->WaitForTracingSetup();
639 producer->WaitForDataSourceStart("data_source");
640
641 std::unique_ptr<TraceWriter> writer =
642 producer->CreateTraceWriter("data_source");
643 producer->WaitForFlush(writer.get());
644
645 producer->WaitForDataSourceStop("data_source");
646 consumer->WaitForTracingDisabled();
647}
648
Primiano Tucci03de28f2018-08-01 11:29:46 +0100649// Tests the session_id logic. Two data sources in the same tracing session
650// should see the same session id.
651TEST_F(TracingServiceImplTest, SessionId) {
652 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
653 consumer->Connect(svc.get());
654
655 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
656 producer1->Connect(svc.get(), "mock_producer1");
657 producer1->RegisterDataSource("ds_1A");
658 producer1->RegisterDataSource("ds_1B");
659
660 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
661 producer2->Connect(svc.get(), "mock_producer2");
662 producer2->RegisterDataSource("ds_2A");
663
664 testing::InSequence seq;
665 TracingSessionID last_session_id = 0;
666 for (int i = 0; i < 3; i++) {
667 TraceConfig trace_config;
668 trace_config.add_buffers()->set_size_kb(128);
669 trace_config.add_data_sources()->mutable_config()->set_name("ds_1A");
670 trace_config.add_data_sources()->mutable_config()->set_name("ds_1B");
671 trace_config.add_data_sources()->mutable_config()->set_name("ds_2A");
672 trace_config.set_duration_ms(1);
673
674 consumer->EnableTracing(trace_config);
675
676 if (i == 0)
677 producer1->WaitForTracingSetup();
678 producer1->WaitForDataSourceStart("ds_1A");
679 producer1->WaitForDataSourceStart("ds_1B");
680
681 if (i == 0)
682 producer2->WaitForTracingSetup();
683 producer2->WaitForDataSourceStart("ds_2A");
684
685 auto* ds1 = producer1->GetDataSourceInstance("ds_1A");
686 auto* ds2 = producer1->GetDataSourceInstance("ds_1B");
687 auto* ds3 = producer2->GetDataSourceInstance("ds_2A");
688 ASSERT_EQ(ds1->session_id, ds2->session_id);
689 ASSERT_EQ(ds1->session_id, ds3->session_id);
690 ASSERT_NE(ds1->session_id, last_session_id);
691 last_session_id = ds1->session_id;
692
693 auto writer1 = producer1->CreateTraceWriter("ds_1A");
694 producer1->WaitForFlush(writer1.get());
695
696 auto writer2 = producer2->CreateTraceWriter("ds_2A");
697 producer2->WaitForFlush(writer2.get());
698
699 producer1->WaitForDataSourceStop("ds_1A");
700 producer1->WaitForDataSourceStop("ds_1B");
701 producer2->WaitForDataSourceStop("ds_2A");
702 consumer->WaitForTracingDisabled();
703 consumer->FreeBuffers();
704 }
705}
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100706
707// Writes a long trace and then tests that the trace parsed in partitions
708// derived by the synchronization markers is identical to the whole trace parsed
709// in one go.
710TEST_F(TracingServiceImplTest, ResynchronizeTraceStreamUsingSyncMarker) {
711 // Setup tracing.
712 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
713 consumer->Connect(svc.get());
714 std::unique_ptr<MockProducer> producer = CreateMockProducer();
715 producer->Connect(svc.get(), "mock_producer");
716 producer->RegisterDataSource("data_source");
717 TraceConfig trace_config;
718 trace_config.add_buffers()->set_size_kb(4096);
719 auto* ds_config = trace_config.add_data_sources()->mutable_config();
720 ds_config->set_name("data_source");
721 trace_config.set_write_into_file(true);
722 trace_config.set_file_write_period_ms(1);
723 base::TempFile tmp_file = base::TempFile::Create();
724 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
725 producer->WaitForTracingSetup();
726 producer->WaitForDataSourceStart("data_source");
727
728 // Write some variable length payload, waiting for sync markers every now
729 // and then.
730 const int kNumMarkers = 5;
731 auto writer = producer->CreateTraceWriter("data_source");
732 for (int i = 1; i <= 100; i++) {
733 std::string payload(i, 'A' + (i % 25));
734 writer->NewTracePacket()->set_for_testing()->set_str(payload.c_str());
735 if (i % (100 / kNumMarkers) == 0) {
736 writer->Flush();
737 WaitForNextSyncMarker();
738 }
739 }
740 writer->Flush();
741 writer.reset();
742 consumer->DisableTracing();
743 producer->WaitForDataSourceStop("data_source");
744 consumer->WaitForTracingDisabled();
745
746 std::string trace_raw;
747 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
748
749 const auto kMarkerSize = sizeof(TracingServiceImpl::kSyncMarker);
750 const std::string kSyncMarkerStr(
751 reinterpret_cast<const char*>(TracingServiceImpl::kSyncMarker),
752 kMarkerSize);
753
754 // Read back the trace in partitions derived from the marker.
755 // The trace should look like this:
756 // [uid, marker] [event] [event] [uid, marker] [event] [event]
757 size_t num_markers = 0;
758 size_t start = 0;
759 size_t end = 0;
760 protos::Trace merged_trace;
761 for (size_t pos = 0; pos != std::string::npos; start = end) {
762 pos = trace_raw.find(kSyncMarkerStr, pos + 1);
763 num_markers++;
764 end = (pos == std::string::npos) ? trace_raw.size() : pos + kMarkerSize;
765 int size = static_cast<int>(end - start);
766 ASSERT_GT(size, 0);
767 protos::Trace trace_partition;
768 ASSERT_TRUE(trace_partition.ParseFromArray(trace_raw.data() + start, size));
769 merged_trace.MergeFrom(trace_partition);
770 }
Lalit Maganti9bdc7ce2018-09-17 15:25:11 +0100771 EXPECT_GE(num_markers, static_cast<size_t>(kNumMarkers));
Primiano Tucci9754d0d2018-09-15 12:41:46 +0100772
773 protos::Trace whole_trace;
774 ASSERT_TRUE(whole_trace.ParseFromString(trace_raw));
775
776 ASSERT_EQ(whole_trace.packet_size(), merged_trace.packet_size());
777 EXPECT_EQ(whole_trace.SerializeAsString(), merged_trace.SerializeAsString());
778}
779
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000780} // namespace perfetto