templates_test.cpp revision 1.1.1.1
1// Copyright 2012 Google Inc. 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: 7// 8// * Redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer. 10// * Redistributions in binary form must reproduce the above copyright 11// notice, this list of conditions and the following disclaimer in the 12// documentation and/or other materials provided with the distribution. 13// * Neither the name of Google Inc. nor the names of its contributors 14// may be used to endorse or promote products derived from this software 15// without specific prior written permission. 16// 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29#include "utils/text/templates.hpp" 30 31#include <fstream> 32#include <sstream> 33 34#include <atf-c++.hpp> 35 36#include "utils/fs/operations.hpp" 37#include "utils/fs/path.hpp" 38#include "utils/text/exceptions.hpp" 39 40namespace fs = utils::fs; 41namespace text = utils::text; 42 43 44namespace { 45 46 47/// Applies a set of templates to an input string and validates the output. 48/// 49/// This fails the test case if exp_output does not match the document generated 50/// by the application of the templates. 51/// 52/// \param templates The templates to apply. 53/// \param input_str The input document to which to apply the templates. 54/// \param exp_output The expected output document. 55static void 56do_test_ok(const text::templates_def& templates, const std::string& input_str, 57 const std::string& exp_output) 58{ 59 std::istringstream input(input_str); 60 std::ostringstream output; 61 62 text::instantiate(templates, input, output); 63 ATF_REQUIRE_EQ(exp_output, output.str()); 64} 65 66 67/// Applies a set of templates to an input string and checks for an error. 68/// 69/// This fails the test case if the exception raised by the template processing 70/// does not match the expected message. 71/// 72/// \param templates The templates to apply. 73/// \param input_str The input document to which to apply the templates. 74/// \param exp_message The expected error message in the raised exception. 75static void 76do_test_fail(const text::templates_def& templates, const std::string& input_str, 77 const std::string& exp_message) 78{ 79 std::istringstream input(input_str); 80 std::ostringstream output; 81 82 ATF_REQUIRE_THROW_RE(text::syntax_error, exp_message, 83 text::instantiate(templates, input, output)); 84} 85 86 87} // anonymous namespace 88 89 90ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_variable__first); 91ATF_TEST_CASE_BODY(templates_def__add_variable__first) 92{ 93 text::templates_def templates; 94 templates.add_variable("the-name", "first-value"); 95 ATF_REQUIRE_EQ("first-value", templates.get_variable("the-name")); 96} 97 98 99ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_variable__replace); 100ATF_TEST_CASE_BODY(templates_def__add_variable__replace) 101{ 102 text::templates_def templates; 103 templates.add_variable("the-name", "first-value"); 104 templates.add_variable("the-name", "second-value"); 105 ATF_REQUIRE_EQ("second-value", templates.get_variable("the-name")); 106} 107 108 109ATF_TEST_CASE_WITHOUT_HEAD(templates_def__remove_variable); 110ATF_TEST_CASE_BODY(templates_def__remove_variable) 111{ 112 text::templates_def templates; 113 templates.add_variable("the-name", "the-value"); 114 templates.get_variable("the-name"); // Should not throw. 115 templates.remove_variable("the-name"); 116 ATF_REQUIRE_THROW(text::syntax_error, templates.get_variable("the-name")); 117} 118 119 120ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_vector__first); 121ATF_TEST_CASE_BODY(templates_def__add_vector__first) 122{ 123 text::templates_def templates; 124 templates.add_vector("the-name"); 125 ATF_REQUIRE(templates.get_vector("the-name").empty()); 126} 127 128 129ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_vector__replace); 130ATF_TEST_CASE_BODY(templates_def__add_vector__replace) 131{ 132 text::templates_def templates; 133 templates.add_vector("the-name"); 134 templates.add_to_vector("the-name", "foo"); 135 ATF_REQUIRE(!templates.get_vector("the-name").empty()); 136 templates.add_vector("the-name"); 137 ATF_REQUIRE(templates.get_vector("the-name").empty()); 138} 139 140 141ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_to_vector); 142ATF_TEST_CASE_BODY(templates_def__add_to_vector) 143{ 144 text::templates_def templates; 145 templates.add_vector("the-name"); 146 ATF_REQUIRE_EQ(0, templates.get_vector("the-name").size()); 147 templates.add_to_vector("the-name", "first"); 148 ATF_REQUIRE_EQ(1, templates.get_vector("the-name").size()); 149 templates.add_to_vector("the-name", "second"); 150 ATF_REQUIRE_EQ(2, templates.get_vector("the-name").size()); 151 templates.add_to_vector("the-name", "third"); 152 ATF_REQUIRE_EQ(3, templates.get_vector("the-name").size()); 153 154 std::vector< std::string > expected; 155 expected.push_back("first"); 156 expected.push_back("second"); 157 expected.push_back("third"); 158 ATF_REQUIRE(expected == templates.get_vector("the-name")); 159} 160 161 162ATF_TEST_CASE_WITHOUT_HEAD(templates_def__exists__variable); 163ATF_TEST_CASE_BODY(templates_def__exists__variable) 164{ 165 text::templates_def templates; 166 ATF_REQUIRE(!templates.exists("some-name")); 167 templates.add_variable("some-name ", "foo"); 168 ATF_REQUIRE(!templates.exists("some-name")); 169 templates.add_variable("some-name", "foo"); 170 ATF_REQUIRE(templates.exists("some-name")); 171} 172 173 174ATF_TEST_CASE_WITHOUT_HEAD(templates_def__exists__vector); 175ATF_TEST_CASE_BODY(templates_def__exists__vector) 176{ 177 text::templates_def templates; 178 ATF_REQUIRE(!templates.exists("some-name")); 179 templates.add_vector("some-name "); 180 ATF_REQUIRE(!templates.exists("some-name")); 181 templates.add_vector("some-name"); 182 ATF_REQUIRE(templates.exists("some-name")); 183} 184 185 186ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_variable__ok); 187ATF_TEST_CASE_BODY(templates_def__get_variable__ok) 188{ 189 text::templates_def templates; 190 templates.add_variable("foo", ""); 191 templates.add_variable("bar", " baz "); 192 ATF_REQUIRE_EQ("", templates.get_variable("foo")); 193 ATF_REQUIRE_EQ(" baz ", templates.get_variable("bar")); 194} 195 196 197ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_variable__unknown); 198ATF_TEST_CASE_BODY(templates_def__get_variable__unknown) 199{ 200 text::templates_def templates; 201 templates.add_variable("foo", ""); 202 ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown variable 'foo '", 203 templates.get_variable("foo ")); 204} 205 206 207ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_vector__ok); 208ATF_TEST_CASE_BODY(templates_def__get_vector__ok) 209{ 210 text::templates_def templates; 211 templates.add_vector("foo"); 212 templates.add_vector("bar"); 213 templates.add_to_vector("bar", "baz"); 214 ATF_REQUIRE_EQ(0, templates.get_vector("foo").size()); 215 ATF_REQUIRE_EQ(1, templates.get_vector("bar").size()); 216} 217 218 219ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_vector__unknown); 220ATF_TEST_CASE_BODY(templates_def__get_vector__unknown) 221{ 222 text::templates_def templates; 223 templates.add_vector("foo"); 224 ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown vector 'foo '", 225 templates.get_vector("foo ")); 226} 227 228 229ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__variable__ok); 230ATF_TEST_CASE_BODY(templates_def__evaluate__variable__ok) 231{ 232 text::templates_def templates; 233 templates.add_variable("foo", ""); 234 templates.add_variable("bar", " baz "); 235 ATF_REQUIRE_EQ("", templates.evaluate("foo")); 236 ATF_REQUIRE_EQ(" baz ", templates.evaluate("bar")); 237} 238 239 240ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__variable__unknown); 241ATF_TEST_CASE_BODY(templates_def__evaluate__variable__unknown) 242{ 243 text::templates_def templates; 244 templates.add_variable("foo", ""); 245 ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown variable 'foo1'", 246 templates.evaluate("foo1")); 247} 248 249 250ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__ok); 251ATF_TEST_CASE_BODY(templates_def__evaluate__vector__ok) 252{ 253 text::templates_def templates; 254 templates.add_vector("v"); 255 templates.add_to_vector("v", "foo"); 256 templates.add_to_vector("v", "bar"); 257 templates.add_to_vector("v", "baz"); 258 259 templates.add_variable("index", "0"); 260 ATF_REQUIRE_EQ("foo", templates.evaluate("v(index)")); 261 templates.add_variable("index", "1"); 262 ATF_REQUIRE_EQ("bar", templates.evaluate("v(index)")); 263 templates.add_variable("index", "2"); 264 ATF_REQUIRE_EQ("baz", templates.evaluate("v(index)")); 265} 266 267 268ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__unknown_vector); 269ATF_TEST_CASE_BODY(templates_def__evaluate__vector__unknown_vector) 270{ 271 text::templates_def templates; 272 templates.add_vector("v"); 273 templates.add_to_vector("v", "foo"); 274 templates.add_variable("index", "0"); 275 ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown vector 'fooz'", 276 templates.evaluate("fooz(index)")); 277} 278 279 280ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__unknown_index); 281ATF_TEST_CASE_BODY(templates_def__evaluate__vector__unknown_index) 282{ 283 text::templates_def templates; 284 templates.add_vector("v"); 285 templates.add_to_vector("v", "foo"); 286 templates.add_variable("index", "0"); 287 ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown variable 'indexz'", 288 templates.evaluate("v(indexz)")); 289} 290 291 292ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__out_of_range); 293ATF_TEST_CASE_BODY(templates_def__evaluate__vector__out_of_range) 294{ 295 text::templates_def templates; 296 templates.add_vector("v"); 297 templates.add_to_vector("v", "foo"); 298 templates.add_variable("index", "1"); 299 ATF_REQUIRE_THROW_RE(text::syntax_error, "Index 'index' out of range " 300 "at position '1'", templates.evaluate("v(index)")); 301} 302 303 304ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__defined); 305ATF_TEST_CASE_BODY(templates_def__evaluate__defined) 306{ 307 text::templates_def templates; 308 templates.add_vector("the-variable"); 309 templates.add_vector("the-vector"); 310 ATF_REQUIRE_EQ("false", templates.evaluate("defined(the-variabl)")); 311 ATF_REQUIRE_EQ("false", templates.evaluate("defined(the-vecto)")); 312 ATF_REQUIRE_EQ("true", templates.evaluate("defined(the-variable)")); 313 ATF_REQUIRE_EQ("true", templates.evaluate("defined(the-vector)")); 314} 315 316 317ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__length__ok); 318ATF_TEST_CASE_BODY(templates_def__evaluate__length__ok) 319{ 320 text::templates_def templates; 321 templates.add_vector("v"); 322 ATF_REQUIRE_EQ("0", templates.evaluate("length(v)")); 323 templates.add_to_vector("v", "foo"); 324 ATF_REQUIRE_EQ("1", templates.evaluate("length(v)")); 325 templates.add_to_vector("v", "bar"); 326 ATF_REQUIRE_EQ("2", templates.evaluate("length(v)")); 327 templates.add_to_vector("v", "baz"); 328 ATF_REQUIRE_EQ("3", templates.evaluate("length(v)")); 329} 330 331 332ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__length__unknown_vector); 333ATF_TEST_CASE_BODY(templates_def__evaluate__length__unknown_vector) 334{ 335 text::templates_def templates; 336 templates.add_vector("foo1"); 337 ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown vector 'foo'", 338 templates.evaluate("length(foo)")); 339} 340 341 342ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__parenthesis_error); 343ATF_TEST_CASE_BODY(templates_def__evaluate__parenthesis_error) 344{ 345 text::templates_def templates; 346 ATF_REQUIRE_THROW_RE(text::syntax_error, 347 "Expected '\\)' in.*'foo\\(abc'", 348 templates.evaluate("foo(abc")); 349 ATF_REQUIRE_THROW_RE(text::syntax_error, 350 "Unexpected text.*'\\)' in.*'a\\(b\\)c'", 351 templates.evaluate("a(b)c")); 352} 353 354 355ATF_TEST_CASE_WITHOUT_HEAD(instantiate__empty_input); 356ATF_TEST_CASE_BODY(instantiate__empty_input) 357{ 358 const text::templates_def templates; 359 do_test_ok(templates, "", ""); 360} 361 362 363ATF_TEST_CASE_WITHOUT_HEAD(instantiate__value__ok); 364ATF_TEST_CASE_BODY(instantiate__value__ok) 365{ 366 const std::string input = 367 "first line\n" 368 "%%testvar1%%\n" 369 "third line\n" 370 "%%testvar2%% %%testvar3%%%%testvar4%%\n" 371 "fifth line\n"; 372 373 const std::string exp_output = 374 "first line\n" 375 "second line\n" 376 "third line\n" 377 "fourth line.\n" 378 "fifth line\n"; 379 380 text::templates_def templates; 381 templates.add_variable("testvar1", "second line"); 382 templates.add_variable("testvar2", "fourth"); 383 templates.add_variable("testvar3", "line"); 384 templates.add_variable("testvar4", "."); 385 386 do_test_ok(templates, input, exp_output); 387} 388 389 390ATF_TEST_CASE_WITHOUT_HEAD(instantiate__value__unknown_variable); 391ATF_TEST_CASE_BODY(instantiate__value__unknown_variable) 392{ 393 const std::string input = 394 "%%testvar1%%\n"; 395 396 text::templates_def templates; 397 templates.add_variable("testvar2", "fourth line"); 398 399 do_test_fail(templates, input, "Unknown variable 'testvar1'"); 400} 401 402 403ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_length__ok); 404ATF_TEST_CASE_BODY(instantiate__vector_length__ok) 405{ 406 const std::string input = 407 "%%length(testvector1)%%\n" 408 "%%length(testvector2)%% - %%length(testvector3)%%\n"; 409 410 const std::string exp_output = 411 "4\n" 412 "0 - 1\n"; 413 414 text::templates_def templates; 415 templates.add_vector("testvector1"); 416 templates.add_to_vector("testvector1", "000"); 417 templates.add_to_vector("testvector1", "111"); 418 templates.add_to_vector("testvector1", "543"); 419 templates.add_to_vector("testvector1", "999"); 420 templates.add_vector("testvector2"); 421 templates.add_vector("testvector3"); 422 templates.add_to_vector("testvector3", "123"); 423 424 do_test_ok(templates, input, exp_output); 425} 426 427 428ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_length__unknown_vector); 429ATF_TEST_CASE_BODY(instantiate__vector_length__unknown_vector) 430{ 431 const std::string input = 432 "%%length(testvector)%%\n"; 433 434 text::templates_def templates; 435 templates.add_vector("testvector2"); 436 437 do_test_fail(templates, input, "Unknown vector 'testvector'"); 438} 439 440 441ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__ok); 442ATF_TEST_CASE_BODY(instantiate__vector_value__ok) 443{ 444 const std::string input = 445 "first line\n" 446 "%%testvector1(i)%%\n" 447 "third line\n" 448 "%%testvector2(j)%%\n" 449 "fifth line\n"; 450 451 const std::string exp_output = 452 "first line\n" 453 "543\n" 454 "third line\n" 455 "123\n" 456 "fifth line\n"; 457 458 text::templates_def templates; 459 templates.add_variable("i", "2"); 460 templates.add_variable("j", "0"); 461 templates.add_vector("testvector1"); 462 templates.add_to_vector("testvector1", "000"); 463 templates.add_to_vector("testvector1", "111"); 464 templates.add_to_vector("testvector1", "543"); 465 templates.add_to_vector("testvector1", "999"); 466 templates.add_vector("testvector2"); 467 templates.add_to_vector("testvector2", "123"); 468 469 do_test_ok(templates, input, exp_output); 470} 471 472 473ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__unknown_vector); 474ATF_TEST_CASE_BODY(instantiate__vector_value__unknown_vector) 475{ 476 const std::string input = 477 "%%testvector(j)%%\n"; 478 479 text::templates_def templates; 480 templates.add_vector("testvector2"); 481 482 do_test_fail(templates, input, "Unknown vector 'testvector'"); 483} 484 485 486ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__out_of_range__empty); 487ATF_TEST_CASE_BODY(instantiate__vector_value__out_of_range__empty) 488{ 489 const std::string input = 490 "%%testvector(j)%%\n"; 491 492 text::templates_def templates; 493 templates.add_vector("testvector"); 494 templates.add_variable("j", "0"); 495 496 do_test_fail(templates, input, "Index 'j' out of range at position '0'"); 497} 498 499 500ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__out_of_range__not_empty); 501ATF_TEST_CASE_BODY(instantiate__vector_value__out_of_range__not_empty) 502{ 503 const std::string input = 504 "%%testvector(j)%%\n"; 505 506 text::templates_def templates; 507 templates.add_vector("testvector"); 508 templates.add_to_vector("testvector", "a"); 509 templates.add_to_vector("testvector", "b"); 510 templates.add_variable("j", "2"); 511 512 do_test_fail(templates, input, "Index 'j' out of range at position '2'"); 513} 514 515 516ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__one_level__taken); 517ATF_TEST_CASE_BODY(instantiate__if__one_level__taken) 518{ 519 const std::string input = 520 "first line\n" 521 "%if defined(some_var)\n" 522 "hello from within the variable conditional\n" 523 "%endif\n" 524 "%if defined(some_vector)\n" 525 "hello from within the vector conditional\n" 526 "%else\n" 527 "bye from within the vector conditional\n" 528 "%endif\n" 529 "some more\n"; 530 531 const std::string exp_output = 532 "first line\n" 533 "hello from within the variable conditional\n" 534 "hello from within the vector conditional\n" 535 "some more\n"; 536 537 text::templates_def templates; 538 templates.add_variable("some_var", "zzz"); 539 templates.add_vector("some_vector"); 540 541 do_test_ok(templates, input, exp_output); 542} 543 544 545ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__one_level__not_taken); 546ATF_TEST_CASE_BODY(instantiate__if__one_level__not_taken) 547{ 548 const std::string input = 549 "first line\n" 550 "%if defined(some_var)\n" 551 "hello from within the variable conditional\n" 552 "%endif\n" 553 "%if defined(some_vector)\n" 554 "hello from within the vector conditional\n" 555 "%else\n" 556 "bye from within the vector conditional\n" 557 "%endif\n" 558 "some more\n"; 559 560 const std::string exp_output = 561 "first line\n" 562 "bye from within the vector conditional\n" 563 "some more\n"; 564 565 text::templates_def templates; 566 567 do_test_ok(templates, input, exp_output); 568} 569 570 571ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__multiple_levels__taken); 572ATF_TEST_CASE_BODY(instantiate__if__multiple_levels__taken) 573{ 574 const std::string input = 575 "first line\n" 576 "%if defined(var1)\n" 577 "first before\n" 578 "%if length(var2)\n" 579 "second before\n" 580 "%if defined(var3)\n" 581 "third before\n" 582 "hello from within the conditional\n" 583 "third after\n" 584 "%endif\n" 585 "second after\n" 586 "%else\n" 587 "second after not shown\n" 588 "%endif\n" 589 "first after\n" 590 "%endif\n" 591 "some more\n"; 592 593 const std::string exp_output = 594 "first line\n" 595 "first before\n" 596 "second before\n" 597 "third before\n" 598 "hello from within the conditional\n" 599 "third after\n" 600 "second after\n" 601 "first after\n" 602 "some more\n"; 603 604 text::templates_def templates; 605 templates.add_variable("var1", "false"); 606 templates.add_vector("var2"); 607 templates.add_to_vector("var2", "not-empty"); 608 templates.add_variable("var3", "foobar"); 609 610 do_test_ok(templates, input, exp_output); 611} 612 613 614ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__multiple_levels__not_taken); 615ATF_TEST_CASE_BODY(instantiate__if__multiple_levels__not_taken) 616{ 617 const std::string input = 618 "first line\n" 619 "%if defined(var1)\n" 620 "first before\n" 621 "%if length(var2)\n" 622 "second before\n" 623 "%if defined(var3)\n" 624 "third before\n" 625 "hello from within the conditional\n" 626 "third after\n" 627 "%else\n" 628 "will not be shown either\n" 629 "%endif\n" 630 "second after\n" 631 "%else\n" 632 "second after shown\n" 633 "%endif\n" 634 "first after\n" 635 "%endif\n" 636 "some more\n"; 637 638 const std::string exp_output = 639 "first line\n" 640 "first before\n" 641 "second after shown\n" 642 "first after\n" 643 "some more\n"; 644 645 text::templates_def templates; 646 templates.add_variable("var1", "false"); 647 templates.add_vector("var2"); 648 templates.add_vector("var3"); 649 650 do_test_ok(templates, input, exp_output); 651} 652 653 654ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__no_iterations); 655ATF_TEST_CASE_BODY(instantiate__loop__no_iterations) 656{ 657 const std::string input = 658 "first line\n" 659 "%loop table1 i\n" 660 "hello\n" 661 "value in vector: %%table1(i)%%\n" 662 "%if defined(var1)\n" "some other text\n" "%endif\n" 663 "%endloop\n" 664 "some more\n"; 665 666 const std::string exp_output = 667 "first line\n" 668 "some more\n"; 669 670 text::templates_def templates; 671 templates.add_variable("var1", "defined"); 672 templates.add_vector("table1"); 673 674 do_test_ok(templates, input, exp_output); 675} 676 677 678ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__multiple_iterations); 679ATF_TEST_CASE_BODY(instantiate__loop__multiple_iterations) 680{ 681 const std::string input = 682 "first line\n" 683 "%loop table1 i\n" 684 "hello %%table1(i)%% %%table2(i)%%\n" 685 "%endloop\n" 686 "some more\n"; 687 688 const std::string exp_output = 689 "first line\n" 690 "hello foo1 foo2\n" 691 "hello bar1 bar2\n" 692 "some more\n"; 693 694 text::templates_def templates; 695 templates.add_vector("table1"); 696 templates.add_to_vector("table1", "foo1"); 697 templates.add_to_vector("table1", "bar1"); 698 templates.add_vector("table2"); 699 templates.add_to_vector("table2", "foo2"); 700 templates.add_to_vector("table2", "bar2"); 701 702 do_test_ok(templates, input, exp_output); 703} 704 705 706ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__nested__no_iterations); 707ATF_TEST_CASE_BODY(instantiate__loop__nested__no_iterations) 708{ 709 const std::string input = 710 "first line\n" 711 "%loop table1 i\n" 712 "before: %%table1(i)%%\n" 713 "%loop table2 j\n" 714 "before: %%table2(j)%%\n" 715 "%loop table3 k\n" 716 "%%table3(k)%%\n" 717 "%endloop\n" 718 "after: %%table2(i)%%\n" 719 "%endloop\n" 720 "after: %%table1(i)%%\n" 721 "%endloop\n" 722 "some more\n"; 723 724 const std::string exp_output = 725 "first line\n" 726 "before: a\n" 727 "after: a\n" 728 "before: b\n" 729 "after: b\n" 730 "some more\n"; 731 732 text::templates_def templates; 733 templates.add_vector("table1"); 734 templates.add_to_vector("table1", "a"); 735 templates.add_to_vector("table1", "b"); 736 templates.add_vector("table2"); 737 templates.add_vector("table3"); 738 templates.add_to_vector("table3", "1"); 739 740 do_test_ok(templates, input, exp_output); 741} 742 743 744ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__nested__multiple_iterations); 745ATF_TEST_CASE_BODY(instantiate__loop__nested__multiple_iterations) 746{ 747 const std::string input = 748 "first line\n" 749 "%loop table1 i\n" 750 "%loop table2 j\n" 751 "%%table1(i)%% %%table2(j)%%\n" 752 "%endloop\n" 753 "%endloop\n" 754 "some more\n"; 755 756 const std::string exp_output = 757 "first line\n" 758 "a 1\n" 759 "a 2\n" 760 "a 3\n" 761 "b 1\n" 762 "b 2\n" 763 "b 3\n" 764 "some more\n"; 765 766 text::templates_def templates; 767 templates.add_vector("table1"); 768 templates.add_to_vector("table1", "a"); 769 templates.add_to_vector("table1", "b"); 770 templates.add_vector("table2"); 771 templates.add_to_vector("table2", "1"); 772 templates.add_to_vector("table2", "2"); 773 templates.add_to_vector("table2", "3"); 774 775 do_test_ok(templates, input, exp_output); 776} 777 778 779ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__sequential); 780ATF_TEST_CASE_BODY(instantiate__loop__sequential) 781{ 782 const std::string input = 783 "first line\n" 784 "%loop table1 iter\n" 785 "1: %%table1(iter)%%\n" 786 "%endloop\n" 787 "divider\n" 788 "%loop table2 iter\n" 789 "2: %%table2(iter)%%\n" 790 "%endloop\n" 791 "divider\n" 792 "%loop table3 iter\n" 793 "3: %%table3(iter)%%\n" 794 "%endloop\n" 795 "divider\n" 796 "%loop table4 iter\n" 797 "4: %%table4(iter)%%\n" 798 "%endloop\n" 799 "some more\n"; 800 801 const std::string exp_output = 802 "first line\n" 803 "1: a\n" 804 "1: b\n" 805 "divider\n" 806 "divider\n" 807 "divider\n" 808 "4: 1\n" 809 "4: 2\n" 810 "4: 3\n" 811 "some more\n"; 812 813 text::templates_def templates; 814 templates.add_vector("table1"); 815 templates.add_to_vector("table1", "a"); 816 templates.add_to_vector("table1", "b"); 817 templates.add_vector("table2"); 818 templates.add_vector("table3"); 819 templates.add_vector("table4"); 820 templates.add_to_vector("table4", "1"); 821 templates.add_to_vector("table4", "2"); 822 templates.add_to_vector("table4", "3"); 823 824 do_test_ok(templates, input, exp_output); 825} 826 827 828ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__scoping); 829ATF_TEST_CASE_BODY(instantiate__loop__scoping) 830{ 831 const std::string input = 832 "%loop table1 i\n" 833 "%if defined(i)\n" "i defined inside scope 1\n" "%endif\n" 834 "%loop table2 j\n" 835 "%if defined(i)\n" "i defined inside scope 2\n" "%endif\n" 836 "%if defined(j)\n" "j defined inside scope 2\n" "%endif\n" 837 "%endloop\n" 838 "%if defined(j)\n" "j defined inside scope 1\n" "%endif\n" 839 "%endloop\n" 840 "%if defined(i)\n" "i defined outside\n" "%endif\n" 841 "%if defined(j)\n" "j defined outside\n" "%endif\n"; 842 843 const std::string exp_output = 844 "i defined inside scope 1\n" 845 "i defined inside scope 2\n" 846 "j defined inside scope 2\n" 847 "i defined inside scope 1\n" 848 "i defined inside scope 2\n" 849 "j defined inside scope 2\n"; 850 851 text::templates_def templates; 852 templates.add_vector("table1"); 853 templates.add_to_vector("table1", "first"); 854 templates.add_to_vector("table1", "second"); 855 templates.add_vector("table2"); 856 templates.add_to_vector("table2", "first"); 857 858 do_test_ok(templates, input, exp_output); 859} 860 861 862ATF_TEST_CASE_WITHOUT_HEAD(instantiate__mismatched_delimiters); 863ATF_TEST_CASE_BODY(instantiate__mismatched_delimiters) 864{ 865 const std::string input = 866 "this is some %% text\n" 867 "and this is %%var%% text%%\n"; 868 869 const std::string exp_output = 870 "this is some %% text\n" 871 "and this is some more text%%\n"; 872 873 text::templates_def templates; 874 templates.add_variable("var", "some more"); 875 876 do_test_ok(templates, input, exp_output); 877} 878 879 880ATF_TEST_CASE_WITHOUT_HEAD(instantiate__empty_statement); 881ATF_TEST_CASE_BODY(instantiate__empty_statement) 882{ 883 do_test_fail(text::templates_def(), "%\n", "Empty statement"); 884} 885 886 887ATF_TEST_CASE_WITHOUT_HEAD(instantiate__unknown_statement); 888ATF_TEST_CASE_BODY(instantiate__unknown_statement) 889{ 890 do_test_fail(text::templates_def(), "%if2\n", "Unknown statement 'if2'"); 891} 892 893 894ATF_TEST_CASE_WITHOUT_HEAD(instantiate__invalid_narguments); 895ATF_TEST_CASE_BODY(instantiate__invalid_narguments) 896{ 897 do_test_fail(text::templates_def(), "%if a b\n", 898 "Invalid number of arguments for statement 'if'"); 899} 900 901 902ATF_TEST_CASE_WITHOUT_HEAD(instantiate__files__ok); 903ATF_TEST_CASE_BODY(instantiate__files__ok) 904{ 905 text::templates_def templates; 906 templates.add_variable("string", "Hello, world!"); 907 908 atf::utils::create_file("input.txt", "The string is: %%string%%\n"); 909 910 text::instantiate(templates, fs::path("input.txt"), fs::path("output.txt")); 911 912 std::ifstream output("output.txt"); 913 std::string line; 914 ATF_REQUIRE(std::getline(output, line).good()); 915 ATF_REQUIRE_EQ(line, "The string is: Hello, world!"); 916 ATF_REQUIRE(std::getline(output, line).eof()); 917} 918 919 920ATF_TEST_CASE_WITHOUT_HEAD(instantiate__files__input_error); 921ATF_TEST_CASE_BODY(instantiate__files__input_error) 922{ 923 text::templates_def templates; 924 ATF_REQUIRE_THROW_RE(text::error, "Failed to open input.txt for read", 925 text::instantiate(templates, fs::path("input.txt"), 926 fs::path("output.txt"))); 927} 928 929 930ATF_TEST_CASE(instantiate__files__output_error); 931ATF_TEST_CASE_HEAD(instantiate__files__output_error) 932{ 933 set_md_var("require.user", "unprivileged"); 934} 935ATF_TEST_CASE_BODY(instantiate__files__output_error) 936{ 937 text::templates_def templates; 938 939 atf::utils::create_file("input.txt", ""); 940 941 fs::mkdir(fs::path("dir"), 0444); 942 943 ATF_REQUIRE_THROW_RE(text::error, "Failed to open dir/output.txt for write", 944 text::instantiate(templates, fs::path("input.txt"), 945 fs::path("dir/output.txt"))); 946} 947 948 949ATF_INIT_TEST_CASES(tcs) 950{ 951 ATF_ADD_TEST_CASE(tcs, templates_def__add_variable__first); 952 ATF_ADD_TEST_CASE(tcs, templates_def__add_variable__replace); 953 ATF_ADD_TEST_CASE(tcs, templates_def__remove_variable); 954 ATF_ADD_TEST_CASE(tcs, templates_def__add_vector__first); 955 ATF_ADD_TEST_CASE(tcs, templates_def__add_vector__replace); 956 ATF_ADD_TEST_CASE(tcs, templates_def__add_to_vector); 957 ATF_ADD_TEST_CASE(tcs, templates_def__exists__variable); 958 ATF_ADD_TEST_CASE(tcs, templates_def__exists__vector); 959 ATF_ADD_TEST_CASE(tcs, templates_def__get_variable__ok); 960 ATF_ADD_TEST_CASE(tcs, templates_def__get_variable__unknown); 961 ATF_ADD_TEST_CASE(tcs, templates_def__get_vector__ok); 962 ATF_ADD_TEST_CASE(tcs, templates_def__get_vector__unknown); 963 ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__variable__ok); 964 ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__variable__unknown); 965 ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__ok); 966 ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__unknown_vector); 967 ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__unknown_index); 968 ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__out_of_range); 969 ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__defined); 970 ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__length__ok); 971 ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__length__unknown_vector); 972 ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__parenthesis_error); 973 974 ATF_ADD_TEST_CASE(tcs, instantiate__empty_input); 975 ATF_ADD_TEST_CASE(tcs, instantiate__value__ok); 976 ATF_ADD_TEST_CASE(tcs, instantiate__value__unknown_variable); 977 ATF_ADD_TEST_CASE(tcs, instantiate__vector_length__ok); 978 ATF_ADD_TEST_CASE(tcs, instantiate__vector_length__unknown_vector); 979 ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__ok); 980 ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__unknown_vector); 981 ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__out_of_range__empty); 982 ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__out_of_range__not_empty); 983 ATF_ADD_TEST_CASE(tcs, instantiate__if__one_level__taken); 984 ATF_ADD_TEST_CASE(tcs, instantiate__if__one_level__not_taken); 985 ATF_ADD_TEST_CASE(tcs, instantiate__if__multiple_levels__taken); 986 ATF_ADD_TEST_CASE(tcs, instantiate__if__multiple_levels__not_taken); 987 ATF_ADD_TEST_CASE(tcs, instantiate__loop__no_iterations); 988 ATF_ADD_TEST_CASE(tcs, instantiate__loop__multiple_iterations); 989 ATF_ADD_TEST_CASE(tcs, instantiate__loop__nested__no_iterations); 990 ATF_ADD_TEST_CASE(tcs, instantiate__loop__nested__multiple_iterations); 991 ATF_ADD_TEST_CASE(tcs, instantiate__loop__sequential); 992 ATF_ADD_TEST_CASE(tcs, instantiate__loop__scoping); 993 ATF_ADD_TEST_CASE(tcs, instantiate__mismatched_delimiters); 994 ATF_ADD_TEST_CASE(tcs, instantiate__empty_statement); 995 ATF_ADD_TEST_CASE(tcs, instantiate__unknown_statement); 996 ATF_ADD_TEST_CASE(tcs, instantiate__invalid_narguments); 997 998 ATF_ADD_TEST_CASE(tcs, instantiate__files__ok); 999 ATF_ADD_TEST_CASE(tcs, instantiate__files__input_error); 1000 ATF_ADD_TEST_CASE(tcs, instantiate__files__output_error); 1001} 1002