Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: minidump/minidump_memory_writer_test.cc

Issue 459973002: Add MinidumpMemoryWriter, MinidumpMemoryListWriter, and their test (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Address review feedback Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « minidump/minidump_memory_writer.cc ('k') | minidump/minidump_misc_info_writer_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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_memory_writer.h"
16
17 #include <dbghelp.h>
18 #include <stdint.h>
19
20 #include "base/basictypes.h"
21 #include "gtest/gtest.h"
22 #include "minidump/minidump_file_writer.h"
23 #include "minidump/minidump_stream_writer.h"
24 #include "minidump/minidump_test_util.h"
25 #include "util/file/string_file_writer.h"
26
27 namespace {
28
29 using namespace crashpad;
30 using namespace crashpad::test;
31
32 const MinidumpStreamType kBogusStreamType =
33 static_cast<MinidumpStreamType>(1234);
34
35 // expected_streams is the expected number of streams in the file. The memory
36 // list must be the last stream. If there is another stream, it must come first,
37 // have stream type kBogusStreamType, and have zero-length data.
38 void GetMemoryListStream(const std::string& file_contents,
39 const MINIDUMP_MEMORY_LIST** memory_list,
40 const uint32_t expected_streams) {
41 const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER);
42 const size_t kMemoryListStreamOffset =
43 kDirectoryOffset + expected_streams * sizeof(MINIDUMP_DIRECTORY);
44 const size_t kMemoryDescriptorsOffset =
45 kMemoryListStreamOffset + sizeof(MINIDUMP_MEMORY_LIST);
46
47 ASSERT_GE(file_contents.size(), kMemoryDescriptorsOffset);
48
49 const MINIDUMP_HEADER* header =
50 reinterpret_cast<const MINIDUMP_HEADER*>(&file_contents[0]);
51
52 VerifyMinidumpHeader(header, expected_streams, 0);
53 if (testing::Test::HasFatalFailure()) {
54 return;
55 }
56
57 const MINIDUMP_DIRECTORY* directory =
58 reinterpret_cast<const MINIDUMP_DIRECTORY*>(
59 &file_contents[kDirectoryOffset]);
60
61 if (expected_streams > 1) {
62 ASSERT_EQ(kBogusStreamType, directory->StreamType);
63 ASSERT_EQ(0u, directory->Location.DataSize);
64 ASSERT_EQ(kMemoryListStreamOffset, directory->Location.Rva);
65 ++directory;
66 }
67
68 ASSERT_EQ(kMinidumpStreamTypeMemoryList, directory->StreamType);
69 ASSERT_GE(directory->Location.DataSize, sizeof(MINIDUMP_MEMORY_LIST));
70 ASSERT_EQ(kMemoryListStreamOffset, directory->Location.Rva);
71
72 *memory_list = reinterpret_cast<const MINIDUMP_MEMORY_LIST*>(
73 &file_contents[kMemoryListStreamOffset]);
74
75 ASSERT_EQ(sizeof(MINIDUMP_MEMORY_LIST) +
76 (*memory_list)->NumberOfMemoryRanges *
77 sizeof(MINIDUMP_MEMORY_DESCRIPTOR),
78 directory->Location.DataSize);
79 }
80
81 TEST(MinidumpMemoryWriter, EmptyMemoryList) {
82 MinidumpFileWriter minidump_file_writer;
83 MinidumpMemoryListWriter memory_list_writer;
84
85 minidump_file_writer.AddStream(&memory_list_writer);
86
87 StringFileWriter file_writer;
88 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
89
90 ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
91 sizeof(MINIDUMP_MEMORY_LIST),
92 file_writer.string().size());
93
94 const MINIDUMP_MEMORY_LIST* memory_list;
95 GetMemoryListStream(file_writer.string(), &memory_list, 1);
96 if (Test::HasFatalFailure()) {
97 return;
98 }
99
100 EXPECT_EQ(0u, memory_list->NumberOfMemoryRanges);
101 }
102
103 class TestMemoryWriter final : public MinidumpMemoryWriter {
104 public:
105 TestMemoryWriter(uint64_t base_address, size_t size, uint8_t value)
106 : MinidumpMemoryWriter(),
107 base_address_(base_address),
108 expected_offset_(-1),
109 size_(size),
110 value_(value) {}
111
112 ~TestMemoryWriter() {}
113
114 protected:
115 // MinidumpMemoryWriter:
116 virtual uint64_t MemoryRangeBaseAddress() const override {
117 EXPECT_EQ(state(), kStateFrozen);
118 return base_address_;
119 }
120
121 virtual size_t MemoryRangeSize() const override {
122 EXPECT_GE(state(), kStateFrozen);
123 return size_;
124 }
125
126 // MinidumpWritable:
127 virtual bool WillWriteAtOffsetImpl(off_t offset) override {
128 EXPECT_EQ(state(), kStateFrozen);
129 expected_offset_ = offset;
130 bool rv = MinidumpMemoryWriter::WillWriteAtOffsetImpl(offset);
131 EXPECT_TRUE(rv);
132 return rv;
133 }
134
135 virtual bool WriteObject(FileWriterInterface* file_writer) override {
136 EXPECT_EQ(state(), kStateWritable);
137 EXPECT_EQ(expected_offset_, file_writer->Seek(0, SEEK_CUR));
138
139 bool rv = true;
140 if (size_ > 0) {
141 std::string data(size_, value_);
142 rv = file_writer->Write(&data[0], size_);
143 EXPECT_TRUE(rv);
144 }
145
146 return rv;
147 }
148
149 private:
150 uint64_t base_address_;
151 off_t expected_offset_;
152 size_t size_;
153 uint8_t value_;
154
155 DISALLOW_COPY_AND_ASSIGN(TestMemoryWriter);
156 };
157
158 void ExpectMemoryDescriptorAndContents(
159 const MINIDUMP_MEMORY_DESCRIPTOR* expected,
160 const MINIDUMP_MEMORY_DESCRIPTOR* observed,
161 const std::string& file_contents,
162 uint8_t value,
163 bool at_eof) {
164 const uint32_t kMemoryAlignment = 16;
165
166 EXPECT_EQ(expected->StartOfMemoryRange, observed->StartOfMemoryRange);
167 EXPECT_EQ(expected->Memory.DataSize, observed->Memory.DataSize);
168 EXPECT_EQ(
169 (expected->Memory.Rva + kMemoryAlignment - 1) & ~(kMemoryAlignment - 1),
170 observed->Memory.Rva);
171 if (at_eof) {
172 EXPECT_EQ(file_contents.size(),
173 observed->Memory.Rva + observed->Memory.DataSize);
174 } else {
175 EXPECT_GE(file_contents.size(),
176 observed->Memory.Rva + observed->Memory.DataSize);
177 }
178
179 std::string expected_data(expected->Memory.DataSize, value);
180 std::string observed_data(&file_contents[observed->Memory.Rva],
181 observed->Memory.DataSize);
182 EXPECT_EQ(expected_data, observed_data);
183 }
184
185 TEST(MinidumpMemoryWriter, OneMemoryRegion) {
186 MinidumpFileWriter minidump_file_writer;
187 MinidumpMemoryListWriter memory_list_writer;
188
189 const uint64_t kBaseAddress = 0xfedcba9876543210ull;
190 const uint64_t kSize = 0x1000;
191 const uint8_t kValue = 'm';
192
193 TestMemoryWriter memory_writer(kBaseAddress, kSize, kValue);
194 memory_list_writer.AddMemory(&memory_writer);
195
196 minidump_file_writer.AddStream(&memory_list_writer);
197
198 StringFileWriter file_writer;
199 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
200
201 const MINIDUMP_MEMORY_LIST* memory_list;
202 GetMemoryListStream(file_writer.string(), &memory_list, 1);
203 if (Test::HasFatalFailure()) {
204 return;
205 }
206
207 MINIDUMP_MEMORY_DESCRIPTOR expected;
208 expected.StartOfMemoryRange = kBaseAddress;
209 expected.Memory.DataSize = kSize;
210 expected.Memory.Rva =
211 sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
212 sizeof(MINIDUMP_MEMORY_LIST) +
213 memory_list->NumberOfMemoryRanges * sizeof(MINIDUMP_MEMORY_DESCRIPTOR);
214 ExpectMemoryDescriptorAndContents(&expected,
215 &memory_list->MemoryRanges[0],
216 file_writer.string(),
217 kValue,
218 true);
219 }
220
221 TEST(MinidumpMemoryWriter, TwoMemoryRegions) {
222 MinidumpFileWriter minidump_file_writer;
223 MinidumpMemoryListWriter memory_list_writer;
224
225 const uint64_t kBaseAddress1 = 0x00c0ffeeull;
226 const uint64_t kSize1 = 0x0100;
227 const uint8_t kValue1 = '6';
228 const uint64_t kBaseAddress2 = 0xfac00facull;
229 const uint64_t kSize2 = 0x0200;
230 const uint8_t kValue2 = '!';
231
232 TestMemoryWriter memory_writer_1(kBaseAddress1, kSize1, kValue1);
233 memory_list_writer.AddMemory(&memory_writer_1);
234 TestMemoryWriter memory_writer_2(kBaseAddress2, kSize2, kValue2);
235 memory_list_writer.AddMemory(&memory_writer_2);
236
237 minidump_file_writer.AddStream(&memory_list_writer);
238
239 StringFileWriter file_writer;
240 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
241
242 const MINIDUMP_MEMORY_LIST* memory_list;
243 GetMemoryListStream(file_writer.string(), &memory_list, 1);
244 if (Test::HasFatalFailure()) {
245 return;
246 }
247
248 EXPECT_EQ(2u, memory_list->NumberOfMemoryRanges);
249
250 MINIDUMP_MEMORY_DESCRIPTOR expected;
251 expected.StartOfMemoryRange = kBaseAddress1;
252 expected.Memory.DataSize = kSize1;
253 expected.Memory.Rva =
254 sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
255 sizeof(MINIDUMP_MEMORY_LIST) +
256 memory_list->NumberOfMemoryRanges * sizeof(MINIDUMP_MEMORY_DESCRIPTOR);
257 ExpectMemoryDescriptorAndContents(&expected,
258 &memory_list->MemoryRanges[0],
259 file_writer.string(),
260 kValue1,
261 false);
262
263 expected.StartOfMemoryRange = kBaseAddress2;
264 expected.Memory.DataSize = kSize2;
265 expected.Memory.Rva = memory_list->MemoryRanges[0].Memory.Rva +
266 memory_list->MemoryRanges[0].Memory.DataSize;
267 ExpectMemoryDescriptorAndContents(&expected,
268 &memory_list->MemoryRanges[1],
269 file_writer.string(),
270 kValue2,
271 true);
272 }
273
274 class TestMemoryStream final : public internal::MinidumpStreamWriter {
275 public:
276 TestMemoryStream(uint64_t base_address, size_t size, uint8_t value)
277 : MinidumpStreamWriter(), memory_(base_address, size, value) {}
278
279 ~TestMemoryStream() {}
280
281 TestMemoryWriter* memory() { return &memory_; }
282
283 // MinidumpStreamWriter:
284 virtual MinidumpStreamType StreamType() const override {
285 return kBogusStreamType;
286 }
287
288 protected:
289 // MinidumpWritable:
290 virtual size_t SizeOfObject() override {
291 EXPECT_GE(state(), kStateFrozen);
292 return 0;
293 }
294
295 virtual std::vector<MinidumpWritable*> Children() override {
296 EXPECT_GE(state(), kStateFrozen);
297 std::vector<MinidumpWritable*> children(1, memory());
298 return children;
299 }
300
301 virtual bool WriteObject(FileWriterInterface* file_writer) override {
302 EXPECT_EQ(kStateWritable, state());
303 return true;
304 }
305
306 private:
307 TestMemoryWriter memory_;
308
309 DISALLOW_COPY_AND_ASSIGN(TestMemoryStream);
310 };
311
312 TEST(MinidumpMemoryWriter, ExtraMemory) {
313 // This tests MinidumpMemoryListWriter::AddExtraMemory(). That method adds
314 // a MinidumpMemoryWriter to the MinidumpMemoryListWriter without making the
315 // memory writer a child of the memory list writer.
316 MinidumpFileWriter minidump_file_writer;
317
318 const uint64_t kBaseAddress1 = 0x0000000000001000ull;
319 const uint64_t kSize1 = 0x0400;
320 const uint8_t kValue1 = '1';
321 TestMemoryStream test_memory_stream(kBaseAddress1, kSize1, kValue1);
322
323 MinidumpMemoryListWriter memory_list_writer;
324 memory_list_writer.AddExtraMemory(test_memory_stream.memory());
325
326 minidump_file_writer.AddStream(&test_memory_stream);
327
328 const uint64_t kBaseAddress2 = 0x0000000000002000ull;
329 const uint64_t kSize2 = 0x0400;
330 const uint8_t kValue2 = 'm';
331
332 TestMemoryWriter memory_writer(kBaseAddress2, kSize2, kValue2);
333 memory_list_writer.AddMemory(&memory_writer);
334
335 minidump_file_writer.AddStream(&memory_list_writer);
336
337 StringFileWriter file_writer;
338 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
339
340 const MINIDUMP_MEMORY_LIST* memory_list;
341 GetMemoryListStream(file_writer.string(), &memory_list, 2);
342 if (Test::HasFatalFailure()) {
343 return;
344 }
345
346 EXPECT_EQ(2u, memory_list->NumberOfMemoryRanges);
347
348 MINIDUMP_MEMORY_DESCRIPTOR expected;
349 expected.StartOfMemoryRange = kBaseAddress1;
350 expected.Memory.DataSize = kSize1;
351 expected.Memory.Rva =
352 sizeof(MINIDUMP_HEADER) + 2 * sizeof(MINIDUMP_DIRECTORY) +
353 sizeof(MINIDUMP_MEMORY_LIST) +
354 memory_list->NumberOfMemoryRanges * sizeof(MINIDUMP_MEMORY_DESCRIPTOR);
355 ExpectMemoryDescriptorAndContents(&expected,
356 &memory_list->MemoryRanges[0],
357 file_writer.string(),
358 kValue1,
359 false);
360
361 expected.StartOfMemoryRange = kBaseAddress2;
362 expected.Memory.DataSize = kSize2;
363 expected.Memory.Rva = memory_list->MemoryRanges[0].Memory.Rva +
364 memory_list->MemoryRanges[0].Memory.DataSize;
365 ExpectMemoryDescriptorAndContents(&expected,
366 &memory_list->MemoryRanges[1],
367 file_writer.string(),
368 kValue2,
369 true);
370 }
371
372 } // namespace
OLDNEW
« no previous file with comments | « minidump/minidump_memory_writer.cc ('k') | minidump/minidump_misc_info_writer_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698