test_buffers.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. /* Copyright (c) 2001-2004, Roger Dingledine.
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2013, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. #define BUFFERS_PRIVATE
  6. #include "or.h"
  7. #include "buffers.h"
  8. #include "ext_orport.h"
  9. #include "test.h"
  10. /** Run unit tests for buffers.c */
  11. static void
  12. test_buffers_basic(void *arg)
  13. {
  14. char str[256];
  15. char str2[256];
  16. buf_t *buf = NULL, *buf2 = NULL;
  17. const char *cp;
  18. int j;
  19. size_t r;
  20. (void) arg;
  21. /****
  22. * buf_new
  23. ****/
  24. if (!(buf = buf_new()))
  25. test_fail();
  26. //test_eq(buf_capacity(buf), 4096);
  27. test_eq(buf_datalen(buf), 0);
  28. /****
  29. * General pointer frobbing
  30. */
  31. for (j=0;j<256;++j) {
  32. str[j] = (char)j;
  33. }
  34. write_to_buf(str, 256, buf);
  35. write_to_buf(str, 256, buf);
  36. test_eq(buf_datalen(buf), 512);
  37. fetch_from_buf(str2, 200, buf);
  38. test_memeq(str, str2, 200);
  39. test_eq(buf_datalen(buf), 312);
  40. memset(str2, 0, sizeof(str2));
  41. fetch_from_buf(str2, 256, buf);
  42. test_memeq(str+200, str2, 56);
  43. test_memeq(str, str2+56, 200);
  44. test_eq(buf_datalen(buf), 56);
  45. memset(str2, 0, sizeof(str2));
  46. /* Okay, now we should be 512 bytes into the 4096-byte buffer. If we add
  47. * another 3584 bytes, we hit the end. */
  48. for (j=0;j<15;++j) {
  49. write_to_buf(str, 256, buf);
  50. }
  51. assert_buf_ok(buf);
  52. test_eq(buf_datalen(buf), 3896);
  53. fetch_from_buf(str2, 56, buf);
  54. test_eq(buf_datalen(buf), 3840);
  55. test_memeq(str+200, str2, 56);
  56. for (j=0;j<15;++j) {
  57. memset(str2, 0, sizeof(str2));
  58. fetch_from_buf(str2, 256, buf);
  59. test_memeq(str, str2, 256);
  60. }
  61. test_eq(buf_datalen(buf), 0);
  62. buf_free(buf);
  63. buf = NULL;
  64. /* Okay, now make sure growing can work. */
  65. buf = buf_new_with_capacity(16);
  66. //test_eq(buf_capacity(buf), 16);
  67. write_to_buf(str+1, 255, buf);
  68. //test_eq(buf_capacity(buf), 256);
  69. fetch_from_buf(str2, 254, buf);
  70. test_memeq(str+1, str2, 254);
  71. //test_eq(buf_capacity(buf), 256);
  72. assert_buf_ok(buf);
  73. write_to_buf(str, 32, buf);
  74. //test_eq(buf_capacity(buf), 256);
  75. assert_buf_ok(buf);
  76. write_to_buf(str, 256, buf);
  77. assert_buf_ok(buf);
  78. //test_eq(buf_capacity(buf), 512);
  79. test_eq(buf_datalen(buf), 33+256);
  80. fetch_from_buf(str2, 33, buf);
  81. test_eq(*str2, str[255]);
  82. test_memeq(str2+1, str, 32);
  83. //test_eq(buf_capacity(buf), 512);
  84. test_eq(buf_datalen(buf), 256);
  85. fetch_from_buf(str2, 256, buf);
  86. test_memeq(str, str2, 256);
  87. /* now try shrinking: case 1. */
  88. buf_free(buf);
  89. buf = buf_new_with_capacity(33668);
  90. for (j=0;j<67;++j) {
  91. write_to_buf(str,255, buf);
  92. }
  93. //test_eq(buf_capacity(buf), 33668);
  94. test_eq(buf_datalen(buf), 17085);
  95. for (j=0; j < 40; ++j) {
  96. fetch_from_buf(str2, 255,buf);
  97. test_memeq(str2, str, 255);
  98. }
  99. /* now try shrinking: case 2. */
  100. buf_free(buf);
  101. buf = buf_new_with_capacity(33668);
  102. for (j=0;j<67;++j) {
  103. write_to_buf(str,255, buf);
  104. }
  105. for (j=0; j < 20; ++j) {
  106. fetch_from_buf(str2, 255,buf);
  107. test_memeq(str2, str, 255);
  108. }
  109. for (j=0;j<80;++j) {
  110. write_to_buf(str,255, buf);
  111. }
  112. //test_eq(buf_capacity(buf),33668);
  113. for (j=0; j < 120; ++j) {
  114. fetch_from_buf(str2, 255,buf);
  115. test_memeq(str2, str, 255);
  116. }
  117. /* Move from buf to buf. */
  118. buf_free(buf);
  119. buf = buf_new_with_capacity(4096);
  120. buf2 = buf_new_with_capacity(4096);
  121. for (j=0;j<100;++j)
  122. write_to_buf(str, 255, buf);
  123. test_eq(buf_datalen(buf), 25500);
  124. for (j=0;j<100;++j) {
  125. r = 10;
  126. move_buf_to_buf(buf2, buf, &r);
  127. test_eq(r, 0);
  128. }
  129. test_eq(buf_datalen(buf), 24500);
  130. test_eq(buf_datalen(buf2), 1000);
  131. for (j=0;j<3;++j) {
  132. fetch_from_buf(str2, 255, buf2);
  133. test_memeq(str2, str, 255);
  134. }
  135. r = 8192; /*big move*/
  136. move_buf_to_buf(buf2, buf, &r);
  137. test_eq(r, 0);
  138. r = 30000; /* incomplete move */
  139. move_buf_to_buf(buf2, buf, &r);
  140. test_eq(r, 13692);
  141. for (j=0;j<97;++j) {
  142. fetch_from_buf(str2, 255, buf2);
  143. test_memeq(str2, str, 255);
  144. }
  145. buf_free(buf);
  146. buf_free(buf2);
  147. buf = buf2 = NULL;
  148. buf = buf_new_with_capacity(5);
  149. cp = "Testing. This is a moderately long Testing string.";
  150. for (j = 0; cp[j]; j++)
  151. write_to_buf(cp+j, 1, buf);
  152. test_eq(0, buf_find_string_offset(buf, "Testing", 7));
  153. test_eq(1, buf_find_string_offset(buf, "esting", 6));
  154. test_eq(1, buf_find_string_offset(buf, "est", 3));
  155. test_eq(39, buf_find_string_offset(buf, "ing str", 7));
  156. test_eq(35, buf_find_string_offset(buf, "Testing str", 11));
  157. test_eq(32, buf_find_string_offset(buf, "ng ", 3));
  158. test_eq(43, buf_find_string_offset(buf, "string.", 7));
  159. test_eq(-1, buf_find_string_offset(buf, "shrdlu", 6));
  160. test_eq(-1, buf_find_string_offset(buf, "Testing thing", 13));
  161. test_eq(-1, buf_find_string_offset(buf, "ngx", 3));
  162. buf_free(buf);
  163. buf = NULL;
  164. /* Try adding a string too long for any freelist. */
  165. {
  166. char *cp = tor_malloc_zero(65536);
  167. buf = buf_new();
  168. write_to_buf(cp, 65536, buf);
  169. tor_free(cp);
  170. tt_int_op(buf_datalen(buf), ==, 65536);
  171. buf_free(buf);
  172. buf = NULL;
  173. }
  174. done:
  175. if (buf)
  176. buf_free(buf);
  177. if (buf2)
  178. buf_free(buf2);
  179. buf_shrink_freelists(1);
  180. }
  181. static void
  182. test_buffer_pullup(void *arg)
  183. {
  184. buf_t *buf;
  185. char *stuff, *tmp;
  186. const char *cp;
  187. size_t sz;
  188. (void)arg;
  189. stuff = tor_malloc(16384);
  190. tmp = tor_malloc(16384);
  191. /* Note: this test doesn't check the nulterminate argument to buf_pullup,
  192. since nothing actually uses it. We should remove it some time. */
  193. buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  194. tt_assert(buf);
  195. tt_int_op(buf_get_default_chunk_size(buf), ==, 4096);
  196. tt_int_op(buf_get_total_allocation(), ==, 0);
  197. /* There are a bunch of cases for pullup. One is the trivial case. Let's
  198. mess around with an empty buffer. */
  199. buf_pullup(buf, 16, 1);
  200. buf_get_first_chunk_data(buf, &cp, &sz);
  201. tt_ptr_op(cp, ==, NULL);
  202. tt_uint_op(sz, ==, 0);
  203. /* Let's make sure nothing got allocated */
  204. tt_int_op(buf_get_total_allocation(), ==, 0);
  205. /* Case 1: everything puts into the first chunk with some moving. */
  206. /* Let's add some data. */
  207. crypto_rand(stuff, 16384);
  208. write_to_buf(stuff, 3000, buf);
  209. write_to_buf(stuff+3000, 3000, buf);
  210. buf_get_first_chunk_data(buf, &cp, &sz);
  211. tt_ptr_op(cp, !=, NULL);
  212. tt_int_op(sz, <=, 4096);
  213. /* Make room for 3000 bytes in the first chunk, so that the pullup-move code
  214. * can get tested. */
  215. tt_int_op(fetch_from_buf(tmp, 3000, buf), ==, 3000);
  216. test_memeq(tmp, stuff, 3000);
  217. buf_pullup(buf, 2048, 0);
  218. assert_buf_ok(buf);
  219. buf_get_first_chunk_data(buf, &cp, &sz);
  220. tt_ptr_op(cp, !=, NULL);
  221. tt_int_op(sz, >=, 2048);
  222. test_memeq(cp, stuff+3000, 2048);
  223. tt_int_op(3000, ==, buf_datalen(buf));
  224. tt_int_op(fetch_from_buf(tmp, 3000, buf), ==, 0);
  225. test_memeq(tmp, stuff+3000, 2048);
  226. buf_free(buf);
  227. /* Now try the large-chunk case. */
  228. buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  229. write_to_buf(stuff, 4000, buf);
  230. write_to_buf(stuff+4000, 4000, buf);
  231. write_to_buf(stuff+8000, 4000, buf);
  232. write_to_buf(stuff+12000, 4000, buf);
  233. tt_int_op(buf_datalen(buf), ==, 16000);
  234. buf_get_first_chunk_data(buf, &cp, &sz);
  235. tt_ptr_op(cp, !=, NULL);
  236. tt_int_op(sz, <=, 4096);
  237. buf_pullup(buf, 12500, 0);
  238. assert_buf_ok(buf);
  239. buf_get_first_chunk_data(buf, &cp, &sz);
  240. tt_ptr_op(cp, !=, NULL);
  241. tt_int_op(sz, >=, 12500);
  242. test_memeq(cp, stuff, 12500);
  243. tt_int_op(buf_datalen(buf), ==, 16000);
  244. fetch_from_buf(tmp, 12400, buf);
  245. test_memeq(tmp, stuff, 12400);
  246. tt_int_op(buf_datalen(buf), ==, 3600);
  247. fetch_from_buf(tmp, 3500, buf);
  248. test_memeq(tmp, stuff+12400, 3500);
  249. fetch_from_buf(tmp, 100, buf);
  250. test_memeq(tmp, stuff+15900, 10);
  251. buf_free(buf);
  252. /* Make sure that the pull-up-whole-buffer case works */
  253. buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  254. write_to_buf(stuff, 4000, buf);
  255. write_to_buf(stuff+4000, 4000, buf);
  256. fetch_from_buf(tmp, 100, buf); /* dump 100 bytes from first chunk */
  257. buf_pullup(buf, 16000, 0); /* Way too much. */
  258. assert_buf_ok(buf);
  259. buf_get_first_chunk_data(buf, &cp, &sz);
  260. tt_ptr_op(cp, !=, NULL);
  261. tt_int_op(sz, ==, 7900);
  262. test_memeq(cp, stuff+100, 7900);
  263. buf_free(buf);
  264. buf = NULL;
  265. buf_shrink_freelists(1);
  266. tt_int_op(buf_get_total_allocation(), ==, 0);
  267. done:
  268. buf_free(buf);
  269. buf_shrink_freelists(1);
  270. tor_free(stuff);
  271. tor_free(tmp);
  272. }
  273. static void
  274. test_buffer_copy(void *arg)
  275. {
  276. generic_buffer_t *buf=NULL, *buf2=NULL;
  277. const char *s;
  278. size_t len;
  279. char b[256];
  280. int i;
  281. (void)arg;
  282. buf = generic_buffer_new();
  283. tt_assert(buf);
  284. /* Copy an empty buffer. */
  285. tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
  286. tt_assert(buf2);
  287. tt_int_op(0, ==, generic_buffer_len(buf2));
  288. /* Now try with a short buffer. */
  289. s = "And now comes an act of enormous enormance!";
  290. len = strlen(s);
  291. generic_buffer_add(buf, s, len);
  292. tt_int_op(len, ==, generic_buffer_len(buf));
  293. /* Add junk to buf2 so we can test replacing.*/
  294. generic_buffer_add(buf2, "BLARG", 5);
  295. tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
  296. tt_int_op(len, ==, generic_buffer_len(buf2));
  297. generic_buffer_get(buf2, b, len);
  298. test_mem_op(b, ==, s, len);
  299. /* Now free buf2 and retry so we can test allocating */
  300. generic_buffer_free(buf2);
  301. buf2 = NULL;
  302. tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
  303. tt_int_op(len, ==, generic_buffer_len(buf2));
  304. generic_buffer_get(buf2, b, len);
  305. test_mem_op(b, ==, s, len);
  306. /* Clear buf for next test */
  307. generic_buffer_get(buf, b, len);
  308. tt_int_op(generic_buffer_len(buf),==,0);
  309. /* Okay, now let's try a bigger buffer. */
  310. s = "Quis autem vel eum iure reprehenderit qui in ea voluptate velit "
  311. "esse quam nihil molestiae consequatur, vel illum qui dolorem eum "
  312. "fugiat quo voluptas nulla pariatur?";
  313. len = strlen(s);
  314. for (i = 0; i < 256; ++i) {
  315. b[0]=i;
  316. generic_buffer_add(buf, b, 1);
  317. generic_buffer_add(buf, s, len);
  318. }
  319. tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
  320. tt_int_op(generic_buffer_len(buf2), ==, generic_buffer_len(buf));
  321. for (i = 0; i < 256; ++i) {
  322. generic_buffer_get(buf2, b, len+1);
  323. tt_int_op((unsigned char)b[0],==,i);
  324. test_mem_op(b+1, ==, s, len);
  325. }
  326. done:
  327. if (buf)
  328. generic_buffer_free(buf);
  329. if (buf2)
  330. generic_buffer_free(buf2);
  331. buf_shrink_freelists(1);
  332. }
  333. static void
  334. test_buffer_ext_or_cmd(void *arg)
  335. {
  336. ext_or_cmd_t *cmd = NULL;
  337. generic_buffer_t *buf = generic_buffer_new();
  338. char *tmp = NULL;
  339. (void) arg;
  340. /* Empty -- should give "not there. */
  341. tt_int_op(0, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
  342. tt_ptr_op(NULL, ==, cmd);
  343. /* Three bytes: shouldn't work. */
  344. generic_buffer_add(buf, "\x00\x20\x00", 3);
  345. tt_int_op(0, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
  346. tt_ptr_op(NULL, ==, cmd);
  347. tt_int_op(3, ==, generic_buffer_len(buf));
  348. /* 0020 0000: That's a nil command. It should work. */
  349. generic_buffer_add(buf, "\x00", 1);
  350. tt_int_op(1, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
  351. tt_ptr_op(NULL, !=, cmd);
  352. tt_int_op(0x20, ==, cmd->cmd);
  353. tt_int_op(0, ==, cmd->len);
  354. tt_int_op(0, ==, generic_buffer_len(buf));
  355. ext_or_cmd_free(cmd);
  356. cmd = NULL;
  357. /* Now try a length-6 command with one byte missing. */
  358. generic_buffer_add(buf, "\x10\x21\x00\x06""abcde", 9);
  359. tt_int_op(0, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
  360. tt_ptr_op(NULL, ==, cmd);
  361. generic_buffer_add(buf, "f", 1);
  362. tt_int_op(1, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
  363. tt_ptr_op(NULL, !=, cmd);
  364. tt_int_op(0x1021, ==, cmd->cmd);
  365. tt_int_op(6, ==, cmd->len);
  366. test_mem_op("abcdef", ==, cmd->body, 6);
  367. tt_int_op(0, ==, generic_buffer_len(buf));
  368. ext_or_cmd_free(cmd);
  369. cmd = NULL;
  370. /* Now try a length-10 command with 4 extra bytes. */
  371. generic_buffer_add(buf, "\xff\xff\x00\x0a"
  372. "loremipsum\x10\x00\xff\xff", 18);
  373. tt_int_op(1, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
  374. tt_ptr_op(NULL, !=, cmd);
  375. tt_int_op(0xffff, ==, cmd->cmd);
  376. tt_int_op(10, ==, cmd->len);
  377. test_mem_op("loremipsum", ==, cmd->body, 10);
  378. tt_int_op(4, ==, generic_buffer_len(buf));
  379. ext_or_cmd_free(cmd);
  380. cmd = NULL;
  381. /* Finally, let's try a maximum-length command. We already have the header
  382. * waiting. */
  383. tt_int_op(0, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
  384. tmp = tor_malloc_zero(65535);
  385. generic_buffer_add(buf, tmp, 65535);
  386. tt_int_op(1, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
  387. tt_ptr_op(NULL, !=, cmd);
  388. tt_int_op(0x1000, ==, cmd->cmd);
  389. tt_int_op(0xffff, ==, cmd->len);
  390. test_mem_op(tmp, ==, cmd->body, 65535);
  391. tt_int_op(0, ==, generic_buffer_len(buf));
  392. ext_or_cmd_free(cmd);
  393. cmd = NULL;
  394. done:
  395. ext_or_cmd_free(cmd);
  396. generic_buffer_free(buf);
  397. tor_free(tmp);
  398. buf_shrink_freelists(1);
  399. }
  400. static void
  401. test_buffer_allocation_tracking(void *arg)
  402. {
  403. char *junk = tor_malloc(16384);
  404. buf_t *buf1 = NULL, *buf2 = NULL;
  405. int i;
  406. (void)arg;
  407. crypto_rand(junk, 16384);
  408. tt_int_op(buf_get_total_allocation(), ==, 0);
  409. buf1 = buf_new();
  410. tt_assert(buf1);
  411. buf2 = buf_new();
  412. tt_assert(buf2);
  413. tt_int_op(buf_allocation(buf1), ==, 0);
  414. tt_int_op(buf_get_total_allocation(), ==, 0);
  415. write_to_buf(junk, 4000, buf1);
  416. write_to_buf(junk, 4000, buf1);
  417. write_to_buf(junk, 4000, buf1);
  418. write_to_buf(junk, 4000, buf1);
  419. tt_int_op(buf_allocation(buf1), ==, 16384);
  420. fetch_from_buf(junk, 100, buf1);
  421. tt_int_op(buf_allocation(buf1), ==, 16384); /* still 4 4k chunks */
  422. tt_int_op(buf_get_total_allocation(), ==, 16384);
  423. fetch_from_buf(junk, 4096, buf1); /* drop a 1k chunk... */
  424. tt_int_op(buf_allocation(buf1), ==, 3*4096); /* now 3 4k chunks */
  425. #ifdef ENABLE_BUF_FREELISTS
  426. tt_int_op(buf_get_total_allocation(), ==, 16384); /* that chunk went onto
  427. the freelist. */
  428. #else
  429. tt_int_op(buf_get_total_allocation(), ==, 12288); /* that chunk was really
  430. freed. */
  431. #endif
  432. write_to_buf(junk, 4000, buf2);
  433. tt_int_op(buf_allocation(buf2), ==, 4096); /* another 4k chunk. */
  434. /*
  435. * If we're using freelists, size stays at 16384 because we just pulled a
  436. * chunk from the freelist. If we aren't, we bounce back up to 16384 by
  437. * allocating a new chunk.
  438. */
  439. tt_int_op(buf_get_total_allocation(), ==, 16384);
  440. write_to_buf(junk, 4000, buf2);
  441. tt_int_op(buf_allocation(buf2), ==, 8192); /* another 4k chunk. */
  442. tt_int_op(buf_get_total_allocation(), ==, 5*4096); /* that chunk was new. */
  443. /* Make a really huge buffer */
  444. for (i = 0; i < 1000; ++i) {
  445. write_to_buf(junk, 4000, buf2);
  446. }
  447. tt_int_op(buf_allocation(buf2), >=, 4008000);
  448. tt_int_op(buf_get_total_allocation(), >=, 4008000);
  449. buf_free(buf2);
  450. buf2 = NULL;
  451. tt_int_op(buf_get_total_allocation(), <, 4008000);
  452. buf_shrink_freelists(1);
  453. tt_int_op(buf_get_total_allocation(), ==, buf_allocation(buf1));
  454. buf_free(buf1);
  455. buf1 = NULL;
  456. buf_shrink_freelists(1);
  457. tt_int_op(buf_get_total_allocation(), ==, 0);
  458. done:
  459. buf_free(buf1);
  460. buf_free(buf2);
  461. buf_shrink_freelists(1);
  462. tor_free(junk);
  463. }
  464. static void
  465. test_buffer_time_tracking(void *arg)
  466. {
  467. buf_t *buf=NULL, *buf2=NULL;
  468. struct timeval tv0;
  469. const time_t START = 1389288246;
  470. const uint32_t START_MSEC = (uint32_t) ((uint64_t)START * 1000);
  471. int i;
  472. char tmp[4096];
  473. (void)arg;
  474. crypto_rand(tmp, sizeof(tmp));
  475. tv0.tv_sec = START;
  476. tv0.tv_usec = 0;
  477. buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  478. tt_assert(buf);
  479. /* Empty buffer means the timestamp is 0. */
  480. tt_int_op(0, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC));
  481. tt_int_op(0, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000));
  482. tor_gettimeofday_cache_set(&tv0);
  483. write_to_buf("ABCDEFG", 7, buf);
  484. tt_int_op(1000, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000));
  485. buf2 = buf_copy(buf);
  486. tt_assert(buf2);
  487. tt_int_op(1234, ==, buf_get_oldest_chunk_timestamp(buf2, START_MSEC+1234));
  488. /* Now add more bytes; enough to overflow the first chunk. */
  489. tv0.tv_usec += 123 * 1000;
  490. tor_gettimeofday_cache_set(&tv0);
  491. for (i = 0; i < 600; ++i)
  492. write_to_buf("ABCDEFG", 7, buf);
  493. tt_int_op(4207, ==, buf_datalen(buf));
  494. /* The oldest bytes are still in the front. */
  495. tt_int_op(2000, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000));
  496. /* Once those bytes are dropped, the chunk is still on the first
  497. * timestamp. */
  498. fetch_from_buf(tmp, 100, buf);
  499. tt_int_op(2000, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000));
  500. /* But once we discard the whole first chunk, we get the data in the second
  501. * chunk. */
  502. fetch_from_buf(tmp, 4000, buf);
  503. tt_int_op(107, ==, buf_datalen(buf));
  504. tt_int_op(2000, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123));
  505. /* This time we'll be grabbing a chunk from the freelist, and making sure
  506. its time gets updated */
  507. tv0.tv_sec += 5;
  508. tv0.tv_usec = 617*1000;
  509. tor_gettimeofday_cache_set(&tv0);
  510. for (i = 0; i < 600; ++i)
  511. write_to_buf("ABCDEFG", 7, buf);
  512. tt_int_op(4307, ==, buf_datalen(buf));
  513. tt_int_op(2000, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123));
  514. fetch_from_buf(tmp, 4000, buf);
  515. fetch_from_buf(tmp, 306, buf);
  516. tt_int_op(0, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+5617));
  517. tt_int_op(383, ==, buf_get_oldest_chunk_timestamp(buf, START_MSEC+6000));
  518. done:
  519. buf_free(buf);
  520. buf_free(buf2);
  521. }
  522. static void
  523. test_buffers_zlib_impl(int finalize_with_nil)
  524. {
  525. char *msg = NULL;
  526. char *contents = NULL;
  527. char *expanded = NULL;
  528. buf_t *buf = NULL;
  529. tor_zlib_state_t *zlib_state = NULL;
  530. size_t out_len, in_len;
  531. int done;
  532. buf = buf_new_with_capacity(128); /* will round up */
  533. zlib_state = tor_zlib_new(1, ZLIB_METHOD);
  534. msg = tor_malloc(512);
  535. crypto_rand(msg, 512);
  536. tt_int_op(write_to_buf_zlib(buf, zlib_state, msg, 128, 0), ==, 0);
  537. tt_int_op(write_to_buf_zlib(buf, zlib_state, msg+128, 128, 0), ==, 0);
  538. tt_int_op(write_to_buf_zlib(buf, zlib_state, msg+256, 256, 0), ==, 0);
  539. done = !finalize_with_nil;
  540. tt_int_op(write_to_buf_zlib(buf, zlib_state, "all done", 9, done), ==, 0);
  541. if (finalize_with_nil) {
  542. tt_int_op(write_to_buf_zlib(buf, zlib_state, "", 0, 1), ==, 0);
  543. }
  544. in_len = buf_datalen(buf);
  545. contents = tor_malloc(in_len);
  546. tt_int_op(fetch_from_buf(contents, in_len, buf), ==, 0);
  547. tt_int_op(0, ==, tor_gzip_uncompress(&expanded, &out_len,
  548. contents, in_len,
  549. ZLIB_METHOD, 1,
  550. LOG_WARN));
  551. tt_int_op(out_len, >=, 128);
  552. tt_mem_op(msg, ==, expanded, 128);
  553. tt_int_op(out_len, >=, 512);
  554. tt_mem_op(msg, ==, expanded, 512);
  555. tt_int_op(out_len, ==, 512+9);
  556. tt_mem_op("all done", ==, expanded+512, 9);
  557. done:
  558. buf_free(buf);
  559. tor_zlib_free(zlib_state);
  560. tor_free(contents);
  561. tor_free(expanded);
  562. tor_free(msg);
  563. }
  564. static void
  565. test_buffers_zlib(void *arg)
  566. {
  567. (void) arg;
  568. test_buffers_zlib_impl(0);
  569. }
  570. static void
  571. test_buffers_zlib_fin_with_nil(void *arg)
  572. {
  573. (void) arg;
  574. test_buffers_zlib_impl(1);
  575. }
  576. static void
  577. test_buffers_zlib_fin_at_chunk_end(void *arg)
  578. {
  579. char *msg = NULL;
  580. char *contents = NULL;
  581. char *expanded = NULL;
  582. buf_t *buf = NULL;
  583. tor_zlib_state_t *zlib_state = NULL;
  584. size_t out_len, in_len;
  585. size_t sz, headerjunk;
  586. (void) arg;
  587. buf = buf_new_with_capacity(128); /* will round up */
  588. sz = buf_get_default_chunk_size(buf);
  589. msg = tor_malloc_zero(sz);
  590. write_to_buf(msg, 1, buf);
  591. tt_assert(buf->head);
  592. /* Fill up the chunk so the zlib stuff won't fit in one chunk. */
  593. tt_uint_op(buf->head->memlen, <, sz);
  594. headerjunk = buf->head->memlen - 7;
  595. write_to_buf(msg, headerjunk-1, buf);
  596. tt_uint_op(buf->head->datalen, ==, headerjunk);
  597. tt_uint_op(buf_datalen(buf), ==, headerjunk);
  598. /* Write an empty string, with finalization on. */
  599. zlib_state = tor_zlib_new(1, ZLIB_METHOD);
  600. tt_int_op(write_to_buf_zlib(buf, zlib_state, "", 0, 1), ==, 0);
  601. in_len = buf_datalen(buf);
  602. contents = tor_malloc(in_len);
  603. tt_int_op(fetch_from_buf(contents, in_len, buf), ==, 0);
  604. tt_uint_op(in_len, >, headerjunk);
  605. tt_int_op(0, ==, tor_gzip_uncompress(&expanded, &out_len,
  606. contents + headerjunk, in_len - headerjunk,
  607. ZLIB_METHOD, 1,
  608. LOG_WARN));
  609. tt_int_op(out_len, ==, 0);
  610. tt_assert(expanded);
  611. done:
  612. buf_free(buf);
  613. tor_zlib_free(zlib_state);
  614. tor_free(contents);
  615. tor_free(expanded);
  616. tor_free(msg);
  617. }
  618. struct testcase_t buffer_tests[] = {
  619. { "basic", test_buffers_basic, TT_FORK, NULL, NULL },
  620. { "copy", test_buffer_copy, TT_FORK, NULL, NULL },
  621. { "pullup", test_buffer_pullup, TT_FORK, NULL, NULL },
  622. { "ext_or_cmd", test_buffer_ext_or_cmd, TT_FORK, NULL, NULL },
  623. { "allocation_tracking", test_buffer_allocation_tracking, TT_FORK,
  624. NULL, NULL },
  625. { "time_tracking", test_buffer_time_tracking, TT_FORK, NULL, NULL },
  626. { "zlib", test_buffers_zlib, TT_FORK, NULL, NULL },
  627. { "zlib_fin_with_nil", test_buffers_zlib_fin_with_nil, TT_FORK, NULL, NULL },
  628. { "zlib_fin_at_chunk_end", test_buffers_zlib_fin_at_chunk_end, TT_FORK,
  629. NULL, NULL},
  630. END_OF_TESTCASES
  631. };