Quellcode durchsuchen

Merge remote-tracking branch 'public/fancy_test_tricks'

Conflicts:
	src/common/include.am

Conflict was from adding testsupport.h near where sandbox.h had
already been added.
Nick Mathewson vor 11 Jahren
Ursprung
Commit
c0391bae75
63 geänderte Dateien mit 566 neuen und 150 gelöschten Zeilen
  1. 6 0
      .gitignore
  2. 8 0
      Makefile.am
  3. 27 0
      changes/fancy_testing
  4. 15 1
      configure.ac
  5. 17 0
      contrib/cov-diff
  6. 13 0
      contrib/coverage
  7. 3 3
      src/common/crypto.c
  8. 3 4
      src/common/crypto.h
  9. 1 1
      src/common/crypto_curve25519.c
  10. 3 2
      src/common/crypto_curve25519.h
  11. 0 1
      src/common/crypto_format.c
  12. 31 4
      src/common/include.am
  13. 4 0
      src/common/log.c
  14. 80 0
      src/common/testsupport.h
  15. 0 6
      src/common/torlog.h
  16. 0 3
      src/common/tortls.c
  17. 2 2
      src/common/util.c
  18. 3 2
      src/common/util.h
  19. 1 1
      src/or/addressmap.c
  20. 4 2
      src/or/addressmap.h
  21. 1 1
      src/or/buffers.c
  22. 3 1
      src/or/buffers.h
  23. 2 3
      src/or/circuitlist.c
  24. 6 0
      src/or/circuitlist.h
  25. 5 5
      src/or/circuitmux.c
  26. 5 3
      src/or/circuitmux.h
  27. 17 4
      src/or/circuitstats.c
  28. 11 10
      src/or/circuitstats.h
  29. 0 2
      src/or/config.c
  30. 0 3
      src/or/config.h
  31. 2 2
      src/or/connection_edge.c
  32. 4 2
      src/or/connection_edge.h
  33. 2 2
      src/or/control.c
  34. 2 2
      src/or/control.h
  35. 9 9
      src/or/dirserv.c
  36. 13 10
      src/or/dirserv.h
  37. 2 2
      src/or/dirvote.c
  38. 4 2
      src/or/dirvote.h
  39. 3 3
      src/or/geoip.c
  40. 5 3
      src/or/geoip.h
  41. 2 0
      src/or/hibernate.c
  42. 2 0
      src/or/hibernate.h
  43. 28 2
      src/or/include.am
  44. 4 5
      src/or/main.c
  45. 0 4
      src/or/main.h
  46. 0 1
      src/or/ntmain.c
  47. 1 1
      src/or/relay.c
  48. 3 2
      src/or/relay.h
  49. 2 2
      src/or/replaycache.c
  50. 2 2
      src/or/replaycache.h
  51. 1 1
      src/or/router.c
  52. 3 1
      src/or/router.h
  53. 2 2
      src/or/routerlist.c
  54. 6 3
      src/or/routerlist.h
  55. 5 5
      src/or/transports.c
  56. 5 5
      src/or/transports.h
  57. 0 1
      src/test/bench.c
  58. 12 5
      src/test/include.am
  59. 2 1
      src/test/test.c
  60. 168 0
      src/test/test_circuitlist.c
  61. 1 2
      src/test/test_crypto.c
  62. 0 2
      src/tools/tor-checkkey.c
  63. 0 2
      src/tools/tor-gencert.c

+ 6 - 0
.gitignore

@@ -128,10 +128,13 @@
 /src/common/Makefile.in
 /src/common/common_sha1.i
 /src/common/libor.a
+/src/common/libor-testing.a
 /src/common/libor.lib
 /src/common/libor-crypto.a
+/src/common/libor-crypto-testing.a
 /src/common/libor-crypto.lib
 /src/common/libor-event.a
+/src/common/libor-event-testing.a
 /src/common/libor-event.lib
 /src/common/libcurve25519_donna.a
 /src/common/libcurve25519_donna.lib
@@ -149,7 +152,10 @@
 /src/or/or_sha1.i
 /src/or/tor
 /src/or/tor.exe
+/src/or/tor-cov
+/src/or/tor-cov.exe
 /src/or/libtor.a
+/src/or/libtor-testing.a
 /src/or/libtor.lib
 
 # /src/test

+ 8 - 0
Makefile.am

@@ -32,6 +32,12 @@ EXTRA_DIST+= \
 	README						\
 	ReleaseNotes
 
+if COVERAGE_ENABLED
+TEST_CFLAGS=-fno-inline -fprofile-arcs -ftest-coverage
+else
+TEST_CFLAGS=
+endif
+
 #install-data-local:
 #	$(INSTALL) -m 755 -d $(LOCALSTATEDIR)/lib/tor
 
@@ -89,3 +95,5 @@ version:
 	   (cd "$(top_srcdir)" && git rev-parse --short=16 HEAD); \
 	fi
 
+mostlyclean-local:
+	rm -f src/*/*.gc{da,no}

+ 27 - 0
changes/fancy_testing

@@ -0,0 +1,27 @@
+  o Build features:
+
+    - Tor now builds each source file in two modes: a mode that avoids
+      exposing identifiers needlessly, and another mode that exposes
+      more identifiers for testing. This lets the compiler do better at
+      optimizing the production code, while enabling us to take more
+      radical measures to let the unit tests test things.
+
+    - The production builds no longer include functions used only
+      in the unit tests; all functions exposed from a module for
+      unit-testing only are now static in production builds.
+
+    - Add an --enable-coverage configuration option to make the unit
+      tests (and a new src/or/tor-cov target) to build with gcov test
+      coverage support.
+
+  o Testing:
+
+    - We now have rudimentary function mocking support that our unit
+      tests can use to test functions in isolation. Function mocking
+      lets the tests temporarily replace a function's dependencies with
+      stub functions, so that the tests can check the function without
+      invoking the other functions it calls.
+
+    - Add more unit tests for the <circid,channel>->circuit map, and
+      the destroy-cell-tracking code to fix bug 7912.
+

+ 15 - 1
configure.ac

@@ -39,6 +39,15 @@ AC_ARG_ENABLE(static-tor,
    AS_HELP_STRING(--enable-static-tor, Create an entirely static Tor binary. Requires --with-openssl-dir and --with-libevent-dir and --with-zlib-dir))
 AC_ARG_ENABLE(curve25519,
    AS_HELP_STRING(--disable-curve25519, Build Tor with no curve25519 elliptic-curve crypto support))
+AC_ARG_ENABLE(unittests,
+   AS_HELP_STRING(--disable-unittests, [Don't build unit tests for Tor. Risky!]))
+AC_ARG_ENABLE(coverage,
+   AS_HELP_STRING(--enable-coverage, [Enable coverage support in the unit-test build]))
+
+AM_CONDITIONAL(UNITTESTS_ENABLED, test x$enable_unittests != xno)
+AM_CONDITIONAL(COVERAGE_ENABLED, test x$enable_coverage = xyes)
+
+echo "COVERAGE: $enable_coverage"
 
 if test "$enable_static_tor" = "yes"; then
   enable_static_libevent="yes";
@@ -1459,7 +1468,12 @@ if test x$enable_gcc_warnings = xyes || test x$enable_gcc_warnings_advisory = xy
 # CFLAGS="$CFLAGS -Winline"
 fi
 
-
+if test "$enable_coverage" = yes && test "$have_clang" = "no"; then
+   case "$host_os" in
+    darwin*)
+      AC_MSG_WARN([Tried to enable coverage on OSX without using the clang compiler. This might not work! If coverage fails, use CC=clang when configuring with --enable-profiling.])
+   esac
+fi
 
 CPPFLAGS="$CPPFLAGS $TOR_CPPFLAGS_libevent $TOR_CPPFLAGS_openssl $TOR_CPPFLAGS_zlib"
 

+ 17 - 0
contrib/cov-diff

@@ -0,0 +1,17 @@
+#!/bin/sh
+# Copyright 2013  The Tor Project, Inc.
+# See LICENSE for licensing information.
+
+# cov-diff -- compare two directories full of gcov files.
+
+DIRA="$1"
+DIRB="$2"
+
+for A in $DIRA/*; do
+  B=$DIRB/`basename $A`
+  perl -pe 's/^\s*\d+:/        1:/; s/^([^:]+:)[\d\s]+:/$1/;' "$A" > "$A.tmp"
+  perl -pe 's/^\s*\d+:/        1:/; s/^([^:]+:)[\d\s]+:/$1/;' "$B" > "$B.tmp"
+  diff -u "$A.tmp" "$B.tmp"
+  rm "$A.tmp" "$B.tmp"
+done
+

+ 13 - 0
contrib/coverage

@@ -0,0 +1,13 @@
+#!/bin/sh
+# Copyright 2013  The Tor Project, Inc.
+# See LICENSE for licensing information.
+
+# coverage -- run gcov on the appropriate set of object files to extract
+# coverage information.
+
+for fn in src/{or,common}/*.c; do
+    BN=`basename $fn`
+    DN=`dirname $fn`
+    F=`echo $BN | sed -e 's/\.c$//;'`
+    gcov -o $DN/src_*$F.o $fn
+done

+ 3 - 3
src/common/crypto.c

@@ -1232,8 +1232,8 @@ crypto_pk_get_all_digests(crypto_pk_t *pk, digests_t *digests_out)
 
 /** Copy <b>in</b> to the <b>outlen</b>-byte buffer <b>out</b>, adding spaces
  * every four spaces. */
