Home | History | Annotate | Line # | Download | only in tools
parser_test.cpp revision 1.1.1.1.8.2
      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);
     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 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);
     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 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);
     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 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:
    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:
    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:
    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:
    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);
    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, 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);
    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 }
   1044