#include "components/allocation_recorder/testing/crash_verification.h"
#include <algorithm>
#include <iostream>
#include <iterator>
#include <memory>
#include <set>
#include <vector>
#include "base/debug/debugging_buildflags.h"
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/ranges/algorithm.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/allocation_recorder/internal/internal.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/crashpad/crashpad/client/crash_report_database.h"
#include "third_party/crashpad/crashpad/snapshot/minidump/minidump_stream.h"
#include "third_party/crashpad/crashpad/snapshot/minidump/process_snapshot_minidump.h"
#include "third_party/crashpad/crashpad/util/misc/uuid.h"
#if BUILDFLAG(ENABLE_ALLOCATION_STACK_TRACE_RECORDER)
#include "components/allocation_recorder/crash_handler/memory_operation_report.pb.h"
#endif
AssertionFailure;
AssertionResult;
AssertionSuccess;
namespace crashpad {
void PrintTo(const CrashReportDatabase::OperationStatus status,
std::ostream* os) { … }
}
namespace {
class CrashpadIntegration { … };
void CrashpadIntegration::SetUp(const base::FilePath& crashpad_database_path) { … }
void CrashpadIntegration::ShutDown() { … }
void CrashpadIntegration::CrashDatabaseHasReport() { … }
void CrashpadIntegration::ReportHasProcessSnapshot() { … }
std::vector<const crashpad::MinidumpStream*>
CrashpadIntegration::GetAllocationRecorderStreams() { … }
void CrashpadIntegration::TryReadCreatedReport() { … }
void CrashpadIntegration::CheckHasNoAllocationRecorderStream() { … }
#if BUILDFLAG(ENABLE_ALLOCATION_STACK_TRACE_RECORDER)
void CrashpadIntegration::GetAllocationRecorderStream(
const crashpad::MinidumpStream*& allocation_recorder_stream) {
const auto allocation_recorder_streams = GetAllocationRecorderStreams();
ASSERT_EQ(std::size(allocation_recorder_streams), 1ul)
<< "Didn't find expected number of allocation recorder streams.";
ASSERT_NE(allocation_recorder_streams.front(), nullptr)
<< "The only allocation recorder stream is nullptr.";
allocation_recorder_stream = allocation_recorder_streams.front();
}
void CrashpadIntegration::GetPayload(allocation_recorder::Payload& payload) {
ASSERT_NO_FATAL_FAILURE(CrashDatabaseHasReport());
ASSERT_NO_FATAL_FAILURE(ReportHasProcessSnapshot());
const crashpad::MinidumpStream* allocation_recorder_stream;
ASSERT_NO_FATAL_FAILURE(
GetAllocationRecorderStream(allocation_recorder_stream));
const std::vector<uint8_t>& data = allocation_recorder_stream->data();
ASSERT_TRUE(payload.ParseFromArray(std::data(data), std::size(data)))
<< "Failed to parse recorder information "
"from recorder stream.";
}
#endif
}
namespace allocation_recorder::testing {
void VerifyCrashCreatesCrashpadReportWithoutAllocationRecorderStream(
const base::FilePath& crashpad_database_path,
base::OnceClosure crash_function) { … }
#if BUILDFLAG(ENABLE_ALLOCATION_STACK_TRACE_RECORDER)
void VerifyCrashCreatesCrashpadReportWithAllocationRecorderStream(
const base::FilePath& crashpad_database_path,
base::OnceClosure crash_function,
base::OnceCallback<void(const allocation_recorder::Payload& payload)>
payload_verification) {
ASSERT_TRUE(crash_function);
CrashpadIntegration crashpad_integration;
ASSERT_NO_FATAL_FAILURE(crashpad_integration.SetUp(crashpad_database_path));
ASSERT_NO_FATAL_FAILURE(std::move(crash_function).Run());
allocation_recorder::Payload payload;
ASSERT_NO_FATAL_FAILURE(crashpad_integration.GetPayload(payload));
if (payload_verification) {
ASSERT_NO_FATAL_FAILURE(std::move(payload_verification).Run(payload));
}
ASSERT_NO_FATAL_FAILURE(crashpad_integration.ShutDown());
}
void VerifyPayload(const bool expect_report_with_content,
const allocation_recorder::Payload& payload) {
ASSERT_TRUE(payload.has_operation_report());
const auto& operation_report = payload.operation_report();
ASSERT_TRUE(operation_report.has_statistics());
const auto& statistics = operation_report.statistics();
if (expect_report_with_content) {
EXPECT_GT(operation_report.memory_operations_size(), 0);
EXPECT_GT(statistics.total_number_of_operations(), 0ul);
} else {
EXPECT_EQ(operation_report.memory_operations_size(), 0);
EXPECT_EQ(statistics.total_number_of_operations(), 0ul);
}
#if BUILDFLAG(ENABLE_ALLOCATION_TRACE_RECORDER_FULL_REPORTING)
EXPECT_TRUE(statistics.has_total_number_of_collisions());
#endif
}
#endif
}