A lot of refactoring
This commit is contained in:
parent
52846ceeac
commit
126ed26b3d
@ -5,23 +5,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
char *tt_filename;
|
#define TT_FAIL(error, ...) dprintf(tt_pipe[1], "\"%s\" Line %d: %s >> " error "\n", tt_current->filename, __LINE__, tt_current->name, __VA_ARGS__);
|
||||||
char *tt_current_test;
|
|
||||||
int tt_fd[2];
|
|
||||||
int tt_color = 1;
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef TT_BUFFER_SIZE
|
|
||||||
#define TT_BUFFER_SIZE 512
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define TT_CLR_RED ((tt_color)?"\x1b[31m":"")
|
|
||||||
#define TT_CLR_GRN ((tt_color)?"\x1b[32m":"")
|
|
||||||
#define TT_CLR_BLU ((tt_color)?"\x1b[34m":"")
|
|
||||||
#define TT_CLR_RES ((tt_color)?"\x1b[0m":"")
|
|
||||||
|
|
||||||
#define TT_FAIL(error, ...) dprintf(tt_fd[1], "\"%s\" Line %d: %s >> " error "\n", tt_filename, __LINE__, tt_current_test, __VA_ARGS__);
|
|
||||||
|
|
||||||
|
|
||||||
#define ASSERT_EQUAL(type, pf, lhs, rhs) do { \
|
#define ASSERT_EQUAL(type, pf, lhs, rhs) do { \
|
||||||
@ -31,7 +15,9 @@ int tt_color = 1;
|
|||||||
TT_FAIL("Expected <%" pf "> got <%" pf ">", tt_rhs, tt_lhs); \
|
TT_FAIL("Expected <%" pf "> got <%" pf ">", tt_rhs, tt_lhs); \
|
||||||
return 1; \
|
return 1; \
|
||||||
} \
|
} \
|
||||||
|
return 0; \
|
||||||
}while(0);
|
}while(0);
|
||||||
|
|
||||||
#define ASSERT_NOT_EQUAL(type, pf, lhs, rhs) do { \
|
#define ASSERT_NOT_EQUAL(type, pf, lhs, rhs) do { \
|
||||||
type tt_lhs = (type)(lhs); \
|
type tt_lhs = (type)(lhs); \
|
||||||
type tt_rhs = (type)(rhs); \
|
type tt_rhs = (type)(rhs); \
|
||||||
@ -39,6 +25,7 @@ int tt_color = 1;
|
|||||||
TT_FAIL("Got <%" pf "> but expected anything else", tt_rhs); \
|
TT_FAIL("Got <%" pf "> but expected anything else", tt_rhs); \
|
||||||
return 1; \
|
return 1; \
|
||||||
} \
|
} \
|
||||||
|
return 0; \
|
||||||
}while(0);
|
}while(0);
|
||||||
|
|
||||||
#define ASSERT_STRN(lhs, rhs, n) do { \
|
#define ASSERT_STRN(lhs, rhs, n) do { \
|
||||||
@ -61,6 +48,7 @@ int tt_color = 1;
|
|||||||
return 1; \
|
return 1; \
|
||||||
} \
|
} \
|
||||||
free(tt_lhs_c); free(tt_rhs_c); \
|
free(tt_lhs_c); free(tt_rhs_c); \
|
||||||
|
return 0; \
|
||||||
}while(0);
|
}while(0);
|
||||||
|
|
||||||
#define ASSERT_EQ_INT(lhs, rhs) ASSERT_EQUAL(int, "d", lhs, rhs)
|
#define ASSERT_EQ_INT(lhs, rhs) ASSERT_EQUAL(int, "d", lhs, rhs)
|
||||||
@ -69,112 +57,184 @@ int tt_color = 1;
|
|||||||
#define ASSERT_NEQ_CHR(lhs, rhs) ASSERT_NOT_EQUAL(char, "c", lhs, rhs)
|
#define ASSERT_NEQ_CHR(lhs, rhs) ASSERT_NOT_EQUAL(char, "c", lhs, rhs)
|
||||||
#define ASSERT_EQ_STR(lhs, rhs, n) ASSERT_STRN(lhs, rhs, n)
|
#define ASSERT_EQ_STR(lhs, rhs, n) ASSERT_STRN(lhs, rhs, n)
|
||||||
|
|
||||||
typedef int (*tt_test)(void);
|
|
||||||
|
|
||||||
struct tt_test
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
int (*test)(void);
|
|
||||||
};
|
|
||||||
struct tt_test *tt_tests;
|
|
||||||
|
|
||||||
int tt_test_count = 0;
|
|
||||||
|
|
||||||
#define TEST(name) \
|
#define TEST(name) \
|
||||||
int ttt_##name(); \
|
int ttt_##name(); \
|
||||||
__attribute__((constructor)) void tttr_##name() { \
|
__attribute__((constructor)) void tttr_##name() { \
|
||||||
tt_register(#name, ttt_##name); \
|
tt_register(#name, ttt_##name, __FILE__); \
|
||||||
} \
|
} \
|
||||||
int ttt_##name()
|
int ttt_##name()
|
||||||
|
|
||||||
#define BEFORE() void tt_before()
|
#define BEFORE() void tt_before()
|
||||||
#define AFTER() void tt_after()
|
#define AFTER() void tt_after()
|
||||||
|
|
||||||
void tt_register(char *name, int (*fn)(void))
|
|
||||||
{
|
|
||||||
tt_tests = realloc(tt_tests, (tt_test_count+1)*sizeof(struct tt_test));
|
|
||||||
tt_tests[tt_test_count].name = name;
|
|
||||||
tt_tests[tt_test_count].test = fn;
|
|
||||||
tt_test_count++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void __attribute__((weak)) tt_before(void);
|
void __attribute__((weak)) tt_before(void);
|
||||||
void __attribute__((weak)) tt_after(void);
|
void __attribute__((weak)) tt_after(void);
|
||||||
|
|
||||||
|
#ifndef TT_BUFFER_SIZE
|
||||||
|
#define TT_BUFFER_SIZE 512
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct tt_test
|
||||||
|
{
|
||||||
|
char *filename;
|
||||||
|
char *name;
|
||||||
|
int (*test)(void);
|
||||||
|
int status;
|
||||||
|
char *output;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Global variables
|
||||||
|
int tt_pipe[2];
|
||||||
|
int tt_color = 1;
|
||||||
|
int tt_verbose = 0;
|
||||||
|
int tt_silent = 0;
|
||||||
|
struct tt_test *tt_tests;
|
||||||
|
struct tt_test *tt_current;
|
||||||
|
int tt_max_name_len = 0;
|
||||||
|
int tt_test_count = 0;
|
||||||
|
|
||||||
|
void tt_register(char *name, int (*fn)(void), char *filename)
|
||||||
|
{
|
||||||
|
tt_tests = realloc(tt_tests, (tt_test_count+1)*sizeof(struct tt_test));
|
||||||
|
|
||||||
|
struct tt_test *t = &tt_tests[tt_test_count++];
|
||||||
|
t->filename = filename;
|
||||||
|
t->name = name;
|
||||||
|
t->test = fn;
|
||||||
|
t->status = 1;
|
||||||
|
t->output = malloc(TT_BUFFER_SIZE);
|
||||||
|
if(strlen(name) > tt_max_name_len)
|
||||||
|
tt_max_name_len = strlen(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define TT_CLR_RED ((tt_color)?"\x1b[31m":"")
|
||||||
|
#define TT_CLR_GRN ((tt_color)?"\x1b[32m":"")
|
||||||
|
#define TT_CLR_YEL ((tt_color)?"\x1b[33m":"")
|
||||||
|
#define TT_CLR_RES ((tt_color)?"\x1b[0m":"")
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
tt_filename = argv[1];
|
|
||||||
|
|
||||||
if(!isatty(1)) tt_color = 0;
|
if(!isatty(1)) tt_color = 0;
|
||||||
|
int opt;
|
||||||
|
while((opt = getopt(argc, argv, "vscn")) != -1)
|
||||||
|
{
|
||||||
|
switch(opt)
|
||||||
|
{
|
||||||
|
case 'v':
|
||||||
|
tt_verbose = 1;
|
||||||
|
tt_silent = 0;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
tt_silent = 1;
|
||||||
|
tt_verbose = 0;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
tt_color = 1;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
tt_color = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char *buffer = malloc(TT_BUFFER_SIZE);
|
int ok = 0;
|
||||||
char **errors = 0;
|
int failed = 0;
|
||||||
|
int crashed = 0;
|
||||||
|
|
||||||
|
if(!tt_silent)
|
||||||
|
printf("\n%s\n", tt_tests[0].filename);
|
||||||
|
|
||||||
int failures = 0;
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(i < tt_test_count)
|
while(i < tt_test_count)
|
||||||
{
|
{
|
||||||
struct tt_test *test = &tt_tests[i];
|
tt_current = &tt_tests[i];
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
pipe(tt_fd);
|
pipe(tt_pipe);
|
||||||
|
|
||||||
int pid;
|
int pid;
|
||||||
tt_current_test = test->name;
|
|
||||||
if(!(pid = fork()))
|
if(!(pid = fork()))
|
||||||
{
|
{
|
||||||
close(tt_fd[0]);
|
// Run test
|
||||||
|
close(tt_pipe[0]);
|
||||||
if(tt_before) tt_before();
|
if(tt_before) tt_before();
|
||||||
int result = test->test();
|
int result = tt_current->test();
|
||||||
if(tt_after) tt_after();
|
if(tt_after) tt_after();
|
||||||
exit(result);
|
exit(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(tt_fd[1]);
|
// Capture test output
|
||||||
|
close(tt_pipe[1]);
|
||||||
|
read(tt_pipe[0], tt_current->output, TT_BUFFER_SIZE);
|
||||||
|
close(tt_pipe[0]);
|
||||||
|
|
||||||
|
// Determine if test passed or not
|
||||||
int status;
|
int status;
|
||||||
waitpid(pid, &status, 0);
|
waitpid(pid, &status, 0);
|
||||||
int failed = 0;
|
|
||||||
if(read(tt_fd[0], buffer, TT_BUFFER_SIZE))
|
|
||||||
{
|
|
||||||
failed = 1;
|
|
||||||
}
|
|
||||||
close(tt_fd[0]);
|
|
||||||
if(!WIFEXITED(status))
|
if(!WIFEXITED(status))
|
||||||
{
|
{
|
||||||
failed = 1;
|
crashed++;
|
||||||
sprintf(buffer, "\"%s\" >> TEST %s CRASHED\n", tt_filename, tt_current_test);
|
tt_current->status = -1;
|
||||||
|
} else if(WEXITSTATUS(status)) {
|
||||||
|
failed++;
|
||||||
|
tt_current->status = WEXITSTATUS(status);
|
||||||
|
} else {
|
||||||
|
ok++;
|
||||||
|
tt_current->status = 0;
|
||||||
}
|
}
|
||||||
if(failed)
|
|
||||||
|
// Output progress
|
||||||
|
if(tt_verbose)
|
||||||
|
printf("%3d/%3d %-*s ", i+1, tt_test_count,
|
||||||
|
tt_max_name_len, tt_current->name);
|
||||||
|
switch(tt_current->status)
|
||||||
{
|
{
|
||||||
failures++;
|
case 0:
|
||||||
errors = realloc(errors, failures*sizeof(char *));
|
if(tt_verbose)
|
||||||
errors[failures-1] = buffer;
|
printf("[%sOK%s]\n", TT_CLR_GRN, TT_CLR_RES);
|
||||||
buffer = malloc(TT_BUFFER_SIZE);
|
|
||||||
printf("%sF%s", TT_CLR_RED, TT_CLR_RES);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
printf("%s.%s", TT_CLR_GRN, TT_CLR_RES);
|
printf("%s.%s", TT_CLR_GRN, TT_CLR_RES);
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
if(tt_verbose)
|
||||||
|
printf("[%sCRASHED%s]\n", TT_CLR_RED, TT_CLR_RES);
|
||||||
|
else
|
||||||
|
printf("%sC%s", TT_CLR_RED, TT_CLR_RES);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if(tt_verbose)
|
||||||
|
printf("[%sFAILED%s]\n", TT_CLR_YEL, TT_CLR_RES);
|
||||||
|
else
|
||||||
|
printf("%sF%s", TT_CLR_YEL, TT_CLR_RES);
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int retval = failed+crashed;
|
||||||
|
|
||||||
|
// Print summary
|
||||||
|
if(!tt_silent)
|
||||||
|
{
|
||||||
|
printf("\n%s", (retval)?TT_CLR_RED:TT_CLR_GRN);
|
||||||
|
printf("%d tests, %d failures", tt_test_count, retval);
|
||||||
|
printf("%s\n", TT_CLR_RES);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(retval && tt_silent)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Ran %d tests in %s\n", i, tt_filename);
|
|
||||||
free(buffer);
|
// Print any errors
|
||||||
if(failures)
|
|
||||||
{
|
|
||||||
printf("%sFAILED%s (failures=%d)\n", TT_CLR_RED, TT_CLR_RES, failures);
|
|
||||||
i = 0;
|
i = 0;
|
||||||
printf("%s========================================%s\n", TT_CLR_RED, TT_CLR_RES);
|
while(i < tt_test_count)
|
||||||
while(i < failures)
|
|
||||||
{
|
{
|
||||||
printf("%s", errors[i]);
|
if(tt_tests[i].status)
|
||||||
free(errors[i]);
|
printf("%s", tt_tests[i].output);
|
||||||
|
free(tt_tests[i].output);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
printf("%s========================================%s\n", TT_CLR_RED, TT_CLR_RES);
|
|
||||||
free(errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
return failures;
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
10
ttest
10
ttest
@ -9,16 +9,15 @@ main()
|
|||||||
local files=`find $dir -name "*.tt"`
|
local files=`find $dir -name "*.tt"`
|
||||||
for suite in $files; do
|
for suite in $files; do
|
||||||
|
|
||||||
|
test_exec="${suite}est"
|
||||||
test_exec=`mktemp /tmp/tmp.XXXXXX`
|
compiler_output=`cc -x c $suite -o $test_exec -I $dir/include -I toolchain -DTTEST 2>&1`
|
||||||
compiler_output=`cc -x c $suite -o $test_exec -ggdb -I $dir/include -I toolchain -DTTEST 2>&1`
|
|
||||||
compiler_status=$?
|
compiler_status=$?
|
||||||
|
|
||||||
echo -e "\x1b[35m$suite\x1b[0m"
|
|
||||||
if [[ "$compiler_status" -eq "0" ]]; then
|
if [[ "$compiler_status" -eq "0" ]]; then
|
||||||
$test_exec $suite || failures=$(($failures + 1))
|
$test_exec $@ || failures=$(($failures + 1))
|
||||||
else
|
else
|
||||||
failures=$(($failures + 1))
|
failures=$(($failures + 1))
|
||||||
|
echo
|
||||||
echo -e "\x1b[31mCOMPILATION OF SUITE FAILED\x1b[0m"
|
echo -e "\x1b[31mCOMPILATION OF SUITE FAILED\x1b[0m"
|
||||||
echo "$compiler_output" | sed -e 's/\.tt\.c:/\.tt:/'
|
echo "$compiler_output" | sed -e 's/\.tt\.c:/\.tt:/'
|
||||||
fi
|
fi
|
||||||
@ -26,6 +25,7 @@ main()
|
|||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
exit $failures
|
exit $failures
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user