Tests for connection_write_ext_or_command.

This commit is contained in:
Nick Mathewson 2013-07-18 16:23:48 -04:00
parent c342ea9879
commit 03e3881043
5 changed files with 101 additions and 6 deletions

View File

@ -3714,9 +3714,9 @@ connection_flush(connection_t *conn)
* it all, so we don't end up with many megabytes of controller info queued at * it all, so we don't end up with many megabytes of controller info queued at
* once. * once.
*/ */
void MOCK_IMPL(void,
connection_write_to_buf_impl_(const char *string, size_t len, connection_write_to_buf_impl_,(const char *string, size_t len,
connection_t *conn, int zlib) connection_t *conn, int zlib))
{ {
/* XXXX This function really needs to return -1 on failure. */ /* XXXX This function really needs to return -1 on failure. */
int r; int r;

View File

@ -130,8 +130,8 @@ int connection_outbuf_too_full(connection_t *conn);
int connection_handle_write(connection_t *conn, int force); int connection_handle_write(connection_t *conn, int force);
int connection_flush(connection_t *conn); int connection_flush(connection_t *conn);
void connection_write_to_buf_impl_(const char *string, size_t len, MOCK_DECL(void, connection_write_to_buf_impl_,
connection_t *conn, int zlib); (const char *string, size_t len, connection_t *conn, int zlib));
/* DOCDOC connection_write_to_buf */ /* DOCDOC connection_write_to_buf */
static void connection_write_to_buf(const char *string, size_t len, static void connection_write_to_buf(const char *string, size_t len,
connection_t *conn); connection_t *conn);

View File

@ -6,6 +6,7 @@
* \brief Code implementing the Extended ORPort. * \brief Code implementing the Extended ORPort.
*/ */
#define EXT_ORPORT_PRIVATE
#include "or.h" #include "or.h"
#include "connection.h" #include "connection.h"
#include "connection_or.h" #include "connection_or.h"
@ -52,7 +53,7 @@ connection_fetch_ext_or_cmd_from_buf(connection_t *conn, ext_or_cmd_t **out)
* <b>command</b> as the command type, <b>bodylen</b> as the body * <b>command</b> as the command type, <b>bodylen</b> as the body
* length, and <b>body</b>, if it's present, as the body of the * length, and <b>body</b>, if it's present, as the body of the
* message. */ * message. */
static int STATIC int
connection_write_ext_or_command(connection_t *conn, connection_write_ext_or_command(connection_t *conn,
uint16_t command, uint16_t command,
const char *body, const char *body,

View File

@ -22,5 +22,12 @@ int connection_ext_or_process_inbuf(or_connection_t *or_conn);
int init_ext_or_cookie_authentication(int is_enabled); int init_ext_or_cookie_authentication(int is_enabled);
char *get_ext_or_auth_cookie_file_name(void); char *get_ext_or_auth_cookie_file_name(void);
#ifdef EXT_ORPORT_PRIVATE
STATIC int connection_write_ext_or_command(connection_t *conn,
uint16_t command,
const char *body,
size_t bodylen);
#endif
#endif #endif

View File

@ -2,7 +2,9 @@
/* See LICENSE for licensing information */ /* See LICENSE for licensing information */
#define CONNECTION_PRIVATE #define CONNECTION_PRIVATE
#define EXT_ORPORT_PRIVATE
#include "or.h" #include "or.h"
#include "buffers.h"
#include "connection.h" #include "connection.h"
#include "ext_orport.h" #include "ext_orport.h"
#include "test.h" #include "test.h"
@ -59,7 +61,92 @@ test_ext_or_id_map(void *arg)
connection_or_clear_ext_or_id_map(); connection_or_clear_ext_or_id_map();
} }
/* Simple connection_write_to_buf_impl_ replacement that unconditionally
* writes to outbuf. */
static void
connection_write_to_buf_impl_replacement(const char *string, size_t len,
connection_t *conn, int zlib)
{
(void) zlib;
tor_assert(string);
tor_assert(conn);
write_to_buf(string, len, conn->outbuf);
}
static char *
buf_get_contents(buf_t *buf, size_t *sz_out)
{
char *out;
*sz_out = buf_datalen(buf);
if (*sz_out >= ULONG_MAX)
return NULL; /* C'mon, really? */
out = tor_malloc(*sz_out + 1);
if (fetch_from_buf(out, (unsigned long)*sz_out, buf) != 0) {
tor_free(out);
return NULL;
}
out[*sz_out] = '\0'; /* Hopefully gratuitous. */
return out;
}
static void
test_ext_or_write_command(void *arg)
{
or_connection_t *c1;
char *cp = NULL;
char *buf = NULL;
size_t sz;
(void) arg;
MOCK(connection_write_to_buf_impl_,
connection_write_to_buf_impl_replacement);
c1 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
tt_assert(c1);
/* Length too long */
tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 100, "X", 100000),
<, 0);
/* Empty command */
tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0x99, NULL, 0),
==, 0);
cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
tt_int_op(sz, ==, 4);
test_mem_op(cp, ==, "\x00\x99\x00\x00", 4);
tor_free(cp);
/* Medium command. */
tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0x99,
"Wai\0Hello", 9), ==, 0);
cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
tt_int_op(sz, ==, 13);
test_mem_op(cp, ==, "\x00\x99\x00\x09Wai\x00Hello", 13);
tor_free(cp);
/* Long command */
buf = tor_malloc(65535);
memset(buf, 'x', 65535);
tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0xf00d,
buf, 65535), ==, 0);
cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
tt_int_op(sz, ==, 65539);
test_mem_op(cp, ==, "\xf0\x0d\xff\xff", 4);
test_mem_op(cp+4, ==, buf, 65535);
tor_free(cp);
done:
if (c1)
connection_free_(TO_CONN(c1));
tor_free(cp);
tor_free(buf);
UNMOCK(connection_write_to_buf_impl_);
}
struct testcase_t extorport_tests[] = { struct testcase_t extorport_tests[] = {
{ "id_map", test_ext_or_id_map, TT_FORK, NULL, NULL }, { "id_map", test_ext_or_id_map, TT_FORK, NULL, NULL },
{ "write_command", test_ext_or_write_command, TT_FORK, NULL, NULL },
END_OF_TESTCASES END_OF_TESTCASES
}; };