test_buffers.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. /* Copyright (c) 2001-2004, Roger Dingledine.
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2017, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. #define BUFFERS_PRIVATE
  6. #define PROTO_HTTP_PRIVATE
  7. #include "or.h"
  8. #include "buffers.h"
  9. #include "buffers_tls.h"
  10. #include "proto_http.h"
  11. #include "proto_socks.h"
  12. #include "test.h"
  13. /** Run unit tests for buffers.c */
  14. static void
  15. test_buffers_basic(void *arg)
  16. {
  17. char str[256];
  18. char str2[256];
  19. buf_t *buf = NULL, *buf2 = NULL;
  20. const char *cp;
  21. int j;
  22. size_t r;
  23. (void) arg;
  24. /****
  25. * buf_new
  26. ****/
  27. if (!(buf = buf_new()))
  28. TT_DIE(("Assertion failed."));
  29. //test_eq(buf_capacity(buf), 4096);
  30. tt_int_op(buf_datalen(buf),OP_EQ, 0);
  31. /****
  32. * General pointer frobbing
  33. */
  34. for (j=0;j<256;++j) {
  35. str[j] = (char)j;
  36. }
  37. buf_add(buf, str, 256);
  38. buf_add(buf, str, 256);
  39. tt_int_op(buf_datalen(buf),OP_EQ, 512);
  40. buf_get_bytes(buf, str2, 200);
  41. tt_mem_op(str,OP_EQ, str2, 200);
  42. tt_int_op(buf_datalen(buf),OP_EQ, 312);
  43. memset(str2, 0, sizeof(str2));
  44. buf_get_bytes(buf, str2, 256);
  45. tt_mem_op(str+200,OP_EQ, str2, 56);
  46. tt_mem_op(str,OP_EQ, str2+56, 200);
  47. tt_int_op(buf_datalen(buf),OP_EQ, 56);
  48. memset(str2, 0, sizeof(str2));
  49. /* Okay, now we should be 512 bytes into the 4096-byte buffer. If we add
  50. * another 3584 bytes, we hit the end. */
  51. for (j=0;j<15;++j) {
  52. buf_add(buf, str, 256);
  53. }
  54. buf_assert_ok(buf);
  55. tt_int_op(buf_datalen(buf),OP_EQ, 3896);
  56. buf_get_bytes(buf, str2, 56);
  57. tt_int_op(buf_datalen(buf),OP_EQ, 3840);
  58. tt_mem_op(str+200,OP_EQ, str2, 56);
  59. for (j=0;j<15;++j) {
  60. memset(str2, 0, sizeof(str2));
  61. buf_get_bytes(buf, str2, 256);
  62. tt_mem_op(str,OP_EQ, str2, 256);
  63. }
  64. tt_int_op(buf_datalen(buf),OP_EQ, 0);
  65. buf_free(buf);
  66. buf = NULL;
  67. /* Okay, now make sure growing can work. */
  68. buf = buf_new_with_capacity(16);
  69. //test_eq(buf_capacity(buf), 16);
  70. buf_add(buf, str+1, 255);
  71. //test_eq(buf_capacity(buf), 256);
  72. buf_get_bytes(buf, str2, 254);
  73. tt_mem_op(str+1,OP_EQ, str2, 254);
  74. //test_eq(buf_capacity(buf), 256);
  75. buf_assert_ok(buf);
  76. buf_add(buf, str, 32);
  77. //test_eq(buf_capacity(buf), 256);
  78. buf_assert_ok(buf);
  79. buf_add(buf, str, 256);
  80. buf_assert_ok(buf);
  81. //test_eq(buf_capacity(buf), 512);
  82. tt_int_op(buf_datalen(buf),OP_EQ, 33+256);
  83. buf_get_bytes(buf, str2, 33);
  84. tt_int_op(*str2,OP_EQ, str[255]);
  85. tt_mem_op(str2+1,OP_EQ, str, 32);
  86. //test_eq(buf_capacity(buf), 512);
  87. tt_int_op(buf_datalen(buf),OP_EQ, 256);
  88. buf_get_bytes(buf, str2, 256);
  89. tt_mem_op(str,OP_EQ, str2, 256);
  90. /* now try shrinking: case 1. */
  91. buf_free(buf);
  92. buf = buf_new_with_capacity(33668);
  93. for (j=0;j<67;++j) {
  94. buf_add(buf, str,255);
  95. }
  96. //test_eq(buf_capacity(buf), 33668);
  97. tt_int_op(buf_datalen(buf),OP_EQ, 17085);
  98. for (j=0; j < 40; ++j) {
  99. buf_get_bytes(buf, str2, 255);
  100. tt_mem_op(str2,OP_EQ, str, 255);
  101. }
  102. /* now try shrinking: case 2. */
  103. buf_free(buf);
  104. buf = buf_new_with_capacity(33668);
  105. for (j=0;j<67;++j) {
  106. buf_add(buf, str, 255);
  107. }
  108. for (j=0; j < 20; ++j) {
  109. buf_get_bytes(buf, str2, 255);
  110. tt_mem_op(str2,OP_EQ, str, 255);
  111. }
  112. for (j=0;j<80;++j) {
  113. buf_add(buf, str, 255);
  114. }
  115. //test_eq(buf_capacity(buf),33668);
  116. for (j=0; j < 120; ++j) {
  117. buf_get_bytes(buf, str2, 255);
  118. tt_mem_op(str2,OP_EQ, str, 255);
  119. }
  120. /* Move from buf to buf. */
  121. buf_free(buf);
  122. buf = buf_new_with_capacity(4096);
  123. buf2 = buf_new_with_capacity(4096);
  124. for (j=0;j<100;++j)
  125. buf_add(buf, str, 255);
  126. tt_int_op(buf_datalen(buf),OP_EQ, 25500);
  127. for (j=0;j<100;++j) {
  128. r = 10;
  129. buf_move_to_buf(buf2, buf, &r);
  130. tt_int_op(r,OP_EQ, 0);
  131. }
  132. tt_int_op(buf_datalen(buf),OP_EQ, 24500);
  133. tt_int_op(buf_datalen(buf2),OP_EQ, 1000);
  134. for (j=0;j<3;++j) {
  135. buf_get_bytes(buf2, str2, 255);
  136. tt_mem_op(str2,OP_EQ, str, 255);
  137. }
  138. r = 8192; /*big move*/
  139. buf_move_to_buf(buf2, buf, &r);
  140. tt_int_op(r,OP_EQ, 0);
  141. r = 30000; /* incomplete move */
  142. buf_move_to_buf(buf2, buf, &r);
  143. tt_int_op(r,OP_EQ, 13692);
  144. for (j=0;j<97;++j) {
  145. buf_get_bytes(buf2, str2, 255);
  146. tt_mem_op(str2,OP_EQ, str, 255);
  147. }
  148. buf_free(buf);
  149. buf_free(buf2);
  150. buf = buf2 = NULL;
  151. buf = buf_new_with_capacity(5);
  152. cp = "Testing. This is a moderately long Testing string.";
  153. for (j = 0; cp[j]; j++)
  154. buf_add(buf, cp+j, 1);
  155. tt_int_op(0,OP_EQ, buf_find_string_offset(buf, "Testing", 7));
  156. tt_int_op(1,OP_EQ, buf_find_string_offset(buf, "esting", 6));
  157. tt_int_op(1,OP_EQ, buf_find_string_offset(buf, "est", 3));
  158. tt_int_op(39,OP_EQ, buf_find_string_offset(buf, "ing str", 7));
  159. tt_int_op(35,OP_EQ, buf_find_string_offset(buf, "Testing str", 11));
  160. tt_int_op(32,OP_EQ, buf_find_string_offset(buf, "ng ", 3));
  161. tt_int_op(43,OP_EQ, buf_find_string_offset(buf, "string.", 7));
  162. tt_int_op(-1,OP_EQ, buf_find_string_offset(buf, "shrdlu", 6));
  163. tt_int_op(-1,OP_EQ, buf_find_string_offset(buf, "Testing thing", 13));
  164. tt_int_op(-1,OP_EQ, buf_find_string_offset(buf, "ngx", 3));
  165. buf_free(buf);
  166. buf = NULL;
  167. /* Try adding a string too long for any freelist. */
  168. {
  169. char *mem = tor_malloc_zero(65536);
  170. buf = buf_new();
  171. buf_add(buf, mem, 65536);
  172. tor_free(mem);
  173. tt_int_op(buf_datalen(buf), OP_EQ, 65536);
  174. buf_free(buf);
  175. buf = NULL;
  176. }
  177. done:
  178. if (buf)
  179. buf_free(buf);
  180. if (buf2)
  181. buf_free(buf2);
  182. }
  183. static void
  184. test_buffer_pullup(void *arg)
  185. {
  186. buf_t *buf;
  187. char *stuff, *tmp;
  188. const char *cp;
  189. size_t sz;
  190. (void)arg;
  191. stuff = tor_malloc(16384);
  192. tmp = tor_malloc(16384);
  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), OP_EQ, 4096);
  196. tt_int_op(buf_get_total_allocation(), OP_EQ, 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, &cp, &sz);
  200. tt_ptr_op(cp, OP_EQ, NULL);
  201. tt_uint_op(sz, OP_EQ, 0);
  202. /* Let's make sure nothing got allocated */
  203. tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
  204. /* Case 1: everything puts into the first chunk with some moving. */
  205. /* Let's add some data. */
  206. crypto_rand(stuff, 16384);
  207. buf_add(buf, stuff, 3000);
  208. buf_add(buf, stuff+3000, 3000);
  209. buf_pullup(buf, 0, &cp, &sz);
  210. tt_ptr_op(cp, OP_NE, NULL);
  211. tt_int_op(sz, OP_LE, 4096);
  212. /* Make room for 3000 bytes in the first chunk, so that the pullup-move code
  213. * can get tested. */
  214. tt_int_op(buf_get_bytes(buf, tmp, 3000), OP_EQ, 3000);
  215. tt_mem_op(tmp,OP_EQ, stuff, 3000);
  216. buf_pullup(buf, 2048, &cp, &sz);
  217. buf_assert_ok(buf);
  218. tt_ptr_op(cp, OP_NE, NULL);
  219. tt_int_op(sz, OP_GE, 2048);
  220. tt_mem_op(cp,OP_EQ, stuff+3000, 2048);
  221. tt_int_op(3000, OP_EQ, buf_datalen(buf));
  222. tt_int_op(buf_get_bytes(buf, tmp, 3000), OP_EQ, 0);
  223. tt_mem_op(tmp,OP_EQ, stuff+3000, 2048);
  224. buf_free(buf);
  225. /* Now try the large-chunk case. */
  226. buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  227. buf_add(buf, stuff, 4000);
  228. buf_add(buf, stuff+4000, 4000);
  229. buf_add(buf, stuff+8000, 4000);
  230. buf_add(buf, stuff+12000, 4000);
  231. tt_int_op(buf_datalen(buf), OP_EQ, 16000);
  232. buf_pullup(buf, 0, &cp, &sz);
  233. tt_ptr_op(cp, OP_NE, NULL);
  234. tt_int_op(sz, OP_LE, 4096);
  235. buf_pullup(buf, 12500, &cp, &sz);
  236. buf_assert_ok(buf);
  237. tt_ptr_op(cp, OP_NE, NULL);
  238. tt_int_op(sz, OP_GE, 12500);
  239. tt_mem_op(cp,OP_EQ, stuff, 12500);
  240. tt_int_op(buf_datalen(buf), OP_EQ, 16000);
  241. buf_get_bytes(buf, tmp, 12400);
  242. tt_mem_op(tmp,OP_EQ, stuff, 12400);
  243. tt_int_op(buf_datalen(buf), OP_EQ, 3600);
  244. buf_get_bytes(buf, tmp, 3500);
  245. tt_mem_op(tmp,OP_EQ, stuff+12400, 3500);
  246. buf_get_bytes(buf, tmp, 100);
  247. tt_mem_op(tmp,OP_EQ, stuff+15900, 10);
  248. buf_free(buf);
  249. /* Make sure that the pull-up-whole-buffer case works */
  250. buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  251. buf_add(buf, stuff, 4000);
  252. buf_add(buf, stuff+4000, 4000);
  253. buf_get_bytes(buf, tmp, 100); /* dump 100 bytes from first chunk */
  254. buf_pullup(buf, 16000, &cp, &sz);
  255. buf_assert_ok(buf);
  256. tt_ptr_op(cp, OP_NE, NULL);
  257. tt_int_op(sz, OP_EQ, 7900);
  258. tt_mem_op(cp,OP_EQ, stuff+100, 7900);
  259. buf_free(buf);
  260. buf = NULL;
  261. tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
  262. done:
  263. buf_free(buf);
  264. tor_free(stuff);
  265. tor_free(tmp);
  266. }
  267. static void
  268. test_buffer_copy(void *arg)
  269. {
  270. buf_t *buf=NULL, *buf2=NULL;
  271. const char *s;
  272. size_t len;
  273. char b[256];
  274. int i;
  275. (void)arg;
  276. buf = buf_new();
  277. tt_assert(buf);
  278. /* Copy an empty buffer. */
  279. tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf));
  280. tt_assert(buf2);
  281. tt_int_op(0, OP_EQ, buf_datalen(buf2));
  282. /* Now try with a short buffer. */
  283. s = "And now comes an act of enormous enormance!";
  284. len = strlen(s);
  285. buf_add(buf, s, len);
  286. tt_int_op(len, OP_EQ, buf_datalen(buf));
  287. /* Add junk to buf2 so we can test replacing.*/
  288. buf_add(buf2, "BLARG", 5);
  289. tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf));
  290. tt_int_op(len, OP_EQ, buf_datalen(buf2));
  291. buf_get_bytes(buf2, b, len);
  292. tt_mem_op(b, OP_EQ, s, len);
  293. /* Now free buf2 and retry so we can test allocating */
  294. buf_free(buf2);
  295. buf2 = NULL;
  296. tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf));
  297. tt_int_op(len, OP_EQ, buf_datalen(buf2));
  298. buf_get_bytes(buf2, b, len);
  299. tt_mem_op(b, OP_EQ, s, len);
  300. /* Clear buf for next test */
  301. buf_get_bytes(buf, b, len);
  302. tt_int_op(buf_datalen(buf),OP_EQ,0);
  303. /* Okay, now let's try a bigger buffer. */
  304. s = "Quis autem vel eum iure reprehenderit qui in ea voluptate velit "
  305. "esse quam nihil molestiae consequatur, vel illum qui dolorem eum "
  306. "fugiat quo voluptas nulla pariatur?";
  307. len = strlen(s);
  308. for (i = 0; i < 256; ++i) {
  309. b[0]=i;
  310. buf_add(buf, b, 1);
  311. buf_add(buf, s, len);
  312. }
  313. tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf));
  314. tt_int_op(buf_datalen(buf2), OP_EQ, buf_datalen(buf));
  315. for (i = 0; i < 256; ++i) {
  316. buf_get_bytes(buf2, b, len+1);
  317. tt_int_op((unsigned char)b[0],OP_EQ,i);
  318. tt_mem_op(b+1, OP_EQ, s, len);
  319. }
  320. done:
  321. if (buf)
  322. buf_free(buf);
  323. if (buf2)
  324. buf_free(buf2);
  325. }
  326. static void
  327. test_buffer_allocation_tracking(void *arg)
  328. {
  329. char *junk = tor_malloc(16384);
  330. buf_t *buf1 = NULL, *buf2 = NULL;
  331. int i;
  332. (void)arg;
  333. crypto_rand(junk, 16384);
  334. tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
  335. buf1 = buf_new();
  336. tt_assert(buf1);
  337. buf2 = buf_new();
  338. tt_assert(buf2);
  339. tt_int_op(buf_allocation(buf1), OP_EQ, 0);
  340. tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
  341. buf_add(buf1, junk, 4000);
  342. buf_add(buf1, junk, 4000);
  343. buf_add(buf1, junk, 4000);
  344. buf_add(buf1, junk, 4000);
  345. tt_int_op(buf_allocation(buf1), OP_EQ, 16384);
  346. buf_get_bytes(buf1, junk, 100);
  347. tt_int_op(buf_allocation(buf1), OP_EQ, 16384); /* still 4 4k chunks */
  348. tt_int_op(buf_get_total_allocation(), OP_EQ, 16384);
  349. buf_get_bytes(buf1, junk, 4096); /* drop a 1k chunk... */
  350. tt_int_op(buf_allocation(buf1), OP_EQ, 3*4096); /* now 3 4k chunks */
  351. tt_int_op(buf_get_total_allocation(), OP_EQ, 12288); /* that chunk was really
  352. freed. */
  353. buf_add(buf2, junk, 4000);
  354. tt_int_op(buf_allocation(buf2), OP_EQ, 4096); /* another 4k chunk. */
  355. /*
  356. * We bounce back up to 16384 by allocating a new chunk.
  357. */
  358. tt_int_op(buf_get_total_allocation(), OP_EQ, 16384);
  359. buf_add(buf2, junk, 4000);
  360. tt_int_op(buf_allocation(buf2), OP_EQ, 8192); /* another 4k chunk. */
  361. tt_int_op(buf_get_total_allocation(),
  362. OP_EQ, 5*4096); /* that chunk was new. */
  363. /* Make a really huge buffer */
  364. for (i = 0; i < 1000; ++i) {
  365. buf_add(buf2, junk, 4000);
  366. }
  367. tt_int_op(buf_allocation(buf2), OP_GE, 4008000);
  368. tt_int_op(buf_get_total_allocation(), OP_GE, 4008000);
  369. buf_free(buf2);
  370. buf2 = NULL;
  371. tt_int_op(buf_get_total_allocation(), OP_LT, 4008000);
  372. tt_int_op(buf_get_total_allocation(), OP_EQ, buf_allocation(buf1));
  373. buf_free(buf1);
  374. buf1 = NULL;
  375. tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
  376. done:
  377. buf_free(buf1);
  378. buf_free(buf2);
  379. tor_free(junk);
  380. }
  381. static void
  382. test_buffer_time_tracking(void *arg)
  383. {
  384. buf_t *buf=NULL, *buf2=NULL;
  385. const time_t START = 1389288246;
  386. const uint64_t START_NSEC = ((uint64_t)START) * 1000000000;
  387. int i;
  388. char tmp[4096];
  389. (void)arg;
  390. crypto_rand(tmp, sizeof(tmp));
  391. monotime_enable_test_mocking();
  392. buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  393. tt_assert(buf);
  394. monotime_coarse_set_mock_time_nsec(START_NSEC);
  395. const uint32_t START_TS = monotime_coarse_get_stamp();
  396. /* Empty buffer means the timestamp is 0. */
  397. tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_TS));
  398. tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_TS+1000));
  399. buf_add(buf, "ABCDEFG", 7);
  400. tt_int_op(1000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_TS+1000));
  401. buf2 = buf_copy(buf);
  402. tt_assert(buf2);
  403. tt_int_op(1234, OP_EQ,
  404. buf_get_oldest_chunk_timestamp(buf2, START_TS+1234));
  405. /* Now add more bytes; enough to overflow the first chunk. */
  406. monotime_coarse_set_mock_time_nsec(START_NSEC + 123 * (uint64_t)1000000);
  407. const uint32_t TS2 = monotime_coarse_get_stamp();
  408. for (i = 0; i < 600; ++i)
  409. buf_add(buf, "ABCDEFG", 7);
  410. tt_int_op(4207, OP_EQ, buf_datalen(buf));
  411. /* The oldest bytes are still in the front. */
  412. tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_TS+2000));
  413. /* Once those bytes are dropped, the chunk is still on the first
  414. * timestamp. */
  415. buf_get_bytes(buf, tmp, 100);
  416. tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_TS+2000));
  417. /* But once we discard the whole first chunk, we get the data in the second
  418. * chunk. */
  419. buf_get_bytes(buf, tmp, 4000);
  420. tt_int_op(107, OP_EQ, buf_datalen(buf));
  421. tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, TS2+2000));
  422. /* This time we'll be grabbing a chunk from the freelist, and making sure
  423. its time gets updated */
  424. monotime_coarse_set_mock_time_nsec(START_NSEC + 5617 * (uint64_t)1000000);
  425. const uint32_t TS3 = monotime_coarse_get_stamp();
  426. for (i = 0; i < 600; ++i)
  427. buf_add(buf, "ABCDEFG", 7);
  428. tt_int_op(4307, OP_EQ, buf_datalen(buf));
  429. tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, TS2+2000));
  430. buf_get_bytes(buf, tmp, 4000);
  431. buf_get_bytes(buf, tmp, 306);
  432. tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, TS3));
  433. tt_int_op(383, OP_EQ, buf_get_oldest_chunk_timestamp(buf, TS3+383));
  434. done:
  435. buf_free(buf);
  436. buf_free(buf2);
  437. monotime_disable_test_mocking();
  438. }
  439. static void
  440. test_buffers_compress_fin_at_chunk_end_impl(compress_method_t method,
  441. compression_level_t level)
  442. {
  443. char *msg = NULL;
  444. char *contents = NULL;
  445. char *expanded = NULL;
  446. buf_t *buf = NULL;
  447. tor_compress_state_t *compress_state = NULL;
  448. size_t out_len, in_len;
  449. size_t sz, headerjunk;
  450. buf = buf_new_with_capacity(128); /* will round up */
  451. sz = buf_get_default_chunk_size(buf);
  452. msg = tor_malloc_zero(sz);
  453. buf_add(buf, msg, 1);
  454. tt_assert(buf->head);
  455. /* Fill up the chunk so the compression stuff won't fit in one chunk. */
  456. tt_uint_op(buf->head->memlen, OP_LT, sz);
  457. headerjunk = buf->head->memlen - 7;
  458. buf_add(buf, msg, headerjunk-1);
  459. tt_uint_op(buf->head->datalen, OP_EQ, headerjunk);
  460. tt_uint_op(buf_datalen(buf), OP_EQ, headerjunk);
  461. /* Write an empty string, with finalization on. */
  462. compress_state = tor_compress_new(1, method, level);
  463. tt_int_op(buf_add_compress(buf, compress_state, "", 0, 1), OP_EQ, 0);
  464. in_len = buf_datalen(buf);
  465. contents = tor_malloc(in_len);
  466. tt_int_op(buf_get_bytes(buf, contents, in_len), OP_EQ, 0);
  467. if (method == NO_METHOD) {
  468. tt_uint_op(in_len, OP_EQ, headerjunk);
  469. } else {
  470. tt_uint_op(in_len, OP_GT, headerjunk);
  471. }
  472. tt_int_op(0, OP_EQ, tor_uncompress(&expanded, &out_len,
  473. contents + headerjunk,
  474. in_len - headerjunk,
  475. method, 1,
  476. LOG_WARN));
  477. tt_int_op(out_len, OP_EQ, 0);
  478. tt_assert(expanded);
  479. done:
  480. buf_free(buf);
  481. tor_compress_free(compress_state);
  482. tor_free(contents);
  483. tor_free(expanded);
  484. tor_free(msg);
  485. }
  486. static void
  487. test_buffers_compress_impl(compress_method_t method,
  488. compression_level_t level,
  489. int finalize_with_nil)
  490. {
  491. char *msg = NULL;
  492. char *contents = NULL;
  493. char *expanded = NULL;
  494. buf_t *buf = NULL;
  495. tor_compress_state_t *compress_state = NULL;
  496. size_t out_len, in_len;
  497. int done;
  498. buf = buf_new_with_capacity(128); /* will round up */
  499. compress_state = tor_compress_new(1, method, level);
  500. msg = tor_malloc(512);
  501. crypto_rand(msg, 512);
  502. tt_int_op(buf_add_compress(buf, compress_state,
  503. msg, 128, 0), OP_EQ, 0);
  504. tt_int_op(buf_add_compress(buf, compress_state,
  505. msg+128, 128, 0), OP_EQ, 0);
  506. tt_int_op(buf_add_compress(buf, compress_state,
  507. msg+256, 256, 0), OP_EQ, 0);
  508. done = !finalize_with_nil;
  509. tt_int_op(buf_add_compress(buf, compress_state,
  510. "all done", 9, done), OP_EQ, 0);
  511. if (finalize_with_nil) {
  512. tt_int_op(buf_add_compress(buf, compress_state, "", 0, 1), OP_EQ, 0);
  513. }
  514. in_len = buf_datalen(buf);
  515. contents = tor_malloc(in_len);
  516. tt_int_op(buf_get_bytes(buf, contents, in_len), OP_EQ, 0);
  517. tt_int_op(0, OP_EQ, tor_uncompress(&expanded, &out_len,
  518. contents, in_len,
  519. method, 1,
  520. LOG_WARN));
  521. tt_int_op(out_len, OP_GE, 128);
  522. tt_mem_op(msg, OP_EQ, expanded, 128);
  523. tt_int_op(out_len, OP_GE, 512);
  524. tt_mem_op(msg, OP_EQ, expanded, 512);
  525. tt_int_op(out_len, OP_EQ, 512+9);
  526. tt_mem_op("all done", OP_EQ, expanded+512, 9);
  527. done:
  528. buf_free(buf);
  529. tor_compress_free(compress_state);
  530. tor_free(contents);
  531. tor_free(expanded);
  532. tor_free(msg);
  533. }
  534. static void
  535. test_buffers_compress(void *arg)
  536. {
  537. const char *methodname = arg;
  538. tt_assert(methodname);
  539. compress_method_t method = compression_method_get_by_name(methodname);
  540. tt_int_op(method, OP_NE, UNKNOWN_METHOD);
  541. if (! tor_compress_supports_method(method)) {
  542. tt_skip();
  543. }
  544. compression_level_t levels[] = {
  545. BEST_COMPRESSION,
  546. HIGH_COMPRESSION,
  547. MEDIUM_COMPRESSION,
  548. LOW_COMPRESSION
  549. };
  550. for (unsigned l = 0; l < ARRAY_LENGTH(levels); ++l) {
  551. compression_level_t level = levels[l];
  552. test_buffers_compress_impl(method, level, 0);
  553. test_buffers_compress_impl(method, level, 1);
  554. test_buffers_compress_fin_at_chunk_end_impl(method, level);
  555. }
  556. done:
  557. ;
  558. }
  559. static const uint8_t *tls_read_ptr;
  560. static int n_remaining;
  561. static int next_reply_val[16];
  562. static int
  563. mock_tls_read(tor_tls_t *tls, char *cp, size_t len)
  564. {
  565. (void)tls;
  566. int rv = next_reply_val[0];
  567. if (rv > 0) {
  568. int max = rv > (int)len ? (int)len : rv;
  569. if (max > n_remaining)
  570. max = n_remaining;
  571. memcpy(cp, tls_read_ptr, max);
  572. rv = max;
  573. n_remaining -= max;
  574. tls_read_ptr += max;
  575. }
  576. memmove(next_reply_val, next_reply_val + 1, 15*sizeof(int));
  577. return rv;
  578. }
  579. static void
  580. test_buffers_tls_read_mocked(void *arg)
  581. {
  582. uint8_t *mem;
  583. buf_t *buf;
  584. (void)arg;
  585. mem = tor_malloc(64*1024);
  586. crypto_rand((char*)mem, 64*1024);
  587. tls_read_ptr = mem;
  588. n_remaining = 64*1024;
  589. MOCK(tor_tls_read, mock_tls_read);
  590. buf = buf_new();
  591. next_reply_val[0] = 1024;
  592. tt_int_op(128, OP_EQ, buf_read_from_tls(buf, NULL, 128));
  593. next_reply_val[0] = 5000;
  594. next_reply_val[1] = 5000;
  595. tt_int_op(6000, OP_EQ, buf_read_from_tls(buf, NULL, 6000));
  596. done:
  597. UNMOCK(tor_tls_read);
  598. tor_free(mem);
  599. buf_free(buf);
  600. }
  601. static void
  602. test_buffers_chunk_size(void *arg)
  603. {
  604. (void)arg;
  605. const int min = 256;
  606. const int max = 65536;
  607. tt_uint_op(buf_preferred_chunk_size(3), OP_EQ, min);
  608. tt_uint_op(buf_preferred_chunk_size(25), OP_EQ, min);
  609. tt_uint_op(buf_preferred_chunk_size(0), OP_EQ, min);
  610. tt_uint_op(buf_preferred_chunk_size(256), OP_EQ, 512);
  611. tt_uint_op(buf_preferred_chunk_size(65400), OP_EQ, max);
  612. /* Here, we're implicitly saying that the chunk header overhead is
  613. * between 1 and 100 bytes. 24..48 would probably be more accurate. */
  614. tt_uint_op(buf_preferred_chunk_size(65536), OP_GT, 65536);
  615. tt_uint_op(buf_preferred_chunk_size(65536), OP_LT, 65536+100);
  616. tt_uint_op(buf_preferred_chunk_size(165536), OP_GT, 165536);
  617. tt_uint_op(buf_preferred_chunk_size(165536), OP_LT, 165536+100);
  618. done:
  619. ;
  620. }
  621. static void
  622. test_buffers_find_contentlen(void *arg)
  623. {
  624. static const struct {
  625. const char *headers;
  626. int r;
  627. int contentlen;
  628. } results[] = {
  629. { "Blah blah\r\nContent-Length: 1\r\n\r\n", 1, 1 },
  630. { "Blah blah\r\n\r\n", 0, 0 }, /* no content-len */
  631. { "Blah blah Content-Length: 1\r\n", 0, 0 }, /* no content-len. */
  632. { "Blah blah\r\nContent-Length: 100000\r\n", 1, 100000},
  633. { "Blah blah\r\nContent-Length: 1000000000000000000000000\r\n", -1, 0},
  634. { "Blah blah\r\nContent-Length: 0\r\n", 1, 0},
  635. { "Blah blah\r\nContent-Length: -1\r\n", -1, 0},
  636. { "Blah blah\r\nContent-Length: 1x\r\n", -1, 0},
  637. { "Blah blah\r\nContent-Length: 1 x\r\n", -1, 0},
  638. { "Blah blah\r\nContent-Length: 1 \r\n", 1, 1},
  639. { "Blah blah\r\nContent-Length: \r\n", -1, 0},
  640. { "Blah blah\r\nContent-Length: ", -1, 0},
  641. { "Blah blah\r\nContent-Length: 5050", -1, 0},
  642. { NULL, 0, 0 }
  643. };
  644. int i;
  645. (void)arg;
  646. for (i = 0; results[i].headers; ++i) {
  647. int r;
  648. size_t sz;
  649. size_t headerlen = strlen(results[i].headers);
  650. char * tmp = tor_memdup(results[i].headers, headerlen);/* ensure no eos */
  651. sz = 999; /* to ensure it gets set */
  652. r = buf_http_find_content_length(tmp, headerlen, &sz);
  653. tor_free(tmp);
  654. log_debug(LD_DIR, "%d: %s", i, escaped(results[i].headers));
  655. tt_int_op(r, OP_EQ, results[i].r);
  656. tt_int_op(sz, OP_EQ, results[i].contentlen);
  657. }
  658. done:
  659. ;
  660. }
  661. static void
  662. test_buffer_peek_startswith(void *arg)
  663. {
  664. (void)arg;
  665. buf_t *buf;
  666. buf = buf_new();
  667. tt_ptr_op(buf, OP_NE, NULL);
  668. tt_assert(buf_peek_startswith(buf, ""));
  669. tt_assert(! buf_peek_startswith(buf, "X"));
  670. buf_add(buf, "Tor", 3);
  671. tt_assert(buf_peek_startswith(buf, ""));
  672. tt_assert(buf_peek_startswith(buf, "T"));
  673. tt_assert(buf_peek_startswith(buf, "To"));
  674. tt_assert(buf_peek_startswith(buf, "Tor"));
  675. tt_assert(! buf_peek_startswith(buf, "Top"));
  676. tt_assert(! buf_peek_startswith(buf, "For"));
  677. tt_assert(! buf_peek_startswith(buf, "Tork"));
  678. tt_assert(! buf_peek_startswith(buf, "Torpor"));
  679. done:
  680. buf_free(buf);
  681. }
  682. struct testcase_t buffer_tests[] = {
  683. { "basic", test_buffers_basic, TT_FORK, NULL, NULL },
  684. { "copy", test_buffer_copy, TT_FORK, NULL, NULL },
  685. { "pullup", test_buffer_pullup, TT_FORK, NULL, NULL },
  686. { "startswith", test_buffer_peek_startswith, 0, NULL, NULL },
  687. { "allocation_tracking", test_buffer_allocation_tracking, TT_FORK,
  688. NULL, NULL },
  689. { "time_tracking", test_buffer_time_tracking, TT_FORK, NULL, NULL },
  690. { "tls_read_mocked", test_buffers_tls_read_mocked, 0,
  691. NULL, NULL },
  692. { "chunk_size", test_buffers_chunk_size, 0, NULL, NULL },
  693. { "find_contentlen", test_buffers_find_contentlen, 0, NULL, NULL },
  694. { "compress/zlib", test_buffers_compress, TT_FORK,
  695. &passthrough_setup, (char*)"deflate" },
  696. { "compress/gzip", test_buffers_compress, TT_FORK,
  697. &passthrough_setup, (char*)"gzip" },
  698. { "compress/zstd", test_buffers_compress, TT_FORK,
  699. &passthrough_setup, (char*)"x-zstd" },
  700. { "compress/lzma", test_buffers_compress, TT_FORK,
  701. &passthrough_setup, (char*)"x-tor-lzma" },
  702. { "compress/none", test_buffers_compress, TT_FORK,
  703. &passthrough_setup, (char*)"identity" },
  704. END_OF_TESTCASES
  705. };