-/* static */ void
-add_spaces_to_fp(char *out, size_t outlen, const char *in)
+void
+crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in)
 {
   int n = 0;
   char *end = out+outlen;
@@ -1270,7 +1270,7 @@ crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out, int add_space)
   }
   base16_encode(hexdigest,sizeof(hexdigest),digest,DIGEST_LEN);
   if (add_space) {
-    add_spaces_to_fp(fp_out, FINGERPRINT_LEN+1, hexdigest);
+    crypto_add_spaces_to_fp(fp_out, FINGERPRINT_LEN+1, hexdigest);
   } else {
     strncpy(fp_out, hexdigest, HEX_DIGEST_LEN+1);
   }

+ 3 - 4
src/common/crypto.h

@@ -15,6 +15,7 @@
 
 #include <stdio.h>
 #include "torint.h"
+#include "testsupport.h"
 
 /*
   Macro to create an arbitrary OpenSSL version number as used by
@@ -283,7 +284,6 @@ void secret_to_key(char *key_out, size_t key_out_len, const char *secret,
 /** OpenSSL-based utility functions. */
 void memwipe(void *mem, uint8_t byte, size_t sz);
 
-#ifdef CRYPTO_PRIVATE
 /* Prototypes for private functions only used by tortls.c, crypto.c, and the
  * unit tests. */
 struct rsa_st;
@@ -294,9 +294,8 @@ crypto_pk_t *crypto_new_pk_from_rsa_(struct rsa_st *rsa);
 struct evp_pkey_st *crypto_pk_get_evp_pkey_(crypto_pk_t *env,
                                                 int private);
 struct dh_st *crypto_dh_get_dh_(crypto_dh_t *dh);
-/* Prototypes for private functions only used by crypto.c and test.c*/
-void add_spaces_to_fp(char *out, size_t outlen, const char *in);
-#endif
+
+void crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in);
 
 #endif
 

+ 1 - 1
src/common/crypto_curve25519.c

