summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xrun_tests.sh69
-rw-r--r--tests/00_syntax/00_single_line_comments15
-rw-r--r--tests/00_syntax/01_unterminated_comment15
-rw-r--r--tests/00_syntax/02_multi_line_comments12
-rw-r--r--tests/00_syntax/03_expression_blocks11
-rw-r--r--tests/00_syntax/04_statement_blocks18
-rw-r--r--tests/00_syntax/05_block_nesting17
-rw-r--r--tests/00_syntax/06_open_statement_block13
-rw-r--r--tests/00_syntax/07_embedded_single_line_comments20
-rw-r--r--tests/00_syntax/08_embedded_multi_line_comments23
-rw-r--r--tests/00_syntax/09_string_literals25
-rw-r--r--tests/00_syntax/10_numeric_literals26
-rw-r--r--tests/00_syntax/11_misc_literals16
-rw-r--r--tests/00_syntax/12_block_whitespace_control46
14 files changed, 326 insertions, 0 deletions
diff --git a/run_tests.sh b/run_tests.sh
new file mode 100755
index 0000000..c5a36ad
--- /dev/null
+++ b/run_tests.sh
@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+
+line='........................................'
+
+extract_section() {
+ local file=$1
+ local tag=$2
+
+ sed -ne '/^-- '"$tag"' --$/ { :n; n; /^-- End --$/b; p; b n }' "$file"
+}
+
+run_test() {
+ local file=$1
+ local name=${file##*/}
+ local res
+
+ printf "%s %s " "$name" "${line:${#name}}"
+
+ extract_section "$file" "Expect stdout" >"/tmp/$$.expout"
+ extract_section "$file" "Expect stderr" >"/tmp/$$.experr"
+ extract_section "$file" "Testcase" >"/tmp/$$.in"
+
+ ./utpl -i "/tmp/$$.in" >"/tmp/$$.out" 2>"/tmp/$$.err"
+
+ local rc=$?
+
+ if ! cmp -s "/tmp/$$.err" "/tmp/$$.experr"; then
+ printf "FAILED:\n"
+ diff -u --color=always --label="Expected stderr" --label="Resulting stderr" "/tmp/$$.experr" "/tmp/$$.err"
+ printf -- "---\n"
+ res=1
+ elif ! cmp -s "/tmp/$$.out" "/tmp/$$.expout"; then
+ printf "FAILED:\n"
+ diff -u --color=always --label="Expected stdout" --label="Resulting stdout" "/tmp/$$.expout" "/tmp/$$.out"
+ printf -- "---\n"
+ res=1
+ #elif [ "$rc" != 0 ]; then
+ # local err="$(cat "/tmp/$$.err")"
+ # printf "FAILED:\n"
+ # printf "Terminated with exit code %d:\n%s\n---\n" $rc "${err:-(no error output)}"
+ # res=1
+ else
+ printf "OK\n"
+ res=0
+ fi
+
+ rm -f "/tmp/$$.in" "/tmp/$$.out" "/tmp/$$.err" "/tmp/$$.expout" "/tmp/$$.experr"
+
+ return $res
+}
+
+
+n_tests=0
+n_fails=0
+
+for catdir in tests/[0-9][0-9]_*; do
+ [ -d "$catdir" ] || continue
+
+ printf "\n##\n## Running %s tests\n##\n\n" "${catdir##*/[0-9][0-9]_}"
+
+ for testfile in "$catdir/"[0-9][0-9]_*; do
+ [ -f "$testfile" ] || continue
+
+ n_tests=$((n_tests + 1))
+ run_test "$testfile" || n_fails=$((n_fails + 1))
+ done
+done
+
+printf "\nRan %d tests, %d okay, %d failures\n" $n_tests $((n_tests - n_fails)) $n_fails
diff --git a/tests/00_syntax/00_single_line_comments b/tests/00_syntax/00_single_line_comments
new file mode 100644
index 0000000..24a32a2
--- /dev/null
+++ b/tests/00_syntax/00_single_line_comments
@@ -0,0 +1,15 @@
+Single line comments.
+
+-- Expect stdout --
+This is a test.
+ a test.
+A test .
+
+-- End --
+
+-- Testcase --
+This is {# a comment within #} a test.
+{# Comment before #} a test.
+A test {# and a comment after #}.
+{# This is a comment with embedded "{#" tag. #}
+-- End --
diff --git a/tests/00_syntax/01_unterminated_comment b/tests/00_syntax/01_unterminated_comment
new file mode 100644
index 0000000..0a28af1
--- /dev/null
+++ b/tests/00_syntax/01_unterminated_comment
@@ -0,0 +1,15 @@
+Unterminated comment
+
+-- Expect stderr --
+Syntax error: Unterminated template block
+In line 1, byte 8:
+
+ `This is {# an unclosed comment`
+ ^-- Near here
+
+
+-- End --
+
+-- Testcase --
+This is {# an unclosed comment
+-- End --
diff --git a/tests/00_syntax/02_multi_line_comments b/tests/00_syntax/02_multi_line_comments
new file mode 100644
index 0000000..99fc37e
--- /dev/null
+++ b/tests/00_syntax/02_multi_line_comments
@@ -0,0 +1,12 @@
+Multiline comments.
+
+-- Expect stdout --
+This is an example text for testing comment blocks.
+-- End --
+
+-- Testcase --
+This is an example text {# containing
+a comment spanning multiple lines and
+ different indentation
+ #} for testing comment blocks.
+-- End --
diff --git a/tests/00_syntax/03_expression_blocks b/tests/00_syntax/03_expression_blocks
new file mode 100644
index 0000000..3568016
--- /dev/null
+++ b/tests/00_syntax/03_expression_blocks
@@ -0,0 +1,11 @@
+Testing expression blocks.
+
+-- Expect stdout --
+The result of 3 * 7 is 21.
+To escape the start tag, output it as string expression: {{
+-- End --
+
+-- Testcase --
+The result of 3 * 7 is {{ 3 * 7 }}.
+To escape the start tag, output it as string expression: {{ "{{" }}
+-- End --
diff --git a/tests/00_syntax/04_statement_blocks b/tests/00_syntax/04_statement_blocks
new file mode 100644
index 0000000..faafd9a
--- /dev/null
+++ b/tests/00_syntax/04_statement_blocks
@@ -0,0 +1,18 @@
+Testing statement blocks.
+
+-- Expect stdout --
+The result of 3 * 7 is 21.
+A statement block may contain multiple statements: Hello World
+To escape the start tag, output it as string expression: {%
+Alternatively print it: {%
+-- End --
+
+-- Testcase --
+The result of 3 * 7 is {% print(3 * 7) %}.
+A statement block may contain multiple statements: {%
+ print("Hello ");
+ print("World");
+%}
+To escape the start tag, output it as string expression: {{ "{%" }}
+Alternatively print it: {% print("{%") %}
+-- End --
diff --git a/tests/00_syntax/05_block_nesting b/tests/00_syntax/05_block_nesting
new file mode 100644
index 0000000..728c00c
--- /dev/null
+++ b/tests/00_syntax/05_block_nesting
@@ -0,0 +1,17 @@
+Nesting blocks into non-comment blocks should fail.
+
+-- Expect stderr --
+Syntax error: Template blocks may not be nested
+In line 2, byte 60:
+
+ `We may not nest statement blocks into expression blocks: {{ {% print(1 + 2) %} }}.`
+ Near here --------------------------------------------------^
+
+
+-- End --
+
+-- Testcase --
+We can nest other block types into comments: {# {% {{ 1 + 2 }} %} #}
+We may not nest statement blocks into expression blocks: {{ {% print(1 + 2) %} }}.
+We may not nest expression blocks into statement blocks: {% {{ 1 + 2 }} %}.
+-- End --
diff --git a/tests/00_syntax/06_open_statement_block b/tests/00_syntax/06_open_statement_block
new file mode 100644
index 0000000..9c2d142
--- /dev/null
+++ b/tests/00_syntax/06_open_statement_block
@@ -0,0 +1,13 @@
+The last statement block of a template may remain open, this is useful for templates
+that contain only code.
+
+-- Expect stdout --
+This template consists entirely of script code!
+-- End --
+
+-- Testcase --
+{%
+ print("This template ");
+ print("consists entirely ");
+ print("of script code!\n");
+-- End --
diff --git a/tests/00_syntax/07_embedded_single_line_comments b/tests/00_syntax/07_embedded_single_line_comments
new file mode 100644
index 0000000..8c5fd4a
--- /dev/null
+++ b/tests/00_syntax/07_embedded_single_line_comments
@@ -0,0 +1,20 @@
+Statement and expression blocks may contain C++-style comments.
+A C++-style comment is started by two subsequent slashes and spans
+until the next newline.
+
+-- Expect stdout --
+The result of 5 + 9 is 14.
+Statement blocks may use C++ comments too: Test Another test.
+-- End --
+
+-- Testcase --
+The result of 5 + 9 is {{ // The block end tag is ignored: }}
+// And the expression block continues here!
+5 + 9 }}.
+Statement blocks may use C++ comments too: {%
+ print("Test"); // A comment.
+
+ // Another comment.
+ print(" Another test.");
+%}
+-- End --
diff --git a/tests/00_syntax/08_embedded_multi_line_comments b/tests/00_syntax/08_embedded_multi_line_comments
new file mode 100644
index 0000000..b27554f
--- /dev/null
+++ b/tests/00_syntax/08_embedded_multi_line_comments
@@ -0,0 +1,23 @@
+Statement and expression blocks may contain C-style comments.
+A C-style comment is started by a slash followed by an asterisk
+and ended by an asterisk followed by a slash.
+
+Such comments may appear everywhere within statement or expression
+blocks, even in the middle of statements or expressions.
+
+-- Expect stdout --
+The result of 12 - 4 is 8.
+Statement blocks may use C comments too: Test Another test. The final test.
+-- End --
+
+-- Testcase --
+The result of 12 - 4 is {{ /* A comment before */ 12 - /* or even within */ 4 /* or after an expression */ }}.
+Statement blocks may use C comments too: {%
+ print("Test"); /* A comment. */
+
+ /* Another comment. */
+ print(" Another test.");
+
+ print(/* A comment within */ " The final test.");
+%}
+-- End --
diff --git a/tests/00_syntax/09_string_literals b/tests/00_syntax/09_string_literals
new file mode 100644
index 0000000..cd84d3e
--- /dev/null
+++ b/tests/00_syntax/09_string_literals
@@ -0,0 +1,25 @@
+String literals may be enclosed in single or double quotes.
+Embedded escape sequences are started with a backslash, followed
+by either a hexadecimal, an octal or a single character escape sequence.
+
+-- Expect stdout --
+Single quoted string
+Double quoted string
+Unicode escape sequence: ☀💩
+Escaped double quote (") character
+Escaped single quote (') character
+Hexadecimal escape: XYZ xyz
+Octal escape: ABC xyz
+{ "Single char escape": "\u0007\b\u001b\f\r\t\u000b\\\n" }
+-- End --
+
+-- Testcase --
+{{ 'Single quoted string' }}
+{{ "Double quoted string" }}
+{{ "Unicode escape sequence: \u2600\uD83D\uDCA9" }}
+{{ "Escaped double quote (\") character" }}
+{{ 'Escaped single quote (\') character' }}
+{{ "Hexadecimal escape: \x58\x59\x5A \x78\x79\x7a" }}
+{{ "Octal escape: \101\102\103 \170\171\172" }}
+{{ { "Single char escape": "\a\b\e\f\r\t\v\\\n" } }}
+-- End --
diff --git a/tests/00_syntax/10_numeric_literals b/tests/00_syntax/10_numeric_literals
new file mode 100644
index 0000000..3e367d0
--- /dev/null
+++ b/tests/00_syntax/10_numeric_literals
@@ -0,0 +1,26 @@
+C-style numeric integer and float literals are understood, as well
+as the special keywords "Infinity" and "NaN" to denote the IEEE 754
+floating point values.
+
+Numeric values are either stored as signed 64 bit integers or signed
+doubles internally.
+
+-- Expect stdout --
+Integers literals: 123, 127, 2748, 57082
+Float literals: 10, 10.3, 1.23456e-65, 16.0625
+Special values: Infinity, Infinity, NaN, NaN
+Minimum values: -9223372036854775808, -1.79769e+308
+Maximum values: 9223372036854775807, 1.79769e+308
+Minimum truncation: -9223372036854775808, -Infinity
+Maximum truncation: 9223372036854775807, Infinity
+-- End --
+
+-- Testcase --
+Integers literals: {{ 123 }}, {{ 0177 }}, {{ 0xabc }}, {{ 0xDEFA }}
+Float literals: {{ 10. }}, {{ 10.3 }}, {{ 123.456e-67 }}, {{ 0x10.1 }}
+Special values: {{ Infinity }}, {{ 1 / 0 }}, {{ NaN }}, {{ "x" / 1 }}
+Minimum values: {{ -9223372036854775808 }}, {{ -1.7976931348623158e+308 }}
+Maximum values: {{ 9223372036854775807 }}, {{ 1.7976931348623158e+308 }}
+Minimum truncation: {{ -10000000000000000000 }}, {{ -1.0e309 }}
+Maximum truncation: {{ 10000000000000000000 }}, {{ 1.0e309 }}
+-- End --
diff --git a/tests/00_syntax/11_misc_literals b/tests/00_syntax/11_misc_literals
new file mode 100644
index 0000000..8a654e1
--- /dev/null
+++ b/tests/00_syntax/11_misc_literals
@@ -0,0 +1,16 @@
+The utpl script language features a number of keywords which represent
+certain special values.
+
+-- Expect stdout --
+The "this" keyword refers to the current function context: object
+The "null" keyword represents the null value: null
+The "true" keyword represents a true boolean value: true
+The "false" keyword represents a false boolean value: false
+-- End --
+
+-- Testcase --
+The "this" keyword refers to the current function context: {{ type(this) }}
+The "null" keyword represents the null value: {{ "" + null }}
+The "true" keyword represents a true boolean value: {{ true }}
+The "false" keyword represents a false boolean value: {{ false }}
+-- End --
diff --git a/tests/00_syntax/12_block_whitespace_control b/tests/00_syntax/12_block_whitespace_control
new file mode 100644
index 0000000..23f7380
--- /dev/null
+++ b/tests/00_syntax/12_block_whitespace_control
@@ -0,0 +1,46 @@
+By default, whitespace before a block start tag or after a block end tag
+is retained. By suffixing the start tag or prefixing the end tag with a
+dash, the leading or trailing whitespace is trimmed respectively.
+
+-- Expect stdout --
+Whitespace control applies to all block types:
+Comment before: | |, after: | |, both: ||
+Statement before: |test |, after: | test|, both: |test|
+Expression before: |test |, after: | test|, both: |test|
+
+By default whitespace around a block is retained.
+Leading whitespace can be trimmed like this.
+The same applies to trailing whitespace.
+It is also possible to trim bothleading and trailingwhitespace.
+
+Stripping works across multiple lines as well:test
+
+Likewise, stripping over multiple lines of trailing whitespace works as
+expected too.This is after the block.
+-- End --
+
+-- Testcase --
+Whitespace control applies to all block types:
+Comment before: | {#- test #} |, after: | {#- test #} |, both: | {#- test -#} |
+Statement before: | {%- print("test") %} |, after: | {% print("test") -%} |, both: | {%- print("test") -%} |
+Expression before: | {{- "test" }} |, after: | {{ "test" -}} |, both: | {{- "test" -}} |
+
+By default whitespace {{ "around a block" }} is retained.
+Leading whitespace can be trimmed {#- note the leading dash #} like this.
+The same applies to {# note the trailing dash -#} trailing whitespace.
+It is also possible to trim both {{- "leading and trailing" -}} whitespace.
+
+Stripping works across multiple lines as well:
+
+{%-
+ /* The word "test" will be printed after "well:" above */
+ print("test")
+%}
+
+Likewise, stripping over multiple lines of trailing whitespace works as
+expected too.
+
+{#- Any whitespace after "expected too." and before "This is after the block" will be trimmed. -#}
+
+This is after the block.
+-- End --