Added the test framework to the tests directory
Separated the test framework into the header. Test definitions should be placed in the test.c.
This commit is contained in:
parent
0924650090
commit
5905cb67b0
162
c_projects/x_tfw4c/tests/include/test.h
Normal file
162
c_projects/x_tfw4c/tests/include/test.h
Normal file
@ -0,0 +1,162 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <assert.h>
|
||||
|
||||
// printf Formating
|
||||
#define X_RED "\x1B[31m"
|
||||
#define X_GREEN "\x1B[32m"
|
||||
#define X_YELLOW "\x1B[33m"
|
||||
#define X_RST "\x1B[0m"
|
||||
|
||||
|
||||
// TEST FRAMEWORK STRUCT
|
||||
typedef struct testnode{
|
||||
char* name;
|
||||
int (*op)(void);
|
||||
struct testnode* next;
|
||||
}testnode;
|
||||
|
||||
// LL nodes
|
||||
static testnode* head = NULL;
|
||||
static testnode* tail = NULL;
|
||||
static testnode* ptr = NULL;
|
||||
|
||||
// TEST FRAMEWORK MACRO
|
||||
// create a new node and pass in the name of the test. Then make a new function
|
||||
// that adds the test to the LL. __attribute__((constructor)) has the function
|
||||
// run before main
|
||||
#define TEST(UNIT)\
|
||||
static int UNIT(void);\
|
||||
static testnode UNIT##node = {#UNIT, UNIT, NULL};\
|
||||
__attribute__((constructor)) \
|
||||
static void add##UNIT(void){ \
|
||||
if (head == NULL){\
|
||||
head = &UNIT##node;\
|
||||
tail = head;\
|
||||
return; \
|
||||
}\
|
||||
ptr = tail;\
|
||||
tail = &UNIT##node;\
|
||||
ptr->next = tail;\
|
||||
}\
|
||||
static int UNIT(void)
|
||||
|
||||
// TEST HELPER FUNCTIONS and STRUCTS
|
||||
typedef enum {START, END} header_opt;
|
||||
static void ptest_headers(header_opt option){
|
||||
switch (option){
|
||||
case START:
|
||||
printf("\n-------------------\n");
|
||||
printf(" Starting Tests\n");
|
||||
printf("-------------------\n");
|
||||
break;
|
||||
case END:
|
||||
printf("-------------------\n");
|
||||
printf(" ENDING TESTS\n");
|
||||
printf("-------------------\n\n");
|
||||
break;
|
||||
default:
|
||||
printf("error: Wrong option in ptest_headers()\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum {PASS, FAIL}rc_opt;
|
||||
static void ppass_fail(rc_opt rc){
|
||||
switch (rc){
|
||||
case PASS:
|
||||
printf("%s[PASS]%s ", X_GREEN, X_RST);
|
||||
printf("%s", ptr->name);
|
||||
break;
|
||||
case FAIL:
|
||||
printf("%s[FAIL]%s ", X_RED, X_RST);
|
||||
printf("%s ", ptr->name);
|
||||
break;
|
||||
default:
|
||||
printf("error: Unknown return code");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int presult(int status){
|
||||
if (WIFEXITED(status)){
|
||||
int rc = WEXITSTATUS(status);
|
||||
if (rc == 0) {
|
||||
ppass_fail(PASS);
|
||||
return 0;
|
||||
}
|
||||
else{
|
||||
ppass_fail(FAIL);
|
||||
printf("- Exit Code %s(%d)%s",
|
||||
X_YELLOW, rc, X_RST);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (WIFSIGNALED(status)){
|
||||
ppass_fail(FAIL);
|
||||
printf("- Termination Signal %s(%d)%s",
|
||||
X_YELLOW, WTERMSIG(status), X_RST);
|
||||
return 1;
|
||||
}
|
||||
else{
|
||||
printf("%s[FAIL]%s ", X_RED, X_RST);
|
||||
printf("%s ", ptr->name);
|
||||
printf("- Unknown Error ");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int run_child(){
|
||||
int status;
|
||||
pid_t cpid = fork();
|
||||
if (cpid < 0){
|
||||
perror("fork");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (cpid == 0){
|
||||
int rc = ptr->op();
|
||||
_exit(rc);
|
||||
}else{
|
||||
if (waitpid(cpid, &status, 0) < 0){
|
||||
perror("waitpid");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int run_tests(){
|
||||
int total_tests = 0;
|
||||
int errors = 0;
|
||||
|
||||
ptest_headers(START);
|
||||
|
||||
ptr = head;
|
||||
while (ptr != NULL){
|
||||
total_tests++;
|
||||
|
||||
|
||||
if(presult(run_child())){
|
||||
errors++;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
|
||||
printf("\nTests completed with %s%d PASS%s", X_GREEN, total_tests - errors, X_RST);
|
||||
printf(" and %s%d FAIL%s\n", X_RED, errors, X_RST);
|
||||
|
||||
ptest_headers(END);
|
||||
|
||||
if (errors > 0){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
29
c_projects/x_tfw4c/tests/test.c
Normal file
29
c_projects/x_tfw4c/tests/test.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include "test.h"
|
||||
|
||||
// INCLUDE PROJECT HEADERS
|
||||
#include "hello_world.h"
|
||||
|
||||
|
||||
// DEFINE TESTS
|
||||
TEST(success){
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(fail){
|
||||
int i = 1;
|
||||
assert(i == 0);
|
||||
printf("after assert\n");
|
||||
return i;
|
||||
}
|
||||
|
||||
TEST(segfault){
|
||||
int* x = NULL;
|
||||
int y = *x;
|
||||
return y;
|
||||
}
|
||||
|
||||
// END OF TEST DEFINITIONS
|
||||
|
||||
int main(void){
|
||||
return run_tests();
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user