summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorphysick <mynameisgennadiy@vk.com>2026-08-12 18:33:52 +0500
committerphysick <mynameisgennadiy@vk.com>2026-08-29 14:17:03 +0500
commitd16a1385efe911b1683e390f672cadee78b842be (patch)
tree9c4a5e8a01952befa6b48c8fee4bd7471dbf421f
parentb1b2586afa06105291355a19f581016c347463bc (diff)
test system
-rw-r--r--build.zig131
-rw-r--r--src/main.c3
-rw-r--r--src/tests/arena_tests.c39
-rw-r--r--src/tests/runner.c37
-rw-r--r--src/tests/test.h16
5 files changed, 177 insertions, 49 deletions
diff --git a/build.zig b/build.zig
index 15e908c..2d7c1ce 100644
--- a/build.zig
+++ b/build.zig
@@ -4,79 +4,118 @@ const builtin = @import("builtin");
const HEAD_location = ".git/HEAD";
const commit_location = ".git/refs/heads/master";
+const common_c_files = &[_][]const u8 {
+ "src/utils/stringBuilder.c",
+ "src/utils/arena.c",
+ "src/wren_inter/wren_inter.c",
+ "src/resources/resources.c",
+ "src/resources/config.c",
+ "src/ui_elements/UI.c",
+ "src/ui_elements/TextEditor.c",
+ "src/ui_elements/Button.c",
+ "src/scenes/sceneManager.c",
+ "src/scenes/mainMenu.c",
+ "src/scenes/resultView.c",
+ "src/scenes/puzzleScene.c",
+ "src/scenes/distractionScene.c",
+ "src/scenes/collectionScene.c",
+ "src/puzzles/puzzle.c",
+ "src/puzzles/parser.c",
+ "src/puzzles//distractions.c",
+};
+
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
- const root = b.addModule("game-mod", .{
+ // ========== Building a game ==========
+
+ var game_root = b.addModule("game-mod", .{
.optimize = optimize,
.target = target,
.link_libc = true,
});
+ FillModule(b, game_root, optimize);
-
- // Adding a build version
+ // The entry point. This is put there separatly to separate from tests entry point
+ game_root.addCSourceFile(.{ .file = b.path("src/main.c") });
- const build_ver = GetVersionString(b, optimize) catch "Build UNTRACKED";
- if (build_ver.len > 0)
- root.addCMacro("BUILD_VERSION", build_ver);
+ const exe = b.addExecutable(.{
+ .name = "game",
+ .root_module = game_root,
+ });
+
+ b.installArtifact(exe);
- root.addCSourceFiles(.{
+ // ========== Running a game ==========
+
+ const run_step = b.step("run", "Run the app");
+ const run_cmd = b.addRunArtifact(exe);
+ run_step.dependOn(&run_cmd.step);
+ if (b.args) |args| {
+ run_cmd.addArgs(args);
+ }
+
+ // ========== Building and running tests ==========
+
+ const test_runner_root = b.addModule("test-runner-mod", .{
+ .optimize = optimize,
+ .target = target,
+ .link_libc = true,
+ });
+ FillModule(b, test_runner_root, optimize);
+
+ // The only difference is the additional files
+ test_runner_root.addCSourceFiles(.{
.files = &[_][]const u8 {
- "src/main.c",
- "src/utils/stringBuilder.c",
- "src/utils/arena.c",
- "src/wren_inter/wren_inter.c",
- "src/resources/resources.c",
- "src/resources/config.c",
- "src/ui_elements/UI.c",
- "src/ui_elements/TextEditor.c",
- "src/ui_elements/Button.c",
- "src/scenes/sceneManager.c",
- "src/scenes/mainMenu.c",
- "src/scenes/resultView.c",
- "src/scenes/puzzleScene.c",
- "src/scenes/distractionScene.c",
- "src/scenes/collectionScene.c",
- "src/puzzles/puzzle.c",
- "src/puzzles/parser.c",
- "src/puzzles/distractions.c",
+ "src/tests/runner.c",
+ "src/tests/arena_tests.c",
}
});
+ const test_runner_exe = b.addExecutable(.{
+ .name = "game_tests",
+ .root_module = test_runner_root,
+ });
+
+ const test_run_step = b.step("test", "Run the test app");
+ const test_run_cmd = b.addRunArtifact(test_runner_exe);
+ test_run_step.dependOn(&test_run_cmd.step);
+ if (b.args) |args| {
+ test_run_cmd.addArgs(args);
+ }
+
+}
+
+fn FillModule(b: *std.Build, mod: *std.Build.Module, opt: std.builtin.OptimizeMode) void {
+ // Adding a build version
+ const build_ver = GetVersionString(b, opt) catch "Build UNTRACKED";
+ if (build_ver.len > 0)
+ mod.addCMacro("BUILD_VERSION", build_ver);
+
+ mod.addCSourceFiles(.{
+ .files = common_c_files,
+ });
+
// Linking raylib
if (builtin.target.os.tag == .windows) {
// If you are building on windows you need to provide your own
// raylib. Put it in the raylib dir
- root.addLibraryPath(b.path("raylib/lib/"));
- root.addIncludePath(b.path("raylib/include/"));
+ mod.addLibraryPath(b.path("raylib/lib/"));
+ mod.addIncludePath(b.path("raylib/include/"));
}
- root.linkSystemLibrary("raylib", .{.needed = true});
- root.addIncludePath(b.path("include/"));
+ mod.linkSystemLibrary("raylib", .{.needed = true});
+ mod.addIncludePath(b.path("include/"));
// Linking wren. They do not provide system-wide libraries so you have to
// provide them yourself
- root.addIncludePath(b.path("wren/src/include/"));
- root.addLibraryPath(b.path("wren/lib/"));
- root.linkSystemLibrary("wren", .{
+ mod.addIncludePath(b.path("wren/src/include/"));
+ mod.addLibraryPath(b.path("wren/lib/"));
+ mod.linkSystemLibrary("wren", .{
.needed = true,
.preferred_link_mode = .static,
});
-
- const exe = b.addExecutable(.{
- .name = "game",
- .root_module = root,
- });
-
- b.installArtifact(exe);
-
- const run_step = b.step("run", "Run the app");
- const run_cmd = b.addRunArtifact(exe);
- run_step.dependOn(&run_cmd.step);
- if (b.args) |args| {
- run_cmd.addArgs(args);
- }
}
// Returns a build version. Returns an empty string if build in release mode
diff --git a/src/main.c b/src/main.c
index 34b32e0..e7275dc 100644
--- a/src/main.c
+++ b/src/main.c
@@ -26,9 +26,6 @@ int main(void) {
return 1;
}
- DeleteSceneFromStack();
- return 0;
-
// if (!AddScene(CreatePuzzleScene(puzzle))) {
// printf("Failed to create a puzzle menu\n");
// return 1;
diff --git a/src/tests/arena_tests.c b/src/tests/arena_tests.c
new file mode 100644
index 0000000..b1c8aa8
--- /dev/null
+++ b/src/tests/arena_tests.c
@@ -0,0 +1,39 @@
+#include "test.h"
+#include "../utils/arena.h"
+#include <stdlib.h>
+#include <string.h>
+
+char *ArenaAllocation() {
+ Arena arena = {0};
+ ArenaInit(&arena, 1024);
+
+ // Init
+ size_t elements = 10;
+ int *arr = ArenaAlloc(&arena, sizeof(int) * elements);
+ if (arr == NULL) return "The int array allocation failed";
+ for (int i = 0; i < elements; ++i) {
+ arr[i] = i;
+ }
+ char *duped = ArenaStrdup(&arena, "Test string");
+ if (arr == NULL) return "The string array allocation failed";
+
+ // Access
+ for (int i = 0; i < elements; ++i) {
+ if (arr[i] != i) return "Arena memory corruption in the int array";
+ }
+ if (strcmp(duped, "Test string") != 0) {
+ return "Arena memory corruption in the string duping";
+ }
+
+ free(arena.mem);
+ return NULL;
+}
+
+char *ArenaOutOfMemory() {
+ Arena arena = {0};
+ ArenaInit(&arena, sizeof(int) * 2);
+ int *arr = ArenaAlloc(&arena, sizeof(int) * 3);
+ free(arena.mem);
+ if (arr != NULL) return "The int array allocation did not fail";
+ return NULL;
+}
diff --git a/src/tests/runner.c b/src/tests/runner.c
new file mode 100644
index 0000000..68c17bf
--- /dev/null
+++ b/src/tests/runner.c
@@ -0,0 +1,37 @@
+#include "test.h"
+#include <stdio.h>
+
+const UnitTest TESTS[] = {
+ (UnitTest) { .Name = "Arena out of mem", .Function = ArenaOutOfMemory },
+ (UnitTest) { .Name = "Arena allocation", .Function = ArenaAllocation },
+};
+
+void SetGreenColor() {
+ printf("\x1b[32m");
+}
+
+void SetRedColor() {
+ printf("\x1b[31m");
+}
+
+void ResetColor() {
+ printf("\x1b[39m");
+}
+
+int main(void) {
+ size_t length = sizeof(TESTS) / sizeof(TESTS[0]);
+ SetGreenColor();
+ for (size_t i = 0; i < length; ++i) {
+ const UnitTest *test = &TESTS[i];
+ char *outp = test->Function();
+ if (outp == NULL) {
+ printf("Test '%s' passed\n", test->Name);
+ } else {
+ SetRedColor();
+ printf("test '%s' failed: %s\n", test->Name, outp);
+ return 1;
+ }
+ }
+ ResetColor();
+ return 0;
+}
diff --git a/src/tests/test.h b/src/tests/test.h
new file mode 100644
index 0000000..d2c4aeb
--- /dev/null
+++ b/src/tests/test.h
@@ -0,0 +1,16 @@
+#ifndef TESTS_H
+#define TESTS_H
+
+typedef struct {
+ char *Name;
+ // The test function. If it returns an error message
+ // the test is concidered as failed
+ char *(*Function)();
+} UnitTest;
+
+// ========== TESTS ==========
+
+char *ArenaAllocation();
+char *ArenaOutOfMemory();
+
+#endif // TESTS_H