From: JINMEI Tatuya Date: Fri, 26 Oct 2012 06:15:39 +0000 (-0700) Subject: [2370] defined MasterLexer and its Token classes, added main methods and tests X-Git-Tag: trac2487_base~32^2^2~8 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a54864927bc88eebbfb0f9515207ba9a3cacaa3e;p=thirdparty%2Fkea.git [2370] defined MasterLexer and its Token classes, added main methods and tests --- diff --git a/src/lib/dns/Makefile.am b/src/lib/dns/Makefile.am index 977854d1e2..f1c2d08984 100644 --- a/src/lib/dns/Makefile.am +++ b/src/lib/dns/Makefile.am @@ -95,6 +95,7 @@ libb10_dns___la_SOURCES += edns.h edns.cc libb10_dns___la_SOURCES += exceptions.h exceptions.cc libb10_dns___la_SOURCES += labelsequence.h labelsequence.cc libb10_dns___la_SOURCES += masterload.h masterload.cc +libb10_dns___la_SOURCES += master_lexer.h libb10_dns___la_SOURCES += message.h message.cc libb10_dns___la_SOURCES += messagerenderer.h messagerenderer.cc libb10_dns___la_SOURCES += name.h name.cc @@ -145,6 +146,8 @@ libdns___include_HEADERS = \ exceptions.h \ labelsequence.h \ message.h \ + master_lexer.h \ + masterload.h \ messagerenderer.h \ name.h \ question.h \ diff --git a/src/lib/dns/master_lexer.h b/src/lib/dns/master_lexer.h new file mode 100644 index 0000000000..5af2c06336 --- /dev/null +++ b/src/lib/dns/master_lexer.h @@ -0,0 +1,101 @@ +// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#ifndef MASTER_LEXER_H +#define MASTER_LEXER_H 1 + +#include + +#include + +#include + +namespace isc { +namespace dns { + +class MasterLexer { +public: + class Token { + public: + enum Type { + ERROR, + END_OF_LINE, + END_OF_FILE, + INITIAL_WS, + STRING, + QSTRING, + NUMBER + }; + + struct StringRegion { + const char* beg; + size_t len; + }; + + explicit Token(Type type) : type_(type) { + if (type >= STRING) { + isc_throw(InvalidParameter, "Token per-type constructor " + "called with invalid type: " << type); + } + } + Token(const char* str_beg, size_t str_len, bool quoted = false) : + type_(quoted ? QSTRING : STRING) + { + val_.str_region_.beg = str_beg; + val_.str_region_.len = str_len; + } + explicit Token(uint32_t number) : type_(NUMBER) { + val_.number_ = number; + } + + Type getType() const { return (type_); } + std::string getString() const { + if (type_ != STRING && type_ != QSTRING) { + isc_throw(InvalidOperation, + "Token::getString() for non string-variant type"); + } + return (std::string(val_.str_region_.beg, + val_.str_region_.beg + val_.str_region_.len)); + } + const StringRegion& getStringRegion() const { + if (type_ != STRING && type_ != QSTRING) { + isc_throw(InvalidOperation, + "Token::getString() for non string-variant type"); + } + return (val_.str_region_); + } + uint32_t getNumber() const { + if (type_ != NUMBER) { + isc_throw(InvalidOperation, + "Token::getNumber() for non number type"); + } + return (val_.number_); + } + + private: + Type type_; + union { + StringRegion str_region_; + uint32_t number_; + } val_; + }; +}; + +} // namespace dns +} // namespace isc +#endif // MASTER_LEXER_H + +// Local Variables: +// mode: c++ +// End: diff --git a/src/lib/dns/tests/Makefile.am b/src/lib/dns/tests/Makefile.am index e8cbe101f5..6df0e624d4 100644 --- a/src/lib/dns/tests/Makefile.am +++ b/src/lib/dns/tests/Makefile.am @@ -24,6 +24,7 @@ run_unittests_SOURCES = unittest_util.h unittest_util.cc run_unittests_SOURCES += edns_unittest.cc run_unittests_SOURCES += labelsequence_unittest.cc run_unittests_SOURCES += messagerenderer_unittest.cc +run_unittests_SOURCES += master_lexer_token_unittest.cc run_unittests_SOURCES += name_unittest.cc run_unittests_SOURCES += nsec3hash_unittest.cc run_unittests_SOURCES += rrclass_unittest.cc rrtype_unittest.cc diff --git a/src/lib/dns/tests/master_lexer_token_unittest.cc b/src/lib/dns/tests/master_lexer_token_unittest.cc new file mode 100644 index 0000000000..a43d6e327d --- /dev/null +++ b/src/lib/dns/tests/master_lexer_token_unittest.cc @@ -0,0 +1,110 @@ +// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#include + +#include + +#include + +#include + +using namespace isc::dns; + +namespace { + +const char TEST_STRING[] = "string token"; + +class MasterLexerTokenTest : public ::testing::Test { +public: + MasterLexerTokenTest() : + token_err(MasterLexer::Token::ERROR), + token_str(TEST_STRING, sizeof(TEST_STRING) - 1), // excluding ending 0 + token_num(42) + {} + + const MasterLexer::Token token_err; + const MasterLexer::Token token_str; + const MasterLexer::Token token_num; +}; + + +TEST_F(MasterLexerTokenTest, strings) { + EXPECT_EQ(MasterLexer::Token::STRING, token_str.getType()); + EXPECT_EQ(std::string("string token"), token_str.getString()); + const MasterLexer::Token::StringRegion str_region = + token_str.getStringRegion(); + EXPECT_EQ(TEST_STRING, str_region.beg); + EXPECT_EQ(sizeof(TEST_STRING) - 1, str_region.len); + + // Construct type of qstring + EXPECT_EQ(MasterLexer::Token::QSTRING, + MasterLexer::Token(TEST_STRING, sizeof(TEST_STRING), true). + getType()); + // if we explicitly set 'quoted' to false, it should be normal string + EXPECT_EQ(MasterLexer::Token::STRING, + MasterLexer::Token(TEST_STRING, sizeof(TEST_STRING), false). + getType()); + + // getString/StringRegion() aren't allowed for non string(-variant) types + EXPECT_THROW(token_err.getString(), isc::InvalidOperation); + EXPECT_THROW(token_num.getString(), isc::InvalidOperation); + EXPECT_THROW(token_err.getStringRegion(), isc::InvalidOperation); + EXPECT_THROW(token_num.getStringRegion(), isc::InvalidOperation); +} + +TEST_F(MasterLexerTokenTest, numbers) { + EXPECT_EQ(42, token_num.getNumber()); + EXPECT_EQ(MasterLexer::Token::NUMBER, token_num.getType()); + + // It's copyable and assignable. + MasterLexer::Token token(token_num); + EXPECT_EQ(42, token.getNumber()); + EXPECT_EQ(MasterLexer::Token::NUMBER, token.getType()); + + token = token_num; + EXPECT_EQ(42, token.getNumber()); + EXPECT_EQ(MasterLexer::Token::NUMBER, token.getType()); + + // it's okay to replace it with a different type of token + token = token_err; + EXPECT_EQ(MasterLexer::Token::ERROR, token.getType()); + + // Possible max value + token = MasterLexer::Token(0xffffffff); + EXPECT_EQ(4294967295u, token.getNumber()); + + // TBD: getNumber for other type + EXPECT_THROW(token_err.getNumber(), isc::InvalidOperation); +} + +TEST_F(MasterLexerTokenTest, specials) { + // Just checking we can construct them and getType() returns correct value. + EXPECT_EQ(MasterLexer::Token::ERROR, token_err.getType()); + EXPECT_EQ(MasterLexer::Token::END_OF_LINE, + MasterLexer::Token(MasterLexer::Token::END_OF_LINE).getType()); + EXPECT_EQ(MasterLexer::Token::END_OF_FILE, + MasterLexer::Token(MasterLexer::Token::END_OF_FILE).getType()); + EXPECT_EQ(MasterLexer::Token::INITIAL_WS, + MasterLexer::Token(MasterLexer::Token::INITIAL_WS).getType()); + + // Special types of tokens cannot have value-based types + EXPECT_THROW(MasterLexer::Token t(MasterLexer::Token::STRING), + isc::InvalidParameter); + EXPECT_THROW(MasterLexer::Token t(MasterLexer::Token::QSTRING), + isc::InvalidParameter); + EXPECT_THROW(MasterLexer::Token t(MasterLexer::Token::NUMBER), + isc::InvalidParameter); +} +}