Merge branch 'main' of gitlab.cs.wallawalla.edu:cptr354/student354 into update-upstream

This commit is contained in:
vel 2024-11-13 23:34:28 -08:00
commit 2855f404a3
Signed by: velvox
GPG Key ID: 59D9762F674151DF
2 changed files with 148 additions and 129 deletions

View File

@ -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) {
char* read_file_dynamic(const char* filename) {
FILE* file = fopen(filename, "r");
if (file == NULL) {
perror("fopen");
exit(EXIT_FAILURE);
return NULL;
}
size_t n =
fread(expected_output, 1, sizeof(expected_output) - 1, expected_file);
expected_output[n] = '\0';
fclose(expected_file);
// 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);
UTEST_F_SETUP(InterpreterTestFile) {
}
// 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(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";
}

View File

@ -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,23 +655,22 @@ 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")), \
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
/*
@ -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,15 +1170,21 @@ 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) { \
} else { \
if (utest_state.tests) { \
free(utest_state.tests); \
utest_state.tests = NULL; \
} \
if (name) { \
free(name); \
} \
} \
} \
UTEST_SURPRESS_WARNINGS_END \
void utest_run_##SET##_##NAME(int *utest_result)
@ -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,14 +1224,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_f_##FIXTURE##_##NAME; \
utest_state.tests[index].name = name; \
UTEST_SNPRINTF(name, name_size, "%s", name_part); \
} else if (name) { \
} else { \
if (utest_state.tests) { \
free(utest_state.tests); \
utest_state.tests = NULL; \
} \
if (name) { \
free(name); \
} \
} \
} \
UTEST_SURPRESS_WARNINGS_END \
void utest_run_##FIXTURE##_##NAME(int *utest_result, \
struct FIXTURE *utest_fixture)
@ -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,17 +1278,23 @@ 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) { \
} else { \
if (utest_state.tests) { \
free(utest_state.tests); \
utest_state.tests = NULL; \
} \
if (name) { \
free(name); \
} \
} \
} \
} \
UTEST_SURPRESS_WARNINGS_END \
void utest_run_##FIXTURE##_##NAME##_##INDEX(int *utest_result, \
struct FIXTURE *utest_fixture)