aboutsummaryrefslogtreecommitdiff
path: root/src/test/test_buffers.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/test_buffers.c')
-rw-r--r--src/test/test_buffers.c342
1 files changed, 342 insertions, 0 deletions
diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c
new file mode 100644
index 0000000000..a009faa0be
--- /dev/null
+++ b/src/test/test_buffers.c
@@ -0,0 +1,342 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2013, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define BUFFERS_PRIVATE
+#include "or.h"
+#include "buffers.h"
+#include "ext_orport.h"
+#include "test.h"
+
+/** Run unit tests for buffers.c */
+static void
+test_buffers_basic(void *arg)
+{
+ char str[256];
+ char str2[256];
+
+ buf_t *buf = NULL, *buf2 = NULL;
+ const char *cp;
+
+ int j;
+ size_t r;
+ (void) arg;
+
+ /****
+ * buf_new
+ ****/
+ if (!(buf = buf_new()))
+ test_fail();
+
+ //test_eq(buf_capacity(buf), 4096);
+ test_eq(buf_datalen(buf), 0);
+
+ /****
+ * General pointer frobbing
+ */
+ for (j=0;j<256;++j) {
+ str[j] = (char)j;
+ }
+ write_to_buf(str, 256, buf);
+ write_to_buf(str, 256, buf);
+ test_eq(buf_datalen(buf), 512);
+ fetch_from_buf(str2, 200, buf);
+ test_memeq(str, str2, 200);
+ test_eq(buf_datalen(buf), 312);
+ memset(str2, 0, sizeof(str2));
+
+ fetch_from_buf(str2, 256, buf);
+ test_memeq(str+200, str2, 56);
+ test_memeq(str, str2+56, 200);
+ test_eq(buf_datalen(buf), 56);
+ memset(str2, 0, sizeof(str2));
+ /* Okay, now we should be 512 bytes into the 4096-byte buffer. If we add
+ * another 3584 bytes, we hit the end. */
+ for (j=0;j<15;++j) {
+ write_to_buf(str, 256, buf);
+ }
+ assert_buf_ok(buf);
+ test_eq(buf_datalen(buf), 3896);
+ fetch_from_buf(str2, 56, buf);
+ test_eq(buf_datalen(buf), 3840);
+ test_memeq(str+200, str2, 56);
+ for (j=0;j<15;++j) {
+ memset(str2, 0, sizeof(str2));
+ fetch_from_buf(str2, 256, buf);
+ test_memeq(str, str2, 256);
+ }
+ test_eq(buf_datalen(buf), 0);
+ buf_free(buf);
+ buf = NULL;
+
+ /* Okay, now make sure growing can work. */
+ buf = buf_new_with_capacity(16);
+ //test_eq(buf_capacity(buf), 16);
+ write_to_buf(str+1, 255, buf);
+ //test_eq(buf_capacity(buf), 256);
+ fetch_from_buf(str2, 254, buf);
+ test_memeq(str+1, str2, 254);
+ //test_eq(buf_capacity(buf), 256);
+ assert_buf_ok(buf);
+ write_to_buf(str, 32, buf);
+ //test_eq(buf_capacity(buf), 256);
+ assert_buf_ok(buf);
+ write_to_buf(str, 256, buf);
+ assert_buf_ok(buf);
+ //test_eq(buf_capacity(buf), 512);
+ test_eq(buf_datalen(buf), 33+256);
+ fetch_from_buf(str2, 33, buf);
+ test_eq(*str2, str[255]);
+
+ test_memeq(str2+1, str, 32);
+ //test_eq(buf_capacity(buf), 512);
+ test_eq(buf_datalen(buf), 256);
+ fetch_from_buf(str2, 256, buf);
+ test_memeq(str, str2, 256);
+
+ /* now try shrinking: case 1. */
+ buf_free(buf);
+ buf = buf_new_with_capacity(33668);
+ for (j=0;j<67;++j) {
+ write_to_buf(str,255, buf);
+ }
+ //test_eq(buf_capacity(buf), 33668);
+ test_eq(buf_datalen(buf), 17085);
+ for (j=0; j < 40; ++j) {
+ fetch_from_buf(str2, 255,buf);
+ test_memeq(str2, str, 255);
+ }
+
+ /* now try shrinking: case 2. */
+ buf_free(buf);
+ buf = buf_new_with_capacity(33668);
+ for (j=0;j<67;++j) {
+ write_to_buf(str,255, buf);
+ }
+ for (j=0; j < 20; ++j) {
+ fetch_from_buf(str2, 255,buf);
+ test_memeq(str2, str, 255);
+ }
+ for (j=0;j<80;++j) {
+ write_to_buf(str,255, buf);
+ }
+ //test_eq(buf_capacity(buf),33668);
+ for (j=0; j < 120; ++j) {
+ fetch_from_buf(str2, 255,buf);
+ test_memeq(str2, str, 255);
+ }
+
+ /* Move from buf to buf. */
+ buf_free(buf);
+ buf = buf_new_with_capacity(4096);
+ buf2 = buf_new_with_capacity(4096);
+ for (j=0;j<100;++j)
+ write_to_buf(str, 255, buf);
+ test_eq(buf_datalen(buf), 25500);
+ for (j=0;j<100;++j) {
+ r = 10;
+ move_buf_to_buf(buf2, buf, &r);
+ test_eq(r, 0);
+ }
+ test_eq(buf_datalen(buf), 24500);
+ test_eq(buf_datalen(buf2), 1000);
+ for (j=0;j<3;++j) {
+ fetch_from_buf(str2, 255, buf2);
+ test_memeq(str2, str, 255);
+ }
+ r = 8192; /*big move*/
+ move_buf_to_buf(buf2, buf, &r);
+ test_eq(r, 0);
+ r = 30000; /* incomplete move */
+ move_buf_to_buf(buf2, buf, &r);
+ test_eq(r, 13692);
+ for (j=0;j<97;++j) {
+ fetch_from_buf(str2, 255, buf2);
+ test_memeq(str2, str, 255);
+ }
+ buf_free(buf);
+ buf_free(buf2);
+ buf = buf2 = NULL;
+
+ buf = buf_new_with_capacity(5);
+ cp = "Testing. This is a moderately long Testing string.";
+ for (j = 0; cp[j]; j++)
+ write_to_buf(cp+j, 1, buf);
+ test_eq(0, buf_find_string_offset(buf, "Testing", 7));
+ test_eq(1, buf_find_string_offset(buf, "esting", 6));
+ test_eq(1, buf_find_string_offset(buf, "est", 3));
+ test_eq(39, buf_find_string_offset(buf, "ing str", 7));
+ test_eq(35, buf_find_string_offset(buf, "Testing str", 11));
+ test_eq(32, buf_find_string_offset(buf, "ng ", 3));
+ test_eq(43, buf_find_string_offset(buf, "string.", 7));
+ test_eq(-1, buf_find_string_offset(buf, "shrdlu", 6));
+ test_eq(-1, buf_find_string_offset(buf, "Testing thing", 13));
+ test_eq(-1, buf_find_string_offset(buf, "ngx", 3));
+ buf_free(buf);
+ buf = NULL;
+
+ /* Try adding a string too long for any freelist. */
+ {
+ char *cp = tor_malloc_zero(65536);
+ buf = buf_new();
+ write_to_buf(cp, 65536, buf);
+ tor_free(cp);
+
+ tt_int_op(buf_datalen(buf), ==, 65536);
+ buf_free(buf);
+ buf = NULL;
+ }
+
+ done:
+ if (buf)
+ buf_free(buf);
+ if (buf2)
+ buf_free(buf2);
+}
+static void
+test_buffer_copy(void *arg)
+{
+ generic_buffer_t *buf=NULL, *buf2=NULL;
+ const char *s;
+ size_t len;
+ char b[256];
+ int i;
+ (void)arg;
+
+ buf = generic_buffer_new();
+ tt_assert(buf);
+
+ /* Copy an empty buffer. */
+ tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
+ tt_assert(buf2);
+ tt_int_op(0, ==, generic_buffer_len(buf2));
+
+ /* Now try with a short buffer. */
+ s = "And now comes an act of enormous enormance!";
+ len = strlen(s);
+ generic_buffer_add(buf, s, len);
+ tt_int_op(len, ==, generic_buffer_len(buf));
+ /* Add junk to buf2 so we can test replacing.*/
+ generic_buffer_add(buf2, "BLARG", 5);
+ tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
+ tt_int_op(len, ==, generic_buffer_len(buf2));
+ generic_buffer_get(buf2, b, len);
+ test_mem_op(b, ==, s, len);
+ /* Now free buf2 and retry so we can test allocating */
+ generic_buffer_free(buf2);
+ buf2 = NULL;
+ tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
+ tt_int_op(len, ==, generic_buffer_len(buf2));
+ generic_buffer_get(buf2, b, len);
+ test_mem_op(b, ==, s, len);
+ /* Clear buf for next test */
+ generic_buffer_get(buf, b, len);
+ tt_int_op(generic_buffer_len(buf),==,0);
+
+ /* Okay, now let's try a bigger buffer. */
+ s = "Quis autem vel eum iure reprehenderit qui in ea voluptate velit "
+ "esse quam nihil molestiae consequatur, vel illum qui dolorem eum "
+ "fugiat quo voluptas nulla pariatur?";
+ len = strlen(s);
+ for (i = 0; i < 256; ++i) {
+ b[0]=i;
+ generic_buffer_add(buf, b, 1);
+ generic_buffer_add(buf, s, len);
+ }
+ tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
+ tt_int_op(generic_buffer_len(buf2), ==, generic_buffer_len(buf));
+ for (i = 0; i < 256; ++i) {
+ generic_buffer_get(buf2, b, len+1);
+ tt_int_op((unsigned char)b[0],==,i);
+ test_mem_op(b+1, ==, s, len);
+ }
+
+ done:
+ if (buf)
+ generic_buffer_free(buf);
+ if (buf2)
+ generic_buffer_free(buf2);
+}
+
+static void
+test_buffer_ext_or_cmd(void *arg)
+{
+ ext_or_cmd_t *cmd = NULL;
+ generic_buffer_t *buf = generic_buffer_new();
+ char *tmp = NULL;
+ (void) arg;
+
+ /* Empty -- should give "not there. */
+ tt_int_op(0, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
+ tt_ptr_op(NULL, ==, cmd);
+
+ /* Three bytes: shouldn't work. */
+ generic_buffer_add(buf, "\x00\x20\x00", 3);
+ tt_int_op(0, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
+ tt_ptr_op(NULL, ==, cmd);
+ tt_int_op(3, ==, generic_buffer_len(buf));
+
+ /* 0020 0000: That's a nil command. It should work. */
+ generic_buffer_add(buf, "\x00", 1);
+ tt_int_op(1, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
+ tt_ptr_op(NULL, !=, cmd);
+ tt_int_op(0x20, ==, cmd->cmd);
+ tt_int_op(0, ==, cmd->len);
+ tt_int_op(0, ==, generic_buffer_len(buf));
+ ext_or_cmd_free(cmd);
+ cmd = NULL;
+
+ /* Now try a length-6 command with one byte missing. */
+ generic_buffer_add(buf, "\x10\x21\x00\x06""abcde", 9);
+ tt_int_op(0, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
+ tt_ptr_op(NULL, ==, cmd);
+ generic_buffer_add(buf, "f", 1);
+ tt_int_op(1, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
+ tt_ptr_op(NULL, !=, cmd);
+ tt_int_op(0x1021, ==, cmd->cmd);
+ tt_int_op(6, ==, cmd->len);
+ test_mem_op("abcdef", ==, cmd->body, 6);
+ tt_int_op(0, ==, generic_buffer_len(buf));
+ ext_or_cmd_free(cmd);
+ cmd = NULL;
+
+ /* Now try a length-10 command with 4 extra bytes. */
+ generic_buffer_add(buf, "\xff\xff\x00\x0a"
+ "loremipsum\x10\x00\xff\xff", 18);
+ tt_int_op(1, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
+ tt_ptr_op(NULL, !=, cmd);
+ tt_int_op(0xffff, ==, cmd->cmd);
+ tt_int_op(10, ==, cmd->len);
+ test_mem_op("loremipsum", ==, cmd->body, 10);
+ tt_int_op(4, ==, generic_buffer_len(buf));
+ ext_or_cmd_free(cmd);
+ cmd = NULL;
+
+ /* Finally, let's try a maximum-length command. We already have the header
+ * waiting. */
+ tt_int_op(0, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
+ tmp = tor_malloc_zero(65535);
+ generic_buffer_add(buf, tmp, 65535);
+ tt_int_op(1, ==, generic_buffer_fetch_ext_or_cmd(buf, &cmd));
+ tt_ptr_op(NULL, !=, cmd);
+ tt_int_op(0x1000, ==, cmd->cmd);
+ tt_int_op(0xffff, ==, cmd->len);
+ test_mem_op(tmp, ==, cmd->body, 65535);
+ tt_int_op(0, ==, generic_buffer_len(buf));
+ ext_or_cmd_free(cmd);
+ cmd = NULL;
+
+ done:
+ ext_or_cmd_free(cmd);
+ generic_buffer_free(buf);
+ tor_free(tmp);
+}
+
+struct testcase_t buffer_tests[] = {
+ { "basic", test_buffers_basic, 0, NULL, NULL },
+ { "copy", test_buffer_copy, 0, NULL, NULL },
+ { "ext_or_cmd", test_buffer_ext_or_cmd, 0, NULL, NULL },
+ END_OF_TESTCASES
+};
+