From 546a35f1d2b01e4296ea12b3a91aa5d4f907b13f Mon Sep 17 00:00:00 2001 From: yukkop Date: Sat, 22 Mar 2025 14:56:03 +0000 Subject: [PATCH] test(hmpl): render interpolation tags --- flake.nix | 4 +- package/c/{chectic => hectic}/default.nix | 12 +- .../c/{chectic/chectic.c => hectic/hectic.c} | 2 +- .../c/{chectic/chectic.h => hectic/hectic.h} | 4 +- .../c/{chectic => hectic}/test/00-logger.c | 2 +- package/c/{chectic => hectic}/test/01-arena.c | 2 +- package/c/{chectic => hectic}/test/02-json.c | 2 +- package/c/hmpl/default.nix | 21 +++- package/c/hmpl/hmpl.c | 12 +- package/c/hmpl/hmpl.h | 4 +- package/c/hmpl/main.c | 4 +- package/c/hmpl/test/test.c | 107 ++++++++++++++++++ 12 files changed, 146 insertions(+), 30 deletions(-) rename package/c/{chectic => hectic}/default.nix (71%) rename package/c/{chectic/chectic.c => hectic/hectic.c} (99%) rename package/c/{chectic/chectic.h => hectic/hectic.h} (99%) rename package/c/{chectic => hectic}/test/00-logger.c (99%) rename package/c/{chectic => hectic}/test/01-arena.c (99%) rename package/c/{chectic => hectic}/test/02-json.c (99%) create mode 100644 package/c/hmpl/test/test.c diff --git a/flake.nix b/flake.nix index e428952..ff13d0d 100644 --- a/flake.nix +++ b/flake.nix @@ -85,9 +85,9 @@ pg-from = pkgs.callPackage ./package/postgres/pg-from/default.nix rust.commonArgs; pg-schema = pkgs.callPackage ./package/postgres/pg-schema/default.nix rust.commonArgs; pg-migration = pkgs.callPackage ./package/postgres/pg-migration/default.nix rust.commonArgs; - chectic = pkgs.callPackage ./package/c/chectic/default.nix {}; + hectic = pkgs.callPackage ./package/c/hectic/default.nix {}; hmpl = pkgs.callPackage ./package/c/hmpl/default.nix { - chectic = self.packages.${system}.chectic; + hectic = self.packages.${system}.hectic; }; }; diff --git a/package/c/chectic/default.nix b/package/c/hectic/default.nix similarity index 71% rename from package/c/chectic/default.nix rename to package/c/hectic/default.nix index e871ab8..5841e7a 100644 --- a/package/c/chectic/default.nix +++ b/package/c/hectic/default.nix @@ -1,7 +1,7 @@ { stdenv, gcc, lib }: stdenv.mkDerivation { - pname = "chectic"; + pname = "hectic"; version = "1.0"; src = ./.; doCheck = true; @@ -11,23 +11,23 @@ stdenv.mkDerivation { ${gcc}/bin/cc -Wall -Wextra -g \ -std=c99 \ -pedantic -fsanitize=address \ - -c chectic.c -o target/chectic.o - ${gcc}/bin/ar rcs target/libchectic.a target/chectic.o + -c hectic.c -o target/hectic.o + ${gcc}/bin/ar rcs target/libhectic.a target/hectic.o ''; checkPhase = '' mkdir -p target/test for test_file in test/*.c; do exe="target/test/$(basename ''${test_file%.c})" - ${gcc}/bin/cc -Wall -Wextra -g -pedantic -fsanitize=address -I. "$test_file" -Ltarget -lchectic -o "$exe" + ${gcc}/bin/cc -Wall -Wextra -g -pedantic -fsanitize=address -I. "$test_file" -Ltarget -lhectic -o "$exe" "$exe" done ''; installPhase = '' mkdir -p $out/lib $out/include - cp target/libchectic.a $out/lib/ - cp chectic.h $out/include/ + cp target/libhectic.a $out/lib/ + cp hectic.h $out/include/ ''; meta = { diff --git a/package/c/chectic/chectic.c b/package/c/hectic/hectic.c similarity index 99% rename from package/c/chectic/chectic.c rename to package/c/hectic/hectic.c index 3e2da21..cea7821 100644 --- a/package/c/chectic/chectic.c +++ b/package/c/hectic/hectic.c @@ -1,4 +1,4 @@ -#include "chectic.h" +#include "hectic.h" void set_output_color_mode(ColorMode mode) { color_mode = mode; diff --git a/package/c/chectic/chectic.h b/package/c/hectic/hectic.h similarity index 99% rename from package/c/chectic/chectic.h rename to package/c/hectic/hectic.h index 50ec474..d8eca97 100644 --- a/package/c/chectic/chectic.h +++ b/package/c/hectic/hectic.h @@ -1,5 +1,5 @@ -#ifndef EPRINTF_CHECTIC -#define EPRINTF_CHECTIC +#ifndef EPRINTF_HECTIC +#define EPRINTF_HECTIC #include #include diff --git a/package/c/chectic/test/00-logger.c b/package/c/hectic/test/00-logger.c similarity index 99% rename from package/c/chectic/test/00-logger.c rename to package/c/hectic/test/00-logger.c index 56e6dcd..cff16ba 100644 --- a/package/c/chectic/test/00-logger.c +++ b/package/c/hectic/test/00-logger.c @@ -2,7 +2,7 @@ #include #include #include -#include "chectic.h" +#include "hectic.h" #define TEST_RAISE_GENERIC(LOG_MACRO, LEVEL, LEVEL_STR) do { \ FILE *orig_stderr = stderr; \ diff --git a/package/c/chectic/test/01-arena.c b/package/c/hectic/test/01-arena.c similarity index 99% rename from package/c/chectic/test/01-arena.c rename to package/c/hectic/test/01-arena.c index a4a36a9..b24ff2c 100644 --- a/package/c/chectic/test/01-arena.c +++ b/package/c/hectic/test/01-arena.c @@ -2,7 +2,7 @@ #include #include #include -#include "chectic.h" +#include "hectic.h" void test_arena_init() { Arena arena = arena_init(128); diff --git a/package/c/chectic/test/02-json.c b/package/c/hectic/test/02-json.c similarity index 99% rename from package/c/chectic/test/02-json.c rename to package/c/hectic/test/02-json.c index 3094c29..d15abf1 100644 --- a/package/c/chectic/test/02-json.c +++ b/package/c/hectic/test/02-json.c @@ -3,7 +3,7 @@ #include #include #include -#include "chectic.h" +#include "hectic.h" #define ARENA_SIZE 1024 * 1024 diff --git a/package/c/hmpl/default.nix b/package/c/hmpl/default.nix index e084aeb..7ae1dce 100644 --- a/package/c/hmpl/default.nix +++ b/package/c/hmpl/default.nix @@ -1,4 +1,4 @@ -{ stdenv, gcc, lib, chectic }: +{ stdenv, gcc, lib, hectic }: stdenv.mkDerivation { pname = "hmpl"; @@ -6,7 +6,7 @@ stdenv.mkDerivation { src = ./.; doCheck = true; - buildInputs = [ chectic ]; + buildInputs = [ hectic ]; buildPhase = '' mkdir -p target @@ -15,7 +15,7 @@ stdenv.mkDerivation { ${gcc}/bin/cc -Wall -Wextra -g \ -std=c99 \ -pedantic -fsanitize=address -c hmpl.c \ - -lchectic \ + -lhectic \ -o target/hmpl.o ${gcc}/bin/ar rcs target/libhmpl.a target/hmpl.o @@ -23,10 +23,19 @@ stdenv.mkDerivation { ${gcc}/bin/cc -Wall -Wextra -g \ -pedantic -fsanitize=address main.c \ -Ltarget -lhmpl \ - -lchectic -o target/hmpl + -lhectic -o target/hmpl ''; - checkPhase = '' ''; + checkPhase = '' + mkdir -p target/test + for test_file in test/*.c; do + exe="target/test/$(basename ''${test_file%.c})" + ${gcc}/bin/cc -Wall -Wextra -g -pedantic \ + -fsanitize=address -I. "$test_file" \ + -Ltarget -lhmpl -lhectic -o "$exe" + "$exe" + done + ''; installPhase = '' mkdir -p $out/bin $out/lib $out/include @@ -36,7 +45,7 @@ stdenv.mkDerivation { ''; meta = { - description = "chectic"; + description = "hectic"; license = lib.licenses.mit; }; } diff --git a/package/c/hmpl/hmpl.c b/package/c/hmpl/hmpl.c index fcb4369..6f2ff9c 100644 --- a/package/c/hmpl/hmpl.c +++ b/package/c/hmpl/hmpl.c @@ -27,8 +27,8 @@ char *eval(Arena *arena, const Json * const context, const char * const key) { } /* Modified: text is passed by reference so we can update it and free old allocations */ -void render_template_placeholders(Arena *arena, char **text_ptr, Json *context, const char * const prefix) { - raise_debug("render_template_placeholders"); +void hmpl_render_interpolation_tags(Arena *arena, char **text_ptr, Json *context, const char * const prefix) { + raise_debug("hmpl_render_interpolation_tags"); char start_pattern[256]; snprintf(start_pattern, sizeof(start_pattern), "{{%s", prefix); int start_pattern_length = strlen(start_pattern); @@ -67,19 +67,19 @@ void render_template_placeholders(Arena *arena, char **text_ptr, Json *context, } } -void render_template_with_arena(Arena *arena, char **text, const Json * const context) { +void hmpl_render_with_arena(Arena *arena, char **text, const Json * const context) { if (context->type != JSON_OBJECT) { raise_exception("Malformed context: context is not json"); exit(1); } - render_template_placeholders(arena, text, context, ""); + hmpl_render_interpolation_tags(arena, text, context, ""); } -void render_template(char **text, const Json * const context) { +void hmpl_render(char **text, const Json * const context) { Arena arena = arena_init(1024 * 1024); - render_template_with_arena(&arena, text, context); + hmpl_render_with_arena(&arena, text, context); arena_free(&arena); } diff --git a/package/c/hmpl/hmpl.h b/package/c/hmpl/hmpl.h index db83090..27233d0 100644 --- a/package/c/hmpl/hmpl.h +++ b/package/c/hmpl/hmpl.h @@ -5,14 +5,14 @@ #include #include #include -#include "chectic.h" +#include "hectic.h" void init_cjson_with_arenas(Arena *arena); char *eval(Arena *arena, const Json * const context, const char * const key); /* Modified: text is passed by reference so we can update it and free old allocations */ -void render_template_placeholders(Arena *arena, char **text_ptr, Json *context, const char * const prefix); +void hmpl_render_interpolation_tags(Arena *arena, char **text_ptr, Json *context, const char * const prefix); void render_template_with_arena(Arena *arena, char **text, const Json * const ccontext); diff --git a/package/c/hmpl/main.c b/package/c/hmpl/main.c index a3a7867..252792a 100644 --- a/package/c/hmpl/main.c +++ b/package/c/hmpl/main.c @@ -2,7 +2,7 @@ #include #include #include -#include "chectic.h" +#include "hectic.h" #include "hmpl.h" int main(int argc, char *argv[]) { @@ -38,7 +38,7 @@ int main(int argc, char *argv[]) { text = arena_strdup(&arena, ""); } - render_template_with_arena(&arena, &text, context); + hmpl_render_with_arena(&arena, &text, context); printf("%s", text); arena_free(&arena); diff --git a/package/c/hmpl/test/test.c b/package/c/hmpl/test/test.c new file mode 100644 index 0000000..367ab9e --- /dev/null +++ b/package/c/hmpl/test/test.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include "hmpl.h" +#include "hectic.h" + +void test_eval_single_level_key(Arena *arena) { + char *context_text = arena_strdup(arena, "{\"name\": \"world\"}"); + Json *context = json_parse(arena, &context_text); + if (!context) { raise_exception("Malformed json"); exit(1); } + + char *result = eval(arena, context, "name"); + raise_debug("eval result: %s", result); + assert(result && strcmp(result, "world") == 0); +} + +void test_eval_nested_key(Arena *arena) { + char *context_text = arena_strdup(arena, "{\"person\": {\"name\": \"Alice\"}}"); + Json *context = json_parse(arena, &context_text); + if (!context) { raise_exception("Malformed json"); exit(1); } + + char *result = eval(arena, context, "person.name"); + raise_notice("context: %s, eval result: %s", json_to_string(arena, context), result); + assert(result && strcmp(result, "Alice") == 0); +} + +void test_render_interpolation_tags(Arena *arena) { + char *context_text = arena_strdup(arena, + "{\n" + " \"persona\": {\n" + " \"name\": \"John\",\n" + " \"surname\": \"Doe\",\n" + " \"address\": {\n" + " \"home\": {\n" + " \"street\": \"123 Main St\",\n" + " \"city\": \"Springfield\",\n" + " \"zip\": \"12345\"\n" + " },\n" + " \"work\": {\n" + " \"street\": \"456 Business Rd\",\n" + " \"city\": \"Metropolis\",\n" + " \"zip\": \"67890\"\n" + " }\n" + " },\n" + " \"contact\": {\n" + " \"email\": \"john@example.com\",\n" + " \"phone\": {\n" + " \"home\": \"555-1234\",\n" + " \"mobile\": \"555-5678\"\n" + " }\n" + " }\n" + " }\n" + "}"); + Json *context = json_parse(arena, &context_text); + if (!context) { raise_exception("Malformed json"); exit(1); } + + char *text = arena_strdup(arena, + "Hello {{persona.name}} {{persona.surname}},\n" + "\n" + "Your home address:\n" + "{{persona.address.home.street}},\n" + "{{persona.address.home.city}},\n" + "{{persona.address.home.zip}}\n" + "\n" + "Your work address:\n" + "{{persona.address.work.street}},\n" + "{{persona.address.work.city}},\n" + "{{persona.address.work.zip}}\n" + "\n" + "Contact information:\n" + "Email: {{persona.contact.email}}\n" + "Home Phone: {{persona.contact.phone.home}}\n" + "Mobile Phone: {{persona.contact.phone.mobile}}\n"); + + hmpl_render_with_arena(arena, &text, context); + assert(strcmp(text, + "Hello John Doe,\n" + "\n" + "Your home address:\n" + "123 Main St,\n" + "Springfield,\n" + "12345\n" + "\n" + "Your work address:\n" + "456 Business Rd,\n" + "Metropolis,\n" + "67890\n" + "\n" + "Contact information:\n" + "Email: john@example.com\n" + "Home Phone: 555-1234\n" + "Mobile Phone: 555-5678\n") == 0); +} + + +int main(void) { + Arena arena = arena_init(1024 * 1024); + + test_eval_single_level_key(&arena); + test_eval_nested_key(&arena); + test_render_interpolation_tags(&arena); + + printf("All tests passed.\n"); + + arena_free(&arena); + return 0; +}