[tor-commits] [tor/master] Unit tests for channel_get_cell_queue_entry_size() and channel_write_*() functions

nickm at torproject.org nickm at torproject.org
Fri Nov 28 03:58:32 UTC 2014


commit 6d886787e3e112693dc8ac9cda021c93eaefee8b
Author: Andrea Shepard <andrea at torproject.org>
Date:   Fri Dec 13 06:34:46 2013 -0800

    Unit tests for channel_get_cell_queue_entry_size() and channel_write_*() functions
---
 src/test/Makefile.nmake |    2 +-
 src/test/include.am     |    1 +
 src/test/test.c         |    3 +
 src/test/test_channel.c |  295 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 300 insertions(+), 1 deletion(-)

diff --git a/src/test/Makefile.nmake b/src/test/Makefile.nmake
index 822431f..fceef99 100644
--- a/src/test/Makefile.nmake
+++ b/src/test/Makefile.nmake
@@ -11,7 +11,7 @@ LIBS = ..\..\..\build-alpha\lib\libevent.lib \
  ws2_32.lib advapi32.lib shell32.lib \
  crypt32.lib gdi32.lib user32.lib
 
-TEST_OBJECTS = test.obj test_addr.obj test_containers.obj \
+TEST_OBJECTS = test.obj test_addr.obj test_channel.obj test_containers.obj \
 	test_controller_events.ogj test_crypto.obj test_data.obj test_dir.obj \
 	test_microdesc.obj test_pt.obj test_util.obj test_config.obj \
 	test_cell_formats.obj test_replay.obj test_introduce.obj tinytest.obj \
diff --git a/src/test/include.am b/src/test/include.am
index 77c92f1..547f23b 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -20,6 +20,7 @@ src_test_test_SOURCES = \
 	src/test/test_addr.c \
 	src/test/test_buffers.c \
 	src/test/test_cell_formats.c \
+	src/test/test_channel.c \
 	src/test/test_circuitlist.c \
 	src/test/test_circuitmux.c \
 	src/test/test_containers.c \
diff --git a/src/test/test.c b/src/test/test.c
index cfbe203..4d4f6f2 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -1308,6 +1308,8 @@ extern struct testcase_t oom_tests[];
 extern struct testcase_t policy_tests[];
 extern struct testcase_t status_tests[];
 extern struct testcase_t routerset_tests[];
