| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
| 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at |
| 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. |
| 14 |
| 15 #include "minidump/minidump_crashpad_info_writer.h" |
| 16 |
| 17 #include <windows.h> |
| 18 #include <dbghelp.h> |
| 19 |
| 20 #include <map> |
| 21 #include <string> |
| 22 |
| 23 #include "gtest/gtest.h" |
| 24 #include "minidump/minidump_extensions.h" |
| 25 #include "minidump/minidump_file_writer.h" |
| 26 #include "minidump/minidump_module_crashpad_info_writer.h" |
| 27 #include "minidump/minidump_simple_string_dictionary_writer.h" |
| 28 #include "minidump/test/minidump_file_writer_test_util.h" |
| 29 #include "minidump/test/minidump_string_writer_test_util.h" |
| 30 #include "minidump/test/minidump_writable_test_util.h" |
| 31 #include "snapshot/test/test_module_snapshot.h" |
| 32 #include "snapshot/test/test_process_snapshot.h" |
| 33 #include "util/file/string_file.h" |
| 34 #include "util/stdlib/move.h" |
| 35 |
| 36 namespace crashpad { |
| 37 namespace test { |
| 38 namespace { |
| 39 |
| 40 void GetCrashpadInfoStream( |
| 41 const std::string& file_contents, |
| 42 const MinidumpCrashpadInfo** crashpad_info, |
| 43 const MinidumpSimpleStringDictionary** simple_annotations, |
| 44 const MinidumpModuleCrashpadInfoList** module_list) { |
| 45 const MINIDUMP_DIRECTORY* directory; |
| 46 const MINIDUMP_HEADER* header = |
| 47 MinidumpHeaderAtStart(file_contents, &directory); |
| 48 ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0)); |
| 49 ASSERT_TRUE(directory); |
| 50 |
| 51 ASSERT_EQ(kMinidumpStreamTypeCrashpadInfo, directory[0].StreamType); |
| 52 |
| 53 *crashpad_info = MinidumpWritableAtLocationDescriptor<MinidumpCrashpadInfo>( |
| 54 file_contents, directory[0].Location); |
| 55 ASSERT_TRUE(*crashpad_info); |
| 56 |
| 57 *simple_annotations = |
| 58 MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>( |
| 59 file_contents, (*crashpad_info)->simple_annotations); |
| 60 |
| 61 *module_list = |
| 62 MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfoList>( |
| 63 file_contents, (*crashpad_info)->module_list); |
| 64 } |
| 65 |
| 66 TEST(MinidumpCrashpadInfoWriter, Empty) { |
| 67 MinidumpFileWriter minidump_file_writer; |
| 68 auto crashpad_info_writer = make_scoped_ptr(new MinidumpCrashpadInfoWriter()); |
| 69 EXPECT_FALSE(crashpad_info_writer->IsUseful()); |
| 70 |
| 71 minidump_file_writer.AddStream(crashpad::move(crashpad_info_writer)); |
| 72 |
| 73 StringFile string_file; |
| 74 ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file)); |
| 75 |
| 76 const MinidumpCrashpadInfo* crashpad_info = nullptr; |
| 77 const MinidumpSimpleStringDictionary* simple_annotations = nullptr; |
| 78 const MinidumpModuleCrashpadInfoList* module_list = nullptr; |
| 79 |
| 80 ASSERT_NO_FATAL_FAILURE(GetCrashpadInfoStream( |
| 81 string_file.string(), &crashpad_info, &simple_annotations, &module_list)); |
| 82 |
| 83 EXPECT_EQ(MinidumpCrashpadInfo::kVersion, crashpad_info->version); |
| 84 EXPECT_EQ(UUID(), crashpad_info->report_id); |
| 85 EXPECT_EQ(UUID(), crashpad_info->client_id); |
| 86 EXPECT_FALSE(simple_annotations); |
| 87 EXPECT_FALSE(module_list); |
| 88 } |
| 89 |
| 90 TEST(MinidumpCrashpadInfoWriter, ReportAndClientID) { |
| 91 MinidumpFileWriter minidump_file_writer; |
| 92 auto crashpad_info_writer = make_scoped_ptr(new MinidumpCrashpadInfoWriter()); |
| 93 |
| 94 UUID report_id; |
| 95 ASSERT_TRUE( |
| 96 report_id.InitializeFromString("01234567-89ab-cdef-0123-456789abcdef")); |
| 97 crashpad_info_writer->SetReportID(report_id); |
| 98 |
| 99 UUID client_id; |
| 100 ASSERT_TRUE( |
| 101 client_id.InitializeFromString("00112233-4455-6677-8899-aabbccddeeff")); |
| 102 crashpad_info_writer->SetClientID(client_id); |
| 103 |
| 104 EXPECT_TRUE(crashpad_info_writer->IsUseful()); |
| 105 |
| 106 minidump_file_writer.AddStream(crashpad::move(crashpad_info_writer)); |
| 107 |
| 108 StringFile string_file; |
| 109 ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file)); |
| 110 |
| 111 const MinidumpCrashpadInfo* crashpad_info = nullptr; |
| 112 const MinidumpSimpleStringDictionary* simple_annotations = nullptr; |
| 113 const MinidumpModuleCrashpadInfoList* module_list = nullptr; |
| 114 |
| 115 ASSERT_NO_FATAL_FAILURE(GetCrashpadInfoStream( |
| 116 string_file.string(), &crashpad_info, &simple_annotations, &module_list)); |
| 117 |
| 118 EXPECT_EQ(MinidumpCrashpadInfo::kVersion, crashpad_info->version); |
| 119 EXPECT_EQ(report_id, crashpad_info->report_id); |
| 120 EXPECT_EQ(client_id, crashpad_info->client_id); |
| 121 EXPECT_FALSE(simple_annotations); |
| 122 EXPECT_FALSE(module_list); |
| 123 } |
| 124 |
| 125 TEST(MinidumpCrashpadInfoWriter, SimpleAnnotations) { |
| 126 MinidumpFileWriter minidump_file_writer; |
| 127 auto crashpad_info_writer = make_scoped_ptr(new MinidumpCrashpadInfoWriter()); |
| 128 |
| 129 const char kKey[] = |
| 130 "a thing that provides a means of gaining access to or understanding " |
| 131 "something"; |
| 132 const char kValue[] = |
| 133 "the numerical amount denoted by an algebraic term; a magnitude, " |
| 134 "quantity, or number"; |
| 135 auto simple_string_dictionary_writer = |
| 136 make_scoped_ptr(new MinidumpSimpleStringDictionaryWriter()); |
| 137 auto simple_string_dictionary_entry_writer = |
| 138 make_scoped_ptr(new MinidumpSimpleStringDictionaryEntryWriter()); |
| 139 simple_string_dictionary_entry_writer->SetKeyValue(kKey, kValue); |
| 140 simple_string_dictionary_writer->AddEntry( |
| 141 crashpad::move(simple_string_dictionary_entry_writer)); |
| 142 crashpad_info_writer->SetSimpleAnnotations( |
| 143 crashpad::move(simple_string_dictionary_writer)); |
| 144 |
| 145 EXPECT_TRUE(crashpad_info_writer->IsUseful()); |
| 146 |
| 147 minidump_file_writer.AddStream(crashpad::move(crashpad_info_writer)); |
| 148 |
| 149 StringFile string_file; |
| 150 ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file)); |
| 151 |
| 152 const MinidumpCrashpadInfo* crashpad_info = nullptr; |
| 153 const MinidumpSimpleStringDictionary* simple_annotations = nullptr; |
| 154 const MinidumpModuleCrashpadInfoList* module_list = nullptr; |
| 155 |
| 156 ASSERT_NO_FATAL_FAILURE(GetCrashpadInfoStream( |
| 157 string_file.string(), &crashpad_info, &simple_annotations, &module_list)); |
| 158 |
| 159 EXPECT_EQ(MinidumpCrashpadInfo::kVersion, crashpad_info->version); |
| 160 EXPECT_FALSE(module_list); |
| 161 |
| 162 ASSERT_TRUE(simple_annotations); |
| 163 ASSERT_EQ(1u, simple_annotations->count); |
| 164 EXPECT_EQ(kKey, |
| 165 MinidumpUTF8StringAtRVAAsString( |
| 166 string_file.string(), simple_annotations->entries[0].key)); |
| 167 EXPECT_EQ(kValue, |
| 168 MinidumpUTF8StringAtRVAAsString( |
| 169 string_file.string(), simple_annotations->entries[0].value)); |
| 170 } |
| 171 |
| 172 TEST(MinidumpCrashpadInfoWriter, CrashpadModuleList) { |
| 173 const uint32_t kMinidumpModuleListIndex = 3; |
| 174 |
| 175 MinidumpFileWriter minidump_file_writer; |
| 176 auto crashpad_info_writer = make_scoped_ptr(new MinidumpCrashpadInfoWriter()); |
| 177 |
| 178 auto module_list_writer = |
| 179 make_scoped_ptr(new MinidumpModuleCrashpadInfoListWriter()); |
| 180 auto module_writer = make_scoped_ptr(new MinidumpModuleCrashpadInfoWriter()); |
| 181 module_list_writer->AddModule(crashpad::move(module_writer), kMinidumpModuleLi
stIndex); |
| 182 crashpad_info_writer->SetModuleList(crashpad::move(module_list_writer)); |
| 183 |
| 184 EXPECT_TRUE(crashpad_info_writer->IsUseful()); |
| 185 |
| 186 minidump_file_writer.AddStream(crashpad::move(crashpad_info_writer)); |
| 187 |
| 188 StringFile string_file; |
| 189 ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file)); |
| 190 |
| 191 const MinidumpCrashpadInfo* crashpad_info = nullptr; |
| 192 const MinidumpSimpleStringDictionary* simple_annotations = nullptr; |
| 193 const MinidumpModuleCrashpadInfoList* module_list = nullptr; |
| 194 |
| 195 ASSERT_NO_FATAL_FAILURE(GetCrashpadInfoStream( |
| 196 string_file.string(), &crashpad_info, &simple_annotations, &module_list)); |
| 197 |
| 198 EXPECT_EQ(MinidumpCrashpadInfo::kVersion, crashpad_info->version); |
| 199 EXPECT_FALSE(simple_annotations); |
| 200 |
| 201 ASSERT_TRUE(module_list); |
| 202 ASSERT_EQ(1u, module_list->count); |
| 203 |
| 204 EXPECT_EQ(kMinidumpModuleListIndex, |
| 205 module_list->modules[0].minidump_module_list_index); |
| 206 const MinidumpModuleCrashpadInfo* module = |
| 207 MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>( |
| 208 string_file.string(), module_list->modules[0].location); |
| 209 ASSERT_TRUE(module); |
| 210 |
| 211 EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module->version); |
| 212 EXPECT_EQ(0u, module->list_annotations.DataSize); |
| 213 EXPECT_EQ(0u, module->list_annotations.Rva); |
| 214 EXPECT_EQ(0u, module->simple_annotations.DataSize); |
| 215 EXPECT_EQ(0u, module->simple_annotations.Rva); |
| 216 } |
| 217 |
| 218 TEST(MinidumpCrashpadInfoWriter, InitializeFromSnapshot) { |
| 219 UUID report_id; |
| 220 ASSERT_TRUE( |
| 221 report_id.InitializeFromString("fedcba98-7654-3210-fedc-ba9876543210")); |
| 222 |
| 223 UUID client_id; |
| 224 ASSERT_TRUE( |
| 225 client_id.InitializeFromString("fedcba98-7654-3210-0123-456789abcdef")); |
| 226 |
| 227 const char kKey[] = "version"; |
| 228 const char kValue[] = "40.0.2214.111"; |
| 229 const char kEntry[] = "This is a simple annotation in a list."; |
| 230 |
| 231 // Test with a useless module, one that doesn’t carry anything that would |
| 232 // require MinidumpCrashpadInfo or any child object. |
| 233 auto process_snapshot = make_scoped_ptr(new TestProcessSnapshot()); |
| 234 |
| 235 auto module_snapshot = make_scoped_ptr(new TestModuleSnapshot()); |
| 236 process_snapshot->AddModule(crashpad::move(module_snapshot)); |
| 237 |
| 238 auto info_writer = make_scoped_ptr(new MinidumpCrashpadInfoWriter()); |
| 239 info_writer->InitializeFromSnapshot(process_snapshot.get()); |
| 240 EXPECT_FALSE(info_writer->IsUseful()); |
| 241 |
| 242 // Try again with a useful module. |
| 243 process_snapshot.reset(new TestProcessSnapshot()); |
| 244 |
| 245 process_snapshot->SetReportID(report_id); |
| 246 process_snapshot->SetClientID(client_id); |
| 247 |
| 248 std::map<std::string, std::string> annotations_simple_map; |
| 249 annotations_simple_map[kKey] = kValue; |
| 250 process_snapshot->SetAnnotationsSimpleMap(annotations_simple_map); |
| 251 |
| 252 module_snapshot.reset(new TestModuleSnapshot()); |
| 253 std::vector<std::string> annotations_list(1, std::string(kEntry)); |
| 254 module_snapshot->SetAnnotationsVector(annotations_list); |
| 255 process_snapshot->AddModule(crashpad::move(module_snapshot)); |
| 256 |
| 257 info_writer.reset(new MinidumpCrashpadInfoWriter()); |
| 258 info_writer->InitializeFromSnapshot(process_snapshot.get()); |
| 259 EXPECT_TRUE(info_writer->IsUseful()); |
| 260 |
| 261 MinidumpFileWriter minidump_file_writer; |
| 262 minidump_file_writer.AddStream(crashpad::move(info_writer)); |
| 263 |
| 264 StringFile string_file; |
| 265 ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file)); |
| 266 |
| 267 const MinidumpCrashpadInfo* info = nullptr; |
| 268 const MinidumpSimpleStringDictionary* simple_annotations; |
| 269 const MinidumpModuleCrashpadInfoList* module_list; |
| 270 ASSERT_NO_FATAL_FAILURE(GetCrashpadInfoStream( |
| 271 string_file.string(), &info, &simple_annotations, &module_list)); |
| 272 |
| 273 EXPECT_EQ(MinidumpCrashpadInfo::kVersion, info->version); |
| 274 |
| 275 EXPECT_EQ(report_id, info->report_id); |
| 276 EXPECT_EQ(client_id, info->client_id); |
| 277 |
| 278 ASSERT_TRUE(simple_annotations); |
| 279 ASSERT_EQ(1u, simple_annotations->count); |
| 280 EXPECT_EQ(kKey, |
| 281 MinidumpUTF8StringAtRVAAsString( |
| 282 string_file.string(), simple_annotations->entries[0].key)); |
| 283 EXPECT_EQ(kValue, |
| 284 MinidumpUTF8StringAtRVAAsString( |
| 285 string_file.string(), simple_annotations->entries[0].value)); |
| 286 |
| 287 ASSERT_TRUE(module_list); |
| 288 ASSERT_EQ(1u, module_list->count); |
| 289 |
| 290 EXPECT_EQ(0u, module_list->modules[0].minidump_module_list_index); |
| 291 const MinidumpModuleCrashpadInfo* module = |
| 292 MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>( |
| 293 string_file.string(), module_list->modules[0].location); |
| 294 ASSERT_TRUE(module); |
| 295 |
| 296 EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module->version); |
| 297 |
| 298 const MinidumpRVAList* list_annotations = |
| 299 MinidumpWritableAtLocationDescriptor<MinidumpRVAList>( |
| 300 string_file.string(), module->list_annotations); |
| 301 ASSERT_TRUE(list_annotations); |
| 302 |
| 303 ASSERT_EQ(1u, list_annotations->count); |
| 304 EXPECT_EQ(kEntry, |
| 305 MinidumpUTF8StringAtRVAAsString(string_file.string(), |
| 306 list_annotations->children[0])); |
| 307 |
| 308 const MinidumpSimpleStringDictionary* module_simple_annotations = |
| 309 MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>( |
| 310 string_file.string(), module->simple_annotations); |
| 311 EXPECT_FALSE(module_simple_annotations); |
| 312 } |
| 313 |
| 314 } // namespace |
| 315 } // namespace test |
| 316 } // namespace crashpad |
| OLD | NEW |