1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251876Speter * contributor license agreements. See the NOTICE file distributed with 3251876Speter * this work for additional information regarding copyright ownership. 4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251876Speter * (the "License"); you may not use this file except in compliance with 6251876Speter * the License. You may obtain a copy of the License at 7251876Speter * 8251876Speter * http://www.apache.org/licenses/LICENSE-2.0 9251876Speter * 10251876Speter * Unless required by applicable law or agreed to in writing, software 11251876Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251876Speter * See the License for the specific language governing permissions and 14251876Speter * limitations under the License. 15251876Speter */ 16251876Speter 17251876Speter#include "abts.h" 18251876Speter#include "abts_tests.h" 19251876Speter#include "testutil.h" 20251876Speter 21251876Speter#define ABTS_STAT_SIZE 6 22251876Speterstatic char status[ABTS_STAT_SIZE] = {'|', '/', '-', '|', '\\', '-'}; 23251876Speterstatic int curr_char; 24251876Speterstatic int verbose = 0; 25251876Speterstatic int exclude = 0; 26251876Speterstatic int quiet = 0; 27251876Speterstatic int list_tests = 0; 28251876Speter 29251876Speterconst char **testlist = NULL; 30251876Speter 31251876Speterstatic int find_test_name(const char *testname) { 32251876Speter int i; 33251876Speter for (i = 0; testlist[i] != NULL; i++) { 34251876Speter if (!strcmp(testlist[i], testname)) { 35251876Speter return 1; 36251876Speter } 37251876Speter } 38251876Speter return 0; 39251876Speter} 40251876Speter 41251876Speter/* Determine if the test should be run at all */ 42251876Speterstatic int should_test_run(const char *testname) { 43251876Speter int found = 0; 44251876Speter if (list_tests == 1) { 45251876Speter return 0; 46251876Speter } 47251876Speter if (testlist == NULL) { 48251876Speter return 1; 49251876Speter } 50251876Speter found = find_test_name(testname); 51251876Speter if ((found && !exclude) || (!found && exclude)) { 52251876Speter return 1; 53251876Speter } 54251876Speter return 0; 55251876Speter} 56251876Speter 57251876Speterstatic void reset_status(void) 58251876Speter{ 59251876Speter curr_char = 0; 60251876Speter} 61251876Speter 62251876Speterstatic void update_status(void) 63251876Speter{ 64251876Speter if (!quiet) { 65251876Speter curr_char = (curr_char + 1) % ABTS_STAT_SIZE; 66251876Speter fprintf(stdout, "\b%c", status[curr_char]); 67251876Speter fflush(stdout); 68251876Speter } 69251876Speter} 70251876Speter 71251876Speterstatic void end_suite(abts_suite *suite) 72251876Speter{ 73251876Speter if (suite != NULL) { 74251876Speter sub_suite *last = suite->tail; 75251876Speter if (!quiet) { 76251876Speter fprintf(stdout, "\b"); 77251876Speter fflush(stdout); 78251876Speter } 79251876Speter if (last->failed == 0) { 80251876Speter fprintf(stdout, "SUCCESS\n"); 81251876Speter fflush(stdout); 82251876Speter } 83251876Speter else { 84251876Speter fprintf(stdout, "FAILED %d of %d\n", last->failed, last->num_test); 85251876Speter fflush(stdout); 86251876Speter } 87251876Speter } 88251876Speter} 89251876Speter 90251876Speterabts_suite *abts_add_suite(abts_suite *suite, const char *suite_name_full) 91251876Speter{ 92251876Speter sub_suite *subsuite; 93251876Speter char *p; 94251876Speter const char *suite_name; 95251876Speter curr_char = 0; 96251876Speter 97251876Speter /* Only end the suite if we actually ran it */ 98251876Speter if (suite && suite->tail &&!suite->tail->not_run) { 99251876Speter end_suite(suite); 100251876Speter } 101251876Speter 102251876Speter subsuite = malloc(sizeof(*subsuite)); 103251876Speter subsuite->num_test = 0; 104251876Speter subsuite->failed = 0; 105251876Speter subsuite->next = NULL; 106251876Speter /* suite_name_full may be an absolute path depending on __FILE__ 107251876Speter * expansion */ 108251876Speter suite_name = strrchr(suite_name_full, '/'); 109262253Speter if (!suite_name) { 110262253Speter suite_name = strrchr(suite_name_full, '\\'); 111262253Speter } 112251876Speter if (suite_name) { 113251876Speter suite_name++; 114251876Speter } else { 115251876Speter suite_name = suite_name_full; 116251876Speter } 117251876Speter p = strrchr(suite_name, '.'); 118251876Speter if (p) { 119251876Speter subsuite->name = memcpy(calloc(p - suite_name + 1, 1), 120251876Speter suite_name, p - suite_name); 121251876Speter } 122251876Speter else { 123251876Speter subsuite->name = suite_name; 124251876Speter } 125251876Speter 126251876Speter if (list_tests) { 127251876Speter fprintf(stdout, "%s\n", subsuite->name); 128251876Speter } 129251876Speter 130251876Speter subsuite->not_run = 0; 131251876Speter 132251876Speter if (suite == NULL) { 133251876Speter suite = malloc(sizeof(*suite)); 134251876Speter suite->head = subsuite; 135251876Speter suite->tail = subsuite; 136251876Speter } 137251876Speter else { 138251876Speter suite->tail->next = subsuite; 139251876Speter suite->tail = subsuite; 140251876Speter } 141251876Speter 142251876Speter if (!should_test_run(subsuite->name)) { 143251876Speter subsuite->not_run = 1; 144251876Speter return suite; 145251876Speter } 146251876Speter 147251876Speter reset_status(); 148251876Speter fprintf(stdout, "%-20s: ", subsuite->name); 149251876Speter update_status(); 150251876Speter fflush(stdout); 151251876Speter 152251876Speter return suite; 153251876Speter} 154251876Speter 155251876Spetervoid abts_run_test(abts_suite *ts, test_func f, void *value) 156251876Speter{ 157251876Speter abts_case *tc; 158251876Speter sub_suite *ss; 159251876Speter 160251876Speter if (!should_test_run(ts->tail->name)) { 161251876Speter return; 162251876Speter } 163251876Speter ss = ts->tail; 164251876Speter 165251876Speter tc = malloc(sizeof(*tc)); 166251876Speter tc->failed = 0; 167251876Speter tc->suite = ss; 168251876Speter 169251876Speter ss->num_test++; 170251876Speter update_status(); 171251876Speter 172251876Speter f(tc, value); 173251876Speter 174251876Speter if (tc->failed) { 175251876Speter ss->failed++; 176251876Speter } 177251876Speter free(tc); 178251876Speter} 179251876Speter 180251876Speterstatic int report(abts_suite *suite) 181251876Speter{ 182251876Speter int count = 0; 183251876Speter sub_suite *dptr; 184251876Speter 185251876Speter if (suite && suite->tail &&!suite->tail->not_run) { 186251876Speter end_suite(suite); 187251876Speter } 188251876Speter 189251876Speter for (dptr = suite->head; dptr; dptr = dptr->next) { 190251876Speter count += dptr->failed; 191251876Speter } 192251876Speter 193251876Speter if (list_tests) { 194251876Speter return 0; 195251876Speter } 196251876Speter 197251876Speter if (count == 0) { 198251876Speter printf("All tests passed.\n"); 199251876Speter return 0; 200251876Speter } 201251876Speter 202251876Speter dptr = suite->head; 203251876Speter fprintf(stdout, "%-15s\t\tTotal\tFail\tFailed %%\n", "Failed Tests"); 204251876Speter fprintf(stdout, "===================================================\n"); 205251876Speter while (dptr != NULL) { 206251876Speter if (dptr->failed != 0) { 207251876Speter float percent = ((float)dptr->failed / (float)dptr->num_test); 208251876Speter fprintf(stdout, "%-15s\t\t%5d\t%4d\t%6.2f%%\n", dptr->name, 209251876Speter dptr->num_test, dptr->failed, percent * 100); 210251876Speter } 211251876Speter dptr = dptr->next; 212251876Speter } 213251876Speter return 1; 214251876Speter} 215251876Speter 216251876Spetervoid abts_log_message(const char *fmt, ...) 217251876Speter{ 218251876Speter va_list args; 219251876Speter update_status(); 220251876Speter 221251876Speter if (verbose) { 222251876Speter va_start(args, fmt); 223251876Speter vfprintf(stderr, fmt, args); 224251876Speter va_end(args); 225251876Speter fprintf(stderr, "\n"); 226251876Speter fflush(stderr); 227251876Speter } 228251876Speter} 229251876Speter 230251876Spetervoid abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno) 231251876Speter{ 232251876Speter update_status(); 233251876Speter if (tc->failed) return; 234251876Speter 235251876Speter if (expected == actual) return; 236251876Speter 237251876Speter tc->failed = TRUE; 238251876Speter if (verbose) { 239251876Speter fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual); 240251876Speter fflush(stderr); 241251876Speter } 242251876Speter} 243251876Speter 244251876Spetervoid abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno) 245251876Speter{ 246251876Speter update_status(); 247251876Speter if (tc->failed) return; 248251876Speter 249251876Speter if (expected != actual) return; 250251876Speter 251251876Speter tc->failed = TRUE; 252251876Speter if (verbose) { 253262253Speter fprintf(stderr, "Line %d: expected something other than <%d>, but saw <%d>\n", 254262253Speter lineno, expected, actual); 255251876Speter fflush(stderr); 256251876Speter } 257251876Speter} 258251876Speter 259251876Spetervoid abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno) 260251876Speter{ 261251876Speter update_status(); 262251876Speter if (tc->failed) return; 263251876Speter 264251876Speter /* If both are NULL, match is good */ 265251876Speter if (!expected && !actual) return; 266251876Speter if (expected && actual) 267251876Speter if (!strcmp(expected, actual)) return; 268251876Speter 269251876Speter tc->failed = TRUE; 270251876Speter if (verbose) { 271251876Speter fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual); 272251876Speter fflush(stderr); 273251876Speter } 274251876Speter} 275251876Speter 276251876Spetervoid abts_str_nequal(abts_case *tc, const char *expected, const char *actual, 277251876Speter size_t n, int lineno) 278251876Speter{ 279251876Speter update_status(); 280251876Speter if (tc->failed) return; 281251876Speter 282251876Speter if (!strncmp(expected, actual, n)) return; 283251876Speter 284251876Speter tc->failed = TRUE; 285251876Speter if (verbose) { 286262253Speter fprintf(stderr, "Line %d: expected something other than <%s>, but saw <%s>\n", 287262253Speter lineno, expected, actual); 288251876Speter fflush(stderr); 289251876Speter } 290251876Speter} 291251876Speter 292251876Spetervoid abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno) 293251876Speter{ 294251876Speter update_status(); 295251876Speter if (tc->failed) return; 296251876Speter 297251876Speter if (ptr != NULL) return; 298251876Speter 299251876Speter tc->failed = TRUE; 300251876Speter if (verbose) { 301251876Speter fprintf(stderr, "Line %d: expected non-NULL, but saw NULL\n", lineno); 302251876Speter fflush(stderr); 303251876Speter } 304251876Speter} 305251876Speter 306251876Spetervoid abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno) 307251876Speter{ 308251876Speter update_status(); 309251876Speter if (tc->failed) return; 310251876Speter 311251876Speter if (expected == actual) return; 312251876Speter 313251876Speter tc->failed = TRUE; 314251876Speter if (verbose) { 315251876Speter fprintf(stderr, "Line %d: expected <%p>, but saw <%p>\n", lineno, expected, actual); 316251876Speter fflush(stderr); 317251876Speter } 318251876Speter} 319251876Speter 320251876Spetervoid abts_fail(abts_case *tc, const char *message, int lineno) 321251876Speter{ 322251876Speter update_status(); 323251876Speter if (tc->failed) return; 324251876Speter 325251876Speter tc->failed = TRUE; 326251876Speter if (verbose) { 327251876Speter fprintf(stderr, "Line %d: %s\n", lineno, message); 328251876Speter fflush(stderr); 329251876Speter } 330251876Speter} 331251876Speter 332251876Spetervoid abts_assert(abts_case *tc, const char *message, int condition, int lineno) 333251876Speter{ 334251876Speter update_status(); 335251876Speter if (tc->failed) return; 336251876Speter 337251876Speter if (condition) return; 338251876Speter 339251876Speter tc->failed = TRUE; 340251876Speter if (verbose) { 341251876Speter fprintf(stderr, "Line %d: %s\n", lineno, message); 342251876Speter fflush(stderr); 343251876Speter } 344251876Speter} 345251876Speter 346251876Spetervoid abts_true(abts_case *tc, int condition, int lineno) 347251876Speter{ 348251876Speter update_status(); 349251876Speter if (tc->failed) return; 350251876Speter 351251876Speter if (condition) return; 352251876Speter 353251876Speter tc->failed = TRUE; 354251876Speter if (verbose) { 355251876Speter fprintf(stderr, "Line %d: Condition is false, but expected true\n", lineno); 356251876Speter fflush(stderr); 357251876Speter } 358251876Speter} 359251876Speter 360251876Spetervoid abts_not_impl(abts_case *tc, const char *message, int lineno) 361251876Speter{ 362251876Speter update_status(); 363251876Speter 364251876Speter tc->suite->not_impl++; 365251876Speter if (verbose) { 366251876Speter fprintf(stderr, "Line %d: %s\n", lineno, message); 367251876Speter fflush(stderr); 368251876Speter } 369251876Speter} 370251876Speter 371251876Speterint main(int argc, const char *const argv[]) { 372251876Speter int i; 373251876Speter int rv; 374251876Speter int list_provided = 0; 375251876Speter abts_suite *suite = NULL; 376251876Speter 377251876Speter initialize(); 378251876Speter 379251876Speter quiet = !isatty(STDOUT_FILENO); 380251876Speter 381251876Speter for (i = 1; i < argc; i++) { 382251876Speter if (!strcmp(argv[i], "-v")) { 383251876Speter verbose = 1; 384251876Speter continue; 385251876Speter } 386251876Speter if (!strcmp(argv[i], "-x")) { 387251876Speter exclude = 1; 388251876Speter continue; 389251876Speter } 390251876Speter if (!strcmp(argv[i], "-l")) { 391251876Speter list_tests = 1; 392251876Speter continue; 393251876Speter } 394251876Speter if (!strcmp(argv[i], "-q")) { 395251876Speter quiet = 1; 396251876Speter continue; 397251876Speter } 398251876Speter if (argv[i][0] == '-') { 399251876Speter fprintf(stderr, "Invalid option: `%s'\n", argv[i]); 400251876Speter exit(1); 401251876Speter } 402251876Speter list_provided = 1; 403251876Speter } 404251876Speter 405251876Speter if (list_provided) { 406251876Speter /* Waste a little space here, because it is easier than counting the 407251876Speter * number of tests listed. Besides it is at most three char *. 408251876Speter */ 409251876Speter testlist = calloc(argc + 1, sizeof(char *)); 410251876Speter for (i = 1; i < argc; i++) { 411251876Speter testlist[i - 1] = argv[i]; 412251876Speter } 413251876Speter } 414251876Speter 415251876Speter for (i = 0; i < (sizeof(alltests) / sizeof(struct testlist *)); i++) { 416251876Speter suite = alltests[i].func(suite); 417251876Speter apr_pool_clear(p); 418251876Speter } 419251876Speter 420251876Speter rv = report(suite); 421251876Speter return rv; 422251876Speter} 423251876Speter 424