OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 #include <gtest/gtest.h> | 51 #include <gtest/gtest.h> |
52 #include <google/protobuf/io/zero_copy_stream_impl.h> | 52 #include <google/protobuf/io/zero_copy_stream_impl.h> |
53 | 53 |
54 | 54 |
55 // This declares an unsigned long long integer literal in a portable way. | 55 // This declares an unsigned long long integer literal in a portable way. |
56 // (The original macro is way too big and ruins my formatting.) | 56 // (The original macro is way too big and ruins my formatting.) |
57 #undef ULL | 57 #undef ULL |
58 #define ULL(x) GOOGLE_ULONGLONG(x) | 58 #define ULL(x) GOOGLE_ULONGLONG(x) |
59 | 59 |
60 namespace google { | 60 namespace google { |
| 61 |
61 namespace protobuf { | 62 namespace protobuf { |
62 namespace io { | 63 namespace io { |
63 namespace { | 64 namespace { |
64 | 65 |
65 // =================================================================== | 66 // =================================================================== |
66 // Data-Driven Test Infrastructure | 67 // Data-Driven Test Infrastructure |
67 | 68 |
68 // TEST_1D and TEST_2D are macros I'd eventually like to see added to | 69 // TEST_1D and TEST_2D are macros I'd eventually like to see added to |
69 // gTest. These macros can be used to declare tests which should be | 70 // gTest. These macros can be used to declare tests which should be |
70 // run multiple times, once for each item in some input array. TEST_1D | 71 // run multiple times, once for each item in some input array. TEST_1D |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 const CaseType2& CASES2##_case) | 128 const CaseType2& CASES2##_case) |
128 | 129 |
129 // =================================================================== | 130 // =================================================================== |
130 | 131 |
131 class CodedStreamTest : public testing::Test { | 132 class CodedStreamTest : public testing::Test { |
132 protected: | 133 protected: |
133 // Helper method used by tests for bytes warning. See implementation comment | 134 // Helper method used by tests for bytes warning. See implementation comment |
134 // for further information. | 135 // for further information. |
135 static void SetupTotalBytesLimitWarningTest( | 136 static void SetupTotalBytesLimitWarningTest( |
136 int total_bytes_limit, int warning_threshold, | 137 int total_bytes_limit, int warning_threshold, |
137 vector<string>* out_errors, vector<string>* out_warnings); | 138 std::vector<string>* out_errors, std::vector<string>* out_warnings); |
138 | 139 |
139 // Buffer used during most of the tests. This assumes tests run sequentially. | 140 // Buffer used during most of the tests. This assumes tests run sequentially. |
140 static const int kBufferSize = 1024 * 64; | 141 static const int kBufferSize = 1024 * 64; |
141 static uint8 buffer_[kBufferSize]; | 142 static uint8 buffer_[kBufferSize]; |
142 }; | 143 }; |
143 | 144 |
144 uint8 CodedStreamTest::buffer_[CodedStreamTest::kBufferSize]; | 145 uint8 CodedStreamTest::buffer_[CodedStreamTest::kBufferSize]; |
145 | 146 |
146 // We test each operation over a variety of block sizes to insure that | 147 // We test each operation over a variety of block sizes to insure that |
147 // we test cases where reads or writes cross buffer boundaries, cases | 148 // we test cases where reads or writes cross buffer boundaries, cases |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 GOOGLE_LOG(FATAL) << "Tests never call this."; | 238 GOOGLE_LOG(FATAL) << "Tests never call this."; |
238 } | 239 } |
239 virtual bool Skip(int count) { | 240 virtual bool Skip(int count) { |
240 GOOGLE_LOG(FATAL) << "Tests never call this."; | 241 GOOGLE_LOG(FATAL) << "Tests never call this."; |
241 return false; | 242 return false; |
242 } | 243 } |
243 virtual int64 ByteCount() const { return 0; } | 244 virtual int64 ByteCount() const { return 0; } |
244 int count_; | 245 int count_; |
245 } in; | 246 } in; |
246 CodedInputStream input(&in); | 247 CodedInputStream input(&in); |
247 input.ReadTag(); | 248 input.ReadTagNoLastTag(); |
248 EXPECT_TRUE(input.ConsumedEntireMessage()); | 249 EXPECT_TRUE(input.ConsumedEntireMessage()); |
249 } | 250 } |
250 | 251 |
251 TEST_1D(CodedStreamTest, ExpectTag, kVarintCases) { | 252 TEST_1D(CodedStreamTest, ExpectTag, kVarintCases) { |
252 // Leave one byte at the beginning of the buffer so we can read it | 253 // Leave one byte at the beginning of the buffer so we can read it |
253 // to force the first buffer to be loaded. | 254 // to force the first buffer to be loaded. |
254 buffer_[0] = '\0'; | 255 buffer_[0] = '\0'; |
255 memcpy(buffer_ + 1, kVarintCases_case.bytes, kVarintCases_case.size); | 256 memcpy(buffer_ + 1, kVarintCases_case.bytes, kVarintCases_case.size); |
256 ArrayInputStream input(buffer_, sizeof(buffer_)); | 257 ArrayInputStream input(buffer_, sizeof(buffer_)); |
257 | 258 |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 TEST_2D(CodedStreamTest, ReadVarint32Error, kVarintErrorCases, kBlockSizes) { | 439 TEST_2D(CodedStreamTest, ReadVarint32Error, kVarintErrorCases, kBlockSizes) { |
439 memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size); | 440 memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size); |
440 ArrayInputStream input(buffer_, kVarintErrorCases_case.size, | 441 ArrayInputStream input(buffer_, kVarintErrorCases_case.size, |
441 kBlockSizes_case); | 442 kBlockSizes_case); |
442 CodedInputStream coded_input(&input); | 443 CodedInputStream coded_input(&input); |
443 | 444 |
444 uint32 value; | 445 uint32 value; |
445 EXPECT_EQ(kVarintErrorCases_case.can_parse, coded_input.ReadVarint32(&value)); | 446 EXPECT_EQ(kVarintErrorCases_case.can_parse, coded_input.ReadVarint32(&value)); |
446 } | 447 } |
447 | 448 |
| 449 TEST_2D(CodedStreamTest, ReadVarint32Error_LeavesValueInInitializedState, |
| 450 kVarintErrorCases, kBlockSizes) { |
| 451 memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size); |
| 452 ArrayInputStream input(buffer_, kVarintErrorCases_case.size, |
| 453 kBlockSizes_case); |
| 454 CodedInputStream coded_input(&input); |
| 455 |
| 456 uint32 value = 0; |
| 457 EXPECT_EQ(kVarintErrorCases_case.can_parse, coded_input.ReadVarint32(&value)); |
| 458 // While the specific value following a failure is not critical, we do want to |
| 459 // ensure that it doesn't get set to an uninitialized value. (This check fails |
| 460 // in MSAN mode if value has been set to an uninitialized value.) |
| 461 EXPECT_EQ(value, value); |
| 462 } |
| 463 |
448 TEST_2D(CodedStreamTest, ReadVarint64Error, kVarintErrorCases, kBlockSizes) { | 464 TEST_2D(CodedStreamTest, ReadVarint64Error, kVarintErrorCases, kBlockSizes) { |
449 memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size); | 465 memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size); |
450 ArrayInputStream input(buffer_, kVarintErrorCases_case.size, | 466 ArrayInputStream input(buffer_, kVarintErrorCases_case.size, |
451 kBlockSizes_case); | 467 kBlockSizes_case); |
452 CodedInputStream coded_input(&input); | 468 CodedInputStream coded_input(&input); |
453 | 469 |
454 uint64 value; | 470 uint64 value; |
455 EXPECT_EQ(kVarintErrorCases_case.can_parse, coded_input.ReadVarint64(&value)); | 471 EXPECT_EQ(kVarintErrorCases_case.can_parse, coded_input.ReadVarint64(&value)); |
456 } | 472 } |
457 | 473 |
| 474 TEST_2D(CodedStreamTest, ReadVarint64Error_LeavesValueInInitializedState, |
| 475 kVarintErrorCases, kBlockSizes) { |
| 476 memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size); |
| 477 ArrayInputStream input(buffer_, kVarintErrorCases_case.size, |
| 478 kBlockSizes_case); |
| 479 CodedInputStream coded_input(&input); |
| 480 |
| 481 uint64 value = 0; |
| 482 EXPECT_EQ(kVarintErrorCases_case.can_parse, coded_input.ReadVarint64(&value)); |
| 483 // While the specific value following a failure is not critical, we do want to |
| 484 // ensure that it doesn't get set to an uninitialized value. (This check fails |
| 485 // in MSAN mode if value has been set to an uninitialized value.) |
| 486 EXPECT_EQ(value, value); |
| 487 } |
| 488 |
458 // ------------------------------------------------------------------- | 489 // ------------------------------------------------------------------- |
459 // VarintSize | 490 // VarintSize |
460 | 491 |
461 struct VarintSizeCase { | 492 struct VarintSizeCase { |
462 uint64 value; | 493 uint64 value; |
463 int size; | 494 int size; |
464 }; | 495 }; |
465 | 496 |
466 inline std::ostream& operator<<(std::ostream& os, const VarintSizeCase& c) { | 497 inline std::ostream& operator<<(std::ostream& os, const VarintSizeCase& c) { |
467 return os << c.value; | 498 return os << c.value; |
(...skipping 19 matching lines...) Expand all Loading... |
487 EXPECT_EQ(kVarintSizeCases_case.size, | 518 EXPECT_EQ(kVarintSizeCases_case.size, |
488 CodedOutputStream::VarintSize32( | 519 CodedOutputStream::VarintSize32( |
489 static_cast<uint32>(kVarintSizeCases_case.value))); | 520 static_cast<uint32>(kVarintSizeCases_case.value))); |
490 } | 521 } |
491 | 522 |
492 TEST_1D(CodedStreamTest, VarintSize64, kVarintSizeCases) { | 523 TEST_1D(CodedStreamTest, VarintSize64, kVarintSizeCases) { |
493 EXPECT_EQ(kVarintSizeCases_case.size, | 524 EXPECT_EQ(kVarintSizeCases_case.size, |
494 CodedOutputStream::VarintSize64(kVarintSizeCases_case.value)); | 525 CodedOutputStream::VarintSize64(kVarintSizeCases_case.value)); |
495 } | 526 } |
496 | 527 |
| 528 TEST_F(CodedStreamTest, VarintSize32PowersOfTwo) { |
| 529 int expected = 1; |
| 530 for (int i = 1; i < 32; i++) { |
| 531 if (i % 7 == 0) { |
| 532 expected += 1; |
| 533 } |
| 534 EXPECT_EQ(expected, |
| 535 CodedOutputStream::VarintSize32(static_cast<uint32>(0x1u << i))); |
| 536 } |
| 537 } |
| 538 |
| 539 TEST_F(CodedStreamTest, VarintSize64PowersOfTwo) { |
| 540 int expected = 1; |
| 541 for (int i = 1; i < 64; i++) { |
| 542 if (i % 7 == 0) { |
| 543 expected += 1; |
| 544 } |
| 545 EXPECT_EQ(expected, CodedOutputStream::VarintSize64( |
| 546 static_cast<uint64>(0x1ull << i))); |
| 547 } |
| 548 } |
| 549 |
497 // ------------------------------------------------------------------- | 550 // ------------------------------------------------------------------- |
498 // Fixed-size int tests | 551 // Fixed-size int tests |
499 | 552 |
500 struct Fixed32Case { | 553 struct Fixed32Case { |
501 uint8 bytes[sizeof(uint32)]; // Encoded bytes. | 554 uint8 bytes[sizeof(uint32)]; // Encoded bytes. |
502 uint32 value; // Parsed value. | 555 uint32 value; // Parsed value. |
503 }; | 556 }; |
504 | 557 |
505 struct Fixed64Case { | 558 struct Fixed64Case { |
506 uint8 bytes[sizeof(uint64)]; // Encoded bytes. | 559 uint8 bytes[sizeof(uint64)]; // Encoded bytes. |
(...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1169 TEST_F(CodedStreamTest, TotalBytesLimit) { | 1222 TEST_F(CodedStreamTest, TotalBytesLimit) { |
1170 ArrayInputStream input(buffer_, sizeof(buffer_)); | 1223 ArrayInputStream input(buffer_, sizeof(buffer_)); |
1171 CodedInputStream coded_input(&input); | 1224 CodedInputStream coded_input(&input); |
1172 coded_input.SetTotalBytesLimit(16, -1); | 1225 coded_input.SetTotalBytesLimit(16, -1); |
1173 EXPECT_EQ(16, coded_input.BytesUntilTotalBytesLimit()); | 1226 EXPECT_EQ(16, coded_input.BytesUntilTotalBytesLimit()); |
1174 | 1227 |
1175 string str; | 1228 string str; |
1176 EXPECT_TRUE(coded_input.ReadString(&str, 16)); | 1229 EXPECT_TRUE(coded_input.ReadString(&str, 16)); |
1177 EXPECT_EQ(0, coded_input.BytesUntilTotalBytesLimit()); | 1230 EXPECT_EQ(0, coded_input.BytesUntilTotalBytesLimit()); |
1178 | 1231 |
1179 vector<string> errors; | 1232 std::vector<string> errors; |
1180 | 1233 |
1181 { | 1234 { |
1182 ScopedMemoryLog error_log; | 1235 ScopedMemoryLog error_log; |
1183 EXPECT_FALSE(coded_input.ReadString(&str, 1)); | 1236 EXPECT_FALSE(coded_input.ReadString(&str, 1)); |
1184 errors = error_log.GetMessages(ERROR); | 1237 errors = error_log.GetMessages(ERROR); |
1185 } | 1238 } |
1186 | 1239 |
1187 ASSERT_EQ(1, errors.size()); | 1240 ASSERT_EQ(1, errors.size()); |
1188 EXPECT_PRED_FORMAT2(testing::IsSubstring, | 1241 EXPECT_PRED_FORMAT2(testing::IsSubstring, |
1189 "A protocol message was rejected because it was too big", errors[0]); | 1242 "A protocol message was rejected because it was too big", errors[0]); |
(...skipping 13 matching lines...) Expand all Loading... |
1203 // Set both total_bytes_limit and a regular limit at 16 bytes. | 1256 // Set both total_bytes_limit and a regular limit at 16 bytes. |
1204 coded_input.SetTotalBytesLimit(16, -1); | 1257 coded_input.SetTotalBytesLimit(16, -1); |
1205 CodedInputStream::Limit limit = coded_input.PushLimit(16); | 1258 CodedInputStream::Limit limit = coded_input.PushLimit(16); |
1206 | 1259 |
1207 // Read 16 bytes. | 1260 // Read 16 bytes. |
1208 string str; | 1261 string str; |
1209 EXPECT_TRUE(coded_input.ReadString(&str, 16)); | 1262 EXPECT_TRUE(coded_input.ReadString(&str, 16)); |
1210 | 1263 |
1211 // Read a tag. Should fail, but report being a valid endpoint since it's | 1264 // Read a tag. Should fail, but report being a valid endpoint since it's |
1212 // a regular limit. | 1265 // a regular limit. |
1213 EXPECT_EQ(0, coded_input.ReadTag()); | 1266 EXPECT_EQ(0, coded_input.ReadTagNoLastTag()); |
1214 EXPECT_TRUE(coded_input.ConsumedEntireMessage()); | 1267 EXPECT_TRUE(coded_input.ConsumedEntireMessage()); |
1215 | 1268 |
1216 // Pop the limit. | 1269 // Pop the limit. |
1217 coded_input.PopLimit(limit); | 1270 coded_input.PopLimit(limit); |
1218 | 1271 |
1219 // Read a tag. Should fail, and report *not* being a valid endpoint, since | 1272 // Read a tag. Should fail, and report *not* being a valid endpoint, since |
1220 // this time we're hitting the total bytes limit. | 1273 // this time we're hitting the total bytes limit. |
1221 EXPECT_EQ(0, coded_input.ReadTag()); | 1274 EXPECT_EQ(0, coded_input.ReadTagNoLastTag()); |
1222 EXPECT_FALSE(coded_input.ConsumedEntireMessage()); | 1275 EXPECT_FALSE(coded_input.ConsumedEntireMessage()); |
1223 } | 1276 } |
1224 | 1277 |
1225 // This method is used by the tests below. | 1278 // This method is used by the tests below. |
1226 // It constructs a CodedInputStream with the given limits and tries to read 2KiB | 1279 // It constructs a CodedInputStream with the given limits and tries to read 2KiB |
1227 // of data from it. Then it returns the logged errors and warnings in the given | 1280 // of data from it. Then it returns the logged errors and warnings in the given |
1228 // vectors. | 1281 // vectors. |
1229 void CodedStreamTest::SetupTotalBytesLimitWarningTest( | 1282 void CodedStreamTest::SetupTotalBytesLimitWarningTest( |
1230 int total_bytes_limit, int warning_threshold, | 1283 int total_bytes_limit, int warning_threshold, |
1231 vector<string>* out_errors, vector<string>* out_warnings) { | 1284 std::vector<string>* out_errors, std::vector<string>* out_warnings) { |
1232 ArrayInputStream raw_input(buffer_, sizeof(buffer_), 128); | 1285 ArrayInputStream raw_input(buffer_, sizeof(buffer_), 128); |
1233 | 1286 |
1234 ScopedMemoryLog scoped_log; | 1287 ScopedMemoryLog scoped_log; |
1235 { | 1288 { |
1236 CodedInputStream input(&raw_input); | 1289 CodedInputStream input(&raw_input); |
1237 input.SetTotalBytesLimit(total_bytes_limit, warning_threshold); | 1290 input.SetTotalBytesLimit(total_bytes_limit, warning_threshold); |
1238 string str; | 1291 string str; |
1239 EXPECT_TRUE(input.ReadString(&str, 2048)); | 1292 EXPECT_TRUE(input.ReadString(&str, 2048)); |
1240 } | 1293 } |
1241 | 1294 |
1242 *out_errors = scoped_log.GetMessages(ERROR); | 1295 *out_errors = scoped_log.GetMessages(ERROR); |
1243 *out_warnings = scoped_log.GetMessages(WARNING); | 1296 *out_warnings = scoped_log.GetMessages(WARNING); |
1244 } | 1297 } |
1245 | 1298 |
1246 TEST_F(CodedStreamTest, TotalBytesLimitWarning) { | 1299 TEST_F(CodedStreamTest, TotalBytesLimitWarning) { |
1247 vector<string> errors; | 1300 std::vector<string> errors; |
1248 vector<string> warnings; | 1301 std::vector<string> warnings; |
1249 SetupTotalBytesLimitWarningTest(10240, 1024, &errors, &warnings); | 1302 SetupTotalBytesLimitWarningTest(10240, 1024, &errors, &warnings); |
1250 | 1303 |
1251 EXPECT_EQ(0, errors.size()); | 1304 EXPECT_EQ(0, errors.size()); |
1252 | 1305 |
1253 ASSERT_EQ(2, warnings.size()); | 1306 EXPECT_EQ(1, warnings.size()); |
1254 EXPECT_PRED_FORMAT2(testing::IsSubstring, | |
1255 "Reading dangerously large protocol message. If the message turns out to " | |
1256 "be larger than 10240 bytes, parsing will be halted for security reasons.", | |
1257 warnings[0]); | |
1258 EXPECT_PRED_FORMAT2(testing::IsSubstring, | 1307 EXPECT_PRED_FORMAT2(testing::IsSubstring, |
1259 "The total number of bytes read was 2048", | 1308 "The total number of bytes read was 2048", |
1260 warnings[1]); | 1309 warnings[0]); |
1261 } | 1310 } |
1262 | 1311 |
1263 TEST_F(CodedStreamTest, TotalBytesLimitWarningDisabled) { | 1312 TEST_F(CodedStreamTest, TotalBytesLimitWarningDisabled) { |
1264 vector<string> errors; | 1313 std::vector<string> errors; |
1265 vector<string> warnings; | 1314 std::vector<string> warnings; |
1266 | 1315 |
1267 // Test with -1 | 1316 // Test with -1 |
1268 SetupTotalBytesLimitWarningTest(10240, -1, &errors, &warnings); | 1317 SetupTotalBytesLimitWarningTest(10240, -1, &errors, &warnings); |
1269 EXPECT_EQ(0, errors.size()); | 1318 EXPECT_EQ(0, errors.size()); |
1270 EXPECT_EQ(0, warnings.size()); | 1319 EXPECT_EQ(0, warnings.size()); |
1271 | 1320 |
1272 // Test again with -2, expecting the same result | 1321 // Test again with -2, expecting the same result |
1273 SetupTotalBytesLimitWarningTest(10240, -2, &errors, &warnings); | 1322 SetupTotalBytesLimitWarningTest(10240, -2, &errors, &warnings); |
1274 EXPECT_EQ(0, errors.size()); | 1323 EXPECT_EQ(0, errors.size()); |
1275 EXPECT_EQ(0, warnings.size()); | 1324 EXPECT_EQ(0, warnings.size()); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1354 private: | 1403 private: |
1355 char buffer_[1024]; | 1404 char buffer_[1024]; |
1356 int64 buffer_count_; | 1405 int64 buffer_count_; |
1357 }; | 1406 }; |
1358 | 1407 |
1359 TEST_F(CodedStreamTest, InputOver2G) { | 1408 TEST_F(CodedStreamTest, InputOver2G) { |
1360 // CodedInputStream should gracefully handle input over 2G and call | 1409 // CodedInputStream should gracefully handle input over 2G and call |
1361 // input.BackUp() with the correct number of bytes on destruction. | 1410 // input.BackUp() with the correct number of bytes on destruction. |
1362 ReallyBigInputStream input; | 1411 ReallyBigInputStream input; |
1363 | 1412 |
1364 vector<string> errors; | 1413 std::vector<string> errors; |
1365 | 1414 |
1366 { | 1415 { |
1367 ScopedMemoryLog error_log; | 1416 ScopedMemoryLog error_log; |
1368 CodedInputStream coded_input(&input); | 1417 CodedInputStream coded_input(&input); |
1369 string str; | 1418 string str; |
1370 EXPECT_TRUE(coded_input.ReadString(&str, 512)); | 1419 EXPECT_TRUE(coded_input.ReadString(&str, 512)); |
1371 EXPECT_TRUE(coded_input.ReadString(&str, 1024)); | 1420 EXPECT_TRUE(coded_input.ReadString(&str, 1024)); |
1372 errors = error_log.GetMessages(ERROR); | 1421 errors = error_log.GetMessages(ERROR); |
1373 } | 1422 } |
1374 | 1423 |
1375 EXPECT_EQ(INT_MAX - 512, input.backup_amount_); | 1424 EXPECT_EQ(INT_MAX - 512, input.backup_amount_); |
1376 EXPECT_EQ(0, errors.size()); | 1425 EXPECT_EQ(0, errors.size()); |
1377 } | 1426 } |
1378 | 1427 |
1379 // =================================================================== | 1428 // =================================================================== |
1380 | 1429 |
1381 | 1430 |
1382 } // namespace | 1431 } // namespace |
1383 } // namespace io | 1432 } // namespace io |
1384 } // namespace protobuf | 1433 } // namespace protobuf |
1385 } // namespace google | 1434 } // namespace google |
OLD | NEW |