Tor 0.4.9.0-alpha-dev
tinytest_demo.c
1/* tinytest_demo.c -- Copyright 2009-2012 Nick Mathewson
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
5 * are met:
6 * 1. Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * 2. Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * 3. The name of the author may not be used to endorse or promote products
12 * derived from this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26
27/* Welcome to the example file for tinytest! I'll show you how to set up
28 * some simple and not-so-simple testcases. */
29
30/* Make sure you include these headers. */
31#include "tinytest.h"
32#include "tinytest_macros.h"
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <errno.h>
38#include <time.h>
39
40#ifdef _WIN32
41#include <windows.h>
42#else
43#include <unistd.h>
44#endif
45
46/* ============================================================ */
47
48/* First, let's see if strcmp is working. (All your test cases should be
49 * functions declared to take a single void * as an argument.) */
50void
51test_strcmp(void *data)
52{
53 (void)data; /* This testcase takes no data. */
54
55 /* Let's make sure the empty string is equal to itself */
56 if (strcmp("","")) {
57 /* This macro tells tinytest to stop the current test
58 * and go straight to the "end" label. */
59 tt_abort_msg("The empty string was not equal to itself");
60 }
61
62 /* Pretty often, calling tt_abort_msg to indicate failure is more
63 heavy-weight than you want. Instead, just say: */
64 tt_assert(strcmp("testcase", "testcase") == 0);
65
66 /* Occasionally, you don't want to stop the current testcase just
67 because a single assertion has failed. In that case, use
68 tt_want: */
69 tt_want(strcmp("tinytest", "testcase") > 0);
70
71 /* You can use the tt_*_op family of macros to compare values and to
72 fail unless they have the relationship you want. They produce
73 more useful output than tt_assert, since they display the actual
74 values of the failing things.
75
76 Fail unless strcmp("abc, "abc") == 0 */
77 tt_int_op(strcmp("abc", "abc"), OP_EQ, 0);
78
79 /* Fail unless strcmp("abc, "abcd") is less than 0 */
80 tt_int_op(strcmp("abc", "abcd"), OP_LT, 0);
81
82 /* Incidentally, there's a test_str_op that uses strcmp internally. */
83 tt_str_op("abc", OP_LT, "abcd");
84
85
86 /* Every test-case function needs to finish with an "end:"
87 label and (optionally) code to clean up local variables. */
88 end:
89 ;
90}
91
92/* ============================================================ */
93
94/* Now let's mess with setup and teardown functions! These are handy if
95 you have a bunch of tests that all need a similar environment, and you
96 want to reconstruct that environment freshly for each one. */
97
98/* First you declare a type to hold the environment info, and functions to
99 set it up and tear it down. */
101 /* We're just going to have couple of character buffer. Using
102 setup/teardown functions is probably overkill for this case.
103
104 You could also do file descriptors, complicated handles, temporary
105 files, etc. */
106 char buffer1[512];
107 char buffer2[512];
108};
109/* The setup function needs to take a const struct testcase_t and return
110 void* */
111void *
112setup_data_buffer(const struct testcase_t *testcase)
113{
114 struct data_buffer *db = malloc(sizeof(struct data_buffer));
115
116 /* If you had a complicated set of setup rules, you might behave
117 differently here depending on testcase->flags or
118 testcase->setup_data or even or testcase->name. */
119
120 /* Returning a NULL here would mean that we couldn't set up for this
121 test, so we don't need to test db for null. */
122 return db;
123}
124/* The clean function deallocates storage carefully and returns true on
125 success. */
126int
127clean_data_buffer(const struct testcase_t *testcase, void *ptr)
128{
129 struct data_buffer *db = ptr;
130
131 if (db) {
132 free(db);
133 return 1;
134 }
135 return 0;
136}
137/* Finally, declare a testcase_setup_t with these functions. */
138struct testcase_setup_t data_buffer_setup = {
139 setup_data_buffer, clean_data_buffer
140};
141
142
143/* Now let's write our test. */
144void
145test_memcpy(void *ptr)
146{
147 /* This time, we use the argument. */
148 struct data_buffer *db = ptr;
149
150 /* We'll also introduce a local variable that might need cleaning up. */
151 char *mem = NULL;
152
153 /* Let's make sure that memcpy does what we'd like. */
154 strcpy(db->buffer1, "String 0");
155 memcpy(db->buffer2, db->buffer1, sizeof(db->buffer1));
156 tt_str_op(db->buffer1, OP_EQ, db->buffer2);
157
158 /* tt_mem_op() does a memcmp, as opposed to the strcmp in tt_str_op() */
159 db->buffer2[100] = 3; /* Make the buffers unequal */
160 tt_mem_op(db->buffer1, OP_LT, db->buffer2, sizeof(db->buffer1));
161
162 /* Now we've allocated memory that's referenced by a local variable.
163 The end block of the function will clean it up. */
164 mem = strdup("Hello world.");
165 tt_assert(mem);
166
167 /* Another rather trivial test. */
168 tt_str_op(db->buffer1, OP_NE, mem);
169
170 end:
171 /* This time our end block has something to do. */
172 if (mem)
173 free(mem);
174}
175
176void
177test_timeout(void *ptr)
178{
179 time_t t1, t2;
180 (void)ptr;
181 t1 = time(NULL);
182#ifdef _WIN32
183 Sleep(5000);
184#else
185 sleep(5);
186#endif
187 t2 = time(NULL);
188
189 tt_int_op(t2-t1, OP_GE, 4);
190
191 tt_int_op(t2-t1, OP_LE, 6);
192
193 end:
194 ;
195}
196
197/* ============================================================ */
198
199/* Now we need to make sure that our tests get invoked. First, you take
200 a bunch of related tests and put them into an array of struct testcase_t.
201*/
202
203struct testcase_t demo_tests[] = {
204 /* Here's a really simple test: it has a name you can refer to it
205 with, and a function to invoke it. */
206 { "strcmp", test_strcmp, },
207
208 /* The second test has a flag, "TT_FORK", to make it run in a
209 subprocess, and a pointer to the testcase_setup_t that configures
210 its environment. */
211 { "memcpy", test_memcpy, TT_FORK, &data_buffer_setup },
212
213 /* This flag is off-by-default, since it takes a while to run. You
214 * can enable it manually by passing +demo/timeout at the command line.*/
215 { "timeout", test_timeout, TT_OFF_BY_DEFAULT },
216
217 /* The array has to end with END_OF_TESTCASES. */
218 END_OF_TESTCASES
219};
220
221/* Next, we make an array of testgroups. This is mandatory. Unlike more
222 heavy-duty testing frameworks, groups can't nest. */
223struct testgroup_t groups[] = {
224
225 /* Every group has a 'prefix', and an array of tests. That's it. */
226 { "demo/", demo_tests },
227
228 END_OF_GROUPS
229};
230
231/* We can also define test aliases. These can be used for types of tests that
232 * cut across groups. */
233const char *alltests[] = { "+..", NULL };
234const char *slowtests[] = { "+demo/timeout", NULL };
235struct testlist_alias_t aliases[] = {
236
237 { "ALL", alltests },
238 { "SLOW", slowtests },
239
240 END_OF_ALIASES
241};
242
243
244int
245main(int c, const char **v)
246{
247 /* Finally, just call tinytest_main(). It lets you specify verbose
248 or quiet output with --verbose and --quiet. You can list
249 specific tests:
250
251 tinytest-demo demo/memcpy
252
253 or use a ..-wildcard to select multiple tests with a common
254 prefix:
255
256 tinytest-demo demo/..
257
258 If you list no tests, you get them all by default, so that
259 "tinytest-demo" and "tinytest-demo .." mean the same thing.
260
261 */
262 tinytest_set_aliases(aliases);
263 return tinytest_main(c, v, groups);
264}
Definitions for timing-related constants.
int main(int argc, char *argv[])
Definition: tor_main.c:25