Updating testing to use fixtures
This commit is contained in:
parent
b5d4b576d1
commit
4e7e1f43f5
|
|
@ -19,20 +19,45 @@ extern int yylineno;
|
|||
|
||||
UTEST_MAIN();
|
||||
|
||||
void read_file(const char *filename, char *expected_output) {
|
||||
// Read the expected output from a file
|
||||
FILE *expected_file = fopen(filename, "r");
|
||||
if (expected_file == NULL) {
|
||||
perror("fopen");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
size_t n =
|
||||
fread(expected_output, 1, sizeof(expected_output) - 1, expected_file);
|
||||
expected_output[n] = '\0';
|
||||
fclose(expected_file);
|
||||
char* read_file_dynamic(const char* filename) {
|
||||
FILE* file = fopen(filename, "r");
|
||||
if (file == NULL) {
|
||||
perror("fopen");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Seek to the end of the file to determine its size
|
||||
fseek(file, 0, SEEK_END);
|
||||
long file_size = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
// Allocate a buffer to hold the file contents
|
||||
char* buffer = (char*)malloc(file_size + 1);
|
||||
if (buffer == NULL) {
|
||||
perror("malloc");
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read the entire file into the buffer
|
||||
size_t read_size = fread(buffer, 1, file_size, file);
|
||||
if (read_size != file_size) {
|
||||
perror("fread");
|
||||
free(buffer);
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Null-terminate the buffer
|
||||
buffer[file_size] = '\0';
|
||||
|
||||
fclose(file);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void redirect_stdout(const char *filename, int evalutate) {
|
||||
fflush(stdout);
|
||||
|
||||
// Redirect stdout to a temporary file
|
||||
FILE *temp_file = fopen(filename, "w");
|
||||
if (temp_file == NULL) {
|
||||
|
|
@ -56,42 +81,18 @@ void redirect_stdout(const char *filename, int evalutate) {
|
|||
close(stdout_fd);
|
||||
}
|
||||
|
||||
UTEST(interpreter, print) {
|
||||
struct InterpreterTestFile {
|
||||
const char *evaluated_file;
|
||||
const char *print_file;
|
||||
const char *test_file;
|
||||
};
|
||||
|
||||
yyin = fopen("samples/multiple_statements.c", "r");
|
||||
yyrestart(yyin);
|
||||
ASSERT_TRUE(yyin);
|
||||
|
||||
// yylineno = 1;
|
||||
yylineno = 1;
|
||||
int result = yyparse();
|
||||
|
||||
if (result == 0) {
|
||||
// Catch the standard output and compare with expected test result
|
||||
redirect_stdout("test_print.txt", 0);
|
||||
redirect_stdout("test_evaluate.txt", 1);
|
||||
}
|
||||
|
||||
// Assert the result to test correctness
|
||||
ASSERT_EQ(result, 0);
|
||||
|
||||
char actual_print[1024];
|
||||
read_file("test_print.txt", actual_print);
|
||||
char expected_print[1024];
|
||||
read_file("samples/multiple_statements_print.txt", expected_print);
|
||||
ASSERT_STREQ(actual_print, expected_print);
|
||||
|
||||
char actual_evaluate[1024];
|
||||
read_file("test_evaluate.txt", actual_evaluate);
|
||||
char expected_evaluate[1024];
|
||||
read_file("samples/multiple_statements_evaluate.txt", expected_evaluate);
|
||||
ASSERT_STREQ(actual_evaluate, expected_evaluate);
|
||||
UTEST_F_SETUP(InterpreterTestFile) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
UTEST(interpreter, program) {
|
||||
yyin = fopen("samples/program.c", "r");
|
||||
UTEST_F_TEARDOWN(InterpreterTestFile) {
|
||||
// and also assert and expect in teardown!
|
||||
yyin = fopen(utest_fixture->test_file, "r");
|
||||
yyrestart(yyin);
|
||||
ASSERT_TRUE(yyin);
|
||||
|
||||
|
|
@ -107,55 +108,23 @@ UTEST(interpreter, program) {
|
|||
// Assert the result to test correctness
|
||||
ASSERT_EQ(result, 0);
|
||||
|
||||
char actual_print[1024];
|
||||
read_file("test_print.txt", actual_print);
|
||||
char expected_print[1024];
|
||||
read_file("samples/program_print.txt", expected_print);
|
||||
char *actual_print = read_file_dynamic("test_print.txt");
|
||||
char *expected_print = read_file_dynamic(utest_fixture->print_file);
|
||||
ASSERT_STREQ(actual_print, expected_print);
|
||||
|
||||
char actual_evaluate[1024];
|
||||
read_file("test_evaluate.txt", actual_evaluate);
|
||||
char expected_evaluate[1024];
|
||||
read_file("samples/program_evaluate.txt", expected_evaluate);
|
||||
char *actual_evaluate = read_file_dynamic("test_evaluate.txt");
|
||||
char *expected_evaluate = read_file_dynamic(utest_fixture->evaluated_file);
|
||||
ASSERT_STREQ(actual_evaluate, expected_evaluate);
|
||||
}
|
||||
|
||||
// UTEST(parser, missing_new_line) {
|
||||
// // Must include the null character to terminate input
|
||||
// char string[] = "1+8/4-3\0";
|
||||
// YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string));
|
||||
UTEST_F(InterpreterTestFile, print) {
|
||||
utest_fixture->test_file = "samples/multiple_statements.c";
|
||||
utest_fixture->print_file = "samples/multiple_statements_print.txt";
|
||||
utest_fixture->evaluated_file = "samples/multiple_statements_evaluate.txt";
|
||||
}
|
||||
|
||||
// yylineno = 1;
|
||||
// int result = yyparse();
|
||||
|
||||
// yy_delete_buffer(buffer);
|
||||
|
||||
// // Assert the result to test correctness
|
||||
// ASSERT_EQ(result, 1);
|
||||
// }
|
||||
|
||||
// UTEST(parser, hello_world) {
|
||||
// // Read sample file as input
|
||||
// yyin = fopen("samples/hello.py", "r");
|
||||
// yyrestart(yyin);
|
||||
// ASSERT_TRUE(yyin);
|
||||
|
||||
// yylineno = 1;
|
||||
// int result = yyparse();
|
||||
|
||||
// // Assert the result to test correctness
|
||||
// ASSERT_EQ(result, 0);
|
||||
// }
|
||||
|
||||
// UTEST(parser, quadratic) {
|
||||
// // Read sample file as input
|
||||
// yyin = fopen("samples/quadratic.py", "r");
|
||||
// yyrestart(yyin);
|
||||
// ASSERT_TRUE(yyin);
|
||||
|
||||
// yylineno = 1;
|
||||
// int result = yyparse();
|
||||
|
||||
// // Assert the result to test correctness
|
||||
// ASSERT_EQ(result, 0);
|
||||
// }
|
||||
UTEST_F(InterpreterTestFile, program_file) {
|
||||
utest_fixture->test_file = "samples/program.c";
|
||||
utest_fixture->print_file = "samples/program_print.txt";
|
||||
utest_fixture->evaluated_file = "samples/program_evaluate.txt";
|
||||
}
|
||||
|
|
|
|||
126
lab-5/utest.h
126
lab-5/utest.h
|
|
@ -255,8 +255,8 @@ UTEST_C_FUNC __declspec(dllimport) int __stdcall QueryPerformanceFrequency(
|
|||
static void __cdecl f(void); \
|
||||
UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \
|
||||
__pragma(comment(linker, "/include:" UTEST_SYMBOL_PREFIX #f "_")) \
|
||||
UTEST_C_FUNC __declspec(allocate(".CRT$XCU")) void(__cdecl * \
|
||||
f##_)(void) = f; \
|
||||
UTEST_C_FUNC \
|
||||
__declspec(allocate(".CRT$XCU")) void(__cdecl * f##_)(void) = f; \
|
||||
UTEST_INITIALIZER_END_DISABLE_WARNINGS \
|
||||
static void __cdecl f(void)
|
||||
#else
|
||||
|
|
@ -321,22 +321,32 @@ static UTEST_INLINE void *utest_realloc(void *const pointer, size_t new_size) {
|
|||
void *const new_pointer = realloc(pointer, new_size);
|
||||
|
||||
if (UTEST_NULL == new_pointer) {
|
||||
free(new_pointer);
|
||||
free(pointer);
|
||||
}
|
||||
|
||||
return new_pointer;
|
||||
}
|
||||
|
||||
// Prevent 64-bit integer overflow when computing a timestamp by using a trick
|
||||
// from Sokol:
|
||||
// https://github.com/floooh/sokol/blob/189843bf4f86969ca4cc4b6d94e793a37c5128a7/sokol_time.h#L204
|
||||
static UTEST_INLINE utest_int64_t utest_mul_div(const utest_int64_t value,
|
||||
const utest_int64_t numer,
|
||||
const utest_int64_t denom) {
|
||||
const utest_int64_t q = value / denom;
|
||||
const utest_int64_t r = value % denom;
|
||||
return q * numer + r * numer / denom;
|
||||
}
|
||||
|
||||
static UTEST_INLINE utest_int64_t utest_ns(void) {
|
||||
#if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__)
|
||||
utest_large_integer counter;
|
||||
utest_large_integer frequency;
|
||||
QueryPerformanceCounter(&counter);
|
||||
QueryPerformanceFrequency(&frequency);
|
||||
return UTEST_CAST(utest_int64_t,
|
||||
(counter.QuadPart * 1000000000) / frequency.QuadPart);
|
||||
return utest_mul_div(counter.QuadPart, 1000000000, frequency.QuadPart);
|
||||
#elif defined(__linux__) && defined(__STRICT_ANSI__)
|
||||
return UTEST_CAST(utest_int64_t, clock()) * 1000000000 / CLOCKS_PER_SEC;
|
||||
return utest_mul_div(clock(), 1000000000, CLOCKS_PER_SEC);
|
||||
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
|
||||
defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun__) || \
|
||||
defined(__HAIKU__)
|
||||
|
|
@ -447,6 +457,15 @@ struct utest_type_deducer final {
|
|||
static void _(const T t);
|
||||
};
|
||||
|
||||
template <> struct utest_type_deducer<char, false> {
|
||||
static void _(const char c) {
|
||||
if (std::is_signed<decltype(c)>::value) {
|
||||
UTEST_PRINTF("%d", static_cast<int>(c));
|
||||
} else {
|
||||
UTEST_PRINTF("%u", static_cast<unsigned int>(c));
|
||||
}
|
||||
}
|
||||
};
|
||||
template <> struct utest_type_deducer<signed char, false> {
|
||||
static void _(const signed char c) {
|
||||
UTEST_PRINTF("%d", static_cast<int>(c));
|
||||
|
|
@ -512,6 +531,10 @@ template <> struct utest_type_deducer<unsigned long long, false> {
|
|||
static void _(const unsigned long long i) { UTEST_PRINTF("%llu", i); }
|
||||
};
|
||||
|
||||
template <> struct utest_type_deducer<bool, false> {
|
||||
static void _(const bool i) { UTEST_PRINTF(i ? "true" : "false"); }
|
||||
};
|
||||
|
||||
template <typename T> struct utest_type_deducer<const T *, false> {
|
||||
static void _(const T *t) {
|
||||
UTEST_PRINTF("%p", static_cast<void *>(const_cast<T *>(t)));
|
||||
|
|
@ -528,6 +551,12 @@ template <typename T> struct utest_type_deducer<T, true> {
|
|||
}
|
||||
};
|
||||
|
||||
template <> struct utest_type_deducer<std::nullptr_t, false> {
|
||||
static void _(std::nullptr_t t) {
|
||||
UTEST_PRINTF("%p", static_cast<void *>(t));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(const T t) {
|
||||
utest_type_deducer<T>::_(t);
|
||||
|
|
@ -626,24 +655,23 @@ utest_type_printer(long long unsigned int i) {
|
|||
!(defined(__MINGW32__) || defined(__MINGW64__)) || \
|
||||
defined(__TINYC__)
|
||||
#define utest_type_printer(val) \
|
||||
UTEST_PRINTF(_Generic((val), signed char \
|
||||
: "%d", unsigned char \
|
||||
: "%u", short \
|
||||
: "%d", unsigned short \
|
||||
: "%u", int \
|
||||
: "%d", long \
|
||||
: "%ld", long long \
|
||||
: "%lld", unsigned \
|
||||
: "%u", unsigned long \
|
||||
: "%lu", unsigned long long \
|
||||
: "%llu", float \
|
||||
: "%f", double \
|
||||
: "%f", long double \
|
||||
: "%Lf", default \
|
||||
: _Generic((val - val), ptrdiff_t \
|
||||
: "%p", default \
|
||||
: "undef")), \
|
||||
(val))
|
||||
UTEST_PRINTF( \
|
||||
_Generic((val), \
|
||||
signed char: "%d", \
|
||||
unsigned char: "%u", \
|
||||
short: "%d", \
|
||||
unsigned short: "%u", \
|
||||
int: "%d", \
|
||||
long: "%ld", \
|
||||
long long: "%lld", \
|
||||
unsigned: "%u", \
|
||||
unsigned long: "%lu", \
|
||||
unsigned long long: "%llu", \
|
||||
float: "%f", \
|
||||
double: "%f", \
|
||||
long double: "%Lf", \
|
||||
default: _Generic((val - val), ptrdiff_t: "%p", default: "undef")), \
|
||||
(val))
|
||||
#else
|
||||
/*
|
||||
we don't have the ability to print the values we got, so we create a macro
|
||||
|
|
@ -724,10 +752,12 @@ utest_strncpy_gcc(char *const dst, const char *const src, const size_t size) {
|
|||
UTEST_AUTO(x) xEval = (x); \
|
||||
UTEST_AUTO(y) yEval = (y); \
|
||||
if (!((xEval)cond(yEval))) { \
|
||||
const char *const xAsString = #x; \
|
||||
const char *const yAsString = #y; \
|
||||
_Pragma("clang diagnostic pop") \
|
||||
UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \
|
||||
UTEST_PRINTF(" Expected : ("); \
|
||||
UTEST_PRINTF(#x ") " #cond " (" #y); \
|
||||
UTEST_PRINTF("%s) " #cond " (%s", xAsString, yAsString); \
|
||||
UTEST_PRINTF(")\n"); \
|
||||
UTEST_PRINTF(" Actual : "); \
|
||||
utest_type_printer(xEval); \
|
||||
|
|
@ -751,9 +781,11 @@ utest_strncpy_gcc(char *const dst, const char *const src, const size_t size) {
|
|||
UTEST_AUTO(x) xEval = (x); \
|
||||
UTEST_AUTO(y) yEval = (y); \
|
||||
if (!((xEval)cond(yEval))) { \
|
||||
const char *const xAsString = #x; \
|
||||
const char *const yAsString = #y; \
|
||||
UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \
|
||||
UTEST_PRINTF(" Expected : ("); \
|
||||
UTEST_PRINTF(#x ") " #cond " (" #y); \
|
||||
UTEST_PRINTF("%s) " #cond " (%s", xAsString, yAsString); \
|
||||
UTEST_PRINTF(")\n"); \
|
||||
UTEST_PRINTF(" Actual : "); \
|
||||
utest_type_printer(xEval); \
|
||||
|
|
@ -1130,7 +1162,7 @@ utest_strncpy_gcc(char *const dst, const char *const src, const size_t size) {
|
|||
} \
|
||||
UTEST_INITIALIZER(utest_register_##SET##_##NAME) { \
|
||||
const size_t index = utest_state.tests_length++; \
|
||||
const char *name_part = #SET "." #NAME; \
|
||||
const char name_part[] = #SET "." #NAME; \
|
||||
const size_t name_size = strlen(name_part) + 1; \
|
||||
char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \
|
||||
utest_state.tests = UTEST_PTR_CAST( \
|
||||
|
|
@ -1138,13 +1170,19 @@ utest_strncpy_gcc(char *const dst, const char *const src, const size_t size) {
|
|||
utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \
|
||||
sizeof(struct utest_test_state_s) * \
|
||||
utest_state.tests_length)); \
|
||||
if (utest_state.tests) { \
|
||||
if (utest_state.tests && name) { \
|
||||
utest_state.tests[index].func = &utest_##SET##_##NAME; \
|
||||
utest_state.tests[index].name = name; \
|
||||
utest_state.tests[index].index = 0; \
|
||||
UTEST_SNPRINTF(name, name_size, "%s", name_part); \
|
||||
} else if (name) { \
|
||||
free(name); \
|
||||
} else { \
|
||||
if (utest_state.tests) { \
|
||||
free(utest_state.tests); \
|
||||
utest_state.tests = NULL; \
|
||||
} \
|
||||
if (name) { \
|
||||
free(name); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
UTEST_SURPRESS_WARNINGS_END \
|
||||
|
|
@ -1178,7 +1216,7 @@ utest_strncpy_gcc(char *const dst, const char *const src, const size_t size) {
|
|||
} \
|
||||
UTEST_INITIALIZER(utest_register_##FIXTURE##_##NAME) { \
|
||||
const size_t index = utest_state.tests_length++; \
|
||||
const char *name_part = #FIXTURE "." #NAME; \
|
||||
const char name_part[] = #FIXTURE "." #NAME; \
|
||||
const size_t name_size = strlen(name_part) + 1; \
|
||||
char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \
|
||||
utest_state.tests = UTEST_PTR_CAST( \
|
||||
|
|
@ -1186,12 +1224,18 @@ utest_strncpy_gcc(char *const dst, const char *const src, const size_t size) {
|
|||
utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \
|
||||
sizeof(struct utest_test_state_s) * \
|
||||
utest_state.tests_length)); \
|
||||
if (utest_state.tests) { \
|
||||
if (utest_state.tests && name) { \
|
||||
utest_state.tests[index].func = &utest_f_##FIXTURE##_##NAME; \
|
||||
utest_state.tests[index].name = name; \
|
||||
UTEST_SNPRINTF(name, name_size, "%s", name_part); \
|
||||
} else if (name) { \
|
||||
free(name); \
|
||||
} else { \
|
||||
if (utest_state.tests) { \
|
||||
free(utest_state.tests); \
|
||||
utest_state.tests = NULL; \
|
||||
} \
|
||||
if (name) { \
|
||||
free(name); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
UTEST_SURPRESS_WARNINGS_END \
|
||||
|
|
@ -1226,7 +1270,7 @@ utest_strncpy_gcc(char *const dst, const char *const src, const size_t size) {
|
|||
utest_uint64_t iUp; \
|
||||
for (i = 0; i < (INDEX); i++) { \
|
||||
const size_t index = utest_state.tests_length++; \
|
||||
const char *name_part = #FIXTURE "." #NAME; \
|
||||
const char name_part[] = #FIXTURE "." #NAME; \
|
||||
const size_t name_size = strlen(name_part) + 32; \
|
||||
char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \
|
||||
utest_state.tests = UTEST_PTR_CAST( \
|
||||
|
|
@ -1234,14 +1278,20 @@ utest_strncpy_gcc(char *const dst, const char *const src, const size_t size) {
|
|||
utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \
|
||||
sizeof(struct utest_test_state_s) * \
|
||||
utest_state.tests_length)); \
|
||||
if (utest_state.tests) { \
|
||||
if (utest_state.tests && name) { \
|
||||
utest_state.tests[index].func = &utest_i_##FIXTURE##_##NAME##_##INDEX; \
|
||||
utest_state.tests[index].index = i; \
|
||||
utest_state.tests[index].name = name; \
|
||||
iUp = UTEST_CAST(utest_uint64_t, i); \
|
||||
UTEST_SNPRINTF(name, name_size, "%s/%" UTEST_PRIu64, name_part, iUp); \
|
||||
} else if (name) { \
|
||||
free(name); \
|
||||
} else { \
|
||||
if (utest_state.tests) { \
|
||||
free(utest_state.tests); \
|
||||
utest_state.tests = NULL; \
|
||||
} \
|
||||
if (name) { \
|
||||
free(name); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
|
|
|
|||
Loading…
Reference in New Issue