aboutsummaryrefslogtreecommitdiff
path: root/src/tests/roscha.c
diff options
context:
space:
mode:
authorYaroslav de la Peña Smirnov <yps@yaroslavps.com>2022-03-24 01:04:02 +0300
committerYaroslav de la Peña Smirnov <yps@yaroslavps.com>2022-03-24 01:04:02 +0300
commit5d66c96a190a396a1535c89bed4e33c2a005fe8d (patch)
tree36a681d8cf226cf30f06b2764c008077d9655dc7 /src/tests/roscha.c
downloadroscha-5d66c96a190a396a1535c89bed4e33c2a005fe8d.tar.gz
roscha-5d66c96a190a396a1535c89bed4e33c2a005fe8d.zip
Initial commit
Basically it works, just needs some polishing and maybe a couple of features that I could actually use. Also probably better docs. Not sure if it will be of use to anybody besides me.
Diffstat (limited to 'src/tests/roscha.c')
-rw-r--r--src/tests/roscha.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/src/tests/roscha.c b/src/tests/roscha.c
new file mode 100644
index 0000000..92b8bc4
--- /dev/null
+++ b/src/tests/roscha.c
@@ -0,0 +1,189 @@
+#define _POSIX_C_SOURCE 200809L
+#include "tests/tests.h"
+#include "roscha.h"
+
+#include <string.h>
+
+static void
+check_env_errors(struct roscha_env *env, const char *file, int line,
+ const char *func)
+{
+ struct vector *errors = roscha_env_check_errors(env);
+ if (!errors) return;
+ printf("\n");
+ size_t i;
+ sds val;
+ vector_foreach (errors, i, val) {
+ printf("parser error %lu: %s\n", i, val);
+ }
+ printf(TBLD TRED "FAIL!\n" TRST);
+ printf("%s:%d: %s: ", file, line, func);
+ printf("parser encountered errors\n");
+ abort();
+}
+
+#define check_env_errors(p) \
+ check_env_errors(p, __FILE__, __LINE__, __func__)
+
+static void
+test_eval_variable(void)
+{
+ char *input = "{{ foo.bar }}"
+ "{{ foo.bar + foo.baz }}"
+ "{{ foo.bar - foo.baz }}"
+ "{{ foo.bar * foo.baz }}"
+ "{{ foo.bar / foo.baz }}"
+ "{{ l }}"
+ "{{ l[0] }}, {{ l[1] }}"
+ "";
+ char *expected = "8"
+ "12"
+ "4"
+ "32"
+ "2"
+ "[ hello, world, ]"
+ "hello, world"
+ "";
+ struct roscha_object *foo = roscha_object_new(hmap_new());
+ roscha_hmap_set_new(foo, "bar", 8);
+ roscha_hmap_set_new(foo, "baz", 4);
+ struct roscha_object *l = roscha_object_new(vector_new());
+ roscha_vector_push_new(l, (slice_whole("hello")));
+ roscha_vector_push_new(l, (slice_whole("world")));
+ struct roscha_env *env = roscha_env_new();
+ roscha_env_add_template(env, strdup("test"), input);
+ check_env_errors(env);
+ roscha_hmap_set(env->vars, "foo", foo);
+ roscha_hmap_set(env->vars, "l", l);
+
+ sds got = roscha_env_render(env, "test");
+ check_env_errors(env);
+ asserteq(strcmp(got, expected), 0);
+ roscha_env_destroy(env);
+ sdsfree(got);
+ roscha_object_unref(foo);
+ roscha_object_unref(l);
+}
+
+static void
+test_eval_cond(void)
+{
+ char *input = "{% if foo > bar %}"
+ "Yes"
+ "{% elif baz %}"
+ "Maybe"
+ "{% else %}"
+ "No"
+ "{% endif %}";
+ char *expected1 = "No";
+ char *expected2 = "Maybe";
+ char *expected3 = "Yes";
+ struct roscha_object *foo = roscha_object_new(10);
+ struct roscha_object *bar = roscha_object_new(20);
+ struct roscha_object *baz = roscha_object_new(69);
+
+ struct roscha_env *env = roscha_env_new();
+ roscha_env_add_template(env, strdup("test"), input);
+ check_env_errors(env);
+ roscha_hmap_set(env->vars, "foo", foo);
+ roscha_hmap_set(env->vars, "bar", bar);
+
+ sds got = roscha_env_render(env, "test");
+ check_env_errors(env);
+ asserteq(strcmp(got, expected1), 0);
+ sdsfree(got);
+
+ roscha_hmap_set(env->vars, "baz", baz);
+ got = roscha_env_render(env, "test");
+ check_env_errors(env);
+ asserteq(strcmp(got, expected2), 0);
+ sdsfree(got);
+
+ foo->integer = 420;
+ got = roscha_env_render(env, "test");
+ check_env_errors(env);
+ asserteq(strcmp(got, expected3), 0);
+ sdsfree(got);
+
+ roscha_env_destroy(env);
+ roscha_object_unref(foo);
+ roscha_object_unref(bar);
+ roscha_object_unref(baz);
+}
+
+static void
+test_eval_loop(void)
+{
+ char *input = "{% for v in foo %}"
+ "{{ loop.index }}"
+ "{{ v }}"
+ "{% endfor %}";
+ char *expected = "0hello1world";
+
+ struct roscha_object *foo = roscha_object_new(vector_new());
+ roscha_vector_push_new(foo, (slice_whole("hello")));
+ roscha_vector_push_new(foo, (slice_whole("world")));
+
+ struct roscha_env *env = roscha_env_new();
+ roscha_env_add_template(env, strdup("test"), input);
+ check_env_errors(env);
+ roscha_hmap_set(env->vars, "foo", foo);
+ sds got = roscha_env_render(env, "test");
+ check_env_errors(env);
+ asserteq(strcmp(got, expected), 0);
+
+ sdsfree(got);
+ roscha_env_destroy(env);
+ roscha_object_unref(foo);
+}
+
+static void
+test_eval_child(void)
+{
+ char *parent = "hello{% block title %}{% endblock %}"
+ "{% block content %}Content{% endblock %}"
+ "{% block foot %}Foot{% endblock %}";
+ char *child = "{% extends \"parent\" %}"
+ "{% block title %}, world{% endblock %}"
+ "{% block content %}"
+ "In a beautiful place out in the country."
+ "{% endblock %}";
+ char *expected = "hello, world"
+ "In a beautiful place out in the country."
+ "Foot";
+ struct roscha_env *env = roscha_env_new();
+ roscha_env_add_template(env, strdup("parent"), parent);
+ check_env_errors(env);
+ roscha_env_add_template(env, strdup("child"), child);
+ check_env_errors(env);
+ sds got = roscha_env_render(env, "child");
+ check_env_errors(env);
+ asserteq(strcmp(got, expected), 0);
+
+ sdsfree(got);
+ roscha_env_destroy(env);
+}
+
+static void
+init(void)
+{
+ roscha_init();
+}
+
+static void
+cleanup(void)
+{
+ roscha_deinit();
+}
+
+int
+main(void)
+{
+ init();
+ INIT_TESTS();
+ RUN_TEST(test_eval_variable);
+ RUN_TEST(test_eval_cond);
+ RUN_TEST(test_eval_loop);
+ RUN_TEST(test_eval_child);
+ cleanup();
+}