blob: 59e42ac395b3507f0303ebf80130e446ab395904 [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
17#include "src/tracing/core/service_impl.h"
18
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 {
57constexpr size_t kDefaultShmSizeKb = ServiceImpl::kDefaultShmSize / 1024;
58constexpr size_t kMaxShmSizeKb = ServiceImpl::kMaxShmSize / 1024;
59} // namespace
60
Sami Kyostila06487a22018-02-27 13:48:38 +000061class ServiceImplTest : public testing::Test {
62 public:
63 ServiceImplTest() {
64 auto shm_factory =
65 std::unique_ptr<SharedMemory::Factory>(new TestSharedMemory::Factory());
66 svc.reset(static_cast<ServiceImpl*>(
67 Service::CreateInstance(std::move(shm_factory), &task_runner)
68 .release()));
69 }
70
Primiano Tuccidca727d2018-04-04 11:31:55 +020071 std::unique_ptr<MockProducer> CreateMockProducer() {
72 return std::unique_ptr<MockProducer>(
73 new StrictMock<MockProducer>(&task_runner));
74 }
75
76 std::unique_ptr<MockConsumer> CreateMockConsumer() {
77 return std::unique_ptr<MockConsumer>(
78 new StrictMock<MockConsumer>(&task_runner));
79 }
80
Primiano Tucci1a1951d2018-04-04 21:08:16 +020081 ProducerID* last_producer_id() { return &svc->last_producer_id_; }
82
83 uid_t GetProducerUid(ProducerID producer_id) {
84 return svc->GetProducer(producer_id)->uid_;
85 }
86
Primiano Tuccid52e6272018-04-06 19:06:53 +020087 size_t GetNumPendingFlushes() {
88 ServiceImpl::TracingSession* tracing_session =
89 svc->GetTracingSession(svc->last_tracing_session_id_);
90 EXPECT_NE(nullptr, tracing_session);
91 return tracing_session->pending_flushes.size();
92 }
93
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000094 base::TestTaskRunner task_runner;
Sami Kyostila06487a22018-02-27 13:48:38 +000095 std::unique_ptr<ServiceImpl> svc;
96};
97
98TEST_F(ServiceImplTest, RegisterAndUnregister) {
Primiano Tuccidca727d2018-04-04 11:31:55 +020099 std::unique_ptr<MockProducer> mock_producer_1 = CreateMockProducer();
100 std::unique_ptr<MockProducer> mock_producer_2 = CreateMockProducer();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000101
Primiano Tuccidca727d2018-04-04 11:31:55 +0200102 mock_producer_1->Connect(svc.get(), "mock_producer_1", 123u /* uid */);
103 mock_producer_2->Connect(svc.get(), "mock_producer_2", 456u /* uid */);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000104
105 ASSERT_EQ(2u, svc->num_producers());
Primiano Tuccidca727d2018-04-04 11:31:55 +0200106 ASSERT_EQ(mock_producer_1->endpoint(), svc->GetProducer(1));
107 ASSERT_EQ(mock_producer_2->endpoint(), svc->GetProducer(2));
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200108 ASSERT_EQ(123u, GetProducerUid(1));
109 ASSERT_EQ(456u, GetProducerUid(2));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000110
Primiano Tuccidca727d2018-04-04 11:31:55 +0200111 mock_producer_1->RegisterDataSource("foo");
112 mock_producer_2->RegisterDataSource("bar");
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000113
Primiano Tuccidca727d2018-04-04 11:31:55 +0200114 mock_producer_1->UnregisterDataSource("foo");
115 mock_producer_2->UnregisterDataSource("bar");
Primiano Tucci9daa4832018-03-28 23:28:17 +0100116
Primiano Tuccidca727d2018-04-04 11:31:55 +0200117 mock_producer_1.reset();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000118 ASSERT_EQ(1u, svc->num_producers());
119 ASSERT_EQ(nullptr, svc->GetProducer(1));
120
Primiano Tuccidca727d2018-04-04 11:31:55 +0200121 mock_producer_2.reset();
122 ASSERT_EQ(nullptr, svc->GetProducer(2));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000123
124 ASSERT_EQ(0u, svc->num_producers());
125}
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100126
Sami Kyostila06487a22018-02-27 13:48:38 +0000127TEST_F(ServiceImplTest, EnableAndDisableTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200128 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
129 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000130
Primiano Tuccidca727d2018-04-04 11:31:55 +0200131 std::unique_ptr<MockProducer> producer = CreateMockProducer();
132 producer->Connect(svc.get(), "mock_producer");
133 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000134
Sami Kyostila06487a22018-02-27 13:48:38 +0000135 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200136 trace_config.add_buffers()->set_size_kb(128);
Sami Kyostila06487a22018-02-27 13:48:38 +0000137 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200138 ds_config->set_name("data_source");
139 consumer->EnableTracing(trace_config);
Sami Kyostila06487a22018-02-27 13:48:38 +0000140
Primiano Tuccidca727d2018-04-04 11:31:55 +0200141 producer->WaitForTracingSetup();
142 producer->WaitForDataSourceStart("data_source");
143
144 consumer->DisableTracing();
145 producer->WaitForDataSourceStop("data_source");
146 consumer->WaitForTracingDisabled();
Sami Kyostila06487a22018-02-27 13:48:38 +0000147}
148
Florian Mayer61c55482018-03-06 14:43:54 +0000149TEST_F(ServiceImplTest, LockdownMode) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200150 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
151 consumer->Connect(svc.get());
152
153 std::unique_ptr<MockProducer> producer = CreateMockProducer();
154 producer->Connect(svc.get(), "mock_producer_sameuid", geteuid());
155 producer->RegisterDataSource("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000156
157 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200158 trace_config.add_buffers()->set_size_kb(128);
159 auto* ds_config = trace_config.add_data_sources()->mutable_config();
160 ds_config->set_name("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000161 trace_config.set_lockdown_mode(
162 TraceConfig::LockdownModeOperation::LOCKDOWN_SET);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200163 consumer->EnableTracing(trace_config);
164
165 producer->WaitForTracingSetup();
166 producer->WaitForDataSourceStart("data_source");
167
168 std::unique_ptr<MockProducer> producer_otheruid = CreateMockProducer();
169 auto x = svc->ConnectProducer(producer_otheruid.get(), geteuid() + 1,
170 "mock_producer_ouid");
171 EXPECT_CALL(*producer_otheruid, OnConnect()).Times(0);
Florian Mayer61c55482018-03-06 14:43:54 +0000172 task_runner.RunUntilIdle();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200173 Mock::VerifyAndClearExpectations(producer_otheruid.get());
Florian Mayer61c55482018-03-06 14:43:54 +0000174
Primiano Tuccidca727d2018-04-04 11:31:55 +0200175 consumer->DisableTracing();
176 consumer->FreeBuffers();
177 producer->WaitForDataSourceStop("data_source");
178 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000179
180 trace_config.set_lockdown_mode(
181 TraceConfig::LockdownModeOperation::LOCKDOWN_CLEAR);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200182 consumer->EnableTracing(trace_config);
183 producer->WaitForDataSourceStart("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000184
Primiano Tuccidca727d2018-04-04 11:31:55 +0200185 std::unique_ptr<MockProducer> producer_otheruid2 = CreateMockProducer();
186 producer_otheruid->Connect(svc.get(), "mock_producer_ouid2", geteuid() + 1);
Florian Mayer61c55482018-03-06 14:43:54 +0000187
Primiano Tuccidca727d2018-04-04 11:31:55 +0200188 consumer->DisableTracing();
189 producer->WaitForDataSourceStop("data_source");
190 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000191}
192
Sami Kyostila06487a22018-02-27 13:48:38 +0000193TEST_F(ServiceImplTest, DisconnectConsumerWhileTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200194 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
195 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000196
Primiano Tuccidca727d2018-04-04 11:31:55 +0200197 std::unique_ptr<MockProducer> producer = CreateMockProducer();
198 producer->Connect(svc.get(), "mock_producer");
199 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000200
Primiano Tuccidca727d2018-04-04 11:31:55 +0200201 TraceConfig trace_config;
202 trace_config.add_buffers()->set_size_kb(128);
203 auto* ds_config = trace_config.add_data_sources()->mutable_config();
204 ds_config->set_name("data_source");
205 consumer->EnableTracing(trace_config);
206
207 producer->WaitForTracingSetup();
208 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000209
210 // Disconnecting the consumer while tracing should trigger data source
211 // teardown.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200212 consumer.reset();
213 producer->WaitForDataSourceStop("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000214}
215
216TEST_F(ServiceImplTest, ReconnectProducerWhileTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200217 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
218 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000219
Primiano Tuccidca727d2018-04-04 11:31:55 +0200220 std::unique_ptr<MockProducer> producer = CreateMockProducer();
221 producer->Connect(svc.get(), "mock_producer");
222 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000223
Sami Kyostila06487a22018-02-27 13:48:38 +0000224 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200225 trace_config.add_buffers()->set_size_kb(128);
Sami Kyostila06487a22018-02-27 13:48:38 +0000226 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200227 ds_config->set_name("data_source");
228 consumer->EnableTracing(trace_config);
Sami Kyostila06487a22018-02-27 13:48:38 +0000229
Primiano Tuccidca727d2018-04-04 11:31:55 +0200230 producer->WaitForTracingSetup();
231 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000232
Primiano Tuccidca727d2018-04-04 11:31:55 +0200233 // Disconnecting and reconnecting a producer with a matching data source.
234 // The Producer should see that data source getting enabled again.
235 producer.reset();
236 producer = CreateMockProducer();
237 producer->Connect(svc.get(), "mock_producer_2");
238 producer->RegisterDataSource("data_source");
239 producer->WaitForTracingSetup();
240 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000241}
242
Primiano Tucci081d46a2018-02-28 11:09:43 +0000243TEST_F(ServiceImplTest, ProducerIDWrapping) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200244 std::vector<std::unique_ptr<MockProducer>> producers;
245 producers.push_back(nullptr);
Primiano Tucci081d46a2018-02-28 11:09:43 +0000246
Primiano Tuccidca727d2018-04-04 11:31:55 +0200247 auto connect_producer_and_get_id = [&producers,
248 this](const std::string& name) {
249 producers.emplace_back(CreateMockProducer());
250 producers.back()->Connect(svc.get(), "mock_producer_" + name);
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200251 return *last_producer_id();
Primiano Tucci081d46a2018-02-28 11:09:43 +0000252 };
253
254 // Connect producers 1-4.
255 for (ProducerID i = 1; i <= 4; i++)
Primiano Tuccidca727d2018-04-04 11:31:55 +0200256 ASSERT_EQ(i, connect_producer_and_get_id(std::to_string(i)));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000257
258 // Disconnect producers 1,3.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200259 producers[1].reset();
260 producers[3].reset();
Primiano Tucci081d46a2018-02-28 11:09:43 +0000261
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200262 *last_producer_id() = kMaxProducerID - 1;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200263 ASSERT_EQ(kMaxProducerID, connect_producer_and_get_id("maxid"));
264 ASSERT_EQ(1u, connect_producer_and_get_id("1_again"));
265 ASSERT_EQ(3u, connect_producer_and_get_id("3_again"));
266 ASSERT_EQ(5u, connect_producer_and_get_id("5"));
267 ASSERT_EQ(6u, connect_producer_and_get_id("6"));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000268}
269
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100270TEST_F(ServiceImplTest, WriteIntoFileAndStopOnMaxSize) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200271 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
272 consumer->Connect(svc.get());
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100273
Primiano Tuccidca727d2018-04-04 11:31:55 +0200274 std::unique_ptr<MockProducer> producer = CreateMockProducer();
275 producer->Connect(svc.get(), "mock_producer");
276 producer->RegisterDataSource("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100277
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100278 TraceConfig trace_config;
279 trace_config.add_buffers()->set_size_kb(4096);
280 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200281 ds_config->set_name("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100282 ds_config->set_target_buffer(0);
283 trace_config.set_write_into_file(true);
284 trace_config.set_file_write_period_ms(1);
285 const uint64_t kMaxFileSize = 512;
286 trace_config.set_max_file_size_bytes(kMaxFileSize);
287 base::TempFile tmp_file = base::TempFile::Create();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200288 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
289
290 producer->WaitForTracingSetup();
291 producer->WaitForDataSourceStart("data_source");
292
293 static const char kPayload[] = "1234567890abcdef-";
294 static const int kNumPackets = 10;
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100295
296 std::unique_ptr<TraceWriter> writer =
Primiano Tuccidca727d2018-04-04 11:31:55 +0200297 producer->CreateTraceWriter("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100298 // All these packets should fit within kMaxFileSize.
299 for (int i = 0; i < kNumPackets; i++) {
300 auto tp = writer->NewTracePacket();
301 std::string payload(kPayload);
302 payload.append(std::to_string(i));
303 tp->set_for_testing()->set_str(payload.c_str(), payload.size());
304 }
305
306 // Finally add a packet that overflows kMaxFileSize. This should cause the
307 // implicit stop of the trace and should *not* be written in the trace.
308 {
309 auto tp = writer->NewTracePacket();
310 char big_payload[kMaxFileSize] = "BIG!";
311 tp->set_for_testing()->set_str(big_payload, sizeof(big_payload));
312 }
313 writer->Flush();
314 writer.reset();
315
Primiano Tuccidca727d2018-04-04 11:31:55 +0200316 consumer->DisableTracing();
317 producer->WaitForDataSourceStop("data_source");
318 consumer->WaitForTracingDisabled();
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100319
320 // Verify the contents of the file.
321 std::string trace_raw;
322 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
323 protos::Trace trace;
324 ASSERT_TRUE(trace.ParseFromString(trace_raw));
325 ASSERT_GE(trace.packet_size(), kNumPackets);
326 int num_testing_packet = 0;
327 for (int i = 0; i < trace.packet_size(); i++) {
328 const protos::TracePacket& tp = trace.packet(i);
329 if (!tp.has_for_testing())
330 continue;
331 ASSERT_EQ(kPayload + std::to_string(num_testing_packet++),
332 tp.for_testing().str());
333 }
Primiano Tuccidca727d2018-04-04 11:31:55 +0200334}
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100335
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200336// Test the logic that allows the trace config to set the shm total size and
337// page size from the trace config. Also check that, if the config doesn't
338// specify a value we fall back on the hint provided by the producer.
339TEST_F(ServiceImplTest, ProducerShmAndPageSizeOverriddenByTraceConfig) {
340 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
341 consumer->Connect(svc.get());
342 const size_t kConfigPageSizesKb[] = /****/ {16, 16, 4, 0, 16, 8, 3, 4096, 4};
343 const size_t kExpectedPageSizesKb[] = /**/ {16, 16, 4, 4, 16, 8, 4, 64, 4};
344
345 const size_t kConfigSizesKb[] = /**/ {0, 16, 0, 20, 32, 7, 0, 96, 4096000};
346 const size_t kHintSizesKb[] = /****/ {0, 0, 16, 32, 16, 0, 7, 96, 4096000};
347 const size_t kExpectedSizesKb[] = {
348 kDefaultShmSizeKb, // Both hint and config are 0, use default.
349 16, // Hint is 0, use config.
350 16, // Config is 0, use hint.
351 20, // Hint is takes precedence over the config.
352 32, // Ditto, even if config is higher than hint.
353 kDefaultShmSizeKb, // Config is invalid and hint is 0, use default.
354 kDefaultShmSizeKb, // Config is 0 and hint is invalid, use default.
355 kDefaultShmSizeKb, // 96 KB isn't a multiple of the page size (64 KB).
356 kMaxShmSizeKb // Too big, cap at kMaxShmSize.
357 };
358
359 const size_t kNumProducers = base::ArraySize(kHintSizesKb);
360 std::unique_ptr<MockProducer> producer[kNumProducers];
361 for (size_t i = 0; i < kNumProducers; i++) {
362 auto name = "mock_producer_" + std::to_string(i);
363 producer[i] = CreateMockProducer();
364 producer[i]->Connect(svc.get(), name, geteuid(), kHintSizesKb[i] * 1024);
365 producer[i]->RegisterDataSource("data_source");
366 }
367
368 TraceConfig trace_config;
369 trace_config.add_buffers()->set_size_kb(128);
370 auto* ds_config = trace_config.add_data_sources()->mutable_config();
371 ds_config->set_name("data_source");
372 for (size_t i = 0; i < kNumProducers; i++) {
373 auto* producer_config = trace_config.add_producers();
374 producer_config->set_producer_name("mock_producer_" + std::to_string(i));
Primiano Tucci3cbb10a2018-04-10 17:52:40 +0100375 producer_config->set_shm_size_kb(static_cast<uint32_t>(kConfigSizesKb[i]));
376 producer_config->set_page_size_kb(
377 static_cast<uint32_t>(kConfigPageSizesKb[i]));
Primiano Tucci1a1951d2018-04-04 21:08:16 +0200378 }
379
380 consumer->EnableTracing(trace_config);
381 size_t actual_shm_sizes_kb[kNumProducers]{};
382 size_t actual_page_sizes_kb[kNumProducers]{};
383 for (size_t i = 0; i < kNumProducers; i++) {
384 producer[i]->WaitForTracingSetup();
385 producer[i]->WaitForDataSourceStart("data_source");
386 actual_shm_sizes_kb[i] =
387 producer[i]->endpoint()->shared_memory()->size() / 1024;
388 actual_page_sizes_kb[i] =
389 producer[i]->endpoint()->shared_buffer_page_size_kb();
390 }
391 ASSERT_THAT(actual_page_sizes_kb, ElementsAreArray(kExpectedPageSizesKb));
392 ASSERT_THAT(actual_shm_sizes_kb, ElementsAreArray(kExpectedSizesKb));
393}
394
Primiano Tuccid52e6272018-04-06 19:06:53 +0200395TEST_F(ServiceImplTest, ExplicitFlush) {
396 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
397 consumer->Connect(svc.get());
398
399 std::unique_ptr<MockProducer> producer = CreateMockProducer();
400 producer->Connect(svc.get(), "mock_producer");
401 producer->RegisterDataSource("data_source");
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
408 consumer->EnableTracing(trace_config);
409 producer->WaitForTracingSetup();
410 producer->WaitForDataSourceStart("data_source");
411
412 std::unique_ptr<TraceWriter> writer =
413 producer->CreateTraceWriter("data_source");
414 {
415 auto tp = writer->NewTracePacket();
416 tp->set_for_testing()->set_str("payload");
417 }
418
419 auto flush_request = consumer->Flush();
420 producer->WaitForFlush(writer.get());
421 ASSERT_TRUE(flush_request.WaitForReply());
422
423 consumer->DisableTracing();
424 producer->WaitForDataSourceStop("data_source");
425 consumer->WaitForTracingDisabled();
426 EXPECT_THAT(
427 consumer->ReadBuffers(),
428 Contains(Property(&protos::TracePacket::for_testing,
429 Property(&protos::TestEvent::str, Eq("payload")))));
430}
431
432TEST_F(ServiceImplTest, ImplicitFlushOnTimedTraces) {
433 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
434 consumer->Connect(svc.get());
435
436 std::unique_ptr<MockProducer> producer = CreateMockProducer();
437 producer->Connect(svc.get(), "mock_producer");
438 producer->RegisterDataSource("data_source");
439
440 TraceConfig trace_config;
441 trace_config.add_buffers()->set_size_kb(128);
442 auto* ds_config = trace_config.add_data_sources()->mutable_config();
443 ds_config->set_name("data_source");
444 trace_config.set_duration_ms(1);
445
446 consumer->EnableTracing(trace_config);
447 producer->WaitForTracingSetup();
448 producer->WaitForDataSourceStart("data_source");
449
450 std::unique_ptr<TraceWriter> writer =
451 producer->CreateTraceWriter("data_source");
452 {
453 auto tp = writer->NewTracePacket();
454 tp->set_for_testing()->set_str("payload");
455 }
456
457 producer->WaitForFlush(writer.get());
458
459 producer->WaitForDataSourceStop("data_source");
460 consumer->WaitForTracingDisabled();
461
462 EXPECT_THAT(
463 consumer->ReadBuffers(),
464 Contains(Property(&protos::TracePacket::for_testing,
465 Property(&protos::TestEvent::str, Eq("payload")))));
466}
467
468// Tests the monotonic semantic of flush request IDs, i.e., once a producer
469// acks flush request N, all flush requests <= N are considered successful and
470// acked to the consumer.
471TEST_F(ServiceImplTest, BatchFlushes) {
472 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
484 consumer->EnableTracing(trace_config);
485 producer->WaitForTracingSetup();
486 producer->WaitForDataSourceStart("data_source");
487
488 std::unique_ptr<TraceWriter> writer =
489 producer->CreateTraceWriter("data_source");
490 {
491 auto tp = writer->NewTracePacket();
492 tp->set_for_testing()->set_str("payload");
493 }
494
495 auto flush_req_1 = consumer->Flush();
496 auto flush_req_2 = consumer->Flush();
497 auto flush_req_3 = consumer->Flush();
498
499 // We'll deliberately let the 4th flush request timeout. Use a lower timeout
500 // to keep test time short.
501 auto flush_req_4 = consumer->Flush(/*timeout_ms=*/10);
502 ASSERT_EQ(4u, GetNumPendingFlushes());
503
504 // Make the producer reply only to the 3rd flush request.
505 testing::InSequence seq;
506 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 1.
507 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 2.
508 producer->WaitForFlush(writer.get()); // Will reply only to flush id == 3.
509 producer->WaitForFlush(nullptr); // Will NOT reply to flush id == 4.
510
511 // Even if the producer explicily replied only to flush ID == 3, all the
512 // previous flushed < 3 should be implicitly acked.
513 ASSERT_TRUE(flush_req_1.WaitForReply());
514 ASSERT_TRUE(flush_req_2.WaitForReply());
515 ASSERT_TRUE(flush_req_3.WaitForReply());
516
517 // At this point flush id == 4 should still be pending and should fail because
518 // of reaching its timeout.
Primiano Tuccid52e6272018-04-06 19:06:53 +0200519 ASSERT_FALSE(flush_req_4.WaitForReply());
520
521 consumer->DisableTracing();
522 producer->WaitForDataSourceStop("data_source");
523 consumer->WaitForTracingDisabled();
524 EXPECT_THAT(
525 consumer->ReadBuffers(),
526 Contains(Property(&protos::TracePacket::for_testing,
527 Property(&protos::TestEvent::str, Eq("payload")))));
528}
529
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000530} // namespace perfetto