diff options
| -rw-r--r-- | build.zig | 131 | ||||
| -rw-r--r-- | src/main.c | 3 | ||||
| -rw-r--r-- | src/tests/arena_tests.c | 39 | ||||
| -rw-r--r-- | src/tests/runner.c | 37 | ||||
| -rw-r--r-- | src/tests/test.h | 16 |
5 files changed, 177 insertions, 49 deletions
@@ -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 @@ -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 |
