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 |