/ src / leveldb / util / coding_test.cc
coding_test.cc
  1  // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  2  // Use of this source code is governed by a BSD-style license that can be
  3  // found in the LICENSE file. See the AUTHORS file for names of contributors.
  4  
  5  #include <vector>
  6  
  7  #include "util/coding.h"
  8  #include "util/testharness.h"
  9  
 10  namespace leveldb {
 11  
 12  class Coding {};
 13  
 14  TEST(Coding, Fixed32) {
 15    std::string s;
 16    for (uint32_t v = 0; v < 100000; v++) {
 17      PutFixed32(&s, v);
 18    }
 19  
 20    const char* p = s.data();
 21    for (uint32_t v = 0; v < 100000; v++) {
 22      uint32_t actual = DecodeFixed32(p);
 23      ASSERT_EQ(v, actual);
 24      p += sizeof(uint32_t);
 25    }
 26  }
 27  
 28  TEST(Coding, Fixed64) {
 29    std::string s;
 30    for (int power = 0; power <= 63; power++) {
 31      uint64_t v = static_cast<uint64_t>(1) << power;
 32      PutFixed64(&s, v - 1);
 33      PutFixed64(&s, v + 0);
 34      PutFixed64(&s, v + 1);
 35    }
 36  
 37    const char* p = s.data();
 38    for (int power = 0; power <= 63; power++) {
 39      uint64_t v = static_cast<uint64_t>(1) << power;
 40      uint64_t actual;
 41      actual = DecodeFixed64(p);
 42      ASSERT_EQ(v - 1, actual);
 43      p += sizeof(uint64_t);
 44  
 45      actual = DecodeFixed64(p);
 46      ASSERT_EQ(v + 0, actual);
 47      p += sizeof(uint64_t);
 48  
 49      actual = DecodeFixed64(p);
 50      ASSERT_EQ(v + 1, actual);
 51      p += sizeof(uint64_t);
 52    }
 53  }
 54  
 55  // Test that encoding routines generate little-endian encodings
 56  TEST(Coding, EncodingOutput) {
 57    std::string dst;
 58    PutFixed32(&dst, 0x04030201);
 59    ASSERT_EQ(4, dst.size());
 60    ASSERT_EQ(0x01, static_cast<int>(dst[0]));
 61    ASSERT_EQ(0x02, static_cast<int>(dst[1]));
 62    ASSERT_EQ(0x03, static_cast<int>(dst[2]));
 63    ASSERT_EQ(0x04, static_cast<int>(dst[3]));
 64  
 65    dst.clear();
 66    PutFixed64(&dst, 0x0807060504030201ull);
 67    ASSERT_EQ(8, dst.size());
 68    ASSERT_EQ(0x01, static_cast<int>(dst[0]));
 69    ASSERT_EQ(0x02, static_cast<int>(dst[1]));
 70    ASSERT_EQ(0x03, static_cast<int>(dst[2]));
 71    ASSERT_EQ(0x04, static_cast<int>(dst[3]));
 72    ASSERT_EQ(0x05, static_cast<int>(dst[4]));
 73    ASSERT_EQ(0x06, static_cast<int>(dst[5]));
 74    ASSERT_EQ(0x07, static_cast<int>(dst[6]));
 75    ASSERT_EQ(0x08, static_cast<int>(dst[7]));
 76  }
 77  
 78  TEST(Coding, Varint32) {
 79    std::string s;
 80    for (uint32_t i = 0; i < (32 * 32); i++) {
 81      uint32_t v = (i / 32) << (i % 32);
 82      PutVarint32(&s, v);
 83    }
 84  
 85    const char* p = s.data();
 86    const char* limit = p + s.size();
 87    for (uint32_t i = 0; i < (32 * 32); i++) {
 88      uint32_t expected = (i / 32) << (i % 32);
 89      uint32_t actual;
 90      const char* start = p;
 91      p = GetVarint32Ptr(p, limit, &actual);
 92      ASSERT_TRUE(p != nullptr);
 93      ASSERT_EQ(expected, actual);
 94      ASSERT_EQ(VarintLength(actual), p - start);
 95    }
 96    ASSERT_EQ(p, s.data() + s.size());
 97  }
 98  
 99  TEST(Coding, Varint64) {
100    // Construct the list of values to check
101    std::vector<uint64_t> values;
102    // Some special values
103    values.push_back(0);
104    values.push_back(100);
105    values.push_back(~static_cast<uint64_t>(0));
106    values.push_back(~static_cast<uint64_t>(0) - 1);
107    for (uint32_t k = 0; k < 64; k++) {
108      // Test values near powers of two
109      const uint64_t power = 1ull << k;
110      values.push_back(power);
111      values.push_back(power - 1);
112      values.push_back(power + 1);
113    }
114  
115    std::string s;
116    for (size_t i = 0; i < values.size(); i++) {
117      PutVarint64(&s, values[i]);
118    }
119  
120    const char* p = s.data();
121    const char* limit = p + s.size();
122    for (size_t i = 0; i < values.size(); i++) {
123      ASSERT_TRUE(p < limit);
124      uint64_t actual;
125      const char* start = p;
126      p = GetVarint64Ptr(p, limit, &actual);
127      ASSERT_TRUE(p != nullptr);
128      ASSERT_EQ(values[i], actual);
129      ASSERT_EQ(VarintLength(actual), p - start);
130    }
131    ASSERT_EQ(p, limit);
132  }
133  
134  TEST(Coding, Varint32Overflow) {
135    uint32_t result;
136    std::string input("\x81\x82\x83\x84\x85\x11");
137    ASSERT_TRUE(GetVarint32Ptr(input.data(), input.data() + input.size(),
138                               &result) == nullptr);
139  }
140  
141  TEST(Coding, Varint32Truncation) {
142    uint32_t large_value = (1u << 31) + 100;
143    std::string s;
144    PutVarint32(&s, large_value);
145    uint32_t result;
146    for (size_t len = 0; len < s.size() - 1; len++) {
147      ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + len, &result) == nullptr);
148    }
149    ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + s.size(), &result) !=
150                nullptr);
151    ASSERT_EQ(large_value, result);
152  }
153  
154  TEST(Coding, Varint64Overflow) {
155    uint64_t result;
156    std::string input("\x81\x82\x83\x84\x85\x81\x82\x83\x84\x85\x11");
157    ASSERT_TRUE(GetVarint64Ptr(input.data(), input.data() + input.size(),
158                               &result) == nullptr);
159  }
160  
161  TEST(Coding, Varint64Truncation) {
162    uint64_t large_value = (1ull << 63) + 100ull;
163    std::string s;
164    PutVarint64(&s, large_value);
165    uint64_t result;
166    for (size_t len = 0; len < s.size() - 1; len++) {
167      ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + len, &result) == nullptr);
168    }
169    ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + s.size(), &result) !=
170                nullptr);
171    ASSERT_EQ(large_value, result);
172  }
173  
174  TEST(Coding, Strings) {
175    std::string s;
176    PutLengthPrefixedSlice(&s, Slice(""));
177    PutLengthPrefixedSlice(&s, Slice("foo"));
178    PutLengthPrefixedSlice(&s, Slice("bar"));
179    PutLengthPrefixedSlice(&s, Slice(std::string(200, 'x')));
180  
181    Slice input(s);
182    Slice v;
183    ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
184    ASSERT_EQ("", v.ToString());
185    ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
186    ASSERT_EQ("foo", v.ToString());
187    ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
188    ASSERT_EQ("bar", v.ToString());
189    ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
190    ASSERT_EQ(std::string(200, 'x'), v.ToString());
191    ASSERT_EQ("", input.ToString());
192  }
193  
194  }  // namespace leveldb
195  
196  int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }