blob: 7c9f0a4ba180c8c8eae60a3e337b181e92aed36c [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
177TEST_F(ServiceImplTest, DisconnectConsumerWhileTracing) {
178 MockProducer mock_producer;
179 std::unique_ptr<Service::ProducerEndpoint> producer_endpoint =
180 svc->ConnectProducer(&mock_producer, 123u /* uid */);
181 MockConsumer mock_consumer;
182 std::unique_ptr<Service::ConsumerEndpoint> consumer_endpoint =
183 svc->ConnectConsumer(&mock_consumer);
184
185 InSequence seq;
186 EXPECT_CALL(mock_producer, OnConnect());
187 EXPECT_CALL(mock_consumer, OnConnect());
188 task_runner.RunUntilIdle();
189
190 DataSourceDescriptor ds_desc;
191 ds_desc.set_name("foo");
192 producer_endpoint->RegisterDataSource(ds_desc, [](DataSourceID) {});
193 task_runner.RunUntilIdle();
194
195 // Disconnecting the consumer while tracing should trigger data source
196 // teardown.
197 EXPECT_CALL(mock_producer, CreateDataSourceInstance(_, _));
198 EXPECT_CALL(mock_producer, TearDownDataSourceInstance(_));
199 TraceConfig trace_config;
200 trace_config.add_buffers()->set_size_kb(4096 * 10);
201 auto* ds_config = trace_config.add_data_sources()->mutable_config();
202 ds_config->set_name("foo");
203 ds_config->set_target_buffer(0);
204 consumer_endpoint->EnableTracing(trace_config);
205 task_runner.RunUntilIdle();
206
207 EXPECT_CALL(mock_consumer, OnDisconnect());
208 consumer_endpoint.reset();
209 task_runner.RunUntilIdle();
210
211 EXPECT_CALL(mock_producer, OnDisconnect());
212 producer_endpoint.reset();
213 Mock::VerifyAndClearExpectations(&mock_producer);
214 Mock::VerifyAndClearExpectations(&mock_consumer);
215}
216
217TEST_F(ServiceImplTest, ReconnectProducerWhileTracing) {
218 MockProducer mock_producer;
219 std::unique_ptr<Service::ProducerEndpoint> producer_endpoint =
220 svc->ConnectProducer(&mock_producer, 123u /* uid */);
221 MockConsumer mock_consumer;
222 std::unique_ptr<Service::ConsumerEndpoint> consumer_endpoint =
223 svc->ConnectConsumer(&mock_consumer);
224
225 InSequence seq;
226 EXPECT_CALL(mock_producer, OnConnect());
227 EXPECT_CALL(mock_consumer, OnConnect());
228 task_runner.RunUntilIdle();
229
230 DataSourceDescriptor ds_desc;
231 ds_desc.set_name("foo");
232 producer_endpoint->RegisterDataSource(ds_desc, [](DataSourceID) {});
233 task_runner.RunUntilIdle();
234
235 // Disconnecting the producer while tracing should trigger data source
236 // teardown.
237 EXPECT_CALL(mock_producer, CreateDataSourceInstance(_, _));
238 EXPECT_CALL(mock_producer, TearDownDataSourceInstance(_));
239 EXPECT_CALL(mock_producer, OnDisconnect());
240 TraceConfig trace_config;
241 trace_config.add_buffers()->set_size_kb(4096 * 10);
242 auto* ds_config = trace_config.add_data_sources()->mutable_config();
243 ds_config->set_name("foo");
244 ds_config->set_target_buffer(0);
245 consumer_endpoint->EnableTracing(trace_config);
246 producer_endpoint.reset();
247 task_runner.RunUntilIdle();
248
249 // Reconnecting a producer with a matching data source should see that data
250 // source getting enabled.
251 EXPECT_CALL(mock_producer, OnConnect());
252 producer_endpoint = svc->ConnectProducer(&mock_producer, 123u /* uid */);
253 task_runner.RunUntilIdle();
254 EXPECT_CALL(mock_producer, CreateDataSourceInstance(_, _));
255 EXPECT_CALL(mock_producer, TearDownDataSourceInstance(_));
256 producer_endpoint->RegisterDataSource(ds_desc, [](DataSourceID) {});
257 task_runner.RunUntilIdle();
258
259 EXPECT_CALL(mock_consumer, OnDisconnect());
260 consumer_endpoint->DisableTracing();
261 consumer_endpoint.reset();
262 task_runner.RunUntilIdle();
263
264 EXPECT_CALL(mock_producer, OnDisconnect());
265 producer_endpoint.reset();
266 Mock::VerifyAndClearExpectations(&mock_producer);
267 Mock::VerifyAndClearExpectations(&mock_consumer);
268}
269
Primiano Tucci081d46a2018-02-28 11:09:43 +0000270TEST_F(ServiceImplTest, ProducerIDWrapping) {
271 base::TestTaskRunner task_runner;
272 auto shm_factory =
273 std::unique_ptr<SharedMemory::Factory>(new TestSharedMemory::Factory());
274 std::unique_ptr<ServiceImpl> svc(static_cast<ServiceImpl*>(
275 Service::CreateInstance(std::move(shm_factory), &task_runner).release()));
276
277 std::map<ProducerID, std::pair<std::unique_ptr<MockProducer>,
278 std::unique_ptr<Service::ProducerEndpoint>>>
279 producers;
280
281 auto ConnectProducerAndWait = [&task_runner, &svc, &producers]() {
282 char checkpoint_name[32];
283 static int checkpoint_num = 0;
284 sprintf(checkpoint_name, "on_connect_%d", checkpoint_num++);
285 auto on_connect = task_runner.CreateCheckpoint(checkpoint_name);
286 std::unique_ptr<MockProducer> producer(new MockProducer());
287 std::unique_ptr<Service::ProducerEndpoint> producer_endpoint =
288 svc->ConnectProducer(producer.get(), 123u /* uid */);
289 EXPECT_CALL(*producer, OnConnect()).WillOnce(Invoke(on_connect));
290 task_runner.RunUntilCheckpoint(checkpoint_name);
291 EXPECT_EQ(&*producer_endpoint, svc->GetProducer(svc->last_producer_id_));
292 const ProducerID pr_id = svc->last_producer_id_;
293 producers.emplace(pr_id, std::make_pair(std::move(producer),
294 std::move(producer_endpoint)));
295 return pr_id;
296 };
297
298 auto DisconnectProducerAndWait = [&task_runner,
299 &producers](ProducerID pr_id) {
300 char checkpoint_name[32];
301 static int checkpoint_num = 0;
302 sprintf(checkpoint_name, "on_disconnect_%d", checkpoint_num++);
303 auto on_disconnect = task_runner.CreateCheckpoint(checkpoint_name);
304 auto it = producers.find(pr_id);
305 PERFETTO_CHECK(it != producers.end());
306 EXPECT_CALL(*it->second.first, OnDisconnect())
307 .WillOnce(Invoke(on_disconnect));
308 producers.erase(pr_id);
309 task_runner.RunUntilCheckpoint(checkpoint_name);
310 };
311
312 // Connect producers 1-4.
313 for (ProducerID i = 1; i <= 4; i++)
314 ASSERT_EQ(i, ConnectProducerAndWait());
315
316 // Disconnect producers 1,3.
317 DisconnectProducerAndWait(1);
318 DisconnectProducerAndWait(3);
319
320 svc->last_producer_id_ = kMaxProducerID - 1;
321 ASSERT_EQ(kMaxProducerID, ConnectProducerAndWait());
322 ASSERT_EQ(1u, ConnectProducerAndWait());
323 ASSERT_EQ(3u, ConnectProducerAndWait());
324 ASSERT_EQ(5u, ConnectProducerAndWait());
325 ASSERT_EQ(6u, ConnectProducerAndWait());
326
327 // Disconnect all producers to mute spurious callbacks.
328 DisconnectProducerAndWait(kMaxProducerID);
329 for (ProducerID i = 1; i <= 6; i++)
330 DisconnectProducerAndWait(i);
331}
332
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000333} // namespace perfetto