blob: 8bda6b2d8ffac257c839b625d8a2bb5de9f29cef [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "perfetto_base/logging.h"
#include "perfetto_base/test/test_task_runner.h"
#include "tracing/core/data_source_config.h"
#include "tracing/core/data_source_descriptor.h"
#include "tracing/core/producer.h"
#include "tracing/core/service.h"
#include "tracing/ipc/producer_ipc_client.h"
#include "tracing/ipc/service_ipc_host.h"
#include "tracing/src/core/service_impl.h"
#include "tracing/src/ipc/posix_shared_memory.h"
#include "tracing/src/ipc/producer/producer_ipc_client_impl.h"
#include "tracing/src/ipc/service/service_ipc_host_impl.h"
namespace perfetto {
namespace {
const char kSocketName[] = "/tmp/perfetto-ipc-test.sock";
class TestProducer : public Producer {
public:
void OnConnect() override {
PERFETTO_DLOG("Connected as Producer");
if (on_connect)
on_connect();
}
void OnDisconnect() override {
PERFETTO_DLOG("Disconnected from tracing service");
}
void CreateDataSourceInstance(DataSourceInstanceID dsid,
const DataSourceConfig& cfg) override {
PERFETTO_DLOG(
"The tracing service requested us to start a new data source %" PRIu64
", config: %s",
dsid, cfg.trace_category_filters.c_str());
}
void TearDownDataSourceInstance(DataSourceInstanceID instance_id) override {
PERFETTO_DLOG(
"The tracing service requested us to shutdown the data source %" PRIu64,
instance_id);
}
std::function<void()> on_connect;
};
void __attribute__((noreturn)) ProducerMain() {
base::TestTaskRunner task_runner;
TestProducer producer;
std::unique_ptr<Service::ProducerEndpoint> endpoint =
ProducerIPCClient::Connect(kSocketName, &producer, &task_runner);
producer.on_connect = task_runner.CreateCheckpoint("connect");
task_runner.RunUntilCheckpoint("connect");
for (int i = 0; i < 3; i++) {
DataSourceDescriptor descriptor;
descriptor.name = "perfetto.test.data_source";
auto reg_checkpoint =
task_runner.CreateCheckpoint("register" + std::to_string(i));
auto on_register = [reg_checkpoint](DataSourceID id) {
printf("Service acked RegisterDataSource() with ID %" PRIu64 "\n", id);
reg_checkpoint();
};
endpoint->RegisterDataSource(descriptor, on_register);
task_runner.RunUntilCheckpoint("register" + std::to_string(i));
auto* ipc_client = static_cast<ProducerIPCClientImpl*>(endpoint.get());
void* shm = ipc_client->shared_memory()->start();
char buf[32];
memcpy(buf, shm, sizeof(buf));
buf[sizeof(buf) - 1] = '\0';
printf("Shared Memory contents: \"%s\"\n", buf);
}
task_runner.Run();
}
void __attribute__((noreturn)) ServiceMain() {
unlink(kSocketName);
base::TestTaskRunner task_runner;
std::unique_ptr<ServiceIPCHostImpl> host(static_cast<ServiceIPCHostImpl*>(
ServiceIPCHost::CreateInstance(&task_runner).release()));
class Observer : public Service::ObserverForTesting {
public:
explicit Observer(ServiceImpl* svc) : svc_(svc) {}
void OnProducerConnected(ProducerID prid) override {
printf("Producer connected: ID=%" PRIu64 "\n", prid);
}
void OnProducerDisconnected(ProducerID prid) override {
printf("Producer disconnected: ID=%" PRIu64 "\n", prid);
}
void OnDataSourceRegistered(ProducerID prid, DataSourceID dsid) override {
printf("Data source registered, Producer=%" PRIu64 " DataSource=%" PRIu64
"\n",
prid, dsid);
DataSourceConfig cfg;
cfg.trace_category_filters = "foo,bar";
SharedMemory* shm = svc_->GetProducer(prid)->shared_memory();
char shm_contents[32];
sprintf(shm_contents, "shmem @ iteration %" PRIu64, dsid);
memcpy(shm->start(), shm_contents, sizeof(shm_contents));
svc_->GetProducer(prid)->producer()->CreateDataSourceInstance(42, cfg);
}
void OnDataSourceUnregistered(ProducerID prid, DataSourceID dsid) override {
printf("Data source unregistered, Producer=%" PRIu64
" DataSource=%" PRIu64 "\n",
prid, dsid);
}
ServiceImpl* svc_;
};
host->Start(kSocketName);
Observer observer(static_cast<ServiceImpl*>(host->service_for_testing()));
host->service_for_testing()->set_observer_for_testing(&observer);
task_runner.Run();
}
} // namespace.
} // namespace perfetto
int main(int argc, char** argv) {
if (argc == 2 && !strcmp(argv[1], "producer"))
perfetto::ProducerMain();
if (argc == 2 && !strcmp(argv[1], "service"))
perfetto::ServiceMain();
fprintf(stderr, "Usage: %s producer | service\n", argv[0]);
return 1;
}