"Fossies" - the Fresh Open Source Software Archive

Member "kea-1.6.2/src/bin/dhcp4/tests/inform_unittest.cc" (21 Feb 2020, 20843 Bytes) of package /linux/misc/kea-1.6.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "inform_unittest.cc": 1.6.1_vs_1.6.2.

    1 // Copyright (C) 2014-2020 Internet Systems Consortium, Inc. ("ISC")
    2 //
    3 // This Source Code Form is subject to the terms of the Mozilla Public
    4 // License, v. 2.0. If a copy of the MPL was not distributed with this
    5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
    6 
    7 #include <config.h>
    8 #include <asiolink/io_address.h>
    9 #include <cc/data.h>
   10 #include <dhcp/dhcp4.h>
   11 #include <dhcp/tests/iface_mgr_test_config.h>
   12 #include <dhcp4/tests/dhcp4_test_utils.h>
   13 #include <dhcp4/tests/dhcp4_client.h>
   14 #include <stats/stats_mgr.h>
   15 
   16 using namespace isc;
   17 using namespace isc::asiolink;
   18 using namespace isc::data;
   19 using namespace isc::dhcp;
   20 using namespace isc::dhcp::test;
   21 
   22 namespace {
   23 
   24 /// @brief Set of JSON configurations used throughout the Inform tests.
   25 ///
   26 /// - Configuration 0:
   27 ///   - Used for testing direct traffic
   28 ///   - 1 subnet: 10.0.0.0/24
   29 ///   - 1 pool: 10.0.0.10-10.0.0.100
   30 ///   - Router option present: 10.0.0.200 and 10.0.0.201
   31 ///   - Domain Name Server option present: 10.0.0.202, 10.0.0.203.
   32 ///   - Log Servers option present: 192.0.2.200 and 192.0.2.201
   33 ///   - Quotes Servers option present: 192.0.2.202, 192.0.2.203.
   34 ///
   35 /// - Configuration 1:
   36 ///   - Use for testing relayed messages
   37 ///   - 1 subnet: 192.0.2.0/24
   38 ///   - Router option present: 192.0.2.200 and 192.0.2.201
   39 ///   - Domain Name Server option present: 192.0.2.202, 192.0.2.203.
   40 ///   - Log Servers option present: 192.0.2.200 and 192.0.2.201
   41 ///   - Quotes Servers option present: 192.0.2.202, 192.0.2.203.
   42 ///
   43 /// - Configuration 2:
   44 ///   - This configuration provides reservations for next-server,
   45 ///     server-hostname and boot-file-name value.
   46 ///   - 1 subnet: 192.0.2.0/24
   47 ///   - 1 reservation for this subnet:
   48 ///     - Client's HW address: aa:bb:cc:dd:ee:ff
   49 ///     - next-server = 10.0.0.7
   50 ///     - server name = "some-name.example.org"
   51 ///     - boot-file-name = "bootfile.efi"
   52 const char* INFORM_CONFIGS[] = {
   53 // Configuration 0
   54     "{ \"interfaces-config\": {"
   55         "      \"interfaces\": [ \"*\" ]"
   56         "},"
   57         "\"valid-lifetime\": 600,"
   58         "\"subnet4\": [ { "
   59         "    \"subnet\": \"10.0.0.0/24\", "
   60         "    \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ],"
   61         "    \"option-data\": [ {"
   62         "        \"name\": \"routers\","
   63         "        \"data\": \"10.0.0.200,10.0.0.201\""
   64         "    },"
   65         "    {"
   66         "        \"name\": \"domain-name-servers\","
   67         "        \"data\": \"10.0.0.202,10.0.0.203\""
   68         "    },"
   69         "    {"
   70         "        \"name\": \"log-servers\","
   71         "        \"data\": \"10.0.0.202,10.0.0.203\""
   72         "    },"
   73         "    {"
   74         "        \"name\": \"cookie-servers\","
   75         "        \"data\": \"10.0.0.200,10.0.0.201\""
   76         "    } ]"
   77         " } ]"
   78     "}",
   79 
   80 // Configuration 1
   81     "{ \"interfaces-config\": {"
   82         "      \"interfaces\": [ \"*\" ]"
   83         "},"
   84         "\"valid-lifetime\": 600,"
   85         "\"subnet4\": [ { "
   86         "    \"subnet\": \"192.0.2.0/24\", "
   87         "    \"option-data\": [ {"
   88         "        \"name\": \"routers\","
   89         "        \"data\": \"192.0.2.200,192.0.2.201\""
   90         "    },"
   91         "    {"
   92         "        \"name\": \"domain-name-servers\","
   93         "        \"data\": \"192.0.2.202,192.0.2.203\""
   94         "    },"
   95         "    {"
   96         "        \"name\": \"log-servers\","
   97         "        \"data\": \"10.0.0.200,10.0.0.201\""
   98         "    },"
   99         "    {"
  100         "        \"name\": \"cookie-servers\","
  101         "        \"data\": \"10.0.0.202,10.0.0.203\""
  102         "    } ]"
  103         " } ]"
  104     "}",
  105 
  106 // Configuration 2
  107     "{ \"interfaces-config\": {"
  108         "      \"interfaces\": [ \"*\" ]"
  109         "},"
  110         "\"valid-lifetime\": 600,"
  111         "\"next-server\": \"10.0.0.1\","
  112         "\"server-hostname\": \"nohost\","
  113         "\"server-hostname\": \"nofile\","
  114         "\"subnet4\": [ { "
  115         "    \"subnet\": \"192.0.2.0/24\", "
  116         "    \"reservations\": [ "
  117         "       {"
  118         "         \"hw-address\": \"aa:bb:cc:dd:ee:ff\","
  119         "         \"next-server\": \"10.0.0.7\","
  120         "         \"server-hostname\": \"some-name.example.org\","
  121         "         \"boot-file-name\": \"bootfile.efi\""
  122         "       }"
  123         "    ]"
  124         "} ]"
  125     "}",
  126 };
  127 
  128 /// @brief Test fixture class for testing DHCPINFORM.
  129 class InformTest : public Dhcpv4SrvTest {
  130 public:
  131 
  132     /// @brief Constructor.
  133     ///
  134     /// Sets up fake interfaces.
  135     InformTest()
  136         : Dhcpv4SrvTest(),
  137           iface_mgr_test_config_(true) {
  138         IfaceMgr::instance().openSockets4();
  139 
  140         // Let's wipe all existing statistics.
  141         isc::stats::StatsMgr::instance().removeAll();
  142     }
  143 
  144     /// @brief Destructor.
  145     ///
  146     /// Cleans up statistics after the test.
  147     ~InformTest() {
  148         // Let's wipe all existing statistics.
  149         isc::stats::StatsMgr::instance().removeAll();
  150     }
  151 
  152     /// @brief Interface Manager's fake configuration control.
  153     IfaceMgrTestConfig iface_mgr_test_config_;
  154 
  155 };
  156 
  157 // Test that directly connected client's DHCPINFORM message is processed and
  158 // DHCPACK message is sent back.
  159 TEST_F(InformTest, directClientBroadcast) {
  160     Dhcp4Client client;
  161     // Configure DHCP server.
  162     configure(INFORM_CONFIGS[0], *client.getServer());
  163     // Request some configuration when DHCPINFORM is sent.
  164     client.requestOptions(DHO_LOG_SERVERS, DHO_COOKIE_SERVERS);
  165     // Preconfigure the client with the IP address.
  166     client.createLease(IOAddress("10.0.0.56"), 600);
  167 
  168     // Send DHCPINFORM message to the server.
  169     ASSERT_NO_THROW(client.doInform());
  170 
  171     // Make sure that the server responded.
  172     ASSERT_TRUE(client.getContext().response_);
  173     Pkt4Ptr resp = client.getContext().response_;
  174     // Make sure that the server has responded with DHCPACK.
  175     ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
  176     // Response should have been unicast to the ciaddr.
  177     EXPECT_EQ(IOAddress("10.0.0.56"), resp->getLocalAddr());
  178     // The ciaddr should have been copied.
  179     EXPECT_EQ(IOAddress("10.0.0.56"), resp->getCiaddr());
  180     // Response must not be relayed.
  181     EXPECT_FALSE(resp->isRelayed());
  182     // Make sure that the server id is present.
  183     EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
  184 
  185     // Make sure that the Routers option has been received.
  186     ASSERT_EQ(2, client.config_.routers_.size());
  187     EXPECT_EQ("10.0.0.200", client.config_.routers_[0].toText());
  188     EXPECT_EQ("10.0.0.201", client.config_.routers_[1].toText());
  189     // Make sure that the DNS Servers option has been received.
  190     ASSERT_EQ(2, client.config_.dns_servers_.size());
  191     EXPECT_EQ("10.0.0.202", client.config_.dns_servers_[0].toText());
  192     EXPECT_EQ("10.0.0.203", client.config_.dns_servers_[1].toText());
  193     // Make sure that the Log Servers option has been received.
  194     ASSERT_EQ(2, client.config_.quotes_servers_.size());
  195     EXPECT_EQ("10.0.0.200", client.config_.quotes_servers_[0].toText());
  196     EXPECT_EQ("10.0.0.201", client.config_.quotes_servers_[1].toText());
  197     // Make sure that the Quotes Servers option has been received.
  198     ASSERT_EQ(2, client.config_.log_servers_.size());
  199     EXPECT_EQ("10.0.0.202", client.config_.log_servers_[0].toText());
  200     EXPECT_EQ("10.0.0.203", client.config_.log_servers_[1].toText());
  201 
  202     // Check that we can send another DHCPINFORM message using
  203     // different ciaddr and we will get the configuration.
  204     client.createLease(IOAddress("10.0.0.12"), 600);
  205     // This time do not request Quotes Servers option and it should not
  206     // be returned.
  207     client.requestOptions(DHO_LOG_SERVERS);
  208 
  209     // Send DHCPINFORM.
  210     ASSERT_NO_THROW(client.doInform());
  211 
  212     // Make sure that the server responded.
  213     resp = client.getContext().response_;
  214     ASSERT_TRUE(resp);
  215     // Make sure that the server has responded with DHCPACK.
  216     ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
  217     // Response should have been unicast to the ciaddr.
  218     EXPECT_EQ(IOAddress("10.0.0.12"), resp->getLocalAddr());
  219     // The ciaddr should have been copied.
  220     EXPECT_EQ(IOAddress("10.0.0.12"), resp->getCiaddr());
  221     // Response must not be relayed.
  222     EXPECT_FALSE(resp->isRelayed());
  223 
  224     // Make sure that the server id is present.
  225     EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
  226     // Make sure that the Routers option has been received.
  227     ASSERT_EQ(2, client.config_.routers_.size());
  228     EXPECT_EQ("10.0.0.200", client.config_.routers_[0].toText());
  229     EXPECT_EQ("10.0.0.201", client.config_.routers_[1].toText());
  230     // Make sure that the DNS Servers option has been received.
  231     ASSERT_EQ(2, client.config_.dns_servers_.size());
  232     EXPECT_EQ("10.0.0.202", client.config_.dns_servers_[0].toText());
  233     EXPECT_EQ("10.0.0.203", client.config_.dns_servers_[1].toText());
  234     // Make sure that the Quotes Servers option hasn't been received.
  235     ASSERT_TRUE(client.config_.quotes_servers_.empty());
  236 }
  237 
  238 // This test checks that the server drops DHCPINFORM message when the
  239 // source address and ciaddr is 0.
  240 TEST_F(InformTest, directClientBroadcastNoAddress) {
  241     Dhcp4Client client;
  242     // Configure DHCP server.
  243     configure(INFORM_CONFIGS[0], *client.getServer());
  244     // Request some configuration when DHCPINFORM is sent.
  245     client.requestOptions(DHO_LOG_SERVERS, DHO_COOKIE_SERVERS);
  246     // Send DHCPINFORM message to the server.
  247     ASSERT_NO_THROW(client.doInform());
  248     // Make sure that the server dropped the message.
  249     ASSERT_FALSE(client.getContext().response_);
  250 }
  251 
  252 // Test that client's DHCPINFORM message sent to a unicast address
  253 // is received and processed by the server and that the DHCPACK is
  254 // is sent.
  255 TEST_F(InformTest, directClientUnicast) {
  256     Dhcp4Client client;
  257     // Configure DHCP server.
  258     configure(INFORM_CONFIGS[0], *client.getServer());
  259     // Preconfigure the client with the IP address.
  260     client.createLease(IOAddress("10.0.0.56"), 600);
  261     // Set remote address to unicast.
  262     client.setDestAddress(IOAddress("10.0.0.1"));
  263     // Send DHCPINFORM message to the server.
  264     ASSERT_NO_THROW(client.doInform());
  265     // Make sure that the server responded.
  266     ASSERT_TRUE(client.getContext().response_);
  267     Pkt4Ptr resp = client.getContext().response_;
  268     // Make sure that the server has responded with DHCPACK.
  269     ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
  270     // Response should have been unicast to the ciaddr.
  271     EXPECT_EQ(IOAddress("10.0.0.56"), resp->getLocalAddr());
  272     // The ciaddr should have been copied.
  273     EXPECT_EQ(IOAddress("10.0.0.56"), resp->getCiaddr());
  274     // Response must not be relayed.
  275     EXPECT_FALSE(resp->isRelayed());
  276     // Make sure that the server id is present.
  277     EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
  278     // Make sure that the Routers option has been received.
  279     ASSERT_EQ(2, client.config_.routers_.size());
  280     EXPECT_EQ("10.0.0.200", client.config_.routers_[0].toText());
  281     EXPECT_EQ("10.0.0.201", client.config_.routers_[1].toText());
  282     // Make sure that the DNS Servers option has been received.
  283     ASSERT_EQ(2, client.config_.dns_servers_.size());
  284     EXPECT_EQ("10.0.0.202", client.config_.dns_servers_[0].toText());
  285     EXPECT_EQ("10.0.0.203", client.config_.dns_servers_[1].toText());
  286 }
  287 
  288 // This test checks that the server responds to the source address of the
  289 // packet received from the directly connected client if the client didn't
  290 // set the ciaddr.
  291 TEST_F(InformTest, directClientNoCiaddr) {
  292     Dhcp4Client client;
  293     // Configure DHCP server.
  294     configure(INFORM_CONFIGS[0], *client.getServer());
  295     // Preconfigure the client with the IP address.
  296     client.createLease(IOAddress("10.0.0.56"), 600);
  297     // Send DHCPINFORM message (with ciaddr not set) to the server.
  298     ASSERT_NO_THROW(client.doInform(false));
  299     // Make sure that the server responded.
  300     ASSERT_TRUE(client.getContext().response_);
  301     Pkt4Ptr resp = client.getContext().response_;
  302     // Make sure that the server has responded with DHCPACK.
  303     ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
  304     // Response should have been unicast to the client address.
  305     EXPECT_EQ(IOAddress("10.0.0.56"), resp->getLocalAddr());
  306     // The ciaddr should be 0.
  307     EXPECT_EQ(IOAddress("0.0.0.0"), resp->getCiaddr());
  308     // Response must not be relayed.
  309     EXPECT_FALSE(resp->isRelayed());
  310     EXPECT_EQ(DHCP4_CLIENT_PORT, resp->getLocalPort());
  311     EXPECT_EQ(DHCP4_SERVER_PORT, resp->getRemotePort());
  312     // Make sure that the server id is present.
  313     EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
  314     // Make sure that the Routers option has been received.
  315     ASSERT_EQ(2, client.config_.routers_.size());
  316     EXPECT_EQ("10.0.0.200", client.config_.routers_[0].toText());
  317     EXPECT_EQ("10.0.0.201", client.config_.routers_[1].toText());
  318     // Make sure that the DNS Servers option has been received.
  319     ASSERT_EQ(2, client.config_.dns_servers_.size());
  320     EXPECT_EQ("10.0.0.202", client.config_.dns_servers_[0].toText());
  321     EXPECT_EQ("10.0.0.203", client.config_.dns_servers_[1].toText());
  322 }
  323 
  324 // This test checks that the server receiving DHCPINFORM via relay, unicasts the
  325 // DHCPACK to the client (ciaddr).
  326 TEST_F(InformTest, relayedClient) {
  327     Dhcp4Client client;
  328     // Configure DHCP server.
  329     configure(INFORM_CONFIGS[1], *client.getServer());
  330     // Message is relayed.
  331     client.useRelay();
  332     // Request some configuration when DHCPINFORM is sent.
  333     client.requestOptions(DHO_LOG_SERVERS, DHO_COOKIE_SERVERS);
  334     // Preconfigure the client with the IP address.
  335     client.createLease(IOAddress("192.0.2.56"), 600);
  336     // Send DHCPINFORM message to the server.
  337     ASSERT_NO_THROW(client.doInform());
  338     // Make sure that the server responded.
  339     ASSERT_TRUE(client.getContext().response_);
  340     Pkt4Ptr resp = client.getContext().response_;
  341     // Make sure that the server has responded with DHCPACK.
  342     ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
  343     // Response should have been unicast to the ciaddr.
  344     EXPECT_EQ(IOAddress("192.0.2.56"), resp->getLocalAddr());
  345     // The ciaddr should have been copied.
  346     EXPECT_EQ(IOAddress("192.0.2.56"), resp->getCiaddr());
  347     // Response is unicast to the client, so it must not be relayed.
  348     EXPECT_FALSE(resp->isRelayed());
  349     EXPECT_EQ(DHCP4_CLIENT_PORT, resp->getLocalPort());
  350     EXPECT_EQ(DHCP4_SERVER_PORT, resp->getRemotePort());
  351     // Make sure that the server id is present.
  352     EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
  353     // Make sure that the Routers option has been received.
  354     ASSERT_EQ(2, client.config_.routers_.size());
  355     EXPECT_EQ("192.0.2.200", client.config_.routers_[0].toText());
  356     EXPECT_EQ("192.0.2.201", client.config_.routers_[1].toText());
  357     // Make sure that the DNS Servers option has been received.
  358     ASSERT_EQ(2, client.config_.dns_servers_.size());
  359     EXPECT_EQ("192.0.2.202", client.config_.dns_servers_[0].toText());
  360     EXPECT_EQ("192.0.2.203", client.config_.dns_servers_[1].toText());
  361     // Make sure that the Quotes Servers option has been received.
  362     ASSERT_EQ(2, client.config_.quotes_servers_.size());
  363     EXPECT_EQ("10.0.0.202", client.config_.quotes_servers_[0].toText());
  364     EXPECT_EQ("10.0.0.203", client.config_.quotes_servers_[1].toText());
  365     // Make sure that the Log Servers option has been received.
  366     ASSERT_EQ(2, client.config_.log_servers_.size());
  367     EXPECT_EQ("10.0.0.200", client.config_.log_servers_[0].toText());
  368     EXPECT_EQ("10.0.0.201", client.config_.log_servers_[1].toText());
  369 }
  370 
  371 // This test checks that the server can respond to the DHCPINFORM message
  372 // received via relay when the ciaddr is not set.
  373 TEST_F(InformTest, relayedClientNoCiaddr) {
  374     Dhcp4Client client;
  375     // Configure DHCP server.
  376     configure(INFORM_CONFIGS[1], *client.getServer());
  377     // Message is relayed.
  378     client.useRelay();
  379     // Send DHCPINFORM message to the server.
  380     ASSERT_NO_THROW(client.doInform());
  381     // Make sure that the server responded.
  382     ASSERT_TRUE(client.getContext().response_);
  383     Pkt4Ptr resp = client.getContext().response_;
  384     // Make sure that the server has responded with DHCPACK.
  385     ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
  386     // Response should go through a relay as there is no ciaddr.
  387     EXPECT_EQ(IOAddress("192.0.2.2"), resp->getLocalAddr());
  388     EXPECT_EQ(IOAddress("192.0.2.2"), resp->getGiaddr());
  389     EXPECT_EQ(1, resp->getHops());
  390     EXPECT_EQ(DHCP4_SERVER_PORT, resp->getLocalPort());
  391     EXPECT_EQ(DHCP4_SERVER_PORT, resp->getRemotePort());
  392     // In the case when the client didn't set the ciaddr and the message
  393     // was received via relay the server sets the Broadcast flag to help
  394     // the relay forwarding the message (without yiaddr) to the client.
  395     EXPECT_EQ(BOOTP_BROADCAST, resp->getFlags() & BOOTP_BROADCAST);
  396     // Make sure that the server id is present.
  397     EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
  398     // Make sure that the Routers option has been received.
  399     ASSERT_EQ(2, client.config_.routers_.size());
  400     EXPECT_EQ("192.0.2.200", client.config_.routers_[0].toText());
  401     EXPECT_EQ("192.0.2.201", client.config_.routers_[1].toText());
  402     // Make sure that the DNS Servers option has been received.
  403     ASSERT_EQ(2, client.config_.dns_servers_.size());
  404     EXPECT_EQ("192.0.2.202", client.config_.dns_servers_[0].toText());
  405     EXPECT_EQ("192.0.2.203", client.config_.dns_servers_[1].toText());
  406 }
  407 
  408 // This test verifies that the server assigns reserved values for the
  409 // siaddr, sname and file fields carried within DHCPv4 message.
  410 TEST_F(InformTest, messageFieldsReservations) {
  411     // Client has a reservation.
  412     Dhcp4Client client(Dhcp4Client::SELECTING);
  413     // Message is relayed.
  414     client.useRelay();
  415     // Set explicit HW address so as it matches the reservation in the
  416     // configuration used below.
  417     client.setHWAddress("aa:bb:cc:dd:ee:ff");
  418     // Configure DHCP server.
  419     configure(INFORM_CONFIGS[2], *client.getServer());
  420     // Client sends DHCPINFORM and should receive reserved fields.
  421     ASSERT_NO_THROW(client.doInform());
  422     // Make sure that the server responded.
  423     ASSERT_TRUE(client.getContext().response_);
  424     Pkt4Ptr resp = client.getContext().response_;
  425     // Make sure that the server has responded with DHCPACK.
  426     ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
  427 
  428     // Check that the reserved values have been assigned.
  429     EXPECT_EQ("10.0.0.7", client.config_.siaddr_.toText());
  430     EXPECT_EQ("some-name.example.org", client.config_.sname_);
  431     EXPECT_EQ("bootfile.efi", client.config_.boot_file_name_);
  432 }
  433 
  434 /// This test verifies that after a client completes its INFORM exchange,
  435 /// appropriate statistics are updated.
  436 TEST_F(InformTest, statisticsInform) {
  437     Dhcp4Client client;
  438     // Configure DHCP server.
  439     configure(INFORM_CONFIGS[0], *client.getServer());
  440     // Request some configuration when DHCPINFORM is sent.
  441     client.requestOptions(DHO_LOG_SERVERS, DHO_COOKIE_SERVERS);
  442     // Preconfigure the client with the IP address.
  443     client.createLease(IOAddress("10.0.0.56"), 600);
  444 
  445     // Send DHCPINFORM message to the server.
  446     ASSERT_NO_THROW(client.doInform());
  447 
  448     // Make sure that the server responded.
  449     ASSERT_TRUE(client.getContext().response_);
  450     Pkt4Ptr resp = client.getContext().response_;
  451     // Make sure that the server has responded with DHCPACK.
  452     ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
  453 
  454     // Ok, let's check the statistics.
  455     using namespace isc::stats;
  456     StatsMgr& mgr = StatsMgr::instance();
  457     ObservationPtr pkt4_received = mgr.getObservation("pkt4-received");
  458     ObservationPtr pkt4_inform_received = mgr.getObservation("pkt4-inform-received");
  459     ObservationPtr pkt4_ack_sent = mgr.getObservation("pkt4-ack-sent");
  460     ObservationPtr pkt4_sent = mgr.getObservation("pkt4-sent");
  461 
  462     // All expected statistics must be present.
  463     ASSERT_TRUE(pkt4_received);
  464     ASSERT_TRUE(pkt4_inform_received);
  465     ASSERT_TRUE(pkt4_ack_sent);
  466     ASSERT_TRUE(pkt4_sent);
  467 
  468     // And they must have expected values.
  469     EXPECT_EQ(1, pkt4_received->getInteger().first);
  470     EXPECT_EQ(1, pkt4_inform_received->getInteger().first);
  471     EXPECT_EQ(1, pkt4_ack_sent->getInteger().first);
  472     EXPECT_EQ(1, pkt4_sent->getInteger().first);
  473 
  474     // Let the client send iform 4 times, which should make the server
  475     // to send 4 acks.
  476     ASSERT_NO_THROW(client.doInform());
  477     ASSERT_NO_THROW(client.doInform());
  478     ASSERT_NO_THROW(client.doInform());
  479     ASSERT_NO_THROW(client.doInform());
  480 
  481     // Let's see if the stats are properly updated.
  482     EXPECT_EQ(5, pkt4_received->getInteger().first);
  483     EXPECT_EQ(5, pkt4_inform_received->getInteger().first);
  484     EXPECT_EQ(5, pkt4_ack_sent->getInteger().first);
  485     EXPECT_EQ(5, pkt4_sent->getInteger().first);
  486 }
  487 
  488 } // end of anonymous namespace