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
9 #include "ext_orport.h"
12 /** Run unit tests for buffers.c */
14 test_buffers_basic(void *arg
)
19 buf_t
*buf
= NULL
, *buf2
= NULL
;
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);
36 * General pointer frobbing
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. */
57 write_to_buf(str
, 256, 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);
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);
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);
82 write_to_buf(str
, 32, buf
);
83 //test_eq(buf_capacity(buf), 256);
85 write_to_buf(str
, 256, 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. */
100 buf
= buf_new_with_capacity(33668);
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. */
113 buf
= buf_new_with_capacity(33668);
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);
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. */
132 buf
= buf_new_with_capacity(4096);
133 buf2
= buf_new_with_capacity(4096);
135 write_to_buf(str
, 255, buf
);
136 tt_int_op(buf_datalen(buf
),OP_EQ
, 25500);
137 for (j
=0;j
<100;++j
) {
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);
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);
155 fetch_from_buf(str2
, 255, buf2
);
156 tt_mem_op(str2
,OP_EQ
, str
, 255);
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));
179 /* Try adding a string too long for any freelist. */
181 char *cp
= tor_malloc_zero(65536);
183 write_to_buf(cp
, 65536, buf
);
186 tt_int_op(buf_datalen(buf
), OP_EQ
, 65536);
199 test_buffer_pullup(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. */
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. */
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
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);
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);
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);
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);
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. */
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);
296 tt_int_op(buf_get_total_allocation(), OP_EQ
, 0);
304 test_buffer_copy(void *arg
)
306 generic_buffer_t
*buf
=NULL
, *buf2
=NULL
;
313 buf
= generic_buffer_new();
316 /* Copy an empty buffer. */
317 tt_int_op(0, OP_EQ
, generic_buffer_set_to_copy(&buf2
, buf
));
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!";
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
);
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?";
348 for (i
= 0; i
< 256; ++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
);
363 generic_buffer_free(buf
);
365 generic_buffer_free(buf2
);
369 test_buffer_ext_or_cmd(void *arg
)
371 ext_or_cmd_t
*cmd
= NULL
;
372 generic_buffer_t
*buf
= generic_buffer_new();
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
);
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
);
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
);
422 /* Finally, let's try a maximum-length command. We already have the header
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
);
437 ext_or_cmd_free(cmd
);
438 generic_buffer_free(buf
);
443 test_buffer_allocation_tracking(void *arg
)
445 char *junk
= tor_malloc(16384);
446 buf_t
*buf1
= NULL
, *buf2
= NULL
;
451 crypto_rand(junk
, 16384);
452 tt_int_op(buf_get_total_allocation(), OP_EQ
, 0);
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
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);
498 tt_int_op(buf_get_total_allocation(), OP_LT
, 4008000);
499 tt_int_op(buf_get_total_allocation(), OP_EQ
, buf_allocation(buf1
));
502 tt_int_op(buf_get_total_allocation(), OP_EQ
, 0);
511 test_buffer_time_tracking(void *arg
)
513 buf_t
*buf
=NULL
, *buf2
=NULL
;
515 const time_t START
= 1389288246;
516 const uint32_t START_MSEC
= (uint32_t) ((uint64_t)START
* 1000);
521 crypto_rand(tmp
, sizeof(tmp
));
526 buf
= buf_new_with_capacity(3000); /* rounds up to next power of 2. */
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
);
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
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
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 */
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));
584 test_buffers_zlib_impl(int finalize_with_nil
)
587 char *contents
= NULL
;
588 char *expanded
= NULL
;
590 tor_zlib_state_t
*zlib_state
= NULL
;
591 size_t out_len
, in_len
;
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
,
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);
627 tor_zlib_free(zlib_state
);
634 test_buffers_zlib(void *arg
)
637 test_buffers_zlib_impl(0);
640 test_buffers_zlib_fin_with_nil(void *arg
)
643 test_buffers_zlib_impl(1);
647 test_buffers_zlib_fin_at_chunk_end(void *arg
)
650 char *contents
= NULL
;
651 char *expanded
= NULL
;
653 tor_zlib_state_t
*zlib_state
= NULL
;
654 size_t out_len
, in_len
;
655 size_t sz
, headerjunk
;
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
,
687 tt_int_op(out_len
, OP_EQ
, 0);
692 tor_zlib_free(zlib_state
);
698 const uint8_t *tls_read_ptr
;
700 int next_reply_val
[16];
703 mock_tls_read(tor_tls_t
*tls
, char *cp
, size_t len
)
706 int rv
= next_reply_val
[0];
708 int max
= rv
> (int)len
? (int)len
: rv
;
709 if (max
> n_remaining
)
711 memcpy(cp
, tls_read_ptr
, max
);
717 memmove(next_reply_val
, next_reply_val
+ 1, 15*sizeof(int));
722 test_buffers_tls_read_mocked(void *arg
)
728 mem
= tor_malloc(64*1024);
729 crypto_rand((char*)mem
, 64*1024);
731 n_remaining
= 64*1024;
733 MOCK(tor_tls_read
, mock_tls_read
);
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
));
745 UNMOCK(tor_tls_read
);
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
,
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
,
762 { "tls_read_mocked", test_buffers_tls_read_mocked
, 0,