blob: 1ea253469fab926fa7b6bcddc2c6a7cccb7bc41e [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"
Sami Kyostila06487a22018-02-27 13:48:38 +000025#include "perfetto/tracing/core/consumer.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000026#include "perfetto/tracing/core/data_source_config.h"
27#include "perfetto/tracing/core/data_source_descriptor.h"
28#include "perfetto/tracing/core/producer.h"
29#include "perfetto/tracing/core/shared_memory.h"
Sami Kyostila06487a22018-02-27 13:48:38 +000030#include "perfetto/tracing/core/trace_packet.h"
Primiano Tucci2ffd1a52018-03-27 01:01:30 +010031#include "perfetto/tracing/core/trace_writer.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000032#include "src/base/test/test_task_runner.h"
Primiano Tuccidca727d2018-04-04 11:31:55 +020033#include "src/tracing/test/mock_consumer.h"
34#include "src/tracing/test/mock_producer.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000035#include "src/tracing/test/test_shared_memory.h"
36
Primiano Tucci2ffd1a52018-03-27 01:01:30 +010037#include "perfetto/trace/test_event.pbzero.h"
38#include "perfetto/trace/trace.pb.h"
Primiano Tuccidca727d2018-04-04 11:31:55 +020039#include "perfetto/trace/trace_packet.pb.h"
Primiano Tucci2ffd1a52018-03-27 01:01:30 +010040#include "perfetto/trace/trace_packet.pbzero.h"
41
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000042using ::testing::_;
Primiano Tuccidca727d2018-04-04 11:31:55 +020043using ::testing::Contains;
44using ::testing::Eq;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000045using ::testing::InSequence;
Primiano Tucci081d46a2018-02-28 11:09:43 +000046using ::testing::Invoke;
Primiano Tuccidca727d2018-04-04 11:31:55 +020047using ::testing::InvokeWithoutArgs;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000048using ::testing::Mock;
Primiano Tuccidca727d2018-04-04 11:31:55 +020049using ::testing::Property;
50using ::testing::StrictMock;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000051
Primiano Tuccidca727d2018-04-04 11:31:55 +020052namespace perfetto {
Sami Kyostila32e0b542018-02-14 08:55:43 +000053
Sami Kyostila06487a22018-02-27 13:48:38 +000054class ServiceImplTest : public testing::Test {
55 public:
56 ServiceImplTest() {
57 auto shm_factory =
58 std::unique_ptr<SharedMemory::Factory>(new TestSharedMemory::Factory());
59 svc.reset(static_cast<ServiceImpl*>(
60 Service::CreateInstance(std::move(shm_factory), &task_runner)
61 .release()));
62 }
63
Primiano Tuccidca727d2018-04-04 11:31:55 +020064 std::unique_ptr<MockProducer> CreateMockProducer() {
65 return std::unique_ptr<MockProducer>(
66 new StrictMock<MockProducer>(&task_runner));
67 }
68
69 std::unique_ptr<MockConsumer> CreateMockConsumer() {
70 return std::unique_ptr<MockConsumer>(
71 new StrictMock<MockConsumer>(&task_runner));
72 }
73
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000074 base::TestTaskRunner task_runner;
Sami Kyostila06487a22018-02-27 13:48:38 +000075 std::unique_ptr<ServiceImpl> svc;
76};
77
78TEST_F(ServiceImplTest, RegisterAndUnregister) {
Primiano Tuccidca727d2018-04-04 11:31:55 +020079 std::unique_ptr<MockProducer> mock_producer_1 = CreateMockProducer();
80 std::unique_ptr<MockProducer> mock_producer_2 = CreateMockProducer();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000081
Primiano Tuccidca727d2018-04-04 11:31:55 +020082 mock_producer_1->Connect(svc.get(), "mock_producer_1", 123u /* uid */);
83 mock_producer_2->Connect(svc.get(), "mock_producer_2", 456u /* uid */);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000084
85 ASSERT_EQ(2u, svc->num_producers());
Primiano Tuccidca727d2018-04-04 11:31:55 +020086 ASSERT_EQ(mock_producer_1->endpoint(), svc->GetProducer(1));
87 ASSERT_EQ(mock_producer_2->endpoint(), svc->GetProducer(2));
Sami Kyostila32e0b542018-02-14 08:55:43 +000088 ASSERT_EQ(123u, svc->GetProducer(1)->uid_);
89 ASSERT_EQ(456u, svc->GetProducer(2)->uid_);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000090
Primiano Tuccidca727d2018-04-04 11:31:55 +020091 mock_producer_1->RegisterDataSource("foo");
92 mock_producer_2->RegisterDataSource("bar");
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000093
Primiano Tuccidca727d2018-04-04 11:31:55 +020094 mock_producer_1->UnregisterDataSource("foo");
95 mock_producer_2->UnregisterDataSource("bar");
Primiano Tucci9daa4832018-03-28 23:28:17 +010096
Primiano Tuccidca727d2018-04-04 11:31:55 +020097 mock_producer_1.reset();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000098 ASSERT_EQ(1u, svc->num_producers());
99 ASSERT_EQ(nullptr, svc->GetProducer(1));
100
Primiano Tuccidca727d2018-04-04 11:31:55 +0200101 mock_producer_2.reset();
102 ASSERT_EQ(nullptr, svc->GetProducer(2));
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000103
104 ASSERT_EQ(0u, svc->num_producers());
105}
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100106
Sami Kyostila06487a22018-02-27 13:48:38 +0000107TEST_F(ServiceImplTest, EnableAndDisableTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200108 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
109 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000110
Primiano Tuccidca727d2018-04-04 11:31:55 +0200111 std::unique_ptr<MockProducer> producer = CreateMockProducer();
112 producer->Connect(svc.get(), "mock_producer");
113 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000114
Sami Kyostila06487a22018-02-27 13:48:38 +0000115 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200116 trace_config.add_buffers()->set_size_kb(128);
Sami Kyostila06487a22018-02-27 13:48:38 +0000117 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200118 ds_config->set_name("data_source");
119 consumer->EnableTracing(trace_config);
Sami Kyostila06487a22018-02-27 13:48:38 +0000120
Primiano Tuccidca727d2018-04-04 11:31:55 +0200121 producer->WaitForTracingSetup();
122 producer->WaitForDataSourceStart("data_source");
123
124 consumer->DisableTracing();
125 producer->WaitForDataSourceStop("data_source");
126 consumer->WaitForTracingDisabled();
Sami Kyostila06487a22018-02-27 13:48:38 +0000127}
128
Florian Mayer61c55482018-03-06 14:43:54 +0000129TEST_F(ServiceImplTest, LockdownMode) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200130 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
131 consumer->Connect(svc.get());
132
133 std::unique_ptr<MockProducer> producer = CreateMockProducer();
134 producer->Connect(svc.get(), "mock_producer_sameuid", geteuid());
135 producer->RegisterDataSource("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000136
137 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200138 trace_config.add_buffers()->set_size_kb(128);
139 auto* ds_config = trace_config.add_data_sources()->mutable_config();
140 ds_config->set_name("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000141 trace_config.set_lockdown_mode(
142 TraceConfig::LockdownModeOperation::LOCKDOWN_SET);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200143 consumer->EnableTracing(trace_config);
144
145 producer->WaitForTracingSetup();
146 producer->WaitForDataSourceStart("data_source");
147
148 std::unique_ptr<MockProducer> producer_otheruid = CreateMockProducer();
149 auto x = svc->ConnectProducer(producer_otheruid.get(), geteuid() + 1,
150 "mock_producer_ouid");
151 EXPECT_CALL(*producer_otheruid, OnConnect()).Times(0);
Florian Mayer61c55482018-03-06 14:43:54 +0000152 task_runner.RunUntilIdle();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200153 Mock::VerifyAndClearExpectations(producer_otheruid.get());
Florian Mayer61c55482018-03-06 14:43:54 +0000154
Primiano Tuccidca727d2018-04-04 11:31:55 +0200155 consumer->DisableTracing();
156 consumer->FreeBuffers();
157 producer->WaitForDataSourceStop("data_source");
158 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000159
160 trace_config.set_lockdown_mode(
161 TraceConfig::LockdownModeOperation::LOCKDOWN_CLEAR);
Primiano Tuccidca727d2018-04-04 11:31:55 +0200162 consumer->EnableTracing(trace_config);
163 producer->WaitForDataSourceStart("data_source");
Florian Mayer61c55482018-03-06 14:43:54 +0000164
Primiano Tuccidca727d2018-04-04 11:31:55 +0200165 std::unique_ptr<MockProducer> producer_otheruid2 = CreateMockProducer();
166 producer_otheruid->Connect(svc.get(), "mock_producer_ouid2", geteuid() + 1);
Florian Mayer61c55482018-03-06 14:43:54 +0000167
Primiano Tuccidca727d2018-04-04 11:31:55 +0200168 consumer->DisableTracing();
169 producer->WaitForDataSourceStop("data_source");
170 consumer->WaitForTracingDisabled();
Florian Mayer61c55482018-03-06 14:43:54 +0000171}
172
Sami Kyostila06487a22018-02-27 13:48:38 +0000173TEST_F(ServiceImplTest, DisconnectConsumerWhileTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200174 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
175 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000176
Primiano Tuccidca727d2018-04-04 11:31:55 +0200177 std::unique_ptr<MockProducer> producer = CreateMockProducer();
178 producer->Connect(svc.get(), "mock_producer");
179 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000180
Primiano Tuccidca727d2018-04-04 11:31:55 +0200181 TraceConfig trace_config;
182 trace_config.add_buffers()->set_size_kb(128);
183 auto* ds_config = trace_config.add_data_sources()->mutable_config();
184 ds_config->set_name("data_source");
185 consumer->EnableTracing(trace_config);
186
187 producer->WaitForTracingSetup();
188 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000189
190 // Disconnecting the consumer while tracing should trigger data source
191 // teardown.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200192 consumer.reset();
193 producer->WaitForDataSourceStop("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000194}
195
196TEST_F(ServiceImplTest, ReconnectProducerWhileTracing) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200197 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
198 consumer->Connect(svc.get());
Sami Kyostila06487a22018-02-27 13:48:38 +0000199
Primiano Tuccidca727d2018-04-04 11:31:55 +0200200 std::unique_ptr<MockProducer> producer = CreateMockProducer();
201 producer->Connect(svc.get(), "mock_producer");
202 producer->RegisterDataSource("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000203
Sami Kyostila06487a22018-02-27 13:48:38 +0000204 TraceConfig trace_config;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200205 trace_config.add_buffers()->set_size_kb(128);
Sami Kyostila06487a22018-02-27 13:48:38 +0000206 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200207 ds_config->set_name("data_source");
208 consumer->EnableTracing(trace_config);
Sami Kyostila06487a22018-02-27 13:48:38 +0000209
Primiano Tuccidca727d2018-04-04 11:31:55 +0200210 producer->WaitForTracingSetup();
211 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000212
Primiano Tuccidca727d2018-04-04 11:31:55 +0200213 // Disconnecting and reconnecting a producer with a matching data source.
214 // The Producer should see that data source getting enabled again.
215 producer.reset();
216 producer = CreateMockProducer();
217 producer->Connect(svc.get(), "mock_producer_2");
218 producer->RegisterDataSource("data_source");
219 producer->WaitForTracingSetup();
220 producer->WaitForDataSourceStart("data_source");
Sami Kyostila06487a22018-02-27 13:48:38 +0000221}
222
Primiano Tucci081d46a2018-02-28 11:09:43 +0000223TEST_F(ServiceImplTest, ProducerIDWrapping) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200224 std::vector<std::unique_ptr<MockProducer>> producers;
225 producers.push_back(nullptr);
Primiano Tucci081d46a2018-02-28 11:09:43 +0000226
Primiano Tuccidca727d2018-04-04 11:31:55 +0200227 auto connect_producer_and_get_id = [&producers,
228 this](const std::string& name) {
229 producers.emplace_back(CreateMockProducer());
230 producers.back()->Connect(svc.get(), "mock_producer_" + name);
231 return svc->last_producer_id_;
Primiano Tucci081d46a2018-02-28 11:09:43 +0000232 };
233
234 // Connect producers 1-4.
235 for (ProducerID i = 1; i <= 4; i++)
Primiano Tuccidca727d2018-04-04 11:31:55 +0200236 ASSERT_EQ(i, connect_producer_and_get_id(std::to_string(i)));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000237
238 // Disconnect producers 1,3.
Primiano Tuccidca727d2018-04-04 11:31:55 +0200239 producers[1].reset();
240 producers[3].reset();
Primiano Tucci081d46a2018-02-28 11:09:43 +0000241
242 svc->last_producer_id_ = kMaxProducerID - 1;
Primiano Tuccidca727d2018-04-04 11:31:55 +0200243 ASSERT_EQ(kMaxProducerID, connect_producer_and_get_id("maxid"));
244 ASSERT_EQ(1u, connect_producer_and_get_id("1_again"));
245 ASSERT_EQ(3u, connect_producer_and_get_id("3_again"));
246 ASSERT_EQ(5u, connect_producer_and_get_id("5"));
247 ASSERT_EQ(6u, connect_producer_and_get_id("6"));
Primiano Tucci081d46a2018-02-28 11:09:43 +0000248}
249
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100250TEST_F(ServiceImplTest, WriteIntoFileAndStopOnMaxSize) {
Primiano Tuccidca727d2018-04-04 11:31:55 +0200251 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
252 consumer->Connect(svc.get());
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100253
Primiano Tuccidca727d2018-04-04 11:31:55 +0200254 std::unique_ptr<MockProducer> producer = CreateMockProducer();
255 producer->Connect(svc.get(), "mock_producer");
256 producer->RegisterDataSource("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100257
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100258 TraceConfig trace_config;
259 trace_config.add_buffers()->set_size_kb(4096);
260 auto* ds_config = trace_config.add_data_sources()->mutable_config();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200261 ds_config->set_name("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100262 ds_config->set_target_buffer(0);
263 trace_config.set_write_into_file(true);
264 trace_config.set_file_write_period_ms(1);
265 const uint64_t kMaxFileSize = 512;
266 trace_config.set_max_file_size_bytes(kMaxFileSize);
267 base::TempFile tmp_file = base::TempFile::Create();
Primiano Tuccidca727d2018-04-04 11:31:55 +0200268 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
269
270 producer->WaitForTracingSetup();
271 producer->WaitForDataSourceStart("data_source");
272
273 static const char kPayload[] = "1234567890abcdef-";
274 static const int kNumPackets = 10;
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100275
276 std::unique_ptr<TraceWriter> writer =
Primiano Tuccidca727d2018-04-04 11:31:55 +0200277 producer->CreateTraceWriter("data_source");
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100278 // All these packets should fit within kMaxFileSize.
279 for (int i = 0; i < kNumPackets; i++) {
280 auto tp = writer->NewTracePacket();
281 std::string payload(kPayload);
282 payload.append(std::to_string(i));
283 tp->set_for_testing()->set_str(payload.c_str(), payload.size());
284 }
285
286 // Finally add a packet that overflows kMaxFileSize. This should cause the
287 // implicit stop of the trace and should *not* be written in the trace.
288 {
289 auto tp = writer->NewTracePacket();
290 char big_payload[kMaxFileSize] = "BIG!";
291 tp->set_for_testing()->set_str(big_payload, sizeof(big_payload));
292 }
293 writer->Flush();
294 writer.reset();
295
Primiano Tuccidca727d2018-04-04 11:31:55 +0200296 consumer->DisableTracing();
297 producer->WaitForDataSourceStop("data_source");
298 consumer->WaitForTracingDisabled();
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100299
300 // Verify the contents of the file.
301 std::string trace_raw;
302 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
303 protos::Trace trace;
304 ASSERT_TRUE(trace.ParseFromString(trace_raw));
305 ASSERT_GE(trace.packet_size(), kNumPackets);
306 int num_testing_packet = 0;
307 for (int i = 0; i < trace.packet_size(); i++) {
308 const protos::TracePacket& tp = trace.packet(i);
309 if (!tp.has_for_testing())
310 continue;
311 ASSERT_EQ(kPayload + std::to_string(num_testing_packet++),
312 tp.for_testing().str());
313 }
Primiano Tuccidca727d2018-04-04 11:31:55 +0200314}
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100315
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000316} // namespace perfetto