From 9468d2a769c726c9612f383f785501933f330232 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 18 Mar 2024 13:14:51 +0100 Subject: -update mustach --- contrib/gana | 2 +- contrib/uncrustify_precommit | 2 +- contrib/wallet-core | 2 +- src/templating/AUTHORS | 4 + src/templating/CHANGELOG.md | 150 +++++++ src/templating/README.md | 16 +- src/templating/dotest.sh | 20 + src/templating/mustach-cjson.c | 35 +- src/templating/mustach-cjson.h | 2 +- src/templating/mustach-jansson.c | 36 +- src/templating/mustach-json-c.c | 37 +- src/templating/mustach-original-Makefile | 20 +- src/templating/mustach-tool.c | 2 + src/templating/mustach-wrap.c | 48 ++- src/templating/mustach.1.gz | Bin 0 -> 742 bytes src/templating/mustach.1.scd | 60 +++ src/templating/mustach.c | 7 +- src/templating/pkgcfgs | 35 ++ src/templating/test-specs/test-specs-cjson.ref | 425 ++++++++++++++++++ src/templating/test-specs/test-specs-jansson.ref | 429 +++++++++++++++++++ src/templating/test-specs/test-specs-json-c.ref | 425 ++++++++++++++++++ src/templating/test-specs/test-specs.c | 520 +++++++++++++++++++++++ src/templating/test1/Makefile | 7 +- src/templating/test1/must | 6 + src/templating/test1/resu.ref | 41 ++ src/templating/test1/vg.ref | 14 + src/templating/test2/Makefile | 7 +- src/templating/test2/resu.ref | 7 + src/templating/test2/vg.ref | 14 + src/templating/test3/Makefile | 7 +- src/templating/test3/resu.ref | 13 + src/templating/test3/vg.ref | 14 + src/templating/test4/Makefile | 7 +- src/templating/test4/resu.ref | 50 +++ src/templating/test4/vg.ref | 14 + src/templating/test5/Makefile | 7 +- src/templating/test5/resu.ref | 38 ++ src/templating/test5/vg.ref | 14 + src/templating/test6/Makefile | 7 +- src/templating/test6/resu.ref | 93 ++++ src/templating/test6/test-custom-write.c | 2 + src/templating/test6/vg.ref | 14 + src/templating/test7/base.mustache | 2 + src/templating/test7/json | 8 + src/templating/test7/node.mustache | 4 + src/templating/test7/resu.ref | 7 + src/templating/test7/vg.ref | 14 + src/templating/test8/.gitignore | 2 + src/templating/test8/json | 8 + src/templating/test8/must | 6 + src/templating/test8/resu.ref | 6 + src/templating/test8/vg.ref | 14 + 52 files changed, 2627 insertions(+), 97 deletions(-) create mode 100644 src/templating/CHANGELOG.md create mode 100755 src/templating/dotest.sh create mode 100644 src/templating/mustach.1.gz create mode 100644 src/templating/mustach.1.scd create mode 100644 src/templating/pkgcfgs create mode 100644 src/templating/test-specs/test-specs-cjson.ref create mode 100644 src/templating/test-specs/test-specs-jansson.ref create mode 100644 src/templating/test-specs/test-specs-json-c.ref create mode 100644 src/templating/test-specs/test-specs.c create mode 100644 src/templating/test1/resu.ref create mode 100644 src/templating/test1/vg.ref create mode 100644 src/templating/test2/resu.ref create mode 100644 src/templating/test2/vg.ref create mode 100644 src/templating/test3/resu.ref create mode 100644 src/templating/test3/vg.ref create mode 100644 src/templating/test4/resu.ref create mode 100644 src/templating/test4/vg.ref create mode 100644 src/templating/test5/resu.ref create mode 100644 src/templating/test5/vg.ref create mode 100644 src/templating/test6/resu.ref create mode 100644 src/templating/test6/vg.ref create mode 100644 src/templating/test7/base.mustache create mode 100644 src/templating/test7/json create mode 100644 src/templating/test7/node.mustache create mode 100644 src/templating/test7/resu.ref create mode 100644 src/templating/test7/vg.ref create mode 100644 src/templating/test8/.gitignore create mode 100644 src/templating/test8/json create mode 100644 src/templating/test8/must create mode 100644 src/templating/test8/resu.ref create mode 100644 src/templating/test8/vg.ref diff --git a/contrib/gana b/contrib/gana index 2b581279a..53d099289 160000 --- a/contrib/gana +++ b/contrib/gana @@ -1 +1 @@ -Subproject commit 2b581279ae67a1068b07a8c010ac1ab7b85e18df +Subproject commit 53d0992890e1ebb8f8c6bd747533abe157baec66 diff --git a/contrib/uncrustify_precommit b/contrib/uncrustify_precommit index faffcec9c..d0a64ef72 100755 --- a/contrib/uncrustify_precommit +++ b/contrib/uncrustify_precommit @@ -4,7 +4,7 @@ exec 1>&2 RET=0 -changed=$(git diff --cached --name-only | grep -v mustach | grep -v templating/test./ | grep -v valgrind.h) +changed=$(git diff --cached --name-only | grep -v mustach | grep -v templating/test | grep -v valgrind.h) crustified="" for f in $changed; diff --git a/contrib/wallet-core b/contrib/wallet-core index c0f306997..35212ac57 160000 --- a/contrib/wallet-core +++ b/contrib/wallet-core @@ -1 +1 @@ -Subproject commit c0f3069970e24d1fa9e308347350d6e5221aed88 +Subproject commit 35212ac57bfe5625fcf574b0fd2d9baf395dc4c0 diff --git a/src/templating/AUTHORS b/src/templating/AUTHORS index b440c24ed..b2042848e 100644 --- a/src/templating/AUTHORS +++ b/src/templating/AUTHORS @@ -5,6 +5,7 @@ Contributors: Abhishek Mishra Atlas Ben Beasley + Dominik Kummer Gabriel Zachmann Harold L Marzan Kurt Jung @@ -15,6 +16,7 @@ Contributors: Ryan Fox Sami Kerola Sijmen J. Mulder + Steve-Chavez Tomasz Sieprawski Packagers: @@ -27,6 +29,8 @@ Thanks to issue submitters: @fabbe Johann Oskarsson Mark Bucciarelli + Nigel Hathaway Paul Wisehart + Tarik @tr001 Thierry Fournier SASU OKFT diff --git a/src/templating/CHANGELOG.md b/src/templating/CHANGELOG.md new file mode 100644 index 000000000..6024189ef --- /dev/null +++ b/src/templating/CHANGELOG.md @@ -0,0 +1,150 @@ +next +---- + +Fix: + - selection of subitem by index (#47) + - get latest iterated key when getting key name (#52) + - allow tests without valgrind + +1.2.6 (2024-01-08) +------------------ + +Fix: + - improve naming (#42) + - magical spaces in recursive partials (#43) + - installation when tool isn't built + - correct detection of falsey values (#45) + +Minor: + - update to newer reference tests + +1.2.5 (2023-02-18) +------------------ +Fix: + - Don't override CFLAGS in Makefile + - Use of $(INSTALL) in Makefile for setting options + +Minor: + - Orthograf of 'instantiate' + +1.2.4 (2023-01-02) +------------------ +Fix: + - Latent SIGSEGV using cJSON + +1.2.3 (2022-12-21) +------------------ + +New: + - Flag Mustach_With_ErrorUndefined (and option --strict for the tool) + for returning a requested tag is not defined + - Test of specifications in separate directory + +Fix: + - Version printing is now okay + - Compiling libraries on Darwin (no soname but install_name) + - Compiling test6 with correct flags + - Update test from specifications + - Better use of valgrind reports + +1.2.2 (2021-10-28) +------------------ + +Fix: + - SONAME of libmustach-json-c.so + +1.2.1 (2021-10-19) +------------------ + +New: + - Add SONAME in libraries. + - Flag Mustach_With_PartialDataFirst to switch the + policy of resolving partials. + +Fix: + - Identification of types in cJSON + +1.2.0 (2021-08-24) +------------------ + +New: + - Add hook 'mustach_wrap_get_partial' for handling partials. + - Add test of mustache specifications https://github.com/mustache/spec. + +Changes: + - Mustach_With_SingleDot is always set. + - Mustach_With_IncPartial is always set. + - Mustach_With_AllExtensions is changed to use currently known extensions. + - Output of tests changed. + - Makefile improved. + - Partials are first searched as file then in current selection. + - Improved management of delimiters. + +Fixes: + - Improved output accordingly to https://github.com/mustache/spec: + - escaping of quote " + - interpolating null with empty string + - removal of empty lines with standalone tag + - don't enter section if null + - indentation of partials + - comment improved for get of mustach_wrap_itf. + +1.1.1 (2021-08-19) +------------------ +Fixes: + - Avoid conflicting with getopt. + - Remove unexpected build artifact. + - Handle correctly a size of 0. + +1.1.0 (2021-05-01) +------------------ +New: + - API refactored to take lengths to ease working with partial or + non-NULL-terminated strings. (ABI break) + +Fixes: + - Use correct int type for jansson (json_int_t instead of int64_t). + - JSON output of different backends is now the same. + +1.0 (2021-04-28, retracted) +--------------------------- +Legal: + - License changed to ISC. + +Fixes: + - Possible data leak in memfile_open() by clearing buffers. + - Fix build on Solaris-likes by including alloca.h. + - Fix Windows build by including malloc.h, using size_t instead of + ssize_t, and using the standard ternary operator syntax. + - Fix JSON in test3 by using double quote characters. + - Fix installation in alternative directories such as + /opt/pkg/lib on macOS by setting install_name. + - Normalise return values in compare() implementations. + +New: + - Support for cJSON and jansson libraries. + - Version info now embedded at build time and shown with mustach(1) + usage. + - Versioned so-names (e.g. libxlsx.so.1.0). + - BINDIR, LIBDIR and INCLUDEDIR variables in Makefile. + - New mustach-wrap.{c,h} to ease implementation new libraries, + extracted and refactored from the existing implementations. + - Makefile now supports 3 modes: single libmustach (default), split + libmustache-core etc, and both. + - Any or all backends (json-c, jansson, etc) can be enabled at compile + time. By default, all available libraries are used. + - mustach(1) can use any JSON backend instead of only json-c. + - MUSTACH_COMPATIBLE_0_99 can be defined for backwards source + compatibility. + - 'No extensions' can now be set Mustach_With_NoExtensions instead of + passing 0. + - pkgconfig (.pc) file for library. + - Manual page for mustach(1). + +Changed: + - Many renames. + - Maximum tag length increased from 1024 to 4096. + - Other headers include json-c.h instead of using forward declarations. + - mustach(1) reads from /dev/stdin instead of fd 0. + - Several structures are now taken as const. + - New/changed Makefile targets. diff --git a/src/templating/README.md b/src/templating/README.md index 7034ef99f..324c9a862 100644 --- a/src/templating/README.md +++ b/src/templating/README.md @@ -5,7 +5,7 @@ template specification. The main site for `mustach` is on [gitlab](https://gitlab.com/jobol/mustach). -The simplest way to use mustach is to copy the files **mustach.h** and **mustach.c** +The simpliest way to use mustach is to copy the files **mustach.h** and **mustach.c** directly into your project and use it. If you are using one of the JSON libraries listed below, you can get extended feature @@ -85,7 +85,7 @@ It then outputs the result of applying the templates files to the JSON file. ### Portability Some system does not provide *open_memstream*. In that case, tell your -preferred compiler to declare the preprocessor symbol **NO_OPEN_MEMSTREAM**. +prefered compiler to declare the preprocessor symbol **NO_OPEN_MEMSTREAM**. Example: CFLAGS=-DNO_OPEN_MEMSTREAM make @@ -154,6 +154,13 @@ The libraries that can be produced are: There is no dependencies of a library to an other. This is intended and doesn't hurt today because the code is small. +### Testing + +The makefile offers the way to execute basic tests. Just type `make test`. + +By default, if valgrind is available, tests are using it. It can be disabled +by typing `make test valgrind=no` or `NOVALGRIND=1 make test`. + ## Extensions The current implementation provides extensions to specifications of **mustache**. @@ -163,7 +170,7 @@ Here is the summary. Flag name | Description -------------------------------+------------------------------------------------ - Mustach_With_Colon | Explicit tag substitution with colon + Mustach_With_Colon | Explicit tag substition with colon Mustach_With_EmptyTag | Empty Tag Allowed -------------------------------+------------------------------------------------ Mustach_With_Equal | Value Testing Equality @@ -180,7 +187,7 @@ For the details, see below. ### Explicit Tag Substitution With Colon (Mustach_With_Colon) -In somecases the name of the key used for substitution begins with a +In somecases the name of the key used for substition begins with a character reserved for mustach: one of `#`, `^`, `/`, `&`, `{`, `>` and `=`. This extension introduces the special character `:` to explicitly @@ -311,3 +318,4 @@ The table below summarize the changes. fdmustach_json_c | mustach_json_c_fd mustach_json_c | mustach_json_c_mem mustach_json_c | mustach_json_c_write + diff --git a/src/templating/dotest.sh b/src/templating/dotest.sh new file mode 100755 index 000000000..99ff8b201 --- /dev/null +++ b/src/templating/dotest.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +mustach=${mustach:-../mustach} +echo starting test +if test "$NOVALGRIND" = 1 +then + $mustach "$@" > resu.last +else + valgrind $mustach "$@" > resu.last 2> vg.last + sed -i 's:^==[0-9]*== ::' vg.last + awk '/^ *total heap usage: .* allocs, .* frees,.*/{if($$4-$$6)exit(1)}' vg.last || echo "ERROR! Alloc/Free issue" +fi +if diff -w resu.ref resu.last +then + echo "result ok" +else + echo "ERROR! Result differs" +fi +echo + diff --git a/src/templating/mustach-cjson.c b/src/templating/mustach-cjson.c index 48b97e7df..ee65c8038 100644 --- a/src/templating/mustach-cjson.c +++ b/src/templating/mustach-cjson.c @@ -6,7 +6,9 @@ SPDX-License-Identifier: ISC */ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include #include @@ -90,11 +92,21 @@ static int sel(void *closure, const char *name) static int subsel(void *closure, const char *name) { struct expl *e = closure; - cJSON *o; - int r; + cJSON *o = NULL; + int r = 0; - o = cJSON_GetObjectItemCaseSensitive(e->selection, name); - r = o != NULL; + if (cJSON_IsObject(e->selection)) { + o = cJSON_GetObjectItemCaseSensitive(e->selection, name); + r = o != NULL; + } + else if (cJSON_IsArray(e->selection) && *name) { + char *end; + int idx = (int)strtol(name, &end, 10); + if (!*end && idx >= 0 && idx < cJSON_GetArraySize(e->selection)) { + o = cJSON_GetArrayItem(e->selection, idx); + r = 1; + } + } if (r) e->selection = o; return r; @@ -125,7 +137,10 @@ static int enter(void *closure, int objiter) e->stack[e->depth].obj = o->child; e->stack[e->depth].next = o->child->next; e->stack[e->depth].cont = o; - } else if ((cJSON_IsObject(o) && o->child == NULL) || (! cJSON_IsFalse(o) && ! cJSON_IsNull(o))) { + } else if ((cJSON_IsObject(o) && o->child != NULL) + || cJSON_IsTrue(o) + || (cJSON_IsString(o) && cJSON_GetStringValue(o)[0] != '\0') + || (cJSON_IsNumber(o) && cJSON_GetNumberValue(o) != 0)) { e->stack[e->depth].obj = o; e->stack[e->depth].cont = NULL; e->stack[e->depth].next = NULL; @@ -170,11 +185,15 @@ static int get(void *closure, struct mustach_sbuf *sbuf, int key) { struct expl *e = closure; const char *s; + int d; if (key) { - s = e->stack[e->depth].is_objiter - ? e->stack[e->depth].obj->string - : ""; + s = ""; + for (d = e->depth ; d >= 0 ; d--) + if (e->stack[d].is_objiter) { + s = e->stack[d].obj->string; + break; + } } else if (cJSON_IsString(e->selection)) s = e->selection->valuestring; diff --git a/src/templating/mustach-cjson.h b/src/templating/mustach-cjson.h index ae0d818cb..e049415f8 100644 --- a/src/templating/mustach-cjson.h +++ b/src/templating/mustach-cjson.h @@ -10,7 +10,7 @@ #define _mustach_cJSON_h_included_ /* - * mustach-json-c is intended to make integration of cJSON + * mustach-cjson is intended to make integration of cJSON * library by providing integrated functions. */ diff --git a/src/templating/mustach-jansson.c b/src/templating/mustach-jansson.c index 3ce0e0a84..d9b50b57e 100644 --- a/src/templating/mustach-jansson.c +++ b/src/templating/mustach-jansson.c @@ -6,7 +6,9 @@ SPDX-License-Identifier: ISC */ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include #include @@ -94,11 +96,21 @@ static int sel(void *closure, const char *name) static int subsel(void *closure, const char *name) { struct expl *e = closure; - json_t *o; - int r; + json_t *o = NULL; + int r = 0; - o = json_object_get(e->selection, name); - r = o != NULL; + if (json_is_object(e->selection)) { + o = json_object_get(e->selection, name); + r = o != NULL; + } + else if (json_is_array(e->selection)) { + char *end; + size_t idx = (size_t)strtol(name, &end, 10); + if (!*end && idx < json_array_size(e->selection)) { + o = json_array_get(e->selection, idx); + r = 1; + } + } if (r) e->selection = o; return r; @@ -130,7 +142,11 @@ static int enter(void *closure, int objiter) e->stack[e->depth].cont = o; e->stack[e->depth].obj = json_array_get(o, 0); e->stack[e->depth].index = 0; - } else if ((json_is_object(o) && json_object_size(0)) || (!json_is_false(o) && !json_is_null(o))) { + } else if ((json_is_object(o) && json_object_size(o)) + || json_is_true(o) + || (json_is_string(o) && json_string_length(o) > 0) + || (json_is_integer(o) && json_integer_value(o) != 0) + || (json_is_real(o) && json_real_value(o) != 0)) { e->stack[e->depth].count = 1; e->stack[e->depth].cont = NULL; e->stack[e->depth].obj = o; @@ -182,11 +198,15 @@ static int get(void *closure, struct mustach_sbuf *sbuf, int key) { struct expl *e = closure; const char *s; + int d; if (key) { - s = e->stack[e->depth].is_objiter - ? json_object_iter_key(e->stack[e->depth].iter) - : ""; + s = ""; + for (d = e->depth ; d >= 0 ; d--) + if (e->stack[d].is_objiter) { + s = json_object_iter_key(e->stack[d].iter); + break; + } } else if (json_is_string(e->selection)) s = json_string_value(e->selection); diff --git a/src/templating/mustach-json-c.c b/src/templating/mustach-json-c.c index a21a113fb..75251c07e 100644 --- a/src/templating/mustach-json-c.c +++ b/src/templating/mustach-json-c.c @@ -6,7 +6,9 @@ SPDX-License-Identifier: ISC */ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include #include @@ -87,10 +89,19 @@ static int sel(void *closure, const char *name) static int subsel(void *closure, const char *name) { struct expl *e = closure; - struct json_object *o; - int r; - - r = json_object_object_get_ex(e->selection, name, &o); + struct json_object *o = NULL; + int r = 0; + + if (json_object_is_type(e->selection, json_type_object)) + r = json_object_object_get_ex(e->selection, name, &o); + else if (json_object_is_type(e->selection, json_type_array)) { + char *end; + size_t idx = (size_t)strtol(name, &end, 10); + if (!*end && idx < json_object_array_length(e->selection)) { + o = json_object_array_get_idx(e->selection, idx); + r = 1; + } + } if (r) e->selection = o; return r; @@ -124,7 +135,8 @@ static int enter(void *closure, int objiter) e->stack[e->depth].cont = o; e->stack[e->depth].obj = json_object_array_get_idx(o, 0); e->stack[e->depth].index = 0; - } else if (json_object_is_type(o, json_type_object) || json_object_get_boolean(o)) { + } else if ((json_object_is_type(o, json_type_object) && json_object_object_length(o) > 0) + || json_object_get_boolean(o)) { e->stack[e->depth].count = 1; e->stack[e->depth].cont = NULL; e->stack[e->depth].obj = o; @@ -176,11 +188,16 @@ static int get(void *closure, struct mustach_sbuf *sbuf, int key) { struct expl *e = closure; const char *s; - - if (key) - s = e->stack[e->depth].is_objiter - ? json_object_iter_peek_name(&e->stack[e->depth].iter) - : ""; + int d; + + if (key) { + s = ""; + for (d = e->depth ; d >= 0 ; d--) + if (e->stack[d].is_objiter) { + s = json_object_iter_peek_name(&e->stack[d].iter); + break; + } + } else switch (json_object_get_type(e->selection)) { case json_type_string: diff --git a/src/templating/mustach-original-Makefile b/src/templating/mustach-original-Makefile index e902b2c71..6d90f33d9 100644 --- a/src/templating/mustach-original-Makefile +++ b/src/templating/mustach-original-Makefile @@ -1,7 +1,7 @@ # version MAJOR := 1 MINOR := 2 -REVIS := 4 +REVIS := 6 # installation settings DESTDIR ?= @@ -214,7 +214,9 @@ mustach-jansson.o: mustach-jansson.c mustach.h mustach-wrap.h mustach-jansson.h .PHONY: install install: all $(INSTALL) -d $(DESTDIR)$(BINDIR) - $(INSTALL) -m0755 mustach $(DESTDIR)$(BINDIR)/ + if test "${tool}" != "none"; then \ + $(INSTALL) -m0755 mustach $(DESTDIR)$(BINDIR)/; \ + fi $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR)/mustach $(INSTALL) -m0644 $(HEADERS) $(DESTDIR)$(INCLUDEDIR)/mustach $(INSTALL) -d $(DESTDIR)$(LIBDIR) @@ -236,6 +238,13 @@ uninstall: rm -rf $(DESTDIR)$(INCLUDEDIR)/mustach # testing +ifeq ($(valgrind),no) + NOVALGRIND := 1 +else + NOVALGRIND := $(shell which -s valgrind && echo 0 || echo 1) +endif +export NOVALGRIND + .PHONY: test test-basic test-specs test: basic-tests spec-tests @@ -245,7 +254,9 @@ basic-tests: mustach @$(MAKE) -C test3 test @$(MAKE) -C test4 test @$(MAKE) -C test5 test -# @$(MAKE) -C test6 test + @$(MAKE) -C test6 test + @$(MAKE) -C test7 test + @$(MAKE) -C test8 test spec-tests: $(TESTSPECS) @@ -291,6 +302,8 @@ clean: @$(MAKE) -C test4 clean @$(MAKE) -C test5 clean @$(MAKE) -C test6 clean + @$(MAKE) -C test7 clean + @$(MAKE) -C test8 clean # manpage .PHONY: manuals @@ -298,3 +311,4 @@ manuals: mustach.1.gz mustach.1.gz: mustach.1.scd if which scdoc >/dev/null 2>&1; then scdoc < mustach.1.scd | gzip > mustach.1.gz; fi + diff --git a/src/templating/mustach-tool.c b/src/templating/mustach-tool.c index 83a0813e5..e2a5c1f40 100644 --- a/src/templating/mustach-tool.c +++ b/src/templating/mustach-tool.c @@ -6,7 +6,9 @@ SPDX-License-Identifier: ISC */ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include #include diff --git a/src/templating/mustach-wrap.c b/src/templating/mustach-wrap.c index 75cc9d1f6..869713c86 100644 --- a/src/templating/mustach-wrap.c +++ b/src/templating/mustach-wrap.c @@ -6,7 +6,9 @@ SPDX-License-Identifier: ISC */ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include #include @@ -227,20 +229,20 @@ static enum sel sel(struct wrap *w, const char *name) return result; } -static int start(void *closure) +static int start_callback(void *closure) { struct wrap *w = closure; return w->itf->start ? w->itf->start(w->closure) : MUSTACH_OK; } -static void stop(void *closure, int status) +static void stop_callback(void *closure, int status) { struct wrap *w = closure; if (w->itf->stop) w->itf->stop(w->closure, status); } -static int write(struct wrap *w, const char *buffer, size_t size, FILE *file) +static int emit(struct wrap *w, const char *buffer, size_t size, FILE *file) { int r; @@ -251,7 +253,7 @@ static int write(struct wrap *w, const char *buffer, size_t size, FILE *file) return r; } -static int emit(void *closure, const char *buffer, size_t size, int escape, FILE *file) +static int emit_callback(void *closure, const char *buffer, size_t size, int escape, FILE *file) { struct wrap *w = closure; int r; @@ -261,7 +263,7 @@ static int emit(void *closure, const char *buffer, size_t size, int escape, FILE if (w->emitcb) r = w->emitcb(file, buffer, size, escape); else if (!escape) - r = write(w, buffer, size, file); + r = emit(w, buffer, size, file); else { i = 0; r = MUSTACH_OK; @@ -270,13 +272,13 @@ static int emit(void *closure, const char *buffer, size_t size, int escape, FILE while (i < size && (car = buffer[i]) != '<' && car != '>' && car != '&' && car != '"') i++; if (i != s) - r = write(w, &buffer[s], i - s, file); + r = emit(w, &buffer[s], i - s, file); if (i < size && r == MUSTACH_OK) { switch(car) { - case '<': r = write(w, "<", 4, file); break; - case '>': r = write(w, ">", 4, file); break; - case '&': r = write(w, "&", 5, file); break; - case '"': r = write(w, """, 6, file); break; + case '<': r = emit(w, "<", 4, file); break; + case '>': r = emit(w, ">", 4, file); break; + case '&': r = emit(w, "&", 5, file); break; + case '"': r = emit(w, """, 6, file); break; } i++; } @@ -285,20 +287,20 @@ static int emit(void *closure, const char *buffer, size_t size, int escape, FILE return r; } -static int enter(void *closure, const char *name) +static int enter_callback(void *closure, const char *name) { struct wrap *w = closure; enum sel s = sel(w, name); return s == S_none ? 0 : w->itf->enter(w->closure, s & S_objiter); } -static int next(void *closure) +static int next_callback(void *closure) { struct wrap *w = closure; return w->itf->next(w->closure); } -static int leave(void *closure) +static int leave_callback(void *closure) { struct wrap *w = closure; return w->itf->leave(w->closure); @@ -312,7 +314,7 @@ static int getoptional(struct wrap *w, const char *name, struct mustach_sbuf *sb return w->itf->get(w->closure, sbuf, s & S_objiter); } -static int get(void *closure, const char *name, struct mustach_sbuf *sbuf) +static int get_callback(void *closure, const char *name, struct mustach_sbuf *sbuf) { struct wrap *w = closure; if (getoptional(w, name, sbuf) <= 0) { @@ -374,7 +376,7 @@ static int get_partial_from_file(const char *name, struct mustach_sbuf *sbuf) return MUSTACH_ERROR_SYSTEM; } -static int partial(void *closure, const char *name, struct mustach_sbuf *sbuf) +static int partial_callback(void *closure, const char *name, struct mustach_sbuf *sbuf) { struct wrap *w = closure; int rc; @@ -397,15 +399,15 @@ static int partial(void *closure, const char *name, struct mustach_sbuf *sbuf) } const struct mustach_itf mustach_wrap_itf = { - .start = start, + .start = start_callback, .put = NULL, - .enter = enter, - .next = next, - .leave = leave, - .partial = partial, - .get = get, - .emit = emit, - .stop = stop + .enter = enter_callback, + .next = next_callback, + .leave = leave_callback, + .partial = partial_callback, + .get = get_callback, + .emit = emit_callback, + .stop = stop_callback }; static void wrap_init(struct wrap *wrap, const struct mustach_wrap_itf *itf, void *closure, int flags, mustach_emit_cb_t *emitcb, mustach_write_cb_t *writecb) diff --git a/src/templating/mustach.1.gz b/src/templating/mustach.1.gz new file mode 100644 index 000000000..15b8a9052 Binary files /dev/null and b/src/templating/mustach.1.gz differ diff --git a/src/templating/mustach.1.scd b/src/templating/mustach.1.scd new file mode 100644 index 000000000..af4f08ef2 --- /dev/null +++ b/src/templating/mustach.1.scd @@ -0,0 +1,60 @@ +mustach(1) + +# NAME + +mustach - Mustache templating command line engine + +# SYNOPSIS + +*mustach* [-s|--strict] JSON TEMPLATE... + +# DESCRIPTION + +Instanciate the TEMPLATE files accordingly to the JSON file. + +If one of the given files is *-*, the standard input is used. + +Option *--strict* make mustach fail if a tag is not found. + +# EXAMPLE + +A typical Mustache template file: *temp.must* + +``` +Hello {{name}} +You have just won {{value}} dollars! +{{#in_ca}} +Well, {{taxed_value}} dollars, after taxes. +{{/in_ca}} +``` + +Given a JSON file: *inst.json* + +``` +{ + "name": "Chris", + "value": 10000, + "taxed_value": 6000, + "in_ca": true +} +``` + +Calling the command *mustach inst.json temp.must* +will produce the following output: + +``` +Hello Chris +You have just won 10000 dollars! +Well, 6000.0 dollars, after taxes. +``` + +# LINK + +Site of *mustach*, the *C* implementation: https://gitlab.com/jobol/mustach + +*Mustache format*: http://mustache.github.io/mustache.5.html + +Main site for *Mustache*: http://mustache.github.io/ + +JSON: https://www.json.org/ + diff --git a/src/templating/mustach.c b/src/templating/mustach.c index 548c38224..9f992c737 100644 --- a/src/templating/mustach.c +++ b/src/templating/mustach.c @@ -6,7 +6,9 @@ SPDX-License-Identifier: ISC */ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include #include @@ -272,6 +274,7 @@ static int process(const char *template, size_t length, struct iwrap *iwrap, FIL template += l; stdalone = 1; pref.len = 0; + pref.prefix = prefix; } else if (!isspace(c)) { if (stdalone == 2 && enabled) { @@ -280,6 +283,7 @@ static int process(const char *template, size_t length, struct iwrap *iwrap, FIL return rc; pref.len = 0; stdalone = 0; + pref.prefix = NULL; } if (c == *opstr && end - beg >= (ssize_t)oplen) { for (l = 1 ; l < oplen && beg[l] == opstr[l] ; l++); @@ -360,6 +364,7 @@ get_name: if (rc < 0) return rc; pref.len = 0; + pref.prefix = NULL; } switch(c) { case '!': @@ -485,7 +490,7 @@ int mustach_file(const char *template, size_t length, const struct mustach_itf * /* process */ rc = itf->start ? itf->start(closure) : 0; if (rc == 0) - rc = process(template, length, &iwrap, file, 0); + rc = process(template, length, &iwrap, file, NULL); if (itf->stop) itf->stop(closure, rc); return rc; diff --git a/src/templating/pkgcfgs b/src/templating/pkgcfgs new file mode 100644 index 000000000..c3e84dc0e --- /dev/null +++ b/src/templating/pkgcfgs @@ -0,0 +1,35 @@ +==libmustach.pc== +Name: libmustach +Version: VERSION +Description: C Mustach single library +Cflags: -Imustach +Libs: -lmustach + +==libmustach-core.pc== +Name: libmustach-core +Version: VERSION +Description: C Mustach core library +Cflags: -Imustach +Libs: -lmustach-core + +==libmustach-cjson.pc== +Name: libmustach-cjson +Version: VERSION +Description: C Mustach library for cJSON +Cflags: -Imustach +Libs: -lmustach-cjson + +==libmustach-json-c.pc== +Name: libmustach-json-c +Version: VERSION +Description: C Mustach library for json-c +Cflags: -Imustach +Libs: -lmustach-json-c + +==libmustach-jansson.pc== +Name: libmustach-jansson +Version: VERSION +Description: C Mustach library for jansson +Cflags: -Imustach +Libs: -lmustach-jansson + diff --git a/src/templating/test-specs/test-specs-cjson.ref b/src/templating/test-specs/test-specs-cjson.ref new file mode 100644 index 000000000..8897c66cc --- /dev/null +++ b/src/templating/test-specs/test-specs-cjson.ref @@ -0,0 +1,425 @@ + +loading test-specs/spec/specs/comments.json +processing file test-specs/spec/specs/comments.json +[0] Inline + Comment blocks should be removed from the template. + => SUCCESS +[1] Multiline + Multiline comments should be permitted. + => SUCCESS +[2] Standalone + All standalone comment lines should be removed. + => SUCCESS +[3] Indented Standalone + All standalone comment lines should be removed. + => SUCCESS +[4] Standalone Line Endings + "\r\n" should be considered a newline for standalone tags. + => SUCCESS +[5] Standalone Without Previous Line + Standalone tags should not require a newline to precede them. + => SUCCESS +[6] Standalone Without Newline + Standalone tags should not require a newline to follow them. + => SUCCESS +[7] Multiline Standalone + All standalone comment lines should be removed. + => SUCCESS +[8] Indented Multiline Standalone + All standalone comment lines should be removed. + => SUCCESS +[9] Indented Inline + Inline comments should not strip whitespace + => SUCCESS +[10] Surrounding Whitespace + Comment removal should preserve surrounding whitespace. + => SUCCESS +[11] Variable Name Collision + Comments must never render, even if variable with same name exists. + => SUCCESS + +loading test-specs/spec/specs/delimiters.json +processing file test-specs/spec/specs/delimiters.json +[0] Pair Behavior + The equals sign (used on both sides) should permit delimiter changes. + => SUCCESS +[1] Special Characters + Characters with special meaning regexen should be valid delimiters. + => SUCCESS +[2] Sections + Delimiters set outside sections should persist. + => SUCCESS +[3] Inverted Sections + Delimiters set outside inverted sections should persist. + => SUCCESS +[4] Partial Inheritence + Delimiters set in a parent template should not affect a partial. + => SUCCESS +[5] Post-Partial Behavior + Delimiters set in a partial should not affect the parent template. + => SUCCESS +[6] Surrounding Whitespace + Surrounding whitespace should be left untouched. + => SUCCESS +[7] Outlying Whitespace (Inline) + Whitespace should be left untouched. + => SUCCESS +[8] Standalone Tag + Standalone lines should be removed from the template. + => SUCCESS +[9] Indented Standalone Tag + Indented standalone lines should be removed from the template. + => SUCCESS +[10] Standalone Line Endings + "\r\n" should be considered a newline for standalone tags. + => SUCCESS +[11] Standalone Without Previous Line + Standalone tags should not require a newline to precede them. + => SUCCESS +[12] Standalone Without Newline + Standalone tags should not require a newline to follow them. + => SUCCESS +[13] Pair with Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS + +loading test-specs/spec/specs/interpolation.json +processing file test-specs/spec/specs/interpolation.json +[0] No Interpolation + Mustache-free templates should render as-is. + => SUCCESS +[1] Basic Interpolation + Unadorned tags should interpolate content into the template. + => SUCCESS +[2] HTML Escaping + Basic interpolation should be HTML escaped. + => SUCCESS +[3] Triple Mustache + Triple mustaches should interpolate without HTML escaping. + => SUCCESS +[4] Ampersand + Ampersand should interpolate without HTML escaping. + => SUCCESS +[5] Basic Integer Interpolation + Integers should interpolate seamlessly. + => SUCCESS +[6] Triple Mustache Integer Interpolation + Integers should interpolate seamlessly. + => SUCCESS +[7] Ampersand Integer Interpolation + Integers should interpolate seamlessly. + => SUCCESS +[8] Basic Decimal Interpolation + Decimals should interpolate seamlessly with proper significance. + => SUCCESS +[9] Triple Mustache Decimal Interpolation + Decimals should interpolate seamlessly with proper significance. + => SUCCESS +[10] Ampersand Decimal Interpolation + Decimals should interpolate seamlessly with proper significance. + => SUCCESS +[11] Basic Null Interpolation + Nulls should interpolate as the empty string. + => SUCCESS +[12] Triple Mustache Null Interpolation + Nulls should interpolate as the empty string. + => SUCCESS +[13] Ampersand Null Interpolation + Nulls should interpolate as the empty string. + => SUCCESS +[14] Basic Context Miss Interpolation + Failed context lookups should default to empty strings. + => SUCCESS +[15] Triple Mustache Context Miss Interpolation + Failed context lookups should default to empty strings. + => SUCCESS +[16] Ampersand Context Miss Interpolation + Failed context lookups should default to empty strings. + => SUCCESS +[17] Dotted Names - Basic Interpolation + Dotted names should be considered a form of shorthand for sections. + => SUCCESS +[18] Dotted Names - Triple Mustache Interpolation + Dotted names should be considered a form of shorthand for sections. + => SUCCESS +[19] Dotted Names - Ampersand Interpolation + Dotted names should be considered a form of shorthand for sections. + => SUCCESS +[20] Dotted Names - Arbitrary Depth + Dotted names should be functional to any level of nesting. + => SUCCESS +[21] Dotted Names - Broken Chains + Any falsey value prior to the last part of the name should yield ''. + => SUCCESS +[22] Dotted Names - Broken Chain Resolution + Each part of a dotted name should resolve only against its parent. + => SUCCESS +[23] Dotted Names - Initial Resolution + The first part of a dotted name should resolve as any other name. + => SUCCESS +[24] Dotted Names - Context Precedence + Dotted names should be resolved against former resolutions. + => SUCCESS +[25] Implicit Iterators - Basic Interpolation + Unadorned tags should interpolate content into the template. + => SUCCESS +[26] Implicit Iterators - HTML Escaping + Basic interpolation should be HTML escaped. + => SUCCESS +[27] Implicit Iterators - Triple Mustache + Triple mustaches should interpolate without HTML escaping. + => SUCCESS +[28] Implicit Iterators - Ampersand + Ampersand should interpolate without HTML escaping. + => SUCCESS +[29] Implicit Iterators - Basic Integer Interpolation + Integers should interpolate seamlessly. + => SUCCESS +[30] Interpolation - Surrounding Whitespace + Interpolation should not alter surrounding whitespace. + => SUCCESS +[31] Triple Mustache - Surrounding Whitespace + Interpolation should not alter surrounding whitespace. + => SUCCESS +[32] Ampersand - Surrounding Whitespace + Interpolation should not alter surrounding whitespace. + => SUCCESS +[33] Interpolation - Standalone + Standalone interpolation should not alter surrounding whitespace. + => SUCCESS +[34] Triple Mustache - Standalone + Standalone interpolation should not alter surrounding whitespace. + => SUCCESS +[35] Ampersand - Standalone + Standalone interpolation should not alter surrounding whitespace. + => SUCCESS +[36] Interpolation With Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS +[37] Triple Mustache With Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS +[38] Ampersand With Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS + +loading test-specs/spec/specs/inverted.json +processing file test-specs/spec/specs/inverted.json +[0] Falsey + Falsey sections should have their contents rendered. + => SUCCESS +[1] Truthy + Truthy sections should have their contents omitted. + => SUCCESS +[2] Null is falsey + Null is falsey. + => SUCCESS +[3] Context + Objects and hashes should behave like truthy values. + => SUCCESS +[4] List + Lists should behave like truthy values. + => SUCCESS +[5] Empty List + Empty lists should behave like falsey values. + => SUCCESS +[6] Doubled + Multiple inverted sections per template should be permitted. + => SUCCESS +[7] Nested (Falsey) + Nested falsey sections should have their contents rendered. + => SUCCESS +[8] Nested (Truthy) + Nested truthy sections should be omitted. + => SUCCESS +[9] Context Misses + Failed context lookups should be considered falsey. + => SUCCESS +[10] Dotted Names - Truthy + Dotted names should be valid for Inverted Section tags. + => SUCCESS +[11] Dotted Names - Falsey + Dotted names should be valid for Inverted Section tags. + => SUCCESS +[12] Dotted Names - Broken Chains + Dotted names that cannot be resolved should be considered falsey. + => SUCCESS +[13] Surrounding Whitespace + Inverted sections should not alter surrounding whitespace. + => SUCCESS +[14] Internal Whitespace + Inverted should not alter internal whitespace. + => SUCCESS +[15] Indented Inline Sections + Single-line sections should not alter surrounding whitespace. + => SUCCESS +[16] Standalone Lines + Standalone lines should be removed from the template. + => SUCCESS +[17] Standalone Indented Lines + Standalone indented lines should be removed from the template. + => SUCCESS +[18] Standalone Line Endings + "\r\n" should be considered a newline for standalone tags. + => SUCCESS +[19] Standalone Without Previous Line + Standalone tags should not require a newline to precede them. + => SUCCESS +[20] Standalone Without Newline + Standalone tags should not require a newline to follow them. + => SUCCESS +[21] Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS + +loading test-specs/spec/specs/partials.json +processing file test-specs/spec/specs/partials.json +[0] Basic Behavior + The greater-than operator should expand to the named partial. + => SUCCESS +[1] Failed Lookup + The empty string should be used when the named partial is not found. + => SUCCESS +[2] Context + The greater-than operator should operate within the current context. + => SUCCESS +[3] Recursion + The greater-than operator should properly recurse. + => SUCCESS +[4] Nested + The greater-than operator should work from within partials. + => SUCCESS +[5] Surrounding Whitespace + The greater-than operator should not alter surrounding whitespace. + => SUCCESS +[6] Inline Indentation + Whitespace should be left untouched. + => SUCCESS +[7] Standalone Line Endings + "\r\n" should be considered a newline for standalone tags. + => SUCCESS +[8] Standalone Without Previous Line + Standalone tags should not require a newline to precede them. + => SUCCESS +[9] Standalone Without Newline + Standalone tags should not require a newline to follow them. + => SUCCESS +[10] Standalone Indentation + Each line of the partial should be indented before rendering. + => SUCCESS +[11] Padding Whitespace + Superfluous in-tag whitespace should be ignored. + => SUCCESS + +loading test-specs/spec/specs/sections.json +processing file test-specs/spec/specs/sections.json +[0] Truthy + Truthy sections should have their contents rendered. + => SUCCESS +[1] Falsey + Falsey sections should have their contents omitted. + => SUCCESS +[2] Null is falsey + Null is falsey. + => SUCCESS +[3] Context + Objects and hashes should be pushed onto the context stack. + => SUCCESS +[4] Parent contexts + Names missing in the current context are looked up in the stack. + => SUCCESS +[5] Variable test + Non-false sections have their value at the top of context, +accessible as {{.}} or through the parent context. This gives +a simple way to display content conditionally if a variable exists. + + => SUCCESS +[6] List Contexts + All elements on the context stack should be accessible within lists. + => SUCCESS +[7] Deeply Nested Contexts + All elements on the context stack should be accessible. + => SUCCESS +[8] List + Lists should be iterated; list items should visit the context stack. + => SUCCESS +[9] Empty List + Empty lists should behave like falsey values. + => SUCCESS +[10] Doubled + Multiple sections per template should be permitted. + => SUCCESS +[11] Nested (Truthy) + Nested truthy sections should have their contents rendered. + => SUCCESS +[12] Nested (Falsey) + Nested falsey sections should be omitted. + => SUCCESS +[13] Context Misses + Failed context lookups should be considered falsey. + => SUCCESS +[14] Implicit Iterator - String + Implicit iterators should directly interpolate strings. + => SUCCESS +[15] Implicit Iterator - Integer + Implicit iterators should cast integers to strings and interpolate. + => SUCCESS +[16] Implicit Iterator - Decimal + Implicit iterators should cast decimals to strings and interpolate. + => SUCCESS +[17] Implicit Iterator - Array + Implicit iterators should allow iterating over nested arrays. + => SUCCESS +[18] Implicit Iterator - HTML Escaping + Implicit iterators with basic interpolation should be HTML escaped. + => SUCCESS +[19] Implicit Iterator - Triple mustache + Implicit iterators in triple mustache should interpolate without HTML escaping. + => SUCCESS +[20] Implicit Iterator - Ampersand + Implicit iterators in an Ampersand tag should interpolate without HTML escaping. + => SUCCESS +[21] Implicit Iterator - Root-level + Implicit iterators should work on root-level lists. + => SUCCESS +[22] Dotted Names - Truthy + Dotted names should be valid for Section tags. + => SUCCESS +[23] Dotted Names - Falsey + Dotted names should be valid for Section tags. + => SUCCESS +[24] Dotted Names - Broken Chains + Dotted names that cannot be resolved should be considered falsey. + => SUCCESS +[25] Surrounding Whitespace + Sections should not alter surrounding whitespace. + => SUCCESS +[26] Internal Whitespace + Sections should not alter internal whitespace. + => SUCCESS +[27] Indented Inline Sections + Single-line sections should not alter surrounding whitespace. + => SUCCESS +[28] Standalone Lines + Standalone lines should be removed from the template. + => SUCCESS +[29] Indented Standalone Lines + Indented standalone lines should be removed from the template. + => SUCCESS +[30] Standalone Line Endings + "\r\n" should be considered a newline for standalone tags. + => SUCCESS +[31] Standalone Without Previous Line + Standalone tags should not require a newline to precede them. + => SUCCESS +[32] Standalone Without Newline + Standalone tags should not require a newline to follow them. + => SUCCESS +[33] Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS + +summary: + error 0 + differ 0 + success 133 diff --git a/src/templating/test-specs/test-specs-jansson.ref b/src/templating/test-specs/test-specs-jansson.ref new file mode 100644 index 000000000..a1cef19c1 --- /dev/null +++ b/src/templating/test-specs/test-specs-jansson.ref @@ -0,0 +1,429 @@ + +loading test-specs/spec/specs/comments.json +processing file test-specs/spec/specs/comments.json +[0] Inline + Comment blocks should be removed from the template. + => SUCCESS +[1] Multiline + Multiline comments should be permitted. + => SUCCESS +[2] Standalone + All standalone comment lines should be removed. + => SUCCESS +[3] Indented Standalone + All standalone comment lines should be removed. + => SUCCESS +[4] Standalone Line Endings + "\r\n" should be considered a newline for standalone tags. + => SUCCESS +[5] Standalone Without Previous Line + Standalone tags should not require a newline to precede them. + => SUCCESS +[6] Standalone Without Newline + Standalone tags should not require a newline to follow them. + => SUCCESS +[7] Multiline Standalone + All standalone comment lines should be removed. + => SUCCESS +[8] Indented Multiline Standalone + All standalone comment lines should be removed. + => SUCCESS +[9] Indented Inline + Inline comments should not strip whitespace + => SUCCESS +[10] Surrounding Whitespace + Comment removal should preserve surrounding whitespace. + => SUCCESS +[11] Variable Name Collision + Comments must never render, even if variable with same name exists. + => SUCCESS + +loading test-specs/spec/specs/delimiters.json +processing file test-specs/spec/specs/delimiters.json +[0] Pair Behavior + The equals sign (used on both sides) should permit delimiter changes. + => SUCCESS +[1] Special Characters + Characters with special meaning regexen should be valid delimiters. + => SUCCESS +[2] Sections + Delimiters set outside sections should persist. + => SUCCESS +[3] Inverted Sections + Delimiters set outside inverted sections should persist. + => SUCCESS +[4] Partial Inheritence + Delimiters set in a parent template should not affect a partial. + => SUCCESS +[5] Post-Partial Behavior + Delimiters set in a partial should not affect the parent template. + => SUCCESS +[6] Surrounding Whitespace + Surrounding whitespace should be left untouched. + => SUCCESS +[7] Outlying Whitespace (Inline) + Whitespace should be left untouched. + => SUCCESS +[8] Standalone Tag + Standalone lines should be removed from the template. + => SUCCESS +[9] Indented Standalone Tag + Indented standalone lines should be removed from the template. + => SUCCESS +[10] Standalone Line Endings + "\r\n" should be considered a newline for standalone tags. + => SUCCESS +[11] Standalone Without Previous Line + Standalone tags should not require a newline to precede them. + => SUCCESS +[12] Standalone Without Newline + Standalone tags should not require a newline to follow them. + => SUCCESS +[13] Pair with Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS + +loading test-specs/spec/specs/interpolation.json +processing file test-specs/spec/specs/interpolation.json +[0] No Interpolation + Mustache-free templates should render as-is. + => SUCCESS +[1] Basic Interpolation + Unadorned tags should interpolate content into the template. + => SUCCESS +[2] HTML Escaping + Basic interpolation should be HTML escaped. + => SUCCESS +[3] Triple Mustache + Triple mustaches should interpolate without HTML escaping. + => SUCCESS +[4] Ampersand + Ampersand should interpolate without HTML escaping. + => SUCCESS +[5] Basic Integer Interpolation + Integers should interpolate seamlessly. + => SUCCESS +[6] Triple Mustache Integer Interpolation + Integers should interpolate seamlessly. + => SUCCESS +[7] Ampersand Integer Interpolation + Integers should interpolate seamlessly. + => SUCCESS +[8] Basic Decimal Interpolation + Decimals should interpolate seamlessly with proper significance. + => SUCCESS +[9] Triple Mustache Decimal Interpolation + Decimals should interpolate seamlessly with proper significance. + => SUCCESS +[10] Ampersand Decimal Interpolation + Decimals should interpolate seamlessly with proper significance. + => SUCCESS +[11] Basic Null Interpolation + Nulls should interpolate as the empty string. + => SUCCESS +[12] Triple Mustache Null Interpolation + Nulls should interpolate as the empty string. + => SUCCESS +[13] Ampersand Null Interpolation + Nulls should interpolate as the empty string. + => SUCCESS +[14] Basic Context Miss Interpolation + Failed context lookups should default to empty strings. + => SUCCESS +[15] Triple Mustache Context Miss Interpolation + Failed context lookups should default to empty strings. + => SUCCESS +[16] Ampersand Context Miss Interpolation + Failed context lookups should default to empty strings. + => SUCCESS +[17] Dotted Names - Basic Interpolation + Dotted names should be considered a form of shorthand for sections. + => SUCCESS +[18] Dotted Names - Triple Mustache Interpolation + Dotted names should be considered a form of shorthand for sections. + => SUCCESS +[19] Dotted Names - Ampersand Interpolation + Dotted names should be considered a form of shorthand for sections. + => SUCCESS +[20] Dotted Names - Arbitrary Depth + Dotted names should be functional to any level of nesting. + => SUCCESS +[21] Dotted Names - Broken Chains + Any falsey value prior to the last part of the name should yield ''. + => SUCCESS +[22] Dotted Names - Broken Chain Resolution + Each part of a dotted name should resolve only against its parent. + => SUCCESS +[23] Dotted Names - Initial Resolution + The first part of a dotted name should resolve as any other name. + => SUCCESS +[24] Dotted Names - Context Precedence + Dotted names should be resolved against former resolutions. + => SUCCESS +[25] Implicit Iterators - Basic Interpolation + Unadorned tags should interpolate content into the template. + => SUCCESS +[26] Implicit Iterators - HTML Escaping + Basic interpolation should be HTML escaped. + => SUCCESS +[27] Implicit Iterators - Triple Mustache + Triple mustaches should interpolate without HTML escaping. + => SUCCESS +[28] Implicit Iterators - Ampersand + Ampersand should interpolate without HTML escaping. + => SUCCESS +[29] Implicit Iterators - Basic Integer Interpolation + Integers should interpolate seamlessly. + => SUCCESS +[30] Interpolation - Surrounding Whitespace + Interpolation should not alter surrounding whitespace. + => SUCCESS +[31] Triple Mustache - Surrounding Whitespace + Interpolation should not alter surrounding whitespace. + => SUCCESS +[32] Ampersand - Surrounding Whitespace + Interpolation should not alter surrounding whitespace. + => SUCCESS +[33] Interpolation - Standalone + Standalone interpolation should not alter surrounding whitespace. + => SUCCESS +[34] Triple Mustache - Standalone + Standalone interpolation should not alter surrounding whitespace. + => SUCCESS +[35] Ampersand - Standalone + Standalone interpolation should not alter surrounding whitespace. + => SUCCESS +[36] Interpolation With Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS +[37] Triple Mustache With Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS +[38] Ampersand With Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS + +loading test-specs/spec/specs/inverted.json +processing file test-specs/spec/specs/inverted.json +[0] Falsey + Falsey sections should have their contents rendered. + => SUCCESS +[1] Truthy + Truthy sections should have their contents omitted. + => SUCCESS +[2] Null is falsey + Null is falsey. + => SUCCESS +[3] Context + Objects and hashes should behave like truthy values. + => SUCCESS +[4] List + Lists should behave like truthy values. + => SUCCESS +[5] Empty List + Empty lists should behave like falsey values. + => SUCCESS +[6] Doubled + Multiple inverted sections per template should be permitted. + => SUCCESS +[7] Nested (Falsey) + Nested falsey sections should have their contents rendered. + => SUCCESS +[8] Nested (Truthy) + Nested truthy sections should be omitted. + => SUCCESS +[9] Context Misses + Failed context lookups should be considered falsey. + => SUCCESS +[10] Dotted Names - Truthy + Dotted names should be valid for Inverted Section tags. + => SUCCESS +[11] Dotted Names - Falsey + Dotted names should be valid for Inverted Section tags. + => SUCCESS +[12] Dotted Names - Broken Chains + Dotted names that cannot be resolved should be considered falsey. + => SUCCESS +[13] Surrounding Whitespace + Inverted sections should not alter surrounding whitespace. + => SUCCESS +[14] Internal Whitespace + Inverted should not alter internal whitespace. + => SUCCESS +[15] Indented Inline Sections + Single-line sections should not alter surrounding whitespace. + => SUCCESS +[16] Standalone Lines + Standalone lines should be removed from the template. + => SUCCESS +[17] Standalone Indented Lines + Standalone indented lines should be removed from the template. + => SUCCESS +[18] Standalone Line Endings + "\r\n" should be considered a newline for standalone tags. + => SUCCESS +[19] Standalone Without Previous Line + Standalone tags should not require a newline to precede them. + => SUCCESS +[20] Standalone Without Newline + Standalone tags should not require a newline to follow them. + => SUCCESS +[21] Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS + +loading test-specs/spec/specs/partials.json +processing file test-specs/spec/specs/partials.json +[0] Basic Behavior + The greater-than operator should expand to the named partial. + => SUCCESS +[1] Failed Lookup + The empty string should be used when the named partial is not found. + => SUCCESS +[2] Context + The greater-than operator should operate within the current context. + => SUCCESS +[3] Recursion + The greater-than operator should properly recurse. + => SUCCESS +[4] Nested + The greater-than operator should work from within partials. + => SUCCESS +[5] Surrounding Whitespace + The greater-than operator should not alter surrounding whitespace. + => SUCCESS +[6] Inline Indentation + Whitespace should be left untouched. + => SUCCESS +[7] Standalone Line Endings + "\r\n" should be considered a newline for standalone tags. + => SUCCESS +[8] Standalone Without Previous Line + Standalone tags should not require a newline to precede them. + => SUCCESS +[9] Standalone Without Newline + Standalone tags should not require a newline to follow them. + => SUCCESS +[10] Standalone Indentation + Each line of the partial should be indented before rendering. + => SUCCESS +[11] Padding Whitespace + Superfluous in-tag whitespace should be ignored. + => SUCCESS + +loading test-specs/spec/specs/sections.json +processing file test-specs/spec/specs/sections.json +[0] Truthy + Truthy sections should have their contents rendered. + => SUCCESS +[1] Falsey + Falsey sections should have their contents omitted. + => SUCCESS +[2] Null is falsey + Null is falsey. + => SUCCESS +[3] Context + Objects and hashes should be pushed onto the context stack. + => SUCCESS +[4] Parent contexts + Names missing in the current context are looked up in the stack. + => SUCCESS +[5] Variable test + Non-false sections have their value at the top of context, +accessible as {{.}} or through the parent context. This gives +a simple way to display content conditionally if a variable exists. + + => SUCCESS +[6] List Contexts + All elements on the context stack should be accessible within lists. + => SUCCESS +[7] Deeply Nested Contexts + All elements on the context stack should be accessible. + => SUCCESS +[8] List + Lists should be iterated; list items should visit the context stack. + => SUCCESS +[9] Empty List + Empty lists should behave like falsey values. + => SUCCESS +[10] Doubled + Multiple sections per template should be permitted. + => SUCCESS +[11] Nested (Truthy) + Nested truthy sections should have their contents rendered. + => SUCCESS +[12] Nested (Falsey) + Nested falsey sections should be omitted. + => SUCCESS +[13] Context Misses + Failed context lookups should be considered falsey. + => SUCCESS +[14] Implicit Iterator - String + Implicit iterators should directly interpolate strings. + => SUCCESS +[15] Implicit Iterator - Integer + Implicit iterators should cast integers to strings and interpolate. + => SUCCESS +[16] Implicit Iterator - Decimal + Implicit iterators should cast decimals to strings and interpolate. + => DIFFERS + .. DATA[{"list":[1.1000000000000001,2.2000000000000002,3.2999999999999998,4.4000000000000004,5.5]}] + .. TEMPLATE["{{#list}}({{.}}){{/list}}"] + .. EXPECTED["(1.1)(2.2)(3.3)(4.4)(5.5)"] + .. GOT["(1.1000000000000001)(2.2000000000000002)(3.2999999999999998)(4.4000000000000004)(5.5)"] +[17] Implicit Iterator - Array + Implicit iterators should allow iterating over nested arrays. + => SUCCESS +[18] Implicit Iterator - HTML Escaping + Implicit iterators with basic interpolation should be HTML escaped. + => SUCCESS +[19] Implicit Iterator - Triple mustache + Implicit iterators in triple mustache should interpolate without HTML escaping. + => SUCCESS +[20] Implicit Iterator - Ampersand + Implicit iterators in an Ampersand tag should interpolate without HTML escaping. + => SUCCESS +[21] Implicit Iterator - Root-level + Implicit iterators should work on root-level lists. + => SUCCESS +[22] Dotted Names - Truthy + Dotted names should be valid for Section tags. + => SUCCESS +[23] Dotted Names - Falsey + Dotted names should be valid for Section tags. + => SUCCESS +[24] Dotted Names - Broken Chains + Dotted names that cannot be resolved should be considered falsey. + => SUCCESS +[25] Surrounding Whitespace + Sections should not alter surrounding whitespace. + => SUCCESS +[26] Internal Whitespace + Sections should not alter internal whitespace. + => SUCCESS +[27] Indented Inline Sections + Single-line sections should not alter surrounding whitespace. + => SUCCESS +[28] Standalone Lines + Standalone lines should be removed from the template. + => SUCCESS +[29] Indented Standalone Lines + Indented standalone lines should be removed from the template. + => SUCCESS +[30] Standalone Line Endings + "\r\n" should be considered a newline for standalone tags. + => SUCCESS +[31] Standalone Without Previous Line + Standalone tags should not require a newline to precede them. + => SUCCESS +[32] Standalone Without Newline + Standalone tags should not require a newline to follow them. + => SUCCESS +[33] Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS + +summary: + error 0 + differ 1 + success 132 diff --git a/src/templating/test-specs/test-specs-json-c.ref b/src/templating/test-specs/test-specs-json-c.ref new file mode 100644 index 000000000..8897c66cc --- /dev/null +++ b/src/templating/test-specs/test-specs-json-c.ref @@ -0,0 +1,425 @@ + +loading test-specs/spec/specs/comments.json +processing file test-specs/spec/specs/comments.json +[0] Inline + Comment blocks should be removed from the template. + => SUCCESS +[1] Multiline + Multiline comments should be permitted. + => SUCCESS +[2] Standalone + All standalone comment lines should be removed. + => SUCCESS +[3] Indented Standalone + All standalone comment lines should be removed. + => SUCCESS +[4] Standalone Line Endings + "\r\n" should be considered a newline for standalone tags. + => SUCCESS +[5] Standalone Without Previous Line + Standalone tags should not require a newline to precede them. + => SUCCESS +[6] Standalone Without Newline + Standalone tags should not require a newline to follow them. + => SUCCESS +[7] Multiline Standalone + All standalone comment lines should be removed. + => SUCCESS +[8] Indented Multiline Standalone + All standalone comment lines should be removed. + => SUCCESS +[9] Indented Inline + Inline comments should not strip whitespace + => SUCCESS +[10] Surrounding Whitespace + Comment removal should preserve surrounding whitespace. + => SUCCESS +[11] Variable Name Collision + Comments must never render, even if variable with same name exists. + => SUCCESS + +loading test-specs/spec/specs/delimiters.json +processing file test-specs/spec/specs/delimiters.json +[0] Pair Behavior + The equals sign (used on both sides) should permit delimiter changes. + => SUCCESS +[1] Special Characters + Characters with special meaning regexen should be valid delimiters. + => SUCCESS +[2] Sections + Delimiters set outside sections should persist. + => SUCCESS +[3] Inverted Sections + Delimiters set outside inverted sections should persist. + => SUCCESS +[4] Partial Inheritence + Delimiters set in a parent template should not affect a partial. + => SUCCESS +[5] Post-Partial Behavior + Delimiters set in a partial should not affect the parent template. + => SUCCESS +[6] Surrounding Whitespace + Surrounding whitespace should be left untouched. + => SUCCESS +[7] Outlying Whitespace (Inline) + Whitespace should be left untouched. + => SUCCESS +[8] Standalone Tag + Standalone lines should be removed from the template. + => SUCCESS +[9] Indented Standalone Tag + Indented standalone lines should be removed from the template. + => SUCCESS +[10] Standalone Line Endings + "\r\n" should be considered a newline for standalone tags. + => SUCCESS +[11] Standalone Without Previous Line + Standalone tags should not require a newline to precede them. + => SUCCESS +[12] Standalone Without Newline + Standalone tags should not require a newline to follow them. + => SUCCESS +[13] Pair with Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS + +loading test-specs/spec/specs/interpolation.json +processing file test-specs/spec/specs/interpolation.json +[0] No Interpolation + Mustache-free templates should render as-is. + => SUCCESS +[1] Basic Interpolation + Unadorned tags should interpolate content into the template. + => SUCCESS +[2] HTML Escaping + Basic interpolation should be HTML escaped. + => SUCCESS +[3] Triple Mustache + Triple mustaches should interpolate without HTML escaping. + => SUCCESS +[4] Ampersand + Ampersand should interpolate without HTML escaping. + => SUCCESS +[5] Basic Integer Interpolation + Integers should interpolate seamlessly. + => SUCCESS +[6] Triple Mustache Integer Interpolation + Integers should interpolate seamlessly. + => SUCCESS +[7] Ampersand Integer Interpolation + Integers should interpolate seamlessly. + => SUCCESS +[8] Basic Decimal Interpolation + Decimals should interpolate seamlessly with proper significance. + => SUCCESS +[9] Triple Mustache Decimal Interpolation + Decimals should interpolate seamlessly with proper significance. + => SUCCESS +[10] Ampersand Decimal Interpolation + Decimals should interpolate seamlessly with proper significance. + => SUCCESS +[11] Basic Null Interpolation + Nulls should interpolate as the empty string. + => SUCCESS +[12] Triple Mustache Null Interpolation + Nulls should interpolate as the empty string. + => SUCCESS +[13] Ampersand Null Interpolation + Nulls should interpolate as the empty string. + => SUCCESS +[14] Basic Context Miss Interpolation + Failed context lookups should default to empty strings. + => SUCCESS +[15] Triple Mustache Context Miss Interpolation + Failed context lookups should default to empty strings. + => SUCCESS +[16] Ampersand Context Miss Interpolation + Failed context lookups should default to empty strings. + => SUCCESS +[17] Dotted Names - Basic Interpolation + Dotted names should be considered a form of shorthand for sections. + => SUCCESS +[18] Dotted Names - Triple Mustache Interpolation + Dotted names should be considered a form of shorthand for sections. + => SUCCESS +[19] Dotted Names - Ampersand Interpolation + Dotted names should be considered a form of shorthand for sections. + => SUCCESS +[20] Dotted Names - Arbitrary Depth + Dotted names should be functional to any level of nesting. + => SUCCESS +[21] Dotted Names - Broken Chains + Any falsey value prior to the last part of the name should yield ''. + => SUCCESS +[22] Dotted Names - Broken Chain Resolution + Each part of a dotted name should resolve only against its parent. + => SUCCESS +[23] Dotted Names - Initial Resolution + The first part of a dotted name should resolve as any other name. + => SUCCESS +[24] Dotted Names - Context Precedence + Dotted names should be resolved against former resolutions. + => SUCCESS +[25] Implicit Iterators - Basic Interpolation + Unadorned tags should interpolate content into the template. + => SUCCESS +[26] Implicit Iterators - HTML Escaping + Basic interpolation should be HTML escaped. + => SUCCESS +[27] Implicit Iterators - Triple Mustache + Triple mustaches should interpolate without HTML escaping. + => SUCCESS +[28] Implicit Iterators - Ampersand + Ampersand should interpolate without HTML escaping. + => SUCCESS +[29] Implicit Iterators - Basic Integer Interpolation + Integers should interpolate seamlessly. + => SUCCESS +[30] Interpolation - Surrounding Whitespace + Interpolation should not alter surrounding whitespace. + => SUCCESS +[31] Triple Mustache - Surrounding Whitespace + Interpolation should not alter surrounding whitespace. + => SUCCESS +[32] Ampersand - Surrounding Whitespace + Interpolation should not alter surrounding whitespace. + => SUCCESS +[33] Interpolation - Standalone + Standalone interpolation should not alter surrounding whitespace. + => SUCCESS +[34] Triple Mustache - Standalone + Standalone interpolation should not alter surrounding whitespace. + => SUCCESS +[35] Ampersand - Standalone + Standalone interpolation should not alter surrounding whitespace. + => SUCCESS +[36] Interpolation With Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS +[37] Triple Mustache With Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS +[38] Ampersand With Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS + +loading test-specs/spec/specs/inverted.json +processing file test-specs/spec/specs/inverted.json +[0] Falsey + Falsey sections should have their contents rendered. + => SUCCESS +[1] Truthy + Truthy sections should have their contents omitted. + => SUCCESS +[2] Null is falsey + Null is falsey. + => SUCCESS +[3] Context + Objects and hashes should behave like truthy values. + => SUCCESS +[4] List + Lists should behave like truthy values. + => SUCCESS +[5] Empty List + Empty lists should behave like falsey values. + => SUCCESS +[6] Doubled + Multiple inverted sections per template should be permitted. + => SUCCESS +[7] Nested (Falsey) + Nested falsey sections should have their contents rendered. + => SUCCESS +[8] Nested (Truthy) + Nested truthy sections should be omitted. + => SUCCESS +[9] Context Misses + Failed context lookups should be considered falsey. + => SUCCESS +[10] Dotted Names - Truthy + Dotted names should be valid for Inverted Section tags. + => SUCCESS +[11] Dotted Names - Falsey + Dotted names should be valid for Inverted Section tags. + => SUCCESS +[12] Dotted Names - Broken Chains + Dotted names that cannot be resolved should be considered falsey. + => SUCCESS +[13] Surrounding Whitespace + Inverted sections should not alter surrounding whitespace. + => SUCCESS +[14] Internal Whitespace + Inverted should not alter internal whitespace. + => SUCCESS +[15] Indented Inline Sections + Single-line sections should not alter surrounding whitespace. + => SUCCESS +[16] Standalone Lines + Standalone lines should be removed from the template. + => SUCCESS +[17] Standalone Indented Lines + Standalone indented lines should be removed from the template. + => SUCCESS +[18] Standalone Line Endings + "\r\n" should be considered a newline for standalone tags. + => SUCCESS +[19] Standalone Without Previous Line + Standalone tags should not require a newline to precede them. + => SUCCESS +[20] Standalone Without Newline + Standalone tags should not require a newline to follow them. + => SUCCESS +[21] Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS + +loading test-specs/spec/specs/partials.json +processing file test-specs/spec/specs/partials.json +[0] Basic Behavior + The greater-than operator should expand to the named partial. + => SUCCESS +[1] Failed Lookup + The empty string should be used when the named partial is not found. + => SUCCESS +[2] Context + The greater-than operator should operate within the current context. + => SUCCESS +[3] Recursion + The greater-than operator should properly recurse. + => SUCCESS +[4] Nested + The greater-than operator should work from within partials. + => SUCCESS +[5] Surrounding Whitespace + The greater-than operator should not alter surrounding whitespace. + => SUCCESS +[6] Inline Indentation + Whitespace should be left untouched. + => SUCCESS +[7] Standalone Line Endings + "\r\n" should be considered a newline for standalone tags. + => SUCCESS +[8] Standalone Without Previous Line + Standalone tags should not require a newline to precede them. + => SUCCESS +[9] Standalone Without Newline + Standalone tags should not require a newline to follow them. + => SUCCESS +[10] Standalone Indentation + Each line of the partial should be indented before rendering. + => SUCCESS +[11] Padding Whitespace + Superfluous in-tag whitespace should be ignored. + => SUCCESS + +loading test-specs/spec/specs/sections.json +processing file test-specs/spec/specs/sections.json +[0] Truthy + Truthy sections should have their contents rendered. + => SUCCESS +[1] Falsey + Falsey sections should have their contents omitted. + => SUCCESS +[2] Null is falsey + Null is falsey. + => SUCCESS +[3] Context + Objects and hashes should be pushed onto the context stack. + => SUCCESS +[4] Parent contexts + Names missing in the current context are looked up in the stack. + => SUCCESS +[5] Variable test + Non-false sections have their value at the top of context, +accessible as {{.}} or through the parent context. This gives +a simple way to display content conditionally if a variable exists. + + => SUCCESS +[6] List Contexts + All elements on the context stack should be accessible within lists. + => SUCCESS +[7] Deeply Nested Contexts + All elements on the context stack should be accessible. + => SUCCESS +[8] List + Lists should be iterated; list items should visit the context stack. + => SUCCESS +[9] Empty List + Empty lists should behave like falsey values. + => SUCCESS +[10] Doubled + Multiple sections per template should be permitted. + => SUCCESS +[11] Nested (Truthy) + Nested truthy sections should have their contents rendered. + => SUCCESS +[12] Nested (Falsey) + Nested falsey sections should be omitted. + => SUCCESS +[13] Context Misses + Failed context lookups should be considered falsey. + => SUCCESS +[14] Implicit Iterator - String + Implicit iterators should directly interpolate strings. + => SUCCESS +[15] Implicit Iterator - Integer + Implicit iterators should cast integers to strings and interpolate. + => SUCCESS +[16] Implicit Iterator - Decimal + Implicit iterators should cast decimals to strings and interpolate. + => SUCCESS +[17] Implicit Iterator - Array + Implicit iterators should allow iterating over nested arrays. + => SUCCESS +[18] Implicit Iterator - HTML Escaping + Implicit iterators with basic interpolation should be HTML escaped. + => SUCCESS +[19] Implicit Iterator - Triple mustache + Implicit iterators in triple mustache should interpolate without HTML escaping. + => SUCCESS +[20] Implicit Iterator - Ampersand + Implicit iterators in an Ampersand tag should interpolate without HTML escaping. + => SUCCESS +[21] Implicit Iterator - Root-level + Implicit iterators should work on root-level lists. + => SUCCESS +[22] Dotted Names - Truthy + Dotted names should be valid for Section tags. + => SUCCESS +[23] Dotted Names - Falsey + Dotted names should be valid for Section tags. + => SUCCESS +[24] Dotted Names - Broken Chains + Dotted names that cannot be resolved should be considered falsey. + => SUCCESS +[25] Surrounding Whitespace + Sections should not alter surrounding whitespace. + => SUCCESS +[26] Internal Whitespace + Sections should not alter internal whitespace. + => SUCCESS +[27] Indented Inline Sections + Single-line sections should not alter surrounding whitespace. + => SUCCESS +[28] Standalone Lines + Standalone lines should be removed from the template. + => SUCCESS +[29] Indented Standalone Lines + Indented standalone lines should be removed from the template. + => SUCCESS +[30] Standalone Line Endings + "\r\n" should be considered a newline for standalone tags. + => SUCCESS +[31] Standalone Without Previous Line + Standalone tags should not require a newline to precede them. + => SUCCESS +[32] Standalone Without Newline + Standalone tags should not require a newline to follow them. + => SUCCESS +[33] Padding + Superfluous in-tag whitespace should be ignored. + => SUCCESS + +summary: + error 0 + differ 0 + success 133 diff --git a/src/templating/test-specs/test-specs.c b/src/templating/test-specs/test-specs.c new file mode 100644 index 000000000..15c94a80e --- /dev/null +++ b/src/templating/test-specs/test-specs.c @@ -0,0 +1,520 @@ +/* + Author: José Bollo + + https://gitlab.com/jobol/mustach + + SPDX-License-Identifier: ISC +*/ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "mustach-wrap.h" + +#define TEST_JSON_C 1 +#define TEST_JANSSON 2 +#define TEST_CJSON 3 + +static const char *errors[] = { + "??? unreferenced ???", + "system", + "unexpected end", + "empty tag", + "tag too long", + "bad separators", + "too depth", + "closing", + "bad unescape tag", + "invalid interface", + "item not found", + "partial not found" +}; + +const char *mustach_error_string(int status) +{ + return status >= 0 ? "no error" + : errors[status <= -(int)(sizeof errors / sizeof * errors) ? 0 : -status]; +} + +static const char *errmsg = 0; +static int flags = 0; +static FILE *output = 0; + +static void help(char *prog) +{ + char *name = basename(prog); +#define STR(x) #x + printf("%s version %s\n", name, STR(VERSION)); +#undef STR + printf("usage: %s test-files...\n", name); + exit(0); +} + +#if TEST == TEST_CJSON + +static const size_t BLOCKSIZE = 8192; + +static char *readfile(const char *filename, size_t *length) +{ + int f; + struct stat s; + char *result; + size_t size, pos; + ssize_t rc; + + result = NULL; + if (filename[0] == '-' && filename[1] == 0) + f = dup(0); + else + f = open(filename, O_RDONLY); + if (f < 0) { + fprintf(stderr, "Can't open file: %s\n", filename); + exit(1); + } + + fstat(f, &s); + switch (s.st_mode & S_IFMT) { + case S_IFREG: + size = s.st_size; + break; + case S_IFSOCK: + case S_IFIFO: + size = BLOCKSIZE; + break; + default: + fprintf(stderr, "Bad file: %s\n", filename); + exit(1); + } + + pos = 0; + result = malloc(size + 1); + do { + if (result == NULL) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + rc = read(f, &result[pos], (size - pos) + 1); + if (rc < 0) { + fprintf(stderr, "Error while reading %s\n", filename); + exit(1); + } + if (rc > 0) { + pos += (size_t)rc; + if (pos > size) { + size = pos + BLOCKSIZE; + result = realloc(result, size + 1); + } + } + } while(rc > 0); + + close(f); + if (length != NULL) + *length = pos; + result[pos] = 0; + return result; +} +#endif + +typedef struct { + unsigned nerror; + unsigned ndiffers; + unsigned nsuccess; + unsigned ninvalid; +} counters; + +static int load_json(const char *filename); +static int process(counters *c); +static void close_json(); +static int get_partial(const char *name, struct mustach_sbuf *sbuf); + +int main(int ac, char **av) +{ + char *f; + char *prog = *av; + int s; + counters c; + + (void)ac; /* unused */ + flags = Mustach_With_SingleDot | Mustach_With_IncPartial; + output = stdout; + mustach_wrap_get_partial = get_partial; + + memset(&c, 0, sizeof c); + while (*++av) { + if (!strcmp(*av, "-h") || !strcmp(*av, "--help")) + help(prog); + f = (av[0][0] == '-' && !av[0][1]) ? "/dev/stdin" : av[0]; + fprintf(output, "\nloading %s\n", f); + s = load_json(f); + if (s < 0) { + fprintf(stderr, "error when loading %s!\n", f); + if(errmsg) + fprintf(stderr, " reason: %s\n", errmsg); + exit(1); + } + fprintf(output, "processing file %s\n", f); + s = process(&c); + if (s < 0) { + fprintf(stderr, "error bad test file %s!\n", f); + exit(1); + } + close_json(); + } + fprintf(output, "\nsummary:\n"); + if (c.ninvalid) + fprintf(output, " invalid %u\n", c.ninvalid); + fprintf(output, " error %u\n", c.nerror); + fprintf(output, " differ %u\n", c.ndiffers); + fprintf(output, " success %u\n", c.nsuccess); + if (c.nerror) + return 2; + if (c.ndiffers) + return 1; + return 0; +} + +void emit(FILE *f, const char *s) +{ + for(;;s++) { + switch(*s) { + case 0: return; + case '\\': fprintf(f, "\\\\"); break; + case '\t': fprintf(f, "\\t"); break; + case '\n': fprintf(f, "\\n"); break; + case '\r': fprintf(f, "\\r"); break; + default: fprintf(f, "%c", *s); break; + } + } +} + +#if TEST == TEST_JSON_C + +#include "mustach-json-c.h" + +static struct json_object *o; + +static struct json_object *partials; +static int get_partial(const char *name, struct mustach_sbuf *sbuf) +{ + struct json_object *x; + if (partials == NULL || !json_object_object_get_ex(partials, name, &x)) + return MUSTACH_ERROR_PARTIAL_NOT_FOUND; + sbuf->value = json_object_get_string(x); + return MUSTACH_OK; +} + +static int load_json(const char *filename) +{ + o = json_object_from_file(filename); +#if JSON_C_VERSION_NUM >= 0x000D00 + errmsg = json_util_get_last_err(); + if (errmsg != NULL) + return -1; +#endif + if (o == NULL) { + errmsg = "null json"; + return -1; + } + return 0; +} +static int process(counters *c) +{ + const char *t, *e; + char *got; + unsigned i, n; + size_t length; + int s; + json_object *tests, *unit, *name, *desc, *data, *template, *expected; + + if (!json_object_object_get_ex(o, "tests", &tests) || json_object_get_type(tests) != json_type_array) + return -1; + + i = 0; + n = (unsigned)json_object_array_length(tests); + while (i < n) { + unit = json_object_array_get_idx(tests, i); + if (json_object_get_type(unit) != json_type_object + || !json_object_object_get_ex(unit, "name", &name) + || !json_object_object_get_ex(unit, "desc", &desc) + || !json_object_object_get_ex(unit, "data", &data) + || !json_object_object_get_ex(unit, "template", &template) + || !json_object_object_get_ex(unit, "expected", &expected) + || json_object_get_type(name) != json_type_string + || json_object_get_type(desc) != json_type_string + || json_object_get_type(template) != json_type_string + || json_object_get_type(expected) != json_type_string) { + fprintf(stderr, "invalid test %u\n", i); + c->ninvalid++; + } + else { + fprintf(output, "[%u] %s\n", i, json_object_get_string(name)); + fprintf(output, "\t%s\n", json_object_get_string(desc)); + if (!json_object_object_get_ex(unit, "partials", &partials)) + partials = NULL; + t = json_object_get_string(template); + e = json_object_get_string(expected); + s = mustach_json_c_mem(t, 0, data, flags, &got, &length); + if (s == 0 && strcmp(got, e) == 0) { + fprintf(output, "\t=> SUCCESS\n"); + c->nsuccess++; + } + else { + if (s < 0) { + fprintf(output, "\t=> ERROR %s\n", mustach_error_string(s)); + c->nerror++; + } + else { + fprintf(output, "\t=> DIFFERS\n"); + c->ndiffers++; + } + if (partials) + fprintf(output, "\t.. PARTIALS[%s]\n", json_object_to_json_string_ext(partials, 0)); + fprintf(output, "\t.. DATA[%s]\n", json_object_to_json_string_ext(data, 0)); + fprintf(output, "\t.. TEMPLATE["); + emit(output, t); + fprintf(output, "]\n"); + fprintf(output, "\t.. EXPECTED["); + emit(output, e); + fprintf(output, "]\n"); + if (s == 0) { + fprintf(output, "\t.. GOT["); + emit(output, got); + fprintf(output, "]\n"); + } + } + free(got); + } + i++; + } + return 0; +} +static void close_json() +{ + json_object_put(o); +} + +#elif TEST == TEST_JANSSON + +#include "mustach-jansson.h" + +static json_t *o; +static json_error_t e; + +static json_t *partials; +static int get_partial(const char *name, struct mustach_sbuf *sbuf) +{ + json_t *x; + if (partials == NULL || !(x = json_object_get(partials, name))) + return MUSTACH_ERROR_PARTIAL_NOT_FOUND; + sbuf->value = json_string_value(x); + return MUSTACH_OK; +} + +static int load_json(const char *filename) +{ + o = json_load_file(filename, JSON_DECODE_ANY, &e); + if (o == NULL) { + errmsg = e.text; + return -1; + } + return 0; +} +static int process(counters *c) +{ + const char *t, *e; + char *got, *tmp; + int i, n; + size_t length; + int s; + json_t *tests, *unit, *name, *desc, *data, *template, *expected; + + tests = json_object_get(o, "tests"); + if (!tests || json_typeof(tests) != JSON_ARRAY) + return -1; + + i = 0; + n = json_array_size(tests); + while (i < n) { + unit = json_array_get(tests, i); + if (!unit || json_typeof(unit) != JSON_OBJECT + || !(name = json_object_get(unit, "name")) + || !(desc = json_object_get(unit, "desc")) + || !(data = json_object_get(unit, "data")) + || !(template = json_object_get(unit, "template")) + || !(expected = json_object_get(unit, "expected")) + || json_typeof(name) != JSON_STRING + || json_typeof(desc) != JSON_STRING + || json_typeof(template) != JSON_STRING + || json_typeof(expected) != JSON_STRING) { + fprintf(stderr, "invalid test %u\n", i); + c->ninvalid++; + } + else { + fprintf(output, "[%u] %s\n", i, json_string_value(name)); + fprintf(output, "\t%s\n", json_string_value(desc)); + partials = json_object_get(unit, "partials"); + t = json_string_value(template); + e = json_string_value(expected); + s = mustach_jansson_mem(t, 0, data, flags, &got, &length); + if (s == 0 && strcmp(got, e) == 0) { + fprintf(output, "\t=> SUCCESS\n"); + c->nsuccess++; + } + else { + if (s < 0) { + fprintf(output, "\t=> ERROR %s\n", mustach_error_string(s)); + c->nerror++; + } + else { + fprintf(output, "\t=> DIFFERS\n"); + c->ndiffers++; + } + if (partials) { + tmp = json_dumps(partials, JSON_ENCODE_ANY | JSON_COMPACT); + fprintf(output, "\t.. PARTIALS[%s]\n", tmp); + free(tmp); + } + tmp = json_dumps(data, JSON_ENCODE_ANY | JSON_COMPACT); + fprintf(output, "\t.. DATA[%s]\n", tmp); + free(tmp); + fprintf(output, "\t.. TEMPLATE["); + emit(output, t); + fprintf(output, "]\n"); + fprintf(output, "\t.. EXPECTED["); + emit(output, e); + fprintf(output, "]\n"); + if (s == 0) { + fprintf(output, "\t.. GOT["); + emit(output, got); + fprintf(output, "]\n"); + } + } + free(got); + } + i++; + } + return 0; +} +static void close_json() +{ + json_decref(o); +} + +#elif TEST == TEST_CJSON + +#include "mustach-cjson.h" + +static cJSON *o; +static cJSON *partials; +static int get_partial(const char *name, struct mustach_sbuf *sbuf) +{ + cJSON *x; + if (partials == NULL || !(x = cJSON_GetObjectItemCaseSensitive(partials, name))) + return MUSTACH_ERROR_PARTIAL_NOT_FOUND; + sbuf->value = x->valuestring; + return MUSTACH_OK; +} + +static int load_json(const char *filename) +{ + char *t; + size_t length; + + t = readfile(filename, &length); + o = t ? cJSON_ParseWithLength(t, length) : NULL; + free(t); + return -!o; +} +static int process(counters *c) +{ + const char *t, *e; + char *got, *tmp; + int i, n; + size_t length; + int s; + cJSON *tests, *unit, *name, *desc, *data, *template, *expected; + + tests = cJSON_GetObjectItemCaseSensitive(o, "tests"); + if (!tests || tests->type != cJSON_Array) + return -1; + + i = 0; + n = cJSON_GetArraySize(tests); + while (i < n) { + unit = cJSON_GetArrayItem(tests, i); + if (!unit || unit->type != cJSON_Object + || !(name = cJSON_GetObjectItemCaseSensitive(unit, "name")) + || !(desc = cJSON_GetObjectItemCaseSensitive(unit, "desc")) + || !(data = cJSON_GetObjectItemCaseSensitive(unit, "data")) + || !(template = cJSON_GetObjectItemCaseSensitive(unit, "template")) + || !(expected = cJSON_GetObjectItemCaseSensitive(unit, "expected")) + || name->type != cJSON_String + || desc->type != cJSON_String + || template->type != cJSON_String + || expected->type != cJSON_String) { + fprintf(stderr, "invalid test %u\n", i); + c->ninvalid++; + } + else { + fprintf(output, "[%u] %s\n", i, name->valuestring); + fprintf(output, "\t%s\n", desc->valuestring); + partials = cJSON_GetObjectItemCaseSensitive(unit, "partials"); + t = template->valuestring; + e = expected->valuestring; + s = mustach_cJSON_mem(t, 0, data, flags, &got, &length); + if (s == 0 && strcmp(got, e) == 0) { + fprintf(output, "\t=> SUCCESS\n"); + c->nsuccess++; + } + else { + if (s < 0) { + fprintf(output, "\t=> ERROR %s\n", mustach_error_string(s)); + c->nerror++; + } + else { + fprintf(output, "\t=> DIFFERS\n"); + c->ndiffers++; + } + if (partials) { + tmp = cJSON_PrintUnformatted(partials); + fprintf(output, "\t.. PARTIALS[%s]\n", tmp); + free(tmp); + } + tmp = cJSON_PrintUnformatted(data); + fprintf(output, "\t.. DATA[%s]\n", tmp); + free(tmp); + fprintf(output, "\t.. TEMPLATE["); + emit(output, t); + fprintf(output, "]\n"); + fprintf(output, "\t.. EXPECTED["); + emit(output, e); + fprintf(output, "]\n"); + if (s == 0) { + fprintf(output, "\t.. GOT["); + emit(output, got); + fprintf(output, "]\n"); + } + } + free(got); + } + i++; + } + return 0; +} +static void close_json() +{ + cJSON_Delete(o); +} + +#else +#error "no defined json library" +#endif diff --git a/src/templating/test1/Makefile b/src/templating/test1/Makefile index bb96b3502..1a3e57914 100644 --- a/src/templating/test1/Makefile +++ b/src/templating/test1/Makefile @@ -1,12 +1,7 @@ .PHONY: test clean test: - @echo starting test - @../mustach json must > resu.last 2> vg.last - @sed -i 's:^==[0-9]*== ::' vg.last - @diff -w resu.ref resu.last && echo "result ok" || echo "ERROR! Result differs" - @awk '/^ *total heap usage: .* allocs, .* frees,.*/{if($$4-$$6)exit(1)}' vg.last || echo "ERROR! Alloc/Free issue" - @echo + @../dotest.sh json must clean: rm -f resu.last vg.last diff --git a/src/templating/test1/must b/src/templating/test1/must index 6df523669..92d30b0b2 100644 --- a/src/templating/test1/must +++ b/src/templating/test1/must @@ -41,3 +41,9 @@ end {{:\=equal}} {{::colon}} {{:>greater}} + +{{#repo}} +who 0 {{who.0}} +who 1 {{who.1}} +who 2 {{who.2}} +{{/repo}} diff --git a/src/templating/test1/resu.ref b/src/templating/test1/resu.ref new file mode 100644 index 000000000..6cd11bb27 --- /dev/null +++ b/src/templating/test1/resu.ref @@ -0,0 +1,41 @@ +Hello Chris +You have just won 10000 dollars! +Well, 6000 dollars, after taxes. +Shown. + No person + + resque reviewers: avrel commiters: joe william + hub reviewers: avrel commiters: jack greg + rip reviewers: joe jack commiters: greg + + Hi Jon! + +===================================== + resque reviewers: avrel commiters: joe william + hub reviewers: avrel commiters: jack greg + rip reviewers: joe jack commiters: greg +===================================== +ggggggggg +----3.14159---- +jjjjjjjjj +end + +# +! +~ +~ +/ see json pointers IETF RFC 6901 +^ += +: +> + +who 0 {"commiter":"joe"} +who 1 {"reviewer":"avrel"} +who 2 {"commiter":"william"} +who 0 {"commiter":"jack"} +who 1 {"reviewer":"avrel"} +who 2 {"commiter":"greg"} +who 0 {"reviewer":"joe"} +who 1 {"reviewer":"jack"} +who 2 {"commiter":"greg"} diff --git a/src/templating/test1/vg.ref b/src/templating/test1/vg.ref new file mode 100644 index 000000000..d086e59c5 --- /dev/null +++ b/src/templating/test1/vg.ref @@ -0,0 +1,14 @@ +Memcheck, a memory error detector +Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. +Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info +Command: ../mustach json must + + +HEAP SUMMARY: + in use at exit: 0 bytes in 0 blocks + total heap usage: 111 allocs, 111 frees, 9,702 bytes allocated + +All heap blocks were freed -- no leaks are possible + +For lists of detected and suppressed errors, rerun with: -s +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) diff --git a/src/templating/test2/Makefile b/src/templating/test2/Makefile index bb96b3502..1a3e57914 100644 --- a/src/templating/test2/Makefile +++ b/src/templating/test2/Makefile @@ -1,12 +1,7 @@ .PHONY: test clean test: - @echo starting test - @../mustach json must > resu.last 2> vg.last - @sed -i 's:^==[0-9]*== ::' vg.last - @diff -w resu.ref resu.last && echo "result ok" || echo "ERROR! Result differs" - @awk '/^ *total heap usage: .* allocs, .* frees,.*/{if($$4-$$6)exit(1)}' vg.last || echo "ERROR! Alloc/Free issue" - @echo + @../dotest.sh json must clean: rm -f resu.last vg.last diff --git a/src/templating/test2/resu.ref b/src/templating/test2/resu.ref new file mode 100644 index 000000000..5a200a9bf --- /dev/null +++ b/src/templating/test2/resu.ref @@ -0,0 +1,7 @@ +

Colors

+ +
  • red
  • +
  • green
  • +
  • blue
  • + + diff --git a/src/templating/test2/vg.ref b/src/templating/test2/vg.ref new file mode 100644 index 000000000..e4b4f6d37 --- /dev/null +++ b/src/templating/test2/vg.ref @@ -0,0 +1,14 @@ +Memcheck, a memory error detector +Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. +Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info +Command: ../mustach json must + + +HEAP SUMMARY: + in use at exit: 0 bytes in 0 blocks + total heap usage: 38 allocs, 38 frees, 5,712 bytes allocated + +All heap blocks were freed -- no leaks are possible + +For lists of detected and suppressed errors, rerun with: -s +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) diff --git a/src/templating/test3/Makefile b/src/templating/test3/Makefile index bb96b3502..1a3e57914 100644 --- a/src/templating/test3/Makefile +++ b/src/templating/test3/Makefile @@ -1,12 +1,7 @@ .PHONY: test clean test: - @echo starting test - @../mustach json must > resu.last 2> vg.last - @sed -i 's:^==[0-9]*== ::' vg.last - @diff -w resu.ref resu.last && echo "result ok" || echo "ERROR! Result differs" - @awk '/^ *total heap usage: .* allocs, .* frees,.*/{if($$4-$$6)exit(1)}' vg.last || echo "ERROR! Alloc/Free issue" - @echo + @../dotest.sh json must clean: rm -f resu.last vg.last diff --git a/src/templating/test3/resu.ref b/src/templating/test3/resu.ref new file mode 100644 index 000000000..ee6dad3fb --- /dev/null +++ b/src/templating/test3/resu.ref @@ -0,0 +1,13 @@ +* Chris +* 18 +* <b>GitHub & Co</b> +* GitHub & Co +* GitHub & Co +* <b>GitHub & Co</b> +* GitHub & Co +* GitHub & Co + +*
    • Chris
    • Kross
    +* skills:
    • JavaScript
    • PHP
    • Java
    +* age: 18 + diff --git a/src/templating/test3/vg.ref b/src/templating/test3/vg.ref new file mode 100644 index 000000000..21f7931eb --- /dev/null +++ b/src/templating/test3/vg.ref @@ -0,0 +1,14 @@ +Memcheck, a memory error detector +Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. +Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info +Command: ../mustach json must + + +HEAP SUMMARY: + in use at exit: 0 bytes in 0 blocks + total heap usage: 30 allocs, 30 frees, 5,831 bytes allocated + +All heap blocks were freed -- no leaks are possible + +For lists of detected and suppressed errors, rerun with: -s +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) diff --git a/src/templating/test4/Makefile b/src/templating/test4/Makefile index bb96b3502..1a3e57914 100644 --- a/src/templating/test4/Makefile +++ b/src/templating/test4/Makefile @@ -1,12 +1,7 @@ .PHONY: test clean test: - @echo starting test - @../mustach json must > resu.last 2> vg.last - @sed -i 's:^==[0-9]*== ::' vg.last - @diff -w resu.ref resu.last && echo "result ok" || echo "ERROR! Result differs" - @awk '/^ *total heap usage: .* allocs, .* frees,.*/{if($$4-$$6)exit(1)}' vg.last || echo "ERROR! Alloc/Free issue" - @echo + @../dotest.sh json must clean: rm -f resu.last vg.last diff --git a/src/templating/test4/resu.ref b/src/templating/test4/resu.ref new file mode 100644 index 000000000..8a71c4e82 --- /dev/null +++ b/src/templating/test4/resu.ref @@ -0,0 +1,50 @@ +This are extensions!! + +Jon +25 + +Fred +The other Fred. + +Hello Jon + + +No Harry? Hey Calahan... + +Hello Fred + + +Hello Fred#2 + + +Hello Jon, 25 years + +Hello Henry, 27 years + + +Salut Amed, 24 ans + +Jon: /25/25 +Henry: /27/ +Amed: 24/24/24 + +Jon: /25/25 +Henry: /27/ +Amed: 24/24/24 + + (1) person: {"name":"Jon","age":25} + (2) name: Jon + (2) age: 25 + (1) person.name: Fred + (1) person.name=Fred: The other Fred. + (1) persons: [{"name":"Jon","age":25,"lang":"en"},{"name":"Henry","age":27,"lang":"en"},{"name":"Amed","age":24,"lang":"fr"}] + (1) fellows: {"Jon":{"age":25,"lang":"en"},"Henry":{"age":27,"lang":"en"},"Amed":{"age":24,"lang":"fr"}} + (2) Jon: {"age":25,"lang":"en"} + (3) age: 25 + (3) lang: en + (2) Henry: {"age":27,"lang":"en"} + (3) age: 27 + (3) lang: en + (2) Amed: {"age":24,"lang":"fr"} + (3) age: 24 + (3) lang: fr diff --git a/src/templating/test4/vg.ref b/src/templating/test4/vg.ref new file mode 100644 index 000000000..922b0676d --- /dev/null +++ b/src/templating/test4/vg.ref @@ -0,0 +1,14 @@ +Memcheck, a memory error detector +Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. +Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info +Command: ../mustach json must + + +HEAP SUMMARY: + in use at exit: 0 bytes in 0 blocks + total heap usage: 121 allocs, 121 frees, 14,608 bytes allocated + +All heap blocks were freed -- no leaks are possible + +For lists of detected and suppressed errors, rerun with: -s +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) diff --git a/src/templating/test5/Makefile b/src/templating/test5/Makefile index bb96b3502..1a3e57914 100644 --- a/src/templating/test5/Makefile +++ b/src/templating/test5/Makefile @@ -1,12 +1,7 @@ .PHONY: test clean test: - @echo starting test - @../mustach json must > resu.last 2> vg.last - @sed -i 's:^==[0-9]*== ::' vg.last - @diff -w resu.ref resu.last && echo "result ok" || echo "ERROR! Result differs" - @awk '/^ *total heap usage: .* allocs, .* frees,.*/{if($$4-$$6)exit(1)}' vg.last || echo "ERROR! Alloc/Free issue" - @echo + @../dotest.sh json must clean: rm -f resu.last vg.last diff --git a/src/templating/test5/resu.ref b/src/templating/test5/resu.ref new file mode 100644 index 000000000..f2a608568 --- /dev/null +++ b/src/templating/test5/resu.ref @@ -0,0 +1,38 @@ +===================================== +from json +----3.14159---- +===================================== +not found +===================================== +without extension first +must2 == BEGIN +Hello Chris +You have just won 10000 dollars! +Well, 6000 dollars, after taxes. +Shown. + No person +must2 == END +===================================== +last with extension +must3.mustache == BEGIN + resque reviewers: avrel commiters: joe william + hub reviewers: avrel commiters: jack greg + rip reviewers: joe jack commiters: greg + + Hi Jon! + +===================================== + resque reviewers: avrel commiters: joe william + hub reviewers: avrel commiters: jack greg + rip reviewers: joe jack commiters: greg +===================================== +must3.mustache == END +===================================== +Ensure must3 didn't change specials + + Hi Jon! + +%(%#person?%)% + Hi %(%name%)%! +%(%/person?%)% + diff --git a/src/templating/test5/vg.ref b/src/templating/test5/vg.ref new file mode 100644 index 000000000..89dc21bcb --- /dev/null +++ b/src/templating/test5/vg.ref @@ -0,0 +1,14 @@ +Memcheck, a memory error detector +Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. +Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info +Command: ../mustach json must + + +HEAP SUMMARY: + in use at exit: 0 bytes in 0 blocks + total heap usage: 123 allocs, 123 frees, 20,610 bytes allocated + +All heap blocks were freed -- no leaks are possible + +For lists of detected and suppressed errors, rerun with: -s +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) diff --git a/src/templating/test6/Makefile b/src/templating/test6/Makefile index 6178902c0..ea4f86e79 100644 --- a/src/templating/test6/Makefile +++ b/src/templating/test6/Makefile @@ -5,12 +5,7 @@ test-custom-write: test-custom-write.c ../mustach-json-c.h ../mustach-json-c.c . $(CC) $(CFLAGS) $(LDFLAGS) -g -o test-custom-write test-custom-write.c ../mustach.c ../mustach-json-c.c ../mustach-wrap.c -ljson-c test: test-custom-write - @echo starting test - @./test-custom-write json -U must -l must -x must > resu.last 2> vg.last - @sed -i 's:^==[0-9]*== ::' vg.last - @diff -w resu.ref resu.last && echo "result ok" || echo "ERROR! Result differs" - @awk '/^ *total heap usage: .* allocs, .* frees,.*/{if($$4-$$6)exit(1)}' vg.last || echo "ERROR! Alloc/Free issue" - @echo + @mustach=./test-custom-write ../dotest.sh json -U must -l must -x must clean: rm -f resu.last vg.last test-custom-write diff --git a/src/templating/test6/resu.ref b/src/templating/test6/resu.ref new file mode 100644 index 000000000..377eb11af --- /dev/null +++ b/src/templating/test6/resu.ref @@ -0,0 +1,93 @@ +HELLO CHRIS +YOU HAVE JUST WON 10000 DOLLARS! +WELL, 6000 DOLLARS, AFTER TAXES. +SHOWN. + NO PERSON + + RESQUE REVIEWERS: AVREL COMMITERS: JOE WILLIAM + HUB REVIEWERS: AVREL COMMITERS: JACK GREG + RIP REVIEWERS: JOE JACK COMMITERS: GREG + + HI JON! + +===================================== + RESQUE REVIEWERS: AVREL COMMITERS: JOE WILLIAM + HUB REVIEWERS: AVREL COMMITERS: JACK GREG + RIP REVIEWERS: JOE JACK COMMITERS: GREG +===================================== +GGGGGGGGG +----3.14159---- +JJJJJJJJJ +END + +# +! +~ +~ +/ SEE JSON POINTERS IETF RFC 6901 +^ += +: +> +hello chris +you have just won 10000 dollars! +well, 6000 dollars, after taxes. +shown. + no person + + resque reviewers: avrel commiters: joe william + hub reviewers: avrel commiters: jack greg + rip reviewers: joe jack commiters: greg + + hi jon! + +===================================== + resque reviewers: avrel commiters: joe william + hub reviewers: avrel commiters: jack greg + rip reviewers: joe jack commiters: greg +===================================== +ggggggggg +----3.14159---- +jjjjjjjjj +end + +# +! +~ +~ +/ see json pointers ietf rfc 6901 +^ += +: +> +Hello Chris +You have just won 10000 dollars! +Well, 6000 dollars, after taxes. +Shown. + No person + + resque reviewers: avrel commiters: joe william + hub reviewers: avrel commiters: jack greg + rip reviewers: joe jack commiters: greg + + Hi Jon! + +===================================== + resque reviewers: avrel commiters: joe william + hub reviewers: avrel commiters: jack greg + rip reviewers: joe jack commiters: greg +===================================== +ggggggggg +----3.14159---- +jjjjjjjjj +end + +# +! +~ +~ +/ see json pointers IETF RFC 6901 +^ += +: +> diff --git a/src/templating/test6/test-custom-write.c b/src/templating/test6/test-custom-write.c index 4ba953a85..20042c1ed 100644 --- a/src/templating/test6/test-custom-write.c +++ b/src/templating/test6/test-custom-write.c @@ -16,7 +16,9 @@ limitations under the License. */ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include #include diff --git a/src/templating/test6/vg.ref b/src/templating/test6/vg.ref new file mode 100644 index 000000000..fb0e31bd8 --- /dev/null +++ b/src/templating/test6/vg.ref @@ -0,0 +1,14 @@ +Memcheck, a memory error detector +Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. +Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info +Command: ./test-custom-write json -U must -l must -x must + + +HEAP SUMMARY: + in use at exit: 0 bytes in 0 blocks + total heap usage: 174 allocs, 174 frees, 24,250 bytes allocated + +All heap blocks were freed -- no leaks are possible + +For lists of detected and suppressed errors, rerun with: -s +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) diff --git a/src/templating/test7/base.mustache b/src/templating/test7/base.mustache new file mode 100644 index 000000000..f701e0c65 --- /dev/null +++ b/src/templating/test7/base.mustache @@ -0,0 +1,2 @@ +family: +{{> node}} diff --git a/src/templating/test7/json b/src/templating/test7/json new file mode 100644 index 000000000..c9ee47150 --- /dev/null +++ b/src/templating/test7/json @@ -0,0 +1,8 @@ +{ "data": "grandparent", "children": [ + { "data": "parent", "children": [ + { "data": "child", "children": [] } + ]}, + { "data": "parent2", "children": [ + { "data": "child2", "children": [ { "data": "pet", "children": false } ]} + ]} +]} diff --git a/src/templating/test7/node.mustache b/src/templating/test7/node.mustache new file mode 100644 index 000000000..4154b12ba --- /dev/null +++ b/src/templating/test7/node.mustache @@ -0,0 +1,4 @@ +<{{data}}> +{{#children}} + {{> node}} +{{/children}} diff --git a/src/templating/test7/resu.ref b/src/templating/test7/resu.ref new file mode 100644 index 000000000..d02b24e11 --- /dev/null +++ b/src/templating/test7/resu.ref @@ -0,0 +1,7 @@ +family: + + + + + + diff --git a/src/templating/test7/vg.ref b/src/templating/test7/vg.ref new file mode 100644 index 000000000..032e6c447 --- /dev/null +++ b/src/templating/test7/vg.ref @@ -0,0 +1,14 @@ +Memcheck, a memory error detector +Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. +Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info +Command: ../mustach json base.mustache + + +HEAP SUMMARY: + in use at exit: 0 bytes in 0 blocks + total heap usage: 69 allocs, 69 frees, 36,313 bytes allocated + +All heap blocks were freed -- no leaks are possible + +For lists of detected and suppressed errors, rerun with: -s +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) diff --git a/src/templating/test8/.gitignore b/src/templating/test8/.gitignore new file mode 100644 index 000000000..4d897daa0 --- /dev/null +++ b/src/templating/test8/.gitignore @@ -0,0 +1,2 @@ +resu.last +vg.last diff --git a/src/templating/test8/json b/src/templating/test8/json new file mode 100644 index 000000000..04a1e4aaa --- /dev/null +++ b/src/templating/test8/json @@ -0,0 +1,8 @@ +{ +"val1": "", +"val2": 0, +"val3": false, +"val4": null, +"val5": [], +"val6": 0.0 +} diff --git a/src/templating/test8/must b/src/templating/test8/must new file mode 100644 index 000000000..a22374438 --- /dev/null +++ b/src/templating/test8/must @@ -0,0 +1,6 @@ +x{{#val1}} {{.}} {{/val1}}x +x{{#val2}} {{.}} {{/val2}}x +x{{#val3}} {{.}} {{/val3}}x +x{{#val4}} {{.}} {{/val4}}x +x{{#val5}} {{.}} {{/val5}}x +x{{#val6}} {{.}} {{/val6}}x diff --git a/src/templating/test8/resu.ref b/src/templating/test8/resu.ref new file mode 100644 index 000000000..e0c16e49a --- /dev/null +++ b/src/templating/test8/resu.ref @@ -0,0 +1,6 @@ +xx +xx +xx +xx +xx +xx diff --git a/src/templating/test8/vg.ref b/src/templating/test8/vg.ref new file mode 100644 index 000000000..b5b0235f9 --- /dev/null +++ b/src/templating/test8/vg.ref @@ -0,0 +1,14 @@ +Memcheck, a memory error detector +Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. +Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info +Command: ../mustach json must + + +HEAP SUMMARY: + in use at exit: 0 bytes in 0 blocks + total heap usage: 17 allocs, 17 frees, 4,832 bytes allocated + +All heap blocks were freed -- no leaks are possible + +For lists of detected and suppressed errors, rerun with: -s +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) -- cgit v1.2.3