xref: /minix3/external/bsd/atf/dist/tools/parser_test.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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 <atf-c++.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);
ATF_TEST_CASE_HEAD(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  }
ATF_TEST_CASE_BODY(parse_error_to_string)46  ATF_TEST_CASE_BODY(parse_error_to_string)
47  {
48      using tools::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);
ATF_TEST_CASE_HEAD(parse_errors_what)59  ATF_TEST_CASE_HEAD(parse_errors_what)
60  {
61      set_md_var("descr", "Tests the parse_errors description");
62  }
ATF_TEST_CASE_BODY(parse_errors_what)63  ATF_TEST_CASE_BODY(parse_errors_what)
64  {
65      using tools::parser::parse_error;
66      using tools::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);
ATF_TEST_CASE_HEAD(token_getters)80  ATF_TEST_CASE_HEAD(token_getters)
81  {
82      set_md_var("descr", "Tests the token getters");
83  }
ATF_TEST_CASE_BODY(token_getters)84  ATF_TEST_CASE_BODY(token_getters)
85  {
86      using tools::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          tools::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 tools::parser::token_type eof_type = 0;
131      static const tools::parser::token_type nl_type = 1;
132      static const tools::parser::token_type word_type = 2;
133  
134      class tokenizer : public tools::parser::tokenizer< std::istream > {
135      public:
tokenizer(std::istream & is,bool skipws)136          tokenizer(std::istream& is, bool skipws) :
137              tools::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 tools::parser::token_type eof_type = 0;
148      static const tools::parser::token_type nl_type = 1;
149      static const tools::parser::token_type word_type = 2;
150      static const tools::parser::token_type plus_type = 3;
151      static const tools::parser::token_type minus_type = 4;
152      static const tools::parser::token_type equal_type = 5;
153  
154      class tokenizer : public tools::parser::tokenizer< std::istream > {
155      public:
tokenizer(std::istream & is,bool skipws)156          tokenizer(std::istream& is, bool skipws) :
157              tools::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 tools::parser::token_type eof_type = 0;
171      static const tools::parser::token_type nl_type = 1;
172      static const tools::parser::token_type word_type = 2;
173      static const tools::parser::token_type var_type = 3;
174      static const tools::parser::token_type loop_type = 4;
175      static const tools::parser::token_type endloop_type = 5;
176  
177      class tokenizer : public tools::parser::tokenizer< std::istream > {
178      public:
tokenizer(std::istream & is,bool skipws)179          tokenizer(std::istream& is, bool skipws) :
180              tools::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 tools::parser::token_type eof_type = 0;
194      static const tools::parser::token_type nl_type = 1;
195      static const tools::parser::token_type word_type = 2;
196      static const tools::parser::token_type dblquote_type = 3;
197  
198      class tokenizer : public tools::parser::tokenizer< std::istream > {
199      public:
tokenizer(std::istream & is,bool skipws)200          tokenizer(std::istream& is, bool skipws) :
201              tools::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);
ATF_TEST_CASE_HEAD(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  }
ATF_TEST_CASE_BODY(tokenizer_minimal_nows)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);
ATF_TEST_CASE_HEAD(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  }
ATF_TEST_CASE_BODY(tokenizer_minimal_ws)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);
ATF_TEST_CASE_HEAD(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  }
ATF_TEST_CASE_BODY(tokenizer_delims_nows)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);
ATF_TEST_CASE_HEAD(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  }
ATF_TEST_CASE_BODY(tokenizer_delims_ws)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);
ATF_TEST_CASE_HEAD(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  }
ATF_TEST_CASE_BODY(tokenizer_keywords_nows)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);
ATF_TEST_CASE_HEAD(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  }
ATF_TEST_CASE_BODY(tokenizer_keywords_ws)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);
ATF_TEST_CASE_HEAD(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  }
ATF_TEST_CASE_BODY(tokenizer_quotes_nows)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);
ATF_TEST_CASE_HEAD(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  }
ATF_TEST_CASE_BODY(tokenizer_quotes_ws)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:
header_reader(std::istream & is)734      header_reader(std::istream& is) :
735          m_is(is)
736      {
737      }
738  
739      void
read(void)740      read(void)
741      {
742          std::pair< size_t, tools::parser::headers_map > hml =
743              tools::parser::read_headers(m_is, 1);
744          tools::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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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);
ATF_TEST_CASE_BODY(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  
ATF_INIT_TEST_CASES(tcs)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  }
1044