|
1 // Copyright (c) 2010, Google Inc. |
|
2 // All rights reserved. |
|
3 // |
|
4 // Redistribution and use in source and binary forms, with or without |
|
5 // modification, are permitted provided that the following conditions are |
|
6 // met: |
|
7 // |
|
8 // * Redistributions of source code must retain the above copyright |
|
9 // notice, this list of conditions and the following disclaimer. |
|
10 // * Redistributions in binary form must reproduce the above |
|
11 // copyright notice, this list of conditions and the following disclaimer |
|
12 // in the documentation and/or other materials provided with the |
|
13 // distribution. |
|
14 // * Neither the name of Google Inc. nor the names of its |
|
15 // contributors may be used to endorse or promote products derived from |
|
16 // this software without specific prior written permission. |
|
17 // |
|
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
29 |
|
30 #include <ios> |
|
31 #include <string> |
|
32 #include <vector> |
|
33 |
|
34 #include "breakpad_googletest_includes.h" |
|
35 #include "common/using_std_string.h" |
|
36 #include "processor/binarystream.h" |
|
37 |
|
38 namespace { |
|
39 using std::ios_base; |
|
40 using std::vector; |
|
41 using google_breakpad::binarystream; |
|
42 |
|
43 |
|
44 class BinaryStreamBasicTest : public ::testing::Test { |
|
45 protected: |
|
46 binarystream stream; |
|
47 }; |
|
48 |
|
49 TEST_F(BinaryStreamBasicTest, ReadU8) { |
|
50 uint8_t u8 = 0; |
|
51 ASSERT_FALSE(stream.eof()); |
|
52 stream >> u8; |
|
53 ASSERT_TRUE(stream.eof()); |
|
54 EXPECT_EQ(0U, u8); |
|
55 stream.rewind(); |
|
56 stream.clear(); |
|
57 stream << (uint8_t)1; |
|
58 ASSERT_FALSE(stream.eof()); |
|
59 stream >> u8; |
|
60 EXPECT_EQ(1, u8); |
|
61 EXPECT_FALSE(stream.eof()); |
|
62 } |
|
63 |
|
64 TEST_F(BinaryStreamBasicTest, ReadU16) { |
|
65 uint16_t u16 = 0; |
|
66 ASSERT_FALSE(stream.eof()); |
|
67 stream >> u16; |
|
68 ASSERT_TRUE(stream.eof()); |
|
69 EXPECT_EQ(0U, u16); |
|
70 stream.rewind(); |
|
71 stream.clear(); |
|
72 stream << (uint16_t)1; |
|
73 ASSERT_FALSE(stream.eof()); |
|
74 stream >> u16; |
|
75 EXPECT_EQ(1, u16); |
|
76 EXPECT_FALSE(stream.eof()); |
|
77 } |
|
78 |
|
79 TEST_F(BinaryStreamBasicTest, ReadU32) { |
|
80 uint32_t u32 = 0; |
|
81 ASSERT_FALSE(stream.eof()); |
|
82 stream >> u32; |
|
83 ASSERT_TRUE(stream.eof()); |
|
84 EXPECT_EQ(0U, u32); |
|
85 stream.rewind(); |
|
86 stream.clear(); |
|
87 stream << (uint32_t)1; |
|
88 ASSERT_FALSE(stream.eof()); |
|
89 stream >> u32; |
|
90 EXPECT_EQ(1U, u32); |
|
91 EXPECT_FALSE(stream.eof()); |
|
92 } |
|
93 |
|
94 TEST_F(BinaryStreamBasicTest, ReadU64) { |
|
95 uint64_t u64 = 0; |
|
96 ASSERT_FALSE(stream.eof()); |
|
97 stream >> u64; |
|
98 ASSERT_TRUE(stream.eof()); |
|
99 EXPECT_EQ(0U, u64); |
|
100 stream.rewind(); |
|
101 stream.clear(); |
|
102 stream << (uint64_t)1; |
|
103 ASSERT_FALSE(stream.eof()); |
|
104 stream >> u64; |
|
105 EXPECT_EQ(1U, u64); |
|
106 EXPECT_FALSE(stream.eof()); |
|
107 } |
|
108 |
|
109 TEST_F(BinaryStreamBasicTest, ReadString) { |
|
110 string s(""); |
|
111 ASSERT_FALSE(stream.eof()); |
|
112 stream >> s; |
|
113 ASSERT_TRUE(stream.eof()); |
|
114 EXPECT_EQ("", s); |
|
115 // write an empty string to the stream, read it back |
|
116 s = "abcd"; |
|
117 stream.rewind(); |
|
118 stream.clear(); |
|
119 stream << string(""); |
|
120 stream >> s; |
|
121 EXPECT_EQ("", s); |
|
122 EXPECT_FALSE(stream.eof()); |
|
123 stream.rewind(); |
|
124 stream.clear(); |
|
125 stream << string("test"); |
|
126 ASSERT_FALSE(stream.eof()); |
|
127 stream >> s; |
|
128 EXPECT_EQ("test", s); |
|
129 EXPECT_FALSE(stream.eof()); |
|
130 } |
|
131 |
|
132 TEST_F(BinaryStreamBasicTest, ReadEmptyString) { |
|
133 string s("abc"); |
|
134 stream << string(""); |
|
135 stream >> s; |
|
136 EXPECT_EQ("", s); |
|
137 } |
|
138 |
|
139 TEST_F(BinaryStreamBasicTest, ReadMultiU8) { |
|
140 const uint8_t ea = 0, eb = 100, ec = 200, ed = 0xFF; |
|
141 uint8_t a, b, c, d, e; |
|
142 stream << ea << eb << ec << ed; |
|
143 stream >> a >> b >> c >> d; |
|
144 ASSERT_FALSE(stream.eof()); |
|
145 EXPECT_EQ(ea, a); |
|
146 EXPECT_EQ(eb, b); |
|
147 EXPECT_EQ(ec, c); |
|
148 EXPECT_EQ(ed, d); |
|
149 ASSERT_FALSE(stream.eof()); |
|
150 e = 0; |
|
151 stream >> e; |
|
152 EXPECT_EQ(0U, e); |
|
153 ASSERT_TRUE(stream.eof()); |
|
154 // try reading all at once, including one past eof |
|
155 stream.rewind(); |
|
156 stream.clear(); |
|
157 ASSERT_FALSE(stream.eof()); |
|
158 a = b = c = d = e = 0; |
|
159 stream << ea << eb << ec << ed; |
|
160 stream >> a >> b >> c >> d >> e; |
|
161 EXPECT_EQ(ea, a); |
|
162 EXPECT_EQ(eb, b); |
|
163 EXPECT_EQ(ec, c); |
|
164 EXPECT_EQ(ed, d); |
|
165 EXPECT_EQ(0U, e); |
|
166 EXPECT_TRUE(stream.eof()); |
|
167 } |
|
168 |
|
169 TEST_F(BinaryStreamBasicTest, ReadMultiU16) { |
|
170 const uint16_t ea = 0, eb = 0x100, ec = 0x8000, ed = 0xFFFF; |
|
171 uint16_t a, b, c, d, e; |
|
172 stream << ea << eb << ec << ed; |
|
173 stream >> a >> b >> c >> d; |
|
174 ASSERT_FALSE(stream.eof()); |
|
175 EXPECT_EQ(ea, a); |
|
176 EXPECT_EQ(eb, b); |
|
177 EXPECT_EQ(ec, c); |
|
178 EXPECT_EQ(ed, d); |
|
179 ASSERT_FALSE(stream.eof()); |
|
180 e = 0; |
|
181 stream >> e; |
|
182 EXPECT_EQ(0U, e); |
|
183 EXPECT_TRUE(stream.eof()); |
|
184 // try reading all at once, including one past eof |
|
185 stream.rewind(); |
|
186 stream.clear(); |
|
187 ASSERT_FALSE(stream.eof()); |
|
188 a = b = c = d = e = 0; |
|
189 stream << ea << eb << ec << ed; |
|
190 stream >> a >> b >> c >> d >> e; |
|
191 EXPECT_EQ(ea, a); |
|
192 EXPECT_EQ(eb, b); |
|
193 EXPECT_EQ(ec, c); |
|
194 EXPECT_EQ(ed, d); |
|
195 EXPECT_EQ(0U, e); |
|
196 EXPECT_TRUE(stream.eof()); |
|
197 } |
|
198 |
|
199 TEST_F(BinaryStreamBasicTest, ReadMultiU32) { |
|
200 const uint32_t ea = 0, eb = 0x10000, ec = 0x8000000, ed = 0xFFFFFFFF; |
|
201 uint32_t a, b, c, d, e; |
|
202 stream << ea << eb << ec << ed; |
|
203 stream >> a >> b >> c >> d; |
|
204 ASSERT_FALSE(stream.eof()); |
|
205 EXPECT_EQ(ea, a); |
|
206 EXPECT_EQ(eb, b); |
|
207 EXPECT_EQ(ec, c); |
|
208 EXPECT_EQ(ed, d); |
|
209 ASSERT_FALSE(stream.eof()); |
|
210 e = 0; |
|
211 stream >> e; |
|
212 EXPECT_EQ(0U, e); |
|
213 EXPECT_TRUE(stream.eof()); |
|
214 // try reading all at once, including one past eof |
|
215 stream.rewind(); |
|
216 stream.clear(); |
|
217 ASSERT_FALSE(stream.eof()); |
|
218 a = b = c = d = e = 0; |
|
219 stream << ea << eb << ec << ed; |
|
220 stream >> a >> b >> c >> d >> e; |
|
221 EXPECT_EQ(ea, a); |
|
222 EXPECT_EQ(eb, b); |
|
223 EXPECT_EQ(ec, c); |
|
224 EXPECT_EQ(ed, d); |
|
225 EXPECT_EQ(0U, e); |
|
226 EXPECT_TRUE(stream.eof()); |
|
227 } |
|
228 |
|
229 TEST_F(BinaryStreamBasicTest, ReadMultiU64) { |
|
230 const uint64_t ea = 0, eb = 0x10000, ec = 0x100000000ULL, |
|
231 ed = 0xFFFFFFFFFFFFFFFFULL; |
|
232 uint64_t a, b, c, d, e; |
|
233 stream << ea << eb << ec << ed; |
|
234 stream >> a >> b >> c >> d; |
|
235 ASSERT_FALSE(stream.eof()); |
|
236 EXPECT_EQ(ea, a); |
|
237 EXPECT_EQ(eb, b); |
|
238 EXPECT_EQ(ec, c); |
|
239 EXPECT_EQ(ed, d); |
|
240 ASSERT_FALSE(stream.eof()); |
|
241 e = 0; |
|
242 stream >> e; |
|
243 EXPECT_EQ(0U, e); |
|
244 EXPECT_TRUE(stream.eof()); |
|
245 // try reading all at once, including one past eof |
|
246 stream.rewind(); |
|
247 stream.clear(); |
|
248 ASSERT_FALSE(stream.eof()); |
|
249 a = b = c = d = e = 0; |
|
250 stream << ea << eb << ec << ed; |
|
251 stream >> a >> b >> c >> d >> e; |
|
252 EXPECT_EQ(ea, a); |
|
253 EXPECT_EQ(eb, b); |
|
254 EXPECT_EQ(ec, c); |
|
255 EXPECT_EQ(ed, d); |
|
256 EXPECT_EQ(0U, e); |
|
257 EXPECT_TRUE(stream.eof()); |
|
258 } |
|
259 |
|
260 TEST_F(BinaryStreamBasicTest, ReadMixed) { |
|
261 const uint8_t e8 = 0x10; |
|
262 const uint16_t e16 = 0x2020; |
|
263 const uint32_t e32 = 0x30303030; |
|
264 const uint64_t e64 = 0x4040404040404040ULL; |
|
265 const string es = "test"; |
|
266 uint8_t u8 = 0; |
|
267 uint16_t u16 = 0; |
|
268 uint32_t u32 = 0; |
|
269 uint64_t u64 = 0; |
|
270 string s("test"); |
|
271 stream << e8 << e16 << e32 << e64 << es; |
|
272 stream >> u8 >> u16 >> u32 >> u64 >> s; |
|
273 EXPECT_FALSE(stream.eof()); |
|
274 EXPECT_EQ(e8, u8); |
|
275 EXPECT_EQ(e16, u16); |
|
276 EXPECT_EQ(e32, u32); |
|
277 EXPECT_EQ(e64, u64); |
|
278 EXPECT_EQ(es, s); |
|
279 } |
|
280 |
|
281 TEST_F(BinaryStreamBasicTest, ReadStringMissing) { |
|
282 // ensure that reading a string where only the length is present fails |
|
283 uint16_t u16 = 8; |
|
284 stream << u16; |
|
285 stream.rewind(); |
|
286 string s(""); |
|
287 stream >> s; |
|
288 EXPECT_EQ("", s); |
|
289 EXPECT_TRUE(stream.eof()); |
|
290 } |
|
291 |
|
292 TEST_F(BinaryStreamBasicTest, ReadStringTruncated) { |
|
293 // ensure that reading a string where not all the data is present fails |
|
294 uint16_t u16 = 8; |
|
295 stream << u16; |
|
296 stream << (uint8_t)'t' << (uint8_t)'e' << (uint8_t)'s' << (uint8_t)'t'; |
|
297 stream.rewind(); |
|
298 string s(""); |
|
299 stream >> s; |
|
300 EXPECT_EQ("", s); |
|
301 EXPECT_TRUE(stream.eof()); |
|
302 } |
|
303 |
|
304 TEST_F(BinaryStreamBasicTest, StreamByteLength) { |
|
305 // Test that the stream buffer contains the right amount of data |
|
306 stream << (uint8_t)0 << (uint16_t)1 << (uint32_t)2 << (uint64_t)3 |
|
307 << string("test"); |
|
308 string s = stream.str(); |
|
309 EXPECT_EQ(21U, s.length()); |
|
310 } |
|
311 |
|
312 TEST_F(BinaryStreamBasicTest, AppendStreamResultsByteLength) { |
|
313 // Test that appending the str() results from two streams |
|
314 // gives the right byte length |
|
315 binarystream stream2; |
|
316 stream << (uint8_t)0 << (uint16_t)1; |
|
317 stream2 << (uint32_t)0 << (uint64_t)2 |
|
318 << string("test"); |
|
319 string s = stream.str(); |
|
320 string s2 = stream2.str(); |
|
321 s.append(s2); |
|
322 EXPECT_EQ(21U, s.length()); |
|
323 } |
|
324 |
|
325 TEST_F(BinaryStreamBasicTest, StreamSetStr) { |
|
326 const string es("test"); |
|
327 stream << es; |
|
328 binarystream stream2; |
|
329 stream2.str(stream.str()); |
|
330 string s; |
|
331 stream2 >> s; |
|
332 EXPECT_FALSE(stream2.eof()); |
|
333 EXPECT_EQ("test", s); |
|
334 s = ""; |
|
335 stream2.str(stream.str()); |
|
336 stream2.rewind(); |
|
337 stream2 >> s; |
|
338 EXPECT_FALSE(stream2.eof()); |
|
339 EXPECT_EQ("test", s); |
|
340 } |
|
341 |
|
342 class BinaryStreamU8Test : public ::testing::Test { |
|
343 protected: |
|
344 binarystream stream; |
|
345 |
|
346 void SetUp() { |
|
347 stream << (uint8_t)1; |
|
348 } |
|
349 }; |
|
350 |
|
351 TEST_F(BinaryStreamU8Test, ReadU16) { |
|
352 uint16_t u16 = 0; |
|
353 ASSERT_FALSE(stream.eof()); |
|
354 stream >> u16; |
|
355 ASSERT_TRUE(stream.eof()); |
|
356 EXPECT_EQ(0U, u16); |
|
357 } |
|
358 |
|
359 TEST_F(BinaryStreamU8Test, ReadU32) { |
|
360 uint32_t u32 = 0; |
|
361 ASSERT_FALSE(stream.eof()); |
|
362 stream >> u32; |
|
363 ASSERT_TRUE(stream.eof()); |
|
364 EXPECT_EQ(0U, u32); |
|
365 } |
|
366 |
|
367 TEST_F(BinaryStreamU8Test, ReadU64) { |
|
368 uint64_t u64 = 0; |
|
369 ASSERT_FALSE(stream.eof()); |
|
370 stream >> u64; |
|
371 ASSERT_TRUE(stream.eof()); |
|
372 EXPECT_EQ(0U, u64); |
|
373 } |
|
374 |
|
375 TEST_F(BinaryStreamU8Test, ReadString) { |
|
376 string s(""); |
|
377 ASSERT_FALSE(stream.eof()); |
|
378 stream >> s; |
|
379 ASSERT_TRUE(stream.eof()); |
|
380 EXPECT_EQ("", s); |
|
381 } |
|
382 |
|
383 |
|
384 TEST(BinaryStreamTest, InitWithData) { |
|
385 const char *data = "abcd"; |
|
386 binarystream stream(data); |
|
387 uint8_t a, b, c, d; |
|
388 stream >> a >> b >> c >> d; |
|
389 ASSERT_FALSE(stream.eof()); |
|
390 EXPECT_EQ('a', a); |
|
391 EXPECT_EQ('b', b); |
|
392 EXPECT_EQ('c', c); |
|
393 EXPECT_EQ('d', d); |
|
394 } |
|
395 |
|
396 TEST(BinaryStreamTest, InitWithDataLeadingNull) { |
|
397 const char *data = "\0abcd"; |
|
398 binarystream stream(data, 5); |
|
399 uint8_t z, a, b, c, d; |
|
400 stream >> z >> a >> b >> c >> d; |
|
401 ASSERT_FALSE(stream.eof()); |
|
402 EXPECT_EQ(0U, z); |
|
403 EXPECT_EQ('a', a); |
|
404 EXPECT_EQ('b', b); |
|
405 EXPECT_EQ('c', c); |
|
406 EXPECT_EQ('d', d); |
|
407 } |
|
408 |
|
409 TEST(BinaryStreamTest, InitWithDataVector) { |
|
410 vector<char> data; |
|
411 data.push_back('a'); |
|
412 data.push_back('b'); |
|
413 data.push_back('c'); |
|
414 data.push_back('d'); |
|
415 data.push_back('e'); |
|
416 data.resize(4); |
|
417 binarystream stream(&data[0], data.size()); |
|
418 uint8_t a, b, c, d; |
|
419 stream >> a >> b >> c >> d; |
|
420 ASSERT_FALSE(stream.eof()); |
|
421 EXPECT_EQ('a', a); |
|
422 EXPECT_EQ('b', b); |
|
423 EXPECT_EQ('c', c); |
|
424 EXPECT_EQ('d', d); |
|
425 } |
|
426 |
|
427 } // namespace |
|
428 |
|
429 int main(int argc, char *argv[]) { |
|
430 ::testing::InitGoogleTest(&argc, argv); |
|
431 return RUN_ALL_TESTS(); |
|
432 } |