1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2019, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #define BUFFERS_PRIVATE
7 #define PROTO_HTTP_PRIVATE
8 #include "core/or/or.h"
9 #include "lib/buf/buffers.h"
10 #include "lib/tls/buffers_tls.h"
11 #include "lib/tls/tortls.h"
12 #include "lib/compress/compress.h"
13 #include "lib/crypt_ops/crypto_rand.h"
14 #include "core/proto/proto_http.h"
15 #include "core/proto/proto_socks.h"
16 #include "test/test.h"
18 /** Run unit tests for buffers.c */
20 test_buffers_basic(void *arg
)
25 buf_t
*buf
= NULL
, *buf2
= NULL
;
35 if (!(buf
= buf_new()))
36 TT_DIE(("Assertion failed."));
38 //test_eq(buf_capacity(buf), 4096);
39 tt_int_op(buf_datalen(buf
),OP_EQ
, 0);
42 * General pointer frobbing
47 buf_add(buf
, str
, 256);
48 buf_add(buf
, str
, 256);
49 tt_int_op(buf_datalen(buf
),OP_EQ
, 512);
50 buf_get_bytes(buf
, str2
, 200);
51 tt_mem_op(str
,OP_EQ
, str2
, 200);
52 tt_int_op(buf_datalen(buf
),OP_EQ
, 312);
53 memset(str2
, 0, sizeof(str2
));
55 buf_get_bytes(buf
, str2
, 256);
56 tt_mem_op(str
+200,OP_EQ
, str2
, 56);
57 tt_mem_op(str
,OP_EQ
, str2
+56, 200);
58 tt_int_op(buf_datalen(buf
),OP_EQ
, 56);
59 memset(str2
, 0, sizeof(str2
));
60 /* Okay, now we should be 512 bytes into the 4096-byte buffer. If we add
61 * another 3584 bytes, we hit the end. */
63 buf_add(buf
, str
, 256);
66 tt_int_op(buf_datalen(buf
),OP_EQ
, 3896);
67 buf_get_bytes(buf
, str2
, 56);
68 tt_int_op(buf_datalen(buf
),OP_EQ
, 3840);
69 tt_mem_op(str
+200,OP_EQ
, str2
, 56);
71 memset(str2
, 0, sizeof(str2
));
72 buf_get_bytes(buf
, str2
, 256);
73 tt_mem_op(str
,OP_EQ
, str2
, 256);
75 tt_int_op(buf_datalen(buf
),OP_EQ
, 0);
79 /* Okay, now make sure growing can work. */
80 buf
= buf_new_with_capacity(16);
81 //test_eq(buf_capacity(buf), 16);
82 buf_add(buf
, str
+1, 255);
83 //test_eq(buf_capacity(buf), 256);
84 buf_get_bytes(buf
, str2
, 254);
85 tt_mem_op(str
+1,OP_EQ
, str2
, 254);
86 //test_eq(buf_capacity(buf), 256);
88 buf_add(buf
, str
, 32);
89 //test_eq(buf_capacity(buf), 256);
91 buf_add(buf
, str
, 256);
93 //test_eq(buf_capacity(buf), 512);
94 tt_int_op(buf_datalen(buf
),OP_EQ
, 33+256);
95 buf_get_bytes(buf
, str2
, 33);
96 tt_int_op(*str2
,OP_EQ
, str
[255]);
98 tt_mem_op(str2
+1,OP_EQ
, str
, 32);
99 //test_eq(buf_capacity(buf), 512);
100 tt_int_op(buf_datalen(buf
),OP_EQ
, 256);
101 buf_get_bytes(buf
, str2
, 256);
102 tt_mem_op(str
,OP_EQ
, str2
, 256);
104 /* now try shrinking: case 1. */
106 buf
= buf_new_with_capacity(33668);
108 buf_add(buf
, str
,255);
110 //test_eq(buf_capacity(buf), 33668);
111 tt_int_op(buf_datalen(buf
),OP_EQ
, 17085);
112 for (j
=0; j
< 40; ++j
) {
113 buf_get_bytes(buf
, str2
, 255);
114 tt_mem_op(str2
,OP_EQ
, str
, 255);
117 /* now try shrinking: case 2. */
119 buf
= buf_new_with_capacity(33668);
121 buf_add(buf
, str
, 255);
123 for (j
=0; j
< 20; ++j
) {
124 buf_get_bytes(buf
, str2
, 255);
125 tt_mem_op(str2
,OP_EQ
, str
, 255);
128 buf_add(buf
, str
, 255);
130 //test_eq(buf_capacity(buf),33668);
131 for (j
=0; j
< 120; ++j
) {
132 buf_get_bytes(buf
, str2
, 255);
133 tt_mem_op(str2
,OP_EQ
, str
, 255);
136 /* Move from buf to buf. */
138 buf
= buf_new_with_capacity(4096);
139 buf2
= buf_new_with_capacity(4096);
141 buf_add(buf
, str
, 255);
142 tt_int_op(buf_datalen(buf
),OP_EQ
, 25500);
143 for (j
=0;j
<100;++j
) {
145 buf_move_to_buf(buf2
, buf
, &r
);
146 tt_int_op(r
,OP_EQ
, 0);
148 tt_int_op(buf_datalen(buf
),OP_EQ
, 24500);
149 tt_int_op(buf_datalen(buf2
),OP_EQ
, 1000);
151 buf_get_bytes(buf2
, str2
, 255);
152 tt_mem_op(str2
,OP_EQ
, str
, 255);
154 r
= 8192; /*big move*/
155 buf_move_to_buf(buf2
, buf
, &r
);
156 tt_int_op(r
,OP_EQ
, 0);
157 r
= 30000; /* incomplete move */
158 buf_move_to_buf(buf2
, buf
, &r
);
159 tt_int_op(r
,OP_EQ
, 13692);
161 buf_get_bytes(buf2
, str2
, 255);
162 tt_mem_op(str2
,OP_EQ
, str
, 255);
168 buf
= buf_new_with_capacity(5);
169 cp
= "Testing. This is a moderately long Testing string.";
170 for (j
= 0; cp
[j
]; j
++)
171 buf_add(buf
, cp
+j
, 1);
172 tt_int_op(0,OP_EQ
, buf_find_string_offset(buf
, "Testing", 7));
173 tt_int_op(1,OP_EQ
, buf_find_string_offset(buf
, "esting", 6));
174 tt_int_op(1,OP_EQ
, buf_find_string_offset(buf
, "est", 3));
175 tt_int_op(39,OP_EQ
, buf_find_string_offset(buf
, "ing str", 7));
176 tt_int_op(35,OP_EQ
, buf_find_string_offset(buf
, "Testing str", 11));
177 tt_int_op(32,OP_EQ
, buf_find_string_offset(buf
, "ng ", 3));
178 tt_int_op(43,OP_EQ
, buf_find_string_offset(buf
, "string.", 7));
179 tt_int_op(-1,OP_EQ
, buf_find_string_offset(buf
, "shrdlu", 6));
180 tt_int_op(-1,OP_EQ
, buf_find_string_offset(buf
, "Testing thing", 13));
181 tt_int_op(-1,OP_EQ
, buf_find_string_offset(buf
, "ngx", 3));
185 /* Try adding a string too long for any freelist. */
187 char *mem
= tor_malloc_zero(65536);
189 buf_add(buf
, mem
, 65536);
192 tt_int_op(buf_datalen(buf
), OP_EQ
, 65536);
205 test_buffer_pullup(void *arg
)
212 stuff
= tor_malloc(16384);
213 tmp
= tor_malloc(16384);
215 buf
= buf_new_with_capacity(3000); /* rounds up to next power of 2. */
218 tt_int_op(buf_get_default_chunk_size(buf
), OP_EQ
, 4096);
220 tt_int_op(buf_get_total_allocation(), OP_EQ
, 0);
222 /* There are a bunch of cases for pullup. One is the trivial case. Let's
223 mess around with an empty buffer. */
224 buf_pullup(buf
, 16, &cp
, &sz
);
225 tt_ptr_op(cp
, OP_EQ
, NULL
);
226 tt_uint_op(sz
, OP_EQ
, 0);
228 /* Let's make sure nothing got allocated */
229 tt_int_op(buf_get_total_allocation(), OP_EQ
, 0);
231 /* Case 1: everything puts into the first chunk with some moving. */
233 /* Let's add some data. */
234 crypto_rand(stuff
, 16384);
235 buf_add(buf
, stuff
, 3000);
236 buf_add(buf
, stuff
+3000, 3000);
237 buf_pullup(buf
, 0, &cp
, &sz
);
238 tt_ptr_op(cp
, OP_NE
, NULL
);
239 tt_int_op(sz
, OP_LE
, 4096);
241 /* Make room for 3000 bytes in the first chunk, so that the pullup-move code
243 tt_int_op(buf_get_bytes(buf
, tmp
, 3000), OP_EQ
, 3000);
244 tt_mem_op(tmp
,OP_EQ
, stuff
, 3000);
245 buf_pullup(buf
, 2048, &cp
, &sz
);
247 tt_ptr_op(cp
, OP_NE
, NULL
);
248 tt_int_op(sz
, OP_GE
, 2048);
249 tt_mem_op(cp
,OP_EQ
, stuff
+3000, 2048);
250 tt_int_op(3000, OP_EQ
, buf_datalen(buf
));
251 tt_int_op(buf_get_bytes(buf
, tmp
, 3000), OP_EQ
, 0);
252 tt_mem_op(tmp
,OP_EQ
, stuff
+3000, 2048);
256 /* Now try the large-chunk case. */
257 buf
= buf_new_with_capacity(3000); /* rounds up to next power of 2. */
258 buf_add(buf
, stuff
, 4000);
259 buf_add(buf
, stuff
+4000, 4000);
260 buf_add(buf
, stuff
+8000, 4000);
261 buf_add(buf
, stuff
+12000, 4000);
262 tt_int_op(buf_datalen(buf
), OP_EQ
, 16000);
263 buf_pullup(buf
, 0, &cp
, &sz
);
264 tt_ptr_op(cp
, OP_NE
, NULL
);
265 tt_int_op(sz
, OP_LE
, 4096);
267 buf_pullup(buf
, 12500, &cp
, &sz
);
269 tt_ptr_op(cp
, OP_NE
, NULL
);
270 tt_int_op(sz
, OP_GE
, 12500);
271 tt_mem_op(cp
,OP_EQ
, stuff
, 12500);
272 tt_int_op(buf_datalen(buf
), OP_EQ
, 16000);
274 buf_get_bytes(buf
, tmp
, 12400);
275 tt_mem_op(tmp
,OP_EQ
, stuff
, 12400);
276 tt_int_op(buf_datalen(buf
), OP_EQ
, 3600);
277 buf_get_bytes(buf
, tmp
, 3500);
278 tt_mem_op(tmp
,OP_EQ
, stuff
+12400, 3500);
279 buf_get_bytes(buf
, tmp
, 100);
280 tt_mem_op(tmp
,OP_EQ
, stuff
+15900, 10);
284 /* Make sure that the pull-up-whole-buffer case works */
285 buf
= buf_new_with_capacity(3000); /* rounds up to next power of 2. */
286 buf_add(buf
, stuff
, 4000);
287 buf_add(buf
, stuff
+4000, 4000);
288 buf_get_bytes(buf
, tmp
, 100); /* dump 100 bytes from first chunk */
289 buf_pullup(buf
, 16000, &cp
, &sz
);
291 tt_ptr_op(cp
, OP_NE
, NULL
);
292 tt_int_op(sz
, OP_EQ
, 7900);
293 tt_mem_op(cp
,OP_EQ
, stuff
+100, 7900);
298 tt_int_op(buf_get_total_allocation(), OP_EQ
, 0);
306 test_buffer_copy(void *arg
)
308 buf_t
*buf
=NULL
, *buf2
=NULL
;
318 /* Copy an empty buffer. */
319 tt_int_op(0, OP_EQ
, buf_set_to_copy(&buf2
, buf
));
321 tt_int_op(0, OP_EQ
, buf_datalen(buf2
));
323 /* Now try with a short buffer. */
324 s
= "And now comes an act of enormous enormance!";
326 buf_add(buf
, s
, len
);
327 tt_int_op(len
, OP_EQ
, buf_datalen(buf
));
328 /* Add junk to buf2 so we can test replacing.*/
329 buf_add(buf2
, "BLARG", 5);
330 tt_int_op(0, OP_EQ
, buf_set_to_copy(&buf2
, buf
));
331 tt_int_op(len
, OP_EQ
, buf_datalen(buf2
));
332 buf_get_bytes(buf2
, b
, len
);
333 tt_mem_op(b
, OP_EQ
, s
, len
);
334 /* Now free buf2 and retry so we can test allocating */
337 tt_int_op(0, OP_EQ
, buf_set_to_copy(&buf2
, buf
));
338 tt_int_op(len
, OP_EQ
, buf_datalen(buf2
));
339 buf_get_bytes(buf2
, b
, len
);
340 tt_mem_op(b
, OP_EQ
, s
, len
);
341 /* Clear buf for next test */
342 buf_get_bytes(buf
, b
, len
);
343 tt_int_op(buf_datalen(buf
),OP_EQ
,0);
345 /* Okay, now let's try a bigger buffer. */
346 s
= "Quis autem vel eum iure reprehenderit qui in ea voluptate velit "
347 "esse quam nihil molestiae consequatur, vel illum qui dolorem eum "
348 "fugiat quo voluptas nulla pariatur?";
350 for (i
= 0; i
< 256; ++i
) {
353 buf_add(buf
, s
, len
);
355 tt_int_op(0, OP_EQ
, buf_set_to_copy(&buf2
, buf
));
356 tt_int_op(buf_datalen(buf2
), OP_EQ
, buf_datalen(buf
));
357 for (i
= 0; i
< 256; ++i
) {
358 buf_get_bytes(buf2
, b
, len
+1);
359 tt_int_op((unsigned char)b
[0],OP_EQ
,i
);
360 tt_mem_op(b
+1, OP_EQ
, s
, len
);
371 test_buffer_allocation_tracking(void *arg
)
373 char *junk
= tor_malloc(16384);
374 buf_t
*buf1
= NULL
, *buf2
= NULL
;
379 crypto_rand(junk
, 16384);
380 tt_int_op(buf_get_total_allocation(), OP_EQ
, 0);
387 tt_int_op(buf_allocation(buf1
), OP_EQ
, 0);
388 tt_int_op(buf_get_total_allocation(), OP_EQ
, 0);
390 buf_add(buf1
, junk
, 4000);
391 buf_add(buf1
, junk
, 4000);
392 buf_add(buf1
, junk
, 4000);
393 buf_add(buf1
, junk
, 4000);
394 tt_int_op(buf_allocation(buf1
), OP_EQ
, 16384);
395 buf_get_bytes(buf1
, junk
, 100);
396 tt_int_op(buf_allocation(buf1
), OP_EQ
, 16384); /* still 4 4k chunks */
398 tt_int_op(buf_get_total_allocation(), OP_EQ
, 16384);
400 buf_get_bytes(buf1
, junk
, 4096); /* drop a 1k chunk... */
401 tt_int_op(buf_allocation(buf1
), OP_EQ
, 3*4096); /* now 3 4k chunks */
403 tt_int_op(buf_get_total_allocation(), OP_EQ
, 12288); /* that chunk was really
406 buf_add(buf2
, junk
, 4000);
407 tt_int_op(buf_allocation(buf2
), OP_EQ
, 4096); /* another 4k chunk. */
409 * We bounce back up to 16384 by allocating a new chunk.
411 tt_int_op(buf_get_total_allocation(), OP_EQ
, 16384);
412 buf_add(buf2
, junk
, 4000);
413 tt_int_op(buf_allocation(buf2
), OP_EQ
, 8192); /* another 4k chunk. */
414 tt_int_op(buf_get_total_allocation(),
415 OP_EQ
, 5*4096); /* that chunk was new. */
417 /* Make a really huge buffer */
418 for (i
= 0; i
< 1000; ++i
) {
419 buf_add(buf2
, junk
, 4000);
421 tt_int_op(buf_allocation(buf2
), OP_GE
, 4008000);
422 tt_int_op(buf_get_total_allocation(), OP_GE
, 4008000);
426 tt_int_op(buf_get_total_allocation(), OP_LT
, 4008000);
427 tt_int_op(buf_get_total_allocation(), OP_EQ
, buf_allocation(buf1
));
430 tt_int_op(buf_get_total_allocation(), OP_EQ
, 0);
439 test_buffer_time_tracking(void *arg
)
441 buf_t
*buf
=NULL
, *buf2
=NULL
;
442 const time_t START
= 1389288246;
443 const uint64_t START_NSEC
= ((uint64_t)START
) * 1000000000;
448 crypto_rand(tmp
, sizeof(tmp
));
450 monotime_enable_test_mocking();
452 buf
= buf_new_with_capacity(3000); /* rounds up to next power of 2. */
455 monotime_coarse_set_mock_time_nsec(START_NSEC
);
456 const uint32_t START_TS
= monotime_coarse_get_stamp();
458 /* Empty buffer means the timestamp is 0. */
459 tt_int_op(0, OP_EQ
, buf_get_oldest_chunk_timestamp(buf
, START_TS
));
460 tt_int_op(0, OP_EQ
, buf_get_oldest_chunk_timestamp(buf
, START_TS
+1000));
462 buf_add(buf
, "ABCDEFG", 7);
463 tt_int_op(1000, OP_EQ
, buf_get_oldest_chunk_timestamp(buf
, START_TS
+1000));
465 buf2
= buf_copy(buf
);
467 tt_int_op(1234, OP_EQ
,
468 buf_get_oldest_chunk_timestamp(buf2
, START_TS
+1234));
470 /* Now add more bytes; enough to overflow the first chunk. */
471 monotime_coarse_set_mock_time_nsec(START_NSEC
+ 123 * (uint64_t)1000000);
472 const uint32_t TS2
= monotime_coarse_get_stamp();
473 for (i
= 0; i
< 600; ++i
)
474 buf_add(buf
, "ABCDEFG", 7);
475 tt_int_op(4207, OP_EQ
, buf_datalen(buf
));
477 /* The oldest bytes are still in the front. */
478 tt_int_op(2000, OP_EQ
, buf_get_oldest_chunk_timestamp(buf
, START_TS
+2000));
480 /* Once those bytes are dropped, the chunk is still on the first
482 buf_get_bytes(buf
, tmp
, 100);
483 tt_int_op(2000, OP_EQ
, buf_get_oldest_chunk_timestamp(buf
, START_TS
+2000));
485 /* But once we discard the whole first chunk, we get the data in the second
487 buf_get_bytes(buf
, tmp
, 4000);
488 tt_int_op(107, OP_EQ
, buf_datalen(buf
));
489 tt_int_op(2000, OP_EQ
, buf_get_oldest_chunk_timestamp(buf
, TS2
+2000));
491 /* This time we'll be grabbing a chunk from the freelist, and making sure
492 its time gets updated */
493 monotime_coarse_set_mock_time_nsec(START_NSEC
+ 5617 * (uint64_t)1000000);
494 const uint32_t TS3
= monotime_coarse_get_stamp();
495 for (i
= 0; i
< 600; ++i
)
496 buf_add(buf
, "ABCDEFG", 7);
497 tt_int_op(4307, OP_EQ
, buf_datalen(buf
));
499 tt_int_op(2000, OP_EQ
, buf_get_oldest_chunk_timestamp(buf
, TS2
+2000));
500 buf_get_bytes(buf
, tmp
, 4000);
501 buf_get_bytes(buf
, tmp
, 306);
502 tt_int_op(0, OP_EQ
, buf_get_oldest_chunk_timestamp(buf
, TS3
));
503 tt_int_op(383, OP_EQ
, buf_get_oldest_chunk_timestamp(buf
, TS3
+383));
508 monotime_disable_test_mocking();
512 test_buffers_compress_fin_at_chunk_end_impl(compress_method_t method
,
513 compression_level_t level
)
516 char *contents
= NULL
;
517 char *expanded
= NULL
;
519 tor_compress_state_t
*compress_state
= NULL
;
520 size_t out_len
, in_len
;
521 size_t sz
, headerjunk
;
523 buf
= buf_new_with_capacity(128); /* will round up */
524 sz
= buf_get_default_chunk_size(buf
);
525 msg
= tor_malloc_zero(sz
);
527 buf_add(buf
, msg
, 1);
528 tt_assert(buf
->head
);
530 /* Fill up the chunk so the compression stuff won't fit in one chunk. */
531 tt_uint_op(buf
->head
->memlen
, OP_LT
, sz
);
532 headerjunk
= buf
->head
->memlen
- 7;
533 buf_add(buf
, msg
, headerjunk
-1);
534 tt_uint_op(buf
->head
->datalen
, OP_EQ
, headerjunk
);
535 tt_uint_op(buf_datalen(buf
), OP_EQ
, headerjunk
);
536 /* Write an empty string, with finalization on. */
537 compress_state
= tor_compress_new(1, method
, level
);
538 tt_int_op(buf_add_compress(buf
, compress_state
, "", 0, 1), OP_EQ
, 0);
540 in_len
= buf_datalen(buf
);
541 contents
= tor_malloc(in_len
);
543 tt_int_op(buf_get_bytes(buf
, contents
, in_len
), OP_EQ
, 0);
545 if (method
== NO_METHOD
) {
546 tt_uint_op(in_len
, OP_EQ
, headerjunk
);
548 tt_uint_op(in_len
, OP_GT
, headerjunk
);
551 tt_int_op(0, OP_EQ
, tor_uncompress(&expanded
, &out_len
,
552 contents
+ headerjunk
,
557 tt_int_op(out_len
, OP_EQ
, 0);
562 tor_compress_free(compress_state
);
569 test_buffers_compress_impl(compress_method_t method
,
570 compression_level_t level
,
571 int finalize_with_nil
)
574 char *contents
= NULL
;
575 char *expanded
= NULL
;
577 tor_compress_state_t
*compress_state
= NULL
;
578 size_t out_len
, in_len
;
581 buf
= buf_new_with_capacity(128); /* will round up */
582 compress_state
= tor_compress_new(1, method
, level
);
584 msg
= tor_malloc(512);
585 crypto_rand(msg
, 512);
586 tt_int_op(buf_add_compress(buf
, compress_state
,
587 msg
, 128, 0), OP_EQ
, 0);
588 tt_int_op(buf_add_compress(buf
, compress_state
,
589 msg
+128, 128, 0), OP_EQ
, 0);
590 tt_int_op(buf_add_compress(buf
, compress_state
,
591 msg
+256, 256, 0), OP_EQ
, 0);
592 done
= !finalize_with_nil
;
593 tt_int_op(buf_add_compress(buf
, compress_state
,
594 "all done", 9, done
), OP_EQ
, 0);
595 if (finalize_with_nil
) {
596 tt_int_op(buf_add_compress(buf
, compress_state
, "", 0, 1), OP_EQ
, 0);
599 in_len
= buf_datalen(buf
);
600 contents
= tor_malloc(in_len
);
602 tt_int_op(buf_get_bytes(buf
, contents
, in_len
), OP_EQ
, 0);
604 tt_int_op(0, OP_EQ
, tor_uncompress(&expanded
, &out_len
,
609 tt_int_op(out_len
, OP_GE
, 128);
610 tt_mem_op(msg
, OP_EQ
, expanded
, 128);
611 tt_int_op(out_len
, OP_GE
, 512);
612 tt_mem_op(msg
, OP_EQ
, expanded
, 512);
613 tt_int_op(out_len
, OP_EQ
, 512+9);
614 tt_mem_op("all done", OP_EQ
, expanded
+512, 9);
618 tor_compress_free(compress_state
);
625 test_buffers_compress(void *arg
)
627 const char *methodname
= arg
;
628 tt_assert(methodname
);
630 compress_method_t method
= compression_method_get_by_name(methodname
);
631 tt_int_op(method
, OP_NE
, UNKNOWN_METHOD
);
633 if (! tor_compress_supports_method(method
)) {
637 compression_level_t levels
[] = {
644 for (unsigned l
= 0; l
< ARRAY_LENGTH(levels
); ++l
) {
645 compression_level_t level
= levels
[l
];
647 test_buffers_compress_impl(method
, level
, 0);
648 test_buffers_compress_impl(method
, level
, 1);
649 test_buffers_compress_fin_at_chunk_end_impl(method
, level
);
656 static const uint8_t *tls_read_ptr
;
657 static int n_remaining
;
658 static int next_reply_val
[16];
661 mock_tls_read(tor_tls_t
*tls
, char *cp
, size_t len
)
664 int rv
= next_reply_val
[0];
666 int max
= rv
> (int)len
? (int)len
: rv
;
667 if (max
> n_remaining
)
669 memcpy(cp
, tls_read_ptr
, max
);
675 memmove(next_reply_val
, next_reply_val
+ 1, 15*sizeof(int));
680 test_buffers_tls_read_mocked(void *arg
)
686 mem
= tor_malloc(64*1024);
687 crypto_rand((char*)mem
, 64*1024);
689 n_remaining
= 64*1024;
691 MOCK(tor_tls_read
, mock_tls_read
);
695 next_reply_val
[0] = 1024;
696 tt_int_op(128, OP_EQ
, buf_read_from_tls(buf
, NULL
, 128));
698 next_reply_val
[0] = 5000;
699 next_reply_val
[1] = 5000;
700 tt_int_op(6000, OP_EQ
, buf_read_from_tls(buf
, NULL
, 6000));
703 UNMOCK(tor_tls_read
);
709 test_buffers_chunk_size(void *arg
)
713 const int max
= 65536;
714 tt_uint_op(buf_preferred_chunk_size(3), OP_EQ
, min
);
715 tt_uint_op(buf_preferred_chunk_size(25), OP_EQ
, min
);
716 tt_uint_op(buf_preferred_chunk_size(0), OP_EQ
, min
);
717 tt_uint_op(buf_preferred_chunk_size(256), OP_EQ
, 512);
718 tt_uint_op(buf_preferred_chunk_size(65400), OP_EQ
, max
);
719 /* Here, we're implicitly saying that the chunk header overhead is
720 * between 1 and 100 bytes. 24..48 would probably be more accurate. */
721 tt_uint_op(buf_preferred_chunk_size(65536), OP_GT
, 65536);
722 tt_uint_op(buf_preferred_chunk_size(65536), OP_LT
, 65536+100);
723 tt_uint_op(buf_preferred_chunk_size(165536), OP_GT
, 165536);
724 tt_uint_op(buf_preferred_chunk_size(165536), OP_LT
, 165536+100);
730 test_buffers_find_contentlen(void *arg
)
732 static const struct {
737 { "Blah blah\r\nContent-Length: 1\r\n\r\n", 1, 1 },
738 { "Blah blah\r\n\r\n", 0, 0 }, /* no content-len */
739 { "Blah blah Content-Length: 1\r\n", 0, 0 }, /* no content-len. */
740 { "Blah blah\r\nContent-Length: 100000\r\n", 1, 100000},
741 { "Blah blah\r\nContent-Length: 1000000000000000000000000\r\n", -1, 0},
742 { "Blah blah\r\nContent-Length: 0\r\n", 1, 0},
743 { "Blah blah\r\nContent-Length: -1\r\n", -1, 0},
744 { "Blah blah\r\nContent-Length: 1x\r\n", -1, 0},
745 { "Blah blah\r\nContent-Length: 1 x\r\n", -1, 0},
746 { "Blah blah\r\nContent-Length: 1 \r\n", 1, 1},
747 { "Blah blah\r\nContent-Length: \r\n", -1, 0},
748 { "Blah blah\r\nContent-Length: ", -1, 0},
749 { "Blah blah\r\nContent-Length: 5050", -1, 0},
756 for (i
= 0; results
[i
].headers
; ++i
) {
759 size_t headerlen
= strlen(results
[i
].headers
);
760 char * tmp
= tor_memdup(results
[i
].headers
, headerlen
);/* ensure no eos */
761 sz
= 999; /* to ensure it gets set */
762 r
= buf_http_find_content_length(tmp
, headerlen
, &sz
);
764 log_debug(LD_DIR
, "%d: %s", i
, escaped(results
[i
].headers
));
765 tt_int_op(r
, OP_EQ
, results
[i
].r
);
766 tt_int_op(sz
, OP_EQ
, results
[i
].contentlen
);
773 test_buffer_peek_startswith(void *arg
)
778 tt_ptr_op(buf
, OP_NE
, NULL
);
780 tt_assert(buf_peek_startswith(buf
, ""));
781 tt_assert(! buf_peek_startswith(buf
, "X"));
783 buf_add(buf
, "Tor", 3);
785 tt_assert(buf_peek_startswith(buf
, ""));
786 tt_assert(buf_peek_startswith(buf
, "T"));
787 tt_assert(buf_peek_startswith(buf
, "To"));
788 tt_assert(buf_peek_startswith(buf
, "Tor"));
789 tt_assert(! buf_peek_startswith(buf
, "Top"));
790 tt_assert(! buf_peek_startswith(buf
, "For"));
791 tt_assert(! buf_peek_startswith(buf
, "Tork"));
792 tt_assert(! buf_peek_startswith(buf
, "Torpor"));
798 struct testcase_t buffer_tests
[] = {
799 { "basic", test_buffers_basic
, TT_FORK
, NULL
, NULL
},
800 { "copy", test_buffer_copy
, TT_FORK
, NULL
, NULL
},
801 { "pullup", test_buffer_pullup
, TT_FORK
, NULL
, NULL
},
802 { "startswith", test_buffer_peek_startswith
, 0, NULL
, NULL
},
803 { "allocation_tracking", test_buffer_allocation_tracking
, TT_FORK
,
805 { "time_tracking", test_buffer_time_tracking
, TT_FORK
, NULL
, NULL
},
806 { "tls_read_mocked", test_buffers_tls_read_mocked
, 0,
808 { "chunk_size", test_buffers_chunk_size
, 0, NULL
, NULL
},
809 { "find_contentlen", test_buffers_find_contentlen
, 0, NULL
, NULL
},
811 { "compress/zlib", test_buffers_compress
, TT_FORK
,
812 &passthrough_setup
, (char*)"deflate" },
813 { "compress/gzip", test_buffers_compress
, TT_FORK
,
814 &passthrough_setup
, (char*)"gzip" },
815 { "compress/zstd", test_buffers_compress
, TT_FORK
,
816 &passthrough_setup
, (char*)"x-zstd" },
817 { "compress/lzma", test_buffers_compress
, TT_FORK
,
818 &passthrough_setup
, (char*)"x-tor-lzma" },
819 { "compress/none", test_buffers_compress
, TT_FORK
,
820 &passthrough_setup
, (char*)"identity" },