blob: 043eae2b64a001ae94403cb0b63af8e52c6f3971 [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"
Sami Kyostila06487a22018-02-27 13:48:38 +000023#include "perfetto/tracing/core/consumer.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000024#include "perfetto/tracing/core/data_source_config.h"
25#include "perfetto/tracing/core/data_source_descriptor.h"
26#include "perfetto/tracing/core/producer.h"
27#include "perfetto/tracing/core/shared_memory.h"
Sami Kyostila06487a22018-02-27 13:48:38 +000028#include "perfetto/tracing/core/trace_packet.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000029#include "src/base/test/test_task_runner.h"
30#include "src/tracing/test/test_shared_memory.h"
31
32namespace perfetto {
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000033using ::testing::_;
34using ::testing::InSequence;
Primiano Tucci081d46a2018-02-28 11:09:43 +000035using ::testing::Invoke;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000036using ::testing::Mock;
37
Sami Kyostila32e0b542018-02-14 08:55:43 +000038namespace {
39
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000040class MockProducer : public Producer {
41 public:
42 ~MockProducer() override {}
43
44 // Producer implementation.
45 MOCK_METHOD0(OnConnect, void());
46 MOCK_METHOD0(OnDisconnect, void());
47 MOCK_METHOD2(CreateDataSourceInstance,
48 void(DataSourceInstanceID, const DataSourceConfig&));
49 MOCK_METHOD1(TearDownDataSourceInstance, void(DataSourceInstanceID));
50};
51
Sami Kyostila06487a22018-02-27 13:48:38 +000052class MockConsumer : public Consumer {
53 public:
54 ~MockConsumer() override {}
55
56 // Consumer implementation.
57 MOCK_METHOD0(OnConnect, void());
58 MOCK_METHOD0(OnDisconnect, void());
59
60 void OnTraceData(std::vector<TracePacket> packets, bool has_more) override {}
61};
62
Sami Kyostila32e0b542018-02-14 08:55:43 +000063} // namespace
64
Sami Kyostila06487a22018-02-27 13:48:38 +000065class ServiceImplTest : public testing::Test {
66 public:
67 ServiceImplTest() {
68 auto shm_factory =
69 std::unique_ptr<SharedMemory::Factory>(new TestSharedMemory::Factory());
70 svc.reset(static_cast<ServiceImpl*>(
71 Service::CreateInstance(std::move(shm_factory), &task_runner)
72 .release()));
73 }
74
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000075 base::TestTaskRunner task_runner;
Sami Kyostila06487a22018-02-27 13:48:38 +000076 std::unique_ptr<ServiceImpl> svc;
77};
78
79TEST_F(ServiceImplTest, RegisterAndUnregister) {
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000080 MockProducer mock_producer_1;
81 MockProducer mock_producer_2;
82 std::unique_ptr<Service::ProducerEndpoint> producer_endpoint_1 =
Sami Kyostila32e0b542018-02-14 08:55:43 +000083 svc->ConnectProducer(&mock_producer_1, 123u /* uid */);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000084 std::unique_ptr<Service::ProducerEndpoint> producer_endpoint_2 =
Sami Kyostila32e0b542018-02-14 08:55:43 +000085 svc->ConnectProducer(&mock_producer_2, 456u /* uid */);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000086
87 ASSERT_TRUE(producer_endpoint_1);
88 ASSERT_TRUE(producer_endpoint_2);
89
90 InSequence seq;
91 EXPECT_CALL(mock_producer_1, OnConnect());
92 EXPECT_CALL(mock_producer_2, OnConnect());
93 task_runner.RunUntilIdle();
94
95 ASSERT_EQ(2u, svc->num_producers());
96 ASSERT_EQ(producer_endpoint_1.get(), svc->GetProducer(1));
97 ASSERT_EQ(producer_endpoint_2.get(), svc->GetProducer(2));
Sami Kyostila32e0b542018-02-14 08:55:43 +000098 ASSERT_EQ(123u, svc->GetProducer(1)->uid_);
99 ASSERT_EQ(456u, svc->GetProducer(2)->uid_);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000100
Primiano Tucci114b6492017-12-11 23:09:45 +0000101 DataSourceDescriptor ds_desc1;
102 ds_desc1.set_name("foo");
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000103 producer_endpoint_1->RegisterDataSource(
Sami Kyostila06487a22018-02-27 13:48:38 +0000104 ds_desc1, [this, &producer_endpoint_1](DataSourceID id) {
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000105 EXPECT_EQ(1u, id);
106 task_runner.PostTask(
107 std::bind(&Service::ProducerEndpoint::UnregisterDataSource,
108 producer_endpoint_1.get(), id));
109 });
110
Primiano Tucci114b6492017-12-11 23:09:45 +0000111 DataSourceDescriptor ds_desc2;
112 ds_desc2.set_name("bar");
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000113 producer_endpoint_2->RegisterDataSource(
Sami Kyostila06487a22018-02-27 13:48:38 +0000114 ds_desc2, [this, &producer_endpoint_2](DataSourceID id) {
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000115 EXPECT_EQ(1u, id);
116 task_runner.PostTask(
117 std::bind(&Service::ProducerEndpoint::UnregisterDataSource,
118 producer_endpoint_2.get(), id));
119 });
120
121 task_runner.RunUntilIdle();
122
123 EXPECT_CALL(mock_producer_1, OnDisconnect());
124 producer_endpoint_1.reset();
125 task_runner.RunUntilIdle();
126 Mock::VerifyAndClearExpectations(&mock_producer_1);
127
128 ASSERT_EQ(1u, svc->num_producers());
129 ASSERT_EQ(nullptr, svc->GetProducer(1));
130
131 EXPECT_CALL(mock_producer_2, OnDisconnect());
132 producer_endpoint_2.reset();
133 task_runner.RunUntilIdle();
134 Mock::VerifyAndClearExpectations(&mock_producer_2);
135
136 ASSERT_EQ(0u, svc->num_producers());
137}
Sami Kyostila06487a22018-02-27 13:48:38 +0000138TEST_F(ServiceImplTest, EnableAndDisableTracing) {
139 MockProducer mock_producer;
140 std::unique_ptr<Service::ProducerEndpoint> producer_endpoint =
141 svc->ConnectProducer(&mock_producer, 123u /* uid */);
142 MockConsumer mock_consumer;
143 std::unique_ptr<Service::ConsumerEndpoint> consumer_endpoint =
144 svc->ConnectConsumer(&mock_consumer);
145
146 InSequence seq;
147 EXPECT_CALL(mock_producer, OnConnect());
148 EXPECT_CALL(mock_consumer, OnConnect());
149 task_runner.RunUntilIdle();
150
151 DataSourceDescriptor ds_desc;
152 ds_desc.set_name("foo");
153 producer_endpoint->RegisterDataSource(ds_desc, [](DataSourceID) {});
154
155 task_runner.RunUntilIdle();
156
157 EXPECT_CALL(mock_producer, CreateDataSourceInstance(_, _));
158 EXPECT_CALL(mock_producer, TearDownDataSourceInstance(_));
159 TraceConfig trace_config;
160 trace_config.add_buffers()->set_size_kb(4096 * 10);
161 auto* ds_config = trace_config.add_data_sources()->mutable_config();
162 ds_config->set_name("foo");
163 ds_config->set_target_buffer(0);
164 consumer_endpoint->EnableTracing(trace_config);
165 task_runner.RunUntilIdle();
166
167 EXPECT_CALL(mock_producer, OnDisconnect());
168 EXPECT_CALL(mock_consumer, OnDisconnect());
169 consumer_endpoint->DisableTracing();
170 producer_endpoint.reset();
171 consumer_endpoint.reset();
172 task_runner.RunUntilIdle();
173 Mock::VerifyAndClearExpectations(&mock_producer);
174 Mock::VerifyAndClearExpectations(&mock_consumer);
175}
176
Florian Mayer61c55482018-03-06 14:43:54 +0000177TEST_F(ServiceImplTest, LockdownMode) {
178 MockConsumer mock_consumer;
179 EXPECT_CALL(mock_consumer, OnConnect());
180 std::unique_ptr<Service::ConsumerEndpoint> consumer_endpoint =
181 svc->ConnectConsumer(&mock_consumer);
182
183 TraceConfig trace_config;
184 trace_config.set_lockdown_mode(
185 TraceConfig::LockdownModeOperation::LOCKDOWN_SET);
186 consumer_endpoint->EnableTracing(trace_config);
187 task_runner.RunUntilIdle();
188
189 InSequence seq;
190
191 MockProducer mock_producer;
192 std::unique_ptr<Service::ProducerEndpoint> producer_endpoint =
193 svc->ConnectProducer(&mock_producer, geteuid() + 1 /* uid */);
194
195 MockProducer mock_producer_sameuid;
196 std::unique_ptr<Service::ProducerEndpoint> producer_endpoint_sameuid =
197 svc->ConnectProducer(&mock_producer_sameuid, geteuid() /* uid */);
198
199 EXPECT_CALL(mock_producer, OnConnect()).Times(0);
200 EXPECT_CALL(mock_producer_sameuid, OnConnect());
201 task_runner.RunUntilIdle();
202
203 Mock::VerifyAndClearExpectations(&mock_producer);
204
205 consumer_endpoint->DisableTracing();
206 task_runner.RunUntilIdle();
207
208 trace_config.set_lockdown_mode(
209 TraceConfig::LockdownModeOperation::LOCKDOWN_CLEAR);
210 consumer_endpoint->EnableTracing(trace_config);
211 task_runner.RunUntilIdle();
212
213 EXPECT_CALL(mock_producer, OnConnect());
214 producer_endpoint_sameuid =
215 svc->ConnectProducer(&mock_producer, geteuid() + 1);
216
217 task_runner.RunUntilIdle();
218}
219
Sami Kyostila06487a22018-02-27 13:48:38 +0000220TEST_F(ServiceImplTest, DisconnectConsumerWhileTracing) {
221 MockProducer mock_producer;
222 std::unique_ptr<Service::ProducerEndpoint> producer_endpoint =
223 svc->ConnectProducer(&mock_producer, 123u /* uid */);
224 MockConsumer mock_consumer;
225 std::unique_ptr<Service::ConsumerEndpoint> consumer_endpoint =
226 svc->ConnectConsumer(&mock_consumer);
227
228 InSequence seq;
229 EXPECT_CALL(mock_producer, OnConnect());
230 EXPECT_CALL(mock_consumer, OnConnect());
231 task_runner.RunUntilIdle();
232
233 DataSourceDescriptor ds_desc;
234 ds_desc.set_name("foo");
235 producer_endpoint->RegisterDataSource(ds_desc, [](DataSourceID) {});
236 task_runner.RunUntilIdle();
237
238 // Disconnecting the consumer while tracing should trigger data source
239 // teardown.
240 EXPECT_CALL(mock_producer, CreateDataSourceInstance(_, _));
241 EXPECT_CALL(mock_producer, TearDownDataSourceInstance(_));
242 TraceConfig trace_config;
243 trace_config.add_buffers()->set_size_kb(4096 * 10);
244 auto* ds_config = trace_config.add_data_sources()->mutable_config();
245 ds_config->set_name("foo");
246 ds_config->set_target_buffer(0);
247 consumer_endpoint->EnableTracing(trace_config);
248 task_runner.RunUntilIdle();
249
250 EXPECT_CALL(mock_consumer, OnDisconnect());
251 consumer_endpoint.reset();
252 task_runner.RunUntilIdle();
253
254 EXPECT_CALL(mock_producer, OnDisconnect());
255 producer_endpoint.reset();
256 Mock::VerifyAndClearExpectations(&mock_producer);
257 Mock::VerifyAndClearExpectations(&mock_consumer);
258}
259
260TEST_F(ServiceImplTest, ReconnectProducerWhileTracing) {
261 MockProducer mock_producer;
262 std::unique_ptr<Service::ProducerEndpoint> producer_endpoint =
263 svc->ConnectProducer(&mock_producer, 123u /* uid */);
264 MockConsumer mock_consumer;
265 std::unique_ptr<Service::ConsumerEndpoint> consumer_endpoint =
266 svc->ConnectConsumer(&mock_consumer);
267
268 InSequence seq;
269 EXPECT_CALL(mock_producer, OnConnect());
270 EXPECT_CALL(mock_consumer, OnConnect());
271 task_runner.RunUntilIdle();
272
273 DataSourceDescriptor ds_desc;
274 ds_desc.set_name("foo");
275 producer_endpoint->RegisterDataSource(ds_desc, [](DataSourceID) {});
276 task_runner.RunUntilIdle();
277
278 // Disconnecting the producer while tracing should trigger data source
279 // teardown.
280 EXPECT_CALL(mock_producer, CreateDataSourceInstance(_, _));
281 EXPECT_CALL(mock_producer, TearDownDataSourceInstance(_));
282 EXPECT_CALL(mock_producer, OnDisconnect());
283 TraceConfig trace_config;
284 trace_config.add_buffers()->set_size_kb(4096 * 10);
285 auto* ds_config = trace_config.add_data_sources()->mutable_config();
286 ds_config->set_name("foo");
287 ds_config->set_target_buffer(0);
288 consumer_endpoint->EnableTracing(trace_config);
289 producer_endpoint.reset();
290 task_runner.RunUntilIdle();
291
292 // Reconnecting a producer with a matching data source should see that data
293 // source getting enabled.
294 EXPECT_CALL(mock_producer, OnConnect());
295 producer_endpoint = svc->ConnectProducer(&mock_producer, 123u /* uid */);
296 task_runner.RunUntilIdle();
297 EXPECT_CALL(mock_producer, CreateDataSourceInstance(_, _));
298 EXPECT_CALL(mock_producer, TearDownDataSourceInstance(_));
299 producer_endpoint->RegisterDataSource(ds_desc, [](DataSourceID) {});
300 task_runner.RunUntilIdle();
301
302 EXPECT_CALL(mock_consumer, OnDisconnect());
303 consumer_endpoint->DisableTracing();
304 consumer_endpoint.reset();
305 task_runner.RunUntilIdle();
306
307 EXPECT_CALL(mock_producer, OnDisconnect());
308 producer_endpoint.reset();
309 Mock::VerifyAndClearExpectations(&mock_producer);
310 Mock::VerifyAndClearExpectations(&mock_consumer);
311}
312
Primiano Tucci081d46a2018-02-28 11:09:43 +0000313TEST_F(ServiceImplTest, ProducerIDWrapping) {
314 base::TestTaskRunner task_runner;
315 auto shm_factory =
316 std::unique_ptr<SharedMemory::Factory>(new TestSharedMemory::Factory());
317 std::unique_ptr<ServiceImpl> svc(static_cast<ServiceImpl*>(
318 Service::CreateInstance(std::move(shm_factory), &task_runner).release()));
319
320 std::map<ProducerID, std::pair<std::unique_ptr<MockProducer>,
321 std::unique_ptr<Service::ProducerEndpoint>>>
322 producers;
323
324 auto ConnectProducerAndWait = [&task_runner, &svc, &producers]() {
325 char checkpoint_name[32];
326 static int checkpoint_num = 0;
327 sprintf(checkpoint_name, "on_connect_%d", checkpoint_num++);
328 auto on_connect = task_runner.CreateCheckpoint(checkpoint_name);
329 std::unique_ptr<MockProducer> producer(new MockProducer());
330 std::unique_ptr<Service::ProducerEndpoint> producer_endpoint =
331 svc->ConnectProducer(producer.get(), 123u /* uid */);
332 EXPECT_CALL(*producer, OnConnect()).WillOnce(Invoke(on_connect));
333 task_runner.RunUntilCheckpoint(checkpoint_name);
334 EXPECT_EQ(&*producer_endpoint, svc->GetProducer(svc->last_producer_id_));
335 const ProducerID pr_id = svc->last_producer_id_;
336 producers.emplace(pr_id, std::make_pair(std::move(producer),
337 std::move(producer_endpoint)));
338 return pr_id;
339 };
340
341 auto DisconnectProducerAndWait = [&task_runner,
342 &producers](ProducerID pr_id) {
343 char checkpoint_name[32];
344 static int checkpoint_num = 0;
345 sprintf(checkpoint_name, "on_disconnect_%d", checkpoint_num++);
346 auto on_disconnect = task_runner.CreateCheckpoint(checkpoint_name);
347 auto it = producers.find(pr_id);
348 PERFETTO_CHECK(it != producers.end());
349 EXPECT_CALL(*it->second.first, OnDisconnect())
350 .WillOnce(Invoke(on_disconnect));
351 producers.erase(pr_id);
352 task_runner.RunUntilCheckpoint(checkpoint_name);
353 };
354
355 // Connect producers 1-4.
356 for (ProducerID i = 1; i <= 4; i++)
357 ASSERT_EQ(i, ConnectProducerAndWait());
358
359 // Disconnect producers 1,3.
360 DisconnectProducerAndWait(1);
361 DisconnectProducerAndWait(3);
362
363 svc->last_producer_id_ = kMaxProducerID - 1;
364 ASSERT_EQ(kMaxProducerID, ConnectProducerAndWait());
365 ASSERT_EQ(1u, ConnectProducerAndWait());
366 ASSERT_EQ(3u, ConnectProducerAndWait());
367 ASSERT_EQ(5u, ConnectProducerAndWait());
368 ASSERT_EQ(6u, ConnectProducerAndWait());
369
370 // Disconnect all producers to mute spurious callbacks.
371 DisconnectProducerAndWait(kMaxProducerID);
372 for (ProducerID i = 1; i <= 6; i++)
373 DisconnectProducerAndWait(i);
374}
375
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000376} // namespace perfetto