libpulsar
A modular compiler for the pulsar programming language
Loading...
Searching...
No Matches
unit_testing.c
Go to the documentation of this file.
1// Copyright (C) 2023 Ethan Uppal. All rights reserved.
2
3#include <stdio.h> // FILE, fopen, fprintf, fclose, fflush
4#include <libgen.h> // basename
5#include <stdlib.h> // exit
6#include <stdarg.h> // va_list, va_start, va_end
7#include <string.h> // snprintf
8#include <stdbool.h> // bool
9#include "unit_testing.h"
10#include "util/abort.h" // ps_abort
11
12// The name of the file being tested
14
15// The name of the file to write the report to
16static char UNIT_TEST_RESULTS_FILE[100];
17
18// Whether or not the output is surpressed
19bool is_surpressed = false;
20
21// Whether or not a test failed during surpression
23
24// The file to write the report to
25static FILE* _ps_unit_test_file = NULL;
26
27// The status of the unit tests
28// 0 = successful
29// 1 = failure
30static int status = 0;
31
33 // Create the report filename
34 _ps_this_file = basename((char*)file); // idk if this cast is bad
35 snprintf(UNIT_TEST_RESULTS_FILE, sizeof(UNIT_TEST_RESULTS_FILE),
36 "tests/reports/%s report.txt", _ps_this_file);
37
38 // Create the report file
39 _ps_unit_test_file = fopen(UNIT_TEST_RESULTS_FILE, "w");
40 if (!_ps_unit_test_file) {
41 ps_abort("failed to create unit test report file.");
42 }
43
44 // Write the header
45 if (fprintf(_ps_unit_test_file, "🤔 Unit test report for %s\n",
47 < 0) {
48 ps_abort("failed to write to unit test report file.");
49 }
50 fflush(_ps_unit_test_file);
51
52 // Register the exit handler
53 atexit(PS_END_UNIT_TESTS);
54}
55
57 // Write the footer
58 fprintf(_ps_unit_test_file, "🫡 Unit test report for %s: %s\n",
59 _ps_this_file, status ? "FAILED" : "PASSED");
60
61 // Close the report file
62 if (fclose(_ps_unit_test_file) != 0) {
63 ps_abort("failed to close unit test report file.");
64 }
65
66 // Exit with the status
67 ps_exit(status);
68}
69
70void _PS_UNIT_ASSERT(int result, STR expr, STR func, u64 line, STR msg, ...) {
71 if (!is_surpressed) {
72 // Print the result of the test
73 fprintf(_ps_unit_test_file, "%s %s:%llu:%s: %s\n", result ? "✅" : "❌",
74 _ps_this_file, line, func, expr);
75
76 // Optionally print the message for the test
77 if (*msg) {
78 fputc('\t', _ps_unit_test_file);
79 va_list args;
80 va_start(args, msg);
81 vfprintf(_ps_unit_test_file, msg, args);
82 va_end(args);
83 fputc('\n', _ps_unit_test_file);
84 }
85
86 // Force the report file to update
87 fflush(_ps_unit_test_file);
88 }
89
90 if (!result) {
91 status = 1;
92
93 if (is_surpressed) {
94 // Surpressed tests should only print their first error
96 fprintf(_ps_unit_test_file,
97 "❌ %s:%llu:%s: %s\n\tAn error occured "
98 "while surpressed\n",
99 _ps_this_file, line, func, expr);
100
101 // Force the report file to update
102 fflush(_ps_unit_test_file);
103 }
105 }
106 }
107}
108
109void _PS_UNIT_SUPPRESS(STR msg, STR func, u64 line) {
110 if (!is_surpressed) {
111 fprintf(_ps_unit_test_file, "🤫 %s:%llu:%s: Output surpressed:\n\t%s\n",
112 _ps_this_file, line, func, msg);
113 fflush(_ps_unit_test_file);
114 }
115 is_surpressed = true;
116 surpressed_gave_error = false;
117}
118
120 if (is_surpressed) {
121 fprintf(_ps_unit_test_file, "🗣️ %s: Output unsurpressed: %s\n",
123 surpressed_gave_error ? "A failure occured" : "No failure occured");
124 fflush(_ps_unit_test_file);
125 }
126 is_surpressed = false;
127}
Defines assertion and abortion functionality.
#define ps_abort(msg)
Aborts the program with the given message.
Definition abort.h:47
#define STR
Definition def.h:40
#define u64
Definition def.h:48
void _PS_BEGIN_UNIT_TESTS(STR file)
void _PS_UNIT_ASSERT(int result, STR expr, STR func, u64 line, STR msg,...)
void PS_END_UNIT_TESTS(void)
End unit tests.
STR _ps_this_file
bool is_surpressed
void _PS_UNIT_SUPPRESS(STR msg, STR func, u64 line)
void PS_UNIT_UNSUPPRESS(void)
Unsuppress unit test output.
bool surpressed_gave_error
Provides assertion macros for unit tests.