consumer_host_unittest.cc 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "services/tracing/perfetto/consumer_host.h"
  5. #include <algorithm>
  6. #include <memory>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10. #include "base/callback.h"
  11. #include "base/callback_helpers.h"
  12. #include "base/run_loop.h"
  13. #include "base/strings/strcat.h"
  14. #include "base/strings/string_number_conversions.h"
  15. #include "base/task/sequenced_task_runner.h"
  16. #include "base/task/thread_pool.h"
  17. #include "base/test/bind.h"
  18. #include "base/test/task_environment.h"
  19. #include "base/trace_event/trace_config.h"
  20. #include "mojo/public/cpp/bindings/receiver.h"
  21. #include "mojo/public/cpp/system/data_pipe.h"
  22. #include "mojo/public/cpp/system/data_pipe_drainer.h"
  23. #include "services/tracing/perfetto/perfetto_service.h"
  24. #include "services/tracing/perfetto/test_utils.h"
  25. #include "testing/gtest/include/gtest/gtest.h"
  26. #include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_packet.h"
  27. #include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h"
  28. #include "third_party/perfetto/protos/perfetto/config/trace_config.pb.h"
  29. #include "third_party/perfetto/protos/perfetto/trace/trace.pb.h"
  30. #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pb.h"
  31. namespace tracing {
  32. constexpr base::ProcessId kProducerPid = 1234;
  33. // This is here so we can properly simulate this running on three
  34. // different sequences (ProducerClient side, Service side, and
  35. // whatever connects via Mojo to the Producer). This is needed
  36. // so we don't get into read/write locks.
  37. class ThreadedPerfettoService : public mojom::TracingSessionClient {
  38. public:
  39. ThreadedPerfettoService()
  40. : task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
  41. {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN,
  42. base::WithBaseSyncPrimitives(),
  43. base::TaskPriority::BEST_EFFORT})) {
  44. perfetto_service_ = std::make_unique<PerfettoService>(task_runner_);
  45. tracing_session_host_ =
  46. std::make_unique<mojo::Remote<mojom::TracingSessionHost>>();
  47. base::RunLoop wait_for_construct;
  48. task_runner_->PostTaskAndReply(
  49. FROM_HERE,
  50. base::BindOnce(&ThreadedPerfettoService::CreateConsumerOnSequence,
  51. base::Unretained(this)),
  52. wait_for_construct.QuitClosure());
  53. wait_for_construct.Run();
  54. }
  55. ~ThreadedPerfettoService() override {
  56. if (receiver_) {
  57. task_runner_->DeleteSoon(FROM_HERE, std::move(receiver_));
  58. }
  59. task_runner_->DeleteSoon(FROM_HERE, std::move(producer_));
  60. if (consumer_) {
  61. task_runner_->DeleteSoon(FROM_HERE, std::move(consumer_));
  62. }
  63. if (tracing_session_host_)
  64. task_runner_->DeleteSoon(FROM_HERE, std::move(tracing_session_host_));
  65. {
  66. base::RunLoop wait_for_destruction;
  67. task_runner_->PostTaskAndReply(FROM_HERE, base::DoNothing(),
  68. wait_for_destruction.QuitClosure());
  69. wait_for_destruction.Run();
  70. }
  71. {
  72. base::RunLoop wait_for_destruction;
  73. task_runner_->PostTaskAndReply(
  74. FROM_HERE,
  75. base::BindOnce(
  76. [](std::unique_ptr<PerfettoService> service) { service.reset(); },
  77. std::move(perfetto_service_)),
  78. wait_for_destruction.QuitClosure());
  79. wait_for_destruction.Run();
  80. }
  81. {
  82. base::RunLoop wait_for_destruction;
  83. PerfettoTracedProcess::GetTaskRunner()
  84. ->GetOrCreateTaskRunner()
  85. ->PostTaskAndReply(FROM_HERE, base::DoNothing(),
  86. wait_for_destruction.QuitClosure());
  87. wait_for_destruction.Run();
  88. }
  89. }
  90. // mojom::TracingSessionClient implementation:
  91. void OnTracingEnabled() override {
  92. EXPECT_FALSE(tracing_enabled_);
  93. tracing_enabled_ = true;
  94. }
  95. void OnTracingDisabled(bool) override {}
  96. void CreateProducer(const std::string& data_source_name,
  97. size_t num_packets,
  98. base::OnceClosure on_tracing_started) {
  99. base::RunLoop wait_for_datasource_registration;
  100. task_runner_->PostTask(
  101. FROM_HERE,
  102. base::BindOnce(&ThreadedPerfettoService::CreateProducerOnSequence,
  103. base::Unretained(this), data_source_name,
  104. wait_for_datasource_registration.QuitClosure(),
  105. std::move(on_tracing_started), num_packets));
  106. wait_for_datasource_registration.Run();
  107. }
  108. void CreateConsumerOnSequence() {
  109. consumer_ = std::make_unique<ConsumerHost>(perfetto_service_.get());
  110. }
  111. void CreateProducerOnSequence(const std::string& data_source_name,
  112. base::OnceClosure on_datasource_registered,
  113. base::OnceClosure on_tracing_started,
  114. size_t num_packets) {
  115. producer_ = std::make_unique<MockProducer>(
  116. base::StrCat({mojom::kPerfettoProducerNamePrefix,
  117. base::NumberToString(kProducerPid)}),
  118. data_source_name, perfetto_service_.get(),
  119. std::move(on_datasource_registered), std::move(on_tracing_started),
  120. num_packets);
  121. }
  122. void EnableTracingWithConfig(const perfetto::TraceConfig& config) {
  123. base::RunLoop wait_for_call;
  124. task_runner_->PostTaskAndReply(
  125. FROM_HERE,
  126. base::BindOnce(&ThreadedPerfettoService::EnableTracingOnSequence,
  127. base::Unretained(this), std::move(config)),
  128. wait_for_call.QuitClosure());
  129. wait_for_call.Run();
  130. }
  131. void EnableTracingOnSequence(const perfetto::TraceConfig& config) {
  132. mojo::PendingRemote<tracing::mojom::TracingSessionClient>
  133. tracing_session_client;
  134. receiver_ = std::make_unique<mojo::Receiver<mojom::TracingSessionClient>>(
  135. this, tracing_session_client.InitWithNewPipeAndPassReceiver());
  136. consumer_->EnableTracing(
  137. tracing_session_host_->BindNewPipeAndPassReceiver(),
  138. std::move(tracing_session_client), std::move(config), base::File());
  139. }
  140. void ReadBuffers(mojo::ScopedDataPipeProducerHandle stream,
  141. ConsumerHost::TracingSession::ReadBuffersCallback callback) {
  142. task_runner_->PostTask(
  143. FROM_HERE,
  144. base::BindOnce(
  145. &ConsumerHost::TracingSession::ReadBuffers,
  146. base::Unretained(consumer_.get()->tracing_session_for_testing()),
  147. std::move(stream), std::move(callback)));
  148. }
  149. void DisableTracing() {
  150. base::RunLoop wait_for_call;
  151. task_runner_->PostTaskAndReply(
  152. FROM_HERE,
  153. base::BindOnce(
  154. &ConsumerHost::TracingSession::DisableTracing,
  155. base::Unretained(consumer_.get()->tracing_session_for_testing())),
  156. wait_for_call.QuitClosure());
  157. wait_for_call.Run();
  158. }
  159. void DisableTracingAndEmitJson(
  160. mojo::ScopedDataPipeProducerHandle stream,
  161. ConsumerHost::TracingSession::DisableTracingAndEmitJsonCallback callback,
  162. bool enable_privacy_filtering) {
  163. base::RunLoop wait_for_call;
  164. task_runner_->PostTaskAndReply(
  165. FROM_HERE,
  166. base::BindOnce(
  167. &ConsumerHost::TracingSession::DisableTracingAndEmitJson,
  168. base::Unretained(consumer_.get()->tracing_session_for_testing()),
  169. std::string(), std::move(stream), enable_privacy_filtering,
  170. std::move(callback)),
  171. wait_for_call.QuitClosure());
  172. wait_for_call.Run();
  173. }
  174. void WritePacketBigly() {
  175. base::RunLoop wait_for_call;
  176. task_runner_->PostTask(FROM_HERE,
  177. base::BindOnce(&MockProducer::WritePacketBigly,
  178. base::Unretained(producer_.get()),
  179. wait_for_call.QuitClosure()));
  180. wait_for_call.Run();
  181. }
  182. void Flush(base::OnceClosure on_flush_complete) {
  183. task_runner_->PostTask(
  184. FROM_HERE,
  185. base::BindOnce(
  186. &ConsumerHost::TracingSession::Flush,
  187. base::Unretained(consumer_.get()->tracing_session_for_testing()),
  188. 10000u,
  189. base::BindOnce(
  190. [](base::OnceClosure callback, bool success) {
  191. EXPECT_TRUE(success);
  192. std::move(callback).Run();
  193. },
  194. std::move(on_flush_complete))));
  195. }
  196. void ExpectPid(base::ProcessId pid) {
  197. base::RunLoop wait_for_call;
  198. task_runner_->PostTaskAndReply(
  199. FROM_HERE,
  200. base::BindOnce(&PerfettoService::AddActiveServicePid,
  201. base::Unretained(perfetto_service_.get()), pid),
  202. wait_for_call.QuitClosure());
  203. wait_for_call.Run();
  204. }
  205. void SetPidsInitialized() {
  206. base::RunLoop wait_for_call;
  207. task_runner_->PostTaskAndReply(
  208. FROM_HERE,
  209. base::BindOnce(&PerfettoService::SetActiveServicePidsInitialized,
  210. base::Unretained(perfetto_service_.get())),
  211. wait_for_call.QuitClosure());
  212. wait_for_call.Run();
  213. }
  214. void RemovePid(base::ProcessId pid) {
  215. base::RunLoop wait_for_call;
  216. task_runner_->PostTaskAndReply(
  217. FROM_HERE,
  218. base::BindOnce(&PerfettoService::RemoveActiveServicePid,
  219. base::Unretained(perfetto_service_.get()), pid),
  220. wait_for_call.QuitClosure());
  221. wait_for_call.Run();
  222. }
  223. bool IsTracingEnabled() const {
  224. bool tracing_enabled;
  225. base::RunLoop wait_for_call;
  226. task_runner_->PostTaskAndReply(
  227. FROM_HERE,
  228. base::BindOnce(&ThreadedPerfettoService::GetTracingEnabledOnSequence,
  229. base::Unretained(this), &tracing_enabled),
  230. wait_for_call.QuitClosure());
  231. wait_for_call.Run();
  232. return tracing_enabled;
  233. }
  234. void GetTracingEnabledOnSequence(bool* tracing_enabled) const {
  235. *tracing_enabled = tracing_enabled_;
  236. }
  237. perfetto::DataSourceConfig GetProducerClientConfig() {
  238. perfetto::DataSourceConfig config;
  239. base::RunLoop wait_loop;
  240. task_runner_->PostTaskAndReply(FROM_HERE, base::BindLambdaForTesting([&]() {
  241. config =
  242. producer_->data_source()->config();
  243. }),
  244. wait_loop.QuitClosure());
  245. wait_loop.Run();
  246. return config;
  247. }
  248. void ClearConsumer() {
  249. base::RunLoop wait_loop;
  250. task_runner_->PostTaskAndReply(
  251. FROM_HERE, base::BindLambdaForTesting([&]() { consumer_.reset(); }),
  252. wait_loop.QuitClosure());
  253. wait_loop.Run();
  254. }
  255. PerfettoService* perfetto_service() const { return perfetto_service_.get(); }
  256. private:
  257. scoped_refptr<base::SequencedTaskRunner> task_runner_;
  258. std::unique_ptr<PerfettoService> perfetto_service_;
  259. std::unique_ptr<ConsumerHost> consumer_;
  260. std::unique_ptr<MockProducer> producer_;
  261. std::unique_ptr<mojo::Receiver<mojom::TracingSessionClient>> receiver_;
  262. std::unique_ptr<mojo::Remote<tracing::mojom::TracingSessionHost>>
  263. tracing_session_host_;
  264. bool tracing_enabled_ = false;
  265. };
  266. // TODO(crbug.com/1006541): Switch this to use TracingUnitTest.
  267. class TracingConsumerTest : public testing::Test,
  268. public mojo::DataPipeDrainer::Client {
  269. public:
  270. void SetUp() override {
  271. task_environment_ = std::make_unique<base::test::TaskEnvironment>();
  272. tracing_environment_ = std::make_unique<base::test::TracingEnvironment>(
  273. *task_environment_, base::ThreadTaskRunnerHandle::Get(),
  274. PerfettoTracedProcess::Get()->perfetto_platform_for_testing());
  275. test_handle_ = tracing::PerfettoTracedProcess::SetupForTesting();
  276. PerfettoTracedProcess::Get()->ClearDataSourcesForTesting();
  277. threaded_service_ = std::make_unique<ThreadedPerfettoService>();
  278. matching_packet_count_ = 0;
  279. total_bytes_received_ = 0;
  280. }
  281. void TearDown() override {
  282. tracing_environment_.reset();
  283. threaded_service_.reset();
  284. task_environment_->RunUntilIdle();
  285. test_handle_.reset();
  286. task_environment_.reset();
  287. }
  288. // mojo::DataPipeDrainer::Client
  289. void OnDataAvailable(const void* data, size_t num_bytes) override {
  290. total_bytes_received_ += num_bytes;
  291. std::copy(static_cast<const uint8_t*>(data),
  292. static_cast<const uint8_t*>(data) + num_bytes,
  293. std::back_inserter(received_data_));
  294. }
  295. // mojo::DataPipeDrainer::Client
  296. void OnDataComplete() override {
  297. if (expect_json_data_) {
  298. std::string output(reinterpret_cast<const char*>(received_data_.data()),
  299. received_data_.size());
  300. if (output.find(packet_testing_str_) != std::string::npos) {
  301. matching_packet_count_++;
  302. }
  303. } else {
  304. auto proto = std::make_unique<perfetto::protos::Trace>();
  305. EXPECT_TRUE(
  306. proto->ParseFromArray(received_data_.data(), received_data_.size()));
  307. for (int i = 0; i < proto->packet_size(); ++i) {
  308. if (proto->packet(i).for_testing().str() == packet_testing_str_) {
  309. matching_packet_count_++;
  310. }
  311. }
  312. }
  313. if (on_data_complete_) {
  314. std::move(on_data_complete_).Run();
  315. }
  316. }
  317. void ExpectPackets(const std::string& testing_str,
  318. base::OnceClosure on_data_complete) {
  319. on_data_complete_ = std::move(on_data_complete);
  320. packet_testing_str_ = testing_str;
  321. matching_packet_count_ = 0;
  322. }
  323. void ReadBuffers() {
  324. MojoCreateDataPipeOptions options = {sizeof(MojoCreateDataPipeOptions),
  325. MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1, 0};
  326. mojo::ScopedDataPipeProducerHandle producer;
  327. mojo::ScopedDataPipeConsumerHandle consumer;
  328. MojoResult rv = mojo::CreateDataPipe(&options, producer, consumer);
  329. ASSERT_EQ(MOJO_RESULT_OK, rv);
  330. threaded_service_->ReadBuffers(std::move(producer), base::OnceClosure());
  331. drainer_ =
  332. std::make_unique<mojo::DataPipeDrainer>(this, std::move(consumer));
  333. }
  334. void DisableTracingAndEmitJson(base::OnceClosure write_callback,
  335. bool enable_privacy_filtering = false) {
  336. expect_json_data_ = true;
  337. MojoCreateDataPipeOptions options = {sizeof(MojoCreateDataPipeOptions),
  338. MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1, 0};
  339. mojo::ScopedDataPipeProducerHandle producer;
  340. mojo::ScopedDataPipeConsumerHandle consumer;
  341. MojoResult rv = mojo::CreateDataPipe(&options, producer, consumer);
  342. ASSERT_EQ(MOJO_RESULT_OK, rv);
  343. threaded_service_->DisableTracingAndEmitJson(std::move(producer),
  344. std::move(write_callback),
  345. enable_privacy_filtering);
  346. drainer_ =
  347. std::make_unique<mojo::DataPipeDrainer>(this, std::move(consumer));
  348. }
  349. perfetto::TraceConfig GetDefaultTraceConfig(
  350. const std::string& data_source_name,
  351. perfetto::protos::gen::ChromeConfig::ClientPriority priority =
  352. perfetto::protos::gen::ChromeConfig::UNKNOWN) {
  353. perfetto::TraceConfig trace_config;
  354. trace_config.add_buffers()->set_size_kb(32 * 1024);
  355. auto* trace_event_config =
  356. trace_config.add_data_sources()->mutable_config();
  357. trace_event_config->set_name(data_source_name);
  358. trace_event_config->set_target_buffer(0);
  359. trace_event_config->mutable_chrome_config()->set_client_priority(priority);
  360. return trace_config;
  361. }
  362. void EnableTracingWithDataSourceName(const std::string& data_source_name,
  363. bool enable_privacy_filtering = false,
  364. bool convert_to_legacy_json = false) {
  365. perfetto::TraceConfig config = GetDefaultTraceConfig(data_source_name);
  366. if (enable_privacy_filtering) {
  367. for (auto& source : *config.mutable_data_sources()) {
  368. source.mutable_config()
  369. ->mutable_chrome_config()
  370. ->set_privacy_filtering_enabled(true);
  371. }
  372. }
  373. if (convert_to_legacy_json) {
  374. for (auto& source : *config.mutable_data_sources()) {
  375. source.mutable_config()
  376. ->mutable_chrome_config()
  377. ->set_convert_to_legacy_json(true);
  378. }
  379. }
  380. threaded_service_->EnableTracingWithConfig(config);
  381. }
  382. bool IsTracingEnabled() {
  383. // Flush any other pending tasks on the perfetto task runner to ensure that
  384. // any pending data source start callbacks have propagated.
  385. task_environment_->RunUntilIdle();
  386. return threaded_service_->IsTracingEnabled();
  387. }
  388. size_t matching_packet_count() const { return matching_packet_count_; }
  389. size_t total_bytes_received() const { return total_bytes_received_; }
  390. ThreadedPerfettoService* threaded_perfetto_service() const {
  391. return threaded_service_.get();
  392. }
  393. private:
  394. std::unique_ptr<ThreadedPerfettoService> threaded_service_;
  395. std::unique_ptr<base::test::TaskEnvironment> task_environment_;
  396. std::unique_ptr<base::test::TracingEnvironment> tracing_environment_;
  397. std::unique_ptr<PerfettoTracedProcess::TestHandle> test_handle_;
  398. base::OnceClosure on_data_complete_;
  399. std::unique_ptr<mojo::DataPipeDrainer> drainer_;
  400. std::vector<uint8_t> received_data_;
  401. std::string packet_testing_str_;
  402. size_t matching_packet_count_ = 0;
  403. size_t total_bytes_received_ = 0;
  404. bool expect_json_data_ = false;
  405. };
  406. TEST_F(TracingConsumerTest, EnableAndDisableTracing) {
  407. EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
  408. base::RunLoop no_more_data;
  409. ExpectPackets(kPerfettoTestString, no_more_data.QuitClosure());
  410. threaded_perfetto_service()->DisableTracing();
  411. ReadBuffers();
  412. no_more_data.Run();
  413. EXPECT_EQ(0u, matching_packet_count());
  414. }
  415. TEST_F(TracingConsumerTest, ReceiveTestPackets) {
  416. EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
  417. base::RunLoop wait_for_tracing_start;
  418. threaded_perfetto_service()->CreateProducer(
  419. mojom::kTraceEventDataSourceName, 10u,
  420. wait_for_tracing_start.QuitClosure());
  421. wait_for_tracing_start.Run();
  422. base::RunLoop no_more_data;
  423. ExpectPackets(kPerfettoTestString, no_more_data.QuitClosure());
  424. threaded_perfetto_service()->DisableTracing();
  425. ReadBuffers();
  426. no_more_data.Run();
  427. EXPECT_EQ(10u, matching_packet_count());
  428. }
  429. TEST_F(TracingConsumerTest, DeleteConsumerWhenReceiving) {
  430. EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
  431. base::RunLoop wait_for_tracing_start;
  432. threaded_perfetto_service()->CreateProducer(
  433. mojom::kTraceEventDataSourceName, 100u,
  434. wait_for_tracing_start.QuitClosure());
  435. wait_for_tracing_start.Run();
  436. base::RunLoop no_more_data;
  437. ExpectPackets(kPerfettoTestString, no_more_data.QuitClosure());
  438. threaded_perfetto_service()->DisableTracing();
  439. ReadBuffers();
  440. threaded_perfetto_service()->ClearConsumer();
  441. no_more_data.Run();
  442. }
  443. TEST_F(TracingConsumerTest, FlushProducers) {
  444. EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
  445. base::RunLoop wait_for_tracing_start;
  446. threaded_perfetto_service()->CreateProducer(
  447. mojom::kTraceEventDataSourceName, 10u,
  448. wait_for_tracing_start.QuitClosure());
  449. wait_for_tracing_start.Run();
  450. base::RunLoop wait_for_packets;
  451. ExpectPackets(kPerfettoTestString, wait_for_packets.QuitClosure());
  452. base::RunLoop wait_for_flush;
  453. threaded_perfetto_service()->Flush(wait_for_flush.QuitClosure());
  454. ReadBuffers();
  455. wait_for_flush.Run();
  456. wait_for_packets.Run();
  457. EXPECT_EQ(10u, matching_packet_count());
  458. }
  459. TEST_F(TracingConsumerTest, LargeDataSize) {
  460. EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
  461. base::RunLoop wait_for_tracing_start;
  462. threaded_perfetto_service()->CreateProducer(
  463. mojom::kTraceEventDataSourceName, 0u,
  464. wait_for_tracing_start.QuitClosure());
  465. wait_for_tracing_start.Run();
  466. base::RunLoop no_more_data;
  467. ExpectPackets(kPerfettoTestString, no_more_data.QuitClosure());
  468. threaded_perfetto_service()->WritePacketBigly();
  469. threaded_perfetto_service()->DisableTracing();
  470. ReadBuffers();
  471. no_more_data.Run();
  472. EXPECT_GE(total_bytes_received(), kLargeMessageSize);
  473. }
  474. TEST_F(TracingConsumerTest, NotifiesOnTracingEnabled) {
  475. threaded_perfetto_service()->SetPidsInitialized();
  476. EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
  477. EXPECT_TRUE(IsTracingEnabled());
  478. }
  479. TEST_F(TracingConsumerTest, NotifiesOnTracingEnabledWaitsForProducer) {
  480. threaded_perfetto_service()->ExpectPid(kProducerPid);
  481. threaded_perfetto_service()->SetPidsInitialized();
  482. EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
  483. // Tracing is only marked as enabled once the expected producer has acked that
  484. // its data source has started.
  485. EXPECT_FALSE(IsTracingEnabled());
  486. base::RunLoop wait_for_tracing_start;
  487. threaded_perfetto_service()->CreateProducer(
  488. mojom::kTraceEventDataSourceName, 0u,
  489. wait_for_tracing_start.QuitClosure());
  490. wait_for_tracing_start.Run();
  491. EXPECT_TRUE(IsTracingEnabled());
  492. }
  493. TEST_F(TracingConsumerTest, NotifiesOnTracingEnabledWaitsForFilteredProducer) {
  494. threaded_perfetto_service()->ExpectPid(kProducerPid);
  495. threaded_perfetto_service()->SetPidsInitialized();
  496. // Filter for the expected producer.
  497. auto config = GetDefaultTraceConfig(mojom::kTraceEventDataSourceName);
  498. *config.mutable_data_sources()->front().add_producer_name_filter() =
  499. base::StrCat({mojom::kPerfettoProducerNamePrefix,
  500. base::NumberToString(kProducerPid)});
  501. threaded_perfetto_service()->EnableTracingWithConfig(config);
  502. // Tracing is only marked as enabled once the expected producer has acked that
  503. // its data source has started.
  504. EXPECT_FALSE(IsTracingEnabled());
  505. base::RunLoop wait_for_tracing_start;
  506. threaded_perfetto_service()->CreateProducer(
  507. mojom::kTraceEventDataSourceName, 0u,
  508. wait_for_tracing_start.QuitClosure());
  509. wait_for_tracing_start.Run();
  510. EXPECT_TRUE(IsTracingEnabled());
  511. }
  512. TEST_F(TracingConsumerTest,
  513. NotifiesOnTracingEnabledDoesNotWaitForUnfilteredProducer) {
  514. threaded_perfetto_service()->ExpectPid(kProducerPid);
  515. threaded_perfetto_service()->SetPidsInitialized();
  516. // Filter for an unexpected producer whose PID is not active.
  517. auto config = GetDefaultTraceConfig(mojom::kTraceEventDataSourceName);
  518. *config.mutable_data_sources()->front().add_producer_name_filter() =
  519. base::StrCat({mojom::kPerfettoProducerNamePrefix,
  520. base::NumberToString(kProducerPid + 1)});
  521. threaded_perfetto_service()->EnableTracingWithConfig(config);
  522. // Tracing should already have been enabled even though the host was told
  523. // about a service with kProducerPid. Since kProducerPid is not included in
  524. // the producer_name_filter, the host should not wait for it.
  525. EXPECT_TRUE(IsTracingEnabled());
  526. }
  527. TEST_F(TracingConsumerTest,
  528. NotifiesOnTracingEnabledWaitsForProducerAndInitializedPids) {
  529. threaded_perfetto_service()->ExpectPid(kProducerPid);
  530. EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName);
  531. // Tracing is only marked as enabled once the expected producer has acked that
  532. // its data source has started and once the PIDs are initialized.
  533. EXPECT_FALSE(IsTracingEnabled());
  534. base::RunLoop wait_for_tracing_start;
  535. threaded_perfetto_service()->CreateProducer(
  536. mojom::kTraceEventDataSourceName, 0u,
  537. wait_for_tracing_start.QuitClosure());
  538. wait_for_tracing_start.Run();
  539. EXPECT_FALSE(IsTracingEnabled());
  540. threaded_perfetto_service()->SetPidsInitialized();
  541. EXPECT_TRUE(IsTracingEnabled());
  542. }
  543. TEST_F(TracingConsumerTest, PrivacyFilterConfig) {
  544. EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName,
  545. /* enable_privacy_filtering =*/true,
  546. /* convert_to_legacy_json =*/false);
  547. base::RunLoop wait_for_tracing_start;
  548. threaded_perfetto_service()->CreateProducer(
  549. mojom::kTraceEventDataSourceName, 10u,
  550. wait_for_tracing_start.QuitClosure());
  551. wait_for_tracing_start.Run();
  552. EXPECT_TRUE(threaded_perfetto_service()
  553. ->GetProducerClientConfig()
  554. .chrome_config()
  555. .privacy_filtering_enabled());
  556. base::trace_event::TraceConfig base_config(threaded_perfetto_service()
  557. ->GetProducerClientConfig()
  558. .chrome_config()
  559. .trace_config());
  560. EXPECT_FALSE(base_config.IsArgumentFilterEnabled());
  561. }
  562. TEST_F(TracingConsumerTest, NoPrivacyFilterWithJsonConversion) {
  563. EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName,
  564. /* enable_privacy_filtering =*/false,
  565. /* convert_to_legacy_json =*/true);
  566. base::RunLoop wait_for_tracing_start;
  567. threaded_perfetto_service()->CreateProducer(
  568. mojom::kTraceEventDataSourceName, 10u,
  569. wait_for_tracing_start.QuitClosure());
  570. wait_for_tracing_start.Run();
  571. EXPECT_FALSE(threaded_perfetto_service()
  572. ->GetProducerClientConfig()
  573. .chrome_config()
  574. .privacy_filtering_enabled());
  575. base::trace_event::TraceConfig base_config(threaded_perfetto_service()
  576. ->GetProducerClientConfig()
  577. .chrome_config()
  578. .trace_config());
  579. EXPECT_FALSE(base_config.IsArgumentFilterEnabled());
  580. }
  581. TEST_F(TracingConsumerTest, PrivacyFilterConfigInJson) {
  582. EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName,
  583. /* enable_privacy_filtering =*/true,
  584. /* convert_to_legacy_json =*/true);
  585. base::RunLoop wait_for_tracing_start;
  586. threaded_perfetto_service()->CreateProducer(
  587. mojom::kTraceEventDataSourceName, 10u,
  588. wait_for_tracing_start.QuitClosure());
  589. wait_for_tracing_start.Run();
  590. EXPECT_FALSE(threaded_perfetto_service()
  591. ->GetProducerClientConfig()
  592. .chrome_config()
  593. .privacy_filtering_enabled());
  594. base::trace_event::TraceConfig base_config(threaded_perfetto_service()
  595. ->GetProducerClientConfig()
  596. .chrome_config()
  597. .trace_config());
  598. EXPECT_TRUE(base_config.IsArgumentFilterEnabled());
  599. base::RunLoop no_more_data;
  600. ExpectPackets("\"trace_processor_stats\":\"__stripped__\"",
  601. no_more_data.QuitClosure());
  602. base::RunLoop write_done;
  603. DisableTracingAndEmitJson(write_done.QuitClosure(),
  604. /* enable_privacy_filtering =*/true);
  605. no_more_data.Run();
  606. write_done.Run();
  607. EXPECT_EQ(1u, matching_packet_count());
  608. }
  609. class MockConsumerHost : public mojom::TracingSessionClient {
  610. public:
  611. explicit MockConsumerHost(PerfettoService* service)
  612. : consumer_host_(std::make_unique<ConsumerHost>(service)) {}
  613. void EnableTracing(const perfetto::TraceConfig& config) {
  614. mojo::PendingRemote<tracing::mojom::TracingSessionClient>
  615. tracing_session_client;
  616. receiver_.Bind(tracing_session_client.InitWithNewPipeAndPassReceiver());
  617. receiver_.set_disconnect_handler(base::BindOnce(
  618. &MockConsumerHost::OnConnectionLost, base::Unretained(this)));
  619. consumer_host_->EnableTracing(
  620. tracing_session_host_.BindNewPipeAndPassReceiver(),
  621. std::move(tracing_session_client), config, base::File());
  622. tracing_session_host_.set_disconnect_handler(base::BindOnce(
  623. &MockConsumerHost::OnConnectionLost, base::Unretained(this)));
  624. }
  625. void DisableTracing() { tracing_session_host_->DisableTracing(); }
  626. void OnConnectionLost() {
  627. CloseTracingSession();
  628. wait_for_connection_lost_.Quit();
  629. }
  630. void CloseTracingSession() {
  631. tracing_session_host_.reset();
  632. receiver_.reset();
  633. }
  634. // mojom::TracingSessionClient implementation:
  635. void OnTracingEnabled() override { wait_for_tracing_enabled_.Quit(); }
  636. void OnTracingDisabled(bool) override { wait_for_tracing_disabled_.Quit(); }
  637. void WaitForConnectionLost() { wait_for_connection_lost_.Run(); }
  638. void WaitForTracingEnabled() { wait_for_tracing_enabled_.Run(); }
  639. void WaitForTracingDisabled() { wait_for_tracing_disabled_.Run(); }
  640. private:
  641. mojo::Remote<tracing::mojom::TracingSessionHost> tracing_session_host_;
  642. mojo::Receiver<mojom::TracingSessionClient> receiver_{this};
  643. std::unique_ptr<ConsumerHost> consumer_host_;
  644. base::RunLoop wait_for_connection_lost_;
  645. base::RunLoop wait_for_tracing_enabled_;
  646. base::RunLoop wait_for_tracing_disabled_;
  647. };
  648. TEST_F(TracingConsumerTest, TestConsumerPriority) {
  649. PerfettoService::GetInstance()->SetActiveServicePidsInitialized();
  650. auto trace_config_background =
  651. GetDefaultTraceConfig(mojom::kTraceEventDataSourceName,
  652. perfetto::protos::gen ::ChromeConfig::BACKGROUND);
  653. auto trace_config_user_initiated = GetDefaultTraceConfig(
  654. mojom::kTraceEventDataSourceName,
  655. perfetto::protos::gen ::ChromeConfig::USER_INITIATED);
  656. MockConsumerHost background_consumer_1(PerfettoService::GetInstance());
  657. background_consumer_1.EnableTracing(trace_config_background);
  658. background_consumer_1.WaitForTracingEnabled();
  659. // Second consumer of the same priority should cause the first one to
  660. // be disabled and the second to start.
  661. MockConsumerHost background_consumer_2(PerfettoService::GetInstance());
  662. background_consumer_2.EnableTracing(trace_config_background);
  663. background_consumer_1.WaitForTracingDisabled();
  664. background_consumer_2.WaitForTracingEnabled();
  665. // Third consumer will have a higher priority, and should kill the second
  666. // one.
  667. MockConsumerHost user_initiated_consumer(PerfettoService::GetInstance());
  668. user_initiated_consumer.EnableTracing(trace_config_user_initiated);
  669. background_consumer_2.WaitForTracingDisabled();
  670. user_initiated_consumer.WaitForTracingEnabled();
  671. // Fourth consumer will be another background consumer, and should be
  672. // itself killed as the third consumer is still running.
  673. MockConsumerHost background_consumer_3(PerfettoService::GetInstance());
  674. background_consumer_3.EnableTracing(trace_config_background);
  675. background_consumer_3.WaitForConnectionLost();
  676. // If we close the user initiated consumer, the third background consumer
  677. // should now be able to trace.
  678. user_initiated_consumer.DisableTracing();
  679. user_initiated_consumer.WaitForTracingDisabled();
  680. user_initiated_consumer.CloseTracingSession();
  681. background_consumer_3.EnableTracing(trace_config_background);
  682. background_consumer_3.WaitForTracingEnabled();
  683. }
  684. } // namespace tracing