Browse Source

[4626] Unit-tests implemented for parser.

Tomek Mrugalski 8 years ago
parent
commit
524830e575

+ 8 - 1
src/lib/dhcpsrv/client_class_def.cc

@@ -44,6 +44,10 @@ ClientClassDef::ClientClassDef(const ClientClassDef& rhs)
     if (rhs.cfg_option_) {
     if (rhs.cfg_option_) {
         rhs.cfg_option_->copyTo(*cfg_option_);
         rhs.cfg_option_->copyTo(*cfg_option_);
     }
     }
+
+    next_server_ = rhs.next_server_;
+    sname_ = rhs.sname_;
+    filename_ = rhs.filename_;
 }
 }
 
 
 ClientClassDef::~ClientClassDef() {
 ClientClassDef::~ClientClassDef() {
@@ -87,7 +91,10 @@ ClientClassDef::equals(const ClientClassDef& other) const {
          (*match_expr_ == *(other.match_expr_)))) &&
          (*match_expr_ == *(other.match_expr_)))) &&
         ((!cfg_option_ && !other.cfg_option_) ||
         ((!cfg_option_ && !other.cfg_option_) ||
         (cfg_option_ && other.cfg_option_ &&
         (cfg_option_ && other.cfg_option_ &&
-         (*cfg_option_ == *other.cfg_option_))));
+         (*cfg_option_ == *other.cfg_option_))) &&
+            (next_server_ == other.next_server_) &&
+            (sname_ == other.sname_) &&
+            (filename_ == other.filename_));
 }
 }
 
 
 std::ostream& operator<<(std::ostream& os, const ClientClassDef& x) {
 std::ostream& operator<<(std::ostream& os, const ClientClassDef& x) {

+ 181 - 0
src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc

@@ -12,6 +12,7 @@
 #include <dhcp/option_string.h>
 #include <dhcp/option_string.h>
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/parsers/client_class_def_parser.h>
 #include <dhcpsrv/parsers/client_class_def_parser.h>
+#include <asiolink/io_address.h>
 #include <eval/evaluate.h>
 #include <eval/evaluate.h>
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 #include <sstream>
 #include <sstream>
@@ -23,6 +24,7 @@
 
 
 using namespace isc::data;
 using namespace isc::data;
 using namespace isc::dhcp;
 using namespace isc::dhcp;
+using namespace isc::asiolink;
 
 
 namespace {
 namespace {
 
 
@@ -583,4 +585,183 @@ TEST_F(ClientClassDefListParserTest, invalidClass) {
                  DhcpConfigError);
                  DhcpConfigError);
 }
 }
 
 
+TEST_F(ClientClassDefParserTest, noFixedFields) {
+
+    std::string cfg_text =
+        "{ \n"
+        "    \"name\": \"MICROSOFT\", \n"
+        "    \"option-data\": [ \n"
+        "        { \n"
+        "           \"name\": \"domain-name-servers\", \n"
+        "           \"data\": \"192.0.2.1, 192.0.2.2\" \n"
+        "        } \n"
+        "      ] \n"
+        "} \n";
+
+    ClientClassDefPtr cclass;
+    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, Option::V4));
+
+    // We should find our class.
+    ASSERT_TRUE(cclass);
+
+    // And it should not have any fixed fields set
+    EXPECT_EQ(IOAddress("0.0.0.0"), cclass->getNextServer());
+    EXPECT_EQ(0, cclass->getSname().size());
+    EXPECT_EQ(0, cclass->getFilename().size());
+}
+
+
+TEST_F(ClientClassDefParserTest, nextServer) {
+
+    std::string cfg_text =
+        "{ \n"
+        "    \"name\": \"MICROSOFT\", \n"
+        "    \"next-server\": \"192.0.2.254\",\n"
+        "    \"option-data\": [ \n"
+        "        { \n"
+        "           \"name\": \"domain-name-servers\", \n"
+        "           \"data\": \"192.0.2.1, 192.0.2.2\" \n"
+        "        } \n"
+        "      ] \n"
+        "} \n";
+
+    ClientClassDefPtr cclass;
+    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, Option::V4));
+
+    // We should find our class.
+    ASSERT_TRUE(cclass);
+
+    // And it should have next-server set, but everything else not set.
+    EXPECT_EQ(IOAddress("192.0.2.254"), cclass->getNextServer());
+    EXPECT_EQ(0, cclass->getSname().size());
+    EXPECT_EQ(0, cclass->getFilename().size());
+}
+
+TEST_F(ClientClassDefParserTest, nextServerBogus) {
+
+    std::string bogus_v6 =
+        "{ \n"
+        "    \"name\": \"MICROSOFT\", \n"
+        "    \"next-server\": \"2001:db8::1\",\n"
+        "    \"option-data\": [ \n"
+        "        { \n"
+        "           \"name\": \"domain-name-servers\", \n"
+        "           \"data\": \"192.0.2.1, 192.0.2.2\" \n"
+        "        } \n"
+        "      ] \n"
+        "} \n";
+    std::string bogus_junk =
+        "{ \n"
+        "    \"name\": \"MICROSOFT\", \n"
+        "    \"next-server\": \"not-an-address\",\n"
+        "    \"option-data\": [ \n"
+        "        { \n"
+        "           \"name\": \"domain-name-servers\", \n"
+        "           \"data\": \"192.0.2.1, 192.0.2.2\" \n"
+        "        } \n"
+        "      ] \n"
+        "} \n";
+
+    EXPECT_THROW(parseClientClassDef(bogus_v6, Option::V4), DhcpConfigError);
+    EXPECT_THROW(parseClientClassDef(bogus_junk, Option::V4), DhcpConfigError);
+}
+
+TEST_F(ClientClassDefParserTest, serverName) {
+
+    std::string cfg_text =
+        "{ \n"
+        "    \"name\": \"MICROSOFT\", \n"
+        "    \"server-hostname\": \"hal9000\",\n"
+        "    \"option-data\": [ \n"
+        "        { \n"
+        "           \"name\": \"domain-name-servers\", \n"
+        "           \"data\": \"192.0.2.1, 192.0.2.2\" \n"
+        "        } \n"
+        "      ] \n"
+        "} \n";
+
+    ClientClassDefPtr cclass;
+    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, Option::V4));
+
+    // We should find our class.
+    ASSERT_TRUE(cclass);
+
+    // And it should not have any fixed fields set
+    std::string exp_txt("hal9000");
+    std::vector<uint8_t> exp_sname(exp_txt.begin(), exp_txt.end());
+
+    EXPECT_EQ(exp_sname, cclass->getSname());
+}
+
+TEST_F(ClientClassDefParserTest, serverNameInvalid) {
+
+    std::string cfg_too_long =
+        "{ \n"
+        "    \"name\": \"MICROSOFT\", \n"
+        "    \"server-hostname\": \"1234567890123456789012345678901234567890"
+                                   "1234567890123456789012345\", \n"
+        "    \"option-data\": [ \n"
+        "        { \n"
+        "           \"name\": \"domain-name-servers\", \n"
+        "           \"data\": \"192.0.2.1, 192.0.2.2\" \n"
+        "        } \n"
+        "      ] \n"
+        "} \n";
+
+    EXPECT_THROW(parseClientClassDef(cfg_too_long, Option::V4), DhcpConfigError);
+}
+
+
+TEST_F(ClientClassDefParserTest, filename) {
+
+    std::string cfg_text =
+        "{ \n"
+        "    \"name\": \"MICROSOFT\", \n"
+        "    \"boot-file-name\": \"ipxe.efi\", \n"
+        "    \"option-data\": [ \n"
+        "        { \n"
+        "           \"name\": \"domain-name-servers\", \n"
+        "           \"data\": \"192.0.2.1, 192.0.2.2\" \n"
+        "        } \n"
+        "      ] \n"
+        "} \n";
+
+    ClientClassDefPtr cclass;
+    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, Option::V4));
+
+    // We should find our class.
+    ASSERT_TRUE(cclass);
+
+    // And it should not have any fixed fields set
+    std::string exp_txt("ipxe.efi");
+    std::vector<uint8_t> exp_filename(exp_txt.begin(), exp_txt.end());
+
+    EXPECT_EQ(exp_filename, cclass->getFilename());
+}
+
+TEST_F(ClientClassDefParserTest, filenameBogus) {
+
+    // boot-file-name is allowed up to 128 bytes, this one is 129.
+    std::string cfg_too_long =
+        "{ \n"
+        "    \"name\": \"MICROSOFT\", \n"
+        "    \"boot-file-name\": \"1234567890123456789012345678901234567890"
+                                  "1234567890123456789012345678901234567890"
+                                  "1234567890123456789012345678901234567890"
+                                  "1234567890123456789012345678901234567890"
+                                  "1234567890123456789012345678901234567890"
+                                  "1234567890123456789012345678901234567890"
+                                  "123456789\", \n"
+        "    \"option-data\": [ \n"
+        "        { \n"
+        "           \"name\": \"domain-name-servers\", \n"
+        "           \"data\": \"192.0.2.1, 192.0.2.2\" \n"
+        "        } \n"
+        "      ] \n"
+        "} \n";
+
+    EXPECT_THROW(parseClientClassDef(cfg_too_long, Option::V4), DhcpConfigError);
+}
+
+
 } // end of anonymous namespace
 } // end of anonymous namespace