+extern struct testcase_t router_tests[];
+extern struct testcase_t channel_tests[];
 
 static struct testgroup_t testgroups[] = {
   { "", test_array },
@@ -1340,6 +1342,7 @@ static struct testgroup_t testgroups[] = {
   { "policy/" , policy_tests },
   { "status/" , status_tests },
   { "routerset/" , routerset_tests },
+  { "channel/", channel_tests },
   END_OF_GROUPS
 };
 
diff --git a/src/test/test_channel.c b/src/test/test_channel.c
new file mode 100644
index 0000000..c4241db
--- /dev/null
+++ b/src/test/test_channel.c
@@ -0,0 +1,295 @@
+/* Copyright (c) 2013, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define TOR_CHANNEL_INTERNAL_
+#include "or.h"
+#include "channel.h"
+/* For channel_note_destroy_not_pending */
+#include "circuitlist.h"
+/* For var_cell_free */
+#include "connection_or.h"
+/* For packed_cell stuff */
+#define RELAY_PRIVATE
+#include "relay.h"
+/* For init/free stuff */
+#include "scheduler.h"
+#include "test.h"
+
+static int test_chan_accept_cells = 0;
+static int test_cells_written = 0;
+static int test_destroy_not_pending_calls = 0;
+
+static void channel_note_destroy_not_pending_mock(channel_t *ch,
+                                                  circid_t circid);
+static void chan_test_close(channel_t *ch);
+static size_t chan_test_num_bytes_queued(channel_t *ch);
+static int chan_test_write_cell(channel_t *ch, cell_t *cell);
+static int chan_test_write_packed_cell(channel_t *ch,
+                                       packed_cell_t *packed_cell);
+static int chan_test_write_var_cell(channel_t *ch, var_cell_t *var_cell);
+static void make_fake_cell(cell_t *c);
+static void make_fake_var_cell(var_cell_t *c);
+static channel_t * new_fake_channel(void);
+static void scheduler_release_channel_mock(channel_t *ch);
+static void test_channel_write(void *arg);
+
+static void
+channel_note_destroy_not_pending_mock(channel_t *ch,
+                                      circid_t circid)
+{
+  (void)ch;
+  (void)circid;
+
+  ++test_destroy_not_pending_calls;
+}
+
+static void
+chan_test_close(channel_t *ch)
+{
+  test_assert(ch);
+
+ done:
+  return;
+}
+
+static size_t
+chan_test_num_bytes_queued(channel_t *ch)
+{
+  test_assert(ch);
+
+ done:
+  return 0;
+}
+
+static int
+chan_test_write_cell(channel_t *ch, cell_t *cell)
+{
+  int rv = 0;
+
+  test_assert(ch);
+  test_assert(cell);
+
+  if (test_chan_accept_cells) {
+    /* Free the cell and bump the counter */
+    tor_free(cell);
+    ++test_cells_written;
+    rv = 1;
+  }
+  /* else return 0, we didn't accept it */
+
+ done:
+  return rv;
+}
+
+static int
+chan_test_write_packed_cell(channel_t *ch,
+                            packed_cell_t *packed_cell)
+{
+  int rv = 0;
+
+  test_assert(ch);
+  test_assert(packed_cell);
+
+  if (test_chan_accept_cells) {
+    /* Free the cell and bump the counter */
+    packed_cell_free(packed_cell);
+    ++test_cells_written;
+    rv = 1;
+  }
+  /* else return 0, we didn't accept it */
+
+ done:
+  return rv;
+}
+
+static int
+chan_test_write_var_cell(channel_t *ch, var_cell_t *var_cell)
+{
+  int rv = 0;
+
+  test_assert(ch);
+  test_assert(var_cell);
+
+  if (test_chan_accept_cells) {
+    /* Free the cell and bump the counter */
+    var_cell_free(var_cell);
+    ++test_cells_written;
+    rv = 1;
+  }
+  /* else return 0, we didn't accept it */
+
+ done:
+  return rv;
+}
+
+static void
+make_fake_cell(cell_t *c)
+{
+  test_assert(c != NULL);
+
+  c->circ_id = 1;
+  c->command = CELL_RELAY;
+  memset(c->payload, 0, CELL_PAYLOAD_SIZE);
+
+ done:
+  return;
+}
+
+static void
+make_fake_var_cell(var_cell_t *c)
+{
+  test_assert(c != NULL);
+
+  c->circ_id = 1;
+  c->command = CELL_VERSIONS;
+  c->payload_len = CELL_PAYLOAD_SIZE / 2;
+  memset(c->payload, 0, c->payload_len);
+
+ done:
+  return;
+}
+
+static channel_t *
+new_fake_channel(void)
+{
+  channel_t *chan = tor_malloc_zero(sizeof(channel_t));
+  channel_init(chan);
+
+  chan->close = chan_test_close;
+  chan->num_bytes_queued = chan_test_num_bytes_queued;
+  chan->write_cell = chan_test_write_cell;
+  chan->write_packed_cell = chan_test_write_packed_cell;
+  chan->write_var_cell = chan_test_write_var_cell;
+  chan->state = CHANNEL_STATE_OPEN;
+
+  return chan;
+}
+
+static void
+scheduler_release_channel_mock(channel_t *ch)
+{
+  (void)ch;
+
+  /* Increment counter */
+  ++test_releases_count;
+
+  return;
+}
+
+static void
+test_channel_write(void *arg)
+{
+  channel_t *ch = NULL;
+  cell_t *cell = tor_malloc_zero(sizeof(cell_t));
+  packed_cell_t *packed_cell = NULL;
+  var_cell_t *var_cell =
+    tor_malloc_zero(sizeof(var_cell_t) + CELL_PAYLOAD_SIZE);
+  int old_count;
+
+  (void)arg;
+
+  init_cell_pool();
+
+  packed_cell = packed_cell_new();
+  test_assert(packed_cell);
+
+  ch = new_fake_channel();
+  test_assert(ch);
+  make_fake_cell(cell);
+  make_fake_var_cell(var_cell);
+
+  /* Tell it to accept cells */
+  test_chan_accept_cells = 1;
+
+  old_count = test_cells_written;
+  channel_write_cell(ch, cell);
+  test_assert(test_cells_written == old_count + 1);
+
+  channel_write_var_cell(ch, var_cell);
+  test_assert(test_cells_written == old_count + 2);
+
+  channel_write_packed_cell(ch, packed_cell);
+  test_assert(test_cells_written == old_count + 3);
+
+  /* Now we test queueing; tell it not to accept cells */
+  test_chan_accept_cells = 0;
+  /* ...and keep it from trying to flush the queue */
+  ch->state = CHANNEL_STATE_MAINT;
+
+  /* Get a fresh cell */
+  cell = tor_malloc_zero(sizeof(cell_t));
+  make_fake_cell(cell);
+
+  old_count = test_cells_written;
+  channel_write_cell(ch, cell);
+  test_assert(test_cells_written == old_count);
+
+  /*
+   * Now change back to open with channel_change_state() and assert that it
+   * gets drained from the queue.
+   */
+  test_chan_accept_cells = 1;
+  channel_change_state(ch, CHANNEL_STATE_OPEN);
+  test_assert(test_cells_written == old_count + 1);
+
+  /*
+   * Check the note destroy case
+   */
+  cell = tor_malloc_zero(sizeof(cell_t));
+  make_fake_cell(cell);
+  cell->command = CELL_DESTROY;
+
+  /* Set up the mock */
+  MOCK(channel_note_destroy_not_pending,
+       channel_note_destroy_not_pending_mock);
+
+  old_count = test_destroy_not_pending_calls;
+  channel_write_cell(ch, cell);
+  test_assert(test_destroy_not_pending_calls == old_count + 1);
+
+  /* Now send a non-destroy and check we don't call it */
+  cell = tor_malloc_zero(sizeof(cell_t));
+  make_fake_cell(cell);
+  channel_write_cell(ch, cell);
+  test_assert(test_destroy_not_pending_calls == old_count + 1);
+
+  UNMOCK(channel_note_destroy_not_pending);
+
+  /*
+   * Now switch it to CLOSING so we can test the discard-cells case
+   * in the channel_write_*() functions.
+   */
+  MOCK(scheduler_release_channel, scheduler_release_channel_mock);
+  channel_mark_for_close(ch);
+  UNMOCK(scheduler_release_channel);
+
+  /* Send cells that will drop in the closing state */
+  old_count = test_cells_written;
+
+  cell = tor_malloc_zero(sizeof(cell_t));
+  make_fake_cell(cell);
+  channel_write_cell(ch, cell);
+  test_assert(test_cells_written == old_count);
+
+  var_cell = tor_malloc_zero(sizeof(var_cell_t) + CELL_PAYLOAD_SIZE);
+  make_fake_var_cell(var_cell);
+  channel_write_var_cell(ch, var_cell);
+  test_assert(test_cells_written == old_count);
+
+  packed_cell = packed_cell_new();
+  channel_write_packed_cell(ch, packed_cell);
+  test_assert(test_cells_written == old_count);
+
+  free_cell_pool();
+
+ done:
+  tor_free(ch);
+
+  return;
+}
+
+struct testcase_t channel_tests[] = {
+  { "write", test_channel_write, TT_FORK, NULL, NULL },
+  END_OF_TESTCASES
+};
+





More information about the tor-commits mailing list