Refactor minidump test utilities for MinidumpWritable,

MinidumpFileWriter, and Minidump*StringWriter.

TEST=minidump_test
R=rsesek@chromium.org

Review URL: https://codereview.chromium.org/664283002
This commit is contained in:
Mark Mentovai 2014-10-21 14:15:07 -04:00
Родитель 01c535b001
Коммит 8a6a4c68e4
17 изменённых файлов: 499 добавлений и 201 удалений

Просмотреть файл

@ -95,6 +95,8 @@
'test/minidump_memory_writer_test_util.h',
'test/minidump_string_writer_test_util.cc',
'test/minidump_string_writer_test_util.h',
'test/minidump_writable_test_util.cc',
'test/minidump_writable_test_util.h',
],
},
],

Просмотреть файл

@ -48,18 +48,15 @@ void GetCrashpadInfoStream(
EXPECT_GE(file_contents.size(), kFileSize);
}
const MINIDUMP_DIRECTORY* directory;
const MINIDUMP_HEADER* header =
reinterpret_cast<const MINIDUMP_HEADER*>(&file_contents[0]);
MinidumpHeaderAtStart(file_contents, &directory);
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
ASSERT_TRUE(directory);
const MINIDUMP_DIRECTORY* directory =
reinterpret_cast<const MINIDUMP_DIRECTORY*>(
&file_contents[kDirectoryOffset]);
ASSERT_EQ(kMinidumpStreamTypeCrashpadInfo, directory->StreamType);
ASSERT_EQ(sizeof(MinidumpCrashpadInfo), directory->Location.DataSize);
ASSERT_EQ(kCrashpadInfoStreamOffset, directory->Location.Rva);
ASSERT_EQ(kMinidumpStreamTypeCrashpadInfo, directory[0].StreamType);
ASSERT_EQ(sizeof(MinidumpCrashpadInfo), directory[0].Location.DataSize);
ASSERT_EQ(kCrashpadInfoStreamOffset, directory[0].Location.Rva);
*crashpad_info = reinterpret_cast<const MinidumpCrashpadInfo*>(
&file_contents[kCrashpadInfoStreamOffset]);
@ -136,18 +133,18 @@ TEST(MinidumpCrashpadInfoWriter, SimpleAnnotations) {
ASSERT_EQ(2u, simple_annotations->count);
EXPECT_EQ(
kKey1,
MinidumpUTF8StringAtRVA(file_writer, simple_annotations->entries[0].key));
EXPECT_EQ(kKey1,
MinidumpUTF8StringAtRVAAsString(
file_writer.string(), simple_annotations->entries[0].key));
EXPECT_EQ(kValue1,
MinidumpUTF8StringAtRVA(file_writer,
simple_annotations->entries[0].value));
EXPECT_EQ(
kKey0,
MinidumpUTF8StringAtRVA(file_writer, simple_annotations->entries[1].key));
MinidumpUTF8StringAtRVAAsString(
file_writer.string(), simple_annotations->entries[0].value));
EXPECT_EQ(kKey0,
MinidumpUTF8StringAtRVAAsString(
file_writer.string(), simple_annotations->entries[1].key));
EXPECT_EQ(kValue0,
MinidumpUTF8StringAtRVA(file_writer,
simple_annotations->entries[1].value));
MinidumpUTF8StringAtRVAAsString(
file_writer.string(), simple_annotations->entries[1].value));
}
} // namespace

Просмотреть файл

