test(hmpl): render interpolation tags

This commit is contained in:
2025-03-22 14:56:03 +00:00
parent aeea41b0e1
commit 546a35f1d2
12 changed files with 146 additions and 30 deletions

View File

@@ -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;
};
};

View File

@@ -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 = {

View File

@@ -1,4 +1,4 @@
#include "chectic.h"
#include "hectic.h"
void set_output_color_mode(ColorMode mode) {
color_mode = mode;

View File

@@ -1,5 +1,5 @@
#ifndef EPRINTF_CHECTIC
#define EPRINTF_CHECTIC
#ifndef EPRINTF_HECTIC
#define EPRINTF_HECTIC
#include <stdio.h>
#include <unistd.h>

View File

@@ -2,7 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "chectic.h"
#include "hectic.h"
#define TEST_RAISE_GENERIC(LOG_MACRO, LEVEL, LEVEL_STR) do { \
FILE *orig_stderr = stderr; \

View File

@@ -2,7 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "chectic.h"
#include "hectic.h"
void test_arena_init() {
Arena arena = arena_init(128);

View File

@@ -3,7 +3,7 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "chectic.h"
#include "hectic.h"
#define ARENA_SIZE 1024 * 1024

View File

@@ -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;
};
}

View File

@@ -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);
}

View File

@@ -5,14 +5,14 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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);

View File

@@ -2,7 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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);

107
package/c/hmpl/test/test.c Normal file
View File

@@ -0,0 +1,107 @@
#include <assert.h>
#include <stdio.h>
#include <string.h>
#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;
}