a couple more changes files issues.
[tor.git] / doc / WritingTests.txt
blob62a17e3709263a5cc24144dc739b9d67643b65c8
2 Writing tests for Tor: an incomplete guide
3 ==========================================
5 Tor uses a variety of testing frameworks and methodologies to try to
6 keep from introducing bugs.  The major ones are:
8    1. Unit tests written in C and shipped with the Tor distribution.
10    2. Integration tests written in Python and shipped with the Tor
11       distribution.
13    3. Integration tests written in Python and shipped with the Stem
14       library.  Some of these use the Tor controller protocol.
16    4. System tests written in Python and SH, and shipped with the
17       Chutney package.  These work by running many instances of Tor
18       locally, and sending traffic through them.
20    5. The Shadow network simulator.
22 How to run these tests
23 ----------------------
25 === The easy version
27 To run all the tests that come bundled with Tor, run "make check"
29 To run the Stem tests as well, fetch stem from the git repository,
30 set STEM_SOURCE_DIR to the checkout, and run "make test-stem".
32 To run the Chutney tests as well, fetch chutney from the git repository,
33 set CHUTNEY_PATH to the checkout, and run "make test-network".
35 To run all of the above, run "make test-full".
37 To run all of the above, plus tests that require a working connection to the
38 internet, run "make test-full-online".
40 === Running particular subtests
42 The Tor unit tests are divided into separate programs and a couple of
43 bundled unit test programs.
45 Separate programs are easy.  For example, to run the memwipe tests in
46 isolation, you just run ./src/test/test-memwipe .
48 To run tests within the unit test programs, you can specify the name
49 of the test.  The string ".." can be used as a wildcard at the end of the
50 test name.  For example, to run all the cell format tests, enter
51 "./src/test/test cellfmt/..".  To run
53 Many tests that need to mess with global state run in forked subprocesses in
54 order to keep from contaminating one another.  But when debugging a failing test,
55 you might want to run it without forking a subprocess.  To do so, use the
56 "--no-fork" option with a single test.  (If you specify it along with
57 multiple tests, they might interfere.)
59 You can turn on logging in the unit tests by passing one of "--debug",
60 "--info", "--notice", or "--warn".  By default only errors are displayed.
62 Unit tests are divided into "./src/test/test" and "./src/test/test-slow".
63 The former are those that should finish in a few seconds; the latter tend to
64 take more time, and may include CPU-intensive operations, deliberate delays,
65 and stuff like that.
67 === Finding test coverage
69 When you configure Tor with the --enable-coverage option, it should
70 build with support for coverage in the unit tests, and in a special
71 "tor-cov" binary.
73 Then, run the tests you'd like to see coverage from.  If you have old
74 coverage output, you may need to run "reset-gcov" first.
76 Now you've got a bunch of files scattered around your build directories
77 called "*.gcda".  In order to extract the coverage output from them, make a
78 temporary directory for them and run "./scripts/test/coverage ${TMPDIR}",
79 where ${TMPDIR} is the temporary directory you made.  This will create a
80 ".gcov" file for each source file under tests, containing that file's source
81 annotated with the number of times the tests hit each line.  (You'll need to
82 have gcov installed.)
84 You can get a summary of the test coverage for each file by running
85 "./scripts/test/cov-display ${TMPDIR}/*" .  Each line lists the file's name,
86 the number of uncovered lines, the number of uncovered lines, and the
87 coverage percentage.
89 For a summary of the test coverage for each _function_, run
90 "./scripts/test/cov-display -f ${TMPDIR}/*" .
92 === Comparing test coverage
94 Sometimes it's useful to compare test coverage for a branch you're writing to
95 coverage from another branch (such as git master, for example).  But you
96 can't run "diff" on the two coverage outputs directly, since the actual
97 number of times each line is executed aren't so important, and aren't wholly
98 deterministic.
100 Instead, follow the instructions above for each branch, creating a separate
101 temporary directory for each.  Then, run "./scripts/test/cov-diff ${D1}
102 ${D2}", where D1 and D2 are the directories you want to compare.  This will
103 produce a diff of the two directories, with all lines normalized to be either
104 covered or uncovered.
106 To count new or modified uncovered lines in D2, you can run:
108     "./scripts/test/cov-diff ${D1} ${D2}" | grep '^+ *\#' |wc -l
111 What kinds of test should I write?
112 ----------------------------------
114 Integration testing and unit testing are complementary: it's probably a
115 good idea to make sure that your code is hit by both if you can.
117 If your code is very-low level, and its behavior is easily described in
118 terms of a relation between inputs and outputs, or a set of state
119 transitions, then it's a natural fit for unit tests.  (If not, please
120 consider refactoring it until most of it _is_ a good fit for unit
121 tests!)
123 If your code adds new externally visible functionality to Tor, it would
124 be great to have a test for that functionality.  That's where
125 integration tests more usually come in.
127 Unit and regression tests: Does this function do what it's supposed to?
128 -----------------------------------------------------------------------
130 Most of Tor's unit tests are made using the "tinytest" testing framework.
131 You can see a guide to using it in the tinytest manual at
133    https://github.com/nmathewson/tinytest/blob/master/tinytest-manual.md
135 To add a new test of this kind, either edit an existing C file in src/test/,
136 or create a new C file there.  Each test is a single function that must
137 be indexed in the table at the end of the file.  We use the label "done:" as
138 a cleanup point for all test functions.
140 (Make sure you read tinytest-manual.md before proceeding.)
142 I use the term "unit test" and "regression tests" very sloppily here.
144 === A simple example
146 Here's an example of a test function for a simple function in util.c:
148     static void
149     test_util_writepid(void *arg)
150     {
151       (void) arg;
153       char *contents = NULL;
154       const char *fname = get_fname("tmp_pid");
155       unsigned long pid;
156       char c;
158       write_pidfile(fname);
160       contents = read_file_to_str(fname, 0, NULL);
161       tt_assert(contents);
163       int n = sscanf(contents, "%lu\n%c", &pid, &c);
164       tt_int_op(n, OP_EQ, 1);
165       tt_int_op(pid, OP_EQ, getpid());
167     done:
168       tor_free(contents);
169     }
171 This should look pretty familiar to you if you've read the tinytest
172 manual.  One thing to note here is that we use the testing-specific
173 function "get_fname" to generate a file with respect to a temporary
174 directory that the tests use.  You don't need to delete the file;
175 it will get removed when the tests are done.
177 Also note our use of OP_EQ instead of == in the tt_int_op() calls.
178 We define OP_* macros to use instead of the binary comparison
179 operators so that analysis tools can more easily parse our code.
180 (Coccinelle really hates to see == used as a macro argument.)
182 Finally, remember that by convention, all *_free() functions that
183 Tor defines are defined to accept NULL harmlessly.  Thus, you don't
184 need to say "if (contents)" in the cleanup block.
186 === Exposing static functions for testing
188 Sometimes you need to test a function, but you don't want to expose
189 it outside its usual module.
191 To support this, Tor's build system compiles a testing version of
192 each module, with extra identifiers exposed.  If you want to
193 declare a function as static but available for testing, use the
194 macro "STATIC" instead of "static".  Then, make sure there's a
195 macro-protected declaration of the function in the module's header.
197 For example, crypto_curve25519.h contains:
199 #ifdef CRYPTO_CURVE25519_PRIVATE
200 STATIC int curve25519_impl(uint8_t *output, const uint8_t *secret,
201                            const uint8_t *basepoint);
202 #endif
204 The crypto_curve25519.c file and the test_crypto.c file both define
205 CRYPTO_CURVE25519_PRIVATE, so they can see this declaration.
207 === Mock functions for testing in isolation
209 Often we want to test that a function works right, but the function to
210 be tested depends on other functions whose behavior is hard to observe,
211 or which require a working Tor network, or something like that.
213 To write tests for this case, you can replace the underlying functions
214 with testing stubs while your unit test is running.  You need to declare
215 the underlying function as 'mockable', as follows:
217    MOCK_DECL(returntype, functionname, (argument list));
219 and then later implement it as:
221     MOCK_IMPL(returntype, functionname, (argument list))
222     {
223        /* implementation here */
224     }
226 For example, if you had a 'connect to remote server' function, you could
227 declare it as:
230    MOCK_DECL(int, connect_to_remote, (const char *name, status_t *status));
232 When you declare a function this way, it will be declared as normal in
233 regular builds, but when the module is built for testing, it is declared
234 as a function pointer initialized to the actual implementation.
236 In your tests, if you want to override the function with a temporary
237 replacement, you say:
239    MOCK(functionname, replacement_function_name);
241 And later, you can restore the original function with:
243    UNMOCK(functionname);
245 For more information, see the definitions of this mocking logic in
246 testsupport.h.
249 === Advanced techniques: Namespaces
251 XXXX write this.  danah boyd made us some really awesome stuff here.
254 Integration tests: Calling Tor from the outside
255 -----------------------------------------------
257 XXXX WRITEME
259 Writing integration tests with Stem
260 -----------------------------------
262 XXXX WRITEME
264 System testing with Chutney
265 ---------------------------
267 XXXX WRITEME
269 Who knows what evil lurks in the timings of networks? The Shadow knows!
270 -----------------------------------------------------------------------
272 XXXX WRITEME