blob: 69baf7df4225ec8a08b2f19d8ebb758f8ede87fb [file] [log] [blame]
Primiano Tucci53589332017-12-19 11:31:13 +01001/*
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/ipc/posix_shared_memory.h"
18
19#include <inttypes.h>
20
21#include "gmock/gmock.h"
22#include "gtest/gtest.h"
23#include "perfetto/tracing/core/consumer.h"
24#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/trace_config.h"
28#include "perfetto/tracing/core/trace_packet.h"
29#include "perfetto/tracing/core/trace_writer.h"
30#include "perfetto/tracing/ipc/consumer_ipc_client.h"
31#include "perfetto/tracing/ipc/producer_ipc_client.h"
32#include "perfetto/tracing/ipc/service_ipc_host.h"
33#include "src/base/test/test_task_runner.h"
34#include "src/ipc/test/test_socket.h"
35
36#include "protos/test_event.pbzero.h"
37#include "protos/trace_packet.pbzero.h"
38
39namespace perfetto {
40namespace {
41
42using testing::Invoke;
43using testing::InvokeWithoutArgs;
44using testing::_;
45
46constexpr char kProducerSockName[] = TEST_SOCK_NAME("tracing_test-producer");
47constexpr char kConsumerSockName[] = TEST_SOCK_NAME("tracing_test-consumer");
48
49class TracingIntegrationTest : public ::testing::Test {
50 public:
51 void SetUp() override {
52 DESTROY_TEST_SOCK(kProducerSockName);
53 DESTROY_TEST_SOCK(kConsumerSockName);
54 task_runner_.reset(new base::TestTaskRunner());
55 }
56
57 void TearDown() override {
58 task_runner_.reset();
59 DESTROY_TEST_SOCK(kProducerSockName);
60 DESTROY_TEST_SOCK(kConsumerSockName);
61 }
62
63 std::unique_ptr<base::TestTaskRunner> task_runner_;
64};
65
66class MockProducer : public Producer {
67 public:
68 ~MockProducer() override {}
69
70 // Producer implementation.
71 MOCK_METHOD0(OnConnect, void());
72 MOCK_METHOD0(OnDisconnect, void());
73 MOCK_METHOD2(CreateDataSourceInstance,
74 void(DataSourceInstanceID, const DataSourceConfig&));
75 MOCK_METHOD1(TearDownDataSourceInstance, void(DataSourceInstanceID));
76};
77
78class MockConsumer : public Consumer {
79 public:
80 ~MockConsumer() override {}
81
82 // Producer implementation.
83 MOCK_METHOD0(OnConnect, void());
84 MOCK_METHOD0(OnDisconnect, void());
Primiano Tucci3324dfc2017-12-20 14:35:58 +010085 MOCK_METHOD2(OnTracePackets, void(std::vector<TracePacket>*, bool));
86
87 // Workaround, gmock doesn't support yet move-only types, passing a pointer.
88 void OnTraceData(std::vector<TracePacket> packets, bool has_more) {
89 OnTracePackets(&packets, has_more);
90 }
Primiano Tucci53589332017-12-19 11:31:13 +010091};
92
93TEST_F(TracingIntegrationTest, WithIPCTransport) {
94 // Create the service host.
95 std::unique_ptr<ServiceIPCHost> svc =
96 ServiceIPCHost::CreateInstance(task_runner_.get());
97 svc->Start(kProducerSockName, kConsumerSockName);
98
99 // Create and connect a Producer.
100 MockProducer producer;
101 std::unique_ptr<Service::ProducerEndpoint> producer_endpoint =
102 ProducerIPCClient::Connect(kProducerSockName, &producer,
103 task_runner_.get());
104 auto on_producer_connect =
105 task_runner_->CreateCheckpoint("on_producer_connect");
106 EXPECT_CALL(producer, OnConnect()).WillOnce(Invoke(on_producer_connect));
107 task_runner_->RunUntilCheckpoint("on_producer_connect");
108
109 // Register a data source.
110 DataSourceDescriptor ds_desc;
111 ds_desc.set_name("perfetto.test");
112 auto on_data_source_registered =
113 task_runner_->CreateCheckpoint("on_data_source_registered");
114 producer_endpoint->RegisterDataSource(
115 ds_desc, [on_data_source_registered](DataSourceID dsid) {
116 PERFETTO_DLOG("Registered data source with ID: %" PRIu64, dsid);
117 on_data_source_registered();
118 });
119 task_runner_->RunUntilCheckpoint("on_data_source_registered");
120
121 // Create and connect a Consumer.
122 MockConsumer consumer;
123 std::unique_ptr<Service::ConsumerEndpoint> consumer_endpoint =
124 ConsumerIPCClient::Connect(kConsumerSockName, &consumer,
125 task_runner_.get());
126 auto on_consumer_connect =
127 task_runner_->CreateCheckpoint("on_consumer_connect");
128 EXPECT_CALL(consumer, OnConnect()).WillOnce(Invoke(on_consumer_connect));
129 task_runner_->RunUntilCheckpoint("on_consumer_connect");
130
131 // Start tracing.
132 TraceConfig trace_config;
133 trace_config.add_buffers()->set_size_kb(4096 * 10);
134 auto* ds_config = trace_config.add_data_sources()->mutable_config();
135 ds_config->set_name("perfetto.test");
136 ds_config->set_target_buffer(0);
137 ds_config->set_trace_category_filters("foo,bar");
138 consumer_endpoint->EnableTracing(trace_config);
139
140 // At this point, the Producer should be asked to turn its data source on.
141 DataSourceInstanceID ds_iid = 0;
142 auto on_create_ds_instance =
143 task_runner_->CreateCheckpoint("on_create_ds_instance");
144 EXPECT_CALL(producer, CreateDataSourceInstance(_, _))
145 .WillOnce(
146 Invoke([on_create_ds_instance, &ds_iid](DataSourceInstanceID id,
147 const DataSourceConfig& cfg) {
148 ASSERT_NE(0u, id);
149 ds_iid = id;
150 ASSERT_EQ("perfetto.test", cfg.name());
151 ASSERT_EQ(0u, cfg.target_buffer());
152 ASSERT_EQ("foo,bar", cfg.trace_category_filters());
153 on_create_ds_instance();
154 }));
155 task_runner_->RunUntilCheckpoint("on_create_ds_instance");
156
157 // Now let the data source fill some pages within the same task.
158 // Doing so should accumulate a bunch of chunks that will be notified by the
159 // a future task in one batch.
160 std::unique_ptr<TraceWriter> writer =
161 producer_endpoint->CreateTraceWriter(1 /* target_buffer */);
162 ASSERT_TRUE(writer);
163
164 const size_t kNumPackets = 10;
165 for (size_t i = 0; i < kNumPackets; i++) {
166 char buf[8];
167 sprintf(buf, "evt_%zu", i);
168 writer->NewTracePacket()->set_test_event()->set_str(buf, strlen(buf));
169 }
170
171 // Allow the service to see the NotifySharedMemoryUpdate() before disabling
172 // tracing.
173 task_runner_->RunUntilIdle();
174
175 // Disable tracing.
176 consumer_endpoint->DisableTracing();
177 auto on_teardown_ds_instance =
178 task_runner_->CreateCheckpoint("on_teardown_ds_instance");
179 EXPECT_CALL(producer, TearDownDataSourceInstance(ds_iid))
180 .WillOnce(InvokeWithoutArgs(on_teardown_ds_instance));
181 task_runner_->RunUntilCheckpoint("on_teardown_ds_instance");
182
183 // Read the log buffer.
184 consumer_endpoint->ReadBuffers();
185 size_t num_pack_rx = 0;
186 auto all_packets_rx = task_runner_->CreateCheckpoint("all_packets_rx");
Primiano Tucci3324dfc2017-12-20 14:35:58 +0100187 EXPECT_CALL(consumer, OnTracePackets(_, _))
Primiano Tucci53589332017-12-19 11:31:13 +0100188 .Times(kNumPackets)
189 .WillRepeatedly(
190 Invoke([&num_pack_rx, all_packets_rx](
Primiano Tucci3324dfc2017-12-20 14:35:58 +0100191 std::vector<TracePacket>* packets, bool has_more) {
Primiano Tucci53589332017-12-19 11:31:13 +0100192 // TODO(primiano): check contents, requires both pblite and pzero.
Primiano Tucci3324dfc2017-12-20 14:35:58 +0100193 num_pack_rx += packets->size();
Primiano Tucci53589332017-12-19 11:31:13 +0100194 if (!has_more)
195 all_packets_rx();
196 }));
197 task_runner_->RunUntilCheckpoint("all_packets_rx");
198
199 // TODO(primiano): cover FreeBuffers.
200
201 // Destroy the service and check that both Producer and Consumer see an
202 // OnDisconnect() call.
203
204 auto on_producer_disconnect =
205 task_runner_->CreateCheckpoint("on_producer_disconnect");
206 EXPECT_CALL(producer, OnDisconnect())
207 .WillOnce(Invoke(on_producer_disconnect));
208
209 auto on_consumer_disconnect =
210 task_runner_->CreateCheckpoint("on_consumer_disconnect");
211 EXPECT_CALL(consumer, OnDisconnect())
212 .WillOnce(Invoke(on_consumer_disconnect));
213
214 svc.reset();
215 task_runner_->RunUntilCheckpoint("on_producer_disconnect");
216 task_runner_->RunUntilCheckpoint("on_consumer_disconnect");
217}
218
219// TODO(primiano): add tests to cover:
220// - unknown fields preserved end-to-end.
221// - >1 data source.
222// - >1 data consumer sharing the same data source, with different TraceBuffers.
223
224} // namespace
225} // namespace perfetto