IOBufTest.cpp 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486
  1. /*
  2. * Copyright 2013-present Facebook, Inc.
  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 <folly/io/IOBuf.h>
  17. #include <folly/io/TypedIOBuf.h>
  18. #include <cstddef>
  19. #include <boost/random.hpp>
  20. #include <folly/Range.h>
  21. #include <folly/memory/Malloc.h>
  22. #include <folly/portability/GTest.h>
  23. using folly::ByteRange;
  24. using folly::fbstring;
  25. using folly::fbvector;
  26. using folly::IOBuf;
  27. using folly::ordering;
  28. using folly::StringPiece;
  29. using folly::TypedIOBuf;
  30. using std::unique_ptr;
  31. void append(std::unique_ptr<IOBuf>& buf, StringPiece str) {
  32. EXPECT_LE(str.size(), buf->tailroom());
  33. memcpy(buf->writableData(), str.data(), str.size());
  34. buf->append(str.size());
  35. }
  36. void prepend(std::unique_ptr<IOBuf>& buf, StringPiece str) {
  37. EXPECT_LE(str.size(), buf->headroom());
  38. memcpy(buf->writableData() - str.size(), str.data(), str.size());
  39. buf->prepend(str.size());
  40. }
  41. TEST(IOBuf, Simple) {
  42. unique_ptr<IOBuf> buf(IOBuf::create(100));
  43. uint32_t cap = buf->capacity();
  44. EXPECT_LE(100, cap);
  45. EXPECT_EQ(0, buf->headroom());
  46. EXPECT_EQ(0, buf->length());
  47. EXPECT_EQ(cap, buf->tailroom());
  48. append(buf, "world");
  49. buf->advance(10);
  50. EXPECT_EQ(10, buf->headroom());
  51. EXPECT_EQ(5, buf->length());
  52. EXPECT_EQ(cap - 15, buf->tailroom());
  53. prepend(buf, "hello ");
  54. EXPECT_EQ(4, buf->headroom());
  55. EXPECT_EQ(11, buf->length());
  56. EXPECT_EQ(cap - 15, buf->tailroom());
  57. const char* p = reinterpret_cast<const char*>(buf->data());
  58. EXPECT_EQ("hello world", std::string(p, buf->length()));
  59. buf->clear();
  60. EXPECT_EQ(0, buf->headroom());
  61. EXPECT_EQ(0, buf->length());
  62. EXPECT_EQ(cap, buf->tailroom());
  63. }
  64. void testAllocSize(uint32_t requestedCapacity) {
  65. unique_ptr<IOBuf> iobuf(IOBuf::create(requestedCapacity));
  66. EXPECT_GE(iobuf->capacity(), requestedCapacity);
  67. }
  68. TEST(IOBuf, AllocSizes) {
  69. // Try with a small allocation size that should fit in the internal buffer
  70. testAllocSize(28);
  71. // Try with a large allocation size that will require an external buffer.
  72. testAllocSize(9000);
  73. // 220 bytes is currently the cutoff
  74. // (It would be nice to use the IOBuf::kMaxInternalDataSize constant,
  75. // but it's private and it doesn't seem worth making it public just for this
  76. // test code.)
  77. testAllocSize(220);
  78. testAllocSize(219);
  79. testAllocSize(221);
  80. }
  81. void deleteArrayBuffer(void* buf, void* arg) {
  82. uint32_t* deleteCount = static_cast<uint32_t*>(arg);
  83. ++(*deleteCount);
  84. uint8_t* bufPtr = static_cast<uint8_t*>(buf);
  85. delete[] bufPtr;
  86. }
  87. TEST(IOBuf, TakeOwnership) {
  88. uint32_t size1 = 99;
  89. uint8_t* buf1 = static_cast<uint8_t*>(malloc(size1));
  90. unique_ptr<IOBuf> iobuf1(IOBuf::takeOwnership(buf1, size1));
  91. EXPECT_EQ(buf1, iobuf1->data());
  92. EXPECT_EQ(size1, iobuf1->length());
  93. EXPECT_EQ(buf1, iobuf1->buffer());
  94. EXPECT_EQ(size1, iobuf1->capacity());
  95. uint32_t deleteCount = 0;
  96. uint32_t size2 = 4321;
  97. uint8_t* buf2 = new uint8_t[size2];
  98. unique_ptr<IOBuf> iobuf2(
  99. IOBuf::takeOwnership(buf2, size2, deleteArrayBuffer, &deleteCount));
  100. EXPECT_EQ(buf2, iobuf2->data());
  101. EXPECT_EQ(size2, iobuf2->length());
  102. EXPECT_EQ(buf2, iobuf2->buffer());
  103. EXPECT_EQ(size2, iobuf2->capacity());
  104. EXPECT_EQ(0, deleteCount);
  105. iobuf2.reset();
  106. EXPECT_EQ(1, deleteCount);
  107. deleteCount = 0;
  108. uint32_t size3 = 3456;
  109. uint8_t* buf3 = new uint8_t[size3];
  110. uint32_t length3 = 48;
  111. unique_ptr<IOBuf> iobuf3(IOBuf::takeOwnership(
  112. buf3, size3, length3, deleteArrayBuffer, &deleteCount));
  113. EXPECT_EQ(buf3, iobuf3->data());
  114. EXPECT_EQ(length3, iobuf3->length());
  115. EXPECT_EQ(buf3, iobuf3->buffer());
  116. EXPECT_EQ(size3, iobuf3->capacity());
  117. EXPECT_EQ(0, deleteCount);
  118. iobuf3.reset();
  119. EXPECT_EQ(1, deleteCount);
  120. deleteCount = 0;
  121. {
  122. uint32_t size4 = 1234;
  123. uint8_t* buf4 = new uint8_t[size4];
  124. uint32_t length4 = 48;
  125. IOBuf iobuf4(
  126. IOBuf::TAKE_OWNERSHIP,
  127. buf4,
  128. size4,
  129. length4,
  130. deleteArrayBuffer,
  131. &deleteCount);
  132. EXPECT_EQ(buf4, iobuf4.data());
  133. EXPECT_EQ(length4, iobuf4.length());
  134. EXPECT_EQ(buf4, iobuf4.buffer());
  135. EXPECT_EQ(size4, iobuf4.capacity());
  136. IOBuf iobuf5 = std::move(iobuf4);
  137. EXPECT_EQ(buf4, iobuf5.data());
  138. EXPECT_EQ(length4, iobuf5.length());
  139. EXPECT_EQ(buf4, iobuf5.buffer());
  140. EXPECT_EQ(size4, iobuf5.capacity());
  141. EXPECT_EQ(0, deleteCount);
  142. }
  143. EXPECT_EQ(1, deleteCount);
  144. }
  145. TEST(IOBuf, WrapBuffer) {
  146. const uint32_t size1 = 1234;
  147. uint8_t buf1[size1];
  148. unique_ptr<IOBuf> iobuf1(IOBuf::wrapBuffer(buf1, size1));
  149. EXPECT_EQ(buf1, iobuf1->data());
  150. EXPECT_EQ(size1, iobuf1->length());
  151. EXPECT_EQ(buf1, iobuf1->buffer());
  152. EXPECT_EQ(size1, iobuf1->capacity());
  153. uint32_t size2 = 0x1234;
  154. unique_ptr<uint8_t[]> buf2(new uint8_t[size2]);
  155. unique_ptr<IOBuf> iobuf2(IOBuf::wrapBuffer(buf2.get(), size2));
  156. EXPECT_EQ(buf2.get(), iobuf2->data());
  157. EXPECT_EQ(size2, iobuf2->length());
  158. EXPECT_EQ(buf2.get(), iobuf2->buffer());
  159. EXPECT_EQ(size2, iobuf2->capacity());
  160. uint32_t size3 = 4321;
  161. unique_ptr<uint8_t[]> buf3(new uint8_t[size3]);
  162. IOBuf iobuf3(IOBuf::WRAP_BUFFER, buf3.get(), size3);
  163. EXPECT_EQ(buf3.get(), iobuf3.data());
  164. EXPECT_EQ(size3, iobuf3.length());
  165. EXPECT_EQ(buf3.get(), iobuf3.buffer());
  166. EXPECT_EQ(size3, iobuf3.capacity());
  167. const uint32_t size4 = 2345;
  168. unique_ptr<uint8_t[]> buf4(new uint8_t[size4]);
  169. IOBuf iobuf4 = IOBuf::wrapBufferAsValue(buf4.get(), size4);
  170. EXPECT_EQ(buf4.get(), iobuf4.data());
  171. EXPECT_EQ(size4, iobuf4.length());
  172. EXPECT_EQ(buf4.get(), iobuf4.buffer());
  173. EXPECT_EQ(size4, iobuf4.capacity());
  174. }
  175. TEST(IOBuf, CreateCombined) {
  176. // Create a combined IOBuf, then destroy it.
  177. // The data buffer and IOBuf both become unused as part of the destruction
  178. {
  179. auto buf = IOBuf::createCombined(256);
  180. EXPECT_FALSE(buf->isShared());
  181. }
  182. // Create a combined IOBuf, clone from it, and then destroy the original
  183. // IOBuf. The data buffer cannot be deleted until the clone is also
  184. // destroyed.
  185. {
  186. auto bufA = IOBuf::createCombined(256);
  187. EXPECT_FALSE(bufA->isShared());
  188. auto bufB = bufA->clone();
  189. EXPECT_TRUE(bufA->isShared());
  190. EXPECT_TRUE(bufB->isShared());
  191. bufA.reset();
  192. EXPECT_FALSE(bufB->isShared());
  193. }
  194. // Create a combined IOBuf, then call reserve() to get a larger buffer.
  195. // The IOBuf no longer points to the combined data buffer, but the
  196. // overall memory segment cannot be deleted until the IOBuf is also
  197. // destroyed.
  198. {
  199. auto buf = IOBuf::createCombined(256);
  200. buf->reserve(0, buf->capacity() + 100);
  201. }
  202. // Create a combined IOBuf, clone from it, then call unshare() on the original
  203. // buffer. This creates a situation where bufB is pointing at the combined
  204. // buffer associated with bufA, but bufA is now using a different buffer.
  205. auto testSwap = [](bool resetAFirst) {
  206. auto bufA = IOBuf::createCombined(256);
  207. EXPECT_FALSE(bufA->isShared());
  208. auto bufB = bufA->clone();
  209. EXPECT_TRUE(bufA->isShared());
  210. EXPECT_TRUE(bufB->isShared());
  211. bufA->unshare();
  212. EXPECT_FALSE(bufA->isShared());
  213. EXPECT_FALSE(bufB->isShared());
  214. if (resetAFirst) {
  215. bufA.reset();
  216. bufB.reset();
  217. } else {
  218. bufB.reset();
  219. bufA.reset();
  220. }
  221. };
  222. testSwap(true);
  223. testSwap(false);
  224. }
  225. void fillBuf(uint8_t* buf, uint32_t length, boost::mt19937& gen) {
  226. for (uint32_t n = 0; n < length; ++n) {
  227. buf[n] = static_cast<uint8_t>(gen() & 0xff);
  228. }
  229. }
  230. void fillBuf(IOBuf* buf, boost::mt19937& gen) {
  231. buf->unshare();
  232. fillBuf(buf->writableData(), buf->length(), gen);
  233. }
  234. void checkBuf(const uint8_t* buf, uint32_t length, boost::mt19937& gen) {
  235. // Rather than using EXPECT_EQ() to check each character,
  236. // count the number of differences and the first character that differs.
  237. // This way on error we'll report just that information, rather than tons of
  238. // failed checks for each byte in the buffer.
  239. uint32_t numDifferences = 0;
  240. uint32_t firstDiffIndex = 0;
  241. uint8_t firstDiffExpected = 0;
  242. for (uint32_t n = 0; n < length; ++n) {
  243. uint8_t expected = static_cast<uint8_t>(gen() & 0xff);
  244. if (buf[n] == expected) {
  245. continue;
  246. }
  247. if (numDifferences == 0) {
  248. firstDiffIndex = n;
  249. firstDiffExpected = expected;
  250. }
  251. ++numDifferences;
  252. }
  253. EXPECT_EQ(0, numDifferences);
  254. if (numDifferences > 0) {
  255. // Cast to int so it will be printed numerically
  256. // rather than as a char if the check fails
  257. EXPECT_EQ(
  258. static_cast<int>(buf[firstDiffIndex]),
  259. static_cast<int>(firstDiffExpected));
  260. }
  261. }
  262. void checkBuf(IOBuf* buf, boost::mt19937& gen) {
  263. checkBuf(buf->data(), buf->length(), gen);
  264. }
  265. void checkBuf(ByteRange buf, boost::mt19937& gen) {
  266. checkBuf(buf.data(), buf.size(), gen);
  267. }
  268. void checkChain(IOBuf* buf, boost::mt19937& gen) {
  269. IOBuf* current = buf;
  270. do {
  271. checkBuf(current->data(), current->length(), gen);
  272. current = current->next();
  273. } while (current != buf);
  274. }
  275. TEST(IOBuf, Chaining) {
  276. uint32_t fillSeed = 0x12345678;
  277. boost::mt19937 gen(fillSeed);
  278. // An IOBuf with external storage
  279. uint32_t headroom = 123;
  280. unique_ptr<IOBuf> iob1(IOBuf::create(2048));
  281. iob1->advance(headroom);
  282. iob1->append(1500);
  283. fillBuf(iob1.get(), gen);
  284. // An IOBuf with internal storage
  285. unique_ptr<IOBuf> iob2(IOBuf::create(20));
  286. iob2->append(20);
  287. fillBuf(iob2.get(), gen);
  288. // An IOBuf around a buffer it doesn't own
  289. uint8_t localbuf[1234];
  290. fillBuf(localbuf, 1234, gen);
  291. unique_ptr<IOBuf> iob3(IOBuf::wrapBuffer(localbuf, sizeof(localbuf)));
  292. // An IOBuf taking ownership of a user-supplied buffer
  293. uint32_t heapBufSize = 900;
  294. uint8_t* heapBuf = static_cast<uint8_t*>(malloc(heapBufSize));
  295. fillBuf(heapBuf, heapBufSize, gen);
  296. unique_ptr<IOBuf> iob4(IOBuf::takeOwnership(heapBuf, heapBufSize));
  297. // An IOBuf taking ownership of a user-supplied buffer with
  298. // a custom free function
  299. uint32_t arrayBufSize = 321;
  300. uint8_t* arrayBuf = new uint8_t[arrayBufSize];
  301. fillBuf(arrayBuf, arrayBufSize, gen);
  302. uint32_t arrayBufFreeCount = 0;
  303. unique_ptr<IOBuf> iob5(IOBuf::takeOwnership(
  304. arrayBuf, arrayBufSize, deleteArrayBuffer, &arrayBufFreeCount));
  305. EXPECT_FALSE(iob1->isChained());
  306. EXPECT_FALSE(iob2->isChained());
  307. EXPECT_FALSE(iob3->isChained());
  308. EXPECT_FALSE(iob4->isChained());
  309. EXPECT_FALSE(iob5->isChained());
  310. EXPECT_FALSE(iob1->isSharedOne());
  311. EXPECT_FALSE(iob2->isSharedOne());
  312. EXPECT_TRUE(iob3->isSharedOne()); // since we own the buffer
  313. EXPECT_FALSE(iob4->isSharedOne());
  314. EXPECT_FALSE(iob5->isSharedOne());
  315. // Chain the buffers all together
  316. // Since we are going to relinquish ownership of iob2-5 to the chain,
  317. // store raw pointers to them so we can reference them later.
  318. IOBuf* iob2ptr = iob2.get();
  319. IOBuf* iob3ptr = iob3.get();
  320. IOBuf* iob4ptr = iob4.get();
  321. IOBuf* iob5ptr = iob5.get();
  322. iob1->prependChain(std::move(iob2));
  323. iob1->prependChain(std::move(iob4));
  324. iob2ptr->appendChain(std::move(iob3));
  325. iob1->prependChain(std::move(iob5));
  326. EXPECT_EQ(iob2ptr, iob1->next());
  327. EXPECT_EQ(iob3ptr, iob2ptr->next());
  328. EXPECT_EQ(iob4ptr, iob3ptr->next());
  329. EXPECT_EQ(iob5ptr, iob4ptr->next());
  330. EXPECT_EQ(iob1.get(), iob5ptr->next());
  331. EXPECT_EQ(iob5ptr, iob1->prev());
  332. EXPECT_EQ(iob1.get(), iob2ptr->prev());
  333. EXPECT_EQ(iob2ptr, iob3ptr->prev());
  334. EXPECT_EQ(iob3ptr, iob4ptr->prev());
  335. EXPECT_EQ(iob4ptr, iob5ptr->prev());
  336. EXPECT_TRUE(iob1->isChained());
  337. EXPECT_TRUE(iob2ptr->isChained());
  338. EXPECT_TRUE(iob3ptr->isChained());
  339. EXPECT_TRUE(iob4ptr->isChained());
  340. EXPECT_TRUE(iob5ptr->isChained());
  341. std::size_t fullLength =
  342. (iob1->length() + iob2ptr->length() + iob3ptr->length() +
  343. iob4ptr->length() + iob5ptr->length());
  344. EXPECT_EQ(5, iob1->countChainElements());
  345. EXPECT_EQ(fullLength, iob1->computeChainDataLength());
  346. // Since iob3 is shared, the entire buffer should report itself as shared
  347. EXPECT_TRUE(iob1->isShared());
  348. // Unshare just iob3
  349. iob3ptr->unshareOne();
  350. EXPECT_FALSE(iob3ptr->isSharedOne());
  351. // Now everything in the chain should be unshared.
  352. // Check on all members of the chain just for good measure
  353. EXPECT_FALSE(iob1->isShared());
  354. EXPECT_FALSE(iob2ptr->isShared());
  355. EXPECT_FALSE(iob3ptr->isShared());
  356. EXPECT_FALSE(iob4ptr->isShared());
  357. EXPECT_FALSE(iob5ptr->isShared());
  358. // Check iteration
  359. gen.seed(fillSeed);
  360. size_t count = 0;
  361. for (auto buf : *iob1) {
  362. checkBuf(buf, gen);
  363. ++count;
  364. }
  365. EXPECT_EQ(5, count);
  366. // Clone one of the IOBufs in the chain
  367. unique_ptr<IOBuf> iob4clone = iob4ptr->cloneOne();
  368. gen.seed(fillSeed);
  369. checkBuf(iob1.get(), gen);
  370. checkBuf(iob2ptr, gen);
  371. checkBuf(iob3ptr, gen);
  372. checkBuf(iob4clone.get(), gen);
  373. checkBuf(iob5ptr, gen);
  374. EXPECT_TRUE(iob1->isShared());
  375. EXPECT_TRUE(iob2ptr->isShared());
  376. EXPECT_TRUE(iob3ptr->isShared());
  377. EXPECT_TRUE(iob4ptr->isShared());
  378. EXPECT_TRUE(iob5ptr->isShared());
  379. EXPECT_FALSE(iob1->isSharedOne());
  380. EXPECT_FALSE(iob2ptr->isSharedOne());
  381. EXPECT_FALSE(iob3ptr->isSharedOne());
  382. EXPECT_TRUE(iob4ptr->isSharedOne());
  383. EXPECT_FALSE(iob5ptr->isSharedOne());
  384. // Unshare that clone
  385. EXPECT_TRUE(iob4clone->isSharedOne());
  386. iob4clone->unshare();
  387. EXPECT_FALSE(iob4clone->isSharedOne());
  388. EXPECT_FALSE(iob4ptr->isSharedOne());
  389. EXPECT_FALSE(iob1->isShared());
  390. iob4clone.reset();
  391. // Create a clone of a different IOBuf
  392. EXPECT_FALSE(iob1->isShared());
  393. EXPECT_FALSE(iob3ptr->isSharedOne());
  394. unique_ptr<IOBuf> iob3clone = iob3ptr->cloneOne();
  395. gen.seed(fillSeed);
  396. checkBuf(iob1.get(), gen);
  397. checkBuf(iob2ptr, gen);
  398. checkBuf(iob3clone.get(), gen);
  399. checkBuf(iob4ptr, gen);
  400. checkBuf(iob5ptr, gen);
  401. EXPECT_TRUE(iob1->isShared());
  402. EXPECT_TRUE(iob3ptr->isSharedOne());
  403. EXPECT_FALSE(iob1->isSharedOne());
  404. // Delete the clone and make sure the original is unshared
  405. iob3clone.reset();
  406. EXPECT_FALSE(iob1->isShared());
  407. EXPECT_FALSE(iob3ptr->isSharedOne());
  408. // Clone the entire chain
  409. unique_ptr<IOBuf> chainClone = iob1->clone();
  410. // Verify that the data is correct.
  411. EXPECT_EQ(fullLength, chainClone->computeChainDataLength());
  412. gen.seed(fillSeed);
  413. checkChain(chainClone.get(), gen);
  414. // Check that the buffers report sharing correctly
  415. EXPECT_TRUE(chainClone->isShared());
  416. EXPECT_TRUE(iob1->isShared());
  417. EXPECT_TRUE(iob1->isSharedOne());
  418. EXPECT_TRUE(iob2ptr->isSharedOne());
  419. EXPECT_TRUE(iob3ptr->isSharedOne());
  420. EXPECT_TRUE(iob4ptr->isSharedOne());
  421. EXPECT_TRUE(iob5ptr->isSharedOne());
  422. // Unshare the cloned chain
  423. chainClone->unshare();
  424. EXPECT_FALSE(chainClone->isShared());
  425. EXPECT_FALSE(iob1->isShared());
  426. // Make sure the unshared result still has the same data
  427. EXPECT_EQ(fullLength, chainClone->computeChainDataLength());
  428. gen.seed(fillSeed);
  429. checkChain(chainClone.get(), gen);
  430. // Destroy this chain
  431. chainClone.reset();
  432. // Clone a new chain
  433. EXPECT_FALSE(iob1->isShared());
  434. chainClone = iob1->clone();
  435. EXPECT_TRUE(iob1->isShared());
  436. EXPECT_TRUE(chainClone->isShared());
  437. // Delete the original chain
  438. iob1.reset();
  439. EXPECT_FALSE(chainClone->isShared());
  440. // Coalesce the chain
  441. //
  442. // Coalescing this chain will create a new buffer and release the last
  443. // refcount on the original buffers we created. Also make sure
  444. // that arrayBufFreeCount increases to one to indicate that arrayBuf was
  445. // freed.
  446. EXPECT_EQ(5, chainClone->countChainElements());
  447. EXPECT_EQ(0, arrayBufFreeCount);
  448. // Buffer lengths: 1500 20 1234 900 321
  449. // Attempting to gather more data than available should fail
  450. EXPECT_THROW(chainClone->gather(4000), std::overflow_error);
  451. // Coalesce the first 3 buffers
  452. chainClone->gather(1521);
  453. EXPECT_EQ(3, chainClone->countChainElements());
  454. EXPECT_EQ(0, arrayBufFreeCount);
  455. // Make sure the data is still the same after coalescing
  456. EXPECT_EQ(fullLength, chainClone->computeChainDataLength());
  457. gen.seed(fillSeed);
  458. checkChain(chainClone.get(), gen);
  459. // cloneCoalesced
  460. {
  461. auto chainCloneCoalesced = chainClone->cloneCoalesced();
  462. EXPECT_EQ(1, chainCloneCoalesced->countChainElements());
  463. EXPECT_EQ(fullLength, chainCloneCoalesced->computeChainDataLength());
  464. gen.seed(fillSeed);
  465. checkChain(chainCloneCoalesced.get(), gen);
  466. }
  467. // Coalesce the entire chain
  468. chainClone->coalesce();
  469. EXPECT_EQ(1, chainClone->countChainElements());
  470. EXPECT_EQ(1, arrayBufFreeCount);
  471. // Make sure the data is still the same after coalescing
  472. EXPECT_EQ(fullLength, chainClone->computeChainDataLength());
  473. gen.seed(fillSeed);
  474. checkChain(chainClone.get(), gen);
  475. // Make a new chain to test the unlink and pop operations
  476. iob1 = IOBuf::create(1);
  477. iob1->append(1);
  478. IOBuf* iob1ptr = iob1.get();
  479. iob2 = IOBuf::create(3);
  480. iob2->append(3);
  481. iob2ptr = iob2.get();
  482. iob3 = IOBuf::create(5);
  483. iob3->append(5);
  484. iob3ptr = iob3.get();
  485. iob4 = IOBuf::create(7);
  486. iob4->append(7);
  487. iob4ptr = iob4.get();
  488. iob1->appendChain(std::move(iob2));
  489. iob1->prev()->appendChain(std::move(iob3));
  490. iob1->prev()->appendChain(std::move(iob4));
  491. EXPECT_EQ(4, iob1->countChainElements());
  492. EXPECT_EQ(16, iob1->computeChainDataLength());
  493. // Unlink from the middle of the chain
  494. iob3 = iob3ptr->unlink();
  495. EXPECT_TRUE(iob3.get() == iob3ptr);
  496. EXPECT_EQ(3, iob1->countChainElements());
  497. EXPECT_EQ(11, iob1->computeChainDataLength());
  498. // Unlink from the end of the chain
  499. iob4 = iob1->prev()->unlink();
  500. EXPECT_TRUE(iob4.get() == iob4ptr);
  501. EXPECT_EQ(2, iob1->countChainElements());
  502. EXPECT_TRUE(iob1->next() == iob2ptr);
  503. EXPECT_EQ(4, iob1->computeChainDataLength());
  504. // Pop from the front of the chain
  505. iob2 = iob1->pop();
  506. EXPECT_TRUE(iob1.get() == iob1ptr);
  507. EXPECT_EQ(1, iob1->countChainElements());
  508. EXPECT_EQ(1, iob1->computeChainDataLength());
  509. EXPECT_TRUE(iob2.get() == iob2ptr);
  510. EXPECT_EQ(1, iob2->countChainElements());
  511. EXPECT_EQ(3, iob2->computeChainDataLength());
  512. }
  513. void testFreeFn(void* buffer, void* ptr) {
  514. uint32_t* freeCount = static_cast<uint32_t*>(ptr);
  515. ;
  516. delete[] static_cast<uint8_t*>(buffer);
  517. if (freeCount) {
  518. ++(*freeCount);
  519. }
  520. }
  521. TEST(IOBuf, Reserve) {
  522. uint32_t fillSeed = 0x23456789;
  523. boost::mt19937 gen(fillSeed);
  524. // Reserve does nothing if empty and doesn't have to grow the buffer
  525. {
  526. gen.seed(fillSeed);
  527. unique_ptr<IOBuf> iob(IOBuf::create(2000));
  528. EXPECT_EQ(0, iob->headroom());
  529. const void* p1 = iob->buffer();
  530. iob->reserve(5, 15);
  531. EXPECT_LE(5, iob->headroom());
  532. EXPECT_EQ(p1, iob->buffer());
  533. }
  534. // Reserve doesn't reallocate if we have enough total room
  535. {
  536. gen.seed(fillSeed);
  537. unique_ptr<IOBuf> iob(IOBuf::create(2000));
  538. iob->append(100);
  539. fillBuf(iob.get(), gen);
  540. EXPECT_EQ(0, iob->headroom());
  541. EXPECT_EQ(100, iob->length());
  542. const void* p1 = iob->buffer();
  543. const uint8_t* d1 = iob->data();
  544. iob->reserve(100, 1800);
  545. EXPECT_LE(100, iob->headroom());
  546. EXPECT_EQ(p1, iob->buffer());
  547. EXPECT_EQ(d1 + 100, iob->data());
  548. gen.seed(fillSeed);
  549. checkBuf(iob.get(), gen);
  550. }
  551. // Reserve reallocates if we don't have enough total room.
  552. // NOTE that, with jemalloc, we know that this won't reallocate in place
  553. // as the size is less than jemallocMinInPlaceExpanadable
  554. {
  555. gen.seed(fillSeed);
  556. unique_ptr<IOBuf> iob(IOBuf::create(2000));
  557. iob->append(100);
  558. fillBuf(iob.get(), gen);
  559. EXPECT_EQ(0, iob->headroom());
  560. EXPECT_EQ(100, iob->length());
  561. const void* p1 = iob->buffer();
  562. iob->reserve(100, 2512); // allocation sizes are multiples of 256
  563. EXPECT_LE(100, iob->headroom());
  564. if (folly::usingJEMalloc()) {
  565. EXPECT_NE(p1, iob->buffer());
  566. }
  567. gen.seed(fillSeed);
  568. checkBuf(iob.get(), gen);
  569. }
  570. // Test reserve from internal buffer, this used to segfault
  571. {
  572. unique_ptr<IOBuf> iob(IOBuf::create(0));
  573. iob->reserve(0, 2000);
  574. EXPECT_EQ(0, iob->headroom());
  575. EXPECT_LE(2000, iob->tailroom());
  576. }
  577. // Test reserving from a user-allocated buffer.
  578. {
  579. uint8_t* buf = static_cast<uint8_t*>(malloc(100));
  580. auto iob = IOBuf::takeOwnership(buf, 100);
  581. iob->reserve(0, 2000);
  582. EXPECT_EQ(0, iob->headroom());
  583. EXPECT_LE(2000, iob->tailroom());
  584. }
  585. // Test reserving from a user-allocated with a custom free function.
  586. {
  587. uint32_t freeCount{0};
  588. uint8_t* buf = new uint8_t[100];
  589. auto iob = IOBuf::takeOwnership(buf, 100, testFreeFn, &freeCount);
  590. iob->reserve(0, 2000);
  591. EXPECT_EQ(0, iob->headroom());
  592. EXPECT_LE(2000, iob->tailroom());
  593. EXPECT_EQ(1, freeCount);
  594. }
  595. }
  596. TEST(IOBuf, copyBuffer) {
  597. std::string s("hello");
  598. auto buf = IOBuf::copyBuffer(s.data(), s.size(), 1, 2);
  599. EXPECT_EQ(1, buf->headroom());
  600. EXPECT_EQ(
  601. s,
  602. std::string(reinterpret_cast<const char*>(buf->data()), buf->length()));
  603. EXPECT_LE(2, buf->tailroom());
  604. buf = IOBuf::copyBuffer(s, 5, 7);
  605. EXPECT_EQ(5, buf->headroom());
  606. EXPECT_EQ(
  607. s,
  608. std::string(reinterpret_cast<const char*>(buf->data()), buf->length()));
  609. EXPECT_LE(7, buf->tailroom());
  610. std::string empty;
  611. buf = IOBuf::copyBuffer(empty, 3, 6);
  612. EXPECT_EQ(3, buf->headroom());
  613. EXPECT_EQ(0, buf->length());
  614. EXPECT_LE(6, buf->tailroom());
  615. // A stack-allocated version
  616. IOBuf stackBuf(IOBuf::COPY_BUFFER, s, 1, 2);
  617. EXPECT_EQ(1, stackBuf.headroom());
  618. EXPECT_EQ(
  619. s,
  620. std::string(
  621. reinterpret_cast<const char*>(stackBuf.data()), stackBuf.length()));
  622. EXPECT_LE(2, stackBuf.tailroom());
  623. }
  624. TEST(IOBuf, maybeCopyBuffer) {
  625. std::string s("this is a test");
  626. auto buf = IOBuf::maybeCopyBuffer(s, 1, 2);
  627. EXPECT_EQ(1, buf->headroom());
  628. EXPECT_EQ(
  629. s,
  630. std::string(reinterpret_cast<const char*>(buf->data()), buf->length()));
  631. EXPECT_LE(2, buf->tailroom());
  632. std::string empty;
  633. buf = IOBuf::maybeCopyBuffer("", 5, 7);
  634. EXPECT_EQ(nullptr, buf.get());
  635. buf = IOBuf::maybeCopyBuffer("");
  636. EXPECT_EQ(nullptr, buf.get());
  637. }
  638. TEST(IOBuf, copyEmptyBuffer) {
  639. auto buf = IOBuf::copyBuffer(nullptr, 0);
  640. EXPECT_EQ(buf->length(), 0);
  641. }
  642. namespace {
  643. int customDeleterCount = 0;
  644. int destructorCount = 0;
  645. struct OwnershipTestClass {
  646. explicit OwnershipTestClass(int v = 0) : val(v) {}
  647. ~OwnershipTestClass() {
  648. ++destructorCount;
  649. }
  650. int val;
  651. };
  652. typedef std::function<void(OwnershipTestClass*)> CustomDeleter;
  653. void customDelete(OwnershipTestClass* p) {
  654. ++customDeleterCount;
  655. delete p;
  656. }
  657. void customDeleteArray(OwnershipTestClass* p) {
  658. ++customDeleterCount;
  659. delete[] p;
  660. }
  661. } // namespace
  662. TEST(IOBuf, takeOwnershipUniquePtr) {
  663. destructorCount = 0;
  664. { std::unique_ptr<OwnershipTestClass> p(new OwnershipTestClass()); }
  665. EXPECT_EQ(1, destructorCount);
  666. destructorCount = 0;
  667. { std::unique_ptr<OwnershipTestClass[]> p(new OwnershipTestClass[2]); }
  668. EXPECT_EQ(2, destructorCount);
  669. destructorCount = 0;
  670. {
  671. std::unique_ptr<OwnershipTestClass> p(new OwnershipTestClass());
  672. std::unique_ptr<IOBuf> buf(IOBuf::takeOwnership(std::move(p)));
  673. EXPECT_EQ(sizeof(OwnershipTestClass), buf->length());
  674. EXPECT_EQ(0, destructorCount);
  675. }
  676. EXPECT_EQ(1, destructorCount);
  677. destructorCount = 0;
  678. {
  679. std::unique_ptr<OwnershipTestClass[]> p(new OwnershipTestClass[2]);
  680. std::unique_ptr<IOBuf> buf(IOBuf::takeOwnership(std::move(p), 2));
  681. EXPECT_EQ(2 * sizeof(OwnershipTestClass), buf->length());
  682. EXPECT_EQ(0, destructorCount);
  683. }
  684. EXPECT_EQ(2, destructorCount);
  685. customDeleterCount = 0;
  686. destructorCount = 0;
  687. {
  688. std::unique_ptr<OwnershipTestClass, CustomDeleter> p(
  689. new OwnershipTestClass(), customDelete);
  690. std::unique_ptr<IOBuf> buf(IOBuf::takeOwnership(std::move(p)));
  691. EXPECT_EQ(sizeof(OwnershipTestClass), buf->length());
  692. EXPECT_EQ(0, destructorCount);
  693. }
  694. EXPECT_EQ(1, destructorCount);
  695. EXPECT_EQ(1, customDeleterCount);
  696. customDeleterCount = 0;
  697. destructorCount = 0;
  698. {
  699. std::unique_ptr<OwnershipTestClass[], CustomDeleter> p(
  700. new OwnershipTestClass[2], CustomDeleter(customDeleteArray));
  701. std::unique_ptr<IOBuf> buf(IOBuf::takeOwnership(std::move(p), 2));
  702. EXPECT_EQ(2 * sizeof(OwnershipTestClass), buf->length());
  703. EXPECT_EQ(0, destructorCount);
  704. }
  705. EXPECT_EQ(2, destructorCount);
  706. EXPECT_EQ(1, customDeleterCount);
  707. }
  708. TEST(IOBuf, Alignment) {
  709. size_t alignment = alignof(std::max_align_t);
  710. std::vector<size_t> sizes{0, 1, 64, 256, 1024, 1 << 10};
  711. for (size_t size : sizes) {
  712. auto buf = IOBuf::create(size);
  713. uintptr_t p = reinterpret_cast<uintptr_t>(buf->data());
  714. EXPECT_EQ(0, p & (alignment - 1)) << "size=" << size;
  715. }
  716. }
  717. TEST(TypedIOBuf, Simple) {
  718. auto buf = IOBuf::create(0);
  719. TypedIOBuf<std::size_t> typed(buf.get());
  720. const std::size_t n = 10000;
  721. typed.reserve(0, n);
  722. EXPECT_LE(n, typed.capacity());
  723. for (std::size_t i = 0; i < n; i++) {
  724. *typed.writableTail() = i;
  725. typed.append(1);
  726. }
  727. EXPECT_EQ(n, typed.length());
  728. for (std::size_t i = 0; i < n; i++) {
  729. EXPECT_EQ(i, typed.data()[i]);
  730. }
  731. }
  732. enum BufType {
  733. CREATE,
  734. TAKE_OWNERSHIP_MALLOC,
  735. TAKE_OWNERSHIP_CUSTOM,
  736. USER_OWNED,
  737. };
  738. // chain element size, number of elements in chain, shared
  739. class MoveToFbStringTest
  740. : public ::testing::TestWithParam<std::tuple<int, int, bool, BufType>> {
  741. protected:
  742. void SetUp() override {
  743. elementSize_ = std::get<0>(GetParam());
  744. elementCount_ = std::get<1>(GetParam());
  745. shared_ = std::get<2>(GetParam());
  746. type_ = std::get<3>(GetParam());
  747. buf_ = makeBuf();
  748. for (int i = 0; i < elementCount_ - 1; ++i) {
  749. buf_->prependChain(makeBuf());
  750. }
  751. EXPECT_EQ(elementCount_, buf_->countChainElements());
  752. EXPECT_EQ(elementCount_ * elementSize_, buf_->computeChainDataLength());
  753. if (shared_) {
  754. buf2_ = buf_->clone();
  755. EXPECT_EQ(elementCount_, buf2_->countChainElements());
  756. EXPECT_EQ(elementCount_ * elementSize_, buf2_->computeChainDataLength());
  757. }
  758. }
  759. std::unique_ptr<IOBuf> makeBuf() {
  760. unique_ptr<IOBuf> buf;
  761. switch (type_) {
  762. case CREATE:
  763. buf = IOBuf::create(elementSize_);
  764. buf->append(elementSize_);
  765. break;
  766. case TAKE_OWNERSHIP_MALLOC: {
  767. void* data = malloc(elementSize_);
  768. if (!data) {
  769. throw std::bad_alloc();
  770. }
  771. buf = IOBuf::takeOwnership(data, elementSize_);
  772. break;
  773. }
  774. case TAKE_OWNERSHIP_CUSTOM: {
  775. uint8_t* data = new uint8_t[elementSize_];
  776. buf = IOBuf::takeOwnership(data, elementSize_, testFreeFn);
  777. break;
  778. }
  779. case USER_OWNED: {
  780. unique_ptr<uint8_t[]> data(new uint8_t[elementSize_]);
  781. buf = IOBuf::wrapBuffer(data.get(), elementSize_);
  782. ownedBuffers_.emplace_back(std::move(data));
  783. break;
  784. }
  785. default:
  786. throw std::invalid_argument("unexpected buffer type parameter");
  787. }
  788. memset(buf->writableData(), 'x', elementSize_);
  789. return buf;
  790. }
  791. void check(std::unique_ptr<IOBuf>& buf) {
  792. fbstring str = buf->moveToFbString();
  793. EXPECT_EQ(elementCount_ * elementSize_, str.size());
  794. EXPECT_EQ(elementCount_ * elementSize_, strspn(str.c_str(), "x"));
  795. EXPECT_EQ(0, buf->length());
  796. EXPECT_EQ(1, buf->countChainElements());
  797. EXPECT_EQ(0, buf->computeChainDataLength());
  798. EXPECT_FALSE(buf->isChained());
  799. }
  800. int elementSize_;
  801. int elementCount_;
  802. bool shared_;
  803. BufType type_;
  804. std::unique_ptr<IOBuf> buf_;
  805. std::unique_ptr<IOBuf> buf2_;
  806. std::vector<std::unique_ptr<uint8_t[]>> ownedBuffers_;
  807. };
  808. TEST_P(MoveToFbStringTest, Simple) {
  809. check(buf_);
  810. if (shared_) {
  811. check(buf2_);
  812. }
  813. }
  814. INSTANTIATE_TEST_CASE_P(
  815. MoveToFbString,
  816. MoveToFbStringTest,
  817. ::testing::Combine(
  818. ::testing::Values(0, 1, 24, 256, 1 << 10, 1 << 20), // element size
  819. ::testing::Values(1, 2, 10), // element count
  820. ::testing::Bool(), // shared
  821. ::testing::Values(
  822. CREATE,
  823. TAKE_OWNERSHIP_MALLOC,
  824. TAKE_OWNERSHIP_CUSTOM,
  825. USER_OWNED)));
  826. TEST(IOBuf, getIov) {
  827. uint32_t fillSeed = 0xdeadbeef;
  828. boost::mt19937 gen(fillSeed);
  829. size_t len = 4096;
  830. size_t count = 32;
  831. auto buf = IOBuf::create(len + 1);
  832. buf->append(rand() % len + 1);
  833. fillBuf(buf.get(), gen);
  834. for (size_t i = 0; i < count - 1; i++) {
  835. auto buf2 = IOBuf::create(len + 1);
  836. buf2->append(rand() % len + 1);
  837. fillBuf(buf2.get(), gen);
  838. buf->prependChain(std::move(buf2));
  839. }
  840. EXPECT_EQ(count, buf->countChainElements());
  841. auto iov = buf->getIov();
  842. EXPECT_EQ(count, iov.size());
  843. IOBuf const* p = buf.get();
  844. for (size_t i = 0; i < count; i++, p = p->next()) {
  845. EXPECT_EQ(p->data(), iov[i].iov_base);
  846. EXPECT_EQ(p->length(), iov[i].iov_len);
  847. }
  848. // an empty buf should be skipped in the iov.
  849. buf->next()->clear();
  850. iov = buf->getIov();
  851. EXPECT_EQ(count - 1, iov.size());
  852. EXPECT_EQ(buf->next()->next()->data(), iov[1].iov_base);
  853. // same for the first one being empty
  854. buf->clear();
  855. iov = buf->getIov();
  856. EXPECT_EQ(count - 2, iov.size());
  857. EXPECT_EQ(buf->next()->next()->data(), iov[0].iov_base);
  858. // and the last one
  859. buf->prev()->clear();
  860. iov = buf->getIov();
  861. EXPECT_EQ(count - 3, iov.size());
  862. // test appending to an existing iovec array
  863. iov.clear();
  864. const char localBuf[] = "hello";
  865. iov.push_back({(void*)localBuf, sizeof(localBuf)});
  866. iov.push_back({(void*)localBuf, sizeof(localBuf)});
  867. buf->appendToIov(&iov);
  868. EXPECT_EQ(count - 1, iov.size());
  869. EXPECT_EQ(localBuf, iov[0].iov_base);
  870. EXPECT_EQ(localBuf, iov[1].iov_base);
  871. // The first two IOBufs were cleared, so the next iov entry
  872. // should be the third IOBuf in the chain.
  873. EXPECT_EQ(buf->next()->next()->data(), iov[2].iov_base);
  874. }
  875. TEST(IOBuf, wrapIov) {
  876. // Test wrapping IOVs
  877. constexpr folly::StringPiece hello = "hello";
  878. constexpr folly::StringPiece world = "world!";
  879. folly::fbvector<struct iovec> iov;
  880. iov.push_back({nullptr, 0});
  881. iov.push_back({(void*)hello.data(), hello.size()});
  882. iov.push_back({(void*)world.data(), world.size()});
  883. auto wrapped = IOBuf::wrapIov(iov.data(), iov.size());
  884. EXPECT_EQ(iov.size() - 1, wrapped->countChainElements());
  885. IOBuf const* w = wrapped.get();
  886. // skip the first iovec, which is empty/null, as it is ignored by
  887. // IOBuf::wrapIov
  888. for (size_t i = 0; i < wrapped->countChainElements(); ++i, w = w->next()) {
  889. EXPECT_EQ(w->data(), iov[i + 1].iov_base);
  890. EXPECT_EQ(w->length(), iov[i + 1].iov_len);
  891. }
  892. }
  893. TEST(IOBuf, takeOwnershipIov) {
  894. // Test taking IOVs ownership
  895. folly::fbvector<folly::StringPiece> words{"hello", "world!"};
  896. folly::fbvector<struct iovec> iov;
  897. iov.push_back({nullptr, 0});
  898. for (size_t i = 0; i < words.size(); i++) {
  899. iov.push_back({(void*)strdup(words[i].data()), words[i].size() + 1});
  900. }
  901. auto buf = IOBuf::takeOwnershipIov(iov.data(), iov.size());
  902. EXPECT_EQ(iov.size() - 1, buf->countChainElements());
  903. IOBuf const* b = buf.get();
  904. // skip the first iovec, which is empty/null, as it is ignored by
  905. // IOBuf::takeIovOwnership
  906. for (size_t i = 0; i < buf->countChainElements(); ++i, b = b->next()) {
  907. EXPECT_EQ(words[i], static_cast<const char*>(iov[i + 1].iov_base));
  908. }
  909. }
  910. TEST(IOBuf, wrapZeroLenIov) {
  911. folly::fbvector<struct iovec> iov;
  912. iov.push_back({nullptr, 0});
  913. iov.push_back({nullptr, 0});
  914. auto wrapped = IOBuf::wrapIov(iov.data(), iov.size());
  915. EXPECT_NE(nullptr, wrapped);
  916. EXPECT_EQ(wrapped->countChainElements(), 1);
  917. EXPECT_EQ(wrapped->length(), 0);
  918. wrapped = IOBuf::wrapIov(nullptr, 0);
  919. EXPECT_NE(nullptr, wrapped);
  920. EXPECT_EQ(wrapped->countChainElements(), 1);
  921. EXPECT_EQ(wrapped->length(), 0);
  922. }
  923. TEST(IOBuf, move) {
  924. // Default allocate an IOBuf on the stack
  925. IOBuf outerBuf;
  926. char data[] = "foobar";
  927. uint32_t length = sizeof(data);
  928. uint32_t actualCapacity{0};
  929. const void* ptr{nullptr};
  930. {
  931. // Create a small IOBuf on the stack.
  932. // Note that IOBufs created on the stack always use an external buffer.
  933. IOBuf b1(IOBuf::CREATE, 10);
  934. actualCapacity = b1.capacity();
  935. EXPECT_GE(actualCapacity, 10);
  936. EXPECT_EQ(0, b1.length());
  937. EXPECT_FALSE(b1.isShared());
  938. ptr = b1.data();
  939. ASSERT_TRUE(ptr != nullptr);
  940. memcpy(b1.writableTail(), data, length);
  941. b1.append(length);
  942. EXPECT_EQ(length, b1.length());
  943. // Use the move constructor
  944. IOBuf b2(std::move(b1));
  945. EXPECT_EQ(ptr, b2.data());
  946. EXPECT_EQ(length, b2.length());
  947. EXPECT_EQ(actualCapacity, b2.capacity());
  948. EXPECT_FALSE(b2.isShared());
  949. // Use the move assignment operator
  950. outerBuf = std::move(b2);
  951. // Close scope, destroying b1 and b2
  952. // (which are both be invalid now anyway after moving out of them)
  953. }
  954. EXPECT_EQ(ptr, outerBuf.data());
  955. EXPECT_EQ(length, outerBuf.length());
  956. EXPECT_EQ(actualCapacity, outerBuf.capacity());
  957. EXPECT_FALSE(outerBuf.isShared());
  958. }
  959. namespace {
  960. std::unique_ptr<IOBuf> fromStr(StringPiece sp) {
  961. return IOBuf::copyBuffer(ByteRange(sp));
  962. }
  963. std::unique_ptr<IOBuf> seq(std::initializer_list<StringPiece> sps) {
  964. auto ret = IOBuf::create(0);
  965. for (auto sp : sps) {
  966. ret->prependChain(IOBuf::copyBuffer(ByteRange(sp)));
  967. }
  968. return ret;
  969. }
  970. } // namespace
  971. TEST(IOBuf, HashAndEqual) {
  972. folly::IOBufEqualTo eq;
  973. folly::IOBufHash hash;
  974. EXPECT_TRUE(eq(nullptr, nullptr));
  975. EXPECT_EQ(0, hash(nullptr));
  976. auto empty = IOBuf::create(0);
  977. EXPECT_TRUE(eq(*empty, *empty));
  978. EXPECT_TRUE(eq(empty, empty));
  979. EXPECT_FALSE(eq(nullptr, empty));
  980. EXPECT_FALSE(eq(empty, nullptr));
  981. EXPECT_EQ(hash(*empty), hash(empty));
  982. EXPECT_NE(0, hash(empty));
  983. auto a = fromStr("hello");
  984. EXPECT_TRUE(eq(*a, *a));
  985. EXPECT_TRUE(eq(a, a));
  986. EXPECT_FALSE(eq(nullptr, a));
  987. EXPECT_FALSE(eq(a, nullptr));
  988. EXPECT_EQ(hash(*a), hash(a));
  989. EXPECT_NE(0, hash(a));
  990. auto b = fromStr("hello");
  991. EXPECT_TRUE(eq(*a, *b));
  992. EXPECT_TRUE(eq(a, b));
  993. EXPECT_EQ(hash(a), hash(b));
  994. auto c = fromStr("hellow");
  995. EXPECT_FALSE(eq(a, c));
  996. EXPECT_NE(hash(a), hash(c));
  997. auto d = fromStr("world");
  998. EXPECT_FALSE(eq(a, d));
  999. EXPECT_NE(hash(a), hash(d));
  1000. auto e = fromStr("helloworld");
  1001. auto f = fromStr("hello");
  1002. f->prependChain(fromStr("wo"));
  1003. f->prependChain(fromStr("rld"));
  1004. EXPECT_TRUE(eq(e, f));
  1005. EXPECT_EQ(hash(e), hash(f));
  1006. }
  1007. TEST(IOBuf, IOBufCompare) {
  1008. folly::IOBufCompare op;
  1009. auto n = std::unique_ptr<IOBuf>{};
  1010. auto e = IOBuf::create(0);
  1011. auto hello1 = seq({"hello"});
  1012. auto hello2 = seq({"hel", "lo"});
  1013. auto hello3 = seq({"he", "ll", "o"});
  1014. auto hellow = seq({"hellow"});
  1015. auto hellox = seq({"hellox"});
  1016. EXPECT_EQ(ordering::eq, op(n, n));
  1017. EXPECT_EQ(ordering::lt, op(n, e));
  1018. EXPECT_EQ(ordering::gt, op(e, n));
  1019. EXPECT_EQ(ordering::lt, op(e, hello1));
  1020. EXPECT_EQ(ordering::gt, op(hello1, e));
  1021. EXPECT_EQ(ordering::eq, op(hello1, hello1));
  1022. EXPECT_EQ(ordering::eq, op(hello1, hello2));
  1023. EXPECT_EQ(ordering::eq, op(hello1, hello3));
  1024. EXPECT_EQ(ordering::lt, op(hello1, hellow));
  1025. EXPECT_EQ(ordering::gt, op(hellow, hello1));
  1026. EXPECT_EQ(ordering::lt, op(hellow, hellox));
  1027. EXPECT_EQ(ordering::gt, op(hellox, hellow));
  1028. }
  1029. // reserveSlow() had a bug when reallocating the buffer in place. It would
  1030. // preserve old headroom if it's not too much (heuristically) but wouldn't
  1031. // adjust the requested amount of memory to account for that; the end result
  1032. // would be that reserve() would return with less tailroom than requested.
  1033. TEST(IOBuf, ReserveWithHeadroom) {
  1034. // This is assuming jemalloc, where we know that 4096 and 8192 bytes are
  1035. // valid (and consecutive) allocation sizes. We're hoping that our
  1036. // 4096-byte buffer can be expanded in place to 8192 (in practice, this
  1037. // usually happens).
  1038. const char data[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit";
  1039. constexpr size_t reservedSize = 24; // sizeof(SharedInfo)
  1040. // chosen carefully so that the buffer is exactly 4096 bytes
  1041. IOBuf buf(IOBuf::CREATE, 4096 - reservedSize);
  1042. buf.advance(10);
  1043. memcpy(buf.writableData(), data, sizeof(data));
  1044. buf.append(sizeof(data));
  1045. EXPECT_EQ(sizeof(data), buf.length());
  1046. // Grow the buffer (hopefully in place); this would incorrectly reserve
  1047. // the 10 bytes of headroom, giving us 10 bytes less than requested.
  1048. size_t tailroom = 8192 - reservedSize - sizeof(data);
  1049. buf.reserve(0, tailroom);
  1050. EXPECT_LE(tailroom, buf.tailroom());
  1051. EXPECT_EQ(sizeof(data), buf.length());
  1052. EXPECT_EQ(0, memcmp(data, buf.data(), sizeof(data)));
  1053. }
  1054. TEST(IOBuf, CopyConstructorAndAssignmentOperator) {
  1055. auto buf = IOBuf::create(4096);
  1056. append(buf, "hello world");
  1057. auto buf2 = IOBuf::create(4096);
  1058. append(buf2, " goodbye");
  1059. buf->prependChain(std::move(buf2));
  1060. EXPECT_FALSE(buf->isShared());
  1061. {
  1062. auto copy = *buf;
  1063. EXPECT_TRUE(buf->isShared());
  1064. EXPECT_TRUE(copy.isShared());
  1065. EXPECT_EQ((void*)buf->data(), (void*)copy.data());
  1066. EXPECT_NE(buf->next(), copy.next()); // actually different buffers
  1067. auto copy2 = *buf;
  1068. copy2.coalesce();
  1069. EXPECT_TRUE(buf->isShared());
  1070. EXPECT_TRUE(copy.isShared());
  1071. EXPECT_FALSE(copy2.isShared());
  1072. auto p = reinterpret_cast<const char*>(copy2.data());
  1073. EXPECT_EQ("hello world goodbye", std::string(p, copy2.length()));
  1074. }
  1075. EXPECT_FALSE(buf->isShared());
  1076. {
  1077. folly::IOBuf newBuf(folly::IOBuf::CREATE, 4096);
  1078. EXPECT_FALSE(newBuf.isShared());
  1079. auto newBufCopy = newBuf;
  1080. EXPECT_TRUE(newBuf.isShared());
  1081. EXPECT_TRUE(newBufCopy.isShared());
  1082. newBufCopy = *buf;
  1083. EXPECT_TRUE(buf->isShared());
  1084. EXPECT_FALSE(newBuf.isShared());
  1085. EXPECT_TRUE(newBufCopy.isShared());
  1086. }
  1087. EXPECT_FALSE(buf->isShared());
  1088. }
  1089. TEST(IOBuf, CloneAsValue) {
  1090. auto buf = IOBuf::create(4096);
  1091. append(buf, "hello world");
  1092. {
  1093. auto buf2 = IOBuf::create(4096);
  1094. append(buf2, " goodbye");
  1095. buf->prependChain(std::move(buf2));
  1096. EXPECT_FALSE(buf->isShared());
  1097. }
  1098. {
  1099. auto copy = buf->cloneOneAsValue();
  1100. EXPECT_TRUE(buf->isShared());
  1101. EXPECT_TRUE(copy.isShared());
  1102. EXPECT_EQ((void*)buf->data(), (void*)copy.data());
  1103. EXPECT_TRUE(buf->isChained());
  1104. EXPECT_FALSE(copy.isChained());
  1105. auto copy2 = buf->cloneAsValue();
  1106. EXPECT_TRUE(buf->isShared());
  1107. EXPECT_TRUE(copy.isShared());
  1108. EXPECT_TRUE(copy2.isShared());
  1109. EXPECT_TRUE(buf->isChained());
  1110. EXPECT_TRUE(copy2.isChained());
  1111. copy.unshareOne();
  1112. EXPECT_TRUE(buf->isShared());
  1113. EXPECT_FALSE(copy.isShared());
  1114. EXPECT_NE((void*)buf->data(), (void*)copy.data());
  1115. EXPECT_TRUE(copy2.isShared());
  1116. auto p = reinterpret_cast<const char*>(copy.data());
  1117. EXPECT_EQ("hello world", std::string(p, copy.length()));
  1118. copy2.coalesce();
  1119. EXPECT_FALSE(buf->isShared());
  1120. EXPECT_FALSE(copy.isShared());
  1121. EXPECT_FALSE(copy2.isShared());
  1122. EXPECT_FALSE(copy2.isChained());
  1123. auto p2 = reinterpret_cast<const char*>(copy2.data());
  1124. EXPECT_EQ("hello world goodbye", std::string(p2, copy2.length()));
  1125. }
  1126. EXPECT_FALSE(buf->isShared());
  1127. }
  1128. namespace {
  1129. // Use with string literals only
  1130. std::unique_ptr<IOBuf> wrap(const char* str) {
  1131. return IOBuf::wrapBuffer(str, strlen(str));
  1132. }
  1133. std::unique_ptr<IOBuf> copy(const char* str) {
  1134. // At least 1KiB of tailroom, to ensure an external buffer
  1135. return IOBuf::copyBuffer(str, strlen(str), 0, 1024);
  1136. }
  1137. std::string toString(const folly::IOBuf& buf) {
  1138. std::string result;
  1139. result.reserve(buf.computeChainDataLength());
  1140. for (auto& b : buf) {
  1141. result.append(reinterpret_cast<const char*>(b.data()), b.size());
  1142. }
  1143. return result;
  1144. }
  1145. char* writableStr(folly::IOBuf& buf) {
  1146. return reinterpret_cast<char*>(buf.writableData());
  1147. }
  1148. } // namespace
  1149. TEST(IOBuf, ExternallyShared) {
  1150. struct Item {
  1151. Item(const char* src, size_t len) : size(len) {
  1152. CHECK_LE(len, sizeof(buffer));
  1153. memcpy(buffer, src, len);
  1154. }
  1155. uint32_t refcount{0};
  1156. uint8_t size;
  1157. char buffer[256];
  1158. };
  1159. auto hello = "hello";
  1160. struct Item it(hello, strlen(hello));
  1161. {
  1162. auto freeFn = [](void* /* unused */, void* userData) {
  1163. auto it2 = static_cast<struct Item*>(userData);
  1164. it2->refcount--;
  1165. };
  1166. it.refcount++;
  1167. auto buf1 = IOBuf::takeOwnership(it.buffer, it.size, freeFn, &it);
  1168. EXPECT_TRUE(buf1->isManagedOne());
  1169. EXPECT_FALSE(buf1->isSharedOne());
  1170. buf1->markExternallyShared();
  1171. EXPECT_TRUE(buf1->isSharedOne());
  1172. {
  1173. auto buf2 = buf1->clone();
  1174. EXPECT_TRUE(buf2->isManagedOne());
  1175. EXPECT_TRUE(buf2->isSharedOne());
  1176. EXPECT_EQ(buf1->data(), buf2->data());
  1177. EXPECT_EQ(it.refcount, 1);
  1178. }
  1179. EXPECT_EQ(it.refcount, 1);
  1180. }
  1181. EXPECT_EQ(it.refcount, 0);
  1182. }
  1183. TEST(IOBuf, Managed) {
  1184. auto hello = "hello";
  1185. auto buf1UP = wrap(hello);
  1186. auto buf1 = buf1UP.get();
  1187. EXPECT_FALSE(buf1->isManagedOne());
  1188. auto buf2UP = copy("world");
  1189. auto buf2 = buf2UP.get();
  1190. EXPECT_TRUE(buf2->isManagedOne());
  1191. auto buf3UP = wrap(hello);
  1192. auto buf3 = buf3UP.get();
  1193. auto buf4UP = buf2->clone();
  1194. auto buf4 = buf4UP.get();
  1195. // buf1 and buf3 share the same memory (but are unmanaged)
  1196. EXPECT_FALSE(buf1->isManagedOne());
  1197. EXPECT_FALSE(buf3->isManagedOne());
  1198. EXPECT_TRUE(buf1->isSharedOne());
  1199. EXPECT_TRUE(buf3->isSharedOne());
  1200. EXPECT_EQ(buf1->data(), buf3->data());
  1201. // buf2 and buf4 share the same memory (but are managed)
  1202. EXPECT_TRUE(buf2->isManagedOne());
  1203. EXPECT_TRUE(buf4->isManagedOne());
  1204. EXPECT_TRUE(buf2->isSharedOne());
  1205. EXPECT_TRUE(buf4->isSharedOne());
  1206. EXPECT_EQ(buf2->data(), buf4->data());
  1207. buf1->prependChain(std::move(buf2UP));
  1208. buf1->prependChain(std::move(buf3UP));
  1209. buf1->prependChain(std::move(buf4UP));
  1210. EXPECT_EQ("helloworldhelloworld", toString(*buf1));
  1211. EXPECT_FALSE(buf1->isManaged());
  1212. buf1->makeManaged();
  1213. EXPECT_TRUE(buf1->isManaged());
  1214. // buf1 and buf3 are now unshared (because they were unmanaged)
  1215. EXPECT_TRUE(buf1->isManagedOne());
  1216. EXPECT_TRUE(buf3->isManagedOne());
  1217. EXPECT_FALSE(buf1->isSharedOne());
  1218. EXPECT_FALSE(buf3->isSharedOne());
  1219. EXPECT_NE(buf1->data(), buf3->data());
  1220. // buf2 and buf4 are still shared
  1221. EXPECT_TRUE(buf2->isManagedOne());
  1222. EXPECT_TRUE(buf4->isManagedOne());
  1223. EXPECT_TRUE(buf2->isSharedOne());
  1224. EXPECT_TRUE(buf4->isSharedOne());
  1225. EXPECT_EQ(buf2->data(), buf4->data());
  1226. // And verify that the truth is what we expect: modify a byte in buf1 and
  1227. // buf2, see that the change from buf1 is *not* reflected in buf3, but the
  1228. // change from buf2 is reflected in buf4.
  1229. writableStr(*buf1)[0] = 'j';
  1230. writableStr(*buf2)[0] = 'x';
  1231. EXPECT_EQ("jelloxorldhelloxorld", toString(*buf1));
  1232. }
  1233. TEST(IOBuf, CoalesceEmptyBuffers) {
  1234. auto b1 = IOBuf::takeOwnership(nullptr, 0);
  1235. auto b2 = fromStr("hello");
  1236. auto b3 = IOBuf::takeOwnership(nullptr, 0);
  1237. b2->appendChain(std::move(b3));
  1238. b1->appendChain(std::move(b2));
  1239. auto br = b1->coalesce();
  1240. EXPECT_TRUE(ByteRange(StringPiece("hello")) == br);
  1241. }
  1242. TEST(IOBuf, CloneCoalescedChain) {
  1243. auto b = IOBuf::createChain(1000, 100);
  1244. b->advance(10);
  1245. const uint32_t fillSeed = 0x12345678;
  1246. boost::mt19937 gen(fillSeed);
  1247. {
  1248. auto c = b.get();
  1249. std::size_t length = c->tailroom();
  1250. do {
  1251. length = std::min(length, c->tailroom());
  1252. c->append(length--);
  1253. fillBuf(c, gen);
  1254. c = c->next();
  1255. } while (c != b.get());
  1256. }
  1257. auto c = b->cloneCoalescedAsValue();
  1258. EXPECT_FALSE(c.isChained()); // Not chained
  1259. EXPECT_FALSE(c.isSharedOne()); // Not shared
  1260. EXPECT_EQ(b->headroom(), c.headroom()); // Preserves headroom
  1261. EXPECT_LE(b->prev()->tailroom(), c.tailroom()); // Preserves minimum tailroom
  1262. EXPECT_EQ(b->computeChainDataLength(), c.length()); // Same length
  1263. gen.seed(fillSeed);
  1264. checkBuf(&c, gen); // Same contents
  1265. }
  1266. TEST(IOBuf, CloneCoalescedSingle) {
  1267. auto b = IOBuf::create(1000);
  1268. b->advance(10);
  1269. b->append(900);
  1270. const uint32_t fillSeed = 0x12345678;
  1271. boost::mt19937 gen(fillSeed);
  1272. fillBuf(b.get(), gen);
  1273. auto c = b->cloneCoalesced();
  1274. EXPECT_FALSE(c->isChained()); // Not chained
  1275. EXPECT_TRUE(c->isSharedOne()); // Shared
  1276. EXPECT_EQ(b->buffer(), c->buffer());
  1277. EXPECT_EQ(b->capacity(), c->capacity());
  1278. EXPECT_EQ(b->data(), c->data());
  1279. EXPECT_EQ(b->length(), c->length());
  1280. }