#include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h"
#include <cstdint>
#include <limits>
#include <memory>
#include <vector>
#include "base/at_exit.h"
#include "base/functional/bind.h"
#include "base/json/json_reader.h"
#include "base/profiler/frame.h"
#include "base/profiler/module_cache.h"
#include "base/profiler/register_context.h"
#include "base/profiler/stack_sampling_profiler.h"
#include "base/profiler/stack_sampling_profiler_test_util.h"
#include "base/profiler/unwinder.h"
#include "base/run_loop.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread.h"
#include "base/trace_event/trace_buffer.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_log.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 "services/tracing/public/cpp/perfetto/trace_event_data_source.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pb.h"
#if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING)
#include "base/test/trace_event_analyzer.h"
#include "services/tracing/public/cpp/stack_sampling/loader_lock_sampler_win.h"
#include "services/tracing/public/cpp/stack_sampling/loader_lock_sampling_thread_win.h"
#endif
#if BUILDFLAG(IS_MAC)
#include "base/mac/mac_util.h"
#endif
namespace tracing {
namespace {
TraceLog;
TracePacket;
_;
AtLeast;
Invoke;
Return;
using PacketVector = TestProducerClient::PacketVector;
std::unique_ptr<perfetto::TracingSession> g_tracing_session;
#if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING)
class MockLoaderLockSampler : public LoaderLockSampler {
public:
MockLoaderLockSampler() = default;
~MockLoaderLockSampler() override = default;
MOCK_METHOD(bool, IsLoaderLockHeld, (), (const, override));
};
class LoaderLockEventAnalyzer {
public:
LoaderLockEventAnalyzer() {
trace_analyzer::Start(TRACE_DISABLED_BY_DEFAULT("cpu_profiler"));
}
size_t CountEvents() {
std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer =
trace_analyzer::Stop();
trace_analyzer::TraceEventVector events;
return analyzer->FindEvents(
trace_analyzer::Query::EventName() ==
trace_analyzer::Query::String(
LoaderLockSamplingThread::kLoaderLockHeldEventName),
&events);
}
};
#endif
class TracingSampleProfilerTest : public testing::Test { … };
class MockUnwinder : public base::Unwinder { … };
base::StackSamplingProfiler::UnwindersFactory
MakeMockUnwinderFactoryWithExpectations() { … }
}
TEST_F(TracingSampleProfilerTest, OnSampleCompleted) { … }
#if defined(THREAD_SANITIZER)
#define MAYBE_JoinRunningTracing …
#else
#define MAYBE_JoinRunningTracing …
#endif
TEST_F(TracingSampleProfilerTest, MAYBE_JoinRunningTracing) { … }
TEST_F(TracingSampleProfilerTest, TestStartupTracing) { … }
TEST_F(TracingSampleProfilerTest, JoinStartupTracing) { … }
#if defined(THREAD_SANITIZER)
#define MAYBE_SamplingChildThread …
#else
#define MAYBE_SamplingChildThread …
#endif
TEST_F(TracingSampleProfilerTest, MAYBE_SamplingChildThread) { … }
#if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING)
TEST_F(TracingSampleProfilerTest, SampleLoaderLockOnMainThread) {
LoaderLockEventAnalyzer event_analyzer;
bool lock_held = false;
size_t call_count = 0;
EXPECT_CALL(mock_loader_lock_sampler_, IsLoaderLockHeld())
.WillRepeatedly(Invoke([&lock_held, &call_count]() {
++call_count;
lock_held = !lock_held;
return lock_held;
}));
auto profiler = TracingSamplerProfiler::CreateOnMainThread();
BeginTrace();
base::RunLoop().RunUntilIdle();
WaitForEvents();
EndTracing();
base::RunLoop().RunUntilIdle();
ASSERT_GE(call_count, 1U);
EXPECT_EQ(event_analyzer.CountEvents(), call_count);
}
TEST_F(TracingSampleProfilerTest, SampleLoaderLockAlwaysHeld) {
LoaderLockEventAnalyzer event_analyzer;
EXPECT_CALL(mock_loader_lock_sampler_, IsLoaderLockHeld())
.WillRepeatedly(Return(true));
auto profiler = TracingSamplerProfiler::CreateOnMainThread();
BeginTrace();
base::RunLoop().RunUntilIdle();
WaitForEvents();
EndTracing();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(event_analyzer.CountEvents(), 1U);
}
TEST_F(TracingSampleProfilerTest, SampleLoaderLockNeverHeld) {
LoaderLockEventAnalyzer event_analyzer;
EXPECT_CALL(mock_loader_lock_sampler_, IsLoaderLockHeld())
.WillRepeatedly(Return(false));
auto profiler = TracingSamplerProfiler::CreateOnMainThread();
BeginTrace();
base::RunLoop().RunUntilIdle();
WaitForEvents();
EndTracing();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(event_analyzer.CountEvents(), 0U);
}
TEST_F(TracingSampleProfilerTest, SampleLoaderLockOnChildThread) {
LoaderLockEventAnalyzer event_analyzer;
EXPECT_CALL(mock_loader_lock_sampler_, IsLoaderLockHeld()).Times(0);
base::Thread sampled_thread("sampling_profiler_test");
sampled_thread.Start();
sampled_thread.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&TracingSamplerProfiler::CreateOnChildThread));
BeginTrace();
base::RunLoop().RunUntilIdle();
WaitForEvents();
EndTracing();
sampled_thread.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&TracingSamplerProfiler::DeleteOnChildThreadForTesting));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(event_analyzer.CountEvents(), 0U);
}
TEST_F(TracingSampleProfilerTest, SampleLoaderLockWithoutMock) {
LoaderLockSamplingThread::SetLoaderLockSamplerForTesting(nullptr);
auto profiler = TracingSamplerProfiler::CreateOnMainThread();
BeginTrace();
base::RunLoop().RunUntilIdle();
WaitForEvents();
EndTracing();
base::RunLoop().RunUntilIdle();
}
#endif
class TracingProfileBuilderTest : public TracingUnitTest { … };
TEST_F(TracingProfileBuilderTest, ValidModule) { … }
TEST_F(TracingProfileBuilderTest, InvalidModule) { … }
}