test_utils.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. // Copyright 2018 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/test_utils.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/run_loop.h"
  8. #include "base/tracing/perfetto_platform.h"
  9. #include "services/tracing/public/cpp/perfetto/shared_memory.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. #include "third_party/perfetto/include/perfetto/ext/tracing/core/commit_data_request.h"
  12. #include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_packet.h"
  13. #include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h"
  14. #include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h"
  15. #include "third_party/perfetto/protos/perfetto/trace/test_event.pbzero.h"
  16. #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pb.h"
  17. #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h"
  18. namespace tracing {
  19. namespace {
  20. perfetto::TraceConfig GetDefaultTraceConfig(
  21. const std::vector<std::string>& data_sources) {
  22. perfetto::TraceConfig trace_config;
  23. trace_config.add_buffers()->set_size_kb(1024 * 32);
  24. for (const auto& data_source : data_sources) {
  25. auto* ds_config = trace_config.add_data_sources()->mutable_config();
  26. ds_config->set_name(data_source);
  27. ds_config->set_target_buffer(0);
  28. }
  29. return trace_config;
  30. }
  31. } // namespace
  32. // static
  33. std::unique_ptr<TestDataSource> TestDataSource::CreateAndRegisterDataSource(
  34. const std::string& data_source_name,
  35. size_t send_packet_count) {
  36. auto data_source = std::unique_ptr<TestDataSource>(
  37. new TestDataSource(data_source_name, send_packet_count));
  38. PerfettoTracedProcess::Get()->AddDataSource(data_source.get());
  39. return data_source;
  40. }
  41. TestDataSource::TestDataSource(const std::string& data_source_name,
  42. size_t send_packet_count)
  43. : DataSourceBase(data_source_name), send_packet_count_(send_packet_count) {
  44. }
  45. TestDataSource::~TestDataSource() = default;
  46. void TestDataSource::WritePacketBigly() {
  47. std::unique_ptr<char[]> payload(new char[kLargeMessageSize]);
  48. memset(payload.get(), '.', kLargeMessageSize);
  49. payload.get()[kLargeMessageSize - 1] = 0;
  50. std::unique_ptr<perfetto::TraceWriter> writer =
  51. producer_->CreateTraceWriter(config_.target_buffer());
  52. CHECK(writer);
  53. writer->NewTracePacket()->set_for_testing()->set_str(payload.get(),
  54. kLargeMessageSize);
  55. }
  56. void TestDataSource::StartTracingImpl(
  57. PerfettoProducer* producer,
  58. const perfetto::DataSourceConfig& data_source_config) {
  59. producer_ = producer;
  60. config_ = data_source_config;
  61. if (send_packet_count_ > 0) {
  62. std::unique_ptr<perfetto::TraceWriter> writer =
  63. producer_->CreateTraceWriter(config_.target_buffer());
  64. CHECK(writer);
  65. for (size_t i = 0; i < send_packet_count_; i++) {
  66. writer->NewTracePacket()->set_for_testing()->set_str(kPerfettoTestString);
  67. }
  68. }
  69. if (!start_tracing_callback_.is_null()) {
  70. std::move(start_tracing_callback_).Run();
  71. }
  72. }
  73. void TestDataSource::StopTracingImpl(base::OnceClosure stop_complete_callback) {
  74. CHECK(producer_);
  75. producer_ = nullptr;
  76. std::move(stop_complete_callback).Run();
  77. }
  78. void TestDataSource::Flush(base::RepeatingClosure flush_complete_callback) {
  79. if (flush_complete_callback) {
  80. flush_complete_callback.Run();
  81. }
  82. }
  83. void TestDataSource::set_start_tracing_callback(
  84. base::OnceClosure start_tracing_callback) {
  85. start_tracing_callback_ = std::move(start_tracing_callback);
  86. }
  87. MockProducerClient::MockProducerClient(
  88. uint32_t num_data_sources,
  89. base::OnceClosure client_enabled_callback,
  90. base::OnceClosure client_disabled_callback)
  91. : ProducerClient(PerfettoTracedProcess::Get()->GetTaskRunner()),
  92. num_data_sources_expected_(num_data_sources),
  93. client_enabled_callback_(std::move(client_enabled_callback)),
  94. client_disabled_callback_(std::move(client_disabled_callback)) {
  95. // Create SMB immediately since we never call ProducerClient's Connect().
  96. CHECK(InitSharedMemoryIfNeeded());
  97. }
  98. MockProducerClient::~MockProducerClient() = default;
  99. // static
  100. std::unique_ptr<MockProducerClient::Handle> MockProducerClient::Create(
  101. uint32_t num_data_sources,
  102. base::OnceClosure client_enabled_callback,
  103. base::OnceClosure client_disabled_callback) {
  104. std::unique_ptr<MockProducerClient> client(new MockProducerClient(
  105. num_data_sources, std::move(client_enabled_callback),
  106. std::move(client_disabled_callback)));
  107. auto handle = std::make_unique<Handle>(client.get());
  108. // Transfer ownership of the client to PerfettoTracedProcess.
  109. PerfettoTracedProcess::Get()
  110. ->GetTaskRunner()
  111. ->GetOrCreateTaskRunner()
  112. ->PostTask(
  113. FROM_HERE,
  114. base::BindOnce(
  115. [](std::unique_ptr<MockProducerClient> client) {
  116. auto* raw_client = client.get();
  117. raw_client->old_producer_ =
  118. PerfettoTracedProcess::Get()->SetProducerClientForTesting(
  119. std::move(client));
  120. },
  121. std::move(client)));
  122. return handle;
  123. }
  124. MockProducerClient::Handle::~Handle() {
  125. // Replace the previous client in PerfettoTracedProcess, deleting the mock
  126. // as a side-effect.
  127. PerfettoTracedProcess::Get()
  128. ->GetTaskRunner()
  129. ->GetOrCreateTaskRunner()
  130. ->PostTask(
  131. FROM_HERE,
  132. base::BindOnce(
  133. [](std::unique_ptr<ProducerClient> old_producer) {
  134. PerfettoTracedProcess::Get()->SetProducerClientForTesting(
  135. std::move(old_producer));
  136. },
  137. std::move(client_->old_producer_)));
  138. }
  139. void MockProducerClient::SetupDataSource(const std::string& data_source_name) {}
  140. void MockProducerClient::StartDataSource(
  141. uint64_t id,
  142. const perfetto::DataSourceConfig& data_source_config,
  143. StartDataSourceCallback callback) {
  144. ProducerClient::StartDataSource(id, std::move(data_source_config),
  145. std::move(callback));
  146. CHECK_LT(num_data_sources_active_, num_data_sources_expected_);
  147. if (++num_data_sources_active_ == num_data_sources_expected_ &&
  148. client_enabled_callback_) {
  149. std::move(client_enabled_callback_).Run();
  150. }
  151. }
  152. void MockProducerClient::StopDataSource(uint64_t id,
  153. StopDataSourceCallback callback) {
  154. ProducerClient::StopDataSource(id, std::move(callback));
  155. CHECK_GT(num_data_sources_active_, 0u);
  156. if (--num_data_sources_active_ == 0 && client_disabled_callback_) {
  157. std::move(client_disabled_callback_).Run();
  158. }
  159. }
  160. void MockProducerClient::CommitData(const perfetto::CommitDataRequest& commit,
  161. CommitDataCallback callback) {
  162. // Only write out commits that have actual data in it; Perfetto
  163. // might send two commits from different threads (one always empty),
  164. // which causes TSan to complain.
  165. if (commit.chunks_to_patch_size() || commit.chunks_to_move_size()) {
  166. all_client_commit_data_requests_.push_back(commit.SerializeAsString());
  167. }
  168. ProducerClient::CommitData(commit, callback);
  169. }
  170. void MockProducerClient::SetAgentEnabledCallback(
  171. base::OnceClosure client_enabled_callback) {
  172. client_enabled_callback_ = std::move(client_enabled_callback);
  173. }
  174. void MockProducerClient::SetAgentDisabledCallback(
  175. base::OnceClosure client_disabled_callback) {
  176. client_disabled_callback_ = std::move(client_disabled_callback);
  177. }
  178. MockConsumer::MockConsumer(std::vector<std::string> data_source_names,
  179. perfetto::TracingService* service,
  180. PacketReceivedCallback packet_received_callback)
  181. : MockConsumer(data_source_names,
  182. service,
  183. std::move(packet_received_callback),
  184. GetDefaultTraceConfig(data_source_names)) {}
  185. MockConsumer::MockConsumer(std::vector<std::string> data_source_names,
  186. perfetto::TracingService* service,
  187. PacketReceivedCallback packet_received_callback,
  188. const perfetto::TraceConfig& config)
  189. : packet_received_callback_(packet_received_callback),
  190. trace_config_(config) {
  191. for (const auto& source : data_source_names) {
  192. data_sources_.emplace_back(DataSourceStatus{
  193. source,
  194. perfetto::ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STOPPED});
  195. }
  196. CHECK(!data_sources_.empty());
  197. consumer_endpoint_ = service->ConnectConsumer(this, /*uid=*/0);
  198. CHECK(consumer_endpoint_);
  199. }
  200. MockConsumer::~MockConsumer() = default;
  201. void MockConsumer::ReadBuffers() {
  202. CHECK(consumer_endpoint_);
  203. consumer_endpoint_->ReadBuffers();
  204. }
  205. void MockConsumer::StopTracing() {
  206. ReadBuffers();
  207. CHECK(consumer_endpoint_);
  208. consumer_endpoint_->DisableTracing();
  209. }
  210. void MockConsumer::StartTracing() {
  211. CHECK(consumer_endpoint_);
  212. consumer_endpoint_->EnableTracing(trace_config_);
  213. }
  214. void MockConsumer::FreeBuffers() {
  215. CHECK(consumer_endpoint_);
  216. consumer_endpoint_->FreeBuffers();
  217. }
  218. void MockConsumer::OnConnect() {
  219. consumer_endpoint_->ObserveEvents(
  220. perfetto::ObservableEvents::TYPE_DATA_SOURCES_INSTANCES);
  221. StartTracing();
  222. }
  223. void MockConsumer::OnDisconnect() {}
  224. void MockConsumer::OnTracingDisabled(const std::string& error) {}
  225. void MockConsumer::OnTraceData(std::vector<perfetto::TracePacket> packets,
  226. bool has_more) {
  227. for (auto& encoded_packet : packets) {
  228. perfetto::protos::TracePacket packet;
  229. EXPECT_TRUE(packet.ParseFromString(encoded_packet.GetRawBytesForTesting()));
  230. ++received_packets_;
  231. if (packet.for_testing().str() == kPerfettoTestString) {
  232. ++received_test_packets_;
  233. }
  234. }
  235. packet_received_callback_(has_more);
  236. }
  237. void MockConsumer::OnDetach(bool /*success*/) {}
  238. void MockConsumer::OnAttach(bool /*success*/, const perfetto::TraceConfig&) {}
  239. void MockConsumer::OnTraceStats(bool /*success*/, const perfetto::TraceStats&) {
  240. }
  241. void MockConsumer::OnObservableEvents(
  242. const perfetto::ObservableEvents& events) {
  243. for (const auto& change : events.instance_state_changes()) {
  244. for (auto& data_source_status : data_sources_) {
  245. if (change.data_source_name() != data_source_status.name) {
  246. continue;
  247. }
  248. data_source_status.state = change.state();
  249. }
  250. CheckForAllDataSourcesStarted();
  251. CheckForAllDataSourcesStopped();
  252. }
  253. }
  254. void MockConsumer::WaitForAllDataSourcesStarted() {
  255. base::RunLoop on_started;
  256. on_started_runloop_ = &on_started;
  257. CheckForAllDataSourcesStarted();
  258. if (on_started_runloop_) {
  259. on_started_runloop_->Run();
  260. }
  261. }
  262. void MockConsumer::WaitForAllDataSourcesStopped() {
  263. base::RunLoop on_stopped;
  264. on_stopped_runloop_ = &on_stopped;
  265. CheckForAllDataSourcesStopped();
  266. if (on_stopped_runloop_) {
  267. on_stopped_runloop_->Run();
  268. }
  269. }
  270. void MockConsumer::CheckForAllDataSourcesStarted() {
  271. for (auto& data_source_status : data_sources_) {
  272. if (data_source_status.state !=
  273. perfetto::ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED) {
  274. return;
  275. }
  276. }
  277. if (on_started_runloop_) {
  278. on_started_runloop_->Quit();
  279. on_started_runloop_ = nullptr;
  280. }
  281. }
  282. void MockConsumer::CheckForAllDataSourcesStopped() {
  283. for (auto& data_source_status : data_sources_) {
  284. if (data_source_status.state !=
  285. perfetto::ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STOPPED) {
  286. return;
  287. }
  288. }
  289. if (on_stopped_runloop_) {
  290. on_stopped_runloop_->Quit();
  291. on_stopped_runloop_ = nullptr;
  292. }
  293. }
  294. MockProducerHost::MockProducerHost(
  295. const std::string& producer_name,
  296. const std::string& data_source_name,
  297. PerfettoService* service,
  298. MockProducerClient* producer_client,
  299. base::OnceClosure datasource_registered_callback)
  300. : ProducerHost(service->perfetto_task_runner()),
  301. producer_name_(producer_name),
  302. datasource_registered_callback_(
  303. std::move(datasource_registered_callback)) {
  304. mojo::PendingRemote<mojom::ProducerClient> client;
  305. mojo::PendingRemote<mojom::ProducerHost> host_remote;
  306. auto client_receiver = client.InitWithNewPipeAndPassReceiver();
  307. Initialize(std::move(client), service->GetService(), producer_name_,
  308. static_cast<ChromeBaseSharedMemory*>(
  309. producer_client->shared_memory_for_testing())
  310. ->CloneRegion(),
  311. PerfettoProducer::kSMBPageSizeBytes);
  312. receiver_.Bind(host_remote.InitWithNewPipeAndPassReceiver());
  313. producer_client->BindClientAndHostPipesForTesting(std::move(client_receiver),
  314. std::move(host_remote));
  315. producer_client->SetupDataSource(data_source_name);
  316. }
  317. MockProducerHost::~MockProducerHost() = default;
  318. void MockProducerHost::RegisterDataSource(
  319. const perfetto::DataSourceDescriptor& registration_info) {
  320. ProducerHost::RegisterDataSource(registration_info);
  321. on_commit_callback_for_testing_ =
  322. base::BindRepeating(&MockProducerHost::OnCommit, base::Unretained(this));
  323. if (datasource_registered_callback_) {
  324. std::move(datasource_registered_callback_).Run();
  325. }
  326. }
  327. void MockProducerHost::OnConnect() {}
  328. void MockProducerHost::OnCommit(
  329. const perfetto::CommitDataRequest& commit_data_request) {
  330. if (!commit_data_request.chunks_to_patch_size() &&
  331. !commit_data_request.chunks_to_move_size()) {
  332. return;
  333. }
  334. all_host_commit_data_requests_.push_back(
  335. commit_data_request.SerializeAsString());
  336. }
  337. MockProducer::MockProducer(const std::string& producer_name,
  338. const std::string& data_source_name,
  339. PerfettoService* service,
  340. base::OnceClosure on_datasource_registered,
  341. base::OnceClosure on_tracing_started,
  342. size_t num_packets) {
  343. // Construct MockProducerClient before TestDataSource to avoid a race.
  344. //
  345. // TestDataSource calls AddDataSource on the global PerfettoTracedProcess,
  346. // which PostTasks to the threadpool in the task it will access the
  347. // |producer_client_| pointer that the PerfettoTracedProcess owns. However in
  348. // the constructor for MockProducerClient we will set the |producer_client_|
  349. // from the real client to the mock, however this is done on a different
  350. // sequence and thus we have a race. By setting the pointer before we
  351. // construct the data source the TestDataSource can not race.
  352. producer_client_ = MockProducerClient::Create(
  353. /* num_data_sources = */ 1, std::move(on_tracing_started));
  354. data_source_ = TestDataSource::CreateAndRegisterDataSource(data_source_name,
  355. num_packets);
  356. producer_host_ = std::make_unique<MockProducerHost>(
  357. producer_name, data_source_name, service, **producer_client_,
  358. std::move(on_datasource_registered));
  359. }
  360. MockProducer::~MockProducer() = default;
  361. void MockProducer::WritePacketBigly(base::OnceClosure on_write_complete) {
  362. PerfettoTracedProcess::Get()
  363. ->GetTaskRunner()
  364. ->GetOrCreateTaskRunner()
  365. ->PostTaskAndReply(FROM_HERE,
  366. base::BindOnce(&TestDataSource::WritePacketBigly,
  367. base::Unretained(data_source())),
  368. std::move(on_write_complete));
  369. }
  370. TracingUnitTest::TracingUnitTest()
  371. : task_environment_(std::make_unique<base::test::TaskEnvironment>(
  372. base::test::TaskEnvironment::MainThreadType::IO)),
  373. tracing_environment_(std::make_unique<base::test::TracingEnvironment>(
  374. *task_environment_,
  375. base::ThreadTaskRunnerHandle::Get(),
  376. PerfettoTracedProcess::Get()->perfetto_platform_for_testing())) {}
  377. TracingUnitTest::~TracingUnitTest() {
  378. CHECK(setup_called_ && teardown_called_);
  379. }
  380. void TracingUnitTest::SetUp() {
  381. setup_called_ = true;
  382. // Also tell PerfettoTracedProcess to use the current task environment.
  383. test_handle_ = PerfettoTracedProcess::SetupForTesting(
  384. base::ThreadTaskRunnerHandle::Get());
  385. PerfettoTracedProcess::Get()->OnThreadPoolAvailable(
  386. /* enable_consumer */ true);
  387. // Wait for any posted construction tasks to execute.
  388. RunUntilIdle();
  389. }
  390. void TracingUnitTest::TearDown() {
  391. teardown_called_ = true;
  392. tracing_environment_.reset();
  393. // Wait for any posted destruction tasks to execute.
  394. RunUntilIdle();
  395. // From here on, no more tasks should be posted.
  396. task_environment_.reset();
  397. // Clear task runner and data sources.
  398. PerfettoTracedProcess::Get()->GetTaskRunner()->ResetTaskRunnerForTesting(
  399. nullptr);
  400. PerfettoTracedProcess::Get()->ClearDataSourcesForTesting();
  401. test_handle_.reset();
  402. }
  403. } // namespace tracing