1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34 //
35 // This file contains tests and benchmarks.
36
37 #include <vector>
38
39 #include <google/protobuf/io/coded_stream.h>
40
41 #include <limits.h>
42
43 #include <google/protobuf/stubs/common.h>
44 #include <google/protobuf/testing/googletest.h>
45 #include <gtest/gtest.h>
46 #include <google/protobuf/io/zero_copy_stream_impl.h>
47
48
49 // This declares an unsigned long long integer literal in a portable way.
50 // (The original macro is way too big and ruins my formatting.)
51 #undef ULL
52 #define ULL(x) GOOGLE_ULONGLONG(x)
53
54 namespace google {
55 namespace protobuf {
56 namespace io {
57 namespace {
58
59 // ===================================================================
60 // Data-Driven Test Infrastructure
61
62 // TEST_1D and TEST_2D are macros I'd eventually like to see added to
63 // gTest. These macros can be used to declare tests which should be
64 // run multiple times, once for each item in some input array. TEST_1D
65 // tests all cases in a single input array. TEST_2D tests all
66 // combinations of cases from two arrays. The arrays must be statically
67 // defined such that the GOOGLE_ARRAYSIZE() macro works on them. Example:
68 //
69 // int kCases[] = {1, 2, 3, 4}
70 // TEST_1D(MyFixture, MyTest, kCases) {
71 // EXPECT_GT(kCases_case, 0);
72 // }
73 //
74 // This test iterates through the numbers 1, 2, 3, and 4 and tests that
75 // they are all grater than zero. In case of failure, the exact case
76 // which failed will be printed. The case type must be printable using
77 // ostream::operator<<.
78
79 // TODO(kenton): gTest now supports "parameterized tests" which would be
80 // a better way to accomplish this. Rewrite when time permits.
81
82 #define TEST_1D(FIXTURE, NAME, CASES) \
83 class FIXTURE##_##NAME##_DD : public FIXTURE { \
84 protected: \
85 template <typename CaseType> \
86 void DoSingleCase(const CaseType& CASES##_case); \
87 }; \
88 \
89 TEST_F(FIXTURE##_##NAME##_DD, NAME) { \
90 for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES); i++) { \
91 SCOPED_TRACE(testing::Message() \
92 << #CASES " case #" << i << ": " << CASES[i]); \
93 DoSingleCase(CASES[i]); \
94 } \
95 } \
96 \
97 template <typename CaseType> \
98 void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType& CASES##_case)
99
100 #define TEST_2D(FIXTURE, NAME, CASES1, CASES2) \
101 class FIXTURE##_##NAME##_DD : public FIXTURE { \
102 protected: \
103 template <typename CaseType1, typename CaseType2> \
104 void DoSingleCase(const CaseType1& CASES1##_case, \
105 const CaseType2& CASES2##_case); \
106 }; \
107 \
108 TEST_F(FIXTURE##_##NAME##_DD, NAME) { \
109 for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES1); i++) { \
110 for (int j = 0; j < GOOGLE_ARRAYSIZE(CASES2); j++) { \
111 SCOPED_TRACE(testing::Message() \
112 << #CASES1 " case #" << i << ": " << CASES1[i] << ", " \
113 << #CASES2 " case #" << j << ": " << CASES2[j]); \
114 DoSingleCase(CASES1[i], CASES2[j]); \
115 } \
116 } \
117 } \
118 \
119 template <typename CaseType1, typename CaseType2> \
120 void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType1& CASES1##_case, \
121 const CaseType2& CASES2##_case)
122
123 // ===================================================================
124
125 class CodedStreamTest : public testing::Test {
126 protected:
127 // Helper method used by tests for bytes warning. See implementation comment
128 // for further information.
129 static void SetupTotalBytesLimitWarningTest(
130 int total_bytes_limit, int warning_threshold,
131 vector<string>* out_errors, vector<string>* out_warnings);
132
133 // Buffer used during most of the tests. This assumes tests run sequentially.
134 static const int kBufferSize = 1024 * 64;
135 static uint8 buffer_[kBufferSize];
136 };
137
138 uint8 CodedStreamTest::buffer_[CodedStreamTest::kBufferSize];
139
140 // We test each operation over a variety of block sizes to insure that
141 // we test cases where reads or writes cross buffer boundaries, cases
142 // where they don't, and cases where there is so much buffer left that
143 // we can use special optimized paths that don't worry about bounds
144 // checks.
145 const int kBlockSizes[] = {1, 2, 3, 5, 7, 13, 32, 1024};
146
147 // -------------------------------------------------------------------
148 // Varint tests.
149
150 struct VarintCase {
151 uint8 bytes[10]; // Encoded bytes.
152 int size; // Encoded size, in bytes.
153 uint64 value; // Parsed value.
154 };
155
operator <<(std::ostream & os,const VarintCase & c)156 inline std::ostream& operator<<(std::ostream& os, const VarintCase& c) {
157 return os << c.value;
158 }
159
160 VarintCase kVarintCases[] = {
161 // 32-bit values
162 {{0x00} , 1, 0},
163 {{0x01} , 1, 1},
164 {{0x7f} , 1, 127},
165 {{0xa2, 0x74}, 2, (0x22 << 0) | (0x74 << 7)}, // 14882
166 {{0xbe, 0xf7, 0x92, 0x84, 0x0b}, 5, // 2961488830
167 (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
168 (ULL(0x0b) << 28)},
169
170 // 64-bit
171 {{0xbe, 0xf7, 0x92, 0x84, 0x1b}, 5, // 7256456126
172 (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
173 (ULL(0x1b) << 28)},
174 {{0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49}, 8, // 41256202580718336
175 (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
176 (ULL(0x43) << 28) | (ULL(0x49) << 35) | (ULL(0x24) << 42) |
177 (ULL(0x49) << 49)},
178 // 11964378330978735131
179 {{0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01}, 10,
180 (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
181 (ULL(0x3b) << 28) | (ULL(0x56) << 35) | (ULL(0x00) << 42) |
182 (ULL(0x05) << 49) | (ULL(0x26) << 56) | (ULL(0x01) << 63)},
183 };
184
TEST_2D(CodedStreamTest,ReadVarint32,kVarintCases,kBlockSizes)185 TEST_2D(CodedStreamTest, ReadVarint32, kVarintCases, kBlockSizes) {
186 memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size);
187 ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
188
189 {
190 CodedInputStream coded_input(&input);
191
192 uint32 value;
193 EXPECT_TRUE(coded_input.ReadVarint32(&value));
194 EXPECT_EQ(static_cast<uint32>(kVarintCases_case.value), value);
195 }
196
197 EXPECT_EQ(kVarintCases_case.size, input.ByteCount());
198 }
199
TEST_2D(CodedStreamTest,ReadTag,kVarintCases,kBlockSizes)200 TEST_2D(CodedStreamTest, ReadTag, kVarintCases, kBlockSizes) {
201 memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size);
202 ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
203
204 {
205 CodedInputStream coded_input(&input);
206
207 uint32 expected_value = static_cast<uint32>(kVarintCases_case.value);
208 EXPECT_EQ(expected_value, coded_input.ReadTag());
209
210 EXPECT_TRUE(coded_input.LastTagWas(expected_value));
211 EXPECT_FALSE(coded_input.LastTagWas(expected_value + 1));
212 }
213
214 EXPECT_EQ(kVarintCases_case.size, input.ByteCount());
215 }
216
217 // This is the regression test that verifies that there is no issues
218 // with the empty input buffers handling.
TEST_F(CodedStreamTest,EmptyInputBeforeEos)219 TEST_F(CodedStreamTest, EmptyInputBeforeEos) {
220 class In : public ZeroCopyInputStream {
221 public:
222 In() : count_(0) {}
223 private:
224 virtual bool Next(const void** data, int* size) {
225 *data = NULL;
226 *size = 0;
227 return count_++ < 2;
228 }
229 virtual void BackUp(int count) {
230 GOOGLE_LOG(FATAL) << "Tests never call this.";
231 }
232 virtual bool Skip(int count) {
233 GOOGLE_LOG(FATAL) << "Tests never call this.";
234 return false;
235 }
236 virtual int64 ByteCount() const { return 0; }
237 int count_;
238 } in;
239 CodedInputStream input(&in);
240 input.ReadTag();
241 EXPECT_TRUE(input.ConsumedEntireMessage());
242 }
243
TEST_1D(CodedStreamTest,ExpectTag,kVarintCases)244 TEST_1D(CodedStreamTest, ExpectTag, kVarintCases) {
245 // Leave one byte at the beginning of the buffer so we can read it
246 // to force the first buffer to be loaded.
247 buffer_[0] = '\0';
248 memcpy(buffer_ + 1, kVarintCases_case.bytes, kVarintCases_case.size);
249 ArrayInputStream input(buffer_, sizeof(buffer_));
250
251 {
252 CodedInputStream coded_input(&input);
253
254 // Read one byte to force coded_input.Refill() to be called. Otherwise,
255 // ExpectTag() will return a false negative.
256 uint8 dummy;
257 coded_input.ReadRaw(&dummy, 1);
258 EXPECT_EQ((uint)'\0', (uint)dummy);
259
260 uint32 expected_value = static_cast<uint32>(kVarintCases_case.value);
261
262 // ExpectTag() produces false negatives for large values.
263 if (kVarintCases_case.size <= 2) {
264 EXPECT_FALSE(coded_input.ExpectTag(expected_value + 1));
265 EXPECT_TRUE(coded_input.ExpectTag(expected_value));
266 } else {
267 EXPECT_FALSE(coded_input.ExpectTag(expected_value));
268 }
269 }
270
271 if (kVarintCases_case.size <= 2) {
272 EXPECT_EQ(kVarintCases_case.size + 1, input.ByteCount());
273 } else {
274 EXPECT_EQ(1, input.ByteCount());
275 }
276 }
277
TEST_1D(CodedStreamTest,ExpectTagFromArray,kVarintCases)278 TEST_1D(CodedStreamTest, ExpectTagFromArray, kVarintCases) {
279 memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size);
280
281 const uint32 expected_value = static_cast<uint32>(kVarintCases_case.value);
282
283 // If the expectation succeeds, it should return a pointer past the tag.
284 if (kVarintCases_case.size <= 2) {
285 EXPECT_TRUE(NULL ==
286 CodedInputStream::ExpectTagFromArray(buffer_,
287 expected_value + 1));
288 EXPECT_TRUE(buffer_ + kVarintCases_case.size ==
289 CodedInputStream::ExpectTagFromArray(buffer_, expected_value));
290 } else {
291 EXPECT_TRUE(NULL ==
292 CodedInputStream::ExpectTagFromArray(buffer_, expected_value));
293 }
294 }
295
TEST_2D(CodedStreamTest,ReadVarint64,kVarintCases,kBlockSizes)296 TEST_2D(CodedStreamTest, ReadVarint64, kVarintCases, kBlockSizes) {
297 memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size);
298 ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
299
300 {
301 CodedInputStream coded_input(&input);
302
303 uint64 value;
304 EXPECT_TRUE(coded_input.ReadVarint64(&value));
305 EXPECT_EQ(kVarintCases_case.value, value);
306 }
307
308 EXPECT_EQ(kVarintCases_case.size, input.ByteCount());
309 }
310
TEST_2D(CodedStreamTest,WriteVarint32,kVarintCases,kBlockSizes)311 TEST_2D(CodedStreamTest, WriteVarint32, kVarintCases, kBlockSizes) {
312 if (kVarintCases_case.value > ULL(0x00000000FFFFFFFF)) {
313 // Skip this test for the 64-bit values.
314 return;
315 }
316
317 ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case);
318
319 {
320 CodedOutputStream coded_output(&output);
321
322 coded_output.WriteVarint32(static_cast<uint32>(kVarintCases_case.value));
323 EXPECT_FALSE(coded_output.HadError());
324
325 EXPECT_EQ(kVarintCases_case.size, coded_output.ByteCount());
326 }
327
328 EXPECT_EQ(kVarintCases_case.size, output.ByteCount());
329 EXPECT_EQ(0,
330 memcmp(buffer_, kVarintCases_case.bytes, kVarintCases_case.size));
331 }
332
TEST_2D(CodedStreamTest,WriteVarint64,kVarintCases,kBlockSizes)333 TEST_2D(CodedStreamTest, WriteVarint64, kVarintCases, kBlockSizes) {
334 ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case);
335
336 {
337 CodedOutputStream coded_output(&output);
338
339 coded_output.WriteVarint64(kVarintCases_case.value);
340 EXPECT_FALSE(coded_output.HadError());
341
342 EXPECT_EQ(kVarintCases_case.size, coded_output.ByteCount());
343 }
344
345 EXPECT_EQ(kVarintCases_case.size, output.ByteCount());
346 EXPECT_EQ(0,
347 memcmp(buffer_, kVarintCases_case.bytes, kVarintCases_case.size));
348 }
349
350 // This test causes gcc 3.3.5 (and earlier?) to give the cryptic error:
351 // "sorry, unimplemented: `method_call_expr' not supported by dump_expr"
352 #if !defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)
353
354 int32 kSignExtendedVarintCases[] = {
355 0, 1, -1, 1237894, -37895138
356 };
357
TEST_2D(CodedStreamTest,WriteVarint32SignExtended,kSignExtendedVarintCases,kBlockSizes)358 TEST_2D(CodedStreamTest, WriteVarint32SignExtended,
359 kSignExtendedVarintCases, kBlockSizes) {
360 ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case);
361
362 {
363 CodedOutputStream coded_output(&output);
364
365 coded_output.WriteVarint32SignExtended(kSignExtendedVarintCases_case);
366 EXPECT_FALSE(coded_output.HadError());
367
368 if (kSignExtendedVarintCases_case < 0) {
369 EXPECT_EQ(10, coded_output.ByteCount());
370 } else {
371 EXPECT_LE(coded_output.ByteCount(), 5);
372 }
373 }
374
375 if (kSignExtendedVarintCases_case < 0) {
376 EXPECT_EQ(10, output.ByteCount());
377 } else {
378 EXPECT_LE(output.ByteCount(), 5);
379 }
380
381 // Read value back in as a varint64 and insure it matches.
382 ArrayInputStream input(buffer_, sizeof(buffer_));
383
384 {
385 CodedInputStream coded_input(&input);
386
387 uint64 value;
388 EXPECT_TRUE(coded_input.ReadVarint64(&value));
389
390 EXPECT_EQ(kSignExtendedVarintCases_case, static_cast<int64>(value));
391 }
392
393 EXPECT_EQ(output.ByteCount(), input.ByteCount());
394 }
395
396 #endif
397
398
399 // -------------------------------------------------------------------
400 // Varint failure test.
401
402 struct VarintErrorCase {
403 uint8 bytes[12];
404 int size;
405 bool can_parse;
406 };
407
operator <<(std::ostream & os,const VarintErrorCase & c)408 inline std::ostream& operator<<(std::ostream& os, const VarintErrorCase& c) {
409 return os << "size " << c.size;
410 }
411
412 const VarintErrorCase kVarintErrorCases[] = {
413 // Control case. (Insures that there isn't something else wrong that
414 // makes parsing always fail.)
415 {{0x00}, 1, true},
416
417 // No input data.
418 {{}, 0, false},
419
420 // Input ends unexpectedly.
421 {{0xf0, 0xab}, 2, false},
422
423 // Input ends unexpectedly after 32 bits.
424 {{0xf0, 0xab, 0xc9, 0x9a, 0xf8, 0xb2}, 6, false},
425
426 // Longer than 10 bytes.
427 {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01},
428 11, false},
429 };
430
TEST_2D(CodedStreamTest,ReadVarint32Error,kVarintErrorCases,kBlockSizes)431 TEST_2D(CodedStreamTest, ReadVarint32Error, kVarintErrorCases, kBlockSizes) {
432 memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size);
433 ArrayInputStream input(buffer_, kVarintErrorCases_case.size,
434 kBlockSizes_case);
435 CodedInputStream coded_input(&input);
436
437 uint32 value;
438 EXPECT_EQ(kVarintErrorCases_case.can_parse, coded_input.ReadVarint32(&value));
439 }
440
TEST_2D(CodedStreamTest,ReadVarint64Error,kVarintErrorCases,kBlockSizes)441 TEST_2D(CodedStreamTest, ReadVarint64Error, kVarintErrorCases, kBlockSizes) {
442 memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size);
443 ArrayInputStream input(buffer_, kVarintErrorCases_case.size,
444 kBlockSizes_case);
445 CodedInputStream coded_input(&input);
446
447 uint64 value;
448 EXPECT_EQ(kVarintErrorCases_case.can_parse, coded_input.ReadVarint64(&value));
449 }
450
451 // -------------------------------------------------------------------
452 // VarintSize
453
454 struct VarintSizeCase {
455 uint64 value;
456 int size;
457 };
458
operator <<(std::ostream & os,const VarintSizeCase & c)459 inline std::ostream& operator<<(std::ostream& os, const VarintSizeCase& c) {
460 return os << c.value;
461 }
462
463 VarintSizeCase kVarintSizeCases[] = {
464 {0u, 1},
465 {1u, 1},
466 {127u, 1},
467 {128u, 2},
468 {758923u, 3},
469 {4000000000u, 5},
470 {ULL(41256202580718336), 8},
471 {ULL(11964378330978735131), 10},
472 };
473
TEST_1D(CodedStreamTest,VarintSize32,kVarintSizeCases)474 TEST_1D(CodedStreamTest, VarintSize32, kVarintSizeCases) {
475 if (kVarintSizeCases_case.value > 0xffffffffu) {
476 // Skip 64-bit values.
477 return;
478 }
479
480 EXPECT_EQ(kVarintSizeCases_case.size,
481 CodedOutputStream::VarintSize32(
482 static_cast<uint32>(kVarintSizeCases_case.value)));
483 }
484
TEST_1D(CodedStreamTest,VarintSize64,kVarintSizeCases)485 TEST_1D(CodedStreamTest, VarintSize64, kVarintSizeCases) {
486 EXPECT_EQ(kVarintSizeCases_case.size,
487 CodedOutputStream::VarintSize64(kVarintSizeCases_case.value));
488 }
489
490 // -------------------------------------------------------------------
491 // Fixed-size int tests
492
493 struct Fixed32Case {
494 uint8 bytes[sizeof(uint32)]; // Encoded bytes.
495 uint32 value; // Parsed value.
496 };
497
498 struct Fixed64Case {
499 uint8 bytes[sizeof(uint64)]; // Encoded bytes.
500 uint64 value; // Parsed value.
501 };
502
operator <<(std::ostream & os,const Fixed32Case & c)503 inline std::ostream& operator<<(std::ostream& os, const Fixed32Case& c) {
504 return os << "0x" << hex << c.value << dec;
505 }
506
operator <<(std::ostream & os,const Fixed64Case & c)507 inline std::ostream& operator<<(std::ostream& os, const Fixed64Case& c) {
508 return os << "0x" << hex << c.value << dec;
509 }
510
511 Fixed32Case kFixed32Cases[] = {
512 {{0xef, 0xcd, 0xab, 0x90}, 0x90abcdefu},
513 {{0x12, 0x34, 0x56, 0x78}, 0x78563412u},
514 };
515
516 Fixed64Case kFixed64Cases[] = {
517 {{0xef, 0xcd, 0xab, 0x90, 0x12, 0x34, 0x56, 0x78}, ULL(0x7856341290abcdef)},
518 {{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, ULL(0x8877665544332211)},
519 };
520
TEST_2D(CodedStreamTest,ReadLittleEndian32,kFixed32Cases,kBlockSizes)521 TEST_2D(CodedStreamTest, ReadLittleEndian32, kFixed32Cases, kBlockSizes) {
522 memcpy(buffer_, kFixed32Cases_case.bytes, sizeof(kFixed32Cases_case.bytes));
523 ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
524
525 {
526 CodedInputStream coded_input(&input);
527
528 uint32 value;
529 EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
530 EXPECT_EQ(kFixed32Cases_case.value, value);
531 }
532
533 EXPECT_EQ(sizeof(uint32), input.ByteCount());
534 }
535
TEST_2D(CodedStreamTest,ReadLittleEndian64,kFixed64Cases,kBlockSizes)536 TEST_2D(CodedStreamTest, ReadLittleEndian64, kFixed64Cases, kBlockSizes) {
537 memcpy(buffer_, kFixed64Cases_case.bytes, sizeof(kFixed64Cases_case.bytes));
538 ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
539
540 {
541 CodedInputStream coded_input(&input);
542
543 uint64 value;
544 EXPECT_TRUE(coded_input.ReadLittleEndian64(&value));
545 EXPECT_EQ(kFixed64Cases_case.value, value);
546 }
547
548 EXPECT_EQ(sizeof(uint64), input.ByteCount());
549 }
550
TEST_2D(CodedStreamTest,WriteLittleEndian32,kFixed32Cases,kBlockSizes)551 TEST_2D(CodedStreamTest, WriteLittleEndian32, kFixed32Cases, kBlockSizes) {
552 ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case);
553
554 {
555 CodedOutputStream coded_output(&output);
556
557 coded_output.WriteLittleEndian32(kFixed32Cases_case.value);
558 EXPECT_FALSE(coded_output.HadError());
559
560 EXPECT_EQ(sizeof(uint32), coded_output.ByteCount());
561 }
562
563 EXPECT_EQ(sizeof(uint32), output.ByteCount());
564 EXPECT_EQ(0, memcmp(buffer_, kFixed32Cases_case.bytes, sizeof(uint32)));
565 }
566
TEST_2D(CodedStreamTest,WriteLittleEndian64,kFixed64Cases,kBlockSizes)567 TEST_2D(CodedStreamTest, WriteLittleEndian64, kFixed64Cases, kBlockSizes) {
568 ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case);
569
570 {
571 CodedOutputStream coded_output(&output);
572
573 coded_output.WriteLittleEndian64(kFixed64Cases_case.value);
574 EXPECT_FALSE(coded_output.HadError());
575
576 EXPECT_EQ(sizeof(uint64), coded_output.ByteCount());
577 }
578
579 EXPECT_EQ(sizeof(uint64), output.ByteCount());
580 EXPECT_EQ(0, memcmp(buffer_, kFixed64Cases_case.bytes, sizeof(uint64)));
581 }
582
583 // Tests using the static methods to read fixed-size values from raw arrays.
584
TEST_1D(CodedStreamTest,ReadLittleEndian32FromArray,kFixed32Cases)585 TEST_1D(CodedStreamTest, ReadLittleEndian32FromArray, kFixed32Cases) {
586 memcpy(buffer_, kFixed32Cases_case.bytes, sizeof(kFixed32Cases_case.bytes));
587
588 uint32 value;
589 const uint8* end = CodedInputStream::ReadLittleEndian32FromArray(
590 buffer_, &value);
591 EXPECT_EQ(kFixed32Cases_case.value, value);
592 EXPECT_TRUE(end == buffer_ + sizeof(value));
593 }
594
TEST_1D(CodedStreamTest,ReadLittleEndian64FromArray,kFixed64Cases)595 TEST_1D(CodedStreamTest, ReadLittleEndian64FromArray, kFixed64Cases) {
596 memcpy(buffer_, kFixed64Cases_case.bytes, sizeof(kFixed64Cases_case.bytes));
597
598 uint64 value;
599 const uint8* end = CodedInputStream::ReadLittleEndian64FromArray(
600 buffer_, &value);
601 EXPECT_EQ(kFixed64Cases_case.value, value);
602 EXPECT_TRUE(end == buffer_ + sizeof(value));
603 }
604
605 // -------------------------------------------------------------------
606 // Raw reads and writes
607
608 const char kRawBytes[] = "Some bytes which will be written and read raw.";
609
TEST_1D(CodedStreamTest,ReadRaw,kBlockSizes)610 TEST_1D(CodedStreamTest, ReadRaw, kBlockSizes) {
611 memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
612 ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
613 char read_buffer[sizeof(kRawBytes)];
614
615 {
616 CodedInputStream coded_input(&input);
617
618 EXPECT_TRUE(coded_input.ReadRaw(read_buffer, sizeof(kRawBytes)));
619 EXPECT_EQ(0, memcmp(kRawBytes, read_buffer, sizeof(kRawBytes)));
620 }
621
622 EXPECT_EQ(sizeof(kRawBytes), input.ByteCount());
623 }
624
TEST_1D(CodedStreamTest,WriteRaw,kBlockSizes)625 TEST_1D(CodedStreamTest, WriteRaw, kBlockSizes) {
626 ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case);
627
628 {
629 CodedOutputStream coded_output(&output);
630
631 coded_output.WriteRaw(kRawBytes, sizeof(kRawBytes));
632 EXPECT_FALSE(coded_output.HadError());
633
634 EXPECT_EQ(sizeof(kRawBytes), coded_output.ByteCount());
635 }
636
637 EXPECT_EQ(sizeof(kRawBytes), output.ByteCount());
638 EXPECT_EQ(0, memcmp(buffer_, kRawBytes, sizeof(kRawBytes)));
639 }
640
TEST_1D(CodedStreamTest,ReadString,kBlockSizes)641 TEST_1D(CodedStreamTest, ReadString, kBlockSizes) {
642 memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
643 ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
644
645 {
646 CodedInputStream coded_input(&input);
647
648 string str;
649 EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes)));
650 EXPECT_EQ(kRawBytes, str);
651 }
652
653 EXPECT_EQ(strlen(kRawBytes), input.ByteCount());
654 }
655
656 // Check to make sure ReadString doesn't crash on impossibly large strings.
TEST_1D(CodedStreamTest,ReadStringImpossiblyLarge,kBlockSizes)657 TEST_1D(CodedStreamTest, ReadStringImpossiblyLarge, kBlockSizes) {
658 ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
659
660 {
661 CodedInputStream coded_input(&input);
662
663 string str;
664 // Try to read a gigabyte.
665 EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30));
666 }
667 }
668
TEST_F(CodedStreamTest,ReadStringImpossiblyLargeFromStringOnStack)669 TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnStack) {
670 // Same test as above, except directly use a buffer. This used to cause
671 // crashes while the above did not.
672 uint8 buffer[8];
673 CodedInputStream coded_input(buffer, 8);
674 string str;
675 EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30));
676 }
677
TEST_F(CodedStreamTest,ReadStringImpossiblyLargeFromStringOnHeap)678 TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnHeap) {
679 scoped_array<uint8> buffer(new uint8[8]);
680 CodedInputStream coded_input(buffer.get(), 8);
681 string str;
682 EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30));
683 }
684
TEST_1D(CodedStreamTest,ReadStringReservesMemoryOnTotalLimit,kBlockSizes)685 TEST_1D(CodedStreamTest, ReadStringReservesMemoryOnTotalLimit, kBlockSizes) {
686 memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
687 ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
688
689 {
690 CodedInputStream coded_input(&input);
691 coded_input.SetTotalBytesLimit(sizeof(kRawBytes), sizeof(kRawBytes));
692 EXPECT_EQ(sizeof(kRawBytes), coded_input.BytesUntilTotalBytesLimit());
693
694 string str;
695 EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes)));
696 EXPECT_EQ(sizeof(kRawBytes) - strlen(kRawBytes),
697 coded_input.BytesUntilTotalBytesLimit());
698 EXPECT_EQ(kRawBytes, str);
699 // TODO(liujisi): Replace with a more meaningful test (see cl/60966023).
700 EXPECT_GE(str.capacity(), strlen(kRawBytes));
701 }
702
703 EXPECT_EQ(strlen(kRawBytes), input.ByteCount());
704 }
705
TEST_1D(CodedStreamTest,ReadStringReservesMemoryOnPushedLimit,kBlockSizes)706 TEST_1D(CodedStreamTest, ReadStringReservesMemoryOnPushedLimit, kBlockSizes) {
707 memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
708 ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
709
710 {
711 CodedInputStream coded_input(&input);
712 coded_input.PushLimit(sizeof(buffer_));
713
714 string str;
715 EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes)));
716 EXPECT_EQ(kRawBytes, str);
717 // TODO(liujisi): Replace with a more meaningful test (see cl/60966023).
718 EXPECT_GE(str.capacity(), strlen(kRawBytes));
719 }
720
721 EXPECT_EQ(strlen(kRawBytes), input.ByteCount());
722 }
723
TEST_F(CodedStreamTest,ReadStringNoReservationIfLimitsNotSet)724 TEST_F(CodedStreamTest, ReadStringNoReservationIfLimitsNotSet) {
725 memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
726 // Buffer size in the input must be smaller than sizeof(kRawBytes),
727 // otherwise check against capacity will fail as ReadStringInline()
728 // will handle the reading and will reserve the memory as needed.
729 ArrayInputStream input(buffer_, sizeof(buffer_), 32);
730
731 {
732 CodedInputStream coded_input(&input);
733
734 string str;
735 EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes)));
736 EXPECT_EQ(kRawBytes, str);
737 // Note: this check depends on string class implementation. It
738 // expects that string will allocate more than strlen(kRawBytes)
739 // if the content of kRawBytes is appended to string in small
740 // chunks.
741 // TODO(liujisi): Replace with a more meaningful test (see cl/60966023).
742 EXPECT_GE(str.capacity(), strlen(kRawBytes));
743 }
744
745 EXPECT_EQ(strlen(kRawBytes), input.ByteCount());
746 }
747
TEST_F(CodedStreamTest,ReadStringNoReservationSizeIsNegative)748 TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsNegative) {
749 memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
750 // Buffer size in the input must be smaller than sizeof(kRawBytes),
751 // otherwise check against capacity will fail as ReadStringInline()
752 // will handle the reading and will reserve the memory as needed.
753 ArrayInputStream input(buffer_, sizeof(buffer_), 32);
754
755 {
756 CodedInputStream coded_input(&input);
757 coded_input.PushLimit(sizeof(buffer_));
758
759 string str;
760 EXPECT_FALSE(coded_input.ReadString(&str, -1));
761 // Note: this check depends on string class implementation. It
762 // expects that string will always allocate the same amount of
763 // memory for an empty string.
764 EXPECT_EQ(string().capacity(), str.capacity());
765 }
766 }
767
TEST_F(CodedStreamTest,ReadStringNoReservationSizeIsLarge)768 TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsLarge) {
769 memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
770 // Buffer size in the input must be smaller than sizeof(kRawBytes),
771 // otherwise check against capacity will fail as ReadStringInline()
772 // will handle the reading and will reserve the memory as needed.
773 ArrayInputStream input(buffer_, sizeof(buffer_), 32);
774
775 {
776 CodedInputStream coded_input(&input);
777 coded_input.PushLimit(sizeof(buffer_));
778
779 string str;
780 EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30));
781 EXPECT_GT(1 << 30, str.capacity());
782 }
783 }
784
TEST_F(CodedStreamTest,ReadStringNoReservationSizeIsOverTheLimit)785 TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsOverTheLimit) {
786 memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
787 // Buffer size in the input must be smaller than sizeof(kRawBytes),
788 // otherwise check against capacity will fail as ReadStringInline()
789 // will handle the reading and will reserve the memory as needed.
790 ArrayInputStream input(buffer_, sizeof(buffer_), 32);
791
792 {
793 CodedInputStream coded_input(&input);
794 coded_input.PushLimit(16);
795
796 string str;
797 EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes)));
798 // Note: this check depends on string class implementation. It
799 // expects that string will allocate less than strlen(kRawBytes)
800 // for an empty string.
801 EXPECT_GT(strlen(kRawBytes), str.capacity());
802 }
803 }
804
TEST_F(CodedStreamTest,ReadStringNoReservationSizeIsOverTheTotalBytesLimit)805 TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsOverTheTotalBytesLimit) {
806 memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
807 // Buffer size in the input must be smaller than sizeof(kRawBytes),
808 // otherwise check against capacity will fail as ReadStringInline()
809 // will handle the reading and will reserve the memory as needed.
810 ArrayInputStream input(buffer_, sizeof(buffer_), 32);
811
812 {
813 CodedInputStream coded_input(&input);
814 coded_input.SetTotalBytesLimit(16, 16);
815
816 string str;
817 EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes)));
818 // Note: this check depends on string class implementation. It
819 // expects that string will allocate less than strlen(kRawBytes)
820 // for an empty string.
821 EXPECT_GT(strlen(kRawBytes), str.capacity());
822 }
823 }
824
TEST_F(CodedStreamTest,ReadStringNoReservationSizeIsOverTheClosestLimit_GlobalLimitIsCloser)825 TEST_F(CodedStreamTest,
826 ReadStringNoReservationSizeIsOverTheClosestLimit_GlobalLimitIsCloser) {
827 memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
828 // Buffer size in the input must be smaller than sizeof(kRawBytes),
829 // otherwise check against capacity will fail as ReadStringInline()
830 // will handle the reading and will reserve the memory as needed.
831 ArrayInputStream input(buffer_, sizeof(buffer_), 32);
832
833 {
834 CodedInputStream coded_input(&input);
835 coded_input.PushLimit(sizeof(buffer_));
836 coded_input.SetTotalBytesLimit(16, 16);
837
838 string str;
839 EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes)));
840 // Note: this check depends on string class implementation. It
841 // expects that string will allocate less than strlen(kRawBytes)
842 // for an empty string.
843 EXPECT_GT(strlen(kRawBytes), str.capacity());
844 }
845 }
846
TEST_F(CodedStreamTest,ReadStringNoReservationSizeIsOverTheClosestLimit_LocalLimitIsCloser)847 TEST_F(CodedStreamTest,
848 ReadStringNoReservationSizeIsOverTheClosestLimit_LocalLimitIsCloser) {
849 memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
850 // Buffer size in the input must be smaller than sizeof(kRawBytes),
851 // otherwise check against capacity will fail as ReadStringInline()
852 // will handle the reading and will reserve the memory as needed.
853 ArrayInputStream input(buffer_, sizeof(buffer_), 32);
854
855 {
856 CodedInputStream coded_input(&input);
857 coded_input.PushLimit(16);
858 coded_input.SetTotalBytesLimit(sizeof(buffer_), sizeof(buffer_));
859 EXPECT_EQ(sizeof(buffer_), coded_input.BytesUntilTotalBytesLimit());
860
861 string str;
862 EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes)));
863 // Note: this check depends on string class implementation. It
864 // expects that string will allocate less than strlen(kRawBytes)
865 // for an empty string.
866 EXPECT_GT(strlen(kRawBytes), str.capacity());
867 }
868 }
869
870
871 // -------------------------------------------------------------------
872 // Skip
873
874 const char kSkipTestBytes[] =
875 "<Before skipping><To be skipped><After skipping>";
876
TEST_1D(CodedStreamTest,SkipInput,kBlockSizes)877 TEST_1D(CodedStreamTest, SkipInput, kBlockSizes) {
878 memcpy(buffer_, kSkipTestBytes, sizeof(kSkipTestBytes));
879 ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
880
881 {
882 CodedInputStream coded_input(&input);
883
884 string str;
885 EXPECT_TRUE(coded_input.ReadString(&str, strlen("<Before skipping>")));
886 EXPECT_EQ("<Before skipping>", str);
887 EXPECT_TRUE(coded_input.Skip(strlen("<To be skipped>")));
888 EXPECT_TRUE(coded_input.ReadString(&str, strlen("<After skipping>")));
889 EXPECT_EQ("<After skipping>", str);
890 }
891
892 EXPECT_EQ(strlen(kSkipTestBytes), input.ByteCount());
893 }
894
895 // -------------------------------------------------------------------
896 // GetDirectBufferPointer
897
TEST_F(CodedStreamTest,GetDirectBufferPointerInput)898 TEST_F(CodedStreamTest, GetDirectBufferPointerInput) {
899 ArrayInputStream input(buffer_, sizeof(buffer_), 8);
900 CodedInputStream coded_input(&input);
901
902 const void* ptr;
903 int size;
904
905 EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size));
906 EXPECT_EQ(buffer_, ptr);
907 EXPECT_EQ(8, size);
908
909 // Peeking again should return the same pointer.
910 EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size));
911 EXPECT_EQ(buffer_, ptr);
912 EXPECT_EQ(8, size);
913
914 // Skip forward in the same buffer then peek again.
915 EXPECT_TRUE(coded_input.Skip(3));
916 EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size));
917 EXPECT_EQ(buffer_ + 3, ptr);
918 EXPECT_EQ(5, size);
919
920 // Skip to end of buffer and peek -- should get next buffer.
921 EXPECT_TRUE(coded_input.Skip(5));
922 EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size));
923 EXPECT_EQ(buffer_ + 8, ptr);
924 EXPECT_EQ(8, size);
925 }
926
TEST_F(CodedStreamTest,GetDirectBufferPointerInlineInput)927 TEST_F(CodedStreamTest, GetDirectBufferPointerInlineInput) {
928 ArrayInputStream input(buffer_, sizeof(buffer_), 8);
929 CodedInputStream coded_input(&input);
930
931 const void* ptr;
932 int size;
933
934 coded_input.GetDirectBufferPointerInline(&ptr, &size);
935 EXPECT_EQ(buffer_, ptr);
936 EXPECT_EQ(8, size);
937
938 // Peeking again should return the same pointer.
939 coded_input.GetDirectBufferPointerInline(&ptr, &size);
940 EXPECT_EQ(buffer_, ptr);
941 EXPECT_EQ(8, size);
942
943 // Skip forward in the same buffer then peek again.
944 EXPECT_TRUE(coded_input.Skip(3));
945 coded_input.GetDirectBufferPointerInline(&ptr, &size);
946 EXPECT_EQ(buffer_ + 3, ptr);
947 EXPECT_EQ(5, size);
948
949 // Skip to end of buffer and peek -- should return false and provide an empty
950 // buffer. It does not try to Refresh().
951 EXPECT_TRUE(coded_input.Skip(5));
952 coded_input.GetDirectBufferPointerInline(&ptr, &size);
953 EXPECT_EQ(buffer_ + 8, ptr);
954 EXPECT_EQ(0, size);
955 }
956
TEST_F(CodedStreamTest,GetDirectBufferPointerOutput)957 TEST_F(CodedStreamTest, GetDirectBufferPointerOutput) {
958 ArrayOutputStream output(buffer_, sizeof(buffer_), 8);
959 CodedOutputStream coded_output(&output);
960
961 void* ptr;
962 int size;
963
964 EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size));
965 EXPECT_EQ(buffer_, ptr);
966 EXPECT_EQ(8, size);
967
968 // Peeking again should return the same pointer.
969 EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size));
970 EXPECT_EQ(buffer_, ptr);
971 EXPECT_EQ(8, size);
972
973 // Skip forward in the same buffer then peek again.
974 EXPECT_TRUE(coded_output.Skip(3));
975 EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size));
976 EXPECT_EQ(buffer_ + 3, ptr);
977 EXPECT_EQ(5, size);
978
979 // Skip to end of buffer and peek -- should get next buffer.
980 EXPECT_TRUE(coded_output.Skip(5));
981 EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size));
982 EXPECT_EQ(buffer_ + 8, ptr);
983 EXPECT_EQ(8, size);
984
985 // Skip over multiple buffers.
986 EXPECT_TRUE(coded_output.Skip(22));
987 EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size));
988 EXPECT_EQ(buffer_ + 30, ptr);
989 EXPECT_EQ(2, size);
990 }
991
992 // -------------------------------------------------------------------
993 // Limits
994
TEST_1D(CodedStreamTest,BasicLimit,kBlockSizes)995 TEST_1D(CodedStreamTest, BasicLimit, kBlockSizes) {
996 ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
997
998 {
999 CodedInputStream coded_input(&input);
1000
1001 EXPECT_EQ(-1, coded_input.BytesUntilLimit());
1002 CodedInputStream::Limit limit = coded_input.PushLimit(8);
1003
1004 // Read until we hit the limit.
1005 uint32 value;
1006 EXPECT_EQ(8, coded_input.BytesUntilLimit());
1007 EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
1008 EXPECT_EQ(4, coded_input.BytesUntilLimit());
1009 EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
1010 EXPECT_EQ(0, coded_input.BytesUntilLimit());
1011 EXPECT_FALSE(coded_input.ReadLittleEndian32(&value));
1012 EXPECT_EQ(0, coded_input.BytesUntilLimit());
1013
1014 coded_input.PopLimit(limit);
1015
1016 EXPECT_EQ(-1, coded_input.BytesUntilLimit());
1017 EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
1018 }
1019
1020 EXPECT_EQ(12, input.ByteCount());
1021 }
1022
1023 // Test what happens when we push two limits where the second (top) one is
1024 // shorter.
TEST_1D(CodedStreamTest,SmallLimitOnTopOfBigLimit,kBlockSizes)1025 TEST_1D(CodedStreamTest, SmallLimitOnTopOfBigLimit, kBlockSizes) {
1026 ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
1027
1028 {
1029 CodedInputStream coded_input(&input);
1030
1031 EXPECT_EQ(-1, coded_input.BytesUntilLimit());
1032 CodedInputStream::Limit limit1 = coded_input.PushLimit(8);
1033 EXPECT_EQ(8, coded_input.BytesUntilLimit());
1034 CodedInputStream::Limit limit2 = coded_input.PushLimit(4);
1035
1036 uint32 value;
1037
1038 // Read until we hit limit2, the top and shortest limit.
1039 EXPECT_EQ(4, coded_input.BytesUntilLimit());
1040 EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
1041 EXPECT_EQ(0, coded_input.BytesUntilLimit());
1042 EXPECT_FALSE(coded_input.ReadLittleEndian32(&value));
1043 EXPECT_EQ(0, coded_input.BytesUntilLimit());
1044
1045 coded_input.PopLimit(limit2);
1046
1047 // Read until we hit limit1.
1048 EXPECT_EQ(4, coded_input.BytesUntilLimit());
1049 EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
1050 EXPECT_EQ(0, coded_input.BytesUntilLimit());
1051 EXPECT_FALSE(coded_input.ReadLittleEndian32(&value));
1052 EXPECT_EQ(0, coded_input.BytesUntilLimit());
1053
1054 coded_input.PopLimit(limit1);
1055
1056 // No more limits.
1057 EXPECT_EQ(-1, coded_input.BytesUntilLimit());
1058 EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
1059 }
1060
1061 EXPECT_EQ(12, input.ByteCount());
1062 }
1063
1064 // Test what happens when we push two limits where the second (top) one is
1065 // longer. In this case, the top limit is shortened to match the previous
1066 // limit.
TEST_1D(CodedStreamTest,BigLimitOnTopOfSmallLimit,kBlockSizes)1067 TEST_1D(CodedStreamTest, BigLimitOnTopOfSmallLimit, kBlockSizes) {
1068 ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
1069
1070 {
1071 CodedInputStream coded_input(&input);
1072
1073 EXPECT_EQ(-1, coded_input.BytesUntilLimit());
1074 CodedInputStream::Limit limit1 = coded_input.PushLimit(4);
1075 EXPECT_EQ(4, coded_input.BytesUntilLimit());
1076 CodedInputStream::Limit limit2 = coded_input.PushLimit(8);
1077
1078 uint32 value;
1079
1080 // Read until we hit limit2. Except, wait! limit1 is shorter, so
1081 // we end up hitting that first, despite having 4 bytes to go on
1082 // limit2.
1083 EXPECT_EQ(4, coded_input.BytesUntilLimit());
1084 EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
1085 EXPECT_EQ(0, coded_input.BytesUntilLimit());
1086 EXPECT_FALSE(coded_input.ReadLittleEndian32(&value));
1087 EXPECT_EQ(0, coded_input.BytesUntilLimit());
1088
1089 coded_input.PopLimit(limit2);
1090
1091 // OK, popped limit2, now limit1 is on top, which we've already hit.
1092 EXPECT_EQ(0, coded_input.BytesUntilLimit());
1093 EXPECT_FALSE(coded_input.ReadLittleEndian32(&value));
1094 EXPECT_EQ(0, coded_input.BytesUntilLimit());
1095
1096 coded_input.PopLimit(limit1);
1097
1098 // No more limits.
1099 EXPECT_EQ(-1, coded_input.BytesUntilLimit());
1100 EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
1101 }
1102
1103 EXPECT_EQ(8, input.ByteCount());
1104 }
1105
TEST_F(CodedStreamTest,ExpectAtEnd)1106 TEST_F(CodedStreamTest, ExpectAtEnd) {
1107 // Test ExpectAtEnd(), which is based on limits.
1108 ArrayInputStream input(buffer_, sizeof(buffer_));
1109 CodedInputStream coded_input(&input);
1110
1111 EXPECT_FALSE(coded_input.ExpectAtEnd());
1112
1113 CodedInputStream::Limit limit = coded_input.PushLimit(4);
1114
1115 uint32 value;
1116 EXPECT_TRUE(coded_input.ReadLittleEndian32(&value));
1117 EXPECT_TRUE(coded_input.ExpectAtEnd());
1118
1119 coded_input.PopLimit(limit);
1120 EXPECT_FALSE(coded_input.ExpectAtEnd());
1121 }
1122
TEST_F(CodedStreamTest,NegativeLimit)1123 TEST_F(CodedStreamTest, NegativeLimit) {
1124 // Check what happens when we push a negative limit.
1125 ArrayInputStream input(buffer_, sizeof(buffer_));
1126 CodedInputStream coded_input(&input);
1127
1128 CodedInputStream::Limit limit = coded_input.PushLimit(-1234);
1129 // BytesUntilLimit() returns -1 to mean "no limit", which actually means
1130 // "the limit is INT_MAX relative to the beginning of the stream".
1131 EXPECT_EQ(-1, coded_input.BytesUntilLimit());
1132 coded_input.PopLimit(limit);
1133 }
1134
TEST_F(CodedStreamTest,NegativeLimitAfterReading)1135 TEST_F(CodedStreamTest, NegativeLimitAfterReading) {
1136 // Check what happens when we push a negative limit.
1137 ArrayInputStream input(buffer_, sizeof(buffer_));
1138 CodedInputStream coded_input(&input);
1139 ASSERT_TRUE(coded_input.Skip(128));
1140
1141 CodedInputStream::Limit limit = coded_input.PushLimit(-64);
1142 // BytesUntilLimit() returns -1 to mean "no limit", which actually means
1143 // "the limit is INT_MAX relative to the beginning of the stream".
1144 EXPECT_EQ(-1, coded_input.BytesUntilLimit());
1145 coded_input.PopLimit(limit);
1146 }
1147
TEST_F(CodedStreamTest,OverflowLimit)1148 TEST_F(CodedStreamTest, OverflowLimit) {
1149 // Check what happens when we push a limit large enough that its absolute
1150 // position is more than 2GB into the stream.
1151 ArrayInputStream input(buffer_, sizeof(buffer_));
1152 CodedInputStream coded_input(&input);
1153 ASSERT_TRUE(coded_input.Skip(128));
1154
1155 CodedInputStream::Limit limit = coded_input.PushLimit(INT_MAX);
1156 // BytesUntilLimit() returns -1 to mean "no limit", which actually means
1157 // "the limit is INT_MAX relative to the beginning of the stream".
1158 EXPECT_EQ(-1, coded_input.BytesUntilLimit());
1159 coded_input.PopLimit(limit);
1160 }
1161
TEST_F(CodedStreamTest,TotalBytesLimit)1162 TEST_F(CodedStreamTest, TotalBytesLimit) {
1163 ArrayInputStream input(buffer_, sizeof(buffer_));
1164 CodedInputStream coded_input(&input);
1165 coded_input.SetTotalBytesLimit(16, -1);
1166 EXPECT_EQ(16, coded_input.BytesUntilTotalBytesLimit());
1167
1168 string str;
1169 EXPECT_TRUE(coded_input.ReadString(&str, 16));
1170 EXPECT_EQ(0, coded_input.BytesUntilTotalBytesLimit());
1171
1172 vector<string> errors;
1173
1174 {
1175 ScopedMemoryLog error_log;
1176 EXPECT_FALSE(coded_input.ReadString(&str, 1));
1177 errors = error_log.GetMessages(ERROR);
1178 }
1179
1180 ASSERT_EQ(1, errors.size());
1181 EXPECT_PRED_FORMAT2(testing::IsSubstring,
1182 "A protocol message was rejected because it was too big", errors[0]);
1183
1184 coded_input.SetTotalBytesLimit(32, -1);
1185 EXPECT_EQ(16, coded_input.BytesUntilTotalBytesLimit());
1186 EXPECT_TRUE(coded_input.ReadString(&str, 16));
1187 EXPECT_EQ(0, coded_input.BytesUntilTotalBytesLimit());
1188 }
1189
TEST_F(CodedStreamTest,TotalBytesLimitNotValidMessageEnd)1190 TEST_F(CodedStreamTest, TotalBytesLimitNotValidMessageEnd) {
1191 // total_bytes_limit_ is not a valid place for a message to end.
1192
1193 ArrayInputStream input(buffer_, sizeof(buffer_));
1194 CodedInputStream coded_input(&input);
1195
1196 // Set both total_bytes_limit and a regular limit at 16 bytes.
1197 coded_input.SetTotalBytesLimit(16, -1);
1198 CodedInputStream::Limit limit = coded_input.PushLimit(16);
1199
1200 // Read 16 bytes.
1201 string str;
1202 EXPECT_TRUE(coded_input.ReadString(&str, 16));
1203
1204 // Read a tag. Should fail, but report being a valid endpoint since it's
1205 // a regular limit.
1206 EXPECT_EQ(0, coded_input.ReadTag());
1207 EXPECT_TRUE(coded_input.ConsumedEntireMessage());
1208
1209 // Pop the limit.
1210 coded_input.PopLimit(limit);
1211
1212 // Read a tag. Should fail, and report *not* being a valid endpoint, since
1213 // this time we're hitting the total bytes limit.
1214 EXPECT_EQ(0, coded_input.ReadTag());
1215 EXPECT_FALSE(coded_input.ConsumedEntireMessage());
1216 }
1217
1218 // This method is used by the tests below.
1219 // It constructs a CodedInputStream with the given limits and tries to read 2KiB
1220 // of data from it. Then it returns the logged errors and warnings in the given
1221 // vectors.
SetupTotalBytesLimitWarningTest(int total_bytes_limit,int warning_threshold,vector<string> * out_errors,vector<string> * out_warnings)1222 void CodedStreamTest::SetupTotalBytesLimitWarningTest(
1223 int total_bytes_limit, int warning_threshold,
1224 vector<string>* out_errors, vector<string>* out_warnings) {
1225 ArrayInputStream raw_input(buffer_, sizeof(buffer_), 128);
1226
1227 ScopedMemoryLog scoped_log;
1228 {
1229 CodedInputStream input(&raw_input);
1230 input.SetTotalBytesLimit(total_bytes_limit, warning_threshold);
1231 string str;
1232 EXPECT_TRUE(input.ReadString(&str, 2048));
1233 }
1234
1235 *out_errors = scoped_log.GetMessages(ERROR);
1236 *out_warnings = scoped_log.GetMessages(WARNING);
1237 }
1238
TEST_F(CodedStreamTest,TotalBytesLimitWarning)1239 TEST_F(CodedStreamTest, TotalBytesLimitWarning) {
1240 vector<string> errors;
1241 vector<string> warnings;
1242 SetupTotalBytesLimitWarningTest(10240, 1024, &errors, &warnings);
1243
1244 EXPECT_EQ(0, errors.size());
1245
1246 ASSERT_EQ(2, warnings.size());
1247 EXPECT_PRED_FORMAT2(testing::IsSubstring,
1248 "Reading dangerously large protocol message. If the message turns out to "
1249 "be larger than 10240 bytes, parsing will be halted for security reasons.",
1250 warnings[0]);
1251 EXPECT_PRED_FORMAT2(testing::IsSubstring,
1252 "The total number of bytes read was 2048",
1253 warnings[1]);
1254 }
1255
TEST_F(CodedStreamTest,TotalBytesLimitWarningDisabled)1256 TEST_F(CodedStreamTest, TotalBytesLimitWarningDisabled) {
1257 vector<string> errors;
1258 vector<string> warnings;
1259
1260 // Test with -1
1261 SetupTotalBytesLimitWarningTest(10240, -1, &errors, &warnings);
1262 EXPECT_EQ(0, errors.size());
1263 EXPECT_EQ(0, warnings.size());
1264
1265 // Test again with -2, expecting the same result
1266 SetupTotalBytesLimitWarningTest(10240, -2, &errors, &warnings);
1267 EXPECT_EQ(0, errors.size());
1268 EXPECT_EQ(0, warnings.size());
1269 }
1270
1271
TEST_F(CodedStreamTest,RecursionLimit)1272 TEST_F(CodedStreamTest, RecursionLimit) {
1273 ArrayInputStream input(buffer_, sizeof(buffer_));
1274 CodedInputStream coded_input(&input);
1275 coded_input.SetRecursionLimit(4);
1276
1277 // This is way too much testing for a counter.
1278 EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 1
1279 EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 2
1280 EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 3
1281 EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 4
1282 EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 5
1283 EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 6
1284 coded_input.DecrementRecursionDepth(); // 5
1285 EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 6
1286 coded_input.DecrementRecursionDepth(); // 5
1287 coded_input.DecrementRecursionDepth(); // 4
1288 coded_input.DecrementRecursionDepth(); // 3
1289 EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 4
1290 EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 5
1291 coded_input.DecrementRecursionDepth(); // 4
1292 coded_input.DecrementRecursionDepth(); // 3
1293 coded_input.DecrementRecursionDepth(); // 2
1294 coded_input.DecrementRecursionDepth(); // 1
1295 coded_input.DecrementRecursionDepth(); // 0
1296 coded_input.DecrementRecursionDepth(); // 0
1297 coded_input.DecrementRecursionDepth(); // 0
1298 EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 1
1299 EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 2
1300 EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 3
1301 EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 4
1302 EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 5
1303
1304 coded_input.SetRecursionLimit(6);
1305 EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 6
1306 EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 7
1307 }
1308
1309
1310 class ReallyBigInputStream : public ZeroCopyInputStream {
1311 public:
ReallyBigInputStream()1312 ReallyBigInputStream() : backup_amount_(0), buffer_count_(0) {}
~ReallyBigInputStream()1313 ~ReallyBigInputStream() {}
1314
1315 // implements ZeroCopyInputStream ----------------------------------
Next(const void ** data,int * size)1316 bool Next(const void** data, int* size) {
1317 // We only expect BackUp() to be called at the end.
1318 EXPECT_EQ(0, backup_amount_);
1319
1320 switch (buffer_count_++) {
1321 case 0:
1322 *data = buffer_;
1323 *size = sizeof(buffer_);
1324 return true;
1325 case 1:
1326 // Return an enormously large buffer that, when combined with the 1k
1327 // returned already, should overflow the total_bytes_read_ counter in
1328 // CodedInputStream. Note that we'll only read the first 1024 bytes
1329 // of this buffer so it's OK that we have it point at buffer_.
1330 *data = buffer_;
1331 *size = INT_MAX;
1332 return true;
1333 default:
1334 return false;
1335 }
1336 }
1337
BackUp(int count)1338 void BackUp(int count) {
1339 backup_amount_ = count;
1340 }
1341
Skip(int count)1342 bool Skip(int count) { GOOGLE_LOG(FATAL) << "Not implemented."; return false; }
ByteCount() const1343 int64 ByteCount() const { GOOGLE_LOG(FATAL) << "Not implemented."; return 0; }
1344
1345 int backup_amount_;
1346
1347 private:
1348 char buffer_[1024];
1349 int64 buffer_count_;
1350 };
1351
TEST_F(CodedStreamTest,InputOver2G)1352 TEST_F(CodedStreamTest, InputOver2G) {
1353 // CodedInputStream should gracefully handle input over 2G and call
1354 // input.BackUp() with the correct number of bytes on destruction.
1355 ReallyBigInputStream input;
1356
1357 vector<string> errors;
1358
1359 {
1360 ScopedMemoryLog error_log;
1361 CodedInputStream coded_input(&input);
1362 string str;
1363 EXPECT_TRUE(coded_input.ReadString(&str, 512));
1364 EXPECT_TRUE(coded_input.ReadString(&str, 1024));
1365 errors = error_log.GetMessages(ERROR);
1366 }
1367
1368 EXPECT_EQ(INT_MAX - 512, input.backup_amount_);
1369 EXPECT_EQ(0, errors.size());
1370 }
1371
1372 // ===================================================================
1373
1374
1375 } // namespace
1376 } // namespace io
1377 } // namespace protobuf
1378 } // namespace google
1379