@@ -29,7 +29,7 @@ int curve25519_donna(uint8_t *mypublic,
 #endif
 #endif
 
-int
+STATIC int
 curve25519_impl(uint8_t *output, const uint8_t *secret,
                 const uint8_t *basepoint)
 {

+ 3 - 2
src/common/crypto_curve25519.h

@@ -4,6 +4,7 @@
 #ifndef TOR_CRYPTO_CURVE25519_H
 #define TOR_CRYPTO_CURVE25519_H
 
+#include "testsupport.h"
 #include "torint.h"
 
 /** Length of a curve25519 public key when encoded. */
@@ -52,8 +53,8 @@ int curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out,
                                       const char *fname);
 
 #ifdef CRYPTO_CURVE25519_PRIVATE
-int curve25519_impl(uint8_t *output, const uint8_t *secret,
-                    const uint8_t *basepoint);
+STATIC int curve25519_impl(uint8_t *output, const uint8_t *secret,
+                           const uint8_t *basepoint);
 #endif
 #endif
 

+ 0 - 1
src/common/crypto_format.c

@@ -3,7 +3,6 @@
 
 /* Formatting and parsing code for crypto-related data structures. */
 
-#define CRYPTO_CURVE25519_PRIVATE
 #include "orconfig.h"
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>

+ 31 - 4
src/common/include.am

@@ -1,5 +1,15 @@
 
-noinst_LIBRARIES+= src/common/libor.a src/common/libor-crypto.a src/common/libor-event.a
+noinst_LIBRARIES += \
+	src/common/libor.a \
+	src/common/libor-crypto.a \
+	src/common/libor-event.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += \
+	src/common/libor-testing.a \
+	src/common/libor-crypto-testing.a \
+	src/common/libor-event-testing.a
+endif
 
 EXTRA_DIST+= \
   src/common/common_sha1.i	\
@@ -38,7 +48,7 @@ if CURVE25519_ENABLED
 libcrypto_extra_source=src/common/crypto_curve25519.c
 endif
 
-src_common_libor_a_SOURCES = \
+LIBOR_A_SOURCES = \
   src/common/address.c					\
   src/common/compat.c					\
   src/common/container.c				\
@@ -52,7 +62,7 @@ src_common_libor_a_SOURCES = \
   src/common/sandbox.c					\
   $(libor_extra_source)
 
-src_common_libor_crypto_a_SOURCES = \
+LIBOR_CRYPTO_A_SOURCES = \
   src/common/aes.c		\
   src/common/crypto.c		\
   src/common/crypto_format.c	\
@@ -60,7 +70,23 @@ src_common_libor_crypto_a_SOURCES = \
   src/common/tortls.c		\
   $(libcrypto_extra_source)
 
-src_common_libor_event_a_SOURCES = src/common/compat_libevent.c
+LIBOR_EVENT_A_SOURCES = src/common/compat_libevent.c
+
+src_common_libor_a_SOURCES = $(LIBOR_A_SOURCES)
+src_common_libor_crypto_a_SOURCES = $(LIBOR_CRYPTO_A_SOURCES)
+src_common_libor_event_a_SOURCES = $(LIBOR_EVENT_A_SOURCES)
+
+src_common_libor_testing_a_SOURCES = $(LIBOR_A_SOURCES)
+src_common_libor_crypto_testing_a_SOURCES = $(LIBOR_CRYPTO_A_SOURCES)
+src_common_libor_event_testing_a_SOURCES = $(LIBOR_EVENT_A_SOURCES)
+
+src_common_libor_testing_a_CPPFLAGS = -DTOR_UNIT_TESTS $(AM_CPPFLAGS)
+src_common_libor_crypto_testing_a_CPPFLAGS = -DTOR_UNIT_TESTS $(AM_CPPFLAGS)
+src_common_libor_event_testing_a_CPPFLAGS = -DTOR_UNIT_TESTS $(AM_CPPFLAGS)
+src_common_libor_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+src_common_libor_crypto_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+src_common_libor_event_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
 
 COMMONHEADERS = \
   src/common/address.h				\
@@ -76,6 +102,7 @@ COMMONHEADERS = \
   src/common/mempool.h				\
   src/common/procmon.h				\
   src/common/sandbox.h				\
+  src/common/testsupport.h			\
   src/common/torgzip.h				\
   src/common/torint.h				\
   src/common/torlog.h				\

+ 4 - 0
src/common/log.c

@@ -36,6 +36,10 @@
 #include "torlog.h"
 #include "container.h"
 
+/** Given a severity, yields an index into log_severity_list_t.masks to use
+ * for that severity. */
+#define SEVERITY_MASK_IDX(sev) ((sev) - LOG_ERR)
+
 /** @{ */
 /** The string we stick at the end of a log message when it is too long,
  * and its length. */

+ 80 - 0
src/common/testsupport.h

@@ -0,0 +1,80 @@
+/* Copyright (c) 2013, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_TESTSUPPORT_H
+#define TOR_TESTSUPPORT_H
+
+#ifdef TOR_UNIT_TESTS
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+/** Quick and dirty macros to implement test mocking.
+ *
+ * To use them, suppose that you have a function you'd like to mock
+ * with the signature "void writebuf(size_t n, char *buf)".  You can then
+ * declare the function as:
+ *
+ *     MOCK_DECL(void, writebuf, (size_t n, char *buf));
+ *
+ * and implement it as:
+ *
+ *     MOCK_IMPL(void
+ *     writebuf,(size_t n, char *buf)
+ *     {
+ *          ...
+ *     }
+ *
+ * For the non-testing build, this will expand simply into:
+ *
+ *     void writebuf(size_t n, char *buf);
+ *     void
+ *     writebuf(size_t n, char *buf)
+ *     {
+ *         ...
+ *     }
+ *
+ * But for the testing case, it will expand into:
+ *
+ *     void writebuf__real(size_t n, char *buf);
+ *     extern void (*writebuf)(size_t n, char *buf);
+ *
+ *     void (*writebuf)(size_t n, char *buf) = writebuf__real;
+ *     void
+ *     writebuf__real(size_t n, char *buf)
+ *     {
+ *         ...
+ *     }
+ *
+ * This is not a great mocking system!  It is deliberately "the simplest
+ * thing that could work", and pays for its simplicity in its lack of
+ * features, and in its uglification of the Tor code.  Replacing it with
+ * something clever would be a fine thing.
+ *
+ * @{ */
+#ifdef TOR_UNIT_TESTS
+#define MOCK_DECL(rv, funcname, arglist)     \
+  rv funcname ##__real arglist;              \
+  extern rv(*funcname) arglist
+#define MOCK_IMPL(rv, funcname, arglist)     \
+  rv(*funcname) arglist = funcname ##__real; \
+  rv funcname ##__real arglist
+#define MOCK(func, replacement)                 \
+  do {                                          \
+    (func) = (replacement);                     \
+  } while (0)
+#define UNMOCK(func)                            \
+  do {                                          \
+    func = func ##__real;                       \
+  } while (0)
+#else
+#define MOCK_DECL(rv, funcname, arglist) \
+  rv funcname arglist
+#define MOCK_IMPL(rv, funcname, arglist) \
+  rv funcname arglist
+#endif
+/** @} */
+
+#endif
+

+ 0 - 6
src/common/torlog.h

@@ -114,12 +114,6 @@ typedef struct log_severity_list_t {
   log_domain_mask_t masks[LOG_DEBUG-LOG_ERR+1];
 } log_severity_list_t;
 
-#ifdef LOG_PRIVATE
-/** Given a severity, yields an index into log_severity_list_t.masks to use
- * for that severity. */
-#define SEVERITY_MASK_IDX(sev) ((sev) - LOG_ERR)
-#endif
-
 /** Callback type used for add_callback_log. */
 typedef void (*log_callback)(int severity, uint32_t domain, const char *msg);
 

+ 0 - 3
src/common/tortls.c

@@ -48,9 +48,6 @@
 #include "compat_libevent.h"
 #endif
 
-#define CRYPTO_PRIVATE /* to import prototypes from crypto.h */
-#define TORTLS_PRIVATE
-
 #include "crypto.h"
 #include "tortls.h"
 #include "util.h"

+ 2 - 2
src/common/util.c

@@ -3402,7 +3402,7 @@ tor_join_win_cmdline(const char *argv[])
  * function; it's designed to be used in code paths where you can't call
  * arbitrary C functions.
  */
-int
+STATIC int
 format_hex_number_for_helper_exit_status(unsigned int x, char *buf,
                                          int max_len)
 {
@@ -3458,7 +3458,7 @@ format_hex_number_for_helper_exit_status(unsigned int x, char *buf,
  * On success return the number of characters added to hex_errno, not counting
  * the terminating NUL; return -1 on error.
  */
-int
+STATIC int
 format_helper_exit_status(unsigned char child_state, int saved_errno,
                           char *hex_errno)
 {

+ 3 - 2
src/common/util.h

@@ -15,6 +15,7 @@
 #include "torint.h"
 #include "compat.h"
 #include "di_ops.h"
+#include "testsupport.h"
 #include <stdio.h>
 #include <stdlib.h>
 #ifdef _WIN32
@@ -520,9 +521,9 @@ int32_t tor_weak_random_range(tor_weak_rng_t *rng, int32_t top);
 #ifdef UTIL_PRIVATE
 /* Prototypes for private functions only used by util.c (and unit tests) */
 
-int format_hex_number_for_helper_exit_status(unsigned int x, char *buf,
+STATIC int format_hex_number_for_helper_exit_status(unsigned int x, char *buf,
                                              int max_len);
-int format_helper_exit_status(unsigned char child_state,
+STATIC int format_helper_exit_status(unsigned char child_state,
                               int saved_errno, char *hex_errno);
 
 /* Space for hex values of child state, a slash, saved_errno (with

+ 1 - 1
src/or/addressmap.c

@@ -798,7 +798,7 @@ address_is_in_virtual_range(const char *address)
 /** Return a random address conforming to the virtual address configuration
  * in <b>conf</b>.
  */
-/* private */ void
+STATIC void
 get_random_virtual_addr(const virtual_addr_conf_t *conf, tor_addr_t *addr_out)
 {
   uint8_t tmp[4];

+ 4 - 2
src/or/addressmap.h

@@ -7,6 +7,8 @@
 #ifndef TOR_ADDRESSMAP_H
 #define TOR_ADDRESSMAP_H
 
+#include "testsupport.h"
+
 void addressmap_init(void);
 void addressmap_clear_excluded_trackexithosts(const or_options_t *options);
 void addressmap_clear_invalid_automaps(const or_options_t *options);
@@ -52,8 +54,8 @@ typedef struct virtual_addr_conf_t {
   maskbits_t bits;
 } virtual_addr_conf_t;
 
-void get_random_virtual_addr(const virtual_addr_conf_t *conf,
-                             tor_addr_t *addr_out);
+STATIC void get_random_virtual_addr(const virtual_addr_conf_t *conf,
+                                    tor_addr_t *addr_out);
 #endif
 
 #endif

+ 1 - 1
src/or/buffers.c

@@ -1294,7 +1294,7 @@ buf_matches_at_pos(const buf_pos_t *pos, const char *s, size_t n)
 
 /** Return the first position in <b>buf</b> at which the <b>n</b>-character
  * string <b>s</b> occurs, or -1 if it does not occur. */
-/*private*/ int
+STATIC int
 buf_find_string_offset(const buf_t *buf, const char *s, size_t n)
 {
   buf_pos_t pos;

+ 3 - 1
src/or/buffers.h

@@ -12,6 +12,8 @@
 #ifndef TOR_BUFFERS_H
 #define TOR_BUFFERS_H
 
+#include "testsupport.h"
+
 buf_t *buf_new(void);
 buf_t *buf_new_with_capacity(size_t size);
 void buf_free(buf_t *buf);
@@ -89,7 +91,7 @@ int generic_buffer_set_to_copy(generic_buffer_t **output,
 void assert_buf_ok(buf_t *buf);
 
 #ifdef BUFFERS_PRIVATE
-int buf_find_string_offset(const buf_t *buf, const char *s, size_t n);
+STATIC int buf_find_string_offset(const buf_t *buf, const char *s, size_t n);
 #endif
 
 #endif

+ 2 - 3
src/or/circuitlist.c

@@ -8,7 +8,7 @@
  * \file circuitlist.c
  * \brief Manage the global circuit list.
  **/
-
+#define CIRCUITLIST_PRIVATE
 #include "or.h"
 #include "channel.h"
 #include "circuitbuild.h"
@@ -41,7 +41,6 @@ circuit_t *global_circuitlist=NULL;
 /** A list of all the circuits in CIRCUIT_STATE_CHAN_WAIT. */
 static smartlist_t *circuits_pending_chans = NULL;
 
-static void circuit_free(circuit_t *circ);
 static void circuit_free_cpath(crypt_path_t *cpath);
 static void circuit_free_cpath_node(crypt_path_t *victim);
 static void cpath_ref_decref(crypt_path_reference_t *cpath_ref);
@@ -736,7 +735,7 @@ or_circuit_new(circid_t p_circ_id, channel_t *p_chan)
 
 /** Deallocate space associated with circ.
  */
-static void
+STATIC void
 circuit_free(circuit_t *circ)
 {
   void *mem;

+ 6 - 0
src/or/circuitlist.h

@@ -12,6 +12,8 @@
 #ifndef TOR_CIRCUITLIST_H
 #define TOR_CIRCUITLIST_H
 
+#include "testsupport.h"
+
 circuit_t * circuit_get_global_list_(void);
 const char *circuit_state_to_string(int state);
 const char *circuit_purpose_to_controller_string(uint8_t purpose);
@@ -68,5 +70,9 @@ void circuits_handle_oom(size_t current_allocation);
 void channel_note_destroy_pending(channel_t *chan, circid_t id);
 void channel_note_destroy_not_pending(channel_t *chan, circid_t id);
 
+#ifdef CIRCUITLIST_PRIVATE
+STATIC void circuit_free(circuit_t *circ);
+#endif
+
 #endif
 

+ 5 - 5
src/or/circuitmux.c

@@ -922,9 +922,9 @@ circuitmux_num_circuits(circuitmux_t *cmux)
  * Attach a circuit to a circuitmux, for the specified direction.
  */
 
-void
-circuitmux_attach_circuit(circuitmux_t *cmux, circuit_t *circ,
-                          cell_direction_t direction)
+MOCK_IMPL(void,
+circuitmux_attach_circuit,(circuitmux_t *cmux, circuit_t *circ,
+                           cell_direction_t direction))
 {
   channel_t *chan = NULL;
   uint64_t channel_id;
@@ -1071,8 +1071,8 @@ circuitmux_attach_circuit(circuitmux_t *cmux, circuit_t *circ,
  * no-op if not attached.
  */
 
-void
-circuitmux_detach_circuit(circuitmux_t *cmux, circuit_t *circ)
+MOCK_IMPL(void,
+circuitmux_detach_circuit,(circuitmux_t *cmux, circuit_t *circ))
 {
   chanid_circid_muxinfo_t search, *hashent = NULL;
   /*

+ 5 - 3
src/or/circuitmux.h

@@ -10,6 +10,7 @@
 #define TOR_CIRCUITMUX_H
 
 #include "or.h"
+#include "testsupport.h"
 
 typedef struct circuitmux_policy_s circuitmux_policy_t;
 typedef struct circuitmux_policy_data_s circuitmux_policy_data_t;
@@ -127,9 +128,10 @@ void circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ,
 void circuitmux_notify_xmit_destroy(circuitmux_t *cmux);
 
 /* Circuit interface */
-void circuitmux_attach_circuit(circuitmux_t *cmux, circuit_t *circ,
-                               cell_direction_t direction);
-void circuitmux_detach_circuit(circuitmux_t *cmux, circuit_t *circ);
+MOCK_DECL(void, circuitmux_attach_circuit, (circuitmux_t *cmux, circuit_t *circ,
+                                            cell_direction_t direction));
+MOCK_DECL(void, circuitmux_detach_circuit,
+          (circuitmux_t *cmux, circuit_t *circ));
 void circuitmux_clear_num_cells(circuitmux_t *cmux, circuit_t *circ);
 void circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ,
                               unsigned int n_cells);

+ 17 - 4
src/or/circuitstats.c

@@ -29,9 +29,13 @@
 /* XXXX024 Make this static; add accessor functions. */
 circuit_build_times_t circ_times;
 
+#ifdef TOR_UNIT_TESTS
 /** If set, we're running the unit tests: we should avoid clobbering
  * our state file or accessing get_options() or get_or_state() */
 static int unit_tests = 0;
+#else
+#define unit_tests 0
+#endif
 
 /**
  * This function decides if CBT learning should be disabled. It returns
@@ -438,7 +442,7 @@ circuit_build_times_get_initial_timeout(void)
  * Leave estimated parameters, timeout and network liveness intact
  * for future use.
  */
-void
+STATIC void
 circuit_build_times_reset(circuit_build_times_t *cbt)
 {
   memset(cbt->circuit_build_times, 0, sizeof(cbt->circuit_build_times));
@@ -949,7 +953,7 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
  * an acceptable approximation because we are only concerned with the
  * accuracy of the CDF of the tail.
  */
-int
+STATIC int
 circuit_build_times_update_alpha(circuit_build_times_t *cbt)
 {
   build_time_t *x=cbt->circuit_build_times;
@@ -1033,7 +1037,7 @@ circuit_build_times_update_alpha(circuit_build_times_t *cbt)
  *
  * Return value is in milliseconds.
  */
-double
+STATIC double
 circuit_build_times_calculate_timeout(circuit_build_times_t *cbt,
                                       double quantile)
 {
@@ -1050,6 +1054,7 @@ circuit_build_times_calculate_timeout(circuit_build_times_t *cbt,
   return ret;
 }
 
+#ifdef TOR_UNIT_TESTS
 /** Pareto CDF */
 double
 circuit_build_times_cdf(circuit_build_times_t *cbt, double x)
@@ -1060,7 +1065,9 @@ circuit_build_times_cdf(circuit_build_times_t *cbt, double x)
   tor_assert(0 <= ret && ret <= 1.0);
   return ret;
 }
+#endif
 
+#ifdef TOR_UNIT_TESTS
 /**
  * Generate a synthetic time using our distribution parameters.
  *
@@ -1093,7 +1100,9 @@ circuit_build_times_generate_sample(circuit_build_times_t *cbt,
   tor_assert(ret > 0);
   return ret;
 }
+#endif
 
+#ifdef TOR_UNIT_TESTS
 /**
  * Estimate an initial alpha parameter by solving the quantile
  * function with a quantile point and a specific timeout value.
@@ -1114,6 +1123,7 @@ circuit_build_times_initial_alpha(circuit_build_times_t *cbt,
     (tor_mathlog(cbt->Xm)-tor_mathlog(timeout_ms));
   tor_assert(cbt->alpha > 0);
 }
+#endif
 
 /**
  * Returns true if we need circuits to be built
@@ -1282,7 +1292,7 @@ circuit_build_times_network_check_live(circuit_build_times_t *cbt)
  * to restart the process of building test circuits and estimating a
  * new timeout.
  */
-int
+STATIC int
 circuit_build_times_network_check_changed(circuit_build_times_t *cbt)
 {
   int total_build_times = cbt->total_build_times;
@@ -1546,6 +1556,8 @@ circuit_build_times_set_timeout(circuit_build_times_t *cbt)
              cbt->total_build_times);
   }
 }
+
+#ifdef TOR_UNIT_TESTS
 /** Make a note that we're running unit tests (rather than running Tor
  * itself), so we avoid clobbering our state file. */
 void
@@ -1553,4 +1565,5 @@ circuitbuild_running_unit_tests(void)
 {
   unit_tests = 1;
 }
+#endif
 

+ 11 - 10
src/or/circuitstats.h

@@ -38,19 +38,23 @@ double circuit_build_times_timeout_rate(const circuit_build_times_t *cbt);
 double circuit_build_times_close_rate(const circuit_build_times_t *cbt);
 
 #ifdef CIRCUITSTATS_PRIVATE
-double circuit_build_times_calculate_timeout(circuit_build_times_t *cbt,
+STATIC double circuit_build_times_calculate_timeout(circuit_build_times_t *cbt,
                                              double quantile);
+STATIC int circuit_build_times_update_alpha(circuit_build_times_t *cbt);
+STATIC void circuit_build_times_reset(circuit_build_times_t *cbt);
+
+/* Network liveness functions */
+STATIC int circuit_build_times_network_check_changed(
+                                             circuit_build_times_t *cbt);
+#endif
+
+#ifdef TOR_UNIT_TESTS
 build_time_t circuit_build_times_generate_sample(circuit_build_times_t *cbt,
                                                  double q_lo, double q_hi);
+double circuit_build_times_cdf(circuit_build_times_t *cbt, double x);
 void circuit_build_times_initial_alpha(circuit_build_times_t *cbt,
                                        double quantile, double time_ms);
-int circuit_build_times_update_alpha(circuit_build_times_t *cbt);
-double circuit_build_times_cdf(circuit_build_times_t *cbt, double x);
 void circuitbuild_running_unit_tests(void);
-void circuit_build_times_reset(circuit_build_times_t *cbt);
-
-/* Network liveness functions */
-int circuit_build_times_network_check_changed(circuit_build_times_t *cbt);
 #endif
 
 /* Network liveness functions */
@@ -58,8 +62,5 @@ void circuit_build_times_network_is_live(circuit_build_times_t *cbt);
 int circuit_build_times_network_check_live(circuit_build_times_t *cbt);
 void circuit_build_times_network_circ_success(circuit_build_times_t *cbt);
 
-/* DOCDOC circuit_build_times_get_bw_scale */
-int circuit_build_times_get_bw_scale(networkstatus_t *ns);
-
 #endif
 

+ 0 - 2
src/or/config.c

@@ -9,8 +9,6 @@
  * \brief Code to parse and interpret configuration files.
  **/
 
-#define CONFIG_PRIVATE
-
 #include "or.h"
 #include "addressmap.h"
 #include "channel.h"

+ 0 - 3
src/or/config.h

@@ -90,10 +90,7 @@ uint32_t get_effective_bwburst(const or_options_t *options);
 
 char *get_transport_bindaddr_from_config(const char *transport);
 
-#ifdef CONFIG_PRIVATE
-/* Used only by config.c and test.c */
 or_options_t *options_new(void);
-#endif
 
 void config_register_addressmaps(const or_options_t *options);
 /* XXXX024 move to connection_edge.h */

+ 2 - 2
src/or/connection_edge.c

@@ -407,7 +407,7 @@ connection_edge_finished_flushing(edge_connection_t *conn)
  * that the name resolution that led us to <b>addr</b> will be valid for
  * <b>ttl</b> seconds. Return -1 on error, or the number of bytes used on
  * success. */
-/* private */int
+STATIC int
 connected_cell_format_payload(uint8_t *payload_out,
                               const tor_addr_t *addr,
                               uint32_t ttl)
@@ -2265,7 +2265,7 @@ connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
  * Return -1 in the case where want to send a RELAY_END cell, and < -1 when
  * we don't.
  **/
-/* static */ int
+STATIC int
 begin_cell_parse(const cell_t *cell, begin_cell_t *bcell,
                  uint8_t *end_reason_out)
 {

+ 4 - 2
src/or/connection_edge.h

@@ -12,6 +12,8 @@
 #ifndef TOR_CONNECTION_EDGE_H
 #define TOR_CONNECTION_EDGE_H
 
+#include "testsupport.h"
+
 #define connection_mark_unattached_ap(conn, endreason) \
   connection_mark_unattached_ap_((conn), (endreason), __LINE__, SHORT_FILE__)
 
@@ -130,9 +132,9 @@ typedef struct begin_cell_t {
   unsigned is_begindir : 1;
 } begin_cell_t;
 
-int begin_cell_parse(const cell_t *cell, begin_cell_t *bcell,
+STATIC int begin_cell_parse(const cell_t *cell, begin_cell_t *bcell,
                      uint8_t *end_reason_out);
-int connected_cell_format_payload(uint8_t *payload_out,
+STATIC int connected_cell_format_payload(uint8_t *payload_out,
                                   const tor_addr_t *addr,
                                   uint32_t ttl);
 #endif

+ 2 - 2
src/or/control.c

@@ -334,7 +334,7 @@ connection_write_str_to_buf(const char *s, control_connection_t *conn)
  * the end. Replace all LF characters sequences with CRLF.  Return the number
  * of bytes in *<b>out</b>.
  */
-/* static */ size_t
+STATIC size_t
 write_escaped_data(const char *data, size_t len, char **out)
 {
   size_t sz_out = len+8;
@@ -382,7 +382,7 @@ write_escaped_data(const char *data, size_t len, char **out)
  * that appears at the start of a line, and replacing all CRLF sequences
  * with LF.   Return the number of
  * bytes in *<b>out</b>. */
-/* static */ size_t
+STATIC size_t
 read_escaped_data(const char *data, size_t len, char **out)
 {
   char *outp;

+ 2 - 2
src/or/control.h

@@ -91,8 +91,8 @@ void control_event_clients_seen(const char *controller_str);
 
 #ifdef CONTROL_PRIVATE
 /* Used only by control.c and test.c */
-size_t write_escaped_data(const char *data, size_t len, char **out);
-size_t read_escaped_data(const char *data, size_t len, char **out);
+STATIC size_t write_escaped_data(const char *data, size_t len, char **out);
+STATIC size_t read_escaped_data(const char *data, size_t len, char **out);
 #endif
 
 #endif

+ 9 - 9
src/or/dirserv.c

@@ -2082,7 +2082,7 @@ static digestmap_t *mbw_cache = NULL;
 
 /** Store a measured bandwidth cache entry when reading the measured
  * bandwidths file. */
-void
+STATIC void
 dirserv_cache_measured_bw(const measured_bw_line_t *parsed_line,
                           time_t as_of)
 {
@@ -2112,7 +2112,7 @@ dirserv_cache_measured_bw(const measured_bw_line_t *parsed_line,
 }
 
 /** Clear and free the measured bandwidth cache */
-void
+STATIC void
 dirserv_clear_measured_bw_cache(void)
 {
   if (mbw_cache) {
@@ -2123,7 +2123,7 @@ dirserv_clear_measured_bw_cache(void)
 }
 
 /** Scan the measured bandwidth cache and remove expired entries */
-void
+STATIC void
 dirserv_expire_measured_bw_cache(time_t now)
 {
 
@@ -2145,7 +2145,7 @@ dirserv_expire_measured_bw_cache(time_t now)
 }
 
 /** Get the current size of the measured bandwidth cache */
-int
+STATIC int
 dirserv_get_measured_bw_cache_size(void)
 {
   if (mbw_cache) return digestmap_size(mbw_cache);
@@ -2155,7 +2155,7 @@ dirserv_get_measured_bw_cache_size(void)
 /** Query the cache by identity digest, return value indicates whether
  * we found it. The bw_out and as_of_out pointers receive the cached
  * bandwidth value and the time it was cached if not NULL. */
-int
+STATIC int
 dirserv_query_measured_bw_cache_kb(const char *node_id, long *bw_kb_out,
                                    time_t *as_of_out)
 {
@@ -2176,7 +2176,7 @@ dirserv_query_measured_bw_cache_kb(const char *node_id, long *bw_kb_out,
 }
 
 /** Predicate wrapper for dirserv_query_measured_bw_cache() */
-int
+STATIC int
 dirserv_has_measured_bw(const char *node_id)
 {
   return dirserv_query_measured_bw_cache_kb(node_id, NULL, NULL);
@@ -2754,7 +2754,7 @@ clear_status_flags_on_sybil(routerstatus_t *rs)
  * into a measured_bw_line_t output structure. Returns -1 on failure
  * or 0 on success.
  */
-int
+STATIC int
 measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line)
 {
   char *line = tor_strdup(orig_line);
@@ -2835,7 +2835,7 @@ measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line)
  * of bandwidth statuses. Returns true if a line is found,
  * false otherwise.
  */
-int
+STATIC int
 measured_bw_line_apply(measured_bw_line_t *parsed_line,
                        smartlist_t *routerstatuses)
 {
@@ -3168,7 +3168,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
 /** For v2 authoritative directories only: Replace the contents of
  * <b>the_v2_networkstatus</b> with a newly generated network status
  * object.  */
-cached_dir_t *
+STATIC cached_dir_t *
 generate_v2_networkstatus_opinion(void)
 {
   cached_dir_t *r = NULL;

+ 13 - 10
src/or/dirserv.h

@@ -12,6 +12,8 @@
 #ifndef TOR_DIRSERV_H
 #define TOR_DIRSERV_H
 
+#include "testsupport.h"
+
 /** What fraction (1 over this number) of the relay ID space do we
  * (as a directory authority) launch connections to at each reachability
  * test? */
@@ -119,20 +121,21 @@ cached_dir_t *new_cached_dir(char *s, time_t published);
 /* Put the MAX_MEASUREMENT_AGE #define here so unit tests can see it */
 #define MAX_MEASUREMENT_AGE (3*24*60*60) /* 3 days */
 
-int measured_bw_line_parse(measured_bw_line_t *out, const char *line);
+STATIC int measured_bw_line_parse(measured_bw_line_t *out, const char *line);
 
-int measured_bw_line_apply(measured_bw_line_t *parsed_line,
+STATIC int measured_bw_line_apply(measured_bw_line_t *parsed_line,
                            smartlist_t *routerstatuses);
 
-void dirserv_cache_measured_bw(const measured_bw_line_t *parsed_line,
+STATIC void dirserv_cache_measured_bw(const measured_bw_line_t *parsed_line,
                                time_t as_of);
-void dirserv_clear_measured_bw_cache(void);
-void dirserv_expire_measured_bw_cache(time_t now);
-int dirserv_get_measured_bw_cache_size(void);
-int dirserv_query_measured_bw_cache_kb(const char *node_id, long *bw_out,
-                                       time_t *as_of_out);
-int dirserv_has_measured_bw(const char *node_id);
-cached_dir_t *generate_v2_networkstatus_opinion(void);
+STATIC void dirserv_clear_measured_bw_cache(void);
+STATIC void dirserv_expire_measured_bw_cache(time_t now);
+STATIC int dirserv_get_measured_bw_cache_size(void);
+STATIC int dirserv_query_measured_bw_cache_kb(const char *node_id,
+                                              long *bw_out,
+                                              time_t *as_of_out);
+STATIC int dirserv_has_measured_bw(const char *node_id);
+STATIC cached_dir_t *generate_v2_networkstatus_opinion(void);
 #endif
 
 int dirserv_read_measured_bandwidths(const char *from_file,

+ 2 - 2
src/or/dirvote.c

@@ -60,7 +60,7 @@ static char *make_consensus_method_list(int low, int high, const char *sep);
 /** Return a new string containing the string representation of the vote in
  * <b>v3_ns</b>, signed with our v3 signing key <b>private_signing_key</b>.
  * For v3 authorities. */
-char *
+STATIC char *
 format_networkstatus_vote(crypto_pk_t *private_signing_key,
                           networkstatus_t *v3_ns)
 {
@@ -587,7 +587,7 @@ compute_consensus_versions_list(smartlist_t *lst, int n_versioning)
 /** Helper: given a list of valid networkstatus_t, return a new string
  * containing the contents of the consensus network parameter set.
  */
-/* private */ char *
+STATIC char *
 dirvote_compute_params(smartlist_t *votes, int method, int total_authorities)
 {
   int i;

+ 4 - 2
src/or/dirvote.h

@@ -12,6 +12,8 @@
 #ifndef TOR_DIRVOTE_H
 #define TOR_DIRVOTE_H
 
+#include "testsupport.h"
+
 /** Lowest allowable value for VoteSeconds. */
 #define MIN_VOTE_SECONDS 2
 /** Lowest allowable value for DistSeconds. */
@@ -136,9 +138,9 @@ document_signature_t *voter_get_sig_by_algorithm(
                            digest_algorithm_t alg);
 
 #ifdef DIRVOTE_PRIVATE
-char *format_networkstatus_vote(crypto_pk_t *private_key,
+STATIC char *format_networkstatus_vote(crypto_pk_t *private_key,
                                  networkstatus_t *v3_ns);
-char *dirvote_compute_params(smartlist_t *votes, int method,
+STATIC char *dirvote_compute_params(smartlist_t *votes, int method,
                              int total_authorities);
 #endif
 

+ 3 - 3
src/or/geoip.c

@@ -120,7 +120,7 @@ geoip_add_entry(const tor_addr_t *low, const tor_addr_t *high,
 
 /** Add an entry to the GeoIP table indicated by <b>family</b>,
  * parsing it from <b>line</b>. The format is as for geoip_load_file(). */
-/*private*/ int
+STATIC int
 geoip_parse_entry(const char *line, sa_family_t family)
 {
   tor_addr_t low_addr, high_addr;
@@ -363,7 +363,7 @@ geoip_load_file(sa_family_t family, const char *filename)
  * be less than geoip_get_n_countries().  To decode it, call
  * geoip_get_country_name().
  */
-int
+STATIC int
 geoip_get_country_by_ipv4(uint32_t ipaddr)
 {
   geoip_ipv4_entry_t *ent;
@@ -379,7 +379,7 @@ geoip_get_country_by_ipv4(uint32_t ipaddr)
  * 0 for the 'unknown country'.  The return value will always be less than
  * geoip_get_n_countries().  To decode it, call geoip_get_country_name().
  */
-int
+STATIC int
 geoip_get_country_by_ipv6(const struct in6_addr *addr)
 {
   geoip_ipv6_entry_t *ent;

+ 5 - 3
src/or/geoip.h

@@ -12,10 +12,12 @@
 #ifndef TOR_GEOIP_H
 #define TOR_GEOIP_H
 
+#include "testsupport.h"
+
 #ifdef GEOIP_PRIVATE
-int geoip_parse_entry(const char *line, sa_family_t family);
-int geoip_get_country_by_ipv4(uint32_t ipaddr);
-int geoip_get_country_by_ipv6(const struct in6_addr *addr);
+STATIC int geoip_parse_entry(const char *line, sa_family_t family);
+STATIC int geoip_get_country_by_ipv4(uint32_t ipaddr);
+STATIC int geoip_get_country_by_ipv6(const struct in6_addr *addr);
 #endif
 int should_record_bridge_info(const or_options_t *options);
 int geoip_load_file(sa_family_t family, const char *filename);

+ 2 - 0
src/or/hibernate.c

@@ -1010,6 +1010,7 @@ getinfo_helper_accounting(control_connection_t *conn,
   return 0;
 }
 
+#ifdef TOR_UNIT_TESTS
 /**
  * Manually change the hibernation state.  Private; used only by the unit
  * tests.
@@ -1019,4 +1020,5 @@ hibernate_set_state_for_testing_(hibernate_state_t newstate)
 {
   hibernate_state = newstate;
 }
+#endif
 

+ 2 - 0
src/or/hibernate.h

@@ -45,8 +45,10 @@ typedef enum {
   HIBERNATE_STATE_INITIAL=5
 } hibernate_state_t;
 
+#ifdef TOR_UNIT_TESTS
 void hibernate_set_state_for_testing_(hibernate_state_t newstate);
 #endif
+#endif
 
 #endif
 

+ 28 - 2
src/or/include.am

@@ -1,5 +1,13 @@
 bin_PROGRAMS+= src/or/tor
-noinst_LIBRARIES+= src/or/libtor.a
+noinst_LIBRARIES += \
+	src/or/libtor.a
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += \
+	src/or/libtor-testing.a
+endif
+if COVERAGE_ENABLED
+noinst_PROGRAMS+= src/or/tor-cov
+endif
 
 if BUILD_NT_SERVICES
 tor_platform_source=src/or/ntmain.c
@@ -21,7 +29,7 @@ else
 onion_ntor_source=
 endif
 
-src_or_libtor_a_SOURCES = \
+LIBTOR_A_SOURCES = \
 	src/or/addressmap.c				\
 	src/or/buffers.c				\
 	src/or/channel.c				\
@@ -77,6 +85,9 @@ src_or_libtor_a_SOURCES = \
 	$(onion_ntor_source)				\
 	src/or/config_codedigest.c
 
+src_or_libtor_a_SOURCES = $(LIBTOR_A_SOURCES)
+src_or_libtor_testing_a_SOURCES = $(LIBTOR_A_SOURCES)
+
 #libtor_a_LIBADD = ../common/libor.a ../common/libor-crypto.a \
 #	../common/libor-event.a
 
@@ -90,6 +101,9 @@ AM_CPPFLAGS += -DSHARE_DATADIR="\"$(datadir)\"" \
         -DLOCALSTATEDIR="\"$(localstatedir)\"" \
         -DBINDIR="\"$(bindir)\""
 
+src_or_libtor_testing_a_CPPFLAGS = -DTOR_UNIT_TESTS $(AM_CPPFLAGS)
+src_or_libtor_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
 # -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.
@@ -102,6 +116,18 @@ src_or_tor_LDADD = src/or/libtor.a src/common/libor.a \
 	@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
 	@TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
 
+if COVERAGE_ENABLED
+src_or_tor_cov_SOURCES = src/or/tor_main.c
+src_or_tor_cov_CPPFLAGS = -DTOR_UNIT_TESTS $(AM_CPPFLAGS)
+src_or_tor_cov_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+src_or_tor_cov_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@
+src_or_tor_cov_LDADD = src/or/libtor-testing.a src/common/libor-testing.a \
+	src/common/libor-crypto-testing.a $(LIBDONNA) \
+	src/common/libor-event-testing.a \
+	@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
+	@TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
+endif
+
 ORHEADERS = \
 	src/or/addressmap.h				\
 	src/or/buffers.h				\

+ 4 - 5
src/or/main.c

@@ -10,7 +10,6 @@
  * connections, implements main loop, and drives scheduled events.
  **/
 
-#define MAIN_PRIVATE
 #include "or.h"
 #include "addressmap.h"
 #include "buffers.h"
@@ -1875,7 +1874,7 @@ do_hup(void)
 }
 
 /** Tor main loop. */
-/* static */ int
+int
 do_main_loop(void)
 {
   int loop_result;
@@ -2302,7 +2301,7 @@ handle_signals(int is_parent)
 
 /** Main entry point for the Tor command-line client.
  */
-/* static */ int
+int
 tor_init(int argc, char *argv[])
 {
   char buf[256];
@@ -2568,7 +2567,7 @@ tor_cleanup(void)
 }
 
 /** Read/create keys as needed, and echo our fingerprint to stdout. */
-/* static */ int
+static int
 do_list_fingerprint(void)
 {
   char buf[FINGERPRINT_LEN+1];
@@ -2598,7 +2597,7 @@ do_list_fingerprint(void)
 
 /** Entry point for password hashing: take the desired password from
  * the command line, and print its salted hash to stdout. **/
-/* static */ void
+static void
 do_hash_password(void)
 {
 

+ 0 - 4
src/or/main.h

@@ -66,12 +66,8 @@ void tor_free_all(int postfork);
 
 int tor_main(int argc, char *argv[]);
 
-#ifdef MAIN_PRIVATE
 int do_main_loop(void);
-int do_list_fingerprint(void);
-void do_hash_password(void);
 int tor_init(int argc, char **argv);
-#endif
 
 #endif
 

+ 0 - 1
src/or/ntmain.c

@@ -3,7 +3,6 @@
  * Copyright (c) 2007-2013, The Tor Project, Inc. */
 /* See LICENSE for licensing information */
 
-#define MAIN_PRIVATE
 #include "or.h"
 #include "config.h"
 #include "main.h"

+ 1 - 1
src/or/relay.c

@@ -969,7 +969,7 @@ remap_event_helper(entry_connection_t *conn, const tor_addr_t *new_addr)
  * <b>addr_out</b> to the address we're connected to, and <b>ttl_out</b> to
  * the ttl of that address, in seconds, and return 0.  On failure, return
  * -1. */
-int
+STATIC int
 connected_cell_parse(const relay_header_t *rh, const cell_t *cell,
                      tor_addr_t *addr_out, int *ttl_out)
 {

+ 3 - 2
src/or/relay.h

@@ -75,10 +75,11 @@ void circuit_clear_cell_queue(circuit_t *circ, channel_t *chan);
 
 void stream_choice_seed_weak_rng(void);
 
-#ifdef RELAY_PRIVATE
 int relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction,
                 crypt_path_t **layer_hint, char *recognized);
-int connected_cell_parse(const relay_header_t *rh, const cell_t *cell,
+
+#ifdef RELAY_PRIVATE
+STATIC int connected_cell_parse(const relay_header_t *rh, const cell_t *cell,
                          tor_addr_t *addr_out, int *ttl_out);
 #endif
 

+ 2 - 2
src/or/replaycache.c

@@ -63,7 +63,7 @@ replaycache_new(time_t horizon, time_t interval)
 /** See documentation for replaycache_add_and_test()
  */
 
-int
+STATIC int
 replaycache_add_and_test_internal(
     time_t present, replaycache_t *r, const void *data, int len,
     time_t *elapsed)
@@ -127,7 +127,7 @@ replaycache_add_and_test_internal(
 /** See documentation for replaycache_scrub_if_needed()
  */
 
-void
+STATIC void
 replaycache_scrub_if_needed_internal(time_t present, replaycache_t *r)
 {
   digestmap_iter_t *itr = NULL;

+ 2 - 2
src/or/replaycache.h

@@ -45,10 +45,10 @@ replaycache_t * replaycache_new(time_t horizon, time_t interval);
  * testing.  For everything else, use the wrappers below instead.
  */
 
-int replaycache_add_and_test_internal(
+STATIC int replaycache_add_and_test_internal(
     time_t present, replaycache_t *r, const void *data, int len,
     time_t *elapsed);
-void replaycache_scrub_if_needed_internal(
+STATIC void replaycache_scrub_if_needed_internal(
     time_t present, replaycache_t *r);
 
 #endif /* REPLAYCACHE_PRIVATE */

+ 1 - 1
src/or/router.c

@@ -2249,7 +2249,7 @@ router_guess_address_from_dir_headers(uint32_t *guess)
  * string describing the version of Tor and the operating system we're
  * currently running on.
  */
-void
+STATIC void
 get_platform_str(char *platform, size_t len)
 {
   tor_snprintf(platform, len, "Tor %s on %s",

+ 3 - 1
src/or/router.h

@@ -12,6 +12,8 @@
 #ifndef TOR_ROUTER_H
 #define TOR_ROUTER_H
 
+#include "testsupport.h"
+
 crypto_pk_t *get_onion_key(void);
 time_t get_onion_key_set_at(void);
 void set_server_identity_key(crypto_pk_t *k);
@@ -146,7 +148,7 @@ smartlist_t *router_get_all_orports(const routerinfo_t *ri);
 
 #ifdef ROUTER_PRIVATE
 /* Used only by router.c and test.c */
-void get_platform_str(char *platform, size_t len);
+STATIC void get_platform_str(char *platform, size_t len);
 #endif
 
 #endif

+ 2 - 2
src/or/routerlist.c

@@ -1801,7 +1801,7 @@ router_get_advertised_bandwidth_capped(const routerinfo_t *router)
  * doubles, convert them to uint64_t, and try to scale them linearly so as to
  * much of the range of uint64_t. If <b>total_out</b> is provided, set it to
  * the sum of all elements in the array _before_ scaling. */
-/* private */ void
+STATIC void
 scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries,
                             uint64_t *total_out)
 {
@@ -1844,7 +1844,7 @@ gt_i64_timei(uint64_t a, uint64_t b)
  * value, and return the index of that element.  If all elements are 0, choose
  * an index at random. Return -1 on error.
  */
-/* private */ int
+STATIC int
 choose_array_element_by_weight(const u64_dbl_t *entries, int n_entries)
 {
   int i, i_chosen=-1, n_chosen=0;

+ 6 - 3
src/or/routerlist.h

@@ -11,6 +11,8 @@
 #ifndef TOR_ROUTERLIST_H
 #define TOR_ROUTERLIST_H
 
+#include "testsupport.h"
+
 int get_n_authorities(dirinfo_type_t type);
 int trusted_dirs_reload_certs(void);
 
@@ -206,9 +208,10 @@ typedef union u64_dbl_t {
   double dbl;
 } u64_dbl_t;
 
-int choose_array_element_by_weight(const u64_dbl_t *entries, int n_entries);
-void scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries,
-                                 uint64_t *total_out);
+STATIC int choose_array_element_by_weight(const u64_dbl_t *entries,
+                                          int n_entries);
+STATIC void scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries,
+                                        uint64_t *total_out);
 #endif
 
 #endif

+ 5 - 5
src/or/transports.c

@@ -776,7 +776,7 @@ handle_methods_done(const managed_proxy_t *mp)
 
 /** Handle a configuration protocol <b>line</b> received from a
  *  managed proxy <b>mp</b>. */
-void
+STATIC void
 handle_proxy_line(const char *line, managed_proxy_t *mp)
 {
   log_info(LD_GENERAL, "Got a line from managed proxy '%s': (%s)",
@@ -877,7 +877,7 @@ handle_proxy_line(const char *line, managed_proxy_t *mp)
 }
 
 /** Parses an ENV-ERROR <b>line</b> and warns the user accordingly. */
-void
+STATIC void
 parse_env_error(const char *line)
 {
   /* (Length of the protocol string) plus (a space) and (the first char of
@@ -893,7 +893,7 @@ parse_env_error(const char *line)
 
 /** Handles a VERSION <b>line</b>. Updates the configuration protocol
  *  version in <b>mp</b>. */
-int
+STATIC int
 parse_version(const char *line, managed_proxy_t *mp)
 {
   if (strlen(line) < (strlen(PROTO_NEG_SUCCESS) + 2)) {
@@ -934,7 +934,7 @@ parse_method_error(const char *line, int is_server)
 
 /** Parses an SMETHOD <b>line</b> and if well-formed it registers the
  *  new transport in <b>mp</b>. */
-int
+STATIC int
 parse_smethod_line(const char *line, managed_proxy_t *mp)
 {
   int r;
@@ -1011,7 +1011,7 @@ parse_smethod_line(const char *line, managed_proxy_t *mp)
 
 /** Parses a CMETHOD <b>line</b>, and if well-formed it registers
  *  the new transport in <b>mp</b>. */
-int
+STATIC int
 parse_cmethod_line(const char *line, managed_proxy_t *mp)
 {
   int r;

+ 5 - 5
src/or/transports.h

@@ -104,12 +104,12 @@ typedef struct {
   smartlist_t *transports;
 } managed_proxy_t;
 
-int parse_cmethod_line(const char *line, managed_proxy_t *mp);
-int parse_smethod_line(const char *line, managed_proxy_t *mp);
+STATIC int parse_cmethod_line(const char *line, managed_proxy_t *mp);
+STATIC int parse_smethod_line(const char *line, managed_proxy_t *mp);
 
-int parse_version(const char *line, managed_proxy_t *mp);
-void parse_env_error(const char *line);
-void handle_proxy_line(const char *line, managed_proxy_t *mp);
+STATIC int parse_version(const char *line, managed_proxy_t *mp);
+STATIC void parse_env_error(const char *line);
+STATIC void handle_proxy_line(const char *line, managed_proxy_t *mp);
 
 #endif
 

+ 0 - 1
src/test/bench.c

@@ -15,7 +15,6 @@ const char tor_git_revision[] = "";
 #include "orconfig.h"
 
 #define RELAY_PRIVATE
-#define CONFIG_PRIVATE
 
 #include "or.h"
 #include "onion_tap.h"

+ 12 - 5
src/test/include.am

@@ -1,11 +1,15 @@
 TESTS+= src/test/test
 
-noinst_PROGRAMS+= src/test/test src/test/test-child src/test/bench
+noinst_PROGRAMS+= src/test/bench
+if UNITTESTS_ENABLED
+noinst_PROGRAMS+= src/test/test src/test/test-child
+endif
 
 src_test_AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
         -DLOCALSTATEDIR="\"$(localstatedir)\"" \
         -DBINDIR="\"$(bindir)\""	       \
-	-I"$(top_srcdir)/src/or" -I"$(top_srcdir)/src/ext"
+	-I"$(top_srcdir)/src/or" -I"$(top_srcdir)/src/ext" \
+	-DTOR_UNIT_TESTS
 
 # -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
@@ -15,6 +19,7 @@ src_test_test_SOURCES = \
 	src/test/test.c \
 	src/test/test_addr.c \
 	src/test/test_cell_formats.c \
+	src/test/test_circuitlist.c \
 	src/test/test_containers.c \
 	src/test/test_crypto.c \
 	src/test/test_data.c \
@@ -27,6 +32,8 @@ src_test_test_SOURCES = \
 	src/test/test_config.c \
 	src/ext/tinytest.c
 
+src_test_test_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
 src_test_test_CPPFLAGS= $(src_test_AM_CPPFLAGS)
 
 src_test_bench_SOURCES = \
@@ -36,9 +43,9 @@ 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 $(LIBDONNA) \
-	src/common/libor-event.a \
+src_test_test_LDADD = src/or/libtor-testing.a src/common/libor-testing.a \
+	src/common/libor-crypto-testing.a $(LIBDONNA) \
+	src/common/libor-event-testing.a \
 	@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
 	@TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
 

+ 2 - 1
src/test/test.c

@@ -29,7 +29,6 @@ const char tor_git_revision[] = "";
 /* These macros pull in declarations for some functions and structures that
  * are typically file-private. */
 #define BUFFERS_PRIVATE
-#define CONFIG_PRIVATE
 #define GEOIP_PRIVATE
 #define ROUTER_PRIVATE
 #define CIRCUITSTATS_PRIVATE
@@ -2133,6 +2132,7 @@ extern struct testcase_t config_tests[];
 extern struct testcase_t introduce_tests[];
 extern struct testcase_t replaycache_tests[];
 extern struct testcase_t cell_format_tests[];
+extern struct testcase_t circuitlist_tests[];
 
 static struct testgroup_t testgroups[] = {
   { "", test_array },
@@ -2148,6 +2148,7 @@ static struct testgroup_t testgroups[] = {
   { "config/", config_tests },
   { "replaycache/", replaycache_tests },
   { "introduce/", introduce_tests },
+  { "circuitlist/", circuitlist_tests },
   END_OF_GROUPS
 };
 

+ 168 - 0
src/test/test_circuitlist.c

@@ -0,0 +1,168 @@
+/* Copyright (c) 2013, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define TOR_CHANNEL_INTERNAL_
+#define CIRCUITLIST_PRIVATE
+#include "or.h"
+#include "channel.h"
+#include "circuitlist.h"
+#include "test.h"
+
+static channel_t *
+new_fake_channel(void)
+{
+  channel_t *chan = tor_malloc_zero(sizeof(channel_t));
+  channel_init(chan);
+  return chan;
+}
+
+static struct {
+  int ncalls;
+  void *cmux;
+  void *circ;
+  cell_direction_t dir;
+} cam;
+
+static void
+circuitmux_attach_mock(circuitmux_t *cmux, circuit_t *circ,
+                         cell_direction_t dir)
+{
+  ++cam.ncalls;
+  cam.cmux = cmux;
+  cam.circ = circ;
+  cam.dir = dir;
+}
+
+static struct {
+  int ncalls;
+  void *cmux;
+  void *circ;
+} cdm;
+
+static void
+circuitmux_detach_mock(circuitmux_t *cmux, circuit_t *circ)
+{
+  ++cdm.ncalls;
+  cdm.cmux = cmux;
+  cdm.circ = circ;
+}
+
+#define GOT_CMUX_ATTACH(mux_, circ_, dir_) do {  \
+    tt_int_op(cam.ncalls, ==, 1);                \
+    tt_ptr_op(cam.cmux, ==, (mux_));             \
+    tt_ptr_op(cam.circ, ==, (circ_));            \
+    tt_ptr_op(cam.dir, ==, (dir_));              \
+    memset(&cam, 0, sizeof(cam));                \
+  } while (0)
+
+#define GOT_CMUX_DETACH(mux_, circ_) do {        \
+    tt_int_op(cdm.ncalls, ==, 1);                \
+    tt_ptr_op(cdm.cmux, ==, (mux_));             \
+    tt_ptr_op(cdm.circ, ==, (circ_));            \
+    memset(&cdm, 0, sizeof(cdm));                \
+  } while (0)
+
+
+static void
+test_clist_maps(void *arg)
+{
+  channel_t *ch1 = new_fake_channel();
+  channel_t *ch2 = new_fake_channel();
+  channel_t *ch3 = new_fake_channel();
+  or_circuit_t *or_c1=NULL, *or_c2=NULL;
+
+  MOCK(circuitmux_attach_circuit, circuitmux_attach_mock);
+  MOCK(circuitmux_detach_circuit, circuitmux_detach_mock);
+  memset(&cam, 0, sizeof(cam));
+  memset(&cdm, 0, sizeof(cdm));
+
+  ch1->cmux = (void*)0x1001;
+  ch2->cmux = (void*)0x1002;
+  ch3->cmux = (void*)0x1003;
+
+  or_c1 = or_circuit_new(100, ch2);
+  tt_assert(or_c1);
+  GOT_CMUX_ATTACH(ch2->cmux, or_c1, CELL_DIRECTION_IN);
+  tt_int_op(or_c1->p_circ_id, ==, 100);
+  tt_ptr_op(or_c1->p_chan, ==, ch2);
+
+  or_c2 = or_circuit_new(100, ch1);
+  tt_assert(or_c2);
+  GOT_CMUX_ATTACH(ch1->cmux, or_c2, CELL_DIRECTION_IN);
+  tt_int_op(or_c2->p_circ_id, ==, 100);
+  tt_ptr_op(or_c2->p_chan, ==, ch1);
+
+  circuit_set_n_circid_chan(TO_CIRCUIT(or_c1), 200, ch1);
+  GOT_CMUX_ATTACH(ch1->cmux, or_c1, CELL_DIRECTION_OUT);
+
+  circuit_set_n_circid_chan(TO_CIRCUIT(or_c2), 200, ch2);
+  GOT_CMUX_ATTACH(ch2->cmux, or_c2, CELL_DIRECTION_OUT);
+
+  tt_ptr_op(circuit_get_by_circid_channel(200, ch1), ==, TO_CIRCUIT(or_c1));
+  tt_ptr_op(circuit_get_by_circid_channel(200, ch2), ==, TO_CIRCUIT(or_c2));
+  tt_ptr_op(circuit_get_by_circid_channel(100, ch2), ==, TO_CIRCUIT(or_c1));
+  /* Try the same thing again, to test the "fast" path. */
+  tt_ptr_op(circuit_get_by_circid_channel(100, ch2), ==, TO_CIRCUIT(or_c1));
+  tt_assert(circuit_id_in_use_on_channel(100, ch2));
+  tt_assert(! circuit_id_in_use_on_channel(101, ch2));
+
+  /* Try changing the circuitid and channel of that circuit. */
+  circuit_set_p_circid_chan(or_c1, 500, ch3);
+  GOT_CMUX_DETACH(ch2->cmux, TO_CIRCUIT(or_c1));
+  GOT_CMUX_ATTACH(ch3->cmux, TO_CIRCUIT(or_c1), CELL_DIRECTION_IN);
+  tt_ptr_op(circuit_get_by_circid_channel(100, ch2), ==, NULL);
+  tt_assert(! circuit_id_in_use_on_channel(100, ch2));
+  tt_ptr_op(circuit_get_by_circid_channel(500, ch3), ==, TO_CIRCUIT(or_c1));
+
+  /* Now let's see about destroy handling. */
+  tt_assert(! circuit_id_in_use_on_channel(205, ch2));
+  tt_assert(circuit_id_in_use_on_channel(200, ch2));
+  channel_note_destroy_pending(ch2, 200);
+  channel_note_destroy_pending(ch2, 205);
+  channel_note_destroy_pending(ch1, 100);
+  tt_assert(circuit_id_in_use_on_channel(205, ch2))
+  tt_assert(circuit_id_in_use_on_channel(200, ch2));
+  tt_assert(circuit_id_in_use_on_channel(100, ch1));
+
+  tt_assert(TO_CIRCUIT(or_c2)->n_delete_pending != 0);
+  tt_ptr_op(circuit_get_by_circid_channel(200, ch2), ==, TO_CIRCUIT(or_c2));
+  tt_ptr_op(circuit_get_by_circid_channel(100, ch1), ==, TO_CIRCUIT(or_c2));
+
+  /* Okay, now free ch2 and make sure that the circuit ID is STILL not
+   * usable, because we haven't declared the destroy to be nonpending */
+  tt_int_op(cdm.ncalls, ==, 0);
+  circuit_free(TO_CIRCUIT(or_c2));
+  or_c2 = NULL; /* prevent free */
+  tt_int_op(cdm.ncalls, ==, 2);
+  memset(&cdm, 0, sizeof(cdm));
+  tt_assert(circuit_id_in_use_on_channel(200, ch2));
+  tt_assert(circuit_id_in_use_on_channel(100, ch1));
+  tt_ptr_op(circuit_get_by_circid_channel(200, ch2), ==, NULL);
+  tt_ptr_op(circuit_get_by_circid_channel(100, ch1), ==, NULL);
+
+  /* Now say that the destroy is nonpending */
+  channel_note_destroy_not_pending(ch2, 200);
+  tt_ptr_op(circuit_get_by_circid_channel(200, ch2), ==, NULL);
+  channel_note_destroy_not_pending(ch1, 100);
+  tt_ptr_op(circuit_get_by_circid_channel(100, ch1), ==, NULL);
+  tt_assert(! circuit_id_in_use_on_channel(200, ch2));
+  tt_assert(! circuit_id_in_use_on_channel(100, ch1));
+
+
+done:
+  tor_free(ch1);
+  tor_free(ch2);
+  tor_free(ch3);
+  if (or_c1)
+    circuit_free(TO_CIRCUIT(or_c1));
+  if (or_c2)
+    circuit_free(TO_CIRCUIT(or_c2));
+  UNMOCK(circuitmux_attach_circuit);
+  UNMOCK(circuitmux_detach_circuit);
+}
+
+
+struct testcase_t circuitlist_tests[] = {
+  { "maps", test_clist_maps, TT_FORK, NULL, NULL },
+  END_OF_TESTCASES
+};

+ 1 - 2
src/test/test_crypto.c

@@ -4,7 +4,6 @@
 /* See LICENSE for licensing information */
 
 #include "orconfig.h"
-#define CRYPTO_PRIVATE
 #define CRYPTO_CURVE25519_PRIVATE
 #include "or.h"
 #include "test.h"
@@ -632,7 +631,7 @@ test_crypto_formats(void)
     data1 = tor_strdup("ABCD1234ABCD56780000ABCD1234ABCD56780000");
     test_eq(strlen(data1), 40);
     data2 = tor_malloc(FINGERPRINT_LEN+1);
-    add_spaces_to_fp(data2, FINGERPRINT_LEN+1, data1);
+    crypto_add_spaces_to_fp(data2, FINGERPRINT_LEN+1, data1);
     test_streq(data2, "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 0000");
     tor_free(data1);
     tor_free(data2);

+ 0 - 2
src/tools/tor-checkkey.c

@@ -1,8 +1,6 @@
 /* Copyright (c) 2008-2013, The Tor Project, Inc. */
 /* See LICENSE for licensing information */
 
-#define CRYPTO_PRIVATE
-
 #include "orconfig.h"
 
 #include <stdio.h>

+ 0 - 2
src/tools/tor-gencert.c

@@ -27,8 +27,6 @@
 #include <assert.h>
 #endif
 
-#define CRYPTO_PRIVATE
-
 #include "compat.h"
 #include "../common/util.h"
 #include "../common/torlog.h"