| // Copyright 2008 Google Inc. |
| // Author: Lincoln Smith |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include <config.h> |
| #include "varint_bigendian.h" |
| #include <stdlib.h> // rand, srand |
| #include <string.h> // strlen |
| #include <string> |
| #include <vector> |
| #include "testing.h" |
| |
| namespace open_vcdiff { |
| namespace { |
| |
| class VarintBETestCommon : public testing::Test { |
| protected: |
| typedef std::string string; |
| |
| VarintBETestCommon() |
| : varint_buf_(VarintBE<int64_t>::kMaxBytes), |
| verify_encoded_byte_index_(0), |
| verify_expected_length_(0), |
| parse_data_ptr_(parse_data_all_FFs) { |
| } |
| |
| virtual ~VarintBETestCommon() { } |
| |
| void ExpectEncodedByte(char expected_byte) { |
| EXPECT_EQ(expected_byte, varint_buf_[verify_encoded_byte_index_]); |
| EXPECT_EQ(expected_byte, s_[verify_encoded_byte_index_]); |
| ++verify_encoded_byte_index_; |
| } |
| |
| static const char parse_data_all_FFs[]; |
| static const char parse_data_CADA1[]; |
| |
| std::vector<char> varint_buf_; |
| string s_; |
| int verify_encoded_byte_index_; |
| int verify_expected_length_; |
| const char* parse_data_ptr_; |
| }; |
| |
| template <typename SignedIntegerType> |
| class VarintBETestTemplate : public VarintBETestCommon { |
| protected: |
| VarintBETestTemplate() { } |
| |
| virtual ~VarintBETestTemplate() { } |
| |
| typedef SignedIntegerType SignedIntType; |
| typedef VarintBE<SignedIntegerType> VarintType; |
| |
| void StartEncodingTest(SignedIntegerType v, int expected_length) { |
| verify_expected_length_ = expected_length; |
| EXPECT_EQ(expected_length, VarintType::Length(v)); |
| EXPECT_EQ(expected_length, VarintType::Encode(v, &varint_buf_[0])); |
| VarintType::AppendToString(v, &s_); |
| EXPECT_EQ(static_cast<size_t>(expected_length), s_.length()); |
| } |
| |
| void TestEncodeInvalid(SignedIntegerType v) { |
| EXPECT_DEATH(VarintType::Length(v), "v >= 0"); |
| EXPECT_DEATH(VarintType::Encode(v, &varint_buf_[0]), "v >= 0"); |
| EXPECT_DEATH(VarintType::AppendToString(v, &s_), ">= 0"); |
| } |
| |
| // Need one function for each test type that will be applied to |
| // multiple classes |
| void TemplateTestDISABLED_EncodeNegative(); |
| void TemplateTestEncodeZero(); |
| void TemplateTestEncodeEightBits(); |
| void TemplateTestEncodeCADAD1A(); |
| void TemplateTestEncode32BitMaxInt(); |
| void TemplateTestEncodeDoesNotOverwriteExistingString(); |
| void TemplateTestParseNullPointer(); |
| void TemplateTestEndPointerPrecedesBeginning(); |
| void TemplateTestParseVarintTooLong(); |
| void TemplateTestParseZero(); |
| void TemplateTestParseCADA1(); |
| void TemplateTestParseEmpty(); |
| void TemplateTestParse123456789(); |
| void TemplateTestDecode31Bits(); |
| void TemplateTestEncodeDecodeRandom(); |
| void TemplateTestContinuationBytesPastEndOfInput(); |
| }; |
| |
| typedef VarintBETestTemplate<int32_t> VarintBEInt32Test; |
| typedef VarintBETestTemplate<int64_t> VarintBEInt64Test; |
| |
| #ifdef GTEST_HAS_DEATH_TEST |
| // These synonyms are needed for the tests that use ASSERT_DEATH |
| typedef VarintBEInt32Test VarintBEInt32DeathTest; |
| typedef VarintBEInt64Test VarintBEInt64DeathTest; |
| #endif // GTEST_HAS_DEATH_TEST |
| |
| const char VarintBETestCommon::parse_data_all_FFs[] = |
| { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
| |
| const char VarintBETestCommon::parse_data_CADA1[] = |
| { 0xCA, 0xDA, 0x01 }; |
| |
| // A macro to allow defining tests once and having them run against |
| // both VarintBE<int32_t> and VarintBE<int64_t>. |
| // |
| #define TEMPLATE_TEST_F(TEST_TYPE, TEST_NAME) \ |
| TEST_F(VarintBEInt32##TEST_TYPE, TEST_NAME) { \ |
| TemplateTest##TEST_NAME(); \ |
| } \ |
| TEST_F(VarintBEInt64##TEST_TYPE, TEST_NAME) { \ |
| TemplateTest##TEST_NAME(); \ |
| } \ |
| template <class CacheType> \ |
| void VarintBETestTemplate<CacheType>::TemplateTest##TEST_NAME() |
| |
| // Encoding tests: Length(), Encode(), AppendToString(), AppendToBuffer() |
| |
| #ifdef GTEST_HAS_DEATH_TEST |
| // This test hangs for non-debug build (DeathTest threading problem) |
| TEMPLATE_TEST_F(DeathTest, DISABLED_EncodeNegative) { |
| TestEncodeInvalid(-1); |
| } |
| #endif // GTEST_HAS_DEATH_TEST |
| |
| TEMPLATE_TEST_F(Test, EncodeZero) { |
| StartEncodingTest(/* value */ 0x00, /* expected length */ 1); |
| ExpectEncodedByte(0x00); |
| EXPECT_EQ(verify_expected_length_, verify_encoded_byte_index_); |
| } |
| |
| TEMPLATE_TEST_F(Test, EncodeEightBits) { |
| StartEncodingTest(/* value */ 0xFF, /* expected length */ 2); |
| ExpectEncodedByte(0x81); |
| ExpectEncodedByte(0x7F); |
| EXPECT_EQ(verify_expected_length_, verify_encoded_byte_index_); |
| } |
| |
| TEMPLATE_TEST_F(Test, EncodeCADAD1A) { |
| StartEncodingTest(/* value */ 0x0CADAD1A, /* expected length */ 4); |
| ExpectEncodedByte(0xE5); |
| ExpectEncodedByte(0xB6); |
| ExpectEncodedByte(0xDA); |
| ExpectEncodedByte(0x1A); |
| EXPECT_EQ(verify_expected_length_, verify_encoded_byte_index_); |
| } |
| |
| TEMPLATE_TEST_F(Test, Encode32BitMaxInt) { |
| StartEncodingTest(/* value */ 0x7FFFFFFF, /* expected length */ 5); |
| ExpectEncodedByte(0x87); |
| ExpectEncodedByte(0xFF); |
| ExpectEncodedByte(0xFF); |
| ExpectEncodedByte(0xFF); |
| ExpectEncodedByte(0x7F); |
| EXPECT_EQ(verify_expected_length_, verify_encoded_byte_index_); |
| } |
| |
| #ifdef GTEST_HAS_DEATH_TEST |
| // This test hangs for non-debug build (DeathTest threading problem) |
| TEST_F(VarintBEInt32DeathTest, DISABLED_Encode32BitsTooBig) { |
| TestEncodeInvalid(0x80000000); |
| } |
| #endif // GTEST_HAS_DEATH_TEST |
| |
| TEST_F(VarintBEInt64Test, Encode32Bits) { |
| StartEncodingTest(/* value */ 0x80000000, /* expected length */ 5); |
| ExpectEncodedByte(0x88); |
| ExpectEncodedByte(0x80); |
| ExpectEncodedByte(0x80); |
| ExpectEncodedByte(0x80); |
| ExpectEncodedByte(0x00); |
| EXPECT_EQ(verify_expected_length_, verify_encoded_byte_index_); |
| } |
| |
| TEST_F(VarintBEInt64Test, Encode63Bits) { |
| StartEncodingTest(/* value */ 0x7FFFFFFFFFFFFFFFULL, /* expected length */ 9); |
| ExpectEncodedByte(0xFF); |
| ExpectEncodedByte(0xFF); |
| ExpectEncodedByte(0xFF); |
| ExpectEncodedByte(0xFF); |
| ExpectEncodedByte(0xFF); |
| ExpectEncodedByte(0xFF); |
| ExpectEncodedByte(0xFF); |
| ExpectEncodedByte(0xFF); |
| ExpectEncodedByte(0x7F); |
| EXPECT_EQ(verify_expected_length_, verify_encoded_byte_index_); |
| } |
| |
| #ifdef GTEST_HAS_DEATH_TEST |
| // This test hangs for non-debug build (DeathTest threading problem) |
| TEST_F(VarintBEInt64DeathTest, DISABLED_Encode64BitsTooBig) { |
| TestEncodeInvalid(0x8000000000000000ULL); |
| } |
| #endif // GTEST_HAS_DEATH_TEST |
| |
| TEMPLATE_TEST_F(Test, EncodeDoesNotOverwriteExistingString) { |
| s_.append("Test"); |
| VarintType::AppendToString('1', &s_); |
| EXPECT_EQ(strlen("Test1"), s_.length()); |
| EXPECT_EQ("Test1", s_); |
| } |
| |
| // Decoding tests: Parse(), ParseFromBuffer() |
| |
| TEMPLATE_TEST_F(Test, ParseVarintTooLong) { |
| EXPECT_EQ(RESULT_ERROR, |
| VarintType::Parse(parse_data_ptr_ + VarintType::kMaxBytes, |
| &parse_data_ptr_)); |
| } |
| |
| TEST_F(VarintBEInt32Test, ParseFourFFs) { |
| // For a 31-bit non-negative VarintBE, the sequence FF FF FF FF is invalid. |
| // Even though the largest allowable 31-bit value occupies 5 bytes as a |
| // Varint, it shouldn't have the highest bits set and so can't begin with FF. |
| EXPECT_EQ(RESULT_ERROR, VarintType::Parse(parse_data_ptr_ + 4, |
| &parse_data_ptr_)); |
| } |
| |
| TEST_F(VarintBEInt32Test, ParseThreeFFs) { |
| EXPECT_EQ(RESULT_END_OF_DATA, VarintType::Parse(parse_data_ptr_ + 3, |
| &parse_data_ptr_)); |
| } |
| |
| TEST_F(VarintBEInt64Test, ParseEightFFs) { |
| // For a 63-bit non-negative VarintBE, a series of eight FFs is valid, because |
| // the largest allowable 63-bit value is expressed as eight FF bytes followed |
| // by a 7F byte. This is in contrast to the 32-bit case (see ParseFourFFs, |
| // above.) |
| EXPECT_EQ(RESULT_END_OF_DATA, VarintType::Parse(parse_data_ptr_ + 8, |
| &parse_data_ptr_)); |
| } |
| |
| TEMPLATE_TEST_F(Test, ParseZero) { |
| const char zero_data[] = { 0x00 }; |
| parse_data_ptr_ = zero_data; |
| EXPECT_EQ(0x00, VarintType::Parse(parse_data_ptr_ + 1, &parse_data_ptr_)); |
| EXPECT_EQ(zero_data + 1, parse_data_ptr_); |
| } |
| |
| TEMPLATE_TEST_F(Test, ParseCADA1) { |
| parse_data_ptr_ = parse_data_CADA1; |
| EXPECT_EQ(0x12AD01, |
| VarintType::Parse(parse_data_CADA1 + sizeof(parse_data_CADA1), |
| &parse_data_ptr_)); |
| EXPECT_EQ(parse_data_CADA1 + 3, parse_data_ptr_); |
| } |
| |
| TEMPLATE_TEST_F(Test, ParseNullPointer) { |
| parse_data_ptr_ = parse_data_CADA1; |
| EXPECT_EQ(RESULT_ERROR, |
| VarintType::Parse((const char*) NULL, &parse_data_ptr_)); |
| } |
| |
| TEMPLATE_TEST_F(Test, EndPointerPrecedesBeginning) { |
| // This is not an error. |
| parse_data_ptr_ = parse_data_CADA1; |
| EXPECT_EQ(RESULT_END_OF_DATA, |
| VarintType::Parse(parse_data_ptr_ - 1, &parse_data_ptr_)); |
| } |
| |
| TEMPLATE_TEST_F(Test, ParseEmpty) { |
| EXPECT_EQ(RESULT_END_OF_DATA, |
| VarintType::Parse(parse_data_ptr_, &parse_data_ptr_)); |
| } |
| |
| // This example is taken from the Varint description in RFC 3284, section 2. |
| TEMPLATE_TEST_F(Test, Parse123456789) { |
| const char parse_data_123456789[] = { 0x80 + 58, 0x80 + 111, 0x80 + 26, 21 }; |
| parse_data_ptr_ = parse_data_123456789; |
| EXPECT_EQ(123456789, VarintType::Parse(parse_data_123456789 |
| + sizeof(parse_data_123456789), |
| &parse_data_ptr_)); |
| } |
| |
| TEMPLATE_TEST_F(Test, Decode31Bits) { |
| const char parse_data_31_bits[] = { 0x87, 0xFF, 0xFF, 0xFF, 0x7F }; |
| parse_data_ptr_ = parse_data_31_bits; |
| EXPECT_EQ(0x7FFFFFFF, |
| VarintType::Parse(parse_data_31_bits + sizeof(parse_data_31_bits), |
| &parse_data_ptr_)); |
| } |
| |
| TEST_F(VarintBEInt32Test, Decode32Bits) { |
| const char parse_data_32_bits[] = { 0x88, 0x80, 0x80, 0x80, 0x00 }; |
| parse_data_ptr_ = parse_data_32_bits; |
| EXPECT_EQ(RESULT_ERROR, |
| VarintType::Parse(parse_data_32_bits + sizeof(parse_data_32_bits), |
| &parse_data_ptr_)); |
| } |
| |
| TEST_F(VarintBEInt64Test, Decode32Bits) { |
| const char parse_data_32_bits[] = { 0x88, 0x80, 0x80, 0x80, 0x00 }; |
| parse_data_ptr_ = parse_data_32_bits; |
| EXPECT_EQ(0x80000000, |
| VarintType::Parse(parse_data_32_bits + sizeof(parse_data_32_bits), |
| &parse_data_ptr_)); |
| } |
| |
| TEMPLATE_TEST_F(Test, EncodeDecodeRandom) { |
| const int test_size = 1024; // 1K random encode/decode operations |
| char encode_buffer[VarintType::kMaxBytes]; |
| srand(1); |
| for (int i = 0; i < test_size; ++i) { |
| SignedIntType value = PortableRandomInRange(VarintType::kMaxVal); |
| int length = VarintType::Encode(value, encode_buffer); |
| EXPECT_EQ(length, VarintType::Length(value)); |
| const char* parse_pointer = encode_buffer; |
| EXPECT_EQ(value, VarintType::Parse(encode_buffer + sizeof(encode_buffer), |
| &parse_pointer)); |
| EXPECT_EQ(encode_buffer + length, parse_pointer); |
| } |
| for (int i = 0; i < test_size; ++i) { |
| s_.clear(); |
| SignedIntType value = PortableRandomInRange(VarintType::kMaxVal); |
| VarintType::AppendToString(value, &s_); |
| const int varint_length = static_cast<int>(s_.length()); |
| EXPECT_EQ(VarintType::Length(value), varint_length); |
| const char* parse_pointer = s_.c_str(); |
| const char* const buffer_end_pointer = s_.c_str() + s_.length(); |
| EXPECT_EQ(value, VarintType::Parse(buffer_end_pointer, &parse_pointer)); |
| EXPECT_EQ(buffer_end_pointer, parse_pointer); |
| } |
| } |
| |
| // If only 10 bytes of data are available, but there are 20 continuation |
| // bytes, Parse() should not read to the end of the continuation bytes. It is |
| // legal (according to the RFC3284 spec) to use any number of continuation |
| // bytes, but they should not cause us to read past the end of available input. |
| TEMPLATE_TEST_F(Test, ContinuationBytesPastEndOfInput) { |
| const char parse_data_20_continuations[] = |
| { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, |
| 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, |
| 0x00 }; |
| parse_data_ptr_ = parse_data_20_continuations; |
| EXPECT_EQ(RESULT_END_OF_DATA, |
| VarintType::Parse(parse_data_20_continuations + 10, |
| &parse_data_ptr_)); |
| } |
| |
| } // anonymous namespace |
| } // namespace open_vcdiff |