1*2b15cb3dSCy Schubert /* tinytest.c -- Copyright 2009-2012 Nick Mathewson 2*2b15cb3dSCy Schubert * 3*2b15cb3dSCy Schubert * Redistribution and use in source and binary forms, with or without 4*2b15cb3dSCy Schubert * modification, are permitted provided that the following conditions 5*2b15cb3dSCy Schubert * are met: 6*2b15cb3dSCy Schubert * 1. Redistributions of source code must retain the above copyright 7*2b15cb3dSCy Schubert * notice, this list of conditions and the following disclaimer. 8*2b15cb3dSCy Schubert * 2. Redistributions in binary form must reproduce the above copyright 9*2b15cb3dSCy Schubert * notice, this list of conditions and the following disclaimer in the 10*2b15cb3dSCy Schubert * documentation and/or other materials provided with the distribution. 11*2b15cb3dSCy Schubert * 3. The name of the author may not be used to endorse or promote products 12*2b15cb3dSCy Schubert * derived from this software without specific prior written permission. 13*2b15cb3dSCy Schubert * 14*2b15cb3dSCy Schubert * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15*2b15cb3dSCy Schubert * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16*2b15cb3dSCy Schubert * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17*2b15cb3dSCy Schubert * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18*2b15cb3dSCy Schubert * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19*2b15cb3dSCy Schubert * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20*2b15cb3dSCy Schubert * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21*2b15cb3dSCy Schubert * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22*2b15cb3dSCy Schubert * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23*2b15cb3dSCy Schubert * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24*2b15cb3dSCy Schubert */ 25*2b15cb3dSCy Schubert #ifdef TINYTEST_LOCAL 26*2b15cb3dSCy Schubert #include "tinytest_local.h" 27*2b15cb3dSCy Schubert #endif 28*2b15cb3dSCy Schubert 29*2b15cb3dSCy Schubert #include <stdio.h> 30*2b15cb3dSCy Schubert #include <stdlib.h> 31*2b15cb3dSCy Schubert #include <string.h> 32*2b15cb3dSCy Schubert #include <assert.h> 33*2b15cb3dSCy Schubert 34*2b15cb3dSCy Schubert #ifdef _WIN32 35*2b15cb3dSCy Schubert #include <windows.h> 36*2b15cb3dSCy Schubert #else 37*2b15cb3dSCy Schubert #include <sys/types.h> 38*2b15cb3dSCy Schubert #include <sys/wait.h> 39*2b15cb3dSCy Schubert #include <unistd.h> 40*2b15cb3dSCy Schubert #endif 41*2b15cb3dSCy Schubert 42*2b15cb3dSCy Schubert #if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) 43*2b15cb3dSCy Schubert #if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \ 44*2b15cb3dSCy Schubert __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070) 45*2b15cb3dSCy Schubert /* Workaround for a stupid bug in OSX 10.6 */ 46*2b15cb3dSCy Schubert #define FORK_BREAKS_GCOV 47*2b15cb3dSCy Schubert #include <vproc.h> 48*2b15cb3dSCy Schubert #endif 49*2b15cb3dSCy Schubert #endif 50*2b15cb3dSCy Schubert 51*2b15cb3dSCy Schubert #ifndef __GNUC__ 52*2b15cb3dSCy Schubert #define __attribute__(x) 53*2b15cb3dSCy Schubert #endif 54*2b15cb3dSCy Schubert 55*2b15cb3dSCy Schubert #include "tinytest.h" 56*2b15cb3dSCy Schubert #include "tinytest_macros.h" 57*2b15cb3dSCy Schubert 58*2b15cb3dSCy Schubert #define LONGEST_TEST_NAME 16384 59*2b15cb3dSCy Schubert 60*2b15cb3dSCy Schubert static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/ 61*2b15cb3dSCy Schubert static int n_ok = 0; /**< Number of tests that have passed */ 62*2b15cb3dSCy Schubert static int n_bad = 0; /**< Number of tests that have failed. */ 63*2b15cb3dSCy Schubert static int n_skipped = 0; /**< Number of tests that have been skipped. */ 64*2b15cb3dSCy Schubert 65*2b15cb3dSCy Schubert static int opt_forked = 0; /**< True iff we're called from inside a win32 fork*/ 66*2b15cb3dSCy Schubert static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */ 67*2b15cb3dSCy Schubert static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */ 68*2b15cb3dSCy Schubert const char *verbosity_flag = ""; 69*2b15cb3dSCy Schubert 70*2b15cb3dSCy Schubert const struct testlist_alias_t *cfg_aliases=NULL; 71*2b15cb3dSCy Schubert 72*2b15cb3dSCy Schubert enum outcome { SKIP=2, OK=1, FAIL=0 }; 73*2b15cb3dSCy Schubert static enum outcome cur_test_outcome = 0; 74*2b15cb3dSCy Schubert const char *cur_test_prefix = NULL; /**< prefix of the current test group */ 75*2b15cb3dSCy Schubert /** Name of the current test, if we haven't logged is yet. Used for --quiet */ 76*2b15cb3dSCy Schubert const char *cur_test_name = NULL; 77*2b15cb3dSCy Schubert 78*2b15cb3dSCy Schubert #ifdef _WIN32 79*2b15cb3dSCy Schubert /* Copy of argv[0] for win32. */ 80*2b15cb3dSCy Schubert static char commandname[MAX_PATH+1]; 81*2b15cb3dSCy Schubert #endif 82*2b15cb3dSCy Schubert 83*2b15cb3dSCy Schubert static void usage(struct testgroup_t *groups, int list_groups) 84*2b15cb3dSCy Schubert __attribute__((noreturn)); 85*2b15cb3dSCy Schubert static int process_test_option(struct testgroup_t *groups, const char *test); 86*2b15cb3dSCy Schubert 87*2b15cb3dSCy Schubert static enum outcome 88*2b15cb3dSCy Schubert testcase_run_bare_(const struct testcase_t *testcase) 89*2b15cb3dSCy Schubert { 90*2b15cb3dSCy Schubert void *env = NULL; 91*2b15cb3dSCy Schubert int outcome; 92*2b15cb3dSCy Schubert if (testcase->setup) { 93*2b15cb3dSCy Schubert env = testcase->setup->setup_fn(testcase); 94*2b15cb3dSCy Schubert if (!env) 95*2b15cb3dSCy Schubert return FAIL; 96*2b15cb3dSCy Schubert else if (env == (void*)TT_SKIP) 97*2b15cb3dSCy Schubert return SKIP; 98*2b15cb3dSCy Schubert } 99*2b15cb3dSCy Schubert 100*2b15cb3dSCy Schubert cur_test_outcome = OK; 101*2b15cb3dSCy Schubert testcase->fn(env); 102*2b15cb3dSCy Schubert outcome = cur_test_outcome; 103*2b15cb3dSCy Schubert 104*2b15cb3dSCy Schubert if (testcase->setup) { 105*2b15cb3dSCy Schubert if (testcase->setup->cleanup_fn(testcase, env) == 0) 106*2b15cb3dSCy Schubert outcome = FAIL; 107*2b15cb3dSCy Schubert } 108*2b15cb3dSCy Schubert 109*2b15cb3dSCy Schubert return outcome; 110*2b15cb3dSCy Schubert } 111*2b15cb3dSCy Schubert 112*2b15cb3dSCy Schubert #define MAGIC_EXITCODE 42 113*2b15cb3dSCy Schubert 114*2b15cb3dSCy Schubert static enum outcome 115*2b15cb3dSCy Schubert testcase_run_forked_(const struct testgroup_t *group, 116*2b15cb3dSCy Schubert const struct testcase_t *testcase) 117*2b15cb3dSCy Schubert { 118*2b15cb3dSCy Schubert #ifdef _WIN32 119*2b15cb3dSCy Schubert /* Fork? On Win32? How primitive! We'll do what the smart kids do: 120*2b15cb3dSCy Schubert we'll invoke our own exe (whose name we recall from the command 121*2b15cb3dSCy Schubert line) with a command line that tells it to run just the test we 122*2b15cb3dSCy Schubert want, and this time without forking. 123*2b15cb3dSCy Schubert 124*2b15cb3dSCy Schubert (No, threads aren't an option. The whole point of forking is to 125*2b15cb3dSCy Schubert share no state between tests.) 126*2b15cb3dSCy Schubert */ 127*2b15cb3dSCy Schubert int ok; 128*2b15cb3dSCy Schubert char buffer[LONGEST_TEST_NAME+256]; 129*2b15cb3dSCy Schubert STARTUPINFOA si; 130*2b15cb3dSCy Schubert PROCESS_INFORMATION info; 131*2b15cb3dSCy Schubert DWORD exitcode; 132*2b15cb3dSCy Schubert 133*2b15cb3dSCy Schubert if (!in_tinytest_main) { 134*2b15cb3dSCy Schubert printf("\nERROR. On Windows, testcase_run_forked_ must be" 135*2b15cb3dSCy Schubert " called from within tinytest_main.\n"); 136*2b15cb3dSCy Schubert abort(); 137*2b15cb3dSCy Schubert } 138*2b15cb3dSCy Schubert if (opt_verbosity>0) 139*2b15cb3dSCy Schubert printf("[forking] "); 140*2b15cb3dSCy Schubert 141*2b15cb3dSCy Schubert snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s", 142*2b15cb3dSCy Schubert commandname, verbosity_flag, group->prefix, testcase->name); 143*2b15cb3dSCy Schubert 144*2b15cb3dSCy Schubert memset(&si, 0, sizeof(si)); 145*2b15cb3dSCy Schubert memset(&info, 0, sizeof(info)); 146*2b15cb3dSCy Schubert si.cb = sizeof(si); 147*2b15cb3dSCy Schubert 148*2b15cb3dSCy Schubert ok = CreateProcessA(commandname, buffer, NULL, NULL, 0, 149*2b15cb3dSCy Schubert 0, NULL, NULL, &si, &info); 150*2b15cb3dSCy Schubert if (!ok) { 151*2b15cb3dSCy Schubert printf("CreateProcess failed!\n"); 152*2b15cb3dSCy Schubert return 0; 153*2b15cb3dSCy Schubert } 154*2b15cb3dSCy Schubert WaitForSingleObject(info.hProcess, INFINITE); 155*2b15cb3dSCy Schubert GetExitCodeProcess(info.hProcess, &exitcode); 156*2b15cb3dSCy Schubert CloseHandle(info.hProcess); 157*2b15cb3dSCy Schubert CloseHandle(info.hThread); 158*2b15cb3dSCy Schubert if (exitcode == 0) 159*2b15cb3dSCy Schubert return OK; 160*2b15cb3dSCy Schubert else if (exitcode == MAGIC_EXITCODE) 161*2b15cb3dSCy Schubert return SKIP; 162*2b15cb3dSCy Schubert else 163*2b15cb3dSCy Schubert return FAIL; 164*2b15cb3dSCy Schubert #else 165*2b15cb3dSCy Schubert int outcome_pipe[2]; 166*2b15cb3dSCy Schubert pid_t pid; 167*2b15cb3dSCy Schubert (void)group; 168*2b15cb3dSCy Schubert 169*2b15cb3dSCy Schubert if (pipe(outcome_pipe)) 170*2b15cb3dSCy Schubert perror("opening pipe"); 171*2b15cb3dSCy Schubert 172*2b15cb3dSCy Schubert if (opt_verbosity>0) 173*2b15cb3dSCy Schubert printf("[forking] "); 174*2b15cb3dSCy Schubert pid = fork(); 175*2b15cb3dSCy Schubert #ifdef FORK_BREAKS_GCOV 176*2b15cb3dSCy Schubert vproc_transaction_begin(0); 177*2b15cb3dSCy Schubert #endif 178*2b15cb3dSCy Schubert if (!pid) { 179*2b15cb3dSCy Schubert /* child. */ 180*2b15cb3dSCy Schubert int test_r, write_r; 181*2b15cb3dSCy Schubert char b[1]; 182*2b15cb3dSCy Schubert close(outcome_pipe[0]); 183*2b15cb3dSCy Schubert test_r = testcase_run_bare_(testcase); 184*2b15cb3dSCy Schubert assert(0<=(int)test_r && (int)test_r<=2); 185*2b15cb3dSCy Schubert b[0] = "NYS"[test_r]; 186*2b15cb3dSCy Schubert write_r = (int)write(outcome_pipe[1], b, 1); 187*2b15cb3dSCy Schubert if (write_r != 1) { 188*2b15cb3dSCy Schubert perror("write outcome to pipe"); 189*2b15cb3dSCy Schubert exit(1); 190*2b15cb3dSCy Schubert } 191*2b15cb3dSCy Schubert exit(0); 192*2b15cb3dSCy Schubert return FAIL; /* unreachable */ 193*2b15cb3dSCy Schubert } else { 194*2b15cb3dSCy Schubert /* parent */ 195*2b15cb3dSCy Schubert int status, r; 196*2b15cb3dSCy Schubert char b[1]; 197*2b15cb3dSCy Schubert /* Close this now, so that if the other side closes it, 198*2b15cb3dSCy Schubert * our read fails. */ 199*2b15cb3dSCy Schubert close(outcome_pipe[1]); 200*2b15cb3dSCy Schubert r = (int)read(outcome_pipe[0], b, 1); 201*2b15cb3dSCy Schubert if (r == 0) { 202*2b15cb3dSCy Schubert printf("[Lost connection!] "); 203*2b15cb3dSCy Schubert return 0; 204*2b15cb3dSCy Schubert } else if (r != 1) { 205*2b15cb3dSCy Schubert perror("read outcome from pipe"); 206*2b15cb3dSCy Schubert } 207*2b15cb3dSCy Schubert waitpid(pid, &status, 0); 208*2b15cb3dSCy Schubert close(outcome_pipe[0]); 209*2b15cb3dSCy Schubert return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL); 210*2b15cb3dSCy Schubert } 211*2b15cb3dSCy Schubert #endif 212*2b15cb3dSCy Schubert } 213*2b15cb3dSCy Schubert 214*2b15cb3dSCy Schubert int 215*2b15cb3dSCy Schubert testcase_run_one(const struct testgroup_t *group, 216*2b15cb3dSCy Schubert const struct testcase_t *testcase) 217*2b15cb3dSCy Schubert { 218*2b15cb3dSCy Schubert enum outcome outcome; 219*2b15cb3dSCy Schubert 220*2b15cb3dSCy Schubert if (testcase->flags & (TT_SKIP|TT_OFF_BY_DEFAULT)) { 221*2b15cb3dSCy Schubert if (opt_verbosity>0) 222*2b15cb3dSCy Schubert printf("%s%s: %s\n", 223*2b15cb3dSCy Schubert group->prefix, testcase->name, 224*2b15cb3dSCy Schubert (testcase->flags & TT_SKIP) ? "SKIPPED" : "DISABLED"); 225*2b15cb3dSCy Schubert ++n_skipped; 226*2b15cb3dSCy Schubert return SKIP; 227*2b15cb3dSCy Schubert } 228*2b15cb3dSCy Schubert 229*2b15cb3dSCy Schubert if (opt_verbosity>0 && !opt_forked) { 230*2b15cb3dSCy Schubert printf("%s%s: ", group->prefix, testcase->name); 231*2b15cb3dSCy Schubert } else { 232*2b15cb3dSCy Schubert if (opt_verbosity==0) printf("."); 233*2b15cb3dSCy Schubert cur_test_prefix = group->prefix; 234*2b15cb3dSCy Schubert cur_test_name = testcase->name; 235*2b15cb3dSCy Schubert } 236*2b15cb3dSCy Schubert 237*2b15cb3dSCy Schubert if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) { 238*2b15cb3dSCy Schubert outcome = testcase_run_forked_(group, testcase); 239*2b15cb3dSCy Schubert } else { 240*2b15cb3dSCy Schubert outcome = testcase_run_bare_(testcase); 241*2b15cb3dSCy Schubert } 242*2b15cb3dSCy Schubert 243*2b15cb3dSCy Schubert if (outcome == OK) { 244*2b15cb3dSCy Schubert ++n_ok; 245*2b15cb3dSCy Schubert if (opt_verbosity>0 && !opt_forked) 246*2b15cb3dSCy Schubert puts(opt_verbosity==1?"OK":""); 247*2b15cb3dSCy Schubert } else if (outcome == SKIP) { 248*2b15cb3dSCy Schubert ++n_skipped; 249*2b15cb3dSCy Schubert if (opt_verbosity>0 && !opt_forked) 250*2b15cb3dSCy Schubert puts("SKIPPED"); 251*2b15cb3dSCy Schubert } else { 252*2b15cb3dSCy Schubert ++n_bad; 253*2b15cb3dSCy Schubert if (!opt_forked) 254*2b15cb3dSCy Schubert printf("\n [%s FAILED]\n", testcase->name); 255*2b15cb3dSCy Schubert } 256*2b15cb3dSCy Schubert 257*2b15cb3dSCy Schubert if (opt_forked) { 258*2b15cb3dSCy Schubert exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1)); 259*2b15cb3dSCy Schubert return 1; /* unreachable */ 260*2b15cb3dSCy Schubert } else { 261*2b15cb3dSCy Schubert return (int)outcome; 262*2b15cb3dSCy Schubert } 263*2b15cb3dSCy Schubert } 264*2b15cb3dSCy Schubert 265*2b15cb3dSCy Schubert int 266*2b15cb3dSCy Schubert tinytest_set_flag_(struct testgroup_t *groups, const char *arg, int set, unsigned long flag) 267*2b15cb3dSCy Schubert { 268*2b15cb3dSCy Schubert int i, j; 269*2b15cb3dSCy Schubert size_t length = LONGEST_TEST_NAME; 270*2b15cb3dSCy Schubert char fullname[LONGEST_TEST_NAME]; 271*2b15cb3dSCy Schubert int found=0; 272*2b15cb3dSCy Schubert if (strstr(arg, "..")) 273*2b15cb3dSCy Schubert length = strstr(arg,"..")-arg; 274*2b15cb3dSCy Schubert for (i=0; groups[i].prefix; ++i) { 275*2b15cb3dSCy Schubert for (j=0; groups[i].cases[j].name; ++j) { 276*2b15cb3dSCy Schubert struct testcase_t *testcase = &groups[i].cases[j]; 277*2b15cb3dSCy Schubert snprintf(fullname, sizeof(fullname), "%s%s", 278*2b15cb3dSCy Schubert groups[i].prefix, testcase->name); 279*2b15cb3dSCy Schubert if (!flag) { /* Hack! */ 280*2b15cb3dSCy Schubert printf(" %s", fullname); 281*2b15cb3dSCy Schubert if (testcase->flags & TT_OFF_BY_DEFAULT) 282*2b15cb3dSCy Schubert puts(" (Off by default)"); 283*2b15cb3dSCy Schubert else if (testcase->flags & TT_SKIP) 284*2b15cb3dSCy Schubert puts(" (DISABLED)"); 285*2b15cb3dSCy Schubert else 286*2b15cb3dSCy Schubert puts(""); 287*2b15cb3dSCy Schubert } 288*2b15cb3dSCy Schubert if (!strncmp(fullname, arg, length)) { 289*2b15cb3dSCy Schubert if (set) 290*2b15cb3dSCy Schubert testcase->flags |= flag; 291*2b15cb3dSCy Schubert else 292*2b15cb3dSCy Schubert testcase->flags &= ~flag; 293*2b15cb3dSCy Schubert ++found; 294*2b15cb3dSCy Schubert } 295*2b15cb3dSCy Schubert } 296*2b15cb3dSCy Schubert } 297*2b15cb3dSCy Schubert return found; 298*2b15cb3dSCy Schubert } 299*2b15cb3dSCy Schubert 300*2b15cb3dSCy Schubert static void 301*2b15cb3dSCy Schubert usage(struct testgroup_t *groups, int list_groups) 302*2b15cb3dSCy Schubert { 303*2b15cb3dSCy Schubert puts("Options are: [--verbose|--quiet|--terse] [--no-fork]"); 304*2b15cb3dSCy Schubert puts(" Specify tests by name, or using a prefix ending with '..'"); 305*2b15cb3dSCy Schubert puts(" To skip a test, prefix its name with a colon."); 306*2b15cb3dSCy Schubert puts(" To enable a disabled test, prefix its name with a plus."); 307*2b15cb3dSCy Schubert puts(" Use --list-tests for a list of tests."); 308*2b15cb3dSCy Schubert if (list_groups) { 309*2b15cb3dSCy Schubert puts("Known tests are:"); 310*2b15cb3dSCy Schubert tinytest_set_flag_(groups, "..", 1, 0); 311*2b15cb3dSCy Schubert } 312*2b15cb3dSCy Schubert exit(0); 313*2b15cb3dSCy Schubert } 314*2b15cb3dSCy Schubert 315*2b15cb3dSCy Schubert static int 316*2b15cb3dSCy Schubert process_test_alias(struct testgroup_t *groups, const char *test) 317*2b15cb3dSCy Schubert { 318*2b15cb3dSCy Schubert int i, j, n, r; 319*2b15cb3dSCy Schubert for (i=0; cfg_aliases && cfg_aliases[i].name; ++i) { 320*2b15cb3dSCy Schubert if (!strcmp(cfg_aliases[i].name, test)) { 321*2b15cb3dSCy Schubert n = 0; 322*2b15cb3dSCy Schubert for (j = 0; cfg_aliases[i].tests[j]; ++j) { 323*2b15cb3dSCy Schubert r = process_test_option(groups, cfg_aliases[i].tests[j]); 324*2b15cb3dSCy Schubert if (r<0) 325*2b15cb3dSCy Schubert return -1; 326*2b15cb3dSCy Schubert n += r; 327*2b15cb3dSCy Schubert } 328*2b15cb3dSCy Schubert return n; 329*2b15cb3dSCy Schubert } 330*2b15cb3dSCy Schubert } 331*2b15cb3dSCy Schubert printf("No such test alias as @%s!",test); 332*2b15cb3dSCy Schubert return -1; 333*2b15cb3dSCy Schubert } 334*2b15cb3dSCy Schubert 335*2b15cb3dSCy Schubert static int 336*2b15cb3dSCy Schubert process_test_option(struct testgroup_t *groups, const char *test) 337*2b15cb3dSCy Schubert { 338*2b15cb3dSCy Schubert int flag = TT_ENABLED_; 339*2b15cb3dSCy Schubert int n = 0; 340*2b15cb3dSCy Schubert if (test[0] == '@') { 341*2b15cb3dSCy Schubert return process_test_alias(groups, test + 1); 342*2b15cb3dSCy Schubert } else if (test[0] == ':') { 343*2b15cb3dSCy Schubert ++test; 344*2b15cb3dSCy Schubert flag = TT_SKIP; 345*2b15cb3dSCy Schubert } else if (test[0] == '+') { 346*2b15cb3dSCy Schubert ++test; 347*2b15cb3dSCy Schubert ++n; 348*2b15cb3dSCy Schubert if (!tinytest_set_flag_(groups, test, 0, TT_OFF_BY_DEFAULT)) { 349*2b15cb3dSCy Schubert printf("No such test as %s!\n", test); 350*2b15cb3dSCy Schubert return -1; 351*2b15cb3dSCy Schubert } 352*2b15cb3dSCy Schubert } else { 353*2b15cb3dSCy Schubert ++n; 354*2b15cb3dSCy Schubert } 355*2b15cb3dSCy Schubert if (!tinytest_set_flag_(groups, test, 1, flag)) { 356*2b15cb3dSCy Schubert printf("No such test as %s!\n", test); 357*2b15cb3dSCy Schubert return -1; 358*2b15cb3dSCy Schubert } 359*2b15cb3dSCy Schubert return n; 360*2b15cb3dSCy Schubert } 361*2b15cb3dSCy Schubert 362*2b15cb3dSCy Schubert void 363*2b15cb3dSCy Schubert tinytest_set_aliases(const struct testlist_alias_t *aliases) 364*2b15cb3dSCy Schubert { 365*2b15cb3dSCy Schubert cfg_aliases = aliases; 366*2b15cb3dSCy Schubert } 367*2b15cb3dSCy Schubert 368*2b15cb3dSCy Schubert int 369*2b15cb3dSCy Schubert tinytest_main(int c, const char **v, struct testgroup_t *groups) 370*2b15cb3dSCy Schubert { 371*2b15cb3dSCy Schubert int i, j, n=0; 372*2b15cb3dSCy Schubert 373*2b15cb3dSCy Schubert #ifdef _WIN32 374*2b15cb3dSCy Schubert const char *sp = strrchr(v[0], '.'); 375*2b15cb3dSCy Schubert const char *extension = ""; 376*2b15cb3dSCy Schubert if (!sp || stricmp(sp, ".exe")) 377*2b15cb3dSCy Schubert extension = ".exe"; /* Add an exe so CreateProcess will work */ 378*2b15cb3dSCy Schubert snprintf(commandname, sizeof(commandname), "%s%s", v[0], extension); 379*2b15cb3dSCy Schubert commandname[MAX_PATH]='\0'; 380*2b15cb3dSCy Schubert #endif 381*2b15cb3dSCy Schubert for (i=1; i<c; ++i) { 382*2b15cb3dSCy Schubert if (v[i][0] == '-') { 383*2b15cb3dSCy Schubert if (!strcmp(v[i], "--RUNNING-FORKED")) { 384*2b15cb3dSCy Schubert opt_forked = 1; 385*2b15cb3dSCy Schubert } else if (!strcmp(v[i], "--no-fork")) { 386*2b15cb3dSCy Schubert opt_nofork = 1; 387*2b15cb3dSCy Schubert } else if (!strcmp(v[i], "--quiet")) { 388*2b15cb3dSCy Schubert opt_verbosity = -1; 389*2b15cb3dSCy Schubert verbosity_flag = "--quiet"; 390*2b15cb3dSCy Schubert } else if (!strcmp(v[i], "--verbose")) { 391*2b15cb3dSCy Schubert opt_verbosity = 2; 392*2b15cb3dSCy Schubert verbosity_flag = "--verbose"; 393*2b15cb3dSCy Schubert } else if (!strcmp(v[i], "--terse")) { 394*2b15cb3dSCy Schubert opt_verbosity = 0; 395*2b15cb3dSCy Schubert verbosity_flag = "--terse"; 396*2b15cb3dSCy Schubert } else if (!strcmp(v[i], "--help")) { 397*2b15cb3dSCy Schubert usage(groups, 0); 398*2b15cb3dSCy Schubert } else if (!strcmp(v[i], "--list-tests")) { 399*2b15cb3dSCy Schubert usage(groups, 1); 400*2b15cb3dSCy Schubert } else { 401*2b15cb3dSCy Schubert printf("Unknown option %s. Try --help\n",v[i]); 402*2b15cb3dSCy Schubert return -1; 403*2b15cb3dSCy Schubert } 404*2b15cb3dSCy Schubert } else { 405*2b15cb3dSCy Schubert int r = process_test_option(groups, v[i]); 406*2b15cb3dSCy Schubert if (r<0) 407*2b15cb3dSCy Schubert return -1; 408*2b15cb3dSCy Schubert n += r; 409*2b15cb3dSCy Schubert } 410*2b15cb3dSCy Schubert } 411*2b15cb3dSCy Schubert if (!n) 412*2b15cb3dSCy Schubert tinytest_set_flag_(groups, "..", 1, TT_ENABLED_); 413*2b15cb3dSCy Schubert 414*2b15cb3dSCy Schubert setvbuf(stdout, NULL, _IONBF, 0); 415*2b15cb3dSCy Schubert 416*2b15cb3dSCy Schubert ++in_tinytest_main; 417*2b15cb3dSCy Schubert for (i=0; groups[i].prefix; ++i) 418*2b15cb3dSCy Schubert for (j=0; groups[i].cases[j].name; ++j) 419*2b15cb3dSCy Schubert if (groups[i].cases[j].flags & TT_ENABLED_) 420*2b15cb3dSCy Schubert testcase_run_one(&groups[i], 421*2b15cb3dSCy Schubert &groups[i].cases[j]); 422*2b15cb3dSCy Schubert 423*2b15cb3dSCy Schubert --in_tinytest_main; 424*2b15cb3dSCy Schubert 425*2b15cb3dSCy Schubert if (opt_verbosity==0) 426*2b15cb3dSCy Schubert puts(""); 427*2b15cb3dSCy Schubert 428*2b15cb3dSCy Schubert if (n_bad) 429*2b15cb3dSCy Schubert printf("%d/%d TESTS FAILED. (%d skipped)\n", n_bad, 430*2b15cb3dSCy Schubert n_bad+n_ok,n_skipped); 431*2b15cb3dSCy Schubert else if (opt_verbosity >= 1) 432*2b15cb3dSCy Schubert printf("%d tests ok. (%d skipped)\n", n_ok, n_skipped); 433*2b15cb3dSCy Schubert 434*2b15cb3dSCy Schubert return (n_bad == 0) ? 0 : 1; 435*2b15cb3dSCy Schubert } 436*2b15cb3dSCy Schubert 437*2b15cb3dSCy Schubert int 438*2b15cb3dSCy Schubert tinytest_get_verbosity_(void) 439*2b15cb3dSCy Schubert { 440*2b15cb3dSCy Schubert return opt_verbosity; 441*2b15cb3dSCy Schubert } 442*2b15cb3dSCy Schubert 443*2b15cb3dSCy Schubert void 444*2b15cb3dSCy Schubert tinytest_set_test_failed_(void) 445*2b15cb3dSCy Schubert { 446*2b15cb3dSCy Schubert if (opt_verbosity <= 0 && cur_test_name) { 447*2b15cb3dSCy Schubert if (opt_verbosity==0) puts(""); 448*2b15cb3dSCy Schubert printf("%s%s: ", cur_test_prefix, cur_test_name); 449*2b15cb3dSCy Schubert cur_test_name = NULL; 450*2b15cb3dSCy Schubert } 451*2b15cb3dSCy Schubert cur_test_outcome = 0; 452*2b15cb3dSCy Schubert } 453*2b15cb3dSCy Schubert 454*2b15cb3dSCy Schubert void 455*2b15cb3dSCy Schubert tinytest_set_test_skipped_(void) 456*2b15cb3dSCy Schubert { 457*2b15cb3dSCy Schubert if (cur_test_outcome==OK) 458*2b15cb3dSCy Schubert cur_test_outcome = SKIP; 459*2b15cb3dSCy Schubert } 460*2b15cb3dSCy Schubert 461