A few more cases for binary conformance tests. (#2500)

* A few more cases for binary conformance tests.

* over-encoded varints (encoded in more bytes than are necessary).
* truncated varints (>32 bits for 32-bit types).

* Fixed Python decoding bug with 32-bit varints.

* Fixed 1L -> 1LL for 32-bit platforms.
This commit is contained in:
Joshua Haberman 2017-01-06 16:58:21 -08:00 committed by GitHub
parent 1041710fce
commit ffa71f8007
2 changed files with 35 additions and 12 deletions

View File

@ -109,13 +109,18 @@ string cat(const string& a, const string& b,
// The maximum number of bytes that it takes to encode a 64-bit varint. // The maximum number of bytes that it takes to encode a 64-bit varint.
#define VARINT_MAX_LEN 10 #define VARINT_MAX_LEN 10
size_t vencode64(uint64_t val, char *buf) { size_t vencode64(uint64_t val, int over_encoded_bytes, char *buf) {
if (val == 0) { buf[0] = 0; return 1; } if (val == 0) { buf[0] = 0; return 1; }
size_t i = 0; size_t i = 0;
while (val) { while (val) {
uint8_t byte = val & 0x7fU; uint8_t byte = val & 0x7fU;
val >>= 7; val >>= 7;
if (val) byte |= 0x80U; if (val || over_encoded_bytes) byte |= 0x80U;
buf[i++] = byte;
}
while (over_encoded_bytes--) {
assert(i < 10);
uint8_t byte = over_encoded_bytes ? 0x80 : 0;
buf[i++] = byte; buf[i++] = byte;
} }
return i; return i;
@ -123,7 +128,15 @@ size_t vencode64(uint64_t val, char *buf) {
string varint(uint64_t x) { string varint(uint64_t x) {
char buf[VARINT_MAX_LEN]; char buf[VARINT_MAX_LEN];
size_t len = vencode64(x, buf); size_t len = vencode64(x, 0, buf);
return string(buf, len);
}
// Encodes a varint that is |extra| bytes longer than it needs to be, but still
// valid.
string longvarint(uint64_t x, int extra) {
char buf[VARINT_MAX_LEN];
size_t len = vencode64(x, extra, buf);
return string(buf, len); return string(buf, len);
} }
@ -744,13 +757,23 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
}); });
TestValidDataForType(FieldDescriptor::TYPE_INT32, { TestValidDataForType(FieldDescriptor::TYPE_INT32, {
{varint(12345), "12345"}, {varint(12345), "12345"},
{longvarint(12345, 2), "12345"},
{longvarint(12345, 7), "12345"},
{varint(kInt32Max), std::to_string(kInt32Max)}, {varint(kInt32Max), std::to_string(kInt32Max)},
{varint(kInt32Min), std::to_string(kInt32Min)}, {varint(kInt32Min), std::to_string(kInt32Min)},
{varint(1LL << 33), std::to_string(static_cast<int32>(1LL << 33))},
{varint((1LL << 33) - 1),
std::to_string(static_cast<int32>((1LL << 33) - 1))},
}); });
TestValidDataForType(FieldDescriptor::TYPE_UINT32, { TestValidDataForType(FieldDescriptor::TYPE_UINT32, {
{varint(12345), "12345"}, {varint(12345), "12345"},
{longvarint(12345, 2), "12345"},
{longvarint(12345, 7), "12345"},
{varint(kUint32Max), std::to_string(kUint32Max)}, // UINT32_MAX {varint(kUint32Max), std::to_string(kUint32Max)}, // UINT32_MAX
{varint(0), "0"} {varint(0), "0"},
{varint(1LL << 33), std::to_string(static_cast<uint32>(1LL << 33))},
{varint((1LL << 33) - 1),
std::to_string(static_cast<uint32>((1LL << 33) - 1))},
}); });
TestValidDataForType(FieldDescriptor::TYPE_FIXED64, { TestValidDataForType(FieldDescriptor::TYPE_FIXED64, {
{u64(12345), "12345"}, {u64(12345), "12345"},

View File

@ -131,9 +131,12 @@ def _VarintDecoder(mask, result_type):
return DecodeVarint return DecodeVarint
def _SignedVarintDecoder(mask, result_type): def _SignedVarintDecoder(bits, result_type):
"""Like _VarintDecoder() but decodes signed values.""" """Like _VarintDecoder() but decodes signed values."""
signbit = 1 << (bits - 1)
mask = (1 << bits) - 1
def DecodeVarint(buffer, pos): def DecodeVarint(buffer, pos):
result = 0 result = 0
shift = 0 shift = 0
@ -142,11 +145,8 @@ def _SignedVarintDecoder(mask, result_type):
result |= ((b & 0x7f) << shift) result |= ((b & 0x7f) << shift)
pos += 1 pos += 1
if not (b & 0x80): if not (b & 0x80):
if result > 0x7fffffffffffffff: result &= mask
result -= (1 << 64) result = (result ^ signbit) - signbit
result |= ~mask
else:
result &= mask
result = result_type(result) result = result_type(result)
return (result, pos) return (result, pos)
shift += 7 shift += 7
@ -159,11 +159,11 @@ def _SignedVarintDecoder(mask, result_type):
# (e.g. the C++ implementation) simpler. # (e.g. the C++ implementation) simpler.
_DecodeVarint = _VarintDecoder((1 << 64) - 1, long) _DecodeVarint = _VarintDecoder((1 << 64) - 1, long)
_DecodeSignedVarint = _SignedVarintDecoder((1 << 64) - 1, long) _DecodeSignedVarint = _SignedVarintDecoder(64, long)
# Use these versions for values which must be limited to 32 bits. # Use these versions for values which must be limited to 32 bits.
_DecodeVarint32 = _VarintDecoder((1 << 32) - 1, int) _DecodeVarint32 = _VarintDecoder((1 << 32) - 1, int)
_DecodeSignedVarint32 = _SignedVarintDecoder((1 << 32) - 1, int) _DecodeSignedVarint32 = _SignedVarintDecoder(32, int)
def ReadTag(buffer, pos): def ReadTag(buffer, pos):