diff --git a/services/tracing/BUILD.gn b/services/tracing/BUILD.gn index e879ab855b458..2f64bca49737b 100644 --- a/services/tracing/BUILD.gn +++ b/services/tracing/BUILD.gn @@ -64,6 +64,8 @@ source_set("test_utils") { deps = [ ":lib", + "//base", + "//base/test:test_support", "//testing/gtest", "//third_party/perfetto/protos/perfetto/common:lite", "//third_party/perfetto/protos/perfetto/trace:lite", diff --git a/services/tracing/perfetto/perfetto_integration_unittest.cc b/services/tracing/perfetto/perfetto_integration_unittest.cc index 75219f69904a1..d0917abb9eadc 100644 --- a/services/tracing/perfetto/perfetto_integration_unittest.cc +++ b/services/tracing/perfetto/perfetto_integration_unittest.cc @@ -11,7 +11,6 @@ #include "base/run_loop.h" #include "base/strings/strcat.h" #include "base/test/bind.h" -#include "base/test/task_environment.h" #include "base/threading/thread.h" #include "services/tracing/perfetto/perfetto_service.h" #include "services/tracing/perfetto/producer_host.h" @@ -42,44 +41,26 @@ std::string GetPerfettoProducerName() { return base::StrCat({mojom::kPerfettoProducerNamePrefix, "123"}); } -RebindableTaskRunner* GetPerfettoTaskRunner() { - static base::NoDestructor task_runner; - return task_runner.get(); -} - -class PerfettoIntegrationTest : public testing::Test { +class PerfettoIntegrationTest : public TracingUnitTest { public: - PerfettoIntegrationTest() - : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {} - void SetUp() override { - // Run both the client library and the PerfettoTracedProcess on the same - // thread (current thread). - auto* perfetto_task_runner = GetPerfettoTaskRunner(); - auto* perfetto_platform = - PerfettoTracedProcess::Get()->perfetto_platform_for_testing(); - if (!perfetto_platform->did_start_task_runner()) - perfetto_platform->StartTaskRunner(perfetto_task_runner); - perfetto_task_runner->set_task_runner(base::ThreadTaskRunnerHandle::Get()); - - PerfettoTracedProcess::ResetTaskRunnerForTesting( - base::ThreadTaskRunnerHandle::Get()); - PerfettoTracedProcess::Get()->ClearDataSourcesForTesting(); + TracingUnitTest::SetUp(); data_source_ = TestDataSource::CreateAndRegisterDataSource( kPerfettoTestDataSourceName, 0); perfetto_service_ = std::make_unique(); RunUntilIdle(); } - void TearDown() override { perfetto_service_.reset(); } + void TearDown() override { + perfetto_service_.reset(); + TracingUnitTest::TearDown(); + } PerfettoService* perfetto_service() const { return perfetto_service_.get(); } - void RunUntilIdle() { task_environment_.RunUntilIdle(); } protected: std::unique_ptr data_source_; std::unique_ptr perfetto_service_; - base::test::TaskEnvironment task_environment_; }; TEST_F(PerfettoIntegrationTest, ProducerDatasourceInitialized) { diff --git a/services/tracing/perfetto/system_perfetto_unittest.cc b/services/tracing/perfetto/system_perfetto_unittest.cc index d8616b26e5d2f..993201a7a2c90 100644 --- a/services/tracing/perfetto/system_perfetto_unittest.cc +++ b/services/tracing/perfetto/system_perfetto_unittest.cc @@ -18,7 +18,6 @@ #include "base/strings/string_number_conversions.h" #include "base/test/bind.h" #include "base/test/scoped_feature_list.h" -#include "base/test/task_environment.h" #include "base/trace_event/trace_config.h" #include "build/build_config.h" #include "services/tracing/perfetto/perfetto_service.h" @@ -47,7 +46,7 @@ namespace { const char kPerfettoTestDataSourceName[] = "org.chromium.chrome_integration_unittest"; - + std::string GetPerfettoProducerName() { return base::StrCat({mojom::kPerfettoProducerNamePrefix, "123"}); } @@ -92,12 +91,10 @@ class ClearAndRestoreSystemProducerScope { std::unique_ptr saved_producer_; }; -class SystemPerfettoTest : public testing::Test { +class SystemPerfettoTest : public TracingUnitTest { public: - SystemPerfettoTest() - : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) { - PerfettoTracedProcess::ResetTaskRunnerForTesting(); - PerfettoTracedProcess::Get()->ClearDataSourcesForTesting(); + void SetUp() override { + TracingUnitTest::SetUp(); EXPECT_TRUE(tmp_dir_.CreateUniqueTempDir()); // We need to set TMPDIR environment variable because when a new producer @@ -131,6 +128,21 @@ class SystemPerfettoTest : public testing::Test { RunUntilIdle(); } + void TearDown() override { + data_sources_.clear(); + perfetto_service_.reset(); + + if (old_tmp_dir_) { + // Restore the old value back to its initial value. + setenv("TMPDIR", old_tmp_dir_, true); + } else { + // TMPDIR wasn't set originally so unset it. + unsetenv("TMPDIR"); + } + + TracingUnitTest::TearDown(); + } + std::unique_ptr CreateMockPosixSystemProducer( MockSystemService* service, int num_data_sources_expected = 0, @@ -173,24 +185,7 @@ class SystemPerfettoTest : public testing::Test { producer_socket_); } - ~SystemPerfettoTest() override { - RunUntilIdle(); - // The producer client will be destroyed in the next iteration of the test, - // but the sequence it was used on disappears with the - // |task_environment_|. So we reset the sequence so it can be freely - // destroyed. - PerfettoTracedProcess::Get()->producer_client()->ResetSequenceForTesting(); - if (old_tmp_dir_) { - // Restore the old value back to its initial value. - setenv("TMPDIR", old_tmp_dir_, true); - } else { - // TMPDIR wasn't set originally so unset it. - unsetenv("TMPDIR"); - } - } - PerfettoService* local_service() const { return perfetto_service_.get(); } - void RunUntilIdle() { task_environment_.RunUntilIdle(); } // Fork() + executes the perfetto cmdline client with the given args and // returns true if we exited with a success otherwise |stderr_| is populated @@ -243,7 +238,6 @@ class SystemPerfettoTest : public testing::Test { std::string consumer_socket_; std::unique_ptr perfetto_service_; std::vector> data_sources_; - base::test::TaskEnvironment task_environment_; std::string stderr_; const char* old_tmp_dir_ = nullptr; }; diff --git a/services/tracing/perfetto/test_utils.cc b/services/tracing/perfetto/test_utils.cc index 146aaf30c436c..1b9ec942a32ba 100644 --- a/services/tracing/perfetto/test_utils.cc +++ b/services/tracing/perfetto/test_utils.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/run_loop.h" +#include "services/tracing/public/cpp/perfetto/perfetto_platform.h" #include "services/tracing/public/cpp/perfetto/shared_memory.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/perfetto/include/perfetto/ext/tracing/core/commit_data_request.h" @@ -19,6 +20,7 @@ namespace tracing { namespace { + perfetto::TraceConfig GetDefaultTraceConfig( const std::vector& data_sources) { perfetto::TraceConfig trace_config; @@ -30,7 +32,14 @@ perfetto::TraceConfig GetDefaultTraceConfig( } return trace_config; } + +RebindableTaskRunner* GetClientLibTaskRunner() { + static base::NoDestructor task_runner; + return task_runner.get(); +} + } // namespace + // static std::unique_ptr TestDataSource::CreateAndRegisterDataSource( const std::string& data_source_name, @@ -441,4 +450,49 @@ bool RebindableTaskRunner::RunsTasksInCurrentSequence() const { return task_runner_->RunsTasksInCurrentSequence(); } +TracingUnitTest::TracingUnitTest() + : task_environment_(std::make_unique( + base::test::TaskEnvironment::MainThreadType::IO)) {} + +TracingUnitTest::~TracingUnitTest() { + CHECK(setup_called_ && teardown_called_); +} + +void TracingUnitTest::SetUp() { + setup_called_ = true; + + // Since Perfetto's platform backend can only be initialized once in a + // process, we give it a task runner that can outlive the per-test task + // environment. + auto* client_lib_task_runner = GetClientLibTaskRunner(); + auto* perfetto_platform = + PerfettoTracedProcess::Get()->perfetto_platform_for_testing(); + if (!perfetto_platform->did_start_task_runner()) + perfetto_platform->StartTaskRunner(client_lib_task_runner); + client_lib_task_runner->set_task_runner(base::ThreadTaskRunnerHandle::Get()); + + // Also tell PerfettoTracedProcess to use the current task environment. + PerfettoTracedProcess::ResetTaskRunnerForTesting( + base::ThreadTaskRunnerHandle::Get()); + PerfettoTracedProcess::Get()->ClearDataSourcesForTesting(); + + // Wait for any posted construction tasks to execute. + RunUntilIdle(); +} + +void TracingUnitTest::TearDown() { + teardown_called_ = true; + + // Wait for any posted destruction tasks to execute. + RunUntilIdle(); + + // From here on, no more tasks should be posted. + task_environment_.reset(); + + // Clear task runner and data sources. + PerfettoTracedProcess::Get()->GetTaskRunner()->ResetTaskRunnerForTesting( + nullptr); + PerfettoTracedProcess::Get()->ClearDataSourcesForTesting(); +} + } // namespace tracing diff --git a/services/tracing/perfetto/test_utils.h b/services/tracing/perfetto/test_utils.h index 21fedd87a5cc0..3ac3c22b36aa5 100644 --- a/services/tracing/perfetto/test_utils.h +++ b/services/tracing/perfetto/test_utils.h @@ -9,11 +9,13 @@ #include #include +#include "base/test/task_environment.h" #include "mojo/public/cpp/bindings/receiver.h" #include "services/tracing/perfetto/perfetto_service.h" #include "services/tracing/perfetto/producer_host.h" #include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h" #include "services/tracing/public/cpp/perfetto/producer_client.h" +#include "testing/gtest/include/gtest/gtest.h" #include "third_party/perfetto/include/perfetto/ext/tracing/core/consumer.h" #include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h" #include "third_party/perfetto/protos/perfetto/common/observable_events.pb.h" @@ -251,6 +253,25 @@ class RebindableTaskRunner : public base::SequencedTaskRunner { scoped_refptr task_runner_; }; +// Base class for various tracing unit tests, ensuring cleanup of +// PerfettoTracedProcess. Tracing tasks are run on the test thread. +class TracingUnitTest : public testing::Test { + public: + TracingUnitTest(); + ~TracingUnitTest() override; + + void SetUp() override; + void TearDown() override; + + protected: + void RunUntilIdle() { task_environment_->RunUntilIdle(); } + + private: + std::unique_ptr task_environment_; + bool setup_called_ = false; + bool teardown_called_ = false; +}; + } // namespace tracing #endif // SERVICES_TRACING_PERFETTO_TEST_UTILS_H_ diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc index 36b82557244f5..2bf23e281a7bf 100644 --- a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc +++ b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc @@ -21,7 +21,6 @@ #include "base/synchronization/waitable_event.h" #include "base/task/post_task.h" #include "base/task/thread_pool.h" -#include "base/test/task_environment.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread_id_name_manager.h" #include "base/threading/thread_restrictions.h" @@ -31,6 +30,7 @@ #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_log.h" #include "components/tracing/common/tracing_switches.h" +#include "services/tracing/perfetto/test_utils.h" #include "services/tracing/public/cpp/perfetto/macros.h" #include "services/tracing/public/cpp/perfetto/producer_test_utils.h" #include "services/tracing/public/cpp/perfetto/trace_time.h" @@ -62,18 +62,11 @@ constexpr const char kCategoryGroup[] = "foo"; constexpr uint32_t kClockIdAbsolute = 64; constexpr uint32_t kClockIdIncremental = 65; -// Resets trace event data source at destruction. -class ScopedDataSourceReset { - public: - ~ScopedDataSourceReset() { - PerfettoTracedProcess::Get()->ClearDataSourcesForTesting(); - TraceEventDataSource::ResetForTesting(); - } -}; - -class TraceEventDataSourceTest : public testing::Test { +class TraceEventDataSourceTest : public TracingUnitTest { public: void SetUp() override { + TracingUnitTest::SetUp(); + TraceEventDataSource::GetInstance()->RegisterStartupHooks(); // TODO(eseckler): Initialize the entire perfetto client library instead. perfetto::internal::TrackRegistry::InitializeInstance(); @@ -85,10 +78,9 @@ class TraceEventDataSourceTest : public testing::Test { base::trace_event::TraceLog::GetInstance()->process_name(); base::trace_event::TraceLog::GetInstance()->set_process_name(kTestProcess); - PerfettoTracedProcess::ResetTaskRunnerForTesting(); PerfettoTracedProcess::GetTaskRunner()->GetOrCreateTaskRunner(); auto perfetto_wrapper = std::make_unique( - task_environment_.GetMainThreadTaskRunner()); + base::ThreadTaskRunnerHandle::Get()); producer_client_ = std::make_unique(std::move(perfetto_wrapper)); TraceEventMetadataSource::GetInstance()->ResetForTesting(); @@ -97,13 +89,8 @@ class TraceEventDataSourceTest : public testing::Test { void TearDown() override { if (base::trace_event::TraceLog::GetInstance()->IsEnabled()) { base::RunLoop wait_for_tracelog_flush; - - TraceEventDataSource::GetInstance()->StopTracing(base::BindOnce( - [](const base::RepeatingClosure& quit_closure) { - quit_closure.Run(); - }, - wait_for_tracelog_flush.QuitClosure())); - + TraceEventDataSource::GetInstance()->StopTracing( + wait_for_tracelog_flush.QuitClosure()); wait_for_tracelog_flush.Run(); } @@ -116,6 +103,12 @@ class TraceEventDataSourceTest : public testing::Test { base::ThreadIdNameManager::GetInstance()->SetName(old_thread_name_); base::trace_event::TraceLog::GetInstance()->set_process_name( old_process_name_); + + TracingUnitTest::TearDown(); + + // Destroy after task environment shuts down so that no other threads try to + // add trace events. + TraceEventDataSource::ResetForTesting(); } void StartTraceEventDataSource(bool privacy_filtering_enabled = false, @@ -577,13 +570,6 @@ class TraceEventDataSourceTest : public testing::Test { } protected: - // Destroy after task environment shuts down so that no other threads try to - // add trace events. - ScopedDataSourceReset reset_trace_event_source_; - - // Do not add any other members above this member. - base::test::TaskEnvironment task_environment_; - std::unique_ptr producer_client_; uint64_t last_timestamp_ = 0; int64_t last_thread_time_ = 0; @@ -1556,6 +1542,7 @@ class TraceEventDataSourceNoInterningTest : public TraceEventDataSourceTest { void SetUp() override { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kPerfettoDisableInterning); + // Reset the data source to pick it up the command line flag. PerfettoTracedProcess::Get()->ClearDataSourcesForTesting(); TraceEventDataSource::ResetForTesting(); TraceEventDataSourceTest::SetUp(); @@ -1625,7 +1612,7 @@ TEST_F(TraceEventDataSourceTest, StartupTracingTimeout) { // abort and flush as soon the current thread can run tasks. producer_client()->set_startup_tracing_timeout_for_testing(base::TimeDelta()); producer_client()->SetupStartupTracing( - base::trace_event::TraceConfig("foo,cat1,cat2,cat3,-*", ""), + base::trace_event::TraceConfig("foo,-*", ""), /*privacy_filtering_enabled=*/true); // The trace event will be added to the SMB for the (soon to be aborted) @@ -1647,9 +1634,13 @@ TEST_F(TraceEventDataSourceTest, StartupTracingTimeout) { TRACE_EVENT_BEGIN0(kCategoryGroup, "maybe_lost"); base::ScopedAllowBaseSyncPrimitivesForTesting allow; wait_for_start_tracing->Wait(); - // This event can be hit while flushing for startup registry or when - // tracing is started or when already stopped tracing. + // This event can be hit while flushing the startup tracing session, + // or when the subsequent tracing session is started or when even + // that one was already stopped. TRACE_EVENT_BEGIN0(kCategoryGroup, "maybe_lost"); + + // Make sure that this thread's the trace writer is cleared away. + TraceEventDataSource::FlushCurrentThread(); }, std::move(wait_for_start_tracing))); @@ -1665,7 +1656,7 @@ TEST_F(TraceEventDataSourceTest, StartupTracingTimeout) { wait_ptr->Signal(); // Verify that the trace buffer does not have the event added to startup - // registry. + // tracing session. producer_client()->FlushPacketIfPossible(); std::set event_names; for (const auto& packet : producer_client()->finalized_packets()) { @@ -1685,6 +1676,10 @@ TEST_F(TraceEventDataSourceTest, StartupTracingTimeout) { wait_for_stop.QuitClosure())); wait_for_stop.Run(); + + // Make sure that the TraceWriter destruction task posted from the ThreadPool + // task's flush is executed. + RunUntilIdle(); } TEST_F(TraceEventDataSourceTest, TypedArgumentsTracingOff) { diff --git a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc index 9e65c205ccae6..8467e993ea931 100644 --- a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc +++ b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc @@ -10,11 +10,11 @@ #include "base/bind.h" #include "base/json/json_reader.h" #include "base/run_loop.h" -#include "base/test/task_environment.h" #include "base/threading/thread.h" #include "base/trace_event/trace_buffer.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" +#include "services/tracing/perfetto/test_utils.h" #include "services/tracing/public/cpp/buildflags.h" #include "services/tracing/public/cpp/perfetto/producer_test_utils.h" #include "testing/gmock/include/gmock/gmock.h" @@ -67,19 +67,18 @@ class LoaderLockEventAnalyzer { #endif // BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) -class TracingSampleProfilerTest : public testing::Test { +class TracingSampleProfilerTest : public TracingUnitTest { public: TracingSampleProfilerTest() = default; ~TracingSampleProfilerTest() override = default; void SetUp() override { + TracingUnitTest::SetUp(); + events_stack_received_count_ = 0u; - PerfettoTracedProcess::ResetTaskRunnerForTesting(); - PerfettoTracedProcess::GetTaskRunner()->GetOrCreateTaskRunner(); auto perfetto_wrapper = std::make_unique( - task_environment_.GetMainThreadTaskRunner()); - + base::ThreadTaskRunnerHandle::Get()); producer_ = std::make_unique(std::move(perfetto_wrapper), /*log_only_main_thread=*/false); @@ -93,12 +92,13 @@ class TracingSampleProfilerTest : public testing::Test { } void TearDown() override { - // Be sure there is no pending/running tasks. - task_environment_.RunUntilIdle(); - #if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) TracingSamplerProfiler::SetLoaderLockSamplerForTesting(nullptr); #endif + + producer_.reset(); + + TracingUnitTest::TearDown(); } void BeginTrace() { @@ -145,8 +145,6 @@ class TracingSampleProfilerTest : public testing::Test { const TestProducerClient* producer() const { return producer_.get(); } protected: - base::test::TaskEnvironment task_environment_; - // We want our singleton torn down after each test. base::ShadowingAtExitManager at_exit_manager_; base::trace_event::TraceResultBuffer trace_buffer_; @@ -428,26 +426,25 @@ TEST_F(TracingSampleProfilerTest, SampleLoaderLockWithoutMock) { #endif // BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) -class TracingProfileBuilderTest : public testing::Test { +class TracingProfileBuilderTest : public TracingUnitTest { public: void SetUp() override { - PerfettoTracedProcess::ResetTaskRunnerForTesting(); - PerfettoTracedProcess::GetTaskRunner()->GetOrCreateTaskRunner(); + TracingUnitTest::SetUp(); auto perfetto_wrapper = std::make_unique( - task_environment_.GetMainThreadTaskRunner()); + base::ThreadTaskRunnerHandle::Get()); producer_client_ = std::make_unique( std::move(perfetto_wrapper), /*log_only_main_thread=*/false); } - void TearDown() override { producer_client_.reset(); } + void TearDown() override { + producer_client_.reset(); + TracingUnitTest::TearDown(); + } TestProducerClient* producer() { return producer_client_.get(); } private: - // Should be the first member. - base::test::TaskEnvironment task_environment_; - std::unique_ptr producer_client_; }; diff --git a/services/tracing/tracing_service_unittest.cc b/services/tracing/tracing_service_unittest.cc index 1216f1ffdf614..18d9ea6e395e7 100644 --- a/services/tracing/tracing_service_unittest.cc +++ b/services/tracing/tracing_service_unittest.cc @@ -13,7 +13,6 @@ #include "base/strings/string_number_conversions.h" #include "base/test/bind.h" #include "base/test/scoped_feature_list.h" -#include "base/test/task_environment.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/thread.h" #include "build/build_config.h" @@ -41,34 +40,17 @@ #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h" namespace tracing { -namespace { -RebindableTaskRunner* GetPerfettoTaskRunner() { - static base::NoDestructor task_runner; - return task_runner.get(); -} - -} // namespace - -class TracingServiceTest : public testing::Test { +class TracingServiceTest : public TracingUnitTest { public: - TracingServiceTest() : service_(&perfetto_service_) { - // Since Perfetto's platform backend can only be initialized once in a - // process, we give it a task runner that can outlive the per-test task - // environment. - auto* perfetto_task_runner = GetPerfettoTaskRunner(); - auto* perfetto_platform = - PerfettoTracedProcess::Get()->perfetto_platform_for_testing(); - if (!perfetto_platform->did_start_task_runner()) - perfetto_platform->StartTaskRunner(perfetto_task_runner); - perfetto_task_runner->set_task_runner(base::ThreadTaskRunnerHandle::Get()); - - // Also tell PerfettoTracedProcess to use the current task environment. - PerfettoTracedProcess::ResetTaskRunnerForTesting( - base::ThreadTaskRunnerHandle::Get()); + TracingServiceTest() : service_(&perfetto_service_) {} + + void SetUp() override { + TracingUnitTest::SetUp(); perfetto_service()->SetActiveServicePidsInitialized(); } - ~TracingServiceTest() override = default; + + void TearDown() override { TracingUnitTest::TearDown(); } protected: PerfettoService* perfetto_service() { return &perfetto_service_; } @@ -130,7 +112,6 @@ class TracingServiceTest : public testing::Test { } private: - base::test::TaskEnvironment task_environment_; PerfettoService perfetto_service_; TracingService service_;