CoolFace
Modelpublic

Felipe97/llama-cpp-compiled

sourceHugging Faceupdated 2d agoView on Hugging Face
0likes1.1kdownloads
test-jinja.cpp2731 linesDownload Raw Back to tests
1#include <string>2#include <iostream>3#include <random>4#include <cstdlib>5 6#include "json.h"7#include "subproc.h"8 9#include "jinja/runtime.h"10#include "jinja/parser.h"11#include "jinja/lexer.h"12#include "jinja/utils.h"13#include "jinja/caps.h"14 15#include "testing.h"16 17using json = common_json;18 19static void test_template(testing & t, const std::string & name, const std::string & tmpl, const json & vars, const std::string & expect);20 21static void test_whitespace_control(testing & t);22static void test_conditionals(testing & t);23static void test_loops(testing & t);24static void test_expressions(testing & t);25static void test_set_statement(testing & t);26static void test_filters(testing & t);27static void test_literals(testing & t);28static void test_comments(testing & t);29static void test_macros(testing & t);30static void test_namespace(testing & t);31static void test_tests(testing & t);32static void test_string_methods(testing & t);33static void test_array_methods(testing & t);34static void test_object_methods(testing & t);35static void test_hasher(testing & t);36static void test_stats(testing & t);37static void test_caps(testing & t);38static void test_string_parts(testing & t);39static void test_fuzzing(testing & t);40 41static bool g_python_mode = false;42 43int main(int argc, char *argv[]) {44    testing t(std::cout);45    t.verbose = true;46 47    // usage: test-jinja [-py] [filter_regex]48    //  -py : enable python mode (use python jinja2 for rendering expected output)49    //        only use this for cross-checking, not for correctness50    //        note: the implementation of this flag is basic, only intented to be used by maintainers51 52    for (int i = 1; i < argc; i++) {53        std::string arg = argv[i];54        if (arg == "-py") {55            g_python_mode = true;56        } else {57            t.set_filter(arg);58        }59    }60 61    t.test("whitespace control", test_whitespace_control);62    t.test("conditionals", test_conditionals);63    t.test("loops", test_loops);64    t.test("expressions", test_expressions);65    t.test("set statement", test_set_statement);66    t.test("filters", test_filters);67    t.test("literals", test_literals);68    t.test("comments", test_comments);69    t.test("macros", test_macros);70    t.test("namespace", test_namespace);71    t.test("tests", test_tests);72    t.test("string methods", test_string_methods);73    t.test("array methods", test_array_methods);74    t.test("object methods", test_object_methods);75    if (!g_python_mode) {76        t.test("hasher", test_hasher);77        t.test("stats", test_stats);78        t.test("caps", test_caps);79        t.test("string parts", test_string_parts);80        t.test("fuzzing", test_fuzzing);81    }82 83    return t.summary();84}85 86static void test_whitespace_control(testing & t) {87    test_template(t, "trim_blocks removes newline after tag",88        "{% if true %}\n"89        "hello\n"90        "{% endif %}\n",91        json::object(),92        "hello\n"93    );94 95    test_template(t, "lstrip_blocks removes leading whitespace",96        "    {% if true %}\n"97        "    hello\n"98        "    {% endif %}\n",99        json::object(),100        "    hello\n"101    );102 103    test_template(t, "for loop with trim_blocks",104        "{% for i in items %}\n"105        "{{ i }}\n"106        "{% endfor %}\n",107        {{"items", json::array({1, 2, 3})}},108        "1\n2\n3\n"109    );110 111    test_template(t, "explicit strip both",112        "  {%- if true -%}  \n"113        "hello\n"114        "  {%- endif -%}  \n",115        json::object(),116        "hello"117    );118 119    test_template(t, "expression whitespace control",120        "  {{- 'hello' -}}  \n",121        json::object(),122        "hello"123    );124 125    test_template(t, "inline block no newline",126        "{% if true %}yes{% endif %}",127        json::object(),128        "yes"129    );130}131 132static void test_conditionals(testing & t) {133    test_template(t, "if true",134        "{% if cond %}yes{% endif %}",135        {{"cond", true}},136        "yes"137    );138 139    test_template(t, "if false",140        "{% if cond %}yes{% endif %}",141        {{"cond", false}},142        ""143    );144 145    test_template(t, "if else",146        "{% if cond %}yes{% else %}no{% endif %}",147        {{"cond", false}},148        "no"149    );150 151    test_template(t, "if elif else",152        "{% if a %}A{% elif b %}B{% else %}C{% endif %}",153        {{"a", false}, {"b", true}},154        "B"155    );156 157    test_template(t, "nested if",158        "{% if outer %}{% if inner %}both{% endif %}{% endif %}",159        {{"outer", true}, {"inner", true}},160        "both"161    );162 163    test_template(t, "comparison operators",164        "{% if x > 5 %}big{% endif %}",165        {{"x", 10}},166        "big"167    );168 169    test_template(t, "object comparison",170        "{% if {0: 1, none: 2, 1.0: 3, '0': 4, true: 5} == {false: 1, none: 2, 1: 5, '0': 4} %}equal{% endif %}",171        json::object(),172        "equal"173    );174 175    test_template(t, "array comparison",176        "{% if [0, 1.0, false] == [false, 1, 0.0] %}equal{% endif %}",177        json::object(),178        "equal"179    );180 181    test_template(t, "logical and",182        "{% if a and b %}both{% endif %}",183        {{"a", true}, {"b", true}},184        "both"185    );186 187    test_template(t, "logical or",188        "{% if a or b %}either{% endif %}",189        {{"a", false}, {"b", true}},190        "either"191    );192 193    test_template(t, "logical not",194        "{% if not a %}negated{% endif %}",195        {{"a", false}},196        "negated"197    );198 199    test_template(t, "in operator (element in array)",200        "{% if 'x' in items %}found{% endif %}",201        {{"items", json::array({"x", "y"})}},202        "found"203    );204 205    test_template(t, "in operator (substring)",206        "{% if 'bc' in 'abcd' %}found{% endif %}",207        json::object(),208        "found"209    );210 211    test_template(t, "in operator (object key)",212        "{% if 'key' in obj %}found{% endif %}",213        {{"obj", {{"key", 1}, {"other", 2}}}},214        "found"215    );216 217    test_template(t, "is defined",218        "{% if x is defined %}yes{% else %}no{% endif %}",219        {{"x", 1}},220        "yes"221    );222 223    test_template(t, "is not defined",224        "{% if y is not defined %}yes{% else %}no{% endif %}",225        json::object(),226        "yes"227    );228 229    test_template(t, "is undefined falsy",230        "{{ 'yes' if not y else 'no' }}",231        json::object(),232        "yes"233    );234 235    test_template(t, "is undefined attribute falsy",236        "{{ 'yes' if not y.x else 'no' }}",237        {{"y", true}},238        "yes"239    );240 241    test_template(t, "is undefined key falsy",242        "{{ 'yes' if not y['x'] else 'no' }}",243        {{"y", json::array({nullptr})}},244        "yes"245    );246 247    test_template(t, "is empty array falsy",248        "{{ 'yes' if not y else 'no' }}",249        {{"y", json::array()}},250        "yes"251    );252 253    test_template(t, "is empty object falsy",254        "{{ 'yes' if not y else 'no' }}",255        {{"y", json::object()}},256        "yes"257    );258 259    test_template(t, "is empty string falsy",260        "{{ 'yes' if not y else 'no' }}",261        {{"y", ""}},262        "yes"263    );264 265    test_template(t, "is 0 falsy",266        "{{ 'yes' if not y else 'no' }}",267        {{"y", 0}},268        "yes"269    );270 271    test_template(t, "is 0.0 falsy",272        "{{ 'yes' if not y else 'no' }}",273        {{"y", 0.0}},274        "yes"275    );276 277    test_template(t, "is non-empty array truthy",278        "{{ 'yes' if y else 'no' }}",279        {{"y", json::array({""})}},280        "yes"281    );282 283    test_template(t, "is non-empty object truthy",284        "{{ 'yes' if y else 'no' }}",285        {{"y", json::array({"x", false})}},286        "yes"287    );288 289    test_template(t, "is non-empty string truthy",290        "{{ 'yes' if y else 'no' }}",291        {{"y", "0"}},292        "yes"293    );294 295    test_template(t, "is 1 truthy",296        "{{ 'yes' if y else 'no' }}",297        {{"y", 1}},298        "yes"299    );300 301    test_template(t, "is 1.0 truthy",302        "{{ 'yes' if y else 'no' }}",303        {{"y", 1.0}},304        "yes"305    );306}307 308static void test_loops(testing & t) {309    test_template(t, "simple for",310        "{% for i in items %}{{ i }}{% endfor %}",311        {{"items", json::array({1, 2, 3})}},312        "123"313    );314 315    test_template(t, "loop.index",316        "{% for i in items %}{{ loop.index }}{% endfor %}",317        {{"items", json::array({"a", "b", "c"})}},318        "123"319    );320 321    test_template(t, "loop.index0",322        "{% for i in items %}{{ loop.index0 }}{% endfor %}",323        {{"items", json::array({"a", "b", "c"})}},324        "012"325    );326 327    test_template(t, "loop.first and loop.last",328        "{% for i in items %}{% if loop.first %}[{% endif %}{{ i }}{% if loop.last %}]{% endif %}{% endfor %}",329        {{"items", json::array({1, 2, 3})}},330        "[123]"331    );332 333    test_template(t, "loop.length",334        "{% for i in items %}{{ loop.length }}{% endfor %}",335        {{"items", json::array({"a", "b"})}},336        "22"337    );338 339    test_template(t, "for over dict items",340        "{% for k, v in data.items() %}{{ k }}={{ v }} {% endfor %}",341        {{"data", {{"x", 1}, {"y", 2}}}},342        "x=1 y=2 "343    );344 345    test_template(t, "for else empty",346        "{% for i in items %}{{ i }}{% else %}empty{% endfor %}",347        {{"items", json::array()}},348        "empty"349    );350 351    test_template(t, "for undefined empty",352        "{% for i in items %}{{ i }}{% else %}empty{% endfor %}",353        json::object(),354        "empty"355    );356 357    test_template(t, "nested for",358        "{% for i in a %}{% for j in b %}{{ i }}{{ j }}{% endfor %}{% endfor %}",359        {{"a", json::array({1, 2})}, {"b", json::array({"x", "y"})}},360        "1x1y2x2y"361    );362 363    test_template(t, "for with range",364        "{% for i in range(3) %}{{ i }}{% endfor %}",365        json::object(),366        "012"367    );368}369 370static void test_expressions(testing & t) {371    test_template(t, "simple variable",372        "{{ x }}",373        {{"x", 42}},374        "42"375    );376 377    test_template(t, "none in object",378        "{{ x in {'low': 1, 'high': 2} }}",379        {{"x", nullptr}},380        "False"381    );382 383    test_template(t, "none not in object",384        "{{ x not in {'low': 1, 'high': 2} }}",385        {{"x", nullptr}},386        "True"387    );388 389    test_template(t, "none in array",390        "{{ x in [1, none, 3] }}",391        {{"x", nullptr}},392        "True"393    );394 395    test_template(t, "dot notation",396        "{{ user.name }}",397        {{"user", {{"name", "Bob"}}}},398        "Bob"399    );400 401    test_template(t, "dot notation (integer property)",402        "{{ {10: 'Bob'}.10 }}",403        json::object(),404        "Bob"405    );406 407    test_template(t, "dot notation (array index)",408        "{{ user.10 }}",409        {{"user", json::array({"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"})}},410        "k"411    );412 413    test_template(t, "negative float (not dot notation)",414        "{{ -1.0 }}",415        json::object(),416        "-1.0"417    );418 419    test_template(t, "bracket notation",420        "{{ user['name'] }}",421        {{"user", {{"name", "Bob"}}}},422        "Bob"423    );424 425    test_template(t, "empty computed member defaults to undefined",426        "{{ a[]|default('fallback') }}",427        {{"a", {{"name", "Bob"}}}},428        "fallback"429    );430 431    test_template(t, "empty computed member is undefined",432        "{{ a[] is undefined }}",433        {{"a", {{"name", "Bob"}}}},434        "True"435    );436 437    test_template(t, "undefined computed member is undefined",438        "{{ a[undefined] is undefined }}",439        {{"a", {{"name", "Bob"}}}},440        "True"441    );442 443    test_template(t, "array access",444        "{{ items[1] }}",445        {{"items", json::array({"a", "b", "c"})}},446        "b"447    );448 449    test_template(t, "array negative access",450        "{{ items[-1] }}",451        {{"items", json::array({"a", "b", "c"})}},452        "c"453    );454 455    test_template(t, "array slice",456        "{{ items[1:-1]|string }}",457        {{"items", json::array({"a", "b", "c"})}},458        "['b']"459    );460 461    test_template(t, "array slice step",462        "{{ items[::2]|string }}",463        {{"items", json::array({"a", "b", "c"})}},464        "['a', 'c']"465    );466 467    test_template(t, "tuple slice",468        "{{ ('a', 'b', 'c')[::-1]|string }}",469        json::object(),470        "('c', 'b', 'a')"471    );472 473    test_template(t, "string slice negative step",474        "{{ 'abcdef'[::-2] }}",475        json::object(),476        "fdb"477    );478 479    test_template(t, "string slice negative start and step",480        "{{ 'abcdef'[-1:1:-1] }}",481        json::object(),482        "fedc"483    );484 485    test_template(t, "string slice negative start, stop and step",486        "{{ 'abcdef'[-1:-5:-1] }}",487        json::object(),488        "fedc"489    );490 491    test_template(t, "arithmetic",492        "{{ (a + b) * c }}",493        {{"a", 2}, {"b", 3}, {"c", 4}},494        "20"495    );496 497    test_template(t, "string concat ~",498        "{{ 'hello' ~ ' ' ~ 'world' }}",499        json::object(),500        "hello world"501    );502 503    test_template(t, "string repetition",504        "{{ 'ab' * 3 }}",505        json::object(),506        "ababab"507    );508 509    test_template(t, "reversed string repetition",510        "{{ 3 * 'ab' }}",511        json::object(),512        "ababab"513    );514 515    test_template(t, "ternary",516        "{{ 'yes' if cond else 'no' }}",517        {{"cond", true}},518        "yes"519    );520}521 522static void test_set_statement(testing & t) {523    test_template(t, "simple set",524        "{% set x = 5 %}{{ x }}",525        json::object(),526        "5"527    );528 529    test_template(t, "set with expression",530        "{% set x = a + b %}{{ x }}",531        {{"a", 10}, {"b", 20}},532        "30"533    );534 535    test_template(t, "set list",536        "{% set items = [1, 2, 3] %}{{ items|length }}",537        json::object(),538        "3"539    );540 541    test_template(t, "set dict",542        "{% set d = {'a': 1} %}{{ d.a }}",543        json::object(),544        "1"545    );546 547    test_template(t, "set dict with mixed type keys",548        "{% set d = {0: 1, none: 2, 1.0: 3, '0': 4, (0, 0): 5, false: 6, 1: 7} %}{{ d[(0, 0)] + d[0] + d[none] + d['0'] + d[false] + d[1.0] + d[1] }}",549        json::object(),550        "37"551    );552 553    test_template(t, "print dict with mixed type keys",554        "{% set d = {0: 1, none: 2, 1.0: 3, '0': 4, (0, 0): 5, true: 6} %}{{ d|string }}",555        json::object(),556        "{0: 1, None: 2, 1.0: 6, '0': 4, (0, 0): 5}"557    );558 559    test_template(t, "print array with mixed types",560        "{% set d = [0, none, 1.0, '0', true, (0, 0)] %}{{ d|string }}",561        json::object(),562        "[0, None, 1.0, '0', True, (0, 0)]"563    );564 565    test_template(t, "object member assignment with mixed key types",566        "{% set d = namespace() %}{% set d.a = 123 %}{{ d['a'] == 123 }}",567        json::object(),568        "True"569    );570 571    test_template(t, "tuple unpacking",572        "{% set t = (1, 2, 3) %}{% set a, b, c = t %}{{ a + b + c }}",573        json::object(),574        "6"575    );576}577 578static void test_filters(testing & t) {579    test_template(t, "upper",580        "{{ 'hello'|upper }}",581        json::object(),582        "HELLO"583    );584 585    test_template(t, "lower",586        "{{ 'HELLO'|lower }}",587        json::object(),588        "hello"589    );590 591    test_template(t, "upper array",592        "{{ items|upper }}",593        {{"items", json::array({"hello", "world"})}},594        "['HELLO', 'WORLD']"595    );596 597    test_template(t, "upper dict",598        "{{ items|upper }}",599        {{"items", {{"hello", "world"}}}},600        "{'HELLO': 'WORLD'}"601    );602 603    test_template(t, "capitalize",604        "{{ 'heLlo World'|capitalize }}",605        json::object(),606        "Hello world"607    );608 609    test_template(t, "title",610        "{{ 'hello world'|title }}",611        json::object(),612        "Hello World"613    );614 615    test_template(t, "trim",616        "{{ '  \r\n\thello\t\n\r  '|trim }}",617        json::object(),618        "hello"619    );620 621    test_template(t, "trim chars",622        "{{ 'xyxhelloxyx'|trim('xy') }}",623        json::object(),624        "hello"625    );626 627    test_template(t, "length string",628        "{{ 'hello'|length }}",629        json::object(),630        "5"631    );632 633    test_template(t, "replace",634        "{{ 'hello world'|replace('world', 'jinja') }}",635        json::object(),636        "hello jinja"637    );638 639    test_template(t, "length (count alias) list",640        "{{ items|count }}",641        {{"items", json::array({1, 2, 3})}},642        "3"643    );644 645    test_template(t, "first",646        "{{ items|first }}",647        {{"items", json::array({10, 20, 30})}},648        "10"649    );650 651    test_template(t, "last",652        "{{ items|last }}",653        {{"items", json::array({10, 20, 30})}},654        "30"655    );656 657    test_template(t, "reverse",658        "{% for i in items|reverse %}{{ i }}{% endfor %}",659        {{"items", json::array({1, 2, 3})}},660        "321"661    );662 663    test_template(t, "sort",664        "{% for i in items|sort %}{{ i }}{% endfor %}",665        {{"items", json::array({3, 1, 2})}},666        "123"667    );668 669    test_template(t, "sort reverse",670        "{% for i in items|sort(true) %}{{ i }}{% endfor %}",671        {{"items", json::array({3, 1, 2})}},672        "321"673    );674 675    test_template(t, "sort with attribute",676        "{{ items|sort(attribute='name')|join(attribute='age') }}",677        {{"items", json::array({678            json({{"name", "c"}, {"age", 3}}),679            json({{"name", "a"}, {"age", 1}}),680            json({{"name", "b"}, {"age", 2}}),681        })}},682        "123"683    );684 685    test_template(t, "sort with numeric attribute",686        "{{ items|sort(attribute=0)|join(attribute=1) }}",687        {{"items", json::array({688            json::array({3, "z"}),689            json::array({1, "x"}),690            json::array({2, "y"}),691        })}},692        "xyz"693    );694 695    test_template(t, "join",696        "{{ items|join(', ') }}",697        {{"items", json::array({"a", "b", "c"})}},698        "a, b, c"699    );700 701    test_template(t, "join default separator",702        "{{ items|join }}",703        {{"items", json::array({"x", "y", "z"})}},704        "xyz"705    );706 707    test_template(t, "abs",708        "{{ -5|abs }}",709        json::object(),710        "5"711    );712 713    test_template(t, "int from string",714        "{{ '42'|int }}",715        json::object(),716        "42"717    );718 719    test_template(t, "int from string with default",720        "{{ ''|int(1) }}",721        json::object(),722        "1"723    );724 725    test_template(t, "int from string with base",726        "{{ '11'|int(base=2) }}",727        json::object(),728        "3"729    );730 731    test_template(t, "float from string",732        "{{ '3.14'|float }}",733        json::object(),734        "3.14"735    );736 737    test_template(t, "default with value",738        "{{ x|default('fallback') }}",739        {{"x", "actual"}},740        "actual"741    );742 743    test_template(t, "default without value",744        "{{ y|default('fallback') }}",745        json::object(),746        "fallback"747    );748 749    test_template(t, "default (d alias) with falsy value",750        "{{ ''|d('fallback', true) }}",751        json::object(),752        "fallback"753    );754 755    test_template(t, "tojson ensure_ascii=true",756        "{{ data|tojson(ensure_ascii=true) }}",757        {{"data", "\u2713"}},758        "\"\\u2713\""759    );760 761    test_template(t, "tojson ensure_ascii=true nested object",762        "{{ data|tojson(ensure_ascii=true) }}",763        {{"data", {764            {"text", "\u2713"},765            {"items", json::array({"é", {{"snowman", "☃"}}})}766        }}},767        "{\"text\": \"\\u2713\", \"items\": [\"\\u00e9\", {\"snowman\": \"\\u2603\"}]}"768    );769 770    test_template(t, "tojson ensure_ascii=true indent=2",771        "{{ data|tojson(ensure_ascii=true, indent=2) }}",772        {{"data", {773            {"text", "\u2713"},774            {"nested", {{"accent", "é"}}}775        }}},776        "{\n  \"text\": \"\\u2713\",\n  \"nested\": {\n    \"accent\": \"\\u00e9\"\n  }\n}"777    );778 779    test_template(t, "tojson ensure_ascii=true preserves existing escapes",780        "{{ data|tojson(ensure_ascii=true) }}",781        {{"data", {782            {"emoji", "😀"},783            {"line", "a\nb"}784        }}},785        "{\"emoji\": \"\\ud83d\\ude00\", \"line\": \"a\\nb\"}"786    );787 788    test_template(t, "tojson sort_keys=true",789        "{{ data|tojson(sort_keys=true) }}",790        {{"data", {{"b", 2}, {"a", 1}}}},791        "{\"a\": 1, \"b\": 2}"792    );793 794    test_template(t, "tojson",795        "{{ data|tojson }}",796        {{"data", {{"a", 1}, {"b", json::array({1, 2})}}}},797        "{\"a\": 1, \"b\": [1, 2]}"798    );799 800    test_template(t, "tojson indent=4",801        "{{ data|tojson(indent=4) }}",802        {{"data", {{"a", 1}, {"b", json::array({1, 2})}}}},803        "{\n    \"a\": 1,\n    \"b\": [\n        1,\n        2\n    ]\n}"804    );805 806    test_template(t, "tojson separators=(',',':')",807        "{{ data|tojson(separators=(',',':')) }}",808        {{"data", {{"a", 1}, {"b", json::array({1, 2})}}}},809        "{\"a\":1,\"b\":[1,2]}"810    );811 812    test_template(t, "tojson separators=(',',': ') indent=2",813        "{{ data|tojson(separators=(',',': '), indent=2) }}",814        {{"data", {{"a", 1}, {"b", json::array({1, 2})}}}},815        "{\n  \"a\": 1,\n  \"b\": [\n    1,\n    2\n  ]\n}"816    );817 818    test_template(t, "indent",819        "{{ data|indent(2) }}",820        {{ "data", "foo\nbar" }},821        "foo\n  bar"822    );823 824    test_template(t, "indent first only",825        "{{ data|indent(width=3,first=true) }}",826        {{ "data", "foo\nbar" }},827        "   foo\n   bar"828    );829 830    test_template(t, "indent blank lines and first line",831        "{{ data|indent(width=5,blank=true,first=true) }}",832        {{ "data", "foo\n\nbar" }},833        "     foo\n     \n     bar"834    );835 836    test_template(t, "indent with default width",837        "{{ data|indent() }}",838        {{ "data", "foo\nbar" }},839        "foo\n    bar"840    );841 842    test_template(t, "indent with no newline",843        "{{ data|indent }}",844        {{ "data", "foo" }},845        "foo"846    );847 848    test_template(t, "indent with trailing newline",849        "{{ data|indent(blank=true) }}",850        {{ "data", "foo\n" }},851        "foo\n    "852    );853 854    test_template(t, "indent with string",855        "{{ data|indent(width='>>>>') }}",856        {{ "data", "foo\nbar" }},857        "foo\n>>>>bar"858    );859 860    test_template(t, "chained filters",861        "{{ '  HELLO  '|trim|lower }}",862        json::object(),863        "hello"864    );865 866    test_template(t, "int filter on integer is identity",867        "{{ value|int }}",868        {{"value", 7}},869        "7"870    );871 872    test_template(t, "none to string",873        "{{ x|string }}",874        {{"x", nullptr}},875        "None"876    );877}878 879static void test_literals(testing & t) {880    test_template(t, "integer",881        "{{ 42 }}",882        json::object(),883        "42"884    );885 886    test_template(t, "float",887        "{{ 3.14 }}",888        json::object(),889        "3.14"890    );891 892    test_template(t, "string",893        "{{ 'hello' }}",894        json::object(),895        "hello"896    );897 898    test_template(t, "boolean true",899        "{{ true }}",900        json::object(),901        "True"902    );903 904    test_template(t, "boolean false",905        "{{ false }}",906        json::object(),907        "False"908    );909 910    test_template(t, "none",911        "{% if x is none %}null{% endif %}",912        {{"x", nullptr}},913        "null"914    );915 916    test_template(t, "list literal",917        "{% for i in [1, 2, 3] %}{{ i }}{% endfor %}",918        json::object(),919        "123"920    );921 922    test_template(t, "dict literal",923        "{% set d = {'a': 1} %}{{ d.a }}",924        json::object(),925        "1"926    );927 928    test_template(t, "integer|abs",929        "{{ -42 | abs }}",930        json::object(),931        "42"932    );933 934    test_template(t, "integer|float",935        "{{ 42 | float }}",936        json::object(),937        "42.0"938    );939 940    test_template(t, "integer|tojson",941        "{{ 42 | tojson }}",942        json::object(),943        "42"944    );945 946    test_template(t, "float|abs",947        "{{ -3.14 | abs }}",948        json::object(),949        "3.14"950    );951 952    test_template(t, "float|int",953        "{{ 3.14 | int }}",954        json::object(),955        "3"956    );957 958    test_template(t, "float|tojson",959        "{{ 3.14 | tojson }}",960        json::object(),961        "3.14"962    );963 964    test_template(t, "string|tojson",965        "{{ 'hello' | tojson }}",966        json::object(),967        "\"hello\""968    );969 970    test_template(t, "boolean|int",971        "{{ true | int }}",972        json::object(),973        "1"974    );975 976    test_template(t, "boolean|float",977        "{{ true | float }}",978        json::object(),979        "1.0"980    );981 982    test_template(t, "boolean|tojson",983        "{{ true | tojson }}",984        json::object(),985        "true"986    );987}988 989static void test_comments(testing & t) {990    test_template(t, "inline comment",991        "before{# comment #}after",992        json::object(),993        "beforeafter"994    );995 996    test_template(t, "comment ignores code",997        "{% set x = 1 %}{# {% set x = 999 %} #}{{ x }}",998        json::object(),999        "1"1000    );1001}1002 1003static void test_macros(testing & t) {1004    test_template(t, "simple macro",1005        "{% macro greet(name) %}Hello {{ name }}{% endmacro %}{{ greet('World') }}",1006        json::object(),1007        "Hello World"1008    );1009 1010    test_template(t, "macro default arg",1011        "{% macro greet(name='Guest') %}Hi {{ name }}{% endmacro %}{{ greet() }}",1012        json::object(),1013        "Hi Guest"1014    );1015 1016    test_template(t, "macro kwargs input",1017        "{% macro my_func(a, b=False) %}{% if b %}{{ a }}{% else %}nope{% endif %}{% endmacro %}{{ my_func(1, b=True) }}",1018        json::object(),1019        "1"1020    );1021 1022    test_template(t, "macro with multiple args",1023        "{% macro add(a, b, c=0) %}{{ a + b + c }}{% endmacro %}{{ add(1, 2) }},{{ add(1, 2, 3) }},{{ add(1, b=10) }},{{ add(1, 2, c=5) }}",1024        json::object(),1025        "3,6,11,8"1026    );1027 1028    test_template(t, "macro with kwarg out-of-order input",1029        "{% macro greet(first, last, greeting='Hello') %}{{ greeting }}, {{ first }} {{ last }}{% endmacro %}{{ greet(last='Smith', first='John') }},{{ greet(last='Doe', greeting='Hi', first='Jane') }}",1030        json::object(),1031        "Hello, John Smith,Hi, Jane Doe"1032    );1033 1034    test_template(t, "macro with caller",1035        "\1036{%- macro nest_dict(o, i, ff='') %}\n\1037  {{- caller(ff) }}\n\1038  {%- for k, v in o|items %}\n\1039    {{- i + k + ': ' }}\n\1040    {%- if v is mapping %}\n\1041      {{- '{' }}\n\1042      {% call(f) nest_dict(v, i + '    ') %}\n\1043        {{- 'fail' if ff is undefined }}\n\1044      {%- endcall %}\n\1045      {{- i + '}' }}\n\1046    {% else %}\n\1047      {{- v|string }}\n\1048    {% endif %}\n\1049  {%- endfor %}\n\1050{%- endmacro %}\n\1051{%- call(f) nest_dict({'root1': 1, 'root2': {'nest1': 1, 'nest2': {'nest3': 2}}}, '    ', 'Dict') %}\n\1052  {{- 'fail' if ff is defined }}\n\1053  {{- f + ' {' }}\n\1054{% endcall %}\n\1055{{- '}' }}",1056        json::object(),1057        "Dict {\n    root1: 1\n    root2: {\n        nest1: 1\n        nest2: {\n            nest3: 2\n        }\n    }\n}"1058    );1059}1060 1061static void test_namespace(testing & t) {1062    test_template(t, "namespace counter",1063        "{% set ns = namespace(count=0) %}{% for i in range(3) %}{% set ns.count = ns.count + 1 %}{% endfor %}{{ ns.count }}",1064        json::object(),1065        "3"1066    );1067}1068 1069static void test_tests(testing & t) {1070    test_template(t, "is odd",1071        "{% if 3 is odd %}yes{% endif %}",1072        json::object(),1073        "yes"1074    );1075 1076    test_template(t, "is even",1077        "{% if 4 is even %}yes{% endif %}",1078        json::object(),1079        "yes"1080    );1081 1082    test_template(t, "is false",1083        "{{ 'yes' if x is false }}",1084        {{"x", false}},1085        "yes"1086    );1087 1088    test_template(t, "is true",1089        "{{ 'yes' if x is true }}",1090        {{"x", true}},1091        "yes"1092    );1093 1094    test_template(t, "string is false",1095        "{{ 'yes' if x is false else 'no' }}",1096        {{"x", ""}},1097        "no"1098    );1099 1100    test_template(t, "is divisibleby",1101        "{{ 'yes' if x is divisibleby(2) }}",1102        {{"x", 2}},1103        "yes"1104    );1105 1106    test_template(t, "is eq",1107        "{{ 'yes' if 3 is eq(3) }}",1108        json::object(),1109        "yes"1110    );1111 1112    test_template(t, "is not equalto",1113        "{{ 'yes' if 3 is not equalto(4) }}",1114        json::object(),1115        "yes"1116    );1117 1118    test_template(t, "is ge",1119        "{{ 'yes' if 3 is ge(3) }}",1120        json::object(),1121        "yes"1122    );1123 1124    test_template(t, "is gt",1125        "{{ 'yes' if 3 is gt(2) }}",1126        json::object(),1127        "yes"1128    );1129 1130    test_template(t, "is greaterthan",1131        "{{ 'yes' if 3 is greaterthan(2) }}",1132        json::object(),1133        "yes"1134    );1135 1136    test_template(t, "is lt",1137        "{{ 'yes' if 2 is lt(3) }}",1138        json::object(),1139        "yes"1140    );1141 1142    test_template(t, "is lessthan",1143        "{{ 'yes' if 2 is lessthan(3) }}",1144        json::object(),1145        "yes"1146    );1147 1148    test_template(t, "is ne",1149        "{{ 'yes' if 2 is ne(3) }}",1150        json::object(),1151        "yes"1152    );1153 1154    test_template(t, "is lower",1155        "{{ 'yes' if 'lowercase' is lower }}",1156        json::object(),1157        "yes"1158    );1159 1160    test_template(t, "is upper",1161        "{{ 'yes' if 'UPPERCASE' is upper }}",1162        json::object(),1163        "yes"1164    );1165 1166    test_template(t, "is sameas",1167        "{{ 'yes' if x is sameas(false) }}",1168        {{"x", false}},1169        "yes"1170    );1171 1172    test_template(t, "is boolean",1173        "{{ 'yes' if x is boolean }}",1174        {{"x", true}},1175        "yes"1176    );1177 1178    test_template(t, "is callable",1179        "{{ 'yes' if ''.strip is callable }}",1180        json::object(),1181        "yes"1182    );1183 1184    test_template(t, "is escaped",1185        "{{ 'yes' if 'foo'|safe is escaped }}",1186        json::object(),1187        "yes"1188    );1189 1190    test_template(t, "is filter",1191        "{{ 'yes' if 'trim' is filter }}",1192        json::object(),1193        "yes"1194    );1195 1196    test_template(t, "is float",1197        "{{ 'yes' if x is float }}",1198        {{"x", 1.1}},1199        "yes"1200    );

Showing the first 1,200 of 2731 lines. Download the file for the rest.