Index: snapshot/minidump/process_snapshot_minidump_test.cc |
diff --git a/snapshot/minidump/process_snapshot_minidump_test.cc b/snapshot/minidump/process_snapshot_minidump_test.cc |
index fcd40d4cfbf1326833f542bca56d37fd9f8ca7f1..a214309ef49e2034dee6f96651b46734ef592e66 100644 |
--- a/snapshot/minidump/process_snapshot_minidump_test.cc |
+++ b/snapshot/minidump/process_snapshot_minidump_test.cc |
@@ -20,6 +20,7 @@ |
#include "base/memory/scoped_ptr.h" |
#include "gtest/gtest.h" |
+#include "snapshot/module_snapshot.h" |
#include "util/file/string_file.h" |
namespace crashpad { |
@@ -57,51 +58,84 @@ TEST(ProcessSnapshotMinidump, Empty) { |
EXPECT_TRUE(process_snapshot.Initialize(&string_file)); |
} |
+// Writes |string| to |writer| as a MinidumpUTF8String, and returns the file |
+// offst of the beginning of the string. |
+RVA WriteString(FileWriterInterface* writer, const std::string& string) { |
+ RVA rva = static_cast<RVA>(writer->SeekGet()); |
+ |
+ uint32_t string_size = string.size(); |
+ EXPECT_TRUE(writer->Write(&string_size, sizeof(string_size))); |
+ |
+ // Include the trailing NUL character. |
+ EXPECT_TRUE(writer->Write(string.c_str(), string.size() + 1)); |
+ |
+ return rva; |
+} |
+ |
+// Writes |dictionary| to |writer| as a MinidumpSimpleStringDictionary, and |
+// populates |location| with a location descriptor identifying what was written. |
+void WriteMinidumpSimpleStringDictionary( |
+ MINIDUMP_LOCATION_DESCRIPTOR* location, |
+ FileWriterInterface* writer, |
+ const std::map<std::string, std::string>& dictionary) { |
+ std::vector<MinidumpSimpleStringDictionaryEntry> entries; |
+ for (const auto& it : dictionary) { |
+ MinidumpSimpleStringDictionaryEntry entry; |
+ entry.key = WriteString(writer, it.first); |
+ entry.value = WriteString(writer, it.second); |
+ entries.push_back(entry); |
+ } |
+ |
+ location->Rva = static_cast<RVA>(writer->SeekGet()); |
+ |
+ const uint32_t simple_string_dictionary_entries = entries.size(); |
+ EXPECT_TRUE(writer->Write(&simple_string_dictionary_entries, |
+ sizeof(simple_string_dictionary_entries))); |
+ for (const MinidumpSimpleStringDictionaryEntry& entry : entries) { |
+ EXPECT_TRUE(writer->Write(&entry, sizeof(entry))); |
+ } |
+ |
+ location->DataSize = |
+ sizeof(simple_string_dictionary_entries) + |
+ entries.size() * sizeof(MinidumpSimpleStringDictionaryEntry); |
+} |
+ |
+// Writes |strings| to |writer| as a MinidumpRVAList referencing |
+// MinidumpUTF8String objects, and populates |location| with a location |
+// descriptor identifying what was written. |
+void WriteMinidumpStringList(MINIDUMP_LOCATION_DESCRIPTOR* location, |
+ FileWriterInterface* writer, |
+ const std::vector<std::string>& strings) { |
+ std::vector<RVA> rvas; |
+ for (const std::string& string : strings) { |
+ rvas.push_back(WriteString(writer, string)); |
+ } |
+ |
+ location->Rva = static_cast<RVA>(writer->SeekGet()); |
+ |
+ const uint32_t string_list_entries = rvas.size(); |
+ EXPECT_TRUE(writer->Write(&string_list_entries, sizeof(string_list_entries))); |
+ for (RVA rva : rvas) { |
+ EXPECT_TRUE(writer->Write(&rva, sizeof(rva))); |
+ } |
+ |
+ location->DataSize = sizeof(string_list_entries) + rvas.size() * sizeof(RVA); |
+} |
+ |
TEST(ProcessSnapshotMinidump, AnnotationsSimpleMap) { |
StringFile string_file; |
MINIDUMP_HEADER header = {}; |
EXPECT_TRUE(string_file.Write(&header, sizeof(header))); |
- MinidumpSimpleStringDictionaryEntry entry0 = {}; |
- entry0.key = static_cast<RVA>(string_file.SeekGet()); |
- const char kKey0[] = "the first key"; |
- uint32_t string_size = strlen(kKey0); |
- EXPECT_TRUE(string_file.Write(&string_size, sizeof(string_size))); |
- EXPECT_TRUE(string_file.Write(kKey0, sizeof(kKey0))); |
- |
- entry0.value = static_cast<RVA>(string_file.SeekGet()); |
- const char kValue0[] = "THE FIRST VALUE EVER!"; |
- string_size = strlen(kValue0); |
- EXPECT_TRUE(string_file.Write(&string_size, sizeof(string_size))); |
- EXPECT_TRUE(string_file.Write(kValue0, sizeof(kValue0))); |
- |
- MinidumpSimpleStringDictionaryEntry entry1 = {}; |
- entry1.key = static_cast<RVA>(string_file.SeekGet()); |
- const char kKey1[] = "2key"; |
- string_size = strlen(kKey1); |
- EXPECT_TRUE(string_file.Write(&string_size, sizeof(string_size))); |
- EXPECT_TRUE(string_file.Write(kKey1, sizeof(kKey1))); |
- |
- entry1.value = static_cast<RVA>(string_file.SeekGet()); |
- const char kValue1[] = "a lowly second value"; |
- string_size = strlen(kValue1); |
- EXPECT_TRUE(string_file.Write(&string_size, sizeof(string_size))); |
- EXPECT_TRUE(string_file.Write(kValue1, sizeof(kValue1))); |
- |
MinidumpCrashpadInfo crashpad_info = {}; |
crashpad_info.version = MinidumpCrashpadInfo::kVersion; |
- crashpad_info.simple_annotations.Rva = |
- static_cast<RVA>(string_file.SeekGet()); |
- uint32_t simple_string_dictionary_entries = 2; |
- EXPECT_TRUE(string_file.Write(&simple_string_dictionary_entries, |
- sizeof(simple_string_dictionary_entries))); |
- EXPECT_TRUE(string_file.Write(&entry0, sizeof(entry0))); |
- EXPECT_TRUE(string_file.Write(&entry1, sizeof(entry1))); |
- crashpad_info.simple_annotations.DataSize = |
- simple_string_dictionary_entries * |
- sizeof(MinidumpSimpleStringDictionaryEntry); |
+ std::map<std::string, std::string> dictionary; |
+ dictionary["the first key"] = "THE FIRST VALUE EVER!"; |
+ dictionary["2key"] = "a lowly second value"; |
+ WriteMinidumpSimpleStringDictionary( |
+ &crashpad_info.simple_annotations, &string_file, dictionary); |
MINIDUMP_DIRECTORY crashpad_info_directory = {}; |
crashpad_info_directory.StreamType = kMinidumpStreamTypeCrashpadInfo; |
@@ -124,15 +158,126 @@ TEST(ProcessSnapshotMinidump, AnnotationsSimpleMap) { |
EXPECT_TRUE(process_snapshot.Initialize(&string_file)); |
const auto annotations_simple_map = process_snapshot.AnnotationsSimpleMap(); |
- EXPECT_EQ(2u, annotations_simple_map.size()); |
+ EXPECT_EQ(dictionary, annotations_simple_map); |
+} |
+ |
+TEST(ProcessSnapshotMinidump, Modules) { |
+ StringFile string_file; |
+ |
+ MINIDUMP_HEADER header = {}; |
+ EXPECT_TRUE(string_file.Write(&header, sizeof(header))); |
+ |
+ MINIDUMP_MODULE minidump_module = {}; |
+ uint32_t minidump_module_count = 3; |
+ |
+ MINIDUMP_DIRECTORY minidump_module_list_directory = {}; |
+ minidump_module_list_directory.StreamType = kMinidumpStreamTypeModuleList; |
+ minidump_module_list_directory.Location.DataSize = |
+ sizeof(MINIDUMP_MODULE_LIST) + |
+ minidump_module_count * sizeof(MINIDUMP_MODULE); |
+ minidump_module_list_directory.Location.Rva = |
+ static_cast<RVA>(string_file.SeekGet()); |
+ |
+ EXPECT_TRUE( |
+ string_file.Write(&minidump_module_count, sizeof(minidump_module_count))); |
+ for (uint32_t minidump_module_index = 0; |
+ minidump_module_index < minidump_module_count; |
+ ++minidump_module_index) { |
+ EXPECT_TRUE(string_file.Write(&minidump_module, sizeof(minidump_module))); |
+ } |
+ |
+ MinidumpModuleCrashpadInfo crashpad_module_0 = {}; |
+ crashpad_module_0.version = MinidumpModuleCrashpadInfo::kVersion; |
+ std::map<std::string, std::string> dictionary_0; |
+ dictionary_0["ptype"] = "browser"; |
+ dictionary_0["pid"] = "12345"; |
+ WriteMinidumpSimpleStringDictionary( |
+ &crashpad_module_0.simple_annotations, &string_file, dictionary_0); |
+ |
+ MinidumpModuleCrashpadInfoLink crashpad_module_0_link = {}; |
+ crashpad_module_0_link.minidump_module_list_index = 0; |
+ crashpad_module_0_link.location.DataSize = sizeof(crashpad_module_0); |
+ crashpad_module_0_link.location.Rva = static_cast<RVA>(string_file.SeekGet()); |
+ EXPECT_TRUE(string_file.Write(&crashpad_module_0, sizeof(crashpad_module_0))); |
+ |
+ MinidumpModuleCrashpadInfo crashpad_module_2 = {}; |
+ crashpad_module_2.version = MinidumpModuleCrashpadInfo::kVersion; |
+ std::map<std::string, std::string> dictionary_2; |
+ dictionary_2["fakemodule"] = "yes"; |
+ WriteMinidumpSimpleStringDictionary( |
+ &crashpad_module_2.simple_annotations, &string_file, dictionary_2); |
+ |
+ std::vector<std::string> list_annotations_2; |
+ list_annotations_2.push_back("first string"); |
+ list_annotations_2.push_back("last string"); |
+ WriteMinidumpStringList( |
+ &crashpad_module_2.list_annotations, &string_file, list_annotations_2); |
+ |
+ MinidumpModuleCrashpadInfoLink crashpad_module_2_link = {}; |
+ crashpad_module_2_link.minidump_module_list_index = 2; |
+ crashpad_module_2_link.location.DataSize = sizeof(crashpad_module_2); |
+ crashpad_module_2_link.location.Rva = static_cast<RVA>(string_file.SeekGet()); |
+ EXPECT_TRUE(string_file.Write(&crashpad_module_2, sizeof(crashpad_module_2))); |
+ |
+ MinidumpCrashpadInfo crashpad_info = {}; |
+ crashpad_info.version = MinidumpCrashpadInfo::kVersion; |
+ |
+ uint32_t crashpad_module_count = 2; |
+ |
+ crashpad_info.module_list.DataSize = |
+ sizeof(MinidumpModuleCrashpadInfoList) + |
+ crashpad_module_count * sizeof(MinidumpModuleCrashpadInfoLink); |
+ crashpad_info.module_list.Rva = static_cast<RVA>(string_file.SeekGet()); |
+ |
+ EXPECT_TRUE( |
+ string_file.Write(&crashpad_module_count, sizeof(crashpad_module_count))); |
+ EXPECT_TRUE(string_file.Write(&crashpad_module_0_link, |
+ sizeof(crashpad_module_0_link))); |
+ EXPECT_TRUE(string_file.Write(&crashpad_module_2_link, |
+ sizeof(crashpad_module_2_link))); |
+ |
+ MINIDUMP_DIRECTORY crashpad_info_directory = {}; |
+ crashpad_info_directory.StreamType = kMinidumpStreamTypeCrashpadInfo; |
+ crashpad_info_directory.Location.DataSize = sizeof(crashpad_info); |
+ crashpad_info_directory.Location.Rva = |
+ static_cast<RVA>(string_file.SeekGet()); |
+ EXPECT_TRUE(string_file.Write(&crashpad_info, sizeof(crashpad_info))); |
+ |
+ header.StreamDirectoryRva = static_cast<RVA>(string_file.SeekGet()); |
+ EXPECT_TRUE(string_file.Write(&minidump_module_list_directory, |
+ sizeof(minidump_module_list_directory))); |
+ EXPECT_TRUE(string_file.Write(&crashpad_info_directory, |
+ sizeof(crashpad_info_directory))); |
+ |
+ header.Signature = MINIDUMP_SIGNATURE; |
+ header.Version = MINIDUMP_VERSION; |
+ header.NumberOfStreams = 2; |
+ EXPECT_TRUE(string_file.SeekSet(0)); |
+ EXPECT_TRUE(string_file.Write(&header, sizeof(header))); |
+ |
+ ProcessSnapshotMinidump process_snapshot; |
+ EXPECT_TRUE(process_snapshot.Initialize(&string_file)); |
+ |
+ std::vector<const ModuleSnapshot*> modules = process_snapshot.Modules(); |
+ ASSERT_EQ(minidump_module_count, modules.size()); |
+ |
+ auto annotations_simple_map = modules[0]->AnnotationsSimpleMap(); |
+ EXPECT_EQ(dictionary_0, annotations_simple_map); |
+ |
+ auto annotations_vector = modules[0]->AnnotationsVector(); |
+ EXPECT_TRUE(annotations_vector.empty()); |
+ |
+ annotations_simple_map = modules[1]->AnnotationsSimpleMap(); |
+ EXPECT_TRUE(annotations_simple_map.empty()); |
+ |
+ annotations_vector = modules[1]->AnnotationsVector(); |
+ EXPECT_TRUE(annotations_vector.empty()); |
- auto it = annotations_simple_map.find(kKey0); |
- ASSERT_NE(it, annotations_simple_map.end()); |
- EXPECT_EQ(kValue0, it->second); |
+ annotations_simple_map = modules[2]->AnnotationsSimpleMap(); |
+ EXPECT_EQ(dictionary_2, annotations_simple_map); |
- it = annotations_simple_map.find(kKey1); |
- ASSERT_NE(it, annotations_simple_map.end()); |
- EXPECT_EQ(kValue1, it->second); |
+ annotations_vector = modules[2]->AnnotationsVector(); |
+ EXPECT_EQ(list_annotations_2, annotations_vector); |
} |
} // namespace |