2 * Copyright 2014 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "folly/GroupVarint.h"
20 // On platforms where it's not supported, GroupVarint will be compiled out.
23 #include <gtest/gtest.h>
25 using namespace folly;
29 class StringAppender {
31 /* implicit */ StringAppender(std::string& s) : s_(s) { }
32 void operator()(StringPiece sp) {
33 s_.append(sp.data(), sp.size());
39 typedef GroupVarintEncoder<uint32_t, StringAppender> GroupVarint32Encoder;
40 typedef GroupVarintEncoder<uint64_t, StringAppender> GroupVarint64Encoder;
41 typedef GroupVarintDecoder<uint32_t> GroupVarint32Decoder;
42 typedef GroupVarintDecoder<uint32_t> GroupVarint64Decoder;
44 // Expected bytes follow, terminate with -1
45 void testGroupVarint32(uint32_t a, uint32_t b, uint32_t c, uint32_t d, ...) {
48 std::vector<char> expectedBytes;
50 while ((byte = va_arg(ap, int)) != -1) {
51 expectedBytes.push_back(byte);
55 size_t size = GroupVarint32::size(a, b, c, d);
56 EXPECT_EQ(expectedBytes.size(), size);
58 std::vector<char> foundBytes;
59 foundBytes.resize(size + 4);
60 char* start = &(foundBytes.front());
61 char* p = GroupVarint32::encode(start, a, b, c, d);
62 EXPECT_EQ((void*)(start + size), (void*)p);
64 for (size_t i = 0; i < size; i++) {
65 EXPECT_EQ(0xff & expectedBytes[i], 0xff & foundBytes[i]);
69 EXPECT_EQ(size, GroupVarint32::encodedSize(start));
71 uint32_t fa, fb, fc, fd;
72 const char* r = GroupVarint32::decode(start, &fa, &fb, &fc, &fd);
73 EXPECT_EQ((void*)(start + size), (void*)r);
81 void testGroupVarint64(uint64_t a, uint64_t b, uint64_t c, uint64_t d,
85 std::vector<char> expectedBytes;
87 while ((byte = va_arg(ap, int)) != -1) {
88 expectedBytes.push_back(byte);
92 size_t size = GroupVarint64::size(a, b, c, d, e);
93 EXPECT_EQ(expectedBytes.size(), size);
95 std::vector<char> foundBytes;
96 foundBytes.resize(size + 8);
97 char* start = &(foundBytes.front());
98 char* p = GroupVarint64::encode(start, a, b, c, d, e);
99 EXPECT_EQ((void*)(start + size), (void*)p);
101 for (size_t i = 0; i < size; i++) {
102 EXPECT_EQ(0xff & expectedBytes[i], 0xff & foundBytes[i]);
106 EXPECT_EQ(size, GroupVarint64::encodedSize(start));
108 uint64_t fa, fb, fc, fd, fe;
109 const char* r = GroupVarint64::decode(start, &fa, &fb, &fc, &fd, &fe);
110 EXPECT_EQ((void*)(start + size), (void*)r);
121 TEST(GroupVarint, GroupVarint32) {
122 EXPECT_EQ(0, GroupVarint32::maxSize(0));
123 EXPECT_EQ(5, GroupVarint32::maxSize(1));
124 EXPECT_EQ(9, GroupVarint32::maxSize(2));
125 EXPECT_EQ(13, GroupVarint32::maxSize(3));
126 EXPECT_EQ(17, GroupVarint32::maxSize(4));
127 EXPECT_EQ(22, GroupVarint32::maxSize(5));
128 EXPECT_EQ(26, GroupVarint32::maxSize(6));
129 testGroupVarint32(0, 0, 0, 0,
131 testGroupVarint32(1, 2, 3, 4,
133 testGroupVarint32(1 << 8, (2 << 16) + 3, (4 << 24) + (5 << 8) + 6, 7,
134 0x39, 0, 1, 3, 0, 2, 6, 5, 0, 4, 7, -1);
137 TEST(GroupVarint, GroupVarint64) {
138 EXPECT_EQ(0, GroupVarint64::maxSize(0));
139 EXPECT_EQ(10, GroupVarint64::maxSize(1));
140 EXPECT_EQ(18, GroupVarint64::maxSize(2));
141 EXPECT_EQ(26, GroupVarint64::maxSize(3));
142 EXPECT_EQ(34, GroupVarint64::maxSize(4));
143 EXPECT_EQ(42, GroupVarint64::maxSize(5));
144 EXPECT_EQ(52, GroupVarint64::maxSize(6));
145 testGroupVarint64(0, 0, 0, 0, 0,
146 0, 0, 0, 0, 0, 0, 0, -1);
147 testGroupVarint64(1, 2, 3, 4, 5,
148 0, 0, 1, 2, 3, 4, 5, -1);
149 testGroupVarint64(1 << 8, (2 << 16) + 3, (4 << 24) + (5 << 8) + 6,
150 (7ULL << 32) + (8 << 16),
151 (9ULL << 56) + (10ULL << 40) + 11,
157 11, 0, 0, 0, 0, 10, 0, 9,
161 TEST(GroupVarint, GroupVarintEncoder) {
164 GroupVarint32Encoder gv(s);
168 EXPECT_EQ(2, s.size());
169 EXPECT_EQ(std::string("\x00\x00", 2), s);
172 GroupVarint32Encoder gv(s);
179 EXPECT_EQ(5, s.size());
180 EXPECT_EQ(std::string("\x00\x01\x02\x03\x04", 5), s);
184 TEST(GroupVarint, GroupVarintDecoder) {
185 // Make sure we don't read out of bounds
186 std::string padding(17, 'X');
189 std::string s("\x00\x00", 2);
191 StringPiece p(s.data(), 2);
193 GroupVarint32Decoder gv(p);
195 EXPECT_TRUE(gv.next(&v));
197 EXPECT_FALSE(gv.next(&v));
198 EXPECT_TRUE(gv.rest().empty());
202 std::string s("\x00\x01\x02\x03\x04\x01\x02\x03\x04", 9);
204 StringPiece p(s.data(), 9);
206 GroupVarint32Decoder gv(p);
208 EXPECT_TRUE(gv.next(&v));
210 EXPECT_TRUE(gv.next(&v));
212 EXPECT_TRUE(gv.next(&v));
214 EXPECT_TRUE(gv.next(&v));
216 EXPECT_TRUE(gv.next(&v));
217 EXPECT_EQ(0x0302, v);
218 EXPECT_TRUE(gv.next(&v));
220 EXPECT_FALSE(gv.next(&v));
221 EXPECT_TRUE(gv.rest().empty());
225 // Limit max count when reading a full block
226 std::string s("\x00\x01\x02\x03\x04\x01\x02\x03\x04", 9);
228 StringPiece p(s.data(), 9);
230 GroupVarint32Decoder gv(p, 3);
232 EXPECT_TRUE(gv.next(&v));
234 EXPECT_TRUE(gv.next(&v));
236 EXPECT_TRUE(gv.next(&v));
238 EXPECT_FALSE(gv.next(&v));
239 EXPECT_EQ(std::string("\x04\x01\x02\x03\x04", 5), gv.rest().toString());
243 // Limit max count when reading a partial block
244 std::string s("\x00\x01\x02\x03\x04\x01\x02\x03\x04", 9);
246 StringPiece p(s.data(), 9);
248 GroupVarint32Decoder gv(p, 5);
250 EXPECT_TRUE(gv.next(&v));
252 EXPECT_TRUE(gv.next(&v));
254 EXPECT_TRUE(gv.next(&v));
256 EXPECT_TRUE(gv.next(&v));
258 EXPECT_TRUE(gv.next(&v));
259 EXPECT_EQ(0x0302, v);
260 EXPECT_FALSE(gv.next(&v));
261 EXPECT_EQ(std::string("\x04", 1), gv.rest().toString());