diff options
-rwxr-xr-x | run_tests.sh | 69 | ||||
-rw-r--r-- | tests/00_syntax/00_single_line_comments | 15 | ||||
-rw-r--r-- | tests/00_syntax/01_unterminated_comment | 15 | ||||
-rw-r--r-- | tests/00_syntax/02_multi_line_comments | 12 | ||||
-rw-r--r-- | tests/00_syntax/03_expression_blocks | 11 | ||||
-rw-r--r-- | tests/00_syntax/04_statement_blocks | 18 | ||||
-rw-r--r-- | tests/00_syntax/05_block_nesting | 17 | ||||
-rw-r--r-- | tests/00_syntax/06_open_statement_block | 13 | ||||
-rw-r--r-- | tests/00_syntax/07_embedded_single_line_comments | 20 | ||||
-rw-r--r-- | tests/00_syntax/08_embedded_multi_line_comments | 23 | ||||
-rw-r--r-- | tests/00_syntax/09_string_literals | 25 | ||||
-rw-r--r-- | tests/00_syntax/10_numeric_literals | 26 | ||||
-rw-r--r-- | tests/00_syntax/11_misc_literals | 16 | ||||
-rw-r--r-- | tests/00_syntax/12_block_whitespace_control | 46 |
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 -- |