aboutsummaryrefslogtreecommitdiff
path: root/src/tests/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/parser.c')
-rw-r--r--src/tests/parser.c335
1 files changed, 223 insertions, 112 deletions
diff --git a/src/tests/parser.c b/src/tests/parser.c
index eb5c2a1..c8bdcc0 100644
--- a/src/tests/parser.c
+++ b/src/tests/parser.c
@@ -18,20 +18,20 @@ struct value {
union {
struct slice ident;
struct slice string;
- int64_t integer;
- bool boolean;
+ int64_t integer;
+ bool boolean;
};
enum value_type type;
};
static void
check_parser_errors(struct parser *parser, const char *file, int line,
- const char *func)
+ const char *func)
{
if (parser->errors->len > 0) {
printf("\n");
size_t i;
- sds val;
+ sds val;
vector_foreach (parser->errors, i, val) {
printf("parser error %lu: %s\n", i, val);
}
@@ -48,7 +48,7 @@ check_parser_errors(struct parser *parser, const char *file, int line,
static void
test_integer_literal(struct expression *expr, int64_t val)
{
- char buf[128];
+ char buf[128];
struct slice sval;
asserteq(expr->type, EXPRESSION_INT);
asserteq(expr->integer.value, val);
@@ -67,7 +67,7 @@ test_identifier(struct expression *expr, struct slice *ident)
static void
test_boolean_literal(struct expression *expr, bool val)
{
- char *str = val ? "true" : "false";
+ char *str = val ? "true" : "false";
struct slice sval = slice_whole(str);
asserteq(expr->type, EXPRESSION_BOOL);
asserteq(expr->boolean.value, val);
@@ -81,41 +81,52 @@ test_string_literal(struct expression *expr, const struct slice *val)
asserteq(slice_cmp(&expr->string.value, val), 0);
}
-
static inline void
test_expected(struct expression *expr, struct value v)
{
- switch(v.type) {
- case VALUE_IDENT:
- test_identifier(expr, &v.ident);
- break;
- case VALUE_INT:
- test_integer_literal(expr, v.integer);
- break;
- case VALUE_BOOL:
- test_boolean_literal(expr, v.boolean);
- break;
- case VALUE_STRING:
- test_string_literal(expr, &v.string);
- break;
+ switch (v.type) {
+ case VALUE_IDENT:
+ test_identifier(expr, &v.ident);
+ break;
+ case VALUE_INT:
+ test_integer_literal(expr, v.integer);
+ break;
+ case VALUE_BOOL:
+ test_boolean_literal(expr, v.boolean);
+ break;
+ case VALUE_STRING:
+ test_string_literal(expr, &v.string);
+ break;
}
}
-#define VIDENT(v) \
- (struct value){ .type = VALUE_IDENT, .ident = slice_whole(v) }
+#define VIDENT(v) \
+ (struct value) \
+ { \
+ .type = VALUE_IDENT, .ident = slice_whole(v) \
+ }
-#define VINT(v) \
- (struct value){ .type = VALUE_INT, .integer = v }
+#define VINT(v) \
+ (struct value) \
+ { \
+ .type = VALUE_INT, .integer = v \
+ }
-#define VBOOL(v) \
- (struct value){ .type = VALUE_BOOL, .boolean = v }
+#define VBOOL(v) \
+ (struct value) \
+ { \
+ .type = VALUE_BOOL, .boolean = v \
+ }
-#define VSTR(v) \
- (struct value){ .type = VALUE_STRING, .string = slice_whole(v) }
+#define VSTR(v) \
+ (struct value) \
+ { \
+ .type = VALUE_STRING, .string = slice_whole(v) \
+ }
static inline void
test_infix(struct infix *expr, struct value lval, struct slice *op,
- struct value rval)
+ struct value rval)
{
test_expected(expr->left, lval);
asserteq(slice_cmp(&expr->operator, op), 0);
@@ -126,18 +137,30 @@ static inline void
test_literal_variables(void)
{
struct {
- char *input;
+ char *input;
struct value val;
} tests[] = {
- { "{{ foo }}", VIDENT("foo"), },
- { "{{ 20 }}", VINT(20), },
- { "{{ true }}", VBOOL(true), },
- { "{{ false }}", VBOOL(false), },
- { 0 },
+ {
+ "{{ foo }}",
+ VIDENT("foo"),
+ },
+ {
+ "{{ 20 }}",
+ VINT(20),
+ },
+ {
+ "{{ true }}",
+ VBOOL(true),
+ },
+ {
+ "{{ false }}",
+ VBOOL(false),
+ },
+ {0},
};
for (size_t i = 0; tests[i].input != NULL; i++) {
- struct parser *parser = parser_new(strdup("test"), tests[i].input);
- struct template *tmpl = parser_parse_template(parser);
+ struct parser *parser = parser_new(strdup("test"), tests[i].input);
+ struct template *tmpl = parser_parse_template(parser);
check_parser_errors(parser);
assertneq(tmpl, NULL);
asserteq(tmpl->blocks->len, 1);
@@ -153,21 +176,45 @@ static inline void
test_prefix_variables(void)
{
struct {
- char *input;
+ char *input;
struct slice operator;
struct value val;
} tests[] = {
- { "{{ !foo }}", slice_whole("!"), VIDENT("foo"), },
- { "{{ -bar }}", slice_whole("-"), VIDENT("bar"), },
- { "{{ -20 }}", slice_whole("-"), VINT(20), },
- { "{{ !true }}", slice_whole("!"), VBOOL(true), },
- { "{{ !false }}", slice_whole("!"), VBOOL(false), },
- { "{{ not false }}", slice_whole("not"), VBOOL(false), },
- { 0 },
+ {
+ "{{ !foo }}",
+ slice_whole("!"),
+ VIDENT("foo"),
+ },
+ {
+ "{{ -bar }}",
+ slice_whole("-"),
+ VIDENT("bar"),
+ },
+ {
+ "{{ -20 }}",
+ slice_whole("-"),
+ VINT(20),
+ },
+ {
+ "{{ !true }}",
+ slice_whole("!"),
+ VBOOL(true),
+ },
+ {
+ "{{ !false }}",
+ slice_whole("!"),
+ VBOOL(false),
+ },
+ {
+ "{{ not false }}",
+ slice_whole("not"),
+ VBOOL(false),
+ },
+ {0},
};
for (size_t i = 0; tests[i].input != NULL; i++) {
- struct parser *parser = parser_new(strdup("test"), tests[i].input);
- struct template *tmpl = parser_parse_template(parser);
+ struct parser *parser = parser_new(strdup("test"), tests[i].input);
+ struct template *tmpl = parser_parse_template(parser);
check_parser_errors(parser);
assertneq(tmpl, NULL);
asserteq(tmpl->blocks->len, 1);
@@ -175,7 +222,7 @@ test_prefix_variables(void)
asserteq(blk->type, BLOCK_VARIABLE);
asserteq(blk->variable.expression->type, EXPRESSION_PREFIX);
struct expression *pref = blk->variable.expression;
- asserteq(slice_cmp(&pref->prefix.operator, &tests[i].operator), 0);
+ asserteq(slice_cmp(&pref->prefix.operator, & tests[i].operator), 0);
test_expected(pref->prefix.right, tests[i].val);
parser_destroy(parser);
template_destroy(tmpl);
@@ -186,28 +233,88 @@ static inline void
test_infix_variables(void)
{
struct {
- char *input;
+ char *input;
struct value left;
struct slice operator;
struct value right;
} tests[] = {
- { "{{ foo + bar }}", VIDENT("foo"), slice_whole("+"), VIDENT("bar"), },
- { "{{ 6 - 9 }}", VINT(6),slice_whole("-"), VINT(9), },
- { "{{ 4 * 20 }}", VINT(4), slice_whole("*"), VINT(20), },
- { "{{ foo / 20 }}", VIDENT("foo"), slice_whole("/"), VINT(20), },
- { "{{ \"str\" == \"str\" }}", VSTR("str"), slice_whole("=="), VSTR("str"), },
- { "{{ true != false }}", VBOOL(true), slice_whole("!="), VBOOL(false), },
- { "{{ 4 < 20 }}", VINT(4), slice_whole("<"), VINT(20), },
- { "{{ 4 <= 20 }}", VINT(4), slice_whole("<="), VINT(20), },
- { "{{ 100 > 20 }}", VINT(100), slice_whole(">"), VINT(20), },
- { "{{ 100 >= 20 }}", VINT(100), slice_whole(">="), VINT(20), },
- { "{{ true and true }}", VBOOL(true), slice_whole("and"), VBOOL(true), },
- { "{{ true or false }}", VBOOL(true), slice_whole("or"), VBOOL(false), },
- { 0 },
+ {
+ "{{ foo + bar }}",
+ VIDENT("foo"),
+ slice_whole("+"),
+ VIDENT("bar"),
+ },
+ {
+ "{{ 6 - 9 }}",
+ VINT(6),
+ slice_whole("-"),
+ VINT(9),
+ },
+ {
+ "{{ 4 * 20 }}",
+ VINT(4),
+ slice_whole("*"),
+ VINT(20),
+ },
+ {
+ "{{ foo / 20 }}",
+ VIDENT("foo"),
+ slice_whole("/"),
+ VINT(20),
+ },
+ {
+ "{{ \"str\" == \"str\" }}",
+ VSTR("str"),
+ slice_whole("=="),
+ VSTR("str"),
+ },
+ {
+ "{{ true != false }}",
+ VBOOL(true),
+ slice_whole("!="),
+ VBOOL(false),
+ },
+ {
+ "{{ 4 < 20 }}",
+ VINT(4),
+ slice_whole("<"),
+ VINT(20),
+ },
+ {
+ "{{ 4 <= 20 }}",
+ VINT(4),
+ slice_whole("<="),
+ VINT(20),
+ },
+ {
+ "{{ 100 > 20 }}",
+ VINT(100),
+ slice_whole(">"),
+ VINT(20),
+ },
+ {
+ "{{ 100 >= 20 }}",
+ VINT(100),
+ slice_whole(">="),
+ VINT(20),
+ },
+ {
+ "{{ true and true }}",
+ VBOOL(true),
+ slice_whole("and"),
+ VBOOL(true),
+ },
+ {
+ "{{ true or false }}",
+ VBOOL(true),
+ slice_whole("or"),
+ VBOOL(false),
+ },
+ {0},
};
for (size_t i = 0; tests[i].input != NULL; i++) {
- struct parser *parser = parser_new(strdup("test"), tests[i].input);
- struct template *tmpl = parser_parse_template(parser);
+ struct parser *parser = parser_new(strdup("test"), tests[i].input);
+ struct template *tmpl = parser_parse_template(parser);
check_parser_errors(parser);
assertneq(tmpl, NULL);
asserteq(tmpl->blocks->len, 1);
@@ -215,7 +322,7 @@ test_infix_variables(void)
asserteq(blk->type, BLOCK_VARIABLE);
asserteq(blk->variable.expression->type, EXPRESSION_INFIX);
test_infix(&blk->variable.expression->infix,
- tests[i].left, &tests[i].operator, tests[i].right);
+ tests[i].left, &tests[i].operator, tests[i].right);
parser_destroy(parser);
template_destroy(tmpl);
}
@@ -224,11 +331,11 @@ test_infix_variables(void)
static inline void
test_map_variables(void)
{
- char *input = "{{ map.key }}";
- struct value left = VIDENT("map");
- struct value key = VIDENT("key");
- struct parser *parser = parser_new(strdup("test"), input);
- struct template *tmpl = parser_parse_template(parser);
+ char *input = "{{ map.key }}";
+ struct value left = VIDENT("map");
+ struct value key = VIDENT("key");
+ struct parser *parser = parser_new(strdup("test"), input);
+ struct template *tmpl = parser_parse_template(parser);
check_parser_errors(parser);
assertneq(tmpl, NULL);
asserteq(tmpl->blocks->len, 1);
@@ -245,13 +352,13 @@ test_map_variables(void)
static inline void
test_index_variables(void)
{
- char *input = "{{ arr[1 + 2] }}";
- struct value left = VIDENT("arr");
- struct value ileft = VINT(1);
- struct slice iop = slice_whole("+");
- struct value iright = VINT(2);
- struct parser *parser = parser_new(strdup("test"), input);
- struct template *tmpl = parser_parse_template(parser);
+ char *input = "{{ arr[1 + 2] }}";
+ struct value left = VIDENT("arr");
+ struct value ileft = VINT(1);
+ struct slice iop = slice_whole("+");
+ struct value iright = VINT(2);
+ struct parser *parser = parser_new(strdup("test"), input);
+ struct template *tmpl = parser_parse_template(parser);
check_parser_errors(parser);
assertneq(tmpl, NULL);
@@ -350,11 +457,11 @@ test_operator_precedence(void)
"{{ foo.bar + bar[0].baz * foo.bar.baz }}",
"{{ (foo.bar + (bar[0].baz * foo.bar.baz)) }}",
},
- { 0 },
+ {0},
};
for (size_t i = 0; tests[i].input != NULL; i++) {
- struct parser *parser = parser_new(strdup("test"), tests[i].input);
- struct template *tmpl = parser_parse_template(parser);
+ struct parser *parser = parser_new(strdup("test"), tests[i].input);
+ struct template *tmpl = parser_parse_template(parser);
check_parser_errors(parser);
assertneq(tmpl, NULL);
asserteq(tmpl->blocks->len, 1);
@@ -371,17 +478,18 @@ test_operator_precedence(void)
static inline void
test_loop_tag(void)
{
- char *input = "{% for v in seq %}"
- "{% break %}"
- "{% endfor %}";
- struct slice item = slice_whole("v");
- struct slice seq = slice_whole("seq");
- struct parser *parser = parser_new(strdup("test"), input);
- struct template *tmpl = parser_parse_template(parser);
+ char *input = "{% for v in seq %}"
+ "{% break %}"
+ "{% endfor %}"
+ "{{ foo }}";
+ struct slice item = slice_whole("v");
+ struct slice seq = slice_whole("seq");
+ struct parser *parser = parser_new(strdup("test"), input);
+ struct template *tmpl = parser_parse_template(parser);
check_parser_errors(parser);
assertneq(tmpl, NULL);
- asserteq(tmpl->blocks->len, 1);
+ asserteq(tmpl->blocks->len, 2);
struct block *blk = tmpl->blocks->values[0];
asserteq(blk->type, BLOCK_TAG);
asserteq(blk->tag.type, TAG_FOR);
@@ -398,6 +506,9 @@ test_loop_tag(void)
asserteq(sub2->tag.type, TAG_CLOSE);
asserteq(sub2->tag.token.type, TOKEN_ENDFOR);
+ struct block *extra_blk = tmpl->blocks->values[1];
+ asserteq(extra_blk->type, BLOCK_VARIABLE);
+
parser_destroy(parser);
template_destroy(tmpl);
}
@@ -405,21 +516,21 @@ test_loop_tag(void)
static inline void
test_cond_tag(void)
{
- char *input = "{% if false %}"
- "{{ foo }}"
- "{% elif 1 > 2 %}"
- "{{ bar }}"
- "{% else %}"
- "baz"
- "{% endif %}";
- struct value ifexp = VIDENT("foo");
- struct value elifl = VINT(1);
- struct slice elifop = slice_whole(">");
- struct value elifr = VINT(2);
- struct value elifexp = VIDENT("bar");
- struct slice elsecont = slice_whole("baz");
- struct parser *parser = parser_new(strdup("test"), input);
- struct template *tmpl = parser_parse_template(parser);
+ char *input = "{% if false %}"
+ "{{ foo }}"
+ "{% elif 1 > 2 %}"
+ "{{ bar }}"
+ "{% else %}"
+ "baz"
+ "{% endif %}";
+ struct value ifexp = VIDENT("foo");
+ struct value elifl = VINT(1);
+ struct slice elifop = slice_whole(">");
+ struct value elifr = VINT(2);
+ struct value elifexp = VIDENT("bar");
+ struct slice elsecont = slice_whole("baz");
+ struct parser *parser = parser_new(strdup("test"), input);
+ struct template *tmpl = parser_parse_template(parser);
check_parser_errors(parser);
assertneq(tmpl, NULL);
@@ -462,10 +573,10 @@ test_cond_tag(void)
static inline void
test_parent_tag(void)
{
- char *input = "{% extends \"base.html\" %}";
- struct slice name = slice_whole("base.html");
- struct parser *parser = parser_new(strdup("test"), input);
- struct template *tmpl = parser_parse_template(parser);
+ char *input = "{% extends \"base.html\" %}";
+ struct slice name = slice_whole("base.html");
+ struct parser *parser = parser_new(strdup("test"), input);
+ struct template *tmpl = parser_parse_template(parser);
check_parser_errors(parser);
assertneq(tmpl, NULL);
@@ -482,11 +593,11 @@ test_parent_tag(void)
static inline void
test_tblock_tag(void)
{
- char *input = "{% block cock %}"
- "{% endblock %}";
- struct slice name = slice_whole("cock");
- struct parser *parser = parser_new(strdup("test"), input);
- struct template *tmpl = parser_parse_template(parser);
+ char *input = "{% block cock %}"
+ "{% endblock %}";
+ struct slice name = slice_whole("cock");
+ struct parser *parser = parser_new(strdup("test"), input);
+ struct template *tmpl = parser_parse_template(parser);
check_parser_errors(parser);
assertneq(tmpl, NULL);