#include <dhcp/option_string.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/parsers/client_class_def_parser.h>
+#include <asiolink/io_address.h>
#include <eval/evaluate.h>
#include <gtest/gtest.h>
#include <sstream>
using namespace isc::data;
using namespace isc::dhcp;
+using namespace isc::asiolink;
namespace {
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
#include <dhcpsrv/client_class_def.h>
#include <exceptions/exceptions.h>
#include <boost/scoped_ptr.hpp>
+#include <asiolink/io_address.h>
#include <gtest/gtest.h>
using namespace std;
using namespace isc::dhcp;
using namespace isc::util;
+using namespace isc::asiolink;
using namespace isc;
namespace {
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