Prop210: Refactor connection_get_* to produce lists and counts
[tor.git] / src / test / test_buffers.c
blob29ee40861695368f648f701c812cdec4b889ca15
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2015, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #define BUFFERS_PRIVATE
7 #include "or.h"
8 #include "buffers.h"
9 #include "ext_orport.h"
10 #include "test.h"
12 /** Run unit tests for buffers.c */
13 static void
14 test_buffers_basic(void *arg)
16 char str[256];
17 char str2[256];
19 buf_t *buf = NULL, *buf2 = NULL;
20 const char *cp;
22 int j;
23 size_t r;
24 (void) arg;
26 /****
27 * buf_new
28 ****/
29 if (!(buf = buf_new()))
30 TT_DIE(("Assertion failed."));
32 //test_eq(buf_capacity(buf), 4096);
33 tt_int_op(buf_datalen(buf),OP_EQ, 0);
35 /****
36 * General pointer frobbing
38 for (j=0;j<256;++j) {
39 str[j] = (char)j;
41 write_to_buf(str, 256, buf);
42 write_to_buf(str, 256, buf);
43 tt_int_op(buf_datalen(buf),OP_EQ, 512);
44 fetch_from_buf(str2, 200, buf);
45 tt_mem_op(str,OP_EQ, str2, 200);
46 tt_int_op(buf_datalen(buf),OP_EQ, 312);
47 memset(str2, 0, sizeof(str2));
49 fetch_from_buf(str2, 256, buf);
50 tt_mem_op(str+200,OP_EQ, str2, 56);
51 tt_mem_op(str,OP_EQ, str2+56, 200);
52 tt_int_op(buf_datalen(buf),OP_EQ, 56);
53 memset(str2, 0, sizeof(str2));
54 /* Okay, now we should be 512 bytes into the 4096-byte buffer. If we add
55 * another 3584 bytes, we hit the end. */
56 for (j=0;j<15;++j) {
57 write_to_buf(str, 256, buf);
59 assert_buf_ok(buf);
60 tt_int_op(buf_datalen(buf),OP_EQ, 3896);
61 fetch_from_buf(str2, 56, buf);
62 tt_int_op(buf_datalen(buf),OP_EQ, 3840);
63 tt_mem_op(str+200,OP_EQ, str2, 56);
64 for (j=0;j<15;++j) {
65 memset(str2, 0, sizeof(str2));
66 fetch_from_buf(str2, 256, buf);
67 tt_mem_op(str,OP_EQ, str2, 256);
69 tt_int_op(buf_datalen(buf),OP_EQ, 0);
70 buf_free(buf);
71 buf = NULL;
73 /* Okay, now make sure growing can work. */
74 buf = buf_new_with_capacity(16);
75 //test_eq(buf_capacity(buf), 16);
76 write_to_buf(str+1, 255, buf);
77 //test_eq(buf_capacity(buf), 256);
78 fetch_from_buf(str2, 254, buf);
79 tt_mem_op(str+1,OP_EQ, str2, 254);
80 //test_eq(buf_capacity(buf), 256);
81 assert_buf_ok(buf);
82 write_to_buf(str, 32, buf);
83 //test_eq(buf_capacity(buf), 256);
84 assert_buf_ok(buf);
85 write_to_buf(str, 256, buf);
86 assert_buf_ok(buf);
87 //test_eq(buf_capacity(buf), 512);
88 tt_int_op(buf_datalen(buf),OP_EQ, 33+256);
89 fetch_from_buf(str2, 33, buf);
90 tt_int_op(*str2,OP_EQ, str[255]);
92 tt_mem_op(str2+1,OP_EQ, str, 32);
93 //test_eq(buf_capacity(buf), 512);
94 tt_int_op(buf_datalen(buf),OP_EQ, 256);
95 fetch_from_buf(str2, 256, buf);
96 tt_mem_op(str,OP_EQ, str2, 256);
98 /* now try shrinking: case 1. */
99 buf_free(buf);
100 buf = buf_new_with_capacity(33668);
101 for (j=0;j<67;++j) {
102 write_to_buf(str,255, buf);
104 //test_eq(buf_capacity(buf), 33668);
105 tt_int_op(buf_datalen(buf),OP_EQ, 17085);
106 for (j=0; j < 40; ++j) {
107 fetch_from_buf(str2, 255,buf);
108 tt_mem_op(str2,OP_EQ, str, 255);
111 /* now try shrinking: case 2. */
112 buf_free(buf);
113 buf = buf_new_with_capacity(33668);
114 for (j=0;j<67;++j) {
115 write_to_buf(str,255, buf);
117 for (j=0; j < 20; ++j) {
118 fetch_from_buf(str2, 255,buf);
119 tt_mem_op(str2,OP_EQ, str, 255);
121 for (j=0;j<80;++j) {
122 write_to_buf(str,255, buf);
124 //test_eq(buf_capacity(buf),33668);
125 for (j=0; j < 120; ++j) {
126 fetch_from_buf(str2, 255,buf);
127 tt_mem_op(str2,OP_EQ, str, 255);
130 /* Move from buf to buf. */
131 buf_free(buf);
132 buf = buf_new_with_capacity(4096);
133 buf2 = buf_new_with_capacity(4096);
134 for (j=0;j<100;++j)
135 write_to_buf(str, 255, buf);
136 tt_int_op(buf_datalen(buf),OP_EQ, 25500);
137 for (j=0;j<100;++j) {
138 r = 10;
139 move_buf_to_buf(buf2, buf, &r);
140 tt_int_op(r,OP_EQ, 0);
142 tt_int_op(buf_datalen(buf),OP_EQ, 24500);
143 tt_int_op(buf_datalen(buf2),OP_EQ, 1000);
144 for (j=0;j<3;++j) {
145 fetch_from_buf(str2, 255, buf2);
146 tt_mem_op(str2,OP_EQ, str, 255);
148 r = 8192; /*big move*/
149 move_buf_to_buf(buf2, buf, &r);
150 tt_int_op(r,OP_EQ, 0);
151 r = 30000; /* incomplete move */
152 move_buf_to_buf(buf2, buf, &r);
153 tt_int_op(r,OP_EQ, 13692);
154 for (j=0;j<97;++j) {
155 fetch_from_buf(str2, 255, buf2);
156 tt_mem_op(str2,OP_EQ, str, 255);
158 buf_free(buf);
159 buf_free(buf2);
160 buf = buf2 = NULL;
162 buf = buf_new_with_capacity(5);
163 cp = "Testing. This is a moderately long Testing string.";
164 for (j = 0; cp[j]; j++)
165 write_to_buf(cp+j, 1, buf);
166 tt_int_op(0,OP_EQ, buf_find_string_offset(buf, "Testing", 7));
167 tt_int_op(1,OP_EQ, buf_find_string_offset(buf, "esting", 6));
168 tt_int_op(1,OP_EQ, buf_find_string_offset(buf, "est", 3));
169 tt_int_op(39,OP_EQ, buf_find_string_offset(buf, "ing str", 7));
170 tt_int_op(35,OP_EQ, buf_find_string_offset(buf, "Testing str", 11));
171 tt_int_op(32,OP_EQ, buf_find_string_offset(buf, "ng ", 3));
172 tt_int_op(43,OP_EQ, buf_find_string_offset(buf, "string.", 7));
173 tt_int_op(-1,OP_EQ, buf_find_string_offset(buf, "shrdlu", 6));
174 tt_int_op(-1,OP_EQ, buf_find_string_offset(buf, "Testing thing", 13));
175 tt_int_op(-1,OP_EQ, buf_find_string_offset(buf, "ngx", 3));
176 buf_free(buf);
177 buf = NULL;
179 /* Try adding a string too long for any freelist. */
181 char *cp = tor_malloc_zero(65536);
182 buf = buf_new();
183 write_to_buf(cp, 65536, buf);
184 tor_free(cp);
186 tt_int_op(buf_datalen(buf), OP_EQ, 65536);
187 buf_free(buf);
188 buf = NULL;
191 done:
192 if (buf)
193 buf_free(buf);
194 if (buf2)
195 buf_free(buf2);
198 static void
199 test_buffer_pullup(void *arg)
201 buf_t *buf;
202 char *stuff, *tmp;
203 const char *cp;
204 size_t sz;
205 (void)arg;
206 stuff = tor_malloc(16384);
207 tmp = tor_malloc(16384);
209 buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
211 tt_assert(buf);
212 tt_int_op(buf_get_default_chunk_size(buf), OP_EQ, 4096);
214 tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
216 /* There are a bunch of cases for pullup. One is the trivial case. Let's
217 mess around with an empty buffer. */
218 buf_pullup(buf, 16);
219 buf_get_first_chunk_data(buf, &cp, &sz);
220 tt_ptr_op(cp, OP_EQ, NULL);
221 tt_uint_op(sz, OP_EQ, 0);
223 /* Let's make sure nothing got allocated */
224 tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
226 /* Case 1: everything puts into the first chunk with some moving. */
228 /* Let's add some data. */
229 crypto_rand(stuff, 16384);
230 write_to_buf(stuff, 3000, buf);
231 write_to_buf(stuff+3000, 3000, buf);
232 buf_get_first_chunk_data(buf, &cp, &sz);
233 tt_ptr_op(cp, OP_NE, NULL);
234 tt_int_op(sz, OP_LE, 4096);
236 /* Make room for 3000 bytes in the first chunk, so that the pullup-move code
237 * can get tested. */
238 tt_int_op(fetch_from_buf(tmp, 3000, buf), OP_EQ, 3000);
239 tt_mem_op(tmp,OP_EQ, stuff, 3000);
240 buf_pullup(buf, 2048);
241 assert_buf_ok(buf);
242 buf_get_first_chunk_data(buf, &cp, &sz);
243 tt_ptr_op(cp, OP_NE, NULL);
244 tt_int_op(sz, OP_GE, 2048);
245 tt_mem_op(cp,OP_EQ, stuff+3000, 2048);
246 tt_int_op(3000, OP_EQ, buf_datalen(buf));
247 tt_int_op(fetch_from_buf(tmp, 3000, buf), OP_EQ, 0);
248 tt_mem_op(tmp,OP_EQ, stuff+3000, 2048);
250 buf_free(buf);
252 /* Now try the large-chunk case. */
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 write_to_buf(stuff+8000, 4000, buf);
257 write_to_buf(stuff+12000, 4000, buf);
258 tt_int_op(buf_datalen(buf), OP_EQ, 16000);
259 buf_get_first_chunk_data(buf, &cp, &sz);
260 tt_ptr_op(cp, OP_NE, NULL);
261 tt_int_op(sz, OP_LE, 4096);
263 buf_pullup(buf, 12500);
264 assert_buf_ok(buf);
265 buf_get_first_chunk_data(buf, &cp, &sz);
266 tt_ptr_op(cp, OP_NE, NULL);
267 tt_int_op(sz, OP_GE, 12500);
268 tt_mem_op(cp,OP_EQ, stuff, 12500);
269 tt_int_op(buf_datalen(buf), OP_EQ, 16000);
271 fetch_from_buf(tmp, 12400, buf);
272 tt_mem_op(tmp,OP_EQ, stuff, 12400);
273 tt_int_op(buf_datalen(buf), OP_EQ, 3600);
274 fetch_from_buf(tmp, 3500, buf);
275 tt_mem_op(tmp,OP_EQ, stuff+12400, 3500);
276 fetch_from_buf(tmp, 100, buf);
277 tt_mem_op(tmp,OP_EQ, stuff+15900, 10);
279 buf_free(buf);
281 /* Make sure that the pull-up-whole-buffer case works */
282 buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
283 write_to_buf(stuff, 4000, buf);
284 write_to_buf(stuff+4000, 4000, buf);
285 fetch_from_buf(tmp, 100, buf); /* dump 100 bytes from first chunk */
286 buf_pullup(buf, 16000); /* Way too much. */
287 assert_buf_ok(buf);
288 buf_get_first_chunk_data(buf, &cp, &sz);
289 tt_ptr_op(cp, OP_NE, NULL);
290 tt_int_op(sz, OP_EQ, 7900);
291 tt_mem_op(cp,OP_EQ, stuff+100, 7900);
293 buf_free(buf);
294 buf = NULL;
296 tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
297 done:
298 buf_free(buf);
299 tor_free(stuff);
300 tor_free(tmp);
303 static void
304 test_buffer_copy(void *arg)
306 generic_buffer_t *buf=NULL, *buf2=NULL;
307 const char *s;
308 size_t len;
309 char b[256];
310 int i;
311 (void)arg;
313 buf = generic_buffer_new();
314 tt_assert(buf);
316 /* Copy an empty buffer. */
317 tt_int_op(0, OP_EQ, generic_buffer_set_to_copy(&buf2, buf));
318 tt_assert(buf2);
319 tt_int_op(0, OP_EQ, generic_buffer_len(buf2));
321 /* Now try with a short buffer. */
322 s = "And now comes an act of enormous enormance!";
323 len = strlen(s);
324 generic_buffer_add(buf, s, len);
325 tt_int_op(len, OP_EQ, generic_buffer_len(buf));
326 /* Add junk to buf2 so we can test replacing.*/
327 generic_buffer_add(buf2, "BLARG", 5);
328 tt_int_op(0, OP_EQ, generic_buffer_set_to_copy(&buf2, buf));
329 tt_int_op(len, OP_EQ, generic_buffer_len(buf2));
330 generic_buffer_get(buf2, b, len);
331 tt_mem_op(b, OP_EQ, s, len);
332 /* Now free buf2 and retry so we can test allocating */
333 generic_buffer_free(buf2);
334 buf2 = NULL;
335 tt_int_op(0, OP_EQ, generic_buffer_set_to_copy(&buf2, buf));
336 tt_int_op(len, OP_EQ, generic_buffer_len(buf2));
337 generic_buffer_get(buf2, b, len);
338 tt_mem_op(b, OP_EQ, s, len);
339 /* Clear buf for next test */
340 generic_buffer_get(buf, b, len);
341 tt_int_op(generic_buffer_len(buf),OP_EQ,0);
343 /* Okay, now let's try a bigger buffer. */
344 s = "Quis autem vel eum iure reprehenderit qui in ea voluptate velit "
345 "esse quam nihil molestiae consequatur, vel illum qui dolorem eum "
346 "fugiat quo voluptas nulla pariatur?";
347 len = strlen(s);
348 for (i = 0; i < 256; ++i) {
349 b[0]=i;
350 generic_buffer_add(buf, b, 1);
351 generic_buffer_add(buf, s, len);
353 tt_int_op(0, OP_EQ, generic_buffer_set_to_copy(&buf2, buf));
354 tt_int_op(generic_buffer_len(buf2), OP_EQ, generic_buffer_len(buf));
355 for (i = 0; i < 256; ++i) {
356 generic_buffer_get(buf2, b, len+1);
357 tt_int_op((unsigned char)b[0],OP_EQ,i);
358 tt_mem_op(b+1, OP_EQ, s, len);
361 done:
362 if (buf)
363 generic_buffer_free(buf);
364 if (buf2)
365 generic_buffer_free(buf2);
368 static void
369 test_buffer_ext_or_cmd(void *arg)
371 ext_or_cmd_t *cmd = NULL;
372 generic_buffer_t *buf = generic_buffer_new();
373 char *tmp = NULL;
374 (void) arg;
376 /* Empty -- should give "not there. */
377 tt_int_op(0, OP_EQ, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
378 tt_ptr_op(NULL, OP_EQ, cmd);
380 /* Three bytes: shouldn't work. */
381 generic_buffer_add(buf, "\x00\x20\x00", 3);
382 tt_int_op(0, OP_EQ, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
383 tt_ptr_op(NULL, OP_EQ, cmd);
384 tt_int_op(3, OP_EQ, generic_buffer_len(buf));
386 /* 0020 0000: That's a nil command. It should work. */
387 generic_buffer_add(buf, "\x00", 1);
388 tt_int_op(1, OP_EQ, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
389 tt_ptr_op(NULL, OP_NE, cmd);
390 tt_int_op(0x20, OP_EQ, cmd->cmd);
391 tt_int_op(0, OP_EQ, cmd->len);
392 tt_int_op(0, OP_EQ, generic_buffer_len(buf));
393 ext_or_cmd_free(cmd);
394 cmd = NULL;
396 /* Now try a length-6 command with one byte missing. */
397 generic_buffer_add(buf, "\x10\x21\x00\x06""abcde", 9);
398 tt_int_op(0, OP_EQ, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
399 tt_ptr_op(NULL, OP_EQ, cmd);
400 generic_buffer_add(buf, "f", 1);
401 tt_int_op(1, OP_EQ, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
402 tt_ptr_op(NULL, OP_NE, cmd);
403 tt_int_op(0x1021, OP_EQ, cmd->cmd);
404 tt_int_op(6, OP_EQ, cmd->len);
405 tt_mem_op("abcdef", OP_EQ, cmd->body, 6);
406 tt_int_op(0, OP_EQ, generic_buffer_len(buf));
407 ext_or_cmd_free(cmd);
408 cmd = NULL;
410 /* Now try a length-10 command with 4 extra bytes. */
411 generic_buffer_add(buf, "\xff\xff\x00\x0a"
412 "loremipsum\x10\x00\xff\xff", 18);
413 tt_int_op(1, OP_EQ, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
414 tt_ptr_op(NULL, OP_NE, cmd);
415 tt_int_op(0xffff, OP_EQ, cmd->cmd);
416 tt_int_op(10, OP_EQ, cmd->len);
417 tt_mem_op("loremipsum", OP_EQ, cmd->body, 10);
418 tt_int_op(4, OP_EQ, generic_buffer_len(buf));
419 ext_or_cmd_free(cmd);
420 cmd = NULL;
422 /* Finally, let's try a maximum-length command. We already have the header
423 * waiting. */
424 tt_int_op(0, OP_EQ, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
425 tmp = tor_malloc_zero(65535);
426 generic_buffer_add(buf, tmp, 65535);
427 tt_int_op(1, OP_EQ, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
428 tt_ptr_op(NULL, OP_NE, cmd);
429 tt_int_op(0x1000, OP_EQ, cmd->cmd);
430 tt_int_op(0xffff, OP_EQ, cmd->len);
431 tt_mem_op(tmp, OP_EQ, cmd->body, 65535);
432 tt_int_op(0, OP_EQ, generic_buffer_len(buf));
433 ext_or_cmd_free(cmd);
434 cmd = NULL;
436 done:
437 ext_or_cmd_free(cmd);
438 generic_buffer_free(buf);
439 tor_free(tmp);
442 static void
443 test_buffer_allocation_tracking(void *arg)
445 char *junk = tor_malloc(16384);
446 buf_t *buf1 = NULL, *buf2 = NULL;
447 int i;
449 (void)arg;
451 crypto_rand(junk, 16384);
452 tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
454 buf1 = buf_new();
455 tt_assert(buf1);
456 buf2 = buf_new();
457 tt_assert(buf2);
459 tt_int_op(buf_allocation(buf1), OP_EQ, 0);
460 tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
462 write_to_buf(junk, 4000, buf1);
463 write_to_buf(junk, 4000, buf1);
464 write_to_buf(junk, 4000, buf1);
465 write_to_buf(junk, 4000, buf1);
466 tt_int_op(buf_allocation(buf1), OP_EQ, 16384);
467 fetch_from_buf(junk, 100, buf1);
468 tt_int_op(buf_allocation(buf1), OP_EQ, 16384); /* still 4 4k chunks */
470 tt_int_op(buf_get_total_allocation(), OP_EQ, 16384);
472 fetch_from_buf(junk, 4096, buf1); /* drop a 1k chunk... */
473 tt_int_op(buf_allocation(buf1), OP_EQ, 3*4096); /* now 3 4k chunks */
475 tt_int_op(buf_get_total_allocation(), OP_EQ, 12288); /* that chunk was really
476 freed. */
478 write_to_buf(junk, 4000, buf2);
479 tt_int_op(buf_allocation(buf2), OP_EQ, 4096); /* another 4k chunk. */
481 * We bounce back up to 16384 by allocating a new chunk.
483 tt_int_op(buf_get_total_allocation(), OP_EQ, 16384);
484 write_to_buf(junk, 4000, buf2);
485 tt_int_op(buf_allocation(buf2), OP_EQ, 8192); /* another 4k chunk. */
486 tt_int_op(buf_get_total_allocation(),
487 OP_EQ, 5*4096); /* that chunk was new. */
489 /* Make a really huge buffer */
490 for (i = 0; i < 1000; ++i) {
491 write_to_buf(junk, 4000, buf2);
493 tt_int_op(buf_allocation(buf2), OP_GE, 4008000);
494 tt_int_op(buf_get_total_allocation(), OP_GE, 4008000);
495 buf_free(buf2);
496 buf2 = NULL;
498 tt_int_op(buf_get_total_allocation(), OP_LT, 4008000);
499 tt_int_op(buf_get_total_allocation(), OP_EQ, buf_allocation(buf1));
500 buf_free(buf1);
501 buf1 = NULL;
502 tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
504 done:
505 buf_free(buf1);
506 buf_free(buf2);
507 tor_free(junk);
510 static void
511 test_buffer_time_tracking(void *arg)
513 buf_t *buf=NULL, *buf2=NULL;
514 struct timeval tv0;
515 const time_t START = 1389288246;
516 const uint32_t START_MSEC = (uint32_t) ((uint64_t)START * 1000);
517 int i;
518 char tmp[4096];
519 (void)arg;
521 crypto_rand(tmp, sizeof(tmp));
523 tv0.tv_sec = START;
524 tv0.tv_usec = 0;
526 buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
527 tt_assert(buf);
529 /* Empty buffer means the timestamp is 0. */
530 tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC));
531 tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000));
533 tor_gettimeofday_cache_set(&tv0);
534 write_to_buf("ABCDEFG", 7, buf);
535 tt_int_op(1000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000));
537 buf2 = buf_copy(buf);
538 tt_assert(buf2);
539 tt_int_op(1234, OP_EQ,
540 buf_get_oldest_chunk_timestamp(buf2, START_MSEC+1234));
542 /* Now add more bytes; enough to overflow the first chunk. */
543 tv0.tv_usec += 123 * 1000;
544 tor_gettimeofday_cache_set(&tv0);
545 for (i = 0; i < 600; ++i)
546 write_to_buf("ABCDEFG", 7, buf);
547 tt_int_op(4207, OP_EQ, buf_datalen(buf));
549 /* The oldest bytes are still in the front. */
550 tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000));
552 /* Once those bytes are dropped, the chunk is still on the first
553 * timestamp. */
554 fetch_from_buf(tmp, 100, buf);
555 tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000));
557 /* But once we discard the whole first chunk, we get the data in the second
558 * chunk. */
559 fetch_from_buf(tmp, 4000, buf);
560 tt_int_op(107, OP_EQ, buf_datalen(buf));
561 tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123));
563 /* This time we'll be grabbing a chunk from the freelist, and making sure
564 its time gets updated */
565 tv0.tv_sec += 5;
566 tv0.tv_usec = 617*1000;
567 tor_gettimeofday_cache_set(&tv0);
568 for (i = 0; i < 600; ++i)
569 write_to_buf("ABCDEFG", 7, buf);
570 tt_int_op(4307, OP_EQ, buf_datalen(buf));
572 tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123));
573 fetch_from_buf(tmp, 4000, buf);
574 fetch_from_buf(tmp, 306, buf);
575 tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+5617));
576 tt_int_op(383, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+6000));
578 done:
579 buf_free(buf);
580 buf_free(buf2);
583 static void
584 test_buffers_zlib_impl(int finalize_with_nil)
586 char *msg = NULL;
587 char *contents = NULL;
588 char *expanded = NULL;
589 buf_t *buf = NULL;
590 tor_zlib_state_t *zlib_state = NULL;
591 size_t out_len, in_len;
592 int done;
594 buf = buf_new_with_capacity(128); /* will round up */
595 zlib_state = tor_zlib_new(1, ZLIB_METHOD, HIGH_COMPRESSION);
597 msg = tor_malloc(512);
598 crypto_rand(msg, 512);
599 tt_int_op(write_to_buf_zlib(buf, zlib_state, msg, 128, 0), OP_EQ, 0);
600 tt_int_op(write_to_buf_zlib(buf, zlib_state, msg+128, 128, 0), OP_EQ, 0);
601 tt_int_op(write_to_buf_zlib(buf, zlib_state, msg+256, 256, 0), OP_EQ, 0);
602 done = !finalize_with_nil;
603 tt_int_op(write_to_buf_zlib(buf, zlib_state, "all done", 9, done), OP_EQ, 0);
604 if (finalize_with_nil) {
605 tt_int_op(write_to_buf_zlib(buf, zlib_state, "", 0, 1), OP_EQ, 0);
608 in_len = buf_datalen(buf);
609 contents = tor_malloc(in_len);
611 tt_int_op(fetch_from_buf(contents, in_len, buf), OP_EQ, 0);
613 tt_int_op(0, OP_EQ, tor_gzip_uncompress(&expanded, &out_len,
614 contents, in_len,
615 ZLIB_METHOD, 1,
616 LOG_WARN));
618 tt_int_op(out_len, OP_GE, 128);
619 tt_mem_op(msg, OP_EQ, expanded, 128);
620 tt_int_op(out_len, OP_GE, 512);
621 tt_mem_op(msg, OP_EQ, expanded, 512);
622 tt_int_op(out_len, OP_EQ, 512+9);
623 tt_mem_op("all done", OP_EQ, expanded+512, 9);
625 done:
626 buf_free(buf);
627 tor_zlib_free(zlib_state);
628 tor_free(contents);
629 tor_free(expanded);
630 tor_free(msg);
633 static void
634 test_buffers_zlib(void *arg)
636 (void) arg;
637 test_buffers_zlib_impl(0);
639 static void
640 test_buffers_zlib_fin_with_nil(void *arg)
642 (void) arg;
643 test_buffers_zlib_impl(1);
646 static void
647 test_buffers_zlib_fin_at_chunk_end(void *arg)
649 char *msg = NULL;
650 char *contents = NULL;
651 char *expanded = NULL;
652 buf_t *buf = NULL;
653 tor_zlib_state_t *zlib_state = NULL;
654 size_t out_len, in_len;
655 size_t sz, headerjunk;
656 (void) arg;
658 buf = buf_new_with_capacity(128); /* will round up */
659 sz = buf_get_default_chunk_size(buf);
660 msg = tor_malloc_zero(sz);
662 write_to_buf(msg, 1, buf);
663 tt_assert(buf->head);
665 /* Fill up the chunk so the zlib stuff won't fit in one chunk. */
666 tt_uint_op(buf->head->memlen, OP_LT, sz);
667 headerjunk = buf->head->memlen - 7;
668 write_to_buf(msg, headerjunk-1, buf);
669 tt_uint_op(buf->head->datalen, OP_EQ, headerjunk);
670 tt_uint_op(buf_datalen(buf), OP_EQ, headerjunk);
671 /* Write an empty string, with finalization on. */
672 zlib_state = tor_zlib_new(1, ZLIB_METHOD, HIGH_COMPRESSION);
673 tt_int_op(write_to_buf_zlib(buf, zlib_state, "", 0, 1), OP_EQ, 0);
675 in_len = buf_datalen(buf);
676 contents = tor_malloc(in_len);
678 tt_int_op(fetch_from_buf(contents, in_len, buf), OP_EQ, 0);
680 tt_uint_op(in_len, OP_GT, headerjunk);
682 tt_int_op(0, OP_EQ, tor_gzip_uncompress(&expanded, &out_len,
683 contents + headerjunk, in_len - headerjunk,
684 ZLIB_METHOD, 1,
685 LOG_WARN));
687 tt_int_op(out_len, OP_EQ, 0);
688 tt_assert(expanded);
690 done:
691 buf_free(buf);
692 tor_zlib_free(zlib_state);
693 tor_free(contents);
694 tor_free(expanded);
695 tor_free(msg);
698 const uint8_t *tls_read_ptr;
699 int n_remaining;
700 int next_reply_val[16];
702 static int
703 mock_tls_read(tor_tls_t *tls, char *cp, size_t len)
705 (void)tls;
706 int rv = next_reply_val[0];
707 if (rv > 0) {
708 int max = rv > (int)len ? (int)len : rv;
709 if (max > n_remaining)
710 max = n_remaining;
711 memcpy(cp, tls_read_ptr, max);
712 rv = max;
713 n_remaining -= max;
714 tls_read_ptr += max;
717 memmove(next_reply_val, next_reply_val + 1, 15*sizeof(int));
718 return rv;
721 static void
722 test_buffers_tls_read_mocked(void *arg)
724 uint8_t *mem;
725 buf_t *buf;
726 (void)arg;
728 mem = tor_malloc(64*1024);
729 crypto_rand((char*)mem, 64*1024);
730 tls_read_ptr = mem;
731 n_remaining = 64*1024;
733 MOCK(tor_tls_read, mock_tls_read);
735 buf = buf_new();
737 next_reply_val[0] = 1024;
738 tt_int_op(128, ==, read_to_buf_tls(NULL, 128, buf));
740 next_reply_val[0] = 5000;
741 next_reply_val[1] = 5000;
742 tt_int_op(6000, ==, read_to_buf_tls(NULL, 6000, buf));
744 done:
745 UNMOCK(tor_tls_read);
746 tor_free(mem);
747 buf_free(buf);
750 struct testcase_t buffer_tests[] = {
751 { "basic", test_buffers_basic, TT_FORK, NULL, NULL },
752 { "copy", test_buffer_copy, TT_FORK, NULL, NULL },
753 { "pullup", test_buffer_pullup, TT_FORK, NULL, NULL },
754 { "ext_or_cmd", test_buffer_ext_or_cmd, TT_FORK, NULL, NULL },
755 { "allocation_tracking", test_buffer_allocation_tracking, TT_FORK,
756 NULL, NULL },
757 { "time_tracking", test_buffer_time_tracking, TT_FORK, NULL, NULL },
758 { "zlib", test_buffers_zlib, TT_FORK, NULL, NULL },
759 { "zlib_fin_with_nil", test_buffers_zlib_fin_with_nil, TT_FORK, NULL, NULL },
760 { "zlib_fin_at_chunk_end", test_buffers_zlib_fin_at_chunk_end, TT_FORK,
761 NULL, NULL},
762 { "tls_read_mocked", test_buffers_tls_read_mocked, 0,
763 NULL, NULL },
764 END_OF_TESTCASES