Path: blob/main/contrib/kyua/utils/text/templates_test.cpp
48180 views
// Copyright 2012 The Kyua Authors.1// All rights reserved.2//3// Redistribution and use in source and binary forms, with or without4// modification, are permitted provided that the following conditions are5// met:6//7// * Redistributions of source code must retain the above copyright8// notice, this list of conditions and the following disclaimer.9// * Redistributions in binary form must reproduce the above copyright10// notice, this list of conditions and the following disclaimer in the11// documentation and/or other materials provided with the distribution.12// * Neither the name of Google Inc. nor the names of its contributors13// may be used to endorse or promote products derived from this software14// without specific prior written permission.15//16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.2728#include "utils/text/templates.hpp"2930#include <fstream>31#include <sstream>3233#include <atf-c++.hpp>3435#include "utils/fs/operations.hpp"36#include "utils/fs/path.hpp"37#include "utils/text/exceptions.hpp"3839namespace fs = utils::fs;40namespace text = utils::text;414243namespace {444546/// Applies a set of templates to an input string and validates the output.47///48/// This fails the test case if exp_output does not match the document generated49/// by the application of the templates.50///51/// \param templates The templates to apply.52/// \param input_str The input document to which to apply the templates.53/// \param exp_output The expected output document.54static void55do_test_ok(const text::templates_def& templates, const std::string& input_str,56const std::string& exp_output)57{58std::istringstream input(input_str);59std::ostringstream output;6061text::instantiate(templates, input, output);62ATF_REQUIRE_EQ(exp_output, output.str());63}646566/// Applies a set of templates to an input string and checks for an error.67///68/// This fails the test case if the exception raised by the template processing69/// does not match the expected message.70///71/// \param templates The templates to apply.72/// \param input_str The input document to which to apply the templates.73/// \param exp_message The expected error message in the raised exception.74static void75do_test_fail(const text::templates_def& templates, const std::string& input_str,76const std::string& exp_message)77{78std::istringstream input(input_str);79std::ostringstream output;8081ATF_REQUIRE_THROW_RE(text::syntax_error, exp_message,82text::instantiate(templates, input, output));83}848586} // anonymous namespace878889ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_variable__first);90ATF_TEST_CASE_BODY(templates_def__add_variable__first)91{92text::templates_def templates;93templates.add_variable("the-name", "first-value");94ATF_REQUIRE_EQ("first-value", templates.get_variable("the-name"));95}969798ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_variable__replace);99ATF_TEST_CASE_BODY(templates_def__add_variable__replace)100{101text::templates_def templates;102templates.add_variable("the-name", "first-value");103templates.add_variable("the-name", "second-value");104ATF_REQUIRE_EQ("second-value", templates.get_variable("the-name"));105}106107108ATF_TEST_CASE_WITHOUT_HEAD(templates_def__remove_variable);109ATF_TEST_CASE_BODY(templates_def__remove_variable)110{111text::templates_def templates;112templates.add_variable("the-name", "the-value");113templates.get_variable("the-name"); // Should not throw.114templates.remove_variable("the-name");115ATF_REQUIRE_THROW(text::syntax_error, templates.get_variable("the-name"));116}117118119ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_vector__first);120ATF_TEST_CASE_BODY(templates_def__add_vector__first)121{122text::templates_def templates;123templates.add_vector("the-name");124ATF_REQUIRE(templates.get_vector("the-name").empty());125}126127128ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_vector__replace);129ATF_TEST_CASE_BODY(templates_def__add_vector__replace)130{131text::templates_def templates;132templates.add_vector("the-name");133templates.add_to_vector("the-name", "foo");134ATF_REQUIRE(!templates.get_vector("the-name").empty());135templates.add_vector("the-name");136ATF_REQUIRE(templates.get_vector("the-name").empty());137}138139140ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_to_vector);141ATF_TEST_CASE_BODY(templates_def__add_to_vector)142{143text::templates_def templates;144templates.add_vector("the-name");145ATF_REQUIRE_EQ(0, templates.get_vector("the-name").size());146templates.add_to_vector("the-name", "first");147ATF_REQUIRE_EQ(1, templates.get_vector("the-name").size());148templates.add_to_vector("the-name", "second");149ATF_REQUIRE_EQ(2, templates.get_vector("the-name").size());150templates.add_to_vector("the-name", "third");151ATF_REQUIRE_EQ(3, templates.get_vector("the-name").size());152153std::vector< std::string > expected;154expected.push_back("first");155expected.push_back("second");156expected.push_back("third");157ATF_REQUIRE(expected == templates.get_vector("the-name"));158}159160161ATF_TEST_CASE_WITHOUT_HEAD(templates_def__exists__variable);162ATF_TEST_CASE_BODY(templates_def__exists__variable)163{164text::templates_def templates;165ATF_REQUIRE(!templates.exists("some-name"));166templates.add_variable("some-name ", "foo");167ATF_REQUIRE(!templates.exists("some-name"));168templates.add_variable("some-name", "foo");169ATF_REQUIRE(templates.exists("some-name"));170}171172173ATF_TEST_CASE_WITHOUT_HEAD(templates_def__exists__vector);174ATF_TEST_CASE_BODY(templates_def__exists__vector)175{176text::templates_def templates;177ATF_REQUIRE(!templates.exists("some-name"));178templates.add_vector("some-name ");179ATF_REQUIRE(!templates.exists("some-name"));180templates.add_vector("some-name");181ATF_REQUIRE(templates.exists("some-name"));182}183184185ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_variable__ok);186ATF_TEST_CASE_BODY(templates_def__get_variable__ok)187{188text::templates_def templates;189templates.add_variable("foo", "");190templates.add_variable("bar", " baz ");191ATF_REQUIRE_EQ("", templates.get_variable("foo"));192ATF_REQUIRE_EQ(" baz ", templates.get_variable("bar"));193}194195196ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_variable__unknown);197ATF_TEST_CASE_BODY(templates_def__get_variable__unknown)198{199text::templates_def templates;200templates.add_variable("foo", "");201ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown variable 'foo '",202templates.get_variable("foo "));203}204205206ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_vector__ok);207ATF_TEST_CASE_BODY(templates_def__get_vector__ok)208{209text::templates_def templates;210templates.add_vector("foo");211templates.add_vector("bar");212templates.add_to_vector("bar", "baz");213ATF_REQUIRE_EQ(0, templates.get_vector("foo").size());214ATF_REQUIRE_EQ(1, templates.get_vector("bar").size());215}216217218ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_vector__unknown);219ATF_TEST_CASE_BODY(templates_def__get_vector__unknown)220{221text::templates_def templates;222templates.add_vector("foo");223ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown vector 'foo '",224templates.get_vector("foo "));225}226227228ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__variable__ok);229ATF_TEST_CASE_BODY(templates_def__evaluate__variable__ok)230{231text::templates_def templates;232templates.add_variable("foo", "");233templates.add_variable("bar", " baz ");234ATF_REQUIRE_EQ("", templates.evaluate("foo"));235ATF_REQUIRE_EQ(" baz ", templates.evaluate("bar"));236}237238239ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__variable__unknown);240ATF_TEST_CASE_BODY(templates_def__evaluate__variable__unknown)241{242text::templates_def templates;243templates.add_variable("foo", "");244ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown variable 'foo1'",245templates.evaluate("foo1"));246}247248249ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__ok);250ATF_TEST_CASE_BODY(templates_def__evaluate__vector__ok)251{252text::templates_def templates;253templates.add_vector("v");254templates.add_to_vector("v", "foo");255templates.add_to_vector("v", "bar");256templates.add_to_vector("v", "baz");257258templates.add_variable("index", "0");259ATF_REQUIRE_EQ("foo", templates.evaluate("v(index)"));260templates.add_variable("index", "1");261ATF_REQUIRE_EQ("bar", templates.evaluate("v(index)"));262templates.add_variable("index", "2");263ATF_REQUIRE_EQ("baz", templates.evaluate("v(index)"));264}265266267ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__unknown_vector);268ATF_TEST_CASE_BODY(templates_def__evaluate__vector__unknown_vector)269{270text::templates_def templates;271templates.add_vector("v");272templates.add_to_vector("v", "foo");273templates.add_variable("index", "0");274ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown vector 'fooz'",275templates.evaluate("fooz(index)"));276}277278279ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__unknown_index);280ATF_TEST_CASE_BODY(templates_def__evaluate__vector__unknown_index)281{282text::templates_def templates;283templates.add_vector("v");284templates.add_to_vector("v", "foo");285templates.add_variable("index", "0");286ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown variable 'indexz'",287templates.evaluate("v(indexz)"));288}289290291ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__out_of_range);292ATF_TEST_CASE_BODY(templates_def__evaluate__vector__out_of_range)293{294text::templates_def templates;295templates.add_vector("v");296templates.add_to_vector("v", "foo");297templates.add_variable("index", "1");298ATF_REQUIRE_THROW_RE(text::syntax_error, "Index 'index' out of range "299"at position '1'", templates.evaluate("v(index)"));300}301302303ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__defined);304ATF_TEST_CASE_BODY(templates_def__evaluate__defined)305{306text::templates_def templates;307templates.add_vector("the-variable");308templates.add_vector("the-vector");309ATF_REQUIRE_EQ("false", templates.evaluate("defined(the-variabl)"));310ATF_REQUIRE_EQ("false", templates.evaluate("defined(the-vecto)"));311ATF_REQUIRE_EQ("true", templates.evaluate("defined(the-variable)"));312ATF_REQUIRE_EQ("true", templates.evaluate("defined(the-vector)"));313}314315316ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__length__ok);317ATF_TEST_CASE_BODY(templates_def__evaluate__length__ok)318{319text::templates_def templates;320templates.add_vector("v");321ATF_REQUIRE_EQ("0", templates.evaluate("length(v)"));322templates.add_to_vector("v", "foo");323ATF_REQUIRE_EQ("1", templates.evaluate("length(v)"));324templates.add_to_vector("v", "bar");325ATF_REQUIRE_EQ("2", templates.evaluate("length(v)"));326templates.add_to_vector("v", "baz");327ATF_REQUIRE_EQ("3", templates.evaluate("length(v)"));328}329330331ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__length__unknown_vector);332ATF_TEST_CASE_BODY(templates_def__evaluate__length__unknown_vector)333{334text::templates_def templates;335templates.add_vector("foo1");336ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown vector 'foo'",337templates.evaluate("length(foo)"));338}339340341ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__parenthesis_error);342ATF_TEST_CASE_BODY(templates_def__evaluate__parenthesis_error)343{344text::templates_def templates;345ATF_REQUIRE_THROW_RE(text::syntax_error,346"Expected '\\)' in.*'foo\\(abc'",347templates.evaluate("foo(abc"));348ATF_REQUIRE_THROW_RE(text::syntax_error,349"Unexpected text.*'\\)' in.*'a\\(b\\)c'",350templates.evaluate("a(b)c"));351}352353354ATF_TEST_CASE_WITHOUT_HEAD(instantiate__empty_input);355ATF_TEST_CASE_BODY(instantiate__empty_input)356{357const text::templates_def templates;358do_test_ok(templates, "", "");359}360361362ATF_TEST_CASE_WITHOUT_HEAD(instantiate__value__ok);363ATF_TEST_CASE_BODY(instantiate__value__ok)364{365const std::string input =366"first line\n"367"%%testvar1%%\n"368"third line\n"369"%%testvar2%% %%testvar3%%%%testvar4%%\n"370"fifth line\n";371372const std::string exp_output =373"first line\n"374"second line\n"375"third line\n"376"fourth line.\n"377"fifth line\n";378379text::templates_def templates;380templates.add_variable("testvar1", "second line");381templates.add_variable("testvar2", "fourth");382templates.add_variable("testvar3", "line");383templates.add_variable("testvar4", ".");384385do_test_ok(templates, input, exp_output);386}387388389ATF_TEST_CASE_WITHOUT_HEAD(instantiate__value__unknown_variable);390ATF_TEST_CASE_BODY(instantiate__value__unknown_variable)391{392const std::string input =393"%%testvar1%%\n";394395text::templates_def templates;396templates.add_variable("testvar2", "fourth line");397398do_test_fail(templates, input, "Unknown variable 'testvar1'");399}400401402ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_length__ok);403ATF_TEST_CASE_BODY(instantiate__vector_length__ok)404{405const std::string input =406"%%length(testvector1)%%\n"407"%%length(testvector2)%% - %%length(testvector3)%%\n";408409const std::string exp_output =410"4\n"411"0 - 1\n";412413text::templates_def templates;414templates.add_vector("testvector1");415templates.add_to_vector("testvector1", "000");416templates.add_to_vector("testvector1", "111");417templates.add_to_vector("testvector1", "543");418templates.add_to_vector("testvector1", "999");419templates.add_vector("testvector2");420templates.add_vector("testvector3");421templates.add_to_vector("testvector3", "123");422423do_test_ok(templates, input, exp_output);424}425426427ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_length__unknown_vector);428ATF_TEST_CASE_BODY(instantiate__vector_length__unknown_vector)429{430const std::string input =431"%%length(testvector)%%\n";432433text::templates_def templates;434templates.add_vector("testvector2");435436do_test_fail(templates, input, "Unknown vector 'testvector'");437}438439440ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__ok);441ATF_TEST_CASE_BODY(instantiate__vector_value__ok)442{443const std::string input =444"first line\n"445"%%testvector1(i)%%\n"446"third line\n"447"%%testvector2(j)%%\n"448"fifth line\n";449450const std::string exp_output =451"first line\n"452"543\n"453"third line\n"454"123\n"455"fifth line\n";456457text::templates_def templates;458templates.add_variable("i", "2");459templates.add_variable("j", "0");460templates.add_vector("testvector1");461templates.add_to_vector("testvector1", "000");462templates.add_to_vector("testvector1", "111");463templates.add_to_vector("testvector1", "543");464templates.add_to_vector("testvector1", "999");465templates.add_vector("testvector2");466templates.add_to_vector("testvector2", "123");467468do_test_ok(templates, input, exp_output);469}470471472ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__unknown_vector);473ATF_TEST_CASE_BODY(instantiate__vector_value__unknown_vector)474{475const std::string input =476"%%testvector(j)%%\n";477478text::templates_def templates;479templates.add_vector("testvector2");480481do_test_fail(templates, input, "Unknown vector 'testvector'");482}483484485ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__out_of_range__empty);486ATF_TEST_CASE_BODY(instantiate__vector_value__out_of_range__empty)487{488const std::string input =489"%%testvector(j)%%\n";490491text::templates_def templates;492templates.add_vector("testvector");493templates.add_variable("j", "0");494495do_test_fail(templates, input, "Index 'j' out of range at position '0'");496}497498499ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__out_of_range__not_empty);500ATF_TEST_CASE_BODY(instantiate__vector_value__out_of_range__not_empty)501{502const std::string input =503"%%testvector(j)%%\n";504505text::templates_def templates;506templates.add_vector("testvector");507templates.add_to_vector("testvector", "a");508templates.add_to_vector("testvector", "b");509templates.add_variable("j", "2");510511do_test_fail(templates, input, "Index 'j' out of range at position '2'");512}513514515ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__one_level__taken);516ATF_TEST_CASE_BODY(instantiate__if__one_level__taken)517{518const std::string input =519"first line\n"520"%if defined(some_var)\n"521"hello from within the variable conditional\n"522"%endif\n"523"%if defined(some_vector)\n"524"hello from within the vector conditional\n"525"%else\n"526"bye from within the vector conditional\n"527"%endif\n"528"some more\n";529530const std::string exp_output =531"first line\n"532"hello from within the variable conditional\n"533"hello from within the vector conditional\n"534"some more\n";535536text::templates_def templates;537templates.add_variable("some_var", "zzz");538templates.add_vector("some_vector");539540do_test_ok(templates, input, exp_output);541}542543544ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__one_level__not_taken);545ATF_TEST_CASE_BODY(instantiate__if__one_level__not_taken)546{547const std::string input =548"first line\n"549"%if defined(some_var)\n"550"hello from within the variable conditional\n"551"%endif\n"552"%if defined(some_vector)\n"553"hello from within the vector conditional\n"554"%else\n"555"bye from within the vector conditional\n"556"%endif\n"557"some more\n";558559const std::string exp_output =560"first line\n"561"bye from within the vector conditional\n"562"some more\n";563564text::templates_def templates;565566do_test_ok(templates, input, exp_output);567}568569570ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__multiple_levels__taken);571ATF_TEST_CASE_BODY(instantiate__if__multiple_levels__taken)572{573const std::string input =574"first line\n"575"%if defined(var1)\n"576"first before\n"577"%if length(var2)\n"578"second before\n"579"%if defined(var3)\n"580"third before\n"581"hello from within the conditional\n"582"third after\n"583"%endif\n"584"second after\n"585"%else\n"586"second after not shown\n"587"%endif\n"588"first after\n"589"%endif\n"590"some more\n";591592const std::string exp_output =593"first line\n"594"first before\n"595"second before\n"596"third before\n"597"hello from within the conditional\n"598"third after\n"599"second after\n"600"first after\n"601"some more\n";602603text::templates_def templates;604templates.add_variable("var1", "false");605templates.add_vector("var2");606templates.add_to_vector("var2", "not-empty");607templates.add_variable("var3", "foobar");608609do_test_ok(templates, input, exp_output);610}611612613ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__multiple_levels__not_taken);614ATF_TEST_CASE_BODY(instantiate__if__multiple_levels__not_taken)615{616const std::string input =617"first line\n"618"%if defined(var1)\n"619"first before\n"620"%if length(var2)\n"621"second before\n"622"%if defined(var3)\n"623"third before\n"624"hello from within the conditional\n"625"third after\n"626"%else\n"627"will not be shown either\n"628"%endif\n"629"second after\n"630"%else\n"631"second after shown\n"632"%endif\n"633"first after\n"634"%endif\n"635"some more\n";636637const std::string exp_output =638"first line\n"639"first before\n"640"second after shown\n"641"first after\n"642"some more\n";643644text::templates_def templates;645templates.add_variable("var1", "false");646templates.add_vector("var2");647templates.add_vector("var3");648649do_test_ok(templates, input, exp_output);650}651652653ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__no_iterations);654ATF_TEST_CASE_BODY(instantiate__loop__no_iterations)655{656const std::string input =657"first line\n"658"%loop table1 i\n"659"hello\n"660"value in vector: %%table1(i)%%\n"661"%if defined(var1)\n" "some other text\n" "%endif\n"662"%endloop\n"663"some more\n";664665const std::string exp_output =666"first line\n"667"some more\n";668669text::templates_def templates;670templates.add_variable("var1", "defined");671templates.add_vector("table1");672673do_test_ok(templates, input, exp_output);674}675676677ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__multiple_iterations);678ATF_TEST_CASE_BODY(instantiate__loop__multiple_iterations)679{680const std::string input =681"first line\n"682"%loop table1 i\n"683"hello %%table1(i)%% %%table2(i)%%\n"684"%endloop\n"685"some more\n";686687const std::string exp_output =688"first line\n"689"hello foo1 foo2\n"690"hello bar1 bar2\n"691"some more\n";692693text::templates_def templates;694templates.add_vector("table1");695templates.add_to_vector("table1", "foo1");696templates.add_to_vector("table1", "bar1");697templates.add_vector("table2");698templates.add_to_vector("table2", "foo2");699templates.add_to_vector("table2", "bar2");700701do_test_ok(templates, input, exp_output);702}703704705ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__nested__no_iterations);706ATF_TEST_CASE_BODY(instantiate__loop__nested__no_iterations)707{708const std::string input =709"first line\n"710"%loop table1 i\n"711"before: %%table1(i)%%\n"712"%loop table2 j\n"713"before: %%table2(j)%%\n"714"%loop table3 k\n"715"%%table3(k)%%\n"716"%endloop\n"717"after: %%table2(i)%%\n"718"%endloop\n"719"after: %%table1(i)%%\n"720"%endloop\n"721"some more\n";722723const std::string exp_output =724"first line\n"725"before: a\n"726"after: a\n"727"before: b\n"728"after: b\n"729"some more\n";730731text::templates_def templates;732templates.add_vector("table1");733templates.add_to_vector("table1", "a");734templates.add_to_vector("table1", "b");735templates.add_vector("table2");736templates.add_vector("table3");737templates.add_to_vector("table3", "1");738739do_test_ok(templates, input, exp_output);740}741742743ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__nested__multiple_iterations);744ATF_TEST_CASE_BODY(instantiate__loop__nested__multiple_iterations)745{746const std::string input =747"first line\n"748"%loop table1 i\n"749"%loop table2 j\n"750"%%table1(i)%% %%table2(j)%%\n"751"%endloop\n"752"%endloop\n"753"some more\n";754755const std::string exp_output =756"first line\n"757"a 1\n"758"a 2\n"759"a 3\n"760"b 1\n"761"b 2\n"762"b 3\n"763"some more\n";764765text::templates_def templates;766templates.add_vector("table1");767templates.add_to_vector("table1", "a");768templates.add_to_vector("table1", "b");769templates.add_vector("table2");770templates.add_to_vector("table2", "1");771templates.add_to_vector("table2", "2");772templates.add_to_vector("table2", "3");773774do_test_ok(templates, input, exp_output);775}776777778ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__sequential);779ATF_TEST_CASE_BODY(instantiate__loop__sequential)780{781const std::string input =782"first line\n"783"%loop table1 iter\n"784"1: %%table1(iter)%%\n"785"%endloop\n"786"divider\n"787"%loop table2 iter\n"788"2: %%table2(iter)%%\n"789"%endloop\n"790"divider\n"791"%loop table3 iter\n"792"3: %%table3(iter)%%\n"793"%endloop\n"794"divider\n"795"%loop table4 iter\n"796"4: %%table4(iter)%%\n"797"%endloop\n"798"some more\n";799800const std::string exp_output =801"first line\n"802"1: a\n"803"1: b\n"804"divider\n"805"divider\n"806"divider\n"807"4: 1\n"808"4: 2\n"809"4: 3\n"810"some more\n";811812text::templates_def templates;813templates.add_vector("table1");814templates.add_to_vector("table1", "a");815templates.add_to_vector("table1", "b");816templates.add_vector("table2");817templates.add_vector("table3");818templates.add_vector("table4");819templates.add_to_vector("table4", "1");820templates.add_to_vector("table4", "2");821templates.add_to_vector("table4", "3");822823do_test_ok(templates, input, exp_output);824}825826827ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__scoping);828ATF_TEST_CASE_BODY(instantiate__loop__scoping)829{830const std::string input =831"%loop table1 i\n"832"%if defined(i)\n" "i defined inside scope 1\n" "%endif\n"833"%loop table2 j\n"834"%if defined(i)\n" "i defined inside scope 2\n" "%endif\n"835"%if defined(j)\n" "j defined inside scope 2\n" "%endif\n"836"%endloop\n"837"%if defined(j)\n" "j defined inside scope 1\n" "%endif\n"838"%endloop\n"839"%if defined(i)\n" "i defined outside\n" "%endif\n"840"%if defined(j)\n" "j defined outside\n" "%endif\n";841842const std::string exp_output =843"i defined inside scope 1\n"844"i defined inside scope 2\n"845"j defined inside scope 2\n"846"i defined inside scope 1\n"847"i defined inside scope 2\n"848"j defined inside scope 2\n";849850text::templates_def templates;851templates.add_vector("table1");852templates.add_to_vector("table1", "first");853templates.add_to_vector("table1", "second");854templates.add_vector("table2");855templates.add_to_vector("table2", "first");856857do_test_ok(templates, input, exp_output);858}859860861ATF_TEST_CASE_WITHOUT_HEAD(instantiate__mismatched_delimiters);862ATF_TEST_CASE_BODY(instantiate__mismatched_delimiters)863{864const std::string input =865"this is some %% text\n"866"and this is %%var%% text%%\n";867868const std::string exp_output =869"this is some %% text\n"870"and this is some more text%%\n";871872text::templates_def templates;873templates.add_variable("var", "some more");874875do_test_ok(templates, input, exp_output);876}877878879ATF_TEST_CASE_WITHOUT_HEAD(instantiate__empty_statement);880ATF_TEST_CASE_BODY(instantiate__empty_statement)881{882do_test_fail(text::templates_def(), "%\n", "Empty statement");883}884885886ATF_TEST_CASE_WITHOUT_HEAD(instantiate__unknown_statement);887ATF_TEST_CASE_BODY(instantiate__unknown_statement)888{889do_test_fail(text::templates_def(), "%if2\n", "Unknown statement 'if2'");890}891892893ATF_TEST_CASE_WITHOUT_HEAD(instantiate__invalid_narguments);894ATF_TEST_CASE_BODY(instantiate__invalid_narguments)895{896do_test_fail(text::templates_def(), "%if a b\n",897"Invalid number of arguments for statement 'if'");898}899900901ATF_TEST_CASE_WITHOUT_HEAD(instantiate__files__ok);902ATF_TEST_CASE_BODY(instantiate__files__ok)903{904text::templates_def templates;905templates.add_variable("string", "Hello, world!");906907atf::utils::create_file("input.txt", "The string is: %%string%%\n");908909text::instantiate(templates, fs::path("input.txt"), fs::path("output.txt"));910911std::ifstream output("output.txt");912std::string line;913ATF_REQUIRE(std::getline(output, line).good());914ATF_REQUIRE_EQ(line, "The string is: Hello, world!");915ATF_REQUIRE(std::getline(output, line).eof());916}917918919ATF_TEST_CASE_WITHOUT_HEAD(instantiate__files__input_error);920ATF_TEST_CASE_BODY(instantiate__files__input_error)921{922text::templates_def templates;923ATF_REQUIRE_THROW_RE(text::error, "Failed to open input.txt for read",924text::instantiate(templates, fs::path("input.txt"),925fs::path("output.txt")));926}927928929ATF_TEST_CASE(instantiate__files__output_error);930ATF_TEST_CASE_HEAD(instantiate__files__output_error)931{932set_md_var("require.user", "unprivileged");933}934ATF_TEST_CASE_BODY(instantiate__files__output_error)935{936text::templates_def templates;937938atf::utils::create_file("input.txt", "");939940fs::mkdir(fs::path("dir"), 0444);941942ATF_REQUIRE_THROW_RE(text::error, "Failed to open dir/output.txt for write",943text::instantiate(templates, fs::path("input.txt"),944fs::path("dir/output.txt")));945}946947948ATF_INIT_TEST_CASES(tcs)949{950ATF_ADD_TEST_CASE(tcs, templates_def__add_variable__first);951ATF_ADD_TEST_CASE(tcs, templates_def__add_variable__replace);952ATF_ADD_TEST_CASE(tcs, templates_def__remove_variable);953ATF_ADD_TEST_CASE(tcs, templates_def__add_vector__first);954ATF_ADD_TEST_CASE(tcs, templates_def__add_vector__replace);955ATF_ADD_TEST_CASE(tcs, templates_def__add_to_vector);956ATF_ADD_TEST_CASE(tcs, templates_def__exists__variable);957ATF_ADD_TEST_CASE(tcs, templates_def__exists__vector);958ATF_ADD_TEST_CASE(tcs, templates_def__get_variable__ok);959ATF_ADD_TEST_CASE(tcs, templates_def__get_variable__unknown);960ATF_ADD_TEST_CASE(tcs, templates_def__get_vector__ok);961ATF_ADD_TEST_CASE(tcs, templates_def__get_vector__unknown);962ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__variable__ok);963ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__variable__unknown);964ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__ok);965ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__unknown_vector);966ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__unknown_index);967ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__out_of_range);968ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__defined);969ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__length__ok);970ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__length__unknown_vector);971ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__parenthesis_error);972973ATF_ADD_TEST_CASE(tcs, instantiate__empty_input);974ATF_ADD_TEST_CASE(tcs, instantiate__value__ok);975ATF_ADD_TEST_CASE(tcs, instantiate__value__unknown_variable);976ATF_ADD_TEST_CASE(tcs, instantiate__vector_length__ok);977ATF_ADD_TEST_CASE(tcs, instantiate__vector_length__unknown_vector);978ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__ok);979ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__unknown_vector);980ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__out_of_range__empty);981ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__out_of_range__not_empty);982ATF_ADD_TEST_CASE(tcs, instantiate__if__one_level__taken);983ATF_ADD_TEST_CASE(tcs, instantiate__if__one_level__not_taken);984ATF_ADD_TEST_CASE(tcs, instantiate__if__multiple_levels__taken);985ATF_ADD_TEST_CASE(tcs, instantiate__if__multiple_levels__not_taken);986ATF_ADD_TEST_CASE(tcs, instantiate__loop__no_iterations);987ATF_ADD_TEST_CASE(tcs, instantiate__loop__multiple_iterations);988ATF_ADD_TEST_CASE(tcs, instantiate__loop__nested__no_iterations);989ATF_ADD_TEST_CASE(tcs, instantiate__loop__nested__multiple_iterations);990ATF_ADD_TEST_CASE(tcs, instantiate__loop__sequential);991ATF_ADD_TEST_CASE(tcs, instantiate__loop__scoping);992ATF_ADD_TEST_CASE(tcs, instantiate__mismatched_delimiters);993ATF_ADD_TEST_CASE(tcs, instantiate__empty_statement);994ATF_ADD_TEST_CASE(tcs, instantiate__unknown_statement);995ATF_ADD_TEST_CASE(tcs, instantiate__invalid_narguments);996997ATF_ADD_TEST_CASE(tcs, instantiate__files__ok);998ATF_ADD_TEST_CASE(tcs, instantiate__files__input_error);999ATF_ADD_TEST_CASE(tcs, instantiate__files__output_error);1000}100110021003