2 * Copyright 2012 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.
17 #include "folly/experimental/io/IOBufQueue.h"
18 #include "folly/Range.h"
20 #include <gflags/gflags.h>
21 #include <gtest/gtest.h>
28 using folly::IOBufQueue;
29 using folly::StringPiece;
32 using std::unique_ptr;
34 // String Comma Length macro for string literals
35 #define SCL(x) (x), sizeof(x) - 1
39 IOBufQueue::Options clOptions;
42 clOptions.cacheChainLength = true;
45 Initializer initializer;
48 stringToIOBuf(const char* s, uint32_t len) {
49 unique_ptr<IOBuf> buf = IOBuf::create(len);
50 memcpy(buf->writableTail(), s, len);
52 return std::move(buf);
55 void checkConsistency(const IOBufQueue& queue) {
56 if (queue.options().cacheChainLength) {
57 size_t len = queue.front() ? queue.front()->computeChainDataLength() : 0;
58 EXPECT_EQ(len, queue.chainLength());
64 TEST(IOBufQueue, Simple) {
65 IOBufQueue queue(clOptions);
66 EXPECT_EQ(NULL, queue.front());
67 queue.append(SCL(""));
68 EXPECT_EQ(NULL, queue.front());
69 queue.append(unique_ptr<IOBuf>());
70 EXPECT_EQ(NULL, queue.front());
72 queue.append(emptyString);
73 EXPECT_EQ(NULL, queue.front());
76 TEST(IOBufQueue, Append) {
77 IOBufQueue queue(clOptions);
78 queue.append(SCL("Hello"));
79 IOBufQueue queue2(clOptions);
80 queue2.append(SCL(", "));
81 queue2.append(SCL("World"));
82 checkConsistency(queue);
83 checkConsistency(queue2);
84 queue.append(queue2.move());
85 checkConsistency(queue);
86 checkConsistency(queue2);
87 const IOBuf* chain = queue.front();
88 EXPECT_NE((IOBuf*)NULL, chain);
89 EXPECT_EQ(12, chain->computeChainDataLength());
90 EXPECT_EQ(NULL, queue2.front());
93 TEST(IOBufQueue, Append2) {
94 IOBufQueue queue(clOptions);
95 queue.append(SCL("Hello"));
96 IOBufQueue queue2(clOptions);
97 queue2.append(SCL(", "));
98 queue2.append(SCL("World"));
99 checkConsistency(queue);
100 checkConsistency(queue2);
101 queue.append(queue2);
102 checkConsistency(queue);
103 checkConsistency(queue2);
104 const IOBuf* chain = queue.front();
105 EXPECT_NE((IOBuf*)NULL, chain);
106 EXPECT_EQ(12, chain->computeChainDataLength());
107 EXPECT_EQ(NULL, queue2.front());
110 TEST(IOBufQueue, Split) {
111 IOBufQueue queue(clOptions);
112 queue.append(stringToIOBuf(SCL("Hello")));
113 queue.append(stringToIOBuf(SCL(",")));
114 queue.append(stringToIOBuf(SCL(" ")));
115 queue.append(stringToIOBuf(SCL("")));
116 queue.append(stringToIOBuf(SCL("World")));
117 checkConsistency(queue);
118 EXPECT_EQ(12, queue.front()->computeChainDataLength());
120 unique_ptr<IOBuf> prefix(queue.split(1));
121 checkConsistency(queue);
122 EXPECT_EQ(1, prefix->computeChainDataLength());
123 EXPECT_EQ(11, queue.front()->computeChainDataLength());
124 prefix = queue.split(2);
125 checkConsistency(queue);
126 EXPECT_EQ(2, prefix->computeChainDataLength());
127 EXPECT_EQ(9, queue.front()->computeChainDataLength());
128 prefix = queue.split(3);
129 checkConsistency(queue);
130 EXPECT_EQ(3, prefix->computeChainDataLength());
131 EXPECT_EQ(6, queue.front()->computeChainDataLength());
132 prefix = queue.split(1);
133 checkConsistency(queue);
134 EXPECT_EQ(1, prefix->computeChainDataLength());
135 EXPECT_EQ(5, queue.front()->computeChainDataLength());
136 prefix = queue.split(5);
137 checkConsistency(queue);
138 EXPECT_EQ(5, prefix->computeChainDataLength());
139 EXPECT_EQ((IOBuf*)NULL, queue.front());
141 queue.append(stringToIOBuf(SCL("Hello,")));
142 queue.append(stringToIOBuf(SCL(" World")));
143 checkConsistency(queue);
144 bool exceptionFired = false;
145 EXPECT_THROW({prefix = queue.split(13);}, std::underflow_error);
146 checkConsistency(queue);
149 TEST(IOBufQueue, Preallocate) {
150 IOBufQueue queue(clOptions);
151 queue.append(string("Hello"));
152 pair<void*,uint32_t> writable = queue.preallocate(2, 64);
153 checkConsistency(queue);
154 EXPECT_NE((void*)NULL, writable.first);
155 EXPECT_LE(2, writable.second);
156 EXPECT_GE(64, writable.second);
157 memcpy(writable.first, SCL(", "));
158 queue.postallocate(2);
159 checkConsistency(queue);
160 EXPECT_EQ(7, queue.front()->computeChainDataLength());
161 queue.append(SCL("World"));
162 checkConsistency(queue);
163 EXPECT_EQ(12, queue.front()->computeChainDataLength());
164 writable = queue.preallocate(1024, 4096);
165 checkConsistency(queue);
166 EXPECT_LE(1024, writable.second);
167 EXPECT_GE(4096, writable.second);
170 TEST(IOBufQueue, Wrap) {
171 IOBufQueue queue(clOptions);
172 const char* buf = "hello world goodbye";
173 size_t len = strlen(buf);
174 queue.wrapBuffer(buf, len, 6);
175 auto iob = queue.move();
176 EXPECT_EQ((len - 1) / 6 + 1, iob->countChainElements());
179 EXPECT_EQ(StringPiece(buf),
180 StringPiece(reinterpret_cast<const char*>(iob->data()),
184 TEST(IOBufQueue, trim) {
185 IOBufQueue queue(clOptions);
186 unique_ptr<IOBuf> a = IOBuf::create(4);
188 queue.append(std::move(a));
189 checkConsistency(queue);
190 a = IOBuf::create(6);
192 queue.append(std::move(a));
193 checkConsistency(queue);
194 a = IOBuf::create(8);
196 queue.append(std::move(a));
197 checkConsistency(queue);
198 a = IOBuf::create(10);
200 queue.append(std::move(a));
201 checkConsistency(queue);
203 EXPECT_EQ(4, queue.front()->countChainElements());
204 EXPECT_EQ(28, queue.front()->computeChainDataLength());
205 EXPECT_EQ(4, queue.front()->length());
208 checkConsistency(queue);
209 EXPECT_EQ(4, queue.front()->countChainElements());
210 EXPECT_EQ(27, queue.front()->computeChainDataLength());
211 EXPECT_EQ(3, queue.front()->length());
214 checkConsistency(queue);
215 EXPECT_EQ(3, queue.front()->countChainElements());
216 EXPECT_EQ(22, queue.front()->computeChainDataLength());
217 EXPECT_EQ(4, queue.front()->length());
220 checkConsistency(queue);
221 EXPECT_EQ(3, queue.front()->countChainElements());
222 EXPECT_EQ(21, queue.front()->computeChainDataLength());
223 EXPECT_EQ(9, queue.front()->prev()->length());
226 checkConsistency(queue);
227 EXPECT_EQ(1, queue.front()->countChainElements());
228 EXPECT_EQ(1, queue.front()->computeChainDataLength());
229 EXPECT_EQ(1, queue.front()->prev()->length());
232 checkConsistency(queue);
233 EXPECT_EQ(NULL, queue.front());
235 EXPECT_THROW(queue.trimStart(2), std::underflow_error);
236 checkConsistency(queue);
238 EXPECT_THROW(queue.trimEnd(30), std::underflow_error);
239 checkConsistency(queue);
242 int main(int argc, char** argv) {
243 testing::InitGoogleTest(&argc, argv);
244 google::ParseCommandLineFlags(&argc, &argv, true);
246 return RUN_ALL_TESTS();