/* 9unit Copyright (C) Jonathan Lamothe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include #include #include #include "9unit.h" // Internal Prototypes static void init_TestState(TestState *); static void print_log(TestState *); static void clear_log(TestState *); static void reindex(TestState *); // Public Functions void run_test(TestState *s, TestResult (*t)(TestState *)) { if (!s) return; s->run++; // a null test function is a pending test if (!t) { s->pending++; return; } switch ((*t)(s)) { case test_success: s->passed++; break; case test_failure: s->failed++; break; case test_pending: s->pending++; break; default: exits("test returned an invalid response"); } } void run_tests(void (*tests)(TestState *)) { if (!tests) return; TestState s; memset(&s, 0, sizeof(TestState)); (*tests)(&s); print_log(&s); printf("Tests run: %d\n", s.run); printf("Tests passed: %d\n", s.passed); printf("Tests failed: %d\n", s.failed); printf("Tests pending: %d\n", s.pending); clear_log(&s); if (s.failed) exits("test(s) failed"); } void append_test_log(TestState *s, const char *msg) { if (!(s && msg)) return; // build a new entry: TestLogEntry *entry = malloc(sizeof(TestLogEntry)); entry->text = malloc(strlen(msg) + 1); strcpy(entry->text, msg); entry->next = 0; // add it to the list: if (!s->last_log) { if (s->first_log) // no last entry but we have a first? { reindex(s); s->last_log->next = entry; } else s->first_log = entry; } else // there's already a last entry { if (!s->first_log) // no first entry but we have a last? reindex(s); // do our best to fix that s->last_log->next = entry; } s->last_log = entry; } // Internal Functions static void print_log(TestState *s) { if (!s) return; TestLogEntry *e = s->first_log; while(e) { if(e->text) printf("%s\n", e->text); else print("(empty message)\n"); e = e->next; } } static void clear_log(TestState *s) { if (!s) return; if(s->last_log && !s->first_log) reindex(s); // fix if broken TestLogEntry *e = s->first_log, *next; s->first_log = 0; s->last_log = 0; while (e) { next = e->next; free(e->text); free(e); e = next; } } static void reindex(TestState *s) { if (!s) return; if (s->first_log) { TestLogEntry *e = s->first_log; while (e) { s->last_log = e; e = e->next; } } else if (s->last_log) // we have a last log but no first? { s->first_log = s->last_log; fprint(2, "potential memory leak in test log\n"); } } //jl