]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/atf/atf-c++/detail/parser_test.cpp
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / contrib / atf / atf-c++ / detail / parser_test.cpp
1 //
2 // Automated Testing Framework (atf)
3 //
4 // Copyright (c) 2007 The NetBSD Foundation, Inc.
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 // 1. Redistributions of source code must retain the above copyright
11 //    notice, this list of conditions and the following disclaimer.
12 // 2. Redistributions in binary form must reproduce the above copyright
13 //    notice, this list of conditions and the following disclaimer in the
14 //    documentation and/or other materials provided with the distribution.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 //
29
30 #include <sstream>
31
32 #include "../macros.hpp"
33
34 #include "parser.hpp"
35 #include "test_helpers.hpp"
36
37 // ------------------------------------------------------------------------
38 // Tests for the "parse_error" class.
39 // ------------------------------------------------------------------------
40
41 ATF_TEST_CASE(parse_error_to_string);
42 ATF_TEST_CASE_HEAD(parse_error_to_string)
43 {
44     set_md_var("descr", "Tests the parse_error conversion to strings");
45 }
46 ATF_TEST_CASE_BODY(parse_error_to_string)
47 {
48     using atf::parser::parse_error;
49
50     const parse_error e(123, "This is the message");
51     ATF_REQUIRE_EQ("123: This is the message", std::string(e));
52 }
53
54 // ------------------------------------------------------------------------
55 // Tests for the "parse_errors" class.
56 // ------------------------------------------------------------------------
57
58 ATF_TEST_CASE(parse_errors_what);
59 ATF_TEST_CASE_HEAD(parse_errors_what)
60 {
61     set_md_var("descr", "Tests the parse_errors description");
62 }
63 ATF_TEST_CASE_BODY(parse_errors_what)
64 {
65     using atf::parser::parse_error;
66     using atf::parser::parse_errors;
67
68     parse_errors es;
69     es.push_back(parse_error(2, "Second error"));
70     es.push_back(parse_error(1, "First error"));
71
72     ATF_REQUIRE_EQ("2: Second error\n1: First error", std::string(es.what()));
73 }
74
75 // ------------------------------------------------------------------------
76 // Tests for the "token" class.
77 // ------------------------------------------------------------------------
78
79 ATF_TEST_CASE(token_getters);
80 ATF_TEST_CASE_HEAD(token_getters)
81 {
82     set_md_var("descr", "Tests the token getters");
83 }
84 ATF_TEST_CASE_BODY(token_getters)
85 {
86     using atf::parser::token;
87
88     {
89         token t(10, 0);
90         ATF_REQUIRE_EQ(t.lineno(), 10);
91         ATF_REQUIRE_EQ(t.type(), 0);
92         ATF_REQUIRE(t.text().empty());
93     }
94
95     {
96         token t(10, 0, "foo");
97         ATF_REQUIRE_EQ(t.lineno(), 10);
98         ATF_REQUIRE_EQ(t.type(), 0);
99         ATF_REQUIRE_EQ(t.text(), "foo");
100     }
101
102     {
103         token t(20, 1);
104         ATF_REQUIRE_EQ(t.lineno(), 20);
105         ATF_REQUIRE_EQ(t.type(), 1);
106         ATF_REQUIRE(t.text().empty());
107     }
108
109     {
110         token t(20, 1, "bar");
111         ATF_REQUIRE_EQ(t.lineno(), 20);
112         ATF_REQUIRE_EQ(t.type(), 1);
113         ATF_REQUIRE_EQ(t.text(), "bar");
114     }
115 }
116
117 // ------------------------------------------------------------------------
118 // Tests for the "tokenizer" class.
119 // ------------------------------------------------------------------------
120
121 #define EXPECT(tkz, ttype, ttext) \
122     do { \
123         atf::parser::token t = tkz.next(); \
124         ATF_REQUIRE(t.type() == ttype); \
125         ATF_REQUIRE_EQ(t.text(), ttext); \
126     } while (false);
127
128 namespace minimal {
129
130     static const atf::parser::token_type eof_type = 0;
131     static const atf::parser::token_type nl_type = 1;
132     static const atf::parser::token_type word_type = 2;
133
134     class tokenizer : public atf::parser::tokenizer< std::istream > {
135     public:
136         tokenizer(std::istream& is, bool skipws) :
137             atf::parser::tokenizer< std::istream >
138                 (is, skipws, eof_type, nl_type, word_type)
139         {
140         }
141     };
142
143 }
144
145 namespace delims {
146
147     static const atf::parser::token_type eof_type = 0;
148     static const atf::parser::token_type nl_type = 1;
149     static const atf::parser::token_type word_type = 2;
150     static const atf::parser::token_type plus_type = 3;
151     static const atf::parser::token_type minus_type = 4;
152     static const atf::parser::token_type equal_type = 5;
153
154     class tokenizer : public atf::parser::tokenizer< std::istream > {
155     public:
156         tokenizer(std::istream& is, bool skipws) :
157             atf::parser::tokenizer< std::istream >
158                 (is, skipws, eof_type, nl_type, word_type)
159         {
160             add_delim('+', plus_type);
161             add_delim('-', minus_type);
162             add_delim('=', equal_type);
163         }
164     };
165
166 }
167
168 namespace keywords {
169
170     static const atf::parser::token_type eof_type = 0;
171     static const atf::parser::token_type nl_type = 1;
172     static const atf::parser::token_type word_type = 2;
173     static const atf::parser::token_type var_type = 3;
174     static const atf::parser::token_type loop_type = 4;
175     static const atf::parser::token_type endloop_type = 5;
176
177     class tokenizer : public atf::parser::tokenizer< std::istream > {
178     public:
179         tokenizer(std::istream& is, bool skipws) :
180             atf::parser::tokenizer< std::istream >
181                 (is, skipws, eof_type, nl_type, word_type)
182         {
183             add_keyword("var", var_type);
184             add_keyword("loop", loop_type);
185             add_keyword("endloop", endloop_type);
186         }
187     };
188
189 }
190
191 namespace quotes {
192
193     static const atf::parser::token_type eof_type = 0;
194     static const atf::parser::token_type nl_type = 1;
195     static const atf::parser::token_type word_type = 2;
196     static const atf::parser::token_type dblquote_type = 3;
197
198     class tokenizer : public atf::parser::tokenizer< std::istream > {
199     public:
200         tokenizer(std::istream& is, bool skipws) :
201             atf::parser::tokenizer< std::istream >
202                 (is, skipws, eof_type, nl_type, word_type)
203         {
204             add_quote('"', dblquote_type);
205         }
206     };
207
208 }
209
210 ATF_TEST_CASE(tokenizer_minimal_nows);
211 ATF_TEST_CASE_HEAD(tokenizer_minimal_nows)
212 {
213     set_md_var("descr", "Tests the tokenizer class using a minimal parser "
214                "and not skipping whitespace");
215 }
216 ATF_TEST_CASE_BODY(tokenizer_minimal_nows)
217 {
218     using namespace minimal;
219
220     {
221         std::istringstream iss("");
222         tokenizer mt(iss, false);
223
224         EXPECT(mt, eof_type, "<<EOF>>");
225         EXPECT(mt, eof_type, "<<EOF>>");
226     }
227
228     {
229         std::istringstream iss("\n");
230         tokenizer mt(iss, false);
231
232         EXPECT(mt, nl_type, "<<NEWLINE>>");
233         EXPECT(mt, eof_type, "<<EOF>>");
234         EXPECT(mt, eof_type, "<<EOF>>");
235     }
236
237     {
238         std::istringstream iss("\n\n\n");
239         tokenizer mt(iss, false);
240
241         EXPECT(mt, nl_type, "<<NEWLINE>>");
242         EXPECT(mt, nl_type, "<<NEWLINE>>");
243         EXPECT(mt, nl_type, "<<NEWLINE>>");
244         EXPECT(mt, eof_type, "<<EOF>>");
245         EXPECT(mt, eof_type, "<<EOF>>");
246     }
247
248     {
249         std::istringstream iss("line 1");
250         tokenizer mt(iss, false);
251
252         EXPECT(mt, word_type, "line 1");
253         EXPECT(mt, eof_type, "<<EOF>>");
254         EXPECT(mt, eof_type, "<<EOF>>");
255     }
256
257     {
258         std::istringstream iss("line 1\n");
259         tokenizer mt(iss, false);
260
261         EXPECT(mt, word_type, "line 1");
262         EXPECT(mt, nl_type, "<<NEWLINE>>");
263         EXPECT(mt, eof_type, "<<EOF>>");
264         EXPECT(mt, eof_type, "<<EOF>>");
265     }
266
267     {
268         std::istringstream iss("line 1\nline 2");
269         tokenizer mt(iss, false);
270
271         EXPECT(mt, word_type, "line 1");
272         EXPECT(mt, nl_type, "<<NEWLINE>>");
273         EXPECT(mt, word_type, "line 2");
274         EXPECT(mt, eof_type, "<<EOF>>");
275         EXPECT(mt, eof_type, "<<EOF>>");
276     }
277
278     {
279         std::istringstream iss("line 1\nline 2\nline 3\n");
280         tokenizer mt(iss, false);
281
282         EXPECT(mt, word_type, "line 1");
283         EXPECT(mt, nl_type, "<<NEWLINE>>");
284         EXPECT(mt, word_type, "line 2");
285         EXPECT(mt, nl_type, "<<NEWLINE>>");
286         EXPECT(mt, word_type, "line 3");
287         EXPECT(mt, nl_type, "<<NEWLINE>>");
288         EXPECT(mt, eof_type, "<<EOF>>");
289         EXPECT(mt, eof_type, "<<EOF>>");
290     }
291 }
292
293 ATF_TEST_CASE(tokenizer_minimal_ws);
294 ATF_TEST_CASE_HEAD(tokenizer_minimal_ws)
295 {
296     set_md_var("descr", "Tests the tokenizer class using a minimal parser "
297                "and skipping whitespace");
298 }
299 ATF_TEST_CASE_BODY(tokenizer_minimal_ws)
300 {
301     using namespace minimal;
302
303     {
304         std::istringstream iss("");
305         minimal::tokenizer mt(iss, true);
306
307         EXPECT(mt, eof_type, "<<EOF>>");
308         EXPECT(mt, eof_type, "<<EOF>>");
309     }
310
311     {
312         std::istringstream iss(" \t ");
313         tokenizer mt(iss, true);
314
315         EXPECT(mt, eof_type, "<<EOF>>");
316         EXPECT(mt, eof_type, "<<EOF>>");
317     }
318
319     {
320         std::istringstream iss("\n");
321         tokenizer mt(iss, true);
322
323         EXPECT(mt, nl_type, "<<NEWLINE>>");
324         EXPECT(mt, eof_type, "<<EOF>>");
325         EXPECT(mt, eof_type, "<<EOF>>");
326     }
327
328     {
329         std::istringstream iss(" \t \n \t ");
330         tokenizer mt(iss, true);
331
332         EXPECT(mt, nl_type, "<<NEWLINE>>");
333         EXPECT(mt, eof_type, "<<EOF>>");
334         EXPECT(mt, eof_type, "<<EOF>>");
335     }
336
337     {
338         std::istringstream iss("\n\n\n");
339         tokenizer mt(iss, true);
340
341         EXPECT(mt, nl_type, "<<NEWLINE>>");
342         EXPECT(mt, nl_type, "<<NEWLINE>>");
343         EXPECT(mt, nl_type, "<<NEWLINE>>");
344         EXPECT(mt, eof_type, "<<EOF>>");
345         EXPECT(mt, eof_type, "<<EOF>>");
346     }
347
348     {
349         std::istringstream iss("line 1");
350         tokenizer mt(iss, true);
351
352         EXPECT(mt, word_type, "line");
353         EXPECT(mt, word_type, "1");
354         EXPECT(mt, eof_type, "<<EOF>>");
355         EXPECT(mt, eof_type, "<<EOF>>");
356     }
357
358     {
359         std::istringstream iss("   \tline\t   1\t");
360         tokenizer mt(iss, true);
361
362         EXPECT(mt, word_type, "line");
363         EXPECT(mt, word_type, "1");
364         EXPECT(mt, eof_type, "<<EOF>>");
365         EXPECT(mt, eof_type, "<<EOF>>");
366     }
367
368     {
369         std::istringstream iss("line 1\n");
370         tokenizer mt(iss, true);
371
372         EXPECT(mt, word_type, "line");
373         EXPECT(mt, word_type, "1");
374         EXPECT(mt, nl_type, "<<NEWLINE>>");
375         EXPECT(mt, eof_type, "<<EOF>>");
376         EXPECT(mt, eof_type, "<<EOF>>");
377     }
378
379     {
380         std::istringstream iss("line 1\nline 2");
381         tokenizer mt(iss, true);
382
383         EXPECT(mt, word_type, "line");
384         EXPECT(mt, word_type, "1");
385         EXPECT(mt, nl_type, "<<NEWLINE>>");
386         EXPECT(mt, word_type, "line");
387         EXPECT(mt, word_type, "2");
388         EXPECT(mt, eof_type, "<<EOF>>");
389         EXPECT(mt, eof_type, "<<EOF>>");
390     }
391
392     {
393         std::istringstream iss("line 1\nline 2\nline 3\n");
394         tokenizer mt(iss, true);
395
396         EXPECT(mt, word_type, "line");
397         EXPECT(mt, word_type, "1");
398         EXPECT(mt, nl_type, "<<NEWLINE>>");
399         EXPECT(mt, word_type, "line");
400         EXPECT(mt, word_type, "2");
401         EXPECT(mt, nl_type, "<<NEWLINE>>");
402         EXPECT(mt, word_type, "line");
403         EXPECT(mt, word_type, "3");
404         EXPECT(mt, nl_type, "<<NEWLINE>>");
405         EXPECT(mt, eof_type, "<<EOF>>");
406         EXPECT(mt, eof_type, "<<EOF>>");
407     }
408
409     {
410         std::istringstream iss(" \t line \t 1\n\tline\t2\n line 3 \n");
411         tokenizer mt(iss, true);
412
413         EXPECT(mt, word_type, "line");
414         EXPECT(mt, word_type, "1");
415         EXPECT(mt, nl_type, "<<NEWLINE>>");
416         EXPECT(mt, word_type, "line");
417         EXPECT(mt, word_type, "2");
418         EXPECT(mt, nl_type, "<<NEWLINE>>");
419         EXPECT(mt, word_type, "line");
420         EXPECT(mt, word_type, "3");
421         EXPECT(mt, nl_type, "<<NEWLINE>>");
422         EXPECT(mt, eof_type, "<<EOF>>");
423         EXPECT(mt, eof_type, "<<EOF>>");
424     }
425 }
426
427 ATF_TEST_CASE(tokenizer_delims_nows);
428 ATF_TEST_CASE_HEAD(tokenizer_delims_nows)
429 {
430     set_md_var("descr", "Tests the tokenizer class using a parser with some "
431                "additional delimiters and not skipping whitespace");
432 }
433 ATF_TEST_CASE_BODY(tokenizer_delims_nows)
434 {
435     using namespace delims;
436
437     {
438         std::istringstream iss("+-=");
439         tokenizer mt(iss, false);
440
441         EXPECT(mt, plus_type, "+");
442         EXPECT(mt, minus_type, "-");
443         EXPECT(mt, equal_type, "=");
444         EXPECT(mt, eof_type, "<<EOF>>");
445         EXPECT(mt, eof_type, "<<EOF>>");
446     }
447
448     {
449         std::istringstream iss("+++");
450         tokenizer mt(iss, false);
451
452         EXPECT(mt, plus_type, "+");
453         EXPECT(mt, plus_type, "+");
454         EXPECT(mt, plus_type, "+");
455         EXPECT(mt, eof_type, "<<EOF>>");
456         EXPECT(mt, eof_type, "<<EOF>>");
457     }
458
459     {
460         std::istringstream iss("\n+\n++\n");
461         tokenizer mt(iss, false);
462
463         EXPECT(mt, nl_type, "<<NEWLINE>>");
464         EXPECT(mt, plus_type, "+");
465         EXPECT(mt, nl_type, "<<NEWLINE>>");
466         EXPECT(mt, plus_type, "+");
467         EXPECT(mt, plus_type, "+");
468         EXPECT(mt, nl_type, "<<NEWLINE>>");
469         EXPECT(mt, eof_type, "<<EOF>>");
470         EXPECT(mt, eof_type, "<<EOF>>");
471     }
472
473     {
474         std::istringstream iss("foo+bar=baz");
475         tokenizer mt(iss, false);
476
477         EXPECT(mt, word_type, "foo");
478         EXPECT(mt, plus_type, "+");
479         EXPECT(mt, word_type, "bar");
480         EXPECT(mt, equal_type, "=");
481         EXPECT(mt, word_type, "baz");
482         EXPECT(mt, eof_type, "<<EOF>>");
483         EXPECT(mt, eof_type, "<<EOF>>");
484     }
485
486     {
487         std::istringstream iss(" foo\t+\tbar = baz ");
488         tokenizer mt(iss, false);
489
490         EXPECT(mt, word_type, " foo\t");
491         EXPECT(mt, plus_type, "+");
492         EXPECT(mt, word_type, "\tbar ");
493         EXPECT(mt, equal_type, "=");
494         EXPECT(mt, word_type, " baz ");
495         EXPECT(mt, eof_type, "<<EOF>>");
496         EXPECT(mt, eof_type, "<<EOF>>");
497     }
498 }
499
500 ATF_TEST_CASE(tokenizer_delims_ws);
501 ATF_TEST_CASE_HEAD(tokenizer_delims_ws)
502 {
503     set_md_var("descr", "Tests the tokenizer class using a parser with some "
504                "additional delimiters and skipping whitespace");
505 }
506 ATF_TEST_CASE_BODY(tokenizer_delims_ws)
507 {
508     using namespace delims;
509
510     {
511         std::istringstream iss(" foo\t+\tbar = baz ");
512         tokenizer mt(iss, true);
513
514         EXPECT(mt, word_type, "foo");
515         EXPECT(mt, plus_type, "+");
516         EXPECT(mt, word_type, "bar");
517         EXPECT(mt, equal_type, "=");
518         EXPECT(mt, word_type, "baz");
519         EXPECT(mt, eof_type, "<<EOF>>");
520         EXPECT(mt, eof_type, "<<EOF>>");
521     }
522 }
523
524 ATF_TEST_CASE(tokenizer_keywords_nows);
525 ATF_TEST_CASE_HEAD(tokenizer_keywords_nows)
526 {
527     set_md_var("descr", "Tests the tokenizer class using a parser with some "
528                "additional keywords and not skipping whitespace");
529 }
530 ATF_TEST_CASE_BODY(tokenizer_keywords_nows)
531 {
532     using namespace keywords;
533
534     {
535         std::istringstream iss("var");
536         tokenizer mt(iss, false);
537
538         EXPECT(mt, var_type, "var");
539         EXPECT(mt, eof_type, "<<EOF>>");
540         EXPECT(mt, eof_type, "<<EOF>>");
541     }
542
543     {
544         std::istringstream iss("va");
545         tokenizer mt(iss, false);
546
547         EXPECT(mt, word_type, "va");
548         EXPECT(mt, eof_type, "<<EOF>>");
549         EXPECT(mt, eof_type, "<<EOF>>");
550     }
551
552     {
553         std::istringstream iss("vara");
554         tokenizer mt(iss, false);
555
556         EXPECT(mt, word_type, "vara");
557         EXPECT(mt, eof_type, "<<EOF>>");
558         EXPECT(mt, eof_type, "<<EOF>>");
559     }
560
561     {
562         std::istringstream iss("var ");
563         tokenizer mt(iss, false);
564
565         EXPECT(mt, word_type, "var ");
566         EXPECT(mt, eof_type, "<<EOF>>");
567         EXPECT(mt, eof_type, "<<EOF>>");
568     }
569
570     {
571         std::istringstream iss("var\nloop\nendloop");
572         tokenizer mt(iss, false);
573
574         EXPECT(mt, var_type, "var");
575         EXPECT(mt, nl_type, "<<NEWLINE>>");
576         EXPECT(mt, loop_type, "loop");
577         EXPECT(mt, nl_type, "<<NEWLINE>>");
578         EXPECT(mt, endloop_type, "endloop");
579         EXPECT(mt, eof_type, "<<EOF>>");
580         EXPECT(mt, eof_type, "<<EOF>>");
581     }
582 }
583
584 ATF_TEST_CASE(tokenizer_keywords_ws);
585 ATF_TEST_CASE_HEAD(tokenizer_keywords_ws)
586 {
587     set_md_var("descr", "Tests the tokenizer class using a parser with some "
588                "additional keywords and not skipping whitespace");
589 }
590 ATF_TEST_CASE_BODY(tokenizer_keywords_ws)
591 {
592     using namespace keywords;
593
594     {
595         std::istringstream iss("var ");
596         tokenizer mt(iss, true);
597
598         EXPECT(mt, var_type, "var");
599         EXPECT(mt, eof_type, "<<EOF>>");
600         EXPECT(mt, eof_type, "<<EOF>>");
601     }
602
603     {
604         std::istringstream iss(" var \n\tloop\t\n \tendloop \t");
605         tokenizer mt(iss, true);
606
607         EXPECT(mt, var_type, "var");
608         EXPECT(mt, nl_type, "<<NEWLINE>>");
609         EXPECT(mt, loop_type, "loop");
610         EXPECT(mt, nl_type, "<<NEWLINE>>");
611         EXPECT(mt, endloop_type, "endloop");
612         EXPECT(mt, eof_type, "<<EOF>>");
613         EXPECT(mt, eof_type, "<<EOF>>");
614     }
615
616     {
617         std::istringstream iss("var loop endloop");
618         tokenizer mt(iss, true);
619
620         EXPECT(mt, var_type, "var");
621         EXPECT(mt, loop_type, "loop");
622         EXPECT(mt, endloop_type, "endloop");
623         EXPECT(mt, eof_type, "<<EOF>>");
624         EXPECT(mt, eof_type, "<<EOF>>");
625     }
626 }
627
628 ATF_TEST_CASE(tokenizer_quotes_nows);
629 ATF_TEST_CASE_HEAD(tokenizer_quotes_nows)
630 {
631     set_md_var("descr", "Tests the tokenizer class using a parser with "
632                "quoted strings and not skipping whitespace");
633 }
634 ATF_TEST_CASE_BODY(tokenizer_quotes_nows)
635 {
636     using namespace quotes;
637
638     {
639         std::istringstream iss("var");
640         tokenizer mt(iss, false);
641
642         EXPECT(mt, word_type, "var");
643         EXPECT(mt, eof_type, "<<EOF>>");
644         EXPECT(mt, eof_type, "<<EOF>>");
645     }
646
647     {
648         std::istringstream iss("\"var\"");
649         tokenizer mt(iss, false);
650
651         EXPECT(mt, word_type, "var");
652         EXPECT(mt, eof_type, "<<EOF>>");
653         EXPECT(mt, eof_type, "<<EOF>>");
654     }
655
656     {
657         std::istringstream iss("var1\"var2\"");
658         tokenizer mt(iss, false);
659
660         EXPECT(mt, word_type, "var1");
661         EXPECT(mt, word_type, "var2");
662         EXPECT(mt, eof_type, "<<EOF>>");
663         EXPECT(mt, eof_type, "<<EOF>>");
664     }
665
666     {
667         std::istringstream iss("var1\"  var2  \"");
668         tokenizer mt(iss, false);
669
670         EXPECT(mt, word_type, "var1");
671         EXPECT(mt, word_type, "  var2  ");
672         EXPECT(mt, eof_type, "<<EOF>>");
673         EXPECT(mt, eof_type, "<<EOF>>");
674     }
675 }
676
677 ATF_TEST_CASE(tokenizer_quotes_ws);
678 ATF_TEST_CASE_HEAD(tokenizer_quotes_ws)
679 {
680     set_md_var("descr", "Tests the tokenizer class using a parser with "
681                "quoted strings and skipping whitespace");
682 }
683 ATF_TEST_CASE_BODY(tokenizer_quotes_ws)
684 {
685     using namespace quotes;
686
687     {
688         std::istringstream iss("  var  ");
689         tokenizer mt(iss, true);
690
691         EXPECT(mt, word_type, "var");
692         EXPECT(mt, eof_type, "<<EOF>>");
693         EXPECT(mt, eof_type, "<<EOF>>");
694     }
695
696     {
697         std::istringstream iss("  \"var\"  ");
698         tokenizer mt(iss, true);
699
700         EXPECT(mt, word_type, "var");
701         EXPECT(mt, eof_type, "<<EOF>>");
702         EXPECT(mt, eof_type, "<<EOF>>");
703     }
704
705     {
706         std::istringstream iss("  var1  \"var2\"  ");
707         tokenizer mt(iss, true);
708
709         EXPECT(mt, word_type, "var1");
710         EXPECT(mt, word_type, "var2");
711         EXPECT(mt, eof_type, "<<EOF>>");
712         EXPECT(mt, eof_type, "<<EOF>>");
713     }
714
715     {
716         std::istringstream iss("  var1  \"  var2  \"  ");
717         tokenizer mt(iss, true);
718
719         EXPECT(mt, word_type, "var1");
720         EXPECT(mt, word_type, "  var2  ");
721         EXPECT(mt, eof_type, "<<EOF>>");
722         EXPECT(mt, eof_type, "<<EOF>>");
723     }
724 }
725
726 // ------------------------------------------------------------------------
727 // Tests for the headers parser.
728 // ------------------------------------------------------------------------
729
730 class header_reader {
731     std::istream& m_is;
732
733 public:
734     header_reader(std::istream& is) :
735         m_is(is)
736     {
737     }
738
739     void
740     read(void)
741     {
742         std::pair< size_t, atf::parser::headers_map > hml =
743             atf::parser::read_headers(m_is, 1);
744         atf::parser::validate_content_type(hml.second,
745             "application/X-atf-headers-test", 1234);
746     }
747
748     std::vector< std::string > m_calls;
749 };
750
751 ATF_TEST_CASE_WITHOUT_HEAD(headers_1);
752 ATF_TEST_CASE_BODY(headers_1)
753 {
754     const char* input =
755         ""
756     ;
757
758     const char* exp_calls[] = {
759         NULL
760     };
761
762     const char* exp_errors[] = {
763         "1: Unexpected token `<<EOF>>'; expected a header name",
764         NULL
765     };
766
767     do_parser_test< header_reader >(input, exp_calls, exp_errors);
768 }
769
770 ATF_TEST_CASE_WITHOUT_HEAD(headers_2);
771 ATF_TEST_CASE_BODY(headers_2)
772 {
773     const char* input =
774         "Content-Type\n"
775     ;
776
777     const char* exp_calls[] = {
778         NULL
779     };
780
781     const char* exp_errors[] = {
782         "1: Unexpected token `<<NEWLINE>>'; expected `:'",
783         NULL
784     };
785
786     do_parser_test< header_reader >(input, exp_calls, exp_errors);
787 }
788
789 ATF_TEST_CASE_WITHOUT_HEAD(headers_3);
790 ATF_TEST_CASE_BODY(headers_3)
791 {
792     const char* input =
793         "Content-Type:\n"
794     ;
795
796     const char* exp_calls[] = {
797         NULL
798     };
799
800     const char* exp_errors[] = {
801         "1: Unexpected token `<<NEWLINE>>'; expected a textual value",
802         NULL
803     };
804
805     do_parser_test< header_reader >(input, exp_calls, exp_errors);
806 }
807
808 ATF_TEST_CASE_WITHOUT_HEAD(headers_4);
809 ATF_TEST_CASE_BODY(headers_4)
810 {
811     const char* input =
812         "Content-Type: application/X-atf-headers-test\n"
813     ;
814
815     const char* exp_calls[] = {
816         NULL
817     };
818
819     const char* exp_errors[] = {
820         "2: Unexpected token `<<EOF>>'; expected a header name",
821         NULL
822     };
823
824     do_parser_test< header_reader >(input, exp_calls, exp_errors);
825 }
826
827 ATF_TEST_CASE_WITHOUT_HEAD(headers_5);
828 ATF_TEST_CASE_BODY(headers_5)
829 {
830     const char* input =
831         "Content-Type: application/X-atf-headers-test;\n"
832     ;
833
834     const char* exp_calls[] = {
835         NULL
836     };
837
838     const char* exp_errors[] = {
839         "1: Unexpected token `<<NEWLINE>>'; expected an attribute name",
840         NULL
841     };
842
843     do_parser_test< header_reader >(input, exp_calls, exp_errors);
844 }
845
846 ATF_TEST_CASE_WITHOUT_HEAD(headers_6);
847 ATF_TEST_CASE_BODY(headers_6)
848 {
849     const char* input =
850         "Content-Type: application/X-atf-headers-test; version\n"
851     ;
852
853     const char* exp_calls[] = {
854         NULL
855     };
856
857     const char* exp_errors[] = {
858         "1: Unexpected token `<<NEWLINE>>'; expected `='",
859         NULL
860     };
861
862     do_parser_test< header_reader >(input, exp_calls, exp_errors);
863 }
864
865 ATF_TEST_CASE_WITHOUT_HEAD(headers_7);
866 ATF_TEST_CASE_BODY(headers_7)
867 {
868     const char* input =
869         "Content-Type: application/X-atf-headers-test; version=\n"
870     ;
871
872     const char* exp_calls[] = {
873         NULL
874     };
875
876     const char* exp_errors[] = {
877         "1: Unexpected token `<<NEWLINE>>'; expected word or quoted string",
878         NULL
879     };
880
881     do_parser_test< header_reader >(input, exp_calls, exp_errors);
882 }
883
884 ATF_TEST_CASE_WITHOUT_HEAD(headers_8);
885 ATF_TEST_CASE_BODY(headers_8)
886 {
887     const char* input =
888         "Content-Type: application/X-atf-headers-test; version=\"1234\n"
889     ;
890
891     const char* exp_calls[] = {
892         NULL
893     };
894
895     const char* exp_errors[] = {
896         "1: Missing double quotes before end of line",
897         NULL
898     };
899
900     do_parser_test< header_reader >(input, exp_calls, exp_errors);
901 }
902
903 ATF_TEST_CASE_WITHOUT_HEAD(headers_9);
904 ATF_TEST_CASE_BODY(headers_9)
905 {
906     const char* input =
907         "Content-Type: application/X-atf-headers-test; version=1234\"\n"
908     ;
909
910     const char* exp_calls[] = {
911         NULL
912     };
913
914     const char* exp_errors[] = {
915         "1: Missing double quotes before end of line",
916         NULL
917     };
918
919     do_parser_test< header_reader >(input, exp_calls, exp_errors);
920 }
921
922 ATF_TEST_CASE_WITHOUT_HEAD(headers_10);
923 ATF_TEST_CASE_BODY(headers_10)
924 {
925     const char* input =
926         "Content-Type: application/X-atf-headers-test; version=1234\n"
927     ;
928
929     const char* exp_calls[] = {
930         NULL
931     };
932
933     const char* exp_errors[] = {
934         "2: Unexpected token `<<EOF>>'; expected a header name",
935         NULL
936     };
937
938     do_parser_test< header_reader >(input, exp_calls, exp_errors);
939 }
940
941 ATF_TEST_CASE_WITHOUT_HEAD(headers_11);
942 ATF_TEST_CASE_BODY(headers_11)
943 {
944     const char* input =
945         "Content-Type: application/X-atf-headers-test; version=\"1234\"\n"
946     ;
947
948     const char* exp_calls[] = {
949         NULL
950     };
951
952     const char* exp_errors[] = {
953         "2: Unexpected token `<<EOF>>'; expected a header name",
954         NULL
955     };
956
957     do_parser_test< header_reader >(input, exp_calls, exp_errors);
958 }
959
960 ATF_TEST_CASE_WITHOUT_HEAD(headers_12);
961 ATF_TEST_CASE_BODY(headers_12)
962 {
963     const char* input =
964         "Content-Type: application/X-atf-headers-test; version=\"1234\"\n"
965         "a b\n"
966         "a-b:\n"
967         "a-b: foo;\n"
968         "a-b: foo; var\n"
969         "a-b: foo; var=\n"
970         "a-b: foo; var=\"a\n"
971         "a-b: foo; var=a\"\n"
972         "a-b: foo; var=\"a\";\n"
973         "a-b: foo; var=\"a\"; second\n"
974         "a-b: foo; var=\"a\"; second=\n"
975         "a-b: foo; var=\"a\"; second=\"b\n"
976         "a-b: foo; var=\"a\"; second=b\"\n"
977         "a-b: foo; var=\"a\"; second=\"b\"\n"
978     ;
979
980     const char* exp_calls[] = {
981         NULL
982     };
983
984     const char* exp_errors[] = {
985         "2: Unexpected token `b'; expected `:'",
986         "3: Unexpected token `<<NEWLINE>>'; expected a textual value",
987         "4: Unexpected token `<<NEWLINE>>'; expected an attribute name",
988         "5: Unexpected token `<<NEWLINE>>'; expected `='",
989         "6: Unexpected token `<<NEWLINE>>'; expected word or quoted string",
990         "7: Missing double quotes before end of line",
991         "8: Missing double quotes before end of line",
992         "9: Unexpected token `<<NEWLINE>>'; expected an attribute name",
993         "10: Unexpected token `<<NEWLINE>>'; expected `='",
994         "11: Unexpected token `<<NEWLINE>>'; expected word or quoted string",
995         "12: Missing double quotes before end of line",
996         "13: Missing double quotes before end of line",
997         NULL
998     };
999
1000     do_parser_test< header_reader >(input, exp_calls, exp_errors);
1001 }
1002
1003 // ------------------------------------------------------------------------
1004 // Main.
1005 // ------------------------------------------------------------------------
1006
1007 ATF_INIT_TEST_CASES(tcs)
1008 {
1009     // Add test cases for the "parse_error" class.
1010     ATF_ADD_TEST_CASE(tcs, parse_error_to_string);
1011
1012     // Add test cases for the "parse_errors" class.
1013     ATF_ADD_TEST_CASE(tcs, parse_errors_what);
1014
1015     // Add test cases for the "token" class.
1016     ATF_ADD_TEST_CASE(tcs, token_getters);
1017
1018     // Add test cases for the "tokenizer" class.
1019     ATF_ADD_TEST_CASE(tcs, tokenizer_minimal_nows);
1020     ATF_ADD_TEST_CASE(tcs, tokenizer_minimal_ws);
1021     ATF_ADD_TEST_CASE(tcs, tokenizer_delims_nows);
1022     ATF_ADD_TEST_CASE(tcs, tokenizer_delims_ws);
1023     ATF_ADD_TEST_CASE(tcs, tokenizer_keywords_nows);
1024     ATF_ADD_TEST_CASE(tcs, tokenizer_keywords_ws);
1025     ATF_ADD_TEST_CASE(tcs, tokenizer_quotes_nows);
1026     ATF_ADD_TEST_CASE(tcs, tokenizer_quotes_ws);
1027
1028     // Add the tests for the headers parser.
1029
1030     // Add the test cases for the header file.
1031     ATF_ADD_TEST_CASE(tcs, headers_1);
1032     ATF_ADD_TEST_CASE(tcs, headers_2);
1033     ATF_ADD_TEST_CASE(tcs, headers_3);
1034     ATF_ADD_TEST_CASE(tcs, headers_4);
1035     ATF_ADD_TEST_CASE(tcs, headers_5);
1036     ATF_ADD_TEST_CASE(tcs, headers_6);
1037     ATF_ADD_TEST_CASE(tcs, headers_7);
1038     ATF_ADD_TEST_CASE(tcs, headers_8);
1039     ATF_ADD_TEST_CASE(tcs, headers_9);
1040     ATF_ADD_TEST_CASE(tcs, headers_10);
1041     ATF_ADD_TEST_CASE(tcs, headers_11);
1042     ATF_ADD_TEST_CASE(tcs, headers_12);
1043 }