Merge master 2ec34e32c2f4 into doc

This commit is contained in:
Mark Mentovai 2017-04-13 13:59:12 -04:00
commit 52af72d371
205 changed files with 6932 additions and 3875 deletions

2
DEPS
View File

@ -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',

View File

@ -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__ isnt 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 wont mention
# __ANDROID_API__, but the standalone toolchains <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__':

View File

@ -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

View File

@ -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 Programmers 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);
}

View File

@ -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',

View File

@ -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 thats already in the
//! completed state.
kReportNotFound,
//! \brief An error occured while performing a file operation on a crash

View File

@ -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;

View File

@ -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(&times[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(&times[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() shouldnt 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

View File

@ -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);
}

View File

@ -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(),

View File

@ -96,10 +96,19 @@ struct CrashpadInfo {
//! SimpleStringDictionary object. It is the callers 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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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)));
}

View File

@ -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

View File

@ -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");
}

View File

@ -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:

View 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_

View File

@ -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:*',

View File

@ -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 \

View File

@ -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

View File

@ -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
View 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:]))

View File

@ -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

View File

@ -252,9 +252,12 @@ void CrashReportUploadThread::ProcessPendingReport(
break;
case CrashReportDatabase::kBusyError:
case CrashReportDatabase::kReportNotFound:
// Someone else may have gotten to it first. If theyre working on it now,
// this will be kBusyError. If theyve already finished with it, itll be
// kReportNotFound.
return;
case CrashReportDatabase::kReportNotFound:
case CrashReportDatabase::kFileSystemError:
case CrashReportDatabase::kDatabaseError:
// In these cases, SkipReportUpload() might not work either, but its best

View File

@ -138,6 +138,51 @@ establish the Crashpad client environment before running a program.
service declared in a jobs `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

View 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

View 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

View File

@ -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',
],

View File

@ -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 theres 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 thats 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()));
}
// Dont 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()) {
// Dont 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()) {

View File

@ -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
View 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',
],
}],
}],
],
}

View File

@ -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);

View File

@ -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);
};

View File

@ -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

View 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

View 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_

View File

@ -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

View File

@ -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(

View File

@ -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);
};

View File

@ -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) {

View File

@ -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);

View File

@ -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>(

View File

@ -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);

View File

@ -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));
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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) {

View File

@ -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>(

View File

@ -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));

View File

@ -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]);
}
}

View File

@ -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 dont 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 dont 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

View File

@ -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]));
}
}

View File

@ -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;
}
}

View File

@ -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',
],
},
],

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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() {}

View File

@ -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);
};

View File

@ -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() {

View File

@ -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_;

View File

@ -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

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View 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

View 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_

View File

@ -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;
}

View File

@ -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 = ' ';

View File

@ -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 shouldnt be consulted at
// all, so theyre 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

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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 its 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 doesnt matter very much, because dyld wont
@ -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;
}

View File

@ -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() doesnt 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 MachOImageReaders
// 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 MachOImageReaders 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 dont 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 dont 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);
}
// Youd 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));
// Theres no good API to get dylds slide, so dont 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

View File

@ -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,

View File

@ -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 its 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 cant 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 cant 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 doesnt 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 doesnt 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 didnt load the main executable, so it couldnt 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 doesnt 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 didnt 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 didnt load itself either, so it couldnt 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 didnt load the main executable or itself, so it couldnt 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 doesnt 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 didnt 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 {

View File

@ -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;
}
}

View File

@ -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 dont. 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);
}
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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):

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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());

View File

@ -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);
}
}

View File

@ -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))))));
}
}
}

View File

@ -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) {

View File

@ -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,

View File

@ -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.
//!

View File

@ -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;
}

View File

@ -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