@ -44,15 +44,11 @@ void GetExceptionStream(const std::string& file_contents,
const size_t kFileSize = kContextOffset + sizeof(MinidumpContextX86);
ASSERT_EQ(file_contents.size(), kFileSize);
const MINIDUMP_DIRECTORY* directory;
const MINIDUMP_HEADER* header =
reinterpret_cast<const MINIDUMP_HEADER*>(&file_contents[0]);
MinidumpHeaderAtStart(file_contents, &directory);
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
const MINIDUMP_DIRECTORY* directory =
reinterpret_cast<const MINIDUMP_DIRECTORY*>(
&file_contents[kDirectoryOffset]);
ASSERT_EQ(kMinidumpStreamTypeException, directory[0].StreamType);
ASSERT_GE(directory[0].Location.DataSize, sizeof(MINIDUMP_EXCEPTION_STREAM));
ASSERT_EQ(kExceptionStreamOffset, directory[0].Location.Rva);

Просмотреть файл

@ -36,10 +36,11 @@ TEST(MinidumpFileWriter, Empty) {
ASSERT_TRUE(minidump_file.WriteEverything(&file_writer));
ASSERT_EQ(sizeof(MINIDUMP_HEADER), file_writer.string().size());
const MINIDUMP_DIRECTORY* directory;
const MINIDUMP_HEADER* header =
reinterpret_cast<const MINIDUMP_HEADER*>(&file_writer.string()[0]);
MinidumpHeaderAtStart(file_writer.string(), &directory);
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 0, 0));
EXPECT_FALSE(directory);
}
class TestStream final : public internal::MinidumpStreamWriter {
@ -95,18 +96,15 @@ TEST(MinidumpFileWriter, OneStream) {
ASSERT_EQ(kFileSize, file_writer.string().size());
const MINIDUMP_DIRECTORY* directory;
const MINIDUMP_HEADER* header =
reinterpret_cast<const MINIDUMP_HEADER*>(&file_writer.string()[0]);
MinidumpHeaderAtStart(file_writer.string(), &directory);
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, kTimestamp));
ASSERT_TRUE(directory);
const MINIDUMP_DIRECTORY* directory =
reinterpret_cast<const MINIDUMP_DIRECTORY*>(
&file_writer.string()[kDirectoryOffset]);
EXPECT_EQ(kStreamType, directory->StreamType);
EXPECT_EQ(kStreamSize, directory->Location.DataSize);
EXPECT_EQ(kStreamOffset, directory->Location.Rva);
EXPECT_EQ(kStreamType, directory[0].StreamType);
EXPECT_EQ(kStreamSize, directory[0].Location.DataSize);
EXPECT_EQ(kStreamOffset, directory[0].Location.Rva);
const uint8_t* stream_data =
reinterpret_cast<const uint8_t*>(&file_writer.string()[kStreamOffset]);
@ -155,14 +153,11 @@ TEST(MinidumpFileWriter, ThreeStreams) {
ASSERT_EQ(kFileSize, file_writer.string().size());
const MINIDUMP_DIRECTORY* directory;
const MINIDUMP_HEADER* header =
reinterpret_cast<const MINIDUMP_HEADER*>(&file_writer.string()[0]);
MinidumpHeaderAtStart(file_writer.string(), &directory);
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 3, kTimestamp));
const MINIDUMP_DIRECTORY* directory =
reinterpret_cast<const MINIDUMP_DIRECTORY*>(
&file_writer.string()[kDirectoryOffset]);
ASSERT_TRUE(directory);
EXPECT_EQ(kStream1Type, directory[0].StreamType);
EXPECT_EQ(kStream1Size, directory[0].Location.DataSize);
@ -217,18 +212,15 @@ TEST(MinidumpFileWriter, ZeroLengthStream) {
ASSERT_EQ(kFileSize, file_writer.string().size());
const MINIDUMP_DIRECTORY* directory;
const MINIDUMP_HEADER* header =
reinterpret_cast<const MINIDUMP_HEADER*>(&file_writer.string()[0]);
MinidumpHeaderAtStart(file_writer.string(), &directory);
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
ASSERT_TRUE(directory);
const MINIDUMP_DIRECTORY* directory =
reinterpret_cast<const MINIDUMP_DIRECTORY*>(
&file_writer.string()[kDirectoryOffset]);
EXPECT_EQ(kStreamType, directory->StreamType);
EXPECT_EQ(kStreamSize, directory->Location.DataSize);
EXPECT_EQ(kStreamOffset, directory->Location.Rva);
EXPECT_EQ(kStreamType, directory[0].StreamType);
EXPECT_EQ(kStreamSize, directory[0].Location.DataSize);
EXPECT_EQ(kStreamOffset, directory[0].Location.Rva);
}
TEST(MinidumpFileWriterDeathTest, SameStreamType) {

Просмотреть файл

@ -47,25 +47,25 @@ void GetMemoryListStream(const std::string& file_contents,
ASSERT_GE(file_contents.size(), kMemoryDescriptorsOffset);
const MINIDUMP_DIRECTORY* directory;
const MINIDUMP_HEADER* header =
reinterpret_cast<const MINIDUMP_HEADER*>(&file_contents[0]);
MinidumpHeaderAtStart(file_contents, &directory);
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, expected_streams, 0));
ASSERT_TRUE(directory);
const MINIDUMP_DIRECTORY* directory =
reinterpret_cast<const MINIDUMP_DIRECTORY*>(
&file_contents[kDirectoryOffset]);
size_t directory_index = 0;
if (expected_streams > 1) {
ASSERT_EQ(kBogusStreamType, directory->StreamType);
ASSERT_EQ(0u, directory->Location.DataSize);
ASSERT_EQ(kMemoryListStreamOffset, directory->Location.Rva);
++directory;
ASSERT_EQ(kBogusStreamType, directory[directory_index].StreamType);
ASSERT_EQ(0u, directory[directory_index].Location.DataSize);
ASSERT_EQ(kMemoryListStreamOffset, directory[directory_index].Location.Rva);
++directory_index;
}
ASSERT_EQ(kMinidumpStreamTypeMemoryList, directory->StreamType);
ASSERT_GE(directory->Location.DataSize, sizeof(MINIDUMP_MEMORY_LIST));
ASSERT_EQ(kMemoryListStreamOffset, directory->Location.Rva);
ASSERT_EQ(kMinidumpStreamTypeMemoryList,
directory[directory_index].StreamType);
ASSERT_GE(directory[directory_index].Location.DataSize,
sizeof(MINIDUMP_MEMORY_LIST));
ASSERT_EQ(kMemoryListStreamOffset, directory[directory_index].Location.Rva);
*memory_list = reinterpret_cast<const MINIDUMP_MEMORY_LIST*>(
&file_contents[kMemoryListStreamOffset]);
@ -73,7 +73,7 @@ void GetMemoryListStream(const std::string& file_contents,
ASSERT_EQ(sizeof(MINIDUMP_MEMORY_LIST) +
(*memory_list)->NumberOfMemoryRanges *
sizeof(MINIDUMP_MEMORY_DESCRIPTOR),
directory->Location.DataSize);
directory[directory_index].Location.DataSize);
}
TEST(MinidumpMemoryWriter, EmptyMemoryList) {

Просмотреть файл

@ -42,18 +42,15 @@ void GetMiscInfoStream(const std::string& file_contents, const T** misc_info) {
ASSERT_EQ(kFileSize, file_contents.size());
const MINIDUMP_DIRECTORY* directory;
const MINIDUMP_HEADER* header =
reinterpret_cast<const MINIDUMP_HEADER*>(&file_contents[0]);
MinidumpHeaderAtStart(file_contents, &directory);
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
ASSERT_TRUE(directory);
const MINIDUMP_DIRECTORY* directory =
reinterpret_cast<const MINIDUMP_DIRECTORY*>(
&file_contents[kDirectoryOffset]);
ASSERT_EQ(kMinidumpStreamTypeMiscInfo, directory->StreamType);
ASSERT_EQ(kMiscInfoStreamSize, directory->Location.DataSize);
ASSERT_EQ(kMiscInfoStreamOffset, directory->Location.Rva);
ASSERT_EQ(kMinidumpStreamTypeMiscInfo, directory[0].StreamType);
ASSERT_EQ(kMiscInfoStreamSize, directory[0].Location.DataSize);
ASSERT_EQ(kMiscInfoStreamOffset, directory[0].Location.Rva);
*misc_info =
reinterpret_cast<const T*>(&file_contents[kMiscInfoStreamOffset]);

Просмотреть файл

@ -23,6 +23,7 @@
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_file_writer.h"
#include "minidump/test/minidump_file_writer_test_util.h"
#include "minidump/test/minidump_string_writer_test_util.h"
#include "util/file/string_file_writer.h"
#include "util/misc/uuid.h"
@ -40,25 +41,22 @@ void GetModuleListStream(const std::string& file_contents,
ASSERT_GE(file_contents.size(), kModulesOffset);
const MINIDUMP_DIRECTORY* directory;
const MINIDUMP_HEADER* header =
reinterpret_cast<const MINIDUMP_HEADER*>(&file_contents[0]);
MinidumpHeaderAtStart(file_contents, &directory);
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
ASSERT_TRUE(directory);
const MINIDUMP_DIRECTORY* directory =
reinterpret_cast<const MINIDUMP_DIRECTORY*>(
&file_contents[kDirectoryOffset]);
ASSERT_EQ(kMinidumpStreamTypeModuleList, directory->StreamType);
ASSERT_GE(directory->Location.DataSize, sizeof(MINIDUMP_MODULE_LIST));
ASSERT_EQ(kModuleListStreamOffset, directory->Location.Rva);
ASSERT_EQ(kMinidumpStreamTypeModuleList, directory[0].StreamType);
ASSERT_GE(directory[0].Location.DataSize, sizeof(MINIDUMP_MODULE_LIST));
ASSERT_EQ(kModuleListStreamOffset, directory[0].Location.Rva);
*module_list = reinterpret_cast<const MINIDUMP_MODULE_LIST*>(
&file_contents[kModuleListStreamOffset]);
ASSERT_EQ(sizeof(MINIDUMP_MODULE_LIST) +
(*module_list)->NumberOfModules * sizeof(MINIDUMP_MODULE),
directory->Location.DataSize);
directory[0].Location.DataSize);
}
TEST(MinidumpModuleWriter, EmptyModuleList) {
@ -256,18 +254,8 @@ void ExpectModule(const MINIDUMP_MODULE* expected,
EXPECT_EQ(0u, observed->Reserved1);
EXPECT_NE(0u, observed->ModuleNameRva);
ASSERT_LE(observed->ModuleNameRva,
file_contents.size() - sizeof(MINIDUMP_STRING));
const MINIDUMP_STRING* module_name = reinterpret_cast<const MINIDUMP_STRING*>(
&file_contents[observed->ModuleNameRva]);
ASSERT_LE(observed->ModuleNameRva + sizeof(MINIDUMP_STRING) +
(module_name->Length + 1),
file_contents.size());
ASSERT_EQ(0u, module_name->Length % 2);
string16 observed_module_name_utf16(
reinterpret_cast<const char16*>(
&file_contents[observed->ModuleNameRva + sizeof(MINIDUMP_STRING)]),
module_name->Length / 2);
string16 observed_module_name_utf16 =
MinidumpStringAtRVAAsString(file_contents, observed->ModuleNameRva);
string16 expected_module_name_utf16 = base::UTF8ToUTF16(expected_module_name);
EXPECT_EQ(expected_module_name_utf16, observed_module_name_utf16);

Просмотреть файл

@ -64,9 +64,11 @@ TEST(MinidumpSimpleStringDictionaryWriter, EmptyKeyValue) {
EXPECT_EQ(12u, dictionary->entries[0].key);
EXPECT_EQ(20u, dictionary->entries[0].value);
EXPECT_EQ("",
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].key));
MinidumpUTF8StringAtRVAAsString(file_writer.string(),
dictionary->entries[0].key));
EXPECT_EQ("",
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].value));
MinidumpUTF8StringAtRVAAsString(file_writer.string(),
dictionary->entries[0].value));
}
TEST(MinidumpSimpleStringDictionaryWriter, OneKeyValue) {
@ -92,9 +94,11 @@ TEST(MinidumpSimpleStringDictionaryWriter, OneKeyValue) {
EXPECT_EQ(12u, dictionary->entries[0].key);
EXPECT_EQ(20u, dictionary->entries[0].value);
EXPECT_EQ(kKey,
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].key));
MinidumpUTF8StringAtRVAAsString(file_writer.string(),
dictionary->entries[0].key));
EXPECT_EQ(kValue,
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].value));
MinidumpUTF8StringAtRVAAsString(file_writer.string(),
dictionary->entries[0].value));
}
TEST(MinidumpSimpleStringDictionaryWriter, ThreeKeysValues) {
@ -143,17 +147,23 @@ TEST(MinidumpSimpleStringDictionaryWriter, ThreeKeysValues) {
// just the easiest way to write this test while the writer will output things
// in a known order.
EXPECT_EQ(kKey2,
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].key));
MinidumpUTF8StringAtRVAAsString(file_writer.string(),
dictionary->entries[0].key));
EXPECT_EQ(kValue2,
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].value));
MinidumpUTF8StringAtRVAAsString(file_writer.string(),
dictionary->entries[0].value));
EXPECT_EQ(kKey0,
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[1].key));
MinidumpUTF8StringAtRVAAsString(file_writer.string(),
dictionary->entries[1].key));
EXPECT_EQ(kValue0,
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[1].value));
MinidumpUTF8StringAtRVAAsString(file_writer.string(),
dictionary->entries[1].value));
EXPECT_EQ(kKey1,
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[2].key));
MinidumpUTF8StringAtRVAAsString(file_writer.string(),
dictionary->entries[2].key));
EXPECT_EQ(kValue1,
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[2].value));
MinidumpUTF8StringAtRVAAsString(file_writer.string(),
dictionary->entries[2].value));
}
TEST(MinidumpSimpleStringDictionaryWriter, DuplicateKeyValue) {
@ -183,9 +193,11 @@ TEST(MinidumpSimpleStringDictionaryWriter, DuplicateKeyValue) {
EXPECT_EQ(12u, dictionary->entries[0].key);
EXPECT_EQ(20u, dictionary->entries[0].value);
EXPECT_EQ(kKey,
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].key));
MinidumpUTF8StringAtRVAAsString(file_writer.string(),
dictionary->entries[0].key));
EXPECT_EQ(kValue1,
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].value));
MinidumpUTF8StringAtRVAAsString(file_writer.string(),
dictionary->entries[0].value));
}
} // namespace

