Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/kyua/utils/text/templates_test.cpp
48180 views
1
// Copyright 2012 The Kyua Authors.
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
40
namespace fs = utils::fs;
41
namespace text = utils::text;
42
43
44
namespace {
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.
55
static void
56
do_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.
75
static void
76
do_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
90
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_variable__first);
91
ATF_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
99
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_variable__replace);
100
ATF_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
109
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__remove_variable);
110
ATF_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
120
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_vector__first);
121
ATF_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
129
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_vector__replace);
130
ATF_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
141
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_to_vector);
142
ATF_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
162
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__exists__variable);
163
ATF_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
174
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__exists__vector);
175
ATF_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
186
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_variable__ok);
187
ATF_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
197
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_variable__unknown);
198
ATF_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
207
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_vector__ok);
208
ATF_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
219
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_vector__unknown);
220
ATF_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
229
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__variable__ok);
230
ATF_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
240
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__variable__unknown);
241
ATF_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
250
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__ok);
251
ATF_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
268
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__unknown_vector);
269
ATF_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
280
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__unknown_index);
281
ATF_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
292
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__out_of_range);
293
ATF_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
304
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__defined);
305
ATF_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
317
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__length__ok);
318
ATF_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
332
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__length__unknown_vector);
333
ATF_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
342
ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__parenthesis_error);
343
ATF_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
355
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__empty_input);
356
ATF_TEST_CASE_BODY(instantiate__empty_input)
357
{
358
const text::templates_def templates;
359
do_test_ok(templates, "", "");
360
}
361
362
363
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__value__ok);
364
ATF_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
390
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__value__unknown_variable);
391
ATF_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
403
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_length__ok);
404
ATF_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
428
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_length__unknown_vector);
429
ATF_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
441
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__ok);
442
ATF_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
473
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__unknown_vector);
474
ATF_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
486
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__out_of_range__empty);
487
ATF_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
500
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__out_of_range__not_empty);
501
ATF_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
516
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__one_level__taken);
517
ATF_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
545
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__one_level__not_taken);
546
ATF_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
571
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__multiple_levels__taken);
572
ATF_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
614
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__multiple_levels__not_taken);
615
ATF_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
654
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__no_iterations);
655
ATF_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
678
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__multiple_iterations);
679
ATF_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
706
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__nested__no_iterations);
707
ATF_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
744
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__nested__multiple_iterations);
745
ATF_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
779
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__sequential);
780
ATF_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
828
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__scoping);
829
ATF_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
862
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__mismatched_delimiters);
863
ATF_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
880
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__empty_statement);
881
ATF_TEST_CASE_BODY(instantiate__empty_statement)
882
{
883
do_test_fail(text::templates_def(), "%\n", "Empty statement");
884
}
885
886
887
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__unknown_statement);
888
ATF_TEST_CASE_BODY(instantiate__unknown_statement)
889
{
890
do_test_fail(text::templates_def(), "%if2\n", "Unknown statement 'if2'");
891
}
892
893
894
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__invalid_narguments);
895
ATF_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
902
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__files__ok);
903
ATF_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
920
ATF_TEST_CASE_WITHOUT_HEAD(instantiate__files__input_error);
921
ATF_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
930
ATF_TEST_CASE(instantiate__files__output_error);
931
ATF_TEST_CASE_HEAD(instantiate__files__output_error)
932
{
933
set_md_var("require.user", "unprivileged");
934
}
935
ATF_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
949
ATF_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
1003