Mercurial
view mrjunejune/test/template_renderer_test.c @ 267:a78f5986011f
discover bundled production runtimes
Locate Bazel-packaged Copilot and Python binaries by stable suffix instead of hardcoding an external repository prefix.
Co-authored-by: Copilot <[email protected]>
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Fri, 07 Aug 2026 12:58:55 -0700 |
| parents | 04fee26ecce0 |
| children |
line wrap: on
line source
/* * template_renderer_test.c — unit tests for the Mjj template renderer. * * Tests cover: * - Passthrough (no includes) * - Include expansion with real parts files * - Missing include (silently skipped, output is still valid) * - Missing file (Mjj_Template_Render_File returns FALSE) * - Capacity-overflow protection (returns FALSE) * - Page bodies contain no literal {{ / }} / <{{ markers * - Rendered pages contain expected design-system asset references */ #include "mrjunejune/template_renderer.h" #include "dowa/dowa.h" #include <assert.h> #include <stdio.h> #include <string.h> #include <stdlib.h> /* ------------------------------------------------------------------ */ /* Utilities */ /* ------------------------------------------------------------------ */ #define ASSERT(cond) \ do { \ if (!(cond)) { \ fprintf(stderr, "FAIL [%s:%d]: %s\n", __FILE__, __LINE__, #cond); \ abort(); \ } \ } while (0) #define TEST(name) \ do { fprintf(stdout, " %-60s", name); fflush(stdout); } while (0) #define PASS() \ do { fprintf(stdout, "PASS\n"); } while (0) /* Capacity used for page-level renders */ #define PAGE_CAP (256 * 1024) /* ------------------------------------------------------------------ */ /* Tests */ /* ------------------------------------------------------------------ */ static void test_passthrough(void) { printf("\n[passthrough — no includes]\n"); Dowa_Arena *arena = Dowa_Arena_Create(4096); ASSERT(arena); TEST("plain text passes through unchanged"); { char out[64]; boolean ok = Mjj_Template_Render(out, sizeof(out), "Hello, world!", arena); ASSERT(ok); ASSERT(strcmp(out, "Hello, world!") == 0); } PASS(); TEST("empty template produces empty string"); { char out[8]; out[0] = 'x'; boolean ok = Mjj_Template_Render(out, sizeof(out), "", arena); ASSERT(ok); ASSERT(out[0] == '\0'); } PASS(); TEST("NULL template returns FALSE"); { char out[8]; boolean ok = Mjj_Template_Render(out, sizeof(out), NULL, arena); ASSERT(!ok); } PASS(); Dowa_Arena_Free(arena); } static void test_capacity_overflow(void) { printf("\n[capacity-overflow protection]\n"); Dowa_Arena *arena = Dowa_Arena_Create(4096); ASSERT(arena); TEST("render into 1-byte buffer returns FALSE"); { char out[1]; boolean ok = Mjj_Template_Render(out, 1, "Hello", arena); ASSERT(!ok); /* NUL-termination must still hold */ ASSERT(out[0] == '\0'); } PASS(); TEST("render into exactly-fitting buffer (size = len+1) returns TRUE"); { const char *src = "Hi"; char out[3]; /* 2 chars + NUL */ boolean ok = Mjj_Template_Render(out, sizeof(out), src, arena); ASSERT(ok); ASSERT(strcmp(out, "Hi") == 0); } PASS(); TEST("render into too-small buffer returns FALSE"); { const char *src = "Hello world"; char out[5]; boolean ok = Mjj_Template_Render(out, sizeof(out), src, arena); ASSERT(!ok); /* Must still be NUL-terminated */ ASSERT(out[sizeof(out) - 1] == '\0'); } PASS(); TEST("Render_File into tiny buffer returns FALSE"); { char out[4]; boolean ok = Mjj_Template_Render_File(out, sizeof(out), "/login/index.html", arena); ASSERT(!ok); ASSERT(out[sizeof(out) - 1] == '\0' || out[0] == '\0'); } PASS(); Dowa_Arena_Free(arena); } static void test_missing_file(void) { printf("\n[missing file / missing include]\n"); Dowa_Arena *arena = Dowa_Arena_Create(4096); ASSERT(arena); TEST("Render_File on non-existent path returns FALSE"); { char out[256]; boolean ok = Mjj_Template_Render_File(out, sizeof(out), "/does/not/exist.html", arena); ASSERT(!ok); } PASS(); TEST("missing include in template is skipped silently"); { char out[256]; boolean ok = Mjj_Template_Render( out, sizeof(out), "before{{/parts/this_does_not_exist.html}}after", arena); ASSERT(ok); ASSERT(strcmp(out, "beforeafter") == 0); /* No literal {{ or }} should remain */ ASSERT(strstr(out, "{{") == NULL); ASSERT(strstr(out, "}}") == NULL); } PASS(); Dowa_Arena_Free(arena); } static void test_include_expansion(void) { printf("\n[include expansion — real parts files]\n"); Dowa_Arena *arena = Dowa_Arena_Create(8192); ASSERT(arena); TEST("{{/parts/base_head.html}} expands to non-empty content"); { char *out = (char *)malloc(PAGE_CAP); ASSERT(out); boolean ok = Mjj_Template_Render( out, PAGE_CAP, "A{{/parts/base_head.html}}B", arena); ASSERT(ok); /* Expansion must have happened: output is longer than "AB" */ ASSERT(strlen(out) > 2); /* No literal markers must remain */ ASSERT(strstr(out, "{{") == NULL); ASSERT(strstr(out, "}}") == NULL); /* base_head includes charset and stylesheet references */ ASSERT(strstr(out, "charset") != NULL); ASSERT(strstr(out, "design-system") != NULL); free(out); } PASS(); TEST("{{/parts/header.html}} expands and contains MrJuneJune link"); { char *out = (char *)malloc(PAGE_CAP); ASSERT(out); boolean ok = Mjj_Template_Render( out, PAGE_CAP, "{{/parts/header.html}}", arena); ASSERT(ok); ASSERT(strlen(out) > 0); ASSERT(strstr(out, "{{") == NULL); ASSERT(strstr(out, "MrJuneJune") != NULL); free(out); } PASS(); Dowa_Arena_Free(arena); } /* Check that a fully rendered page contains no literal template markers. */ static void assert_page_clean(const char *path, char *buf) { Dowa_Arena *arena = Dowa_Arena_Create(8192); ASSERT(arena); boolean ok = Mjj_Template_Render_File(buf, PAGE_CAP, path, arena); if (!ok) { fprintf(stderr, " FAIL: Mjj_Template_Render_File returned FALSE for '%s'\n", path); abort(); } if (strstr(buf, "{{")) { fprintf(stderr, " FAIL: rendered '%s' contains '{{'\n", path); abort(); } if (strstr(buf, "}}")) { fprintf(stderr, " FAIL: rendered '%s' contains '}}'\n", path); abort(); } if (strstr(buf, "<{{")) { fprintf(stderr, " FAIL: rendered '%s' contains '<{{'\n", path); abort(); } Dowa_Arena_Free(arena); } static void test_page_bodies(void) { printf("\n[page bodies — no literal markers, design-system assets present]\n"); char *buf = (char *)malloc(PAGE_CAP); ASSERT(buf); const char *pages[] = { "/login/index.html", "/account/password.html", "/admin/users/index.html", "/index.html", "/resume/index.html", "/tools/index.html", "/blog/index.html", "/talk/index.html", "/notes/index.html", NULL }; for (int i = 0; pages[i]; i++) { char label[128]; snprintf(label, sizeof(label), "no {{ in rendered '%s'", pages[i]); TEST(label); assert_page_clean(pages[i], buf); PASS(); } /* Verify design-system stylesheet and component script are referenced in the login page (canonical example that contains base_head). */ TEST("login page references design-system/styles/tokens.css"); { Dowa_Arena *arena = Dowa_Arena_Create(4096); ASSERT(arena); boolean ok = Mjj_Template_Render_File(buf, PAGE_CAP, "/login/index.html", arena); ASSERT(ok); ASSERT(strstr(buf, "design-system") != NULL); ASSERT(strstr(buf, "tokens.css") != NULL); Dowa_Arena_Free(arena); } PASS(); TEST("admin page references design-system and header"); { Dowa_Arena *arena = Dowa_Arena_Create(4096); ASSERT(arena); boolean ok = Mjj_Template_Render_File(buf, PAGE_CAP, "/admin/users/index.html", arena); ASSERT(ok); ASSERT(strstr(buf, "design-system") != NULL); ASSERT(strstr(buf, "MrJuneJune") != NULL); Dowa_Arena_Free(arena); } PASS(); TEST("password page references design-system and header"); { Dowa_Arena *arena = Dowa_Arena_Create(4096); ASSERT(arena); boolean ok = Mjj_Template_Render_File(buf, PAGE_CAP, "/account/password.html", arena); ASSERT(ok); ASSERT(strstr(buf, "design-system") != NULL); ASSERT(strstr(buf, "MrJuneJune") != NULL); Dowa_Arena_Free(arena); } PASS(); free(buf); } /* ------------------------------------------------------------------ */ /* main */ /* ------------------------------------------------------------------ */ int main(void) { printf("=== template_renderer_test ===\n"); /* The renderer defaults to "mrjunejune/src"; in Bazel test, CWD is the runfiles root where mrjunejune/src/... is directly accessible. */ test_passthrough(); test_capacity_overflow(); test_missing_file(); test_include_expansion(); test_page_bodies(); printf("\nAll template_renderer tests passed.\n"); return 0; }