#include <config/command_mgr.h>
#include <config/timeouts.h>
#include <dhcp/dhcp4.h>
-#include <dhcp4/ctrl_dhcp4_srv.h>
-#include <dhcp4/tests/dhcp4_test_utils.h>
+#include <dhcp/libdhcp++.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/lease.h>
#include <dhcpsrv/lease_mgr_factory.h>
+#include <dhcp4/ctrl_dhcp4_srv.h>
+#include <dhcp4/tests/dhcp4_test_utils.h>
#include <hooks/hooks_manager.h>
#include <log/logger_support.h>
#include <stats/stats_mgr.h>
}
void createUnixChannelServer() {
- ::remove(socket_path_.c_str());
+ static_cast<void>(::remove(socket_path_.c_str()));
// Just a simple config. The important part here is the socket
// location information.
// changed.
CfgMgr::instance().commit();
-
ASSERT_TRUE(answer);
int status = 0;
CfgMgr::instance().clear();
// Remove unix socket file
- ::remove(socket_path_.c_str());
+ static_cast<void>(::remove(socket_path_.c_str()));
}
/// @brief Conducts a command/response exchange via UnixCommandSocket
}
// Check that the "libreload" command will reload libraries
-
TEST_F(CtrlChannelDhcpv4SrvTest, libreload) {
createUnixChannelServer();
HooksManager::loadLibraries(libraries);
// Check they are loaded.
- std::vector<std::string> loaded_libraries =
- HooksManager::getLibraryNames();
- ASSERT_TRUE(extractNames(libraries) == loaded_libraries);
+ HookLibsCollection loaded_libraries =
+ HooksManager::getLibraryInfo();
+ ASSERT_TRUE(libraries == loaded_libraries);
// ... which also included checking that the marker file created by the
// load functions exists and holds the correct value (of "12" - the
EXPECT_TRUE(checkMarkerFile(LOAD_MARKER_FILE, "1212"));
}
-// This test checks which commands are registered by the DHCPv4 server.
-TEST_F(CtrlChannelDhcpv4SrvTest, commandsRegistration) {
+// Check that the "config-set" command will replace current configuration
+TEST_F(CtrlChannelDhcpv4SrvTest, configSet) {
+ createUnixChannelServer();
- ConstElementPtr list_cmds = createCommand("list-commands");
- ConstElementPtr answer;
+ // Define strings to permutate the config arguments
+ // (Note the line feeds makes errors easy to find)
+ string set_config_txt = "{ \"command\": \"config-set\" \n";
+ string args_txt = " \"arguments\": { \n";
+ string dhcp4_cfg_txt =
+ " \"Dhcp4\": { \n"
+ " \"interfaces-config\": { \n"
+ " \"interfaces\": [\"*\"] \n"
+ " }, \n"
+ " \"valid-lifetime\": 4000, \n"
+ " \"renew-timer\": 1000, \n"
+ " \"rebind-timer\": 2000, \n"
+ " \"lease-database\": { \n"
+ " \"type\": \"memfile\", \n"
+ " \"persist\":false, \n"
+ " \"lfc-interval\": 0 \n"
+ " }, \n"
+ " \"expired-leases-processing\": { \n"
+ " \"reclaim-timer-wait-time\": 0, \n"
+ " \"hold-reclaimed-time\": 0, \n"
+ " \"flush-reclaimed-timer-wait-time\": 0 \n"
+ " },"
+ " \"subnet4\": [ \n";
+ string subnet1 =
+ " {\"subnet\": \"192.2.0.0/24\", \n"
+ " \"pools\": [{ \"pool\": \"192.2.0.1-192.2.0.50\" }]}\n";
+ string subnet2 =
+ " {\"subnet\": \"192.2.1.0/24\", \n"
+ " \"pools\": [{ \"pool\": \"192.2.1.1-192.2.1.50\" }]}\n";
+ string bad_subnet =
+ " {\"comment\": \"192.2.2.0/24\", \n"
+ " \"pools\": [{ \"pool\": \"192.2.2.1-192.2.2.50\" }]}\n";
+ string subnet_footer =
+ " ] \n";
+ string option_def =
+ " ,\"option-def\": [\n"
+ " {\n"
+ " \"name\": \"foo\",\n"
+ " \"code\": 163,\n"
+ " \"type\": \"uint32\",\n"
+ " \"array\": false,\n"
+ " \"record-types\": \"\",\n"
+ " \"space\": \"dhcp4\",\n"
+ " \"encapsulate\": \"\"\n"
+ " }\n"
+ "]\n";
+ string option_data =
+ " ,\"option-data\": [\n"
+ " {\n"
+ " \"name\": \"foo\",\n"
+ " \"code\": 163,\n"
+ " \"space\": \"dhcp4\",\n"
+ " \"csv-format\": true,\n"
+ " \"data\": \"12345\"\n"
+ " }\n"
+ "]\n";
+ string control_socket_header =
+ " ,\"control-socket\": { \n"
+ " \"socket-type\": \"unix\", \n"
+ " \"socket-name\": \"";
+ string control_socket_footer =
+ "\" \n} \n";
+ string logger_txt =
+ " \"Logging\": { \n"
+ " \"loggers\": [ { \n"
+ " \"name\": \"kea\", \n"
+ " \"severity\": \"FATAL\", \n"
+ " \"output_options\": [{ \n"
+ " \"output\": \"/dev/null\" \n"
+ " }] \n"
+ " }] \n"
+ " } \n";
- // By default the list should be empty (except the standard list-commands
- // supported by the CommandMgr itself)
- EXPECT_NO_THROW(answer = CommandMgr::instance().processCommand(list_cmds));
- ASSERT_TRUE(answer);
- ASSERT_TRUE(answer->get("arguments"));
- EXPECT_EQ("[ \"list-commands\" ]", answer->get("arguments")->str());
+ std::ostringstream os;
- // Created server should register several additional commands.
- ASSERT_NO_THROW(
- server_.reset(new NakedControlledDhcpv4Srv());
- );
+ // Create a valid config with all the parts should parse
+ os << set_config_txt << ","
+ << args_txt
+ << dhcp4_cfg_txt
+ << subnet1
+ << subnet_footer
+ << option_def
+ << option_data
+ << control_socket_header
+ << socket_path_
+ << control_socket_footer
+ << "}\n" // close dhcp4
+ << ","
+ << logger_txt
+ << "}}";
- EXPECT_NO_THROW(answer = CommandMgr::instance().processCommand(list_cmds));
- ASSERT_TRUE(answer);
- ASSERT_TRUE(answer->get("arguments"));
- std::string command_list = answer->get("arguments")->str();
+ // Send the config-set command
+ std::string response;
+ sendUnixCommand(os.str(), response);
- EXPECT_TRUE(command_list.find("\"list-commands\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"build-report\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"config-get\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"config-set\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"config-write\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"leases-reclaim\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"libreload\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"server-tag-get\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"shutdown\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"statistic-get\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"statistic-get-all\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"statistic-remove\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"statistic-remove-all\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"statistic-reset\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"statistic-reset-all\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"statistic-sample-age-set\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"statistic-sample-age-set-all\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"statistic-sample-count-set\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"statistic-sample-count-set-all\"") != string::npos);
- EXPECT_TRUE(command_list.find("\"version-get\"") != string::npos);
+ // Verify the configuration was successful.
+ EXPECT_EQ("{ \"result\": 0, \"text\": \"Configuration successful.\" }",
+ response);
- // Ok, and now delete the server. It should deregister its commands.
- server_.reset();
+ // Check that the config was indeed applied.
+ const Subnet4Collection* subnets =
+ CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
+ EXPECT_EQ(1, subnets->size());
- // The list should be (almost) empty again.
- EXPECT_NO_THROW(answer = CommandMgr::instance().processCommand(list_cmds));
- ASSERT_TRUE(answer);
- ASSERT_TRUE(answer->get("arguments"));
- EXPECT_EQ("[ \"list-commands\" ]", answer->get("arguments")->str());
-}
+ OptionDefinitionPtr def = LibDHCP::getRuntimeOptionDef("dhcp4", 163);
+ ASSERT_TRUE(def);
-// Tests that the server properly responds to invalid commands sent
-// via ControlChannel
-TEST_F(CtrlChannelDhcpv4SrvTest, controlChannelNegative) {
- createUnixChannelServer();
- std::string response;
+ // Create a config with malformed subnet that should fail to parse.
+ os.str("");
+ os << set_config_txt << ","
+ << args_txt
+ << dhcp4_cfg_txt
+ << bad_subnet
+ << subnet_footer
+ << control_socket_header
+ << socket_path_
+ << control_socket_footer
+ << "}\n" // close dhcp4
+ "}}";
- sendUnixCommand("{ \"command\": \"bogus\" }", response);
- EXPECT_EQ("{ \"result\": 2,"
- " \"text\": \"'bogus' command not supported.\" }", response);
+ // Send the config-set command
+ sendUnixCommand(os.str(), response);
- sendUnixCommand("utter nonsense", response);
+ // Should fail with a syntax error
EXPECT_EQ("{ \"result\": 1, "
- "\"text\": \"invalid first character u\" }",
+ "\"text\": \"subnet configuration failed: mandatory 'subnet' "
+ "parameter is missing for a subnet being configured (<wire>:19:17)\" }",
response);
-}
-
-// Tests that the server properly responds to shtudown command sent
-// via ControlChannel
-TEST_F(CtrlChannelDhcpv4SrvTest, controlChannelShutdown) {
- createUnixChannelServer();
- std::string response;
-
- sendUnixCommand("{ \"command\": \"shutdown\" }", response);
- EXPECT_EQ("{ \"result\": 0, \"text\": \"Shutting down.\" }",response);
-}
-// This test verifies that the DHCP server immediately reclaims expired
-// leases on leases-reclaim command
-TEST_F(CtrlChannelDhcpv4SrvTest, controlLeasesReclaim) {
- createUnixChannelServer();
+ // Check that the config was not lost
+ subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
+ EXPECT_EQ(1, subnets->size());
- // Create expired leases. Leases are expired by 40 seconds ago
- // (valid lifetime = 60, cltt = now - 100).
- HWAddrPtr hwaddr0(new HWAddr(HWAddr::fromText("00:01:02:03:04:05")));
- Lease4Ptr lease0(new Lease4(IOAddress("10.0.0.1"), hwaddr0,
- ClientIdPtr(), 60,
- time(NULL) - 100, SubnetID(1)));
- HWAddrPtr hwaddr1(new HWAddr(HWAddr::fromText("01:02:03:04:05:06")));
- Lease4Ptr lease1(new Lease4(IOAddress("10.0.0.2"), hwaddr1,
- ClientIdPtr(), 60,
- time(NULL) - 100, SubnetID(1)));
+ def = LibDHCP::getRuntimeOptionDef("dhcp4", 163);
+ ASSERT_TRUE(def);
- // Add leases to the database.
- LeaseMgr& lease_mgr = LeaseMgrFactory::instance();
- ASSERT_NO_THROW(lease_mgr.addLease(lease0));
- ASSERT_NO_THROW(lease_mgr.addLease(lease1));
+ // Create a valid config with two subnets and no command channel.
+ // It should succeed, client should still receive the response
+ os.str("");
+ os << set_config_txt << ","
+ << args_txt
+ << dhcp4_cfg_txt
+ << subnet1
+ << ",\n"
+ << subnet2
+ << subnet_footer
+ << "}\n" // close dhcp4
+ << "}}";
- // Make sure they have been added.
- ASSERT_TRUE(lease_mgr.getLease4(IOAddress("10.0.0.1")));
- ASSERT_TRUE(lease_mgr.getLease4(IOAddress("10.0.0.2")));
+ // Verify the control channel socket exists.
+ ASSERT_TRUE(fileExists(socket_path_));
- // No arguments
- std::string response;
- sendUnixCommand("{ \"command\": \"leases-reclaim\" }", response);
- EXPECT_EQ("{ \"result\": 1, \"text\": "
- "\"Missing mandatory 'remove' parameter.\" }", response);
+ // Send the config-set command.
+ sendUnixCommand(os.str(), response);
- // Bad argument name
- sendUnixCommand("{ \"command\": \"leases-reclaim\", "
- "\"arguments\": { \"reclaim\": true } }", response);
- EXPECT_EQ("{ \"result\": 1, \"text\": "
- "\"Missing mandatory 'remove' parameter.\" }", response);
+ // Verify the control channel socket no longer exists.
+ EXPECT_FALSE(fileExists(socket_path_));
- // Bad remove argument type
- sendUnixCommand("{ \"command\": \"leases-reclaim\", "
- "\"arguments\": { \"remove\": \"bogus\" } }", response);
- EXPECT_EQ("{ \"result\": 1, \"text\": "
- "\"'remove' parameter expected to be a boolean.\" }", response);
+ // With no command channel, should still receive the response.
+ EXPECT_EQ("{ \"result\": 0, \"text\": \"Configuration successful.\" }",
+ response);
- // Send the command
- sendUnixCommand("{ \"command\": \"leases-reclaim\", "
- "\"arguments\": { \"remove\": false } }", response);
- EXPECT_EQ("{ \"result\": 0, \"text\": "
- "\"Reclamation of expired leases is complete.\" }", response);
+ // Check that the config was not lost
+ subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
+ EXPECT_EQ(2, subnets->size());
- // Leases should be reclaimed, but not removed
- ASSERT_NO_THROW(lease0 = lease_mgr.getLease4(IOAddress("10.0.0.1")));
- ASSERT_NO_THROW(lease1 = lease_mgr.getLease4(IOAddress("10.0.0.2")));
- ASSERT_TRUE(lease0);
- ASSERT_TRUE(lease1);
- EXPECT_TRUE(lease0->stateExpiredReclaimed());
- EXPECT_TRUE(lease1->stateExpiredReclaimed());
+ // Clean up after the test.
+ CfgMgr::instance().clear();
}
-// This test verifies that the DHCP server handles version-get commands
-TEST_F(CtrlChannelDhcpv4SrvTest, getversion) {
- createUnixChannelServer();
-
- std::string response;
-
- // Send the version-get command
- sendUnixCommand("{ \"command\": \"version-get\" }", response);
- EXPECT_TRUE(response.find("\"result\": 0") != string::npos);
- EXPECT_TRUE(response.find("log4cplus") != string::npos);
- EXPECT_FALSE(response.find("GTEST_VERSION") != string::npos);
-
- // Send the build-report command
- sendUnixCommand("{ \"command\": \"build-report\" }", response);
- EXPECT_TRUE(response.find("\"result\": 0") != string::npos);
- EXPECT_TRUE(response.find("GTEST_VERSION") != string::npos);
-}
-
-// This test verifies that the DHCP server handles server-tag-get command
-TEST_F(CtrlChannelDhcpv4SrvTest, serverTagGet) {
- createUnixChannelServer();
-
- std::string response;
- std::string expected;
-
- // Send the server-tag-get command
- sendUnixCommand("{ \"command\": \"server-tag-get\" }", response);
- expected = "{ \"arguments\": { \"server-tag\": \"\" }, \"result\": 0 }";
- EXPECT_EQ(expected, response);
-
- // Set a value to the server tag
- CfgMgr::instance().getCurrentCfg()->setServerTag("foobar");
-
- // Retry...
- sendUnixCommand("{ \"command\": \"server-tag-get\" }", response);
- expected = "{ \"arguments\": { \"server-tag\": \"foobar\" }, \"result\": 0 }";
-}
-
-// This test verifies that the DHCP server immediately removed expired
-// This test verifies that the DHCP server immediately removed expired
-// leases on leases-reclaim command with remove = true
-TEST_F(CtrlChannelDhcpv4SrvTest, controlLeasesReclaimRemove) {
- createUnixChannelServer();
-
- // Create expired leases. Leases are expired by 40 seconds ago
- // (valid lifetime = 60, cltt = now - 100).
- HWAddrPtr hwaddr0(new HWAddr(HWAddr::fromText("00:01:02:03:04:05")));
- Lease4Ptr lease0(new Lease4(IOAddress("10.0.0.1"), hwaddr0,
- ClientIdPtr(), 60,
- time(NULL) - 100, SubnetID(1)));
- HWAddrPtr hwaddr1(new HWAddr(HWAddr::fromText("01:02:03:04:05:06")));
- Lease4Ptr lease1(new Lease4(IOAddress("10.0.0.2"), hwaddr1,
- ClientIdPtr(), 60,
- time(NULL) - 100, SubnetID(1)));
-
- // Add leases to the database.
- LeaseMgr& lease_mgr = LeaseMgrFactory::instance();
- ASSERT_NO_THROW(lease_mgr.addLease(lease0));
- ASSERT_NO_THROW(lease_mgr.addLease(lease1));
-
- // Make sure they have been added.
- ASSERT_TRUE(lease_mgr.getLease4(IOAddress("10.0.0.1")));
- ASSERT_TRUE(lease_mgr.getLease4(IOAddress("10.0.0.2")));
-
- // Send the command
- std::string response;
- sendUnixCommand("{ \"command\": \"leases-reclaim\", "
- "\"arguments\": { \"remove\": true } }", response);
- EXPECT_EQ("{ \"result\": 0, \"text\": "
- "\"Reclamation of expired leases is complete.\" }", response);
-
- // Leases should have been removed.
- ASSERT_NO_THROW(lease0 = lease_mgr.getLease4(IOAddress("10.0.0.1")));
- ASSERT_NO_THROW(lease1 = lease_mgr.getLease4(IOAddress("10.0.0.2")));
- EXPECT_FALSE(lease0);
- EXPECT_FALSE(lease1);
-}
-
-// Tests that the server properly responds to statistics commands. Note this
-// is really only intended to verify that the appropriate Statistics handler
-// is called based on the command. It is not intended to be an exhaustive
-// test of Dhcpv4 statistics.
-TEST_F(CtrlChannelDhcpv4SrvTest, controlChannelStats) {
- createUnixChannelServer();
- std::string response;
-
- // Check statistic-get
- sendUnixCommand("{ \"command\" : \"statistic-get\", "
- " \"arguments\": {"
- " \"name\":\"bogus\" }}", response);
- EXPECT_EQ("{ \"arguments\": { }, \"result\": 0 }", response);
-
- // Check statistic-get-all
- sendUnixCommand("{ \"command\" : \"statistic-get-all\", "
- " \"arguments\": {}}", response);
- EXPECT_EQ("{ \"arguments\": { }, \"result\": 0 }", response);
-
- // Check statistic-reset
- sendUnixCommand("{ \"command\" : \"statistic-reset\", "
- " \"arguments\": {"
- " \"name\":\"bogus\" }}", response);
- EXPECT_EQ("{ \"result\": 1, \"text\": \"No 'bogus' statistic found\" }",
- response);
-
- // Check statistic-reset-all
- sendUnixCommand("{ \"command\" : \"statistic-reset-all\", "
- " \"arguments\": {}}", response);
- EXPECT_EQ("{ \"result\": 0, \"text\": "
- "\"All statistics reset to neutral values.\" }", response);
-
- // Check statistic-remove
- sendUnixCommand("{ \"command\" : \"statistic-remove\", "
- " \"arguments\": {"
- " \"name\":\"bogus\" }}", response);
- EXPECT_EQ("{ \"result\": 1, \"text\": \"No 'bogus' statistic found\" }",
- response);
-
- // Check statistic-remove-all
- sendUnixCommand("{ \"command\" : \"statistic-remove-all\", "
- " \"arguments\": {}}", response);
- EXPECT_EQ("{ \"result\": 0, \"text\": \"All statistics removed.\" }",
- response);
-
- // Check statistic-sample-age-set
- sendUnixCommand("{ \"command\" : \"statistic-sample-age-set\", "
- " \"arguments\": {"
- " \"name\":\"bogus\", \"duration\": 1245 }}", response);
- EXPECT_EQ("{ \"result\": 1, \"text\": \"No 'bogus' statistic found\" }",
- response);
-
- // Check statistic-sample-age-set-all
- sendUnixCommand("{ \"command\" : \"statistic-sample-age-set-all\", "
- " \"arguments\": {"
- " \"duration\": 1245 }}", response);
- EXPECT_EQ("{ \"result\": 0, \"text\": \"All statistics duration limit are set.\" }",
- response);
-
- // Check statistic-sample-count-set
- sendUnixCommand("{ \"command\" : \"statistic-sample-count-set\", "
- " \"arguments\": {"
- " \"name\":\"bogus\", \"max-samples\": 100 }}", response);
- EXPECT_EQ("{ \"result\": 1, \"text\": \"No 'bogus' statistic found\" }",
- response);
-
- // Check statistic-sample-count-set-all
- sendUnixCommand("{ \"command\" : \"statistic-sample-count-set-all\", "
- " \"arguments\": {"
- " \"max-samples\": 100 }}", response);
- EXPECT_EQ("{ \"result\": 0, \"text\": \"All statistics count limit are set.\" }",
- response);
-}
-
-// Check that the "config-set" command will replace current configuration
-TEST_F(CtrlChannelDhcpv4SrvTest, configSet) {
+// Verify that the "config-test" command will do what we expect.
+TEST_F(CtrlChannelDhcpv4SrvTest, configTest) {
createUnixChannelServer();
// Define strings to permutate the config arguments
// (Note the line feeds makes errors easy to find)
string set_config_txt = "{ \"command\": \"config-set\" \n";
+ string config_test_txt = "{ \"command\": \"config-test\" \n";
string args_txt = " \"arguments\": { \n";
string dhcp4_cfg_txt =
" \"Dhcp4\": { \n"
// Create a config with malformed subnet that should fail to parse.
os.str("");
- os << set_config_txt << ","
+ os << config_test_txt << ","
<< args_txt
<< dhcp4_cfg_txt
<< bad_subnet
<< "}\n" // close dhcp4
"}}";
- // Send the config-set command
+ // Send the config-test command
sendUnixCommand(os.str(), response);
// Should fail with a syntax error
EXPECT_EQ("{ \"result\": 1, "
- "\"text\": \"subnet configuration failed: mandatory 'subnet' "
- "parameter is missing for a subnet being configured (<wire>:19:17)\" }",
+ "\"text\": \"subnet configuration failed: mandatory 'subnet' parameter "
+ "is missing for a subnet being configured (<wire>:19:17)\" }",
response);
// Check that the config was not lost
EXPECT_EQ(1, subnets->size());
// Create a valid config with two subnets and no command channel.
- // It should succeed, client should still receive the response
os.str("");
- os << set_config_txt << ","
+ os << config_test_txt << ","
<< args_txt
<< dhcp4_cfg_txt
<< subnet1
// Verify the control channel socket exists.
ASSERT_TRUE(fileExists(socket_path_));
- // Send the config-set command.
+ // Send the config-test command.
sendUnixCommand(os.str(), response);
- // Verify the control channel socket no longer exists.
- EXPECT_FALSE(fileExists(socket_path_));
+ // Verify the control channel socket still exists.
+ EXPECT_TRUE(fileExists(socket_path_));
- // With no command channel, should still receive the response.
- EXPECT_EQ("{ \"result\": 0, \"text\": \"Configuration successful.\" }",
+ // Verify the configuration was successful.
+ EXPECT_EQ("{ \"result\": 0, \"text\": \"Configuration seems sane. "
+ "Control-socket, hook-libraries, and D2 configuration were "
+ "sanity checked, but not applied.\" }",
response);
- // Check that the config was not lost
+ // Check that the config was not applied.
subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
- EXPECT_EQ(2, subnets->size());
+ EXPECT_EQ(1, subnets->size());
// Clean up after the test.
CfgMgr::instance().clear();
}
+// This test checks which commands are registered by the DHCPv4 server.
+TEST_F(CtrlChannelDhcpv4SrvTest, commandsRegistration) {
-// Tests that the server properly responds to shtudown command sent
-// via ControlChannel
-TEST_F(CtrlChannelDhcpv4SrvTest, listCommands) {
- createUnixChannelServer();
- std::string response;
-
- sendUnixCommand("{ \"command\": \"list-commands\" }", response);
+ ConstElementPtr list_cmds = createCommand("list-commands");
+ ConstElementPtr answer;
- ConstElementPtr rsp;
- EXPECT_NO_THROW(rsp = Element::fromJSON(response));
+ // By default the list should be empty (except the standard list-commands
+ // supported by the CommandMgr itself)
+ EXPECT_NO_THROW(answer = CommandMgr::instance().processCommand(list_cmds));
+ ASSERT_TRUE(answer);
+ ASSERT_TRUE(answer->get("arguments"));
+ EXPECT_EQ("[ \"list-commands\" ]", answer->get("arguments")->str());
- // We expect the server to report at least the following commands:
- checkListCommands(rsp, "build-report");
- checkListCommands(rsp, "config-get");
- checkListCommands(rsp, "config-reload");
- checkListCommands(rsp, "config-set");
- checkListCommands(rsp, "config-write");
- checkListCommands(rsp, "list-commands");
- checkListCommands(rsp, "leases-reclaim");
- checkListCommands(rsp, "libreload");
- checkListCommands(rsp, "server-tag-get");
- checkListCommands(rsp, "shutdown");
- checkListCommands(rsp, "statistic-get");
- checkListCommands(rsp, "statistic-get-all");
- checkListCommands(rsp, "statistic-remove");
- checkListCommands(rsp, "statistic-remove-all");
- checkListCommands(rsp, "statistic-reset");
- checkListCommands(rsp, "statistic-reset-all");
- checkListCommands(rsp, "statistic-sample-age-set");
- checkListCommands(rsp, "statistic-sample-age-set-all");
- checkListCommands(rsp, "statistic-sample-count-set");
- checkListCommands(rsp, "statistic-sample-count-set-all");
- checkListCommands(rsp, "version-get");
-}
+ // Created server should register several additional commands.
+ ASSERT_NO_THROW(
+ server_.reset(new NakedControlledDhcpv4Srv());
+ );
-// Tests if the server returns its configuration using config-get.
-// Note there are separate tests that verify if toElement() called by the
-// config-get handler are actually converting the configuration correctly.
-TEST_F(CtrlChannelDhcpv4SrvTest, configGet) {
- createUnixChannelServer();
- std::string response;
+ EXPECT_NO_THROW(answer = CommandMgr::instance().processCommand(list_cmds));
+ ASSERT_TRUE(answer);
- sendUnixCommand("{ \"command\": \"config-get\" }", response);
- ConstElementPtr rsp;
+ ASSERT_TRUE(answer->get("arguments"));
+ std::string command_list = answer->get("arguments")->str();
- // The response should be a valid JSON.
- EXPECT_NO_THROW(rsp = Element::fromJSON(response));
- ASSERT_TRUE(rsp);
+ EXPECT_TRUE(command_list.find("\"list-commands\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"build-report\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"config-get\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"config-set\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"config-write\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"leases-reclaim\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"libreload\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"server-tag-get\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"shutdown\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"statistic-get\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"statistic-get-all\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"statistic-remove\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"statistic-remove-all\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"statistic-reset\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"statistic-reset-all\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"statistic-sample-age-set\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"statistic-sample-age-set-all\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"statistic-sample-count-set\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"statistic-sample-count-set-all\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"version-get\"") != string::npos);
- int status;
- ConstElementPtr cfg = parseAnswer(status, rsp);
- EXPECT_EQ(CONTROL_RESULT_SUCCESS, status);
+ // Ok, and now delete the server. It should deregister its commands.
+ server_.reset();
- // Ok, now roughly check if the response seems legit.
- ASSERT_TRUE(cfg);
- ASSERT_EQ(Element::map, cfg->getType());
- EXPECT_TRUE(cfg->get("Dhcp4"));
+ // The list should be (almost) empty again.
+ EXPECT_NO_THROW(answer = CommandMgr::instance().processCommand(list_cmds));
+ ASSERT_TRUE(answer);
+ ASSERT_TRUE(answer->get("arguments"));
+ EXPECT_EQ("[ \"list-commands\" ]", answer->get("arguments")->str());
}
-// Verify that the "config-test" command will do what we expect.
-TEST_F(CtrlChannelDhcpv4SrvTest, configTest) {
+// Tests that the server properly responds to invalid commands sent
+// via ControlChannel
+TEST_F(CtrlChannelDhcpv4SrvTest, controlChannelNegative) {
createUnixChannelServer();
+ std::string response;
- // Define strings to permutate the config arguments
- // (Note the line feeds makes errors easy to find)
- string set_config_txt = "{ \"command\": \"config-set\" \n";
- string config_test_txt = "{ \"command\": \"config-test\" \n";
- string args_txt = " \"arguments\": { \n";
- string dhcp4_cfg_txt =
- " \"Dhcp4\": { \n"
- " \"interfaces-config\": { \n"
- " \"interfaces\": [\"*\"] \n"
- " }, \n"
- " \"valid-lifetime\": 4000, \n"
- " \"renew-timer\": 1000, \n"
- " \"rebind-timer\": 2000, \n"
- " \"lease-database\": { \n"
- " \"type\": \"memfile\", \n"
- " \"persist\":false, \n"
- " \"lfc-interval\": 0 \n"
- " }, \n"
- " \"expired-leases-processing\": { \n"
- " \"reclaim-timer-wait-time\": 0, \n"
- " \"hold-reclaimed-time\": 0, \n"
- " \"flush-reclaimed-timer-wait-time\": 0 \n"
- " },"
- " \"subnet4\": [ \n";
- string subnet1 =
- " {\"subnet\": \"192.2.0.0/24\", \n"
- " \"pools\": [{ \"pool\": \"192.2.0.1-192.2.0.50\" }]}\n";
- string subnet2 =
- " {\"subnet\": \"192.2.1.0/24\", \n"
- " \"pools\": [{ \"pool\": \"192.2.1.1-192.2.1.50\" }]}\n";
- string bad_subnet =
- " {\"comment\": \"192.2.2.0/24\", \n"
- " \"pools\": [{ \"pool\": \"192.2.2.1-192.2.2.50\" }]}\n";
- string subnet_footer =
- " ] \n";
- string control_socket_header =
- " ,\"control-socket\": { \n"
- " \"socket-type\": \"unix\", \n"
- " \"socket-name\": \"";
- string control_socket_footer =
- "\" \n} \n";
- string logger_txt =
- " \"Logging\": { \n"
- " \"loggers\": [ { \n"
- " \"name\": \"kea\", \n"
- " \"severity\": \"FATAL\", \n"
- " \"output_options\": [{ \n"
- " \"output\": \"/dev/null\" \n"
- " }] \n"
- " }] \n"
- " } \n";
+ sendUnixCommand("{ \"command\": \"bogus\" }", response);
+ EXPECT_EQ("{ \"result\": 2,"
+ " \"text\": \"'bogus' command not supported.\" }", response);
- std::ostringstream os;
+ sendUnixCommand("utter nonsense", response);
+ EXPECT_EQ("{ \"result\": 1, "
+ "\"text\": \"invalid first character u\" }",
+ response);
+}
- // Create a valid config with all the parts should parse
- os << set_config_txt << ","
- << args_txt
- << dhcp4_cfg_txt
- << subnet1
- << subnet_footer
- << control_socket_header
- << socket_path_
- << control_socket_footer
- << "}\n" // close dhcp4
- << ","
- << logger_txt
- << "}}";
+// Tests that the server properly responds to shtudown command sent
+// via ControlChannel
+TEST_F(CtrlChannelDhcpv4SrvTest, controlChannelShutdown) {
+ createUnixChannelServer();
+ std::string response;
+
+ sendUnixCommand("{ \"command\": \"shutdown\" }", response);
+ EXPECT_EQ("{ \"result\": 0, \"text\": \"Shutting down.\" }",response);
+}
+
+// This test verifies that the DHCP server handles version-get commands
+TEST_F(CtrlChannelDhcpv4SrvTest, getversion) {
+ createUnixChannelServer();
- // Send the config-set command
std::string response;
- sendUnixCommand(os.str(), response);
- // Verify the configuration was successful.
- EXPECT_EQ("{ \"result\": 0, \"text\": \"Configuration successful.\" }",
- response);
+ // Send the version-get command
+ sendUnixCommand("{ \"command\": \"version-get\" }", response);
+ EXPECT_TRUE(response.find("\"result\": 0") != string::npos);
+ EXPECT_TRUE(response.find("log4cplus") != string::npos);
+ EXPECT_FALSE(response.find("GTEST_VERSION") != string::npos);
- // Check that the config was indeed applied.
- const Subnet4Collection* subnets =
- CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
- EXPECT_EQ(1, subnets->size());
+ // Send the build-report command
+ sendUnixCommand("{ \"command\": \"build-report\" }", response);
+ EXPECT_TRUE(response.find("\"result\": 0") != string::npos);
+ EXPECT_TRUE(response.find("GTEST_VERSION") != string::npos);
+}
- // Create a config with malformed subnet that should fail to parse.
- os.str("");
- os << config_test_txt << ","
- << args_txt
- << dhcp4_cfg_txt
- << bad_subnet
- << subnet_footer
- << control_socket_header
- << socket_path_
- << control_socket_footer
- << "}\n" // close dhcp4
- "}}";
+// This test verifies that the DHCP server immediately reclaims expired
+// leases on leases-reclaim command
+TEST_F(CtrlChannelDhcpv4SrvTest, controlLeasesReclaim) {
+ createUnixChannelServer();
- // Send the config-test command
- sendUnixCommand(os.str(), response);
+ // Create expired leases. Leases are expired by 40 seconds ago
+ // (valid lifetime = 60, cltt = now - 100).
+ HWAddrPtr hwaddr0(new HWAddr(HWAddr::fromText("00:01:02:03:04:05")));
+ Lease4Ptr lease0(new Lease4(IOAddress("10.0.0.1"), hwaddr0,
+ ClientIdPtr(), 60,
+ time(NULL) - 100, SubnetID(1)));
+ HWAddrPtr hwaddr1(new HWAddr(HWAddr::fromText("01:02:03:04:05:06")));
+ Lease4Ptr lease1(new Lease4(IOAddress("10.0.0.2"), hwaddr1,
+ ClientIdPtr(), 60,
+ time(NULL) - 100, SubnetID(1)));
- // Should fail with a syntax error
- EXPECT_EQ("{ \"result\": 1, "
- "\"text\": \"subnet configuration failed: mandatory 'subnet' "
- "parameter is missing for a subnet being configured (<wire>:19:17)\" }",
+ // Add leases to the database.
+ LeaseMgr& lease_mgr = LeaseMgrFactory::instance();
+ ASSERT_NO_THROW(lease_mgr.addLease(lease0));
+ ASSERT_NO_THROW(lease_mgr.addLease(lease1));
+
+ // Make sure they have been added.
+ ASSERT_TRUE(lease_mgr.getLease4(IOAddress("10.0.0.1")));
+ ASSERT_TRUE(lease_mgr.getLease4(IOAddress("10.0.0.2")));
+
+ // No arguments
+ std::string response;
+ sendUnixCommand("{ \"command\": \"leases-reclaim\" }", response);
+ EXPECT_EQ("{ \"result\": 1, \"text\": "
+ "\"Missing mandatory 'remove' parameter.\" }", response);
+
+ // Bad argument name
+ sendUnixCommand("{ \"command\": \"leases-reclaim\", "
+ "\"arguments\": { \"reclaim\": true } }", response);
+ EXPECT_EQ("{ \"result\": 1, \"text\": "
+ "\"Missing mandatory 'remove' parameter.\" }", response);
+
+ // Bad remove argument type
+ sendUnixCommand("{ \"command\": \"leases-reclaim\", "
+ "\"arguments\": { \"remove\": \"bogus\" } }", response);
+ EXPECT_EQ("{ \"result\": 1, \"text\": "
+ "\"'remove' parameter expected to be a boolean.\" }", response);
+
+ // Send the command
+ sendUnixCommand("{ \"command\": \"leases-reclaim\", "
+ "\"arguments\": { \"remove\": false } }", response);
+ EXPECT_EQ("{ \"result\": 0, \"text\": "
+ "\"Reclamation of expired leases is complete.\" }", response);
+
+ // Leases should be reclaimed, but not removed
+ ASSERT_NO_THROW(lease0 = lease_mgr.getLease4(IOAddress("10.0.0.1")));
+ ASSERT_NO_THROW(lease1 = lease_mgr.getLease4(IOAddress("10.0.0.2")));
+ ASSERT_TRUE(lease0);
+ ASSERT_TRUE(lease1);
+ EXPECT_TRUE(lease0->stateExpiredReclaimed());
+ EXPECT_TRUE(lease1->stateExpiredReclaimed());
+}
+
+// This test verifies that the DHCP server immediately reclaims expired
+// leases on leases-reclaim command with remove = true
+TEST_F(CtrlChannelDhcpv4SrvTest, controlLeasesReclaimRemove) {
+ createUnixChannelServer();
+
+ // Create expired leases. Leases are expired by 40 seconds ago
+ // (valid lifetime = 60, cltt = now - 100).
+ HWAddrPtr hwaddr0(new HWAddr(HWAddr::fromText("00:01:02:03:04:05")));
+ Lease4Ptr lease0(new Lease4(IOAddress("10.0.0.1"), hwaddr0,
+ ClientIdPtr(), 60,
+ time(NULL) - 100, SubnetID(1)));
+ HWAddrPtr hwaddr1(new HWAddr(HWAddr::fromText("01:02:03:04:05:06")));
+ Lease4Ptr lease1(new Lease4(IOAddress("10.0.0.2"), hwaddr1,
+ ClientIdPtr(), 60,
+ time(NULL) - 100, SubnetID(1)));
+
+ // Add leases to the database.
+ LeaseMgr& lease_mgr = LeaseMgrFactory::instance();
+ ASSERT_NO_THROW(lease_mgr.addLease(lease0));
+ ASSERT_NO_THROW(lease_mgr.addLease(lease1));
+
+ // Make sure they have been added.
+ ASSERT_TRUE(lease_mgr.getLease4(IOAddress("10.0.0.1")));
+ ASSERT_TRUE(lease_mgr.getLease4(IOAddress("10.0.0.2")));
+
+ // Send the command
+ std::string response;
+ sendUnixCommand("{ \"command\": \"leases-reclaim\", "
+ "\"arguments\": { \"remove\": true } }", response);
+ EXPECT_EQ("{ \"result\": 0, \"text\": "
+ "\"Reclamation of expired leases is complete.\" }", response);
+
+ // Leases should have been removed.
+ ASSERT_NO_THROW(lease0 = lease_mgr.getLease4(IOAddress("10.0.0.1")));
+ ASSERT_NO_THROW(lease1 = lease_mgr.getLease4(IOAddress("10.0.0.2")));
+ EXPECT_FALSE(lease0);
+ EXPECT_FALSE(lease1);
+}
+
+// Tests that the server properly responds to statistics commands. Note this
+// is really only intended to verify that the appropriate Statistics handler
+// is called based on the command. It is not intended to be an exhaustive
+// test of Dhcpv4 statistics.
+TEST_F(CtrlChannelDhcpv4SrvTest, controlChannelStats) {
+ createUnixChannelServer();
+ std::string response;
+
+ // Check statistic-get
+ sendUnixCommand("{ \"command\" : \"statistic-get\", "
+ " \"arguments\": {"
+ " \"name\":\"bogus\" }}", response);
+ EXPECT_EQ("{ \"arguments\": { }, \"result\": 0 }", response);
+
+ // Check statistic-get-all
+ sendUnixCommand("{ \"command\" : \"statistic-get-all\", "
+ " \"arguments\": {}}", response);
+ EXPECT_EQ("{ \"arguments\": { }, \"result\": 0 }", response);
+
+ // Check statistic-reset
+ sendUnixCommand("{ \"command\" : \"statistic-reset\", "
+ " \"arguments\": {"
+ " \"name\":\"bogus\" }}", response);
+ EXPECT_EQ("{ \"result\": 1, \"text\": \"No 'bogus' statistic found\" }",
response);
- // Check that the config was not lost
- subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
- EXPECT_EQ(1, subnets->size());
+ // Check statistic-reset-all
+ sendUnixCommand("{ \"command\" : \"statistic-reset-all\", "
+ " \"arguments\": {}}", response);
+ EXPECT_EQ("{ \"result\": 0, \"text\": "
+ "\"All statistics reset to neutral values.\" }", response);
- // Create a valid config with two subnets and no command channel.
- os.str("");
- os << config_test_txt << ","
- << args_txt
- << dhcp4_cfg_txt
- << subnet1
- << ",\n"
- << subnet2
- << subnet_footer
- << "}\n" // close dhcp4
- << "}}";
+ // Check statistic-remove
+ sendUnixCommand("{ \"command\" : \"statistic-remove\", "
+ " \"arguments\": {"
+ " \"name\":\"bogus\" }}", response);
+ EXPECT_EQ("{ \"result\": 1, \"text\": \"No 'bogus' statistic found\" }",
+ response);
- // Verify the control channel socket exists.
- ASSERT_TRUE(fileExists(socket_path_));
+ // Check statistic-remove-all
+ sendUnixCommand("{ \"command\" : \"statistic-remove-all\", "
+ " \"arguments\": {}}", response);
+ EXPECT_EQ("{ \"result\": 0, \"text\": \"All statistics removed.\" }",
+ response);
- // Send the config-test command
- sendUnixCommand(os.str(), response);
+ // Check statistic-sample-age-set
+ sendUnixCommand("{ \"command\" : \"statistic-sample-age-set\", "
+ " \"arguments\": {"
+ " \"name\":\"bogus\", \"duration\": 1245 }}", response);
+ EXPECT_EQ("{ \"result\": 1, \"text\": \"No 'bogus' statistic found\" }",
+ response);
- // Verify the control channel socket still exists.
- EXPECT_TRUE(fileExists(socket_path_));
+ // Check statistic-sample-age-set-all
+ sendUnixCommand("{ \"command\" : \"statistic-sample-age-set-all\", "
+ " \"arguments\": {"
+ " \"duration\": 1245 }}", response);
+ EXPECT_EQ("{ \"result\": 0, \"text\": \"All statistics duration limit are set.\" }",
+ response);
- // Verify the configuration was successful.
- EXPECT_EQ("{ \"result\": 0, \"text\": \"Configuration seems sane. "
- "Control-socket, hook-libraries, and D2 configuration were "
- "sanity checked, but not applied.\" }",
+ // Check statistic-sample-count-set
+ sendUnixCommand("{ \"command\" : \"statistic-sample-count-set\", "
+ " \"arguments\": {"
+ " \"name\":\"bogus\", \"max-samples\": 100 }}", response);
+ EXPECT_EQ("{ \"result\": 1, \"text\": \"No 'bogus' statistic found\" }",
response);
- // Check that the config was not applied
- subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
- EXPECT_EQ(1, subnets->size());
+ // Check statistic-sample-count-set-all
+ sendUnixCommand("{ \"command\" : \"statistic-sample-count-set-all\", "
+ " \"arguments\": {"
+ " \"max-samples\": 100 }}", response);
+ EXPECT_EQ("{ \"result\": 0, \"text\": \"All statistics count limit are set.\" }",
+ response);
+}
- // Clean up after the test.
- CfgMgr::instance().clear();
+// Tests that the server properly responds to shtudown command sent
+// via ControlChannel
+TEST_F(CtrlChannelDhcpv4SrvTest, listCommands) {
+ createUnixChannelServer();
+ std::string response;
+
+ sendUnixCommand("{ \"command\": \"list-commands\" }", response);
+
+ ConstElementPtr rsp;
+ EXPECT_NO_THROW(rsp = Element::fromJSON(response));
+
+ // We expect the server to report at least the following commands:
+ checkListCommands(rsp, "build-report");
+ checkListCommands(rsp, "config-get");
+ checkListCommands(rsp, "config-reload");
+ checkListCommands(rsp, "config-set");
+ checkListCommands(rsp, "config-test");
+ checkListCommands(rsp, "config-write");
+ checkListCommands(rsp, "list-commands");
+ checkListCommands(rsp, "leases-reclaim");
+ checkListCommands(rsp, "libreload");
+ checkListCommands(rsp, "version-get");
+ checkListCommands(rsp, "server-tag-get");
+ checkListCommands(rsp, "shutdown");
+ checkListCommands(rsp, "statistic-get");
+ checkListCommands(rsp, "statistic-get-all");
+ checkListCommands(rsp, "statistic-remove");
+ checkListCommands(rsp, "statistic-remove-all");
+ checkListCommands(rsp, "statistic-reset");
+ checkListCommands(rsp, "statistic-reset-all");
+ checkListCommands(rsp, "statistic-sample-age-set");
+ checkListCommands(rsp, "statistic-sample-age-set-all");
+ checkListCommands(rsp, "statistic-sample-count-set");
+ checkListCommands(rsp, "statistic-sample-count-set-all");
+}
+
+// Tests if the server returns its configuration using config-get.
+// Note there are separate tests that verify if toElement() called by the
+// config-get handler are actually converting the configuration correctly.
+TEST_F(CtrlChannelDhcpv4SrvTest, configGet) {
+ createUnixChannelServer();
+ std::string response;
+
+ sendUnixCommand("{ \"command\": \"config-get\" }", response);
+ ConstElementPtr rsp;
+
+ // The response should be a valid JSON.
+ EXPECT_NO_THROW(rsp = Element::fromJSON(response));
+ ASSERT_TRUE(rsp);
+
+ int status;
+ ConstElementPtr cfg = parseAnswer(status, rsp);
+ EXPECT_EQ(CONTROL_RESULT_SUCCESS, status);
+
+ // Ok, now roughly check if the response seems legit.
+ ASSERT_TRUE(cfg);
+ ASSERT_EQ(Element::map, cfg->getType());
+ EXPECT_TRUE(cfg->get("Dhcp4"));
}
// Tests if config-write can be called without any parameters.
-TEST_F(CtrlChannelDhcpv4SrvTest, writeConfigNoFilename) {
+TEST_F(CtrlChannelDhcpv4SrvTest, configWriteNoFilename) {
createUnixChannelServer();
std::string response;
}
// Tests if config-write can be called with a valid filename as parameter.
-TEST_F(CtrlChannelDhcpv4SrvTest, writeConfigFilename) {
+TEST_F(CtrlChannelDhcpv4SrvTest, configWriteFilename) {
createUnixChannelServer();
std::string response;
}
// This test verifies that the server signals timeout if the transmission
-// takes too long, after receiving a partial command.
+// takes too long, having received a partial command.
TEST_F(CtrlChannelDhcpv4SrvTest, connectionTimeoutPartialCommand) {
createUnixChannelServer();
// Check that the server has signalled a timeout.
EXPECT_EQ("{ \"result\": 1, \"text\": "
"\"Connection over control channel timed out, "
- "discarded partial command of 19 bytes\" }" , response);
+ "discarded partial command of 19 bytes\" }", response);
}
// This test verifies that the server signals timeout if the transmission
ASSERT_TRUE(client);
ASSERT_TRUE(client->connectToServer(socket_path_));
+ // Having sent nothing let's just wait and see if Server times us out.
// Let's wait up to 15s for the server's response. The response
// should arrive sooner assuming that the timeout mechanism for
// the server is working properly.