123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "services/tracing/perfetto/consumer_host.h"
- #include <algorithm>
- #include <memory>
- #include <string>
- #include <utility>
- #include <vector>
- #include "base/callback.h"
- #include "base/callback_helpers.h"
- #include "base/run_loop.h"
- #include "base/strings/strcat.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/task/sequenced_task_runner.h"
- #include "base/task/thread_pool.h"
- #include "base/test/bind.h"
- #include "base/test/task_environment.h"
- #include "base/trace_event/trace_config.h"
- #include "mojo/public/cpp/bindings/receiver.h"
- #include "mojo/public/cpp/system/data_pipe.h"
- #include "mojo/public/cpp/system/data_pipe_drainer.h"
- #include "services/tracing/perfetto/perfetto_service.h"
- #include "services/tracing/perfetto/test_utils.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_packet.h"
- #include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h"
- #include "third_party/perfetto/protos/perfetto/config/trace_config.pb.h"
- #include "third_party/perfetto/protos/perfetto/trace/trace.pb.h"
- #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pb.h"
- namespace tracing {
- constexpr base::ProcessId kProducerPid = 1234;
- // This is here so we can properly simulate this running on three
- // different sequences (ProducerClient side, Service side, and
- // whatever connects via Mojo to the Producer). This is needed
- // so we don't get into read/write locks.
- class ThreadedPerfettoService : public mojom::TracingSessionClient {
- public:
- ThreadedPerfettoService()
- : task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
- {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN,
- base::WithBaseSyncPrimitives(),
- base::TaskPriority::BEST_EFFORT})) {
- perfetto_service_ = std::make_unique<PerfettoService>(task_runner_);
- tracing_session_host_ =
- std::make_unique<mojo::Remote<mojom::TracingSessionHost>>();
- base::RunLoop wait_for_construct;
- task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(&ThreadedPerfettoService::CreateConsumerOnSequence,
- base::Unretained(this)),
- wait_for_construct.QuitClosure());
- wait_for_construct.Run();
- }
- ~ThreadedPerfettoService() override {
- if (receiver_) {
- task_runner_->DeleteSoon(FROM_HERE, std::move(receiver_));
- }
- task_runner_->DeleteSoon(FROM_HERE, std::move(producer_));
- if (consumer_) {
- task_runner_->DeleteSoon(FROM_HERE, std::move(consumer_));
- }
- if (tracing_session_host_)
- task_runner_->DeleteSoon(FROM_HERE, std::move(tracing_session_host_));
- {
- base::RunLoop wait_for_destruction;
- task_runner_->PostTaskAndReply(FROM_HERE, base::DoNothing(),
- wait_for_destruction.QuitClosure());
- wait_for_destruction.Run();
- }
- {
- base::RunLoop wait_for_destruction;
- task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(
- [](std::unique_ptr<PerfettoService> service) { service.reset(); },
- std::move(perfetto_service_)),
- wait_for_destruction.QuitClosure());
- wait_for_destruction.Run();
- }
- {
- base::RunLoop wait_for_destruction;
- PerfettoTracedProcess::GetTaskRunner()
- ->GetOrCreateTaskRunner()
- ->PostTaskAndReply(FROM_HERE, base::DoNothing(),
- wait_for_destruction.QuitClosure());
- wait_for_destruction.Run();
- }
- }
- // mojom::TracingSessionClient implementation:
- void OnTracingEnabled() override {
- EXPECT_FALSE(tracing_enabled_);
- tracing_enabled_ = true;
- }
- void OnTracingDisabled(bool) override {}
- void CreateProducer(const std::string& data_source_name,
- size_t num_packets,
- base::OnceClosure on_tracing_started) {
- base::RunLoop wait_for_datasource_registration;
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&ThreadedPerfettoService::CreateProducerOnSequence,
- base::Unretained(this), data_source_name,
- wait_for_datasource_registration.QuitClosure(),
- std::move(on_tracing_started), num_packets));
- wait_for_datasource_registration.Run();
- }
- void CreateConsumerOnSequence() {
- consumer_ = std::make_unique<ConsumerHost>(perfetto_service_.get());
- }
- void CreateProducerOnSequence(const std::string& data_source_name,
- base::OnceClosure on_datasource_registered,
- base::OnceClosure on_tracing_started,
- size_t num_packets) {
- producer_ = std::make_unique<MockProducer>(
- base::StrCat({mojom::kPerfettoProducerNamePrefix,
- base::NumberToString(kProducerPid)}),
- data_source_name, perfetto_service_.get(),
- std::move(on_datasource_registered), std::move(on_tracing_started),
- num_packets);
- }
- void EnableTracingWithConfig(const perfetto::TraceConfig& config) {
- base::RunLoop wait_for_call;
- task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(&ThreadedPerfettoService::EnableTracingOnSequence,
- base::Unretained(this), std::move(config)),
- wait_for_call.QuitClosure());
- wait_for_call.Run();
- }
- void EnableTracingOnSequence(const perfetto::TraceConfig& config) {
- mojo::PendingRemote<tracing::mojom::TracingSessionClient>
- tracing_session_client;
- receiver_ = std::make_unique<mojo::Receiver<mojom::TracingSessionClient>>(
- this, tracing_session_client.InitWithNewPipeAndPassReceiver());
- consumer_->EnableTracing(
- tracing_session_host_->BindNewPipeAndPassReceiver(),
- std::move(tracing_session_client), std::move(config), base::File());
- }
- void ReadBuffers(mojo::ScopedDataPipeProducerHandle stream,
- ConsumerHost::TracingSession::ReadBuffersCallback callback) {
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &ConsumerHost::TracingSession::ReadBuffers,
- base::Unretained(consumer_.get()->tracing_session_for_testing()),
- std::move(stream), std::move(callback)));
- }
- void DisableTracing() {
- base::RunLoop wait_for_call;
- task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(
- &ConsumerHost::TracingSession::DisableTracing,
- base::Unretained(consumer_.get()->tracing_session_for_testing())),
- wait_for_call.QuitClosure());
- wait_for_call.Run();
- }
- void DisableTracingAndEmitJson(
- mojo::ScopedDataPipeProducerHandle stream,
- ConsumerHost::TracingSession::DisableTracingAndEmitJsonCallback callback,
- bool enable_privacy_filtering) {
- base::RunLoop wait_for_call;
- task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(
- &ConsumerHost::TracingSession::DisableTracingAndEmitJson,
- base::Unretained(consumer_.get()->tracing_session_for_testing()),
- std::string(), std::move(stream), enable_privacy_filtering,
- std::move(callback)),
- wait_for_call.QuitClosure());
- wait_for_call.Run();
- }
- void WritePacketBigly() {
- base::RunLoop wait_for_call;
- task_runner_->PostTask(FROM_HERE,
- base::BindOnce(&MockProducer::WritePacketBigly,
- base::Unretained(producer_.get()),
- wait_for_call.QuitClosure()));
- wait_for_call.Run();
- }
- void Flush(base::OnceClosure on_flush_complete) {
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &ConsumerHost::TracingSession::Flush,
- base::Unretained(consumer_.get()->tracing_session_for_testing()),
- 10000u,
- base::BindOnce(
- [](base::OnceClosure callback, bool success) {
- EXPECT_TRUE(success);
- std::move(callback).Run();
- },
- std::move(on_flush_complete))));
- }
- void ExpectPid(base::ProcessId pid) {
- base::RunLoop wait_for_call;
- task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(&PerfettoService::AddActiveServicePid,
- base::Unretained(perfetto_service_.get()), pid),
- wait_for_call.QuitClosure());
- wait_for_call.Run();
- }
- void SetPidsInitialized() {
- base::RunLoop wait_for_call;
- task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(&PerfettoService::SetActiveServicePidsInitialized,
- base::Unretained(perfetto_service_.get())),
- wait_for_call.QuitClosure());
- wait_for_call.Run();
- }
- void RemovePid(base::ProcessId pid) {
- base::RunLoop wait_for_call;
- task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(&PerfettoService::RemoveActiveServicePid,
- base::Unretained(perfetto_service_.get()), pid),
- wait_for_call.QuitClosure());
- wait_for_call.Run();
- }
- bool IsTracingEnabled() const {
- bool tracing_enabled;
- base::RunLoop wait_for_call;
- task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(&ThreadedPerfettoService::GetTracingEnabledOnSequence,
- base::Unretained(this), &tracing_enabled),
- wait_for_call.QuitClosure());
- wait_for_call.Run();
- return tracing_enabled;
- }
- void GetTracingEnabledOnSequence(bool* tracing_enabled) const {
- *tracing_enabled = tracing_enabled_;
- }
- perfetto::DataSourceConfig GetProducerClientConfig() {
- perfetto::DataSourceConfig config;
- base::RunLoop wait_loop;
- task_runner_->PostTaskAndReply(FROM_HERE, base::BindLambdaForTesting([&]() {
- config =
- producer_->data_source()->config();
- }),
- wait_loop.QuitClosure());
- wait_loop.Run();
- return config;
- }
- void ClearConsumer() {
- base::RunLoop wait_loop;
- task_runner_->PostTaskAndReply(
- FROM_HERE, base::BindLambdaForTesting([&]() { consumer_.reset(); }),
- wait_loop.QuitClosure());
- wait_loop.Run();
- }
- PerfettoService* perfetto_service() const { return perfetto_service_.get(); }
- private:
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
- std::unique_ptr<PerfettoService> perfetto_service_;
- std::unique_ptr<ConsumerHost> consumer_;
- std::unique_ptr<MockProducer> producer_;
- std::unique_ptr<mojo::Receiver<mojom::TracingSessionClient>> receiver_;
- std::unique_ptr<mojo::Remote<tracing::mojom::TracingSessionHost>>
- tracing_session_host_;
- bool tracing_enabled_ = false;
- };
- // TODO(crbug.com/1006541): Switch this to use TracingUnitTest.
- class TracingConsumerTest : public testing::Test,
- public mojo::DataPipeDrainer::Client {
- public:
- void SetUp() override {
- task_environment_ = std::make_unique<base::test::TaskEnvironment>();
- tracing_environment_ = std::make_unique<base::test::TracingEnvironment>(
- *task_environment_, base::ThreadTaskRunnerHandle::Get(),
- PerfettoTracedProcess::Get()->perfetto_platform_for_testing());
- test_handle_ = tracing::PerfettoTracedProcess::SetupForTesting();
- PerfettoTracedProcess::Get()->ClearDataSourcesForTesting();
- threaded_service_ = std::make_unique<ThreadedPerfettoService>();
- matching_packet_count_ = 0;
- total_bytes_received_ = 0;
- }
- void TearDown() override {
- tracing_environment_.reset();
- threaded_service_.reset();
- task_environment_->RunUntilIdle();
- test_handle_.reset();
- task_environment_.reset();
- }
- // mojo::DataPipeDrainer::Client
- void OnDataAvailable(const void* data, size_t num_bytes) override {
- total_bytes_received_ += num_bytes;
- std::copy(static_cast<const uint8_t*>(data),
- static_cast<const uint8_t*>(data) + num_bytes,
- std::back_inserter(received_data_));
- }
- // mojo::DataPipeDrainer::Client
- void OnDataComplete() override {
- if (expect_json_data_) {
- std::string output(reinterpret_cast<const char*>(received_data_.data()),
- received_data_.size());
- if (output.find(packet_testing_str_) != std::string::npos) {
- matching_packet_count_++;
- }
- } else {
- auto proto = std::make_unique<perfetto::protos::Trace>();
- EXPECT_TRUE(
- proto->ParseFromArray(received_data_.data(), received_data_.size()));
- for (int i = 0; i < proto->packet_size(); ++i) {
- if (proto->packet(i).for_testing().str() == packet_testing_str_) {
- matching_packet_count_++;
- }
- }
- }
- if (on_data_complete_) {
- std::move(on_data_complete_).Run();
- }
- }
- void ExpectPackets(const std::string& testing_str,
- base::OnceClosure on_data_complete) {
- on_data_complete_ = std::move(on_data_complete);
- packet_testing_str_ = testing_str;
- matching_packet_count_ = 0;
- }
- void ReadBuffers() {
- MojoCreateDataPipeOptions options = {sizeof(MojoCreateDataPipeOptions),
- MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1, 0};
- mojo::ScopedDataPipeProducerHandle producer;
- mojo::ScopedDataPipeConsumerHandle consumer;
- MojoResult rv = mojo::CreateDataPipe(&options, producer, consumer);
- ASSERT_EQ(MOJO_RESULT_OK, rv);
- threaded_service_->ReadBuffers(std::move(producer), base::OnceClosure());
- drainer_ =
- std::make_unique<mojo::DataPipeDrainer>(this, std::move(consumer));
- }
- void DisableTracingAndEmitJson(base::OnceClosure write_callback,
- bool enable_privacy_filtering = false) {
- expect_json_data_ = true;
- MojoCreateDataPipeOptions options = {sizeof(MojoCreateDataPipeOptions),
- MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1, 0};
- mojo::ScopedDataPipeProducerHandle producer;
- mojo::ScopedDataPipeConsumerHandle consumer;
- MojoResult rv = mojo::CreateDataPipe(&options, producer, consumer);
- ASSERT_EQ(MOJO_RESULT_OK, rv);
- threaded_service_->DisableTracingAndEmitJson(std::move(producer),
- std::move(write_callback),
- enable_privacy_filtering);
- drainer_ =
- std::make_unique<mojo::DataPipeDrainer>(this, std::move(consumer));
- }
- perfetto::TraceConfig GetDefaultTraceConfig(
- const std::string& data_source_name,
- perfetto::protos::gen::ChromeConfig::ClientPriority priority =
- perfetto::protos::gen::ChromeConfig::UNKNOWN) {
- perfetto::TraceConfig trace_config;
- trace_config.add_buffers()->set_size_kb(32 * 1024);
- auto* trace_event_config =
- trace_config.add_data_sources()->mutable_config();
- trace_event_config->set_name(data_source_name);
- trace_event_config->set_target_buffer(0);
- trace_event_config->mutable_chrome_config()->set_client_priority(priority);
- return trace_config;
- }
- void EnableTracingWithDataSourceName(const std::string& data_source_name,
- bool enable_privacy_filtering = false,
- bool convert_to_legacy_json = false) {
- perfetto::TraceConfig config = GetDefaultTraceConfig(data_source_name);
- if (enable_privacy_filtering) {
- for (auto& source : *config.mutable_data_sources()) {
- source.mutable_config()
- ->mutable_chrome_config()
- ->set_privacy_filtering_enabled(true);
- }
- }
- if (convert_to_legacy_json) {
- for (auto& source : *config.mutable_data_sources()) {
- source.mutable_config()
- ->mutable_chrome_config()
- ->set_convert_to_legacy_json(true);
- }
- }
- threaded_service_->EnableTracingWithConfig(config);
- }
- bool IsTracingEnabled() {
- // Flush any other pending tasks on the perfetto task runner to ensure that
- // any pending data source start callbacks have propagated.
- task_environment_->RunUntilIdle();
- return threaded_service_->IsTracingEnabled();
- }
- size_t matching_packet_count() const { return matching_packet_count_; }
- size_t total_bytes_received() const { return total_bytes_received_; }
- ThreadedPerfettoService* threaded_perfetto_service() const {
- return threaded_service_.get();
- }
- private:
- std::unique_ptr<ThreadedPerfettoService> threaded_service_;
- std::unique_ptr<base::test::TaskEnvironment> task_environment_;
- std::unique_ptr<base::test::TracingEnvironment> tracing_environment_;
- std::unique_ptr<PerfettoTracedProcess::TestHandle> test_handle_;
- base::OnceClosure on_data_complete_;
- std::unique_ptr<mojo::DataPipeDrainer> drainer_;
- std::vector<uint8_t> received_data_;
- std::string packet_testing_str_;
- size_t matching_packet_count_ = 0;
- size_t total_bytes_received_ = 0;
- bool expect_json_data_ = false;
- };
- TEST_F(TracingConsumerTest, EnableAndDisableTracing) {
- EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
- base::RunLoop no_more_data;
- ExpectPackets(kPerfettoTestString, no_more_data.QuitClosure());
- threaded_perfetto_service()->DisableTracing();
- ReadBuffers();
- no_more_data.Run();
- EXPECT_EQ(0u, matching_packet_count());
- }
- TEST_F(TracingConsumerTest, ReceiveTestPackets) {
- EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
- base::RunLoop wait_for_tracing_start;
- threaded_perfetto_service()->CreateProducer(
- mojom::kTraceEventDataSourceName, 10u,
- wait_for_tracing_start.QuitClosure());
- wait_for_tracing_start.Run();
- base::RunLoop no_more_data;
- ExpectPackets(kPerfettoTestString, no_more_data.QuitClosure());
- threaded_perfetto_service()->DisableTracing();
- ReadBuffers();
- no_more_data.Run();
- EXPECT_EQ(10u, matching_packet_count());
- }
- TEST_F(TracingConsumerTest, DeleteConsumerWhenReceiving) {
- EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
- base::RunLoop wait_for_tracing_start;
- threaded_perfetto_service()->CreateProducer(
- mojom::kTraceEventDataSourceName, 100u,
- wait_for_tracing_start.QuitClosure());
- wait_for_tracing_start.Run();
- base::RunLoop no_more_data;
- ExpectPackets(kPerfettoTestString, no_more_data.QuitClosure());
- threaded_perfetto_service()->DisableTracing();
- ReadBuffers();
- threaded_perfetto_service()->ClearConsumer();
- no_more_data.Run();
- }
- TEST_F(TracingConsumerTest, FlushProducers) {
- EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
- base::RunLoop wait_for_tracing_start;
- threaded_perfetto_service()->CreateProducer(
- mojom::kTraceEventDataSourceName, 10u,
- wait_for_tracing_start.QuitClosure());
- wait_for_tracing_start.Run();
- base::RunLoop wait_for_packets;
- ExpectPackets(kPerfettoTestString, wait_for_packets.QuitClosure());
- base::RunLoop wait_for_flush;
- threaded_perfetto_service()->Flush(wait_for_flush.QuitClosure());
- ReadBuffers();
- wait_for_flush.Run();
- wait_for_packets.Run();
- EXPECT_EQ(10u, matching_packet_count());
- }
- TEST_F(TracingConsumerTest, LargeDataSize) {
- EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
- base::RunLoop wait_for_tracing_start;
- threaded_perfetto_service()->CreateProducer(
- mojom::kTraceEventDataSourceName, 0u,
- wait_for_tracing_start.QuitClosure());
- wait_for_tracing_start.Run();
- base::RunLoop no_more_data;
- ExpectPackets(kPerfettoTestString, no_more_data.QuitClosure());
- threaded_perfetto_service()->WritePacketBigly();
- threaded_perfetto_service()->DisableTracing();
- ReadBuffers();
- no_more_data.Run();
- EXPECT_GE(total_bytes_received(), kLargeMessageSize);
- }
- TEST_F(TracingConsumerTest, NotifiesOnTracingEnabled) {
- threaded_perfetto_service()->SetPidsInitialized();
- EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
- EXPECT_TRUE(IsTracingEnabled());
- }
- TEST_F(TracingConsumerTest, NotifiesOnTracingEnabledWaitsForProducer) {
- threaded_perfetto_service()->ExpectPid(kProducerPid);
- threaded_perfetto_service()->SetPidsInitialized();
- EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
- // Tracing is only marked as enabled once the expected producer has acked that
- // its data source has started.
- EXPECT_FALSE(IsTracingEnabled());
- base::RunLoop wait_for_tracing_start;
- threaded_perfetto_service()->CreateProducer(
- mojom::kTraceEventDataSourceName, 0u,
- wait_for_tracing_start.QuitClosure());
- wait_for_tracing_start.Run();
- EXPECT_TRUE(IsTracingEnabled());
- }
- TEST_F(TracingConsumerTest, NotifiesOnTracingEnabledWaitsForFilteredProducer) {
- threaded_perfetto_service()->ExpectPid(kProducerPid);
- threaded_perfetto_service()->SetPidsInitialized();
- // Filter for the expected producer.
- auto config = GetDefaultTraceConfig(mojom::kTraceEventDataSourceName);
- *config.mutable_data_sources()->front().add_producer_name_filter() =
- base::StrCat({mojom::kPerfettoProducerNamePrefix,
- base::NumberToString(kProducerPid)});
- threaded_perfetto_service()->EnableTracingWithConfig(config);
- // Tracing is only marked as enabled once the expected producer has acked that
- // its data source has started.
- EXPECT_FALSE(IsTracingEnabled());
- base::RunLoop wait_for_tracing_start;
- threaded_perfetto_service()->CreateProducer(
- mojom::kTraceEventDataSourceName, 0u,
- wait_for_tracing_start.QuitClosure());
- wait_for_tracing_start.Run();
- EXPECT_TRUE(IsTracingEnabled());
- }
- TEST_F(TracingConsumerTest,
- NotifiesOnTracingEnabledDoesNotWaitForUnfilteredProducer) {
- threaded_perfetto_service()->ExpectPid(kProducerPid);
- threaded_perfetto_service()->SetPidsInitialized();
- // Filter for an unexpected producer whose PID is not active.
- auto config = GetDefaultTraceConfig(mojom::kTraceEventDataSourceName);
- *config.mutable_data_sources()->front().add_producer_name_filter() =
- base::StrCat({mojom::kPerfettoProducerNamePrefix,
- base::NumberToString(kProducerPid + 1)});
- threaded_perfetto_service()->EnableTracingWithConfig(config);
- // Tracing should already have been enabled even though the host was told
- // about a service with kProducerPid. Since kProducerPid is not included in
- // the producer_name_filter, the host should not wait for it.
- EXPECT_TRUE(IsTracingEnabled());
- }
- TEST_F(TracingConsumerTest,
- NotifiesOnTracingEnabledWaitsForProducerAndInitializedPids) {
- threaded_perfetto_service()->ExpectPid(kProducerPid);
- EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
- // Tracing is only marked as enabled once the expected producer has acked that
- // its data source has started and once the PIDs are initialized.
- EXPECT_FALSE(IsTracingEnabled());
- base::RunLoop wait_for_tracing_start;
- threaded_perfetto_service()->CreateProducer(
- mojom::kTraceEventDataSourceName, 0u,
- wait_for_tracing_start.QuitClosure());
- wait_for_tracing_start.Run();
- EXPECT_FALSE(IsTracingEnabled());
- threaded_perfetto_service()->SetPidsInitialized();
- EXPECT_TRUE(IsTracingEnabled());
- }
- TEST_F(TracingConsumerTest, PrivacyFilterConfig) {
- EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName,
- /* enable_privacy_filtering =*/true,
- /* convert_to_legacy_json =*/false);
- base::RunLoop wait_for_tracing_start;
- threaded_perfetto_service()->CreateProducer(
- mojom::kTraceEventDataSourceName, 10u,
- wait_for_tracing_start.QuitClosure());
- wait_for_tracing_start.Run();
- EXPECT_TRUE(threaded_perfetto_service()
- ->GetProducerClientConfig()
- .chrome_config()
- .privacy_filtering_enabled());
- base::trace_event::TraceConfig base_config(threaded_perfetto_service()
- ->GetProducerClientConfig()
- .chrome_config()
- .trace_config());
- EXPECT_FALSE(base_config.IsArgumentFilterEnabled());
- }
- TEST_F(TracingConsumerTest, NoPrivacyFilterWithJsonConversion) {
- EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName,
- /* enable_privacy_filtering =*/false,
- /* convert_to_legacy_json =*/true);
- base::RunLoop wait_for_tracing_start;
- threaded_perfetto_service()->CreateProducer(
- mojom::kTraceEventDataSourceName, 10u,
- wait_for_tracing_start.QuitClosure());
- wait_for_tracing_start.Run();
- EXPECT_FALSE(threaded_perfetto_service()
- ->GetProducerClientConfig()
- .chrome_config()
- .privacy_filtering_enabled());
- base::trace_event::TraceConfig base_config(threaded_perfetto_service()
- ->GetProducerClientConfig()
- .chrome_config()
- .trace_config());
- EXPECT_FALSE(base_config.IsArgumentFilterEnabled());
- }
- TEST_F(TracingConsumerTest, PrivacyFilterConfigInJson) {
- EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName,
- /* enable_privacy_filtering =*/true,
- /* convert_to_legacy_json =*/true);
- base::RunLoop wait_for_tracing_start;
- threaded_perfetto_service()->CreateProducer(
- mojom::kTraceEventDataSourceName, 10u,
- wait_for_tracing_start.QuitClosure());
- wait_for_tracing_start.Run();
- EXPECT_FALSE(threaded_perfetto_service()
- ->GetProducerClientConfig()
- .chrome_config()
- .privacy_filtering_enabled());
- base::trace_event::TraceConfig base_config(threaded_perfetto_service()
- ->GetProducerClientConfig()
- .chrome_config()
- .trace_config());
- EXPECT_TRUE(base_config.IsArgumentFilterEnabled());
- base::RunLoop no_more_data;
- ExpectPackets("\"trace_processor_stats\":\"__stripped__\"",
- no_more_data.QuitClosure());
- base::RunLoop write_done;
- DisableTracingAndEmitJson(write_done.QuitClosure(),
- /* enable_privacy_filtering =*/true);
- no_more_data.Run();
- write_done.Run();
- EXPECT_EQ(1u, matching_packet_count());
- }
- class MockConsumerHost : public mojom::TracingSessionClient {
- public:
- explicit MockConsumerHost(PerfettoService* service)
- : consumer_host_(std::make_unique<ConsumerHost>(service)) {}
- void EnableTracing(const perfetto::TraceConfig& config) {
- mojo::PendingRemote<tracing::mojom::TracingSessionClient>
- tracing_session_client;
- receiver_.Bind(tracing_session_client.InitWithNewPipeAndPassReceiver());
- receiver_.set_disconnect_handler(base::BindOnce(
- &MockConsumerHost::OnConnectionLost, base::Unretained(this)));
- consumer_host_->EnableTracing(
- tracing_session_host_.BindNewPipeAndPassReceiver(),
- std::move(tracing_session_client), config, base::File());
- tracing_session_host_.set_disconnect_handler(base::BindOnce(
- &MockConsumerHost::OnConnectionLost, base::Unretained(this)));
- }
- void DisableTracing() { tracing_session_host_->DisableTracing(); }
- void OnConnectionLost() {
- CloseTracingSession();
- wait_for_connection_lost_.Quit();
- }
- void CloseTracingSession() {
- tracing_session_host_.reset();
- receiver_.reset();
- }
- // mojom::TracingSessionClient implementation:
- void OnTracingEnabled() override { wait_for_tracing_enabled_.Quit(); }
- void OnTracingDisabled(bool) override { wait_for_tracing_disabled_.Quit(); }
- void WaitForConnectionLost() { wait_for_connection_lost_.Run(); }
- void WaitForTracingEnabled() { wait_for_tracing_enabled_.Run(); }
- void WaitForTracingDisabled() { wait_for_tracing_disabled_.Run(); }
- private:
- mojo::Remote<tracing::mojom::TracingSessionHost> tracing_session_host_;
- mojo::Receiver<mojom::TracingSessionClient> receiver_{this};
- std::unique_ptr<ConsumerHost> consumer_host_;
- base::RunLoop wait_for_connection_lost_;
- base::RunLoop wait_for_tracing_enabled_;
- base::RunLoop wait_for_tracing_disabled_;
- };
- TEST_F(TracingConsumerTest, TestConsumerPriority) {
- PerfettoService::GetInstance()->SetActiveServicePidsInitialized();
- auto trace_config_background =
- GetDefaultTraceConfig(mojom::kTraceEventDataSourceName,
- perfetto::protos::gen ::ChromeConfig::BACKGROUND);
- auto trace_config_user_initiated = GetDefaultTraceConfig(
- mojom::kTraceEventDataSourceName,
- perfetto::protos::gen ::ChromeConfig::USER_INITIATED);
- MockConsumerHost background_consumer_1(PerfettoService::GetInstance());
- background_consumer_1.EnableTracing(trace_config_background);
- background_consumer_1.WaitForTracingEnabled();
- // Second consumer of the same priority should cause the first one to
- // be disabled and the second to start.
- MockConsumerHost background_consumer_2(PerfettoService::GetInstance());
- background_consumer_2.EnableTracing(trace_config_background);
- background_consumer_1.WaitForTracingDisabled();
- background_consumer_2.WaitForTracingEnabled();
- // Third consumer will have a higher priority, and should kill the second
- // one.
- MockConsumerHost user_initiated_consumer(PerfettoService::GetInstance());
- user_initiated_consumer.EnableTracing(trace_config_user_initiated);
- background_consumer_2.WaitForTracingDisabled();
- user_initiated_consumer.WaitForTracingEnabled();
- // Fourth consumer will be another background consumer, and should be
- // itself killed as the third consumer is still running.
- MockConsumerHost background_consumer_3(PerfettoService::GetInstance());
- background_consumer_3.EnableTracing(trace_config_background);
- background_consumer_3.WaitForConnectionLost();
- // If we close the user initiated consumer, the third background consumer
- // should now be able to trace.
- user_initiated_consumer.DisableTracing();
- user_initiated_consumer.WaitForTracingDisabled();
- user_initiated_consumer.CloseTracingSession();
- background_consumer_3.EnableTracing(trace_config_background);
- background_consumer_3.WaitForTracingEnabled();
- }
- } // namespace tracing
|