| OLD | NEW |
| 1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with 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 | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. | 13 // limitations under the License. |
| 14 | 14 |
| 15 #include "minidump/minidump_file_writer.h" | 15 #include "minidump/minidump_file_writer.h" |
| 16 | 16 |
| 17 #include <stdint.h> | 17 #include <stdint.h> |
| 18 #include <string.h> | 18 #include <string.h> |
| 19 | 19 |
| 20 #include <string> | 20 #include <string> |
| 21 #include <utility> | 21 #include <utility> |
| 22 | 22 |
| 23 #include "base/compiler_specific.h" | 23 #include "base/compiler_specific.h" |
| 24 #include "base/macros.h" | 24 #include "base/macros.h" |
| 25 #include "base/memory/ptr_util.h" | 25 #include "base/memory/ptr_util.h" |
| 26 #include "gtest/gtest.h" | 26 #include "gtest/gtest.h" |
| 27 #include "minidump/minidump_stream_writer.h" | 27 #include "minidump/minidump_stream_writer.h" |
| 28 #include "minidump/minidump_user_extension_stream_data_source.h" |
| 28 #include "minidump/minidump_writable.h" | 29 #include "minidump/minidump_writable.h" |
| 29 #include "minidump/test/minidump_file_writer_test_util.h" | 30 #include "minidump/test/minidump_file_writer_test_util.h" |
| 30 #include "minidump/test/minidump_writable_test_util.h" | 31 #include "minidump/test/minidump_writable_test_util.h" |
| 31 #include "snapshot/test/test_cpu_context.h" | 32 #include "snapshot/test/test_cpu_context.h" |
| 32 #include "snapshot/test/test_exception_snapshot.h" | 33 #include "snapshot/test/test_exception_snapshot.h" |
| 33 #include "snapshot/test/test_memory_snapshot.h" | 34 #include "snapshot/test/test_memory_snapshot.h" |
| 34 #include "snapshot/test/test_module_snapshot.h" | 35 #include "snapshot/test/test_module_snapshot.h" |
| 35 #include "snapshot/test/test_process_snapshot.h" | 36 #include "snapshot/test/test_process_snapshot.h" |
| 36 #include "snapshot/test/test_system_snapshot.h" | 37 #include "snapshot/test/test_system_snapshot.h" |
| 37 #include "snapshot/test/test_thread_snapshot.h" | 38 #include "snapshot/test/test_thread_snapshot.h" |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 TEST(MinidumpFileWriter, OneStream) { | 92 TEST(MinidumpFileWriter, OneStream) { |
| 92 MinidumpFileWriter minidump_file; | 93 MinidumpFileWriter minidump_file; |
| 93 const time_t kTimestamp = 0x155d2fb8; | 94 const time_t kTimestamp = 0x155d2fb8; |
| 94 minidump_file.SetTimestamp(kTimestamp); | 95 minidump_file.SetTimestamp(kTimestamp); |
| 95 | 96 |
| 96 const size_t kStreamSize = 5; | 97 const size_t kStreamSize = 5; |
| 97 const MinidumpStreamType kStreamType = static_cast<MinidumpStreamType>(0x4d); | 98 const MinidumpStreamType kStreamType = static_cast<MinidumpStreamType>(0x4d); |
| 98 const uint8_t kStreamValue = 0x5a; | 99 const uint8_t kStreamValue = 0x5a; |
| 99 auto stream = | 100 auto stream = |
| 100 base::WrapUnique(new TestStream(kStreamType, kStreamSize, kStreamValue)); | 101 base::WrapUnique(new TestStream(kStreamType, kStreamSize, kStreamValue)); |
| 101 minidump_file.AddStream(std::move(stream)); | 102 ASSERT_TRUE(minidump_file.AddStream(std::move(stream))); |
| 102 | 103 |
| 103 StringFile string_file; | 104 StringFile string_file; |
| 104 ASSERT_TRUE(minidump_file.WriteEverything(&string_file)); | 105 ASSERT_TRUE(minidump_file.WriteEverything(&string_file)); |
| 105 | 106 |
| 106 const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER); | 107 const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER); |
| 107 const size_t kStreamOffset = kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY); | 108 const size_t kStreamOffset = kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY); |
| 108 const size_t kFileSize = kStreamOffset + kStreamSize; | 109 const size_t kFileSize = kStreamOffset + kStreamSize; |
| 109 | 110 |
| 110 ASSERT_EQ(kFileSize, string_file.string().size()); | 111 ASSERT_EQ(kFileSize, string_file.string().size()); |
| 111 | 112 |
| 112 const MINIDUMP_DIRECTORY* directory; | 113 const MINIDUMP_DIRECTORY* directory; |
| 113 const MINIDUMP_HEADER* header = | 114 const MINIDUMP_HEADER* header = |
| 114 MinidumpHeaderAtStart(string_file.string(), &directory); | 115 MinidumpHeaderAtStart(string_file.string(), &directory); |
| 115 ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, kTimestamp)); | 116 ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, kTimestamp)); |
| 116 ASSERT_TRUE(directory); | 117 ASSERT_TRUE(directory); |
| 117 | 118 |
| 118 EXPECT_EQ(kStreamType, directory[0].StreamType); | 119 EXPECT_EQ(kStreamType, directory[0].StreamType); |
| 119 EXPECT_EQ(kStreamSize, directory[0].Location.DataSize); | 120 EXPECT_EQ(kStreamSize, directory[0].Location.DataSize); |
| 120 EXPECT_EQ(kStreamOffset, directory[0].Location.Rva); | 121 EXPECT_EQ(kStreamOffset, directory[0].Location.Rva); |
| 121 | 122 |
| 122 const uint8_t* stream_data = MinidumpWritableAtLocationDescriptor<uint8_t>( | 123 const uint8_t* stream_data = MinidumpWritableAtLocationDescriptor<uint8_t>( |
| 123 string_file.string(), directory[0].Location); | 124 string_file.string(), directory[0].Location); |
| 124 ASSERT_TRUE(stream_data); | 125 ASSERT_TRUE(stream_data); |
| 125 | 126 |
| 126 std::string expected_stream(kStreamSize, kStreamValue); | 127 std::string expected_stream(kStreamSize, kStreamValue); |
| 127 EXPECT_EQ(0, memcmp(stream_data, expected_stream.c_str(), kStreamSize)); | 128 EXPECT_EQ(0, memcmp(stream_data, expected_stream.c_str(), kStreamSize)); |
| 128 } | 129 } |
| 129 | 130 |
| 131 TEST(MinidumpFileWriter, AddUserExtensionStream) { |
| 132 MinidumpFileWriter minidump_file; |
| 133 const time_t kTimestamp = 0x155d2fb8; |
| 134 minidump_file.SetTimestamp(kTimestamp); |
| 135 |
| 136 static const uint8_t kStreamData[] = "Hello World!"; |
| 137 const size_t kStreamSize = arraysize(kStreamData); |
| 138 const MinidumpStreamType kStreamType = static_cast<MinidumpStreamType>(0x4d); |
| 139 |
| 140 auto stream = base::WrapUnique(new MinidumpUserExtensionStreamDataSource( |
| 141 kStreamType, kStreamData, kStreamSize)); |
| 142 ASSERT_TRUE(minidump_file.AddUserExtensionStream(std::move(stream))); |
| 143 |
| 144 // Adding the same stream type a second time should fail. |
| 145 stream = base::WrapUnique(new MinidumpUserExtensionStreamDataSource( |
| 146 kStreamType, kStreamData, kStreamSize)); |
| 147 ASSERT_FALSE(minidump_file.AddUserExtensionStream(std::move(stream))); |
| 148 |
| 149 StringFile string_file; |
| 150 ASSERT_TRUE(minidump_file.WriteEverything(&string_file)); |
| 151 |
| 152 const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER); |
| 153 const size_t kStreamOffset = kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY); |
| 154 const size_t kFileSize = kStreamOffset + kStreamSize; |
| 155 |
| 156 ASSERT_EQ(kFileSize, string_file.string().size()); |
| 157 |
| 158 const MINIDUMP_DIRECTORY* directory; |
| 159 const MINIDUMP_HEADER* header = |
| 160 MinidumpHeaderAtStart(string_file.string(), &directory); |
| 161 ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, kTimestamp)); |
| 162 ASSERT_TRUE(directory); |
| 163 |
| 164 EXPECT_EQ(kStreamType, directory[0].StreamType); |
| 165 EXPECT_EQ(kStreamSize, directory[0].Location.DataSize); |
| 166 EXPECT_EQ(kStreamOffset, directory[0].Location.Rva); |
| 167 |
| 168 const uint8_t* stream_data = MinidumpWritableAtLocationDescriptor<uint8_t>( |
| 169 string_file.string(), directory[0].Location); |
| 170 ASSERT_TRUE(stream_data); |
| 171 |
| 172 EXPECT_EQ(0, memcmp(stream_data, kStreamData, kStreamSize)); |
| 173 } |
| 174 |
| 130 TEST(MinidumpFileWriter, ThreeStreams) { | 175 TEST(MinidumpFileWriter, ThreeStreams) { |
| 131 MinidumpFileWriter minidump_file; | 176 MinidumpFileWriter minidump_file; |
| 132 const time_t kTimestamp = 0x155d2fb8; | 177 const time_t kTimestamp = 0x155d2fb8; |
| 133 minidump_file.SetTimestamp(kTimestamp); | 178 minidump_file.SetTimestamp(kTimestamp); |
| 134 | 179 |
| 135 const size_t kStream0Size = 5; | 180 const size_t kStream0Size = 5; |
| 136 const MinidumpStreamType kStream0Type = static_cast<MinidumpStreamType>(0x6d); | 181 const MinidumpStreamType kStream0Type = static_cast<MinidumpStreamType>(0x6d); |
| 137 const uint8_t kStream0Value = 0x5a; | 182 const uint8_t kStream0Value = 0x5a; |
| 138 auto stream0 = base::WrapUnique( | 183 auto stream0 = base::WrapUnique( |
| 139 new TestStream(kStream0Type, kStream0Size, kStream0Value)); | 184 new TestStream(kStream0Type, kStream0Size, kStream0Value)); |
| 140 minidump_file.AddStream(std::move(stream0)); | 185 ASSERT_TRUE(minidump_file.AddStream(std::move(stream0))); |
| 141 | 186 |
| 142 // Make the second stream’s type be a smaller quantity than the first stream’s | 187 // Make the second stream’s type be a smaller quantity than the first stream’s |
| 143 // to test that the streams show up in the order that they were added, not in | 188 // to test that the streams show up in the order that they were added, not in |
| 144 // numeric order. | 189 // numeric order. |
| 145 const size_t kStream1Size = 3; | 190 const size_t kStream1Size = 3; |
| 146 const MinidumpStreamType kStream1Type = static_cast<MinidumpStreamType>(0x4d); | 191 const MinidumpStreamType kStream1Type = static_cast<MinidumpStreamType>(0x4d); |
| 147 const uint8_t kStream1Value = 0xa5; | 192 const uint8_t kStream1Value = 0xa5; |
| 148 auto stream1 = base::WrapUnique( | 193 auto stream1 = base::WrapUnique( |
| 149 new TestStream(kStream1Type, kStream1Size, kStream1Value)); | 194 new TestStream(kStream1Type, kStream1Size, kStream1Value)); |
| 150 minidump_file.AddStream(std::move(stream1)); | 195 ASSERT_TRUE(minidump_file.AddStream(std::move(stream1))); |
| 151 | 196 |
| 152 const size_t kStream2Size = 1; | 197 const size_t kStream2Size = 1; |
| 153 const MinidumpStreamType kStream2Type = static_cast<MinidumpStreamType>(0x7e); | 198 const MinidumpStreamType kStream2Type = static_cast<MinidumpStreamType>(0x7e); |
| 154 const uint8_t kStream2Value = 0x36; | 199 const uint8_t kStream2Value = 0x36; |
| 155 auto stream2 = base::WrapUnique( | 200 auto stream2 = base::WrapUnique( |
| 156 new TestStream(kStream2Type, kStream2Size, kStream2Value)); | 201 new TestStream(kStream2Type, kStream2Size, kStream2Value)); |
| 157 minidump_file.AddStream(std::move(stream2)); | 202 ASSERT_TRUE(minidump_file.AddStream(std::move(stream2))); |
| 158 | 203 |
| 159 StringFile string_file; | 204 StringFile string_file; |
| 160 ASSERT_TRUE(minidump_file.WriteEverything(&string_file)); | 205 ASSERT_TRUE(minidump_file.WriteEverything(&string_file)); |
| 161 | 206 |
| 162 const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER); | 207 const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER); |
| 163 const size_t kStream0Offset = | 208 const size_t kStream0Offset = |
| 164 kDirectoryOffset + 3 * sizeof(MINIDUMP_DIRECTORY); | 209 kDirectoryOffset + 3 * sizeof(MINIDUMP_DIRECTORY); |
| 165 const size_t kStream1Padding = 3; | 210 const size_t kStream1Padding = 3; |
| 166 const size_t kStream1Offset = kStream0Offset + kStream0Size + kStream1Padding; | 211 const size_t kStream1Offset = kStream0Offset + kStream0Size + kStream1Padding; |
| 167 const size_t kStream2Padding = 1; | 212 const size_t kStream2Padding = 1; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 std::string expected_stream2(kStream2Size, kStream2Value); | 259 std::string expected_stream2(kStream2Size, kStream2Value); |
| 215 EXPECT_EQ(0, memcmp(stream2_data, expected_stream2.c_str(), kStream2Size)); | 260 EXPECT_EQ(0, memcmp(stream2_data, expected_stream2.c_str(), kStream2Size)); |
| 216 } | 261 } |
| 217 | 262 |
| 218 TEST(MinidumpFileWriter, ZeroLengthStream) { | 263 TEST(MinidumpFileWriter, ZeroLengthStream) { |
| 219 MinidumpFileWriter minidump_file; | 264 MinidumpFileWriter minidump_file; |
| 220 | 265 |
| 221 const size_t kStreamSize = 0; | 266 const size_t kStreamSize = 0; |
| 222 const MinidumpStreamType kStreamType = static_cast<MinidumpStreamType>(0x4d); | 267 const MinidumpStreamType kStreamType = static_cast<MinidumpStreamType>(0x4d); |
| 223 auto stream = base::WrapUnique(new TestStream(kStreamType, kStreamSize, 0)); | 268 auto stream = base::WrapUnique(new TestStream(kStreamType, kStreamSize, 0)); |
| 224 minidump_file.AddStream(std::move(stream)); | 269 ASSERT_TRUE(minidump_file.AddStream(std::move(stream))); |
| 225 | 270 |
| 226 StringFile string_file; | 271 StringFile string_file; |
| 227 ASSERT_TRUE(minidump_file.WriteEverything(&string_file)); | 272 ASSERT_TRUE(minidump_file.WriteEverything(&string_file)); |
| 228 | 273 |
| 229 const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER); | 274 const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER); |
| 230 const size_t kStreamOffset = kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY); | 275 const size_t kStreamOffset = kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY); |
| 231 const size_t kFileSize = kStreamOffset + kStreamSize; | 276 const size_t kFileSize = kStreamOffset + kStreamSize; |
| 232 | 277 |
| 233 ASSERT_EQ(kFileSize, string_file.string().size()); | 278 ASSERT_EQ(kFileSize, string_file.string().size()); |
| 234 | 279 |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 | 477 |
| 433 EXPECT_EQ(kMinidumpStreamTypeCrashpadInfo, directory[5].StreamType); | 478 EXPECT_EQ(kMinidumpStreamTypeCrashpadInfo, directory[5].StreamType); |
| 434 EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MinidumpCrashpadInfo>( | 479 EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MinidumpCrashpadInfo>( |
| 435 string_file.string(), directory[5].Location)); | 480 string_file.string(), directory[5].Location)); |
| 436 | 481 |
| 437 EXPECT_EQ(kMinidumpStreamTypeMemoryList, directory[6].StreamType); | 482 EXPECT_EQ(kMinidumpStreamTypeMemoryList, directory[6].StreamType); |
| 438 EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_MEMORY_LIST>( | 483 EXPECT_TRUE(MinidumpWritableAtLocationDescriptor<MINIDUMP_MEMORY_LIST>( |
| 439 string_file.string(), directory[6].Location)); | 484 string_file.string(), directory[6].Location)); |
| 440 } | 485 } |
| 441 | 486 |
| 442 TEST(MinidumpFileWriterDeathTest, SameStreamType) { | 487 TEST(MinidumpFileWriter, SameStreamType) { |
| 443 MinidumpFileWriter minidump_file; | 488 MinidumpFileWriter minidump_file; |
| 444 | 489 |
| 445 const size_t kStream0Size = 5; | 490 const size_t kStream0Size = 3; |
| 446 const MinidumpStreamType kStream0Type = static_cast<MinidumpStreamType>(0x4d); | 491 const MinidumpStreamType kStreamType = static_cast<MinidumpStreamType>(0x4d); |
| 447 const uint8_t kStream0Value = 0x5a; | 492 const uint8_t kStream0Value = 0x5a; |
| 448 auto stream0 = base::WrapUnique( | 493 auto stream0 = base::WrapUnique( |
| 449 new TestStream(kStream0Type, kStream0Size, kStream0Value)); | 494 new TestStream(kStreamType, kStream0Size, kStream0Value)); |
| 450 minidump_file.AddStream(std::move(stream0)); | 495 ASSERT_TRUE(minidump_file.AddStream(std::move(stream0))); |
| 451 | 496 |
| 452 // It is an error to add a second stream of the same type. | 497 // An attempt to add a second stream of the same type should fail. |
| 453 const size_t kStream1Size = 3; | 498 const size_t kStream1Size = 5; |
| 454 const MinidumpStreamType kStream1Type = static_cast<MinidumpStreamType>(0x4d); | |
| 455 const uint8_t kStream1Value = 0xa5; | 499 const uint8_t kStream1Value = 0xa5; |
| 456 auto stream1 = base::WrapUnique( | 500 auto stream1 = base::WrapUnique( |
| 457 new TestStream(kStream1Type, kStream1Size, kStream1Value)); | 501 new TestStream(kStreamType, kStream1Size, kStream1Value)); |
| 458 ASSERT_DEATH_CHECK(minidump_file.AddStream(std::move(stream1)), | 502 ASSERT_FALSE(minidump_file.AddStream(std::move(stream1))); |
| 459 "already present"); | 503 |
| 504 StringFile string_file; |
| 505 ASSERT_TRUE(minidump_file.WriteEverything(&string_file)); |
| 506 |
| 507 const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER); |
| 508 const size_t kStream0Offset = kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY); |
| 509 const size_t kFileSize = kStream0Offset + kStream0Size; |
| 510 |
| 511 ASSERT_EQ(kFileSize, string_file.string().size()); |
| 512 |
| 513 const MINIDUMP_DIRECTORY* directory; |
| 514 const MINIDUMP_HEADER* header = |
| 515 MinidumpHeaderAtStart(string_file.string(), &directory); |
| 516 ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0)); |
| 517 ASSERT_TRUE(directory); |
| 518 |
| 519 EXPECT_EQ(kStreamType, directory[0].StreamType); |
| 520 EXPECT_EQ(kStream0Size, directory[0].Location.DataSize); |
| 521 EXPECT_EQ(kStream0Offset, directory[0].Location.Rva); |
| 522 |
| 523 const uint8_t* stream_data = MinidumpWritableAtLocationDescriptor<uint8_t>( |
| 524 string_file.string(), directory[0].Location); |
| 525 ASSERT_TRUE(stream_data); |
| 526 |
| 527 std::string expected_stream(kStream0Size, kStream0Value); |
| 528 EXPECT_EQ(0, memcmp(stream_data, expected_stream.c_str(), kStream0Size)); |
| 460 } | 529 } |
| 461 | 530 |
| 462 } // namespace | 531 } // namespace |
| 463 } // namespace test | 532 } // namespace test |
| 464 } // namespace crashpad | 533 } // namespace crashpad |
| OLD | NEW |