aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/Makefile.am49
-rw-r--r--src/test/bench.c4
-rw-r--r--src/test/include.am52
-rw-r--r--src/test/test.c10
-rw-r--r--src/test/test.h8
-rw-r--r--src/test/test_addr.c6
-rw-r--r--src/test/test_config.c1
-rw-r--r--src/test/test_containers.c70
-rw-r--r--src/test/test_crypto.c5
-rw-r--r--src/test/test_dir.c137
-rw-r--r--src/test/test_introduce.c528
-rw-r--r--src/test/test_replay.c184
-rw-r--r--src/test/test_util.c270
-rw-r--r--src/test/tinytest.c387
-rw-r--r--src/test/tinytest.h87
-rw-r--r--src/test/tinytest_demo.c215
-rw-r--r--src/test/tinytest_macros.h184
17 files changed, 1152 insertions, 1045 deletions
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
deleted file mode 100644
index 31a464ee7..000000000
--- a/src/test/Makefile.am
+++ /dev/null
@@ -1,49 +0,0 @@
-TESTS = test
-
-noinst_PROGRAMS = test test-child bench
-
-AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
- -DLOCALSTATEDIR="\"$(localstatedir)\"" \
- -DBINDIR="\"$(bindir)\"" \
- -I"$(top_srcdir)/src/or"
-
-# -L flags need to go in LDFLAGS. -l flags need to go in LDADD.
-# This seems to matter nowhere but on Windows, but I assure you that it
-# matters a lot there, and is quite hard to debug if you forget to do it.
-
-test_SOURCES = \
- test.c \
- test_addr.c \
- test_containers.c \
- test_crypto.c \
- test_data.c \
- test_dir.c \
- test_microdesc.c \
- test_pt.c \
- test_util.c \
- test_config.c \
- tinytest.c
-
-bench_SOURCES = \
- bench.c
-
-test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
- @TOR_LDFLAGS_libevent@
-test_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \
- ../common/libor-event.a \
- @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
- @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
-
-bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
- @TOR_LDFLAGS_libevent@
-bench_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \
- ../common/libor-event.a \
- @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
- @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
-
-noinst_HEADERS = \
- tinytest.h \
- tinytest_macros.h \
- test.h
-
-
diff --git a/src/test/bench.c b/src/test/bench.c
index 3eae532d3..2e65d0b2d 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -214,8 +214,8 @@ bench_cell_ops(void)
crypto_rand((char*)cell->payload, sizeof(cell->payload));
/* Mock-up or_circuit_t */
- or_circ->_base.magic = OR_CIRCUIT_MAGIC;
- or_circ->_base.purpose = CIRCUIT_PURPOSE_OR;
+ or_circ->base_.magic = OR_CIRCUIT_MAGIC;
+ or_circ->base_.purpose = CIRCUIT_PURPOSE_OR;
/* Initialize crypto */
or_circ->p_crypto = crypto_cipher_new(NULL);
diff --git a/src/test/include.am b/src/test/include.am
new file mode 100644
index 000000000..bdfe498d6
--- /dev/null
+++ b/src/test/include.am
@@ -0,0 +1,52 @@
+TESTS+= src/test/test
+
+noinst_PROGRAMS+= src/test/test src/test/test-child src/test/bench
+
+src_test_AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
+ -DLOCALSTATEDIR="\"$(localstatedir)\"" \
+ -DBINDIR="\"$(bindir)\"" \
+ -I"$(top_srcdir)/src/or" -I"$(top_srcdir)/src/ext"
+
+# -L flags need to go in LDFLAGS. -l flags need to go in LDADD.
+# This seems to matter nowhere but on Windows, but I assure you that it
+# matters a lot there, and is quite hard to debug if you forget to do it.
+
+src_test_test_SOURCES = \
+ src/test/test.c \
+ src/test/test_addr.c \
+ src/test/test_containers.c \
+ src/test/test_crypto.c \
+ src/test/test_data.c \
+ src/test/test_dir.c \
+ src/test/test_introduce.c \
+ src/test/test_microdesc.c \
+ src/test/test_pt.c \
+ src/test/test_replay.c \
+ src/test/test_util.c \
+ src/test/test_config.c \
+ src/ext/tinytest.c
+
+src_test_test_CPPFLAGS= $(src_test_AM_CPPFLAGS)
+
+src_test_bench_SOURCES = \
+ src/test/bench.c
+
+src_test_bench_CPPFLAGS= $(src_test_AM_CPPFLAGS)
+
+src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
+ @TOR_LDFLAGS_libevent@
+src_test_test_LDADD = src/or/libtor.a src/common/libor.a src/common/libor-crypto.a \
+ src/common/libor-event.a \
+ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
+ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+
+src_test_bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
+ @TOR_LDFLAGS_libevent@
+src_test_bench_LDADD = src/or/libtor.a src/common/libor.a src/common/libor-crypto.a \
+ src/common/libor-event.a \
+ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
+ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+
+noinst_HEADERS+= \
+ src/test/test.h
+
diff --git a/src/test/test.c b/src/test/test.c
index ddfd6337b..210b9a4f8 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -32,7 +32,7 @@ const char tor_git_revision[] = "";
#define CONFIG_PRIVATE
#define GEOIP_PRIVATE
#define ROUTER_PRIVATE
-#define CIRCUIT_PRIVATE
+#define CIRCUITSTATS_PRIVATE
/*
* Linux doesn't provide lround in math.h by default, but mac os does...
@@ -44,7 +44,7 @@ double fabs(double x);
#include "or.h"
#include "buffers.h"
-#include "circuitbuild.h"
+#include "circuitstats.h"
#include "config.h"
#include "connection_edge.h"
#include "geoip.h"
@@ -1929,6 +1929,8 @@ extern struct testcase_t dir_tests[];
extern struct testcase_t microdesc_tests[];
extern struct testcase_t pt_tests[];
extern struct testcase_t config_tests[];
+extern struct testcase_t introduce_tests[];
+extern struct testcase_t replaycache_tests[];
static struct testgroup_t testgroups[] = {
{ "", test_array },
@@ -1941,6 +1943,8 @@ static struct testgroup_t testgroups[] = {
{ "dir/md/", microdesc_tests },
{ "pt/", pt_tests },
{ "config/", config_tests },
+ { "replaycache/", replaycache_tests },
+ { "introduce/", introduce_tests },
END_OF_GROUPS
};
@@ -1956,7 +1960,7 @@ main(int c, const char **v)
#ifdef USE_DMALLOC
{
- int r = CRYPTO_set_mem_ex_functions(_tor_malloc, _tor_realloc, _tor_free);
+ int r = CRYPTO_set_mem_ex_functions(tor_malloc_, tor_realloc_, tor_free_);
tor_assert(r);
}
#endif
diff --git a/src/test/test.h b/src/test/test.h
index 0b6e6c60c..08fad6b31 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -3,8 +3,8 @@
* Copyright (c) 2007-2012, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#ifndef _TOR_TEST_H
-#define _TOR_TEST_H
+#ifndef TOR_TEST_H
+#define TOR_TEST_H
/**
* \file test.h
@@ -65,6 +65,10 @@
#define test_memeq_hex(expr1, hex) test_mem_op_hex(expr1, ==, hex)
+#define tt_double_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,double,(val1_ op val2_),"%f", \
+ TT_EXIT_TEST_FUNCTION)
+
const char *get_fname(const char *name);
crypto_pk_t *pk_generate(int idx);
diff --git a/src/test/test_addr.c b/src/test/test_addr.c
index 9007a23c5..0dcc0174a 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -70,7 +70,7 @@ test_addr_basic(void)
;
}
-#define _test_op_ip6(a,op,b,e1,e2) \
+#define test_op_ip6_(a,op,b,e1,e2) \
STMT_BEGIN \
tt_assert_test_fmt_type(a,b,e1" "#op" "e2,struct in6_addr*, \
(memcmp(val1_->s6_addr, val2_->s6_addr, 16) op 0), \
@@ -93,7 +93,7 @@ test_addr_basic(void)
#define test_pton6_same(a,b) STMT_BEGIN \
test_eq(tor_inet_pton(AF_INET6, a, &a1), 1); \
test_eq(tor_inet_pton(AF_INET6, b, &a2), 1); \
- _test_op_ip6(&a1,==,&a2,#a,#b); \
+ test_op_ip6_(&a1,==,&a2,#a,#b); \
STMT_END
/** Helper: Assert that <b>a</b> is recognized as a bad IPv6 address by
@@ -108,7 +108,7 @@ test_addr_basic(void)
test_eq(tor_inet_pton(AF_INET6, a, &a1), 1); \
test_streq(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)), b); \
test_eq(tor_inet_pton(AF_INET6, b, &a2), 1); \
- _test_op_ip6(&a1, ==, &a2, a, b); \
+ test_op_ip6_(&a1, ==, &a2, a, b); \
STMT_END
/** Helper: assert that <b>a</b> parses by tor_inet_pton() into a address that
diff --git a/src/test/test_config.c b/src/test/test_config.c
index ff251a24d..d9fcd8b35 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -6,6 +6,7 @@
#include "orconfig.h"
#include "or.h"
#include "config.h"
+#include "confparse.h"
#include "connection_edge.h"
#include "test.h"
diff --git a/src/test/test_containers.c b/src/test/test_containers.c
index 45898df4e..10146c5f6 100644
--- a/src/test/test_containers.c
+++ b/src/test/test_containers.c
@@ -10,25 +10,16 @@
/** Helper: return a tristate based on comparing the strings in *<b>a</b> and
* *<b>b</b>. */
static int
-_compare_strs(const void **a, const void **b)
+compare_strs_(const void **a, const void **b)
{
const char *s1 = *a, *s2 = *b;
return strcmp(s1, s2);
}
-/** Helper: return a tristate based on comparing the strings in <b>a</b> and
- * *<b>b</b>. */
-static int
-compare_strs_for_bsearch_(const void *a, const void **b)
-{
- const char *s1 = a, *s2 = *b;
- return strcmp(s1, s2);
-}
-
/** Helper: return a tristate based on comparing the strings in *<b>a</b> and
* *<b>b</b>, excluding a's first character, and ignoring case. */
static int
-_compare_without_first_ch(const void *a, const void **b)
+compare_without_first_ch_(const void *a, const void **b)
{
const char *s1 = a, *s2 = *b;
return strcasecmp(s1+1, s2);
@@ -185,7 +176,7 @@ test_container_smartlist_strings(void)
/* Test swapping, shuffling, and sorting. */
smartlist_split_string(sl, "the,onion,router,by,arma,and,nickm", ",", 0, 0);
test_eq(7, smartlist_len(sl));
- smartlist_sort(sl, _compare_strs);
+ smartlist_sort(sl, compare_strs_);
cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
test_streq(cp_alloc,"and,arma,by,nickm,onion,router,the");
tor_free(cp_alloc);
@@ -204,54 +195,27 @@ test_container_smartlist_strings(void)
test_assert(smartlist_string_isin(sl, "the"));
/* Test bsearch. */
- smartlist_sort(sl, _compare_strs);
+ smartlist_sort(sl, compare_strs_);
test_streq("nickm", smartlist_bsearch(sl, "zNicKM",
- _compare_without_first_ch));
- test_streq("and", smartlist_bsearch(sl, " AND", _compare_without_first_ch));
- test_eq_ptr(NULL, smartlist_bsearch(sl, " ANz", _compare_without_first_ch));
+ compare_without_first_ch_));
+ test_streq("and", smartlist_bsearch(sl, " AND", compare_without_first_ch_));
+ test_eq_ptr(NULL, smartlist_bsearch(sl, " ANz", compare_without_first_ch_));
/* Test bsearch_idx */
{
int f;
- smartlist_t *tmp = NULL;
-
- test_eq(0, smartlist_bsearch_idx(sl," aaa",_compare_without_first_ch,&f));
+ test_eq(0, smartlist_bsearch_idx(sl," aaa",compare_without_first_ch_,&f));
test_eq(f, 0);
- test_eq(0, smartlist_bsearch_idx(sl," and",_compare_without_first_ch,&f));
+ test_eq(0, smartlist_bsearch_idx(sl," and",compare_without_first_ch_,&f));
test_eq(f, 1);
- test_eq(1, smartlist_bsearch_idx(sl," arm",_compare_without_first_ch,&f));
+ test_eq(1, smartlist_bsearch_idx(sl," arm",compare_without_first_ch_,&f));
test_eq(f, 0);
- test_eq(1, smartlist_bsearch_idx(sl," arma",_compare_without_first_ch,&f));
+ test_eq(1, smartlist_bsearch_idx(sl," arma",compare_without_first_ch_,&f));
test_eq(f, 1);
- test_eq(2, smartlist_bsearch_idx(sl," armb",_compare_without_first_ch,&f));
+ test_eq(2, smartlist_bsearch_idx(sl," armb",compare_without_first_ch_,&f));
test_eq(f, 0);
- test_eq(7, smartlist_bsearch_idx(sl," zzzz",_compare_without_first_ch,&f));
- test_eq(f, 0);
-
- /* Test trivial cases for list of length 0 or 1 */
- tmp = smartlist_new();
- test_eq(0, smartlist_bsearch_idx(tmp, "foo",
- compare_strs_for_bsearch_, &f));
- test_eq(f, 0);
- smartlist_insert(tmp, 0, (void *)("bar"));
- test_eq(1, smartlist_bsearch_idx(tmp, "foo",
- compare_strs_for_bsearch_, &f));
- test_eq(f, 0);
- test_eq(0, smartlist_bsearch_idx(tmp, "aaa",
- compare_strs_for_bsearch_, &f));
- test_eq(f, 0);
- test_eq(0, smartlist_bsearch_idx(tmp, "bar",
- compare_strs_for_bsearch_, &f));
- test_eq(f, 1);
- /* ... and one for length 2 */
- smartlist_insert(tmp, 1, (void *)("foo"));
- test_eq(1, smartlist_bsearch_idx(tmp, "foo",
- compare_strs_for_bsearch_, &f));
- test_eq(f, 1);
- test_eq(2, smartlist_bsearch_idx(tmp, "goo",
- compare_strs_for_bsearch_, &f));
+ test_eq(7, smartlist_bsearch_idx(sl," zzzz",compare_without_first_ch_,&f));
test_eq(f, 0);
- smartlist_free(tmp);
}
/* Test reverse() and pop_last() */
@@ -272,8 +236,8 @@ test_container_smartlist_strings(void)
smartlist_split_string(sl,
"50,noon,radar,a,man,a,plan,a,canal,panama,radar,noon,50",
",", 0, 0);
- smartlist_sort(sl, _compare_strs);
- smartlist_uniq(sl, _compare_strs, _tor_free);
+ smartlist_sort(sl, compare_strs_);
+ smartlist_uniq(sl, compare_strs_, tor_free_);
cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
test_streq(cp_alloc, "50,a,canal,man,noon,panama,plan,radar");
tor_free(cp_alloc);
@@ -558,7 +522,7 @@ typedef struct pq_entry_t {
/** Helper: return a tristate based on comparing two pq_entry_t values. */
static int
-_compare_strings_for_pqueue(const void *p1, const void *p2)
+compare_strings_for_pqueue_(const void *p1, const void *p2)
{
const pq_entry_t *e1=p1, *e2=p2;
return strcmp(e1->val, e2->val);
@@ -588,7 +552,7 @@ test_container_pqueue(void)
#define OK() smartlist_pqueue_assert_ok(sl, cmp, offset)
- cmp = _compare_strings_for_pqueue;
+ cmp = compare_strings_for_pqueue_;
smartlist_pqueue_add(sl, cmp, offset, &cows);
smartlist_pqueue_add(sl, cmp, offset, &zebras);
smartlist_pqueue_add(sl, cmp, offset, &fish);
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index 7f4347a41..fd983de00 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -427,6 +427,11 @@ test_crypto_pk(void)
test_assert(! crypto_pk_read_public_key_from_string(pk2, encoded, size));
test_eq(0, crypto_pk_cmp_keys(pk1, pk2));
+ /* comparison between keys and NULL */
+ tt_int_op(crypto_pk_cmp_keys(NULL, pk1), <, 0);
+ tt_int_op(crypto_pk_cmp_keys(NULL, NULL), ==, 0);
+ tt_int_op(crypto_pk_cmp_keys(pk1, NULL), >, 0);
+
test_eq(128, crypto_pk_keysize(pk1));
test_eq(1024, crypto_pk_num_bits(pk1));
test_eq(128, crypto_pk_keysize(pk2));
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 83c612045..9bf44b116 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -4,9 +4,12 @@
/* See LICENSE for licensing information */
#include "orconfig.h"
+#include <math.h>
+
#define DIRSERV_PRIVATE
#define DIRVOTE_PRIVATE
#define ROUTER_PRIVATE
+#define ROUTERLIST_PRIVATE
#define HIBERNATE_PRIVATE
#include "or.h"
#include "directory.h"
@@ -147,9 +150,9 @@ test_dir_formats(void)
"platform Tor "VERSION" on ", sizeof(buf2));
strlcat(buf2, get_uname(), sizeof(buf2));
strlcat(buf2, "\n"
- "opt protocols Link 1 2 Circuit 1\n"
+ "protocols Link 1 2 Circuit 1\n"
"published 1970-01-01 00:00:00\n"
- "opt fingerprint ", sizeof(buf2));
+ "fingerprint ", sizeof(buf2));
test_assert(!crypto_pk_get_fingerprint(pk2, fingerprint, 1));
strlcat(buf2, fingerprint, sizeof(buf2));
strlcat(buf2, "\nuptime 0\n"
@@ -161,7 +164,7 @@ test_dir_formats(void)
strlcat(buf2, pk1_str, sizeof(buf2));
strlcat(buf2, "signing-key\n", sizeof(buf2));
strlcat(buf2, pk2_str, sizeof(buf2));
- strlcat(buf2, "opt hidden-service-dir\n", sizeof(buf2));
+ strlcat(buf2, "hidden-service-dir\n", sizeof(buf2));
strlcat(buf2, "reject *:*\nrouter-signature\n", sizeof(buf2));
buf[strlen(buf2)] = '\0'; /* Don't compare the sig; it's never the same
* twice */
@@ -797,6 +800,7 @@ test_dir_v3_networkstatus(void)
networkstatus_t *vote=NULL, *v1=NULL, *v2=NULL, *v3=NULL, *con=NULL,
*con_md=NULL;
vote_routerstatus_t *vrs;
+ tor_addr_t addr_ipv6;
routerstatus_t *rs;
char *v1_text=NULL, *v2_text=NULL, *v3_text=NULL, *consensus_text=NULL, *cp;
smartlist_t *votes = smartlist_new();
@@ -893,6 +897,9 @@ test_dir_v3_networkstatus(void)
rs->addr = 0x99009901;
rs->or_port = 443;
rs->dir_port = 0;
+ tor_addr_parse(&addr_ipv6, "[1:2:3::4]");
+ tor_addr_copy(&rs->ipv6_addr, &addr_ipv6);
+ rs->ipv6_orport = 4711;
rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running =
rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1;
smartlist_add(vote->routerstatus_list, vrs);
@@ -987,6 +994,8 @@ test_dir_v3_networkstatus(void)
test_eq(rs->addr, 0x99009901);
test_eq(rs->or_port, 443);
test_eq(rs->dir_port, 0);
+ test_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6));
+ test_eq(rs->ipv6_orport, 4711);
test_eq(vrs->flags, U64_LITERAL(254)); // all flags except "authority."
{
@@ -1169,6 +1178,8 @@ test_dir_v3_networkstatus(void)
test_eq(rs->addr, 0x99009901);
test_eq(rs->or_port, 443);
test_eq(rs->dir_port, 0);
+ test_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6));
+ test_eq(rs->ipv6_orport, 4711);
test_assert(!rs->is_authority);
test_assert(rs->is_exit);
test_assert(rs->is_fast);
@@ -1381,6 +1392,124 @@ test_dir_v3_networkstatus(void)
ns_detached_signatures_free(dsig2);
}
+static void
+test_dir_scale_bw(void *testdata)
+{
+ double v[8] = { 2.0/3,
+ 7.0,
+ 1.0,
+ 3.0,
+ 1.0/5,
+ 1.0/7,
+ 12.0,
+ 24.0 };
+ u64_dbl_t vals[8];
+ uint64_t total;
+ int i;
+
+ (void) testdata;
+
+ for (i=0; i<8; ++i)
+ vals[i].dbl = v[i];
+
+ scale_array_elements_to_u64(vals, 8, &total);
+
+ tt_int_op((int)total, ==, 48);
+ total = 0;
+ for (i=0; i<8; ++i) {
+ total += vals[i].u64;
+ }
+ tt_assert(total >= (U64_LITERAL(1)<<60));
+ tt_assert(total <= (U64_LITERAL(1)<<62));
+
+ for (i=0; i<8; ++i) {
+ double ratio = ((double)vals[i].u64) / vals[2].u64;
+ tt_double_op(fabs(ratio - v[i]), <, .00001);
+ }
+
+ done:
+ ;
+}
+
+static void
+test_dir_random_weighted(void *testdata)
+{
+ int histogram[10];
+ uint64_t vals[10] = {3,1,2,4,6,0,7,5,8,9}, total=0;
+ u64_dbl_t inp[10];
+ int i, choice;
+ const int n = 50000;
+ double max_sq_error;
+ (void) testdata;
+
+ /* Try a ten-element array with values from 0 through 10. The values are
+ * in a scrambled order to make sure we don't depend on order. */
+ memset(histogram,0,sizeof(histogram));
+ for (i=0; i<10; ++i) {
+ inp[i].u64 = vals[i];
+ total += vals[i];
+ }
+ tt_int_op(total, ==, 45);
+ for (i=0; i<n; ++i) {
+ choice = choose_array_element_by_weight(inp, 10);
+ tt_int_op(choice, >=, 0);
+ tt_int_op(choice, <, 10);
+ histogram[choice]++;
+ }
+
+ /* Now see if we chose things about frequently enough. */
+ max_sq_error = 0;
+ for (i=0; i<10; ++i) {
+ int expected = (int)(n*vals[i]/total);
+ double frac_diff = 0, sq;
+ TT_BLATHER((" %d : %5d vs %5d\n", (int)vals[i], histogram[i], expected));
+ if (expected)
+ frac_diff = (histogram[i] - expected) / ((double)expected);
+ else
+ tt_int_op(histogram[i], ==, 0);
+
+ sq = frac_diff * frac_diff;
+ if (sq > max_sq_error)
+ max_sq_error = sq;
+ }
+ /* It should almost always be much much less than this. If you want to
+ * figure out the odds, please feel free. */
+ tt_double_op(max_sq_error, <, .05);
+
+ /* Now try a singleton; do we choose it? */
+ for (i = 0; i < 100; ++i) {
+ choice = choose_array_element_by_weight(inp, 1);
+ tt_int_op(choice, ==, 0);
+ }
+
+ /* Now try an array of zeros. We should choose randomly. */
+ memset(histogram,0,sizeof(histogram));
+ for (i = 0; i < 5; ++i)
+ inp[i].u64 = 0;
+ for (i = 0; i < n; ++i) {
+ choice = choose_array_element_by_weight(inp, 5);
+ tt_int_op(choice, >=, 0);
+ tt_int_op(choice, <, 5);
+ histogram[choice]++;
+ }
+ /* Now see if we chose things about frequently enough. */
+ max_sq_error = 0;
+ for (i=0; i<5; ++i) {
+ int expected = n/5;
+ double frac_diff = 0, sq;
+ TT_BLATHER((" %d : %5d vs %5d\n", (int)vals[i], histogram[i], expected));
+ frac_diff = (histogram[i] - expected) / ((double)expected);
+ sq = frac_diff * frac_diff;
+ if (sq > max_sq_error)
+ max_sq_error = sq;
+ }
+ /* It should almost always be much much less than this. If you want to
+ * figure out the odds, please feel free. */
+ tt_double_op(max_sq_error, <, .05);
+ done:
+ ;
+}
+
#define DIR_LEGACY(name) \
{ #name, legacy_test_helper, TT_FORK, &legacy_setup, test_dir_ ## name }
@@ -1396,6 +1525,8 @@ struct testcase_t dir_tests[] = {
DIR_LEGACY(measured_bw),
DIR_LEGACY(param_voting),
DIR_LEGACY(v3_networkstatus),
+ DIR(random_weighted),
+ DIR(scale_bw),
END_OF_TESTCASES
};
diff --git a/src/test/test_introduce.c b/src/test/test_introduce.c
new file mode 100644
index 000000000..992d9cd50
--- /dev/null
+++ b/src/test/test_introduce.c
@@ -0,0 +1,528 @@
+/* Copyright (c) 2012, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "crypto.h"
+#include "or.h"
+#include "test.h"
+
+#define RENDSERVICE_PRIVATE
+#include "rendservice.h"
+
+extern const char AUTHORITY_SIGNKEY_1[];
+
+static uint8_t v0_test_plaintext[] =
+ /* 20 bytes of rendezvous point nickname */
+ { 0x4e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ /* 20 bytes dummy rendezvous cookie */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13,
+ /* 128 bytes dummy DH handshake data */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
+
+static uint8_t v1_test_plaintext[] =
+ /* Version byte */
+ { 0x01,
+ /* 42 bytes of dummy rendezvous point hex digest */
+ 0x24, 0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30,
+ 0x33, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30,
+ 0x37, 0x30, 0x38, 0x30, 0x39, 0x30, 0x41, 0x30,
+ 0x42, 0x30, 0x43, 0x30, 0x44, 0x30, 0x45, 0x30,
+ 0x46, 0x31, 0x30, 0x31, 0x31, 0x31, 0x32, 0x31,
+ 0x33, 0x00,
+ /* 20 bytes dummy rendezvous cookie */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13,
+ /* 128 bytes dummy DH handshake data */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
+
+static uint8_t v2_test_plaintext[] =
+ /* Version byte */
+ { 0x02,
+ /* 4 bytes rendezvous point's IP address */
+ 0xc0, 0xa8, 0x00, 0x01,
+ /* 2 bytes rendezvous point's OR port */
+ 0x23, 0x5a,
+ /* 20 bytes dummy rendezvous point's identity digest */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13,
+ /* 2 bytes length of onion key */
+ 0x00, 0x8c,
+ /* Onion key (140 bytes taken from live test) */
+ 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xb1,
+ 0xcd, 0x46, 0xa9, 0x18, 0xd2, 0x0f, 0x01, 0xf8,
+ 0xb2, 0xad, 0xa4, 0x79, 0xb4, 0xbb, 0x4b, 0xf4,
+ 0x54, 0x1e, 0x3f, 0x03, 0x54, 0xcf, 0x7c, 0xb6,
+ 0xb5, 0xf0, 0xfe, 0xed, 0x4b, 0x7d, 0xd7, 0x61,
+ 0xdb, 0x6d, 0xd9, 0x19, 0xe2, 0x72, 0x04, 0xaa,
+ 0x3e, 0x89, 0x26, 0x14, 0x62, 0x9a, 0x6c, 0x11,
+ 0x0b, 0x35, 0x99, 0x2c, 0x9f, 0x2c, 0x64, 0xa1,
+ 0xd9, 0xe2, 0x88, 0xce, 0xf6, 0x54, 0xfe, 0x1d,
+ 0x37, 0x5e, 0x6d, 0x73, 0x95, 0x54, 0x90, 0xf0,
+ 0x7b, 0xfa, 0xd4, 0x44, 0xac, 0xb2, 0x23, 0x9f,
+ 0x75, 0x36, 0xe2, 0x78, 0x62, 0x82, 0x80, 0xa4,
+ 0x23, 0x22, 0xc9, 0xbf, 0xc4, 0x36, 0xd1, 0x31,
+ 0x33, 0x8e, 0x64, 0xb4, 0xa9, 0x74, 0xa1, 0xcb,
+ 0x42, 0x8d, 0x60, 0xc7, 0xbb, 0x8e, 0x6e, 0x0f,
+ 0x36, 0x74, 0x8e, 0xf4, 0x08, 0x99, 0x06, 0x92,
+ 0xb1, 0x3f, 0xb3, 0xdd, 0xed, 0xf7, 0xc9, 0x02,
+ 0x03, 0x01, 0x00, 0x01,
+ /* 20 bytes dummy rendezvous cookie */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13,
+ /* 128 bytes dummy DH handshake data */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
+
+static uint8_t v3_no_auth_test_plaintext[] =
+ /* Version byte */
+ { 0x03,
+ /* Auth type (0 for no auth len/auth data) */
+ 0x00,
+ /* Timestamp */
+ 0x50, 0x0b, 0xb5, 0xaa,
+ /* 4 bytes rendezvous point's IP address */
+ 0xc0, 0xa8, 0x00, 0x01,
+ /* 2 bytes rendezvous point's OR port */
+ 0x23, 0x5a,
+ /* 20 bytes dummy rendezvous point's identity digest */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13,
+ /* 2 bytes length of onion key */
+ 0x00, 0x8c,
+ /* Onion key (140 bytes taken from live test) */
+ 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xb1,
+ 0xcd, 0x46, 0xa9, 0x18, 0xd2, 0x0f, 0x01, 0xf8,
+ 0xb2, 0xad, 0xa4, 0x79, 0xb4, 0xbb, 0x4b, 0xf4,
+ 0x54, 0x1e, 0x3f, 0x03, 0x54, 0xcf, 0x7c, 0xb6,
+ 0xb5, 0xf0, 0xfe, 0xed, 0x4b, 0x7d, 0xd7, 0x61,
+ 0xdb, 0x6d, 0xd9, 0x19, 0xe2, 0x72, 0x04, 0xaa,
+ 0x3e, 0x89, 0x26, 0x14, 0x62, 0x9a, 0x6c, 0x11,
+ 0x0b, 0x35, 0x99, 0x2c, 0x9f, 0x2c, 0x64, 0xa1,
+ 0xd9, 0xe2, 0x88, 0xce, 0xf6, 0x54, 0xfe, 0x1d,
+ 0x37, 0x5e, 0x6d, 0x73, 0x95, 0x54, 0x90, 0xf0,
+ 0x7b, 0xfa, 0xd4, 0x44, 0xac, 0xb2, 0x23, 0x9f,
+ 0x75, 0x36, 0xe2, 0x78, 0x62, 0x82, 0x80, 0xa4,
+ 0x23, 0x22, 0xc9, 0xbf, 0xc4, 0x36, 0xd1, 0x31,
+ 0x33, 0x8e, 0x64, 0xb4, 0xa9, 0x74, 0xa1, 0xcb,
+ 0x42, 0x8d, 0x60, 0xc7, 0xbb, 0x8e, 0x6e, 0x0f,
+ 0x36, 0x74, 0x8e, 0xf4, 0x08, 0x99, 0x06, 0x92,
+ 0xb1, 0x3f, 0xb3, 0xdd, 0xed, 0xf7, 0xc9, 0x02,
+ 0x03, 0x01, 0x00, 0x01,
+ /* 20 bytes dummy rendezvous cookie */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13,
+ /* 128 bytes dummy DH handshake data */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
+
+static uint8_t v3_basic_auth_test_plaintext[] =
+ /* Version byte */
+ { 0x03,
+ /* Auth type (1 for REND_BASIC_AUTH) */
+ 0x01,
+ /* Auth len (must be 16 bytes for REND_BASIC_AUTH) */
+ 0x00, 0x10,
+ /* Auth data (a 16-byte dummy descriptor cookie) */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ /* Timestamp */
+ 0x50, 0x0b, 0xb5, 0xaa,
+ /* 4 bytes rendezvous point's IP address */
+ 0xc0, 0xa8, 0x00, 0x01,
+ /* 2 bytes rendezvous point's OR port */
+ 0x23, 0x5a,
+ /* 20 bytes dummy rendezvous point's identity digest */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13,
+ /* 2 bytes length of onion key */
+ 0x00, 0x8c,
+ /* Onion key (140 bytes taken from live test) */
+ 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xb1,
+ 0xcd, 0x46, 0xa9, 0x18, 0xd2, 0x0f, 0x01, 0xf8,
+ 0xb2, 0xad, 0xa4, 0x79, 0xb4, 0xbb, 0x4b, 0xf4,
+ 0x54, 0x1e, 0x3f, 0x03, 0x54, 0xcf, 0x7c, 0xb6,
+ 0xb5, 0xf0, 0xfe, 0xed, 0x4b, 0x7d, 0xd7, 0x61,
+ 0xdb, 0x6d, 0xd9, 0x19, 0xe2, 0x72, 0x04, 0xaa,
+ 0x3e, 0x89, 0x26, 0x14, 0x62, 0x9a, 0x6c, 0x11,
+ 0x0b, 0x35, 0x99, 0x2c, 0x9f, 0x2c, 0x64, 0xa1,
+ 0xd9, 0xe2, 0x88, 0xce, 0xf6, 0x54, 0xfe, 0x1d,
+ 0x37, 0x5e, 0x6d, 0x73, 0x95, 0x54, 0x90, 0xf0,
+ 0x7b, 0xfa, 0xd4, 0x44, 0xac, 0xb2, 0x23, 0x9f,
+ 0x75, 0x36, 0xe2, 0x78, 0x62, 0x82, 0x80, 0xa4,
+ 0x23, 0x22, 0xc9, 0xbf, 0xc4, 0x36, 0xd1, 0x31,
+ 0x33, 0x8e, 0x64, 0xb4, 0xa9, 0x74, 0xa1, 0xcb,
+ 0x42, 0x8d, 0x60, 0xc7, 0xbb, 0x8e, 0x6e, 0x0f,
+ 0x36, 0x74, 0x8e, 0xf4, 0x08, 0x99, 0x06, 0x92,
+ 0xb1, 0x3f, 0xb3, 0xdd, 0xed, 0xf7, 0xc9, 0x02,
+ 0x03, 0x01, 0x00, 0x01,
+ /* 20 bytes dummy rendezvous cookie */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13,
+ /* 128 bytes dummy DH handshake data */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
+
+static void do_decrypt_test(uint8_t *plaintext, size_t plaintext_len);
+static void do_early_parse_test(uint8_t *plaintext, size_t plaintext_len);
+static void do_late_parse_test(uint8_t *plaintext, size_t plaintext_len);
+static void do_parse_test(uint8_t *plaintext, size_t plaintext_len, int phase);
+static ssize_t make_intro_from_plaintext(
+ void *buf, size_t len, crypto_pk_t *key, void **cell_out);
+
+#define EARLY_PARSE_ONLY 1
+#define DECRYPT_ONLY 2
+#define ALL_PARSING 3
+
+static void
+do_early_parse_test(uint8_t *plaintext, size_t plaintext_len)
+{
+ do_parse_test(plaintext, plaintext_len, EARLY_PARSE_ONLY);
+}
+
+static void
+do_decrypt_test(uint8_t *plaintext, size_t plaintext_len)
+{
+ do_parse_test(plaintext, plaintext_len, DECRYPT_ONLY);
+}
+
+static void
+do_late_parse_test(uint8_t *plaintext, size_t plaintext_len)
+{
+ do_parse_test(plaintext, plaintext_len, ALL_PARSING);
+}
+
+/** Test utility function: checks that the <b>plaintext_len</b>-byte string at
+ * <b>plaintext</b> is at least superficially parseable.
+ */
+static void
+do_parse_test(uint8_t *plaintext, size_t plaintext_len, int phase)
+{
+ crypto_pk_t *k = NULL;
+ ssize_t r;
+ uint8_t *cell = NULL;
+ size_t cell_len;
+ rend_intro_cell_t *parsed_req = NULL;
+ char *err_msg = NULL;
+ char digest[DIGEST_LEN];
+
+ /* Get a key */
+ k = crypto_pk_new();
+ test_assert(k);
+ r = crypto_pk_read_private_key_from_string(k, AUTHORITY_SIGNKEY_1, -1);
+ test_assert(!r);
+
+ /* Get digest for future comparison */
+ r = crypto_pk_get_digest(k, digest);
+ test_assert(r >= 0);
+
+ /* Make a cell out of it */
+ r = make_intro_from_plaintext(
+ plaintext, plaintext_len,
+ k, (void **)(&cell));
+ test_assert(r > 0);
+ test_assert(cell);
+ cell_len = r;
+
+ /* Do early parsing */
+ parsed_req = rend_service_begin_parse_intro(cell, cell_len, 2, &err_msg);
+ test_assert(parsed_req);
+ test_assert(!err_msg);
+ test_memeq(parsed_req->pk, digest, DIGEST_LEN);
+ test_assert(parsed_req->ciphertext);
+ test_assert(parsed_req->ciphertext_len > 0);
+
+ if (phase == EARLY_PARSE_ONLY)
+ goto done;
+
+ /* Do decryption */
+ r = rend_service_decrypt_intro(parsed_req, k, &err_msg);
+ test_assert(!r);
+ test_assert(!err_msg);
+ test_assert(parsed_req->plaintext);
+ test_assert(parsed_req->plaintext_len > 0);
+
+ if (phase == DECRYPT_ONLY)
+ goto done;
+
+ /* Do late parsing */
+ r = rend_service_parse_intro_plaintext(parsed_req, &err_msg);
+ test_assert(!r);
+ test_assert(!err_msg);
+ test_assert(parsed_req->parsed);
+
+ done:
+ tor_free(cell);
+ crypto_pk_free(k);
+ rend_service_free_intro(parsed_req);
+ tor_free(err_msg);
+}
+
+/** Given the plaintext of the encrypted part of an INTRODUCE1/2 and a key,
+ * construct the encrypted cell for testing.
+ */
+
+static ssize_t
+make_intro_from_plaintext(
+ void *buf, size_t len, crypto_pk_t *key, void **cell_out)
+{
+ char *cell = NULL;
+ ssize_t cell_len = -1, r;
+ /* Assemble key digest and ciphertext, then construct the cell */
+ ssize_t ciphertext_size;
+
+ if (!(buf && key && len > 0 && cell_out)) goto done;
+
+ /*
+ * Figure out an upper bound on how big the ciphertext will be
+ * (see crypto_pk_public_hybrid_encrypt())
+ */
+ ciphertext_size = PKCS1_OAEP_PADDING_OVERHEAD;
+ ciphertext_size += crypto_pk_keysize(key);
+ ciphertext_size += CIPHER_KEY_LEN;
+ ciphertext_size += len;
+
+ /*
+ * Allocate space for the cell
+ */
+ cell = tor_malloc(DIGEST_LEN + ciphertext_size);
+
+ /* Compute key digest (will be first DIGEST_LEN octets of cell) */
+ r = crypto_pk_get_digest(key, cell);
+ test_assert(r >= 0);
+
+ /* Do encryption */
+ r = crypto_pk_public_hybrid_encrypt(
+ key, cell + DIGEST_LEN, ciphertext_size,
+ buf, len,
+ PK_PKCS1_OAEP_PADDING, 0);
+ test_assert(r >= 0);
+
+ /* Figure out cell length */
+ cell_len = DIGEST_LEN + r;
+
+ /* Output the cell */
+ *cell_out = cell;
+
+ done:
+ return cell_len;
+}
+
+/** Test v0 INTRODUCE2 parsing through decryption only
+ */
+
+static void
+test_introduce_decrypt_v0(void)
+{
+ do_decrypt_test(v0_test_plaintext, sizeof(v0_test_plaintext));
+}
+
+/** Test v1 INTRODUCE2 parsing through decryption only
+ */
+
+static void
+test_introduce_decrypt_v1(void)
+{
+ do_decrypt_test(v1_test_plaintext, sizeof(v1_test_plaintext));
+}
+
+/** Test v2 INTRODUCE2 parsing through decryption only
+ */
+
+static void
+test_introduce_decrypt_v2(void)
+{
+ do_decrypt_test(v2_test_plaintext, sizeof(v2_test_plaintext));
+}
+
+/** Test v3 INTRODUCE2 parsing through decryption only
+ */
+
+static void
+test_introduce_decrypt_v3(void)
+{
+ do_decrypt_test(
+ v3_no_auth_test_plaintext, sizeof(v3_no_auth_test_plaintext));
+ do_decrypt_test(
+ v3_basic_auth_test_plaintext, sizeof(v3_basic_auth_test_plaintext));
+}
+
+/** Test v0 INTRODUCE2 parsing through early parsing only
+ */
+
+static void
+test_introduce_early_parse_v0(void)
+{
+ do_early_parse_test(v0_test_plaintext, sizeof(v0_test_plaintext));
+}
+
+/** Test v1 INTRODUCE2 parsing through early parsing only
+ */
+
+static void
+test_introduce_early_parse_v1(void)
+{
+ do_early_parse_test(v1_test_plaintext, sizeof(v1_test_plaintext));
+}
+
+/** Test v2 INTRODUCE2 parsing through early parsing only
+ */
+
+static void
+test_introduce_early_parse_v2(void)
+{
+ do_early_parse_test(v2_test_plaintext, sizeof(v2_test_plaintext));
+}
+
+/** Test v3 INTRODUCE2 parsing through early parsing only
+ */
+
+static void
+test_introduce_early_parse_v3(void)
+{
+ do_early_parse_test(
+ v3_no_auth_test_plaintext, sizeof(v3_no_auth_test_plaintext));
+ do_early_parse_test(
+ v3_basic_auth_test_plaintext, sizeof(v3_basic_auth_test_plaintext));
+}
+
+/** Test v0 INTRODUCE2 parsing
+ */
+
+static void
+test_introduce_late_parse_v0(void)
+{
+ do_late_parse_test(v0_test_plaintext, sizeof(v0_test_plaintext));
+}
+
+/** Test v1 INTRODUCE2 parsing
+ */
+
+static void
+test_introduce_late_parse_v1(void)
+{
+ do_late_parse_test(v1_test_plaintext, sizeof(v1_test_plaintext));
+}
+
+/** Test v2 INTRODUCE2 parsing
+ */
+
+static void
+test_introduce_late_parse_v2(void)
+{
+ do_late_parse_test(v2_test_plaintext, sizeof(v2_test_plaintext));
+}
+
+/** Test v3 INTRODUCE2 parsing
+ */
+
+static void
+test_introduce_late_parse_v3(void)
+{
+ do_late_parse_test(
+ v3_no_auth_test_plaintext, sizeof(v3_no_auth_test_plaintext));
+ do_late_parse_test(
+ v3_basic_auth_test_plaintext, sizeof(v3_basic_auth_test_plaintext));
+}
+
+#define INTRODUCE_LEGACY(name) \
+ { #name, legacy_test_helper, 0, &legacy_setup, test_introduce_ ## name }
+
+struct testcase_t introduce_tests[] = {
+ INTRODUCE_LEGACY(early_parse_v0),
+ INTRODUCE_LEGACY(early_parse_v1),
+ INTRODUCE_LEGACY(early_parse_v2),
+ INTRODUCE_LEGACY(early_parse_v3),
+ INTRODUCE_LEGACY(decrypt_v0),
+ INTRODUCE_LEGACY(decrypt_v1),
+ INTRODUCE_LEGACY(decrypt_v2),
+ INTRODUCE_LEGACY(decrypt_v3),
+ INTRODUCE_LEGACY(late_parse_v0),
+ INTRODUCE_LEGACY(late_parse_v1),
+ INTRODUCE_LEGACY(late_parse_v2),
+ INTRODUCE_LEGACY(late_parse_v3),
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_replay.c b/src/test/test_replay.c
new file mode 100644
index 000000000..b08818f06
--- /dev/null
+++ b/src/test/test_replay.c
@@ -0,0 +1,184 @@
+/* Copyright (c) 2012, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define REPLAYCACHE_PRIVATE
+
+#include "orconfig.h"
+#include "or.h"
+#include "replaycache.h"
+#include "test.h"
+
+static const char *test_buffer =
+ "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed do eiusmod"
+ " tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim"
+ " veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea"
+ " commodo consequat. Duis aute irure dolor in reprehenderit in voluptate"
+ " velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint"
+ " occaecat cupidatat non proident, sunt in culpa qui officia deserunt"
+ " mollit anim id est laborum.";
+
+static void
+test_replaycache_alloc(void)
+{
+ replaycache_t *r = NULL;
+
+ r = replaycache_new(600, 300);
+ test_assert(r != NULL);
+ if (!r) goto done;
+
+ done:
+ if (r) replaycache_free(r);
+
+ return;
+}
+
+static void
+test_replaycache_miss(void)
+{
+ replaycache_t *r = NULL;
+ int result;
+
+ r = replaycache_new(600, 300);
+ test_assert(r != NULL);
+ if (!r) goto done;
+
+ result =
+ replaycache_add_and_test_internal(1200, r, test_buffer,
+ (int)strlen(test_buffer), NULL);
+ test_eq(result, 0);
+
+ done:
+ if (r) replaycache_free(r);
+
+ return;
+}
+
+static void
+test_replaycache_hit(void)
+{
+ replaycache_t *r = NULL;
+ int result;
+
+ r = replaycache_new(600, 300);
+ test_assert(r != NULL);
+ if (!r) goto done;
+
+ result =
+ replaycache_add_and_test_internal(1200, r, test_buffer,
+ (int)strlen(test_buffer), NULL);
+ test_eq(result, 0);
+
+ result =
+ replaycache_add_and_test_internal(1300, r, test_buffer,
+ (int)strlen(test_buffer), NULL);
+ test_eq(result, 1);
+
+ done:
+ if (r) replaycache_free(r);
+
+ return;
+}
+
+static void
+test_replaycache_age(void)
+{
+ replaycache_t *r = NULL;
+ int result;
+
+ r = replaycache_new(600, 300);
+ test_assert(r != NULL);
+ if (!r) goto done;
+
+ result =
+ replaycache_add_and_test_internal(1200, r, test_buffer,
+ (int)strlen(test_buffer), NULL);
+ test_eq(result, 0);
+
+ result =
+ replaycache_add_and_test_internal(1300, r, test_buffer,
+ (int)strlen(test_buffer), NULL);
+ test_eq(result, 1);
+
+ result =
+ replaycache_add_and_test_internal(3000, r, test_buffer,
+ (int)strlen(test_buffer), NULL);
+ test_eq(result, 0);
+
+ done:
+ if (r) replaycache_free(r);
+
+ return;
+}
+
+static void
+test_replaycache_elapsed(void)
+{
+ replaycache_t *r = NULL;
+ int result;
+ time_t elapsed;
+
+ r = replaycache_new(600, 300);
+ test_assert(r != NULL);
+ if (!r) goto done;
+
+ result =
+ replaycache_add_and_test_internal(1200, r, test_buffer,
+ (int)strlen(test_buffer), NULL);
+ test_eq(result, 0);
+
+ result =
+ replaycache_add_and_test_internal(1300, r, test_buffer,
+ (int)strlen(test_buffer), &elapsed);
+ test_eq(result, 1);
+ test_eq(elapsed, 100);
+
+ done:
+ if (r) replaycache_free(r);
+
+ return;
+}
+
+static void
+test_replaycache_noexpire(void)
+{
+ replaycache_t *r = NULL;
+ int result;
+
+ r = replaycache_new(0, 0);
+ test_assert(r != NULL);
+ if (!r) goto done;
+
+ result =
+ replaycache_add_and_test_internal(1200, r, test_buffer,
+ (int)strlen(test_buffer), NULL);
+ test_eq(result, 0);
+
+ result =
+ replaycache_add_and_test_internal(1300, r, test_buffer,
+ (int)strlen(test_buffer), NULL);
+ test_eq(result, 1);
+
+ result =
+ replaycache_add_and_test_internal(3000, r, test_buffer,
+ (int)strlen(test_buffer), NULL);
+ test_eq(result, 1);
+
+ done:
+ if (r) replaycache_free(r);
+
+ return;
+}
+
+#define REPLAYCACHE_LEGACY(name) \
+ { #name, legacy_test_helper, 0, &legacy_setup, test_replaycache_ ## name }
+
+struct testcase_t replaycache_tests[] = {
+ REPLAYCACHE_LEGACY(alloc),
+ REPLAYCACHE_LEGACY(miss),
+ REPLAYCACHE_LEGACY(hit),
+ REPLAYCACHE_LEGACY(age),
+ REPLAYCACHE_LEGACY(elapsed),
+ REPLAYCACHE_LEGACY(noexpire),
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 4f9eb73e0..3ceea3890 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -32,6 +32,74 @@ tor_timegm_wrapper(const struct tm *tm)
#define tor_timegm tor_timegm_wrapper
static void
+test_util_read_until_eof_impl(const char *fname, size_t file_len,
+ size_t read_limit)
+{
+ char *fifo_name = NULL;
+ char *test_str = NULL;
+ char *str = NULL;
+ size_t sz = 9999999;
+ int fd = -1;
+ int r;
+
+ fifo_name = tor_strdup(get_fname(fname));
+ test_str = tor_malloc(file_len);
+ crypto_rand(test_str, file_len);
+
+ r = write_bytes_to_file(fifo_name, test_str, file_len, 1);
+ tt_int_op(r, ==, 0);
+
+ fd = open(fifo_name, O_RDONLY|O_BINARY);
+ tt_int_op(fd, >=, 0);
+ str = read_file_to_str_until_eof(fd, read_limit, &sz);
+ close(fd);
+ tt_assert(str != NULL);
+
+ if (read_limit < file_len)
+ tt_int_op(sz, ==, read_limit);
+ else
+ tt_int_op(sz, ==, file_len);
+
+ test_mem_op(test_str, ==, str, sz);
+ test_assert(str[sz] == '\0');
+
+ done:
+ unlink(fifo_name);
+ tor_free(fifo_name);
+ tor_free(test_str);
+ tor_free(str);
+}
+
+static void
+test_util_read_file_eof_tiny_limit(void *arg)
+{
+ (void)arg;
+ // purposely set limit shorter than what we wrote to the FIFO to
+ // test the maximum, and that it puts the NUL in the right spot
+
+ test_util_read_until_eof_impl("tor_test_fifo_tiny", 5, 4);
+}
+
+static void
+test_util_read_file_eof_two_loops(void *arg)
+{
+ (void)arg;
+ // write more than 1024 bytes to the FIFO to test two passes through
+ // the loop in the method; if the re-alloc size is changed this
+ // should be updated as well.
+
+ test_util_read_until_eof_impl("tor_test_fifo_2k", 2048, 10000);
+}
+
+static void
+test_util_read_file_eof_zero_bytes(void *arg)
+{
+ (void)arg;
+ // zero-byte fifo
+ test_util_read_until_eof_impl("tor_test_fifo_empty", 0, 10000);
+}
+
+static void
test_util_time(void)
{
struct timeval start, end;
@@ -1109,6 +1177,7 @@ test_util_pow2(void)
test_eq(tor_log2(64), 6);
test_eq(tor_log2(65), 6);
test_eq(tor_log2(63), 5);
+ test_eq(tor_log2(0), 0); /* incorrect mathematically, but as specified */
test_eq(tor_log2(1), 0);
test_eq(tor_log2(2), 1);
test_eq(tor_log2(3), 1);
@@ -1123,26 +1192,35 @@ test_util_pow2(void)
test_eq(round_to_power_of_2(130), 128);
test_eq(round_to_power_of_2(U64_LITERAL(40000000000000000)),
U64_LITERAL(1)<<55);
- test_eq(round_to_power_of_2(0), 2);
+ test_eq(round_to_power_of_2(U64_LITERAL(0xffffffffffffffff)),
+ U64_LITERAL(1)<<63);
+ test_eq(round_to_power_of_2(0), 1);
+ test_eq(round_to_power_of_2(1), 1);
+ test_eq(round_to_power_of_2(2), 2);
+ test_eq(round_to_power_of_2(3), 2);
+ test_eq(round_to_power_of_2(4), 4);
+ test_eq(round_to_power_of_2(5), 4);
+ test_eq(round_to_power_of_2(6), 4);
+ test_eq(round_to_power_of_2(7), 8);
done:
;
}
/** mutex for thread test to stop the threads hitting data at the same time. */
-static tor_mutex_t *_thread_test_mutex = NULL;
+static tor_mutex_t *thread_test_mutex_ = NULL;
/** mutexes for the thread test to make sure that the threads have to
* interleave somewhat. */
-static tor_mutex_t *_thread_test_start1 = NULL,
- *_thread_test_start2 = NULL;
+static tor_mutex_t *thread_test_start1_ = NULL,
+ *thread_test_start2_ = NULL;
/** Shared strmap for the thread test. */
-static strmap_t *_thread_test_strmap = NULL;
+static strmap_t *thread_test_strmap_ = NULL;
/** The name of thread1 for the thread test */
-static char *_thread1_name = NULL;
+static char *thread1_name_ = NULL;
/** The name of thread2 for the thread test */
-static char *_thread2_name = NULL;
+static char *thread2_name_ = NULL;
-static void _thread_test_func(void* _s) ATTR_NORETURN;
+static void thread_test_func_(void* _s) ATTR_NORETURN;
/** How many iterations have the threads in the unit test run? */
static int t1_count = 0, t2_count = 0;
@@ -1150,9 +1228,9 @@ static int t1_count = 0, t2_count = 0;
/** Helper function for threading unit tests: This function runs in a
* subthread. It grabs its own mutex (start1 or start2) to make sure that it
* should start, then it repeatedly alters _test_thread_strmap protected by
- * _thread_test_mutex. */
+ * thread_test_mutex_. */
static void
-_thread_test_func(void* _s)
+thread_test_func_(void* _s)
{
char *s = _s;
int i, *count;
@@ -1160,12 +1238,12 @@ _thread_test_func(void* _s)
char buf[64];
char **cp;
if (!strcmp(s, "thread 1")) {
- m = _thread_test_start1;
- cp = &_thread1_name;
+ m = thread_test_start1_;
+ cp = &thread1_name_;
count = &t1_count;
} else {
- m = _thread_test_start2;
- cp = &_thread2_name;
+ m = thread_test_start2_;
+ cp = &thread2_name_;
count = &t2_count;
}
@@ -1175,14 +1253,14 @@ _thread_test_func(void* _s)
tor_mutex_acquire(m);
for (i=0; i<10000; ++i) {
- tor_mutex_acquire(_thread_test_mutex);
- strmap_set(_thread_test_strmap, "last to run", *cp);
+ tor_mutex_acquire(thread_test_mutex_);
+ strmap_set(thread_test_strmap_, "last to run", *cp);
++*count;
- tor_mutex_release(_thread_test_mutex);
+ tor_mutex_release(thread_test_mutex_);
}
- tor_mutex_acquire(_thread_test_mutex);
- strmap_set(_thread_test_strmap, s, *cp);
- tor_mutex_release(_thread_test_mutex);
+ tor_mutex_acquire(thread_test_mutex_);
+ strmap_set(thread_test_strmap_, s, *cp);
+ tor_mutex_release(thread_test_mutex_);
tor_mutex_release(m);
@@ -1207,67 +1285,67 @@ test_util_threads(void)
if (1)
return;
#endif
- _thread_test_mutex = tor_mutex_new();
- _thread_test_start1 = tor_mutex_new();
- _thread_test_start2 = tor_mutex_new();
- _thread_test_strmap = strmap_new();
+ thread_test_mutex_ = tor_mutex_new();
+ thread_test_start1_ = tor_mutex_new();
+ thread_test_start2_ = tor_mutex_new();
+ thread_test_strmap_ = strmap_new();
s1 = tor_strdup("thread 1");
s2 = tor_strdup("thread 2");
- tor_mutex_acquire(_thread_test_start1);
- tor_mutex_acquire(_thread_test_start2);
- spawn_func(_thread_test_func, s1);
- spawn_func(_thread_test_func, s2);
- tor_mutex_release(_thread_test_start2);
- tor_mutex_release(_thread_test_start1);
+ tor_mutex_acquire(thread_test_start1_);
+ tor_mutex_acquire(thread_test_start2_);
+ spawn_func(thread_test_func_, s1);
+ spawn_func(thread_test_func_, s2);
+ tor_mutex_release(thread_test_start2_);
+ tor_mutex_release(thread_test_start1_);
started = time(NULL);
while (!done) {
- tor_mutex_acquire(_thread_test_mutex);
- strmap_assert_ok(_thread_test_strmap);
- if (strmap_get(_thread_test_strmap, "thread 1") &&
- strmap_get(_thread_test_strmap, "thread 2")) {
+ tor_mutex_acquire(thread_test_mutex_);
+ strmap_assert_ok(thread_test_strmap_);
+ if (strmap_get(thread_test_strmap_, "thread 1") &&
+ strmap_get(thread_test_strmap_, "thread 2")) {
done = 1;
} else if (time(NULL) > started + 150) {
timedout = done = 1;
}
- tor_mutex_release(_thread_test_mutex);
+ tor_mutex_release(thread_test_mutex_);
#ifndef _WIN32
/* Prevent the main thread from starving the worker threads. */
select(0, NULL, NULL, NULL, &tv);
#endif
}
- tor_mutex_acquire(_thread_test_start1);
- tor_mutex_release(_thread_test_start1);
- tor_mutex_acquire(_thread_test_start2);
- tor_mutex_release(_thread_test_start2);
+ tor_mutex_acquire(thread_test_start1_);
+ tor_mutex_release(thread_test_start1_);
+ tor_mutex_acquire(thread_test_start2_);
+ tor_mutex_release(thread_test_start2_);
- tor_mutex_free(_thread_test_mutex);
+ tor_mutex_free(thread_test_mutex_);
if (timedout) {
printf("\nTimed out: %d %d", t1_count, t2_count);
- test_assert(strmap_get(_thread_test_strmap, "thread 1"));
- test_assert(strmap_get(_thread_test_strmap, "thread 2"));
+ test_assert(strmap_get(thread_test_strmap_, "thread 1"));
+ test_assert(strmap_get(thread_test_strmap_, "thread 2"));
test_assert(!timedout);
}
/* different thread IDs. */
- test_assert(strcmp(strmap_get(_thread_test_strmap, "thread 1"),
- strmap_get(_thread_test_strmap, "thread 2")));
- test_assert(!strcmp(strmap_get(_thread_test_strmap, "thread 1"),
- strmap_get(_thread_test_strmap, "last to run")) ||
- !strcmp(strmap_get(_thread_test_strmap, "thread 2"),
- strmap_get(_thread_test_strmap, "last to run")));
+ test_assert(strcmp(strmap_get(thread_test_strmap_, "thread 1"),
+ strmap_get(thread_test_strmap_, "thread 2")));
+ test_assert(!strcmp(strmap_get(thread_test_strmap_, "thread 1"),
+ strmap_get(thread_test_strmap_, "last to run")) ||
+ !strcmp(strmap_get(thread_test_strmap_, "thread 2"),
+ strmap_get(thread_test_strmap_, "last to run")));
done:
tor_free(s1);
tor_free(s2);
- tor_free(_thread1_name);
- tor_free(_thread2_name);
- if (_thread_test_strmap)
- strmap_free(_thread_test_strmap, NULL);
- if (_thread_test_start1)
- tor_mutex_free(_thread_test_start1);
- if (_thread_test_start2)
- tor_mutex_free(_thread_test_start2);
+ tor_free(thread1_name_);
+ tor_free(thread2_name_);
+ if (thread_test_strmap_)
+ strmap_free(thread_test_strmap_, NULL);
+ if (thread_test_start1_)
+ tor_mutex_free(thread_test_start1_);
+ if (thread_test_start2_)
+ tor_mutex_free(thread_test_start2_);
}
/** Run unit tests for compression functions */
@@ -1474,12 +1552,28 @@ test_util_control_formats(void)
tor_free(out);
}
+#define test_feq(value1,value2) do { \
+ double v1 = (value1), v2=(value2); \
+ double tf_diff = v1-v2; \
+ double tf_tolerance = ((v1+v2)/2.0)/1e8; \
+ if (tf_diff<0) tf_diff=-tf_diff; \
+ if (tf_tolerance<0) tf_tolerance=-tf_tolerance; \
+ if (tf_diff<tf_tolerance) { \
+ TT_BLATHER(("%s ~~ %s: %f ~~ %f",#value1,#value2,v1,v2)); \
+ } else { \
+ TT_FAIL(("%s ~~ %s: %f != %f",#value1,#value2,v1,v2)); \
+ } \
+ } while (0)
+
static void
test_util_sscanf(void)
{
unsigned u1, u2, u3;
char s1[20], s2[10], s3[10], ch;
int r;
+ long lng1,lng2;
+ int int1, int2;
+ double d1,d2,d3,d4;
/* Simple tests (malformed patterns, literal matching, ...) */
test_eq(-1, tor_sscanf("123", "%i", &r)); /* %i is not supported */
@@ -1608,6 +1702,65 @@ test_util_sscanf(void)
test_eq(4, tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
test_eq(' ', ch);
+ r = tor_sscanf("12345 -67890 -1", "%d %ld %d", &int1, &lng1, &int2);
+ test_eq(r,3);
+ test_eq(int1, 12345);
+ test_eq(lng1, -67890);
+ test_eq(int2, -1);
+
+#if SIZEOF_INT == 4
+ r = tor_sscanf("-2147483648. 2147483647.", "%d. %d.", &int1, &int2);
+ test_eq(r,2);
+ test_eq(int1, -2147483647-1);
+ test_eq(int2, 2147483647);
+
+ r = tor_sscanf("-2147483679.", "%d.", &int1);
+ test_eq(r,0);
+
+ r = tor_sscanf("2147483678.", "%d.", &int1);
+ test_eq(r,0);
+#elif SIZEOF_INT == 8
+ r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
+ "%d. %d.", &int1, &int2);
+ test_eq(r,2);
+ test_eq(int1, -9223372036854775807-1);
+ test_eq(int2, 9223372036854775807);
+
+ r = tor_sscanf("-9223372036854775809.", "%d.", &int1);
+ test_eq(r,0);
+
+ r = tor_sscanf("9223372036854775808.", "%d.", &int1);
+ test_eq(r,0);
+#endif
+
+#if SIZEOF_LONG == 4
+ r = tor_sscanf("-2147483648. 2147483647.", "%ld. %ld.", &lng1, &lng2);
+ test_eq(r,2);
+ test_eq(lng1, -2147483647 - 1);
+ test_eq(lng2, 2147483647);
+#elif SIZEOF_LONG == 8
+ r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
+ "%ld. %ld.", &lng1, &lng2);
+ test_eq(r,2);
+ test_eq(lng1, -9223372036854775807L - 1);
+ test_eq(lng2, 9223372036854775807L);
+
+ r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
+ "%ld. %ld.", &lng1, &lng2);
+ test_eq(r,1);
+ r = tor_sscanf("-9223372036854775809. 9223372036854775808.",
+ "%ld. %ld.", &lng1, &lng2);
+ test_eq(r,0);
+#endif
+
+ r = tor_sscanf("123.456 .000007 -900123123.2000787 00003.2",
+ "%lf %lf %lf %lf", &d1,&d2,&d3,&d4);
+ test_eq(r,4);
+ test_feq(d1, 123.456);
+ test_feq(d2, .000007);
+ test_feq(d3, -900123123.2000787);
+ test_feq(d4, 3.2);
+
done:
;
}
@@ -3044,7 +3197,7 @@ test_util_set_env_var_in_sl(void *ptr)
SMARTLIST_FOREACH(new_env_vars, char *, env_var,
set_environment_variable_in_smartlist(merged_env_vars,
env_var,
- _tor_free,
+ tor_free_,
1));
smartlist_sort_strings(merged_env_vars);
@@ -3129,6 +3282,9 @@ struct testcase_t util_tests[] = {
UTIL_TEST(envnames, 0),
UTIL_TEST(make_environment, 0),
UTIL_TEST(set_env_var_in_sl, 0),
+ UTIL_TEST(read_file_eof_tiny_limit, 0),
+ UTIL_TEST(read_file_eof_two_loops, 0),
+ UTIL_TEST(read_file_eof_zero_bytes, 0),
END_OF_TESTCASES
};
diff --git a/src/test/tinytest.c b/src/test/tinytest.c
deleted file mode 100644
index 4d9afacce..000000000
--- a/src/test/tinytest.c
+++ /dev/null
@@ -1,387 +0,0 @@
-/* tinytest.c -- Copyright 2009-2012 Nick Mathewson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifdef TINYTEST_LOCAL
-#include "tinytest_local.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#ifdef _WIN32
-#include <windows.h>
-#else
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#endif
-
-#ifndef __GNUC__
-#define __attribute__(x)
-#endif
-
-#include "tinytest.h"
-#include "tinytest_macros.h"
-
-#define LONGEST_TEST_NAME 16384
-
-static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/
-static int n_ok = 0; /**< Number of tests that have passed */
-static int n_bad = 0; /**< Number of tests that have failed. */
-static int n_skipped = 0; /**< Number of tests that have been skipped. */
-
-static int opt_forked = 0; /**< True iff we're called from inside a win32 fork*/
-static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */
-static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */
-const char *verbosity_flag = "";
-
-enum outcome { SKIP=2, OK=1, FAIL=0 };
-static enum outcome cur_test_outcome = 0;
-const char *cur_test_prefix = NULL; /**< prefix of the current test group */
-/** Name of the current test, if we haven't logged is yet. Used for --quiet */
-const char *cur_test_name = NULL;
-
-#ifdef _WIN32
-/* Copy of argv[0] for win32. */
-static char commandname[MAX_PATH+1];
-#endif
-
-static void usage(struct testgroup_t *groups, int list_groups)
- __attribute__((noreturn));
-
-static enum outcome
-testcase_run_bare_(const struct testcase_t *testcase)
-{
- void *env = NULL;
- int outcome;
- if (testcase->setup) {
- env = testcase->setup->setup_fn(testcase);
- if (!env)
- return FAIL;
- else if (env == (void*)TT_SKIP)
- return SKIP;
- }
-
- cur_test_outcome = OK;
- testcase->fn(env);
- outcome = cur_test_outcome;
-
- if (testcase->setup) {
- if (testcase->setup->cleanup_fn(testcase, env) == 0)
- outcome = FAIL;
- }
-
- return outcome;
-}
-
-#define MAGIC_EXITCODE 42
-
-static enum outcome
-testcase_run_forked_(const struct testgroup_t *group,
- const struct testcase_t *testcase)
-{
-#ifdef _WIN32
- /* Fork? On Win32? How primitive! We'll do what the smart kids do:
- we'll invoke our own exe (whose name we recall from the command
- line) with a command line that tells it to run just the test we
- want, and this time without forking.
-
- (No, threads aren't an option. The whole point of forking is to
- share no state between tests.)
- */
- int ok;
- char buffer[LONGEST_TEST_NAME+256];
- STARTUPINFOA si;
- PROCESS_INFORMATION info;
- DWORD exitcode;
-
- if (!in_tinytest_main) {
- printf("\nERROR. On Windows, testcase_run_forked_ must be"
- " called from within tinytest_main.\n");
- abort();
- }
- if (opt_verbosity>0)
- printf("[forking] ");
-
- snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s",
- commandname, verbosity_flag, group->prefix, testcase->name);
-
- memset(&si, 0, sizeof(si));
- memset(&info, 0, sizeof(info));
- si.cb = sizeof(si);
-
- ok = CreateProcessA(commandname, buffer, NULL, NULL, 0,
- 0, NULL, NULL, &si, &info);
- if (!ok) {
- printf("CreateProcess failed!\n");
- return 0;
- }
- WaitForSingleObject(info.hProcess, INFINITE);
- GetExitCodeProcess(info.hProcess, &exitcode);
- CloseHandle(info.hProcess);
- CloseHandle(info.hThread);
- if (exitcode == 0)
- return OK;
- else if (exitcode == MAGIC_EXITCODE)
- return SKIP;
- else
- return FAIL;
-#else
- int outcome_pipe[2];
- pid_t pid;
- (void)group;
-
- if (pipe(outcome_pipe))
- perror("opening pipe");
-
- if (opt_verbosity>0)
- printf("[forking] ");
- pid = fork();
- if (!pid) {
- /* child. */
- int test_r, write_r;
- char b[1];
- close(outcome_pipe[0]);
- test_r = testcase_run_bare_(testcase);
- assert(0<=(int)test_r && (int)test_r<=2);
- b[0] = "NYS"[test_r];
- write_r = (int)write(outcome_pipe[1], b, 1);
- if (write_r != 1) {
- perror("write outcome to pipe");
- exit(1);
- }
- exit(0);
- return FAIL; /* unreachable */
- } else {
- /* parent */
- int status, r;
- char b[1];
- /* Close this now, so that if the other side closes it,
- * our read fails. */
- close(outcome_pipe[1]);
- r = (int)read(outcome_pipe[0], b, 1);
- if (r == 0) {
- printf("[Lost connection!] ");
- return 0;
- } else if (r != 1) {
- perror("read outcome from pipe");
- }
- waitpid(pid, &status, 0);
- close(outcome_pipe[0]);
- return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL);
- }
-#endif
-}
-
-int
-testcase_run_one(const struct testgroup_t *group,
- const struct testcase_t *testcase)
-{
- enum outcome outcome;
-
- if (testcase->flags & TT_SKIP) {
- if (opt_verbosity>0)
- printf("%s%s: SKIPPED\n",
- group->prefix, testcase->name);
- ++n_skipped;
- return SKIP;
- }
-
- if (opt_verbosity>0 && !opt_forked) {
- printf("%s%s: ", group->prefix, testcase->name);
- } else {
- if (opt_verbosity==0) printf(".");
- cur_test_prefix = group->prefix;
- cur_test_name = testcase->name;
- }
-
- if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) {
- outcome = testcase_run_forked_(group, testcase);
- } else {
- outcome = testcase_run_bare_(testcase);
- }
-
- if (outcome == OK) {
- ++n_ok;
- if (opt_verbosity>0 && !opt_forked)
- puts(opt_verbosity==1?"OK":"");
- } else if (outcome == SKIP) {
- ++n_skipped;
- if (opt_verbosity>0 && !opt_forked)
- puts("SKIPPED");
- } else {
- ++n_bad;
- if (!opt_forked)
- printf("\n [%s FAILED]\n", testcase->name);
- }
-
- if (opt_forked) {
- exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1));
- return 1; /* unreachable */
- } else {
- return (int)outcome;
- }
-}
-
-int
-tinytest_set_flag_(struct testgroup_t *groups, const char *arg, unsigned long flag)
-{
- int i, j;
- size_t length = LONGEST_TEST_NAME;
- char fullname[LONGEST_TEST_NAME];
- int found=0;
- if (strstr(arg, ".."))
- length = strstr(arg,"..")-arg;
- for (i=0; groups[i].prefix; ++i) {
- for (j=0; groups[i].cases[j].name; ++j) {
- snprintf(fullname, sizeof(fullname), "%s%s",
- groups[i].prefix, groups[i].cases[j].name);
- if (!flag) /* Hack! */
- printf(" %s\n", fullname);
- if (!strncmp(fullname, arg, length)) {
- groups[i].cases[j].flags |= flag;
- ++found;
- }
- }
- }
- return found;
-}
-
-static void
-usage(struct testgroup_t *groups, int list_groups)
-{
- puts("Options are: [--verbose|--quiet|--terse] [--no-fork]");
- puts(" Specify tests by name, or using a prefix ending with '..'");
- puts(" To skip a test, list give its name prefixed with a colon.");
- puts(" Use --list-tests for a list of tests.");
- if (list_groups) {
- puts("Known tests are:");
- tinytest_set_flag_(groups, "..", 0);
- }
- exit(0);
-}
-
-int
-tinytest_main(int c, const char **v, struct testgroup_t *groups)
-{
- int i, j, n=0;
-
-#ifdef _WIN32
- const char *sp = strrchr(v[0], '.');
- const char *extension = "";
- if (!sp || stricmp(sp, ".exe"))
- extension = ".exe"; /* Add an exe so CreateProcess will work */
- snprintf(commandname, sizeof(commandname), "%s%s", v[0], extension);
- commandname[MAX_PATH]='\0';
-#endif
- for (i=1; i<c; ++i) {
- if (v[i][0] == '-') {
- if (!strcmp(v[i], "--RUNNING-FORKED")) {
- opt_forked = 1;
- } else if (!strcmp(v[i], "--no-fork")) {
- opt_nofork = 1;
- } else if (!strcmp(v[i], "--quiet")) {
- opt_verbosity = -1;
- verbosity_flag = "--quiet";
- } else if (!strcmp(v[i], "--verbose")) {
- opt_verbosity = 2;
- verbosity_flag = "--verbose";
- } else if (!strcmp(v[i], "--terse")) {
- opt_verbosity = 0;
- verbosity_flag = "--terse";
- } else if (!strcmp(v[i], "--help")) {
- usage(groups, 0);
- } else if (!strcmp(v[i], "--list-tests")) {
- usage(groups, 1);
- } else {
- printf("Unknown option %s. Try --help\n",v[i]);
- return -1;
- }
- } else {
- const char *test = v[i];
- int flag = TT_ENABLED_;
- if (test[0] == ':') {
- ++test;
- flag = TT_SKIP;
- } else {
- ++n;
- }
- if (!tinytest_set_flag_(groups, test, flag)) {
- printf("No such test as %s!\n", v[i]);
- return -1;
- }
- }
- }
- if (!n)
- tinytest_set_flag_(groups, "..", TT_ENABLED_);
-
- setvbuf(stdout, NULL, _IONBF, 0);
-
- ++in_tinytest_main;
- for (i=0; groups[i].prefix; ++i)
- for (j=0; groups[i].cases[j].name; ++j)
- if (groups[i].cases[j].flags & TT_ENABLED_)
- testcase_run_one(&groups[i],
- &groups[i].cases[j]);
-
- --in_tinytest_main;
-
- if (opt_verbosity==0)
- puts("");
-
- if (n_bad)
- printf("%d/%d TESTS FAILED. (%d skipped)\n", n_bad,
- n_bad+n_ok,n_skipped);
- else if (opt_verbosity >= 1)
- printf("%d tests ok. (%d skipped)\n", n_ok, n_skipped);
-
- return (n_bad == 0) ? 0 : 1;
-}
-
-int
-tinytest_get_verbosity_(void)
-{
- return opt_verbosity;
-}
-
-void
-tinytest_set_test_failed_(void)
-{
- if (opt_verbosity <= 0 && cur_test_name) {
- if (opt_verbosity==0) puts("");
- printf("%s%s: ", cur_test_prefix, cur_test_name);
- cur_test_name = NULL;
- }
- cur_test_outcome = 0;
-}
-
-void
-tinytest_set_test_skipped_(void)
-{
- if (cur_test_outcome==OK)
- cur_test_outcome = SKIP;
-}
-
diff --git a/src/test/tinytest.h b/src/test/tinytest.h
deleted file mode 100644
index bcac9f079..000000000
--- a/src/test/tinytest.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* tinytest.h -- Copyright 2009-2012 Nick Mathewson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TINYTEST_H_INCLUDED_
-#define TINYTEST_H_INCLUDED_
-
-/** Flag for a test that needs to run in a subprocess. */
-#define TT_FORK (1<<0)
-/** Runtime flag for a test we've decided to skip. */
-#define TT_SKIP (1<<1)
-/** Internal runtime flag for a test we've decided to run. */
-#define TT_ENABLED_ (1<<2)
-/** If you add your own flags, make them start at this point. */
-#define TT_FIRST_USER_FLAG (1<<3)
-
-typedef void (*testcase_fn)(void *);
-
-struct testcase_t;
-
-/** Functions to initialize/teardown a structure for a testcase. */
-struct testcase_setup_t {
- /** Return a new structure for use by a given testcase. */
- void *(*setup_fn)(const struct testcase_t *);
- /** Clean/free a structure from setup_fn. Return 1 if ok, 0 on err. */
- int (*cleanup_fn)(const struct testcase_t *, void *);
-};
-
-/** A single test-case that you can run. */
-struct testcase_t {
- const char *name; /**< An identifier for this case. */
- testcase_fn fn; /**< The function to run to implement this case. */
- unsigned long flags; /**< Bitfield of TT_* flags. */
- const struct testcase_setup_t *setup; /**< Optional setup/cleanup fns*/
- void *setup_data; /**< Extra data usable by setup function */
-};
-#define END_OF_TESTCASES { NULL, NULL, 0, NULL, NULL }
-
-/** A group of tests that are selectable together. */
-struct testgroup_t {
- const char *prefix; /**< Prefix to prepend to testnames. */
- struct testcase_t *cases; /** Array, ending with END_OF_TESTCASES */
-};
-#define END_OF_GROUPS { NULL, NULL}
-
-/** Implementation: called from a test to indicate failure, before logging. */
-void tinytest_set_test_failed_(void);
-/** Implementation: called from a test to indicate that we're skipping. */
-void tinytest_set_test_skipped_(void);
-/** Implementation: return 0 for quiet, 1 for normal, 2 for loud. */
-int tinytest_get_verbosity_(void);
-/** Implementation: Set a flag on tests matching a name; returns number
- * of tests that matched. */
-int tinytest_set_flag_(struct testgroup_t *, const char *, unsigned long);
-
-/** Set all tests in 'groups' matching the name 'named' to be skipped. */
-#define tinytest_skip(groups, named) \
- tinytest_set_flag_(groups, named, TT_SKIP)
-
-/** Run a single testcase in a single group. */
-int testcase_run_one(const struct testgroup_t *,const struct testcase_t *);
-/** Run a set of testcases from an END_OF_GROUPS-terminated array of groups,
- as selected from the command line. */
-int tinytest_main(int argc, const char **argv, struct testgroup_t *groups);
-
-#endif
diff --git a/src/test/tinytest_demo.c b/src/test/tinytest_demo.c
deleted file mode 100644
index be95ce4c1..000000000
--- a/src/test/tinytest_demo.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* tinytest_demo.c -- Copyright 2009-2012 Nick Mathewson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-/* Welcome to the example file for tinytest! I'll show you how to set up
- * some simple and not-so-simple testcases. */
-
-/* Make sure you include these headers. */
-#include "tinytest.h"
-#include "tinytest_macros.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-/* ============================================================ */
-
-/* First, let's see if strcmp is working. (All your test cases should be
- * functions declared to take a single void * as an argument.) */
-void
-test_strcmp(void *data)
-{
- (void)data; /* This testcase takes no data. */
-
- /* Let's make sure the empty string is equal to itself */
- if (strcmp("","")) {
- /* This macro tells tinytest to stop the current test
- * and go straight to the "end" label. */
- tt_abort_msg("The empty string was not equal to itself");
- }
-
- /* Pretty often, calling tt_abort_msg to indicate failure is more
- heavy-weight than you want. Instead, just say: */
- tt_assert(strcmp("testcase", "testcase") == 0);
-
- /* Occasionally, you don't want to stop the current testcase just
- because a single assertion has failed. In that case, use
- tt_want: */
- tt_want(strcmp("tinytest", "testcase") > 0);
-
- /* You can use the tt_*_op family of macros to compare values and to
- fail unless they have the relationship you want. They produce
- more useful output than tt_assert, since they display the actual
- values of the failing things.
-
- Fail unless strcmp("abc, "abc") == 0 */
- tt_int_op(strcmp("abc", "abc"), ==, 0);
-
- /* Fail unless strcmp("abc, "abcd") is less than 0 */
- tt_int_op(strcmp("abc", "abcd"), < , 0);
-
- /* Incidentally, there's a test_str_op that uses strcmp internally. */
- tt_str_op("abc", <, "abcd");
-
-
- /* Every test-case function needs to finish with an "end:"
- label and (optionally) code to clean up local variables. */
- end:
- ;
-}
-
-/* ============================================================ */
-
-/* Now let's mess with setup and teardown functions! These are handy if
- you have a bunch of tests that all need a similar environment, and you
- want to reconstruct that environment freshly for each one. */
-
-/* First you declare a type to hold the environment info, and functions to
- set it up and tear it down. */
-struct data_buffer {
- /* We're just going to have couple of character buffer. Using
- setup/teardown functions is probably overkill for this case.
-
- You could also do file descriptors, complicated handles, temporary
- files, etc. */
- char buffer1[512];
- char buffer2[512];
-};
-/* The setup function needs to take a const struct testcase_t and return
- void* */
-void *
-setup_data_buffer(const struct testcase_t *testcase)
-{
- struct data_buffer *db = malloc(sizeof(struct data_buffer));
-
- /* If you had a complicated set of setup rules, you might behave
- differently here depending on testcase->flags or
- testcase->setup_data or even or testcase->name. */
-
- /* Returning a NULL here would mean that we couldn't set up for this
- test, so we don't need to test db for null. */
- return db;
-}
-/* The clean function deallocates storage carefully and returns true on
- success. */
-int
-clean_data_buffer(const struct testcase_t *testcase, void *ptr)
-{
- struct data_buffer *db = ptr;
-
- if (db) {
- free(db);
- return 1;
- }
- return 0;
-}
-/* Finally, declare a testcase_setup_t with these functions. */
-struct testcase_setup_t data_buffer_setup = {
- setup_data_buffer, clean_data_buffer
-};
-
-
-/* Now let's write our test. */
-void
-test_memcpy(void *ptr)
-{
- /* This time, we use the argument. */
- struct data_buffer *db = ptr;
-
- /* We'll also introduce a local variable that might need cleaning up. */
- char *mem = NULL;
-
- /* Let's make sure that memcpy does what we'd like. */
- strcpy(db->buffer1, "String 0");
- memcpy(db->buffer2, db->buffer1, sizeof(db->buffer1));
- tt_str_op(db->buffer1, ==, db->buffer2);
-
- /* Now we've allocated memory that's referenced by a local variable.
- The end block of the function will clean it up. */
- mem = strdup("Hello world.");
- tt_assert(mem);
-
- /* Another rather trivial test. */
- tt_str_op(db->buffer1, !=, mem);
-
- end:
- /* This time our end block has something to do. */
- if (mem)
- free(mem);
-}
-
-/* ============================================================ */
-
-/* Now we need to make sure that our tests get invoked. First, you take
- a bunch of related tests and put them into an array of struct testcase_t.
-*/
-
-struct testcase_t demo_tests[] = {
- /* Here's a really simple test: it has a name you can refer to it
- with, and a function to invoke it. */
- { "strcmp", test_strcmp, },
-
- /* The second test has a flag, "TT_FORK", to make it run in a
- subprocess, and a pointer to the testcase_setup_t that configures
- its environment. */
- { "memcpy", test_memcpy, TT_FORK, &data_buffer_setup },
-
- /* The array has to end with END_OF_TESTCASES. */
- END_OF_TESTCASES
-};
-
-/* Next, we make an array of testgroups. This is mandatory. Unlike more
- heavy-duty testing frameworks, groups can't nest. */
-struct testgroup_t groups[] = {
-
- /* Every group has a 'prefix', and an array of tests. That's it. */
- { "demo/", demo_tests },
-
- END_OF_GROUPS
-};
-
-
-int
-main(int c, const char **v)
-{
- /* Finally, just call tinytest_main(). It lets you specify verbose
- or quiet output with --verbose and --quiet. You can list
- specific tests:
-
- tinytest-demo demo/memcpy
-
- or use a ..-wildcard to select multiple tests with a common
- prefix:
-
- tinytest-demo demo/..
-
- If you list no tests, you get them all by default, so that
- "tinytest-demo" and "tinytest-demo .." mean the same thing.
-
- */
- return tinytest_main(c, v, groups);
-}
diff --git a/src/test/tinytest_macros.h b/src/test/tinytest_macros.h
deleted file mode 100644
index 9ff69b1d5..000000000
--- a/src/test/tinytest_macros.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/* tinytest_macros.h -- Copyright 2009-2012 Nick Mathewson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TINYTEST_MACROS_H_INCLUDED_
-#define TINYTEST_MACROS_H_INCLUDED_
-
-/* Helpers for defining statement-like macros */
-#define TT_STMT_BEGIN do {
-#define TT_STMT_END } while (0)
-
-/* Redefine this if your test functions want to abort with something besides
- * "goto end;" */
-#ifndef TT_EXIT_TEST_FUNCTION
-#define TT_EXIT_TEST_FUNCTION TT_STMT_BEGIN goto end; TT_STMT_END
-#endif
-
-/* Redefine this if you want to note success/failure in some different way. */
-#ifndef TT_DECLARE
-#define TT_DECLARE(prefix, args) \
- TT_STMT_BEGIN \
- printf("\n %s %s:%d: ",prefix,__FILE__,__LINE__); \
- printf args ; \
- TT_STMT_END
-#endif
-
-/* Announce a failure. Args are parenthesized printf args. */
-#define TT_GRIPE(args) TT_DECLARE("FAIL", args)
-
-/* Announce a non-failure if we're verbose. */
-#define TT_BLATHER(args) \
- TT_STMT_BEGIN \
- if (tinytest_get_verbosity_()>1) TT_DECLARE(" OK", args); \
- TT_STMT_END
-
-#define TT_DIE(args) \
- TT_STMT_BEGIN \
- tinytest_set_test_failed_(); \
- TT_GRIPE(args); \
- TT_EXIT_TEST_FUNCTION; \
- TT_STMT_END
-
-#define TT_FAIL(args) \
- TT_STMT_BEGIN \
- tinytest_set_test_failed_(); \
- TT_GRIPE(args); \
- TT_STMT_END
-
-/* Fail and abort the current test for the reason in msg */
-#define tt_abort_printf(msg) TT_DIE(msg)
-#define tt_abort_perror(op) TT_DIE(("%s: %s [%d]",(op),strerror(errno), errno))
-#define tt_abort_msg(msg) TT_DIE(("%s", msg))
-#define tt_abort() TT_DIE(("%s", "(Failed.)"))
-
-/* Fail but do not abort the current test for the reason in msg. */
-#define tt_failprint_f(msg) TT_FAIL(msg)
-#define tt_fail_perror(op) TT_FAIL(("%s: %s [%d]",(op),strerror(errno), errno))
-#define tt_fail_msg(msg) TT_FAIL(("%s", msg))
-#define tt_fail() TT_FAIL(("%s", "(Failed.)"))
-
-/* End the current test, and indicate we are skipping it. */
-#define tt_skip() \
- TT_STMT_BEGIN \
- tinytest_set_test_skipped_(); \
- TT_EXIT_TEST_FUNCTION; \
- TT_STMT_END
-
-#define tt_want_(b, msg, fail) \
- TT_STMT_BEGIN \
- if (!(b)) { \
- tinytest_set_test_failed_(); \
- TT_GRIPE(("%s",msg)); \
- fail; \
- } else { \
- TT_BLATHER(("%s",msg)); \
- } \
- TT_STMT_END
-
-/* Assert b, but do not stop the test if b fails. Log msg on failure. */
-#define tt_want_msg(b, msg) \
- tt_want_(b, msg, );
-
-/* Assert b and stop the test if b fails. Log msg on failure. */
-#define tt_assert_msg(b, msg) \
- tt_want_(b, msg, TT_EXIT_TEST_FUNCTION);
-
-/* Assert b, but do not stop the test if b fails. */
-#define tt_want(b) tt_want_msg( (b), "want("#b")")
-/* Assert b, and stop the test if b fails. */
-#define tt_assert(b) tt_assert_msg((b), "assert("#b")")
-
-#define tt_assert_test_fmt_type(a,b,str_test,type,test,printf_type,printf_fmt, \
- setup_block,cleanup_block,die_on_fail) \
- TT_STMT_BEGIN \
- type val1_ = (type)(a); \
- type val2_ = (type)(b); \
- int tt_status_ = (test); \
- if (!tt_status_ || tinytest_get_verbosity_()>1) { \
- printf_type print_; \
- printf_type print1_; \
- printf_type print2_; \
- type value_ = val1_; \
- setup_block; \
- print1_ = print_; \
- value_ = val2_; \
- setup_block; \
- print2_ = print_; \
- TT_DECLARE(tt_status_?" OK":"FAIL", \
- ("assert(%s): "printf_fmt" vs "printf_fmt, \
- str_test, print1_, print2_)); \
- print_ = print1_; \
- cleanup_block; \
- print_ = print2_; \
- cleanup_block; \
- if (!tt_status_) { \
- tinytest_set_test_failed_(); \
- die_on_fail ; \
- } \
- } \
- TT_STMT_END
-
-#define tt_assert_test_type(a,b,str_test,type,test,fmt,die_on_fail) \
- tt_assert_test_fmt_type(a,b,str_test,type,test,type,fmt, \
- {print_=value_;},{},die_on_fail)
-
-/* Helper: assert that a op b, when cast to type. Format the values with
- * printf format fmt on failure. */
-#define tt_assert_op_type(a,op,b,type,fmt) \
- tt_assert_test_type(a,b,#a" "#op" "#b,type,(val1_ op val2_),fmt, \
- TT_EXIT_TEST_FUNCTION)
-
-#define tt_int_op(a,op,b) \
- tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_), \
- "%ld",TT_EXIT_TEST_FUNCTION)
-
-#define tt_uint_op(a,op,b) \
- tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \
- (val1_ op val2_),"%lu",TT_EXIT_TEST_FUNCTION)
-
-#define tt_ptr_op(a,op,b) \
- tt_assert_test_type(a,b,#a" "#op" "#b,void*, \
- (val1_ op val2_),"%p",TT_EXIT_TEST_FUNCTION)
-
-#define tt_str_op(a,op,b) \
- tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \
- (strcmp(val1_,val2_) op 0),"<%s>",TT_EXIT_TEST_FUNCTION)
-
-#define tt_want_int_op(a,op,b) \
- tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_),"%ld",(void)0)
-
-#define tt_want_uint_op(a,op,b) \
- tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \
- (val1_ op val2_),"%lu",(void)0)
-
-#define tt_want_ptr_op(a,op,b) \
- tt_assert_test_type(a,b,#a" "#op" "#b,void*, \
- (val1_ op val2_),"%p",(void)0)
-
-#define tt_want_str_op(a,op,b) \
- tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \
- (strcmp(val1_,val2_) op 0),"<%s>",(void)0)
-
-#endif