diff options
Diffstat (limited to 'unit/atf-src/tools/parser_test.cpp')
-rw-r--r-- | unit/atf-src/tools/parser_test.cpp | 1043 |
1 files changed, 1043 insertions, 0 deletions
diff --git a/unit/atf-src/tools/parser_test.cpp b/unit/atf-src/tools/parser_test.cpp new file mode 100644 index 0000000..434a1a6 --- /dev/null +++ b/unit/atf-src/tools/parser_test.cpp @@ -0,0 +1,1043 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include <sstream> + +#include <atf-c++.hpp> + +#include "parser.hpp" +#include "test_helpers.hpp" + +// ------------------------------------------------------------------------ +// Tests for the "parse_error" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(parse_error_to_string); +ATF_TEST_CASE_HEAD(parse_error_to_string) +{ + set_md_var("descr", "Tests the parse_error conversion to strings"); +} +ATF_TEST_CASE_BODY(parse_error_to_string) +{ + using tools::parser::parse_error; + + const parse_error e(123, "This is the message"); + ATF_REQUIRE_EQ("123: This is the message", std::string(e)); +} + +// ------------------------------------------------------------------------ +// Tests for the "parse_errors" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(parse_errors_what); +ATF_TEST_CASE_HEAD(parse_errors_what) +{ + set_md_var("descr", "Tests the parse_errors description"); +} +ATF_TEST_CASE_BODY(parse_errors_what) +{ + using tools::parser::parse_error; + using tools::parser::parse_errors; + + parse_errors es; + es.push_back(parse_error(2, "Second error")); + es.push_back(parse_error(1, "First error")); + + ATF_REQUIRE_EQ("2: Second error\n1: First error", std::string(es.what())); +} + +// ------------------------------------------------------------------------ +// Tests for the "token" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(token_getters); +ATF_TEST_CASE_HEAD(token_getters) +{ + set_md_var("descr", "Tests the token getters"); +} +ATF_TEST_CASE_BODY(token_getters) +{ + using tools::parser::token; + + { + token t(10, 0); + ATF_REQUIRE_EQ(t.lineno(), 10); + ATF_REQUIRE_EQ(t.type(), 0); + ATF_REQUIRE(t.text().empty()); + } + + { + token t(10, 0, "foo"); + ATF_REQUIRE_EQ(t.lineno(), 10); + ATF_REQUIRE_EQ(t.type(), 0); + ATF_REQUIRE_EQ(t.text(), "foo"); + } + + { + token t(20, 1); + ATF_REQUIRE_EQ(t.lineno(), 20); + ATF_REQUIRE_EQ(t.type(), 1); + ATF_REQUIRE(t.text().empty()); + } + + { + token t(20, 1, "bar"); + ATF_REQUIRE_EQ(t.lineno(), 20); + ATF_REQUIRE_EQ(t.type(), 1); + ATF_REQUIRE_EQ(t.text(), "bar"); + } +} + +// ------------------------------------------------------------------------ +// Tests for the "tokenizer" class. +// ------------------------------------------------------------------------ + +#define EXPECT(tkz, ttype, ttext) \ + do { \ + tools::parser::token t = tkz.next(); \ + ATF_REQUIRE(t.type() == ttype); \ + ATF_REQUIRE_EQ(t.text(), ttext); \ + } while (false); + +namespace minimal { + + static const tools::parser::token_type eof_type = 0; + static const tools::parser::token_type nl_type = 1; + static const tools::parser::token_type word_type = 2; + + class tokenizer : public tools::parser::tokenizer< std::istream > { + public: + tokenizer(std::istream& is, bool skipws) : + tools::parser::tokenizer< std::istream > + (is, skipws, eof_type, nl_type, word_type) + { + } + }; + +} + +namespace delims { + + static const tools::parser::token_type eof_type = 0; + static const tools::parser::token_type nl_type = 1; + static const tools::parser::token_type word_type = 2; + static const tools::parser::token_type plus_type = 3; + static const tools::parser::token_type minus_type = 4; + static const tools::parser::token_type equal_type = 5; + + class tokenizer : public tools::parser::tokenizer< std::istream > { + public: + tokenizer(std::istream& is, bool skipws) : + tools::parser::tokenizer< std::istream > + (is, skipws, eof_type, nl_type, word_type) + { + add_delim('+', plus_type); + add_delim('-', minus_type); + add_delim('=', equal_type); + } + }; + +} + +namespace keywords { + + static const tools::parser::token_type eof_type = 0; + static const tools::parser::token_type nl_type = 1; + static const tools::parser::token_type word_type = 2; + static const tools::parser::token_type var_type = 3; + static const tools::parser::token_type loop_type = 4; + static const tools::parser::token_type endloop_type = 5; + + class tokenizer : public tools::parser::tokenizer< std::istream > { + public: + tokenizer(std::istream& is, bool skipws) : + tools::parser::tokenizer< std::istream > + (is, skipws, eof_type, nl_type, word_type) + { + add_keyword("var", var_type); + add_keyword("loop", loop_type); + add_keyword("endloop", endloop_type); + } + }; + +} + +namespace quotes { + + static const tools::parser::token_type eof_type = 0; + static const tools::parser::token_type nl_type = 1; + static const tools::parser::token_type word_type = 2; + static const tools::parser::token_type dblquote_type = 3; + + class tokenizer : public tools::parser::tokenizer< std::istream > { + public: + tokenizer(std::istream& is, bool skipws) : + tools::parser::tokenizer< std::istream > + (is, skipws, eof_type, nl_type, word_type) + { + add_quote('"', dblquote_type); + } + }; + +} + +ATF_TEST_CASE(tokenizer_minimal_nows); +ATF_TEST_CASE_HEAD(tokenizer_minimal_nows) +{ + set_md_var("descr", "Tests the tokenizer class using a minimal parser " + "and not skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_minimal_nows) +{ + using namespace minimal; + + { + std::istringstream iss(""); + tokenizer mt(iss, false); + + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("\n"); + tokenizer mt(iss, false); + + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("\n\n\n"); + tokenizer mt(iss, false); + + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("line 1"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "line 1"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("line 1\n"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "line 1"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("line 1\nline 2"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "line 1"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, word_type, "line 2"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("line 1\nline 2\nline 3\n"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "line 1"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, word_type, "line 2"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, word_type, "line 3"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } +} + +ATF_TEST_CASE(tokenizer_minimal_ws); +ATF_TEST_CASE_HEAD(tokenizer_minimal_ws) +{ + set_md_var("descr", "Tests the tokenizer class using a minimal parser " + "and skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_minimal_ws) +{ + using namespace minimal; + + { + std::istringstream iss(""); + minimal::tokenizer mt(iss, true); + + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss(" \t "); + tokenizer mt(iss, true); + + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("\n"); + tokenizer mt(iss, true); + + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss(" \t \n \t "); + tokenizer mt(iss, true); + + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("\n\n\n"); + tokenizer mt(iss, true); + + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("line 1"); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "1"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss(" \tline\t 1\t"); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "1"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("line 1\n"); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "1"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("line 1\nline 2"); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "1"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "2"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("line 1\nline 2\nline 3\n"); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "1"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "2"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "3"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss(" \t line \t 1\n\tline\t2\n line 3 \n"); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "1"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "2"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "3"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } +} + +ATF_TEST_CASE(tokenizer_delims_nows); +ATF_TEST_CASE_HEAD(tokenizer_delims_nows) +{ + set_md_var("descr", "Tests the tokenizer class using a parser with some " + "additional delimiters and not skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_delims_nows) +{ + using namespace delims; + + { + std::istringstream iss("+-="); + tokenizer mt(iss, false); + + EXPECT(mt, plus_type, "+"); + EXPECT(mt, minus_type, "-"); + EXPECT(mt, equal_type, "="); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("+++"); + tokenizer mt(iss, false); + + EXPECT(mt, plus_type, "+"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("\n+\n++\n"); + tokenizer mt(iss, false); + + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("foo+bar=baz"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "foo"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, word_type, "bar"); + EXPECT(mt, equal_type, "="); + EXPECT(mt, word_type, "baz"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss(" foo\t+\tbar = baz "); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, " foo\t"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, word_type, "\tbar "); + EXPECT(mt, equal_type, "="); + EXPECT(mt, word_type, " baz "); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } +} + +ATF_TEST_CASE(tokenizer_delims_ws); +ATF_TEST_CASE_HEAD(tokenizer_delims_ws) +{ + set_md_var("descr", "Tests the tokenizer class using a parser with some " + "additional delimiters and skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_delims_ws) +{ + using namespace delims; + + { + std::istringstream iss(" foo\t+\tbar = baz "); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "foo"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, word_type, "bar"); + EXPECT(mt, equal_type, "="); + EXPECT(mt, word_type, "baz"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } +} + +ATF_TEST_CASE(tokenizer_keywords_nows); +ATF_TEST_CASE_HEAD(tokenizer_keywords_nows) +{ + set_md_var("descr", "Tests the tokenizer class using a parser with some " + "additional keywords and not skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_keywords_nows) +{ + using namespace keywords; + + { + std::istringstream iss("var"); + tokenizer mt(iss, false); + + EXPECT(mt, var_type, "var"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("va"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "va"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("vara"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "vara"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("var "); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "var "); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("var\nloop\nendloop"); + tokenizer mt(iss, false); + + EXPECT(mt, var_type, "var"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, loop_type, "loop"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, endloop_type, "endloop"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } +} + +ATF_TEST_CASE(tokenizer_keywords_ws); +ATF_TEST_CASE_HEAD(tokenizer_keywords_ws) +{ + set_md_var("descr", "Tests the tokenizer class using a parser with some " + "additional keywords and not skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_keywords_ws) +{ + using namespace keywords; + + { + std::istringstream iss("var "); + tokenizer mt(iss, true); + + EXPECT(mt, var_type, "var"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss(" var \n\tloop\t\n \tendloop \t"); + tokenizer mt(iss, true); + + EXPECT(mt, var_type, "var"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, loop_type, "loop"); + EXPECT(mt, nl_type, "<<NEWLINE>>"); + EXPECT(mt, endloop_type, "endloop"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("var loop endloop"); + tokenizer mt(iss, true); + + EXPECT(mt, var_type, "var"); + EXPECT(mt, loop_type, "loop"); + EXPECT(mt, endloop_type, "endloop"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } +} + +ATF_TEST_CASE(tokenizer_quotes_nows); +ATF_TEST_CASE_HEAD(tokenizer_quotes_nows) +{ + set_md_var("descr", "Tests the tokenizer class using a parser with " + "quoted strings and not skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_quotes_nows) +{ + using namespace quotes; + + { + std::istringstream iss("var"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "var"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("\"var\""); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "var"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("var1\"var2\""); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "var1"); + EXPECT(mt, word_type, "var2"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss("var1\" var2 \""); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "var1"); + EXPECT(mt, word_type, " var2 "); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } +} + +ATF_TEST_CASE(tokenizer_quotes_ws); +ATF_TEST_CASE_HEAD(tokenizer_quotes_ws) +{ + set_md_var("descr", "Tests the tokenizer class using a parser with " + "quoted strings and skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_quotes_ws) +{ + using namespace quotes; + + { + std::istringstream iss(" var "); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "var"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss(" \"var\" "); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "var"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss(" var1 \"var2\" "); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "var1"); + EXPECT(mt, word_type, "var2"); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } + + { + std::istringstream iss(" var1 \" var2 \" "); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "var1"); + EXPECT(mt, word_type, " var2 "); + EXPECT(mt, eof_type, "<<EOF>>"); + EXPECT(mt, eof_type, "<<EOF>>"); + } +} + +// ------------------------------------------------------------------------ +// Tests for the headers parser. +// ------------------------------------------------------------------------ + +class header_reader { + std::istream& m_is; + +public: + header_reader(std::istream& is) : + m_is(is) + { + } + + void + read(void) + { + std::pair< size_t, tools::parser::headers_map > hml = + tools::parser::read_headers(m_is, 1); + tools::parser::validate_content_type(hml.second, + "application/X-atf-headers-test", 1234); + } + + std::vector< std::string > m_calls; +}; + +ATF_TEST_CASE_WITHOUT_HEAD(headers_1); +ATF_TEST_CASE_BODY(headers_1) +{ + const char* input = + "" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Unexpected token `<<EOF>>'; expected a header name", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_2); +ATF_TEST_CASE_BODY(headers_2) +{ + const char* input = + "Content-Type\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Unexpected token `<<NEWLINE>>'; expected `:'", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_3); +ATF_TEST_CASE_BODY(headers_3) +{ + const char* input = + "Content-Type:\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Unexpected token `<<NEWLINE>>'; expected a textual value", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_4); +ATF_TEST_CASE_BODY(headers_4) +{ + const char* input = + "Content-Type: application/X-atf-headers-test\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "2: Unexpected token `<<EOF>>'; expected a header name", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_5); +ATF_TEST_CASE_BODY(headers_5) +{ + const char* input = + "Content-Type: application/X-atf-headers-test;\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Unexpected token `<<NEWLINE>>'; expected an attribute name", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_6); +ATF_TEST_CASE_BODY(headers_6) +{ + const char* input = + "Content-Type: application/X-atf-headers-test; version\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Unexpected token `<<NEWLINE>>'; expected `='", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_7); +ATF_TEST_CASE_BODY(headers_7) +{ + const char* input = + "Content-Type: application/X-atf-headers-test; version=\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Unexpected token `<<NEWLINE>>'; expected word or quoted string", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_8); +ATF_TEST_CASE_BODY(headers_8) +{ + const char* input = + "Content-Type: application/X-atf-headers-test; version=\"1234\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Missing double quotes before end of line", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_9); +ATF_TEST_CASE_BODY(headers_9) +{ + const char* input = + "Content-Type: application/X-atf-headers-test; version=1234\"\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Missing double quotes before end of line", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_10); +ATF_TEST_CASE_BODY(headers_10) +{ + const char* input = + "Content-Type: application/X-atf-headers-test; version=1234\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "2: Unexpected token `<<EOF>>'; expected a header name", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_11); +ATF_TEST_CASE_BODY(headers_11) +{ + const char* input = + "Content-Type: application/X-atf-headers-test; version=\"1234\"\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "2: Unexpected token `<<EOF>>'; expected a header name", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_12); +ATF_TEST_CASE_BODY(headers_12) +{ + const char* input = + "Content-Type: application/X-atf-headers-test; version=\"1234\"\n" + "a b\n" + "a-b:\n" + "a-b: foo;\n" + "a-b: foo; var\n" + "a-b: foo; var=\n" + "a-b: foo; var=\"a\n" + "a-b: foo; var=a\"\n" + "a-b: foo; var=\"a\";\n" + "a-b: foo; var=\"a\"; second\n" + "a-b: foo; var=\"a\"; second=\n" + "a-b: foo; var=\"a\"; second=\"b\n" + "a-b: foo; var=\"a\"; second=b\"\n" + "a-b: foo; var=\"a\"; second=\"b\"\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "2: Unexpected token `b'; expected `:'", + "3: Unexpected token `<<NEWLINE>>'; expected a textual value", + "4: Unexpected token `<<NEWLINE>>'; expected an attribute name", + "5: Unexpected token `<<NEWLINE>>'; expected `='", + "6: Unexpected token `<<NEWLINE>>'; expected word or quoted string", + "7: Missing double quotes before end of line", + "8: Missing double quotes before end of line", + "9: Unexpected token `<<NEWLINE>>'; expected an attribute name", + "10: Unexpected token `<<NEWLINE>>'; expected `='", + "11: Unexpected token `<<NEWLINE>>'; expected word or quoted string", + "12: Missing double quotes before end of line", + "13: Missing double quotes before end of line", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add test cases for the "parse_error" class. + ATF_ADD_TEST_CASE(tcs, parse_error_to_string); + + // Add test cases for the "parse_errors" class. + ATF_ADD_TEST_CASE(tcs, parse_errors_what); + + // Add test cases for the "token" class. + ATF_ADD_TEST_CASE(tcs, token_getters); + + // Add test cases for the "tokenizer" class. + ATF_ADD_TEST_CASE(tcs, tokenizer_minimal_nows); + ATF_ADD_TEST_CASE(tcs, tokenizer_minimal_ws); + ATF_ADD_TEST_CASE(tcs, tokenizer_delims_nows); + ATF_ADD_TEST_CASE(tcs, tokenizer_delims_ws); + ATF_ADD_TEST_CASE(tcs, tokenizer_keywords_nows); + ATF_ADD_TEST_CASE(tcs, tokenizer_keywords_ws); + ATF_ADD_TEST_CASE(tcs, tokenizer_quotes_nows); + ATF_ADD_TEST_CASE(tcs, tokenizer_quotes_ws); + + // Add the tests for the headers parser. + + // Add the test cases for the header file. + ATF_ADD_TEST_CASE(tcs, headers_1); + ATF_ADD_TEST_CASE(tcs, headers_2); + ATF_ADD_TEST_CASE(tcs, headers_3); + ATF_ADD_TEST_CASE(tcs, headers_4); + ATF_ADD_TEST_CASE(tcs, headers_5); + ATF_ADD_TEST_CASE(tcs, headers_6); + ATF_ADD_TEST_CASE(tcs, headers_7); + ATF_ADD_TEST_CASE(tcs, headers_8); + ATF_ADD_TEST_CASE(tcs, headers_9); + ATF_ADD_TEST_CASE(tcs, headers_10); + ATF_ADD_TEST_CASE(tcs, headers_11); + ATF_ADD_TEST_CASE(tcs, headers_12); +} |