+ 57 - 0
src/lib/dhcpsrv/tests/client_class_def_unittest.cc

@@ -8,6 +8,7 @@
 #include <dhcpsrv/client_class_def.h>
 #include <dhcpsrv/client_class_def.h>
 #include <exceptions/exceptions.h>
 #include <exceptions/exceptions.h>
 #include <boost/scoped_ptr.hpp>
 #include <boost/scoped_ptr.hpp>
+#include <asiolink/io_address.h>
 
 
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 
 
@@ -17,6 +18,7 @@
 using namespace std;
 using namespace std;
 using namespace isc::dhcp;
 using namespace isc::dhcp;
 using namespace isc::util;
 using namespace isc::util;
+using namespace isc::asiolink;
 using namespace isc;
 using namespace isc;
 
 
 namespace {
 namespace {
@@ -298,4 +300,59 @@ TEST(ClientClassDictionary, copyAndEquality) {
     EXPECT_TRUE(*dictionary != *dictionary2);
     EXPECT_TRUE(*dictionary != *dictionary2);
 }
 }
 
 
+// Tests the default constructor regarding fixed fields
+TEST(ClientClassDef, fixedFieldsDefaults) {
+    boost::scoped_ptr<ClientClassDef> cclass;
+
+    std::string name = "class1";
+    ExpressionPtr expr;
+    CfgOptionPtr cfg_option;
+
+    // Classes cannot have blank names
+    ASSERT_THROW(cclass.reset(new ClientClassDef("", expr, cfg_option)),
+                 BadValue);
+
+    // Verify we can create a class with a name, expression, and no cfg_option
+    ASSERT_NO_THROW(cclass.reset(new ClientClassDef(name, expr)));
+
+    // Let's checks that it doesn't return any nonsense
+    vector<uint8_t> empty;
+    ASSERT_EQ(IOAddress("0.0.0.0"), cclass->getNextServer());
+    EXPECT_EQ(empty, cclass->getSname());
+    EXPECT_EQ(empty, cclass->getFilename());
+}
+
+// Tests basic operations of fixed fields
+TEST(ClientClassDef, fixedFieldsBasics) {
+    boost::scoped_ptr<ClientClassDef> cclass;
+
+    std::string name = "class1";
+    ExpressionPtr expr;
+    CfgOptionPtr cfg_option;
+
+    // Classes cannot have blank names
+    ASSERT_THROW(cclass.reset(new ClientClassDef("", expr, cfg_option)),
+                 BadValue);
+
+    // Verify we can create a class with a name, expression, and no cfg_option
+    ASSERT_NO_THROW(cclass.reset(new ClientClassDef(name, expr)));
+
+
+    string sname_txt = "This is a very long string that can be a server name";
+    vector<uint8_t> sname(sname_txt.begin(), sname_txt.end());
+
+    string filename_txt = "this-is-a-slightly-longish-name-of-a-file.txt";
+    vector<uint8_t> filename(sname_txt.begin(), sname_txt.end());
+
+    cclass->setNextServer(IOAddress("1.2.3.4"));
+    cclass->setSname(sname);
+    cclass->setFilename(filename);
+
+    // Let's checks that it doesn't return any nonsense
+    ASSERT_EQ(IOAddress("1.2.3.4"), cclass->getNextServer());
+    EXPECT_EQ(sname, cclass->getSname());
+    EXPECT_EQ(filename, cclass->getFilename());
+}
+
+
 } // end of anonymous namespace
 } // end of anonymous namespace