Просмотреть файл

@ -22,16 +22,13 @@
#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
#include "gtest/gtest.h"
#include "minidump/test/minidump_string_writer_test_util.h"
#include "util/file/string_file_writer.h"
namespace crashpad {
namespace test {
namespace {
const MINIDUMP_STRING* MinidumpStringCast(const StringFileWriter& file_writer) {
return reinterpret_cast<const MINIDUMP_STRING*>(&file_writer.string()[0]);
}
TEST(MinidumpStringWriter, MinidumpUTF16StringWriter) {
StringFileWriter file_writer;
@ -41,9 +38,11 @@ TEST(MinidumpStringWriter, MinidumpUTF16StringWriter) {
crashpad::internal::MinidumpUTF16StringWriter string_writer;
EXPECT_TRUE(string_writer.WriteEverything(&file_writer));
ASSERT_EQ(6u, file_writer.string().size());
const MINIDUMP_STRING* minidump_string = MinidumpStringCast(file_writer);
EXPECT_EQ(0u, minidump_string->Length);
EXPECT_EQ(0, minidump_string->Buffer[0]);
const MINIDUMP_STRING* minidump_string =
MinidumpStringAtRVA(file_writer.string(), 0);
EXPECT_TRUE(minidump_string);
EXPECT_EQ(string16(), MinidumpStringAtRVAAsString(file_writer.string(), 0));
}
const struct {
@ -88,14 +87,14 @@ TEST(MinidumpStringWriter, MinidumpUTF16StringWriter) {
expected_utf16_units_with_nul * sizeof(MINIDUMP_STRING::Buffer[0]);
ASSERT_EQ(sizeof(MINIDUMP_STRING) + expected_utf16_bytes,
file_writer.string().size());
const MINIDUMP_STRING* minidump_string = MinidumpStringCast(file_writer);
EXPECT_EQ(
kTestData[index].output_length * sizeof(minidump_string->Buffer[0]),
minidump_string->Length);
EXPECT_EQ(0,
base::c16memcmp(kTestData[index].output_string,
minidump_string->Buffer,
expected_utf16_units_with_nul));
const MINIDUMP_STRING* minidump_string =
MinidumpStringAtRVA(file_writer.string(), 0);
EXPECT_TRUE(minidump_string);
string16 expect_string = string16(kTestData[index].output_string,
kTestData[index].output_length);
EXPECT_EQ(expect_string,
MinidumpStringAtRVAAsString(file_writer.string(), 0));
}
}
@ -122,27 +121,21 @@ TEST(MinidumpStringWriter, ConvertInvalidUTF8ToUTF16) {
// The requirements for conversion of invalid UTF-8 input are lax. Make sure
// that at least enough data was written for a string that has one unit and
// a NUL terminator, make sure that the length field matches the length of
// data written, make sure the data is NUL-terminated, and make sure that at
// least one U+FFFD replacement character was written.
ASSERT_GE(file_writer.string().size(),
sizeof(MINIDUMP_STRING) + 2 * sizeof(MINIDUMP_STRING::Buffer[0]));
const MINIDUMP_STRING* minidump_string = MinidumpStringCast(file_writer);
// data written, and make sure that at least one U+FFFD replacement
// character was written.
const MINIDUMP_STRING* minidump_string =
MinidumpStringAtRVA(file_writer.string(), 0);
EXPECT_TRUE(minidump_string);
EXPECT_EQ(file_writer.string().size() - sizeof(MINIDUMP_STRING) -
sizeof(MINIDUMP_STRING::Buffer[0]),
minidump_string->Length);
size_t out_units =
minidump_string->Length / sizeof(minidump_string->Buffer[0]);
EXPECT_EQ(0, minidump_string->Buffer[out_units]);
EXPECT_NE(nullptr,
base::c16memchr(minidump_string->Buffer, 0xfffd, out_units));
string16 output_string =
MinidumpStringAtRVAAsString(file_writer.string(), 0);
EXPECT_FALSE(output_string.empty());
EXPECT_NE(string16::npos, output_string.find(0xfffd));
}
}
const MinidumpUTF8String* MinidumpUTF8StringCast(
const StringFileWriter& file_writer) {
return reinterpret_cast<const MinidumpUTF8String*>(&file_writer.string()[0]);
}
TEST(MinidumpStringWriter, MinidumpUTF8StringWriter) {
StringFileWriter file_writer;
@ -152,10 +145,12 @@ TEST(MinidumpStringWriter, MinidumpUTF8StringWriter) {
crashpad::internal::MinidumpUTF8StringWriter string_writer;
EXPECT_TRUE(string_writer.WriteEverything(&file_writer));
ASSERT_EQ(5u, file_writer.string().size());
const MinidumpUTF8String* minidump_string =
MinidumpUTF8StringCast(file_writer);
EXPECT_EQ(0u, minidump_string->Length);
EXPECT_EQ(0, minidump_string->Buffer[0]);
MinidumpUTF8StringAtRVA(file_writer.string(), 0);
EXPECT_TRUE(minidump_string);
EXPECT_EQ(std::string(),
MinidumpUTF8StringAtRVAAsString(file_writer.string(), 0));
}
const struct {
@ -189,13 +184,12 @@ TEST(MinidumpStringWriter, MinidumpUTF8StringWriter) {
const size_t expected_utf8_bytes_with_nul = kTestData[index].length + 1;
ASSERT_EQ(sizeof(MinidumpUTF8String) + expected_utf8_bytes_with_nul,
file_writer.string().size());
const MinidumpUTF8String* minidump_string =
MinidumpUTF8StringCast(file_writer);
EXPECT_EQ(kTestData[index].length, minidump_string->Length);
EXPECT_EQ(0,
memcmp(kTestData[index].string,
minidump_string->Buffer,
expected_utf8_bytes_with_nul));
MinidumpUTF8StringAtRVA(file_writer.string(), 0);
EXPECT_TRUE(minidump_string);
EXPECT_EQ(test_string,
MinidumpUTF8StringAtRVAAsString(file_writer.string(), 0));
}
}

Просмотреть файл

@ -22,6 +22,7 @@
#include "gtest/gtest.h"
#include "minidump/minidump_file_writer.h"
#include "minidump/test/minidump_file_writer_test_util.h"
#include "minidump/test/minidump_string_writer_test_util.h"
#include "util/file/string_file_writer.h"
namespace crashpad {
@ -48,27 +49,23 @@ void GetSystemInfoStream(const std::string& file_contents,
ASSERT_EQ(kFileSize, file_contents.size());
const MINIDUMP_DIRECTORY* directory;
const MINIDUMP_HEADER* header =
reinterpret_cast<const MINIDUMP_HEADER*>(&file_contents[0]);
MinidumpHeaderAtStart(file_contents, &directory);
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
ASSERT_TRUE(directory);
const MINIDUMP_DIRECTORY* directory =
reinterpret_cast<const MINIDUMP_DIRECTORY*>(
&file_contents[kDirectoryOffset]);
ASSERT_EQ(kMinidumpStreamTypeSystemInfo, directory->StreamType);
ASSERT_EQ(sizeof(MINIDUMP_SYSTEM_INFO), directory->Location.DataSize);
ASSERT_EQ(kSystemInfoStreamOffset, directory->Location.Rva);
ASSERT_EQ(kMinidumpStreamTypeSystemInfo, directory[0].StreamType);
ASSERT_EQ(sizeof(MINIDUMP_SYSTEM_INFO), directory[0].Location.DataSize);
ASSERT_EQ(kSystemInfoStreamOffset, directory[0].Location.Rva);
*system_info = reinterpret_cast<const MINIDUMP_SYSTEM_INFO*>(
&file_contents[kSystemInfoStreamOffset]);
ASSERT_EQ(kCSDVersionOffset, (*system_info)->CSDVersionRva);
*csd_version = reinterpret_cast<const MINIDUMP_STRING*>(
&file_contents[kCSDVersionOffset]);
*csd_version =
MinidumpStringAtRVA(file_contents, (*system_info)->CSDVersionRva);
ASSERT_EQ(kCSDVersionBytes, (*csd_version)->Length);
}

Просмотреть файл

@ -44,14 +44,11 @@ void GetThreadListStream(const std::string& file_contents,
ASSERT_GE(file_contents.size(), kThreadsOffset);
const MINIDUMP_DIRECTORY* directory;
const MINIDUMP_HEADER* header =
reinterpret_cast<const MINIDUMP_HEADER*>(&file_contents[0]);
MinidumpHeaderAtStart(file_contents, &directory);
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, kExpectedStreams, 0));
const MINIDUMP_DIRECTORY* directory =
reinterpret_cast<const MINIDUMP_DIRECTORY*>(
&file_contents[kDirectoryOffset]);
ASSERT_TRUE(directory);
ASSERT_EQ(kMinidumpStreamTypeThreadList, directory[0].StreamType);
ASSERT_GE(directory[0].Location.DataSize, sizeof(MINIDUMP_THREAD_LIST));

Просмотреть файл

@ -15,13 +15,48 @@
#include "minidump/test/minidump_file_writer_test_util.h"
#include "gtest/gtest.h"
#include "minidump/test/minidump_writable_test_util.h"
namespace crashpad {
namespace test {
const MINIDUMP_HEADER* MinidumpHeaderAtStart(
const std::string& file_contents,
const MINIDUMP_DIRECTORY** directory) {
MINIDUMP_LOCATION_DESCRIPTOR location_descriptor;
location_descriptor.DataSize = sizeof(MINIDUMP_HEADER);
location_descriptor.Rva = 0;
const MINIDUMP_HEADER* header =
MinidumpWritableAtLocationDescriptor<MINIDUMP_HEADER>(
file_contents, location_descriptor);
if (header) {
if (header->Signature != MINIDUMP_SIGNATURE) {
EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_SIGNATURE), header->Signature);
return nullptr;
}
if (header->Version != MINIDUMP_VERSION) {
EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_VERSION), header->Version);
return nullptr;
}
location_descriptor.DataSize =
header->NumberOfStreams * sizeof(MINIDUMP_DIRECTORY);
location_descriptor.Rva = header->StreamDirectoryRva;
*directory = MinidumpWritableAtLocationDescriptor<MINIDUMP_DIRECTORY>(
file_contents, location_descriptor);
} else {
*directory = nullptr;
}
return header;
}
void VerifyMinidumpHeader(const MINIDUMP_HEADER* header,
uint32_t streams,
uint32_t timestamp) {
ASSERT_TRUE(header);
EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_SIGNATURE), header->Signature);
EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_VERSION), header->Version);
ASSERT_EQ(streams, header->NumberOfStreams);

