blob: 8bda6b2d8ffac257c839b625d8a2bb5de9f29cef [file] [log] [blame]
Primiano Tucci1d94e7d2017-11-20 14:45: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 <inttypes.h>
18#include <stdio.h>
19#include <string.h>
20#include <unistd.h>
21
Oystein Eftevaagdd727e42017-12-05 08:49:55 -080022#include "perfetto_base/logging.h"
23#include "perfetto_base/test/test_task_runner.h"
Primiano Tucci1d94e7d2017-11-20 14:45:16 +000024#include "tracing/core/data_source_config.h"
25#include "tracing/core/data_source_descriptor.h"
26#include "tracing/core/producer.h"
27#include "tracing/core/service.h"
28#include "tracing/ipc/producer_ipc_client.h"
29#include "tracing/ipc/service_ipc_host.h"
30#include "tracing/src/core/service_impl.h"
Primiano Tuccif54cae42017-11-21 19:37:13 +000031#include "tracing/src/ipc/posix_shared_memory.h"
32#include "tracing/src/ipc/producer/producer_ipc_client_impl.h"
Primiano Tucci1d94e7d2017-11-20 14:45:16 +000033#include "tracing/src/ipc/service/service_ipc_host_impl.h"
34
35namespace perfetto {
36
37namespace {
38
39const char kSocketName[] = "/tmp/perfetto-ipc-test.sock";
40
41class TestProducer : public Producer {
42 public:
43 void OnConnect() override {
44 PERFETTO_DLOG("Connected as Producer");
45 if (on_connect)
46 on_connect();
47 }
48
49 void OnDisconnect() override {
50 PERFETTO_DLOG("Disconnected from tracing service");
51 }
52
53 void CreateDataSourceInstance(DataSourceInstanceID dsid,
54 const DataSourceConfig& cfg) override {
55 PERFETTO_DLOG(
56 "The tracing service requested us to start a new data source %" PRIu64
57 ", config: %s",
58 dsid, cfg.trace_category_filters.c_str());
59 }
60
61 void TearDownDataSourceInstance(DataSourceInstanceID instance_id) override {
62 PERFETTO_DLOG(
63 "The tracing service requested us to shutdown the data source %" PRIu64,
64 instance_id);
65 }
66
67 std::function<void()> on_connect;
68};
69
70void __attribute__((noreturn)) ProducerMain() {
71 base::TestTaskRunner task_runner;
72 TestProducer producer;
73 std::unique_ptr<Service::ProducerEndpoint> endpoint =
74 ProducerIPCClient::Connect(kSocketName, &producer, &task_runner);
75 producer.on_connect = task_runner.CreateCheckpoint("connect");
76 task_runner.RunUntilCheckpoint("connect");
77
78 for (int i = 0; i < 3; i++) {
79 DataSourceDescriptor descriptor;
80 descriptor.name = "perfetto.test.data_source";
81 auto reg_checkpoint =
82 task_runner.CreateCheckpoint("register" + std::to_string(i));
83 auto on_register = [reg_checkpoint](DataSourceID id) {
Primiano Tuccif54cae42017-11-21 19:37:13 +000084 printf("Service acked RegisterDataSource() with ID %" PRIu64 "\n", id);
Primiano Tucci1d94e7d2017-11-20 14:45:16 +000085 reg_checkpoint();
86 };
87 endpoint->RegisterDataSource(descriptor, on_register);
88 task_runner.RunUntilCheckpoint("register" + std::to_string(i));
Primiano Tucci1d94e7d2017-11-20 14:45:16 +000089
Primiano Tuccif54cae42017-11-21 19:37:13 +000090 auto* ipc_client = static_cast<ProducerIPCClientImpl*>(endpoint.get());
91 void* shm = ipc_client->shared_memory()->start();
92 char buf[32];
93 memcpy(buf, shm, sizeof(buf));
94 buf[sizeof(buf) - 1] = '\0';
95 printf("Shared Memory contents: \"%s\"\n", buf);
96 }
Primiano Tucci1d94e7d2017-11-20 14:45:16 +000097 task_runner.Run();
98}
99
100void __attribute__((noreturn)) ServiceMain() {
101 unlink(kSocketName);
102 base::TestTaskRunner task_runner;
103 std::unique_ptr<ServiceIPCHostImpl> host(static_cast<ServiceIPCHostImpl*>(
104 ServiceIPCHost::CreateInstance(&task_runner).release()));
105
106 class Observer : public Service::ObserverForTesting {
107 public:
108 explicit Observer(ServiceImpl* svc) : svc_(svc) {}
109 void OnProducerConnected(ProducerID prid) override {
110 printf("Producer connected: ID=%" PRIu64 "\n", prid);
111 }
112
113 void OnProducerDisconnected(ProducerID prid) override {
114 printf("Producer disconnected: ID=%" PRIu64 "\n", prid);
115 }
116
117 void OnDataSourceRegistered(ProducerID prid, DataSourceID dsid) override {
118 printf("Data source registered, Producer=%" PRIu64 " DataSource=%" PRIu64
119 "\n",
120 prid, dsid);
121 DataSourceConfig cfg;
122 cfg.trace_category_filters = "foo,bar";
Primiano Tuccif54cae42017-11-21 19:37:13 +0000123 SharedMemory* shm = svc_->GetProducer(prid)->shared_memory();
124 char shm_contents[32];
125 sprintf(shm_contents, "shmem @ iteration %" PRIu64, dsid);
126 memcpy(shm->start(), shm_contents, sizeof(shm_contents));
Primiano Tucci1d94e7d2017-11-20 14:45:16 +0000127 svc_->GetProducer(prid)->producer()->CreateDataSourceInstance(42, cfg);
128 }
129
130 void OnDataSourceUnregistered(ProducerID prid, DataSourceID dsid) override {
131 printf("Data source unregistered, Producer=%" PRIu64
132 " DataSource=%" PRIu64 "\n",
133 prid, dsid);
134 }
135
136 ServiceImpl* svc_;
137 };
138
139 host->Start(kSocketName);
140 Observer observer(static_cast<ServiceImpl*>(host->service_for_testing()));
141 host->service_for_testing()->set_observer_for_testing(&observer);
142 task_runner.Run();
143}
144
145} // namespace.
146} // namespace perfetto
147
148int main(int argc, char** argv) {
149 if (argc == 2 && !strcmp(argv[1], "producer"))
150 perfetto::ProducerMain();
151 if (argc == 2 && !strcmp(argv[1], "service"))
152 perfetto::ServiceMain();
153
154 fprintf(stderr, "Usage: %s producer | service\n", argv[0]);
155 return 1;
156}