Tor  0.4.6.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.) */
50 void
51 test_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. */
100 struct data_buffer {
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* */
111 void *
112 setup_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. */
126 int
127 clean_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. */
138 struct testcase_setup_t data_buffer_setup = {
139  setup_data_buffer, clean_data_buffer
140 };
141 
142 
143 /* Now let's write our test. */
144 void
145 test_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 
176 void
177 test_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 
203 struct 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. */
223 struct 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. */
233 const char *alltests[] = { "+..", NULL };
234 const char *slowtests[] = { "+demo/timeout", NULL };
235 struct testlist_alias_t aliases[] = {
236 
237  { "ALL", alltests },
238  { "SLOW", slowtests },
239 
240  END_OF_ALIASES
241 };
242 
243 
244 int
245 main(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 }
data_buffer
Definition: tinytest_demo.c:100
testcase_t
Definition: tinytest.h:53
time.h
Definitions for timing-related constants.
testcase_setup_t
Definition: tinytest.h:45
testgroup_t
Definition: tinytest.h:63
main
int main(int argc, char *argv[])
Definition: tor_main.c:25
testlist_alias_t
Definition: tinytest.h:69