Просмотреть файл

@ -18,9 +18,30 @@
#include <dbghelp.h>
#include <stdint.h>
#include <string>
namespace crashpad {
namespace test {
//! \brief Returns the MINIDUMP_HEADER at the start of a minidump file, along
//! with the MINIDUMP_DIRECTORY it references.
//!
//! This function validates the MINIDUMP_HEADER::Signature and
//! MINIDUMP_HEADER::Version fields.
//!
//! \param[in] file_contents The contents of the minidump file.
//! \param[out] directory The MINIDUMP_DIRECTORY referenced by the
//! MINIDUMP_HEADER. If the MINIDUMP_HEADER does not reference a
//! MINIDUMP_DIRECTORY, `nullptr` without raising a gtest assertion. If the
//! referenced MINIDUMP_DIRECTORY is not valid, `nullptr` with a gtest
//! assertion raised. On failure, `nullptr`.
//!
//! \return On success, the MINIDUMP_HEADER at the beginning of the minidump
//! file. On failure, raises a gtest assertion and returns `nullptr`.
const MINIDUMP_HEADER* MinidumpHeaderAtStart(
const std::string& file_contents,
const MINIDUMP_DIRECTORY** directory);
//! \brief Verifies, via gtest assertions, that a MINIDUMP_HEADER contains
//! expected values.
//!

Просмотреть файл

@ -16,41 +16,90 @@
#include "gtest/gtest.h"
#include "minidump/minidump_extensions.h"
#include "minidump/test/minidump_writable_test_util.h"
namespace crashpad {
namespace test {
std::string MinidumpUTF8StringAtRVA(const StringFileWriter& file_writer,
RVA rva) {
const std::string& contents = file_writer.string();
if (rva == 0) {
return std::string();
namespace {
template <typename T>
const T* TMinidumpStringAtRVA(const std::string& file_contents, RVA rva) {
const T* string_base = MinidumpWritableAtRVA<T>(file_contents, rva);
if (!string_base) {
return nullptr;
}
if (rva + sizeof(MinidumpUTF8String) > contents.size()) {
ADD_FAILURE()
<< "rva " << rva << " too large for contents " << contents.size();
return std::string();
// |Length| must indicate the ability to store an integral number of code
// units.
const size_t kCodeUnitSize = sizeof(string_base->Buffer[0]);
if (string_base->Length % kCodeUnitSize != 0) {
EXPECT_EQ(0u, string_base->Length % kCodeUnitSize);
return nullptr;
}
const MinidumpUTF8String* minidump_string =
reinterpret_cast<const MinidumpUTF8String*>(&contents[rva]);
// Verify that the file has enough data for the strings stated length plus
// its required NUL terminator.
if (rva + sizeof(MinidumpUTF8String) + minidump_string->Length + 1 >
contents.size()) {
ADD_FAILURE()
<< "rva " << rva << ", length " << minidump_string->Length
<< " too large for contents " << contents.size();
return std::string();
// |Length| does not include space for the required NUL terminator.
MINIDUMP_LOCATION_DESCRIPTOR location;
location.DataSize =
sizeof(*string_base) + string_base->Length + kCodeUnitSize;
location.Rva = rva;
const T* string =
MinidumpWritableAtLocationDescriptor<T>(file_contents, location);
if (!string) {
return nullptr;
}
std::string minidump_string_data(
reinterpret_cast<const char*>(&minidump_string->Buffer[0]),
minidump_string->Length);
EXPECT_EQ(string_base, string);
// Require the NUL terminator to be NUL.
if (string->Buffer[string->Length / kCodeUnitSize] != '\0') {
EXPECT_EQ('\0', string->Buffer[string->Length / kCodeUnitSize]);
return nullptr;
}
return string;
}
template <typename StringType, typename MinidumpStringType>
StringType TMinidumpStringAtRVAAsString(const std::string& file_contents,
RVA rva) {
const MinidumpStringType* minidump_string =
TMinidumpStringAtRVA<MinidumpStringType>(file_contents, rva);
if (!minidump_string) {
return StringType();
}
StringType minidump_string_data(
reinterpret_cast<const typename StringType::value_type*>(
&minidump_string->Buffer[0]),
minidump_string->Length / sizeof(minidump_string->Buffer[0]));
return minidump_string_data;
}
} // namespace
const MINIDUMP_STRING* MinidumpStringAtRVA(const std::string& file_contents,
RVA rva) {
return TMinidumpStringAtRVA<MINIDUMP_STRING>(file_contents, rva);
}
const MinidumpUTF8String* MinidumpUTF8StringAtRVA(
const std::string& file_contents,
RVA rva) {
return TMinidumpStringAtRVA<MinidumpUTF8String>(file_contents, rva);
}
string16 MinidumpStringAtRVAAsString(const std::string& file_contents,
RVA rva) {
return TMinidumpStringAtRVAAsString<string16, MINIDUMP_STRING>(file_contents,
rva);
}
std::string MinidumpUTF8StringAtRVAAsString(const std::string& file_contents,
RVA rva) {
return TMinidumpStringAtRVAAsString<std::string, MinidumpUTF8String>(
file_contents, rva);
}
} // namespace test
} // namespace crashpad

Просмотреть файл

@ -19,27 +19,82 @@
#include <string>
#include "util/file/string_file_writer.h"
#include "base/strings/string16.h"
namespace crashpad {
struct MinidumpUTF8String;
namespace test {
//! \brief Returns the contents of a MinidumpUTF8String.
//! \brief Returns a MINIDUMP_STRING located within a minidump files contents.
//!
//! If \a rva points outside of the range of \a file_writer, or if any of the
//! string data would lie outside of the range of \a file_writer, this function
//! will fail.
//! If \a rva points outside of the range of \a file_contents, if the string has
//! an incorrect length or is not `NUL`-terminated, or if any of the string data
//! would lie outside of the range of \a file_contents, this function will fail.
//!
//! \param[in] file_writer A StringFileWriter into which MinidumpWritable
//! objects have been written.
//! \param[in] rva An offset in \a file_writer at which to find the desired
//! string.
//! \param[in] file_contents The contents of the minidump file.
//! \param[in] rva The offset within the minidump file of the desired
//! MINIDUMP_STRING.
//!
//! \return On success, a pointer to the MINIDUMP_STRING in \a file_contents. On
//! failure, raises a gtest assertion and returns `nullptr`.
//!
//! \sa MinidumpStringAtRVAAsString()
//! \sa MinidumpUTF8StringAtRVA()
const MINIDUMP_STRING* MinidumpStringAtRVA(const std::string& file_contents,
RVA rva);
//! \brief Returns a MinidumpUTF8String located within a minidump files
//! contents.
//!
//! If \a rva points outside of the range of \a file_contents, if the string has
//! an incorrect length or is not `NUL`-terminated, or if any of the string data
//! would lie outside of the range of \a file_contents, this function will fail.
//!
//! \param[in] file_contents The contents of the minidump file.
//! \param[in] rva The offset within the minidump file of the desired
//! MinidumpUTF8String.
//!
//! \return On success, a pointer to the MinidumpUTF8String in \a file_contents.
//! On failure, raises a gtest assertion and returns `nullptr`.
//!
//! \sa MinidumpUTF8StringAtRVAAsString()
//! \sa MinidumpStringAtRVA()
const MinidumpUTF8String* MinidumpUTF8StringAtRVA(
const std::string& file_contents,
RVA rva);
//! \brief Returns the contents of a MINIDUMP_STRING as a `string16`.
//!
//! This function uses MinidumpStringAtRVA() to obtain a MINIDUMP_STRING, and
//! returns the string data as a `string16`.
//!
//! \param[in] file_contents The contents of the minidump file.
//! \param[in] rva The offset within the minidump file of the desired
//! MINIDUMP_STRING.
//!
//! \return On success, the string read from \a file_writer at offset \a rva. On
//! failure, returns an empty string, with a nonfatal assertion logged to
//! gtest.
std::string MinidumpUTF8StringAtRVA(const StringFileWriter& file_writer,
RVA rva);
//! failure, raises a gtest assertion and returns an empty string.
//!
//! \sa MinidumpUTF8StringAtRVAAsString()
string16 MinidumpStringAtRVAAsString(const std::string& file_contents, RVA rva);
//! \brief Returns the contents of a MinidumpUTF8String as a `std::string`.
//!
//! This function uses MinidumpUTF16StringAtRVA() to obtain a
//! MinidumpUTF16String, and returns the string data as a `std::string`.
//!
//! \param[in] file_contents The contents of the minidump file.
//! \param[in] rva The offset within the minidump file of the desired
//! MinidumpUTF8String.
//!
//! \return On success, the string read from \a file_writer at offset \a rva. On
//! failure, raises a gtest assertion and returns an empty string.
//!
//! \sa MinidumpStringAtRVAAsString()
std::string MinidumpUTF8StringAtRVAAsString(const std::string& file_contents,
RVA rva);
} // namespace test
} // namespace crashpad

Просмотреть файл

@ -0,0 +1,58 @@
// Copyright 2014 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_writable_test_util.h"
#include <string>
#include "gtest/gtest.h"
namespace crashpad {
namespace test {
const void* MinidumpWritableAtRVAInternal(const std::string& file_contents,
RVA rva) {
if (rva >= file_contents.size()) {
EXPECT_LT(rva, file_contents.size());
return nullptr;
}
return &file_contents[rva];
}
const void* MinidumpWritableAtLocationDescriptorInternal(
const std::string& file_contents,
const MINIDUMP_LOCATION_DESCRIPTOR& location,
size_t expected_minimum_size) {
if (location.DataSize == 0) {
EXPECT_EQ(0u, location.Rva);
return nullptr;
} else if (location.DataSize < expected_minimum_size) {
EXPECT_GE(location.DataSize, expected_minimum_size);
return nullptr;
}
RVA end = location.Rva + location.DataSize;
if (end > file_contents.size()) {
EXPECT_LE(end, file_contents.size());
return nullptr;
}
const void* rv = MinidumpWritableAtRVAInternal(file_contents, location.Rva);
return rv;
}
} // namespace test
} // namespace crashpad

Просмотреть файл

@ -0,0 +1,108 @@
// Copyright 2014 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_WRITABLE_TEST_UTIL_H_
#define CRASHPAD_MINIDUMP_TEST_MINIDUMP_WRITABLE_TEST_UTIL_H_
#include <dbghelp.h>
#include <string>
#include "gtest/gtest.h"
namespace crashpad {
namespace test {
//! \brief Returns an untyped minidump object located within a minidump files
//! contents, where the offset of the object is known.
//!
//! \param[in] file_contents The contents of the minidump file.
//! \param[in] rva The offset within the minidump file of the desired object.
//!
//! \return If \a rva is within the range of \a file_contents, returns a pointer
//! into \a file_contents at offset \a rva. Otherwise, raises a gtest
//! assertion failure and returns `nullptr`.
//!
//! Do not call this function. Use the typed version, MinidumpWritableAtRVA<>(),
//! or another type-specific function.
//!
//! \sa MinidumpWritableAtLocationDescriptorInternal()
const void* MinidumpWritableAtRVAInternal(const std::string& file_contents,
RVA rva);
//! \brief Returns an untyped minidump object located within a minidump files
//! contents, where the offset and size of the object are known.
//!
//! \param[in] file_contents The contents of the minidump file.
//! \param[in] location A MINIDUMP_LOCATION_DESCRIPTOR giving the offset within
//! the minidump file of the desired object, as well as its size.
//! \param[in] expected_minimum_size The minimum size allowable for the object.
//!
//! \return If the size of \a location is at least as big as \a
//! expected_minimum_size, and if \a location is within the range of \a
//! file_contents, returns a pointer into \a file_contents at offset \a rva.
//! Otherwise, raises a gtest assertion failure and returns `nullptr`.
//!
//! Do not call this function. Use the typed version,
//! MinidumpWritableAtLocationDescriptor<>(), or another type-specific function.
//!
//! \sa MinidumpWritableAtRVAInternal()
const void* MinidumpWritableAtLocationDescriptorInternal(
const std::string& file_contents,
const MINIDUMP_LOCATION_DESCRIPTOR& location,
size_t expected_minimum_size);
//! \brief Returns a typed minidump object located within a minidump files
//! contents, where the offset of the object is known.
//!
//! \param[in] file_contents The contents of the minidump file.
//! \param[in] rva The offset within the minidump file of the desired object.
//!
//! \return If \a rva is within the range of \a file_contents, returns a pointer
//! into \a file_contents at offset \a rva. Otherwise, raises a gtest
//! assertion failure and returns `nullptr`.
//!
//! \sa MinidumpWritableAtLocationDescriptor<>()
template <typename T>
const T* MinidumpWritableAtRVA(const std::string& file_contents, RVA rva) {
return reinterpret_cast<const T*>(
MinidumpWritableAtRVAInternal(file_contents, rva));
}
//! \brief Returns a typed minidump object located within a minidump files
//! contents, where the offset and size of the object are known.
//!
//! \param[in] file_contents The contents of the minidump file.
//! \param[in] location A MINIDUMP_LOCATION_DESCRIPTOR giving the offset within
//! the minidump file of the desired object, as well as its size.
//!
//! \return If the size of \a location is at least as big as the size of the
//! requested object, and if \a location is within the range of \a
//! file_contents, returns a pointer into \a file_contents at offset \a rva.
//! Otherwise, raises a gtest assertion failure and returns `nullptr`.
//!
//! \sa MinidumpWritableAtRVA()
template <typename T>
const T* MinidumpWritableAtLocationDescriptor(
const std::string& file_contents,
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
return reinterpret_cast<const T*>(
MinidumpWritableAtLocationDescriptorInternal(
file_contents, location, sizeof(T)));
}
} // namespace test
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_TEST_MINIDUMP_WRITABLE_TEST_UTIL_H_