openvcdiff | 311c714 | 2008-08-26 19:29:25 +0000 | [diff] [blame] | 1 | // Copyright 2008 Google Inc. |
| 2 | // Author: Lincoln Smith |
| 3 | // |
| 4 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | // you may not use this file except in compliance with the License. |
| 6 | // You may obtain a copy of the License at |
| 7 | // |
| 8 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | // |
| 10 | // Unless required by applicable law or agreed to in writing, software |
| 11 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | // See the License for the specific language governing permissions and |
| 14 | // limitations under the License. |
| 15 | |
| 16 | #include <config.h> |
| 17 | #include "varint_bigendian.h" |
openvcdiff | 28db807 | 2008-10-10 23:29:11 +0000 | [diff] [blame^] | 18 | #include <stdlib.h> // rand, srand |
| 19 | #include <string.h> // strlen |
openvcdiff | 311c714 | 2008-08-26 19:29:25 +0000 | [diff] [blame] | 20 | #include <string> |
| 21 | #include <vector> |
| 22 | #include "logging.h" |
| 23 | #include "testing.h" |
| 24 | |
| 25 | namespace open_vcdiff { |
| 26 | namespace { |
| 27 | |
openvcdiff | 311c714 | 2008-08-26 19:29:25 +0000 | [diff] [blame] | 28 | class VarintBETestCommon : public testing::Test { |
| 29 | protected: |
openvcdiff | 28db807 | 2008-10-10 23:29:11 +0000 | [diff] [blame^] | 30 | #ifndef VCDIFF_HAS_GLOBAL_STRING |
| 31 | typedef std::string string; |
| 32 | #endif // !VCDIFF_HAS_GLOBAL_STRING |
| 33 | |
openvcdiff | 311c714 | 2008-08-26 19:29:25 +0000 | [diff] [blame] | 34 | VarintBETestCommon() |
| 35 | : varint_buf_(VarintBE<int64_t>::kMaxBytes), |
| 36 | verify_encoded_byte_index_(0), |
| 37 | verify_expected_length_(0), |
| 38 | parse_data_ptr_(parse_data_all_FFs) { |
| 39 | } |
| 40 | |
| 41 | virtual ~VarintBETestCommon() { } |
| 42 | |
| 43 | void ExpectEncodedByte(char expected_byte) { |
| 44 | EXPECT_EQ(expected_byte, varint_buf_[verify_encoded_byte_index_]); |
| 45 | EXPECT_EQ(expected_byte, s_[verify_encoded_byte_index_]); |
| 46 | ++verify_encoded_byte_index_; |
| 47 | } |
| 48 | |
| 49 | static const char parse_data_all_FFs[]; |
| 50 | static const char parse_data_CADA1[]; |
| 51 | |
| 52 | std::vector<char> varint_buf_; |
| 53 | string s_; |
| 54 | int verify_encoded_byte_index_; |
| 55 | int verify_expected_length_; |
| 56 | const char* parse_data_ptr_; |
| 57 | }; |
| 58 | |
| 59 | template <typename SignedIntegerType> |
| 60 | class VarintBETestTemplate : public VarintBETestCommon { |
| 61 | protected: |
| 62 | VarintBETestTemplate() { } |
| 63 | |
| 64 | virtual ~VarintBETestTemplate() { } |
| 65 | |
| 66 | typedef SignedIntegerType SignedIntType; |
| 67 | typedef VarintBE<SignedIntegerType> VarintType; |
| 68 | |
| 69 | void StartEncodingTest(SignedIntegerType v, int expected_length) { |
| 70 | verify_expected_length_ = expected_length; |
| 71 | EXPECT_EQ(expected_length, VarintType::Length(v)); |
| 72 | EXPECT_EQ(expected_length, VarintType::Encode(v, &varint_buf_[0])); |
| 73 | VarintType::AppendToString(v, &s_); |
| 74 | EXPECT_EQ(static_cast<size_t>(expected_length), s_.length()); |
| 75 | } |
| 76 | |
| 77 | void TestEncodeInvalid(SignedIntegerType v) { |
| 78 | EXPECT_DEATH(VarintType::Length(v), "v >= 0"); |
| 79 | EXPECT_DEATH(VarintType::Encode(v, &varint_buf_[0]), "v >= 0"); |
| 80 | EXPECT_DEATH(VarintType::AppendToString(v, &s_), ">= 0"); |
| 81 | } |
| 82 | |
| 83 | // Need one function for each test type that will be applied to |
| 84 | // multiple classes |
| 85 | void TemplateTestDISABLED_EncodeNegative(); |
| 86 | void TemplateTestEncodeZero(); |
| 87 | void TemplateTestEncodeEightBits(); |
| 88 | void TemplateTestEncodeCADAD1A(); |
| 89 | void TemplateTestEncode32BitMaxInt(); |
| 90 | void TemplateTestEncodeDoesNotOverwriteExistingString(); |
| 91 | void TemplateTestParseNullPointer(); |
| 92 | void TemplateTestEndPointerPrecedesBeginning(); |
| 93 | void TemplateTestParseVarintTooLong(); |
| 94 | void TemplateTestParseIncompleteVarint(); |
| 95 | void TemplateTestParseZero(); |
| 96 | void TemplateTestParseCADA1(); |
| 97 | void TemplateTestParseEmpty(); |
| 98 | void TemplateTestParse123456789(); |
| 99 | void TemplateTestDecode31Bits(); |
| 100 | void TemplateTestEncodeDecodeRandom(); |
| 101 | }; |
| 102 | |
| 103 | typedef VarintBETestTemplate<int32_t> VarintBEInt32Test; |
| 104 | typedef VarintBETestTemplate<int64_t> VarintBEInt64Test; |
| 105 | |
| 106 | #ifdef GTEST_HAS_DEATH_TEST |
| 107 | // These synonyms are needed for the tests that use ASSERT_DEATH |
| 108 | typedef VarintBEInt32Test VarintBEInt32DeathTest; |
| 109 | typedef VarintBEInt64Test VarintBEInt64DeathTest; |
| 110 | #endif // GTEST_HAS_DEATH_TEST |
| 111 | |
| 112 | const char VarintBETestCommon::parse_data_all_FFs[] = |
| 113 | { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
| 114 | |
| 115 | const char VarintBETestCommon::parse_data_CADA1[] = |
| 116 | { 0xCA, 0xDA, 0x01 }; |
| 117 | |
| 118 | // A macro to allow defining tests once and having them run against |
| 119 | // both VarintBE<int32_t> and VarintBE<int64_t>. |
| 120 | // |
| 121 | #define TEMPLATE_TEST_F(TEST_TYPE, TEST_NAME) \ |
| 122 | TEST_F(VarintBEInt32##TEST_TYPE, TEST_NAME) { \ |
| 123 | TemplateTest##TEST_NAME(); \ |
| 124 | } \ |
| 125 | TEST_F(VarintBEInt64##TEST_TYPE, TEST_NAME) { \ |
| 126 | TemplateTest##TEST_NAME(); \ |
| 127 | } \ |
| 128 | template <class CacheType> \ |
| 129 | void VarintBETestTemplate<CacheType>::TemplateTest##TEST_NAME() |
| 130 | |
| 131 | // Encoding tests: Length(), Encode(), AppendToString(), AppendToBuffer() |
| 132 | |
| 133 | #ifdef GTEST_HAS_DEATH_TEST |
| 134 | // This test hangs for non-debug build (DeathTest threading problem) |
| 135 | TEMPLATE_TEST_F(DeathTest, DISABLED_EncodeNegative) { |
| 136 | TestEncodeInvalid(-1); |
| 137 | } |
| 138 | #endif // GTEST_HAS_DEATH_TEST |
| 139 | |
| 140 | TEMPLATE_TEST_F(Test, EncodeZero) { |
| 141 | StartEncodingTest(/* value */ 0x00, /* expected length */ 1); |
| 142 | ExpectEncodedByte(0x00); |
| 143 | EXPECT_EQ(verify_expected_length_, verify_encoded_byte_index_); |
| 144 | } |
| 145 | |
| 146 | TEMPLATE_TEST_F(Test, EncodeEightBits) { |
| 147 | StartEncodingTest(/* value */ 0xFF, /* expected length */ 2); |
| 148 | ExpectEncodedByte(0x81); |
| 149 | ExpectEncodedByte(0x7F); |
| 150 | EXPECT_EQ(verify_expected_length_, verify_encoded_byte_index_); |
| 151 | } |
| 152 | |
| 153 | TEMPLATE_TEST_F(Test, EncodeCADAD1A) { |
| 154 | StartEncodingTest(/* value */ 0x0CADAD1A, /* expected length */ 4); |
| 155 | ExpectEncodedByte(0xE5); |
| 156 | ExpectEncodedByte(0xB6); |
| 157 | ExpectEncodedByte(0xDA); |
| 158 | ExpectEncodedByte(0x1A); |
| 159 | EXPECT_EQ(verify_expected_length_, verify_encoded_byte_index_); |
| 160 | } |
| 161 | |
| 162 | TEMPLATE_TEST_F(Test, Encode32BitMaxInt) { |
| 163 | StartEncodingTest(/* value */ 0x7FFFFFFF, /* expected length */ 5); |
| 164 | ExpectEncodedByte(0x87); |
| 165 | ExpectEncodedByte(0xFF); |
| 166 | ExpectEncodedByte(0xFF); |
| 167 | ExpectEncodedByte(0xFF); |
| 168 | ExpectEncodedByte(0x7F); |
| 169 | EXPECT_EQ(verify_expected_length_, verify_encoded_byte_index_); |
| 170 | } |
| 171 | |
| 172 | #ifdef GTEST_HAS_DEATH_TEST |
| 173 | // This test hangs for non-debug build (DeathTest threading problem) |
| 174 | TEST_F(VarintBEInt32DeathTest, DISABLED_Encode32BitsTooBig) { |
| 175 | TestEncodeInvalid(0x80000000); |
| 176 | } |
| 177 | #endif // GTEST_HAS_DEATH_TEST |
| 178 | |
| 179 | TEST_F(VarintBEInt64Test, Encode32Bits) { |
| 180 | StartEncodingTest(/* value */ 0x80000000, /* expected length */ 5); |
| 181 | ExpectEncodedByte(0x88); |
| 182 | ExpectEncodedByte(0x80); |
| 183 | ExpectEncodedByte(0x80); |
| 184 | ExpectEncodedByte(0x80); |
| 185 | ExpectEncodedByte(0x00); |
| 186 | EXPECT_EQ(verify_expected_length_, verify_encoded_byte_index_); |
| 187 | } |
| 188 | |
| 189 | TEST_F(VarintBEInt64Test, Encode63Bits) { |
| 190 | StartEncodingTest(/* value */ 0x7FFFFFFFFFFFFFFFULL, /* expected length */ 9); |
| 191 | ExpectEncodedByte(0xFF); |
| 192 | ExpectEncodedByte(0xFF); |
| 193 | ExpectEncodedByte(0xFF); |
| 194 | ExpectEncodedByte(0xFF); |
| 195 | ExpectEncodedByte(0xFF); |
| 196 | ExpectEncodedByte(0xFF); |
| 197 | ExpectEncodedByte(0xFF); |
| 198 | ExpectEncodedByte(0xFF); |
| 199 | ExpectEncodedByte(0x7F); |
| 200 | EXPECT_EQ(verify_expected_length_, verify_encoded_byte_index_); |
| 201 | } |
| 202 | |
| 203 | #ifdef GTEST_HAS_DEATH_TEST |
| 204 | // This test hangs for non-debug build (DeathTest threading problem) |
| 205 | TEST_F(VarintBEInt64DeathTest, DISABLED_Encode64BitsTooBig) { |
| 206 | TestEncodeInvalid(0x8000000000000000ULL); |
| 207 | } |
| 208 | #endif // GTEST_HAS_DEATH_TEST |
| 209 | |
| 210 | TEMPLATE_TEST_F(Test, EncodeDoesNotOverwriteExistingString) { |
| 211 | s_.append("Test"); |
| 212 | VarintType::AppendToString('1', &s_); |
| 213 | EXPECT_EQ(strlen("Test1"), s_.length()); |
| 214 | EXPECT_EQ("Test1", s_); |
| 215 | } |
| 216 | |
| 217 | // Decoding tests: Parse(), ParseFromBuffer() |
| 218 | |
| 219 | TEMPLATE_TEST_F(Test, ParseVarintTooLong) { |
| 220 | EXPECT_EQ(RESULT_ERROR, |
| 221 | VarintType::Parse(parse_data_ptr_ + VarintType::kMaxBytes, |
| 222 | &parse_data_ptr_)); |
| 223 | } |
| 224 | |
| 225 | TEMPLATE_TEST_F(Test, ParseIncompleteVarint) { |
| 226 | EXPECT_EQ(RESULT_END_OF_DATA, |
| 227 | VarintType::Parse(parse_data_ptr_ + VarintType::kMaxBytes - 1, |
| 228 | &parse_data_ptr_)); |
| 229 | } |
| 230 | |
| 231 | TEMPLATE_TEST_F(Test, ParseZero) { |
| 232 | const char zero_data[] = { 0x00 }; |
| 233 | parse_data_ptr_ = zero_data; |
| 234 | EXPECT_EQ(0x00, VarintType::Parse(parse_data_ptr_ + 1, &parse_data_ptr_)); |
| 235 | EXPECT_EQ(zero_data + 1, parse_data_ptr_); |
| 236 | } |
| 237 | |
| 238 | TEMPLATE_TEST_F(Test, ParseCADA1) { |
| 239 | parse_data_ptr_ = parse_data_CADA1; |
| 240 | EXPECT_EQ(0x12AD01, |
| 241 | VarintType::Parse(parse_data_CADA1 + sizeof(parse_data_CADA1), |
| 242 | &parse_data_ptr_)); |
| 243 | EXPECT_EQ(parse_data_CADA1 + 3, parse_data_ptr_); |
| 244 | } |
| 245 | |
| 246 | #ifdef GTEST_HAS_DEATH_TEST |
| 247 | TEMPLATE_TEST_F(DeathTest, ParseNullPointer) { |
| 248 | // limit == NULL is not an error |
| 249 | parse_data_ptr_ = parse_data_CADA1; |
| 250 | EXPECT_EQ(0x12AD01, VarintType::Parse((const char*) NULL, &parse_data_ptr_)); |
| 251 | } |
| 252 | #endif // GTEST_HAS_DEATH_TEST |
| 253 | |
| 254 | TEMPLATE_TEST_F(Test, EndPointerPrecedesBeginning) { |
| 255 | // This is not an error. |
| 256 | parse_data_ptr_ = parse_data_CADA1; |
| 257 | EXPECT_EQ(0x12AD01, VarintType::Parse(parse_data_ptr_ - 1, &parse_data_ptr_)); |
| 258 | } |
| 259 | |
| 260 | TEMPLATE_TEST_F(Test, ParseEmpty) { |
| 261 | EXPECT_EQ(RESULT_END_OF_DATA, |
| 262 | VarintType::Parse(parse_data_ptr_, &parse_data_ptr_)); |
| 263 | } |
| 264 | |
| 265 | // This example is taken from the Varint description in RFC 3284, section 2. |
| 266 | TEMPLATE_TEST_F(Test, Parse123456789) { |
| 267 | const char parse_data_123456789[] = { 0x80 + 58, 0x80 + 111, 0x80 + 26, 21 }; |
| 268 | parse_data_ptr_ = parse_data_123456789; |
| 269 | EXPECT_EQ(123456789, VarintType::Parse(parse_data_123456789 |
| 270 | + sizeof(parse_data_123456789), |
| 271 | &parse_data_ptr_)); |
| 272 | } |
| 273 | |
| 274 | TEMPLATE_TEST_F(Test, Decode31Bits) { |
| 275 | const char parse_data_31_bits[] = { 0x87, 0xFF, 0xFF, 0xFF, 0x7F }; |
| 276 | parse_data_ptr_ = parse_data_31_bits; |
| 277 | EXPECT_EQ(0x7FFFFFFF, |
| 278 | VarintType::Parse(parse_data_31_bits + sizeof(parse_data_31_bits), |
| 279 | &parse_data_ptr_)); |
| 280 | } |
| 281 | |
| 282 | TEST_F(VarintBEInt32Test, Decode32Bits) { |
| 283 | const char parse_data_32_bits[] = { 0x88, 0x80, 0x80, 0x80, 0x00 }; |
| 284 | parse_data_ptr_ = parse_data_32_bits; |
| 285 | EXPECT_EQ(RESULT_ERROR, |
| 286 | VarintType::Parse(parse_data_32_bits + sizeof(parse_data_32_bits), |
| 287 | &parse_data_ptr_)); |
| 288 | } |
| 289 | |
| 290 | TEST_F(VarintBEInt64Test, Decode32Bits) { |
| 291 | const char parse_data_32_bits[] = { 0x88, 0x80, 0x80, 0x80, 0x00 }; |
| 292 | parse_data_ptr_ = parse_data_32_bits; |
| 293 | EXPECT_EQ(0x80000000, |
| 294 | VarintType::Parse(parse_data_32_bits + sizeof(parse_data_32_bits), |
| 295 | &parse_data_ptr_)); |
| 296 | } |
| 297 | |
| 298 | TEMPLATE_TEST_F(Test, EncodeDecodeRandom) { |
| 299 | const int test_size = 1024; // 1K random encode/decode operations |
| 300 | char encode_buffer[VarintType::kMaxBytes]; |
| 301 | srand(1); |
| 302 | for (int i = 0; i < test_size; ++i) { |
| 303 | SignedIntType value = PortableRandomInRange(VarintType::kMaxVal); |
| 304 | int length = VarintType::Encode(value, encode_buffer); |
| 305 | EXPECT_EQ(length, VarintType::Length(value)); |
| 306 | const char* parse_pointer = encode_buffer; |
| 307 | EXPECT_EQ(value, VarintType::Parse(encode_buffer + sizeof(encode_buffer), |
| 308 | &parse_pointer)); |
| 309 | EXPECT_EQ(encode_buffer + length, parse_pointer); |
| 310 | } |
| 311 | for (int i = 0; i < test_size; ++i) { |
| 312 | s_.clear(); |
| 313 | SignedIntType value = PortableRandomInRange(VarintType::kMaxVal); |
| 314 | VarintType::AppendToString(value, &s_); |
| 315 | const int varint_length = static_cast<int>(s_.length()); |
| 316 | EXPECT_EQ(VarintType::Length(value), varint_length); |
| 317 | const char* parse_pointer = s_.c_str(); |
| 318 | const char* const buffer_end_pointer = s_.c_str() + s_.length(); |
| 319 | EXPECT_EQ(value, VarintType::Parse(buffer_end_pointer, &parse_pointer)); |
| 320 | EXPECT_EQ(buffer_end_pointer, parse_pointer); |
| 321 | } |
| 322 | } |
| 323 | |
| 324 | } // anonymous namespace |
| 325 | } // namespace open_vcdiff |