tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

tinytest_demo.c (8480B)


      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 #ifdef _WIN32
     40 #include <windows.h>
     41 #else
     42 #include <unistd.h>
     43 #endif
     44 
     45 /* ============================================================ */
     46 
     47 /* First, let's see if strcmp is working.  (All your test cases should be
     48 * functions declared to take a single void * as an argument.) */
     49 void
     50 test_strcmp(void *data)
     51 {
     52 (void)data; /* This testcase takes no data. */
     53 
     54 /* Let's make sure the empty string is equal to itself */
     55 if (strcmp("","")) {
     56 	/* This macro tells tinytest to stop the current test
     57 	 * and go straight to the "end" label. */
     58 	tt_abort_msg("The empty string was not equal to itself");
     59 }
     60 
     61 /* Pretty often, calling tt_abort_msg to indicate failure is more
     62    heavy-weight than you want.	Instead, just say: */
     63 tt_assert(strcmp("testcase", "testcase") == 0);
     64 
     65 /* Occasionally, you don't want to stop the current testcase just
     66    because a single assertion has failed.  In that case, use
     67    tt_want: */
     68 tt_want(strcmp("tinytest", "testcase") > 0);
     69 
     70 /* You can use the tt_*_op family of macros to compare values and to
     71    fail unless they have the relationship you want.  They produce
     72    more useful output than tt_assert, since they display the actual
     73    values of the failing things.
     74 
     75    Fail unless strcmp("abc, "abc") == 0 */
     76 tt_int_op(strcmp("abc", "abc"), ==, 0);
     77 
     78 /* Fail unless strcmp("abc, "abcd") is less than 0 */
     79 tt_int_op(strcmp("abc", "abcd"), < , 0);
     80 
     81 /* Incidentally, there's a test_str_op that uses strcmp internally. */
     82 tt_str_op("abc", <, "abcd");
     83 
     84 
     85 /* Every test-case function needs to finish with an "end:"
     86    label and (optionally) code to clean up local variables. */
     87 end:
     88 ;
     89 }
     90 
     91 /* ============================================================ */
     92 
     93 /* Now let's mess with setup and teardown functions!  These are handy if
     94   you have a bunch of tests that all need a similar environment, and you
     95   want to reconstruct that environment freshly for each one. */
     96 
     97 /* First you declare a type to hold the environment info, and functions to
     98   set it up and tear it down. */
     99 struct data_buffer {
    100 /* We're just going to have couple of character buffer.	 Using
    101    setup/teardown functions is probably overkill for this case.
    102 
    103    You could also do file descriptors, complicated handles, temporary
    104    files, etc. */
    105 char buffer1[512];
    106 char buffer2[512];
    107 };
    108 /* The setup function needs to take a const struct testcase_t and return
    109   void* */
    110 void *
    111 setup_data_buffer(const struct testcase_t *testcase)
    112 {
    113 struct data_buffer *db = malloc(sizeof(struct data_buffer));
    114 
    115 /* If you had a complicated set of setup rules, you might behave
    116    differently here depending on testcase->flags or
    117    testcase->setup_data or even or testcase->name. */
    118 
    119 /* Returning a NULL here would mean that we couldn't set up for this
    120    test, so we don't need to test db for null. */
    121 return db;
    122 }
    123 /* The clean function deallocates storage carefully and returns true on
    124   success. */
    125 int
    126 clean_data_buffer(const struct testcase_t *testcase, void *ptr)
    127 {
    128 struct data_buffer *db = ptr;
    129 
    130 if (db) {
    131 	free(db);
    132 	return 1;
    133 }
    134 return 0;
    135 }
    136 /* Finally, declare a testcase_setup_t with these functions. */
    137 struct testcase_setup_t data_buffer_setup = {
    138 setup_data_buffer, clean_data_buffer
    139 };
    140 
    141 
    142 /* Now let's write our test. */
    143 void
    144 test_memcpy(void *ptr)
    145 {
    146 /* This time, we use the argument. */
    147 struct data_buffer *db = ptr;
    148 
    149 /* We'll also introduce a local variable that might need cleaning up. */
    150 char *mem = NULL;
    151 
    152 /* Let's make sure that memcpy does what we'd like. */
    153 strcpy(db->buffer1, "String 0");
    154 memcpy(db->buffer2, db->buffer1, sizeof(db->buffer1));
    155 tt_str_op(db->buffer1, ==, db->buffer2);
    156 
    157        /* This one works if there's an internal NUL. */
    158        tt_mem_op(db->buffer1, <, db->buffer2, sizeof(db->buffer1));
    159 
    160 /* Now we've allocated memory that's referenced by a local variable.
    161    The end block of the function will clean it up. */
    162 mem = strdup("Hello world.");
    163 tt_assert(mem);
    164 
    165 /* Another rather trivial test. */
    166 tt_str_op(db->buffer1, !=, mem);
    167 
    168 end:
    169 /* This time our end block has something to do. */
    170 if (mem)
    171 	free(mem);
    172 }
    173 
    174 void
    175 test_timeout(void *ptr)
    176 {
    177 time_t t1, t2;
    178 (void)ptr;
    179 t1 = time(NULL);
    180 #ifdef _WIN32
    181 Sleep(5000);
    182 #else
    183 sleep(5);
    184 #endif
    185 t2 = time(NULL);
    186 
    187 tt_int_op(t2-t1, >=, 4);
    188 
    189 tt_int_op(t2-t1, <=, 6);
    190 
    191 end:
    192 ;
    193 }
    194 
    195 void
    196 test_timeout_retry(void *ptr)
    197 {
    198 static int i = 0;
    199 
    200 ++i;
    201 tt_int_op(i, !=, 1);
    202 
    203 time_t t1, t2;
    204 (void)ptr;
    205 t1 = time(NULL);
    206 #ifdef _WIN32
    207 Sleep(5000);
    208 #else
    209 sleep(5);
    210 #endif
    211 t2 = time(NULL);
    212 
    213 tt_int_op(t2-t1, >=, 4);
    214 
    215 tt_int_op(t2-t1, <=, 6);
    216 
    217 end:
    218 ;
    219 }
    220 
    221 /* ============================================================ */
    222 
    223 /* Now we need to make sure that our tests get invoked.	  First, you take
    224   a bunch of related tests and put them into an array of struct testcase_t.
    225 */
    226 
    227 struct testcase_t demo_tests[] = {
    228 /* Here's a really simple test: it has a name you can refer to it
    229    with, and a function to invoke it. */
    230 { "strcmp", test_strcmp, },
    231 
    232 /* The second test has a flag, "TT_FORK", to make it run in a
    233    subprocess, and a pointer to the testcase_setup_t that configures
    234    its environment. */
    235 { "memcpy", test_memcpy, TT_FORK, &data_buffer_setup },
    236 
    237 /* This flag is off-by-default, since it takes a while to run.	You
    238  * can enable it manually by passing +demo/timeout at the command line.*/
    239 { "timeout", test_timeout, TT_OFF_BY_DEFAULT },
    240 
    241 /* This test will be retried. (and it will not pass from the first
    242  * time) */
    243 { "timeout_retry", test_timeout_retry, TT_RETRIABLE },
    244 
    245 /* The array has to end with END_OF_TESTCASES. */
    246 END_OF_TESTCASES
    247 };
    248 
    249 /* Next, we make an array of testgroups.  This is mandatory.  Unlike more
    250   heavy-duty testing frameworks, groups can't nest. */
    251 struct testgroup_t groups[] = {
    252 
    253 /* Every group has a 'prefix', and an array of tests.  That's it. */
    254 { "demo/", demo_tests },
    255 
    256 END_OF_GROUPS
    257 };
    258 
    259 /* We can also define test aliases. These can be used for types of tests that
    260 * cut across groups. */
    261 const char *alltests[] = { "+..", NULL };
    262 const char *slowtests[] = { "+demo/timeout", NULL };
    263 struct testlist_alias_t aliases[] = {
    264 
    265 { "ALL", alltests },
    266 { "SLOW", slowtests },
    267 
    268 END_OF_ALIASES
    269 };
    270 
    271 
    272 int
    273 main(int c, const char **v)
    274 {
    275 /* Finally, just call tinytest_main().	It lets you specify verbose
    276    or quiet output with --verbose and --quiet.	You can list
    277    specific tests:
    278 
    279        tinytest-demo demo/memcpy
    280 
    281    or use a ..-wildcard to select multiple tests with a common
    282    prefix:
    283 
    284        tinytest-demo demo/..
    285 
    286    If you list no tests, you get them all by default, so that
    287    "tinytest-demo" and "tinytest-demo .." mean the same thing.
    288 
    289 */
    290 tinytest_set_aliases(aliases);
    291 return tinytest_main(c, v, groups);
    292 }