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_file_writer.h" | |
16 | |
17 #include <dbghelp.h> | |
18 | |
19 #include <string> | |
20 | |
21 #include "base/basictypes.h" | |
22 #include "gtest/gtest.h" | |
23 #include "minidump/minidump_stream_writer.h" | |
24 #include "minidump/minidump_writable.h" | |
25 #include "util/file/file_writer.h" | |
26 #include "util/file/string_file_writer.h" | |
27 | |
28 namespace { | |
29 | |
30 using namespace crashpad; | |
31 | |
32 TEST(MinidumpFileWriter, Empty) { | |
33 MinidumpFileWriter minidump_file; | |
34 StringFileWriter file_writer; | |
35 ASSERT_TRUE(minidump_file.WriteEverything(&file_writer)); | |
36 ASSERT_EQ(sizeof(MINIDUMP_HEADER), file_writer.string().size()); | |
37 | |
38 const MINIDUMP_HEADER* header = | |
39 reinterpret_cast<const MINIDUMP_HEADER*>(&file_writer.string()[0]); | |
40 | |
41 EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_SIGNATURE), header->Signature); | |
42 EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_VERSION), header->Version); | |
43 EXPECT_EQ(0u, header->NumberOfStreams); | |
44 EXPECT_EQ(0u, header->StreamDirectoryRva); | |
45 EXPECT_EQ(0u, header->CheckSum); | |
46 EXPECT_EQ(0u, header->TimeDateStamp); | |
47 EXPECT_EQ(MiniDumpNormal, header->Flags); | |
48 } | |
49 | |
50 class TestStream final : public internal::MinidumpStreamWriter { | |
51 public: | |
52 TestStream(MinidumpStreamType stream_type, | |
53 size_t stream_size, | |
54 uint8_t stream_value) | |
55 : stream_data_(stream_size, stream_value), stream_type_(stream_type) {} | |
56 | |
57 ~TestStream() {} | |
58 | |
59 // MinidumpStreamWriter: | |
60 virtual MinidumpStreamType StreamType() const override { | |
61 return stream_type_; | |
62 } | |
63 | |
64 protected: | |
65 // MinidumpWritable: | |
66 virtual size_t SizeOfObject() override { | |
67 EXPECT_GE(state(), kStateFrozen); | |
68 return stream_data_.size(); | |
69 } | |
70 | |
71 virtual bool WriteObject(FileWriterInterface* file_writer) override { | |
72 EXPECT_EQ(state(), kStateWritable); | |
73 return file_writer->Write(&stream_data_[0], stream_data_.size()); | |
74 } | |
75 | |
76 private: | |
77 std::string stream_data_; | |
78 MinidumpStreamType stream_type_; | |
79 | |
80 DISALLOW_COPY_AND_ASSIGN(TestStream); | |
81 }; | |
82 | |
83 TEST(MinidumpFileWriter, OneStream) { | |
84 MinidumpFileWriter minidump_file; | |
85 const time_t kTimestamp = 0x155d2fb8; | |
86 minidump_file.SetTimestamp(kTimestamp); | |
87 | |
88 const size_t kStreamSize = 5; | |
89 const MinidumpStreamType kStreamType = static_cast<MinidumpStreamType>(0x4d); | |
90 const uint8_t kStreamValue = 0x5a; | |
91 TestStream stream(kStreamType, kStreamSize, kStreamValue); | |
92 minidump_file.AddStream(&stream); | |
93 | |
94 StringFileWriter file_writer; | |
95 ASSERT_TRUE(minidump_file.WriteEverything(&file_writer)); | |
96 | |
97 const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER); | |
98 const size_t kStreamOffset = kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY); | |
99 const size_t kFileSize = kStreamOffset + kStreamSize; | |
100 | |
101 ASSERT_EQ(kFileSize, file_writer.string().size()); | |
102 | |
103 const MINIDUMP_HEADER* header = | |
104 reinterpret_cast<const MINIDUMP_HEADER*>(&file_writer.string()[0]); | |
105 | |
106 EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_SIGNATURE), header->Signature); | |
107 EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_VERSION), header->Version); | |
108 EXPECT_EQ(1u, header->NumberOfStreams); | |
109 EXPECT_EQ(kDirectoryOffset, header->StreamDirectoryRva); | |
110 EXPECT_EQ(0u, header->CheckSum); | |
111 EXPECT_EQ(kTimestamp, header->TimeDateStamp); | |
112 EXPECT_EQ(MiniDumpNormal, header->Flags); | |
113 | |
114 const MINIDUMP_DIRECTORY* directory = | |
115 reinterpret_cast<const MINIDUMP_DIRECTORY*>( | |
116 &file_writer.string()[kDirectoryOffset]); | |
117 | |
118 EXPECT_EQ(kStreamType, directory->StreamType); | |
119 EXPECT_EQ(kStreamSize, directory->Location.DataSize); | |
120 EXPECT_EQ(kStreamOffset, directory->Location.Rva); | |
121 | |
122 const uint8_t* stream_data = | |
123 reinterpret_cast<const uint8_t*>(&file_writer.string()[kStreamOffset]); | |
124 | |
125 std::string expected_stream(kStreamSize, kStreamValue); | |
126 EXPECT_EQ(0, memcmp(stream_data, expected_stream.c_str(), kStreamSize)); | |
127 } | |
128 | |
129 TEST(MinidumpFileWriter, ThreeStreams) { | |
130 MinidumpFileWriter minidump_file; | |
131 const time_t kTimestamp = 0x155d2fb8; | |
132 minidump_file.SetTimestamp(kTimestamp); | |
133 | |
134 const size_t kStream1Size = 5; | |
135 const MinidumpStreamType kStream1Type = static_cast<MinidumpStreamType>(0x6d); | |
136 const uint8_t kStream1Value = 0x5a; | |
137 TestStream stream1(kStream1Type, kStream1Size, kStream1Value); | |
138 minidump_file.AddStream(&stream1); | |
139 | |
140 // Make the second stream’s type be a smaller quantity than the first stream’s | |
141 // to test that the streams show up in the order that they were added, not in | |
142 // numeric order. | |
143 const size_t kStream2Size = 3; | |
144 const MinidumpStreamType kStream2Type = static_cast<MinidumpStreamType>(0x4d); | |
145 const uint8_t kStream2Value = 0xa5; | |
146 TestStream stream2(kStream2Type, kStream2Size, kStream2Value); | |
147 minidump_file.AddStream(&stream2); | |
148 | |
149 const size_t kStream3Size = 1; | |
150 const MinidumpStreamType kStream3Type = static_cast<MinidumpStreamType>(0x7e); | |
151 const uint8_t kStream3Value = 0x36; | |
152 TestStream stream3(kStream3Type, kStream3Size, kStream3Value); | |
153 minidump_file.AddStream(&stream3); | |
154 | |
155 StringFileWriter file_writer; | |
156 ASSERT_TRUE(minidump_file.WriteEverything(&file_writer)); | |
157 | |
158 const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER); | |
159 const size_t kStream1Offset = | |
160 kDirectoryOffset + 3 * sizeof(MINIDUMP_DIRECTORY); | |
161 const size_t kStream2Padding = 3; | |
162 const size_t kStream2Offset = kStream1Offset + kStream1Size + kStream2Padding; | |
163 const size_t kStream3Padding = 1; | |
164 const size_t kStream3Offset = kStream2Offset + kStream2Size + kStream3Padding; | |
165 const size_t kFileSize = kStream3Offset + kStream3Size; | |
166 | |
167 ASSERT_EQ(kFileSize, file_writer.string().size()); | |
168 | |
169 const MINIDUMP_HEADER* header = | |
170 reinterpret_cast<const MINIDUMP_HEADER*>(&file_writer.string()[0]); | |
171 | |
172 EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_SIGNATURE), header->Signature); | |
173 EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_VERSION), header->Version); | |
174 EXPECT_EQ(3u, header->NumberOfStreams); | |
175 EXPECT_EQ(kDirectoryOffset, header->StreamDirectoryRva); | |
176 EXPECT_EQ(0u, header->CheckSum); | |
177 EXPECT_EQ(kTimestamp, header->TimeDateStamp); | |
178 EXPECT_EQ(MiniDumpNormal, header->Flags); | |
179 | |
180 const MINIDUMP_DIRECTORY* directory = | |
181 reinterpret_cast<const MINIDUMP_DIRECTORY*>( | |
182 &file_writer.string()[kDirectoryOffset]); | |
183 | |
184 EXPECT_EQ(kStream1Type, directory[0].StreamType); | |
185 EXPECT_EQ(kStream1Size, directory[0].Location.DataSize); | |
186 EXPECT_EQ(kStream1Offset, directory[0].Location.Rva); | |
187 EXPECT_EQ(kStream2Type, directory[1].StreamType); | |
188 EXPECT_EQ(kStream2Size, directory[1].Location.DataSize); | |
189 EXPECT_EQ(kStream2Offset, directory[1].Location.Rva); | |
190 EXPECT_EQ(kStream3Type, directory[2].StreamType); | |
191 EXPECT_EQ(kStream3Size, directory[2].Location.DataSize); | |
192 EXPECT_EQ(kStream3Offset, directory[2].Location.Rva); | |
193 | |
194 const uint8_t* stream1_data = | |
195 reinterpret_cast<const uint8_t*>(&file_writer.string()[kStream1Offset]); | |
196 | |
197 std::string expected_stream1(kStream1Size, kStream1Value); | |
198 EXPECT_EQ(0, memcmp(stream1_data, expected_stream1.c_str(), kStream1Size)); | |
199 | |
200 const int kZeroes[16] = {}; | |
201 ASSERT_GE(sizeof(kZeroes), kStream2Padding); | |
202 ASSERT_GE(sizeof(kZeroes), kStream3Padding); | |
203 | |
204 EXPECT_EQ(0, memcmp(stream1_data + kStream1Size, kZeroes, kStream2Padding)); | |
205 | |
206 const uint8_t* stream2_data = | |
207 reinterpret_cast<const uint8_t*>(&file_writer.string()[kStream2Offset]); | |
208 | |
209 std::string expected_stream2(kStream2Size, kStream2Value); | |
210 EXPECT_EQ(0, memcmp(stream2_data, expected_stream2.c_str(), kStream2Size)); | |
211 | |
212 EXPECT_EQ(0, memcmp(stream2_data + kStream2Size, kZeroes, kStream3Padding)); | |
213 | |
214 const uint8_t* stream3_data = | |
215 reinterpret_cast<const uint8_t*>(&file_writer.string()[kStream3Offset]); | |
216 | |
217 std::string expected_stream3(kStream3Size, kStream3Value); | |
218 EXPECT_EQ(0, memcmp(stream3_data, expected_stream3.c_str(), kStream3Size)); | |
219 } | |
220 | |
221 TEST(MinidumpFileWriterDeathTest, SameStreamType) { | |
222 MinidumpFileWriter minidump_file; | |
223 | |
224 const size_t kStream1Size = 5; | |
225 const MinidumpStreamType kStream1Type = static_cast<MinidumpStreamType>(0x4d); | |
226 const uint8_t kStream1Value = 0x5a; | |
227 TestStream stream1(kStream1Type, kStream1Size, kStream1Value); | |
228 minidump_file.AddStream(&stream1); | |
229 | |
230 // It is an error to add a second stream of the same type. | |
231 const size_t kStream2Size = 3; | |
232 const MinidumpStreamType kStream2Type = static_cast<MinidumpStreamType>(0x4d); | |
233 const uint8_t kStream2Value = 0xa5; | |
234 TestStream stream2(kStream2Type, kStream2Size, kStream2Value); | |
235 ASSERT_DEATH(minidump_file.AddStream(&stream2), "already present"); | |
Robert Sesek
2014/08/03 21:20:55
I guess this is why exceptions are kind of nice, b
Mark Mentovai
2014/08/03 22:45:54
rsesek wrote:
| |
236 } | |
237 | |
238 } // namespace | |
OLD | NEW |