aboutsummaryrefslogtreecommitdiffstats
path: root/utils/text/templates_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/text/templates_test.cpp')
-rw-r--r--utils/text/templates_test.cpp1001
1 files changed, 1001 insertions, 0 deletions
diff --git a/utils/text/templates_test.cpp b/utils/text/templates_test.cpp
new file mode 100644
index 000000000000..4524dc61a416
--- /dev/null
+++ b/utils/text/templates_test.cpp
@@ -0,0 +1,1001 @@
+// Copyright 2012 The Kyua Authors.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "utils/text/templates.hpp"
+
+#include <fstream>
+#include <sstream>
+
+#include <atf-c++.hpp>
+
+#include "utils/fs/operations.hpp"
+#include "utils/fs/path.hpp"
+#include "utils/text/exceptions.hpp"
+
+namespace fs = utils::fs;
+namespace text = utils::text;
+
+
+namespace {
+
+
+/// Applies a set of templates to an input string and validates the output.
+///
+/// This fails the test case if exp_output does not match the document generated
+/// by the application of the templates.
+///
+/// \param templates The templates to apply.
+/// \param input_str The input document to which to apply the templates.
+/// \param exp_output The expected output document.
+static void
+do_test_ok(const text::templates_def& templates, const std::string& input_str,
+ const std::string& exp_output)
+{
+ std::istringstream input(input_str);
+ std::ostringstream output;
+
+ text::instantiate(templates, input, output);
+ ATF_REQUIRE_EQ(exp_output, output.str());
+}
+
+
+/// Applies a set of templates to an input string and checks for an error.
+///
+/// This fails the test case if the exception raised by the template processing
+/// does not match the expected message.
+///
+/// \param templates The templates to apply.
+/// \param input_str The input document to which to apply the templates.
+/// \param exp_message The expected error message in the raised exception.
+static void
+do_test_fail(const text::templates_def& templates, const std::string& input_str,
+ const std::string& exp_message)
+{
+ std::istringstream input(input_str);
+ std::ostringstream output;
+
+ ATF_REQUIRE_THROW_RE(text::syntax_error, exp_message,
+ text::instantiate(templates, input, output));
+}
+
+
+} // anonymous namespace
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_variable__first);
+ATF_TEST_CASE_BODY(templates_def__add_variable__first)
+{
+ text::templates_def templates;
+ templates.add_variable("the-name", "first-value");
+ ATF_REQUIRE_EQ("first-value", templates.get_variable("the-name"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_variable__replace);
+ATF_TEST_CASE_BODY(templates_def__add_variable__replace)
+{
+ text::templates_def templates;
+ templates.add_variable("the-name", "first-value");
+ templates.add_variable("the-name", "second-value");
+ ATF_REQUIRE_EQ("second-value", templates.get_variable("the-name"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__remove_variable);
+ATF_TEST_CASE_BODY(templates_def__remove_variable)
+{
+ text::templates_def templates;
+ templates.add_variable("the-name", "the-value");
+ templates.get_variable("the-name"); // Should not throw.
+ templates.remove_variable("the-name");
+ ATF_REQUIRE_THROW(text::syntax_error, templates.get_variable("the-name"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_vector__first);
+ATF_TEST_CASE_BODY(templates_def__add_vector__first)
+{
+ text::templates_def templates;
+ templates.add_vector("the-name");
+ ATF_REQUIRE(templates.get_vector("the-name").empty());
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_vector__replace);
+ATF_TEST_CASE_BODY(templates_def__add_vector__replace)
+{
+ text::templates_def templates;
+ templates.add_vector("the-name");
+ templates.add_to_vector("the-name", "foo");
+ ATF_REQUIRE(!templates.get_vector("the-name").empty());
+ templates.add_vector("the-name");
+ ATF_REQUIRE(templates.get_vector("the-name").empty());
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_to_vector);
+ATF_TEST_CASE_BODY(templates_def__add_to_vector)
+{
+ text::templates_def templates;
+ templates.add_vector("the-name");
+ ATF_REQUIRE_EQ(0, templates.get_vector("the-name").size());
+ templates.add_to_vector("the-name", "first");
+ ATF_REQUIRE_EQ(1, templates.get_vector("the-name").size());
+ templates.add_to_vector("the-name", "second");
+ ATF_REQUIRE_EQ(2, templates.get_vector("the-name").size());
+ templates.add_to_vector("the-name", "third");
+ ATF_REQUIRE_EQ(3, templates.get_vector("the-name").size());
+
+ std::vector< std::string > expected;
+ expected.push_back("first");
+ expected.push_back("second");
+ expected.push_back("third");
+ ATF_REQUIRE(expected == templates.get_vector("the-name"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__exists__variable);
+ATF_TEST_CASE_BODY(templates_def__exists__variable)
+{
+ text::templates_def templates;
+ ATF_REQUIRE(!templates.exists("some-name"));
+ templates.add_variable("some-name ", "foo");
+ ATF_REQUIRE(!templates.exists("some-name"));
+ templates.add_variable("some-name", "foo");
+ ATF_REQUIRE(templates.exists("some-name"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__exists__vector);
+ATF_TEST_CASE_BODY(templates_def__exists__vector)
+{
+ text::templates_def templates;
+ ATF_REQUIRE(!templates.exists("some-name"));
+ templates.add_vector("some-name ");
+ ATF_REQUIRE(!templates.exists("some-name"));
+ templates.add_vector("some-name");
+ ATF_REQUIRE(templates.exists("some-name"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_variable__ok);
+ATF_TEST_CASE_BODY(templates_def__get_variable__ok)
+{
+ text::templates_def templates;
+ templates.add_variable("foo", "");
+ templates.add_variable("bar", " baz ");
+ ATF_REQUIRE_EQ("", templates.get_variable("foo"));
+ ATF_REQUIRE_EQ(" baz ", templates.get_variable("bar"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_variable__unknown);
+ATF_TEST_CASE_BODY(templates_def__get_variable__unknown)
+{
+ text::templates_def templates;
+ templates.add_variable("foo", "");
+ ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown variable 'foo '",
+ templates.get_variable("foo "));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_vector__ok);
+ATF_TEST_CASE_BODY(templates_def__get_vector__ok)
+{
+ text::templates_def templates;
+ templates.add_vector("foo");
+ templates.add_vector("bar");
+ templates.add_to_vector("bar", "baz");
+ ATF_REQUIRE_EQ(0, templates.get_vector("foo").size());
+ ATF_REQUIRE_EQ(1, templates.get_vector("bar").size());
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_vector__unknown);
+ATF_TEST_CASE_BODY(templates_def__get_vector__unknown)
+{
+ text::templates_def templates;
+ templates.add_vector("foo");
+ ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown vector 'foo '",
+ templates.get_vector("foo "));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__variable__ok);
+ATF_TEST_CASE_BODY(templates_def__evaluate__variable__ok)
+{
+ text::templates_def templates;
+ templates.add_variable("foo", "");
+ templates.add_variable("bar", " baz ");
+ ATF_REQUIRE_EQ("", templates.evaluate("foo"));
+ ATF_REQUIRE_EQ(" baz ", templates.evaluate("bar"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__variable__unknown);
+ATF_TEST_CASE_BODY(templates_def__evaluate__variable__unknown)
+{
+ text::templates_def templates;
+ templates.add_variable("foo", "");
+ ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown variable 'foo1'",
+ templates.evaluate("foo1"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__ok);
+ATF_TEST_CASE_BODY(templates_def__evaluate__vector__ok)
+{
+ text::templates_def templates;
+ templates.add_vector("v");
+ templates.add_to_vector("v", "foo");
+ templates.add_to_vector("v", "bar");
+ templates.add_to_vector("v", "baz");
+
+ templates.add_variable("index", "0");
+ ATF_REQUIRE_EQ("foo", templates.evaluate("v(index)"));
+ templates.add_variable("index", "1");
+ ATF_REQUIRE_EQ("bar", templates.evaluate("v(index)"));
+ templates.add_variable("index", "2");
+ ATF_REQUIRE_EQ("baz", templates.evaluate("v(index)"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__unknown_vector);
+ATF_TEST_CASE_BODY(templates_def__evaluate__vector__unknown_vector)
+{
+ text::templates_def templates;
+ templates.add_vector("v");
+ templates.add_to_vector("v", "foo");
+ templates.add_variable("index", "0");
+ ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown vector 'fooz'",
+ templates.evaluate("fooz(index)"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__unknown_index);
+ATF_TEST_CASE_BODY(templates_def__evaluate__vector__unknown_index)
+{
+ text::templates_def templates;
+ templates.add_vector("v");
+ templates.add_to_vector("v", "foo");
+ templates.add_variable("index", "0");
+ ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown variable 'indexz'",
+ templates.evaluate("v(indexz)"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__out_of_range);
+ATF_TEST_CASE_BODY(templates_def__evaluate__vector__out_of_range)
+{
+ text::templates_def templates;
+ templates.add_vector("v");
+ templates.add_to_vector("v", "foo");
+ templates.add_variable("index", "1");
+ ATF_REQUIRE_THROW_RE(text::syntax_error, "Index 'index' out of range "
+ "at position '1'", templates.evaluate("v(index)"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__defined);
+ATF_TEST_CASE_BODY(templates_def__evaluate__defined)
+{
+ text::templates_def templates;
+ templates.add_vector("the-variable");
+ templates.add_vector("the-vector");
+ ATF_REQUIRE_EQ("false", templates.evaluate("defined(the-variabl)"));
+ ATF_REQUIRE_EQ("false", templates.evaluate("defined(the-vecto)"));
+ ATF_REQUIRE_EQ("true", templates.evaluate("defined(the-variable)"));
+ ATF_REQUIRE_EQ("true", templates.evaluate("defined(the-vector)"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__length__ok);
+ATF_TEST_CASE_BODY(templates_def__evaluate__length__ok)
+{
+ text::templates_def templates;
+ templates.add_vector("v");
+ ATF_REQUIRE_EQ("0", templates.evaluate("length(v)"));
+ templates.add_to_vector("v", "foo");
+ ATF_REQUIRE_EQ("1", templates.evaluate("length(v)"));
+ templates.add_to_vector("v", "bar");
+ ATF_REQUIRE_EQ("2", templates.evaluate("length(v)"));
+ templates.add_to_vector("v", "baz");
+ ATF_REQUIRE_EQ("3", templates.evaluate("length(v)"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__length__unknown_vector);
+ATF_TEST_CASE_BODY(templates_def__evaluate__length__unknown_vector)
+{
+ text::templates_def templates;
+ templates.add_vector("foo1");
+ ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown vector 'foo'",
+ templates.evaluate("length(foo)"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__parenthesis_error);
+ATF_TEST_CASE_BODY(templates_def__evaluate__parenthesis_error)
+{
+ text::templates_def templates;
+ ATF_REQUIRE_THROW_RE(text::syntax_error,
+ "Expected '\\)' in.*'foo\\(abc'",
+ templates.evaluate("foo(abc"));
+ ATF_REQUIRE_THROW_RE(text::syntax_error,
+ "Unexpected text.*'\\)' in.*'a\\(b\\)c'",
+ templates.evaluate("a(b)c"));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__empty_input);
+ATF_TEST_CASE_BODY(instantiate__empty_input)
+{
+ const text::templates_def templates;
+ do_test_ok(templates, "", "");
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__value__ok);
+ATF_TEST_CASE_BODY(instantiate__value__ok)
+{
+ const std::string input =
+ "first line\n"
+ "%%testvar1%%\n"
+ "third line\n"
+ "%%testvar2%% %%testvar3%%%%testvar4%%\n"
+ "fifth line\n";
+
+ const std::string exp_output =
+ "first line\n"
+ "second line\n"
+ "third line\n"
+ "fourth line.\n"
+ "fifth line\n";
+
+ text::templates_def templates;
+ templates.add_variable("testvar1", "second line");
+ templates.add_variable("testvar2", "fourth");
+ templates.add_variable("testvar3", "line");
+ templates.add_variable("testvar4", ".");
+
+ do_test_ok(templates, input, exp_output);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__value__unknown_variable);
+ATF_TEST_CASE_BODY(instantiate__value__unknown_variable)
+{
+ const std::string input =
+ "%%testvar1%%\n";
+
+ text::templates_def templates;
+ templates.add_variable("testvar2", "fourth line");
+
+ do_test_fail(templates, input, "Unknown variable 'testvar1'");
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_length__ok);
+ATF_TEST_CASE_BODY(instantiate__vector_length__ok)
+{
+ const std::string input =
+ "%%length(testvector1)%%\n"
+ "%%length(testvector2)%% - %%length(testvector3)%%\n";
+
+ const std::string exp_output =
+ "4\n"
+ "0 - 1\n";
+
+ text::templates_def templates;
+ templates.add_vector("testvector1");
+ templates.add_to_vector("testvector1", "000");
+ templates.add_to_vector("testvector1", "111");
+ templates.add_to_vector("testvector1", "543");
+ templates.add_to_vector("testvector1", "999");
+ templates.add_vector("testvector2");
+ templates.add_vector("testvector3");
+ templates.add_to_vector("testvector3", "123");
+
+ do_test_ok(templates, input, exp_output);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_length__unknown_vector);
+ATF_TEST_CASE_BODY(instantiate__vector_length__unknown_vector)
+{
+ const std::string input =
+ "%%length(testvector)%%\n";
+
+ text::templates_def templates;
+ templates.add_vector("testvector2");
+
+ do_test_fail(templates, input, "Unknown vector 'testvector'");
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__ok);
+ATF_TEST_CASE_BODY(instantiate__vector_value__ok)
+{
+ const std::string input =
+ "first line\n"
+ "%%testvector1(i)%%\n"
+ "third line\n"
+ "%%testvector2(j)%%\n"
+ "fifth line\n";
+
+ const std::string exp_output =
+ "first line\n"
+ "543\n"
+ "third line\n"
+ "123\n"
+ "fifth line\n";
+
+ text::templates_def templates;
+ templates.add_variable("i", "2");
+ templates.add_variable("j", "0");
+ templates.add_vector("testvector1");
+ templates.add_to_vector("testvector1", "000");
+ templates.add_to_vector("testvector1", "111");
+ templates.add_to_vector("testvector1", "543");
+ templates.add_to_vector("testvector1", "999");
+ templates.add_vector("testvector2");
+ templates.add_to_vector("testvector2", "123");
+
+ do_test_ok(templates, input, exp_output);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__unknown_vector);
+ATF_TEST_CASE_BODY(instantiate__vector_value__unknown_vector)
+{
+ const std::string input =
+ "%%testvector(j)%%\n";
+
+ text::templates_def templates;
+ templates.add_vector("testvector2");
+
+ do_test_fail(templates, input, "Unknown vector 'testvector'");
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__out_of_range__empty);
+ATF_TEST_CASE_BODY(instantiate__vector_value__out_of_range__empty)
+{
+ const std::string input =
+ "%%testvector(j)%%\n";
+
+ text::templates_def templates;
+ templates.add_vector("testvector");
+ templates.add_variable("j", "0");
+
+ do_test_fail(templates, input, "Index 'j' out of range at position '0'");
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__out_of_range__not_empty);
+ATF_TEST_CASE_BODY(instantiate__vector_value__out_of_range__not_empty)
+{
+ const std::string input =
+ "%%testvector(j)%%\n";
+
+ text::templates_def templates;
+ templates.add_vector("testvector");
+ templates.add_to_vector("testvector", "a");
+ templates.add_to_vector("testvector", "b");
+ templates.add_variable("j", "2");
+
+ do_test_fail(templates, input, "Index 'j' out of range at position '2'");
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__one_level__taken);
+ATF_TEST_CASE_BODY(instantiate__if__one_level__taken)
+{
+ const std::string input =
+ "first line\n"
+ "%if defined(some_var)\n"
+ "hello from within the variable conditional\n"
+ "%endif\n"
+ "%if defined(some_vector)\n"
+ "hello from within the vector conditional\n"
+ "%else\n"
+ "bye from within the vector conditional\n"
+ "%endif\n"
+ "some more\n";
+
+ const std::string exp_output =
+ "first line\n"
+ "hello from within the variable conditional\n"
+ "hello from within the vector conditional\n"
+ "some more\n";
+
+ text::templates_def templates;
+ templates.add_variable("some_var", "zzz");
+ templates.add_vector("some_vector");
+
+ do_test_ok(templates, input, exp_output);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__one_level__not_taken);
+ATF_TEST_CASE_BODY(instantiate__if__one_level__not_taken)
+{
+ const std::string input =
+ "first line\n"
+ "%if defined(some_var)\n"
+ "hello from within the variable conditional\n"
+ "%endif\n"
+ "%if defined(some_vector)\n"
+ "hello from within the vector conditional\n"
+ "%else\n"
+ "bye from within the vector conditional\n"
+ "%endif\n"
+ "some more\n";
+
+ const std::string exp_output =
+ "first line\n"
+ "bye from within the vector conditional\n"
+ "some more\n";
+
+ text::templates_def templates;
+
+ do_test_ok(templates, input, exp_output);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__multiple_levels__taken);
+ATF_TEST_CASE_BODY(instantiate__if__multiple_levels__taken)
+{
+ const std::string input =
+ "first line\n"
+ "%if defined(var1)\n"
+ "first before\n"
+ "%if length(var2)\n"
+ "second before\n"
+ "%if defined(var3)\n"
+ "third before\n"
+ "hello from within the conditional\n"
+ "third after\n"
+ "%endif\n"
+ "second after\n"
+ "%else\n"
+ "second after not shown\n"
+ "%endif\n"
+ "first after\n"
+ "%endif\n"
+ "some more\n";
+
+ const std::string exp_output =
+ "first line\n"
+ "first before\n"
+ "second before\n"
+ "third before\n"
+ "hello from within the conditional\n"
+ "third after\n"
+ "second after\n"
+ "first after\n"
+ "some more\n";
+
+ text::templates_def templates;
+ templates.add_variable("var1", "false");
+ templates.add_vector("var2");
+ templates.add_to_vector("var2", "not-empty");
+ templates.add_variable("var3", "foobar");
+
+ do_test_ok(templates, input, exp_output);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__multiple_levels__not_taken);
+ATF_TEST_CASE_BODY(instantiate__if__multiple_levels__not_taken)
+{
+ const std::string input =
+ "first line\n"
+ "%if defined(var1)\n"
+ "first before\n"
+ "%if length(var2)\n"
+ "second before\n"
+ "%if defined(var3)\n"
+ "third before\n"
+ "hello from within the conditional\n"
+ "third after\n"
+ "%else\n"
+ "will not be shown either\n"
+ "%endif\n"
+ "second after\n"
+ "%else\n"
+ "second after shown\n"
+ "%endif\n"
+ "first after\n"
+ "%endif\n"
+ "some more\n";
+
+ const std::string exp_output =
+ "first line\n"
+ "first before\n"
+ "second after shown\n"
+ "first after\n"
+ "some more\n";
+
+ text::templates_def templates;
+ templates.add_variable("var1", "false");
+ templates.add_vector("var2");
+ templates.add_vector("var3");
+
+ do_test_ok(templates, input, exp_output);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__no_iterations);
+ATF_TEST_CASE_BODY(instantiate__loop__no_iterations)
+{
+ const std::string input =
+ "first line\n"
+ "%loop table1 i\n"
+ "hello\n"
+ "value in vector: %%table1(i)%%\n"
+ "%if defined(var1)\n" "some other text\n" "%endif\n"
+ "%endloop\n"
+ "some more\n";
+
+ const std::string exp_output =
+ "first line\n"
+ "some more\n";
+
+ text::templates_def templates;
+ templates.add_variable("var1", "defined");
+ templates.add_vector("table1");
+
+ do_test_ok(templates, input, exp_output);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__multiple_iterations);
+ATF_TEST_CASE_BODY(instantiate__loop__multiple_iterations)
+{
+ const std::string input =
+ "first line\n"
+ "%loop table1 i\n"
+ "hello %%table1(i)%% %%table2(i)%%\n"
+ "%endloop\n"
+ "some more\n";
+
+ const std::string exp_output =
+ "first line\n"
+ "hello foo1 foo2\n"
+ "hello bar1 bar2\n"
+ "some more\n";
+
+ text::templates_def templates;
+ templates.add_vector("table1");
+ templates.add_to_vector("table1", "foo1");
+ templates.add_to_vector("table1", "bar1");
+ templates.add_vector("table2");
+ templates.add_to_vector("table2", "foo2");
+ templates.add_to_vector("table2", "bar2");
+
+ do_test_ok(templates, input, exp_output);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__nested__no_iterations);
+ATF_TEST_CASE_BODY(instantiate__loop__nested__no_iterations)
+{
+ const std::string input =
+ "first line\n"
+ "%loop table1 i\n"
+ "before: %%table1(i)%%\n"
+ "%loop table2 j\n"
+ "before: %%table2(j)%%\n"
+ "%loop table3 k\n"
+ "%%table3(k)%%\n"
+ "%endloop\n"
+ "after: %%table2(i)%%\n"
+ "%endloop\n"
+ "after: %%table1(i)%%\n"
+ "%endloop\n"
+ "some more\n";
+
+ const std::string exp_output =
+ "first line\n"
+ "before: a\n"
+ "after: a\n"
+ "before: b\n"
+ "after: b\n"
+ "some more\n";
+
+ text::templates_def templates;
+ templates.add_vector("table1");
+ templates.add_to_vector("table1", "a");
+ templates.add_to_vector("table1", "b");
+ templates.add_vector("table2");
+ templates.add_vector("table3");
+ templates.add_to_vector("table3", "1");
+
+ do_test_ok(templates, input, exp_output);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__nested__multiple_iterations);
+ATF_TEST_CASE_BODY(instantiate__loop__nested__multiple_iterations)
+{
+ const std::string input =
+ "first line\n"
+ "%loop table1 i\n"
+ "%loop table2 j\n"
+ "%%table1(i)%% %%table2(j)%%\n"
+ "%endloop\n"
+ "%endloop\n"
+ "some more\n";
+
+ const std::string exp_output =
+ "first line\n"
+ "a 1\n"
+ "a 2\n"
+ "a 3\n"
+ "b 1\n"
+ "b 2\n"
+ "b 3\n"
+ "some more\n";
+
+ text::templates_def templates;
+ templates.add_vector("table1");
+ templates.add_to_vector("table1", "a");
+ templates.add_to_vector("table1", "b");
+ templates.add_vector("table2");
+ templates.add_to_vector("table2", "1");
+ templates.add_to_vector("table2", "2");
+ templates.add_to_vector("table2", "3");
+
+ do_test_ok(templates, input, exp_output);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__sequential);
+ATF_TEST_CASE_BODY(instantiate__loop__sequential)
+{
+ const std::string input =
+ "first line\n"
+ "%loop table1 iter\n"
+ "1: %%table1(iter)%%\n"
+ "%endloop\n"
+ "divider\n"
+ "%loop table2 iter\n"
+ "2: %%table2(iter)%%\n"
+ "%endloop\n"
+ "divider\n"
+ "%loop table3 iter\n"
+ "3: %%table3(iter)%%\n"
+ "%endloop\n"
+ "divider\n"
+ "%loop table4 iter\n"
+ "4: %%table4(iter)%%\n"
+ "%endloop\n"
+ "some more\n";
+
+ const std::string exp_output =
+ "first line\n"
+ "1: a\n"
+ "1: b\n"
+ "divider\n"
+ "divider\n"
+ "divider\n"
+ "4: 1\n"
+ "4: 2\n"
+ "4: 3\n"
+ "some more\n";
+
+ text::templates_def templates;
+ templates.add_vector("table1");
+ templates.add_to_vector("table1", "a");
+ templates.add_to_vector("table1", "b");
+ templates.add_vector("table2");
+ templates.add_vector("table3");
+ templates.add_vector("table4");
+ templates.add_to_vector("table4", "1");
+ templates.add_to_vector("table4", "2");
+ templates.add_to_vector("table4", "3");
+
+ do_test_ok(templates, input, exp_output);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__scoping);
+ATF_TEST_CASE_BODY(instantiate__loop__scoping)
+{
+ const std::string input =
+ "%loop table1 i\n"
+ "%if defined(i)\n" "i defined inside scope 1\n" "%endif\n"
+ "%loop table2 j\n"
+ "%if defined(i)\n" "i defined inside scope 2\n" "%endif\n"
+ "%if defined(j)\n" "j defined inside scope 2\n" "%endif\n"
+ "%endloop\n"
+ "%if defined(j)\n" "j defined inside scope 1\n" "%endif\n"
+ "%endloop\n"
+ "%if defined(i)\n" "i defined outside\n" "%endif\n"
+ "%if defined(j)\n" "j defined outside\n" "%endif\n";
+
+ const std::string exp_output =
+ "i defined inside scope 1\n"
+ "i defined inside scope 2\n"
+ "j defined inside scope 2\n"
+ "i defined inside scope 1\n"
+ "i defined inside scope 2\n"
+ "j defined inside scope 2\n";
+
+ text::templates_def templates;
+ templates.add_vector("table1");
+ templates.add_to_vector("table1", "first");
+ templates.add_to_vector("table1", "second");
+ templates.add_vector("table2");
+ templates.add_to_vector("table2", "first");
+
+ do_test_ok(templates, input, exp_output);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__mismatched_delimiters);
+ATF_TEST_CASE_BODY(instantiate__mismatched_delimiters)
+{
+ const std::string input =
+ "this is some %% text\n"
+ "and this is %%var%% text%%\n";
+
+ const std::string exp_output =
+ "this is some %% text\n"
+ "and this is some more text%%\n";
+
+ text::templates_def templates;
+ templates.add_variable("var", "some more");
+
+ do_test_ok(templates, input, exp_output);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__empty_statement);
+ATF_TEST_CASE_BODY(instantiate__empty_statement)
+{
+ do_test_fail(text::templates_def(), "%\n", "Empty statement");
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__unknown_statement);
+ATF_TEST_CASE_BODY(instantiate__unknown_statement)
+{
+ do_test_fail(text::templates_def(), "%if2\n", "Unknown statement 'if2'");
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__invalid_narguments);
+ATF_TEST_CASE_BODY(instantiate__invalid_narguments)
+{
+ do_test_fail(text::templates_def(), "%if a b\n",
+ "Invalid number of arguments for statement 'if'");
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__files__ok);
+ATF_TEST_CASE_BODY(instantiate__files__ok)
+{
+ text::templates_def templates;
+ templates.add_variable("string", "Hello, world!");
+
+ atf::utils::create_file("input.txt", "The string is: %%string%%\n");
+
+ text::instantiate(templates, fs::path("input.txt"), fs::path("output.txt"));
+
+ std::ifstream output("output.txt");
+ std::string line;
+ ATF_REQUIRE(std::getline(output, line).good());
+ ATF_REQUIRE_EQ(line, "The string is: Hello, world!");
+ ATF_REQUIRE(std::getline(output, line).eof());
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(instantiate__files__input_error);
+ATF_TEST_CASE_BODY(instantiate__files__input_error)
+{
+ text::templates_def templates;
+ ATF_REQUIRE_THROW_RE(text::error, "Failed to open input.txt for read",
+ text::instantiate(templates, fs::path("input.txt"),
+ fs::path("output.txt")));
+}
+
+
+ATF_TEST_CASE(instantiate__files__output_error);
+ATF_TEST_CASE_HEAD(instantiate__files__output_error)
+{
+ set_md_var("require.user", "unprivileged");
+}
+ATF_TEST_CASE_BODY(instantiate__files__output_error)
+{
+ text::templates_def templates;
+
+ atf::utils::create_file("input.txt", "");
+
+ fs::mkdir(fs::path("dir"), 0444);
+
+ ATF_REQUIRE_THROW_RE(text::error, "Failed to open dir/output.txt for write",
+ text::instantiate(templates, fs::path("input.txt"),
+ fs::path("dir/output.txt")));
+}
+
+
+ATF_INIT_TEST_CASES(tcs)
+{
+ ATF_ADD_TEST_CASE(tcs, templates_def__add_variable__first);
+ ATF_ADD_TEST_CASE(tcs, templates_def__add_variable__replace);
+ ATF_ADD_TEST_CASE(tcs, templates_def__remove_variable);
+ ATF_ADD_TEST_CASE(tcs, templates_def__add_vector__first);
+ ATF_ADD_TEST_CASE(tcs, templates_def__add_vector__replace);
+ ATF_ADD_TEST_CASE(tcs, templates_def__add_to_vector);
+ ATF_ADD_TEST_CASE(tcs, templates_def__exists__variable);
+ ATF_ADD_TEST_CASE(tcs, templates_def__exists__vector);
+ ATF_ADD_TEST_CASE(tcs, templates_def__get_variable__ok);
+ ATF_ADD_TEST_CASE(tcs, templates_def__get_variable__unknown);
+ ATF_ADD_TEST_CASE(tcs, templates_def__get_vector__ok);
+ ATF_ADD_TEST_CASE(tcs, templates_def__get_vector__unknown);
+ ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__variable__ok);
+ ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__variable__unknown);
+ ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__ok);
+ ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__unknown_vector);
+ ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__unknown_index);
+ ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__out_of_range);
+ ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__defined);
+ ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__length__ok);
+ ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__length__unknown_vector);
+ ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__parenthesis_error);
+
+ ATF_ADD_TEST_CASE(tcs, instantiate__empty_input);
+ ATF_ADD_TEST_CASE(tcs, instantiate__value__ok);
+ ATF_ADD_TEST_CASE(tcs, instantiate__value__unknown_variable);
+ ATF_ADD_TEST_CASE(tcs, instantiate__vector_length__ok);
+ ATF_ADD_TEST_CASE(tcs, instantiate__vector_length__unknown_vector);
+ ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__ok);
+ ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__unknown_vector);
+ ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__out_of_range__empty);
+ ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__out_of_range__not_empty);
+ ATF_ADD_TEST_CASE(tcs, instantiate__if__one_level__taken);
+ ATF_ADD_TEST_CASE(tcs, instantiate__if__one_level__not_taken);
+ ATF_ADD_TEST_CASE(tcs, instantiate__if__multiple_levels__taken);
+ ATF_ADD_TEST_CASE(tcs, instantiate__if__multiple_levels__not_taken);
+ ATF_ADD_TEST_CASE(tcs, instantiate__loop__no_iterations);
+ ATF_ADD_TEST_CASE(tcs, instantiate__loop__multiple_iterations);
+ ATF_ADD_TEST_CASE(tcs, instantiate__loop__nested__no_iterations);
+ ATF_ADD_TEST_CASE(tcs, instantiate__loop__nested__multiple_iterations);
+ ATF_ADD_TEST_CASE(tcs, instantiate__loop__sequential);
+ ATF_ADD_TEST_CASE(tcs, instantiate__loop__scoping);
+ ATF_ADD_TEST_CASE(tcs, instantiate__mismatched_delimiters);
+ ATF_ADD_TEST_CASE(tcs, instantiate__empty_statement);
+ ATF_ADD_TEST_CASE(tcs, instantiate__unknown_statement);
+ ATF_ADD_TEST_CASE(tcs, instantiate__invalid_narguments);
+
+ ATF_ADD_TEST_CASE(tcs, instantiate__files__ok);
+ ATF_ADD_TEST_CASE(tcs, instantiate__files__input_error);
+ ATF_ADD_TEST_CASE(tcs, instantiate__files__output_error);
+}