aboutsummaryrefslogtreecommitdiff
path: root/tests/test.h
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test.h')
-rw-r--r--tests/test.h217
1 files changed, 217 insertions, 0 deletions
diff --git a/tests/test.h b/tests/test.h
new file mode 100644
index 0000000..23fb5cd
--- /dev/null
+++ b/tests/test.h
@@ -0,0 +1,217 @@
+// Library used for writing tests, must be included once for definitions and
+// once for the `main()` function.
+//
+// DOCUMENTATION
+// Expect(expr)
+// Macro that will return early if the expression is false, calling
+// `tb_shutdown()` to save the terminal. It will also print the expression
+// and line on which it occurred for convenience
+//
+// test_functions TestFunctions
+// Global variable containing the function (test). This array is
+// 0-terminated.
+//
+// TESTFUNC()
+// Macro for adding functions to TestFunctions array conveniently.
+//
+// tb_get_cell(x, y)
+// Function
+//
+// EXAMPLE
+// #define TEST_IMPL
+// #include "test.h"
+//
+// bool FooTest()
+// {
+// Expect(0 == 1);
+// return true;
+// }
+//
+// test_functions TestFunctions[] = {
+// TESTFUNC(FooTest),
+// {0}
+// }
+//
+// int main(int Argc, int Argv)
+// {
+// Test(Argc, Argv);
+// }
+
+#ifndef TEST_H
+#define TEST_H
+
+#include <stdio.h>
+#include <stdbool.h>
+
+#include "../source/chatty.h"
+
+/* Macro's */
+#define Expect(expr) if (!(expr)) \
+ { \
+ tb_shutdown(); \
+ printf("\n %d: %s\n", __LINE__, #expr); \
+ return false; \
+ }
+
+#define TESTFUNC(func) { func, #func }
+
+/* Types */
+typedef struct {
+ bool (*Func)(void);
+ const char * Name;
+} test_functions;
+
+typedef struct {
+ s32 X, Y, W, H;
+} rect;
+
+/* Declarations */
+struct tb_cell tb_get_cell(s32 x, s32 y);
+void RectCopy(rect Dest, rect Source);
+bool RectCmp(rect Dest, rect Source);
+bool TextCmp(s32 X, s32 Y, wchar_t *Text, s32 TextLen);
+bool TextCmpWithColor(s32 X, s32 Y, wchar_t *Text, s32 TextLen, s32 fg, s32 bg);
+
+/* Global variables */
+void (*Before)(void);
+void (*After)(void);
+
+/* Functions*/
+struct tb_cell
+tb_get_cell(s32 x, s32 y)
+{
+ return global.back.cells[global.width * y + x];
+}
+
+void
+RectCopy(rect Dest, rect Source)
+{
+ for (u32 Y = 0; Y < Source.H; Y++)
+ {
+ for (u32 X = 0; X < Source.W; X++)
+ {
+ struct tb_cell Cell = tb_get_cell(Source.X + X, Source.Y + Y);
+ tb_set_cell(Dest.X + X, Dest.Y + Y, Cell.ch, Cell.fg, Cell.bg);
+ }
+ }
+}
+
+bool
+RectCmp(rect Dest, rect Source)
+{
+ for (u32 Y = 0; Y < Source.H; Y++)
+ {
+ for (u32 X = 0; X < Source.W; X++)
+ {
+ struct tb_cell SourceCell = tb_get_cell(Source.X + X, Source.Y + Y);
+ struct tb_cell DestCell = tb_get_cell(Dest.X + X, Dest.Y + Y);
+ if (!(SourceCell.fg == DestCell.fg &&
+ SourceCell.bg == DestCell.bg &&
+ SourceCell.ch == DestCell.ch))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool
+TextCmp(s32 X, s32 Y, wchar_t *Text, s32 TextLen)
+{
+ for (u32 At = 0;
+ At < TextLen;
+ At++)
+ {
+ struct tb_cell DestCell = tb_get_cell(X++, Y);
+ if (DestCell.ch != Text[At]) return false;
+ }
+
+ return true;
+}
+
+bool
+TextCmpWithColor(s32 X, s32 Y, wchar_t *Text, s32 TextLen, s32 fg, s32 bg)
+{
+ for (u32 At = 0;
+ At < TextLen;
+ At++)
+ {
+ struct tb_cell DestCell = tb_get_cell(X++, Y);
+ if (DestCell.ch != Text[At] ||
+ DestCell.fg != fg ||
+ DestCell.bg != bg)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int
+Test(test_functions *TestFunctions, int Argc, char *Argv[])
+{
+ u32 TestFunctionsLen = 0;
+ while (TestFunctions[TestFunctionsLen].Func) TestFunctionsLen++;
+
+ if (Argc > 1)
+ {
+ for (u32 Arg = 0;
+ Arg < Argc;
+ Arg++)
+ {
+ char *Function = Argv[Arg];
+
+ for (u32 TestFunc = 0;
+ TestFunc < TestFunctionsLen;
+ TestFunc++)
+ {
+ if(!strcmp(Function, TestFunctions[TestFunc].Name))
+ {
+ printf("%s ", TestFunctions[TestFunc].Name);
+
+ if (Before) Before();
+ bool Ret = TestFunctions[TestFunc].Func();
+ if (After) After();
+
+ if (Ret)
+ {
+ printf("\033[32mPASSED\033[0m\n");
+ }
+ else
+ {
+ printf("\033[31mFAILED\033[0m\n"); \
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ for (int At = 0;
+ TestFunctions[At].Func;
+ At++)
+ {
+ printf("%s ", TestFunctions[At].Name);
+
+ if (Before) Before();
+ bool Ret = TestFunctions[At].Func();
+ if (After) After();
+
+ if (Ret)
+ {
+ printf("\033[32mPASSED\033[0m\n");
+ }
+ else
+ {
+ printf("\033[31mFAILED\033[0m\n"); \
+ }
+ }
+ }
+
+ return 0;
+}
+
+#endif // TEST_H