mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-20 10:43:46 +00:00
Merge master 2ec34e32c2f4 into doc
This commit is contained in:
commit
52af72d371
2
DEPS
2
DEPS
@ -38,7 +38,7 @@ deps = {
|
||||
|
||||
'crashpad/third_party/mini_chromium/mini_chromium':
|
||||
Var('chromium_git') + '/chromium/mini_chromium@' +
|
||||
'9e0d322ae9f87acbe17c4ced025319b4964bf0b7',
|
||||
'62e6015f633dd4acb1610db15a064889315cadaa',
|
||||
'crashpad/third_party/zlib/zlib':
|
||||
Var('chromium_git') + '/chromium/src/third_party/zlib@' +
|
||||
'13dc246a58e4b72104d35f9b1809af95221ebda7',
|
||||
|
@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# coding: utf-8
|
||||
|
||||
# Copyright 2017 The Crashpad Authors. All rights reserved.
|
||||
#
|
||||
@ -18,6 +19,7 @@ import argparse
|
||||
import glob
|
||||
import gyp_crashpad
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
@ -31,7 +33,7 @@ def main(args):
|
||||
default='clang',
|
||||
choices=('clang', 'gcc'),
|
||||
help='The compiler to use, clang by default')
|
||||
(parsed, extra_args) = parser.parse_known_args(args)
|
||||
(parsed, extra_command_line_args) = parser.parse_known_args(args)
|
||||
|
||||
NDK_ERROR=(
|
||||
'NDK must be a valid standalone NDK toolchain.\n' +
|
||||
@ -55,8 +57,11 @@ def main(args):
|
||||
|
||||
ndk_bin_dir = os.path.join(parsed.ndk, 'bin')
|
||||
|
||||
clang_path = os.path.join(ndk_bin_dir, 'clang')
|
||||
extra_args = []
|
||||
|
||||
if parsed.compiler == 'clang':
|
||||
os.environ['CC_target'] = os.path.join(ndk_bin_dir, 'clang')
|
||||
os.environ['CC_target'] = clang_path
|
||||
os.environ['CXX_target'] = os.path.join(ndk_bin_dir, 'clang++')
|
||||
elif parsed.compiler == 'gcc':
|
||||
os.environ['CC_target'] = os.path.join(ndk_bin_dir,
|
||||
@ -64,6 +69,27 @@ def main(args):
|
||||
os.environ['CXX_target'] = os.path.join(ndk_bin_dir,
|
||||
'%s-g++' % arch_triplet)
|
||||
|
||||
# Unlike the Clang build, when using GCC with “unified headers,”
|
||||
# __ANDROID_API__ isn’t set automatically and must be pushed in to the
|
||||
# build. Fish the correct value out of the Clang wrapper script. If unified
|
||||
# headers are not being used, the Clang wrapper won’t mention
|
||||
# __ANDROID_API__, but the standalone toolchain’s <android/api-level.h> will
|
||||
# #define it for both Clang and GCC.
|
||||
#
|
||||
# Unified headers are the way of the future, according to
|
||||
# https://android.googlesource.com/platform/ndk/+/ndk-r14/CHANGELOG.md and
|
||||
# https://android.googlesource.com/platform/ndk/+/master/docs/UnifiedHeaders.md.
|
||||
with open(clang_path, 'r') as file:
|
||||
clang_script_contents = file.read()
|
||||
matches = re.finditer(r'\s-D__ANDROID_API__=([\d]+)\s',
|
||||
clang_script_contents)
|
||||
match = next(matches, None)
|
||||
if match:
|
||||
android_api = int(match.group(1))
|
||||
extra_args.extend(['-D', 'android_api_level=%d' % android_api])
|
||||
if next(matches, None):
|
||||
raise AssertionError('__ANDROID_API__ defined too many times')
|
||||
|
||||
for tool in ('ar', 'nm', 'readelf'):
|
||||
os.environ['%s_target' % tool.upper()] = (
|
||||
os.path.join(ndk_bin_dir, '%s-%s' % (arch_triplet, tool)))
|
||||
@ -72,7 +98,9 @@ def main(args):
|
||||
['-D', 'OS=android',
|
||||
'-D', 'target_arch=%s' % arch,
|
||||
'-D', 'clang=%d' % (1 if parsed.compiler == 'clang' else 0),
|
||||
'-f', 'ninja-android'] + extra_args)
|
||||
'-f', 'ninja-android'] +
|
||||
extra_args +
|
||||
extra_command_line_args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -38,6 +38,11 @@ def main(args):
|
||||
'crashpad_test_test',
|
||||
'crashpad_util_test',
|
||||
]
|
||||
|
||||
if sys.platform == 'win32':
|
||||
tests.append('crashpad_handler_test')
|
||||
tests = sorted(tests)
|
||||
|
||||
for test in tests:
|
||||
print '-' * 80
|
||||
print test
|
||||
|
@ -35,11 +35,11 @@ namespace {
|
||||
// gtest assertions.
|
||||
void SanityCheckContext(const NativeCPUContext& context) {
|
||||
#if defined(ARCH_CPU_X86)
|
||||
ASSERT_EQ(x86_THREAD_STATE32, context.tsh.flavor);
|
||||
ASSERT_EQ(implicit_cast<int>(x86_THREAD_STATE32_COUNT), context.tsh.count);
|
||||
ASSERT_EQ(context.tsh.flavor, x86_THREAD_STATE32);
|
||||
ASSERT_EQ(context.tsh.count, implicit_cast<int>(x86_THREAD_STATE32_COUNT));
|
||||
#elif defined(ARCH_CPU_X86_64)
|
||||
ASSERT_EQ(x86_THREAD_STATE64, context.tsh.flavor);
|
||||
ASSERT_EQ(implicit_cast<int>(x86_THREAD_STATE64_COUNT), context.tsh.count);
|
||||
ASSERT_EQ(context.tsh.flavor, x86_THREAD_STATE64);
|
||||
ASSERT_EQ(context.tsh.count, implicit_cast<int>(x86_THREAD_STATE64_COUNT));
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
@ -57,18 +57,18 @@ void SanityCheckContext(const NativeCPUContext& context) {
|
||||
// 3.4.3 “EFLAGS Register”, and AMD Architecture Programmer’s Manual, Volume
|
||||
// 2: System Programming (24593-3.24), 3.1.6 “RFLAGS Register”.
|
||||
#if defined(ARCH_CPU_X86)
|
||||
EXPECT_EQ(0u, context.uts.ts32.__cs & ~0xffff);
|
||||
EXPECT_EQ(0u, context.uts.ts32.__ds & ~0xffff);
|
||||
EXPECT_EQ(0u, context.uts.ts32.__es & ~0xffff);
|
||||
EXPECT_EQ(0u, context.uts.ts32.__fs & ~0xffff);
|
||||
EXPECT_EQ(0u, context.uts.ts32.__gs & ~0xffff);
|
||||
EXPECT_EQ(0u, context.uts.ts32.__ss & ~0xffff);
|
||||
EXPECT_EQ(2u, context.uts.ts32.__eflags & 0xffc0802a);
|
||||
EXPECT_EQ(context.uts.ts32.__cs & ~0xffff, 0u);
|
||||
EXPECT_EQ(context.uts.ts32.__ds & ~0xffff, 0u);
|
||||
EXPECT_EQ(context.uts.ts32.__es & ~0xffff, 0u);
|
||||
EXPECT_EQ(context.uts.ts32.__fs & ~0xffff, 0u);
|
||||
EXPECT_EQ(context.uts.ts32.__gs & ~0xffff, 0u);
|
||||
EXPECT_EQ(context.uts.ts32.__ss & ~0xffff, 0u);
|
||||
EXPECT_EQ(context.uts.ts32.__eflags & 0xffc0802a, 2u);
|
||||
#elif defined(ARCH_CPU_X86_64)
|
||||
EXPECT_EQ(0u, context.uts.ts64.__cs & ~UINT64_C(0xffff));
|
||||
EXPECT_EQ(0u, context.uts.ts64.__fs & ~UINT64_C(0xffff));
|
||||
EXPECT_EQ(0u, context.uts.ts64.__gs & ~UINT64_C(0xffff));
|
||||
EXPECT_EQ(2u, context.uts.ts64.__rflags & UINT64_C(0xffffffffffc0802a));
|
||||
EXPECT_EQ(context.uts.ts64.__cs & ~UINT64_C(0xffff), 0u);
|
||||
EXPECT_EQ(context.uts.ts64.__fs & ~UINT64_C(0xffff), 0u);
|
||||
EXPECT_EQ(context.uts.ts64.__gs & ~UINT64_C(0xffff), 0u);
|
||||
EXPECT_EQ(context.uts.ts64.__rflags & UINT64_C(0xffffffffffc0802a), 2u);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@ -141,7 +141,7 @@ void TestCaptureContext() {
|
||||
ASSERT_NO_FATAL_FAILURE(SanityCheckContext(context_2));
|
||||
}
|
||||
|
||||
EXPECT_EQ(sp, StackPointerFromContext(context_2));
|
||||
EXPECT_EQ(StackPointerFromContext(context_2), sp);
|
||||
EXPECT_GT(ProgramCounterFromContext(context_2), pc);
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'client.gyp:crashpad_client',
|
||||
'../compat/compat.gyp:crashpad_compat',
|
||||
'../handler/handler.gyp:crashpad_handler',
|
||||
'../test/test.gyp:crashpad_gmock_main',
|
||||
'../test/test.gyp:crashpad_test',
|
||||
|
@ -144,6 +144,11 @@ class CrashReportDatabase {
|
||||
kNoError = 0,
|
||||
|
||||
//! \brief The report that was requested could not be located.
|
||||
//!
|
||||
//! This may occur when the report is present in the database but not in a
|
||||
//! state appropriate for the requested operation, for example, if
|
||||
//! GetReportForUploading() is called to obtain report that’s already in the
|
||||
//! completed state.
|
||||
kReportNotFound,
|
||||
|
||||
//! \brief An error occured while performing a file operation on a crash
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
@ -146,6 +147,17 @@ class CrashReportDatabaseMac : public CrashReportDatabase {
|
||||
OperationStatus RequestUpload(const UUID& uuid) override;
|
||||
|
||||
private:
|
||||
//! \brief Report states for use with LocateCrashReport().
|
||||
//!
|
||||
//! ReportState may be considered to be a bitfield.
|
||||
enum ReportState : uint8_t {
|
||||
kReportStateWrite = 1 << 0, // in kWriteDirectory
|
||||
kReportStatePending = 1 << 1, // in kUploadPendingDirectory
|
||||
kReportStateCompleted = 1 << 2, // in kCompletedDirectory
|
||||
kReportStateAny =
|
||||
kReportStateWrite | kReportStatePending | kReportStateCompleted,
|
||||
};
|
||||
|
||||
//! \brief A private extension of the Report class that maintains bookkeeping
|
||||
//! information of the database.
|
||||
struct UploadReport : public Report {
|
||||
@ -157,10 +169,12 @@ class CrashReportDatabaseMac : public CrashReportDatabase {
|
||||
//! \brief Locates a crash report in the database by UUID.
|
||||
//!
|
||||
//! \param[in] uuid The UUID of the crash report to locate.
|
||||
//! \param[in] desired_state The state of the report to locate, composed of
|
||||
//! ReportState values.
|
||||
//!
|
||||
//! \return The full path to the report file, or an empty path if it cannot be
|
||||
//! found.
|
||||
base::FilePath LocateCrashReport(const UUID& uuid);
|
||||
base::FilePath LocateCrashReport(const UUID& uuid, uint8_t desired_state);
|
||||
|
||||
//! \brief Obtains an exclusive advisory lock on a file.
|
||||
//!
|
||||
@ -392,7 +406,7 @@ CrashReportDatabaseMac::LookUpCrashReport(const UUID& uuid,
|
||||
CrashReportDatabase::Report* report) {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
||||
base::FilePath path = LocateCrashReport(uuid);
|
||||
base::FilePath path = LocateCrashReport(uuid, kReportStateAny);
|
||||
if (path.empty())
|
||||
return kReportNotFound;
|
||||
|
||||
@ -429,7 +443,7 @@ CrashReportDatabaseMac::GetReportForUploading(const UUID& uuid,
|
||||
const Report** report) {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
||||
base::FilePath report_path = LocateCrashReport(uuid);
|
||||
base::FilePath report_path = LocateCrashReport(uuid, kReportStatePending);
|
||||
if (report_path.empty())
|
||||
return kReportNotFound;
|
||||
|
||||
@ -459,7 +473,8 @@ CrashReportDatabaseMac::RecordUploadAttempt(const Report* report,
|
||||
DCHECK(report);
|
||||
DCHECK(successful || id.empty());
|
||||
|
||||
base::FilePath report_path = LocateCrashReport(report->uuid);
|
||||
base::FilePath report_path =
|
||||
LocateCrashReport(report->uuid, kReportStatePending);
|
||||
if (report_path.empty())
|
||||
return kReportNotFound;
|
||||
|
||||
@ -513,7 +528,7 @@ CrashReportDatabase::OperationStatus CrashReportDatabaseMac::SkipReportUpload(
|
||||
|
||||
Metrics::CrashUploadSkipped(reason);
|
||||
|
||||
base::FilePath report_path = LocateCrashReport(uuid);
|
||||
base::FilePath report_path = LocateCrashReport(uuid, kReportStatePending);
|
||||
if (report_path.empty())
|
||||
return kReportNotFound;
|
||||
|
||||
@ -528,7 +543,7 @@ CrashReportDatabase::OperationStatus CrashReportDatabaseMac::DeleteReport(
|
||||
const UUID& uuid) {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
||||
base::FilePath report_path = LocateCrashReport(uuid);
|
||||
base::FilePath report_path = LocateCrashReport(uuid, kReportStateAny);
|
||||
if (report_path.empty())
|
||||
return kReportNotFound;
|
||||
|
||||
@ -544,11 +559,25 @@ CrashReportDatabase::OperationStatus CrashReportDatabaseMac::DeleteReport(
|
||||
return kNoError;
|
||||
}
|
||||
|
||||
base::FilePath CrashReportDatabaseMac::LocateCrashReport(const UUID& uuid) {
|
||||
base::FilePath CrashReportDatabaseMac::LocateCrashReport(
|
||||
const UUID& uuid,
|
||||
uint8_t desired_state) {
|
||||
const std::string target_uuid = uuid.ToString();
|
||||
for (size_t i = 0; i < arraysize(kReportDirectories); ++i) {
|
||||
|
||||
std::vector<std::string> report_directories;
|
||||
if (desired_state & kReportStateWrite) {
|
||||
report_directories.push_back(kWriteDirectory);
|
||||
}
|
||||
if (desired_state & kReportStatePending) {
|
||||
report_directories.push_back(kUploadPendingDirectory);
|
||||
}
|
||||
if (desired_state & kReportStateCompleted) {
|
||||
report_directories.push_back(kCompletedDirectory);
|
||||
}
|
||||
|
||||
for (const std::string& report_directory : report_directories) {
|
||||
base::FilePath path =
|
||||
base_dir_.Append(kReportDirectories[i])
|
||||
base_dir_.Append(report_directory)
|
||||
.Append(target_uuid + "." + kCrashReportFileExtension);
|
||||
|
||||
// Test if the path exists.
|
||||
@ -573,7 +602,8 @@ CrashReportDatabase::OperationStatus CrashReportDatabaseMac::RequestUpload(
|
||||
const UUID& uuid) {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
||||
base::FilePath report_path = LocateCrashReport(uuid);
|
||||
base::FilePath report_path =
|
||||
LocateCrashReport(uuid, kReportStatePending | kReportStateCompleted);
|
||||
if (report_path.empty())
|
||||
return kReportNotFound;
|
||||
|
||||
|
@ -49,17 +49,17 @@ class CrashReportDatabaseTest : public testing::Test {
|
||||
|
||||
void CreateCrashReport(CrashReportDatabase::Report* report) {
|
||||
CrashReportDatabase::NewReport* new_report = nullptr;
|
||||
ASSERT_EQ(CrashReportDatabase::kNoError,
|
||||
db_->PrepareNewCrashReport(&new_report));
|
||||
ASSERT_EQ(db_->PrepareNewCrashReport(&new_report),
|
||||
CrashReportDatabase::kNoError);
|
||||
const char kTest[] = "test";
|
||||
ASSERT_TRUE(LoggingWriteFile(new_report->handle, kTest, sizeof(kTest)));
|
||||
|
||||
UUID uuid;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db_->FinishedWritingCrashReport(new_report, &uuid));
|
||||
EXPECT_EQ(db_->FinishedWritingCrashReport(new_report, &uuid),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db_->LookUpCrashReport(uuid, report));
|
||||
EXPECT_EQ(db_->LookUpCrashReport(uuid, report),
|
||||
CrashReportDatabase::kNoError);
|
||||
ExpectPreparedCrashReport(*report);
|
||||
ASSERT_TRUE(FileExists(report->file_path));
|
||||
}
|
||||
@ -71,14 +71,14 @@ class CrashReportDatabaseTest : public testing::Test {
|
||||
ASSERT_TRUE(settings->GetLastUploadAttemptTime(×[0]));
|
||||
|
||||
const CrashReportDatabase::Report* report = nullptr;
|
||||
ASSERT_EQ(CrashReportDatabase::kNoError,
|
||||
db_->GetReportForUploading(uuid, &report));
|
||||
EXPECT_NE(UUID(), report->uuid);
|
||||
ASSERT_EQ(db_->GetReportForUploading(uuid, &report),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_NE(report->uuid, UUID());
|
||||
EXPECT_FALSE(report->file_path.empty());
|
||||
EXPECT_TRUE(FileExists(report->file_path)) << report->file_path.value();
|
||||
EXPECT_GT(report->creation_time, 0);
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db_->RecordUploadAttempt(report, successful, id));
|
||||
EXPECT_EQ(db_->RecordUploadAttempt(report, successful, id),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
ASSERT_TRUE(settings->GetLastUploadAttemptTime(×[1]));
|
||||
EXPECT_NE(times[1], 0);
|
||||
@ -86,14 +86,14 @@ class CrashReportDatabaseTest : public testing::Test {
|
||||
}
|
||||
|
||||
void ExpectPreparedCrashReport(const CrashReportDatabase::Report& report) {
|
||||
EXPECT_NE(UUID(), report.uuid);
|
||||
EXPECT_NE(report.uuid, UUID());
|
||||
EXPECT_FALSE(report.file_path.empty());
|
||||
EXPECT_TRUE(FileExists(report.file_path)) << report.file_path.value();
|
||||
EXPECT_TRUE(report.id.empty());
|
||||
EXPECT_GT(report.creation_time, 0);
|
||||
EXPECT_FALSE(report.uploaded);
|
||||
EXPECT_EQ(0, report.last_upload_attempt_time);
|
||||
EXPECT_EQ(0, report.upload_attempts);
|
||||
EXPECT_EQ(report.last_upload_attempt_time, 0);
|
||||
EXPECT_EQ(report.upload_attempts, 0);
|
||||
EXPECT_FALSE(report.upload_explicitly_requested);
|
||||
}
|
||||
|
||||
@ -107,8 +107,8 @@ class CrashReportDatabaseTest : public testing::Test {
|
||||
CrashReportDatabase::OperationStatus os = db()->RequestUpload(uuid);
|
||||
|
||||
CrashReportDatabase::Report report;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db_->LookUpCrashReport(uuid, &report));
|
||||
EXPECT_EQ(db_->LookUpCrashReport(uuid, &report),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
return os;
|
||||
}
|
||||
@ -132,7 +132,7 @@ TEST_F(CrashReportDatabaseTest, Initialize) {
|
||||
|
||||
time_t last_upload_attempt_time;
|
||||
ASSERT_TRUE(settings->GetLastUploadAttemptTime(&last_upload_attempt_time));
|
||||
EXPECT_EQ(0, last_upload_attempt_time);
|
||||
EXPECT_EQ(last_upload_attempt_time, 0);
|
||||
|
||||
// Close and reopen the database at the same path.
|
||||
ResetDatabase();
|
||||
@ -143,10 +143,10 @@ TEST_F(CrashReportDatabaseTest, Initialize) {
|
||||
settings = db->GetSettings();
|
||||
|
||||
ASSERT_TRUE(settings->GetClientID(&client_ids[1]));
|
||||
EXPECT_EQ(client_ids[0], client_ids[1]);
|
||||
EXPECT_EQ(client_ids[1], client_ids[0]);
|
||||
|
||||
ASSERT_TRUE(settings->GetLastUploadAttemptTime(&last_upload_attempt_time));
|
||||
EXPECT_EQ(0, last_upload_attempt_time);
|
||||
EXPECT_EQ(last_upload_attempt_time, 0);
|
||||
|
||||
// Check that the database can also be opened by the method that is permitted
|
||||
// to create it.
|
||||
@ -156,16 +156,16 @@ TEST_F(CrashReportDatabaseTest, Initialize) {
|
||||
settings = db->GetSettings();
|
||||
|
||||
ASSERT_TRUE(settings->GetClientID(&client_ids[2]));
|
||||
EXPECT_EQ(client_ids[0], client_ids[2]);
|
||||
EXPECT_EQ(client_ids[2], client_ids[0]);
|
||||
|
||||
ASSERT_TRUE(settings->GetLastUploadAttemptTime(&last_upload_attempt_time));
|
||||
EXPECT_EQ(0, last_upload_attempt_time);
|
||||
EXPECT_EQ(last_upload_attempt_time, 0);
|
||||
|
||||
std::vector<CrashReportDatabase::Report> reports;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, db->GetPendingReports(&reports));
|
||||
EXPECT_EQ(db->GetPendingReports(&reports), CrashReportDatabase::kNoError);
|
||||
EXPECT_TRUE(reports.empty());
|
||||
reports.clear();
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, db->GetCompletedReports(&reports));
|
||||
EXPECT_EQ(db->GetCompletedReports(&reports), CrashReportDatabase::kNoError);
|
||||
EXPECT_TRUE(reports.empty());
|
||||
|
||||
// InitializeWithoutCreating() shouldn’t create a nonexistent database.
|
||||
@ -177,38 +177,38 @@ TEST_F(CrashReportDatabaseTest, Initialize) {
|
||||
|
||||
TEST_F(CrashReportDatabaseTest, NewCrashReport) {
|
||||
CrashReportDatabase::NewReport* new_report;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->PrepareNewCrashReport(&new_report));
|
||||
EXPECT_EQ(db()->PrepareNewCrashReport(&new_report),
|
||||
CrashReportDatabase::kNoError);
|
||||
UUID expect_uuid = new_report->uuid;
|
||||
EXPECT_TRUE(FileExists(new_report->path)) << new_report->path.value();
|
||||
UUID uuid;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->FinishedWritingCrashReport(new_report, &uuid));
|
||||
EXPECT_EQ(expect_uuid, uuid);
|
||||
EXPECT_EQ(db()->FinishedWritingCrashReport(new_report, &uuid),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_EQ(uuid, expect_uuid);
|
||||
|
||||
CrashReportDatabase::Report report;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(uuid, &report));
|
||||
EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
|
||||
CrashReportDatabase::kNoError);
|
||||
ExpectPreparedCrashReport(report);
|
||||
|
||||
std::vector<CrashReportDatabase::Report> reports;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, db()->GetPendingReports(&reports));
|
||||
ASSERT_EQ(1u, reports.size());
|
||||
EXPECT_EQ(report.uuid, reports[0].uuid);
|
||||
EXPECT_EQ(db()->GetPendingReports(&reports), CrashReportDatabase::kNoError);
|
||||
ASSERT_EQ(reports.size(), 1u);
|
||||
EXPECT_EQ(reports[0].uuid, report.uuid);
|
||||
|
||||
reports.clear();
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, db()->GetCompletedReports(&reports));
|
||||
EXPECT_EQ(db()->GetCompletedReports(&reports), CrashReportDatabase::kNoError);
|
||||
EXPECT_TRUE(reports.empty());
|
||||
}
|
||||
|
||||
TEST_F(CrashReportDatabaseTest, ErrorWritingCrashReport) {
|
||||
CrashReportDatabase::NewReport* new_report = nullptr;
|
||||
ASSERT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->PrepareNewCrashReport(&new_report));
|
||||
ASSERT_EQ(db()->PrepareNewCrashReport(&new_report),
|
||||
CrashReportDatabase::kNoError);
|
||||
base::FilePath new_report_path = new_report->path;
|
||||
EXPECT_TRUE(FileExists(new_report_path)) << new_report_path.value();
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->ErrorWritingCrashReport(new_report));
|
||||
EXPECT_EQ(db()->ErrorWritingCrashReport(new_report),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_FALSE(FileExists(new_report_path)) << new_report_path.value();
|
||||
}
|
||||
|
||||
@ -223,14 +223,14 @@ TEST_F(CrashReportDatabaseTest, LookUpCrashReport) {
|
||||
|
||||
{
|
||||
CrashReportDatabase::Report report;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(uuid, &report));
|
||||
EXPECT_EQ(uuid, report.uuid);
|
||||
EXPECT_NE(std::string::npos, report.file_path.value().find(path().value()));
|
||||
EXPECT_EQ(std::string(), report.id);
|
||||
EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_EQ(report.uuid, uuid);
|
||||
EXPECT_NE(report.file_path.value().find(path().value()), std::string::npos);
|
||||
EXPECT_EQ(report.id, std::string());
|
||||
EXPECT_FALSE(report.uploaded);
|
||||
EXPECT_EQ(0, report.last_upload_attempt_time);
|
||||
EXPECT_EQ(0, report.upload_attempts);
|
||||
EXPECT_EQ(report.last_upload_attempt_time, 0);
|
||||
EXPECT_EQ(report.upload_attempts, 0);
|
||||
EXPECT_FALSE(report.upload_explicitly_requested);
|
||||
}
|
||||
|
||||
@ -238,14 +238,14 @@ TEST_F(CrashReportDatabaseTest, LookUpCrashReport) {
|
||||
|
||||
{
|
||||
CrashReportDatabase::Report report;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(uuid, &report));
|
||||
EXPECT_EQ(uuid, report.uuid);
|
||||
EXPECT_NE(std::string::npos, report.file_path.value().find(path().value()));
|
||||
EXPECT_EQ("test", report.id);
|
||||
EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_EQ(report.uuid, uuid);
|
||||
EXPECT_NE(report.file_path.value().find(path().value()), std::string::npos);
|
||||
EXPECT_EQ(report.id, "test");
|
||||
EXPECT_TRUE(report.uploaded);
|
||||
EXPECT_NE(0, report.last_upload_attempt_time);
|
||||
EXPECT_EQ(1, report.upload_attempts);
|
||||
EXPECT_NE(report.last_upload_attempt_time, 0);
|
||||
EXPECT_EQ(report.upload_attempts, 1);
|
||||
EXPECT_FALSE(report.upload_explicitly_requested);
|
||||
}
|
||||
}
|
||||
@ -261,76 +261,76 @@ TEST_F(CrashReportDatabaseTest, RecordUploadAttempt) {
|
||||
UploadReport(reports[2].uuid, true, "abc123");
|
||||
|
||||
std::vector<CrashReportDatabase::Report> query(3);
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(reports[0].uuid, &query[0]));
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(reports[1].uuid, &query[1]));
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(reports[2].uuid, &query[2]));
|
||||
EXPECT_EQ(db()->LookUpCrashReport(reports[0].uuid, &query[0]),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_EQ(db()->LookUpCrashReport(reports[1].uuid, &query[1]),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_EQ(db()->LookUpCrashReport(reports[2].uuid, &query[2]),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
EXPECT_EQ(std::string(), query[0].id);
|
||||
EXPECT_EQ(std::string(), query[1].id);
|
||||
EXPECT_EQ("abc123", query[2].id);
|
||||
EXPECT_EQ(query[0].id, std::string());
|
||||
EXPECT_EQ(query[1].id, std::string());
|
||||
EXPECT_EQ(query[2].id, "abc123");
|
||||
|
||||
EXPECT_FALSE(query[0].uploaded);
|
||||
EXPECT_FALSE(query[1].uploaded);
|
||||
EXPECT_TRUE(query[2].uploaded);
|
||||
|
||||
EXPECT_EQ(0, query[0].last_upload_attempt_time);
|
||||
EXPECT_NE(0, query[1].last_upload_attempt_time);
|
||||
EXPECT_NE(0, query[2].last_upload_attempt_time);
|
||||
EXPECT_EQ(query[0].last_upload_attempt_time, 0);
|
||||
EXPECT_NE(query[1].last_upload_attempt_time, 0);
|
||||
EXPECT_NE(query[2].last_upload_attempt_time, 0);
|
||||
|
||||
EXPECT_EQ(0, query[0].upload_attempts);
|
||||
EXPECT_EQ(1, query[1].upload_attempts);
|
||||
EXPECT_EQ(1, query[2].upload_attempts);
|
||||
EXPECT_EQ(query[0].upload_attempts, 0);
|
||||
EXPECT_EQ(query[1].upload_attempts, 1);
|
||||
EXPECT_EQ(query[2].upload_attempts, 1);
|
||||
|
||||
// Attempt to upload and fail again.
|
||||
UploadReport(reports[1].uuid, false, std::string());
|
||||
|
||||
time_t report_2_upload_time = query[2].last_upload_attempt_time;
|
||||
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(reports[0].uuid, &query[0]));
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(reports[1].uuid, &query[1]));
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(reports[2].uuid, &query[2]));
|
||||
EXPECT_EQ(db()->LookUpCrashReport(reports[0].uuid, &query[0]),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_EQ(db()->LookUpCrashReport(reports[1].uuid, &query[1]),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_EQ(db()->LookUpCrashReport(reports[2].uuid, &query[2]),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
EXPECT_FALSE(query[0].uploaded);
|
||||
EXPECT_FALSE(query[1].uploaded);
|
||||
EXPECT_TRUE(query[2].uploaded);
|
||||
|
||||
EXPECT_EQ(0, query[0].last_upload_attempt_time);
|
||||
EXPECT_EQ(query[0].last_upload_attempt_time, 0);
|
||||
EXPECT_GE(query[1].last_upload_attempt_time, report_2_upload_time);
|
||||
EXPECT_EQ(report_2_upload_time, query[2].last_upload_attempt_time);
|
||||
EXPECT_EQ(query[2].last_upload_attempt_time, report_2_upload_time);
|
||||
|
||||
EXPECT_EQ(0, query[0].upload_attempts);
|
||||
EXPECT_EQ(2, query[1].upload_attempts);
|
||||
EXPECT_EQ(1, query[2].upload_attempts);
|
||||
EXPECT_EQ(query[0].upload_attempts, 0);
|
||||
EXPECT_EQ(query[1].upload_attempts, 2);
|
||||
EXPECT_EQ(query[2].upload_attempts, 1);
|
||||
|
||||
// Third time's the charm: upload and succeed.
|
||||
UploadReport(reports[1].uuid, true, "666hahaha");
|
||||
|
||||
time_t report_1_upload_time = query[1].last_upload_attempt_time;
|
||||
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(reports[0].uuid, &query[0]));
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(reports[1].uuid, &query[1]));
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(reports[2].uuid, &query[2]));
|
||||
EXPECT_EQ(db()->LookUpCrashReport(reports[0].uuid, &query[0]),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_EQ(db()->LookUpCrashReport(reports[1].uuid, &query[1]),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_EQ(db()->LookUpCrashReport(reports[2].uuid, &query[2]),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
EXPECT_FALSE(query[0].uploaded);
|
||||
EXPECT_TRUE(query[1].uploaded);
|
||||
EXPECT_TRUE(query[2].uploaded);
|
||||
|
||||
EXPECT_EQ(0, query[0].last_upload_attempt_time);
|
||||
EXPECT_EQ(query[0].last_upload_attempt_time, 0);
|
||||
EXPECT_GE(query[1].last_upload_attempt_time, report_1_upload_time);
|
||||
EXPECT_EQ(report_2_upload_time, query[2].last_upload_attempt_time);
|
||||
EXPECT_EQ(query[2].last_upload_attempt_time, report_2_upload_time);
|
||||
|
||||
EXPECT_EQ(0, query[0].upload_attempts);
|
||||
EXPECT_EQ(3, query[1].upload_attempts);
|
||||
EXPECT_EQ(1, query[2].upload_attempts);
|
||||
EXPECT_EQ(query[0].upload_attempts, 0);
|
||||
EXPECT_EQ(query[1].upload_attempts, 3);
|
||||
EXPECT_EQ(query[2].upload_attempts, 1);
|
||||
}
|
||||
|
||||
// This test covers both query functions since they are related.
|
||||
@ -349,52 +349,52 @@ TEST_F(CrashReportDatabaseTest, GetCompletedAndNotUploadedReports) {
|
||||
const UUID& report_4_uuid = reports[4].uuid;
|
||||
|
||||
std::vector<CrashReportDatabase::Report> pending;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, db()->GetPendingReports(&pending));
|
||||
EXPECT_EQ(db()->GetPendingReports(&pending), CrashReportDatabase::kNoError);
|
||||
|
||||
std::vector<CrashReportDatabase::Report> completed;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->GetCompletedReports(&completed));
|
||||
EXPECT_EQ(db()->GetCompletedReports(&completed),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
EXPECT_EQ(reports.size(), pending.size());
|
||||
EXPECT_EQ(0u, completed.size());
|
||||
EXPECT_EQ(pending.size(), reports.size());
|
||||
EXPECT_EQ(completed.size(), 0u);
|
||||
|
||||
// Upload one report successfully.
|
||||
UploadReport(report_1_uuid, true, "report1");
|
||||
|
||||
pending.clear();
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, db()->GetPendingReports(&pending));
|
||||
EXPECT_EQ(db()->GetPendingReports(&pending), CrashReportDatabase::kNoError);
|
||||
completed.clear();
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->GetCompletedReports(&completed));
|
||||
EXPECT_EQ(db()->GetCompletedReports(&completed),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
EXPECT_EQ(4u, pending.size());
|
||||
ASSERT_EQ(1u, completed.size());
|
||||
EXPECT_EQ(pending.size(), 4u);
|
||||
ASSERT_EQ(completed.size(), 1u);
|
||||
|
||||
for (const auto& report : pending) {
|
||||
EXPECT_NE(report_1_uuid, report.uuid);
|
||||
EXPECT_NE(report.uuid, report_1_uuid);
|
||||
EXPECT_FALSE(report.file_path.empty());
|
||||
}
|
||||
EXPECT_EQ(report_1_uuid, completed[0].uuid);
|
||||
EXPECT_EQ("report1", completed[0].id);
|
||||
EXPECT_EQ(true, completed[0].uploaded);
|
||||
EXPECT_EQ(completed[0].uuid, report_1_uuid);
|
||||
EXPECT_EQ(completed[0].id, "report1");
|
||||
EXPECT_EQ(completed[0].uploaded, true);
|
||||
EXPECT_GT(completed[0].last_upload_attempt_time, 0);
|
||||
EXPECT_EQ(1, completed[0].upload_attempts);
|
||||
EXPECT_EQ(completed[0].upload_attempts, 1);
|
||||
|
||||
// Fail to upload one report.
|
||||
UploadReport(report_2_uuid, false, std::string());
|
||||
|
||||
pending.clear();
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, db()->GetPendingReports(&pending));
|
||||
EXPECT_EQ(db()->GetPendingReports(&pending), CrashReportDatabase::kNoError);
|
||||
completed.clear();
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->GetCompletedReports(&completed));
|
||||
EXPECT_EQ(db()->GetCompletedReports(&completed),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
EXPECT_EQ(4u, pending.size());
|
||||
ASSERT_EQ(1u, completed.size());
|
||||
EXPECT_EQ(pending.size(), 4u);
|
||||
ASSERT_EQ(completed.size(), 1u);
|
||||
|
||||
for (const auto& report : pending) {
|
||||
if (report.upload_attempts != 0) {
|
||||
EXPECT_EQ(report_2_uuid, report.uuid);
|
||||
EXPECT_EQ(report.uuid, report_2_uuid);
|
||||
EXPECT_GT(report.last_upload_attempt_time, 0);
|
||||
EXPECT_FALSE(report.uploaded);
|
||||
EXPECT_TRUE(report.id.empty());
|
||||
@ -406,25 +406,25 @@ TEST_F(CrashReportDatabaseTest, GetCompletedAndNotUploadedReports) {
|
||||
UploadReport(report_4_uuid, true, "report_4");
|
||||
|
||||
pending.clear();
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, db()->GetPendingReports(&pending));
|
||||
EXPECT_EQ(db()->GetPendingReports(&pending), CrashReportDatabase::kNoError);
|
||||
completed.clear();
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->GetCompletedReports(&completed));
|
||||
EXPECT_EQ(db()->GetCompletedReports(&completed),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
EXPECT_EQ(3u, pending.size());
|
||||
ASSERT_EQ(2u, completed.size());
|
||||
EXPECT_EQ(pending.size(), 3u);
|
||||
ASSERT_EQ(completed.size(), 2u);
|
||||
|
||||
// Succeed the failed report.
|
||||
UploadReport(report_2_uuid, true, "report 2");
|
||||
|
||||
pending.clear();
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, db()->GetPendingReports(&pending));
|
||||
EXPECT_EQ(db()->GetPendingReports(&pending), CrashReportDatabase::kNoError);
|
||||
completed.clear();
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->GetCompletedReports(&completed));
|
||||
EXPECT_EQ(db()->GetCompletedReports(&completed),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
EXPECT_EQ(2u, pending.size());
|
||||
ASSERT_EQ(3u, completed.size());
|
||||
EXPECT_EQ(pending.size(), 2u);
|
||||
ASSERT_EQ(completed.size(), 3u);
|
||||
|
||||
for (const auto& report : pending) {
|
||||
EXPECT_TRUE(report.uuid == report_0_uuid || report.uuid == report_3_uuid);
|
||||
@ -432,26 +432,26 @@ TEST_F(CrashReportDatabaseTest, GetCompletedAndNotUploadedReports) {
|
||||
}
|
||||
|
||||
// Skip upload for one report.
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->SkipReportUpload(
|
||||
report_3_uuid, Metrics::CrashSkippedReason::kUploadsDisabled));
|
||||
EXPECT_EQ(db()->SkipReportUpload(
|
||||
report_3_uuid, Metrics::CrashSkippedReason::kUploadsDisabled),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
pending.clear();
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, db()->GetPendingReports(&pending));
|
||||
EXPECT_EQ(db()->GetPendingReports(&pending), CrashReportDatabase::kNoError);
|
||||
completed.clear();
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->GetCompletedReports(&completed));
|
||||
EXPECT_EQ(db()->GetCompletedReports(&completed),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
ASSERT_EQ(1u, pending.size());
|
||||
ASSERT_EQ(4u, completed.size());
|
||||
ASSERT_EQ(pending.size(), 1u);
|
||||
ASSERT_EQ(completed.size(), 4u);
|
||||
|
||||
EXPECT_EQ(report_0_uuid, pending[0].uuid);
|
||||
EXPECT_EQ(pending[0].uuid, report_0_uuid);
|
||||
|
||||
for (const auto& report : completed) {
|
||||
if (report.uuid == report_3_uuid) {
|
||||
EXPECT_FALSE(report.uploaded);
|
||||
EXPECT_EQ(0, report.upload_attempts);
|
||||
EXPECT_EQ(0, report.last_upload_attempt_time);
|
||||
EXPECT_EQ(report.upload_attempts, 0);
|
||||
EXPECT_EQ(report.last_upload_attempt_time, 0);
|
||||
} else {
|
||||
EXPECT_TRUE(report.uploaded);
|
||||
EXPECT_GT(report.upload_attempts, 0);
|
||||
@ -466,58 +466,74 @@ TEST_F(CrashReportDatabaseTest, DuelingUploads) {
|
||||
CreateCrashReport(&report);
|
||||
|
||||
const CrashReportDatabase::Report* upload_report;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->GetReportForUploading(report.uuid, &upload_report));
|
||||
EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
const CrashReportDatabase::Report* upload_report_2 = nullptr;
|
||||
EXPECT_EQ(CrashReportDatabase::kBusyError,
|
||||
db()->GetReportForUploading(report.uuid, &upload_report_2));
|
||||
EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report_2),
|
||||
CrashReportDatabase::kBusyError);
|
||||
EXPECT_FALSE(upload_report_2);
|
||||
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->RecordUploadAttempt(upload_report, true, std::string()));
|
||||
EXPECT_EQ(db()->RecordUploadAttempt(upload_report, true, std::string()),
|
||||
CrashReportDatabase::kNoError);
|
||||
}
|
||||
|
||||
TEST_F(CrashReportDatabaseTest, UploadAlreadyUploaded) {
|
||||
CrashReportDatabase::Report report;
|
||||
CreateCrashReport(&report);
|
||||
|
||||
const CrashReportDatabase::Report* upload_report;
|
||||
EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_EQ(db()->RecordUploadAttempt(upload_report, true, std::string()),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
const CrashReportDatabase::Report* upload_report_2 = nullptr;
|
||||
EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report_2),
|
||||
CrashReportDatabase::kReportNotFound);
|
||||
EXPECT_FALSE(upload_report_2);
|
||||
}
|
||||
|
||||
TEST_F(CrashReportDatabaseTest, MoveDatabase) {
|
||||
CrashReportDatabase::NewReport* new_report;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->PrepareNewCrashReport(&new_report));
|
||||
EXPECT_EQ(db()->PrepareNewCrashReport(&new_report),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_TRUE(FileExists(new_report->path)) << new_report->path.value();
|
||||
UUID uuid;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->FinishedWritingCrashReport(new_report, &uuid));
|
||||
EXPECT_EQ(db()->FinishedWritingCrashReport(new_report, &uuid),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
RelocateDatabase();
|
||||
|
||||
CrashReportDatabase::Report report;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(uuid, &report));
|
||||
EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
|
||||
CrashReportDatabase::kNoError);
|
||||
ExpectPreparedCrashReport(report);
|
||||
EXPECT_TRUE(FileExists(report.file_path)) << report.file_path.value();
|
||||
}
|
||||
|
||||
TEST_F(CrashReportDatabaseTest, ReportRemoved) {
|
||||
CrashReportDatabase::NewReport* new_report;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->PrepareNewCrashReport(&new_report));
|
||||
EXPECT_EQ(db()->PrepareNewCrashReport(&new_report),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_TRUE(FileExists(new_report->path)) << new_report->path.value();
|
||||
UUID uuid;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->FinishedWritingCrashReport(new_report, &uuid));
|
||||
EXPECT_EQ(db()->FinishedWritingCrashReport(new_report, &uuid),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
CrashReportDatabase::Report report;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(uuid, &report));
|
||||
EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
EXPECT_EQ(0, _wunlink(report.file_path.value().c_str()));
|
||||
EXPECT_EQ(_wunlink(report.file_path.value().c_str()), 0);
|
||||
#else
|
||||
EXPECT_EQ(0, unlink(report.file_path.value().c_str()))
|
||||
EXPECT_EQ(unlink(report.file_path.value().c_str()), 0)
|
||||
<< ErrnoMessage("unlink");
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(CrashReportDatabase::kReportNotFound,
|
||||
db()->LookUpCrashReport(uuid, &report));
|
||||
EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
|
||||
CrashReportDatabase::kReportNotFound);
|
||||
}
|
||||
|
||||
TEST_F(CrashReportDatabaseTest, DeleteReport) {
|
||||
@ -539,34 +555,34 @@ TEST_F(CrashReportDatabaseTest, DeleteReport) {
|
||||
UploadReport(keep_completed.uuid, true, "1");
|
||||
UploadReport(delete_completed.uuid, true, "2");
|
||||
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(keep_completed.uuid, &keep_completed));
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(delete_completed.uuid, &delete_completed));
|
||||
EXPECT_EQ(db()->LookUpCrashReport(keep_completed.uuid, &keep_completed),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_EQ(db()->LookUpCrashReport(delete_completed.uuid, &delete_completed),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
EXPECT_TRUE(FileExists(keep_completed.file_path));
|
||||
EXPECT_TRUE(FileExists(delete_completed.file_path));
|
||||
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->DeleteReport(delete_pending.uuid));
|
||||
EXPECT_EQ(db()->DeleteReport(delete_pending.uuid),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_FALSE(FileExists(delete_pending.file_path));
|
||||
EXPECT_EQ(CrashReportDatabase::kReportNotFound,
|
||||
db()->LookUpCrashReport(delete_pending.uuid, &delete_pending));
|
||||
EXPECT_EQ(CrashReportDatabase::kReportNotFound,
|
||||
db()->DeleteReport(delete_pending.uuid));
|
||||
EXPECT_EQ(db()->LookUpCrashReport(delete_pending.uuid, &delete_pending),
|
||||
CrashReportDatabase::kReportNotFound);
|
||||
EXPECT_EQ(db()->DeleteReport(delete_pending.uuid),
|
||||
CrashReportDatabase::kReportNotFound);
|
||||
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->DeleteReport(delete_completed.uuid));
|
||||
EXPECT_EQ(db()->DeleteReport(delete_completed.uuid),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_FALSE(FileExists(delete_completed.file_path));
|
||||
EXPECT_EQ(CrashReportDatabase::kReportNotFound,
|
||||
db()->LookUpCrashReport(delete_completed.uuid, &delete_completed));
|
||||
EXPECT_EQ(CrashReportDatabase::kReportNotFound,
|
||||
db()->DeleteReport(delete_completed.uuid));
|
||||
EXPECT_EQ(db()->LookUpCrashReport(delete_completed.uuid, &delete_completed),
|
||||
CrashReportDatabase::kReportNotFound);
|
||||
EXPECT_EQ(db()->DeleteReport(delete_completed.uuid),
|
||||
CrashReportDatabase::kReportNotFound);
|
||||
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(keep_pending.uuid, &keep_pending));
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(keep_completed.uuid, &keep_completed));
|
||||
EXPECT_EQ(db()->LookUpCrashReport(keep_pending.uuid, &keep_pending),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_EQ(db()->LookUpCrashReport(keep_completed.uuid, &keep_completed),
|
||||
CrashReportDatabase::kNoError);
|
||||
}
|
||||
|
||||
TEST_F(CrashReportDatabaseTest, DeleteReportEmptyingDatabase) {
|
||||
@ -577,20 +593,20 @@ TEST_F(CrashReportDatabaseTest, DeleteReportEmptyingDatabase) {
|
||||
|
||||
UploadReport(report.uuid, true, "1");
|
||||
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(report.uuid, &report));
|
||||
EXPECT_EQ(db()->LookUpCrashReport(report.uuid, &report),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
EXPECT_TRUE(FileExists(report.file_path));
|
||||
|
||||
// This causes an empty database to be written, make sure this is handled.
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, db()->DeleteReport(report.uuid));
|
||||
EXPECT_EQ(db()->DeleteReport(report.uuid), CrashReportDatabase::kNoError);
|
||||
EXPECT_FALSE(FileExists(report.file_path));
|
||||
}
|
||||
|
||||
TEST_F(CrashReportDatabaseTest, ReadEmptyDatabase) {
|
||||
CrashReportDatabase::Report report;
|
||||
CreateCrashReport(&report);
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, db()->DeleteReport(report.uuid));
|
||||
EXPECT_EQ(db()->DeleteReport(report.uuid), CrashReportDatabase::kNoError);
|
||||
|
||||
// Deleting and the creating another report causes an empty database to be
|
||||
// loaded. Make sure this is handled.
|
||||
@ -608,22 +624,22 @@ TEST_F(CrashReportDatabaseTest, RequestUpload) {
|
||||
const UUID& report_1_uuid = reports[1].uuid;
|
||||
|
||||
// Skipped report gets back to pending state after RequestUpload is called.
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->SkipReportUpload(
|
||||
report_1_uuid, Metrics::CrashSkippedReason::kUploadsDisabled));
|
||||
EXPECT_EQ(db()->SkipReportUpload(
|
||||
report_1_uuid, Metrics::CrashSkippedReason::kUploadsDisabled),
|
||||
CrashReportDatabase::kNoError);
|
||||
|
||||
std::vector<CrashReportDatabase::Report> pending_reports;
|
||||
CrashReportDatabase::OperationStatus os =
|
||||
db()->GetPendingReports(&pending_reports);
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, os);
|
||||
ASSERT_EQ(1u, pending_reports.size());
|
||||
EXPECT_EQ(pending_reports[0].uuid, report_0_uuid);
|
||||
EXPECT_EQ(os, CrashReportDatabase::kNoError);
|
||||
ASSERT_EQ(pending_reports.size(), 1u);
|
||||
EXPECT_EQ(report_0_uuid, pending_reports[0].uuid);
|
||||
|
||||
pending_reports.clear();
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, RequestUpload(report_1_uuid));
|
||||
EXPECT_EQ(RequestUpload(report_1_uuid), CrashReportDatabase::kNoError);
|
||||
os = db()->GetPendingReports(&pending_reports);
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, os);
|
||||
ASSERT_EQ(2u, pending_reports.size());
|
||||
EXPECT_EQ(os, CrashReportDatabase::kNoError);
|
||||
ASSERT_EQ(pending_reports.size(), 2u);
|
||||
|
||||
// Check individual reports.
|
||||
const CrashReportDatabase::Report* expicitly_requested_report;
|
||||
@ -636,35 +652,35 @@ TEST_F(CrashReportDatabaseTest, RequestUpload) {
|
||||
expicitly_requested_report = &pending_reports[0];
|
||||
}
|
||||
|
||||
EXPECT_EQ(report_0_uuid, pending_report->uuid);
|
||||
EXPECT_EQ(pending_report->uuid, report_0_uuid);
|
||||
EXPECT_FALSE(pending_report->upload_explicitly_requested);
|
||||
|
||||
EXPECT_EQ(report_1_uuid, expicitly_requested_report->uuid);
|
||||
EXPECT_EQ(expicitly_requested_report->uuid, report_1_uuid);
|
||||
EXPECT_TRUE(expicitly_requested_report->upload_explicitly_requested);
|
||||
|
||||
// Explicitly requested reports will not have upload_explicitly_requested bit
|
||||
// after getting skipped.
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->SkipReportUpload(
|
||||
report_1_uuid, Metrics::CrashSkippedReason::kUploadsDisabled));
|
||||
EXPECT_EQ(db()->SkipReportUpload(
|
||||
report_1_uuid, Metrics::CrashSkippedReason::kUploadsDisabled),
|
||||
CrashReportDatabase::kNoError);
|
||||
CrashReportDatabase::Report report;
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError,
|
||||
db()->LookUpCrashReport(report_1_uuid, &report));
|
||||
EXPECT_EQ(db()->LookUpCrashReport(report_1_uuid, &report),
|
||||
CrashReportDatabase::kNoError);
|
||||
EXPECT_FALSE(report.upload_explicitly_requested);
|
||||
|
||||
// Pending report gets correctly affected after RequestUpload is called.
|
||||
pending_reports.clear();
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, RequestUpload(report_0_uuid));
|
||||
EXPECT_EQ(RequestUpload(report_0_uuid), CrashReportDatabase::kNoError);
|
||||
os = db()->GetPendingReports(&pending_reports);
|
||||
EXPECT_EQ(CrashReportDatabase::kNoError, os);
|
||||
EXPECT_EQ(1u, pending_reports.size());
|
||||
EXPECT_EQ(pending_reports[0].uuid, report_0_uuid);
|
||||
EXPECT_EQ(os, CrashReportDatabase::kNoError);
|
||||
EXPECT_EQ(pending_reports.size(), 1u);
|
||||
EXPECT_EQ(report_0_uuid, pending_reports[0].uuid);
|
||||
EXPECT_TRUE(pending_reports[0].upload_explicitly_requested);
|
||||
|
||||
// Already uploaded report cannot be requested for the new upload.
|
||||
UploadReport(report_0_uuid, true, "1");
|
||||
EXPECT_EQ(CrashReportDatabase::kCannotRequestUpload,
|
||||
RequestUpload(report_0_uuid));
|
||||
EXPECT_EQ(RequestUpload(report_0_uuid),
|
||||
CrashReportDatabase::kCannotRequestUpload);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -242,8 +242,9 @@ class Metadata {
|
||||
//! written to disk via Write().
|
||||
//!
|
||||
//! \return #kNoError on success. #kReportNotFound if there was no report with
|
||||
//! the specified UUID. #kBusyError if the report was not in the specified
|
||||
//! state.
|
||||
//! the specified UUID, or if the report was not in the specified state
|
||||
//! and was not uploading. #kBusyError if the report was not in the
|
||||
//! specified state and was uploading.
|
||||
OperationStatus FindSingleReportAndMarkDirty(const UUID& uuid,
|
||||
ReportState desired_state,
|
||||
ReportDisk** report_disk);
|
||||
@ -530,9 +531,13 @@ OperationStatus Metadata::VerifyReportAnyState(const ReportDisk& report_disk) {
|
||||
// static
|
||||
OperationStatus Metadata::VerifyReport(const ReportDisk& report_disk,
|
||||
ReportState desired_state) {
|
||||
return (report_disk.state == desired_state)
|
||||
? VerifyReportAnyState(report_disk)
|
||||
: CrashReportDatabase::kBusyError;
|
||||
if (report_disk.state == desired_state) {
|
||||
return VerifyReportAnyState(report_disk);
|
||||
}
|
||||
|
||||
return report_disk.state == ReportState::kUploading
|
||||
? CrashReportDatabase::kBusyError
|
||||
: CrashReportDatabase::kReportNotFound;
|
||||
}
|
||||
|
||||
bool EnsureDirectory(const base::FilePath& path) {
|
||||
@ -876,7 +881,7 @@ OperationStatus CrashReportDatabaseWin::RequestUpload(const UUID& uuid) {
|
||||
// TODO(gayane): Search for the report only once regardless of its state.
|
||||
OperationStatus os = metadata->FindSingleReportAndMarkDirty(
|
||||
uuid, ReportState::kCompleted, &report_disk);
|
||||
if (os == kBusyError) {
|
||||
if (os == kReportNotFound) {
|
||||
os = metadata->FindSingleReportAndMarkDirty(
|
||||
uuid, ReportState::kPending, &report_disk);
|
||||
}
|
||||
|
@ -14,25 +14,31 @@
|
||||
|
||||
#include "client/crashpad_client.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/logging.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/paths.h"
|
||||
#include "test/test_paths.h"
|
||||
#include "test/scoped_temp_dir.h"
|
||||
#include "test/win/win_multiprocess.h"
|
||||
#include "test/win/win_multiprocess_with_temp_dir.h"
|
||||
#include "util/win/scoped_handle.h"
|
||||
#include "util/win/termination_codes.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
void StartAndUseHandler() {
|
||||
ScopedTempDir temp_dir;
|
||||
base::FilePath handler_path = Paths::Executable().DirName().Append(
|
||||
void StartAndUseHandler(const base::FilePath& temp_dir) {
|
||||
base::FilePath handler_path = TestPaths::Executable().DirName().Append(
|
||||
FILE_PATH_LITERAL("crashpad_handler.com"));
|
||||
|
||||
CrashpadClient client;
|
||||
ASSERT_TRUE(client.StartHandler(handler_path,
|
||||
temp_dir.path(),
|
||||
temp_dir,
|
||||
base::FilePath(),
|
||||
"",
|
||||
std::map<std::string, std::string>(),
|
||||
@ -42,9 +48,9 @@ void StartAndUseHandler() {
|
||||
ASSERT_TRUE(client.WaitForHandlerStart(INFINITE));
|
||||
}
|
||||
|
||||
class StartWithInvalidHandles final : public WinMultiprocess {
|
||||
class StartWithInvalidHandles final : public WinMultiprocessWithTempDir {
|
||||
public:
|
||||
StartWithInvalidHandles() : WinMultiprocess() {}
|
||||
StartWithInvalidHandles() : WinMultiprocessWithTempDir() {}
|
||||
~StartWithInvalidHandles() {}
|
||||
|
||||
private:
|
||||
@ -56,7 +62,7 @@ class StartWithInvalidHandles final : public WinMultiprocess {
|
||||
SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE);
|
||||
SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE);
|
||||
|
||||
StartAndUseHandler();
|
||||
StartAndUseHandler(GetTempDirPath());
|
||||
|
||||
SetStdHandle(STD_OUTPUT_HANDLE, original_stdout);
|
||||
SetStdHandle(STD_ERROR_HANDLE, original_stderr);
|
||||
@ -64,12 +70,12 @@ class StartWithInvalidHandles final : public WinMultiprocess {
|
||||
};
|
||||
|
||||
TEST(CrashpadClient, StartWithInvalidHandles) {
|
||||
WinMultiprocess::Run<StartWithInvalidHandles>();
|
||||
WinMultiprocessWithTempDir::Run<StartWithInvalidHandles>();
|
||||
}
|
||||
|
||||
class StartWithSameStdoutStderr final : public WinMultiprocess {
|
||||
class StartWithSameStdoutStderr final : public WinMultiprocessWithTempDir {
|
||||
public:
|
||||
StartWithSameStdoutStderr() : WinMultiprocess() {}
|
||||
StartWithSameStdoutStderr() : WinMultiprocessWithTempDir() {}
|
||||
~StartWithSameStdoutStderr() {}
|
||||
|
||||
private:
|
||||
@ -80,19 +86,19 @@ class StartWithSameStdoutStderr final : public WinMultiprocess {
|
||||
HANDLE original_stderr = GetStdHandle(STD_ERROR_HANDLE);
|
||||
SetStdHandle(STD_OUTPUT_HANDLE, original_stderr);
|
||||
|
||||
StartAndUseHandler();
|
||||
StartAndUseHandler(GetTempDirPath());
|
||||
|
||||
SetStdHandle(STD_OUTPUT_HANDLE, original_stdout);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(CrashpadClient, StartWithSameStdoutStderr) {
|
||||
WinMultiprocess::Run<StartWithSameStdoutStderr>();
|
||||
WinMultiprocessWithTempDir::Run<StartWithSameStdoutStderr>();
|
||||
}
|
||||
|
||||
void StartAndUseBrokenHandler(CrashpadClient* client) {
|
||||
ScopedTempDir temp_dir;
|
||||
base::FilePath handler_path = Paths::Executable().DirName().Append(
|
||||
base::FilePath handler_path = TestPaths::Executable().DirName().Append(
|
||||
FILE_PATH_LITERAL("fake_handler_that_crashes_at_startup.exe"));
|
||||
ASSERT_TRUE(client->StartHandler(handler_path,
|
||||
temp_dir.path(),
|
||||
|
@ -96,10 +96,19 @@ struct CrashpadInfo {
|
||||
//! SimpleStringDictionary object. It is the caller’s responsibility to
|
||||
//! ensure that this pointer remains valid while it is in effect for a
|
||||
//! CrashpadInfo object.
|
||||
//!
|
||||
//! \sa simple_annotations()
|
||||
void set_simple_annotations(SimpleStringDictionary* simple_annotations) {
|
||||
simple_annotations_ = simple_annotations;
|
||||
}
|
||||
|
||||
//! \return The simple annotations dictionary.
|
||||
//!
|
||||
//! \sa set_simple_annotations()
|
||||
SimpleStringDictionary* simple_annotations() const {
|
||||
return simple_annotations_;
|
||||
}
|
||||
|
||||
//! \brief Enables or disables Crashpad handler processing.
|
||||
//!
|
||||
//! When handling an exception, the Crashpad handler will scan all modules in
|
||||
|
@ -185,9 +185,9 @@ TEST(PruneCrashReports, BinaryCondition) {
|
||||
auto rhs = new StaticCondition(test.rhs_value);
|
||||
BinaryPruneCondition condition(test.op, lhs, rhs);
|
||||
CrashReportDatabase::Report report;
|
||||
EXPECT_EQ(test.cond_result, condition.ShouldPruneReport(report));
|
||||
EXPECT_EQ(test.lhs_executed, lhs->did_execute());
|
||||
EXPECT_EQ(test.rhs_executed, rhs->did_execute());
|
||||
EXPECT_EQ(condition.ShouldPruneReport(report), test.cond_result);
|
||||
EXPECT_EQ(lhs->did_execute(), test.lhs_executed);
|
||||
EXPECT_EQ(rhs->did_execute(), test.rhs_executed);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,13 +62,13 @@ class SettingsTest : public testing::Test {
|
||||
TEST_F(SettingsTest, ClientID) {
|
||||
UUID client_id;
|
||||
EXPECT_TRUE(settings()->GetClientID(&client_id));
|
||||
EXPECT_NE(UUID(), client_id);
|
||||
EXPECT_NE(client_id, UUID());
|
||||
|
||||
Settings local_settings(settings_path());
|
||||
EXPECT_TRUE(local_settings.Initialize());
|
||||
UUID actual;
|
||||
EXPECT_TRUE(local_settings.GetClientID(&actual));
|
||||
EXPECT_EQ(client_id, actual);
|
||||
EXPECT_EQ(actual, client_id);
|
||||
}
|
||||
|
||||
TEST_F(SettingsTest, UploadsEnabled) {
|
||||
@ -100,18 +100,18 @@ TEST_F(SettingsTest, LastUploadAttemptTime) {
|
||||
time_t actual = -1;
|
||||
EXPECT_TRUE(settings()->GetLastUploadAttemptTime(&actual));
|
||||
// Default value is 0.
|
||||
EXPECT_EQ(0, actual);
|
||||
EXPECT_EQ(actual, 0);
|
||||
|
||||
const time_t expected = time(nullptr);
|
||||
EXPECT_TRUE(settings()->SetLastUploadAttemptTime(expected));
|
||||
EXPECT_TRUE(settings()->GetLastUploadAttemptTime(&actual));
|
||||
EXPECT_EQ(expected, actual);
|
||||
EXPECT_EQ(actual, expected);
|
||||
|
||||
Settings local_settings(settings_path());
|
||||
EXPECT_TRUE(local_settings.Initialize());
|
||||
actual = -1;
|
||||
EXPECT_TRUE(local_settings.GetLastUploadAttemptTime(&actual));
|
||||
EXPECT_EQ(expected, actual);
|
||||
EXPECT_EQ(actual, expected);
|
||||
}
|
||||
|
||||
// The following tests write a corrupt settings file and test the recovery
|
||||
@ -129,13 +129,13 @@ TEST_F(SettingsTest, BadFileOnGet) {
|
||||
|
||||
UUID client_id;
|
||||
EXPECT_TRUE(settings()->GetClientID(&client_id));
|
||||
EXPECT_NE(UUID(), client_id);
|
||||
EXPECT_NE(client_id, UUID());
|
||||
|
||||
Settings local_settings(settings_path());
|
||||
EXPECT_TRUE(local_settings.Initialize());
|
||||
UUID actual;
|
||||
EXPECT_TRUE(local_settings.GetClientID(&actual));
|
||||
EXPECT_EQ(client_id, actual);
|
||||
EXPECT_EQ(actual, client_id);
|
||||
}
|
||||
|
||||
TEST_F(SettingsTest, BadFileOnSet) {
|
||||
@ -154,10 +154,10 @@ TEST_F(SettingsTest, UnlinkFile) {
|
||||
EXPECT_TRUE(settings()->SetLastUploadAttemptTime(time(nullptr)));
|
||||
|
||||
#if defined(OS_WIN)
|
||||
EXPECT_EQ(0, _wunlink(settings_path().value().c_str()))
|
||||
EXPECT_EQ(_wunlink(settings_path().value().c_str()), 0)
|
||||
<< ErrnoMessage("_wunlink");
|
||||
#else
|
||||
EXPECT_EQ(0, unlink(settings_path().value().c_str()))
|
||||
EXPECT_EQ(unlink(settings_path().value().c_str()), 0)
|
||||
<< ErrnoMessage("unlink");
|
||||
#endif
|
||||
|
||||
@ -165,7 +165,7 @@ TEST_F(SettingsTest, UnlinkFile) {
|
||||
EXPECT_TRUE(local_settings.Initialize());
|
||||
UUID new_client_id;
|
||||
EXPECT_TRUE(local_settings.GetClientID(&new_client_id));
|
||||
EXPECT_NE(client_id, new_client_id);
|
||||
EXPECT_NE(new_client_id, client_id);
|
||||
|
||||
// Check that all values are reset.
|
||||
bool enabled = true;
|
||||
@ -174,7 +174,7 @@ TEST_F(SettingsTest, UnlinkFile) {
|
||||
|
||||
time_t time = -1;
|
||||
EXPECT_TRUE(local_settings.GetLastUploadAttemptTime(&time));
|
||||
EXPECT_EQ(0, time);
|
||||
EXPECT_EQ(time, 0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -32,13 +32,13 @@ TEST(SimpleAddressRangeBag, Entry) {
|
||||
bag.Insert(reinterpret_cast<void*>(0x1000), 200);
|
||||
entry = TestBag::Iterator(bag).Next();
|
||||
ASSERT_TRUE(entry);
|
||||
EXPECT_EQ(entry->base, 0x1000u);
|
||||
EXPECT_EQ(entry->size, 200u);
|
||||
EXPECT_EQ(0x1000u, entry->base);
|
||||
EXPECT_EQ(200u, entry->size);
|
||||
|
||||
bag.Remove(reinterpret_cast<void*>(0x1000), 200);
|
||||
EXPECT_FALSE(entry->is_active());
|
||||
EXPECT_EQ(entry->base, 0u);
|
||||
EXPECT_EQ(entry->size, 0u);
|
||||
EXPECT_EQ(0u, entry->base);
|
||||
EXPECT_EQ(0u, entry->size);
|
||||
}
|
||||
|
||||
TEST(SimpleAddressRangeBag, SimpleAddressRangeBag) {
|
||||
@ -48,24 +48,24 @@ TEST(SimpleAddressRangeBag, SimpleAddressRangeBag) {
|
||||
EXPECT_TRUE(bag.Insert(reinterpret_cast<void*>(0x2000), 20));
|
||||
EXPECT_TRUE(bag.Insert(CheckedRange<uint64_t>(0x3000, 30)));
|
||||
|
||||
EXPECT_EQ(bag.GetCount(), 3u);
|
||||
EXPECT_EQ(3u, bag.GetCount());
|
||||
|
||||
// Duplicates added too.
|
||||
EXPECT_TRUE(bag.Insert(CheckedRange<uint64_t>(0x3000, 30)));
|
||||
EXPECT_TRUE(bag.Insert(CheckedRange<uint64_t>(0x3000, 30)));
|
||||
EXPECT_EQ(bag.GetCount(), 5u);
|
||||
EXPECT_EQ(5u, bag.GetCount());
|
||||
|
||||
// Can be removed 3 times, but not the 4th time.
|
||||
EXPECT_TRUE(bag.Remove(CheckedRange<uint64_t>(0x3000, 30)));
|
||||
EXPECT_TRUE(bag.Remove(CheckedRange<uint64_t>(0x3000, 30)));
|
||||
EXPECT_TRUE(bag.Remove(CheckedRange<uint64_t>(0x3000, 30)));
|
||||
EXPECT_EQ(bag.GetCount(), 2u);
|
||||
EXPECT_EQ(2u, bag.GetCount());
|
||||
EXPECT_FALSE(bag.Remove(CheckedRange<uint64_t>(0x3000, 30)));
|
||||
EXPECT_EQ(bag.GetCount(), 2u);
|
||||
EXPECT_EQ(2u, bag.GetCount());
|
||||
|
||||
EXPECT_TRUE(bag.Remove(reinterpret_cast<void*>(0x1000), 10));
|
||||
EXPECT_TRUE(bag.Remove(reinterpret_cast<void*>(0x2000), 20));
|
||||
EXPECT_EQ(bag.GetCount(), 0u);
|
||||
EXPECT_EQ(0u, bag.GetCount());
|
||||
}
|
||||
|
||||
TEST(SimpleAddressRangeBag, CopyAndAssign) {
|
||||
@ -74,24 +74,24 @@ TEST(SimpleAddressRangeBag, CopyAndAssign) {
|
||||
EXPECT_TRUE(bag.Insert(CheckedRange<uint64_t>(3, 4)));
|
||||
EXPECT_TRUE(bag.Insert(CheckedRange<uint64_t>(5, 6)));
|
||||
EXPECT_TRUE(bag.Remove(CheckedRange<uint64_t>(3, 4)));
|
||||
EXPECT_EQ(2u, bag.GetCount());
|
||||
EXPECT_EQ(bag.GetCount(), 2u);
|
||||
|
||||
// Test copy.
|
||||
TSimpleAddressRangeBag<10> bag_copy(bag);
|
||||
EXPECT_EQ(2u, bag_copy.GetCount());
|
||||
EXPECT_EQ(bag_copy.GetCount(), 2u);
|
||||
EXPECT_TRUE(bag_copy.Remove(CheckedRange<uint64_t>(1, 2)));
|
||||
EXPECT_TRUE(bag_copy.Remove(CheckedRange<uint64_t>(5, 6)));
|
||||
EXPECT_EQ(0u, bag_copy.GetCount());
|
||||
EXPECT_EQ(2u, bag.GetCount());
|
||||
EXPECT_EQ(bag_copy.GetCount(), 0u);
|
||||
EXPECT_EQ(bag.GetCount(), 2u);
|
||||
|
||||
// Test assign.
|
||||
TSimpleAddressRangeBag<10> bag_assign;
|
||||
bag_assign = bag;
|
||||
EXPECT_EQ(2u, bag_assign.GetCount());
|
||||
EXPECT_EQ(bag_assign.GetCount(), 2u);
|
||||
EXPECT_TRUE(bag_assign.Remove(CheckedRange<uint64_t>(1, 2)));
|
||||
EXPECT_TRUE(bag_assign.Remove(CheckedRange<uint64_t>(5, 6)));
|
||||
EXPECT_EQ(0u, bag_assign.GetCount());
|
||||
EXPECT_EQ(2u, bag.GetCount());
|
||||
EXPECT_EQ(bag_assign.GetCount(), 0u);
|
||||
EXPECT_EQ(bag.GetCount(), 2u);
|
||||
}
|
||||
|
||||
// Running out of space shouldn't crash.
|
||||
@ -100,7 +100,7 @@ TEST(SimpleAddressRangeBag, OutOfSpace) {
|
||||
EXPECT_TRUE(bag.Insert(CheckedRange<uint64_t>(1, 2)));
|
||||
EXPECT_TRUE(bag.Insert(CheckedRange<uint64_t>(3, 4)));
|
||||
EXPECT_FALSE(bag.Insert(CheckedRange<uint64_t>(5, 6)));
|
||||
EXPECT_EQ(2u, bag.GetCount());
|
||||
EXPECT_EQ(bag.GetCount(), 2u);
|
||||
EXPECT_FALSE(bag.Remove(CheckedRange<uint64_t>(5, 6)));
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,8 @@ TEST(SimpleStringDictionary, Entry) {
|
||||
// Clear the entry and verify the key and value are empty strings.
|
||||
map.RemoveKey("key1");
|
||||
EXPECT_FALSE(entry->is_active());
|
||||
EXPECT_EQ(strlen(entry->key), 0u);
|
||||
EXPECT_EQ(strlen(entry->value), 0u);
|
||||
EXPECT_EQ(0u, strlen(entry->key));
|
||||
EXPECT_EQ(0u, strlen(entry->value));
|
||||
}
|
||||
|
||||
TEST(SimpleStringDictionary, SimpleStringDictionary) {
|
||||
@ -62,7 +62,7 @@ TEST(SimpleStringDictionary, SimpleStringDictionary) {
|
||||
EXPECT_NE(dict.GetValueForKey("key1"), "value1");
|
||||
EXPECT_NE(dict.GetValueForKey("key2"), "value2");
|
||||
EXPECT_NE(dict.GetValueForKey("key3"), "value3");
|
||||
EXPECT_EQ(dict.GetCount(), 3u);
|
||||
EXPECT_EQ(3u, dict.GetCount());
|
||||
// try an unknown key
|
||||
EXPECT_FALSE(dict.GetValueForKey("key4"));
|
||||
|
||||
@ -85,11 +85,11 @@ TEST(SimpleStringDictionary, CopyAndAssign) {
|
||||
map.SetKeyValue("two", "b");
|
||||
map.SetKeyValue("three", "c");
|
||||
map.RemoveKey("two");
|
||||
EXPECT_EQ(2u, map.GetCount());
|
||||
EXPECT_EQ(map.GetCount(), 2u);
|
||||
|
||||
// Test copy.
|
||||
TSimpleStringDictionary<10, 10, 10> map_copy(map);
|
||||
EXPECT_EQ(2u, map_copy.GetCount());
|
||||
EXPECT_EQ(map_copy.GetCount(), 2u);
|
||||
EXPECT_STREQ("a", map_copy.GetValueForKey("one"));
|
||||
EXPECT_STREQ("c", map_copy.GetValueForKey("three"));
|
||||
map_copy.SetKeyValue("four", "d");
|
||||
@ -99,7 +99,7 @@ TEST(SimpleStringDictionary, CopyAndAssign) {
|
||||
// Test assign.
|
||||
TSimpleStringDictionary<10, 10, 10> map_assign;
|
||||
map_assign = map;
|
||||
EXPECT_EQ(2u, map_assign.GetCount());
|
||||
EXPECT_EQ(map_assign.GetCount(), 2u);
|
||||
EXPECT_STREQ("a", map_assign.GetValueForKey("one"));
|
||||
EXPECT_STREQ("c", map_assign.GetValueForKey("three"));
|
||||
map_assign.SetKeyValue("four", "d");
|
||||
@ -129,7 +129,7 @@ TEST(SimpleStringDictionary, Iterator) {
|
||||
|
||||
// We'll keep track of the number of key/value pairs we think should be in the
|
||||
// dictionary
|
||||
int expectedDictionarySize = 0;
|
||||
int expected_dictionary_size = 0;
|
||||
|
||||
// Set a bunch of key/value pairs like key0/value0, key1/value1, ...
|
||||
for (int i = 0; i < kPartitionIndex; ++i) {
|
||||
@ -137,7 +137,7 @@ TEST(SimpleStringDictionary, Iterator) {
|
||||
sprintf(value, "value%d", i);
|
||||
dict->SetKeyValue(key, value);
|
||||
}
|
||||
expectedDictionarySize = kPartitionIndex;
|
||||
expected_dictionary_size = kPartitionIndex;
|
||||
|
||||
// set a couple of the keys twice (with the same value) - should be nop
|
||||
dict->SetKeyValue("key2", "value2");
|
||||
@ -149,7 +149,7 @@ TEST(SimpleStringDictionary, Iterator) {
|
||||
dict->RemoveKey("key18");
|
||||
dict->RemoveKey("key23");
|
||||
dict->RemoveKey("key31");
|
||||
expectedDictionarySize -= 4; // we just removed four key/value pairs
|
||||
expected_dictionary_size -= 4; // we just removed four key/value pairs
|
||||
|
||||
// Set some more key/value pairs like key59/value59, key60/value60, ...
|
||||
for (int i = kPartitionIndex; i < kDictionaryCapacity; ++i) {
|
||||
@ -157,7 +157,7 @@ TEST(SimpleStringDictionary, Iterator) {
|
||||
sprintf(value, "value%d", i);
|
||||
dict->SetKeyValue(key, value);
|
||||
}
|
||||
expectedDictionarySize += kDictionaryCapacity - kPartitionIndex;
|
||||
expected_dictionary_size += kDictionaryCapacity - kPartitionIndex;
|
||||
|
||||
// Now create an iterator on the dictionary
|
||||
SimpleStringDictionary::Iterator iter(*dict);
|
||||
@ -170,35 +170,36 @@ TEST(SimpleStringDictionary, Iterator) {
|
||||
int count[kDictionaryCapacity];
|
||||
memset(count, 0, sizeof(count));
|
||||
|
||||
int totalCount = 0;
|
||||
int total_count = 0;
|
||||
|
||||
for (;;) {
|
||||
const SimpleStringDictionary::Entry* entry = iter.Next();
|
||||
if (!entry)
|
||||
break;
|
||||
totalCount++;
|
||||
total_count++;
|
||||
|
||||
// Extract keyNumber from a string of the form key<keyNumber>
|
||||
int keyNumber;
|
||||
sscanf(entry->key, "key%d", &keyNumber);
|
||||
// Extract key_number from a string of the form key<key_number>
|
||||
int key_number;
|
||||
sscanf(entry->key, "key%d", &key_number);
|
||||
|
||||
// Extract valueNumber from a string of the form value<valueNumber>
|
||||
int valueNumber;
|
||||
sscanf(entry->value, "value%d", &valueNumber);
|
||||
// Extract value_number from a string of the form value<value_number>
|
||||
int value_number;
|
||||
sscanf(entry->value, "value%d", &value_number);
|
||||
|
||||
// The value number should equal the key number since that's how we set them
|
||||
EXPECT_EQ(keyNumber, valueNumber);
|
||||
EXPECT_EQ(value_number, key_number);
|
||||
|
||||
// Key and value numbers should be in proper range: 0 <= keyNumber <
|
||||
// Key and value numbers should be in proper range: 0 <= key_number <
|
||||
// kDictionaryCapacity
|
||||
bool isKeyInGoodRange = (keyNumber >= 0 && keyNumber < kDictionaryCapacity);
|
||||
bool isValueInGoodRange =
|
||||
(valueNumber >= 0 && valueNumber < kDictionaryCapacity);
|
||||
EXPECT_TRUE(isKeyInGoodRange);
|
||||
EXPECT_TRUE(isValueInGoodRange);
|
||||
bool key_in_good_range =
|
||||
key_number >= 0 && key_number < kDictionaryCapacity;
|
||||
bool value_in_good_range =
|
||||
value_number >= 0 && value_number < kDictionaryCapacity;
|
||||
EXPECT_TRUE(key_in_good_range);
|
||||
EXPECT_TRUE(value_in_good_range);
|
||||
|
||||
if (isKeyInGoodRange && isValueInGoodRange) {
|
||||
++count[keyNumber];
|
||||
if (key_in_good_range && value_in_good_range) {
|
||||
++count[key_number];
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,12 +208,12 @@ TEST(SimpleStringDictionary, Iterator) {
|
||||
for (size_t i = 0; i < kDictionaryCapacity; ++i) {
|
||||
// Skip over key7, key18, key23, and key31, since we removed them
|
||||
if (!(i == 7 || i == 18 || i == 23 || i == 31)) {
|
||||
EXPECT_EQ(count[i], 1);
|
||||
EXPECT_EQ(1, count[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the number of iterations matches the expected dictionary size.
|
||||
EXPECT_EQ(totalCount, expectedDictionarySize);
|
||||
EXPECT_EQ(total_count, expected_dictionary_size);
|
||||
}
|
||||
|
||||
TEST(SimpleStringDictionary, AddRemove) {
|
||||
@ -221,22 +222,22 @@ TEST(SimpleStringDictionary, AddRemove) {
|
||||
map.SetKeyValue("mike", "pink");
|
||||
map.SetKeyValue("mark", "allays");
|
||||
|
||||
EXPECT_EQ(3u, map.GetCount());
|
||||
EXPECT_EQ(map.GetCount(), 3u);
|
||||
EXPECT_STREQ("ert", map.GetValueForKey("rob"));
|
||||
EXPECT_STREQ("pink", map.GetValueForKey("mike"));
|
||||
EXPECT_STREQ("allays", map.GetValueForKey("mark"));
|
||||
|
||||
map.RemoveKey("mike");
|
||||
|
||||
EXPECT_EQ(2u, map.GetCount());
|
||||
EXPECT_EQ(map.GetCount(), 2u);
|
||||
EXPECT_FALSE(map.GetValueForKey("mike"));
|
||||
|
||||
map.SetKeyValue("mark", "mal");
|
||||
EXPECT_EQ(2u, map.GetCount());
|
||||
EXPECT_EQ(map.GetCount(), 2u);
|
||||
EXPECT_STREQ("mal", map.GetValueForKey("mark"));
|
||||
|
||||
map.RemoveKey("mark");
|
||||
EXPECT_EQ(1u, map.GetCount());
|
||||
EXPECT_EQ(map.GetCount(), 1u);
|
||||
EXPECT_FALSE(map.GetValueForKey("mark"));
|
||||
}
|
||||
|
||||
@ -246,7 +247,7 @@ TEST(SimpleStringDictionary, OutOfSpace) {
|
||||
map.SetKeyValue("a", "1");
|
||||
map.SetKeyValue("b", "2");
|
||||
map.SetKeyValue("c", "3");
|
||||
EXPECT_EQ(2u, map.GetCount());
|
||||
EXPECT_EQ(map.GetCount(), 2u);
|
||||
EXPECT_FALSE(map.GetValueForKey("c"));
|
||||
}
|
||||
|
||||
@ -262,7 +263,7 @@ TEST(SimpleStringDictionaryDeathTest, NullKey) {
|
||||
|
||||
ASSERT_DEATH_CHECK(map.GetValueForKey(nullptr), "key");
|
||||
map.RemoveKey("hi");
|
||||
EXPECT_EQ(0u, map.GetCount());
|
||||
EXPECT_EQ(map.GetCount(), 0u);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -101,41 +101,41 @@ class TestSimulateCrashMac final : public MachMultiprocess,
|
||||
// Check the entire exception message, because most or all of it was
|
||||
// generated by SimulateCrash() instead of the kernel.
|
||||
|
||||
EXPECT_EQ(behavior_, behavior);
|
||||
EXPECT_EQ(LocalPort(), exception_port);
|
||||
EXPECT_EQ(behavior, behavior_);
|
||||
EXPECT_EQ(exception_port, LocalPort());
|
||||
if (ExceptionBehaviorHasIdentity(behavior)) {
|
||||
EXPECT_NE(THREAD_NULL, thread);
|
||||
EXPECT_EQ(ChildTask(), task);
|
||||
EXPECT_NE(thread, THREAD_NULL);
|
||||
EXPECT_EQ(task, ChildTask());
|
||||
} else {
|
||||
EXPECT_EQ(THREAD_NULL, thread);
|
||||
EXPECT_EQ(TASK_NULL, task);
|
||||
EXPECT_EQ(thread, THREAD_NULL);
|
||||
EXPECT_EQ(task, TASK_NULL);
|
||||
}
|
||||
EXPECT_EQ(kMachExceptionSimulated, exception);
|
||||
EXPECT_EQ(2u, code_count);
|
||||
EXPECT_EQ(exception, kMachExceptionSimulated);
|
||||
EXPECT_EQ(code_count, 2u);
|
||||
if (code_count >= 1) {
|
||||
EXPECT_EQ(0, code[0]);
|
||||
EXPECT_EQ(code[0], 0);
|
||||
}
|
||||
if (code_count >= 2) {
|
||||
EXPECT_EQ(0, code[1]);
|
||||
EXPECT_EQ(code[1], 0);
|
||||
}
|
||||
if (!ExceptionBehaviorHasState(behavior)) {
|
||||
EXPECT_EQ(THREAD_STATE_NONE, *flavor);
|
||||
EXPECT_EQ(*flavor, THREAD_STATE_NONE);
|
||||
} else {
|
||||
EXPECT_EQ(flavor_, *flavor);
|
||||
EXPECT_EQ(*flavor, flavor_);
|
||||
switch (*flavor) {
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
case x86_THREAD_STATE: {
|
||||
EXPECT_EQ(x86_THREAD_STATE_COUNT, old_state_count);
|
||||
EXPECT_EQ(old_state_count, x86_THREAD_STATE_COUNT);
|
||||
const x86_thread_state* state =
|
||||
reinterpret_cast<const x86_thread_state*>(old_state);
|
||||
switch (state->tsh.flavor) {
|
||||
case x86_THREAD_STATE32:
|
||||
EXPECT_EQ(implicit_cast<int>(x86_THREAD_STATE32_COUNT),
|
||||
state->tsh.count);
|
||||
EXPECT_EQ(state->tsh.count,
|
||||
implicit_cast<int>(x86_THREAD_STATE32_COUNT));
|
||||
break;
|
||||
case x86_THREAD_STATE64:
|
||||
EXPECT_EQ(implicit_cast<int>(x86_THREAD_STATE64_COUNT),
|
||||
state->tsh.count);
|
||||
EXPECT_EQ(state->tsh.count,
|
||||
implicit_cast<int>(x86_THREAD_STATE64_COUNT));
|
||||
break;
|
||||
default:
|
||||
ADD_FAILURE() << "unexpected tsh.flavor " << state->tsh.flavor;
|
||||
@ -144,17 +144,17 @@ class TestSimulateCrashMac final : public MachMultiprocess,
|
||||
break;
|
||||
}
|
||||
case x86_FLOAT_STATE: {
|
||||
EXPECT_EQ(x86_FLOAT_STATE_COUNT, old_state_count);
|
||||
EXPECT_EQ(old_state_count, x86_FLOAT_STATE_COUNT);
|
||||
const x86_float_state* state =
|
||||
reinterpret_cast<const x86_float_state*>(old_state);
|
||||
switch (state->fsh.flavor) {
|
||||
case x86_FLOAT_STATE32:
|
||||
EXPECT_EQ(implicit_cast<int>(x86_FLOAT_STATE32_COUNT),
|
||||
state->fsh.count);
|
||||
EXPECT_EQ(state->fsh.count,
|
||||
implicit_cast<int>(x86_FLOAT_STATE32_COUNT));
|
||||
break;
|
||||
case x86_FLOAT_STATE64:
|
||||
EXPECT_EQ(implicit_cast<int>(x86_FLOAT_STATE64_COUNT),
|
||||
state->fsh.count);
|
||||
EXPECT_EQ(state->fsh.count,
|
||||
implicit_cast<int>(x86_FLOAT_STATE64_COUNT));
|
||||
break;
|
||||
default:
|
||||
ADD_FAILURE() << "unexpected fsh.flavor " << state->fsh.flavor;
|
||||
@ -163,17 +163,17 @@ class TestSimulateCrashMac final : public MachMultiprocess,
|
||||
break;
|
||||
}
|
||||
case x86_DEBUG_STATE: {
|
||||
EXPECT_EQ(x86_DEBUG_STATE_COUNT, old_state_count);
|
||||
EXPECT_EQ(old_state_count, x86_DEBUG_STATE_COUNT);
|
||||
const x86_debug_state* state =
|
||||
reinterpret_cast<const x86_debug_state*>(old_state);
|
||||
switch (state->dsh.flavor) {
|
||||
case x86_DEBUG_STATE32:
|
||||
EXPECT_EQ(implicit_cast<int>(x86_DEBUG_STATE32_COUNT),
|
||||
state->dsh.count);
|
||||
EXPECT_EQ(state->dsh.count,
|
||||
implicit_cast<int>(x86_DEBUG_STATE32_COUNT));
|
||||
break;
|
||||
case x86_DEBUG_STATE64:
|
||||
EXPECT_EQ(implicit_cast<int>(x86_DEBUG_STATE64_COUNT),
|
||||
state->dsh.count);
|
||||
EXPECT_EQ(state->dsh.count,
|
||||
implicit_cast<int>(x86_DEBUG_STATE64_COUNT));
|
||||
break;
|
||||
default:
|
||||
ADD_FAILURE() << "unexpected dsh.flavor " << state->dsh.flavor;
|
||||
@ -182,22 +182,22 @@ class TestSimulateCrashMac final : public MachMultiprocess,
|
||||
break;
|
||||
}
|
||||
case x86_THREAD_STATE32:
|
||||
EXPECT_EQ(x86_THREAD_STATE32_COUNT, old_state_count);
|
||||
EXPECT_EQ(old_state_count, x86_THREAD_STATE32_COUNT);
|
||||
break;
|
||||
case x86_FLOAT_STATE32:
|
||||
EXPECT_EQ(x86_FLOAT_STATE32_COUNT, old_state_count);
|
||||
EXPECT_EQ(old_state_count, x86_FLOAT_STATE32_COUNT);
|
||||
break;
|
||||
case x86_DEBUG_STATE32:
|
||||
EXPECT_EQ(x86_DEBUG_STATE32_COUNT, old_state_count);
|
||||
EXPECT_EQ(old_state_count, x86_DEBUG_STATE32_COUNT);
|
||||
break;
|
||||
case x86_THREAD_STATE64:
|
||||
EXPECT_EQ(x86_THREAD_STATE64_COUNT, old_state_count);
|
||||
EXPECT_EQ(old_state_count, x86_THREAD_STATE64_COUNT);
|
||||
break;
|
||||
case x86_FLOAT_STATE64:
|
||||
EXPECT_EQ(x86_FLOAT_STATE64_COUNT, old_state_count);
|
||||
EXPECT_EQ(old_state_count, x86_FLOAT_STATE64_COUNT);
|
||||
break;
|
||||
case x86_DEBUG_STATE64:
|
||||
EXPECT_EQ(x86_DEBUG_STATE64_COUNT, old_state_count);
|
||||
EXPECT_EQ(old_state_count, x86_DEBUG_STATE64_COUNT);
|
||||
break;
|
||||
#else
|
||||
#error Port to your CPU architecture
|
||||
@ -223,7 +223,7 @@ class TestSimulateCrashMac final : public MachMultiprocess,
|
||||
// thread-level EXC_CRASH handler. To test that it will fall back to
|
||||
// trying the task-level EXC_CRASH handler, return a failure code, which
|
||||
// should cause SimulateCrash() to try the next target.
|
||||
EXPECT_EQ(kExceptionPortsTargetBoth, target_);
|
||||
EXPECT_EQ(target_, kExceptionPortsTargetBoth);
|
||||
return KERN_ABORTED;
|
||||
}
|
||||
|
||||
@ -259,7 +259,7 @@ class TestSimulateCrashMac final : public MachMultiprocess,
|
||||
MachMessageServer::kOneShot,
|
||||
MachMessageServer::kReceiveLargeError,
|
||||
kMachMessageTimeoutWaitIndefinitely);
|
||||
EXPECT_EQ(MACH_MSG_SUCCESS, mr)
|
||||
EXPECT_EQ(mr, MACH_MSG_SUCCESS)
|
||||
<< MachErrorMessage(mr, "MachMessageServer::Run");
|
||||
}
|
||||
|
||||
@ -270,7 +270,7 @@ class TestSimulateCrashMac final : public MachMultiprocess,
|
||||
MachMessageServer::kOneShot,
|
||||
MachMessageServer::kReceiveLargeError,
|
||||
kMachMessageTimeoutWaitIndefinitely);
|
||||
EXPECT_EQ(MACH_MSG_SUCCESS, mr)
|
||||
EXPECT_EQ(mr, MACH_MSG_SUCCESS)
|
||||
<< MachErrorMessage(mr, "MachMessageServer::Run");
|
||||
}
|
||||
|
||||
|
@ -17,5 +17,4 @@ GERRIT_SQUASH_UPLOADS: True
|
||||
CODE_REVIEW_SERVER: https://canary-chromium-review.googlesource.com/
|
||||
VIEW_VC: https://chromium.googlesource.com/crashpad/crashpad/+/
|
||||
PROJECT: crashpad
|
||||
BUG_LINE_FORMAT: Bug: %s
|
||||
BUG_PREFIX: crashpad:
|
||||
|
25
compat/android/linux/prctl.h
Normal file
25
compat/android/linux/prctl.h
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2017 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CRASHPAD_COMPAT_ANDROID_LINUX_PRCTL_H_
|
||||
#define CRASHPAD_COMPAT_ANDROID_LINUX_PRCTL_H_
|
||||
|
||||
#include_next <linux/prctl.h>
|
||||
|
||||
// Android 5.0.0 (API 21) NDK
|
||||
#if !defined(PR_SET_PTRACER)
|
||||
#define PR_SET_PTRACER 0x59616d61
|
||||
#endif
|
||||
|
||||
#endif // CRASHPAD_COMPAT_ANDROID_LINUX_PRCTL_H_
|
@ -22,6 +22,7 @@
|
||||
'client/client_test.gyp:*',
|
||||
'compat/compat.gyp:*',
|
||||
'handler/handler.gyp:*',
|
||||
'handler/handler_test.gyp:*',
|
||||
'minidump/minidump.gyp:*',
|
||||
'minidump/minidump_test.gyp:*',
|
||||
'snapshot/snapshot.gyp:*',
|
||||
|
@ -214,9 +214,9 @@ $ adb push \
|
||||
/data/local/tmp/
|
||||
[100%] /data/local/tmp/crashpad_test_test_multiprocess_exec_test_child
|
||||
$ adb shell mkdir -p /data/local/tmp/crashpad_test_data_root/test
|
||||
$ adb push test/paths_test_data_root.txt \
|
||||
$ adb push test/test_paths_test_data_root.txt \
|
||||
/data/local/tmp/crashpad_test_data_root/test/
|
||||
[100%] /data/local/tmp/crashpad_test_data_root/test/paths_test_data_root.txt
|
||||
[100%] /data/local/tmp/crashpad_test_data_root/test/test_paths_test_data_root.txt
|
||||
$ adb shell
|
||||
device:/ $ cd /data/local/tmp
|
||||
device:/data/local/tmp $ CRASHPAD_TEST_DATA_ROOT=crashpad_test_data_root \
|
||||
|
@ -452,6 +452,8 @@ suspend and resume and such.
|
||||
|
||||
### Extensibility
|
||||
|
||||
#### Client Extensibility
|
||||
|
||||
Clients are able to extend the generated crash reports in two ways, by
|
||||
manipulating their CrashpadInfo structure.
|
||||
The two extensibility points are:
|
||||
@ -461,6 +463,18 @@ The two extensibility points are:
|
||||
In both cases the CrashpadInfo structure has to be updated before a crash
|
||||
occurs.
|
||||
|
||||
##### Embedder Extensibility
|
||||
|
||||
Additionally, embedders of the handler can provide "user stream data source"
|
||||
instances to the handler's main function. Any time a minidump is written, these
|
||||
instances get called.
|
||||
|
||||
Each data source may contribute a custom stream to the minidump, which can be
|
||||
computed from e.g. system or application state relevant to the crash.
|
||||
|
||||
As a case in point, it can be handy to know whether the system was under memory
|
||||
or other resource duress at the time of crash.
|
||||
|
||||
### Dependencies
|
||||
|
||||
Aside from system headers and APIs, when used outside of Chromium, Crashpad has
|
||||
|
@ -28,7 +28,7 @@ cd "$(dirname "${0}")/../.."
|
||||
|
||||
source doc/support/compat.sh
|
||||
|
||||
doc/support/generate_doxygen.sh
|
||||
python doc/support/generate_doxygen.py
|
||||
|
||||
output_dir=doc/generated
|
||||
maybe_mkdir "${output_dir}"
|
||||
|
49
doc/support/generate_doxygen.py
Executable file
49
doc/support/generate_doxygen.py
Executable file
@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python
|
||||
# coding: utf-8
|
||||
|
||||
# Copyright 2017 The Crashpad Authors. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Generating Doxygen documentation requires Doxygen, http://www.doxygen.org/.
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def main(args):
|
||||
script_dir = os.path.dirname(__file__)
|
||||
crashpad_dir = os.path.join(script_dir, os.pardir, os.pardir)
|
||||
|
||||
# Run from the Crashpad project root directory.
|
||||
os.chdir(crashpad_dir)
|
||||
|
||||
output_dir = os.path.join('out', 'doc', 'doxygen')
|
||||
|
||||
if os.path.isdir(output_dir) and not os.path.islink(output_dir):
|
||||
shutil.rmtree(output_dir)
|
||||
elif os.path.exists(output_dir):
|
||||
os.unlink(output_dir)
|
||||
|
||||
os.makedirs(output_dir, 0755)
|
||||
|
||||
doxy_file = os.path.join('doc', 'support', 'crashpad.doxy')
|
||||
subprocess.check_call(['doxygen', doxy_file])
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
@ -1,29 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright 2015 The Crashpad Authors. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set -e
|
||||
|
||||
# Generating Doxygen documentation requires Doxygen, http://www.doxygen.org/.
|
||||
|
||||
# Run from the Crashpad project root directory.
|
||||
cd "$(dirname "${0}")/../.."
|
||||
|
||||
output_dir=out/doc/doxygen
|
||||
|
||||
rm -rf "${output_dir}"
|
||||
mkdir -p "${output_dir}"
|
||||
|
||||
doxygen doc/support/crashpad.doxy
|
@ -252,9 +252,12 @@ void CrashReportUploadThread::ProcessPendingReport(
|
||||
break;
|
||||
|
||||
case CrashReportDatabase::kBusyError:
|
||||
case CrashReportDatabase::kReportNotFound:
|
||||
// Someone else may have gotten to it first. If they’re working on it now,
|
||||
// this will be kBusyError. If they’ve already finished with it, it’ll be
|
||||
// kReportNotFound.
|
||||
return;
|
||||
|
||||
case CrashReportDatabase::kReportNotFound:
|
||||
case CrashReportDatabase::kFileSystemError:
|
||||
case CrashReportDatabase::kDatabaseError:
|
||||
// In these cases, SkipReportUpload() might not work either, but it’s best
|
||||
|
@ -138,6 +138,51 @@ establish the Crashpad client environment before running a program.
|
||||
service declared in a job’s `MachServices` dictionary (see launchd.plist(5)).
|
||||
The service name may also be completely unknown to the system.
|
||||
|
||||
* **--metrics-dir**=_DIR_
|
||||
|
||||
Metrics information will be written to _DIR_. This option only has an effect
|
||||
when built as part of Chromium. In non-Chromium builds, and in the absence of
|
||||
this option, metrics information will not be written.
|
||||
|
||||
* **--monitor-self**
|
||||
|
||||
Causes a second instance of the Crashpad handler program to be started,
|
||||
monitoring the original instance for exceptions. The original instance will
|
||||
become a client of the second one. The second instance will be started with
|
||||
the same **--annotation**, **--database**, **--monitor-self-annotation**,
|
||||
**--no-rate-limit**, **--no-upload-gzip**, and **--url** arguments as the
|
||||
original one. The second instance will not be started with a
|
||||
**--metrics-dir** argument even if the original instance was.
|
||||
|
||||
Where supported by the underlying operating system, the second instance will
|
||||
be restarted should it exit before the first instance. The second instance
|
||||
will not be eligible to be started asynchronously.
|
||||
|
||||
* **--monitor-self-annotation**=_KEY_=_VALUE_
|
||||
|
||||
Sets a module-level annotation mapping _KEY_ to _VALUE_ in the Crashpad
|
||||
handler. This option may appear zero, one, or more times.
|
||||
|
||||
If **--monitor-self** is in use, the second instance of the Crashpad handler
|
||||
program will find these annotations stored in the original instance and will
|
||||
include them in any crash reports written for the original instance.
|
||||
|
||||
These annotations will only appear in crash reports written for the Crashpad
|
||||
handler itself. To apply a process-level annotation to all crash reports
|
||||
written by an instance of the Crashpad handler, use **--annotation** instead.
|
||||
|
||||
* **--monitor-self-argument**=_ARGUMENT_
|
||||
|
||||
When directed by **--monitor-self** to start a second instance of the
|
||||
Crashpad handler program, the second instance will be started with _ARGUMENT_
|
||||
as one of its arguments. This option may appear zero, one, or more times.
|
||||
This option has no effect in the absence of **--monitor-self**.
|
||||
|
||||
This supports embedding the Crashpad handler into a multi-purpose executable
|
||||
that dispatches to the desired entry point based on a command-line argument.
|
||||
To prevent excessive accumulation of handler processes, _ARGUMENT_ must not
|
||||
be `--monitor-self`.
|
||||
|
||||
* **--no-rate-limit**
|
||||
|
||||
Do not rate limit the upload of crash reports. By default uploads are
|
||||
|
132
handler/crashpad_handler_test.cc
Normal file
132
handler/crashpad_handler_test.cc
Normal file
@ -0,0 +1,132 @@
|
||||
// Copyright 2017 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <windows.h>
|
||||
#include <dbghelp.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "client/crash_report_database.h"
|
||||
#include "client/crashpad_client.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "minidump/test/minidump_file_writer_test_util.h"
|
||||
#include "test/test_paths.h"
|
||||
#include "test/win/win_multiprocess_with_temp_dir.h"
|
||||
#include "util/file/file_reader.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
void StartAndCrashWithExtendedHandler(const base::FilePath& temp_dir) {
|
||||
base::FilePath handler_path = TestPaths::Executable().DirName().Append(
|
||||
FILE_PATH_LITERAL("crashpad_handler_test_extended_handler.exe"));
|
||||
|
||||
CrashpadClient client;
|
||||
ASSERT_TRUE(client.StartHandler(handler_path,
|
||||
temp_dir,
|
||||
base::FilePath(),
|
||||
"",
|
||||
std::map<std::string, std::string>(),
|
||||
std::vector<std::string>(),
|
||||
false,
|
||||
false));
|
||||
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
class CrashWithExtendedHandler final : public WinMultiprocessWithTempDir {
|
||||
public:
|
||||
CrashWithExtendedHandler() : WinMultiprocessWithTempDir() {}
|
||||
~CrashWithExtendedHandler() {}
|
||||
|
||||
private:
|
||||
void ValidateGeneratedDump();
|
||||
|
||||
void WinMultiprocessParent() override {
|
||||
SetExpectedChildExitCode(EXCEPTION_BREAKPOINT);
|
||||
}
|
||||
|
||||
void WinMultiprocessChild() override {
|
||||
StartAndCrashWithExtendedHandler(GetTempDirPath());
|
||||
}
|
||||
|
||||
void WinMultiprocessParentAfterChild(HANDLE child) override {
|
||||
// At this point the child has exited, which means the crash report should
|
||||
// have been written.
|
||||
ValidateGeneratedDump();
|
||||
|
||||
// Delegate the cleanup to the superclass.
|
||||
WinMultiprocessWithTempDir::WinMultiprocessParentAfterChild(child);
|
||||
}
|
||||
};
|
||||
|
||||
void CrashWithExtendedHandler::ValidateGeneratedDump() {
|
||||
// Open the database and find the sole dump that should have been created.
|
||||
std::unique_ptr<CrashReportDatabase> database(
|
||||
CrashReportDatabase::Initialize(GetTempDirPath()));
|
||||
ASSERT_TRUE(database);
|
||||
|
||||
std::vector<CrashReportDatabase::Report> reports;
|
||||
ASSERT_EQ(database->GetCompletedReports(&reports),
|
||||
CrashReportDatabase::kNoError);
|
||||
ASSERT_EQ(reports.size(), 1u);
|
||||
|
||||
// Open the dump and validate that it has the extension stream with the
|
||||
// expected contents.
|
||||
FileReader reader;
|
||||
ASSERT_TRUE(reader.Open(reports[0].file_path));
|
||||
|
||||
// Read the header.
|
||||
MINIDUMP_HEADER header = {};
|
||||
ASSERT_TRUE(reader.ReadExactly(&header, sizeof(header)));
|
||||
|
||||
// Read the directory.
|
||||
std::vector<MINIDUMP_DIRECTORY> directory(header.NumberOfStreams);
|
||||
ASSERT_TRUE(reader.SeekSet(header.StreamDirectoryRva));
|
||||
ASSERT_TRUE(reader.ReadExactly(directory.data(),
|
||||
directory.size() * sizeof(directory[0])));
|
||||
|
||||
// Search for the extension stream.
|
||||
size_t found_extension_streams = 0;
|
||||
for (const auto& entry : directory) {
|
||||
if (entry.StreamType == 0xCAFEBABE) {
|
||||
++found_extension_streams;
|
||||
|
||||
ASSERT_TRUE(reader.SeekSet(entry.Location.Rva));
|
||||
|
||||
std::vector<char> data;
|
||||
data.resize(entry.Location.DataSize);
|
||||
|
||||
ASSERT_TRUE(reader.ReadExactly(data.data(), data.size()));
|
||||
|
||||
static const char kExpectedData[] = "Injected extension stream!";
|
||||
EXPECT_EQ(memcmp(kExpectedData, data.data(), sizeof(kExpectedData)), 0);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ(found_extension_streams, 1u);
|
||||
}
|
||||
|
||||
TEST(CrashpadHandler, ExtensibilityCalloutsWork) {
|
||||
WinMultiprocessWithTempDir::Run<CrashWithExtendedHandler>();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
70
handler/crashpad_handler_test_extended_handler.cc
Normal file
70
handler/crashpad_handler_test_extended_handler.cc
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright 2017 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "build/build_config.h"
|
||||
#include "handler/handler_main.h"
|
||||
#include "minidump/test/minidump_user_extension_stream_util.h"
|
||||
#include "tools/tool_support.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
class TestUserStreamDataSource : public crashpad::UserStreamDataSource {
|
||||
public:
|
||||
TestUserStreamDataSource() {}
|
||||
|
||||
std::unique_ptr<crashpad::MinidumpUserExtensionStreamDataSource>
|
||||
ProduceStreamData(crashpad::ProcessSnapshot* process_snapshot) override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TestUserStreamDataSource);
|
||||
};
|
||||
|
||||
std::unique_ptr<crashpad::MinidumpUserExtensionStreamDataSource>
|
||||
TestUserStreamDataSource::ProduceStreamData(
|
||||
crashpad::ProcessSnapshot* process_snapshot) {
|
||||
static const char kTestData[] = "Injected extension stream!";
|
||||
|
||||
return base::WrapUnique(new crashpad::test::BufferExtensionStreamDataSource(
|
||||
0xCAFEBABE, kTestData, sizeof(kTestData)));
|
||||
}
|
||||
|
||||
int ExtendedHandlerMain(int argc, char* argv[]) {
|
||||
crashpad::UserStreamDataSources user_stream_data_sources;
|
||||
user_stream_data_sources.push_back(
|
||||
base::WrapUnique(new TestUserStreamDataSource()));
|
||||
|
||||
return crashpad::HandlerMain(argc, argv, &user_stream_data_sources);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
return ExtendedHandlerMain(argc, argv);
|
||||
}
|
||||
|
||||
#elif defined(OS_WIN)
|
||||
|
||||
int wmain(int argc, wchar_t* argv[]) {
|
||||
return crashpad::ToolSupport::Wmain(argc, argv, &ExtendedHandlerMain);
|
||||
}
|
||||
|
||||
#endif // OS_MACOSX
|
@ -45,6 +45,8 @@
|
||||
'mac/exception_handler_server.h',
|
||||
'prune_crash_reports_thread.cc',
|
||||
'prune_crash_reports_thread.h',
|
||||
'user_stream_data_source.cc',
|
||||
'user_stream_data_source.h',
|
||||
'win/crash_report_exception_handler.cc',
|
||||
'win/crash_report_exception_handler.h',
|
||||
],
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -33,16 +34,20 @@
|
||||
#include "base/logging.h"
|
||||
#include "base/metrics/persistent_histogram_allocator.h"
|
||||
#include "base/scoped_generic.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "build/build_config.h"
|
||||
#include "client/crash_report_database.h"
|
||||
#include "client/crashpad_client.h"
|
||||
#include "client/crashpad_info.h"
|
||||
#include "client/prune_crash_reports.h"
|
||||
#include "client/simple_string_dictionary.h"
|
||||
#include "handler/crash_report_upload_thread.h"
|
||||
#include "handler/prune_crash_reports_thread.h"
|
||||
#include "tools/tool_support.h"
|
||||
#include "util/file/file_io.h"
|
||||
#include "util/misc/metrics.h"
|
||||
#include "util/misc/paths.h"
|
||||
#include "util/numeric/in_range_cast.h"
|
||||
#include "util/stdlib/map_insert.h"
|
||||
#include "util/stdlib/string_number_conversion.h"
|
||||
@ -83,8 +88,8 @@ void Usage(const base::FilePath& me) {
|
||||
" --database=PATH store the crash report database at PATH\n"
|
||||
#if defined(OS_MACOSX)
|
||||
" --handshake-fd=FD establish communication with the client over FD\n"
|
||||
" --mach-service=SERVICE register SERVICE with the bootstrap server\n"
|
||||
#elif defined(OS_WIN)
|
||||
#endif // OS_MACOSX
|
||||
#if defined(OS_WIN)
|
||||
" --initial-client-data=HANDLE_request_crash_dump,\n"
|
||||
" HANDLE_request_non_crash_dump,\n"
|
||||
" HANDLE_non_crash_dump_completed,\n"
|
||||
@ -94,15 +99,24 @@ void Usage(const base::FilePath& me) {
|
||||
" Address_non_crash_exception_information,\n"
|
||||
" Address_debug_critical_section\n"
|
||||
" use precreated data to register initial client\n"
|
||||
#endif // OS_WIN
|
||||
#if defined(OS_MACOSX)
|
||||
" --mach-service=SERVICE register SERVICE with the bootstrap server\n"
|
||||
#endif // OS_MACOSX
|
||||
" --metrics-dir=DIR store metrics files in DIR (only in Chromium)\n"
|
||||
" --monitor-self run a second handler to catch crashes in the first\n"
|
||||
" --monitor-self-annotation=KEY=VALUE\n"
|
||||
" set a module annotation in the handler\n"
|
||||
" --monitor-self-argument=ARGUMENT\n"
|
||||
" provide additional arguments to the second handler\n"
|
||||
" --no-rate-limit don't rate limit crash uploads\n"
|
||||
" --no-upload-gzip don't use gzip compression when uploading\n"
|
||||
#if defined(OS_WIN)
|
||||
" --pipe-name=PIPE communicate with the client over PIPE\n"
|
||||
#endif // OS_WIN
|
||||
#if defined(OS_MACOSX)
|
||||
" --reset-own-crash-exception-port-to-system-default\n"
|
||||
" reset the server's exception handler to default\n"
|
||||
#elif defined(OS_WIN)
|
||||
" --pipe-name=PIPE communicate with the client over PIPE\n"
|
||||
#endif // OS_MACOSX
|
||||
" --url=URL send crash reports to this Breakpad server URL,\n"
|
||||
" only if uploads are enabled for the database\n"
|
||||
@ -112,6 +126,49 @@ void Usage(const base::FilePath& me) {
|
||||
ToolSupport::UsageTail(me);
|
||||
}
|
||||
|
||||
struct Options {
|
||||
std::map<std::string, std::string> annotations;
|
||||
std::map<std::string, std::string> monitor_self_annotations;
|
||||
std::string url;
|
||||
base::FilePath database;
|
||||
base::FilePath metrics_dir;
|
||||
std::vector<std::string> monitor_self_arguments;
|
||||
#if defined(OS_MACOSX)
|
||||
std::string mach_service;
|
||||
int handshake_fd;
|
||||
bool reset_own_crash_exception_port_to_system_default;
|
||||
#elif defined(OS_WIN)
|
||||
std::string pipe_name;
|
||||
InitialClientData initial_client_data;
|
||||
#endif // OS_MACOSX
|
||||
bool monitor_self;
|
||||
bool rate_limit;
|
||||
bool upload_gzip;
|
||||
};
|
||||
|
||||
// Splits |key_value| on '=' and inserts the resulting key and value into |map|.
|
||||
// If |key_value| has the wrong format, logs an error and returns false. If the
|
||||
// key is already in the map, logs a warning, replaces the existing value, and
|
||||
// returns true. If the key and value were inserted into the map, returns true.
|
||||
// |argument| is used to give context to logged messages.
|
||||
bool AddKeyValueToMap(std::map<std::string, std::string>* map,
|
||||
const std::string& key_value,
|
||||
const char* argument) {
|
||||
std::string key;
|
||||
std::string value;
|
||||
if (!SplitStringFirst(key_value, '=', &key, &value)) {
|
||||
LOG(ERROR) << argument << " requires KEY=VALUE";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string old_value;
|
||||
if (!MapInsertOrReplace(map, key, value, &old_value)) {
|
||||
LOG(WARNING) << argument << " has duplicate key " << key
|
||||
<< ", discarding value " << old_value;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Calls Metrics::HandlerLifetimeMilestone, but only on the first call. This is
|
||||
// to prevent multiple exit events from inadvertently being recorded, which
|
||||
// might happen if a crash occurs during destruction in what would otherwise be
|
||||
@ -188,6 +245,13 @@ void HandleTerminateSignal(int sig, siginfo_t* siginfo, void* context) {
|
||||
Signals::RestoreHandlerAndReraiseSignalOnReturn(siginfo, nullptr);
|
||||
}
|
||||
|
||||
void ReinstallCrashHandler() {
|
||||
// This is used to re-enable the metrics-recording crash handler after
|
||||
// MonitorSelf() sets up a Crashpad exception handler. On macOS, the
|
||||
// metrics-recording handler uses signals and the Crashpad handler uses Mach
|
||||
// exceptions, so there’s nothing to re-enable.
|
||||
}
|
||||
|
||||
void InstallCrashHandler() {
|
||||
Signals::InstallCrashHandlers(HandleCrashSignal, 0, nullptr);
|
||||
|
||||
@ -254,9 +318,17 @@ class TerminateHandler final : public SessionEndWatcher {
|
||||
DISALLOW_COPY_AND_ASSIGN(TerminateHandler);
|
||||
};
|
||||
|
||||
void InstallCrashHandler() {
|
||||
void ReinstallCrashHandler() {
|
||||
// This is used to re-enable the metrics-recording crash handler after
|
||||
// MonitorSelf() sets up a Crashpad exception handler. The Crashpad handler
|
||||
// takes over the UnhandledExceptionFilter, so reinstall the metrics-recording
|
||||
// one.
|
||||
g_original_exception_filter =
|
||||
SetUnhandledExceptionFilter(&UnhandledExceptionHandler);
|
||||
}
|
||||
|
||||
void InstallCrashHandler() {
|
||||
ReinstallCrashHandler();
|
||||
|
||||
// These are termination handlers, not crash handlers, but that’s close
|
||||
// enough. Note that destroying the TerminateHandler would wait for its thread
|
||||
@ -268,9 +340,57 @@ void InstallCrashHandler() {
|
||||
|
||||
#endif // OS_MACOSX
|
||||
|
||||
void MonitorSelf(const Options& options) {
|
||||
base::FilePath executable_path;
|
||||
if (!Paths::Executable(&executable_path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (std::find(options.monitor_self_arguments.begin(),
|
||||
options.monitor_self_arguments.end(),
|
||||
"--monitor-self") != options.monitor_self_arguments.end()) {
|
||||
LOG(WARNING) << "--monitor-self-argument=--monitor-self is not supported";
|
||||
return;
|
||||
}
|
||||
std::vector<std::string> extra_arguments(options.monitor_self_arguments);
|
||||
if (!options.rate_limit) {
|
||||
extra_arguments.push_back("--no-rate-limit");
|
||||
}
|
||||
if (!options.upload_gzip) {
|
||||
extra_arguments.push_back("--no-upload-gzip");
|
||||
}
|
||||
for (const auto& iterator : options.monitor_self_annotations) {
|
||||
extra_arguments.push_back(
|
||||
base::StringPrintf("--monitor-self-annotation=%s=%s",
|
||||
iterator.first.c_str(),
|
||||
iterator.second.c_str()));
|
||||
}
|
||||
|
||||
// Don’t use options.metrics_dir. The current implementation only allows one
|
||||
// instance of crashpad_handler to be writing metrics at a time, and it should
|
||||
// be the primary instance.
|
||||
CrashpadClient crashpad_client;
|
||||
if (!crashpad_client.StartHandler(executable_path,
|
||||
options.database,
|
||||
base::FilePath(),
|
||||
options.url,
|
||||
options.annotations,
|
||||
extra_arguments,
|
||||
true,
|
||||
false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure that appropriate metrics will be recorded on crash before this
|
||||
// process is terminated.
|
||||
ReinstallCrashHandler();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int HandlerMain(int argc, char* argv[]) {
|
||||
int HandlerMain(int argc,
|
||||
char* argv[],
|
||||
const UserStreamDataSources* user_stream_sources) {
|
||||
InstallCrashHandler();
|
||||
CallMetricsRecordNormalExit metrics_record_normal_exit;
|
||||
|
||||
@ -293,12 +413,16 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
kOptionMachService,
|
||||
#endif // OS_MACOSX
|
||||
kOptionMetrics,
|
||||
kOptionMonitorSelf,
|
||||
kOptionMonitorSelfAnnotation,
|
||||
kOptionMonitorSelfArgument,
|
||||
kOptionNoRateLimit,
|
||||
kOptionNoUploadGzip,
|
||||
#if defined(OS_WIN)
|
||||
kOptionPipeName,
|
||||
#endif // OS_WIN
|
||||
#if defined(OS_MACOSX)
|
||||
kOptionResetOwnCrashExceptionPortToSystemDefault,
|
||||
#elif defined(OS_WIN)
|
||||
kOptionPipeName,
|
||||
#endif // OS_MACOSX
|
||||
kOptionURL,
|
||||
|
||||
@ -307,28 +431,6 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
kOptionVersion = -3,
|
||||
};
|
||||
|
||||
struct {
|
||||
std::map<std::string, std::string> annotations;
|
||||
std::string url;
|
||||
const char* database;
|
||||
const char* metrics;
|
||||
#if defined(OS_MACOSX)
|
||||
int handshake_fd;
|
||||
std::string mach_service;
|
||||
bool reset_own_crash_exception_port_to_system_default;
|
||||
#elif defined(OS_WIN)
|
||||
std::string pipe_name;
|
||||
InitialClientData initial_client_data;
|
||||
#endif // OS_MACOSX
|
||||
bool rate_limit;
|
||||
bool upload_gzip;
|
||||
} options = {};
|
||||
#if defined(OS_MACOSX)
|
||||
options.handshake_fd = -1;
|
||||
#endif
|
||||
options.rate_limit = true;
|
||||
options.upload_gzip = true;
|
||||
|
||||
const option long_options[] = {
|
||||
{"annotation", required_argument, nullptr, kOptionAnnotation},
|
||||
{"database", required_argument, nullptr, kOptionDatabase},
|
||||
@ -345,15 +447,25 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
{"mach-service", required_argument, nullptr, kOptionMachService},
|
||||
#endif // OS_MACOSX
|
||||
{"metrics-dir", required_argument, nullptr, kOptionMetrics},
|
||||
{"monitor-self", no_argument, nullptr, kOptionMonitorSelf},
|
||||
{"monitor-self-annotation",
|
||||
required_argument,
|
||||
nullptr,
|
||||
kOptionMonitorSelfAnnotation},
|
||||
{"monitor-self-argument",
|
||||
required_argument,
|
||||
nullptr,
|
||||
kOptionMonitorSelfArgument},
|
||||
{"no-rate-limit", no_argument, nullptr, kOptionNoRateLimit},
|
||||
{"no-upload-gzip", no_argument, nullptr, kOptionNoUploadGzip},
|
||||
#if defined(OS_WIN)
|
||||
{"pipe-name", required_argument, nullptr, kOptionPipeName},
|
||||
#endif // OS_WIN
|
||||
#if defined(OS_MACOSX)
|
||||
{"reset-own-crash-exception-port-to-system-default",
|
||||
no_argument,
|
||||
nullptr,
|
||||
kOptionResetOwnCrashExceptionPortToSystemDefault},
|
||||
#elif defined(OS_WIN)
|
||||
{"pipe-name", required_argument, nullptr, kOptionPipeName},
|
||||
#endif // OS_MACOSX
|
||||
{"url", required_argument, nullptr, kOptionURL},
|
||||
{"help", no_argument, nullptr, kOptionHelp},
|
||||
@ -361,25 +473,25 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
{nullptr, 0, nullptr, 0},
|
||||
};
|
||||
|
||||
Options options = {};
|
||||
#if defined(OS_MACOSX)
|
||||
options.handshake_fd = -1;
|
||||
#endif
|
||||
options.rate_limit = true;
|
||||
options.upload_gzip = true;
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt_long(argc, argv, "", long_options, nullptr)) != -1) {
|
||||
switch (opt) {
|
||||
case kOptionAnnotation: {
|
||||
std::string key;
|
||||
std::string value;
|
||||
if (!SplitStringFirst(optarg, '=', &key, &value)) {
|
||||
ToolSupport::UsageHint(me, "--annotation requires KEY=VALUE");
|
||||
if (!AddKeyValueToMap(&options.annotations, optarg, "--annotation")) {
|
||||
return ExitFailure();
|
||||
}
|
||||
std::string old_value;
|
||||
if (!MapInsertOrReplace(&options.annotations, key, value, &old_value)) {
|
||||
LOG(WARNING) << "duplicate key " << key << ", discarding value "
|
||||
<< old_value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kOptionDatabase: {
|
||||
options.database = optarg;
|
||||
options.database = base::FilePath(
|
||||
ToolSupport::CommandLineArgumentToFilePathStringType(optarg));
|
||||
break;
|
||||
}
|
||||
#if defined(OS_MACOSX)
|
||||
@ -396,7 +508,8 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
options.mach_service = optarg;
|
||||
break;
|
||||
}
|
||||
#elif defined(OS_WIN)
|
||||
#endif // OS_MACOSX
|
||||
#if defined(OS_WIN)
|
||||
case kOptionInitialClientData: {
|
||||
if (!options.initial_client_data.InitializeFromString(optarg)) {
|
||||
ToolSupport::UsageHint(
|
||||
@ -405,9 +518,26 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif // OS_MACOSX
|
||||
#endif // OS_WIN
|
||||
case kOptionMetrics: {
|
||||
options.metrics = optarg;
|
||||
options.metrics_dir = base::FilePath(
|
||||
ToolSupport::CommandLineArgumentToFilePathStringType(optarg));
|
||||
break;
|
||||
}
|
||||
case kOptionMonitorSelf: {
|
||||
options.monitor_self = true;
|
||||
break;
|
||||
}
|
||||
case kOptionMonitorSelfAnnotation: {
|
||||
if (!AddKeyValueToMap(&options.monitor_self_annotations,
|
||||
optarg,
|
||||
"--monitor-self-annotation")) {
|
||||
return ExitFailure();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kOptionMonitorSelfArgument: {
|
||||
options.monitor_self_arguments.push_back(optarg);
|
||||
break;
|
||||
}
|
||||
case kOptionNoRateLimit: {
|
||||
@ -418,16 +548,17 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
options.upload_gzip = false;
|
||||
break;
|
||||
}
|
||||
#if defined(OS_WIN)
|
||||
case kOptionPipeName: {
|
||||
options.pipe_name = optarg;
|
||||
break;
|
||||
}
|
||||
#endif // OS_WIN
|
||||
#if defined(OS_MACOSX)
|
||||
case kOptionResetOwnCrashExceptionPortToSystemDefault: {
|
||||
options.reset_own_crash_exception_port_to_system_default = true;
|
||||
break;
|
||||
}
|
||||
#elif defined(OS_WIN)
|
||||
case kOptionPipeName: {
|
||||
options.pipe_name = optarg;
|
||||
break;
|
||||
}
|
||||
#endif // OS_MACOSX
|
||||
case kOptionURL: {
|
||||
options.url = optarg;
|
||||
@ -475,7 +606,7 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
}
|
||||
#endif // OS_MACOSX
|
||||
|
||||
if (!options.database) {
|
||||
if (options.database.empty()) {
|
||||
ToolSupport::UsageHint(me, "--database is required");
|
||||
return ExitFailure();
|
||||
}
|
||||
@ -485,16 +616,42 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
return ExitFailure();
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
if (options.reset_own_crash_exception_port_to_system_default) {
|
||||
CrashpadClient::UseSystemDefaultHandler();
|
||||
}
|
||||
#endif // OS_MACOSX
|
||||
|
||||
if (options.monitor_self) {
|
||||
MonitorSelf(options);
|
||||
}
|
||||
|
||||
if (!options.monitor_self_annotations.empty()) {
|
||||
// Establish these annotations even if --monitor-self is not present, in
|
||||
// case something such as generate_dump wants to try to access them later.
|
||||
//
|
||||
// If the handler is part of a multi-purpose executable, simple annotations
|
||||
// may already be present for this module. If they are, use them.
|
||||
CrashpadInfo* crashpad_info = CrashpadInfo::GetCrashpadInfo();
|
||||
SimpleStringDictionary* module_annotations =
|
||||
crashpad_info->simple_annotations();
|
||||
if (!module_annotations) {
|
||||
module_annotations = new SimpleStringDictionary();
|
||||
crashpad_info->set_simple_annotations(module_annotations);
|
||||
}
|
||||
|
||||
for (const auto& iterator : options.monitor_self_annotations) {
|
||||
module_annotations->SetKeyValue(iterator.first.c_str(),
|
||||
iterator.second.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
if (options.mach_service.empty()) {
|
||||
// Don’t do this when being run by launchd. See launchd.plist(5).
|
||||
CloseStdinAndStdout();
|
||||
}
|
||||
|
||||
if (options.reset_own_crash_exception_port_to_system_default) {
|
||||
CrashpadClient::UseSystemDefaultHandler();
|
||||
}
|
||||
|
||||
base::mac::ScopedMachReceiveRight receive_right;
|
||||
|
||||
if (options.handshake_fd >= 0) {
|
||||
@ -543,13 +700,11 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
#endif // OS_MACOSX
|
||||
|
||||
base::GlobalHistogramAllocator* histogram_allocator = nullptr;
|
||||
if (options.metrics) {
|
||||
const base::FilePath metrics_dir(
|
||||
ToolSupport::CommandLineArgumentToFilePathStringType(options.metrics));
|
||||
if (!options.metrics_dir.empty()) {
|
||||
static const char kMetricsName[] = "CrashpadMetrics";
|
||||
const size_t kMetricsFileSize = 1 << 20;
|
||||
if (base::GlobalHistogramAllocator::CreateWithActiveFileInDir(
|
||||
metrics_dir, kMetricsFileSize, 0, kMetricsName)) {
|
||||
options.metrics_dir, kMetricsFileSize, 0, kMetricsName)) {
|
||||
histogram_allocator = base::GlobalHistogramAllocator::Get();
|
||||
histogram_allocator->CreateTrackingHistograms(kMetricsName);
|
||||
}
|
||||
@ -557,9 +712,8 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
|
||||
Metrics::HandlerLifetimeMilestone(Metrics::LifetimeMilestone::kStarted);
|
||||
|
||||
std::unique_ptr<CrashReportDatabase> database(CrashReportDatabase::Initialize(
|
||||
base::FilePath(ToolSupport::CommandLineArgumentToFilePathStringType(
|
||||
options.database))));
|
||||
std::unique_ptr<CrashReportDatabase> database(
|
||||
CrashReportDatabase::Initialize(options.database));
|
||||
if (!database) {
|
||||
return ExitFailure();
|
||||
}
|
||||
@ -575,8 +729,10 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
PruneCondition::GetDefault());
|
||||
prune_thread.Start();
|
||||
|
||||
CrashReportExceptionHandler exception_handler(
|
||||
database.get(), &upload_thread, &options.annotations);
|
||||
CrashReportExceptionHandler exception_handler(database.get(),
|
||||
&upload_thread,
|
||||
&options.annotations,
|
||||
user_stream_sources);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
if (options.initial_client_data.IsValid()) {
|
||||
|
@ -15,13 +15,24 @@
|
||||
#ifndef CRASHPAD_HANDLER_HANDLER_MAIN_H_
|
||||
#define CRASHPAD_HANDLER_HANDLER_MAIN_H_
|
||||
|
||||
#include "handler/user_stream_data_source.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
//! \brief The `main()` of the `crashpad_handler` binary.
|
||||
//!
|
||||
//! This is exposed so that `crashpad_handler` can be embedded into another
|
||||
//! binary, but called and used as if it were a standalone executable.
|
||||
int HandlerMain(int argc, char* argv[]);
|
||||
//!
|
||||
//! \param[in] argc \a argc as passed to `main()`.
|
||||
//! \param[in] argv \a argv as passed to `main()`.
|
||||
//! \param[in] user_stream_sources An optional vector containing the
|
||||
//! extensibility data sources to call on crash. Each time a minidump is
|
||||
//! created, the sources are called in turn. Any streams returned are added
|
||||
//! to the minidump.
|
||||
int HandlerMain(int argc,
|
||||
char* argv[],
|
||||
const UserStreamDataSources* user_stream_sources);
|
||||
|
||||
} // namespace crashpad
|
||||
|
||||
|
64
handler/handler_test.gyp
Normal file
64
handler/handler_test.gyp
Normal file
@ -0,0 +1,64 @@
|
||||
# Copyright 2017 The Crashpad Authors. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
{
|
||||
'includes': [
|
||||
'../build/crashpad.gypi',
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'crashpad_handler_test_extended_handler',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'../compat/compat.gyp:crashpad_compat',
|
||||
'../minidump/minidump_test.gyp:crashpad_minidump_test_lib',
|
||||
'../third_party/mini_chromium/mini_chromium.gyp:base',
|
||||
'../tools/tools.gyp:crashpad_tool_support',
|
||||
'handler.gyp:crashpad_handler_lib',
|
||||
],
|
||||
'include_dirs': [
|
||||
'..',
|
||||
],
|
||||
'sources': [
|
||||
'crashpad_handler_test_extended_handler.cc',
|
||||
],
|
||||
},
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
'targets': [{
|
||||
# The handler is only tested on Windows for now.
|
||||
'target_name': 'crashpad_handler_test',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'crashpad_handler_test_extended_handler',
|
||||
'handler.gyp:crashpad_handler_lib',
|
||||
'../client/client.gyp:crashpad_client',
|
||||
'../compat/compat.gyp:crashpad_compat',
|
||||
'../test/test.gyp:crashpad_gtest_main',
|
||||
'../test/test.gyp:crashpad_test',
|
||||
'../third_party/gtest/gtest.gyp:gtest',
|
||||
'../third_party/mini_chromium/mini_chromium.gyp:base',
|
||||
'../util/util.gyp:crashpad_util',
|
||||
],
|
||||
'include_dirs': [
|
||||
'..',
|
||||
],
|
||||
'sources': [
|
||||
'crashpad_handler_test.cc',
|
||||
],
|
||||
}],
|
||||
}],
|
||||
],
|
||||
}
|
@ -22,6 +22,7 @@
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "client/settings.h"
|
||||
#include "minidump/minidump_file_writer.h"
|
||||
#include "minidump/minidump_user_extension_stream_data_source.h"
|
||||
#include "snapshot/crashpad_info_client_options.h"
|
||||
#include "snapshot/mac/process_snapshot_mac.h"
|
||||
#include "util/file/file_writer.h"
|
||||
@ -41,11 +42,12 @@ namespace crashpad {
|
||||
CrashReportExceptionHandler::CrashReportExceptionHandler(
|
||||
CrashReportDatabase* database,
|
||||
CrashReportUploadThread* upload_thread,
|
||||
const std::map<std::string, std::string>* process_annotations)
|
||||
const std::map<std::string, std::string>* process_annotations,
|
||||
const UserStreamDataSources* user_stream_data_sources)
|
||||
: database_(database),
|
||||
upload_thread_(upload_thread),
|
||||
process_annotations_(process_annotations) {
|
||||
}
|
||||
process_annotations_(process_annotations),
|
||||
user_stream_data_sources_(user_stream_data_sources) {}
|
||||
|
||||
CrashReportExceptionHandler::~CrashReportExceptionHandler() {
|
||||
}
|
||||
@ -169,6 +171,9 @@ kern_return_t CrashReportExceptionHandler::CatchMachException(
|
||||
|
||||
MinidumpFileWriter minidump;
|
||||
minidump.InitializeFromSnapshot(&process_snapshot);
|
||||
AddUserExtensionStreams(
|
||||
user_stream_data_sources_, &process_snapshot, &minidump);
|
||||
|
||||
if (!minidump.WriteEverything(&file_writer)) {
|
||||
Metrics::ExceptionCaptureResult(
|
||||
Metrics::CaptureResult::kMinidumpWriteFailed);
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "base/macros.h"
|
||||
#include "client/crash_report_database.h"
|
||||
#include "handler/crash_report_upload_thread.h"
|
||||
#include "handler/user_stream_data_source.h"
|
||||
#include "util/mach/exc_server_variants.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -46,10 +47,15 @@ class CrashReportExceptionHandler : public UniversalMachExcServer::Interface {
|
||||
//! To interoperate with Breakpad servers, the recommended practice is to
|
||||
//! specify values for the `"prod"` and `"ver"` keys as process
|
||||
//! annotations.
|
||||
//! \param[in] user_stream_data_sources Data sources to be used to extend
|
||||
//! crash reports. For each crash report that is written, the data sources
|
||||
//! are called in turn. These data sources may contribute additional
|
||||
//! minidump streams. `nullptr` if not required.
|
||||
CrashReportExceptionHandler(
|
||||
CrashReportDatabase* database,
|
||||
CrashReportUploadThread* upload_thread,
|
||||
const std::map<std::string, std::string>* process_annotations);
|
||||
const std::map<std::string, std::string>* process_annotations,
|
||||
const UserStreamDataSources* user_stream_data_sources);
|
||||
|
||||
~CrashReportExceptionHandler();
|
||||
|
||||
@ -77,6 +83,7 @@ class CrashReportExceptionHandler : public UniversalMachExcServer::Interface {
|
||||
CrashReportDatabase* database_; // weak
|
||||
CrashReportUploadThread* upload_thread_; // weak
|
||||
const std::map<std::string, std::string>* process_annotations_; // weak
|
||||
const UserStreamDataSources* user_stream_data_sources_; // weak
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CrashReportExceptionHandler);
|
||||
};
|
||||
|
@ -23,10 +23,18 @@
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
int main(int argc, char* argv[]) {
|
||||
return crashpad::HandlerMain(argc, argv);
|
||||
return crashpad::HandlerMain(argc, argv, nullptr);
|
||||
}
|
||||
#elif defined(OS_WIN)
|
||||
namespace {
|
||||
|
||||
int HandlerMainAdaptor(int argc, char* argv[]) {
|
||||
return crashpad::HandlerMain(argc, argv, nullptr);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int APIENTRY wWinMain(HINSTANCE, HINSTANCE, wchar_t*, int) {
|
||||
return crashpad::ToolSupport::Wmain(__argc, __wargv, crashpad::HandlerMain);
|
||||
return crashpad::ToolSupport::Wmain(__argc, __wargv, HandlerMainAdaptor);
|
||||
}
|
||||
#endif // OS_MACOSX
|
||||
|
43
handler/user_stream_data_source.cc
Normal file
43
handler/user_stream_data_source.cc
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2017 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "handler/user_stream_data_source.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "minidump/minidump_file_writer.h"
|
||||
#include "minidump/minidump_user_extension_stream_data_source.h"
|
||||
#include "snapshot/process_snapshot.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
void AddUserExtensionStreams(
|
||||
const UserStreamDataSources* user_stream_data_sources,
|
||||
ProcessSnapshot* process_snapshot,
|
||||
MinidumpFileWriter* minidump_file_writer) {
|
||||
if (!user_stream_data_sources)
|
||||
return;
|
||||
for (const auto& source : *user_stream_data_sources) {
|
||||
std::unique_ptr<MinidumpUserExtensionStreamDataSource> data_source(
|
||||
source->ProduceStreamData(process_snapshot));
|
||||
if (data_source &&
|
||||
!minidump_file_writer->AddUserExtensionStream(std::move(data_source))) {
|
||||
// This should only happen if multiple user stream sources yield the
|
||||
// same stream type. It's the user's responsibility to make sure
|
||||
// sources don't collide on the same stream type.
|
||||
LOG(ERROR) << "AddUserExtensionStream failed";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace crashpad
|
68
handler/user_stream_data_source.h
Normal file
68
handler/user_stream_data_source.h
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright 2017 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CRASHPAD_HANDLER_USER_STREAM_DATA_SOURCE_H_
|
||||
#define CRASHPAD_HANDLER_USER_STREAM_DATA_SOURCE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
class MinidumpFileWriter;
|
||||
class MinidumpUserExtensionStreamDataSource;
|
||||
class ProcessSnapshot;
|
||||
|
||||
//! \brief Extensibility interface for embedders who wish to add custom streams
|
||||
//! to minidumps.
|
||||
class UserStreamDataSource {
|
||||
public:
|
||||
virtual ~UserStreamDataSource() {}
|
||||
|
||||
//! \brief Produce the contents for an extension stream for a crashed program.
|
||||
//!
|
||||
//! Called after \a process_snapshot has been initialized for the crashed
|
||||
//! process to (optionally) produce the contents of a user extension stream
|
||||
//! that will be attached to the minidump.
|
||||
//!
|
||||
//! \param[in] process_snapshot An initialized snapshot for the crashed
|
||||
//! process.
|
||||
//!
|
||||
//! \return A new data source for the stream to add to the minidump or
|
||||
//! `nullptr` on failure or to opt out of adding a stream.
|
||||
virtual std::unique_ptr<MinidumpUserExtensionStreamDataSource>
|
||||
ProduceStreamData(ProcessSnapshot* process_snapshot) = 0;
|
||||
};
|
||||
|
||||
using UserStreamDataSources =
|
||||
std::vector<std::unique_ptr<UserStreamDataSource>>;
|
||||
|
||||
//! \brief Adds user extension streams to a minidump.
|
||||
//!
|
||||
//! Dispatches to each source in \a user_stream_data_sources and adds returned
|
||||
//! extension streams to \a minidump_file_writer.
|
||||
//!
|
||||
//! \param[in] user_stream_data_sources A pointer to the data sources, or
|
||||
//! `nullptr`.
|
||||
//! \param[in] process_snapshot An initialized snapshot to the crashing process.
|
||||
//! \param[in] minidump_file_writer Any extension streams will be added to this
|
||||
//! minidump.
|
||||
void AddUserExtensionStreams(
|
||||
const UserStreamDataSources* user_stream_data_sources,
|
||||
ProcessSnapshot* process_snapshot,
|
||||
MinidumpFileWriter* minidump_file_writer);
|
||||
|
||||
} // namespace crashpad
|
||||
|
||||
#endif // CRASHPAD_HANDLER_USER_STREAM_DATA_SOURCE_H_
|
@ -18,8 +18,9 @@
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "client/crashpad_client.h"
|
||||
#include "test/paths.h"
|
||||
#include "test/test_paths.h"
|
||||
#include "test/win/child_launcher.h"
|
||||
#include "util/file/file_io.h"
|
||||
#include "util/win/scoped_handle.h"
|
||||
@ -29,20 +30,21 @@ namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
constexpr DWORD kCrashAndDumpTargetExitCode = 0xdeadbea7;
|
||||
|
||||
bool CrashAndDumpTarget(const CrashpadClient& client, HANDLE process) {
|
||||
DWORD target_pid = GetProcessId(process);
|
||||
|
||||
HANDLE thread_snap_raw = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||
if (thread_snap_raw == INVALID_HANDLE_VALUE) {
|
||||
LOG(ERROR) << "CreateToolhelp32Snapshot";
|
||||
ScopedFileHANDLE thread_snap(CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0));
|
||||
if (!thread_snap.is_valid()) {
|
||||
PLOG(ERROR) << "CreateToolhelp32Snapshot";
|
||||
return false;
|
||||
}
|
||||
ScopedFileHANDLE thread_snap(thread_snap_raw);
|
||||
|
||||
THREADENTRY32 te32;
|
||||
te32.dwSize = sizeof(THREADENTRY32);
|
||||
if (!Thread32First(thread_snap.get(), &te32)) {
|
||||
LOG(ERROR) << "Thread32First";
|
||||
PLOG(ERROR) << "Thread32First";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -55,9 +57,12 @@ bool CrashAndDumpTarget(const CrashpadClient& client, HANDLE process) {
|
||||
if (te32.tpBasePri == 9) {
|
||||
ScopedKernelHANDLE thread(
|
||||
OpenThread(kXPThreadAllAccess, false, te32.th32ThreadID));
|
||||
if (!thread.is_valid()) {
|
||||
PLOG(ERROR) << "OpenThread";
|
||||
return false;
|
||||
}
|
||||
if (!client.DumpAndCrashTargetProcess(
|
||||
process, thread.get(), 0xdeadbea7)) {
|
||||
LOG(ERROR) << "DumpAndCrashTargetProcess failed";
|
||||
process, thread.get(), kCrashAndDumpTargetExitCode)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -65,6 +70,7 @@ bool CrashAndDumpTarget(const CrashpadClient& client, HANDLE process) {
|
||||
}
|
||||
} while (Thread32Next(thread_snap.get(), &te32));
|
||||
|
||||
LOG(ERROR) << "target not found";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -73,7 +79,7 @@ int CrashOtherProgram(int argc, wchar_t* argv[]) {
|
||||
|
||||
if (argc == 2 || argc == 3) {
|
||||
if (!client.SetHandlerIPCPipe(argv[1])) {
|
||||
LOG(ERROR) << "SetHandler";
|
||||
LOG(ERROR) << "SetHandlerIPCPipe";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} else {
|
||||
@ -82,7 +88,7 @@ int CrashOtherProgram(int argc, wchar_t* argv[]) {
|
||||
}
|
||||
|
||||
// Launch another process that hangs.
|
||||
base::FilePath test_executable = Paths::Executable();
|
||||
base::FilePath test_executable = TestPaths::Executable();
|
||||
std::wstring child_test_executable =
|
||||
test_executable.DirName().Append(L"hanging_program.exe").value();
|
||||
ChildLauncher child(child_test_executable, argv[1]);
|
||||
@ -96,15 +102,28 @@ int CrashOtherProgram(int argc, wchar_t* argv[]) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
DWORD expect_exit_code;
|
||||
if (argc == 3 && wcscmp(argv[2], L"noexception") == 0) {
|
||||
client.DumpAndCrashTargetProcess(child.process_handle(), 0, 0);
|
||||
return EXIT_SUCCESS;
|
||||
expect_exit_code = CrashpadClient::kTriggeredExceptionCode;
|
||||
if (!client.DumpAndCrashTargetProcess(child.process_handle(), 0, 0))
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
if (CrashAndDumpTarget(client, child.process_handle()))
|
||||
return EXIT_SUCCESS;
|
||||
expect_exit_code = kCrashAndDumpTargetExitCode;
|
||||
if (!CrashAndDumpTarget(client, child.process_handle())) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
DWORD exit_code = child.WaitForExit();
|
||||
if (exit_code != expect_exit_code) {
|
||||
LOG(ERROR) << base::StringPrintf(
|
||||
"incorrect exit code, expected 0x%x, observed 0x%x",
|
||||
expect_exit_code,
|
||||
exit_code);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "client/settings.h"
|
||||
#include "handler/crash_report_upload_thread.h"
|
||||
#include "minidump/minidump_file_writer.h"
|
||||
#include "minidump/minidump_user_extension_stream_data_source.h"
|
||||
#include "snapshot/win/process_snapshot_win.h"
|
||||
#include "util/file/file_writer.h"
|
||||
#include "util/misc/metrics.h"
|
||||
@ -32,11 +33,12 @@ namespace crashpad {
|
||||
CrashReportExceptionHandler::CrashReportExceptionHandler(
|
||||
CrashReportDatabase* database,
|
||||
CrashReportUploadThread* upload_thread,
|
||||
const std::map<std::string, std::string>* process_annotations)
|
||||
const std::map<std::string, std::string>* process_annotations,
|
||||
const UserStreamDataSources* user_stream_data_sources)
|
||||
: database_(database),
|
||||
upload_thread_(upload_thread),
|
||||
process_annotations_(process_annotations) {
|
||||
}
|
||||
process_annotations_(process_annotations),
|
||||
user_stream_data_sources_(user_stream_data_sources) {}
|
||||
|
||||
CrashReportExceptionHandler::~CrashReportExceptionHandler() {
|
||||
}
|
||||
@ -107,6 +109,9 @@ unsigned int CrashReportExceptionHandler::ExceptionHandlerServerException(
|
||||
|
||||
MinidumpFileWriter minidump;
|
||||
minidump.InitializeFromSnapshot(&process_snapshot);
|
||||
AddUserExtensionStreams(
|
||||
user_stream_data_sources_, &process_snapshot, &minidump);
|
||||
|
||||
if (!minidump.WriteEverything(&file_writer)) {
|
||||
LOG(ERROR) << "WriteEverything failed";
|
||||
Metrics::ExceptionCaptureResult(
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "handler/user_stream_data_source.h"
|
||||
#include "util/win/exception_handler_server.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -47,10 +48,15 @@ class CrashReportExceptionHandler : public ExceptionHandlerServer::Delegate {
|
||||
//! To interoperate with Breakpad servers, the recommended practice is to
|
||||
//! specify values for the `"prod"` and `"ver"` keys as process
|
||||
//! annotations.
|
||||
//! \param[in] user_stream_data_sources Data sources to be used to extend
|
||||
//! crash reports. For each crash report that is written, the data sources
|
||||
//! are called in turn. These data sources may contribute additional
|
||||
//! minidump streams. `nullptr` if not required.
|
||||
CrashReportExceptionHandler(
|
||||
CrashReportDatabase* database,
|
||||
CrashReportUploadThread* upload_thread,
|
||||
const std::map<std::string, std::string>* process_annotations);
|
||||
const std::map<std::string, std::string>* process_annotations,
|
||||
const UserStreamDataSources* user_stream_data_sources);
|
||||
|
||||
~CrashReportExceptionHandler() override;
|
||||
|
||||
@ -68,6 +74,7 @@ class CrashReportExceptionHandler : public ExceptionHandlerServer::Delegate {
|
||||
CrashReportDatabase* database_; // weak
|
||||
CrashReportUploadThread* upload_thread_; // weak
|
||||
const std::map<std::string, std::string>* process_annotations_; // weak
|
||||
const UserStreamDataSources* user_stream_data_sources_; // weak
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CrashReportExceptionHandler);
|
||||
};
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "base/logging.h"
|
||||
#include "build/build_config.h"
|
||||
#include "client/crashpad_client.h"
|
||||
#include "test/paths.h"
|
||||
#include "test/test_paths.h"
|
||||
|
||||
#if !defined(ARCH_CPU_X86)
|
||||
#error This test is only supported on x86.
|
||||
@ -43,7 +43,7 @@ int CrashyLoadZ7Main(int argc, wchar_t* argv[]) {
|
||||
// The DLL has /Z7 symbols embedded in the binary (rather than in a .pdb).
|
||||
// There's only an x86 version of this dll as newer x64 toolchains can't
|
||||
// generate this format any more.
|
||||
base::FilePath z7_path = test::Paths::TestDataRoot().Append(
|
||||
base::FilePath z7_path = test::TestPaths::TestDataRoot().Append(
|
||||
FILE_PATH_LITERAL("handler/win/z7_test.dll"));
|
||||
HMODULE z7_test = LoadLibrary(z7_path.value().c_str());
|
||||
if (!z7_test) {
|
||||
|
@ -39,7 +39,7 @@ TEST(MinidumpContextWriter, MinidumpContextX86Writer) {
|
||||
MinidumpContextX86Writer context_writer;
|
||||
|
||||
EXPECT_TRUE(context_writer.WriteEverything(&string_file));
|
||||
ASSERT_EQ(sizeof(MinidumpContextX86), string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), sizeof(MinidumpContextX86));
|
||||
|
||||
const MinidumpContextX86* observed =
|
||||
MinidumpWritableAtRVA<MinidumpContextX86>(string_file.string(), 0);
|
||||
@ -58,7 +58,7 @@ TEST(MinidumpContextWriter, MinidumpContextX86Writer) {
|
||||
InitializeMinidumpContextX86(context_writer.context(), kSeed);
|
||||
|
||||
EXPECT_TRUE(context_writer.WriteEverything(&string_file));
|
||||
ASSERT_EQ(sizeof(MinidumpContextX86), string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), sizeof(MinidumpContextX86));
|
||||
|
||||
const MinidumpContextX86* observed =
|
||||
MinidumpWritableAtRVA<MinidumpContextX86>(string_file.string(), 0);
|
||||
@ -79,7 +79,7 @@ TEST(MinidumpContextWriter, MinidumpContextAMD64Writer) {
|
||||
MinidumpContextAMD64Writer context_writer;
|
||||
|
||||
EXPECT_TRUE(context_writer.WriteEverything(&string_file));
|
||||
ASSERT_EQ(sizeof(MinidumpContextAMD64), string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), sizeof(MinidumpContextAMD64));
|
||||
|
||||
const MinidumpContextAMD64* observed =
|
||||
MinidumpWritableAtRVA<MinidumpContextAMD64>(string_file.string(), 0);
|
||||
@ -98,7 +98,7 @@ TEST(MinidumpContextWriter, MinidumpContextAMD64Writer) {
|
||||
InitializeMinidumpContextAMD64(context_writer.context(), kSeed);
|
||||
|
||||
EXPECT_TRUE(context_writer.WriteEverything(&string_file));
|
||||
ASSERT_EQ(sizeof(MinidumpContextAMD64), string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), sizeof(MinidumpContextAMD64));
|
||||
|
||||
const MinidumpContextAMD64* observed =
|
||||
MinidumpWritableAtRVA<MinidumpContextAMD64>(string_file.string(), 0);
|
||||
|
@ -49,7 +49,7 @@ void GetCrashpadInfoStream(
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeCrashpadInfo, directory[0].StreamType);
|
||||
ASSERT_EQ(directory[0].StreamType, kMinidumpStreamTypeCrashpadInfo);
|
||||
|
||||
*crashpad_info = MinidumpWritableAtLocationDescriptor<MinidumpCrashpadInfo>(
|
||||
file_contents, directory[0].Location);
|
||||
@ -82,9 +82,9 @@ TEST(MinidumpCrashpadInfoWriter, Empty) {
|
||||
ASSERT_NO_FATAL_FAILURE(GetCrashpadInfoStream(
|
||||
string_file.string(), &crashpad_info, &simple_annotations, &module_list));
|
||||
|
||||
EXPECT_EQ(MinidumpCrashpadInfo::kVersion, crashpad_info->version);
|
||||
EXPECT_EQ(UUID(), crashpad_info->report_id);
|
||||
EXPECT_EQ(UUID(), crashpad_info->client_id);
|
||||
EXPECT_EQ(crashpad_info->version, MinidumpCrashpadInfo::kVersion);
|
||||
EXPECT_EQ(crashpad_info->report_id, UUID());
|
||||
EXPECT_EQ(crashpad_info->client_id, UUID());
|
||||
EXPECT_FALSE(simple_annotations);
|
||||
EXPECT_FALSE(module_list);
|
||||
}
|
||||
@ -118,9 +118,9 @@ TEST(MinidumpCrashpadInfoWriter, ReportAndClientID) {
|
||||
ASSERT_NO_FATAL_FAILURE(GetCrashpadInfoStream(
|
||||
string_file.string(), &crashpad_info, &simple_annotations, &module_list));
|
||||
|
||||
EXPECT_EQ(MinidumpCrashpadInfo::kVersion, crashpad_info->version);
|
||||
EXPECT_EQ(report_id, crashpad_info->report_id);
|
||||
EXPECT_EQ(client_id, crashpad_info->client_id);
|
||||
EXPECT_EQ(crashpad_info->version, MinidumpCrashpadInfo::kVersion);
|
||||
EXPECT_EQ(crashpad_info->report_id, report_id);
|
||||
EXPECT_EQ(crashpad_info->client_id, client_id);
|
||||
EXPECT_FALSE(simple_annotations);
|
||||
EXPECT_FALSE(module_list);
|
||||
}
|
||||
@ -160,17 +160,17 @@ TEST(MinidumpCrashpadInfoWriter, SimpleAnnotations) {
|
||||
ASSERT_NO_FATAL_FAILURE(GetCrashpadInfoStream(
|
||||
string_file.string(), &crashpad_info, &simple_annotations, &module_list));
|
||||
|
||||
EXPECT_EQ(MinidumpCrashpadInfo::kVersion, crashpad_info->version);
|
||||
EXPECT_EQ(crashpad_info->version, MinidumpCrashpadInfo::kVersion);
|
||||
EXPECT_FALSE(module_list);
|
||||
|
||||
ASSERT_TRUE(simple_annotations);
|
||||
ASSERT_EQ(1u, simple_annotations->count);
|
||||
EXPECT_EQ(kKey,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations->entries[0].key));
|
||||
EXPECT_EQ(kValue,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations->entries[0].value));
|
||||
ASSERT_EQ(simple_annotations->count, 1u);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
simple_annotations->entries[0].key),
|
||||
kKey);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations->entries[0].value),
|
||||
kValue);
|
||||
}
|
||||
|
||||
TEST(MinidumpCrashpadInfoWriter, CrashpadModuleList) {
|
||||
@ -201,24 +201,24 @@ TEST(MinidumpCrashpadInfoWriter, CrashpadModuleList) {
|
||||
ASSERT_NO_FATAL_FAILURE(GetCrashpadInfoStream(
|
||||
string_file.string(), &crashpad_info, &simple_annotations, &module_list));
|
||||
|
||||
EXPECT_EQ(MinidumpCrashpadInfo::kVersion, crashpad_info->version);
|
||||
EXPECT_EQ(crashpad_info->version, MinidumpCrashpadInfo::kVersion);
|
||||
EXPECT_FALSE(simple_annotations);
|
||||
|
||||
ASSERT_TRUE(module_list);
|
||||
ASSERT_EQ(1u, module_list->count);
|
||||
ASSERT_EQ(module_list->count, 1u);
|
||||
|
||||
EXPECT_EQ(kMinidumpModuleListIndex,
|
||||
module_list->modules[0].minidump_module_list_index);
|
||||
EXPECT_EQ(module_list->modules[0].minidump_module_list_index,
|
||||
kMinidumpModuleListIndex);
|
||||
const MinidumpModuleCrashpadInfo* module =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||
string_file.string(), module_list->modules[0].location);
|
||||
ASSERT_TRUE(module);
|
||||
|
||||
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module->version);
|
||||
EXPECT_EQ(0u, module->list_annotations.DataSize);
|
||||
EXPECT_EQ(0u, module->list_annotations.Rva);
|
||||
EXPECT_EQ(0u, module->simple_annotations.DataSize);
|
||||
EXPECT_EQ(0u, module->simple_annotations.Rva);
|
||||
EXPECT_EQ(module->version, MinidumpModuleCrashpadInfo::kVersion);
|
||||
EXPECT_EQ(module->list_annotations.DataSize, 0u);
|
||||
EXPECT_EQ(module->list_annotations.Rva, 0u);
|
||||
EXPECT_EQ(module->simple_annotations.DataSize, 0u);
|
||||
EXPECT_EQ(module->simple_annotations.Rva, 0u);
|
||||
}
|
||||
|
||||
TEST(MinidumpCrashpadInfoWriter, InitializeFromSnapshot) {
|
||||
@ -276,40 +276,40 @@ TEST(MinidumpCrashpadInfoWriter, InitializeFromSnapshot) {
|
||||
ASSERT_NO_FATAL_FAILURE(GetCrashpadInfoStream(
|
||||
string_file.string(), &info, &simple_annotations, &module_list));
|
||||
|
||||
EXPECT_EQ(MinidumpCrashpadInfo::kVersion, info->version);
|
||||
EXPECT_EQ(info->version, MinidumpCrashpadInfo::kVersion);
|
||||
|
||||
EXPECT_EQ(report_id, info->report_id);
|
||||
EXPECT_EQ(client_id, info->client_id);
|
||||
EXPECT_EQ(info->report_id, report_id);
|
||||
EXPECT_EQ(info->client_id, client_id);
|
||||
|
||||
ASSERT_TRUE(simple_annotations);
|
||||
ASSERT_EQ(1u, simple_annotations->count);
|
||||
EXPECT_EQ(kKey,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations->entries[0].key));
|
||||
EXPECT_EQ(kValue,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations->entries[0].value));
|
||||
ASSERT_EQ(simple_annotations->count, 1u);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
simple_annotations->entries[0].key),
|
||||
kKey);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations->entries[0].value),
|
||||
kValue);
|
||||
|
||||
ASSERT_TRUE(module_list);
|
||||
ASSERT_EQ(1u, module_list->count);
|
||||
ASSERT_EQ(module_list->count, 1u);
|
||||
|
||||
EXPECT_EQ(0u, module_list->modules[0].minidump_module_list_index);
|
||||
EXPECT_EQ(module_list->modules[0].minidump_module_list_index, 0u);
|
||||
const MinidumpModuleCrashpadInfo* module =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||
string_file.string(), module_list->modules[0].location);
|
||||
ASSERT_TRUE(module);
|
||||
|
||||
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module->version);
|
||||
EXPECT_EQ(module->version, MinidumpModuleCrashpadInfo::kVersion);
|
||||
|
||||
const MinidumpRVAList* list_annotations =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpRVAList>(
|
||||
string_file.string(), module->list_annotations);
|
||||
ASSERT_TRUE(list_annotations);
|
||||
|
||||
ASSERT_EQ(1u, list_annotations->count);
|
||||
EXPECT_EQ(kEntry,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
list_annotations->children[0]));
|
||||
ASSERT_EQ(list_annotations->count, 1u);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
list_annotations->children[0]),
|
||||
kEntry);
|
||||
|
||||
const MinidumpSimpleStringDictionary* module_simple_annotations =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
||||
|
@ -45,15 +45,15 @@ void GetExceptionStream(const std::string& file_contents,
|
||||
const size_t kContextOffset =
|
||||
kExceptionStreamOffset + sizeof(MINIDUMP_EXCEPTION_STREAM);
|
||||
const size_t kFileSize = kContextOffset + sizeof(MinidumpContextX86);
|
||||
ASSERT_EQ(file_contents.size(), kFileSize);
|
||||
ASSERT_EQ(kFileSize, file_contents.size());
|
||||
|
||||
const MINIDUMP_DIRECTORY* directory;
|
||||
const MINIDUMP_HEADER* header =
|
||||
MinidumpHeaderAtStart(file_contents, &directory);
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeException, directory[0].StreamType);
|
||||
EXPECT_EQ(kExceptionStreamOffset, directory[0].Location.Rva);
|
||||
ASSERT_EQ(directory[0].StreamType, kMinidumpStreamTypeException);
|
||||
EXPECT_EQ(directory[0].Location.Rva, kExceptionStreamOffset);
|
||||
|
||||
*exception_stream =
|
||||
MinidumpWritableAtLocationDescriptor<MINIDUMP_EXCEPTION_STREAM>(
|
||||
@ -68,24 +68,24 @@ void ExpectExceptionStream(const MINIDUMP_EXCEPTION_STREAM* expected,
|
||||
const MINIDUMP_EXCEPTION_STREAM* observed,
|
||||
const std::string& file_contents,
|
||||
const MinidumpContextX86** context) {
|
||||
EXPECT_EQ(expected->ThreadId, observed->ThreadId);
|
||||
EXPECT_EQ(0u, observed->__alignment);
|
||||
EXPECT_EQ(expected->ExceptionRecord.ExceptionCode,
|
||||
observed->ExceptionRecord.ExceptionCode);
|
||||
EXPECT_EQ(expected->ExceptionRecord.ExceptionFlags,
|
||||
observed->ExceptionRecord.ExceptionFlags);
|
||||
EXPECT_EQ(expected->ExceptionRecord.ExceptionRecord,
|
||||
observed->ExceptionRecord.ExceptionRecord);
|
||||
EXPECT_EQ(expected->ExceptionRecord.ExceptionAddress,
|
||||
observed->ExceptionRecord.ExceptionAddress);
|
||||
EXPECT_EQ(expected->ExceptionRecord.NumberParameters,
|
||||
observed->ExceptionRecord.NumberParameters);
|
||||
EXPECT_EQ(0u, observed->ExceptionRecord.__unusedAlignment);
|
||||
EXPECT_EQ(observed->ThreadId, expected->ThreadId);
|
||||
EXPECT_EQ(observed->__alignment, 0u);
|
||||
EXPECT_EQ(observed->ExceptionRecord.ExceptionCode,
|
||||
expected->ExceptionRecord.ExceptionCode);
|
||||
EXPECT_EQ(observed->ExceptionRecord.ExceptionFlags,
|
||||
expected->ExceptionRecord.ExceptionFlags);
|
||||
EXPECT_EQ(observed->ExceptionRecord.ExceptionRecord,
|
||||
expected->ExceptionRecord.ExceptionRecord);
|
||||
EXPECT_EQ(observed->ExceptionRecord.ExceptionAddress,
|
||||
expected->ExceptionRecord.ExceptionAddress);
|
||||
EXPECT_EQ(observed->ExceptionRecord.NumberParameters,
|
||||
expected->ExceptionRecord.NumberParameters);
|
||||
EXPECT_EQ(observed->ExceptionRecord.__unusedAlignment, 0u);
|
||||
for (size_t index = 0;
|
||||
index < arraysize(observed->ExceptionRecord.ExceptionInformation);
|
||||
++index) {
|
||||
EXPECT_EQ(expected->ExceptionRecord.ExceptionInformation[index],
|
||||
observed->ExceptionRecord.ExceptionInformation[index]);
|
||||
EXPECT_EQ(observed->ExceptionRecord.ExceptionInformation[index],
|
||||
expected->ExceptionRecord.ExceptionInformation[index]);
|
||||
}
|
||||
*context = MinidumpWritableAtLocationDescriptor<MinidumpContextX86>(
|
||||
file_contents, observed->ThreadContext);
|
||||
|
@ -206,9 +206,8 @@ bool MinidumpFileWriter::AddUserExtensionStream(
|
||||
DCHECK_EQ(state(), kStateMutable);
|
||||
|
||||
auto user_stream = base::WrapUnique(new MinidumpUserStreamWriter());
|
||||
user_stream->InitializeFromBuffer(user_extension_stream_data->stream_type(),
|
||||
user_extension_stream_data->buffer(),
|
||||
user_extension_stream_data->buffer_size());
|
||||
user_stream->InitializeFromUserExtensionStream(
|
||||
std::move(user_extension_stream_data));
|
||||
|
||||
return AddStream(std::move(user_stream));
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "minidump/minidump_user_extension_stream_data_source.h"
|
||||
#include "minidump/minidump_writable.h"
|
||||
#include "minidump/test/minidump_file_writer_test_util.h"
|
||||
#include "minidump/test/minidump_user_extension_stream_util.h"
|
||||
#include "minidump/test/minidump_writable_test_util.h"
|
||||
#include "snapshot/test/test_cpu_context.h"
|
||||
#include "snapshot/test/test_exception_snapshot.h"
|
||||
@ -47,7 +48,7 @@ TEST(MinidumpFileWriter, Empty) {
|
||||
MinidumpFileWriter minidump_file;
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file.WriteEverything(&string_file));
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER), string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), sizeof(MINIDUMP_HEADER));
|
||||
|
||||
const MINIDUMP_DIRECTORY* directory;
|
||||
const MINIDUMP_HEADER* header =
|
||||
@ -78,7 +79,7 @@ class TestStream final : public internal::MinidumpStreamWriter {
|
||||
}
|
||||
|
||||
bool WriteObject(FileWriterInterface* file_writer) override {
|
||||
EXPECT_EQ(state(), kStateWritable);
|
||||
EXPECT_EQ(kStateWritable, state());
|
||||
return file_writer->Write(&stream_data_[0], stream_data_.size());
|
||||
}
|
||||
|
||||
@ -108,7 +109,7 @@ TEST(MinidumpFileWriter, OneStream) {
|
||||
const size_t kStreamOffset = kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY);
|
||||
const size_t kFileSize = kStreamOffset + kStreamSize;
|
||||
|
||||
ASSERT_EQ(kFileSize, string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), kFileSize);
|
||||
|
||||
const MINIDUMP_DIRECTORY* directory;
|
||||
const MINIDUMP_HEADER* header =
|
||||
@ -116,16 +117,16 @@ TEST(MinidumpFileWriter, OneStream) {
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, kTimestamp));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
EXPECT_EQ(kStreamType, directory[0].StreamType);
|
||||
EXPECT_EQ(kStreamSize, directory[0].Location.DataSize);
|
||||
EXPECT_EQ(kStreamOffset, directory[0].Location.Rva);
|
||||
EXPECT_EQ(directory[0].StreamType, kStreamType);
|
||||
EXPECT_EQ(directory[0].Location.DataSize, kStreamSize);
|
||||
EXPECT_EQ(directory[0].Location.Rva, kStreamOffset);
|
||||
|
||||
const uint8_t* stream_data = MinidumpWritableAtLocationDescriptor<uint8_t>(
|
||||
string_file.string(), directory[0].Location);
|
||||
ASSERT_TRUE(stream_data);
|
||||
|
||||
std::string expected_stream(kStreamSize, kStreamValue);
|
||||
EXPECT_EQ(0, memcmp(stream_data, expected_stream.c_str(), kStreamSize));
|
||||
EXPECT_EQ(memcmp(stream_data, expected_stream.c_str(), kStreamSize), 0);
|
||||
}
|
||||
|
||||
TEST(MinidumpFileWriter, AddUserExtensionStream) {
|
||||
@ -137,14 +138,14 @@ TEST(MinidumpFileWriter, AddUserExtensionStream) {
|
||||
const size_t kStreamSize = arraysize(kStreamData);
|
||||
const MinidumpStreamType kStreamType = static_cast<MinidumpStreamType>(0x4d);
|
||||
|
||||
auto stream = base::WrapUnique(new MinidumpUserExtensionStreamDataSource(
|
||||
auto data_source = base::WrapUnique(new test::BufferExtensionStreamDataSource(
|
||||
kStreamType, kStreamData, kStreamSize));
|
||||
ASSERT_TRUE(minidump_file.AddUserExtensionStream(std::move(stream)));
|
||||
ASSERT_TRUE(minidump_file.AddUserExtensionStream(std::move(data_source)));
|
||||
|
||||
// Adding the same stream type a second time should fail.
|
||||
stream = base::WrapUnique(new MinidumpUserExtensionStreamDataSource(
|
||||
data_source = base::WrapUnique(new test::BufferExtensionStreamDataSource(
|
||||
kStreamType, kStreamData, kStreamSize));
|
||||
ASSERT_FALSE(minidump_file.AddUserExtensionStream(std::move(stream)));
|
||||
ASSERT_FALSE(minidump_file.AddUserExtensionStream(std::move(data_source)));
|
||||
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file.WriteEverything(&string_file));
|
||||
@ -153,7 +154,7 @@ TEST(MinidumpFileWriter, AddUserExtensionStream) {
|
||||
const size_t kStreamOffset = kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY);
|
||||
const size_t kFileSize = kStreamOffset + kStreamSize;
|
||||
|
||||
ASSERT_EQ(kFileSize, string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), kFileSize);
|
||||
|
||||
const MINIDUMP_DIRECTORY* directory;
|
||||
const MINIDUMP_HEADER* header =
|
||||
@ -161,15 +162,46 @@ TEST(MinidumpFileWriter, AddUserExtensionStream) {
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, kTimestamp));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
EXPECT_EQ(kStreamType, directory[0].StreamType);
|
||||
EXPECT_EQ(kStreamSize, directory[0].Location.DataSize);
|
||||
EXPECT_EQ(kStreamOffset, directory[0].Location.Rva);
|
||||
EXPECT_EQ(directory[0].StreamType, kStreamType);
|
||||
EXPECT_EQ(directory[0].Location.DataSize, kStreamSize);
|
||||
EXPECT_EQ(directory[0].Location.Rva, kStreamOffset);
|
||||
|
||||
const uint8_t* stream_data = MinidumpWritableAtLocationDescriptor<uint8_t>(
|
||||
string_file.string(), directory[0].Location);
|
||||
ASSERT_TRUE(stream_data);
|
||||
|
||||
EXPECT_EQ(0, memcmp(stream_data, kStreamData, kStreamSize));
|
||||
EXPECT_EQ(memcmp(stream_data, kStreamData, kStreamSize), 0);
|
||||
}
|
||||
|
||||
TEST(MinidumpFileWriter, AddEmptyUserExtensionStream) {
|
||||
MinidumpFileWriter minidump_file;
|
||||
const time_t kTimestamp = 0x155d2fb8;
|
||||
minidump_file.SetTimestamp(kTimestamp);
|
||||
|
||||
const MinidumpStreamType kStreamType = static_cast<MinidumpStreamType>(0x4d);
|
||||
|
||||
auto data_source = base::WrapUnique(
|
||||
new test::BufferExtensionStreamDataSource(kStreamType, nullptr, 0));
|
||||
ASSERT_TRUE(minidump_file.AddUserExtensionStream(std::move(data_source)));
|
||||
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file.WriteEverything(&string_file));
|
||||
|
||||
const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER);
|
||||
const size_t kStreamOffset = kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY);
|
||||
const size_t kFileSize = kStreamOffset;
|
||||
|
||||
ASSERT_EQ(string_file.string().size(), kFileSize);
|
||||
|
||||
const MINIDUMP_DIRECTORY* directory;
|
||||
const MINIDUMP_HEADER* header =
|
||||
MinidumpHeaderAtStart(string_file.string(), &directory);
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, kTimestamp));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
EXPECT_EQ(directory[0].StreamType, kStreamType);
|
||||
EXPECT_EQ(directory[0].Location.DataSize, 0u);
|
||||
EXPECT_EQ(directory[0].Location.Rva, kStreamOffset);
|
||||
}
|
||||
|
||||
TEST(MinidumpFileWriter, ThreeStreams) {
|
||||
@ -213,7 +245,7 @@ TEST(MinidumpFileWriter, ThreeStreams) {
|
||||
const size_t kStream2Offset = kStream1Offset + kStream1Size + kStream2Padding;
|
||||
const size_t kFileSize = kStream2Offset + kStream2Size;
|
||||
|
||||
ASSERT_EQ(kFileSize, string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), kFileSize);
|
||||
|
||||
const MINIDUMP_DIRECTORY* directory;
|
||||
const MINIDUMP_HEADER* header =
|
||||
@ -221,43 +253,43 @@ TEST(MinidumpFileWriter, ThreeStreams) {
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 3, kTimestamp));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
EXPECT_EQ(kStream0Type, directory[0].StreamType);
|
||||
EXPECT_EQ(kStream0Size, directory[0].Location.DataSize);
|
||||
EXPECT_EQ(kStream0Offset, directory[0].Location.Rva);
|
||||
EXPECT_EQ(kStream1Type, directory[1].StreamType);
|
||||
EXPECT_EQ(kStream1Size, directory[1].Location.DataSize);
|
||||
EXPECT_EQ(kStream1Offset, directory[1].Location.Rva);
|
||||
EXPECT_EQ(kStream2Type, directory[2].StreamType);
|
||||
EXPECT_EQ(kStream2Size, directory[2].Location.DataSize);
|
||||
EXPECT_EQ(kStream2Offset, directory[2].Location.Rva);
|
||||
EXPECT_EQ(directory[0].StreamType, kStream0Type);
|
||||
EXPECT_EQ(directory[0].Location.DataSize, kStream0Size);
|
||||
EXPECT_EQ(directory[0].Location.Rva, kStream0Offset);
|
||||
EXPECT_EQ(directory[1].StreamType, kStream1Type);
|
||||
EXPECT_EQ(directory[1].Location.DataSize, kStream1Size);
|
||||
EXPECT_EQ(directory[1].Location.Rva, kStream1Offset);
|
||||
EXPECT_EQ(directory[2].StreamType, kStream2Type);
|
||||
EXPECT_EQ(directory[2].Location.DataSize, kStream2Size);
|
||||
EXPECT_EQ(directory[2].Location.Rva, kStream2Offset);
|
||||
|
||||
const uint8_t* stream0_data = MinidumpWritableAtLocationDescriptor<uint8_t>(
|
||||
string_file.string(), directory[0].Location);
|
||||
ASSERT_TRUE(stream0_data);
|
||||
|
||||
std::string expected_stream0(kStream0Size, kStream0Value);
|
||||
EXPECT_EQ(0, memcmp(stream0_data, expected_stream0.c_str(), kStream0Size));
|
||||
EXPECT_EQ(memcmp(stream0_data, expected_stream0.c_str(), kStream0Size), 0);
|
||||
|
||||
const int kZeroes[16] = {};
|
||||
ASSERT_GE(sizeof(kZeroes), kStream1Padding);
|
||||
EXPECT_EQ(0, memcmp(stream0_data + kStream0Size, kZeroes, kStream1Padding));
|
||||
EXPECT_EQ(memcmp(stream0_data + kStream0Size, kZeroes, kStream1Padding), 0);
|
||||
|
||||
const uint8_t* stream1_data = MinidumpWritableAtLocationDescriptor<uint8_t>(
|
||||
string_file.string(), directory[1].Location);
|
||||
ASSERT_TRUE(stream1_data);
|
||||
|
||||
std::string expected_stream1(kStream1Size, kStream1Value);
|
||||
EXPECT_EQ(0, memcmp(stream1_data, expected_stream1.c_str(), kStream1Size));
|
||||
EXPECT_EQ(memcmp(stream1_data, expected_stream1.c_str(), kStream1Size), 0);
|
||||
|
||||
ASSERT_GE(sizeof(kZeroes), kStream2Padding);
|
||||
EXPECT_EQ(0, memcmp(stream1_data + kStream1Size, kZeroes, kStream2Padding));
|
||||
EXPECT_EQ(memcmp(stream1_data + kStream1Size, kZeroes, kStream2Padding), 0);
|
||||
|
||||
const uint8_t* stream2_data = MinidumpWritableAtLocationDescriptor<uint8_t>(
|
||||
string_file.string(), directory[2].Location);
|
||||
ASSERT_TRUE(stream2_data);
|
||||
|
||||
std::string expected_stream2(kStream2Size, kStream2Value);
|
||||
EXPECT_EQ(0, memcmp(stream2_data, expected_stream2.c_str(), kStream2Size));
|
||||
EXPECT_EQ(memcmp(stream2_data, expected_stream2.c_str(), kStream2Size), 0);
|
||||
}
|
||||
|
||||
TEST(MinidumpFileWriter, ZeroLengthStream) {
|
||||
@ -275,7 +307,7 @@ TEST(MinidumpFileWriter, ZeroLengthStream) {
|
||||
const size_t kStreamOffset = kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY);
|
||||
const size_t kFileSize = kStreamOffset + kStreamSize;
|
||||
|
||||
ASSERT_EQ(kFileSize, string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), kFileSize);
|
||||
|
||||
const MINIDUMP_DIRECTORY* directory;
|
||||
const MINIDUMP_HEADER* header =
|
||||
@ -283,9 +315,9 @@ TEST(MinidumpFileWriter, ZeroLengthStream) {
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
EXPECT_EQ(kStreamType, directory[0].StreamType);
|
||||
EXPECT_EQ(kStreamSize, directory[0].Location.DataSize);
|
||||
EXPECT_EQ(kStreamOffset, directory[0].Location.Rva);
|
||||
EXPECT_EQ(directory[0].StreamType, kStreamType);
|
||||
EXPECT_EQ(directory[0].Location.DataSize, kStreamSize);
|
||||
EXPECT_EQ(directory[0].Location.Rva, kStreamOffset);
|
||||
}
|
||||
|
||||
TEST(MinidumpFileWriter, InitializeFromSnapshot_Basic) {
|
||||
@ -320,32 +352,32 @@ TEST(MinidumpFileWriter, InitializeFromSnapshot_Basic) {
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 5, kSnapshotTime));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeSystemInfo, directory[0].StreamType);
|
||||
EXPECT_EQ(directory[0].StreamType, kMinidumpStreamTypeSystemInfo);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_SYSTEM_INFO>(
|
||||
string_file.string(), directory[0].Location));
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeMiscInfo, directory[1].StreamType);
|
||||
EXPECT_EQ(directory[1].StreamType, kMinidumpStreamTypeMiscInfo);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_MISC_INFO_4>(
|
||||
string_file.string(), directory[1].Location));
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeThreadList, directory[2].StreamType);
|
||||
EXPECT_EQ(directory[2].StreamType, kMinidumpStreamTypeThreadList);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_THREAD_LIST>(
|
||||
string_file.string(), directory[2].Location));
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeModuleList, directory[3].StreamType);
|
||||
EXPECT_EQ(directory[3].StreamType, kMinidumpStreamTypeModuleList);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_MODULE_LIST>(
|
||||
string_file.string(), directory[3].Location));
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeMemoryList, directory[4].StreamType);
|
||||
EXPECT_EQ(directory[4].StreamType, kMinidumpStreamTypeMemoryList);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_MEMORY_LIST>(
|
||||
string_file.string(), directory[4].Location));
|
||||
|
||||
const MINIDUMP_MEMORY_LIST* memory_list =
|
||||
MinidumpWritableAtLocationDescriptor<MINIDUMP_MEMORY_LIST>(
|
||||
string_file.string(), directory[4].Location);
|
||||
EXPECT_EQ(1u, memory_list->NumberOfMemoryRanges);
|
||||
EXPECT_EQ(kPebAddress, memory_list->MemoryRanges[0].StartOfMemoryRange);
|
||||
EXPECT_EQ(kPebSize, memory_list->MemoryRanges[0].Memory.DataSize);
|
||||
EXPECT_EQ(memory_list->NumberOfMemoryRanges, 1u);
|
||||
EXPECT_EQ(memory_list->MemoryRanges[0].StartOfMemoryRange, kPebAddress);
|
||||
EXPECT_EQ(memory_list->MemoryRanges[0].Memory.DataSize, kPebSize);
|
||||
}
|
||||
|
||||
TEST(MinidumpFileWriter, InitializeFromSnapshot_Exception) {
|
||||
@ -391,27 +423,27 @@ TEST(MinidumpFileWriter, InitializeFromSnapshot_Exception) {
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 6, kSnapshotTime));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeSystemInfo, directory[0].StreamType);
|
||||
EXPECT_EQ(directory[0].StreamType, kMinidumpStreamTypeSystemInfo);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_SYSTEM_INFO>(
|
||||
string_file.string(), directory[0].Location));
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeMiscInfo, directory[1].StreamType);
|
||||
EXPECT_EQ(directory[1].StreamType, kMinidumpStreamTypeMiscInfo);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_MISC_INFO_4>(
|
||||
string_file.string(), directory[1].Location));
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeThreadList, directory[2].StreamType);
|
||||
EXPECT_EQ(directory[2].StreamType, kMinidumpStreamTypeThreadList);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_THREAD_LIST>(
|
||||
string_file.string(), directory[2].Location));
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeException, directory[3].StreamType);
|
||||
EXPECT_EQ(directory[3].StreamType, kMinidumpStreamTypeException);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_EXCEPTION_STREAM>(
|
||||
string_file.string(), directory[3].Location));
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeModuleList, directory[4].StreamType);
|
||||
EXPECT_EQ(directory[4].StreamType, kMinidumpStreamTypeModuleList);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_MODULE_LIST>(
|
||||
string_file.string(), directory[4].Location));
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeMemoryList, directory[5].StreamType);
|
||||
EXPECT_EQ(directory[5].StreamType, kMinidumpStreamTypeMemoryList);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_MEMORY_LIST>(
|
||||
string_file.string(), directory[5].Location));
|
||||
}
|
||||
@ -455,31 +487,31 @@ TEST(MinidumpFileWriter, InitializeFromSnapshot_CrashpadInfo) {
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 7, kSnapshotTime));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeSystemInfo, directory[0].StreamType);
|
||||
EXPECT_EQ(directory[0].StreamType, kMinidumpStreamTypeSystemInfo);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_SYSTEM_INFO>(
|
||||
string_file.string(), directory[0].Location));
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeMiscInfo, directory[1].StreamType);
|
||||
EXPECT_EQ(directory[1].StreamType, kMinidumpStreamTypeMiscInfo);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_MISC_INFO_4>(
|
||||
string_file.string(), directory[1].Location));
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeThreadList, directory[2].StreamType);
|
||||
EXPECT_EQ(directory[2].StreamType, kMinidumpStreamTypeThreadList);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_THREAD_LIST>(
|
||||
string_file.string(), directory[2].Location));
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeException, directory[3].StreamType);
|
||||
EXPECT_EQ(directory[3].StreamType, kMinidumpStreamTypeException);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_EXCEPTION_STREAM>(
|
||||
string_file.string(), directory[3].Location));
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeModuleList, directory[4].StreamType);
|
||||
EXPECT_EQ(directory[4].StreamType, kMinidumpStreamTypeModuleList);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_MODULE_LIST>(
|
||||
string_file.string(), directory[4].Location));
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeCrashpadInfo, directory[5].StreamType);
|
||||
EXPECT_EQ(directory[5].StreamType, kMinidumpStreamTypeCrashpadInfo);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MinidumpCrashpadInfo>(
|
||||
string_file.string(), directory[5].Location));
|
||||
|
||||
EXPECT_EQ(kMinidumpStreamTypeMemoryList, directory[6].StreamType);
|
||||
EXPECT_EQ(directory[6].StreamType, kMinidumpStreamTypeMemoryList);
|
||||
EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_MEMORY_LIST>(
|
||||
string_file.string(), directory[6].Location));
|
||||
}
|
||||
@ -508,7 +540,7 @@ TEST(MinidumpFileWriter, SameStreamType) {
|
||||
const size_t kStream0Offset = kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY);
|
||||
const size_t kFileSize = kStream0Offset + kStream0Size;
|
||||
|
||||
ASSERT_EQ(kFileSize, string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), kFileSize);
|
||||
|
||||
const MINIDUMP_DIRECTORY* directory;
|
||||
const MINIDUMP_HEADER* header =
|
||||
@ -516,16 +548,16 @@ TEST(MinidumpFileWriter, SameStreamType) {
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
EXPECT_EQ(kStreamType, directory[0].StreamType);
|
||||
EXPECT_EQ(kStream0Size, directory[0].Location.DataSize);
|
||||
EXPECT_EQ(kStream0Offset, directory[0].Location.Rva);
|
||||
EXPECT_EQ(directory[0].StreamType, kStreamType);
|
||||
EXPECT_EQ(directory[0].Location.DataSize, kStream0Size);
|
||||
EXPECT_EQ(directory[0].Location.Rva, kStream0Offset);
|
||||
|
||||
const uint8_t* stream_data = MinidumpWritableAtLocationDescriptor<uint8_t>(
|
||||
string_file.string(), directory[0].Location);
|
||||
ASSERT_TRUE(stream_data);
|
||||
|
||||
std::string expected_stream(kStream0Size, kStream0Value);
|
||||
EXPECT_EQ(0, memcmp(stream_data, expected_stream.c_str(), kStream0Size));
|
||||
EXPECT_EQ(memcmp(stream_data, expected_stream.c_str(), kStream0Size), 0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -46,9 +46,9 @@ void GetHandleDataStream(
|
||||
|
||||
const size_t kDirectoryIndex = 0;
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeHandleData,
|
||||
directory[kDirectoryIndex].StreamType);
|
||||
EXPECT_EQ(kHandleDataStreamOffset, directory[kDirectoryIndex].Location.Rva);
|
||||
ASSERT_EQ(directory[kDirectoryIndex].StreamType,
|
||||
kMinidumpStreamTypeHandleData);
|
||||
EXPECT_EQ(directory[kDirectoryIndex].Location.Rva, kHandleDataStreamOffset);
|
||||
|
||||
*handle_data_stream =
|
||||
MinidumpWritableAtLocationDescriptor<MINIDUMP_HANDLE_DATA_STREAM>(
|
||||
@ -64,15 +64,15 @@ TEST(MinidumpHandleDataWriter, Empty) {
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_HANDLE_DATA_STREAM),
|
||||
string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_HANDLE_DATA_STREAM));
|
||||
|
||||
const MINIDUMP_HANDLE_DATA_STREAM* handle_data_stream = nullptr;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetHandleDataStream(string_file.string(), &handle_data_stream));
|
||||
|
||||
EXPECT_EQ(0u, handle_data_stream->NumberOfDescriptors);
|
||||
EXPECT_EQ(handle_data_stream->NumberOfDescriptors, 0u);
|
||||
}
|
||||
|
||||
TEST(MinidumpHandleDataWriter, OneHandle) {
|
||||
@ -99,29 +99,29 @@ TEST(MinidumpHandleDataWriter, OneHandle) {
|
||||
|
||||
const size_t kTypeNameStringDataLength =
|
||||
(handle_snapshot.type_name.size() + 1) * sizeof(base::char16);
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_HANDLE_DATA_STREAM) +
|
||||
sizeof(MINIDUMP_HANDLE_DESCRIPTOR) + sizeof(MINIDUMP_STRING) +
|
||||
kTypeNameStringDataLength,
|
||||
string_file.string().size());
|
||||
kTypeNameStringDataLength);
|
||||
|
||||
const MINIDUMP_HANDLE_DATA_STREAM* handle_data_stream = nullptr;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetHandleDataStream(string_file.string(), &handle_data_stream));
|
||||
|
||||
EXPECT_EQ(1u, handle_data_stream->NumberOfDescriptors);
|
||||
EXPECT_EQ(handle_data_stream->NumberOfDescriptors, 1u);
|
||||
const MINIDUMP_HANDLE_DESCRIPTOR* handle_descriptor =
|
||||
reinterpret_cast<const MINIDUMP_HANDLE_DESCRIPTOR*>(
|
||||
&handle_data_stream[1]);
|
||||
EXPECT_EQ(handle_snapshot.handle, handle_descriptor->Handle);
|
||||
EXPECT_EQ(handle_snapshot.type_name,
|
||||
base::UTF16ToUTF8(MinidumpStringAtRVAAsString(
|
||||
string_file.string(), handle_descriptor->TypeNameRva)));
|
||||
EXPECT_EQ(0u, handle_descriptor->ObjectNameRva);
|
||||
EXPECT_EQ(handle_snapshot.attributes, handle_descriptor->Attributes);
|
||||
EXPECT_EQ(handle_snapshot.granted_access, handle_descriptor->GrantedAccess);
|
||||
EXPECT_EQ(handle_snapshot.handle_count, handle_descriptor->HandleCount);
|
||||
EXPECT_EQ(handle_snapshot.pointer_count, handle_descriptor->PointerCount);
|
||||
EXPECT_EQ(handle_descriptor->Handle, handle_snapshot.handle);
|
||||
EXPECT_EQ(base::UTF16ToUTF8(MinidumpStringAtRVAAsString(
|
||||
string_file.string(), handle_descriptor->TypeNameRva)),
|
||||
handle_snapshot.type_name);
|
||||
EXPECT_EQ(handle_descriptor->ObjectNameRva, 0u);
|
||||
EXPECT_EQ(handle_descriptor->Attributes, handle_snapshot.attributes);
|
||||
EXPECT_EQ(handle_descriptor->GrantedAccess, handle_snapshot.granted_access);
|
||||
EXPECT_EQ(handle_descriptor->HandleCount, handle_snapshot.handle_count);
|
||||
EXPECT_EQ(handle_descriptor->PointerCount, handle_snapshot.pointer_count);
|
||||
}
|
||||
|
||||
TEST(MinidumpHandleDataWriter, RepeatedTypeName) {
|
||||
@ -157,45 +157,45 @@ TEST(MinidumpHandleDataWriter, RepeatedTypeName) {
|
||||
|
||||
const size_t kTypeNameStringDataLength =
|
||||
(handle_snapshot.type_name.size() + 1) * sizeof(base::char16);
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_HANDLE_DATA_STREAM) +
|
||||
(sizeof(MINIDUMP_HANDLE_DESCRIPTOR) * 2) +
|
||||
sizeof(MINIDUMP_STRING) + kTypeNameStringDataLength,
|
||||
string_file.string().size());
|
||||
sizeof(MINIDUMP_STRING) + kTypeNameStringDataLength);
|
||||
|
||||
const MINIDUMP_HANDLE_DATA_STREAM* handle_data_stream = nullptr;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetHandleDataStream(string_file.string(), &handle_data_stream));
|
||||
|
||||
EXPECT_EQ(2u, handle_data_stream->NumberOfDescriptors);
|
||||
EXPECT_EQ(handle_data_stream->NumberOfDescriptors, 2u);
|
||||
const MINIDUMP_HANDLE_DESCRIPTOR* handle_descriptor =
|
||||
reinterpret_cast<const MINIDUMP_HANDLE_DESCRIPTOR*>(
|
||||
&handle_data_stream[1]);
|
||||
EXPECT_EQ(handle_snapshot.handle, handle_descriptor->Handle);
|
||||
EXPECT_EQ(handle_snapshot.type_name,
|
||||
base::UTF16ToUTF8(MinidumpStringAtRVAAsString(
|
||||
string_file.string(), handle_descriptor->TypeNameRva)));
|
||||
EXPECT_EQ(0u, handle_descriptor->ObjectNameRva);
|
||||
EXPECT_EQ(handle_snapshot.attributes, handle_descriptor->Attributes);
|
||||
EXPECT_EQ(handle_snapshot.granted_access, handle_descriptor->GrantedAccess);
|
||||
EXPECT_EQ(handle_snapshot.handle_count, handle_descriptor->HandleCount);
|
||||
EXPECT_EQ(handle_snapshot.pointer_count, handle_descriptor->PointerCount);
|
||||
EXPECT_EQ(handle_descriptor->Handle, handle_snapshot.handle);
|
||||
EXPECT_EQ(base::UTF16ToUTF8(MinidumpStringAtRVAAsString(
|
||||
string_file.string(), handle_descriptor->TypeNameRva)),
|
||||
handle_snapshot.type_name);
|
||||
EXPECT_EQ(handle_descriptor->ObjectNameRva, 0u);
|
||||
EXPECT_EQ(handle_descriptor->Attributes, handle_snapshot.attributes);
|
||||
EXPECT_EQ(handle_descriptor->GrantedAccess, handle_snapshot.granted_access);
|
||||
EXPECT_EQ(handle_descriptor->HandleCount, handle_snapshot.handle_count);
|
||||
EXPECT_EQ(handle_descriptor->PointerCount, handle_snapshot.pointer_count);
|
||||
|
||||
const MINIDUMP_HANDLE_DESCRIPTOR* handle_descriptor2 =
|
||||
reinterpret_cast<const MINIDUMP_HANDLE_DESCRIPTOR*>(
|
||||
reinterpret_cast<const unsigned char*>(&handle_data_stream[1]) +
|
||||
sizeof(MINIDUMP_HANDLE_DESCRIPTOR));
|
||||
EXPECT_EQ(handle_snapshot2.handle, handle_descriptor2->Handle);
|
||||
EXPECT_EQ(handle_snapshot2.type_name,
|
||||
base::UTF16ToUTF8(MinidumpStringAtRVAAsString(
|
||||
string_file.string(), handle_descriptor2->TypeNameRva)));
|
||||
EXPECT_EQ(0u, handle_descriptor2->ObjectNameRva);
|
||||
EXPECT_EQ(handle_snapshot2.attributes, handle_descriptor2->Attributes);
|
||||
EXPECT_EQ(handle_snapshot2.granted_access, handle_descriptor2->GrantedAccess);
|
||||
EXPECT_EQ(handle_snapshot2.handle_count, handle_descriptor2->HandleCount);
|
||||
EXPECT_EQ(handle_snapshot2.pointer_count, handle_descriptor2->PointerCount);
|
||||
EXPECT_EQ(handle_descriptor2->Handle, handle_snapshot2.handle);
|
||||
EXPECT_EQ(base::UTF16ToUTF8(MinidumpStringAtRVAAsString(
|
||||
string_file.string(), handle_descriptor2->TypeNameRva)),
|
||||
handle_snapshot2.type_name);
|
||||
EXPECT_EQ(handle_descriptor2->ObjectNameRva, 0u);
|
||||
EXPECT_EQ(handle_descriptor2->Attributes, handle_snapshot2.attributes);
|
||||
EXPECT_EQ(handle_descriptor2->GrantedAccess, handle_snapshot2.granted_access);
|
||||
EXPECT_EQ(handle_descriptor2->HandleCount, handle_snapshot2.handle_count);
|
||||
EXPECT_EQ(handle_descriptor2->PointerCount, handle_snapshot2.pointer_count);
|
||||
|
||||
EXPECT_EQ(handle_descriptor->TypeNameRva, handle_descriptor2->TypeNameRva);
|
||||
EXPECT_EQ(handle_descriptor2->TypeNameRva, handle_descriptor->TypeNameRva);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -45,10 +45,10 @@ void GetMemoryInfoListStream(
|
||||
|
||||
const size_t kDirectoryIndex = 0;
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeMemoryInfoList,
|
||||
directory[kDirectoryIndex].StreamType);
|
||||
EXPECT_EQ(kMemoryInfoListStreamOffset,
|
||||
directory[kDirectoryIndex].Location.Rva);
|
||||
ASSERT_EQ(directory[kDirectoryIndex].StreamType,
|
||||
kMinidumpStreamTypeMemoryInfoList);
|
||||
EXPECT_EQ(directory[kDirectoryIndex].Location.Rva,
|
||||
kMemoryInfoListStreamOffset);
|
||||
|
||||
*memory_info_list =
|
||||
MinidumpWritableAtLocationDescriptor<MINIDUMP_MEMORY_INFO_LIST>(
|
||||
@ -66,15 +66,15 @@ TEST(MinidumpMemoryInfoWriter, Empty) {
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_MEMORY_INFO_LIST),
|
||||
string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_MEMORY_INFO_LIST));
|
||||
|
||||
const MINIDUMP_MEMORY_INFO_LIST* memory_info_list = nullptr;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetMemoryInfoListStream(string_file.string(), &memory_info_list));
|
||||
|
||||
EXPECT_EQ(0u, memory_info_list->NumberOfEntries);
|
||||
EXPECT_EQ(memory_info_list->NumberOfEntries, 0u);
|
||||
}
|
||||
|
||||
TEST(MinidumpMemoryInfoWriter, OneRegion) {
|
||||
@ -104,25 +104,25 @@ TEST(MinidumpMemoryInfoWriter, OneRegion) {
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_MEMORY_INFO_LIST) +
|
||||
sizeof(MINIDUMP_MEMORY_INFO),
|
||||
string_file.string().size());
|
||||
sizeof(MINIDUMP_MEMORY_INFO));
|
||||
|
||||
const MINIDUMP_MEMORY_INFO_LIST* memory_info_list = nullptr;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetMemoryInfoListStream(string_file.string(), &memory_info_list));
|
||||
|
||||
EXPECT_EQ(1u, memory_info_list->NumberOfEntries);
|
||||
EXPECT_EQ(memory_info_list->NumberOfEntries, 1u);
|
||||
const MINIDUMP_MEMORY_INFO* memory_info =
|
||||
reinterpret_cast<const MINIDUMP_MEMORY_INFO*>(&memory_info_list[1]);
|
||||
EXPECT_EQ(mmi.BaseAddress, memory_info->BaseAddress);
|
||||
EXPECT_EQ(mmi.AllocationBase, memory_info->AllocationBase);
|
||||
EXPECT_EQ(mmi.AllocationProtect, memory_info->AllocationProtect);
|
||||
EXPECT_EQ(mmi.RegionSize, memory_info->RegionSize);
|
||||
EXPECT_EQ(mmi.State, memory_info->State);
|
||||
EXPECT_EQ(mmi.Protect, memory_info->Protect);
|
||||
EXPECT_EQ(mmi.Type, memory_info->Type);
|
||||
EXPECT_EQ(memory_info->BaseAddress, mmi.BaseAddress);
|
||||
EXPECT_EQ(memory_info->AllocationBase, mmi.AllocationBase);
|
||||
EXPECT_EQ(memory_info->AllocationProtect, mmi.AllocationProtect);
|
||||
EXPECT_EQ(memory_info->RegionSize, mmi.RegionSize);
|
||||
EXPECT_EQ(memory_info->State, mmi.State);
|
||||
EXPECT_EQ(memory_info->Protect, mmi.Protect);
|
||||
EXPECT_EQ(memory_info->Type, mmi.Type);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -60,15 +60,15 @@ void GetMemoryListStream(const std::string& file_contents,
|
||||
|
||||
size_t directory_index = 0;
|
||||
if (expected_streams > 1) {
|
||||
ASSERT_EQ(kBogusStreamType, directory[directory_index].StreamType);
|
||||
ASSERT_EQ(0u, directory[directory_index].Location.DataSize);
|
||||
ASSERT_EQ(kMemoryListStreamOffset, directory[directory_index].Location.Rva);
|
||||
ASSERT_EQ(directory[directory_index].StreamType, kBogusStreamType);
|
||||
ASSERT_EQ(directory[directory_index].Location.DataSize, 0u);
|
||||
ASSERT_EQ(directory[directory_index].Location.Rva, kMemoryListStreamOffset);
|
||||
++directory_index;
|
||||
}
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeMemoryList,
|
||||
directory[directory_index].StreamType);
|
||||
EXPECT_EQ(kMemoryListStreamOffset, directory[directory_index].Location.Rva);
|
||||
ASSERT_EQ(directory[directory_index].StreamType,
|
||||
kMinidumpStreamTypeMemoryList);
|
||||
EXPECT_EQ(directory[directory_index].Location.Rva, kMemoryListStreamOffset);
|
||||
|
||||
*memory_list = MinidumpWritableAtLocationDescriptor<MINIDUMP_MEMORY_LIST>(
|
||||
file_contents, directory[directory_index].Location);
|
||||
@ -84,15 +84,15 @@ TEST(MinidumpMemoryWriter, EmptyMemoryList) {
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_MEMORY_LIST),
|
||||
string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_MEMORY_LIST));
|
||||
|
||||
const MINIDUMP_MEMORY_LIST* memory_list = nullptr;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetMemoryListStream(string_file.string(), &memory_list, 1));
|
||||
|
||||
EXPECT_EQ(0u, memory_list->NumberOfMemoryRanges);
|
||||
EXPECT_EQ(memory_list->NumberOfMemoryRanges, 0u);
|
||||
}
|
||||
|
||||
TEST(MinidumpMemoryWriter, OneMemoryRegion) {
|
||||
@ -157,7 +157,7 @@ TEST(MinidumpMemoryWriter, TwoMemoryRegions) {
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetMemoryListStream(string_file.string(), &memory_list, 1));
|
||||
|
||||
EXPECT_EQ(2u, memory_list->NumberOfMemoryRanges);
|
||||
EXPECT_EQ(memory_list->NumberOfMemoryRanges, 2u);
|
||||
|
||||
MINIDUMP_MEMORY_DESCRIPTOR expected;
|
||||
|
||||
@ -222,7 +222,7 @@ class TestMemoryStream final : public internal::MinidumpStreamWriter {
|
||||
}
|
||||
|
||||
bool WriteObject(FileWriterInterface* file_writer) override {
|
||||
EXPECT_EQ(kStateWritable, state());
|
||||
EXPECT_EQ(state(), kStateWritable);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -266,7 +266,7 @@ TEST(MinidumpMemoryWriter, ExtraMemory) {
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetMemoryListStream(string_file.string(), &memory_list, 2));
|
||||
|
||||
EXPECT_EQ(2u, memory_list->NumberOfMemoryRanges);
|
||||
EXPECT_EQ(memory_list->NumberOfMemoryRanges, 2u);
|
||||
|
||||
MINIDUMP_MEMORY_DESCRIPTOR expected;
|
||||
|
||||
@ -344,7 +344,7 @@ TEST(MinidumpMemoryWriter, AddFromSnapshot) {
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetMemoryListStream(string_file.string(), &memory_list, 1));
|
||||
|
||||
ASSERT_EQ(3u, memory_list->NumberOfMemoryRanges);
|
||||
ASSERT_EQ(memory_list->NumberOfMemoryRanges, 3u);
|
||||
|
||||
for (size_t index = 0; index < memory_list->NumberOfMemoryRanges; ++index) {
|
||||
SCOPED_TRACE(base::StringPrintf("index %" PRIuS, index));
|
||||
|
@ -49,7 +49,7 @@ void GetMiscInfoStream(const std::string& file_contents, const T** misc_info) {
|
||||
const size_t kMiscInfoStreamSize = sizeof(T);
|
||||
const size_t kFileSize = kMiscInfoStreamOffset + kMiscInfoStreamSize;
|
||||
|
||||
ASSERT_EQ(kFileSize, file_contents.size());
|
||||
ASSERT_EQ(file_contents.size(), kFileSize);
|
||||
|
||||
const MINIDUMP_DIRECTORY* directory;
|
||||
const MINIDUMP_HEADER* header =
|
||||
@ -57,8 +57,8 @@ void GetMiscInfoStream(const std::string& file_contents, const T** misc_info) {
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeMiscInfo, directory[0].StreamType);
|
||||
EXPECT_EQ(kMiscInfoStreamOffset, directory[0].Location.Rva);
|
||||
ASSERT_EQ(directory[0].StreamType, kMinidumpStreamTypeMiscInfo);
|
||||
EXPECT_EQ(directory[0].Location.Rva, kMiscInfoStreamOffset);
|
||||
|
||||
*misc_info = MinidumpWritableAtLocationDescriptor<T>(file_contents,
|
||||
directory[0].Location);
|
||||
@ -70,19 +70,19 @@ void ExpectNULPaddedString16Equal(const base::char16* expected,
|
||||
size_t size) {
|
||||
base::string16 expected_string(expected, size);
|
||||
base::string16 observed_string(observed, size);
|
||||
EXPECT_EQ(expected_string, observed_string);
|
||||
EXPECT_EQ(observed_string, expected_string);
|
||||
}
|
||||
|
||||
void ExpectSystemTimeEqual(const SYSTEMTIME* expected,
|
||||
const SYSTEMTIME* observed) {
|
||||
EXPECT_EQ(expected->wYear, observed->wYear);
|
||||
EXPECT_EQ(expected->wMonth, observed->wMonth);
|
||||
EXPECT_EQ(expected->wDayOfWeek, observed->wDayOfWeek);
|
||||
EXPECT_EQ(expected->wDay, observed->wDay);
|
||||
EXPECT_EQ(expected->wHour, observed->wHour);
|
||||
EXPECT_EQ(expected->wMinute, observed->wMinute);
|
||||
EXPECT_EQ(expected->wSecond, observed->wSecond);
|
||||
EXPECT_EQ(expected->wMilliseconds, observed->wMilliseconds);
|
||||
EXPECT_EQ(observed->wYear, expected->wYear);
|
||||
EXPECT_EQ(observed->wMonth, expected->wMonth);
|
||||
EXPECT_EQ(observed->wDayOfWeek, expected->wDayOfWeek);
|
||||
EXPECT_EQ(observed->wDay, expected->wDay);
|
||||
EXPECT_EQ(observed->wHour, expected->wHour);
|
||||
EXPECT_EQ(observed->wMinute, expected->wMinute);
|
||||
EXPECT_EQ(observed->wSecond, expected->wSecond);
|
||||
EXPECT_EQ(observed->wMilliseconds, expected->wMilliseconds);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -92,11 +92,11 @@ template <>
|
||||
void ExpectMiscInfoEqual<MINIDUMP_MISC_INFO>(
|
||||
const MINIDUMP_MISC_INFO* expected,
|
||||
const MINIDUMP_MISC_INFO* observed) {
|
||||
EXPECT_EQ(expected->Flags1, observed->Flags1);
|
||||
EXPECT_EQ(expected->ProcessId, observed->ProcessId);
|
||||
EXPECT_EQ(expected->ProcessCreateTime, observed->ProcessCreateTime);
|
||||
EXPECT_EQ(expected->ProcessUserTime, observed->ProcessUserTime);
|
||||
EXPECT_EQ(expected->ProcessKernelTime, observed->ProcessKernelTime);
|
||||
EXPECT_EQ(observed->Flags1, expected->Flags1);
|
||||
EXPECT_EQ(observed->ProcessId, expected->ProcessId);
|
||||
EXPECT_EQ(observed->ProcessCreateTime, expected->ProcessCreateTime);
|
||||
EXPECT_EQ(observed->ProcessUserTime, expected->ProcessUserTime);
|
||||
EXPECT_EQ(observed->ProcessKernelTime, expected->ProcessKernelTime);
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -106,12 +106,12 @@ void ExpectMiscInfoEqual<MINIDUMP_MISC_INFO_2>(
|
||||
ExpectMiscInfoEqual<MINIDUMP_MISC_INFO>(
|
||||
reinterpret_cast<const MINIDUMP_MISC_INFO*>(expected),
|
||||
reinterpret_cast<const MINIDUMP_MISC_INFO*>(observed));
|
||||
EXPECT_EQ(expected->ProcessorMaxMhz, observed->ProcessorMaxMhz);
|
||||
EXPECT_EQ(expected->ProcessorCurrentMhz, observed->ProcessorCurrentMhz);
|
||||
EXPECT_EQ(expected->ProcessorMhzLimit, observed->ProcessorMhzLimit);
|
||||
EXPECT_EQ(expected->ProcessorMaxIdleState, observed->ProcessorMaxIdleState);
|
||||
EXPECT_EQ(expected->ProcessorCurrentIdleState,
|
||||
observed->ProcessorCurrentIdleState);
|
||||
EXPECT_EQ(observed->ProcessorMaxMhz, expected->ProcessorMaxMhz);
|
||||
EXPECT_EQ(observed->ProcessorCurrentMhz, expected->ProcessorCurrentMhz);
|
||||
EXPECT_EQ(observed->ProcessorMhzLimit, expected->ProcessorMhzLimit);
|
||||
EXPECT_EQ(observed->ProcessorMaxIdleState, expected->ProcessorMaxIdleState);
|
||||
EXPECT_EQ(observed->ProcessorCurrentIdleState,
|
||||
expected->ProcessorCurrentIdleState);
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -121,11 +121,11 @@ void ExpectMiscInfoEqual<MINIDUMP_MISC_INFO_3>(
|
||||
ExpectMiscInfoEqual<MINIDUMP_MISC_INFO_2>(
|
||||
reinterpret_cast<const MINIDUMP_MISC_INFO_2*>(expected),
|
||||
reinterpret_cast<const MINIDUMP_MISC_INFO_2*>(observed));
|
||||
EXPECT_EQ(expected->ProcessIntegrityLevel, observed->ProcessIntegrityLevel);
|
||||
EXPECT_EQ(expected->ProcessExecuteFlags, observed->ProcessExecuteFlags);
|
||||
EXPECT_EQ(expected->ProtectedProcess, observed->ProtectedProcess);
|
||||
EXPECT_EQ(expected->TimeZoneId, observed->TimeZoneId);
|
||||
EXPECT_EQ(expected->TimeZone.Bias, observed->TimeZone.Bias);
|
||||
EXPECT_EQ(observed->ProcessIntegrityLevel, expected->ProcessIntegrityLevel);
|
||||
EXPECT_EQ(observed->ProcessExecuteFlags, expected->ProcessExecuteFlags);
|
||||
EXPECT_EQ(observed->ProtectedProcess, expected->ProtectedProcess);
|
||||
EXPECT_EQ(observed->TimeZoneId, expected->TimeZoneId);
|
||||
EXPECT_EQ(observed->TimeZone.Bias, expected->TimeZone.Bias);
|
||||
{
|
||||
SCOPED_TRACE("Standard");
|
||||
ExpectNULPaddedString16Equal(expected->TimeZone.StandardName,
|
||||
@ -133,7 +133,7 @@ void ExpectMiscInfoEqual<MINIDUMP_MISC_INFO_3>(
|
||||
arraysize(expected->TimeZone.StandardName));
|
||||
ExpectSystemTimeEqual(&expected->TimeZone.StandardDate,
|
||||
&observed->TimeZone.StandardDate);
|
||||
EXPECT_EQ(expected->TimeZone.StandardBias, observed->TimeZone.StandardBias);
|
||||
EXPECT_EQ(observed->TimeZone.StandardBias, expected->TimeZone.StandardBias);
|
||||
}
|
||||
{
|
||||
SCOPED_TRACE("Daylight");
|
||||
@ -142,7 +142,7 @@ void ExpectMiscInfoEqual<MINIDUMP_MISC_INFO_3>(
|
||||
arraysize(expected->TimeZone.DaylightName));
|
||||
ExpectSystemTimeEqual(&expected->TimeZone.DaylightDate,
|
||||
&observed->TimeZone.DaylightDate);
|
||||
EXPECT_EQ(expected->TimeZone.DaylightBias, observed->TimeZone.DaylightBias);
|
||||
EXPECT_EQ(observed->TimeZone.DaylightBias, expected->TimeZone.DaylightBias);
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,20 +174,20 @@ void ExpectMiscInfoEqual<MINIDUMP_MISC_INFO_5>(
|
||||
ExpectMiscInfoEqual<MINIDUMP_MISC_INFO_4>(
|
||||
reinterpret_cast<const MINIDUMP_MISC_INFO_4*>(expected),
|
||||
reinterpret_cast<const MINIDUMP_MISC_INFO_4*>(observed));
|
||||
EXPECT_EQ(expected->XStateData.SizeOfInfo, observed->XStateData.SizeOfInfo);
|
||||
EXPECT_EQ(expected->XStateData.ContextSize, observed->XStateData.ContextSize);
|
||||
EXPECT_EQ(expected->XStateData.EnabledFeatures,
|
||||
observed->XStateData.EnabledFeatures);
|
||||
EXPECT_EQ(observed->XStateData.SizeOfInfo, expected->XStateData.SizeOfInfo);
|
||||
EXPECT_EQ(observed->XStateData.ContextSize, expected->XStateData.ContextSize);
|
||||
EXPECT_EQ(observed->XStateData.EnabledFeatures,
|
||||
expected->XStateData.EnabledFeatures);
|
||||
for (size_t feature_index = 0;
|
||||
feature_index < arraysize(observed->XStateData.Features);
|
||||
++feature_index) {
|
||||
SCOPED_TRACE(base::StringPrintf("feature_index %" PRIuS, feature_index));
|
||||
EXPECT_EQ(expected->XStateData.Features[feature_index].Offset,
|
||||
observed->XStateData.Features[feature_index].Offset);
|
||||
EXPECT_EQ(expected->XStateData.Features[feature_index].Size,
|
||||
observed->XStateData.Features[feature_index].Size);
|
||||
EXPECT_EQ(observed->XStateData.Features[feature_index].Offset,
|
||||
expected->XStateData.Features[feature_index].Offset);
|
||||
EXPECT_EQ(observed->XStateData.Features[feature_index].Size,
|
||||
expected->XStateData.Features[feature_index].Size);
|
||||
}
|
||||
EXPECT_EQ(expected->ProcessCookie, observed->ProcessCookie);
|
||||
EXPECT_EQ(observed->ProcessCookie, expected->ProcessCookie);
|
||||
}
|
||||
|
||||
TEST(MinidumpMiscInfoWriter, Empty) {
|
||||
|
@ -50,7 +50,7 @@ const MinidumpModuleCrashpadInfoList* MinidumpModuleCrashpadInfoListAtStart(
|
||||
}
|
||||
|
||||
if (list->count != count) {
|
||||
EXPECT_EQ(count, list->count);
|
||||
EXPECT_EQ(list->count, count);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -65,8 +65,8 @@ TEST(MinidumpModuleCrashpadInfoWriter, EmptyList) {
|
||||
EXPECT_FALSE(module_list_writer->IsUseful());
|
||||
|
||||
EXPECT_TRUE(module_list_writer->WriteEverything(&string_file));
|
||||
ASSERT_EQ(sizeof(MinidumpModuleCrashpadInfoList),
|
||||
string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MinidumpModuleCrashpadInfoList));
|
||||
|
||||
const MinidumpModuleCrashpadInfoList* module_list =
|
||||
MinidumpModuleCrashpadInfoListAtStart(string_file.string(), 0);
|
||||
@ -85,26 +85,26 @@ TEST(MinidumpModuleCrashpadInfoWriter, EmptyModule) {
|
||||
EXPECT_TRUE(module_list_writer->IsUseful());
|
||||
|
||||
EXPECT_TRUE(module_list_writer->WriteEverything(&string_file));
|
||||
ASSERT_EQ(sizeof(MinidumpModuleCrashpadInfoList) +
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MinidumpModuleCrashpadInfoList) +
|
||||
sizeof(MinidumpModuleCrashpadInfoLink) +
|
||||
sizeof(MinidumpModuleCrashpadInfo),
|
||||
string_file.string().size());
|
||||
sizeof(MinidumpModuleCrashpadInfo));
|
||||
|
||||
const MinidumpModuleCrashpadInfoList* module_list =
|
||||
MinidumpModuleCrashpadInfoListAtStart(string_file.string(), 1);
|
||||
ASSERT_TRUE(module_list);
|
||||
|
||||
EXPECT_EQ(0u, module_list->modules[0].minidump_module_list_index);
|
||||
EXPECT_EQ(module_list->modules[0].minidump_module_list_index, 0u);
|
||||
const MinidumpModuleCrashpadInfo* module =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||
string_file.string(), module_list->modules[0].location);
|
||||
ASSERT_TRUE(module);
|
||||
|
||||
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module->version);
|
||||
EXPECT_EQ(0u, module->list_annotations.DataSize);
|
||||
EXPECT_EQ(0u, module->list_annotations.Rva);
|
||||
EXPECT_EQ(0u, module->simple_annotations.DataSize);
|
||||
EXPECT_EQ(0u, module->simple_annotations.Rva);
|
||||
EXPECT_EQ(module->version, MinidumpModuleCrashpadInfo::kVersion);
|
||||
EXPECT_EQ(module->list_annotations.DataSize, 0u);
|
||||
EXPECT_EQ(module->list_annotations.Rva, 0u);
|
||||
EXPECT_EQ(module->simple_annotations.DataSize, 0u);
|
||||
EXPECT_EQ(module->simple_annotations.Rva, 0u);
|
||||
}
|
||||
|
||||
TEST(MinidumpModuleCrashpadInfoWriter, FullModule) {
|
||||
@ -140,7 +140,8 @@ TEST(MinidumpModuleCrashpadInfoWriter, FullModule) {
|
||||
EXPECT_TRUE(module_list_writer->IsUseful());
|
||||
|
||||
EXPECT_TRUE(module_list_writer->WriteEverything(&string_file));
|
||||
ASSERT_EQ(sizeof(MinidumpModuleCrashpadInfoList) +
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MinidumpModuleCrashpadInfoList) +
|
||||
sizeof(MinidumpModuleCrashpadInfoLink) +
|
||||
sizeof(MinidumpModuleCrashpadInfo) +
|
||||
sizeof(MinidumpRVAList) +
|
||||
@ -149,48 +150,47 @@ TEST(MinidumpModuleCrashpadInfoWriter, FullModule) {
|
||||
sizeof(MinidumpSimpleStringDictionaryEntry) +
|
||||
sizeof(MinidumpUTF8String) + arraysize(kEntry) + 2 + // padding
|
||||
sizeof(MinidumpUTF8String) + arraysize(kKey) +
|
||||
sizeof(MinidumpUTF8String) + arraysize(kValue),
|
||||
string_file.string().size());
|
||||
sizeof(MinidumpUTF8String) + arraysize(kValue));
|
||||
|
||||
const MinidumpModuleCrashpadInfoList* module_list =
|
||||
MinidumpModuleCrashpadInfoListAtStart(string_file.string(), 1);
|
||||
ASSERT_TRUE(module_list);
|
||||
|
||||
EXPECT_EQ(kMinidumpModuleListIndex,
|
||||
module_list->modules[0].minidump_module_list_index);
|
||||
EXPECT_EQ(module_list->modules[0].minidump_module_list_index,
|
||||
kMinidumpModuleListIndex);
|
||||
const MinidumpModuleCrashpadInfo* module =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||
string_file.string(), module_list->modules[0].location);
|
||||
ASSERT_TRUE(module);
|
||||
|
||||
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module->version);
|
||||
EXPECT_NE(0u, module->list_annotations.DataSize);
|
||||
EXPECT_NE(0u, module->list_annotations.Rva);
|
||||
EXPECT_NE(0u, module->simple_annotations.DataSize);
|
||||
EXPECT_NE(0u, module->simple_annotations.Rva);
|
||||
EXPECT_EQ(module->version, MinidumpModuleCrashpadInfo::kVersion);
|
||||
EXPECT_NE(module->list_annotations.DataSize, 0u);
|
||||
EXPECT_NE(module->list_annotations.Rva, 0u);
|
||||
EXPECT_NE(module->simple_annotations.DataSize, 0u);
|
||||
EXPECT_NE(module->simple_annotations.Rva, 0u);
|
||||
|
||||
const MinidumpRVAList* list_annotations =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpRVAList>(
|
||||
string_file.string(), module->list_annotations);
|
||||
ASSERT_TRUE(list_annotations);
|
||||
|
||||
ASSERT_EQ(1u, list_annotations->count);
|
||||
EXPECT_EQ(kEntry,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
list_annotations->children[0]));
|
||||
ASSERT_EQ(list_annotations->count, 1u);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
list_annotations->children[0]),
|
||||
kEntry);
|
||||
|
||||
const MinidumpSimpleStringDictionary* simple_annotations =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
||||
string_file.string(), module->simple_annotations);
|
||||
ASSERT_TRUE(simple_annotations);
|
||||
|
||||
ASSERT_EQ(1u, simple_annotations->count);
|
||||
EXPECT_EQ(kKey,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations->entries[0].key));
|
||||
EXPECT_EQ(kValue,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations->entries[0].value));
|
||||
ASSERT_EQ(simple_annotations->count, 1u);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
simple_annotations->entries[0].key),
|
||||
kKey);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations->entries[0].value),
|
||||
kValue);
|
||||
}
|
||||
|
||||
TEST(MinidumpModuleCrashpadInfoWriter, ThreeModules) {
|
||||
@ -258,14 +258,14 @@ TEST(MinidumpModuleCrashpadInfoWriter, ThreeModules) {
|
||||
MinidumpModuleCrashpadInfoListAtStart(string_file.string(), 3);
|
||||
ASSERT_TRUE(module_list);
|
||||
|
||||
EXPECT_EQ(kMinidumpModuleListIndex0,
|
||||
module_list->modules[0].minidump_module_list_index);
|
||||
EXPECT_EQ(module_list->modules[0].minidump_module_list_index,
|
||||
kMinidumpModuleListIndex0);
|
||||
const MinidumpModuleCrashpadInfo* module_0 =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||
string_file.string(), module_list->modules[0].location);
|
||||
ASSERT_TRUE(module_0);
|
||||
|
||||
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module_0->version);
|
||||
EXPECT_EQ(module_0->version, MinidumpModuleCrashpadInfo::kVersion);
|
||||
|
||||
const MinidumpRVAList* list_annotations_0 =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpRVAList>(
|
||||
@ -277,22 +277,22 @@ TEST(MinidumpModuleCrashpadInfoWriter, ThreeModules) {
|
||||
string_file.string(), module_0->simple_annotations);
|
||||
ASSERT_TRUE(simple_annotations_0);
|
||||
|
||||
ASSERT_EQ(1u, simple_annotations_0->count);
|
||||
EXPECT_EQ(kKey0,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_0->entries[0].key));
|
||||
EXPECT_EQ(kValue0,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_0->entries[0].value));
|
||||
ASSERT_EQ(simple_annotations_0->count, 1u);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_0->entries[0].key),
|
||||
kKey0);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_0->entries[0].value),
|
||||
kValue0);
|
||||
|
||||
EXPECT_EQ(kMinidumpModuleListIndex1,
|
||||
module_list->modules[1].minidump_module_list_index);
|
||||
EXPECT_EQ(module_list->modules[1].minidump_module_list_index,
|
||||
kMinidumpModuleListIndex1);
|
||||
const MinidumpModuleCrashpadInfo* module_1 =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||
string_file.string(), module_list->modules[1].location);
|
||||
ASSERT_TRUE(module_1);
|
||||
|
||||
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module_1->version);
|
||||
EXPECT_EQ(module_1->version, MinidumpModuleCrashpadInfo::kVersion);
|
||||
|
||||
const MinidumpRVAList* list_annotations_1 =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpRVAList>(
|
||||
@ -304,14 +304,14 @@ TEST(MinidumpModuleCrashpadInfoWriter, ThreeModules) {
|
||||
string_file.string(), module_1->simple_annotations);
|
||||
EXPECT_FALSE(simple_annotations_1);
|
||||
|
||||
EXPECT_EQ(kMinidumpModuleListIndex2,
|
||||
module_list->modules[2].minidump_module_list_index);
|
||||
EXPECT_EQ(module_list->modules[2].minidump_module_list_index,
|
||||
kMinidumpModuleListIndex2);
|
||||
const MinidumpModuleCrashpadInfo* module_2 =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||
string_file.string(), module_list->modules[2].location);
|
||||
ASSERT_TRUE(module_2);
|
||||
|
||||
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module_2->version);
|
||||
EXPECT_EQ(module_2->version, MinidumpModuleCrashpadInfo::kVersion);
|
||||
|
||||
const MinidumpRVAList* list_annotations_2 =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpRVAList>(
|
||||
@ -323,19 +323,19 @@ TEST(MinidumpModuleCrashpadInfoWriter, ThreeModules) {
|
||||
string_file.string(), module_2->simple_annotations);
|
||||
ASSERT_TRUE(simple_annotations_2);
|
||||
|
||||
ASSERT_EQ(2u, simple_annotations_2->count);
|
||||
EXPECT_EQ(kKey2A,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_2->entries[0].key));
|
||||
EXPECT_EQ(kValue2A,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_2->entries[0].value));
|
||||
EXPECT_EQ(kKey2B,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_2->entries[1].key));
|
||||
EXPECT_EQ(kValue2B,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_2->entries[1].value));
|
||||
ASSERT_EQ(simple_annotations_2->count, 2u);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_2->entries[0].key),
|
||||
kKey2A);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_2->entries[0].value),
|
||||
kValue2A);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_2->entries[1].key),
|
||||
kKey2B);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_2->entries[1].value),
|
||||
kValue2B);
|
||||
}
|
||||
|
||||
TEST(MinidumpModuleCrashpadInfoWriter, InitializeFromSnapshot) {
|
||||
@ -387,13 +387,13 @@ TEST(MinidumpModuleCrashpadInfoWriter, InitializeFromSnapshot) {
|
||||
MinidumpModuleCrashpadInfoListAtStart(string_file.string(), 3);
|
||||
ASSERT_TRUE(module_list);
|
||||
|
||||
EXPECT_EQ(0u, module_list->modules[0].minidump_module_list_index);
|
||||
EXPECT_EQ(module_list->modules[0].minidump_module_list_index, 0u);
|
||||
const MinidumpModuleCrashpadInfo* module_0 =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||
string_file.string(), module_list->modules[0].location);
|
||||
ASSERT_TRUE(module_0);
|
||||
|
||||
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module_0->version);
|
||||
EXPECT_EQ(module_0->version, MinidumpModuleCrashpadInfo::kVersion);
|
||||
|
||||
const MinidumpRVAList* list_annotations_0 =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpRVAList>(
|
||||
@ -405,27 +405,27 @@ TEST(MinidumpModuleCrashpadInfoWriter, InitializeFromSnapshot) {
|
||||
string_file.string(), module_0->simple_annotations);
|
||||
ASSERT_TRUE(simple_annotations_0);
|
||||
|
||||
ASSERT_EQ(annotations_simple_map_0.size(), simple_annotations_0->count);
|
||||
EXPECT_EQ(kKey0B,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_0->entries[0].key));
|
||||
EXPECT_EQ(kValue0B,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_0->entries[0].value));
|
||||
EXPECT_EQ(kKey0A,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_0->entries[1].key));
|
||||
EXPECT_EQ(kValue0A,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_0->entries[1].value));
|
||||
ASSERT_EQ(simple_annotations_0->count, annotations_simple_map_0.size());
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_0->entries[0].key),
|
||||
kKey0B);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_0->entries[0].value),
|
||||
kValue0B);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_0->entries[1].key),
|
||||
kKey0A);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_0->entries[1].value),
|
||||
kValue0A);
|
||||
|
||||
EXPECT_EQ(2u, module_list->modules[1].minidump_module_list_index);
|
||||
EXPECT_EQ(module_list->modules[1].minidump_module_list_index, 2u);
|
||||
const MinidumpModuleCrashpadInfo* module_2 =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||
string_file.string(), module_list->modules[1].location);
|
||||
ASSERT_TRUE(module_2);
|
||||
|
||||
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module_2->version);
|
||||
EXPECT_EQ(module_2->version, MinidumpModuleCrashpadInfo::kVersion);
|
||||
|
||||
const MinidumpRVAList* list_annotations_2 =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpRVAList>(
|
||||
@ -437,34 +437,34 @@ TEST(MinidumpModuleCrashpadInfoWriter, InitializeFromSnapshot) {
|
||||
string_file.string(), module_2->simple_annotations);
|
||||
ASSERT_TRUE(simple_annotations_2);
|
||||
|
||||
ASSERT_EQ(annotations_simple_map_2.size(), simple_annotations_2->count);
|
||||
EXPECT_EQ(kKey2,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_2->entries[0].key));
|
||||
EXPECT_EQ(kValue2,
|
||||
MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_2->entries[0].value));
|
||||
ASSERT_EQ(simple_annotations_2->count, annotations_simple_map_2.size());
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_2->entries[0].key),
|
||||
kKey2);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(
|
||||
string_file.string(), simple_annotations_2->entries[0].value),
|
||||
kValue2);
|
||||
|
||||
EXPECT_EQ(3u, module_list->modules[2].minidump_module_list_index);
|
||||
EXPECT_EQ(module_list->modules[2].minidump_module_list_index, 3u);
|
||||
const MinidumpModuleCrashpadInfo* module_3 =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||
string_file.string(), module_list->modules[2].location);
|
||||
ASSERT_TRUE(module_3);
|
||||
|
||||
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module_3->version);
|
||||
EXPECT_EQ(module_3->version, MinidumpModuleCrashpadInfo::kVersion);
|
||||
|
||||
const MinidumpRVAList* list_annotations_3 =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpRVAList>(
|
||||
string_file.string(), module_3->list_annotations);
|
||||
ASSERT_TRUE(list_annotations_3);
|
||||
|
||||
ASSERT_EQ(annotations_vector_3.size(), list_annotations_3->count);
|
||||
EXPECT_EQ(kEntry3A,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
list_annotations_3->children[0]));
|
||||
EXPECT_EQ(kEntry3B,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
list_annotations_3->children[1]));
|
||||
ASSERT_EQ(list_annotations_3->count, annotations_vector_3.size());
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
list_annotations_3->children[0]),
|
||||
kEntry3A);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
list_annotations_3->children[1]),
|
||||
kEntry3B);
|
||||
|
||||
const MinidumpSimpleStringDictionary* simple_annotations_3 =
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
||||
|
@ -56,8 +56,8 @@ void GetModuleListStream(const std::string& file_contents,
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeModuleList, directory[0].StreamType);
|
||||
EXPECT_EQ(kModuleListStreamOffset, directory[0].Location.Rva);
|
||||
ASSERT_EQ(directory[0].StreamType, kMinidumpStreamTypeModuleList);
|
||||
EXPECT_EQ(directory[0].Location.Rva, kModuleListStreamOffset);
|
||||
|
||||
*module_list = MinidumpWritableAtLocationDescriptor<MINIDUMP_MODULE_LIST>(
|
||||
file_contents, directory[0].Location);
|
||||
@ -73,15 +73,15 @@ TEST(MinidumpModuleWriter, EmptyModuleList) {
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_MODULE_LIST),
|
||||
string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_MODULE_LIST));
|
||||
|
||||
const MINIDUMP_MODULE_LIST* module_list = nullptr;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetModuleListStream(string_file.string(), &module_list));
|
||||
|
||||
EXPECT_EQ(0u, module_list->NumberOfModules);
|
||||
EXPECT_EQ(module_list->NumberOfModules, 0u);
|
||||
}
|
||||
|
||||
// If |expected_pdb_name| is not nullptr, |codeview_record| is used to locate a
|
||||
@ -96,7 +96,7 @@ void ExpectCodeViewRecord(const MINIDUMP_LOCATION_DESCRIPTOR* codeview_record,
|
||||
time_t expected_pdb_timestamp,
|
||||
uint32_t expected_pdb_age) {
|
||||
if (expected_pdb_name) {
|
||||
EXPECT_NE(0u, codeview_record->Rva);
|
||||
EXPECT_NE(codeview_record->Rva, 0u);
|
||||
|
||||
std::string observed_pdb_name;
|
||||
if (expected_pdb_uuid) {
|
||||
@ -105,11 +105,11 @@ void ExpectCodeViewRecord(const MINIDUMP_LOCATION_DESCRIPTOR* codeview_record,
|
||||
MinidumpWritableAtLocationDescriptor<CodeViewRecordPDB70>(
|
||||
file_contents, *codeview_record);
|
||||
ASSERT_TRUE(codeview_pdb70_record);
|
||||
EXPECT_EQ(0,
|
||||
memcmp(expected_pdb_uuid,
|
||||
EXPECT_EQ(memcmp(expected_pdb_uuid,
|
||||
&codeview_pdb70_record->uuid,
|
||||
sizeof(codeview_pdb70_record->uuid)));
|
||||
EXPECT_EQ(expected_pdb_age, codeview_pdb70_record->age);
|
||||
sizeof(codeview_pdb70_record->uuid)),
|
||||
0);
|
||||
EXPECT_EQ(codeview_pdb70_record->age, expected_pdb_age);
|
||||
|
||||
observed_pdb_name.assign(
|
||||
reinterpret_cast<const char*>(&codeview_pdb70_record->pdb_name[0]),
|
||||
@ -120,9 +120,9 @@ void ExpectCodeViewRecord(const MINIDUMP_LOCATION_DESCRIPTOR* codeview_record,
|
||||
MinidumpWritableAtLocationDescriptor<CodeViewRecordPDB20>(
|
||||
file_contents, *codeview_record);
|
||||
ASSERT_TRUE(codeview_pdb20_record);
|
||||
EXPECT_EQ(static_cast<uint32_t>(expected_pdb_timestamp),
|
||||
codeview_pdb20_record->timestamp);
|
||||
EXPECT_EQ(expected_pdb_age, codeview_pdb20_record->age);
|
||||
EXPECT_EQ(codeview_pdb20_record->timestamp,
|
||||
static_cast<uint32_t>(expected_pdb_timestamp));
|
||||
EXPECT_EQ(codeview_pdb20_record->age, expected_pdb_age);
|
||||
|
||||
observed_pdb_name.assign(
|
||||
reinterpret_cast<const char*>(&codeview_pdb20_record->pdb_name[0]),
|
||||
@ -130,14 +130,14 @@ void ExpectCodeViewRecord(const MINIDUMP_LOCATION_DESCRIPTOR* codeview_record,
|
||||
}
|
||||
|
||||
// Check for, and then remove, the NUL terminator.
|
||||
EXPECT_EQ('\0', observed_pdb_name[observed_pdb_name.size() - 1]);
|
||||
EXPECT_EQ(observed_pdb_name[observed_pdb_name.size() - 1], '\0');
|
||||
observed_pdb_name.resize(observed_pdb_name.size() - 1);
|
||||
|
||||
EXPECT_EQ(expected_pdb_name, observed_pdb_name);
|
||||
EXPECT_EQ(observed_pdb_name, expected_pdb_name);
|
||||
} else {
|
||||
// There should be no CodeView record.
|
||||
EXPECT_EQ(0u, codeview_record->DataSize);
|
||||
EXPECT_EQ(0u, codeview_record->Rva);
|
||||
EXPECT_EQ(codeview_record->DataSize, 0u);
|
||||
EXPECT_EQ(codeview_record->Rva, 0u);
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,21 +152,21 @@ void ExpectMiscellaneousDebugRecord(
|
||||
uint32_t expected_debug_type,
|
||||
bool expected_debug_utf16) {
|
||||
if (expected_debug_name) {
|
||||
EXPECT_NE(0u, misc_record->Rva);
|
||||
EXPECT_NE(misc_record->Rva, 0u);
|
||||
const IMAGE_DEBUG_MISC* misc_debug_record =
|
||||
MinidumpWritableAtLocationDescriptor<IMAGE_DEBUG_MISC>(file_contents,
|
||||
*misc_record);
|
||||
ASSERT_TRUE(misc_debug_record);
|
||||
EXPECT_EQ(expected_debug_type, misc_debug_record->DataType);
|
||||
EXPECT_EQ(expected_debug_utf16, misc_debug_record->Unicode != 0);
|
||||
EXPECT_EQ(0u, misc_debug_record->Reserved[0]);
|
||||
EXPECT_EQ(0u, misc_debug_record->Reserved[1]);
|
||||
EXPECT_EQ(0u, misc_debug_record->Reserved[2]);
|
||||
EXPECT_EQ(misc_debug_record->DataType, expected_debug_type);
|
||||
EXPECT_EQ(misc_debug_record->Unicode != 0, expected_debug_utf16);
|
||||
EXPECT_EQ(misc_debug_record->Reserved[0], 0u);
|
||||
EXPECT_EQ(misc_debug_record->Reserved[1], 0u);
|
||||
EXPECT_EQ(misc_debug_record->Reserved[2], 0u);
|
||||
|
||||
// Check for the NUL terminator.
|
||||
size_t bytes_available =
|
||||
misc_debug_record->Length - offsetof(IMAGE_DEBUG_MISC, Data);
|
||||
EXPECT_EQ('\0', misc_debug_record->Data[bytes_available - 1]);
|
||||
EXPECT_EQ(misc_debug_record->Data[bytes_available - 1], '\0');
|
||||
std::string observed_data(
|
||||
reinterpret_cast<const char*>(misc_debug_record->Data));
|
||||
|
||||
@ -184,14 +184,14 @@ void ExpectMiscellaneousDebugRecord(
|
||||
|
||||
// Make sure that any padding bytes after the first NUL are also NUL.
|
||||
for (size_t index = bytes_used; index < bytes_available; ++index) {
|
||||
EXPECT_EQ('\0', misc_debug_record->Data[index]);
|
||||
EXPECT_EQ(misc_debug_record->Data[index], '\0');
|
||||
}
|
||||
|
||||
EXPECT_EQ(expected_debug_name, observed_data);
|
||||
EXPECT_EQ(observed_data, expected_debug_name);
|
||||
} else {
|
||||
// There should be no miscellaneous debugging record.
|
||||
EXPECT_EQ(0u, misc_record->DataSize);
|
||||
EXPECT_EQ(0u, misc_record->Rva);
|
||||
EXPECT_EQ(misc_record->DataSize, 0u);
|
||||
EXPECT_EQ(misc_record->Rva, 0u);
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,43 +215,43 @@ void ExpectModule(const MINIDUMP_MODULE* expected,
|
||||
const char* expected_debug_name,
|
||||
uint32_t expected_debug_type,
|
||||
bool expected_debug_utf16) {
|
||||
EXPECT_EQ(expected->BaseOfImage, observed->BaseOfImage);
|
||||
EXPECT_EQ(expected->SizeOfImage, observed->SizeOfImage);
|
||||
EXPECT_EQ(expected->CheckSum, observed->CheckSum);
|
||||
EXPECT_EQ(expected->TimeDateStamp, observed->TimeDateStamp);
|
||||
EXPECT_EQ(implicit_cast<uint32_t>(VS_FFI_SIGNATURE),
|
||||
observed->VersionInfo.dwSignature);
|
||||
EXPECT_EQ(implicit_cast<uint32_t>(VS_FFI_STRUCVERSION),
|
||||
observed->VersionInfo.dwStrucVersion);
|
||||
EXPECT_EQ(expected->VersionInfo.dwFileVersionMS,
|
||||
observed->VersionInfo.dwFileVersionMS);
|
||||
EXPECT_EQ(expected->VersionInfo.dwFileVersionLS,
|
||||
observed->VersionInfo.dwFileVersionLS);
|
||||
EXPECT_EQ(expected->VersionInfo.dwProductVersionMS,
|
||||
observed->VersionInfo.dwProductVersionMS);
|
||||
EXPECT_EQ(expected->VersionInfo.dwProductVersionLS,
|
||||
observed->VersionInfo.dwProductVersionLS);
|
||||
EXPECT_EQ(expected->VersionInfo.dwFileFlagsMask,
|
||||
observed->VersionInfo.dwFileFlagsMask);
|
||||
EXPECT_EQ(expected->VersionInfo.dwFileFlags,
|
||||
observed->VersionInfo.dwFileFlags);
|
||||
EXPECT_EQ(expected->VersionInfo.dwFileOS, observed->VersionInfo.dwFileOS);
|
||||
EXPECT_EQ(expected->VersionInfo.dwFileType, observed->VersionInfo.dwFileType);
|
||||
EXPECT_EQ(expected->VersionInfo.dwFileSubtype,
|
||||
observed->VersionInfo.dwFileSubtype);
|
||||
EXPECT_EQ(expected->VersionInfo.dwFileDateMS,
|
||||
observed->VersionInfo.dwFileDateMS);
|
||||
EXPECT_EQ(expected->VersionInfo.dwFileDateLS,
|
||||
observed->VersionInfo.dwFileDateLS);
|
||||
EXPECT_EQ(0u, observed->Reserved0);
|
||||
EXPECT_EQ(0u, observed->Reserved1);
|
||||
EXPECT_EQ(observed->BaseOfImage, expected->BaseOfImage);
|
||||
EXPECT_EQ(observed->SizeOfImage, expected->SizeOfImage);
|
||||
EXPECT_EQ(observed->CheckSum, expected->CheckSum);
|
||||
EXPECT_EQ(observed->TimeDateStamp, expected->TimeDateStamp);
|
||||
EXPECT_EQ(observed->VersionInfo.dwSignature,
|
||||
implicit_cast<uint32_t>(VS_FFI_SIGNATURE));
|
||||
EXPECT_EQ(observed->VersionInfo.dwStrucVersion,
|
||||
implicit_cast<uint32_t>(VS_FFI_STRUCVERSION));
|
||||
EXPECT_EQ(observed->VersionInfo.dwFileVersionMS,
|
||||
expected->VersionInfo.dwFileVersionMS);
|
||||
EXPECT_EQ(observed->VersionInfo.dwFileVersionLS,
|
||||
expected->VersionInfo.dwFileVersionLS);
|
||||
EXPECT_EQ(observed->VersionInfo.dwProductVersionMS,
|
||||
expected->VersionInfo.dwProductVersionMS);
|
||||
EXPECT_EQ(observed->VersionInfo.dwProductVersionLS,
|
||||
expected->VersionInfo.dwProductVersionLS);
|
||||
EXPECT_EQ(observed->VersionInfo.dwFileFlagsMask,
|
||||
expected->VersionInfo.dwFileFlagsMask);
|
||||
EXPECT_EQ(observed->VersionInfo.dwFileFlags,
|
||||
expected->VersionInfo.dwFileFlags);
|
||||
EXPECT_EQ(observed->VersionInfo.dwFileOS, expected->VersionInfo.dwFileOS);
|
||||
EXPECT_EQ(observed->VersionInfo.dwFileType, expected->VersionInfo.dwFileType);
|
||||
EXPECT_EQ(observed->VersionInfo.dwFileSubtype,
|
||||
expected->VersionInfo.dwFileSubtype);
|
||||
EXPECT_EQ(observed->VersionInfo.dwFileDateMS,
|
||||
expected->VersionInfo.dwFileDateMS);
|
||||
EXPECT_EQ(observed->VersionInfo.dwFileDateLS,
|
||||
expected->VersionInfo.dwFileDateLS);
|
||||
EXPECT_EQ(observed->Reserved0, 0u);
|
||||
EXPECT_EQ(observed->Reserved1, 0u);
|
||||
|
||||
EXPECT_NE(0u, observed->ModuleNameRva);
|
||||
EXPECT_NE(observed->ModuleNameRva, 0u);
|
||||
base::string16 observed_module_name_utf16 =
|
||||
MinidumpStringAtRVAAsString(file_contents, observed->ModuleNameRva);
|
||||
base::string16 expected_module_name_utf16 =
|
||||
base::UTF8ToUTF16(expected_module_name);
|
||||
EXPECT_EQ(expected_module_name_utf16, observed_module_name_utf16);
|
||||
EXPECT_EQ(observed_module_name_utf16, expected_module_name_utf16);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(ExpectCodeViewRecord(&observed->CvRecord,
|
||||
file_contents,
|
||||
@ -290,7 +290,7 @@ TEST(MinidumpModuleWriter, EmptyModule) {
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetModuleListStream(string_file.string(), &module_list));
|
||||
|
||||
EXPECT_EQ(1u, module_list->NumberOfModules);
|
||||
EXPECT_EQ(module_list->NumberOfModules, 1u);
|
||||
|
||||
MINIDUMP_MODULE expected = {};
|
||||
ASSERT_NO_FATAL_FAILURE(ExpectModule(&expected,
|
||||
@ -381,7 +381,7 @@ TEST(MinidumpModuleWriter, OneModule) {
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetModuleListStream(string_file.string(), &module_list));
|
||||
|
||||
EXPECT_EQ(1u, module_list->NumberOfModules);
|
||||
EXPECT_EQ(module_list->NumberOfModules, 1u);
|
||||
|
||||
MINIDUMP_MODULE expected = {};
|
||||
expected.BaseOfImage = kModuleBase;
|
||||
@ -456,7 +456,7 @@ TEST(MinidumpModuleWriter, OneModule_CodeViewUsesPDB20_MiscUsesUTF16) {
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetModuleListStream(string_file.string(), &module_list));
|
||||
|
||||
EXPECT_EQ(1u, module_list->NumberOfModules);
|
||||
EXPECT_EQ(module_list->NumberOfModules, 1u);
|
||||
|
||||
MINIDUMP_MODULE expected = {};
|
||||
|
||||
@ -548,7 +548,7 @@ TEST(MinidumpModuleWriter, ThreeModules) {
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetModuleListStream(string_file.string(), &module_list));
|
||||
|
||||
EXPECT_EQ(3u, module_list->NumberOfModules);
|
||||
EXPECT_EQ(module_list->NumberOfModules, 3u);
|
||||
|
||||
MINIDUMP_MODULE expected = {};
|
||||
|
||||
@ -733,7 +733,7 @@ TEST(MinidumpModuleWriter, InitializeFromSnapshot) {
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetModuleListStream(string_file.string(), &module_list));
|
||||
|
||||
ASSERT_EQ(3u, module_list->NumberOfModules);
|
||||
ASSERT_EQ(module_list->NumberOfModules, 3u);
|
||||
|
||||
for (size_t index = 0; index < module_list->NumberOfModules; ++index) {
|
||||
SCOPED_TRACE(base::StringPrintf("index %" PRIuS, index));
|
||||
|
@ -48,7 +48,7 @@ TEST(MinidumpRVAListWriter, Empty) {
|
||||
StringFile string_file;
|
||||
|
||||
ASSERT_TRUE(list_writer.WriteEverything(&string_file));
|
||||
EXPECT_EQ(sizeof(MinidumpRVAList), string_file.string().size());
|
||||
EXPECT_EQ(string_file.string().size(), sizeof(MinidumpRVAList));
|
||||
|
||||
const MinidumpRVAList* list = MinidumpRVAListAtStart(string_file.string(), 0);
|
||||
ASSERT_TRUE(list);
|
||||
@ -70,7 +70,7 @@ TEST(MinidumpRVAListWriter, OneChild) {
|
||||
const uint32_t* child = MinidumpWritableAtRVA<uint32_t>(
|
||||
string_file.string(), list->children[0]);
|
||||
ASSERT_TRUE(child);
|
||||
EXPECT_EQ(kValue, *child);
|
||||
EXPECT_EQ(*child, kValue);
|
||||
}
|
||||
|
||||
TEST(MinidumpRVAListWriter, ThreeChildren) {
|
||||
@ -96,7 +96,7 @@ TEST(MinidumpRVAListWriter, ThreeChildren) {
|
||||
const uint32_t* child = MinidumpWritableAtRVA<uint32_t>(
|
||||
string_file.string(), list->children[index]);
|
||||
ASSERT_TRUE(child);
|
||||
EXPECT_EQ(kValues[index], *child);
|
||||
EXPECT_EQ(*child, kValues[index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,13 +51,13 @@ TEST(MinidumpSimpleStringDictionaryWriter, EmptySimpleStringDictionary) {
|
||||
EXPECT_FALSE(dictionary_writer.IsUseful());
|
||||
|
||||
EXPECT_TRUE(dictionary_writer.WriteEverything(&string_file));
|
||||
ASSERT_EQ(sizeof(MinidumpSimpleStringDictionary),
|
||||
string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MinidumpSimpleStringDictionary));
|
||||
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryAtStart(string_file.string(), 0);
|
||||
ASSERT_TRUE(dictionary);
|
||||
EXPECT_EQ(0u, dictionary->count);
|
||||
EXPECT_EQ(dictionary->count, 0u);
|
||||
}
|
||||
|
||||
TEST(MinidumpSimpleStringDictionaryWriter, EmptyKeyValue) {
|
||||
@ -71,23 +71,23 @@ TEST(MinidumpSimpleStringDictionaryWriter, EmptyKeyValue) {
|
||||
EXPECT_TRUE(dictionary_writer.IsUseful());
|
||||
|
||||
EXPECT_TRUE(dictionary_writer.WriteEverything(&string_file));
|
||||
ASSERT_EQ(sizeof(MinidumpSimpleStringDictionary) +
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MinidumpSimpleStringDictionary) +
|
||||
sizeof(MinidumpSimpleStringDictionaryEntry) +
|
||||
2 * sizeof(MinidumpUTF8String) + 1 + 3 + 1, // 3 for padding
|
||||
string_file.string().size());
|
||||
2 * sizeof(MinidumpUTF8String) + 1 + 3 + 1); // 3 for padding
|
||||
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryAtStart(string_file.string(), 1);
|
||||
ASSERT_TRUE(dictionary);
|
||||
EXPECT_EQ(1u, dictionary->count);
|
||||
EXPECT_EQ(12u, dictionary->entries[0].key);
|
||||
EXPECT_EQ(20u, dictionary->entries[0].value);
|
||||
EXPECT_EQ("",
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].key));
|
||||
EXPECT_EQ("",
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].value));
|
||||
EXPECT_EQ(dictionary->count, 1u);
|
||||
EXPECT_EQ(dictionary->entries[0].key, 12u);
|
||||
EXPECT_EQ(dictionary->entries[0].value, 20u);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].key),
|
||||
"");
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].value),
|
||||
"");
|
||||
}
|
||||
|
||||
TEST(MinidumpSimpleStringDictionaryWriter, OneKeyValue) {
|
||||
@ -105,23 +105,23 @@ TEST(MinidumpSimpleStringDictionaryWriter, OneKeyValue) {
|
||||
EXPECT_TRUE(dictionary_writer.IsUseful());
|
||||
|
||||
EXPECT_TRUE(dictionary_writer.WriteEverything(&string_file));
|
||||
ASSERT_EQ(sizeof(MinidumpSimpleStringDictionary) +
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MinidumpSimpleStringDictionary) +
|
||||
sizeof(MinidumpSimpleStringDictionaryEntry) +
|
||||
2 * sizeof(MinidumpUTF8String) + sizeof(kKey) + sizeof(kValue),
|
||||
string_file.string().size());
|
||||
2 * sizeof(MinidumpUTF8String) + sizeof(kKey) + sizeof(kValue));
|
||||
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryAtStart(string_file.string(), 1);
|
||||
ASSERT_TRUE(dictionary);
|
||||
EXPECT_EQ(1u, dictionary->count);
|
||||
EXPECT_EQ(12u, dictionary->entries[0].key);
|
||||
EXPECT_EQ(20u, dictionary->entries[0].value);
|
||||
EXPECT_EQ(kKey,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].key));
|
||||
EXPECT_EQ(kValue,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].value));
|
||||
EXPECT_EQ(dictionary->count, 1u);
|
||||
EXPECT_EQ(dictionary->entries[0].key, 12u);
|
||||
EXPECT_EQ(dictionary->entries[0].value, 20u);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].key),
|
||||
kKey);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].value),
|
||||
kValue);
|
||||
}
|
||||
|
||||
TEST(MinidumpSimpleStringDictionaryWriter, ThreeKeysValues) {
|
||||
@ -151,23 +151,23 @@ TEST(MinidumpSimpleStringDictionaryWriter, ThreeKeysValues) {
|
||||
EXPECT_TRUE(dictionary_writer.IsUseful());
|
||||
|
||||
EXPECT_TRUE(dictionary_writer.WriteEverything(&string_file));
|
||||
ASSERT_EQ(sizeof(MinidumpSimpleStringDictionary) +
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MinidumpSimpleStringDictionary) +
|
||||
3 * sizeof(MinidumpSimpleStringDictionaryEntry) +
|
||||
6 * sizeof(MinidumpUTF8String) + sizeof(kKey2) +
|
||||
sizeof(kValue2) + 3 + sizeof(kKey0) + 1 + sizeof(kValue0) + 1 +
|
||||
sizeof(kKey1) + 3 + sizeof(kValue1),
|
||||
string_file.string().size());
|
||||
sizeof(kKey1) + 3 + sizeof(kValue1));
|
||||
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryAtStart(string_file.string(), 3);
|
||||
ASSERT_TRUE(dictionary);
|
||||
EXPECT_EQ(3u, dictionary->count);
|
||||
EXPECT_EQ(28u, dictionary->entries[0].key);
|
||||
EXPECT_EQ(36u, dictionary->entries[0].value);
|
||||
EXPECT_EQ(48u, dictionary->entries[1].key);
|
||||
EXPECT_EQ(56u, dictionary->entries[1].value);
|
||||
EXPECT_EQ(68u, dictionary->entries[2].key);
|
||||
EXPECT_EQ(80u, dictionary->entries[2].value);
|
||||
EXPECT_EQ(dictionary->count, 3u);
|
||||
EXPECT_EQ(dictionary->entries[0].key, 28u);
|
||||
EXPECT_EQ(dictionary->entries[0].value, 36u);
|
||||
EXPECT_EQ(dictionary->entries[1].key, 48u);
|
||||
EXPECT_EQ(dictionary->entries[1].value, 56u);
|
||||
EXPECT_EQ(dictionary->entries[2].key, 68u);
|
||||
EXPECT_EQ(dictionary->entries[2].value, 80u);
|
||||
|
||||
// The entries don’t appear in the order they were added. The current
|
||||
// implementation uses a std::map and sorts keys, so the entires appear in
|
||||
@ -175,24 +175,24 @@ TEST(MinidumpSimpleStringDictionaryWriter, ThreeKeysValues) {
|
||||
// if the writer stops sorting in this order. Testing for a specific order is
|
||||
// just the easiest way to write this test while the writer will output things
|
||||
// in a known order.
|
||||
EXPECT_EQ(kKey2,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].key));
|
||||
EXPECT_EQ(kValue2,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].value));
|
||||
EXPECT_EQ(kKey0,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[1].key));
|
||||
EXPECT_EQ(kValue0,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[1].value));
|
||||
EXPECT_EQ(kKey1,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[2].key));
|
||||
EXPECT_EQ(kValue1,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[2].value));
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].key),
|
||||
kKey2);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].value),
|
||||
kValue2);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[1].key),
|
||||
kKey0);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[1].value),
|
||||
kValue0);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[2].key),
|
||||
kKey1);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[2].value),
|
||||
kValue1);
|
||||
}
|
||||
|
||||
TEST(MinidumpSimpleStringDictionaryWriter, DuplicateKeyValue) {
|
||||
@ -215,23 +215,24 @@ TEST(MinidumpSimpleStringDictionaryWriter, DuplicateKeyValue) {
|
||||
EXPECT_TRUE(dictionary_writer.IsUseful());
|
||||
|
||||
EXPECT_TRUE(dictionary_writer.WriteEverything(&string_file));
|
||||
ASSERT_EQ(sizeof(MinidumpSimpleStringDictionary) +
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MinidumpSimpleStringDictionary) +
|
||||
sizeof(MinidumpSimpleStringDictionaryEntry) +
|
||||
2 * sizeof(MinidumpUTF8String) + sizeof(kKey) + sizeof(kValue1),
|
||||
string_file.string().size());
|
||||
2 * sizeof(MinidumpUTF8String) + sizeof(kKey) +
|
||||
sizeof(kValue1));
|
||||
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryAtStart(string_file.string(), 1);
|
||||
ASSERT_TRUE(dictionary);
|
||||
EXPECT_EQ(1u, dictionary->count);
|
||||
EXPECT_EQ(12u, dictionary->entries[0].key);
|
||||
EXPECT_EQ(20u, dictionary->entries[0].value);
|
||||
EXPECT_EQ(kKey,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].key));
|
||||
EXPECT_EQ(kValue1,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].value));
|
||||
EXPECT_EQ(dictionary->count, 1u);
|
||||
EXPECT_EQ(dictionary->entries[0].key, 12u);
|
||||
EXPECT_EQ(dictionary->entries[0].value, 20u);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].key),
|
||||
kKey);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].value),
|
||||
kValue1);
|
||||
}
|
||||
|
||||
TEST(MinidumpSimpleStringDictionaryWriter, InitializeFromMap) {
|
||||
@ -258,7 +259,7 @@ TEST(MinidumpSimpleStringDictionaryWriter, InitializeFromMap) {
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryAtStart(string_file.string(), map.size());
|
||||
ASSERT_TRUE(dictionary);
|
||||
ASSERT_EQ(3u, dictionary->count);
|
||||
ASSERT_EQ(dictionary->count, 3u);
|
||||
|
||||
// The entries don’t appear in the order they were added. The current
|
||||
// implementation uses a std::map and sorts keys, so the entires appear in
|
||||
@ -266,24 +267,24 @@ TEST(MinidumpSimpleStringDictionaryWriter, InitializeFromMap) {
|
||||
// if the writer stops sorting in this order. Testing for a specific order is
|
||||
// just the easiest way to write this test while the writer will output things
|
||||
// in a known order.
|
||||
EXPECT_EQ(kKey1,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].key));
|
||||
EXPECT_EQ(kValue1,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].value));
|
||||
EXPECT_EQ(kKey0,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[1].key));
|
||||
EXPECT_EQ(kValue0,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[1].value));
|
||||
EXPECT_EQ(kKey2,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[2].key));
|
||||
EXPECT_EQ(kValue2,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[2].value));
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].key),
|
||||
kKey1);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[0].value),
|
||||
kValue1);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[1].key),
|
||||
kKey0);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[1].value),
|
||||
kValue0);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[2].key),
|
||||
kKey2);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||
dictionary->entries[2].value),
|
||||
kValue2);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -40,13 +40,13 @@ TEST(MinidumpStringWriter, MinidumpUTF16StringWriter) {
|
||||
string_file.Reset();
|
||||
crashpad::internal::MinidumpUTF16StringWriter string_writer;
|
||||
EXPECT_TRUE(string_writer.WriteEverything(&string_file));
|
||||
ASSERT_EQ(6u, string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), 6u);
|
||||
|
||||
const MINIDUMP_STRING* minidump_string =
|
||||
MinidumpStringAtRVA(string_file.string(), 0);
|
||||
EXPECT_TRUE(minidump_string);
|
||||
EXPECT_EQ(base::string16(),
|
||||
MinidumpStringAtRVAAsString(string_file.string(), 0));
|
||||
EXPECT_EQ(MinidumpStringAtRVAAsString(string_file.string(), 0),
|
||||
base::string16());
|
||||
}
|
||||
|
||||
const struct {
|
||||
@ -74,10 +74,9 @@ TEST(MinidumpStringWriter, MinidumpUTF16StringWriter) {
|
||||
|
||||
// Make sure that the expected output string with its NUL terminator fits in
|
||||
// the space provided.
|
||||
ASSERT_EQ(
|
||||
0,
|
||||
kTestData[index]
|
||||
.output_string[arraysize(kTestData[index].output_string) - 1]);
|
||||
ASSERT_EQ(kTestData[index]
|
||||
.output_string[arraysize(kTestData[index].output_string) - 1],
|
||||
0);
|
||||
|
||||
string_file.Reset();
|
||||
crashpad::internal::MinidumpUTF16StringWriter string_writer;
|
||||
@ -91,16 +90,16 @@ TEST(MinidumpStringWriter, MinidumpUTF16StringWriter) {
|
||||
ALLOW_UNUSED_LOCAL(tmp);
|
||||
const size_t expected_utf16_bytes =
|
||||
expected_utf16_units_with_nul * sizeof(tmp.Buffer[0]);
|
||||
ASSERT_EQ(sizeof(MINIDUMP_STRING) + expected_utf16_bytes,
|
||||
string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MINIDUMP_STRING) + expected_utf16_bytes);
|
||||
|
||||
const MINIDUMP_STRING* minidump_string =
|
||||
MinidumpStringAtRVA(string_file.string(), 0);
|
||||
EXPECT_TRUE(minidump_string);
|
||||
base::string16 expect_string = base::string16(
|
||||
kTestData[index].output_string, kTestData[index].output_length);
|
||||
EXPECT_EQ(expect_string,
|
||||
MinidumpStringAtRVAAsString(string_file.string(), 0));
|
||||
EXPECT_EQ(MinidumpStringAtRVAAsString(string_file.string(), 0),
|
||||
expect_string);
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,13 +133,13 @@ TEST(MinidumpStringWriter, ConvertInvalidUTF8ToUTF16) {
|
||||
EXPECT_TRUE(minidump_string);
|
||||
MINIDUMP_STRING tmp = {0};
|
||||
ALLOW_UNUSED_LOCAL(tmp);
|
||||
EXPECT_EQ(string_file.string().size() - sizeof(MINIDUMP_STRING) -
|
||||
sizeof(tmp.Buffer[0]),
|
||||
minidump_string->Length);
|
||||
EXPECT_EQ(minidump_string->Length,
|
||||
string_file.string().size() - sizeof(MINIDUMP_STRING) -
|
||||
sizeof(tmp.Buffer[0]));
|
||||
base::string16 output_string =
|
||||
MinidumpStringAtRVAAsString(string_file.string(), 0);
|
||||
EXPECT_FALSE(output_string.empty());
|
||||
EXPECT_NE(base::string16::npos, output_string.find(0xfffd));
|
||||
EXPECT_NE(output_string.find(0xfffd), base::string16::npos);
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,13 +151,13 @@ TEST(MinidumpStringWriter, MinidumpUTF8StringWriter) {
|
||||
string_file.Reset();
|
||||
crashpad::internal::MinidumpUTF8StringWriter string_writer;
|
||||
EXPECT_TRUE(string_writer.WriteEverything(&string_file));
|
||||
ASSERT_EQ(5u, string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), 5u);
|
||||
|
||||
const MinidumpUTF8String* minidump_string =
|
||||
MinidumpUTF8StringAtRVA(string_file.string(), 0);
|
||||
EXPECT_TRUE(minidump_string);
|
||||
EXPECT_EQ(std::string(),
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(), 0));
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(), 0),
|
||||
std::string());
|
||||
}
|
||||
|
||||
const struct {
|
||||
@ -186,18 +185,18 @@ TEST(MinidumpStringWriter, MinidumpUTF8StringWriter) {
|
||||
crashpad::internal::MinidumpUTF8StringWriter string_writer;
|
||||
std::string test_string(kTestData[index].string, kTestData[index].length);
|
||||
string_writer.SetUTF8(test_string);
|
||||
EXPECT_EQ(test_string, string_writer.UTF8());
|
||||
EXPECT_EQ(string_writer.UTF8(), test_string);
|
||||
EXPECT_TRUE(string_writer.WriteEverything(&string_file));
|
||||
|
||||
const size_t expected_utf8_bytes_with_nul = kTestData[index].length + 1;
|
||||
ASSERT_EQ(sizeof(MinidumpUTF8String) + expected_utf8_bytes_with_nul,
|
||||
string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MinidumpUTF8String) + expected_utf8_bytes_with_nul);
|
||||
|
||||
const MinidumpUTF8String* minidump_string =
|
||||
MinidumpUTF8StringAtRVA(string_file.string(), 0);
|
||||
EXPECT_TRUE(minidump_string);
|
||||
EXPECT_EQ(test_string,
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(), 0));
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(), 0),
|
||||
test_string);
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,9 +244,9 @@ void MinidumpStringListTest() {
|
||||
ASSERT_TRUE(list);
|
||||
|
||||
for (size_t index = 0; index < strings.size(); ++index) {
|
||||
EXPECT_EQ(Traits::ExpectationForUTF8(strings[index]),
|
||||
Traits::ObservationAtRVA(string_file.string(),
|
||||
list->children[index]));
|
||||
EXPECT_EQ(
|
||||
Traits::ObservationAtRVA(string_file.string(), list->children[index]),
|
||||
Traits::ExpectationForUTF8(strings[index]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ void GetSystemInfoStream(const std::string& file_contents,
|
||||
const size_t kFileSize =
|
||||
kCSDVersionOffset + sizeof(MINIDUMP_STRING) + kCSDVersionBytesWithNUL;
|
||||
|
||||
ASSERT_EQ(kFileSize, file_contents.size());
|
||||
ASSERT_EQ(file_contents.size(), kFileSize);
|
||||
|
||||
const MINIDUMP_DIRECTORY* directory;
|
||||
const MINIDUMP_HEADER* header =
|
||||
@ -62,18 +62,18 @@ void GetSystemInfoStream(const std::string& file_contents,
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeSystemInfo, directory[0].StreamType);
|
||||
EXPECT_EQ(kSystemInfoStreamOffset, directory[0].Location.Rva);
|
||||
ASSERT_EQ(directory[0].StreamType, kMinidumpStreamTypeSystemInfo);
|
||||
EXPECT_EQ(directory[0].Location.Rva, kSystemInfoStreamOffset);
|
||||
|
||||
*system_info = MinidumpWritableAtLocationDescriptor<MINIDUMP_SYSTEM_INFO>(
|
||||
file_contents, directory[0].Location);
|
||||
ASSERT_TRUE(system_info);
|
||||
|
||||
EXPECT_EQ(kCSDVersionOffset, (*system_info)->CSDVersionRva);
|
||||
EXPECT_EQ((*system_info)->CSDVersionRva, kCSDVersionOffset);
|
||||
|
||||
*csd_version =
|
||||
MinidumpStringAtRVA(file_contents, (*system_info)->CSDVersionRva);
|
||||
EXPECT_EQ(kCSDVersionBytes, (*csd_version)->Length);
|
||||
EXPECT_EQ((*csd_version)->Length, kCSDVersionBytes);
|
||||
}
|
||||
|
||||
TEST(MinidumpSystemInfoWriter, Empty) {
|
||||
@ -93,27 +93,27 @@ TEST(MinidumpSystemInfoWriter, Empty) {
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetSystemInfoStream(string_file.string(), 0, &system_info, &csd_version));
|
||||
|
||||
EXPECT_EQ(kMinidumpCPUArchitectureUnknown,
|
||||
system_info->ProcessorArchitecture);
|
||||
EXPECT_EQ(0u, system_info->ProcessorLevel);
|
||||
EXPECT_EQ(0u, system_info->ProcessorRevision);
|
||||
EXPECT_EQ(0u, system_info->NumberOfProcessors);
|
||||
EXPECT_EQ(0u, system_info->ProductType);
|
||||
EXPECT_EQ(0u, system_info->MajorVersion);
|
||||
EXPECT_EQ(0u, system_info->MinorVersion);
|
||||
EXPECT_EQ(0u, system_info->BuildNumber);
|
||||
EXPECT_EQ(0u, system_info->PlatformId);
|
||||
EXPECT_EQ(0u, system_info->SuiteMask);
|
||||
EXPECT_EQ(0u, system_info->Cpu.X86CpuInfo.VendorId[0]);
|
||||
EXPECT_EQ(0u, system_info->Cpu.X86CpuInfo.VendorId[1]);
|
||||
EXPECT_EQ(0u, system_info->Cpu.X86CpuInfo.VendorId[2]);
|
||||
EXPECT_EQ(0u, system_info->Cpu.X86CpuInfo.VersionInformation);
|
||||
EXPECT_EQ(0u, system_info->Cpu.X86CpuInfo.FeatureInformation);
|
||||
EXPECT_EQ(0u, system_info->Cpu.X86CpuInfo.AMDExtendedCpuFeatures);
|
||||
EXPECT_EQ(0u, system_info->Cpu.OtherCpuInfo.ProcessorFeatures[0]);
|
||||
EXPECT_EQ(0u, system_info->Cpu.OtherCpuInfo.ProcessorFeatures[1]);
|
||||
EXPECT_EQ(system_info->ProcessorArchitecture,
|
||||
kMinidumpCPUArchitectureUnknown);
|
||||
EXPECT_EQ(system_info->ProcessorLevel, 0u);
|
||||
EXPECT_EQ(system_info->ProcessorRevision, 0u);
|
||||
EXPECT_EQ(system_info->NumberOfProcessors, 0u);
|
||||
EXPECT_EQ(system_info->ProductType, 0u);
|
||||
EXPECT_EQ(system_info->MajorVersion, 0u);
|
||||
EXPECT_EQ(system_info->MinorVersion, 0u);
|
||||
EXPECT_EQ(system_info->BuildNumber, 0u);
|
||||
EXPECT_EQ(system_info->PlatformId, 0u);
|
||||
EXPECT_EQ(system_info->SuiteMask, 0u);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VendorId[0], 0u);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VendorId[1], 0u);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VendorId[2], 0u);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VersionInformation, 0u);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.FeatureInformation, 0u);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.AMDExtendedCpuFeatures, 0u);
|
||||
EXPECT_EQ(system_info->Cpu.OtherCpuInfo.ProcessorFeatures[0], 0u);
|
||||
EXPECT_EQ(system_info->Cpu.OtherCpuInfo.ProcessorFeatures[1], 0u);
|
||||
|
||||
EXPECT_EQ('\0', csd_version->Buffer[0]);
|
||||
EXPECT_EQ(csd_version->Buffer[0], '\0');
|
||||
}
|
||||
|
||||
TEST(MinidumpSystemInfoWriter, X86_Win) {
|
||||
@ -137,7 +137,7 @@ TEST(MinidumpSystemInfoWriter, X86_Win) {
|
||||
const uint32_t kAMDFeatures = 0xefd3fbff;
|
||||
|
||||
uint32_t cpu_vendor_registers[3];
|
||||
ASSERT_EQ(sizeof(cpu_vendor_registers), strlen(kCPUVendor));
|
||||
ASSERT_EQ(strlen(kCPUVendor), sizeof(cpu_vendor_registers));
|
||||
memcpy(cpu_vendor_registers, kCPUVendor, sizeof(cpu_vendor_registers));
|
||||
|
||||
system_info_writer->SetCPUArchitecture(kCPUArchitecture);
|
||||
@ -164,25 +164,25 @@ TEST(MinidumpSystemInfoWriter, X86_Win) {
|
||||
ASSERT_NO_FATAL_FAILURE(GetSystemInfoStream(
|
||||
string_file.string(), strlen(kCSDVersion), &system_info, &csd_version));
|
||||
|
||||
EXPECT_EQ(kCPUArchitecture, system_info->ProcessorArchitecture);
|
||||
EXPECT_EQ(kCPULevel, system_info->ProcessorLevel);
|
||||
EXPECT_EQ(kCPURevision, system_info->ProcessorRevision);
|
||||
EXPECT_EQ(kCPUCount, system_info->NumberOfProcessors);
|
||||
EXPECT_EQ(kOSType, system_info->ProductType);
|
||||
EXPECT_EQ(kOSVersionMajor, system_info->MajorVersion);
|
||||
EXPECT_EQ(kOSVersionMinor, system_info->MinorVersion);
|
||||
EXPECT_EQ(kOSVersionBuild, system_info->BuildNumber);
|
||||
EXPECT_EQ(kOS, system_info->PlatformId);
|
||||
EXPECT_EQ(kSuiteMask, system_info->SuiteMask);
|
||||
EXPECT_EQ(cpu_vendor_registers[0], system_info->Cpu.X86CpuInfo.VendorId[0]);
|
||||
EXPECT_EQ(cpu_vendor_registers[1], system_info->Cpu.X86CpuInfo.VendorId[1]);
|
||||
EXPECT_EQ(cpu_vendor_registers[2], system_info->Cpu.X86CpuInfo.VendorId[2]);
|
||||
EXPECT_EQ(kCPUVersion, system_info->Cpu.X86CpuInfo.VersionInformation);
|
||||
EXPECT_EQ(kCPUFeatures, system_info->Cpu.X86CpuInfo.FeatureInformation);
|
||||
EXPECT_EQ(kAMDFeatures, system_info->Cpu.X86CpuInfo.AMDExtendedCpuFeatures);
|
||||
EXPECT_EQ(system_info->ProcessorArchitecture, kCPUArchitecture);
|
||||
EXPECT_EQ(system_info->ProcessorLevel, kCPULevel);
|
||||
EXPECT_EQ(system_info->ProcessorRevision, kCPURevision);
|
||||
EXPECT_EQ(system_info->NumberOfProcessors, kCPUCount);
|
||||
EXPECT_EQ(system_info->ProductType, kOSType);
|
||||
EXPECT_EQ(system_info->MajorVersion, kOSVersionMajor);
|
||||
EXPECT_EQ(system_info->MinorVersion, kOSVersionMinor);
|
||||
EXPECT_EQ(system_info->BuildNumber, kOSVersionBuild);
|
||||
EXPECT_EQ(system_info->PlatformId, kOS);
|
||||
EXPECT_EQ(system_info->SuiteMask, kSuiteMask);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VendorId[0], cpu_vendor_registers[0]);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VendorId[1], cpu_vendor_registers[1]);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VendorId[2], cpu_vendor_registers[2]);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VersionInformation, kCPUVersion);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.FeatureInformation, kCPUFeatures);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.AMDExtendedCpuFeatures, kAMDFeatures);
|
||||
|
||||
for (size_t index = 0; index < strlen(kCSDVersion); ++index) {
|
||||
EXPECT_EQ(kCSDVersion[index], csd_version->Buffer[index]) << index;
|
||||
EXPECT_EQ(csd_version->Buffer[index], kCSDVersion[index]) << index;
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,20 +224,20 @@ TEST(MinidumpSystemInfoWriter, AMD64_Mac) {
|
||||
ASSERT_NO_FATAL_FAILURE(GetSystemInfoStream(
|
||||
string_file.string(), strlen(kCSDVersion), &system_info, &csd_version));
|
||||
|
||||
EXPECT_EQ(kCPUArchitecture, system_info->ProcessorArchitecture);
|
||||
EXPECT_EQ(kCPULevel, system_info->ProcessorLevel);
|
||||
EXPECT_EQ(kCPURevision, system_info->ProcessorRevision);
|
||||
EXPECT_EQ(kCPUCount, system_info->NumberOfProcessors);
|
||||
EXPECT_EQ(kOSType, system_info->ProductType);
|
||||
EXPECT_EQ(kOSVersionMajor, system_info->MajorVersion);
|
||||
EXPECT_EQ(kOSVersionMinor, system_info->MinorVersion);
|
||||
EXPECT_EQ(kOSVersionBuild, system_info->BuildNumber);
|
||||
EXPECT_EQ(kOS, system_info->PlatformId);
|
||||
EXPECT_EQ(0u, system_info->SuiteMask);
|
||||
EXPECT_EQ(kCPUFeatures[0],
|
||||
system_info->Cpu.OtherCpuInfo.ProcessorFeatures[0]);
|
||||
EXPECT_EQ(kCPUFeatures[1],
|
||||
system_info->Cpu.OtherCpuInfo.ProcessorFeatures[1]);
|
||||
EXPECT_EQ(system_info->ProcessorArchitecture, kCPUArchitecture);
|
||||
EXPECT_EQ(system_info->ProcessorLevel, kCPULevel);
|
||||
EXPECT_EQ(system_info->ProcessorRevision, kCPURevision);
|
||||
EXPECT_EQ(system_info->NumberOfProcessors, kCPUCount);
|
||||
EXPECT_EQ(system_info->ProductType, kOSType);
|
||||
EXPECT_EQ(system_info->MajorVersion, kOSVersionMajor);
|
||||
EXPECT_EQ(system_info->MinorVersion, kOSVersionMinor);
|
||||
EXPECT_EQ(system_info->BuildNumber, kOSVersionBuild);
|
||||
EXPECT_EQ(system_info->PlatformId, kOS);
|
||||
EXPECT_EQ(system_info->SuiteMask, 0u);
|
||||
EXPECT_EQ(system_info->Cpu.OtherCpuInfo.ProcessorFeatures[0],
|
||||
kCPUFeatures[0]);
|
||||
EXPECT_EQ(system_info->Cpu.OtherCpuInfo.ProcessorFeatures[1],
|
||||
kCPUFeatures[1]);
|
||||
}
|
||||
|
||||
TEST(MinidumpSystemInfoWriter, X86_CPUVendorFromRegisters) {
|
||||
@ -266,12 +266,12 @@ TEST(MinidumpSystemInfoWriter, X86_CPUVendorFromRegisters) {
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetSystemInfoStream(string_file.string(), 0, &system_info, &csd_version));
|
||||
|
||||
EXPECT_EQ(kCPUArchitecture, system_info->ProcessorArchitecture);
|
||||
EXPECT_EQ(0u, system_info->ProcessorLevel);
|
||||
EXPECT_EQ(kCPUVendor[0], system_info->Cpu.X86CpuInfo.VendorId[0]);
|
||||
EXPECT_EQ(kCPUVendor[1], system_info->Cpu.X86CpuInfo.VendorId[1]);
|
||||
EXPECT_EQ(kCPUVendor[2], system_info->Cpu.X86CpuInfo.VendorId[2]);
|
||||
EXPECT_EQ(0u, system_info->Cpu.X86CpuInfo.VersionInformation);
|
||||
EXPECT_EQ(system_info->ProcessorArchitecture, kCPUArchitecture);
|
||||
EXPECT_EQ(system_info->ProcessorLevel, 0u);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VendorId[0], kCPUVendor[0]);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VendorId[1], kCPUVendor[1]);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VendorId[2], kCPUVendor[2]);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VersionInformation, 0u);
|
||||
}
|
||||
|
||||
TEST(MinidumpSystemInfoWriter, InitializeFromSnapshot_X86) {
|
||||
@ -347,32 +347,32 @@ TEST(MinidumpSystemInfoWriter, InitializeFromSnapshot_X86) {
|
||||
&system_info,
|
||||
&csd_version));
|
||||
|
||||
EXPECT_EQ(expect_system_info.ProcessorArchitecture,
|
||||
system_info->ProcessorArchitecture);
|
||||
EXPECT_EQ(expect_system_info.ProcessorLevel, system_info->ProcessorLevel);
|
||||
EXPECT_EQ(expect_system_info.ProcessorRevision,
|
||||
system_info->ProcessorRevision);
|
||||
EXPECT_EQ(expect_system_info.NumberOfProcessors,
|
||||
system_info->NumberOfProcessors);
|
||||
EXPECT_EQ(expect_system_info.ProductType, system_info->ProductType);
|
||||
EXPECT_EQ(expect_system_info.MajorVersion, system_info->MajorVersion);
|
||||
EXPECT_EQ(expect_system_info.MinorVersion, system_info->MinorVersion);
|
||||
EXPECT_EQ(expect_system_info.BuildNumber, system_info->BuildNumber);
|
||||
EXPECT_EQ(expect_system_info.PlatformId, system_info->PlatformId);
|
||||
EXPECT_EQ(expect_system_info.SuiteMask, system_info->SuiteMask);
|
||||
EXPECT_EQ(expect_system_info.Cpu.X86CpuInfo.VendorId[0],
|
||||
system_info->Cpu.X86CpuInfo.VendorId[0]);
|
||||
EXPECT_EQ(expect_system_info.Cpu.X86CpuInfo.VendorId[1],
|
||||
system_info->Cpu.X86CpuInfo.VendorId[1]);
|
||||
EXPECT_EQ(expect_system_info.Cpu.X86CpuInfo.VendorId[2],
|
||||
system_info->Cpu.X86CpuInfo.VendorId[2]);
|
||||
EXPECT_EQ(expect_system_info.Cpu.X86CpuInfo.VersionInformation,
|
||||
system_info->Cpu.X86CpuInfo.VersionInformation);
|
||||
EXPECT_EQ(expect_system_info.Cpu.X86CpuInfo.FeatureInformation,
|
||||
system_info->Cpu.X86CpuInfo.FeatureInformation);
|
||||
EXPECT_EQ(system_info->ProcessorArchitecture,
|
||||
expect_system_info.ProcessorArchitecture);
|
||||
EXPECT_EQ(system_info->ProcessorLevel, expect_system_info.ProcessorLevel);
|
||||
EXPECT_EQ(system_info->ProcessorRevision,
|
||||
expect_system_info.ProcessorRevision);
|
||||
EXPECT_EQ(system_info->NumberOfProcessors,
|
||||
expect_system_info.NumberOfProcessors);
|
||||
EXPECT_EQ(system_info->ProductType, expect_system_info.ProductType);
|
||||
EXPECT_EQ(system_info->MajorVersion, expect_system_info.MajorVersion);
|
||||
EXPECT_EQ(system_info->MinorVersion, expect_system_info.MinorVersion);
|
||||
EXPECT_EQ(system_info->BuildNumber, expect_system_info.BuildNumber);
|
||||
EXPECT_EQ(system_info->PlatformId, expect_system_info.PlatformId);
|
||||
EXPECT_EQ(system_info->SuiteMask, expect_system_info.SuiteMask);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VendorId[0],
|
||||
expect_system_info.Cpu.X86CpuInfo.VendorId[0]);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VendorId[1],
|
||||
expect_system_info.Cpu.X86CpuInfo.VendorId[1]);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VendorId[2],
|
||||
expect_system_info.Cpu.X86CpuInfo.VendorId[2]);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.VersionInformation,
|
||||
expect_system_info.Cpu.X86CpuInfo.VersionInformation);
|
||||
EXPECT_EQ(system_info->Cpu.X86CpuInfo.FeatureInformation,
|
||||
expect_system_info.Cpu.X86CpuInfo.FeatureInformation);
|
||||
|
||||
for (size_t index = 0; index < strlen(kOSVersionBuild); ++index) {
|
||||
EXPECT_EQ(kOSVersionBuild[index], csd_version->Buffer[index]) << index;
|
||||
EXPECT_EQ(csd_version->Buffer[index], kOSVersionBuild[index]) << index;
|
||||
}
|
||||
}
|
||||
|
||||
@ -443,26 +443,26 @@ TEST(MinidumpSystemInfoWriter, InitializeFromSnapshot_AMD64) {
|
||||
&system_info,
|
||||
&csd_version));
|
||||
|
||||
EXPECT_EQ(expect_system_info.ProcessorArchitecture,
|
||||
system_info->ProcessorArchitecture);
|
||||
EXPECT_EQ(expect_system_info.ProcessorLevel, system_info->ProcessorLevel);
|
||||
EXPECT_EQ(expect_system_info.ProcessorRevision,
|
||||
system_info->ProcessorRevision);
|
||||
EXPECT_EQ(expect_system_info.NumberOfProcessors,
|
||||
system_info->NumberOfProcessors);
|
||||
EXPECT_EQ(expect_system_info.ProductType, system_info->ProductType);
|
||||
EXPECT_EQ(expect_system_info.MajorVersion, system_info->MajorVersion);
|
||||
EXPECT_EQ(expect_system_info.MinorVersion, system_info->MinorVersion);
|
||||
EXPECT_EQ(expect_system_info.BuildNumber, system_info->BuildNumber);
|
||||
EXPECT_EQ(expect_system_info.PlatformId, system_info->PlatformId);
|
||||
EXPECT_EQ(expect_system_info.SuiteMask, system_info->SuiteMask);
|
||||
EXPECT_EQ(expect_system_info.Cpu.OtherCpuInfo.ProcessorFeatures[0],
|
||||
system_info->Cpu.OtherCpuInfo.ProcessorFeatures[0]);
|
||||
EXPECT_EQ(expect_system_info.Cpu.OtherCpuInfo.ProcessorFeatures[1],
|
||||
system_info->Cpu.OtherCpuInfo.ProcessorFeatures[1]);
|
||||
EXPECT_EQ(system_info->ProcessorArchitecture,
|
||||
expect_system_info.ProcessorArchitecture);
|
||||
EXPECT_EQ(system_info->ProcessorLevel, expect_system_info.ProcessorLevel);
|
||||
EXPECT_EQ(system_info->ProcessorRevision,
|
||||
expect_system_info.ProcessorRevision);
|
||||
EXPECT_EQ(system_info->NumberOfProcessors,
|
||||
expect_system_info.NumberOfProcessors);
|
||||
EXPECT_EQ(system_info->ProductType, expect_system_info.ProductType);
|
||||
EXPECT_EQ(system_info->MajorVersion, expect_system_info.MajorVersion);
|
||||
EXPECT_EQ(system_info->MinorVersion, expect_system_info.MinorVersion);
|
||||
EXPECT_EQ(system_info->BuildNumber, expect_system_info.BuildNumber);
|
||||
EXPECT_EQ(system_info->PlatformId, expect_system_info.PlatformId);
|
||||
EXPECT_EQ(system_info->SuiteMask, expect_system_info.SuiteMask);
|
||||
EXPECT_EQ(system_info->Cpu.OtherCpuInfo.ProcessorFeatures[0],
|
||||
expect_system_info.Cpu.OtherCpuInfo.ProcessorFeatures[0]);
|
||||
EXPECT_EQ(system_info->Cpu.OtherCpuInfo.ProcessorFeatures[1],
|
||||
expect_system_info.Cpu.OtherCpuInfo.ProcessorFeatures[1]);
|
||||
|
||||
for (size_t index = 0; index < strlen(kOSVersionBuild); ++index) {
|
||||
EXPECT_EQ(kOSVersionBuild[index], csd_version->Buffer[index]) << index;
|
||||
EXPECT_EQ(csd_version->Buffer[index], kOSVersionBuild[index]) << index;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,10 +17,39 @@
|
||||
'../build/crashpad.gypi',
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'crashpad_minidump_test_lib',
|
||||
'type': 'static_library',
|
||||
'dependencies': [
|
||||
'minidump.gyp:crashpad_minidump',
|
||||
'../third_party/gtest/gtest.gyp:gtest',
|
||||
'../third_party/mini_chromium/mini_chromium.gyp:base',
|
||||
],
|
||||
'include_dirs': [
|
||||
'..',
|
||||
],
|
||||
'sources': [
|
||||
'test/minidump_context_test_util.cc',
|
||||
'test/minidump_context_test_util.h',
|
||||
'test/minidump_file_writer_test_util.cc',
|
||||
'test/minidump_file_writer_test_util.h',
|
||||
'test/minidump_memory_writer_test_util.cc',
|
||||
'test/minidump_memory_writer_test_util.h',
|
||||
'test/minidump_rva_list_test_util.cc',
|
||||
'test/minidump_rva_list_test_util.h',
|
||||
'test/minidump_string_writer_test_util.cc',
|
||||
'test/minidump_string_writer_test_util.h',
|
||||
'test/minidump_user_extension_stream_util.cc',
|
||||
'test/minidump_user_extension_stream_util.h',
|
||||
'test/minidump_writable_test_util.cc',
|
||||
'test/minidump_writable_test_util.h',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'crashpad_minidump_test',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'crashpad_minidump_test_lib',
|
||||
'minidump.gyp:crashpad_minidump',
|
||||
'../snapshot/snapshot_test.gyp:crashpad_snapshot_test_lib',
|
||||
'../test/test.gyp:crashpad_gtest_main',
|
||||
@ -36,8 +65,8 @@
|
||||
'minidump_context_writer_test.cc',
|
||||
'minidump_crashpad_info_writer_test.cc',
|
||||
'minidump_exception_writer_test.cc',
|
||||
'minidump_handle_writer_test.cc',
|
||||
'minidump_file_writer_test.cc',
|
||||
'minidump_handle_writer_test.cc',
|
||||
'minidump_memory_info_writer_test.cc',
|
||||
'minidump_memory_writer_test.cc',
|
||||
'minidump_misc_info_writer_test.cc',
|
||||
@ -52,18 +81,6 @@
|
||||
'minidump_unloaded_module_writer_test.cc',
|
||||
'minidump_user_stream_writer_test.cc',
|
||||
'minidump_writable_test.cc',
|
||||
'test/minidump_context_test_util.cc',
|
||||
'test/minidump_context_test_util.h',
|
||||
'test/minidump_file_writer_test_util.cc',
|
||||
'test/minidump_file_writer_test_util.h',
|
||||
'test/minidump_memory_writer_test_util.cc',
|
||||
'test/minidump_memory_writer_test_util.h',
|
||||
'test/minidump_rva_list_test_util.cc',
|
||||
'test/minidump_rva_list_test_util.h',
|
||||
'test/minidump_string_writer_test_util.cc',
|
||||
'test/minidump_string_writer_test_util.h',
|
||||
'test/minidump_writable_test_util.cc',
|
||||
'test/minidump_writable_test_util.h',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
@ -48,11 +48,11 @@ class MinidumpThreadIDMapTest : public testing::Test {
|
||||
const MinidumpThreadIDMap* map, uint64_t key, uint32_t expected_value) {
|
||||
auto iterator = map->find(key);
|
||||
if (iterator == map->end()) {
|
||||
EXPECT_NE(map->end(), iterator);
|
||||
EXPECT_NE(iterator, map->end());
|
||||
return false;
|
||||
}
|
||||
if (iterator->second != expected_value) {
|
||||
EXPECT_EQ(expected_value, iterator->second);
|
||||
EXPECT_EQ(iterator->second, expected_value);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -95,7 +95,7 @@ TEST_F(MinidumpThreadIDMapTest, SimpleMapping) {
|
||||
MinidumpThreadIDMap thread_id_map;
|
||||
BuildMinidumpThreadIDMap(thread_snapshots(), &thread_id_map);
|
||||
|
||||
EXPECT_EQ(5u, thread_id_map.size());
|
||||
EXPECT_EQ(thread_id_map.size(), 5u);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 1, 1);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 3, 3);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 5, 5);
|
||||
@ -113,7 +113,7 @@ TEST_F(MinidumpThreadIDMapTest, Truncation) {
|
||||
MinidumpThreadIDMap thread_id_map;
|
||||
BuildMinidumpThreadIDMap(thread_snapshots(), &thread_id_map);
|
||||
|
||||
EXPECT_EQ(5u, thread_id_map.size());
|
||||
EXPECT_EQ(thread_id_map.size(), 5u);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000000000000, 0x00000000);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x9999999900000001, 0x00000001);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x9999999980000001, 0x80000001);
|
||||
@ -131,7 +131,7 @@ TEST_F(MinidumpThreadIDMapTest, DuplicateThreadID) {
|
||||
MinidumpThreadIDMap thread_id_map;
|
||||
BuildMinidumpThreadIDMap(thread_snapshots(), &thread_id_map);
|
||||
|
||||
EXPECT_EQ(4u, thread_id_map.size());
|
||||
EXPECT_EQ(thread_id_map.size(), 4u);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 2, 2);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 4, 4);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 6, 6);
|
||||
@ -148,7 +148,7 @@ TEST_F(MinidumpThreadIDMapTest, Collision) {
|
||||
MinidumpThreadIDMap thread_id_map;
|
||||
BuildMinidumpThreadIDMap(thread_snapshots(), &thread_id_map);
|
||||
|
||||
EXPECT_EQ(5u, thread_id_map.size());
|
||||
EXPECT_EQ(thread_id_map.size(), 5u);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000000000010, 0);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000000000020, 1);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000000000030, 2);
|
||||
@ -166,7 +166,7 @@ TEST_F(MinidumpThreadIDMapTest, DuplicateAndCollision) {
|
||||
MinidumpThreadIDMap thread_id_map;
|
||||
BuildMinidumpThreadIDMap(thread_snapshots(), &thread_id_map);
|
||||
|
||||
EXPECT_EQ(4u, thread_id_map.size());
|
||||
EXPECT_EQ(thread_id_map.size(), 4u);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000100000010, 0);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000000000010, 1);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000000000020, 2);
|
||||
@ -183,7 +183,7 @@ TEST_F(MinidumpThreadIDMapTest, AllDuplicates) {
|
||||
MinidumpThreadIDMap thread_id_map;
|
||||
BuildMinidumpThreadIDMap(thread_snapshots(), &thread_id_map);
|
||||
|
||||
EXPECT_EQ(1u, thread_id_map.size());
|
||||
EXPECT_EQ(thread_id_map.size(), 1u);
|
||||
EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 6, 6);
|
||||
}
|
||||
|
||||
|
@ -61,15 +61,15 @@ void GetThreadListStream(const std::string& file_contents,
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, kExpectedStreams, 0));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeThreadList, directory[0].StreamType);
|
||||
EXPECT_EQ(kThreadListStreamOffset, directory[0].Location.Rva);
|
||||
ASSERT_EQ(directory[0].StreamType, kMinidumpStreamTypeThreadList);
|
||||
EXPECT_EQ(directory[0].Location.Rva, kThreadListStreamOffset);
|
||||
|
||||
*thread_list = MinidumpWritableAtLocationDescriptor<MINIDUMP_THREAD_LIST>(
|
||||
file_contents, directory[0].Location);
|
||||
ASSERT_TRUE(thread_list);
|
||||
|
||||
if (memory_list) {
|
||||
ASSERT_EQ(kMinidumpStreamTypeMemoryList, directory[1].StreamType);
|
||||
ASSERT_EQ(directory[1].StreamType, kMinidumpStreamTypeMemoryList);
|
||||
|
||||
*memory_list = MinidumpWritableAtLocationDescriptor<MINIDUMP_MEMORY_LIST>(
|
||||
file_contents, directory[1].Location);
|
||||
@ -86,15 +86,15 @@ TEST(MinidumpThreadWriter, EmptyThreadList) {
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_THREAD_LIST),
|
||||
string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_THREAD_LIST));
|
||||
|
||||
const MINIDUMP_THREAD_LIST* thread_list = nullptr;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetThreadListStream(string_file.string(), &thread_list, nullptr));
|
||||
|
||||
EXPECT_EQ(0u, thread_list->NumberOfThreads);
|
||||
EXPECT_EQ(thread_list->NumberOfThreads, 0u);
|
||||
}
|
||||
|
||||
// The MINIDUMP_THREADs |expected| and |observed| are compared against each
|
||||
@ -109,30 +109,30 @@ void ExpectThread(const MINIDUMP_THREAD* expected,
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_MEMORY_DESCRIPTOR** stack,
|
||||
const void** context_base) {
|
||||
EXPECT_EQ(expected->ThreadId, observed->ThreadId);
|
||||
EXPECT_EQ(expected->SuspendCount, observed->SuspendCount);
|
||||
EXPECT_EQ(expected->PriorityClass, observed->PriorityClass);
|
||||
EXPECT_EQ(expected->Priority, observed->Priority);
|
||||
EXPECT_EQ(expected->Teb, observed->Teb);
|
||||
EXPECT_EQ(observed->ThreadId, expected->ThreadId);
|
||||
EXPECT_EQ(observed->SuspendCount, expected->SuspendCount);
|
||||
EXPECT_EQ(observed->PriorityClass, expected->PriorityClass);
|
||||
EXPECT_EQ(observed->Priority, expected->Priority);
|
||||
EXPECT_EQ(observed->Teb, expected->Teb);
|
||||
|
||||
EXPECT_EQ(expected->Stack.StartOfMemoryRange,
|
||||
observed->Stack.StartOfMemoryRange);
|
||||
EXPECT_EQ(expected->Stack.Memory.DataSize, observed->Stack.Memory.DataSize);
|
||||
EXPECT_EQ(observed->Stack.StartOfMemoryRange,
|
||||
expected->Stack.StartOfMemoryRange);
|
||||
EXPECT_EQ(observed->Stack.Memory.DataSize, expected->Stack.Memory.DataSize);
|
||||
if (stack) {
|
||||
ASSERT_NE(0u, observed->Stack.Memory.DataSize);
|
||||
ASSERT_NE(0u, observed->Stack.Memory.Rva);
|
||||
ASSERT_NE(observed->Stack.Memory.DataSize, 0u);
|
||||
ASSERT_NE(observed->Stack.Memory.Rva, 0u);
|
||||
ASSERT_GE(file_contents.size(),
|
||||
observed->Stack.Memory.Rva + observed->Stack.Memory.DataSize);
|
||||
*stack = &observed->Stack;
|
||||
} else {
|
||||
EXPECT_EQ(0u, observed->Stack.StartOfMemoryRange);
|
||||
EXPECT_EQ(0u, observed->Stack.Memory.DataSize);
|
||||
EXPECT_EQ(0u, observed->Stack.Memory.Rva);
|
||||
EXPECT_EQ(observed->Stack.StartOfMemoryRange, 0u);
|
||||
EXPECT_EQ(observed->Stack.Memory.DataSize, 0u);
|
||||
EXPECT_EQ(observed->Stack.Memory.Rva, 0u);
|
||||
}
|
||||
|
||||
EXPECT_EQ(expected->ThreadContext.DataSize, observed->ThreadContext.DataSize);
|
||||
ASSERT_NE(0u, observed->ThreadContext.DataSize);
|
||||
ASSERT_NE(0u, observed->ThreadContext.Rva);
|
||||
EXPECT_EQ(observed->ThreadContext.DataSize, expected->ThreadContext.DataSize);
|
||||
ASSERT_NE(observed->ThreadContext.DataSize, 0u);
|
||||
ASSERT_NE(observed->ThreadContext.Rva, 0u);
|
||||
ASSERT_GE(file_contents.size(),
|
||||
observed->ThreadContext.Rva + expected->ThreadContext.DataSize);
|
||||
*context_base = &file_contents[observed->ThreadContext.Rva];
|
||||
@ -166,16 +166,16 @@ TEST(MinidumpThreadWriter, OneThread_x86_NoStack) {
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_THREAD_LIST) + 1 * sizeof(MINIDUMP_THREAD) +
|
||||
1 * sizeof(MinidumpContextX86),
|
||||
string_file.string().size());
|
||||
1 * sizeof(MinidumpContextX86));
|
||||
|
||||
const MINIDUMP_THREAD_LIST* thread_list = nullptr;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetThreadListStream(string_file.string(), &thread_list, nullptr));
|
||||
|
||||
EXPECT_EQ(1u, thread_list->NumberOfThreads);
|
||||
EXPECT_EQ(thread_list->NumberOfThreads, 1u);
|
||||
|
||||
MINIDUMP_THREAD expected = {};
|
||||
expected.ThreadId = kThreadID;
|
||||
@ -236,16 +236,16 @@ TEST(MinidumpThreadWriter, OneThread_AMD64_Stack) {
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_THREAD_LIST) + 1 * sizeof(MINIDUMP_THREAD) +
|
||||
1 * sizeof(MinidumpContextAMD64) + kMemorySize,
|
||||
string_file.string().size());
|
||||
1 * sizeof(MinidumpContextAMD64) + kMemorySize);
|
||||
|
||||
const MINIDUMP_THREAD_LIST* thread_list = nullptr;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetThreadListStream(string_file.string(), &thread_list, nullptr));
|
||||
|
||||
EXPECT_EQ(1u, thread_list->NumberOfThreads);
|
||||
EXPECT_EQ(thread_list->NumberOfThreads, 1u);
|
||||
|
||||
MINIDUMP_THREAD expected = {};
|
||||
expected.ThreadId = kThreadID;
|
||||
@ -369,21 +369,22 @@ TEST(MinidumpThreadWriter, ThreeThreads_x86_MemoryList) {
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + 2 * sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_THREAD_LIST) + 3 * sizeof(MINIDUMP_THREAD) +
|
||||
sizeof(MINIDUMP_MEMORY_LIST) +
|
||||
3 * sizeof(MINIDUMP_MEMORY_DESCRIPTOR) +
|
||||
3 * sizeof(MinidumpContextX86) + kMemorySize0 + kMemorySize1 +
|
||||
kMemorySize2 + 12, // 12 for alignment
|
||||
string_file.string().size());
|
||||
ASSERT_EQ(
|
||||
string_file.string().size(),
|
||||
sizeof(MINIDUMP_HEADER) + 2 * sizeof(MINIDUMP_DIRECTORY) +
|
||||
sizeof(MINIDUMP_THREAD_LIST) + 3 * sizeof(MINIDUMP_THREAD) +
|
||||
sizeof(MINIDUMP_MEMORY_LIST) +
|
||||
3 * sizeof(MINIDUMP_MEMORY_DESCRIPTOR) +
|
||||
3 * sizeof(MinidumpContextX86) + kMemorySize0 + kMemorySize1 +
|
||||
kMemorySize2 + 12); // 12 for alignment
|
||||
|
||||
const MINIDUMP_THREAD_LIST* thread_list = nullptr;
|
||||
const MINIDUMP_MEMORY_LIST* memory_list = nullptr;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetThreadListStream(string_file.string(), &thread_list, &memory_list));
|
||||
|
||||
EXPECT_EQ(3u, thread_list->NumberOfThreads);
|
||||
EXPECT_EQ(3u, memory_list->NumberOfMemoryRanges);
|
||||
EXPECT_EQ(thread_list->NumberOfThreads, 3u);
|
||||
EXPECT_EQ(memory_list->NumberOfMemoryRanges, 3u);
|
||||
|
||||
{
|
||||
SCOPED_TRACE("thread 0");
|
||||
@ -634,8 +635,8 @@ void RunInitializeFromSnapshotTest(bool thread_id_collision) {
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetThreadListStream(string_file.string(), &thread_list, &memory_list));
|
||||
|
||||
ASSERT_EQ(3u, thread_list->NumberOfThreads);
|
||||
ASSERT_EQ(5u, memory_list->NumberOfMemoryRanges);
|
||||
ASSERT_EQ(thread_list->NumberOfThreads, 3u);
|
||||
ASSERT_EQ(memory_list->NumberOfMemoryRanges, 5u);
|
||||
|
||||
size_t memory_index = 0;
|
||||
for (size_t index = 0; index < thread_list->NumberOfThreads; ++index) {
|
||||
@ -678,7 +679,7 @@ void RunInitializeFromSnapshotTest(bool thread_id_collision) {
|
||||
std::string expected_data(kTebSize, static_cast<char>('t' + index));
|
||||
std::string observed_data(&string_file.string()[memory->Memory.Rva],
|
||||
memory->Memory.DataSize);
|
||||
EXPECT_EQ(expected_data, observed_data);
|
||||
EXPECT_EQ(observed_data, expected_data);
|
||||
++memory_index;
|
||||
}
|
||||
}
|
||||
|
@ -31,16 +31,16 @@ void ExpectUnloadedModule(const MINIDUMP_UNLOADED_MODULE* expected,
|
||||
const MINIDUMP_UNLOADED_MODULE* observed,
|
||||
const std::string& file_contents,
|
||||
const std::string& expected_module_name) {
|
||||
EXPECT_EQ(expected->BaseOfImage, observed->BaseOfImage);
|
||||
EXPECT_EQ(expected->SizeOfImage, observed->SizeOfImage);
|
||||
EXPECT_EQ(expected->CheckSum, observed->CheckSum);
|
||||
EXPECT_EQ(expected->TimeDateStamp, observed->TimeDateStamp);
|
||||
EXPECT_NE(0u, observed->ModuleNameRva);
|
||||
EXPECT_EQ(observed->BaseOfImage, expected->BaseOfImage);
|
||||
EXPECT_EQ(observed->SizeOfImage, expected->SizeOfImage);
|
||||
EXPECT_EQ(observed->CheckSum, expected->CheckSum);
|
||||
EXPECT_EQ(observed->TimeDateStamp, expected->TimeDateStamp);
|
||||
EXPECT_NE(observed->ModuleNameRva, 0u);
|
||||
base::string16 observed_module_name_utf16 =
|
||||
MinidumpStringAtRVAAsString(file_contents, observed->ModuleNameRva);
|
||||
base::string16 expected_module_name_utf16 =
|
||||
base::UTF8ToUTF16(expected_module_name);
|
||||
EXPECT_EQ(expected_module_name_utf16, observed_module_name_utf16);
|
||||
EXPECT_EQ(observed_module_name_utf16, expected_module_name_utf16);
|
||||
}
|
||||
|
||||
void GetUnloadedModuleListStream(
|
||||
@ -60,8 +60,8 @@ void GetUnloadedModuleListStream(
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeUnloadedModuleList, directory[0].StreamType);
|
||||
EXPECT_EQ(kUnloadedModuleListStreamOffset, directory[0].Location.Rva);
|
||||
ASSERT_EQ(directory[0].StreamType, kMinidumpStreamTypeUnloadedModuleList);
|
||||
EXPECT_EQ(directory[0].Location.Rva, kUnloadedModuleListStreamOffset);
|
||||
|
||||
*unloaded_module_list =
|
||||
MinidumpWritableAtLocationDescriptor<MINIDUMP_UNLOADED_MODULE_LIST>(
|
||||
@ -97,7 +97,7 @@ TEST(MinidumpUnloadedModuleWriter, EmptyModule) {
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetUnloadedModuleListStream(string_file.string(), &unloaded_module_list));
|
||||
|
||||
EXPECT_EQ(1u, unloaded_module_list->NumberOfEntries);
|
||||
EXPECT_EQ(unloaded_module_list->NumberOfEntries, 1u);
|
||||
|
||||
MINIDUMP_UNLOADED_MODULE expected = {};
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
@ -144,7 +144,7 @@ TEST(MinidumpUnloadedModuleWriter, OneModule) {
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GetUnloadedModuleListStream(string_file.string(), &unloaded_module_list));
|
||||
|
||||
EXPECT_EQ(1u, unloaded_module_list->NumberOfEntries);
|
||||
EXPECT_EQ(unloaded_module_list->NumberOfEntries, 1u);
|
||||
|
||||
MINIDUMP_UNLOADED_MODULE expected = {};
|
||||
expected.BaseOfImage = kModuleBase;
|
||||
|
@ -17,12 +17,8 @@
|
||||
namespace crashpad {
|
||||
|
||||
MinidumpUserExtensionStreamDataSource::MinidumpUserExtensionStreamDataSource(
|
||||
uint32_t stream_type,
|
||||
const void* buffer,
|
||||
size_t buffer_size)
|
||||
: stream_type_(static_cast<MinidumpStreamType>(stream_type)),
|
||||
buffer_(buffer),
|
||||
buffer_size_(buffer_size) {}
|
||||
uint32_t stream_type)
|
||||
: stream_type_(static_cast<MinidumpStreamType>(stream_type)) {}
|
||||
|
||||
MinidumpUserExtensionStreamDataSource::
|
||||
~MinidumpUserExtensionStreamDataSource() {}
|
||||
|
@ -27,25 +27,54 @@ namespace crashpad {
|
||||
//! \brief Describes a user extension data stream in a minidump.
|
||||
class MinidumpUserExtensionStreamDataSource {
|
||||
public:
|
||||
//! \brief An interface implemented by readers of
|
||||
//! MinidumpUserExtensionStreamDataSource.
|
||||
class Delegate {
|
||||
public:
|
||||
//! \brief Called by MinidumpUserExtensionStreamDataSource::Read() to
|
||||
//! provide data requested by a call to that method.
|
||||
//!
|
||||
//! \param[in] data A pointer to the data that was read. The callee does not
|
||||
//! take ownership of this data. This data is only valid for the
|
||||
//! duration of the call to this method. This parameter may be `nullptr`
|
||||
//! if \a size is `0`.
|
||||
//! \param[in] size The size of the data that was read.
|
||||
//!
|
||||
//! \return `true` on success, `false` on failure.
|
||||
//! MinidumpUserExtensionStreamDataSource::ReadStreamData() will use
|
||||
//! this as its own return value.
|
||||
virtual bool ExtensionStreamDataSourceRead(const void* data,
|
||||
size_t size) = 0;
|
||||
|
||||
protected:
|
||||
~Delegate() {}
|
||||
};
|
||||
|
||||
//! \brief Constructs a MinidumpUserExtensionStreamDataSource.
|
||||
//!
|
||||
//! \param[in] stream_type The type of the user extension stream.
|
||||
//! \param[in] buffer Points to the data for this stream. \a buffer is not
|
||||
//! owned, and must outlive the use of this object.
|
||||
//! \param[in] buffer_size The length of data in \a buffer.
|
||||
MinidumpUserExtensionStreamDataSource(uint32_t stream_type,
|
||||
const void* buffer,
|
||||
size_t buffer_size);
|
||||
~MinidumpUserExtensionStreamDataSource();
|
||||
explicit MinidumpUserExtensionStreamDataSource(uint32_t stream_type);
|
||||
virtual ~MinidumpUserExtensionStreamDataSource();
|
||||
|
||||
MinidumpStreamType stream_type() const { return stream_type_; }
|
||||
const void* buffer() const { return buffer_; }
|
||||
size_t buffer_size() const { return buffer_size_; }
|
||||
|
||||
//! \brief The size of this data stream.
|
||||
virtual size_t StreamDataSize() = 0;
|
||||
|
||||
//! \brief Calls Delegate::UserStreamDataSourceRead(), providing it with
|
||||
//! the stream data.
|
||||
//!
|
||||
//! Implementations do not necessarily compute the stream data prior to
|
||||
//! this method being called. The stream data may be computed or loaded
|
||||
//! lazily and may be discarded after being passed to the delegate.
|
||||
//!
|
||||
//! \return `false` on failure, otherwise, the return value of
|
||||
//! Delegate::ExtensionStreamDataSourceRead(), which should be `true` on
|
||||
//! success and `false` on failure.
|
||||
virtual bool ReadStreamData(Delegate* delegate) = 0;
|
||||
|
||||
private:
|
||||
MinidumpStreamType stream_type_;
|
||||
const void* buffer_; // weak
|
||||
size_t buffer_size_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MinidumpUserExtensionStreamDataSource);
|
||||
};
|
||||
|
@ -56,22 +56,32 @@ class MinidumpUserStreamWriter::SnapshotContentsWriter final
|
||||
DISALLOW_COPY_AND_ASSIGN(SnapshotContentsWriter);
|
||||
};
|
||||
|
||||
class MinidumpUserStreamWriter::BufferContentsWriter final
|
||||
: public MinidumpUserStreamWriter::ContentsWriter {
|
||||
class MinidumpUserStreamWriter::ExtensionStreamContentsWriter final
|
||||
: public MinidumpUserStreamWriter::ContentsWriter,
|
||||
public MinidumpUserExtensionStreamDataSource::Delegate {
|
||||
public:
|
||||
BufferContentsWriter(const void* buffer, size_t buffer_size)
|
||||
: buffer_(buffer), buffer_size_(buffer_size) {}
|
||||
explicit ExtensionStreamContentsWriter(
|
||||
std::unique_ptr<MinidumpUserExtensionStreamDataSource> data_source)
|
||||
: data_source_(std::move(data_source)), writer_(nullptr) {}
|
||||
|
||||
bool WriteContents(FileWriterInterface* writer) override {
|
||||
return writer->Write(buffer_, buffer_size_);
|
||||
DCHECK(!writer_);
|
||||
|
||||
writer_ = writer;
|
||||
return data_source_->ReadStreamData(this);
|
||||
}
|
||||
|
||||
size_t GetSize() const override { return data_source_->StreamDataSize(); }
|
||||
|
||||
bool ExtensionStreamDataSourceRead(const void* data, size_t size) override {
|
||||
return writer_->Write(data, size);
|
||||
}
|
||||
size_t GetSize() const override { return buffer_size_; }
|
||||
|
||||
private:
|
||||
const void* buffer_;
|
||||
size_t buffer_size_;
|
||||
std::unique_ptr<MinidumpUserExtensionStreamDataSource> data_source_;
|
||||
FileWriterInterface* writer_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BufferContentsWriter);
|
||||
DISALLOW_COPY_AND_ASSIGN(ExtensionStreamContentsWriter);
|
||||
};
|
||||
|
||||
MinidumpUserStreamWriter::MinidumpUserStreamWriter() : stream_type_() {}
|
||||
@ -89,16 +99,14 @@ void MinidumpUserStreamWriter::InitializeFromSnapshot(
|
||||
base::WrapUnique(new SnapshotContentsWriter(stream->memory()));
|
||||
}
|
||||
|
||||
void MinidumpUserStreamWriter::InitializeFromBuffer(
|
||||
MinidumpStreamType stream_type,
|
||||
const void* buffer,
|
||||
size_t buffer_size) {
|
||||
void MinidumpUserStreamWriter::InitializeFromUserExtensionStream(
|
||||
std::unique_ptr<MinidumpUserExtensionStreamDataSource> data_source) {
|
||||
DCHECK_EQ(state(), kStateMutable);
|
||||
DCHECK(!contents_writer_.get());
|
||||
|
||||
stream_type_ = stream_type;
|
||||
contents_writer_ =
|
||||
base::WrapUnique(new BufferContentsWriter(buffer, buffer_size));
|
||||
stream_type_ = data_source->stream_type();
|
||||
contents_writer_ = base::WrapUnique(
|
||||
new ExtensionStreamContentsWriter(std::move(data_source)));
|
||||
}
|
||||
|
||||
bool MinidumpUserStreamWriter::Freeze() {
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "minidump/minidump_extensions.h"
|
||||
#include "minidump/minidump_stream_writer.h"
|
||||
#include "minidump/minidump_writable.h"
|
||||
#include "minidump/minidump_user_extension_stream_data_source.h"
|
||||
#include "snapshot/module_snapshot.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -42,17 +43,13 @@ class MinidumpUserStreamWriter final : public internal::MinidumpStreamWriter {
|
||||
//! \note Valid in #kStateMutable.
|
||||
void InitializeFromSnapshot(const UserMinidumpStream* stream);
|
||||
|
||||
//! \brief Initializes a MINIDUMP_USER_STREAM based on \a stream_type,
|
||||
//! \a buffer and \a buffer_size.
|
||||
//! \brief Initializes a MINIDUMP_USER_STREAM based on \a data_source.
|
||||
//!
|
||||
//! \param[in] stream_type The type of the stream.
|
||||
//! \param[in] buffer The data for the stream.
|
||||
//! \param[in] buffer_size The length of \a buffer, and the resulting stream.
|
||||
//! \param[in] data_source The content and type of the stream.
|
||||
//!
|
||||
//! \note Valid in #kStateMutable.
|
||||
void InitializeFromBuffer(MinidumpStreamType stream_type,
|
||||
const void* buffer,
|
||||
size_t buffer_size);
|
||||
void InitializeFromUserExtensionStream(
|
||||
std::unique_ptr<MinidumpUserExtensionStreamDataSource> data_source);
|
||||
|
||||
protected:
|
||||
// MinidumpWritable:
|
||||
@ -67,7 +64,7 @@ class MinidumpUserStreamWriter final : public internal::MinidumpStreamWriter {
|
||||
private:
|
||||
class ContentsWriter;
|
||||
class SnapshotContentsWriter;
|
||||
class BufferContentsWriter;
|
||||
class ExtensionStreamContentsWriter;
|
||||
|
||||
std::unique_ptr<ContentsWriter> contents_writer_;
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "minidump/minidump_file_writer.h"
|
||||
#include "minidump/test/minidump_file_writer_test_util.h"
|
||||
#include "minidump/test/minidump_user_extension_stream_util.h"
|
||||
#include "minidump/test/minidump_writable_test_util.h"
|
||||
#include "snapshot/test/test_memory_snapshot.h"
|
||||
#include "util/file/string_file.h"
|
||||
@ -46,9 +47,9 @@ void GetUserStream(const std::string& file_contents,
|
||||
|
||||
const size_t kDirectoryIndex = 0;
|
||||
|
||||
ASSERT_EQ(stream_type, directory[kDirectoryIndex].StreamType);
|
||||
EXPECT_EQ(kUserStreamOffset, directory[kDirectoryIndex].Location.Rva);
|
||||
EXPECT_EQ(stream_size, directory[kDirectoryIndex].Location.DataSize);
|
||||
ASSERT_EQ(directory[kDirectoryIndex].StreamType, stream_type);
|
||||
EXPECT_EQ(directory[kDirectoryIndex].Location.Rva, kUserStreamOffset);
|
||||
EXPECT_EQ(directory[kDirectoryIndex].Location.DataSize, stream_size);
|
||||
*user_stream_location = directory[kDirectoryIndex].Location;
|
||||
}
|
||||
|
||||
@ -66,25 +67,27 @@ TEST(MinidumpUserStreamWriter, InitializeFromSnapshotNoData) {
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY),
|
||||
string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY));
|
||||
|
||||
MINIDUMP_LOCATION_DESCRIPTOR user_stream_location;
|
||||
ASSERT_NO_FATAL_FAILURE(GetUserStream(
|
||||
string_file.string(), &user_stream_location, kTestStreamId, 0u));
|
||||
}
|
||||
|
||||
TEST(MinidumpUserStreamWriter, InitializeFromBufferNoData) {
|
||||
TEST(MinidumpUserStreamWriter, InitializeFromUserExtensionStreamNoData) {
|
||||
MinidumpFileWriter minidump_file_writer;
|
||||
auto data_source = base::WrapUnique(
|
||||
new test::BufferExtensionStreamDataSource(kTestStreamId, nullptr, 0));
|
||||
auto user_stream_writer = base::WrapUnique(new MinidumpUserStreamWriter());
|
||||
user_stream_writer->InitializeFromBuffer(kTestStreamId, nullptr, 0);
|
||||
user_stream_writer->InitializeFromUserExtensionStream(std::move(data_source));
|
||||
minidump_file_writer.AddStream(std::move(user_stream_writer));
|
||||
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY),
|
||||
string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY));
|
||||
|
||||
MINIDUMP_LOCATION_DESCRIPTOR user_stream_location;
|
||||
ASSERT_NO_FATAL_FAILURE(GetUserStream(
|
||||
@ -108,39 +111,40 @@ TEST(MinidumpUserStreamWriter, InitializeFromSnapshotOneStream) {
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + kStreamSize,
|
||||
string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + kStreamSize);
|
||||
|
||||
MINIDUMP_LOCATION_DESCRIPTOR user_stream_location = {};
|
||||
ASSERT_NO_FATAL_FAILURE(GetUserStream(
|
||||
string_file.string(), &user_stream_location, kTestStreamId, kStreamSize));
|
||||
const std::string stream_data = string_file.string().substr(
|
||||
user_stream_location.Rva, user_stream_location.DataSize);
|
||||
EXPECT_EQ(std::string(kStreamSize, 'c'), stream_data);
|
||||
EXPECT_EQ(stream_data, std::string(kStreamSize, 'c'));
|
||||
}
|
||||
|
||||
TEST(MinidumpUserStreamWriter, InitializeFromBufferOneStream) {
|
||||
MinidumpFileWriter minidump_file_writer;
|
||||
auto user_stream_writer = base::WrapUnique(new MinidumpUserStreamWriter());
|
||||
|
||||
const size_t kStreamSize = 128;
|
||||
std::vector<uint8_t> data(kStreamSize, 'c');
|
||||
user_stream_writer->InitializeFromBuffer(
|
||||
kTestStreamId, &data[0], data.size());
|
||||
auto data_source = base::WrapUnique(new test::BufferExtensionStreamDataSource(
|
||||
kTestStreamId, &data[0], data.size()));
|
||||
auto user_stream_writer = base::WrapUnique(new MinidumpUserStreamWriter());
|
||||
user_stream_writer->InitializeFromUserExtensionStream(std::move(data_source));
|
||||
minidump_file_writer.AddStream(std::move(user_stream_writer));
|
||||
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + kStreamSize,
|
||||
string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + kStreamSize);
|
||||
|
||||
MINIDUMP_LOCATION_DESCRIPTOR user_stream_location = {};
|
||||
ASSERT_NO_FATAL_FAILURE(GetUserStream(
|
||||
string_file.string(), &user_stream_location, kTestStreamId, kStreamSize));
|
||||
const std::string stream_data = string_file.string().substr(
|
||||
user_stream_location.Rva, user_stream_location.DataSize);
|
||||
EXPECT_EQ(std::string(kStreamSize, 'c'), stream_data);
|
||||
EXPECT_EQ(stream_data, std::string(kStreamSize, 'c'));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -53,7 +53,7 @@ class BaseTestMinidumpWritable : public crashpad::internal::MinidumpWritable {
|
||||
|
||||
void Verify() {
|
||||
verified_ = true;
|
||||
EXPECT_EQ(kStateWritten, state());
|
||||
EXPECT_EQ(state(), kStateWritten);
|
||||
for (BaseTestMinidumpWritable* child : children_) {
|
||||
child->Verify();
|
||||
}
|
||||
@ -61,10 +61,10 @@ class BaseTestMinidumpWritable : public crashpad::internal::MinidumpWritable {
|
||||
|
||||
protected:
|
||||
bool Freeze() override {
|
||||
EXPECT_EQ(kStateMutable, state());
|
||||
EXPECT_EQ(state(), kStateMutable);
|
||||
bool rv = MinidumpWritable::Freeze();
|
||||
EXPECT_TRUE(rv);
|
||||
EXPECT_EQ(kStateFrozen, state());
|
||||
EXPECT_EQ(state(), kStateFrozen);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ class BaseTestMinidumpWritable : public crashpad::internal::MinidumpWritable {
|
||||
}
|
||||
|
||||
bool WillWriteAtOffsetImpl(FileOffset offset) override {
|
||||
EXPECT_EQ(state(), kStateFrozen);
|
||||
EXPECT_EQ(kStateFrozen, state());
|
||||
expected_offset_ = offset;
|
||||
bool rv = MinidumpWritable::WillWriteAtOffsetImpl(offset);
|
||||
EXPECT_TRUE(rv);
|
||||
@ -98,8 +98,8 @@ class BaseTestMinidumpWritable : public crashpad::internal::MinidumpWritable {
|
||||
}
|
||||
|
||||
bool WriteObject(FileWriterInterface* file_writer) override {
|
||||
EXPECT_EQ(state(), kStateWritable);
|
||||
EXPECT_EQ(expected_offset_, file_writer->Seek(0, SEEK_CUR));
|
||||
EXPECT_EQ(kStateWritable, state());
|
||||
EXPECT_EQ(file_writer->Seek(0, SEEK_CUR), expected_offset_);
|
||||
|
||||
// Subclasses must override this.
|
||||
return false;
|
||||
@ -162,8 +162,8 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
TestStringMinidumpWritable string_writable;
|
||||
string_writable.SetData("a");
|
||||
EXPECT_TRUE(string_writable.WriteEverything(&string_file));
|
||||
EXPECT_EQ(1u, string_file.string().size());
|
||||
EXPECT_EQ("a", string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 1u);
|
||||
EXPECT_EQ(string_file.string(), "a");
|
||||
string_writable.Verify();
|
||||
}
|
||||
|
||||
@ -176,8 +176,8 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
child.SetData("c");
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(5u, string_file.string().size());
|
||||
EXPECT_EQ(std::string("b\0\0\0c", 5), string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 5u);
|
||||
EXPECT_EQ(string_file.string(), std::string("b\0\0\0c", 5));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -190,8 +190,8 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
child.SetData("f");
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(5u, string_file.string().size());
|
||||
EXPECT_EQ(std::string("de\0\0f", 5), string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 5u);
|
||||
EXPECT_EQ(string_file.string(), std::string("de\0\0f", 5));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -204,8 +204,8 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
child.SetData("j");
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(5u, string_file.string().size());
|
||||
EXPECT_EQ(std::string("ghi\0j", 5), string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 5u);
|
||||
EXPECT_EQ(string_file.string(), std::string("ghi\0j", 5));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -218,8 +218,8 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
child.SetData("o");
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(5u, string_file.string().size());
|
||||
EXPECT_EQ("klmno", string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 5u);
|
||||
EXPECT_EQ(string_file.string(), "klmno");
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -232,8 +232,8 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
child.SetData("u");
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(9u, string_file.string().size());
|
||||
EXPECT_EQ(std::string("pqrst\0\0\0u", 9), string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 9u);
|
||||
EXPECT_EQ(string_file.string(), std::string("pqrst\0\0\0u", 9));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -249,8 +249,9 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
child_1.SetData("child_1");
|
||||
parent.AddChild(&child_1);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(23u, string_file.string().size());
|
||||
EXPECT_EQ(std::string("parent\0\0child_0\0child_1", 23), string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 23u);
|
||||
EXPECT_EQ(string_file.string(),
|
||||
std::string("parent\0\0child_0\0child_1", 23));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -266,9 +267,9 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
grandchild.SetData("grandchild");
|
||||
child.AddChild(&grandchild);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(26u, string_file.string().size());
|
||||
EXPECT_EQ(std::string("parent\0\0child\0\0\0grandchild", 26),
|
||||
string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 26u);
|
||||
EXPECT_EQ(string_file.string(),
|
||||
std::string("parent\0\0child\0\0\0grandchild", 26));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -283,8 +284,8 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
grandchild.SetData("grandchild");
|
||||
child.AddChild(&grandchild);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(18u, string_file.string().size());
|
||||
EXPECT_EQ(std::string("child\0\0\0grandchild", 18), string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 18u);
|
||||
EXPECT_EQ(string_file.string(), std::string("child\0\0\0grandchild", 18));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -299,8 +300,8 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
grandchild.SetData("grandchild");
|
||||
child.AddChild(&grandchild);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(18u, string_file.string().size());
|
||||
EXPECT_EQ(std::string("parent\0\0grandchild", 18), string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 18u);
|
||||
EXPECT_EQ(string_file.string(), std::string("parent\0\0grandchild", 18));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -315,8 +316,8 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
TestStringMinidumpWritable grandchild;
|
||||
child.AddChild(&grandchild);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(13u, string_file.string().size());
|
||||
EXPECT_EQ(std::string("parent\0\0child", 13), string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 13u);
|
||||
EXPECT_EQ(string_file.string(), std::string("parent\0\0child", 13));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -333,9 +334,9 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
grandchild.SetPhaseLate();
|
||||
child.AddChild(&grandchild);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(26u, string_file.string().size());
|
||||
EXPECT_EQ(std::string("parent\0\0child\0\0\0grandchild", 26),
|
||||
string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 26u);
|
||||
EXPECT_EQ(string_file.string(),
|
||||
std::string("parent\0\0child\0\0\0grandchild", 26));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -352,9 +353,9 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
grandchild.SetData("grandchild");
|
||||
child.AddChild(&grandchild);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(25u, string_file.string().size());
|
||||
EXPECT_EQ(std::string("parent\0\0grandchild\0\0child", 25),
|
||||
string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 25u);
|
||||
EXPECT_EQ(string_file.string(),
|
||||
std::string("parent\0\0grandchild\0\0child", 25));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -382,9 +383,9 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
grandchild_11.SetData("G11");
|
||||
child_1.AddChild(&grandchild_11);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(27u, string_file.string().size());
|
||||
EXPECT_EQ(std::string("P..\0C0.\0G00\0G01\0C1.\0G10\0G11", 27),
|
||||
string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 27u);
|
||||
EXPECT_EQ(string_file.string(),
|
||||
std::string("P..\0C0.\0G00\0G01\0C1.\0G10\0G11", 27));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -413,9 +414,9 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
grandchild_11.SetData("G11");
|
||||
child_1.AddChild(&grandchild_11);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(27u, string_file.string().size());
|
||||
EXPECT_EQ(std::string("P..\0G00\0G01\0C1.\0G10\0G11\0C0.", 27),
|
||||
string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 27u);
|
||||
EXPECT_EQ(string_file.string(),
|
||||
std::string("P..\0G00\0G01\0C1.\0G10\0G11\0C0.", 27));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -445,9 +446,9 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
grandchild_11.SetData("G11");
|
||||
child_1.AddChild(&grandchild_11);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(27u, string_file.string().size());
|
||||
EXPECT_EQ(std::string("P..\0C0.\0C1.\0G10\0G11\0G00\0G01", 27),
|
||||
string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 27u);
|
||||
EXPECT_EQ(string_file.string(),
|
||||
std::string("P..\0C0.\0C1.\0G10\0G11\0G00\0G01", 27));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -461,8 +462,8 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
child.SetAlignment(1);
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(2u, string_file.string().size());
|
||||
EXPECT_EQ("pc", string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 2u);
|
||||
EXPECT_EQ(string_file.string(), "pc");
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -476,8 +477,8 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
child.SetAlignment(2);
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
EXPECT_EQ(3u, string_file.string().size());
|
||||
EXPECT_EQ(std::string("p\0c", 3), string_file.string());
|
||||
EXPECT_EQ(string_file.string().size(), 3u);
|
||||
EXPECT_EQ(string_file.string(), std::string("p\0c", 3));
|
||||
parent.Verify();
|
||||
}
|
||||
}
|
||||
@ -521,8 +522,8 @@ TEST(MinidumpWritable, RVA) {
|
||||
TestRVAMinidumpWritable rva_writable;
|
||||
EXPECT_TRUE(rva_writable.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(RVA), string_file.string().size());
|
||||
EXPECT_EQ(0 * sizeof(RVA), RVAAtIndex(string_file.string(), 0));
|
||||
ASSERT_EQ(string_file.string().size(), sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 0 * sizeof(RVA));
|
||||
rva_writable.Verify();
|
||||
}
|
||||
|
||||
@ -533,8 +534,8 @@ TEST(MinidumpWritable, RVA) {
|
||||
rva_writable.SetRVA(&rva_writable);
|
||||
EXPECT_TRUE(rva_writable.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(sizeof(RVA), string_file.string().size());
|
||||
EXPECT_EQ(0 * sizeof(RVA), RVAAtIndex(string_file.string(), 0));
|
||||
ASSERT_EQ(string_file.string().size(), sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 0 * sizeof(RVA));
|
||||
rva_writable.Verify();
|
||||
}
|
||||
|
||||
@ -548,9 +549,9 @@ TEST(MinidumpWritable, RVA) {
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(2 * sizeof(RVA), string_file.string().size());
|
||||
EXPECT_EQ(0 * sizeof(RVA), RVAAtIndex(string_file.string(), 0));
|
||||
EXPECT_EQ(1 * sizeof(RVA), RVAAtIndex(string_file.string(), 1));
|
||||
ASSERT_EQ(string_file.string().size(), 2 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 0 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 1), 1 * sizeof(RVA));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -563,9 +564,9 @@ TEST(MinidumpWritable, RVA) {
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(2 * sizeof(RVA), string_file.string().size());
|
||||
EXPECT_EQ(1 * sizeof(RVA), RVAAtIndex(string_file.string(), 0));
|
||||
EXPECT_EQ(0 * sizeof(RVA), RVAAtIndex(string_file.string(), 1));
|
||||
ASSERT_EQ(string_file.string().size(), 2 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 1 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 1), 0 * sizeof(RVA));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -579,9 +580,9 @@ TEST(MinidumpWritable, RVA) {
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(2 * sizeof(RVA), string_file.string().size());
|
||||
EXPECT_EQ(1 * sizeof(RVA), RVAAtIndex(string_file.string(), 0));
|
||||
EXPECT_EQ(0 * sizeof(RVA), RVAAtIndex(string_file.string(), 1));
|
||||
ASSERT_EQ(string_file.string().size(), 2 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 1 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 1), 0 * sizeof(RVA));
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -603,12 +604,12 @@ TEST(MinidumpWritable, RVA) {
|
||||
child.AddChild(&grandchild_2);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(5 * sizeof(RVA), string_file.string().size());
|
||||
EXPECT_EQ(1 * sizeof(RVA), RVAAtIndex(string_file.string(), 0));
|
||||
EXPECT_EQ(0 * sizeof(RVA), RVAAtIndex(string_file.string(), 1));
|
||||
EXPECT_EQ(1 * sizeof(RVA), RVAAtIndex(string_file.string(), 2));
|
||||
EXPECT_EQ(1 * sizeof(RVA), RVAAtIndex(string_file.string(), 3));
|
||||
EXPECT_EQ(1 * sizeof(RVA), RVAAtIndex(string_file.string(), 4));
|
||||
ASSERT_EQ(string_file.string().size(), 5 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 1 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 1), 0 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 2), 1 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 3), 1 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 4), 1 * sizeof(RVA));
|
||||
parent.Verify();
|
||||
}
|
||||
}
|
||||
@ -674,10 +675,10 @@ TEST(MinidumpWritable, LocationDescriptor) {
|
||||
TestLocationDescriptorMinidumpWritable location_descriptor_writable;
|
||||
EXPECT_TRUE(location_descriptor_writable.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(9u, string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), 9u);
|
||||
const LocationDescriptorAndData* ldd = LDDAtIndex(string_file.string(), 0);
|
||||
EXPECT_EQ(0u, ldd->location_descriptor.DataSize);
|
||||
EXPECT_EQ(0u, ldd->location_descriptor.Rva);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 0u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 0u);
|
||||
location_descriptor_writable.Verify();
|
||||
}
|
||||
|
||||
@ -689,10 +690,10 @@ TEST(MinidumpWritable, LocationDescriptor) {
|
||||
&location_descriptor_writable);
|
||||
EXPECT_TRUE(location_descriptor_writable.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(9u, string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), 9u);
|
||||
const LocationDescriptorAndData* ldd = LDDAtIndex(string_file.string(), 0);
|
||||
EXPECT_EQ(9u, ldd->location_descriptor.DataSize);
|
||||
EXPECT_EQ(0u, ldd->location_descriptor.Rva);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 9u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 0u);
|
||||
location_descriptor_writable.Verify();
|
||||
}
|
||||
|
||||
@ -705,10 +706,10 @@ TEST(MinidumpWritable, LocationDescriptor) {
|
||||
location_descriptor_writable.SetString("zz");
|
||||
EXPECT_TRUE(location_descriptor_writable.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(11u, string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), 11u);
|
||||
const LocationDescriptorAndData* ldd = LDDAtIndex(string_file.string(), 0);
|
||||
EXPECT_EQ(11u, ldd->location_descriptor.DataSize);
|
||||
EXPECT_EQ(0u, ldd->location_descriptor.Rva);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 11u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 0u);
|
||||
EXPECT_STREQ("zz", ldd->string);
|
||||
location_descriptor_writable.Verify();
|
||||
}
|
||||
@ -725,14 +726,14 @@ TEST(MinidumpWritable, LocationDescriptor) {
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(22u, string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), 22u);
|
||||
const LocationDescriptorAndData* ldd = LDDAtIndex(string_file.string(), 0);
|
||||
EXPECT_EQ(11u, ldd->location_descriptor.DataSize);
|
||||
EXPECT_EQ(0u, ldd->location_descriptor.Rva);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 11u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 0u);
|
||||
EXPECT_STREQ("yy", ldd->string);
|
||||
ldd = LDDAtIndex(string_file.string(), 12);
|
||||
EXPECT_EQ(10u, ldd->location_descriptor.DataSize);
|
||||
EXPECT_EQ(12u, ldd->location_descriptor.Rva);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 10u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 12u);
|
||||
EXPECT_STREQ("x", ldd->string);
|
||||
parent.Verify();
|
||||
}
|
||||
@ -748,14 +749,14 @@ TEST(MinidumpWritable, LocationDescriptor) {
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(23u, string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), 23u);
|
||||
const LocationDescriptorAndData* ldd = LDDAtIndex(string_file.string(), 0);
|
||||
EXPECT_EQ(11u, ldd->location_descriptor.DataSize);
|
||||
EXPECT_EQ(12u, ldd->location_descriptor.Rva);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 11u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 12u);
|
||||
EXPECT_STREQ("www", ldd->string);
|
||||
ldd = LDDAtIndex(string_file.string(), 12);
|
||||
EXPECT_EQ(0u, ldd->location_descriptor.DataSize);
|
||||
EXPECT_EQ(0u, ldd->location_descriptor.Rva);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 0u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 0u);
|
||||
EXPECT_STREQ("vv", ldd->string);
|
||||
parent.Verify();
|
||||
}
|
||||
@ -772,14 +773,14 @@ TEST(MinidumpWritable, LocationDescriptor) {
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(29u, string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), 29u);
|
||||
const LocationDescriptorAndData* ldd = LDDAtIndex(string_file.string(), 0);
|
||||
EXPECT_EQ(13u, ldd->location_descriptor.DataSize);
|
||||
EXPECT_EQ(16u, ldd->location_descriptor.Rva);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 13u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 16u);
|
||||
EXPECT_STREQ("uuuu", ldd->string);
|
||||
ldd = LDDAtIndex(string_file.string(), 16);
|
||||
EXPECT_EQ(13u, ldd->location_descriptor.DataSize);
|
||||
EXPECT_EQ(0u, ldd->location_descriptor.Rva);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 13u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 0u);
|
||||
EXPECT_STREQ("tttt", ldd->string);
|
||||
parent.Verify();
|
||||
}
|
||||
@ -807,26 +808,26 @@ TEST(MinidumpWritable, LocationDescriptor) {
|
||||
child.AddChild(&grandchild_2);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(58u, string_file.string().size());
|
||||
ASSERT_EQ(string_file.string().size(), 58u);
|
||||
const LocationDescriptorAndData* ldd = LDDAtIndex(string_file.string(), 0);
|
||||
EXPECT_EQ(10u, ldd->location_descriptor.DataSize);
|
||||
EXPECT_EQ(12u, ldd->location_descriptor.Rva);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 10u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 12u);
|
||||
EXPECT_STREQ("s", ldd->string);
|
||||
ldd = LDDAtIndex(string_file.string(), 12);
|
||||
EXPECT_EQ(0u, ldd->location_descriptor.DataSize);
|
||||
EXPECT_EQ(0u, ldd->location_descriptor.Rva);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 0u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 0u);
|
||||
EXPECT_STREQ("r", ldd->string);
|
||||
ldd = LDDAtIndex(string_file.string(), 24);
|
||||
EXPECT_EQ(10u, ldd->location_descriptor.DataSize);
|
||||
EXPECT_EQ(12u, ldd->location_descriptor.Rva);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 10u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 12u);
|
||||
EXPECT_STREQ("q", ldd->string);
|
||||
ldd = LDDAtIndex(string_file.string(), 36);
|
||||
EXPECT_EQ(10u, ldd->location_descriptor.DataSize);
|
||||
EXPECT_EQ(12u, ldd->location_descriptor.Rva);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 10u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 12u);
|
||||
EXPECT_STREQ("p", ldd->string);
|
||||
ldd = LDDAtIndex(string_file.string(), 48);
|
||||
EXPECT_EQ(10u, ldd->location_descriptor.DataSize);
|
||||
EXPECT_EQ(12u, ldd->location_descriptor.Rva);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 10u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 12u);
|
||||
EXPECT_STREQ("o", ldd->string);
|
||||
parent.Verify();
|
||||
}
|
||||
|
@ -149,48 +149,48 @@ namespace {
|
||||
template <typename FxsaveType>
|
||||
void ExpectMinidumpContextFxsave(const FxsaveType* expected,
|
||||
const FxsaveType* observed) {
|
||||
EXPECT_EQ(expected->fcw, observed->fcw);
|
||||
EXPECT_EQ(expected->fsw, observed->fsw);
|
||||
EXPECT_EQ(expected->ftw, observed->ftw);
|
||||
EXPECT_EQ(expected->reserved_1, observed->reserved_1);
|
||||
EXPECT_EQ(expected->fop, observed->fop);
|
||||
EXPECT_EQ(expected->fpu_ip, observed->fpu_ip);
|
||||
EXPECT_EQ(expected->fpu_cs, observed->fpu_cs);
|
||||
EXPECT_EQ(expected->reserved_2, observed->reserved_2);
|
||||
EXPECT_EQ(expected->fpu_dp, observed->fpu_dp);
|
||||
EXPECT_EQ(expected->fpu_ds, observed->fpu_ds);
|
||||
EXPECT_EQ(expected->reserved_3, observed->reserved_3);
|
||||
EXPECT_EQ(expected->mxcsr, observed->mxcsr);
|
||||
EXPECT_EQ(expected->mxcsr_mask, observed->mxcsr_mask);
|
||||
EXPECT_EQ(observed->fcw, expected->fcw);
|
||||
EXPECT_EQ(observed->fsw, expected->fsw);
|
||||
EXPECT_EQ(observed->ftw, expected->ftw);
|
||||
EXPECT_EQ(observed->reserved_1, expected->reserved_1);
|
||||
EXPECT_EQ(observed->fop, expected->fop);
|
||||
EXPECT_EQ(observed->fpu_ip, expected->fpu_ip);
|
||||
EXPECT_EQ(observed->fpu_cs, expected->fpu_cs);
|
||||
EXPECT_EQ(observed->reserved_2, expected->reserved_2);
|
||||
EXPECT_EQ(observed->fpu_dp, expected->fpu_dp);
|
||||
EXPECT_EQ(observed->fpu_ds, expected->fpu_ds);
|
||||
EXPECT_EQ(observed->reserved_3, expected->reserved_3);
|
||||
EXPECT_EQ(observed->mxcsr, expected->mxcsr);
|
||||
EXPECT_EQ(observed->mxcsr_mask, expected->mxcsr_mask);
|
||||
for (size_t st_mm_index = 0;
|
||||
st_mm_index < arraysize(expected->st_mm);
|
||||
++st_mm_index) {
|
||||
SCOPED_TRACE(base::StringPrintf("st_mm_index %" PRIuS, st_mm_index));
|
||||
EXPECT_EQ(BytesToHexString(expected->st_mm[st_mm_index].st,
|
||||
arraysize(expected->st_mm[st_mm_index].st)),
|
||||
BytesToHexString(observed->st_mm[st_mm_index].st,
|
||||
arraysize(observed->st_mm[st_mm_index].st)));
|
||||
EXPECT_EQ(BytesToHexString(observed->st_mm[st_mm_index].st,
|
||||
arraysize(observed->st_mm[st_mm_index].st)),
|
||||
BytesToHexString(expected->st_mm[st_mm_index].st,
|
||||
arraysize(expected->st_mm[st_mm_index].st)));
|
||||
EXPECT_EQ(
|
||||
BytesToHexString(expected->st_mm[st_mm_index].st_reserved,
|
||||
arraysize(expected->st_mm[st_mm_index].st_reserved)),
|
||||
BytesToHexString(observed->st_mm[st_mm_index].st_reserved,
|
||||
arraysize(observed->st_mm[st_mm_index].st_reserved)));
|
||||
arraysize(observed->st_mm[st_mm_index].st_reserved)),
|
||||
BytesToHexString(expected->st_mm[st_mm_index].st_reserved,
|
||||
arraysize(expected->st_mm[st_mm_index].st_reserved)));
|
||||
}
|
||||
for (size_t xmm_index = 0;
|
||||
xmm_index < arraysize(expected->xmm);
|
||||
++xmm_index) {
|
||||
EXPECT_EQ(BytesToHexString(expected->xmm[xmm_index],
|
||||
arraysize(expected->xmm[xmm_index])),
|
||||
BytesToHexString(observed->xmm[xmm_index],
|
||||
arraysize(observed->xmm[xmm_index])))
|
||||
EXPECT_EQ(BytesToHexString(observed->xmm[xmm_index],
|
||||
arraysize(observed->xmm[xmm_index])),
|
||||
BytesToHexString(expected->xmm[xmm_index],
|
||||
arraysize(expected->xmm[xmm_index])))
|
||||
<< "xmm_index " << xmm_index;
|
||||
}
|
||||
EXPECT_EQ(
|
||||
BytesToHexString(expected->reserved_4, arraysize(expected->reserved_4)),
|
||||
BytesToHexString(observed->reserved_4, arraysize(observed->reserved_4)));
|
||||
BytesToHexString(observed->reserved_4, arraysize(observed->reserved_4)),
|
||||
BytesToHexString(expected->reserved_4, arraysize(expected->reserved_4)));
|
||||
EXPECT_EQ(
|
||||
BytesToHexString(expected->available, arraysize(expected->available)),
|
||||
BytesToHexString(observed->available, arraysize(observed->available)));
|
||||
BytesToHexString(observed->available, arraysize(observed->available)),
|
||||
BytesToHexString(expected->available, arraysize(expected->available)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -200,50 +200,50 @@ void ExpectMinidumpContextX86(
|
||||
MinidumpContextX86 expected;
|
||||
InitializeMinidumpContextX86(&expected, expect_seed);
|
||||
|
||||
EXPECT_EQ(expected.context_flags, observed->context_flags);
|
||||
EXPECT_EQ(expected.dr0, observed->dr0);
|
||||
EXPECT_EQ(expected.dr1, observed->dr1);
|
||||
EXPECT_EQ(expected.dr2, observed->dr2);
|
||||
EXPECT_EQ(expected.dr3, observed->dr3);
|
||||
EXPECT_EQ(expected.dr6, observed->dr6);
|
||||
EXPECT_EQ(expected.dr7, observed->dr7);
|
||||
EXPECT_EQ(observed->context_flags, expected.context_flags);
|
||||
EXPECT_EQ(observed->dr0, expected.dr0);
|
||||
EXPECT_EQ(observed->dr1, expected.dr1);
|
||||
EXPECT_EQ(observed->dr2, expected.dr2);
|
||||
EXPECT_EQ(observed->dr3, expected.dr3);
|
||||
EXPECT_EQ(observed->dr6, expected.dr6);
|
||||
EXPECT_EQ(observed->dr7, expected.dr7);
|
||||
|
||||
EXPECT_EQ(expected.fsave.fcw, observed->fsave.fcw);
|
||||
EXPECT_EQ(expected.fsave.fsw, observed->fsave.fsw);
|
||||
EXPECT_EQ(expected.fsave.ftw, observed->fsave.ftw);
|
||||
EXPECT_EQ(expected.fsave.fpu_ip, observed->fsave.fpu_ip);
|
||||
EXPECT_EQ(expected.fsave.fpu_cs, observed->fsave.fpu_cs);
|
||||
EXPECT_EQ(expected.fsave.fpu_dp, observed->fsave.fpu_dp);
|
||||
EXPECT_EQ(expected.fsave.fpu_ds, observed->fsave.fpu_ds);
|
||||
EXPECT_EQ(observed->fsave.fcw, expected.fsave.fcw);
|
||||
EXPECT_EQ(observed->fsave.fsw, expected.fsave.fsw);
|
||||
EXPECT_EQ(observed->fsave.ftw, expected.fsave.ftw);
|
||||
EXPECT_EQ(observed->fsave.fpu_ip, expected.fsave.fpu_ip);
|
||||
EXPECT_EQ(observed->fsave.fpu_cs, expected.fsave.fpu_cs);
|
||||
EXPECT_EQ(observed->fsave.fpu_dp, expected.fsave.fpu_dp);
|
||||
EXPECT_EQ(observed->fsave.fpu_ds, expected.fsave.fpu_ds);
|
||||
for (size_t index = 0; index < arraysize(expected.fsave.st); ++index) {
|
||||
EXPECT_EQ(BytesToHexString(expected.fsave.st[index],
|
||||
arraysize(expected.fsave.st[index])),
|
||||
BytesToHexString(observed->fsave.st[index],
|
||||
arraysize(observed->fsave.st[index])))
|
||||
EXPECT_EQ(BytesToHexString(observed->fsave.st[index],
|
||||
arraysize(observed->fsave.st[index])),
|
||||
BytesToHexString(expected.fsave.st[index],
|
||||
arraysize(expected.fsave.st[index])))
|
||||
<< "index " << index;
|
||||
}
|
||||
if (snapshot) {
|
||||
EXPECT_EQ(0u, observed->float_save.spare_0);
|
||||
EXPECT_EQ(observed->float_save.spare_0, 0u);
|
||||
} else {
|
||||
EXPECT_EQ(expected.float_save.spare_0, observed->float_save.spare_0);
|
||||
EXPECT_EQ(observed->float_save.spare_0, expected.float_save.spare_0);
|
||||
}
|
||||
|
||||
EXPECT_EQ(expected.gs, observed->gs);
|
||||
EXPECT_EQ(expected.fs, observed->fs);
|
||||
EXPECT_EQ(expected.es, observed->es);
|
||||
EXPECT_EQ(expected.ds, observed->ds);
|
||||
EXPECT_EQ(expected.edi, observed->edi);
|
||||
EXPECT_EQ(expected.esi, observed->esi);
|
||||
EXPECT_EQ(expected.ebx, observed->ebx);
|
||||
EXPECT_EQ(expected.edx, observed->edx);
|
||||
EXPECT_EQ(expected.ecx, observed->ecx);
|
||||
EXPECT_EQ(expected.eax, observed->eax);
|
||||
EXPECT_EQ(expected.ebp, observed->ebp);
|
||||
EXPECT_EQ(expected.eip, observed->eip);
|
||||
EXPECT_EQ(expected.cs, observed->cs);
|
||||
EXPECT_EQ(expected.eflags, observed->eflags);
|
||||
EXPECT_EQ(expected.esp, observed->esp);
|
||||
EXPECT_EQ(expected.ss, observed->ss);
|
||||
EXPECT_EQ(observed->gs, expected.gs);
|
||||
EXPECT_EQ(observed->fs, expected.fs);
|
||||
EXPECT_EQ(observed->es, expected.es);
|
||||
EXPECT_EQ(observed->ds, expected.ds);
|
||||
EXPECT_EQ(observed->edi, expected.edi);
|
||||
EXPECT_EQ(observed->esi, expected.esi);
|
||||
EXPECT_EQ(observed->ebx, expected.ebx);
|
||||
EXPECT_EQ(observed->edx, expected.edx);
|
||||
EXPECT_EQ(observed->ecx, expected.ecx);
|
||||
EXPECT_EQ(observed->eax, expected.eax);
|
||||
EXPECT_EQ(observed->ebp, expected.ebp);
|
||||
EXPECT_EQ(observed->eip, expected.eip);
|
||||
EXPECT_EQ(observed->cs, expected.cs);
|
||||
EXPECT_EQ(observed->eflags, expected.eflags);
|
||||
EXPECT_EQ(observed->esp, expected.esp);
|
||||
EXPECT_EQ(observed->ss, expected.ss);
|
||||
|
||||
ExpectMinidumpContextFxsave(&expected.fxsave, &observed->fxsave);
|
||||
}
|
||||
@ -253,98 +253,100 @@ void ExpectMinidumpContextAMD64(
|
||||
MinidumpContextAMD64 expected;
|
||||
InitializeMinidumpContextAMD64(&expected, expect_seed);
|
||||
|
||||
EXPECT_EQ(expected.context_flags, observed->context_flags);
|
||||
EXPECT_EQ(observed->context_flags, expected.context_flags);
|
||||
|
||||
if (snapshot) {
|
||||
EXPECT_EQ(0u, observed->p1_home);
|
||||
EXPECT_EQ(0u, observed->p2_home);
|
||||
EXPECT_EQ(0u, observed->p3_home);
|
||||
EXPECT_EQ(0u, observed->p4_home);
|
||||
EXPECT_EQ(0u, observed->p5_home);
|
||||
EXPECT_EQ(0u, observed->p6_home);
|
||||
EXPECT_EQ(observed->p1_home, 0u);
|
||||
EXPECT_EQ(observed->p2_home, 0u);
|
||||
EXPECT_EQ(observed->p3_home, 0u);
|
||||
EXPECT_EQ(observed->p4_home, 0u);
|
||||
EXPECT_EQ(observed->p5_home, 0u);
|
||||
EXPECT_EQ(observed->p6_home, 0u);
|
||||
} else {
|
||||
EXPECT_EQ(expected.p1_home, observed->p1_home);
|
||||
EXPECT_EQ(expected.p2_home, observed->p2_home);
|
||||
EXPECT_EQ(expected.p3_home, observed->p3_home);
|
||||
EXPECT_EQ(expected.p4_home, observed->p4_home);
|
||||
EXPECT_EQ(expected.p5_home, observed->p5_home);
|
||||
EXPECT_EQ(expected.p6_home, observed->p6_home);
|
||||
EXPECT_EQ(observed->p1_home, expected.p1_home);
|
||||
EXPECT_EQ(observed->p2_home, expected.p2_home);
|
||||
EXPECT_EQ(observed->p3_home, expected.p3_home);
|
||||
EXPECT_EQ(observed->p4_home, expected.p4_home);
|
||||
EXPECT_EQ(observed->p5_home, expected.p5_home);
|
||||
EXPECT_EQ(observed->p6_home, expected.p6_home);
|
||||
}
|
||||
|
||||
EXPECT_EQ(expected.mx_csr, observed->mx_csr);
|
||||
EXPECT_EQ(observed->mx_csr, expected.mx_csr);
|
||||
|
||||
EXPECT_EQ(expected.cs, observed->cs);
|
||||
EXPECT_EQ(observed->cs, expected.cs);
|
||||
if (snapshot) {
|
||||
EXPECT_EQ(0u, observed->ds);
|
||||
EXPECT_EQ(0u, observed->es);
|
||||
EXPECT_EQ(observed->ds, 0u);
|
||||
EXPECT_EQ(observed->es, 0u);
|
||||
} else {
|
||||
EXPECT_EQ(expected.ds, observed->ds);
|
||||
EXPECT_EQ(expected.es, observed->es);
|
||||
EXPECT_EQ(observed->ds, expected.ds);
|
||||
EXPECT_EQ(observed->es, expected.es);
|
||||
}
|
||||
EXPECT_EQ(expected.fs, observed->fs);
|
||||
EXPECT_EQ(expected.gs, observed->gs);
|
||||
EXPECT_EQ(observed->fs, expected.fs);
|
||||
EXPECT_EQ(observed->gs, expected.gs);
|
||||
if (snapshot) {
|
||||
EXPECT_EQ(0u, observed->ss);
|
||||
EXPECT_EQ(observed->ss, 0u);
|
||||
} else {
|
||||
EXPECT_EQ(expected.ss, observed->ss);
|
||||
EXPECT_EQ(observed->ss, expected.ss);
|
||||
}
|
||||
|
||||
EXPECT_EQ(expected.eflags, observed->eflags);
|
||||
EXPECT_EQ(observed->eflags, expected.eflags);
|
||||
|
||||
EXPECT_EQ(expected.dr0, observed->dr0);
|
||||
EXPECT_EQ(expected.dr1, observed->dr1);
|
||||
EXPECT_EQ(expected.dr2, observed->dr2);
|
||||
EXPECT_EQ(expected.dr3, observed->dr3);
|
||||
EXPECT_EQ(expected.dr6, observed->dr6);
|
||||
EXPECT_EQ(expected.dr7, observed->dr7);
|
||||
EXPECT_EQ(observed->dr0, expected.dr0);
|
||||
EXPECT_EQ(observed->dr1, expected.dr1);
|
||||
EXPECT_EQ(observed->dr2, expected.dr2);
|
||||
EXPECT_EQ(observed->dr3, expected.dr3);
|
||||
EXPECT_EQ(observed->dr6, expected.dr6);
|
||||
EXPECT_EQ(observed->dr7, expected.dr7);
|
||||
|
||||
EXPECT_EQ(expected.rax, observed->rax);
|
||||
EXPECT_EQ(expected.rcx, observed->rcx);
|
||||
EXPECT_EQ(expected.rdx, observed->rdx);
|
||||
EXPECT_EQ(expected.rbx, observed->rbx);
|
||||
EXPECT_EQ(expected.rsp, observed->rsp);
|
||||
EXPECT_EQ(expected.rbp, observed->rbp);
|
||||
EXPECT_EQ(expected.rsi, observed->rsi);
|
||||
EXPECT_EQ(expected.rdi, observed->rdi);
|
||||
EXPECT_EQ(expected.r8, observed->r8);
|
||||
EXPECT_EQ(expected.r9, observed->r9);
|
||||
EXPECT_EQ(expected.r10, observed->r10);
|
||||
EXPECT_EQ(expected.r11, observed->r11);
|
||||
EXPECT_EQ(expected.r12, observed->r12);
|
||||
EXPECT_EQ(expected.r13, observed->r13);
|
||||
EXPECT_EQ(expected.r14, observed->r14);
|
||||
EXPECT_EQ(expected.r15, observed->r15);
|
||||
EXPECT_EQ(expected.rip, observed->rip);
|
||||
EXPECT_EQ(observed->rax, expected.rax);
|
||||
EXPECT_EQ(observed->rcx, expected.rcx);
|
||||
EXPECT_EQ(observed->rdx, expected.rdx);
|
||||
EXPECT_EQ(observed->rbx, expected.rbx);
|
||||
EXPECT_EQ(observed->rsp, expected.rsp);
|
||||
EXPECT_EQ(observed->rbp, expected.rbp);
|
||||
EXPECT_EQ(observed->rsi, expected.rsi);
|
||||
EXPECT_EQ(observed->rdi, expected.rdi);
|
||||
EXPECT_EQ(observed->r8, expected.r8);
|
||||
EXPECT_EQ(observed->r9, expected.r9);
|
||||
EXPECT_EQ(observed->r10, expected.r10);
|
||||
EXPECT_EQ(observed->r11, expected.r11);
|
||||
EXPECT_EQ(observed->r12, expected.r12);
|
||||
EXPECT_EQ(observed->r13, expected.r13);
|
||||
EXPECT_EQ(observed->r14, expected.r14);
|
||||
EXPECT_EQ(observed->r15, expected.r15);
|
||||
EXPECT_EQ(observed->rip, expected.rip);
|
||||
|
||||
ExpectMinidumpContextFxsave(&expected.fxsave, &observed->fxsave);
|
||||
|
||||
for (size_t index = 0; index < arraysize(expected.vector_register); ++index) {
|
||||
if (snapshot) {
|
||||
EXPECT_EQ(0u, observed->vector_register[index].lo) << "index " << index;
|
||||
EXPECT_EQ(0u, observed->vector_register[index].hi) << "index " << index;
|
||||
EXPECT_EQ(observed->vector_register[index].lo, 0u) << "index " << index;
|
||||
EXPECT_EQ(observed->vector_register[index].hi, 0u) << "index " << index;
|
||||
} else {
|
||||
EXPECT_EQ(expected.vector_register[index].lo,
|
||||
observed->vector_register[index].lo) << "index " << index;
|
||||
EXPECT_EQ(expected.vector_register[index].hi,
|
||||
observed->vector_register[index].hi) << "index " << index;
|
||||
EXPECT_EQ(observed->vector_register[index].lo,
|
||||
expected.vector_register[index].lo)
|
||||
<< "index " << index;
|
||||
EXPECT_EQ(observed->vector_register[index].hi,
|
||||
expected.vector_register[index].hi)
|
||||
<< "index " << index;
|
||||
}
|
||||
}
|
||||
|
||||
if (snapshot) {
|
||||
EXPECT_EQ(0u, observed->vector_control);
|
||||
EXPECT_EQ(0u, observed->debug_control);
|
||||
EXPECT_EQ(0u, observed->last_branch_to_rip);
|
||||
EXPECT_EQ(0u, observed->last_branch_from_rip);
|
||||
EXPECT_EQ(0u, observed->last_exception_to_rip);
|
||||
EXPECT_EQ(0u, observed->last_exception_from_rip);
|
||||
EXPECT_EQ(observed->vector_control, 0u);
|
||||
EXPECT_EQ(observed->debug_control, 0u);
|
||||
EXPECT_EQ(observed->last_branch_to_rip, 0u);
|
||||
EXPECT_EQ(observed->last_branch_from_rip, 0u);
|
||||
EXPECT_EQ(observed->last_exception_to_rip, 0u);
|
||||
EXPECT_EQ(observed->last_exception_from_rip, 0u);
|
||||
} else {
|
||||
EXPECT_EQ(expected.vector_control, observed->vector_control);
|
||||
EXPECT_EQ(expected.debug_control, observed->debug_control);
|
||||
EXPECT_EQ(expected.last_branch_to_rip, observed->last_branch_to_rip);
|
||||
EXPECT_EQ(expected.last_branch_from_rip, observed->last_branch_from_rip);
|
||||
EXPECT_EQ(expected.last_exception_to_rip, observed->last_exception_to_rip);
|
||||
EXPECT_EQ(expected.last_exception_from_rip,
|
||||
observed->last_exception_from_rip);
|
||||
EXPECT_EQ(observed->vector_control, expected.vector_control);
|
||||
EXPECT_EQ(observed->debug_control, expected.debug_control);
|
||||
EXPECT_EQ(observed->last_branch_to_rip, expected.last_branch_to_rip);
|
||||
EXPECT_EQ(observed->last_branch_from_rip, expected.last_branch_from_rip);
|
||||
EXPECT_EQ(observed->last_exception_to_rip, expected.last_exception_to_rip);
|
||||
EXPECT_EQ(observed->last_exception_from_rip,
|
||||
expected.last_exception_from_rip);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,11 +48,11 @@ void VerifyMinidumpHeader(const MINIDUMP_HEADER* header,
|
||||
uint32_t streams,
|
||||
uint32_t timestamp) {
|
||||
ASSERT_TRUE(header);
|
||||
ASSERT_EQ(streams, header->NumberOfStreams);
|
||||
ASSERT_EQ(streams ? sizeof(MINIDUMP_HEADER) : 0u, header->StreamDirectoryRva);
|
||||
EXPECT_EQ(0u, header->CheckSum);
|
||||
EXPECT_EQ(timestamp, header->TimeDateStamp);
|
||||
EXPECT_EQ(MiniDumpNormal, header->Flags);
|
||||
ASSERT_EQ(header->NumberOfStreams, streams);
|
||||
ASSERT_EQ(header->StreamDirectoryRva, streams ? sizeof(MINIDUMP_HEADER) : 0u);
|
||||
EXPECT_EQ(header->CheckSum, 0u);
|
||||
EXPECT_EQ(header->TimeDateStamp, timestamp);
|
||||
EXPECT_EQ(header->Flags, MiniDumpNormal);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
@ -34,13 +34,13 @@ TestMinidumpMemoryWriter::~TestMinidumpMemoryWriter() {
|
||||
void ExpectMinidumpMemoryDescriptor(
|
||||
const MINIDUMP_MEMORY_DESCRIPTOR* expected,
|
||||
const MINIDUMP_MEMORY_DESCRIPTOR* observed) {
|
||||
EXPECT_EQ(expected->StartOfMemoryRange, observed->StartOfMemoryRange);
|
||||
EXPECT_EQ(expected->Memory.DataSize, observed->Memory.DataSize);
|
||||
EXPECT_EQ(observed->StartOfMemoryRange, expected->StartOfMemoryRange);
|
||||
EXPECT_EQ(observed->Memory.DataSize, expected->Memory.DataSize);
|
||||
if (expected->Memory.Rva != 0) {
|
||||
const uint32_t kMemoryAlignment = 16;
|
||||
EXPECT_EQ(
|
||||
(expected->Memory.Rva + kMemoryAlignment - 1) & ~(kMemoryAlignment - 1),
|
||||
observed->Memory.Rva);
|
||||
EXPECT_EQ(observed->Memory.Rva,
|
||||
(expected->Memory.Rva + kMemoryAlignment - 1) &
|
||||
~(kMemoryAlignment - 1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,8 +53,8 @@ void ExpectMinidumpMemoryDescriptorAndContents(
|
||||
ExpectMinidumpMemoryDescriptor(expected, observed);
|
||||
|
||||
if (at_eof) {
|
||||
EXPECT_EQ(file_contents.size(),
|
||||
observed->Memory.Rva + observed->Memory.DataSize);
|
||||
EXPECT_EQ(observed->Memory.Rva + observed->Memory.DataSize,
|
||||
file_contents.size());
|
||||
} else {
|
||||
EXPECT_GE(file_contents.size(),
|
||||
observed->Memory.Rva + observed->Memory.DataSize);
|
||||
@ -63,7 +63,7 @@ void ExpectMinidumpMemoryDescriptorAndContents(
|
||||
std::string expected_data(expected->Memory.DataSize, value);
|
||||
std::string observed_data(&file_contents[observed->Memory.Rva],
|
||||
observed->Memory.DataSize);
|
||||
EXPECT_EQ(expected_data, observed_data);
|
||||
EXPECT_EQ(observed_data, expected_data);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
@ -39,7 +39,7 @@ const MinidumpRVAList* MinidumpRVAListAtStart(const std::string& file_contents,
|
||||
}
|
||||
|
||||
if (list->count != count) {
|
||||
EXPECT_EQ(count, list->count);
|
||||
EXPECT_EQ(list->count, count);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ const T* TMinidumpStringAtRVA(const std::string& file_contents, RVA rva) {
|
||||
// units.
|
||||
const size_t kCodeUnitSize = sizeof(string_base->Buffer[0]);
|
||||
if (string_base->Length % kCodeUnitSize != 0) {
|
||||
EXPECT_EQ(0u, string_base->Length % kCodeUnitSize);
|
||||
EXPECT_EQ(string_base->Length % kCodeUnitSize, 0u);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -51,11 +51,11 @@ const T* TMinidumpStringAtRVA(const std::string& file_contents, RVA rva) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EXPECT_EQ(string_base, string);
|
||||
EXPECT_EQ(string, string_base);
|
||||
|
||||
// Require the NUL terminator to be NUL.
|
||||
if (string->Buffer[string->Length / kCodeUnitSize] != '\0') {
|
||||
EXPECT_EQ('\0', string->Buffer[string->Length / kCodeUnitSize]);
|
||||
EXPECT_EQ(string->Buffer[string->Length / kCodeUnitSize], '\0');
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
43
minidump/test/minidump_user_extension_stream_util.cc
Normal file
43
minidump/test/minidump_user_extension_stream_util.cc
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2017 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "minidump/test/minidump_user_extension_stream_util.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
|
||||
BufferExtensionStreamDataSource::BufferExtensionStreamDataSource(
|
||||
uint32_t stream_type,
|
||||
const void* data,
|
||||
size_t data_size)
|
||||
: MinidumpUserExtensionStreamDataSource(stream_type) {
|
||||
data_.resize(data_size);
|
||||
|
||||
if (data_size)
|
||||
memcpy(data_.data(), data, data_size);
|
||||
}
|
||||
|
||||
size_t BufferExtensionStreamDataSource::StreamDataSize() {
|
||||
return data_.size();
|
||||
}
|
||||
|
||||
bool BufferExtensionStreamDataSource::ReadStreamData(Delegate* delegate) {
|
||||
return delegate->ExtensionStreamDataSourceRead(
|
||||
data_.size() ? data_.data() : nullptr, data_.size());
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
53
minidump/test/minidump_user_extension_stream_util.h
Normal file
53
minidump/test/minidump_user_extension_stream_util.h
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2017 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CRASHPAD_MINIDUMP_TEST_MINIDUMP_USER_EXTENSION_STREAM_UTIL_H_
|
||||
#define CRASHPAD_MINIDUMP_TEST_MINIDUMP_USER_EXTENSION_STREAM_UTIL_H_
|
||||
|
||||
#include "minidump/minidump_user_extension_stream_data_source.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
|
||||
//! \brief A user extension data source that wraps a buffer.
|
||||
class BufferExtensionStreamDataSource final
|
||||
: public MinidumpUserExtensionStreamDataSource {
|
||||
public:
|
||||
//! \brief Creates a data source with \a stream_type.
|
||||
//!
|
||||
//! param[in] stream_type The type of the stream.
|
||||
//! param[in] data The data of the stream.
|
||||
//! param[in] data_size The length of \a data.
|
||||
BufferExtensionStreamDataSource(uint32_t stream_type,
|
||||
const void* data,
|
||||
size_t data_size);
|
||||
|
||||
size_t StreamDataSize() override;
|
||||
bool ReadStreamData(Delegate* delegate) override;
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> data_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BufferExtensionStreamDataSource);
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
||||
|
||||
#endif // CRASHPAD_MINIDUMP_TEST_MINIDUMP_USER_EXTENSION_STREAM_UTIL_H_
|
@ -58,7 +58,7 @@ const void* MinidumpWritableAtLocationDescriptorInternal(
|
||||
size_t expected_size,
|
||||
bool allow_oversized_data) {
|
||||
if (location.DataSize == 0) {
|
||||
EXPECT_EQ(0u, location.Rva);
|
||||
EXPECT_EQ(location.Rva, 0u);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ const void* MinidumpWritableAtLocationDescriptorInternal(
|
||||
return nullptr;
|
||||
}
|
||||
} else if (location.DataSize != expected_size) {
|
||||
EXPECT_EQ(expected_size, location.DataSize);
|
||||
EXPECT_EQ(location.DataSize, expected_size);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -95,25 +95,25 @@ const IMAGE_DEBUG_MISC* MinidumpWritableAtLocationDescriptor<IMAGE_DEBUG_MISC>(
|
||||
}
|
||||
|
||||
if (misc->DataType != IMAGE_DEBUG_MISC_EXENAME) {
|
||||
EXPECT_EQ(implicit_cast<uint32_t>(IMAGE_DEBUG_MISC_EXENAME),
|
||||
misc->DataType);
|
||||
EXPECT_EQ(misc->DataType,
|
||||
implicit_cast<uint32_t>(IMAGE_DEBUG_MISC_EXENAME));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (misc->Length != location.DataSize) {
|
||||
EXPECT_EQ(location.DataSize, misc->Length);
|
||||
EXPECT_EQ(misc->Length, location.DataSize);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (misc->Unicode == 0) {
|
||||
size_t string_length = misc->Length - offsetof(IMAGE_DEBUG_MISC, Data) - 1;
|
||||
if (misc->Data[string_length] != '\0') {
|
||||
EXPECT_EQ('\0', misc->Data[string_length]);
|
||||
EXPECT_EQ(misc->Data[string_length], '\0');
|
||||
return nullptr;
|
||||
}
|
||||
} else if (misc->Unicode == 1) {
|
||||
if (misc->Length % sizeof(base::char16) != 0) {
|
||||
EXPECT_EQ(0u, misc->Length % sizeof(base::char16));
|
||||
EXPECT_EQ(misc->Length % sizeof(base::char16), 0u);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ const IMAGE_DEBUG_MISC* MinidumpWritableAtLocationDescriptor<IMAGE_DEBUG_MISC>(
|
||||
const base::char16* data16 =
|
||||
reinterpret_cast<const base::char16*>(misc->Data);
|
||||
if (data16[string_length] != '\0') {
|
||||
EXPECT_EQ('\0', data16[string_length]);
|
||||
EXPECT_EQ(data16[string_length], '\0');
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
@ -146,11 +146,11 @@ const MINIDUMP_HEADER* MinidumpWritableAtLocationDescriptor<MINIDUMP_HEADER>(
|
||||
}
|
||||
|
||||
if (header->Signature != MINIDUMP_SIGNATURE) {
|
||||
EXPECT_EQ(implicit_cast<uint32_t>(MINIDUMP_SIGNATURE), header->Signature);
|
||||
EXPECT_EQ(header->Signature, implicit_cast<uint32_t>(MINIDUMP_SIGNATURE));
|
||||
return nullptr;
|
||||
}
|
||||
if (header->Version != MINIDUMP_VERSION) {
|
||||
EXPECT_EQ(implicit_cast<uint32_t>(MINIDUMP_VERSION), header->Version);
|
||||
EXPECT_EQ(header->Version, implicit_cast<uint32_t>(MINIDUMP_VERSION));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -237,7 +237,7 @@ const typename T::ListType* MinidumpListAtLocationDescriptor(
|
||||
size_t expected_size =
|
||||
sizeof(typename T::ListType) + T::ElementCount(list) * T::kElementSize;
|
||||
if (location.DataSize != expected_size) {
|
||||
EXPECT_EQ(expected_size, location.DataSize);
|
||||
EXPECT_EQ(location.DataSize, expected_size);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -326,13 +326,13 @@ const T* MinidumpCVPDBAtLocationDescriptor(
|
||||
}
|
||||
|
||||
if (cv_pdb->signature != T::kSignature) {
|
||||
EXPECT_EQ(T::kSignature, cv_pdb->signature);
|
||||
EXPECT_EQ(cv_pdb->signature, T::kSignature);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t string_length = location.DataSize - offsetof(T, pdb_name) - 1;
|
||||
if (cv_pdb->pdb_name[string_length] != '\0') {
|
||||
EXPECT_EQ('\0', cv_pdb->pdb_name[string_length]);
|
||||
EXPECT_EQ(cv_pdb->pdb_name[string_length], '\0');
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -42,9 +42,9 @@ class ModuleAnnotationsMultiprocessTest final : public WinMultiprocess {
|
||||
ASSERT_TRUE(ReadModuleAnnotations(process_handle, module, &annotations));
|
||||
|
||||
EXPECT_GE(annotations.size(), 3u);
|
||||
EXPECT_EQ("value", annotations["#APITEST# key"]);
|
||||
EXPECT_EQ("y", annotations["#APITEST# x"]);
|
||||
EXPECT_EQ("", annotations["#APITEST# empty_value"]);
|
||||
EXPECT_EQ(annotations["#APITEST# key"], "value");
|
||||
EXPECT_EQ(annotations["#APITEST# x"], "y");
|
||||
EXPECT_EQ(annotations["#APITEST# empty_value"], "");
|
||||
|
||||
// Signal the child process to terminate.
|
||||
char c = ' ';
|
||||
|
@ -136,22 +136,22 @@ TEST(CPUContextX86, FxsaveToFsave) {
|
||||
|
||||
// Everything should have come over from fxsave. Reserved fields should be
|
||||
// zero.
|
||||
EXPECT_EQ(fxsave.fcw, fsave.fcw);
|
||||
EXPECT_EQ(0, fsave.reserved_1);
|
||||
EXPECT_EQ(fxsave.fsw, fsave.fsw);
|
||||
EXPECT_EQ(0, fsave.reserved_2);
|
||||
EXPECT_EQ(0xfe90, fsave.ftw); // FxsaveToFsaveTagWord
|
||||
EXPECT_EQ(0, fsave.reserved_3);
|
||||
EXPECT_EQ(fxsave.fpu_ip, fsave.fpu_ip);
|
||||
EXPECT_EQ(fxsave.fpu_cs, fsave.fpu_cs);
|
||||
EXPECT_EQ(fxsave.fop, fsave.fop);
|
||||
EXPECT_EQ(fxsave.fpu_dp, fsave.fpu_dp);
|
||||
EXPECT_EQ(fxsave.fpu_ds, fsave.fpu_ds);
|
||||
EXPECT_EQ(0, fsave.reserved_4);
|
||||
EXPECT_EQ(fsave.fcw, fxsave.fcw);
|
||||
EXPECT_EQ(fsave.reserved_1, 0);
|
||||
EXPECT_EQ(fsave.fsw, fxsave.fsw);
|
||||
EXPECT_EQ(fsave.reserved_2, 0);
|
||||
EXPECT_EQ(fsave.ftw, 0xfe90); // FxsaveToFsaveTagWord
|
||||
EXPECT_EQ(fsave.reserved_3, 0);
|
||||
EXPECT_EQ(fsave.fpu_ip, fxsave.fpu_ip);
|
||||
EXPECT_EQ(fsave.fpu_cs, fxsave.fpu_cs);
|
||||
EXPECT_EQ(fsave.fop, fxsave.fop);
|
||||
EXPECT_EQ(fsave.fpu_dp, fxsave.fpu_dp);
|
||||
EXPECT_EQ(fsave.fpu_ds, fxsave.fpu_ds);
|
||||
EXPECT_EQ(fsave.reserved_4, 0);
|
||||
for (size_t index = 0; index < arraysize(fsave.st); ++index) {
|
||||
EXPECT_EQ(BytesToHexString(fxsave.st_mm[index].st,
|
||||
arraysize(fxsave.st_mm[index].st)),
|
||||
BytesToHexString(fsave.st[index], arraysize(fsave.st[index])))
|
||||
EXPECT_EQ(BytesToHexString(fsave.st[index], arraysize(fsave.st[index])),
|
||||
BytesToHexString(fxsave.st_mm[index].st,
|
||||
arraysize(fxsave.st_mm[index].st)))
|
||||
<< "index " << index;
|
||||
}
|
||||
}
|
||||
@ -191,32 +191,32 @@ TEST(CPUContextX86, FsaveToFxsave) {
|
||||
|
||||
// Everything in fsave should have come over from there. Fields not present in
|
||||
// fsave and reserved fields should be zero.
|
||||
EXPECT_EQ(fsave.fcw, fxsave.fcw);
|
||||
EXPECT_EQ(fsave.fsw, fxsave.fsw);
|
||||
EXPECT_EQ(0xf0, fxsave.ftw); // FsaveToFxsaveTagWord
|
||||
EXPECT_EQ(0, fxsave.reserved_1);
|
||||
EXPECT_EQ(fsave.fop, fxsave.fop);
|
||||
EXPECT_EQ(fsave.fpu_ip, fxsave.fpu_ip);
|
||||
EXPECT_EQ(fsave.fpu_cs, fxsave.fpu_cs);
|
||||
EXPECT_EQ(0, fxsave.reserved_2);
|
||||
EXPECT_EQ(fsave.fpu_dp, fxsave.fpu_dp);
|
||||
EXPECT_EQ(fsave.fpu_ds, fxsave.fpu_ds);
|
||||
EXPECT_EQ(0, fxsave.reserved_3);
|
||||
EXPECT_EQ(0u, fxsave.mxcsr);
|
||||
EXPECT_EQ(0u, fxsave.mxcsr_mask);
|
||||
EXPECT_EQ(fxsave.fcw, fsave.fcw);
|
||||
EXPECT_EQ(fxsave.fsw, fsave.fsw);
|
||||
EXPECT_EQ(fxsave.ftw, 0xf0); // FsaveToFxsaveTagWord
|
||||
EXPECT_EQ(fxsave.reserved_1, 0);
|
||||
EXPECT_EQ(fxsave.fop, fsave.fop);
|
||||
EXPECT_EQ(fxsave.fpu_ip, fsave.fpu_ip);
|
||||
EXPECT_EQ(fxsave.fpu_cs, fsave.fpu_cs);
|
||||
EXPECT_EQ(fxsave.reserved_2, 0);
|
||||
EXPECT_EQ(fxsave.fpu_dp, fsave.fpu_dp);
|
||||
EXPECT_EQ(fxsave.fpu_ds, fsave.fpu_ds);
|
||||
EXPECT_EQ(fxsave.reserved_3, 0);
|
||||
EXPECT_EQ(fxsave.mxcsr, 0u);
|
||||
EXPECT_EQ(fxsave.mxcsr_mask, 0u);
|
||||
for (size_t index = 0; index < arraysize(fxsave.st_mm); ++index) {
|
||||
EXPECT_EQ(BytesToHexString(fsave.st[index], arraysize(fsave.st[index])),
|
||||
BytesToHexString(fxsave.st_mm[index].st,
|
||||
arraysize(fxsave.st_mm[index].st)))
|
||||
EXPECT_EQ(BytesToHexString(fxsave.st_mm[index].st,
|
||||
arraysize(fxsave.st_mm[index].st)),
|
||||
BytesToHexString(fsave.st[index], arraysize(fsave.st[index])))
|
||||
<< "index " << index;
|
||||
EXPECT_EQ(std::string(arraysize(fxsave.st_mm[index].st_reserved) * 2, '0'),
|
||||
BytesToHexString(fxsave.st_mm[index].st_reserved,
|
||||
arraysize(fxsave.st_mm[index].st_reserved)))
|
||||
EXPECT_EQ(BytesToHexString(fxsave.st_mm[index].st_reserved,
|
||||
arraysize(fxsave.st_mm[index].st_reserved)),
|
||||
std::string(arraysize(fxsave.st_mm[index].st_reserved) * 2, '0'))
|
||||
<< "index " << index;
|
||||
}
|
||||
size_t unused_len = sizeof(fxsave) - offsetof(decltype(fxsave), xmm);
|
||||
EXPECT_EQ(std::string(unused_len * 2, '0'),
|
||||
BytesToHexString(fxsave.xmm, unused_len));
|
||||
EXPECT_EQ(BytesToHexString(fxsave.xmm, unused_len),
|
||||
std::string(unused_len * 2, '0'));
|
||||
|
||||
// Since the fsave format is a subset of the fxsave format, fsave-fxsave-fsave
|
||||
// should round-trip cleanly.
|
||||
@ -229,7 +229,7 @@ TEST(CPUContextX86, FsaveToFxsave) {
|
||||
fsave.reserved_2 = 0;
|
||||
fsave.reserved_3 = 0;
|
||||
fsave.reserved_4 = 0;
|
||||
EXPECT_EQ(0, memcmp(&fsave, &fsave_2, sizeof(fsave)));
|
||||
EXPECT_EQ(memcmp(&fsave, &fsave_2, sizeof(fsave)), 0);
|
||||
}
|
||||
|
||||
TEST(CPUContextX86, FxsaveToFsaveTagWord) {
|
||||
@ -258,8 +258,8 @@ TEST(CPUContextX86, FxsaveToFsaveTagWord) {
|
||||
SetX87OrMMXRegister(&st_mm[5], kExponentNormal, true, kFractionNormal);
|
||||
SetX87OrMMXRegister(&st_mm[6], kExponentNormal, false, kFractionAllZero);
|
||||
SetX87OrMMXRegister(&st_mm[7], kExponentNormal, true, kFractionAllZero);
|
||||
EXPECT_EQ(0xff22,
|
||||
CPUContextX86::FxsaveToFsaveTagWord(fsw, fxsave_tag, st_mm));
|
||||
EXPECT_EQ(CPUContextX86::FxsaveToFsaveTagWord(fsw, fxsave_tag, st_mm),
|
||||
0xff22);
|
||||
|
||||
fsw = 2 << 11; // top = 2: logical 0-7 maps to physical 2-7, 0-1
|
||||
fxsave_tag = 0xf0; // physical 0-3 (logical 6-7, 0-1) empty
|
||||
@ -275,8 +275,8 @@ TEST(CPUContextX86, FxsaveToFsaveTagWord) {
|
||||
&st_mm[5], kExponentAllZero, true, kFractionNormal); // spec.
|
||||
SetX87OrMMXRegister(&st_mm[6], kExponentAllZero, false, kFractionAllZero);
|
||||
SetX87OrMMXRegister(&st_mm[7], kExponentAllZero, true, kFractionAllZero);
|
||||
EXPECT_EQ(0xa9ff,
|
||||
CPUContextX86::FxsaveToFsaveTagWord(fsw, fxsave_tag, st_mm));
|
||||
EXPECT_EQ(CPUContextX86::FxsaveToFsaveTagWord(fsw, fxsave_tag, st_mm),
|
||||
0xa9ff);
|
||||
|
||||
fsw = 5 << 11; // top = 5: logical 0-7 maps to physical 5-7, 0-4
|
||||
fxsave_tag = 0x5a; // physical 0, 2, 5, and 7 (logical 5, 0, 2, and 3) empty
|
||||
@ -292,8 +292,8 @@ TEST(CPUContextX86, FxsaveToFsaveTagWord) {
|
||||
&st_mm[6], kExponentAllOne, false, kFractionAllZero); // spec.
|
||||
SetX87OrMMXRegister(
|
||||
&st_mm[7], kExponentAllOne, true, kFractionAllZero); // spec.
|
||||
EXPECT_EQ(0xeebb,
|
||||
CPUContextX86::FxsaveToFsaveTagWord(fsw, fxsave_tag, st_mm));
|
||||
EXPECT_EQ(CPUContextX86::FxsaveToFsaveTagWord(fsw, fxsave_tag, st_mm),
|
||||
0xeebb);
|
||||
|
||||
// This set set is just a mix of all of the possible tag types in a single
|
||||
// register file.
|
||||
@ -312,8 +312,8 @@ TEST(CPUContextX86, FxsaveToFsaveTagWord) {
|
||||
SetX87OrMMXRegister(&st_mm[6], kExponentAllZero, false, kFractionAllZero);
|
||||
SetX87OrMMXRegister(
|
||||
&st_mm[7], kExponentNormal, true, kFractionNormal); // valid
|
||||
EXPECT_EQ(0xfe90,
|
||||
CPUContextX86::FxsaveToFsaveTagWord(fsw, fxsave_tag, st_mm));
|
||||
EXPECT_EQ(CPUContextX86::FxsaveToFsaveTagWord(fsw, fxsave_tag, st_mm),
|
||||
0xfe90);
|
||||
|
||||
// In this set, everything is valid.
|
||||
fsw = 0 << 11; // top = 0: logical 0-7 maps to physical 0-7
|
||||
@ -321,25 +321,25 @@ TEST(CPUContextX86, FxsaveToFsaveTagWord) {
|
||||
for (size_t index = 0; index < arraysize(st_mm); ++index) {
|
||||
SetX87OrMMXRegister(&st_mm[index], kExponentNormal, true, kFractionAllZero);
|
||||
}
|
||||
EXPECT_EQ(0, CPUContextX86::FxsaveToFsaveTagWord(fsw, fxsave_tag, st_mm));
|
||||
EXPECT_EQ(CPUContextX86::FxsaveToFsaveTagWord(fsw, fxsave_tag, st_mm), 0);
|
||||
|
||||
// In this set, everything is empty. The registers shouldn’t be consulted at
|
||||
// all, so they’re left alone from the previous set.
|
||||
fsw = 0 << 11; // top = 0: logical 0-7 maps to physical 0-7
|
||||
fxsave_tag = 0; // everything empty
|
||||
EXPECT_EQ(0xffff,
|
||||
CPUContextX86::FxsaveToFsaveTagWord(fsw, fxsave_tag, st_mm));
|
||||
EXPECT_EQ(CPUContextX86::FxsaveToFsaveTagWord(fsw, fxsave_tag, st_mm),
|
||||
0xffff);
|
||||
}
|
||||
|
||||
TEST(CPUContextX86, FsaveToFxsaveTagWord) {
|
||||
// The register sets that these x87 tag words might apply to are given in the
|
||||
// FxsaveToFsaveTagWord test above.
|
||||
EXPECT_EQ(0x0f, CPUContextX86::FsaveToFxsaveTagWord(0xff22));
|
||||
EXPECT_EQ(0xf0, CPUContextX86::FsaveToFxsaveTagWord(0xa9ff));
|
||||
EXPECT_EQ(0x5a, CPUContextX86::FsaveToFxsaveTagWord(0xeebb));
|
||||
EXPECT_EQ(0x1f, CPUContextX86::FsaveToFxsaveTagWord(0xfe90));
|
||||
EXPECT_EQ(0xff, CPUContextX86::FsaveToFxsaveTagWord(0x0000));
|
||||
EXPECT_EQ(0x00, CPUContextX86::FsaveToFxsaveTagWord(0xffff));
|
||||
EXPECT_EQ(CPUContextX86::FsaveToFxsaveTagWord(0xff22), 0x0f);
|
||||
EXPECT_EQ(CPUContextX86::FsaveToFxsaveTagWord(0xa9ff), 0xf0);
|
||||
EXPECT_EQ(CPUContextX86::FsaveToFxsaveTagWord(0xeebb), 0x5a);
|
||||
EXPECT_EQ(CPUContextX86::FsaveToFxsaveTagWord(0xfe90), 0x1f);
|
||||
EXPECT_EQ(CPUContextX86::FsaveToFxsaveTagWord(0x0000), 0xff);
|
||||
EXPECT_EQ(CPUContextX86::FsaveToFxsaveTagWord(0xffff), 0x00);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "client/crashpad_info.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/errors.h"
|
||||
#include "test/paths.h"
|
||||
#include "test/test_paths.h"
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#include <dlfcn.h>
|
||||
@ -36,20 +36,20 @@ namespace test {
|
||||
namespace {
|
||||
|
||||
TEST(CrashpadInfoClientOptions, TriStateFromCrashpadInfo) {
|
||||
EXPECT_EQ(TriState::kUnset,
|
||||
CrashpadInfoClientOptions::TriStateFromCrashpadInfo(0));
|
||||
EXPECT_EQ(TriState::kEnabled,
|
||||
CrashpadInfoClientOptions::TriStateFromCrashpadInfo(1));
|
||||
EXPECT_EQ(TriState::kDisabled,
|
||||
CrashpadInfoClientOptions::TriStateFromCrashpadInfo(2));
|
||||
EXPECT_EQ(CrashpadInfoClientOptions::TriStateFromCrashpadInfo(0),
|
||||
TriState::kUnset);
|
||||
EXPECT_EQ(CrashpadInfoClientOptions::TriStateFromCrashpadInfo(1),
|
||||
TriState::kEnabled);
|
||||
EXPECT_EQ(CrashpadInfoClientOptions::TriStateFromCrashpadInfo(2),
|
||||
TriState::kDisabled);
|
||||
|
||||
// These will produce log messages but should result in kUnset being returned.
|
||||
EXPECT_EQ(TriState::kUnset,
|
||||
CrashpadInfoClientOptions::TriStateFromCrashpadInfo(3));
|
||||
EXPECT_EQ(TriState::kUnset,
|
||||
CrashpadInfoClientOptions::TriStateFromCrashpadInfo(4));
|
||||
EXPECT_EQ(TriState::kUnset,
|
||||
CrashpadInfoClientOptions::TriStateFromCrashpadInfo(0xff));
|
||||
EXPECT_EQ(CrashpadInfoClientOptions::TriStateFromCrashpadInfo(3),
|
||||
TriState::kUnset);
|
||||
EXPECT_EQ(CrashpadInfoClientOptions::TriStateFromCrashpadInfo(4),
|
||||
TriState::kUnset);
|
||||
EXPECT_EQ(CrashpadInfoClientOptions::TriStateFromCrashpadInfo(0xff),
|
||||
TriState::kUnset);
|
||||
}
|
||||
|
||||
class ScopedUnsetCrashpadInfoOptions {
|
||||
@ -92,10 +92,10 @@ TEST(CrashpadInfoClientOptions, OneModule) {
|
||||
// Make sure that the initial state has all values unset.
|
||||
auto options = SelfProcessSnapshotAndGetCrashpadOptions();
|
||||
|
||||
EXPECT_EQ(TriState::kUnset, options.crashpad_handler_behavior);
|
||||
EXPECT_EQ(TriState::kUnset, options.system_crash_reporter_forwarding);
|
||||
EXPECT_EQ(TriState::kUnset, options.gather_indirectly_referenced_memory);
|
||||
EXPECT_EQ(0u, options.indirectly_referenced_memory_cap);
|
||||
EXPECT_EQ(options.crashpad_handler_behavior, TriState::kUnset);
|
||||
EXPECT_EQ(options.system_crash_reporter_forwarding, TriState::kUnset);
|
||||
EXPECT_EQ(options.gather_indirectly_referenced_memory, TriState::kUnset);
|
||||
EXPECT_EQ(options.indirectly_referenced_memory_cap, 0u);
|
||||
|
||||
CrashpadInfo* crashpad_info = CrashpadInfo::GetCrashpadInfo();
|
||||
ASSERT_TRUE(crashpad_info);
|
||||
@ -106,10 +106,10 @@ TEST(CrashpadInfoClientOptions, OneModule) {
|
||||
crashpad_info->set_crashpad_handler_behavior(TriState::kEnabled);
|
||||
|
||||
options = SelfProcessSnapshotAndGetCrashpadOptions();
|
||||
EXPECT_EQ(TriState::kEnabled, options.crashpad_handler_behavior);
|
||||
EXPECT_EQ(TriState::kUnset, options.system_crash_reporter_forwarding);
|
||||
EXPECT_EQ(TriState::kUnset, options.gather_indirectly_referenced_memory);
|
||||
EXPECT_EQ(0u, options.indirectly_referenced_memory_cap);
|
||||
EXPECT_EQ(options.crashpad_handler_behavior, TriState::kEnabled);
|
||||
EXPECT_EQ(options.system_crash_reporter_forwarding, TriState::kUnset);
|
||||
EXPECT_EQ(options.gather_indirectly_referenced_memory, TriState::kUnset);
|
||||
EXPECT_EQ(options.indirectly_referenced_memory_cap, 0u);
|
||||
}
|
||||
|
||||
{
|
||||
@ -118,10 +118,10 @@ TEST(CrashpadInfoClientOptions, OneModule) {
|
||||
crashpad_info->set_system_crash_reporter_forwarding(TriState::kDisabled);
|
||||
|
||||
options = SelfProcessSnapshotAndGetCrashpadOptions();
|
||||
EXPECT_EQ(TriState::kUnset, options.crashpad_handler_behavior);
|
||||
EXPECT_EQ(TriState::kDisabled, options.system_crash_reporter_forwarding);
|
||||
EXPECT_EQ(TriState::kUnset, options.gather_indirectly_referenced_memory);
|
||||
EXPECT_EQ(0u, options.indirectly_referenced_memory_cap);
|
||||
EXPECT_EQ(options.crashpad_handler_behavior, TriState::kUnset);
|
||||
EXPECT_EQ(options.system_crash_reporter_forwarding, TriState::kDisabled);
|
||||
EXPECT_EQ(options.gather_indirectly_referenced_memory, TriState::kUnset);
|
||||
EXPECT_EQ(options.indirectly_referenced_memory_cap, 0u);
|
||||
}
|
||||
|
||||
{
|
||||
@ -131,10 +131,10 @@ TEST(CrashpadInfoClientOptions, OneModule) {
|
||||
1234);
|
||||
|
||||
options = SelfProcessSnapshotAndGetCrashpadOptions();
|
||||
EXPECT_EQ(TriState::kUnset, options.crashpad_handler_behavior);
|
||||
EXPECT_EQ(TriState::kUnset, options.system_crash_reporter_forwarding);
|
||||
EXPECT_EQ(TriState::kEnabled, options.gather_indirectly_referenced_memory);
|
||||
EXPECT_EQ(1234u, options.indirectly_referenced_memory_cap);
|
||||
EXPECT_EQ(options.crashpad_handler_behavior, TriState::kUnset);
|
||||
EXPECT_EQ(options.system_crash_reporter_forwarding, TriState::kUnset);
|
||||
EXPECT_EQ(options.gather_indirectly_referenced_memory, TriState::kEnabled);
|
||||
EXPECT_EQ(options.indirectly_referenced_memory_cap, 1234u);
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,7 +187,7 @@ TEST(CrashpadInfoClientOptions, TwoModules) {
|
||||
#elif defined(OS_WIN)
|
||||
const base::FilePath::StringType kDlExtension = FILE_PATH_LITERAL(".dll");
|
||||
#endif
|
||||
base::FilePath module_path = Paths::Executable().DirName().Append(
|
||||
base::FilePath module_path = TestPaths::Executable().DirName().Append(
|
||||
FILE_PATH_LITERAL("crashpad_snapshot_test_module") + kDlExtension);
|
||||
#if defined(OS_MACOSX)
|
||||
ScopedDlHandle dl_handle(
|
||||
@ -213,9 +213,9 @@ TEST(CrashpadInfoClientOptions, TwoModules) {
|
||||
auto options = SelfProcessSnapshotAndGetCrashpadOptions();
|
||||
|
||||
// Make sure that the initial state has all values unset.
|
||||
EXPECT_EQ(TriState::kUnset, options.crashpad_handler_behavior);
|
||||
EXPECT_EQ(TriState::kUnset, options.system_crash_reporter_forwarding);
|
||||
EXPECT_EQ(TriState::kUnset, options.gather_indirectly_referenced_memory);
|
||||
EXPECT_EQ(options.crashpad_handler_behavior, TriState::kUnset);
|
||||
EXPECT_EQ(options.system_crash_reporter_forwarding, TriState::kUnset);
|
||||
EXPECT_EQ(options.gather_indirectly_referenced_memory, TriState::kUnset);
|
||||
|
||||
// Get both CrashpadInfo structures.
|
||||
CrashpadInfo* local_crashpad_info = CrashpadInfo::GetCrashpadInfo();
|
||||
@ -232,9 +232,9 @@ TEST(CrashpadInfoClientOptions, TwoModules) {
|
||||
remote_crashpad_info->set_crashpad_handler_behavior(TriState::kEnabled);
|
||||
|
||||
options = SelfProcessSnapshotAndGetCrashpadOptions();
|
||||
EXPECT_EQ(TriState::kEnabled, options.crashpad_handler_behavior);
|
||||
EXPECT_EQ(TriState::kUnset, options.system_crash_reporter_forwarding);
|
||||
EXPECT_EQ(TriState::kUnset, options.gather_indirectly_referenced_memory);
|
||||
EXPECT_EQ(options.crashpad_handler_behavior, TriState::kEnabled);
|
||||
EXPECT_EQ(options.system_crash_reporter_forwarding, TriState::kUnset);
|
||||
EXPECT_EQ(options.gather_indirectly_referenced_memory, TriState::kUnset);
|
||||
|
||||
// When more than one module sets a value, the first one in the module list
|
||||
// applies to the process. The local module should appear before the remote
|
||||
@ -242,9 +242,9 @@ TEST(CrashpadInfoClientOptions, TwoModules) {
|
||||
local_crashpad_info->set_crashpad_handler_behavior(TriState::kDisabled);
|
||||
|
||||
options = SelfProcessSnapshotAndGetCrashpadOptions();
|
||||
EXPECT_EQ(TriState::kDisabled, options.crashpad_handler_behavior);
|
||||
EXPECT_EQ(TriState::kUnset, options.system_crash_reporter_forwarding);
|
||||
EXPECT_EQ(TriState::kUnset, options.gather_indirectly_referenced_memory);
|
||||
EXPECT_EQ(options.crashpad_handler_behavior, TriState::kDisabled);
|
||||
EXPECT_EQ(options.system_crash_reporter_forwarding, TriState::kUnset);
|
||||
EXPECT_EQ(options.gather_indirectly_referenced_memory, TriState::kUnset);
|
||||
}
|
||||
|
||||
{
|
||||
@ -256,9 +256,9 @@ TEST(CrashpadInfoClientOptions, TwoModules) {
|
||||
TriState::kDisabled);
|
||||
|
||||
options = SelfProcessSnapshotAndGetCrashpadOptions();
|
||||
EXPECT_EQ(TriState::kUnset, options.crashpad_handler_behavior);
|
||||
EXPECT_EQ(TriState::kDisabled, options.system_crash_reporter_forwarding);
|
||||
EXPECT_EQ(TriState::kUnset, options.gather_indirectly_referenced_memory);
|
||||
EXPECT_EQ(options.crashpad_handler_behavior, TriState::kUnset);
|
||||
EXPECT_EQ(options.system_crash_reporter_forwarding, TriState::kDisabled);
|
||||
EXPECT_EQ(options.gather_indirectly_referenced_memory, TriState::kUnset);
|
||||
|
||||
// When more than one module sets a value, the first one in the module list
|
||||
// applies to the process. The local module should appear before the remote
|
||||
@ -267,9 +267,9 @@ TEST(CrashpadInfoClientOptions, TwoModules) {
|
||||
TriState::kEnabled);
|
||||
|
||||
options = SelfProcessSnapshotAndGetCrashpadOptions();
|
||||
EXPECT_EQ(TriState::kUnset, options.crashpad_handler_behavior);
|
||||
EXPECT_EQ(TriState::kEnabled, options.system_crash_reporter_forwarding);
|
||||
EXPECT_EQ(TriState::kUnset, options.gather_indirectly_referenced_memory);
|
||||
EXPECT_EQ(options.crashpad_handler_behavior, TriState::kUnset);
|
||||
EXPECT_EQ(options.system_crash_reporter_forwarding, TriState::kEnabled);
|
||||
EXPECT_EQ(options.gather_indirectly_referenced_memory, TriState::kUnset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,9 +43,9 @@ TEST(CPUContextMac, InitializeContextX86) {
|
||||
&x86_thread_state32,
|
||||
&x86_float_state32,
|
||||
&x86_debug_state32);
|
||||
EXPECT_EQ(1u, cpu_context_x86.eax);
|
||||
EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw);
|
||||
EXPECT_EQ(3u, cpu_context_x86.dr0);
|
||||
EXPECT_EQ(cpu_context_x86.eax, 1u);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.ftw, 2u);
|
||||
EXPECT_EQ(cpu_context_x86.dr0, 3u);
|
||||
}
|
||||
|
||||
// Supply context in a CPU-specific “flavor” parameter expected to be used
|
||||
@ -69,9 +69,9 @@ TEST(CPUContextMac, InitializeContextX86) {
|
||||
&x86_thread_state32,
|
||||
&x86_float_state32,
|
||||
&x86_debug_state32);
|
||||
EXPECT_EQ(4u, cpu_context_x86.eax);
|
||||
EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw);
|
||||
EXPECT_EQ(3u, cpu_context_x86.dr0);
|
||||
EXPECT_EQ(cpu_context_x86.eax, 4u);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.ftw, 2u);
|
||||
EXPECT_EQ(cpu_context_x86.dr0, 3u);
|
||||
}
|
||||
|
||||
{
|
||||
@ -87,9 +87,9 @@ TEST(CPUContextMac, InitializeContextX86) {
|
||||
&x86_thread_state32,
|
||||
&x86_float_state32,
|
||||
&x86_debug_state32);
|
||||
EXPECT_EQ(1u, cpu_context_x86.eax);
|
||||
EXPECT_EQ(5u, cpu_context_x86.fxsave.ftw);
|
||||
EXPECT_EQ(3u, cpu_context_x86.dr0);
|
||||
EXPECT_EQ(cpu_context_x86.eax, 1u);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.ftw, 5u);
|
||||
EXPECT_EQ(cpu_context_x86.dr0, 3u);
|
||||
}
|
||||
|
||||
{
|
||||
@ -105,9 +105,9 @@ TEST(CPUContextMac, InitializeContextX86) {
|
||||
&x86_thread_state32,
|
||||
&x86_float_state32,
|
||||
&x86_debug_state32);
|
||||
EXPECT_EQ(1u, cpu_context_x86.eax);
|
||||
EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw);
|
||||
EXPECT_EQ(6u, cpu_context_x86.dr0);
|
||||
EXPECT_EQ(cpu_context_x86.eax, 1u);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.ftw, 2u);
|
||||
EXPECT_EQ(cpu_context_x86.dr0, 6u);
|
||||
}
|
||||
|
||||
// Supply context in a universal “flavor” parameter expected to be used
|
||||
@ -132,9 +132,9 @@ TEST(CPUContextMac, InitializeContextX86) {
|
||||
&x86_thread_state32,
|
||||
&x86_float_state32,
|
||||
&x86_debug_state32);
|
||||
EXPECT_EQ(7u, cpu_context_x86.eax);
|
||||
EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw);
|
||||
EXPECT_EQ(3u, cpu_context_x86.dr0);
|
||||
EXPECT_EQ(cpu_context_x86.eax, 7u);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.ftw, 2u);
|
||||
EXPECT_EQ(cpu_context_x86.dr0, 3u);
|
||||
}
|
||||
|
||||
{
|
||||
@ -152,9 +152,9 @@ TEST(CPUContextMac, InitializeContextX86) {
|
||||
&x86_thread_state32,
|
||||
&x86_float_state32,
|
||||
&x86_debug_state32);
|
||||
EXPECT_EQ(1u, cpu_context_x86.eax);
|
||||
EXPECT_EQ(8u, cpu_context_x86.fxsave.ftw);
|
||||
EXPECT_EQ(3u, cpu_context_x86.dr0);
|
||||
EXPECT_EQ(cpu_context_x86.eax, 1u);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.ftw, 8u);
|
||||
EXPECT_EQ(cpu_context_x86.dr0, 3u);
|
||||
}
|
||||
|
||||
{
|
||||
@ -172,9 +172,9 @@ TEST(CPUContextMac, InitializeContextX86) {
|
||||
&x86_thread_state32,
|
||||
&x86_float_state32,
|
||||
&x86_debug_state32);
|
||||
EXPECT_EQ(1u, cpu_context_x86.eax);
|
||||
EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw);
|
||||
EXPECT_EQ(9u, cpu_context_x86.dr0);
|
||||
EXPECT_EQ(cpu_context_x86.eax, 1u);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.ftw, 2u);
|
||||
EXPECT_EQ(cpu_context_x86.dr0, 9u);
|
||||
}
|
||||
|
||||
// Supply inappropriate “flavor” contexts to test that
|
||||
@ -194,9 +194,9 @@ TEST(CPUContextMac, InitializeContextX86) {
|
||||
&x86_thread_state32,
|
||||
&x86_float_state32,
|
||||
&x86_debug_state32);
|
||||
EXPECT_EQ(1u, cpu_context_x86.eax);
|
||||
EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw);
|
||||
EXPECT_EQ(3u, cpu_context_x86.dr0);
|
||||
EXPECT_EQ(cpu_context_x86.eax, 1u);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.ftw, 2u);
|
||||
EXPECT_EQ(cpu_context_x86.dr0, 3u);
|
||||
}
|
||||
|
||||
{
|
||||
@ -213,9 +213,9 @@ TEST(CPUContextMac, InitializeContextX86) {
|
||||
&x86_thread_state32,
|
||||
&x86_float_state32,
|
||||
&x86_debug_state32);
|
||||
EXPECT_EQ(1u, cpu_context_x86.eax);
|
||||
EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw);
|
||||
EXPECT_EQ(3u, cpu_context_x86.dr0);
|
||||
EXPECT_EQ(cpu_context_x86.eax, 1u);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.ftw, 2u);
|
||||
EXPECT_EQ(cpu_context_x86.dr0, 3u);
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,9 +238,9 @@ TEST(CPUContextMac, InitializeContextX86_64) {
|
||||
&x86_thread_state64,
|
||||
&x86_float_state64,
|
||||
&x86_debug_state64);
|
||||
EXPECT_EQ(10u, cpu_context_x86_64.rax);
|
||||
EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw);
|
||||
EXPECT_EQ(12u, cpu_context_x86_64.dr0);
|
||||
EXPECT_EQ(cpu_context_x86_64.rax, 10u);
|
||||
EXPECT_EQ(cpu_context_x86_64.fxsave.ftw, 11u);
|
||||
EXPECT_EQ(cpu_context_x86_64.dr0, 12u);
|
||||
}
|
||||
|
||||
// Supply context in a CPU-specific “flavor” parameter expected to be used
|
||||
@ -264,9 +264,9 @@ TEST(CPUContextMac, InitializeContextX86_64) {
|
||||
&x86_thread_state64,
|
||||
&x86_float_state64,
|
||||
&x86_debug_state64);
|
||||
EXPECT_EQ(13u, cpu_context_x86_64.rax);
|
||||
EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw);
|
||||
EXPECT_EQ(12u, cpu_context_x86_64.dr0);
|
||||
EXPECT_EQ(cpu_context_x86_64.rax, 13u);
|
||||
EXPECT_EQ(cpu_context_x86_64.fxsave.ftw, 11u);
|
||||
EXPECT_EQ(cpu_context_x86_64.dr0, 12u);
|
||||
}
|
||||
|
||||
{
|
||||
@ -282,9 +282,9 @@ TEST(CPUContextMac, InitializeContextX86_64) {
|
||||
&x86_thread_state64,
|
||||
&x86_float_state64,
|
||||
&x86_debug_state64);
|
||||
EXPECT_EQ(10u, cpu_context_x86_64.rax);
|
||||
EXPECT_EQ(14u, cpu_context_x86_64.fxsave.ftw);
|
||||
EXPECT_EQ(12u, cpu_context_x86_64.dr0);
|
||||
EXPECT_EQ(cpu_context_x86_64.rax, 10u);
|
||||
EXPECT_EQ(cpu_context_x86_64.fxsave.ftw, 14u);
|
||||
EXPECT_EQ(cpu_context_x86_64.dr0, 12u);
|
||||
}
|
||||
|
||||
{
|
||||
@ -300,9 +300,9 @@ TEST(CPUContextMac, InitializeContextX86_64) {
|
||||
&x86_thread_state64,
|
||||
&x86_float_state64,
|
||||
&x86_debug_state64);
|
||||
EXPECT_EQ(10u, cpu_context_x86_64.rax);
|
||||
EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw);
|
||||
EXPECT_EQ(15u, cpu_context_x86_64.dr0);
|
||||
EXPECT_EQ(cpu_context_x86_64.rax, 10u);
|
||||
EXPECT_EQ(cpu_context_x86_64.fxsave.ftw, 11u);
|
||||
EXPECT_EQ(cpu_context_x86_64.dr0, 15u);
|
||||
}
|
||||
|
||||
// Supply context in a universal “flavor” parameter expected to be used
|
||||
@ -327,9 +327,9 @@ TEST(CPUContextMac, InitializeContextX86_64) {
|
||||
&x86_thread_state64,
|
||||
&x86_float_state64,
|
||||
&x86_debug_state64);
|
||||
EXPECT_EQ(16u, cpu_context_x86_64.rax);
|
||||
EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw);
|
||||
EXPECT_EQ(12u, cpu_context_x86_64.dr0);
|
||||
EXPECT_EQ(cpu_context_x86_64.rax, 16u);
|
||||
EXPECT_EQ(cpu_context_x86_64.fxsave.ftw, 11u);
|
||||
EXPECT_EQ(cpu_context_x86_64.dr0, 12u);
|
||||
}
|
||||
|
||||
{
|
||||
@ -347,9 +347,9 @@ TEST(CPUContextMac, InitializeContextX86_64) {
|
||||
&x86_thread_state64,
|
||||
&x86_float_state64,
|
||||
&x86_debug_state64);
|
||||
EXPECT_EQ(10u, cpu_context_x86_64.rax);
|
||||
EXPECT_EQ(17u, cpu_context_x86_64.fxsave.ftw);
|
||||
EXPECT_EQ(12u, cpu_context_x86_64.dr0);
|
||||
EXPECT_EQ(cpu_context_x86_64.rax, 10u);
|
||||
EXPECT_EQ(cpu_context_x86_64.fxsave.ftw, 17u);
|
||||
EXPECT_EQ(cpu_context_x86_64.dr0, 12u);
|
||||
}
|
||||
|
||||
{
|
||||
@ -367,9 +367,9 @@ TEST(CPUContextMac, InitializeContextX86_64) {
|
||||
&x86_thread_state64,
|
||||
&x86_float_state64,
|
||||
&x86_debug_state64);
|
||||
EXPECT_EQ(10u, cpu_context_x86_64.rax);
|
||||
EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw);
|
||||
EXPECT_EQ(18u, cpu_context_x86_64.dr0);
|
||||
EXPECT_EQ(cpu_context_x86_64.rax, 10u);
|
||||
EXPECT_EQ(cpu_context_x86_64.fxsave.ftw, 11u);
|
||||
EXPECT_EQ(cpu_context_x86_64.dr0, 18u);
|
||||
}
|
||||
|
||||
// Supply inappropriate “flavor” contexts to test that
|
||||
@ -389,9 +389,9 @@ TEST(CPUContextMac, InitializeContextX86_64) {
|
||||
&x86_thread_state64,
|
||||
&x86_float_state64,
|
||||
&x86_debug_state64);
|
||||
EXPECT_EQ(10u, cpu_context_x86_64.rax);
|
||||
EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw);
|
||||
EXPECT_EQ(12u, cpu_context_x86_64.dr0);
|
||||
EXPECT_EQ(cpu_context_x86_64.rax, 10u);
|
||||
EXPECT_EQ(cpu_context_x86_64.fxsave.ftw, 11u);
|
||||
EXPECT_EQ(cpu_context_x86_64.dr0, 12u);
|
||||
}
|
||||
|
||||
{
|
||||
@ -408,9 +408,9 @@ TEST(CPUContextMac, InitializeContextX86_64) {
|
||||
&x86_thread_state64,
|
||||
&x86_float_state64,
|
||||
&x86_debug_state64);
|
||||
EXPECT_EQ(10u, cpu_context_x86_64.rax);
|
||||
EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw);
|
||||
EXPECT_EQ(12u, cpu_context_x86_64.dr0);
|
||||
EXPECT_EQ(cpu_context_x86_64.rax, 10u);
|
||||
EXPECT_EQ(cpu_context_x86_64.fxsave.ftw, 11u);
|
||||
EXPECT_EQ(cpu_context_x86_64.dr0, 12u);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include "test/errors.h"
|
||||
#include "test/mac/mach_errors.h"
|
||||
#include "test/mac/mach_multiprocess.h"
|
||||
#include "test/paths.h"
|
||||
#include "test/test_paths.h"
|
||||
#include "util/file/file_io.h"
|
||||
#include "util/mac/mac_util.h"
|
||||
#include "util/mach/exc_server_variants.h"
|
||||
@ -50,12 +50,12 @@ namespace {
|
||||
|
||||
// \return The path to crashpad_snapshot_test_module_crashy_initializer.so
|
||||
std::string ModuleWithCrashyInitializer() {
|
||||
return Paths::Executable().value() + "_module_crashy_initializer.so";
|
||||
return TestPaths::Executable().value() + "_module_crashy_initializer.so";
|
||||
}
|
||||
|
||||
//! \return The path to the crashpad_snapshot_test_no_op executable.
|
||||
base::FilePath NoOpExecutable() {
|
||||
return base::FilePath(Paths::Executable().value() + "_no_op");
|
||||
return base::FilePath(TestPaths::Executable().value() + "_no_op");
|
||||
}
|
||||
|
||||
class TestMachOImageAnnotationsReader final
|
||||
@ -121,14 +121,14 @@ class TestMachOImageAnnotationsReader final
|
||||
// In 10.12.1 and later, the task port will not match ChildTask() in the
|
||||
// kCrashDyld case, because kCrashDyld uses execl(), which results in a
|
||||
// new task port being assigned.
|
||||
EXPECT_EQ(ChildTask(), task);
|
||||
EXPECT_EQ(task, ChildTask());
|
||||
}
|
||||
|
||||
// The process ID should always compare favorably.
|
||||
pid_t task_pid;
|
||||
kern_return_t kr = pid_for_task(task, &task_pid);
|
||||
EXPECT_EQ(KERN_SUCCESS, kr) << MachErrorMessage(kr, "pid_for_task");
|
||||
EXPECT_EQ(ChildPID(), task_pid);
|
||||
EXPECT_EQ(kr, KERN_SUCCESS) << MachErrorMessage(kr, "pid_for_task");
|
||||
EXPECT_EQ(task_pid, ChildPID());
|
||||
|
||||
ProcessReader process_reader;
|
||||
bool rv = process_reader.Initialize(task);
|
||||
@ -261,11 +261,11 @@ class TestMachOImageAnnotationsReader final
|
||||
}
|
||||
|
||||
EXPECT_GE(all_annotations_simple_map.size(), 5u);
|
||||
EXPECT_EQ("crash", all_annotations_simple_map["#TEST# pad"]);
|
||||
EXPECT_EQ("value", all_annotations_simple_map["#TEST# key"]);
|
||||
EXPECT_EQ("y", all_annotations_simple_map["#TEST# x"]);
|
||||
EXPECT_EQ("shorter", all_annotations_simple_map["#TEST# longer"]);
|
||||
EXPECT_EQ("", all_annotations_simple_map["#TEST# empty_value"]);
|
||||
EXPECT_EQ(all_annotations_simple_map["#TEST# pad"], "crash");
|
||||
EXPECT_EQ(all_annotations_simple_map["#TEST# key"], "value");
|
||||
EXPECT_EQ(all_annotations_simple_map["#TEST# x"], "y");
|
||||
EXPECT_EQ(all_annotations_simple_map["#TEST# longer"], "shorter");
|
||||
EXPECT_EQ(all_annotations_simple_map["#TEST# empty_value"], "");
|
||||
|
||||
// Tell the child process that it’s permitted to crash.
|
||||
CheckedWriteFile(WritePipeHandle(), &c, sizeof(c));
|
||||
@ -282,7 +282,7 @@ class TestMachOImageAnnotationsReader final
|
||||
MachMessageServer::kOneShot,
|
||||
MachMessageServer::kReceiveLargeError,
|
||||
kMachMessageTimeoutWaitIndefinitely);
|
||||
EXPECT_EQ(MACH_MSG_SUCCESS, mr)
|
||||
EXPECT_EQ(mr, MACH_MSG_SUCCESS)
|
||||
<< MachErrorMessage(mr, "MachMessageServer::Run");
|
||||
|
||||
switch (test_type_) {
|
||||
@ -360,7 +360,7 @@ class TestMachOImageAnnotationsReader final
|
||||
// This should have crashed in the dlopen(). If dlopen() failed, the
|
||||
// ASSERT_NE() will show the message. If it succeeded without crashing,
|
||||
// the FAIL() will fail the test.
|
||||
ASSERT_NE(nullptr, dl_handle) << dlerror();
|
||||
ASSERT_NE(dl_handle, nullptr) << dlerror();
|
||||
FAIL();
|
||||
break;
|
||||
}
|
||||
@ -369,9 +369,9 @@ class TestMachOImageAnnotationsReader final
|
||||
// Set DYLD_INSERT_LIBRARIES to contain a library that does not exist.
|
||||
// Unable to load it, dyld will abort with a fatal error.
|
||||
ASSERT_EQ(
|
||||
0,
|
||||
setenv(
|
||||
"DYLD_INSERT_LIBRARIES", "/var/empty/NoDirectory/NoLibrary", 1))
|
||||
"DYLD_INSERT_LIBRARIES", "/var/empty/NoDirectory/NoLibrary", 1),
|
||||
0)
|
||||
<< ErrnoMessage("setenv");
|
||||
|
||||
// The actual executable doesn’t matter very much, because dyld won’t
|
||||
@ -381,9 +381,10 @@ class TestMachOImageAnnotationsReader final
|
||||
// with system executables on OS X 10.11 due to System Integrity
|
||||
// Protection.
|
||||
base::FilePath no_op_executable = NoOpExecutable();
|
||||
ASSERT_EQ(0, execl(no_op_executable.value().c_str(),
|
||||
no_op_executable.BaseName().value().c_str(),
|
||||
nullptr))
|
||||
ASSERT_EQ(execl(no_op_executable.value().c_str(),
|
||||
no_op_executable.BaseName().value().c_str(),
|
||||
nullptr),
|
||||
0)
|
||||
<< ErrnoMessage("execl");
|
||||
break;
|
||||
}
|
||||
|
@ -76,20 +76,20 @@ void ExpectSection(const Section* expect_section,
|
||||
ASSERT_TRUE(actual_section);
|
||||
|
||||
EXPECT_EQ(
|
||||
MachOImageSegmentReader::SectionNameString(expect_section->sectname),
|
||||
MachOImageSegmentReader::SectionNameString(actual_section->sectname));
|
||||
MachOImageSegmentReader::SectionNameString(actual_section->sectname),
|
||||
MachOImageSegmentReader::SectionNameString(expect_section->sectname));
|
||||
EXPECT_EQ(
|
||||
MachOImageSegmentReader::SegmentNameString(expect_section->segname),
|
||||
MachOImageSegmentReader::SegmentNameString(actual_section->segname));
|
||||
EXPECT_EQ(expect_section->addr, actual_section->addr);
|
||||
EXPECT_EQ(expect_section->size, actual_section->size);
|
||||
EXPECT_EQ(expect_section->offset, actual_section->offset);
|
||||
EXPECT_EQ(expect_section->align, actual_section->align);
|
||||
EXPECT_EQ(expect_section->reloff, actual_section->reloff);
|
||||
EXPECT_EQ(expect_section->nreloc, actual_section->nreloc);
|
||||
EXPECT_EQ(expect_section->flags, actual_section->flags);
|
||||
EXPECT_EQ(expect_section->reserved1, actual_section->reserved1);
|
||||
EXPECT_EQ(expect_section->reserved2, actual_section->reserved2);
|
||||
MachOImageSegmentReader::SegmentNameString(actual_section->segname),
|
||||
MachOImageSegmentReader::SegmentNameString(expect_section->segname));
|
||||
EXPECT_EQ(actual_section->addr, expect_section->addr);
|
||||
EXPECT_EQ(actual_section->size, expect_section->size);
|
||||
EXPECT_EQ(actual_section->offset, expect_section->offset);
|
||||
EXPECT_EQ(actual_section->align, expect_section->align);
|
||||
EXPECT_EQ(actual_section->reloff, expect_section->reloff);
|
||||
EXPECT_EQ(actual_section->nreloc, expect_section->nreloc);
|
||||
EXPECT_EQ(actual_section->flags, expect_section->flags);
|
||||
EXPECT_EQ(actual_section->reserved1, expect_section->reserved1);
|
||||
EXPECT_EQ(actual_section->reserved2, expect_section->reserved2);
|
||||
}
|
||||
|
||||
// Verifies that |expect_segment| is a valid Mach-O segment load command for the
|
||||
@ -115,27 +115,28 @@ void ExpectSegmentCommand(const SegmentCommand* expect_segment,
|
||||
ASSERT_TRUE(expect_segment);
|
||||
ASSERT_TRUE(actual_segment);
|
||||
|
||||
EXPECT_EQ(kSegmentCommand, expect_segment->cmd);
|
||||
EXPECT_EQ(expect_segment->cmd, kSegmentCommand);
|
||||
|
||||
std::string segment_name = actual_segment->Name();
|
||||
EXPECT_EQ(MachOImageSegmentReader::SegmentNameString(expect_segment->segname),
|
||||
segment_name);
|
||||
EXPECT_EQ(expect_segment->vmaddr, actual_segment->vmaddr());
|
||||
EXPECT_EQ(expect_segment->vmsize, actual_segment->vmsize());
|
||||
EXPECT_EQ(expect_segment->fileoff, actual_segment->fileoff());
|
||||
EXPECT_EQ(
|
||||
segment_name,
|
||||
MachOImageSegmentReader::SegmentNameString(expect_segment->segname));
|
||||
EXPECT_EQ(actual_segment->vmaddr(), expect_segment->vmaddr);
|
||||
EXPECT_EQ(actual_segment->vmsize(), expect_segment->vmsize);
|
||||
EXPECT_EQ(actual_segment->fileoff(), expect_segment->fileoff);
|
||||
|
||||
if (actual_segment->SegmentSlides()) {
|
||||
EXPECT_EQ(actual_segment->Address(),
|
||||
actual_segment->vmaddr() + actual_image->Slide());
|
||||
EXPECT_EQ(actual_segment->vmaddr() + actual_image->Slide(),
|
||||
actual_segment->Address());
|
||||
|
||||
unsigned long expect_segment_size;
|
||||
const uint8_t* expect_segment_data = getsegmentdata(
|
||||
expect_image, segment_name.c_str(), &expect_segment_size);
|
||||
mach_vm_address_t expect_segment_address =
|
||||
reinterpret_cast<mach_vm_address_t>(expect_segment_data);
|
||||
EXPECT_EQ(expect_segment_address, actual_segment->Address());
|
||||
EXPECT_EQ(expect_segment_size, actual_segment->vmsize());
|
||||
EXPECT_EQ(actual_segment->vmsize(), actual_segment->Size());
|
||||
EXPECT_EQ(actual_segment->Address(), expect_segment_address);
|
||||
EXPECT_EQ(actual_segment->vmsize(), expect_segment_size);
|
||||
EXPECT_EQ(actual_segment->Size(), actual_segment->vmsize());
|
||||
} else {
|
||||
// getsegmentdata() doesn’t return appropriate data for the __PAGEZERO
|
||||
// segment because getsegmentdata() always adjusts for slide, but the
|
||||
@ -143,18 +144,18 @@ void ExpectSegmentCommand(const SegmentCommand* expect_segment,
|
||||
// check for that segment according to the same rules that the kernel uses
|
||||
// to identify __PAGEZERO. See 10.9.4 xnu-2422.110.17/bsd/kern/mach_loader.c
|
||||
// load_segment().
|
||||
EXPECT_EQ(actual_segment->Address(), actual_segment->vmaddr());
|
||||
EXPECT_EQ(actual_segment->vmsize() + actual_image->Slide(),
|
||||
actual_segment->Size());
|
||||
EXPECT_EQ(actual_segment->vmaddr(), actual_segment->Address());
|
||||
EXPECT_EQ(actual_segment->Size(),
|
||||
actual_segment->vmsize() + actual_image->Slide());
|
||||
}
|
||||
|
||||
ASSERT_EQ(expect_segment->nsects, actual_segment->nsects());
|
||||
ASSERT_EQ(actual_segment->nsects(), expect_segment->nsects);
|
||||
|
||||
// Make sure that the expected load command is big enough for the number of
|
||||
// sections that it claims to have, and set up a pointer to its first section
|
||||
// structure.
|
||||
ASSERT_EQ(sizeof(*expect_segment) + expect_segment->nsects * sizeof(Section),
|
||||
expect_segment->cmdsize);
|
||||
ASSERT_EQ(expect_segment->cmdsize,
|
||||
sizeof(*expect_segment) + expect_segment->nsects * sizeof(Section));
|
||||
const Section* expect_sections =
|
||||
reinterpret_cast<const Section*>(&expect_segment[1]);
|
||||
|
||||
@ -170,7 +171,7 @@ void ExpectSegmentCommand(const SegmentCommand* expect_segment,
|
||||
MachOImageSegmentReader::SectionNameString(expect_section->sectname);
|
||||
const process_types::section* actual_section_by_name =
|
||||
actual_segment->GetSectionByName(section_name, nullptr);
|
||||
EXPECT_EQ(actual_section, actual_section_by_name);
|
||||
EXPECT_EQ(actual_section_by_name, actual_section);
|
||||
|
||||
// Make sure that the section is accessible by the parent MachOImageReader’s
|
||||
// GetSectionByName.
|
||||
@ -178,11 +179,11 @@ void ExpectSegmentCommand(const SegmentCommand* expect_segment,
|
||||
const process_types::section* actual_section_from_image_by_name =
|
||||
actual_image->GetSectionByName(
|
||||
segment_name, section_name, &actual_section_address);
|
||||
EXPECT_EQ(actual_section, actual_section_from_image_by_name);
|
||||
EXPECT_EQ(actual_section_from_image_by_name, actual_section);
|
||||
|
||||
if (actual_segment->SegmentSlides()) {
|
||||
EXPECT_EQ(actual_section_address,
|
||||
actual_section->addr + actual_image->Slide());
|
||||
EXPECT_EQ(actual_section->addr + actual_image->Slide(),
|
||||
actual_section_address);
|
||||
|
||||
unsigned long expect_section_size;
|
||||
const uint8_t* expect_section_data = getsectiondata(expect_image,
|
||||
@ -191,10 +192,10 @@ void ExpectSegmentCommand(const SegmentCommand* expect_segment,
|
||||
&expect_section_size);
|
||||
mach_vm_address_t expect_section_address =
|
||||
reinterpret_cast<mach_vm_address_t>(expect_section_data);
|
||||
EXPECT_EQ(expect_section_address, actual_section_address);
|
||||
EXPECT_EQ(expect_section_size, actual_section->size);
|
||||
EXPECT_EQ(actual_section_address, expect_section_address);
|
||||
EXPECT_EQ(actual_section->size, expect_section_size);
|
||||
} else {
|
||||
EXPECT_EQ(actual_section_address, actual_section->addr);
|
||||
EXPECT_EQ(actual_section->addr, actual_section_address);
|
||||
}
|
||||
|
||||
// Test the parent MachOImageReader’s GetSectionAtIndex as well.
|
||||
@ -204,13 +205,13 @@ void ExpectSegmentCommand(const SegmentCommand* expect_segment,
|
||||
actual_image->GetSectionAtIndex(++(*section_index),
|
||||
&containing_segment,
|
||||
&actual_section_address_at_index);
|
||||
EXPECT_EQ(actual_section, actual_section_from_image_at_index);
|
||||
EXPECT_EQ(actual_segment, containing_segment);
|
||||
EXPECT_EQ(actual_section_address, actual_section_address_at_index);
|
||||
EXPECT_EQ(actual_section_from_image_at_index, actual_section);
|
||||
EXPECT_EQ(containing_segment, actual_segment);
|
||||
EXPECT_EQ(actual_section_address_at_index, actual_section_address);
|
||||
}
|
||||
|
||||
EXPECT_EQ(nullptr,
|
||||
actual_segment->GetSectionByName("NoSuchSection", nullptr));
|
||||
EXPECT_EQ(actual_segment->GetSectionByName("NoSuchSection", nullptr),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
// Walks through the load commands of |expect_image|, finding all of the
|
||||
@ -256,15 +257,15 @@ void ExpectSegmentCommands(const MachHeader* expect_image,
|
||||
}
|
||||
position += command->cmdsize;
|
||||
}
|
||||
EXPECT_EQ(expect_image->sizeofcmds, position);
|
||||
EXPECT_EQ(position, expect_image->sizeofcmds);
|
||||
|
||||
if (test_section_index_bounds) {
|
||||
// GetSectionAtIndex uses a 1-based index. Make sure that the range is
|
||||
// correct.
|
||||
EXPECT_EQ(nullptr, actual_image->GetSectionAtIndex(0, nullptr, nullptr));
|
||||
EXPECT_EQ(actual_image->GetSectionAtIndex(0, nullptr, nullptr), nullptr);
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
actual_image->GetSectionAtIndex(section_index + 1, nullptr, nullptr));
|
||||
actual_image->GetSectionAtIndex(section_index + 1, nullptr, nullptr),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
// Make sure that by-name lookups for names that don’t exist work properly:
|
||||
@ -306,9 +307,9 @@ void ExpectSegmentCommands(const MachHeader* expect_image,
|
||||
MachOImageSegmentReader::SectionNameString(section->sectname);
|
||||
|
||||
// It should be possible to look up the first section by name.
|
||||
EXPECT_EQ(section,
|
||||
actual_image->GetSectionByName(
|
||||
section->segname, section->sectname, nullptr));
|
||||
EXPECT_EQ(actual_image->GetSectionByName(
|
||||
section->segname, section->sectname, nullptr),
|
||||
section);
|
||||
}
|
||||
EXPECT_FALSE(
|
||||
actual_image->GetSectionByName("NoSuchSegment", test_section, nullptr));
|
||||
@ -345,29 +346,29 @@ void ExpectMachImage(const MachHeader* expect_image,
|
||||
ASSERT_TRUE(expect_image);
|
||||
ASSERT_TRUE(actual_image);
|
||||
|
||||
EXPECT_EQ(kMachMagic, expect_image->magic);
|
||||
EXPECT_EQ(kCPUType, expect_image->cputype);
|
||||
EXPECT_EQ(expect_image->magic, kMachMagic);
|
||||
EXPECT_EQ(expect_image->cputype, kCPUType);
|
||||
|
||||
EXPECT_EQ(expect_image->filetype, actual_image->FileType());
|
||||
EXPECT_EQ(expect_image_address, actual_image->Address());
|
||||
EXPECT_EQ(actual_image->FileType(), expect_image->filetype);
|
||||
EXPECT_EQ(actual_image->Address(), expect_image_address);
|
||||
if (expect_image_slide != kSlideUnknown) {
|
||||
EXPECT_EQ(expect_image_slide, actual_image->Slide());
|
||||
EXPECT_EQ(actual_image->Slide(), expect_image_slide);
|
||||
}
|
||||
|
||||
const MachOImageSegmentReader* actual_text_segment =
|
||||
actual_image->GetSegmentByName(SEG_TEXT);
|
||||
ASSERT_TRUE(actual_text_segment);
|
||||
EXPECT_EQ(expect_image_address, actual_text_segment->Address());
|
||||
EXPECT_EQ(actual_image->Size(), actual_text_segment->Size());
|
||||
EXPECT_EQ(expect_image_address - actual_text_segment->vmaddr(),
|
||||
actual_image->Slide());
|
||||
EXPECT_EQ(actual_text_segment->Address(), expect_image_address);
|
||||
EXPECT_EQ(actual_text_segment->Size(), actual_image->Size());
|
||||
EXPECT_EQ(actual_image->Slide(),
|
||||
expect_image_address - actual_text_segment->vmaddr());
|
||||
|
||||
uint32_t file_type = actual_image->FileType();
|
||||
EXPECT_TRUE(file_type == MH_EXECUTE || file_type == MH_DYLIB ||
|
||||
file_type == MH_DYLINKER || file_type == MH_BUNDLE);
|
||||
|
||||
if (file_type == MH_EXECUTE || file_type == MH_DYLINKER) {
|
||||
EXPECT_EQ("/usr/lib/dyld", actual_image->DylinkerName());
|
||||
EXPECT_EQ(actual_image->DylinkerName(), "/usr/lib/dyld");
|
||||
}
|
||||
|
||||
// For these, just don’t crash or anything.
|
||||
@ -418,10 +419,10 @@ void ExpectSymbol(const Nlist* entry,
|
||||
EXPECT_GE(entry->n_sect, 1u);
|
||||
expect_address += actual_image->Slide();
|
||||
} else {
|
||||
EXPECT_EQ(NO_SECT, entry->n_sect);
|
||||
EXPECT_EQ(entry->n_sect, NO_SECT);
|
||||
}
|
||||
|
||||
EXPECT_EQ(expect_address, actual_address);
|
||||
EXPECT_EQ(actual_address, expect_address);
|
||||
}
|
||||
|
||||
// You’d think that it might be a good idea to verify that if the conditions
|
||||
@ -452,7 +453,7 @@ void ExpectSymbolTable(const MachHeader* expect_image,
|
||||
ASSERT_LE(position + command->cmdsize, expect_image->sizeofcmds);
|
||||
if (command->cmd == LC_SYMTAB) {
|
||||
ASSERT_FALSE(symtab);
|
||||
ASSERT_EQ(sizeof(symtab_command), command->cmdsize);
|
||||
ASSERT_EQ(command->cmdsize, sizeof(symtab_command));
|
||||
symtab = reinterpret_cast<const symtab_command*>(command);
|
||||
} else if (command->cmd == kSegmentCommand) {
|
||||
ASSERT_GE(command->cmdsize, sizeof(SegmentCommand));
|
||||
@ -498,7 +499,7 @@ TEST(MachOImageReader, Self_MainExecutable) {
|
||||
|
||||
const MachHeader* mh_execute_header =
|
||||
reinterpret_cast<MachHeader*>(dlsym(RTLD_MAIN_ONLY, MH_EXECUTE_SYM));
|
||||
ASSERT_NE(nullptr, mh_execute_header);
|
||||
ASSERT_NE(mh_execute_header, nullptr);
|
||||
mach_vm_address_t mh_execute_header_address =
|
||||
reinterpret_cast<mach_vm_address_t>(mh_execute_header);
|
||||
|
||||
@ -506,7 +507,7 @@ TEST(MachOImageReader, Self_MainExecutable) {
|
||||
ASSERT_TRUE(image_reader.Initialize(
|
||||
&process_reader, mh_execute_header_address, "executable"));
|
||||
|
||||
EXPECT_EQ(implicit_cast<uint32_t>(MH_EXECUTE), image_reader.FileType());
|
||||
EXPECT_EQ(image_reader.FileType(), implicit_cast<uint32_t>(MH_EXECUTE));
|
||||
|
||||
// The main executable has image index 0.
|
||||
intptr_t image_slide = _dyld_get_image_vmaddr_slide(0);
|
||||
@ -522,7 +523,7 @@ TEST(MachOImageReader, Self_MainExecutable) {
|
||||
mach_vm_address_t symbol_address;
|
||||
ASSERT_TRUE(image_reader.LookUpExternalDefinedSymbol(_MH_EXECUTE_SYM,
|
||||
&symbol_address));
|
||||
EXPECT_EQ(mh_execute_header_address, symbol_address);
|
||||
EXPECT_EQ(symbol_address, mh_execute_header_address);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(ExpectSymbolTable(mh_execute_header, &image_reader));
|
||||
}
|
||||
@ -554,7 +555,7 @@ TEST(MachOImageReader, Self_DyldImages) {
|
||||
|
||||
uint32_t file_type = image_reader.FileType();
|
||||
if (index == 0) {
|
||||
EXPECT_EQ(implicit_cast<uint32_t>(MH_EXECUTE), file_type);
|
||||
EXPECT_EQ(file_type, implicit_cast<uint32_t>(MH_EXECUTE));
|
||||
} else {
|
||||
EXPECT_TRUE(file_type == MH_DYLIB || file_type == MH_BUNDLE);
|
||||
}
|
||||
@ -578,7 +579,7 @@ TEST(MachOImageReader, Self_DyldImages) {
|
||||
const struct dyld_all_image_infos* dyld_image_infos =
|
||||
_dyld_get_all_image_infos();
|
||||
ASSERT_GE(dyld_image_infos->version, 1u);
|
||||
EXPECT_EQ(count, dyld_image_infos->infoArrayCount);
|
||||
EXPECT_EQ(dyld_image_infos->infoArrayCount, count);
|
||||
|
||||
if (dyld_image_infos->version >= 2) {
|
||||
SCOPED_TRACE("dyld");
|
||||
@ -593,7 +594,7 @@ TEST(MachOImageReader, Self_DyldImages) {
|
||||
ASSERT_TRUE(
|
||||
image_reader.Initialize(&process_reader, image_address, "dyld"));
|
||||
|
||||
EXPECT_EQ(implicit_cast<uint32_t>(MH_DYLINKER), image_reader.FileType());
|
||||
EXPECT_EQ(image_reader.FileType(), implicit_cast<uint32_t>(MH_DYLINKER));
|
||||
|
||||
// There’s no good API to get dyld’s slide, so don’t bother checking it.
|
||||
ASSERT_NO_FATAL_FAILURE(ExpectMachImage(
|
||||
@ -634,7 +635,7 @@ TEST(MachOImageReader, Self_DyldImages) {
|
||||
expected_uuid.InitializeFromBytes(dyld_image->imageUUID);
|
||||
UUID actual_uuid;
|
||||
image_reader.UUID(&actual_uuid);
|
||||
EXPECT_EQ(expected_uuid, actual_uuid);
|
||||
EXPECT_EQ(actual_uuid, expected_uuid);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -36,20 +36,20 @@ namespace {
|
||||
TEST(MachOImageSegmentReader, SegmentNameString) {
|
||||
// The output value should be a string of up to 16 characters, even if the
|
||||
// input value is not NUL-terminated within 16 characters.
|
||||
EXPECT_EQ("__TEXT", MachOImageSegmentReader::SegmentNameString("__TEXT"));
|
||||
EXPECT_EQ("__OVER", MachOImageSegmentReader::SegmentNameString("__OVER"));
|
||||
EXPECT_EQ("", MachOImageSegmentReader::SegmentNameString(""));
|
||||
EXPECT_EQ("p", MachOImageSegmentReader::SegmentNameString("p"));
|
||||
EXPECT_EQ("NoUnderChar",
|
||||
MachOImageSegmentReader::SegmentNameString("NoUnderChar"));
|
||||
EXPECT_EQ("0123456789abcde",
|
||||
MachOImageSegmentReader::SegmentNameString("0123456789abcde"));
|
||||
EXPECT_EQ("0123456789abcdef",
|
||||
MachOImageSegmentReader::SegmentNameString("0123456789abcdef"));
|
||||
EXPECT_EQ("gfedcba987654321",
|
||||
MachOImageSegmentReader::SegmentNameString("gfedcba9876543210"));
|
||||
EXPECT_EQ("hgfedcba98765432",
|
||||
MachOImageSegmentReader::SegmentNameString("hgfedcba9876543210"));
|
||||
EXPECT_EQ(MachOImageSegmentReader::SegmentNameString("__TEXT"), "__TEXT");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SegmentNameString("__OVER"), "__OVER");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SegmentNameString(""), "");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SegmentNameString("p"), "p");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SegmentNameString("NoUnderChar"),
|
||||
"NoUnderChar");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SegmentNameString("0123456789abcde"),
|
||||
"0123456789abcde");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SegmentNameString("0123456789abcdef"),
|
||||
"0123456789abcdef");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SegmentNameString("gfedcba9876543210"),
|
||||
"gfedcba987654321");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SegmentNameString("hgfedcba9876543210"),
|
||||
"hgfedcba98765432");
|
||||
|
||||
// Segment names defined in <mach-o/loader.h>. All of these should come
|
||||
// through SegmentNameString() cleanly and without truncation.
|
||||
@ -65,8 +65,8 @@ TEST(MachOImageSegmentReader, SegmentNameString) {
|
||||
|
||||
for (size_t index = 0; index < arraysize(kSegmentTestData); ++index) {
|
||||
EXPECT_EQ(
|
||||
kSegmentTestData[index],
|
||||
MachOImageSegmentReader::SegmentNameString(kSegmentTestData[index]))
|
||||
MachOImageSegmentReader::SegmentNameString(kSegmentTestData[index]),
|
||||
kSegmentTestData[index])
|
||||
<< base::StringPrintf("index %zu", index);
|
||||
}
|
||||
}
|
||||
@ -74,20 +74,20 @@ TEST(MachOImageSegmentReader, SegmentNameString) {
|
||||
TEST(MachOImageSegmentReader, SectionNameString) {
|
||||
// The output value should be a string of up to 16 characters, even if the
|
||||
// input value is not NUL-terminated within 16 characters.
|
||||
EXPECT_EQ("__text", MachOImageSegmentReader::SectionNameString("__text"));
|
||||
EXPECT_EQ("__over", MachOImageSegmentReader::SectionNameString("__over"));
|
||||
EXPECT_EQ("", MachOImageSegmentReader::SectionNameString(""));
|
||||
EXPECT_EQ("p", MachOImageSegmentReader::SectionNameString("p"));
|
||||
EXPECT_EQ("NoUnderChar",
|
||||
MachOImageSegmentReader::SectionNameString("NoUnderChar"));
|
||||
EXPECT_EQ("0123456789abcde",
|
||||
MachOImageSegmentReader::SectionNameString("0123456789abcde"));
|
||||
EXPECT_EQ("0123456789abcdef",
|
||||
MachOImageSegmentReader::SectionNameString("0123456789abcdef"));
|
||||
EXPECT_EQ("gfedcba987654321",
|
||||
MachOImageSegmentReader::SectionNameString("gfedcba9876543210"));
|
||||
EXPECT_EQ("hgfedcba98765432",
|
||||
MachOImageSegmentReader::SectionNameString("hgfedcba9876543210"));
|
||||
EXPECT_EQ(MachOImageSegmentReader::SectionNameString("__text"), "__text");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SectionNameString("__over"), "__over");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SectionNameString(""), "");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SectionNameString("p"), "p");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SectionNameString("NoUnderChar"),
|
||||
"NoUnderChar");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SectionNameString("0123456789abcde"),
|
||||
"0123456789abcde");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SectionNameString("0123456789abcdef"),
|
||||
"0123456789abcdef");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SectionNameString("gfedcba9876543210"),
|
||||
"gfedcba987654321");
|
||||
EXPECT_EQ(MachOImageSegmentReader::SectionNameString("hgfedcba9876543210"),
|
||||
"hgfedcba98765432");
|
||||
|
||||
// Section names defined in <mach-o/loader.h>. All of these should come
|
||||
// through SectionNameString() cleanly and without truncation.
|
||||
@ -108,8 +108,8 @@ TEST(MachOImageSegmentReader, SectionNameString) {
|
||||
|
||||
for (size_t index = 0; index < arraysize(kSectionTestData); ++index) {
|
||||
EXPECT_EQ(
|
||||
kSectionTestData[index],
|
||||
MachOImageSegmentReader::SectionNameString(kSectionTestData[index]))
|
||||
MachOImageSegmentReader::SectionNameString(kSectionTestData[index]),
|
||||
kSectionTestData[index])
|
||||
<< base::StringPrintf("index %zu", index);
|
||||
}
|
||||
}
|
||||
@ -173,9 +173,9 @@ TEST(MachOImageSegmentReader, SegmentAndSectionNameString) {
|
||||
for (size_t index = 0; index < arraysize(kSegmentAndSectionTestData);
|
||||
++index) {
|
||||
const SegmentAndSectionTestData& test = kSegmentAndSectionTestData[index];
|
||||
EXPECT_EQ(test.output,
|
||||
MachOImageSegmentReader::SegmentAndSectionNameString(
|
||||
test.segment, test.section))
|
||||
EXPECT_EQ(MachOImageSegmentReader::SegmentAndSectionNameString(
|
||||
test.segment, test.section),
|
||||
test.output)
|
||||
<< base::StringPrintf("index %zu, segment %s, section %s",
|
||||
index,
|
||||
test.segment,
|
||||
|
@ -68,8 +68,8 @@ TEST(ProcessReader, SelfBasic) {
|
||||
EXPECT_TRUE(process_reader.Is64Bit());
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(getpid(), process_reader.ProcessID());
|
||||
EXPECT_EQ(getppid(), process_reader.ParentProcessID());
|
||||
EXPECT_EQ(process_reader.ProcessID(), getpid());
|
||||
EXPECT_EQ(process_reader.ParentProcessID(), getppid());
|
||||
|
||||
const char kTestMemory[] = "Some test memory";
|
||||
char buffer[arraysize(kTestMemory)];
|
||||
@ -99,8 +99,8 @@ class ProcessReaderChild final : public MachMultiprocess {
|
||||
EXPECT_TRUE(process_reader.Is64Bit());
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(getpid(), process_reader.ParentProcessID());
|
||||
EXPECT_EQ(ChildPID(), process_reader.ProcessID());
|
||||
EXPECT_EQ(process_reader.ParentProcessID(), getpid());
|
||||
EXPECT_EQ(process_reader.ProcessID(), ChildPID());
|
||||
|
||||
FileHandle read_handle = ReadPipeHandle();
|
||||
|
||||
@ -109,7 +109,7 @@ class ProcessReaderChild final : public MachMultiprocess {
|
||||
|
||||
std::string read_string;
|
||||
ASSERT_TRUE(process_reader.Memory()->ReadCString(address, &read_string));
|
||||
EXPECT_EQ(kTestMemory, read_string);
|
||||
EXPECT_EQ(read_string, kTestMemory);
|
||||
}
|
||||
|
||||
void MachMultiprocessChild() override {
|
||||
@ -153,12 +153,12 @@ TEST(ProcessReader, SelfOneThread) {
|
||||
// thread, not exactly one thread.
|
||||
ASSERT_GE(threads.size(), 1u);
|
||||
|
||||
EXPECT_EQ(PthreadToThreadID(pthread_self()), threads[0].id);
|
||||
EXPECT_EQ(threads[0].id, PthreadToThreadID(pthread_self()));
|
||||
|
||||
thread_t thread_self = MachThreadSelf();
|
||||
EXPECT_EQ(thread_self, threads[0].port);
|
||||
EXPECT_EQ(threads[0].port, thread_self);
|
||||
|
||||
EXPECT_EQ(0, threads[0].suspend_count);
|
||||
EXPECT_EQ(threads[0].suspend_count, 0);
|
||||
}
|
||||
|
||||
class TestThreadPool {
|
||||
@ -178,7 +178,7 @@ class TestThreadPool {
|
||||
thread_t thread_port = pthread_mach_thread_np(thread_info->pthread);
|
||||
while (thread_info->suspend_count > 0) {
|
||||
kern_return_t kr = thread_resume(thread_port);
|
||||
EXPECT_EQ(KERN_SUCCESS, kr) << MachErrorMessage(kr, "thread_resume");
|
||||
EXPECT_EQ(kr, KERN_SUCCESS) << MachErrorMessage(kr, "thread_resume");
|
||||
--thread_info->suspend_count;
|
||||
}
|
||||
}
|
||||
@ -207,7 +207,7 @@ class TestThreadPool {
|
||||
nullptr,
|
||||
ThreadMain,
|
||||
thread_info);
|
||||
ASSERT_EQ(0, rv);
|
||||
ASSERT_EQ(rv, 0);
|
||||
}
|
||||
|
||||
for (ThreadInfo* thread_info : thread_infos_) {
|
||||
@ -225,7 +225,7 @@ class TestThreadPool {
|
||||
suspend_count < thread_index;
|
||||
++suspend_count) {
|
||||
kern_return_t kr = thread_suspend(thread_port);
|
||||
EXPECT_EQ(KERN_SUCCESS, kr) << MachErrorMessage(kr, "thread_suspend");
|
||||
EXPECT_EQ(kr, KERN_SUCCESS) << MachErrorMessage(kr, "thread_suspend");
|
||||
if (kr == KERN_SUCCESS) {
|
||||
++thread_infos_[thread_index]->suspend_count;
|
||||
}
|
||||
@ -317,7 +317,7 @@ void ExpectSeveralThreads(ThreadMap* thread_map,
|
||||
if (tolerate_extra_threads) {
|
||||
ASSERT_GE(threads.size(), thread_map->size());
|
||||
} else {
|
||||
ASSERT_EQ(thread_map->size(), threads.size());
|
||||
ASSERT_EQ(threads.size(), thread_map->size());
|
||||
}
|
||||
|
||||
for (size_t thread_index = 0; thread_index < threads.size(); ++thread_index) {
|
||||
@ -328,14 +328,14 @@ void ExpectSeveralThreads(ThreadMap* thread_map,
|
||||
const auto& iterator = thread_map->find(thread.id);
|
||||
if (!tolerate_extra_threads) {
|
||||
// Make sure that the thread is in the expectation map.
|
||||
ASSERT_NE(thread_map->end(), iterator);
|
||||
ASSERT_NE(iterator, thread_map->end());
|
||||
}
|
||||
|
||||
if (iterator != thread_map->end()) {
|
||||
EXPECT_GE(iterator->second.stack_address, thread.stack_region_address);
|
||||
EXPECT_LT(iterator->second.stack_address, thread_stack_region_end);
|
||||
|
||||
EXPECT_EQ(iterator->second.suspend_count, thread.suspend_count);
|
||||
EXPECT_EQ(thread.suspend_count, iterator->second.suspend_count);
|
||||
|
||||
// Remove the thread from the expectation map since it’s already been
|
||||
// found. This makes it easy to check for duplicate thread IDs, and makes
|
||||
@ -350,14 +350,14 @@ void ExpectSeveralThreads(ThreadMap* thread_map,
|
||||
for (size_t other_thread_index = 0;
|
||||
other_thread_index < threads.size();
|
||||
++other_thread_index) {
|
||||
if (thread_index == other_thread_index) {
|
||||
if (other_thread_index == thread_index) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const ProcessReader::Thread& other_thread = threads[other_thread_index];
|
||||
|
||||
EXPECT_NE(thread.id, other_thread.id);
|
||||
EXPECT_NE(thread.port, other_thread.port);
|
||||
EXPECT_NE(other_thread.id, thread.id);
|
||||
EXPECT_NE(other_thread.port, thread.port);
|
||||
|
||||
mach_vm_address_t other_thread_stack_region_end =
|
||||
other_thread.stack_region_address + other_thread.stack_region_size;
|
||||
@ -398,7 +398,7 @@ TEST(ProcessReader, SelfSeveralThreads) {
|
||||
uint64_t thread_id = thread_pool.GetThreadInfo(thread_index, &expectation);
|
||||
|
||||
// There can’t be any duplicate thread IDs.
|
||||
EXPECT_EQ(0u, thread_map.count(thread_id));
|
||||
EXPECT_EQ(thread_map.count(thread_id), 0u);
|
||||
|
||||
thread_map[thread_id] = expectation;
|
||||
}
|
||||
@ -418,7 +418,7 @@ TEST(ProcessReader, SelfSeveralThreads) {
|
||||
if (thread.port == thread_self) {
|
||||
EXPECT_FALSE(found_thread_self);
|
||||
found_thread_self = true;
|
||||
EXPECT_EQ(self_thread_id, thread.id);
|
||||
EXPECT_EQ(thread.id, self_thread_id);
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(found_thread_self);
|
||||
@ -459,7 +459,7 @@ class ProcessReaderThreadedChild final : public MachMultiprocess {
|
||||
sizeof(expectation.suspend_count));
|
||||
|
||||
// There can’t be any duplicate thread IDs.
|
||||
EXPECT_EQ(0u, thread_map.count(thread_id));
|
||||
EXPECT_EQ(thread_map.count(thread_id), 0u);
|
||||
|
||||
thread_map[thread_id] = expectation;
|
||||
}
|
||||
@ -556,24 +556,24 @@ class ScopedOpenCLNoOpKernel {
|
||||
~ScopedOpenCLNoOpKernel() {
|
||||
if (kernel_) {
|
||||
cl_int rv = clReleaseKernel(kernel_);
|
||||
EXPECT_EQ(CL_SUCCESS, rv) << "clReleaseKernel";
|
||||
EXPECT_EQ(rv, CL_SUCCESS) << "clReleaseKernel";
|
||||
}
|
||||
|
||||
if (program_) {
|
||||
cl_int rv = clReleaseProgram(program_);
|
||||
EXPECT_EQ(CL_SUCCESS, rv) << "clReleaseProgram";
|
||||
EXPECT_EQ(rv, CL_SUCCESS) << "clReleaseProgram";
|
||||
}
|
||||
|
||||
if (context_) {
|
||||
cl_int rv = clReleaseContext(context_);
|
||||
EXPECT_EQ(CL_SUCCESS, rv) << "clReleaseContext";
|
||||
EXPECT_EQ(rv, CL_SUCCESS) << "clReleaseContext";
|
||||
}
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
cl_platform_id platform_id;
|
||||
cl_int rv = clGetPlatformIDs(1, &platform_id, nullptr);
|
||||
ASSERT_EQ(CL_SUCCESS, rv) << "clGetPlatformIDs";
|
||||
ASSERT_EQ(rv, CL_SUCCESS) << "clGetPlatformIDs";
|
||||
|
||||
// Use CL_DEVICE_TYPE_CPU to ensure that the kernel would execute on the
|
||||
// CPU. This is the only device type that a cl_kernels image will be created
|
||||
@ -581,10 +581,10 @@ class ScopedOpenCLNoOpKernel {
|
||||
cl_device_id device_id;
|
||||
rv =
|
||||
clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_CPU, 1, &device_id, nullptr);
|
||||
ASSERT_EQ(CL_SUCCESS, rv) << "clGetDeviceIDs";
|
||||
ASSERT_EQ(rv, CL_SUCCESS) << "clGetDeviceIDs";
|
||||
|
||||
context_ = clCreateContext(nullptr, 1, &device_id, nullptr, nullptr, &rv);
|
||||
ASSERT_EQ(CL_SUCCESS, rv) << "clCreateContext";
|
||||
ASSERT_EQ(rv, CL_SUCCESS) << "clCreateContext";
|
||||
|
||||
// The goal of the program in |sources| is to produce a cl_kernels image
|
||||
// that doesn’t strictly conform to Mach-O expectations. On OS X 10.10,
|
||||
@ -610,14 +610,14 @@ class ScopedOpenCLNoOpKernel {
|
||||
|
||||
program_ = clCreateProgramWithSource(
|
||||
context_, arraysize(sources), sources, source_lengths, &rv);
|
||||
ASSERT_EQ(CL_SUCCESS, rv) << "clCreateProgramWithSource";
|
||||
ASSERT_EQ(rv, CL_SUCCESS) << "clCreateProgramWithSource";
|
||||
|
||||
rv = clBuildProgram(
|
||||
program_, 1, &device_id, "-cl-opt-disable", nullptr, nullptr);
|
||||
ASSERT_EQ(CL_SUCCESS, rv) << "clBuildProgram";
|
||||
ASSERT_EQ(rv, CL_SUCCESS) << "clBuildProgram";
|
||||
|
||||
kernel_ = clCreateKernel(program_, "NoOp", &rv);
|
||||
ASSERT_EQ(CL_SUCCESS, rv) << "clCreateKernel";
|
||||
ASSERT_EQ(rv, CL_SUCCESS) << "clCreateKernel";
|
||||
}
|
||||
|
||||
private:
|
||||
@ -655,7 +655,7 @@ TEST(ProcessReader, SelfModules) {
|
||||
|
||||
// dyld_image_count doesn’t include an entry for dyld itself, but |modules|
|
||||
// does.
|
||||
ASSERT_EQ(dyld_image_count + 1, modules.size());
|
||||
ASSERT_EQ(modules.size(), dyld_image_count + 1);
|
||||
|
||||
bool found_cl_kernels = false;
|
||||
for (uint32_t index = 0; index < dyld_image_count; ++index) {
|
||||
@ -663,49 +663,48 @@ TEST(ProcessReader, SelfModules) {
|
||||
"index %u, name %s", index, modules[index].name.c_str()));
|
||||
|
||||
const char* dyld_image_name = _dyld_get_image_name(index);
|
||||
EXPECT_EQ(dyld_image_name, modules[index].name);
|
||||
EXPECT_EQ(modules[index].name, dyld_image_name);
|
||||
ASSERT_TRUE(modules[index].reader);
|
||||
EXPECT_EQ(
|
||||
reinterpret_cast<mach_vm_address_t>(_dyld_get_image_header(index)),
|
||||
modules[index].reader->Address());
|
||||
modules[index].reader->Address(),
|
||||
reinterpret_cast<mach_vm_address_t>(_dyld_get_image_header(index)));
|
||||
|
||||
if (index == 0) {
|
||||
// dyld didn’t load the main executable, so it couldn’t record its
|
||||
// timestamp, and it is reported as 0.
|
||||
EXPECT_EQ(0, modules[index].timestamp);
|
||||
EXPECT_EQ(modules[index].timestamp, 0);
|
||||
} else if (modules[index].reader->FileType() == MH_BUNDLE &&
|
||||
modules[index].name == "cl_kernels") {
|
||||
// cl_kernels doesn’t exist as a file.
|
||||
EXPECT_EQ(0, modules[index].timestamp);
|
||||
EXPECT_EQ(modules[index].timestamp, 0);
|
||||
found_cl_kernels = true;
|
||||
} else {
|
||||
// Hope that the module didn’t change on disk.
|
||||
struct stat stat_buf;
|
||||
int rv = stat(dyld_image_name, &stat_buf);
|
||||
EXPECT_EQ(0, rv) << ErrnoMessage("stat");
|
||||
EXPECT_EQ(rv, 0) << ErrnoMessage("stat");
|
||||
if (rv == 0) {
|
||||
EXPECT_EQ(stat_buf.st_mtime, modules[index].timestamp);
|
||||
EXPECT_EQ(modules[index].timestamp, stat_buf.st_mtime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ(ExpectCLKernels(), found_cl_kernels);
|
||||
EXPECT_EQ(found_cl_kernels, ExpectCLKernels());
|
||||
|
||||
size_t index = modules.size() - 1;
|
||||
EXPECT_EQ(kDyldPath, modules[index].name);
|
||||
EXPECT_EQ(modules[index].name, kDyldPath);
|
||||
|
||||
// dyld didn’t load itself either, so it couldn’t record its timestamp, and it
|
||||
// is also reported as 0.
|
||||
EXPECT_EQ(0, modules[index].timestamp);
|
||||
EXPECT_EQ(modules[index].timestamp, 0);
|
||||
|
||||
const struct dyld_all_image_infos* dyld_image_infos =
|
||||
_dyld_get_all_image_infos();
|
||||
if (dyld_image_infos->version >= 2) {
|
||||
ASSERT_TRUE(modules[index].reader);
|
||||
EXPECT_EQ(
|
||||
reinterpret_cast<mach_vm_address_t>(
|
||||
dyld_image_infos->dyldImageLoadAddress),
|
||||
modules[index].reader->Address());
|
||||
EXPECT_EQ(modules[index].reader->Address(),
|
||||
reinterpret_cast<mach_vm_address_t>(
|
||||
dyld_image_infos->dyldImageLoadAddress));
|
||||
}
|
||||
}
|
||||
|
||||
@ -733,7 +732,7 @@ class ProcessReaderModulesChild final : public MachMultiprocess {
|
||||
CheckedReadFileExactly(
|
||||
read_handle, &expect_modules, sizeof(expect_modules));
|
||||
|
||||
ASSERT_EQ(expect_modules, modules.size());
|
||||
ASSERT_EQ(modules.size(), expect_modules);
|
||||
|
||||
bool found_cl_kernels = false;
|
||||
for (size_t index = 0; index < modules.size(); ++index) {
|
||||
@ -747,35 +746,35 @@ class ProcessReaderModulesChild final : public MachMultiprocess {
|
||||
// The NUL terminator is not read.
|
||||
std::string expect_name(expect_name_length, '\0');
|
||||
CheckedReadFileExactly(read_handle, &expect_name[0], expect_name_length);
|
||||
EXPECT_EQ(expect_name, modules[index].name);
|
||||
EXPECT_EQ(modules[index].name, expect_name);
|
||||
|
||||
mach_vm_address_t expect_address;
|
||||
CheckedReadFileExactly(
|
||||
read_handle, &expect_address, sizeof(expect_address));
|
||||
ASSERT_TRUE(modules[index].reader);
|
||||
EXPECT_EQ(expect_address, modules[index].reader->Address());
|
||||
EXPECT_EQ(modules[index].reader->Address(), expect_address);
|
||||
|
||||
if (index == 0 || index == modules.size() - 1) {
|
||||
// dyld didn’t load the main executable or itself, so it couldn’t record
|
||||
// these timestamps, and they are reported as 0.
|
||||
EXPECT_EQ(0, modules[index].timestamp);
|
||||
EXPECT_EQ(modules[index].timestamp, 0);
|
||||
} else if (modules[index].reader->FileType() == MH_BUNDLE &&
|
||||
modules[index].name == "cl_kernels") {
|
||||
// cl_kernels doesn’t exist as a file.
|
||||
EXPECT_EQ(0, modules[index].timestamp);
|
||||
EXPECT_EQ(modules[index].timestamp, 0);
|
||||
found_cl_kernels = true;
|
||||
} else {
|
||||
// Hope that the module didn’t change on disk.
|
||||
struct stat stat_buf;
|
||||
int rv = stat(expect_name.c_str(), &stat_buf);
|
||||
EXPECT_EQ(0, rv) << ErrnoMessage("stat");
|
||||
EXPECT_EQ(rv, 0) << ErrnoMessage("stat");
|
||||
if (rv == 0) {
|
||||
EXPECT_EQ(stat_buf.st_mtime, modules[index].timestamp);
|
||||
EXPECT_EQ(modules[index].timestamp, stat_buf.st_mtime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ(ExpectCLKernels(), found_cl_kernels);
|
||||
EXPECT_EQ(found_cl_kernels, ExpectCLKernels());
|
||||
}
|
||||
|
||||
void MachMultiprocessChild() override {
|
||||
|
@ -39,7 +39,7 @@ namespace {
|
||||
std::string proctype_string; \
|
||||
ASSERT_TRUE(process_reader.Memory()->ReadCString(proctype_view.field, \
|
||||
&proctype_string)); \
|
||||
EXPECT_EQ(self_view->field, proctype_string); \
|
||||
EXPECT_EQ(proctype_string, self_view->field); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
@ -66,7 +66,7 @@ TEST(ProcessTypes, DyldImagesSelf) {
|
||||
}
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
|
||||
if (self_image_infos->version >= 9) {
|
||||
EXPECT_EQ(self_image_infos, self_image_infos->dyldAllImageInfosAddress);
|
||||
EXPECT_EQ(self_image_infos->dyldAllImageInfosAddress, self_image_infos);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -78,10 +78,10 @@ TEST(ProcessTypes, DyldImagesSelf) {
|
||||
TASK_DYLD_INFO,
|
||||
reinterpret_cast<task_info_t>(&dyld_info),
|
||||
&count);
|
||||
ASSERT_EQ(KERN_SUCCESS, kr);
|
||||
ASSERT_EQ(kr, KERN_SUCCESS);
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<mach_vm_address_t>(self_image_infos),
|
||||
dyld_info.all_image_info_addr);
|
||||
EXPECT_EQ(dyld_info.all_image_info_addr,
|
||||
reinterpret_cast<mach_vm_address_t>(self_image_infos));
|
||||
EXPECT_GT(dyld_info.all_image_info_size, 1u);
|
||||
|
||||
// This field is only present in the OS X 10.7 SDK (at build time) and kernel
|
||||
@ -89,9 +89,9 @@ TEST(ProcessTypes, DyldImagesSelf) {
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
|
||||
if (MacOSXMinorVersion() >= 7) {
|
||||
#if !defined(ARCH_CPU_64_BITS)
|
||||
EXPECT_EQ(TASK_DYLD_ALL_IMAGE_INFO_32, dyld_info.all_image_info_format);
|
||||
EXPECT_EQ(dyld_info.all_image_info_format, TASK_DYLD_ALL_IMAGE_INFO_32);
|
||||
#else
|
||||
EXPECT_EQ(TASK_DYLD_ALL_IMAGE_INFO_64, dyld_info.all_image_info_format);
|
||||
EXPECT_EQ(dyld_info.all_image_info_format, TASK_DYLD_ALL_IMAGE_INFO_64);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@ -113,9 +113,9 @@ TEST(ProcessTypes, DyldImagesSelf) {
|
||||
|
||||
// Make sure that the size of the structure as declared in the SDK matches the
|
||||
// size expected for the version of the structure that the SDK describes.
|
||||
EXPECT_EQ(sizeof(dyld_all_image_infos),
|
||||
process_types::dyld_all_image_infos::ExpectedSizeForVersion(
|
||||
&process_reader, kDyldAllImageInfosVersionInSDK));
|
||||
EXPECT_EQ(process_types::dyld_all_image_infos::ExpectedSizeForVersion(
|
||||
&process_reader, kDyldAllImageInfosVersionInSDK),
|
||||
sizeof(dyld_all_image_infos));
|
||||
|
||||
// Make sure that the computed sizes of various versions of this structure are
|
||||
// correct at different bitnessses.
|
||||
@ -143,50 +143,50 @@ TEST(ProcessTypes, DyldImagesSelf) {
|
||||
uint32_t version = kVersionsAndSizes[index].version;
|
||||
SCOPED_TRACE(base::StringPrintf("index %zu, version %u", index, version));
|
||||
|
||||
EXPECT_EQ(kVersionsAndSizes[index].size_32,
|
||||
process_types::internal::dyld_all_image_infos<
|
||||
process_types::internal::Traits32>::
|
||||
ExpectedSizeForVersion(version));
|
||||
EXPECT_EQ(kVersionsAndSizes[index].size_64,
|
||||
process_types::internal::dyld_all_image_infos<
|
||||
process_types::internal::Traits64>::
|
||||
ExpectedSizeForVersion(version));
|
||||
EXPECT_EQ(
|
||||
process_types::internal::dyld_all_image_infos<
|
||||
process_types::internal::Traits32>::ExpectedSizeForVersion(version),
|
||||
kVersionsAndSizes[index].size_32);
|
||||
EXPECT_EQ(
|
||||
process_types::internal::dyld_all_image_infos<
|
||||
process_types::internal::Traits64>::ExpectedSizeForVersion(version),
|
||||
kVersionsAndSizes[index].size_64);
|
||||
}
|
||||
|
||||
process_types::dyld_all_image_infos proctype_image_infos;
|
||||
ASSERT_TRUE(proctype_image_infos.Read(&process_reader,
|
||||
dyld_info.all_image_info_addr));
|
||||
|
||||
ASSERT_EQ(self_image_infos->version, proctype_image_infos.version);
|
||||
ASSERT_EQ(proctype_image_infos.version, self_image_infos->version);
|
||||
|
||||
if (proctype_image_infos.version >= 1) {
|
||||
EXPECT_EQ(self_image_infos->infoArrayCount,
|
||||
proctype_image_infos.infoArrayCount);
|
||||
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->infoArray),
|
||||
proctype_image_infos.infoArray);
|
||||
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->notification),
|
||||
proctype_image_infos.notification);
|
||||
EXPECT_EQ(self_image_infos->processDetachedFromSharedRegion,
|
||||
proctype_image_infos.processDetachedFromSharedRegion);
|
||||
EXPECT_EQ(proctype_image_infos.infoArrayCount,
|
||||
self_image_infos->infoArrayCount);
|
||||
EXPECT_EQ(proctype_image_infos.infoArray,
|
||||
reinterpret_cast<uint64_t>(self_image_infos->infoArray));
|
||||
EXPECT_EQ(proctype_image_infos.notification,
|
||||
reinterpret_cast<uint64_t>(self_image_infos->notification));
|
||||
EXPECT_EQ(proctype_image_infos.processDetachedFromSharedRegion,
|
||||
self_image_infos->processDetachedFromSharedRegion);
|
||||
}
|
||||
if (proctype_image_infos.version >= 2) {
|
||||
EXPECT_EQ(self_image_infos->libSystemInitialized,
|
||||
proctype_image_infos.libSystemInitialized);
|
||||
EXPECT_EQ(proctype_image_infos.libSystemInitialized,
|
||||
self_image_infos->libSystemInitialized);
|
||||
EXPECT_EQ(
|
||||
reinterpret_cast<uint64_t>(self_image_infos->dyldImageLoadAddress),
|
||||
proctype_image_infos.dyldImageLoadAddress);
|
||||
proctype_image_infos.dyldImageLoadAddress,
|
||||
reinterpret_cast<uint64_t>(self_image_infos->dyldImageLoadAddress));
|
||||
}
|
||||
if (proctype_image_infos.version >= 3) {
|
||||
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->jitInfo),
|
||||
proctype_image_infos.jitInfo);
|
||||
EXPECT_EQ(proctype_image_infos.jitInfo,
|
||||
reinterpret_cast<uint64_t>(self_image_infos->jitInfo));
|
||||
}
|
||||
if (proctype_image_infos.version >= 5) {
|
||||
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->dyldVersion),
|
||||
proctype_image_infos.dyldVersion);
|
||||
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->errorMessage),
|
||||
proctype_image_infos.errorMessage);
|
||||
EXPECT_EQ(implicit_cast<uint64_t>(self_image_infos->terminationFlags),
|
||||
proctype_image_infos.terminationFlags);
|
||||
EXPECT_EQ(proctype_image_infos.dyldVersion,
|
||||
reinterpret_cast<uint64_t>(self_image_infos->dyldVersion));
|
||||
EXPECT_EQ(proctype_image_infos.errorMessage,
|
||||
reinterpret_cast<uint64_t>(self_image_infos->errorMessage));
|
||||
EXPECT_EQ(proctype_image_infos.terminationFlags,
|
||||
implicit_cast<uint64_t>(self_image_infos->terminationFlags));
|
||||
|
||||
TEST_STRING(
|
||||
process_reader, self_image_infos, proctype_image_infos, dyldVersion);
|
||||
@ -195,38 +195,38 @@ TEST(ProcessTypes, DyldImagesSelf) {
|
||||
}
|
||||
if (proctype_image_infos.version >= 6) {
|
||||
EXPECT_EQ(
|
||||
reinterpret_cast<uint64_t>(self_image_infos->coreSymbolicationShmPage),
|
||||
proctype_image_infos.coreSymbolicationShmPage);
|
||||
proctype_image_infos.coreSymbolicationShmPage,
|
||||
reinterpret_cast<uint64_t>(self_image_infos->coreSymbolicationShmPage));
|
||||
}
|
||||
if (proctype_image_infos.version >= 7) {
|
||||
EXPECT_EQ(implicit_cast<uint64_t>(self_image_infos->systemOrderFlag),
|
||||
proctype_image_infos.systemOrderFlag);
|
||||
EXPECT_EQ(proctype_image_infos.systemOrderFlag,
|
||||
implicit_cast<uint64_t>(self_image_infos->systemOrderFlag));
|
||||
}
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
|
||||
if (proctype_image_infos.version >= 8) {
|
||||
EXPECT_EQ(implicit_cast<uint64_t>(self_image_infos->uuidArrayCount),
|
||||
proctype_image_infos.uuidArrayCount);
|
||||
EXPECT_EQ(proctype_image_infos.uuidArrayCount,
|
||||
implicit_cast<uint64_t>(self_image_infos->uuidArrayCount));
|
||||
}
|
||||
if (proctype_image_infos.version >= 9) {
|
||||
EXPECT_EQ(
|
||||
reinterpret_cast<uint64_t>(self_image_infos->dyldAllImageInfosAddress),
|
||||
proctype_image_infos.dyldAllImageInfosAddress);
|
||||
proctype_image_infos.dyldAllImageInfosAddress,
|
||||
reinterpret_cast<uint64_t>(self_image_infos->dyldAllImageInfosAddress));
|
||||
}
|
||||
if (proctype_image_infos.version >= 10) {
|
||||
EXPECT_EQ(implicit_cast<uint64_t>(self_image_infos->initialImageCount),
|
||||
proctype_image_infos.initialImageCount);
|
||||
EXPECT_EQ(proctype_image_infos.initialImageCount,
|
||||
implicit_cast<uint64_t>(self_image_infos->initialImageCount));
|
||||
}
|
||||
if (proctype_image_infos.version >= 11) {
|
||||
EXPECT_EQ(implicit_cast<uint64_t>(self_image_infos->errorKind),
|
||||
proctype_image_infos.errorKind);
|
||||
EXPECT_EQ(proctype_image_infos.errorKind,
|
||||
implicit_cast<uint64_t>(self_image_infos->errorKind));
|
||||
EXPECT_EQ(
|
||||
reinterpret_cast<uint64_t>(self_image_infos->errorClientOfDylibPath),
|
||||
proctype_image_infos.errorClientOfDylibPath);
|
||||
proctype_image_infos.errorClientOfDylibPath,
|
||||
reinterpret_cast<uint64_t>(self_image_infos->errorClientOfDylibPath));
|
||||
EXPECT_EQ(
|
||||
reinterpret_cast<uint64_t>(self_image_infos->errorTargetDylibPath),
|
||||
proctype_image_infos.errorTargetDylibPath);
|
||||
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->errorSymbol),
|
||||
proctype_image_infos.errorSymbol);
|
||||
proctype_image_infos.errorTargetDylibPath,
|
||||
reinterpret_cast<uint64_t>(self_image_infos->errorTargetDylibPath));
|
||||
EXPECT_EQ(proctype_image_infos.errorSymbol,
|
||||
reinterpret_cast<uint64_t>(self_image_infos->errorSymbol));
|
||||
|
||||
TEST_STRING(process_reader,
|
||||
self_image_infos,
|
||||
@ -240,31 +240,32 @@ TEST(ProcessTypes, DyldImagesSelf) {
|
||||
process_reader, self_image_infos, proctype_image_infos, errorSymbol);
|
||||
}
|
||||
if (proctype_image_infos.version >= 12) {
|
||||
EXPECT_EQ(implicit_cast<uint64_t>(self_image_infos->sharedCacheSlide),
|
||||
proctype_image_infos.sharedCacheSlide);
|
||||
EXPECT_EQ(proctype_image_infos.sharedCacheSlide,
|
||||
implicit_cast<uint64_t>(self_image_infos->sharedCacheSlide));
|
||||
}
|
||||
#endif
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
|
||||
if (proctype_image_infos.version >= 13) {
|
||||
EXPECT_EQ(0,
|
||||
memcmp(self_image_infos->sharedCacheUUID,
|
||||
EXPECT_EQ(memcmp(self_image_infos->sharedCacheUUID,
|
||||
proctype_image_infos.sharedCacheUUID,
|
||||
sizeof(self_image_infos->sharedCacheUUID)));
|
||||
sizeof(self_image_infos->sharedCacheUUID)),
|
||||
0);
|
||||
}
|
||||
#endif
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
|
||||
if (proctype_image_infos.version >= 15) {
|
||||
EXPECT_EQ(self_image_infos->infoArrayChangeTimestamp,
|
||||
proctype_image_infos.infoArrayChangeTimestamp);
|
||||
EXPECT_EQ(self_image_infos->sharedCacheBaseAddress,
|
||||
proctype_image_infos.sharedCacheBaseAddress);
|
||||
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->dyldPath),
|
||||
proctype_image_infos.dyldPath);
|
||||
EXPECT_EQ(proctype_image_infos.infoArrayChangeTimestamp,
|
||||
self_image_infos->infoArrayChangeTimestamp);
|
||||
EXPECT_EQ(proctype_image_infos.sharedCacheBaseAddress,
|
||||
self_image_infos->sharedCacheBaseAddress);
|
||||
EXPECT_EQ(proctype_image_infos.dyldPath,
|
||||
reinterpret_cast<uint64_t>(self_image_infos->dyldPath));
|
||||
for (size_t index = 0;
|
||||
index < arraysize(self_image_infos->notifyPorts);
|
||||
++index) {
|
||||
EXPECT_EQ(self_image_infos->notifyPorts[index],
|
||||
proctype_image_infos.notifyPorts[index]) << "index " << index;
|
||||
EXPECT_EQ(proctype_image_infos.notifyPorts[index],
|
||||
self_image_infos->notifyPorts[index])
|
||||
<< "index " << index;
|
||||
}
|
||||
|
||||
TEST_STRING(
|
||||
@ -283,16 +284,16 @@ TEST(ProcessTypes, DyldImagesSelf) {
|
||||
for (size_t index = 0;
|
||||
index < arraysize(proctype_image_infos.reserved);
|
||||
++index) {
|
||||
EXPECT_EQ(implicit_cast<uint64_t>(self_image_infos->reserved[index]),
|
||||
proctype_image_infos.reserved[index])
|
||||
EXPECT_EQ(proctype_image_infos.reserved[index],
|
||||
implicit_cast<uint64_t>(self_image_infos->reserved[index]))
|
||||
<< "index " << index;
|
||||
}
|
||||
#if defined(ARCH_CPU_64_BITS)
|
||||
EXPECT_EQ(self_image_infos->reserved[4], proctype_image_infos.reserved_4);
|
||||
EXPECT_EQ(self_image_infos->reserved[5], proctype_image_infos.reserved_5);
|
||||
EXPECT_EQ(self_image_infos->reserved[6], proctype_image_infos.reserved_6);
|
||||
EXPECT_EQ(self_image_infos->reserved[7], proctype_image_infos.reserved_7);
|
||||
EXPECT_EQ(self_image_infos->reserved[8], proctype_image_infos.reserved_8);
|
||||
EXPECT_EQ(proctype_image_infos.reserved_4, self_image_infos->reserved[4]);
|
||||
EXPECT_EQ(proctype_image_infos.reserved_5, self_image_infos->reserved[5]);
|
||||
EXPECT_EQ(proctype_image_infos.reserved_6, self_image_infos->reserved[6]);
|
||||
EXPECT_EQ(proctype_image_infos.reserved_7, self_image_infos->reserved[7]);
|
||||
EXPECT_EQ(proctype_image_infos.reserved_8, self_image_infos->reserved[8]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@ -314,14 +315,14 @@ TEST(ProcessTypes, DyldImagesSelf) {
|
||||
const process_types::dyld_image_info& proctype_image_info =
|
||||
proctype_image_info_vector[index];
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_info->imageLoadAddress),
|
||||
proctype_image_info.imageLoadAddress)
|
||||
EXPECT_EQ(proctype_image_info.imageLoadAddress,
|
||||
reinterpret_cast<uint64_t>(self_image_info->imageLoadAddress))
|
||||
<< "index " << index;
|
||||
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_info->imageFilePath),
|
||||
proctype_image_info.imageFilePath)
|
||||
EXPECT_EQ(proctype_image_info.imageFilePath,
|
||||
reinterpret_cast<uint64_t>(self_image_info->imageFilePath))
|
||||
<< "index " << index;
|
||||
EXPECT_EQ(implicit_cast<uint64_t>(self_image_info->imageFileModDate),
|
||||
proctype_image_info.imageFileModDate)
|
||||
EXPECT_EQ(proctype_image_info.imageFileModDate,
|
||||
implicit_cast<uint64_t>(self_image_info->imageFileModDate))
|
||||
<< "index " << index;
|
||||
|
||||
TEST_STRING(
|
||||
@ -347,13 +348,13 @@ TEST(ProcessTypes, DyldImagesSelf) {
|
||||
const process_types::dyld_uuid_info& proctype_uuid_info =
|
||||
proctype_uuid_info_vector[index];
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<uint64_t>(self_uuid_info->imageLoadAddress),
|
||||
proctype_uuid_info.imageLoadAddress)
|
||||
EXPECT_EQ(proctype_uuid_info.imageLoadAddress,
|
||||
reinterpret_cast<uint64_t>(self_uuid_info->imageLoadAddress))
|
||||
<< "index " << index;
|
||||
EXPECT_EQ(0,
|
||||
memcmp(self_uuid_info->imageUUID,
|
||||
EXPECT_EQ(memcmp(self_uuid_info->imageUUID,
|
||||
proctype_uuid_info.imageUUID,
|
||||
sizeof(self_uuid_info->imageUUID)))
|
||||
sizeof(self_uuid_info->imageUUID)),
|
||||
0)
|
||||
<< "index " << index;
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ class SystemSnapshotMacTest : public testing::Test {
|
||||
// testing::Test:
|
||||
void SetUp() override {
|
||||
ASSERT_TRUE(process_reader_.Initialize(mach_task_self()));
|
||||
ASSERT_EQ(0, gettimeofday(&snapshot_time_, nullptr))
|
||||
ASSERT_EQ(gettimeofday(&snapshot_time_, nullptr), 0)
|
||||
<< ErrnoMessage("gettimeofday");
|
||||
system_snapshot_.Initialize(&process_reader_, &snapshot_time_);
|
||||
}
|
||||
@ -69,9 +69,9 @@ TEST_F(SystemSnapshotMacTest, GetCPUArchitecture) {
|
||||
CPUArchitecture cpu_architecture = system_snapshot().GetCPUArchitecture();
|
||||
|
||||
#if defined(ARCH_CPU_X86)
|
||||
EXPECT_EQ(kCPUArchitectureX86, cpu_architecture);
|
||||
EXPECT_EQ(cpu_architecture, kCPUArchitectureX86);
|
||||
#elif defined(ARCH_CPU_X86_64)
|
||||
EXPECT_EQ(kCPUArchitectureX86_64, cpu_architecture);
|
||||
EXPECT_EQ(cpu_architecture, kCPUArchitectureX86_64);
|
||||
#else
|
||||
#error port to your architecture
|
||||
#endif
|
||||
@ -105,8 +105,8 @@ TEST_F(SystemSnapshotMacTest, CPUX86SupportsDAZ) {
|
||||
#endif
|
||||
|
||||
TEST_F(SystemSnapshotMacTest, GetOperatingSystem) {
|
||||
EXPECT_EQ(SystemSnapshot::kOperatingSystemMacOSX,
|
||||
system_snapshot().GetOperatingSystem());
|
||||
EXPECT_EQ(system_snapshot().GetOperatingSystem(),
|
||||
SystemSnapshot::kOperatingSystemMacOSX);
|
||||
}
|
||||
|
||||
TEST_F(SystemSnapshotMacTest, OSVersion) {
|
||||
@ -116,8 +116,8 @@ TEST_F(SystemSnapshotMacTest, OSVersion) {
|
||||
std::string build;
|
||||
system_snapshot().OSVersion(&major, &minor, &bugfix, &build);
|
||||
|
||||
EXPECT_EQ(10, major);
|
||||
EXPECT_EQ(MacOSXMinorVersion(), minor);
|
||||
EXPECT_EQ(major, 10);
|
||||
EXPECT_EQ(minor, MacOSXMinorVersion());
|
||||
EXPECT_FALSE(build.empty());
|
||||
}
|
||||
|
||||
@ -138,15 +138,15 @@ class ScopedSetTZ {
|
||||
old_tz_.assign(old_tz);
|
||||
}
|
||||
|
||||
EXPECT_EQ(0, setenv(kTZ, tz.c_str(), 1)) << ErrnoMessage("setenv");
|
||||
EXPECT_EQ(setenv(kTZ, tz.c_str(), 1), 0) << ErrnoMessage("setenv");
|
||||
tzset();
|
||||
}
|
||||
|
||||
~ScopedSetTZ() {
|
||||
if (old_tz_set_) {
|
||||
EXPECT_EQ(0, setenv(kTZ, old_tz_.c_str(), 1)) << ErrnoMessage("setenv");
|
||||
EXPECT_EQ(setenv(kTZ, old_tz_.c_str(), 1), 0) << ErrnoMessage("setenv");
|
||||
} else {
|
||||
EXPECT_EQ(0, unsetenv(kTZ)) << ErrnoMessage("unsetenv");
|
||||
EXPECT_EQ(unsetenv(kTZ), 0) << ErrnoMessage("unsetenv");
|
||||
}
|
||||
tzset();
|
||||
}
|
||||
@ -177,20 +177,20 @@ TEST_F(SystemSnapshotMacTest, TimeZone) {
|
||||
|
||||
// |standard_offset_seconds| gives seconds east of UTC, and |timezone| gives
|
||||
// seconds west of UTC.
|
||||
EXPECT_EQ(-timezone, standard_offset_seconds);
|
||||
EXPECT_EQ(standard_offset_seconds, -timezone);
|
||||
|
||||
// In contemporary usage, most time zones have an integer hour offset from
|
||||
// UTC, although several are at a half-hour offset, and two are at 15-minute
|
||||
// offsets. Throughout history, other variations existed. See
|
||||
// http://www.timeanddate.com/time/time-zones-interesting.html.
|
||||
EXPECT_EQ(0, standard_offset_seconds % (15 * 60))
|
||||
EXPECT_EQ(standard_offset_seconds % (15 * 60), 0)
|
||||
<< "standard_offset_seconds " << standard_offset_seconds;
|
||||
|
||||
if (dst_status == SystemSnapshot::kDoesNotObserveDaylightSavingTime) {
|
||||
EXPECT_EQ(standard_offset_seconds, daylight_offset_seconds);
|
||||
EXPECT_EQ(standard_name, daylight_name);
|
||||
EXPECT_EQ(daylight_offset_seconds, standard_offset_seconds);
|
||||
EXPECT_EQ(daylight_name, standard_name);
|
||||
} else {
|
||||
EXPECT_EQ(0, daylight_offset_seconds % (15 * 60))
|
||||
EXPECT_EQ(daylight_offset_seconds % (15 * 60), 0)
|
||||
<< "daylight_offset_seconds " << daylight_offset_seconds;
|
||||
|
||||
// In contemporary usage, dst_delta_seconds will almost always be one hour,
|
||||
@ -207,6 +207,9 @@ TEST_F(SystemSnapshotMacTest, TimeZone) {
|
||||
|
||||
// Test a variety of time zones. Some of these observe daylight saving time,
|
||||
// some don’t. Some used to but no longer do. Some have uncommon UTC offsets.
|
||||
// standard_name and daylight_name can be nullptr where no name exists to
|
||||
// verify, as may happen when some versions of the timezone database carry
|
||||
// invented names and others do not.
|
||||
const struct {
|
||||
const char* tz;
|
||||
bool observes_dst;
|
||||
@ -229,8 +232,8 @@ TEST_F(SystemSnapshotMacTest, TimeZone) {
|
||||
{"Australia/Adelaide", true, 9.5, 10.5, "ACST", "ACDT"},
|
||||
{"Australia/Brisbane", false, 10, 10, "AEST", "AEST"},
|
||||
{"Australia/Darwin", false, 9.5, 9.5, "ACST", "ACST"},
|
||||
{"Australia/Eucla", false, 8.75, 8.75, "ACWST", "ACWST"},
|
||||
{"Australia/Lord_Howe", true, 10.5, 11, "LHST", "LHDT"},
|
||||
{"Australia/Eucla", false, 8.75, 8.75, nullptr, nullptr},
|
||||
{"Australia/Lord_Howe", true, 10.5, 11, nullptr, nullptr},
|
||||
{"Australia/Perth", false, 8, 8, "AWST", "AWST"},
|
||||
{"Australia/Sydney", true, 10, 11, "AEST", "AEDT"},
|
||||
{"Europe/Bucharest", true, 2, 3, "EET", "EEST"},
|
||||
@ -257,14 +260,18 @@ TEST_F(SystemSnapshotMacTest, TimeZone) {
|
||||
&daylight_name);
|
||||
}
|
||||
|
||||
EXPECT_EQ(test_time_zone.observes_dst,
|
||||
dst_status != SystemSnapshot::kDoesNotObserveDaylightSavingTime);
|
||||
EXPECT_EQ(test_time_zone.standard_offset_hours * 60 * 60,
|
||||
standard_offset_seconds);
|
||||
EXPECT_EQ(test_time_zone.daylight_offset_hours * 60 * 60,
|
||||
daylight_offset_seconds);
|
||||
EXPECT_EQ(test_time_zone.standard_name, standard_name);
|
||||
EXPECT_EQ(test_time_zone.daylight_name, daylight_name);
|
||||
EXPECT_EQ(dst_status != SystemSnapshot::kDoesNotObserveDaylightSavingTime,
|
||||
test_time_zone.observes_dst);
|
||||
EXPECT_EQ(standard_offset_seconds,
|
||||
test_time_zone.standard_offset_hours * 60 * 60);
|
||||
EXPECT_EQ(daylight_offset_seconds,
|
||||
test_time_zone.daylight_offset_hours * 60 * 60);
|
||||
if (test_time_zone.standard_name) {
|
||||
EXPECT_EQ(standard_name, test_time_zone.standard_name);
|
||||
}
|
||||
if (test_time_zone.daylight_name) {
|
||||
EXPECT_EQ(daylight_name, test_time_zone.daylight_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ TEST(ProcessSnapshotMinidump, Empty) {
|
||||
|
||||
UUID client_id;
|
||||
process_snapshot.ClientID(&client_id);
|
||||
EXPECT_EQ(UUID(), client_id);
|
||||
EXPECT_EQ(client_id, UUID());
|
||||
|
||||
EXPECT_TRUE(process_snapshot.AnnotationsSimpleMap().empty());
|
||||
}
|
||||
@ -167,7 +167,7 @@ TEST(ProcessSnapshotMinidump, ClientID) {
|
||||
|
||||
UUID actual_client_id;
|
||||
process_snapshot.ClientID(&actual_client_id);
|
||||
EXPECT_EQ(client_id, actual_client_id);
|
||||
EXPECT_EQ(actual_client_id, client_id);
|
||||
|
||||
EXPECT_TRUE(process_snapshot.AnnotationsSimpleMap().empty());
|
||||
}
|
||||
@ -209,10 +209,10 @@ TEST(ProcessSnapshotMinidump, AnnotationsSimpleMap) {
|
||||
|
||||
UUID client_id;
|
||||
process_snapshot.ClientID(&client_id);
|
||||
EXPECT_EQ(UUID(), client_id);
|
||||
EXPECT_EQ(client_id, UUID());
|
||||
|
||||
const auto annotations_simple_map = process_snapshot.AnnotationsSimpleMap();
|
||||
EXPECT_EQ(dictionary, annotations_simple_map);
|
||||
EXPECT_EQ(annotations_simple_map, dictionary);
|
||||
}
|
||||
|
||||
TEST(ProcessSnapshotMinidump, Modules) {
|
||||
@ -313,10 +313,10 @@ TEST(ProcessSnapshotMinidump, Modules) {
|
||||
EXPECT_TRUE(process_snapshot.Initialize(&string_file));
|
||||
|
||||
std::vector<const ModuleSnapshot*> modules = process_snapshot.Modules();
|
||||
ASSERT_EQ(minidump_module_count, modules.size());
|
||||
ASSERT_EQ(modules.size(), minidump_module_count);
|
||||
|
||||
auto annotations_simple_map = modules[0]->AnnotationsSimpleMap();
|
||||
EXPECT_EQ(dictionary_0, annotations_simple_map);
|
||||
EXPECT_EQ(annotations_simple_map, dictionary_0);
|
||||
|
||||
auto annotations_vector = modules[0]->AnnotationsVector();
|
||||
EXPECT_TRUE(annotations_vector.empty());
|
||||
@ -328,10 +328,10 @@ TEST(ProcessSnapshotMinidump, Modules) {
|
||||
EXPECT_TRUE(annotations_vector.empty());
|
||||
|
||||
annotations_simple_map = modules[2]->AnnotationsSimpleMap();
|
||||
EXPECT_EQ(dictionary_2, annotations_simple_map);
|
||||
EXPECT_EQ(annotations_simple_map, dictionary_2);
|
||||
|
||||
annotations_vector = modules[2]->AnnotationsVector();
|
||||
EXPECT_EQ(list_annotations_2, annotations_vector);
|
||||
EXPECT_EQ(annotations_vector, list_annotations_2);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -41,9 +41,9 @@ void TestInitializeX86Context() {
|
||||
{
|
||||
CPUContextX86 cpu_context_x86 = {};
|
||||
InitializeX86Context(context, &cpu_context_x86);
|
||||
EXPECT_EQ(1u, cpu_context_x86.eax);
|
||||
EXPECT_EQ(2u, cpu_context_x86.fxsave.ftw);
|
||||
EXPECT_EQ(3u, cpu_context_x86.dr0);
|
||||
EXPECT_EQ(cpu_context_x86.eax, 1u);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.ftw, 2u);
|
||||
EXPECT_EQ(cpu_context_x86.dr0, 3u);
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,29 +74,29 @@ void TestInitializeX86Context_FsaveWithoutFxsave() {
|
||||
CPUContextX86 cpu_context_x86 = {};
|
||||
InitializeX86Context(context, &cpu_context_x86);
|
||||
|
||||
EXPECT_EQ(1u, cpu_context_x86.eax);
|
||||
EXPECT_EQ(cpu_context_x86.eax, 1u);
|
||||
|
||||
EXPECT_EQ(0x027f, cpu_context_x86.fxsave.fcw);
|
||||
EXPECT_EQ(0x0004, cpu_context_x86.fxsave.fsw);
|
||||
EXPECT_EQ(0x00f0, cpu_context_x86.fxsave.ftw);
|
||||
EXPECT_EQ(0x0bad, cpu_context_x86.fxsave.fop);
|
||||
EXPECT_EQ(0x01234567, cpu_context_x86.fxsave.fpu_ip);
|
||||
EXPECT_EQ(0x0003, cpu_context_x86.fxsave.fpu_cs);
|
||||
EXPECT_EQ(0x89abcdef, cpu_context_x86.fxsave.fpu_dp);
|
||||
EXPECT_EQ(0x0007, cpu_context_x86.fxsave.fpu_ds);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.fcw, 0x027f);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.fsw, 0x0004);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.ftw, 0x00f0);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.fop, 0x0bad);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.fpu_ip, 0x01234567);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.fpu_cs, 0x0003);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.fpu_dp, 0x89abcdef);
|
||||
EXPECT_EQ(cpu_context_x86.fxsave.fpu_ds, 0x0007);
|
||||
for (size_t st_mm = 0; st_mm < 7; ++st_mm) {
|
||||
EXPECT_EQ(
|
||||
std::string(arraysize(cpu_context_x86.fxsave.st_mm[st_mm].st) * 2,
|
||||
'0'),
|
||||
BytesToHexString(cpu_context_x86.fxsave.st_mm[st_mm].st,
|
||||
arraysize(cpu_context_x86.fxsave.st_mm[st_mm].st)))
|
||||
arraysize(cpu_context_x86.fxsave.st_mm[st_mm].st)),
|
||||
std::string(arraysize(cpu_context_x86.fxsave.st_mm[st_mm].st) * 2,
|
||||
'0'))
|
||||
<< "st_mm " << st_mm;
|
||||
}
|
||||
EXPECT_EQ("0000000000000080ff7f",
|
||||
BytesToHexString(cpu_context_x86.fxsave.st_mm[7].st,
|
||||
arraysize(cpu_context_x86.fxsave.st_mm[7].st)));
|
||||
EXPECT_EQ(BytesToHexString(cpu_context_x86.fxsave.st_mm[7].st,
|
||||
arraysize(cpu_context_x86.fxsave.st_mm[7].st)),
|
||||
"0000000000000080ff7f");
|
||||
|
||||
EXPECT_EQ(3u, cpu_context_x86.dr0);
|
||||
EXPECT_EQ(cpu_context_x86.dr0, 3u);
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,9 +117,9 @@ TEST(CPUContextWin, InitializeX64Context) {
|
||||
{
|
||||
CPUContextX86_64 cpu_context_x86_64 = {};
|
||||
InitializeX64Context(context, &cpu_context_x86_64);
|
||||
EXPECT_EQ(10u, cpu_context_x86_64.rax);
|
||||
EXPECT_EQ(11u, cpu_context_x86_64.fxsave.ftw);
|
||||
EXPECT_EQ(12u, cpu_context_x86_64.dr0);
|
||||
EXPECT_EQ(cpu_context_x86_64.rax, 10u);
|
||||
EXPECT_EQ(cpu_context_x86_64.fxsave.ftw, 11u);
|
||||
EXPECT_EQ(cpu_context_x86_64.dr0, 12u);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,10 +17,14 @@
|
||||
#include "base/logging.h"
|
||||
#include "client/crashpad_info.h"
|
||||
#include "util/file/file_io.h"
|
||||
#include "util/synchronization/semaphore.h"
|
||||
#include "util/win/scoped_handle.h"
|
||||
|
||||
namespace {
|
||||
|
||||
DWORD WINAPI LotsOfReferencesThreadProc(void* param) {
|
||||
LONG* count = reinterpret_cast<LONG*>(param);
|
||||
crashpad::Semaphore* semaphore =
|
||||
reinterpret_cast<crashpad::Semaphore*>(param);
|
||||
|
||||
// Allocate a bunch of pointers to things on the stack.
|
||||
int* pointers[1000];
|
||||
@ -28,28 +32,31 @@ DWORD WINAPI LotsOfReferencesThreadProc(void* param) {
|
||||
pointers[i] = new int[2048];
|
||||
}
|
||||
|
||||
InterlockedIncrement(count);
|
||||
semaphore->Signal();
|
||||
Sleep(INFINITE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int wmain(int argc, wchar_t* argv[]) {
|
||||
CHECK_EQ(argc, 2);
|
||||
|
||||
crashpad::ScopedKernelHANDLE done(CreateEvent(nullptr, true, false, argv[1]));
|
||||
PCHECK(done.is_valid()) << "CreateEvent";
|
||||
|
||||
PCHECK(LoadLibrary(L"crashpad_snapshot_test_image_reader_module.dll"))
|
||||
<< "LoadLibrary";
|
||||
|
||||
// Create threads with lots of stack pointers to memory. This is used to
|
||||
// verify the cap on pointed-to memory.
|
||||
LONG thread_ready_count = 0;
|
||||
crashpad::Semaphore semaphore(0);
|
||||
crashpad::ScopedKernelHANDLE threads[100];
|
||||
for (int i = 0; i < arraysize(threads); ++i) {
|
||||
threads[i].reset(CreateThread(nullptr,
|
||||
0,
|
||||
&LotsOfReferencesThreadProc,
|
||||
reinterpret_cast<void*>(&thread_ready_count),
|
||||
reinterpret_cast<void*>(&semaphore),
|
||||
0,
|
||||
nullptr));
|
||||
if (!threads[i].is_valid()) {
|
||||
@ -58,14 +65,8 @@ int wmain(int argc, wchar_t* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (InterlockedCompareExchange(&thread_ready_count,
|
||||
arraysize(threads),
|
||||
arraysize(threads) == arraysize(threads))) {
|
||||
// All threads have allocated their references.
|
||||
break;
|
||||
}
|
||||
Sleep(10);
|
||||
for (int i = 0; i < arraysize(threads); ++i) {
|
||||
semaphore.Wait();
|
||||
}
|
||||
|
||||
crashpad::CrashpadInfo* crashpad_info =
|
||||
@ -80,8 +81,8 @@ int wmain(int argc, wchar_t* argv[]) {
|
||||
crashpad::CheckedWriteFile(out, &c, sizeof(c));
|
||||
|
||||
// Parent process says we can exit.
|
||||
CHECK_EQ(WAIT_OBJECT_0, WaitForSingleObject(done.get(), INFINITE));
|
||||
PCHECK(WaitForSingleObject(done.get(), INFINITE) == WAIT_OBJECT_0)
|
||||
<< "WaitForSingleObject";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import win32con
|
||||
|
||||
|
||||
g_temp_dirs = []
|
||||
@ -80,23 +81,23 @@ def GetCdbPath():
|
||||
return None
|
||||
|
||||
|
||||
def GetDumpFromProgram(out_dir, pipe_name, executable_name, *args):
|
||||
def GetDumpFromProgram(
|
||||
out_dir, pipe_name, executable_name, expect_exit_code, *args):
|
||||
"""Initialize a crash database, and run |executable_name| connecting to a
|
||||
crash handler. If pipe_name is set, crashpad_handler will be started first. If
|
||||
pipe_name is empty, the executable is responsible for starting
|
||||
crashpad_handler. *args will be passed after other arguments to
|
||||
executable_name. Returns the minidump generated by crashpad_handler for
|
||||
further testing.
|
||||
executable_name. If the child process does not exit with |expect_exit_code|,
|
||||
an exception will be raised. Returns the path to the minidump generated by
|
||||
crashpad_handler for further testing.
|
||||
"""
|
||||
test_database = MakeTempDir()
|
||||
handler = None
|
||||
|
||||
try:
|
||||
if subprocess.call(
|
||||
subprocess.check_call(
|
||||
[os.path.join(out_dir, 'crashpad_database_util.exe'), '--create',
|
||||
'--database=' + test_database]) != 0:
|
||||
print 'could not initialize report database'
|
||||
return None
|
||||
'--database=' + test_database])
|
||||
|
||||
if pipe_name is not None:
|
||||
handler = subprocess.Popen([
|
||||
@ -113,12 +114,16 @@ def GetDumpFromProgram(out_dir, pipe_name, executable_name, *args):
|
||||
printed = True
|
||||
time.sleep(0.1)
|
||||
|
||||
subprocess.call([os.path.join(out_dir, executable_name), pipe_name] +
|
||||
list(args))
|
||||
exit_code = subprocess.call(
|
||||
[os.path.join(out_dir, executable_name), pipe_name] + list(args))
|
||||
else:
|
||||
subprocess.call([os.path.join(out_dir, executable_name),
|
||||
os.path.join(out_dir, 'crashpad_handler.com'),
|
||||
test_database] + list(args))
|
||||
exit_code = subprocess.call(
|
||||
[os.path.join(out_dir, executable_name),
|
||||
os.path.join(out_dir, 'crashpad_handler.com'),
|
||||
test_database] +
|
||||
list(args))
|
||||
if exit_code != expect_exit_code:
|
||||
raise CalledProcessError(exit_code, executable_name)
|
||||
|
||||
out = subprocess.check_output([
|
||||
os.path.join(out_dir, 'crashpad_database_util.exe'),
|
||||
@ -135,24 +140,38 @@ def GetDumpFromProgram(out_dir, pipe_name, executable_name, *args):
|
||||
|
||||
|
||||
def GetDumpFromCrashyProgram(out_dir, pipe_name):
|
||||
return GetDumpFromProgram(out_dir, pipe_name, 'crashy_program.exe')
|
||||
return GetDumpFromProgram(out_dir,
|
||||
pipe_name,
|
||||
'crashy_program.exe',
|
||||
win32con.EXCEPTION_ACCESS_VIOLATION)
|
||||
|
||||
|
||||
def GetDumpFromOtherProgram(out_dir, pipe_name, *args):
|
||||
return GetDumpFromProgram(out_dir, pipe_name, 'crash_other_program.exe',
|
||||
*args)
|
||||
return GetDumpFromProgram(
|
||||
out_dir, pipe_name, 'crash_other_program.exe', 0, *args)
|
||||
|
||||
|
||||
def GetDumpFromSignal(out_dir, pipe_name, *args):
|
||||
return GetDumpFromProgram(out_dir, pipe_name, 'crashy_signal.exe', *args)
|
||||
STATUS_FATAL_APP_EXIT = 0x40000015 # Not known by win32con.
|
||||
return GetDumpFromProgram(out_dir,
|
||||
pipe_name,
|
||||
'crashy_signal.exe',
|
||||
STATUS_FATAL_APP_EXIT,
|
||||
*args)
|
||||
|
||||
|
||||
def GetDumpFromSelfDestroyingProgram(out_dir, pipe_name):
|
||||
return GetDumpFromProgram(out_dir, pipe_name, 'self_destroying_program.exe')
|
||||
return GetDumpFromProgram(out_dir,
|
||||
pipe_name,
|
||||
'self_destroying_program.exe',
|
||||
win32con.EXCEPTION_BREAKPOINT)
|
||||
|
||||
|
||||
def GetDumpFromZ7Program(out_dir, pipe_name):
|
||||
return GetDumpFromProgram(out_dir, pipe_name, 'crashy_z7_loader.exe')
|
||||
return GetDumpFromProgram(out_dir,
|
||||
pipe_name,
|
||||
'crashy_z7_loader.exe',
|
||||
win32con.EXCEPTION_ACCESS_VIOLATION)
|
||||
|
||||
|
||||
class CdbRun(object):
|
||||
|
@ -22,7 +22,8 @@
|
||||
#include "client/crashpad_client.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "snapshot/win/process_snapshot_win.h"
|
||||
#include "test/paths.h"
|
||||
#include "test/errors.h"
|
||||
#include "test/test_paths.h"
|
||||
#include "test/win/child_launcher.h"
|
||||
#include "util/file/file_io.h"
|
||||
#include "util/thread/thread.h"
|
||||
@ -96,7 +97,7 @@ class CrashingDelegate : public ExceptionHandlerServer::Delegate {
|
||||
|
||||
// Confirm the exception record was read correctly.
|
||||
EXPECT_NE(snapshot.Exception()->ThreadID(), 0u);
|
||||
EXPECT_EQ(snapshot.Exception()->Exception(), EXCEPTION_BREAKPOINT);
|
||||
EXPECT_EQ(EXCEPTION_BREAKPOINT, snapshot.Exception()->Exception());
|
||||
|
||||
// Verify the exception happened at the expected location with a bit of
|
||||
// slop space to allow for reading the current PC before the exception
|
||||
@ -122,7 +123,9 @@ class CrashingDelegate : public ExceptionHandlerServer::Delegate {
|
||||
void TestCrashingChild(const base::string16& directory_modification) {
|
||||
// Set up the registration server on a background thread.
|
||||
ScopedKernelHANDLE server_ready(CreateEvent(nullptr, false, false, nullptr));
|
||||
ASSERT_TRUE(server_ready.is_valid()) << ErrorMessage("CreateEvent");
|
||||
ScopedKernelHANDLE completed(CreateEvent(nullptr, false, false, nullptr));
|
||||
ASSERT_TRUE(completed.is_valid()) << ErrorMessage("CreateEvent");
|
||||
CrashingDelegate delegate(server_ready.get(), completed.get());
|
||||
|
||||
ExceptionHandlerServer exception_handler_server(true);
|
||||
@ -133,10 +136,11 @@ void TestCrashingChild(const base::string16& directory_modification) {
|
||||
ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread(
|
||||
&exception_handler_server, &server_thread);
|
||||
|
||||
WaitForSingleObject(server_ready.get(), INFINITE);
|
||||
EXPECT_EQ(WaitForSingleObject(server_ready.get(), INFINITE), WAIT_OBJECT_0)
|
||||
<< ErrorMessage("WaitForSingleObject");
|
||||
|
||||
// Spawn a child process, passing it the pipe name to connect to.
|
||||
base::FilePath test_executable = Paths::Executable();
|
||||
base::FilePath test_executable = TestPaths::Executable();
|
||||
std::wstring child_test_executable =
|
||||
test_executable.DirName()
|
||||
.Append(directory_modification)
|
||||
@ -154,7 +158,10 @@ void TestCrashingChild(const base::string16& directory_modification) {
|
||||
delegate.set_break_near(break_near_address);
|
||||
|
||||
// Wait for the child to crash and the exception information to be validated.
|
||||
WaitForSingleObject(completed.get(), INFINITE);
|
||||
EXPECT_EQ(WaitForSingleObject(completed.get(), INFINITE), WAIT_OBJECT_0)
|
||||
<< ErrorMessage("WaitForSingleObject");
|
||||
|
||||
EXPECT_EQ(child.WaitForExit(), EXCEPTION_BREAKPOINT);
|
||||
}
|
||||
|
||||
TEST(ExceptionSnapshotWinTest, ChildCrash) {
|
||||
@ -194,7 +201,7 @@ class SimulateDelegate : public ExceptionHandlerServer::Delegate {
|
||||
exception_information_address,
|
||||
debug_critical_section_address);
|
||||
EXPECT_TRUE(snapshot.Exception());
|
||||
EXPECT_EQ(0x517a7ed, snapshot.Exception()->Exception());
|
||||
EXPECT_EQ(snapshot.Exception()->Exception(), 0x517a7ed);
|
||||
|
||||
// Verify the dump was captured at the expected location with some slop
|
||||
// space.
|
||||
@ -204,8 +211,8 @@ class SimulateDelegate : public ExceptionHandlerServer::Delegate {
|
||||
EXPECT_LT(snapshot.Exception()->Context()->InstructionPointer(),
|
||||
dump_near_ + kAllowedOffset);
|
||||
|
||||
EXPECT_EQ(snapshot.Exception()->Context()->InstructionPointer(),
|
||||
snapshot.Exception()->ExceptionAddress());
|
||||
EXPECT_EQ(snapshot.Exception()->ExceptionAddress(),
|
||||
snapshot.Exception()->Context()->InstructionPointer());
|
||||
|
||||
SetEvent(completed_test_event_);
|
||||
|
||||
@ -224,7 +231,9 @@ void TestDumpWithoutCrashingChild(
|
||||
const base::string16& directory_modification) {
|
||||
// Set up the registration server on a background thread.
|
||||
ScopedKernelHANDLE server_ready(CreateEvent(nullptr, false, false, nullptr));
|
||||
ASSERT_TRUE(server_ready.is_valid()) << ErrorMessage("CreateEvent");
|
||||
ScopedKernelHANDLE completed(CreateEvent(nullptr, false, false, nullptr));
|
||||
ASSERT_TRUE(completed.is_valid()) << ErrorMessage("CreateEvent");
|
||||
SimulateDelegate delegate(server_ready.get(), completed.get());
|
||||
|
||||
ExceptionHandlerServer exception_handler_server(true);
|
||||
@ -235,10 +244,11 @@ void TestDumpWithoutCrashingChild(
|
||||
ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread(
|
||||
&exception_handler_server, &server_thread);
|
||||
|
||||
WaitForSingleObject(server_ready.get(), INFINITE);
|
||||
EXPECT_EQ(WaitForSingleObject(server_ready.get(), INFINITE), WAIT_OBJECT_0)
|
||||
<< ErrorMessage("WaitForSingleObject");
|
||||
|
||||
// Spawn a child process, passing it the pipe name to connect to.
|
||||
base::FilePath test_executable = Paths::Executable();
|
||||
base::FilePath test_executable = TestPaths::Executable();
|
||||
std::wstring child_test_executable =
|
||||
test_executable.DirName()
|
||||
.Append(directory_modification)
|
||||
@ -256,7 +266,10 @@ void TestDumpWithoutCrashingChild(
|
||||
delegate.set_dump_near(dump_near_address);
|
||||
|
||||
// Wait for the child to crash and the exception information to be validated.
|
||||
WaitForSingleObject(completed.get(), INFINITE);
|
||||
EXPECT_EQ(WaitForSingleObject(completed.get(), INFINITE), WAIT_OBJECT_0)
|
||||
<< ErrorMessage("WaitForSingleObject");
|
||||
|
||||
EXPECT_EQ(child.WaitForExit(), 0);
|
||||
}
|
||||
|
||||
TEST(SimulateCrash, ChildDumpWithoutCrashing) {
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "client/simple_address_range_bag.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "snapshot/win/process_snapshot_win.h"
|
||||
#include "test/paths.h"
|
||||
#include "test/test_paths.h"
|
||||
#include "test/win/child_launcher.h"
|
||||
#include "util/file/file_io.h"
|
||||
#include "util/win/process_info.h"
|
||||
@ -45,7 +45,7 @@ enum TestType {
|
||||
void TestExtraMemoryRanges(TestType type,
|
||||
const base::string16& directory_modification) {
|
||||
// Spawn a child process, passing it the pipe name to connect to.
|
||||
base::FilePath test_executable = Paths::Executable();
|
||||
base::FilePath test_executable = TestPaths::Executable();
|
||||
std::wstring child_test_executable =
|
||||
test_executable.DirName()
|
||||
.Append(directory_modification)
|
||||
@ -71,15 +71,15 @@ void TestExtraMemoryRanges(TestType type,
|
||||
all_ranges.insert(range);
|
||||
}
|
||||
|
||||
EXPECT_EQ(5u, all_ranges.size());
|
||||
EXPECT_NE(all_ranges.end(), all_ranges.find(CheckedRange<uint64_t>(0, 1)));
|
||||
EXPECT_NE(all_ranges.end(), all_ranges.find(CheckedRange<uint64_t>(1, 0)));
|
||||
EXPECT_NE(all_ranges.end(),
|
||||
all_ranges.find(CheckedRange<uint64_t>(1234, 5678)));
|
||||
EXPECT_NE(all_ranges.end(),
|
||||
all_ranges.find(CheckedRange<uint64_t>(0x1000000000ULL, 0x1000)));
|
||||
EXPECT_NE(all_ranges.end(),
|
||||
all_ranges.find(CheckedRange<uint64_t>(0x2000, 0x2000000000ULL)));
|
||||
EXPECT_EQ(all_ranges.size(), 5u);
|
||||
EXPECT_NE(all_ranges.find(CheckedRange<uint64_t>(0, 1)), all_ranges.end());
|
||||
EXPECT_NE(all_ranges.find(CheckedRange<uint64_t>(1, 0)), all_ranges.end());
|
||||
EXPECT_NE(all_ranges.find(CheckedRange<uint64_t>(1234, 5678)),
|
||||
all_ranges.end());
|
||||
EXPECT_NE(all_ranges.find(CheckedRange<uint64_t>(0x1000000000ULL, 0x1000)),
|
||||
all_ranges.end());
|
||||
EXPECT_NE(all_ranges.find(CheckedRange<uint64_t>(0x2000, 0x2000000000ULL)),
|
||||
all_ranges.end());
|
||||
|
||||
// Tell the child process to continue.
|
||||
DWORD expected_exit_code;
|
||||
@ -97,7 +97,7 @@ void TestExtraMemoryRanges(TestType type,
|
||||
}
|
||||
CheckedWriteFile(child.stdin_write_handle(), &c, sizeof(c));
|
||||
|
||||
EXPECT_EQ(expected_exit_code, child.WaitForExit());
|
||||
EXPECT_EQ(child.WaitForExit(), expected_exit_code);
|
||||
}
|
||||
|
||||
TEST(ExtraMemoryRanges, DontCrash) {
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "snapshot/win/pe_image_reader.h"
|
||||
#include "snapshot/win/process_reader_win.h"
|
||||
#include "test/paths.h"
|
||||
#include "test/test_paths.h"
|
||||
#include "test/win/child_launcher.h"
|
||||
#include "util/file/file_io.h"
|
||||
#include "util/win/process_info.h"
|
||||
@ -49,7 +49,7 @@ enum TestType {
|
||||
void TestAnnotationsOnCrash(TestType type,
|
||||
const base::string16& directory_modification) {
|
||||
// Spawn a child process, passing it the pipe name to connect to.
|
||||
base::FilePath test_executable = Paths::Executable();
|
||||
base::FilePath test_executable = TestPaths::Executable();
|
||||
std::wstring child_test_executable =
|
||||
test_executable.DirName()
|
||||
.Append(directory_modification)
|
||||
@ -86,11 +86,11 @@ void TestAnnotationsOnCrash(TestType type,
|
||||
}
|
||||
|
||||
EXPECT_GE(all_annotations_simple_map.size(), 5u);
|
||||
EXPECT_EQ("crash", all_annotations_simple_map["#TEST# pad"]);
|
||||
EXPECT_EQ("value", all_annotations_simple_map["#TEST# key"]);
|
||||
EXPECT_EQ("y", all_annotations_simple_map["#TEST# x"]);
|
||||
EXPECT_EQ("shorter", all_annotations_simple_map["#TEST# longer"]);
|
||||
EXPECT_EQ("", all_annotations_simple_map["#TEST# empty_value"]);
|
||||
EXPECT_EQ(all_annotations_simple_map["#TEST# pad"], "crash");
|
||||
EXPECT_EQ(all_annotations_simple_map["#TEST# key"], "value");
|
||||
EXPECT_EQ(all_annotations_simple_map["#TEST# x"], "y");
|
||||
EXPECT_EQ(all_annotations_simple_map["#TEST# longer"], "shorter");
|
||||
EXPECT_EQ(all_annotations_simple_map["#TEST# empty_value"], "");
|
||||
|
||||
// Tell the child process to continue.
|
||||
DWORD expected_exit_code;
|
||||
@ -108,7 +108,7 @@ void TestAnnotationsOnCrash(TestType type,
|
||||
}
|
||||
CheckedWriteFile(child.stdin_write_handle(), &c, sizeof(c));
|
||||
|
||||
EXPECT_EQ(expected_exit_code, child.WaitForExit());
|
||||
EXPECT_EQ(child.WaitForExit(), expected_exit_code);
|
||||
}
|
||||
|
||||
TEST(PEImageAnnotationsReader, DontCrash) {
|
||||
|
@ -42,7 +42,7 @@ TEST(PEImageReader, DebugDirectory) {
|
||||
ASSERT_TRUE(CrashpadGetModuleInformation(
|
||||
GetCurrentProcess(), self, &module_info, sizeof(module_info)))
|
||||
<< ErrorMessage("GetModuleInformation");
|
||||
EXPECT_EQ(self, module_info.lpBaseOfDll);
|
||||
EXPECT_EQ(module_info.lpBaseOfDll, self);
|
||||
ASSERT_TRUE(pe_image_reader.Initialize(&process_reader,
|
||||
reinterpret_cast<WinVMAddress>(self),
|
||||
module_info.SizeOfImage,
|
||||
@ -51,11 +51,11 @@ TEST(PEImageReader, DebugDirectory) {
|
||||
DWORD age;
|
||||
std::string pdbname;
|
||||
EXPECT_TRUE(pe_image_reader.DebugDirectoryInformation(&uuid, &age, &pdbname));
|
||||
EXPECT_NE(std::string::npos, pdbname.find("crashpad_snapshot_test"));
|
||||
EXPECT_NE(pdbname.find("crashpad_snapshot_test"), std::string::npos);
|
||||
const std::string suffix(".pdb");
|
||||
EXPECT_EQ(
|
||||
0,
|
||||
pdbname.compare(pdbname.size() - suffix.size(), suffix.size(), suffix));
|
||||
pdbname.compare(pdbname.size() - suffix.size(), suffix.size(), suffix),
|
||||
0);
|
||||
}
|
||||
|
||||
void TestVSFixedFileInfo(ProcessReaderWin* process_reader,
|
||||
@ -72,12 +72,12 @@ void TestVSFixedFileInfo(ProcessReaderWin* process_reader,
|
||||
ASSERT_TRUE(observed_rv || !known_dll);
|
||||
|
||||
if (observed_rv) {
|
||||
EXPECT_EQ(VS_FFI_SIGNATURE, observed.dwSignature);
|
||||
EXPECT_EQ(VS_FFI_STRUCVERSION, observed.dwStrucVersion);
|
||||
EXPECT_EQ(0, observed.dwFileFlags & ~observed.dwFileFlagsMask);
|
||||
EXPECT_EQ(VOS_NT_WINDOWS32, observed.dwFileOS);
|
||||
EXPECT_EQ(observed.dwSignature, VS_FFI_SIGNATURE);
|
||||
EXPECT_EQ(observed.dwStrucVersion, VS_FFI_STRUCVERSION);
|
||||
EXPECT_EQ(observed.dwFileFlags & ~observed.dwFileFlagsMask, 0);
|
||||
EXPECT_EQ(observed.dwFileOS, VOS_NT_WINDOWS32);
|
||||
if (known_dll) {
|
||||
EXPECT_EQ(VFT_DLL, observed.dwFileType);
|
||||
EXPECT_EQ(observed.dwFileType, VFT_DLL);
|
||||
} else {
|
||||
EXPECT_TRUE(observed.dwFileType == VFT_APP ||
|
||||
observed.dwFileType == VFT_DLL);
|
||||
@ -103,22 +103,22 @@ void TestVSFixedFileInfo(ProcessReaderWin* process_reader,
|
||||
const bool expected_rv = GetModuleVersionAndType(module_path, &expected);
|
||||
ASSERT_TRUE(expected_rv || !known_dll);
|
||||
|
||||
EXPECT_EQ(expected_rv, observed_rv);
|
||||
EXPECT_EQ(observed_rv, expected_rv);
|
||||
|
||||
if (observed_rv && expected_rv) {
|
||||
EXPECT_EQ(expected.dwSignature, observed.dwSignature);
|
||||
EXPECT_EQ(expected.dwStrucVersion, observed.dwStrucVersion);
|
||||
EXPECT_EQ(expected.dwFileVersionMS, observed.dwFileVersionMS);
|
||||
EXPECT_EQ(expected.dwFileVersionLS, observed.dwFileVersionLS);
|
||||
EXPECT_EQ(expected.dwProductVersionMS, observed.dwProductVersionMS);
|
||||
EXPECT_EQ(expected.dwProductVersionLS, observed.dwProductVersionLS);
|
||||
EXPECT_EQ(expected.dwFileFlagsMask, observed.dwFileFlagsMask);
|
||||
EXPECT_EQ(expected.dwFileFlags, observed.dwFileFlags);
|
||||
EXPECT_EQ(expected.dwFileOS, observed.dwFileOS);
|
||||
EXPECT_EQ(expected.dwFileType, observed.dwFileType);
|
||||
EXPECT_EQ(expected.dwFileSubtype, observed.dwFileSubtype);
|
||||
EXPECT_EQ(expected.dwFileDateMS, observed.dwFileDateMS);
|
||||
EXPECT_EQ(expected.dwFileDateLS, observed.dwFileDateLS);
|
||||
EXPECT_EQ(observed.dwSignature, expected.dwSignature);
|
||||
EXPECT_EQ(observed.dwStrucVersion, expected.dwStrucVersion);
|
||||
EXPECT_EQ(observed.dwFileVersionMS, expected.dwFileVersionMS);
|
||||
EXPECT_EQ(observed.dwFileVersionLS, expected.dwFileVersionLS);
|
||||
EXPECT_EQ(observed.dwProductVersionMS, expected.dwProductVersionMS);
|
||||
EXPECT_EQ(observed.dwProductVersionLS, expected.dwProductVersionLS);
|
||||
EXPECT_EQ(observed.dwFileFlagsMask, expected.dwFileFlagsMask);
|
||||
EXPECT_EQ(observed.dwFileFlags, expected.dwFileFlags);
|
||||
EXPECT_EQ(observed.dwFileOS, expected.dwFileOS);
|
||||
EXPECT_EQ(observed.dwFileType, expected.dwFileType);
|
||||
EXPECT_EQ(observed.dwFileSubtype, expected.dwFileSubtype);
|
||||
EXPECT_EQ(observed.dwFileDateMS, expected.dwFileDateMS);
|
||||
EXPECT_EQ(observed.dwFileDateLS, expected.dwFileDateLS);
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,7 +135,7 @@ TEST(PEImageReader, VSFixedFileInfo_OneModule) {
|
||||
ASSERT_TRUE(CrashpadGetModuleInformation(
|
||||
GetCurrentProcess(), module_handle, &module_info, sizeof(module_info)))
|
||||
<< ErrorMessage("GetModuleInformation");
|
||||
EXPECT_EQ(module_handle, module_info.lpBaseOfDll);
|
||||
EXPECT_EQ(module_info.lpBaseOfDll, module_handle);
|
||||
|
||||
ProcessInfo::Module module;
|
||||
module.name = kModuleName;
|
||||
|
@ -57,6 +57,7 @@ process_types::SYSTEM_PROCESS_INFORMATION<Traits>* GetProcessInformation(
|
||||
HANDLE process_handle,
|
||||
std::unique_ptr<uint8_t[]>* buffer) {
|
||||
ULONG buffer_size = 16384;
|
||||
ULONG actual_size;
|
||||
buffer->reset(new uint8_t[buffer_size]);
|
||||
NTSTATUS status;
|
||||
// This must be in retry loop, as we're racing with process creation on the
|
||||
@ -66,13 +67,19 @@ process_types::SYSTEM_PROCESS_INFORMATION<Traits>* GetProcessInformation(
|
||||
SystemProcessInformation,
|
||||
reinterpret_cast<void*>(buffer->get()),
|
||||
buffer_size,
|
||||
&buffer_size);
|
||||
&actual_size);
|
||||
if (status == STATUS_BUFFER_TOO_SMALL ||
|
||||
status == STATUS_INFO_LENGTH_MISMATCH) {
|
||||
DCHECK_GT(actual_size, buffer_size);
|
||||
|
||||
// Add a little extra to try to avoid an additional loop iteration. We're
|
||||
// racing with system-wide process creation between here and the next call
|
||||
// to NtQuerySystemInformation().
|
||||
buffer_size += 4096;
|
||||
buffer_size = actual_size + 4096;
|
||||
|
||||
// Free the old buffer before attempting to allocate a new one.
|
||||
buffer->reset();
|
||||
|
||||
buffer->reset(new uint8_t[buffer_size]);
|
||||
} else {
|
||||
break;
|
||||
@ -84,6 +91,8 @@ process_types::SYSTEM_PROCESS_INFORMATION<Traits>* GetProcessInformation(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DCHECK_LE(actual_size, buffer_size);
|
||||
|
||||
process_types::SYSTEM_PROCESS_INFORMATION<Traits>* process =
|
||||
reinterpret_cast<process_types::SYSTEM_PROCESS_INFORMATION<Traits>*>(
|
||||
buffer->get());
|
||||
|
@ -38,7 +38,7 @@ TEST(ProcessReaderWin, SelfBasic) {
|
||||
EXPECT_TRUE(process_reader.Is64Bit());
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(GetCurrentProcessId(), process_reader.GetProcessInfo().ProcessID());
|
||||
EXPECT_EQ(process_reader.GetProcessInfo().ProcessID(), GetCurrentProcessId());
|
||||
|
||||
const char kTestMemory[] = "Some test memory";
|
||||
char buffer[arraysize(kTestMemory)];
|
||||
@ -74,7 +74,7 @@ class ProcessReaderChild final : public WinMultiprocess {
|
||||
char buffer[sizeof(kTestMemory)];
|
||||
ASSERT_TRUE(
|
||||
process_reader.ReadMemory(address, sizeof(kTestMemory), &buffer));
|
||||
EXPECT_EQ(0, strcmp(kTestMemory, buffer));
|
||||
EXPECT_EQ(strcmp(kTestMemory, buffer), 0);
|
||||
}
|
||||
|
||||
void WinMultiprocessChild() override {
|
||||
@ -106,14 +106,14 @@ TEST(ProcessReaderWin, SelfOneThread) {
|
||||
// thread, not exactly one thread.
|
||||
ASSERT_GE(threads.size(), 1u);
|
||||
|
||||
EXPECT_EQ(GetCurrentThreadId(), threads[0].id);
|
||||
EXPECT_EQ(threads[0].id, GetCurrentThreadId());
|
||||
#if defined(ARCH_CPU_64_BITS)
|
||||
EXPECT_NE(0, threads[0].context.native.Rip);
|
||||
EXPECT_NE(threads[0].context.native.Rip, 0);
|
||||
#else
|
||||
EXPECT_NE(0u, threads[0].context.native.Eip);
|
||||
EXPECT_NE(threads[0].context.native.Eip, 0u);
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(0, threads[0].suspend_count);
|
||||
EXPECT_EQ(threads[0].suspend_count, 0);
|
||||
}
|
||||
|
||||
class ProcessReaderChildThreadSuspendCount final : public WinMultiprocess {
|
||||
@ -143,7 +143,7 @@ class ProcessReaderChildThreadSuspendCount final : public WinMultiprocess {
|
||||
void WinMultiprocessParent() override {
|
||||
char c;
|
||||
CheckedReadFileExactly(ReadPipeHandle(), &c, sizeof(c));
|
||||
ASSERT_EQ(' ', c);
|
||||
ASSERT_EQ(c, ' ');
|
||||
|
||||
{
|
||||
ProcessReaderWin process_reader;
|
||||
@ -153,7 +153,7 @@ class ProcessReaderChildThreadSuspendCount final : public WinMultiprocess {
|
||||
const auto& threads = process_reader.Threads();
|
||||
ASSERT_GE(threads.size(), kCreatedThreads + 1);
|
||||
for (const auto& thread : threads)
|
||||
EXPECT_EQ(0u, thread.suspend_count);
|
||||
EXPECT_EQ(thread.suspend_count, 0u);
|
||||
}
|
||||
|
||||
{
|
||||
@ -168,7 +168,7 @@ class ProcessReaderChildThreadSuspendCount final : public WinMultiprocess {
|
||||
const auto& threads = process_reader.Threads();
|
||||
ASSERT_GE(threads.size(), kCreatedThreads + 1);
|
||||
for (const auto& thread : threads)
|
||||
EXPECT_EQ(0u, thread.suspend_count);
|
||||
EXPECT_EQ(thread.suspend_count, 0u);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "snapshot/win/process_snapshot_win.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -325,8 +326,9 @@ void ProcessSnapshotWin::InitializeUnloadedModules() {
|
||||
uet.SizeOfImage,
|
||||
uet.CheckSum,
|
||||
uet.TimeDateStamp,
|
||||
base::UTF16ToUTF8(
|
||||
base::StringPiece16(uet.ImageName, arraysize(uet.ImageName)))));
|
||||
base::UTF16ToUTF8(base::StringPiece16(
|
||||
uet.ImageName,
|
||||
wcsnlen(uet.ImageName, arraysize(uet.ImageName))))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,8 @@
|
||||
#include "snapshot/win/module_snapshot_win.h"
|
||||
#include "snapshot/win/pe_image_reader.h"
|
||||
#include "snapshot/win/process_reader_win.h"
|
||||
#include "test/paths.h"
|
||||
#include "test/errors.h"
|
||||
#include "test/test_paths.h"
|
||||
#include "test/win/child_launcher.h"
|
||||
#include "util/file/file_io.h"
|
||||
#include "util/win/scoped_handle.h"
|
||||
@ -35,9 +36,9 @@ void TestImageReaderChild(const base::string16& directory_modification) {
|
||||
done_uuid.InitializeWithNew();
|
||||
ScopedKernelHANDLE done(
|
||||
CreateEvent(nullptr, true, false, done_uuid.ToString16().c_str()));
|
||||
ASSERT_TRUE(done.get());
|
||||
ASSERT_TRUE(done.is_valid()) << ErrorMessage("CreateEvent");
|
||||
|
||||
base::FilePath test_executable = Paths::Executable();
|
||||
base::FilePath test_executable = TestPaths::Executable();
|
||||
std::wstring child_test_executable =
|
||||
test_executable.DirName()
|
||||
.Append(directory_modification)
|
||||
@ -50,61 +51,65 @@ void TestImageReaderChild(const base::string16& directory_modification) {
|
||||
char c;
|
||||
ASSERT_TRUE(
|
||||
LoggingReadFileExactly(child.stdout_read_handle(), &c, sizeof(c)));
|
||||
ASSERT_EQ(' ', c);
|
||||
ASSERT_EQ(c, ' ');
|
||||
|
||||
ScopedProcessSuspend suspend(child.process_handle());
|
||||
{
|
||||
ScopedProcessSuspend suspend(child.process_handle());
|
||||
|
||||
ProcessSnapshotWin process_snapshot;
|
||||
ASSERT_TRUE(process_snapshot.Initialize(
|
||||
child.process_handle(), ProcessSuspensionState::kSuspended, 0, 0));
|
||||
ProcessSnapshotWin process_snapshot;
|
||||
ASSERT_TRUE(process_snapshot.Initialize(
|
||||
child.process_handle(), ProcessSuspensionState::kSuspended, 0, 0));
|
||||
|
||||
ASSERT_GE(process_snapshot.Modules().size(), 2u);
|
||||
ASSERT_GE(process_snapshot.Modules().size(), 2u);
|
||||
|
||||
UUID uuid;
|
||||
DWORD age;
|
||||
std::string pdbname;
|
||||
const std::string suffix(".pdb");
|
||||
UUID uuid;
|
||||
DWORD age;
|
||||
std::string pdbname;
|
||||
const std::string suffix(".pdb");
|
||||
|
||||
// Check the main .exe to see that we can retrieve its sections.
|
||||
auto module = reinterpret_cast<const internal::ModuleSnapshotWin*>(
|
||||
process_snapshot.Modules()[0]);
|
||||
ASSERT_TRUE(module->pe_image_reader().DebugDirectoryInformation(
|
||||
&uuid, &age, &pdbname));
|
||||
EXPECT_NE(std::string::npos,
|
||||
pdbname.find("crashpad_snapshot_test_image_reader"));
|
||||
EXPECT_EQ(
|
||||
0,
|
||||
pdbname.compare(pdbname.size() - suffix.size(), suffix.size(), suffix));
|
||||
// Check the main .exe to see that we can retrieve its sections.
|
||||
auto module = reinterpret_cast<const internal::ModuleSnapshotWin*>(
|
||||
process_snapshot.Modules()[0]);
|
||||
ASSERT_TRUE(module->pe_image_reader().DebugDirectoryInformation(
|
||||
&uuid, &age, &pdbname));
|
||||
EXPECT_NE(pdbname.find("crashpad_snapshot_test_image_reader"),
|
||||
std::string::npos);
|
||||
EXPECT_EQ(
|
||||
pdbname.compare(pdbname.size() - suffix.size(), suffix.size(), suffix),
|
||||
0);
|
||||
|
||||
// Check the dll it loads too.
|
||||
module = reinterpret_cast<const internal::ModuleSnapshotWin*>(
|
||||
process_snapshot.Modules().back());
|
||||
ASSERT_TRUE(module->pe_image_reader().DebugDirectoryInformation(
|
||||
&uuid, &age, &pdbname));
|
||||
EXPECT_NE(std::string::npos,
|
||||
pdbname.find("crashpad_snapshot_test_image_reader_module"));
|
||||
EXPECT_EQ(
|
||||
0,
|
||||
pdbname.compare(pdbname.size() - suffix.size(), suffix.size(), suffix));
|
||||
// Check the dll it loads too.
|
||||
module = reinterpret_cast<const internal::ModuleSnapshotWin*>(
|
||||
process_snapshot.Modules().back());
|
||||
ASSERT_TRUE(module->pe_image_reader().DebugDirectoryInformation(
|
||||
&uuid, &age, &pdbname));
|
||||
EXPECT_NE(pdbname.find("crashpad_snapshot_test_image_reader_module"),
|
||||
std::string::npos);
|
||||
EXPECT_EQ(
|
||||
pdbname.compare(pdbname.size() - suffix.size(), suffix.size(), suffix),
|
||||
0);
|
||||
|
||||
// Sum the size of the extra memory in all the threads and confirm it's near
|
||||
// the limit that the child process set in its CrashpadInfo.
|
||||
EXPECT_GE(process_snapshot.Threads().size(), 100u);
|
||||
// Sum the size of the extra memory in all the threads and confirm it's near
|
||||
// the limit that the child process set in its CrashpadInfo.
|
||||
EXPECT_GE(process_snapshot.Threads().size(), 100u);
|
||||
|
||||
size_t extra_memory_total = 0;
|
||||
for (const auto* thread : process_snapshot.Threads()) {
|
||||
for (const auto* extra_memory : thread->ExtraMemory()) {
|
||||
extra_memory_total += extra_memory->Size();
|
||||
size_t extra_memory_total = 0;
|
||||
for (const auto* thread : process_snapshot.Threads()) {
|
||||
for (const auto* extra_memory : thread->ExtraMemory()) {
|
||||
extra_memory_total += extra_memory->Size();
|
||||
}
|
||||
}
|
||||
|
||||
// Confirm that less than 1M of extra data was gathered. The cap is set to
|
||||
// only 100K, but there are other "extra memory" regions that aren't
|
||||
// included in the cap. (Completely uncapped it would be > 10M.)
|
||||
EXPECT_LT(extra_memory_total, 1000000u);
|
||||
}
|
||||
|
||||
// We confirm we gathered less than 1M of extra data. The cap is set to only
|
||||
// 100K, but there are other "extra memory" regions that aren't included in
|
||||
// the cap. (Completely uncapped it would be > 10M.)
|
||||
EXPECT_LT(extra_memory_total, 1000000u);
|
||||
|
||||
// Tell the child it can terminate.
|
||||
SetEvent(done.get());
|
||||
EXPECT_TRUE(SetEvent(done.get())) << ErrorMessage("SetEvent");
|
||||
|
||||
EXPECT_EQ(child.WaitForExit(), 0);
|
||||
}
|
||||
|
||||
TEST(ProcessSnapshotTest, CrashpadInfoChild) {
|
||||
|
@ -57,9 +57,9 @@ TEST_F(SystemSnapshotWinTest, GetCPUArchitecture) {
|
||||
CPUArchitecture cpu_architecture = system_snapshot().GetCPUArchitecture();
|
||||
|
||||
#if defined(ARCH_CPU_X86)
|
||||
EXPECT_EQ(kCPUArchitectureX86, cpu_architecture);
|
||||
EXPECT_EQ(cpu_architecture, kCPUArchitectureX86);
|
||||
#elif defined(ARCH_CPU_X86_64)
|
||||
EXPECT_EQ(kCPUArchitectureX86_64, cpu_architecture);
|
||||
EXPECT_EQ(cpu_architecture, kCPUArchitectureX86_64);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -82,8 +82,8 @@ TEST_F(SystemSnapshotWinTest, CPUX86SupportsDAZ) {
|
||||
}
|
||||
|
||||
TEST_F(SystemSnapshotWinTest, GetOperatingSystem) {
|
||||
EXPECT_EQ(SystemSnapshot::kOperatingSystemWindows,
|
||||
system_snapshot().GetOperatingSystem());
|
||||
EXPECT_EQ(system_snapshot().GetOperatingSystem(),
|
||||
SystemSnapshot::kOperatingSystemWindows);
|
||||
}
|
||||
|
||||
TEST_F(SystemSnapshotWinTest, OSVersion) {
|
||||
@ -127,20 +127,20 @@ TEST_F(SystemSnapshotWinTest, TimeZone) {
|
||||
long timezone = 0;
|
||||
_get_timezone(&timezone);
|
||||
#endif
|
||||
EXPECT_EQ(-timezone, standard_offset_seconds);
|
||||
EXPECT_EQ(standard_offset_seconds, -timezone);
|
||||
|
||||
// In contemporary usage, most time zones have an integer hour offset from
|
||||
// UTC, although several are at a half-hour offset, and two are at 15-minute
|
||||
// offsets. Throughout history, other variations existed. See
|
||||
// http://www.timeanddate.com/time/time-zones-interesting.html.
|
||||
EXPECT_EQ(0, standard_offset_seconds % (15 * 60))
|
||||
EXPECT_EQ(standard_offset_seconds % (15 * 60), 0)
|
||||
<< "standard_offset_seconds " << standard_offset_seconds;
|
||||
|
||||
if (dst_status == SystemSnapshot::kDoesNotObserveDaylightSavingTime) {
|
||||
EXPECT_EQ(standard_offset_seconds, daylight_offset_seconds);
|
||||
EXPECT_EQ(standard_name, daylight_name);
|
||||
EXPECT_EQ(daylight_offset_seconds, standard_offset_seconds);
|
||||
EXPECT_EQ(daylight_name, standard_name);
|
||||
} else {
|
||||
EXPECT_EQ(0, daylight_offset_seconds % (15 * 60))
|
||||
EXPECT_EQ(daylight_offset_seconds % (15 * 60), 0)
|
||||
<< "daylight_offset_seconds " << daylight_offset_seconds;
|
||||
|
||||
// In contemporary usage, dst_delta_seconds will almost always be one hour,
|
||||
|
@ -30,7 +30,7 @@ namespace test {
|
||||
// Where non-test code could do:
|
||||
// PCHECK(rv == 0) << "close";
|
||||
// gtest-based test code can do:
|
||||
// EXPECT_EQ(0, rv) << ErrnoMessage("close");
|
||||
// EXPECT_EQ(rv, 0) << ErrnoMessage("close");
|
||||
|
||||
//! \brief Formats an error message using an `errno` value.
|
||||
//!
|
||||
|
@ -37,7 +37,7 @@ bool FileExists(const base::FilePath& path) {
|
||||
#error "Not implemented"
|
||||
#endif
|
||||
if (rv < 0) {
|
||||
EXPECT_EQ(ENOENT, errno) << ErrnoMessage(stat_function) << " "
|
||||
EXPECT_EQ(errno, ENOENT) << ErrnoMessage(stat_function) << " "
|
||||
<< path.value();
|
||||
return false;
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ namespace test {
|
||||
//! uint8_t expected[10];
|
||||
//! uint8_t observed[10];
|
||||
//! // …
|
||||
//! EXPECT_EQ(BytesToHexString(expected, arraysize(expected)),
|
||||
//! BytesToHexString(observed, arraysize(observed)));
|
||||
//! EXPECT_EQ(BytesToHexString(observed, arraysize(observed)),
|
||||
//! BytesToHexString(expected, arraysize(expected)));
|
||||
//! \endcode
|
||||
std::string BytesToHexString(const void* bytes, size_t length);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user