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, '/'); 109251876Speter if (suite_name) { 110251876Speter suite_name++; 111251876Speter } else { 112251876Speter suite_name = suite_name_full; 113251876Speter } 114251876Speter p = strrchr(suite_name, '.'); 115251876Speter if (p) { 116251876Speter subsuite->name = memcpy(calloc(p - suite_name + 1, 1), 117251876Speter suite_name, p - suite_name); 118251876Speter } 119251876Speter else { 120251876Speter subsuite->name = suite_name; 121251876Speter } 122251876Speter 123251876Speter if (list_tests) { 124251876Speter fprintf(stdout, "%s\n", subsuite->name); 125251876Speter } 126251876Speter 127251876Speter subsuite->not_run = 0; 128251876Speter 129251876Speter if (suite == NULL) { 130251876Speter suite = malloc(sizeof(*suite)); 131251876Speter suite->head = subsuite; 132251876Speter suite->tail = subsuite; 133251876Speter } 134251876Speter else { 135251876Speter suite->tail->next = subsuite; 136251876Speter suite->tail = subsuite; 137251876Speter } 138251876Speter 139251876Speter if (!should_test_run(subsuite->name)) { 140251876Speter subsuite->not_run = 1; 141251876Speter return suite; 142251876Speter } 143251876Speter 144251876Speter reset_status(); 145251876Speter fprintf(stdout, "%-20s: ", subsuite->name); 146251876Speter update_status(); 147251876Speter fflush(stdout); 148251876Speter 149251876Speter return suite; 150251876Speter} 151251876Speter 152251876Spetervoid abts_run_test(abts_suite *ts, test_func f, void *value) 153251876Speter{ 154251876Speter abts_case *tc; 155251876Speter sub_suite *ss; 156251876Speter 157251876Speter if (!should_test_run(ts->tail->name)) { 158251876Speter return; 159251876Speter } 160251876Speter ss = ts->tail; 161251876Speter 162251876Speter tc = malloc(sizeof(*tc)); 163251876Speter tc->failed = 0; 164251876Speter tc->suite = ss; 165251876Speter 166251876Speter ss->num_test++; 167251876Speter update_status(); 168251876Speter 169251876Speter f(tc, value); 170251876Speter 171251876Speter if (tc->failed) { 172251876Speter ss->failed++; 173251876Speter } 174251876Speter free(tc); 175251876Speter} 176251876Speter 177251876Speterstatic int report(abts_suite *suite) 178251876Speter{ 179251876Speter int count = 0; 180251876Speter sub_suite *dptr; 181251876Speter 182251876Speter if (suite && suite->tail &&!suite->tail->not_run) { 183251876Speter end_suite(suite); 184251876Speter } 185251876Speter 186251876Speter for (dptr = suite->head; dptr; dptr = dptr->next) { 187251876Speter count += dptr->failed; 188251876Speter } 189251876Speter 190251876Speter if (list_tests) { 191251876Speter return 0; 192251876Speter } 193251876Speter 194251876Speter if (count == 0) { 195251876Speter printf("All tests passed.\n"); 196251876Speter return 0; 197251876Speter } 198251876Speter 199251876Speter dptr = suite->head; 200251876Speter fprintf(stdout, "%-15s\t\tTotal\tFail\tFailed %%\n", "Failed Tests"); 201251876Speter fprintf(stdout, "===================================================\n"); 202251876Speter while (dptr != NULL) { 203251876Speter if (dptr->failed != 0) { 204251876Speter float percent = ((float)dptr->failed / (float)dptr->num_test); 205251876Speter fprintf(stdout, "%-15s\t\t%5d\t%4d\t%6.2f%%\n", dptr->name, 206251876Speter dptr->num_test, dptr->failed, percent * 100); 207251876Speter } 208251876Speter dptr = dptr->next; 209251876Speter } 210251876Speter return 1; 211251876Speter} 212251876Speter 213251876Spetervoid abts_log_message(const char *fmt, ...) 214251876Speter{ 215251876Speter va_list args; 216251876Speter update_status(); 217251876Speter 218251876Speter if (verbose) { 219251876Speter va_start(args, fmt); 220251876Speter vfprintf(stderr, fmt, args); 221251876Speter va_end(args); 222251876Speter fprintf(stderr, "\n"); 223251876Speter fflush(stderr); 224251876Speter } 225251876Speter} 226251876Speter 227251876Spetervoid abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno) 228251876Speter{ 229251876Speter update_status(); 230251876Speter if (tc->failed) return; 231251876Speter 232251876Speter if (expected == actual) return; 233251876Speter 234251876Speter tc->failed = TRUE; 235251876Speter if (verbose) { 236251876Speter fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual); 237251876Speter fflush(stderr); 238251876Speter } 239251876Speter} 240251876Speter 241251876Spetervoid abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno) 242251876Speter{ 243251876Speter update_status(); 244251876Speter if (tc->failed) return; 245251876Speter 246251876Speter if (expected != actual) return; 247251876Speter 248251876Speter tc->failed = TRUE; 249251876Speter if (verbose) { 250251876Speter fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual); 251251876Speter fflush(stderr); 252251876Speter } 253251876Speter} 254251876Speter 255251876Spetervoid abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno) 256251876Speter{ 257251876Speter update_status(); 258251876Speter if (tc->failed) return; 259251876Speter 260251876Speter /* If both are NULL, match is good */ 261251876Speter if (!expected && !actual) return; 262251876Speter if (expected && actual) 263251876Speter if (!strcmp(expected, actual)) return; 264251876Speter 265251876Speter tc->failed = TRUE; 266251876Speter if (verbose) { 267251876Speter fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual); 268251876Speter fflush(stderr); 269251876Speter } 270251876Speter} 271251876Speter 272251876Spetervoid abts_str_nequal(abts_case *tc, const char *expected, const char *actual, 273251876Speter size_t n, int lineno) 274251876Speter{ 275251876Speter update_status(); 276251876Speter if (tc->failed) return; 277251876Speter 278251876Speter if (!strncmp(expected, actual, n)) return; 279251876Speter 280251876Speter tc->failed = TRUE; 281251876Speter if (verbose) { 282251876Speter fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual); 283251876Speter fflush(stderr); 284251876Speter } 285251876Speter} 286251876Speter 287251876Spetervoid abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno) 288251876Speter{ 289251876Speter update_status(); 290251876Speter if (tc->failed) return; 291251876Speter 292251876Speter if (ptr != NULL) return; 293251876Speter 294251876Speter tc->failed = TRUE; 295251876Speter if (verbose) { 296251876Speter fprintf(stderr, "Line %d: expected non-NULL, but saw NULL\n", lineno); 297251876Speter fflush(stderr); 298251876Speter } 299251876Speter} 300251876Speter 301251876Spetervoid abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno) 302251876Speter{ 303251876Speter update_status(); 304251876Speter if (tc->failed) return; 305251876Speter 306251876Speter if (expected == actual) return; 307251876Speter 308251876Speter tc->failed = TRUE; 309251876Speter if (verbose) { 310251876Speter fprintf(stderr, "Line %d: expected <%p>, but saw <%p>\n", lineno, expected, actual); 311251876Speter fflush(stderr); 312251876Speter } 313251876Speter} 314251876Speter 315251876Spetervoid abts_fail(abts_case *tc, const char *message, int lineno) 316251876Speter{ 317251876Speter update_status(); 318251876Speter if (tc->failed) return; 319251876Speter 320251876Speter tc->failed = TRUE; 321251876Speter if (verbose) { 322251876Speter fprintf(stderr, "Line %d: %s\n", lineno, message); 323251876Speter fflush(stderr); 324251876Speter } 325251876Speter} 326251876Speter 327251876Spetervoid abts_assert(abts_case *tc, const char *message, int condition, int lineno) 328251876Speter{ 329251876Speter update_status(); 330251876Speter if (tc->failed) return; 331251876Speter 332251876Speter if (condition) return; 333251876Speter 334251876Speter tc->failed = TRUE; 335251876Speter if (verbose) { 336251876Speter fprintf(stderr, "Line %d: %s\n", lineno, message); 337251876Speter fflush(stderr); 338251876Speter } 339251876Speter} 340251876Speter 341251876Spetervoid abts_true(abts_case *tc, int condition, int lineno) 342251876Speter{ 343251876Speter update_status(); 344251876Speter if (tc->failed) return; 345251876Speter 346251876Speter if (condition) return; 347251876Speter 348251876Speter tc->failed = TRUE; 349251876Speter if (verbose) { 350251876Speter fprintf(stderr, "Line %d: Condition is false, but expected true\n", lineno); 351251876Speter fflush(stderr); 352251876Speter } 353251876Speter} 354251876Speter 355251876Spetervoid abts_not_impl(abts_case *tc, const char *message, int lineno) 356251876Speter{ 357251876Speter update_status(); 358251876Speter 359251876Speter tc->suite->not_impl++; 360251876Speter if (verbose) { 361251876Speter fprintf(stderr, "Line %d: %s\n", lineno, message); 362251876Speter fflush(stderr); 363251876Speter } 364251876Speter} 365251876Speter 366251876Speterint main(int argc, const char *const argv[]) { 367251876Speter int i; 368251876Speter int rv; 369251876Speter int list_provided = 0; 370251876Speter abts_suite *suite = NULL; 371251876Speter 372251876Speter initialize(); 373251876Speter 374251876Speter quiet = !isatty(STDOUT_FILENO); 375251876Speter 376251876Speter for (i = 1; i < argc; i++) { 377251876Speter if (!strcmp(argv[i], "-v")) { 378251876Speter verbose = 1; 379251876Speter continue; 380251876Speter } 381251876Speter if (!strcmp(argv[i], "-x")) { 382251876Speter exclude = 1; 383251876Speter continue; 384251876Speter } 385251876Speter if (!strcmp(argv[i], "-l")) { 386251876Speter list_tests = 1; 387251876Speter continue; 388251876Speter } 389251876Speter if (!strcmp(argv[i], "-q")) { 390251876Speter quiet = 1; 391251876Speter continue; 392251876Speter } 393251876Speter if (argv[i][0] == '-') { 394251876Speter fprintf(stderr, "Invalid option: `%s'\n", argv[i]); 395251876Speter exit(1); 396251876Speter } 397251876Speter list_provided = 1; 398251876Speter } 399251876Speter 400251876Speter if (list_provided) { 401251876Speter /* Waste a little space here, because it is easier than counting the 402251876Speter * number of tests listed. Besides it is at most three char *. 403251876Speter */ 404251876Speter testlist = calloc(argc + 1, sizeof(char *)); 405251876Speter for (i = 1; i < argc; i++) { 406251876Speter testlist[i - 1] = argv[i]; 407251876Speter } 408251876Speter } 409251876Speter 410251876Speter for (i = 0; i < (sizeof(alltests) / sizeof(struct testlist *)); i++) { 411251876Speter suite = alltests[i].func(suite); 412251876Speter apr_pool_clear(p); 413251876Speter } 414251876Speter 415251876Speter rv = report(suite); 416251876Speter return rv; 417251876Speter} 418251876Speter 419