]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#2054] added stats counter for allocation failures
authorRazvan Becheriu <razvan@isc.org>
Fri, 11 Feb 2022 13:20:40 +0000 (15:20 +0200)
committerRazvan Becheriu <razvan@isc.org>
Thu, 17 Feb 2022 17:50:29 +0000 (19:50 +0200)
12 files changed:
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc
src/bin/dhcp4/tests/dora_unittest.cc
src/bin/dhcp6/dhcp6_srv.cc
src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
src/bin/dhcp6/tests/shared_network_unittest.cc
src/lib/dhcpsrv/alloc_engine.cc
src/lib/dhcpsrv/alloc_engine_messages.cc
src/lib/dhcpsrv/alloc_engine_messages.h
src/lib/dhcpsrv/alloc_engine_messages.mes
src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc
src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc

index 7df4010255d9b111e1cb72debe75bb72e610f1bf..e8b669798196c081b435193be0422fbfbcf44d3c 100644 (file)
@@ -130,7 +130,12 @@ std::set<std::string> dhcp4_statistics = {
     "pkt4-ack-sent",
     "pkt4-nak-sent",
     "pkt4-parse-failed",
-    "pkt4-receive-drop"
+    "pkt4-receive-drop",
+    "v4-allocation-fail",
+    "v4-allocation-fail-shared-network",
+    "v4-allocation-fail-subnet",
+    "v4-allocation-fail-no-pools",
+    "v4-allocation-fail-classes"
 };
 
 } // end of anonymous namespace
index 9efc45294f7224cee45010605699eb799a0364e9..69580a0c25ce0566a40cb9530b658c9412df16ef 100644 (file)
@@ -643,7 +643,12 @@ TEST_F(CtrlChannelDhcpv4SrvTest, controlChannelStats) {
         "pkt4-ack-sent",
         "pkt4-nak-sent",
         "pkt4-parse-failed",
-        "pkt4-receive-drop"
+        "pkt4-receive-drop",
+        "v4-allocation-fail",
+        "v4-allocation-fail-shared-network",
+        "v4-allocation-fail-subnet",
+        "v4-allocation-fail-no-pools",
+        "v4-allocation-fail-classes"
     };
 
     // preparing the schema which check if all statistics are set to zero
index b8de99c7cb0c695e327e0e9f206255f87db67fe8..e3074fc9d784ed7870b9d5797afeef0c018f8dc1 100644 (file)
@@ -2573,7 +2573,7 @@ DORATest::changingCircuitId() {
     Pkt4Ptr resp = client.getContext().response_;
     // Make sure that the server has responded with DHCPOFFER
     ASSERT_EQ(DHCPOFFER, static_cast<int>(resp->getType()));
-    // Make sure that the client has been offerred a different address
+    // Make sure that the client has been offered a different address
     // given that circuit-id is not used.
     EXPECT_NE("10.0.0.9", resp->getYiaddr().toText());
 
@@ -2587,14 +2587,14 @@ DORATest::changingCircuitId() {
     resp = client.getContext().response_;
     // Make sure that the server has responded with DHCPOFFER
     ASSERT_EQ(DHCPOFFER, static_cast<int>(resp->getType()));
-    // Make sure that the client has been offerred reserved address given that
+    // Make sure that the client has been offered reserved address given that
     // matching circuit-id has been specified.
     EXPECT_EQ("10.0.0.9", resp->getYiaddr().toText());
 
     // Let's now change the circuit-id.
     client.setCircuitId("gdansk");
 
-    // The client requests offerred address but should be refused this address
+    // The client requests offered address but should be refused this address
     // given that the circuit-id is not matching.
     ASSERT_NO_THROW(client.doRequest());
     // Make sure that the server responded.
index b33a1a56e129a10281cc3b5bdc515e751d0a2b36..555c566713124ea3c15cc68a8ac2a566f384e789 100644 (file)
@@ -196,7 +196,12 @@ std::set<std::string> dhcp6_statistics = {
     "pkt6-reply-sent",
     "pkt6-dhcpv4-response-sent",
     "pkt6-parse-failed",
-    "pkt6-receive-drop"
+    "pkt6-receive-drop",
+    "v6-allocation-fail",
+    "v6-allocation-fail-shared-network",
+    "v6-allocation-fail-subnet",
+    "v6-allocation-fail-no-pools",
+    "v6-allocation-fail-classes"
 };
 
 }  // namespace
index fb513058a662fe886311e11fceba8124391ae329..946b24acf01cb18a718c4c3862e7a6e516c72c10 100644 (file)
@@ -1266,7 +1266,12 @@ TEST_F(CtrlChannelDhcpv6SrvTest, controlChannelStats) {
         "pkt6-reply-sent",
         "pkt6-dhcpv4-response-sent",
         "pkt6-parse-failed",
-        "pkt6-receive-drop"
+        "pkt6-receive-drop",
+        "v6-allocation-fail",
+        "v6-allocation-fail-shared-network",
+        "v6-allocation-fail-subnet",
+        "v6-allocation-fail-no-pools",
+        "v6-allocation-fail-classes"
     };
 
     std::ostringstream s;
index 63aee55e00c1b491c4ea0399ebf3bff513baf135..0a1b706a0ee27adce0bae15c6f5ea8fd8ea69953 100644 (file)
@@ -1632,7 +1632,7 @@ TEST_F(Dhcpv6SharedNetworkTest, hintWithinSharedNetwork) {
     ASSERT_TRUE(hasLeaseForAddress(client, IOAddress("2001:db8:1::20"),
                                    LeaseOnServer::MUST_NOT_EXIST));
 
-    // Similarly, we should be offerred an address from another subnet within
+    // Similarly, we should be offered an address from another subnet within
     // the same shared network when we ask for it.
     client.clearRequestedIAs();
     ASSERT_NO_THROW(client.requestAddress(0xabca, IOAddress("2001:db8:2::20")));
@@ -1962,7 +1962,7 @@ TEST_F(Dhcpv6SharedNetworkTest, optionsFromSelectedSubnet) {
     // Request Name Servers option.
     ASSERT_NO_THROW(client.requestOption(D6O_NAME_SERVERS));
 
-    // Send solicit without a hint. The client should be offerred an address from the
+    // Send solicit without a hint. The client should be offered an address from the
     // shared network. Depending on the subnet from which the address has been allocated
     // a specific value of the Name Servers option should be returned.
     testAssigned([&client] {
@@ -2143,7 +2143,7 @@ TEST_F(Dhcpv6SharedNetworkTest, sharedNetworkSelectedByClass) {
     // respectively.
     ASSERT_NO_FATAL_FAILURE(configure(NETWORKS_CONFIG[11], *client1.getServer()));
 
-    // The client 1 should be offerred an address from the second subnet.
+    // The client 1 should be offered an address from the second subnet.
     testAssigned([&client1] {
         ASSERT_NO_THROW(client1.doSolicit(true));
     });
@@ -2159,7 +2159,7 @@ TEST_F(Dhcpv6SharedNetworkTest, sharedNetworkSelectedByClass) {
     option1234.reset(new OptionUint16(Option::V6, 1234, 0x0001));
     client2.addExtraOption(option1234);
 
-    // Client 2 should be offerred an address from the first subnet.
+    // Client 2 should be offered an address from the first subnet.
     testAssigned([&client2] {
         ASSERT_NO_THROW(client2.doSolicit(true));
     });
index d04be22b6c11784daf6f3448cfdd1c7c4fec4e4c..75f6d76169dd8e0d1081d57488ce0ac204e489f4 100644 (file)
@@ -1212,13 +1212,16 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
             .arg(network->getName())
             .arg(subnets_with_unavail_leases)
             .arg(subnets_with_unavail_pools);
-
+        StatsMgr::instance().addValue("v6-allocation-fail-shared-network",
+                                      static_cast<int64_t>(1));
     } else {
         // The client is not connected to a shared network. It is connected
         // to a subnet. Let's log the ID of that subnet.
         LOG_WARN(alloc_engine_logger, ALLOC_ENGINE_V6_ALLOC_FAIL_SUBNET)
             .arg(ctx.query_->getLabel())
             .arg(ctx.subnet_->getID());
+        StatsMgr::instance().addValue("v6-allocation-fail-subnet",
+                                      static_cast<int64_t>(1));
     }
     if (total_attempts == 0) {
         // In this case, it seems that none of the pools in the subnets could
@@ -1227,6 +1230,8 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
         // rejected to use the pools because of the client classes' mismatch.
         LOG_WARN(alloc_engine_logger, ALLOC_ENGINE_V6_ALLOC_FAIL_NO_POOLS)
             .arg(ctx.query_->getLabel());
+        StatsMgr::instance().addValue("v6-allocation-fail-no-pools",
+                                      static_cast<int64_t>(1));
     } else {
         // This is an old log message which provides a number of attempts
         // made by the allocation engine to allocate a lease. The only case
@@ -1235,6 +1240,17 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
         LOG_WARN(alloc_engine_logger, ALLOC_ENGINE_V6_ALLOC_FAIL)
             .arg(ctx.query_->getLabel())
             .arg(total_attempts);
+        StatsMgr::instance().addValue("v6-allocation-fail",
+                                      static_cast<int64_t>(1));
+    }
+
+    const ClientClasses& classes = ctx.query_->getClasses();
+    if (!classes.empty()) {
+        LOG_WARN(alloc_engine_logger, ALLOC_ENGINE_V6_ALLOC_FAIL_CLASSES)
+            .arg(ctx.query_->getLabel())
+            .arg(classes.toText());
+        StatsMgr::instance().addValue("v6-allocation-fail-classes",
+                                      static_cast<int64_t>(1));
     }
 
     // We failed to allocate anything. Let's return empty collection.
@@ -4447,7 +4463,8 @@ AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
             .arg(network->getName())
             .arg(subnets_with_unavail_leases)
             .arg(subnets_with_unavail_pools);
-
+        StatsMgr::instance().addValue("v4-allocation-fail-shared-network",
+                                      static_cast<int64_t>(1));
     } else {
         // The client is not connected to a shared network. It is connected
         // to a subnet. Let's log some details about the subnet.
@@ -4456,6 +4473,8 @@ AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
             .arg(ctx.subnet_->toText())
             .arg(ctx.subnet_->getID())
             .arg(ctx.subnet_->getSharedNetworkName());
+        StatsMgr::instance().addValue("v4-allocation-fail-subnet",
+                                      static_cast<int64_t>(1));
     }
     if (total_attempts == 0) {
         // In this case, it seems that none of the pools in the subnets could
@@ -4464,6 +4483,8 @@ AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
         // rejected to use the pools because of the client classes' mismatch.
         LOG_WARN(alloc_engine_logger, ALLOC_ENGINE_V4_ALLOC_FAIL_NO_POOLS)
             .arg(ctx.query_->getLabel());
+        StatsMgr::instance().addValue("v4-allocation-fail-no-pools",
+                                      static_cast<int64_t>(1));
     } else {
         // This is an old log message which provides a number of attempts
         // made by the allocation engine to allocate a lease. The only case
@@ -4472,6 +4493,8 @@ AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
         LOG_WARN(alloc_engine_logger, ALLOC_ENGINE_V4_ALLOC_FAIL)
             .arg(ctx.query_->getLabel())
             .arg(total_attempts);
+        StatsMgr::instance().addValue("v4-allocation-fail",
+                                      static_cast<int64_t>(1));
     }
 
     const ClientClasses& classes = ctx.query_->getClasses();
@@ -4479,6 +4502,8 @@ AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
         LOG_WARN(alloc_engine_logger, ALLOC_ENGINE_V4_ALLOC_FAIL_CLASSES)
             .arg(ctx.query_->getLabel())
             .arg(classes.toText());
+        StatsMgr::instance().addValue("v4-allocation-fail-classes",
+                                      static_cast<int64_t>(1));
     }
 
     return (new_lease);
index ba62fdf6eaf1392d462d5339699796611de796eb..55ec69b93c2092c71443c39ee2a9eaf2aaaad3c2 100644 (file)
@@ -43,6 +43,7 @@ extern const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_USE_HR = "ALLOC_ENGINE_
 extern const isc::log::MessageID ALLOC_ENGINE_V4_REUSE_EXPIRED_LEASE_DATA = "ALLOC_ENGINE_V4_REUSE_EXPIRED_LEASE_DATA";
 extern const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_ERROR = "ALLOC_ENGINE_V6_ALLOC_ERROR";
 extern const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL = "ALLOC_ENGINE_V6_ALLOC_FAIL";
+extern const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_CLASSES = "ALLOC_ENGINE_V6_ALLOC_FAIL_CLASSES";
 extern const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_NO_POOLS = "ALLOC_ENGINE_V6_ALLOC_FAIL_NO_POOLS";
 extern const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_SHARED_NETWORK = "ALLOC_ENGINE_V6_ALLOC_FAIL_SHARED_NETWORK";
 extern const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_SUBNET = "ALLOC_ENGINE_V6_ALLOC_FAIL_SUBNET";
@@ -123,6 +124,7 @@ const char* values[] = {
     "ALLOC_ENGINE_V4_REUSE_EXPIRED_LEASE_DATA", "%1: reusing expired lease, updated lease information: %2",
     "ALLOC_ENGINE_V6_ALLOC_ERROR", "%1: error during attempt to allocate an IPv6 address: %2",
     "ALLOC_ENGINE_V6_ALLOC_FAIL", "%1: failed to allocate an IPv6 lease after %2 attempt(s)",
+    "ALLOC_ENGINE_V6_ALLOC_FAIL_CLASSES", "%1: Failed to allocate an IPv6 address for client with classes: %2",
     "ALLOC_ENGINE_V6_ALLOC_FAIL_NO_POOLS", "%1: no pools were available for the lease allocation",
     "ALLOC_ENGINE_V6_ALLOC_FAIL_SHARED_NETWORK", "%1: failed to allocate a lease in the shared network %2: %3 subnets have no available leases, %4 subnets have no matching pools",
     "ALLOC_ENGINE_V6_ALLOC_FAIL_SUBNET", "%1: failed to allocate an IPv6 lease in the subnet with id %2",
index d432c1f2ccca1c40015e71917fe0c7d6e436bee4..22e144a35dd9f427cc56f20ad795abf0879fa2ee 100644 (file)
@@ -44,6 +44,7 @@ extern const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_USE_HR;
 extern const isc::log::MessageID ALLOC_ENGINE_V4_REUSE_EXPIRED_LEASE_DATA;
 extern const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_ERROR;
 extern const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL;
+extern const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_CLASSES;
 extern const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_NO_POOLS;
 extern const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_SHARED_NETWORK;
 extern const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_SUBNET;
index 5859622131554559acada0f416ee3dcf90fbe4b5..8fcab76026a72702452380ab92c0cb6bf1c787b9 100644 (file)
@@ -298,6 +298,16 @@ available, you may want to consider reducing the lease lifetime. This way, lease
 allocated to clients that are no longer active on the network will become available
 sooner.
 
+% ALLOC_ENGINE_V6_ALLOC_FAIL_CLASSES %1: Failed to allocate an IPv6 address for client with classes: %2
+This warning message is printed when Kea failed to allocate an address
+and the client's packet belongs to one or more classes. There may be several
+reasons why a lease was not assigned. One of them may be a case when all
+pools require packet to belong to certain classes and the incoming packet
+didn't belong to any of them. Another case where this information may be
+useful is to point out that the pool reserved to a given class has ran
+out of addresses. When you see this message, you may consider checking your
+pool size and your classification definitions.
+
 % ALLOC_ENGINE_V6_ALLOC_FAIL_NO_POOLS %1: no pools were available for the lease allocation
 This warning message is issued when the allocation engine fails to
 allocate a lease because it could not use any configured pools for the
index 999d140dc68d16ecf805ed2b35defcfe83aa4600..0ff6fa39fdd6fcff8011bf3fa98d99413404252f 100644 (file)
@@ -95,7 +95,7 @@ TEST_F(AllocEngine4Test, simpleAlloc4) {
 
     Lease4Ptr lease = engine->allocateLease4(ctx);
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -139,7 +139,7 @@ TEST_F(AllocEngine4Test, simpleAlloc4) {
     lease = engine->allocateLease4(ctx2);
 
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx2.old_lease_);
+    ASSERT_FALSE(ctx2.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -174,7 +174,7 @@ TEST_F(AllocEngine4Test, defaultAlloc4) {
 
     Lease4Ptr lease = engine->allocateLease4(ctx);
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -211,7 +211,7 @@ TEST_F(AllocEngine4Test, hintAlloc4) {
 
     Lease4Ptr lease = engine->allocateLease4(ctx);
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -249,7 +249,7 @@ TEST_F(AllocEngine4Test, minAlloc4) {
 
     Lease4Ptr lease = engine->allocateLease4(ctx);
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -287,7 +287,7 @@ TEST_F(AllocEngine4Test, maxAlloc4) {
 
     Lease4Ptr lease = engine->allocateLease4(ctx);
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -323,7 +323,7 @@ TEST_F(AllocEngine4Test, bootpAlloc4) {
 
     Lease4Ptr lease = engine->allocateLease4(ctx);
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -372,7 +372,7 @@ TEST_F(AllocEngine4Test, fakeAlloc4) {
     Lease4Ptr lease = engine->allocateLease4(ctx);
 
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -391,7 +391,6 @@ TEST_F(AllocEngine4Test, fakeAlloc4) {
     EXPECT_EQ(glbl_cumulative, getStatistics("cumulative-assigned-addresses"));
 }
 
-
 // This test checks if the allocation with a hint that is valid (in range,
 // in pool and free) can succeed
 TEST_F(AllocEngine4Test, allocWithValidHint4) {
@@ -410,7 +409,7 @@ TEST_F(AllocEngine4Test, allocWithValidHint4) {
     ASSERT_TRUE(lease);
 
     // We have allocated the new lease, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // We should get what we asked for
     EXPECT_EQ(lease->addr_.toText(), "192.0.2.105");
@@ -426,7 +425,6 @@ TEST_F(AllocEngine4Test, allocWithValidHint4) {
     detailCompareLease(lease, from_mgr);
 }
 
-
 // This test checks if the allocation with a hint that is in range,
 // in pool, but is currently used can succeed
 TEST_F(AllocEngine4Test, allocWithUsedHint4) {
@@ -454,7 +452,7 @@ TEST_F(AllocEngine4Test, allocWithUsedHint4) {
     Lease4Ptr lease = engine->allocateLease4(ctx);
 
     // New lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -473,7 +471,6 @@ TEST_F(AllocEngine4Test, allocWithUsedHint4) {
     ASSERT_FALSE(from_mgr);
 }
 
-
 // This test checks if an allocation with a hint that is out of the blue
 // can succeed. The invalid hint should be ignored completely.
 TEST_F(AllocEngine4Test, allocBogusHint4) {
@@ -494,7 +491,7 @@ TEST_F(AllocEngine4Test, allocBogusHint4) {
     ASSERT_TRUE(lease);
 
     // We have allocated a new lease, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // We should NOT get what we asked for, because it is used already
     EXPECT_NE("10.1.1.1", lease->addr_.toText());
@@ -516,34 +513,46 @@ TEST_F(AllocEngine4Test, allocateLease4Nulls) {
 
     // Allocations without subnet are not allowed
     AllocEngine::ClientContext4 ctx1(Subnet4Ptr(), clientid_, hwaddr_,
-                                    IOAddress("0.0.0.0"), false, false,
-                                    "", false);
+                                     IOAddress("0.0.0.0"), false, false,
+                                     "", false);
     ctx1.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     Lease4Ptr lease = engine->allocateLease4(ctx1);
 
-    EXPECT_FALSE(lease);
+    ASSERT_FALSE(lease);
+
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-classes"));
 
     // Allocations without HW address are not allowed
     AllocEngine::ClientContext4 ctx2(subnet_, clientid_, HWAddrPtr(),
-                                    IOAddress("0.0.0.0"), false, false,
-                                    "", false);
+                                     IOAddress("0.0.0.0"), false, false,
+                                     "", false);
     ctx2.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     lease = engine->allocateLease4(ctx2);
-    EXPECT_FALSE(lease);
-    EXPECT_FALSE(ctx2.old_lease_);
+    ASSERT_FALSE(lease);
+    ASSERT_FALSE(ctx2.old_lease_);
+
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-classes"));
 
     // Allocations without client-id are allowed
     clientid_.reset();
     AllocEngine::ClientContext4 ctx3(subnet_, ClientIdPtr(), hwaddr_,
-                                    IOAddress("0.0.0.0"), false, false,
-                                    "", false);
+                                     IOAddress("0.0.0.0"), false, false,
+                                     "", false);
     ctx3.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     lease = engine->allocateLease4(ctx3);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
     // New lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx3.old_lease_);
+    ASSERT_FALSE(ctx3.old_lease_);
 
     // Do all checks on the lease
     checkLease4(lease);
@@ -580,7 +589,7 @@ TEST_F(AllocEngine4Test, simpleRenew4) {
     checkLease4(lease);
 
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // We should have incremented assigned-addresses
     EXPECT_TRUE(testStatistics("assigned-addresses", 1, subnet_->getID()));
@@ -629,7 +638,7 @@ TEST_F(AllocEngine4Test, defaultRenew4) {
     EXPECT_EQ(subnet_->getValid(), lease->valid_lft_);
 
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Do it again, this should amount to the renew of an existing lease
     Lease4Ptr lease2 = engine->allocateLease4(ctx);
@@ -671,7 +680,7 @@ TEST_F(AllocEngine4Test, hintRenew4) {
     EXPECT_EQ(opt->getValue(), lease->valid_lft_);
 
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Do it again, this should amount to the renew of an existing lease
     Lease4Ptr lease2 = engine->allocateLease4(ctx);
@@ -714,7 +723,7 @@ TEST_F(AllocEngine4Test, minRenew4) {
     EXPECT_EQ(subnet_->getValid().getMin(), lease->valid_lft_);
 
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Do it again, this should amount to the renew of an existing lease
     Lease4Ptr lease2 = engine->allocateLease4(ctx);
@@ -757,7 +766,7 @@ TEST_F(AllocEngine4Test, maxRenew4) {
     EXPECT_EQ(subnet_->getValid().getMax(), lease->valid_lft_);
 
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Do it again, this should amount to the renew of an existing lease
     Lease4Ptr lease2 = engine->allocateLease4(ctx);
@@ -807,7 +816,7 @@ TEST_F(AllocEngine4Test, bootpRenew4) {
     EXPECT_EQ(infinity_lft, lease->valid_lft_);
 
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Do it again, this should amount to the renew of an existing lease
     Lease4Ptr lease2 = engine->allocateLease4(ctx);
@@ -923,7 +932,6 @@ TEST_F(AllocEngine4Test, IterativeAllocator_manyPools4) {
     }
 }
 
-
 // This test checks if really small pools are working
 TEST_F(AllocEngine4Test, smallPool4) {
     boost::scoped_ptr<AllocEngine> engine;
@@ -953,7 +961,7 @@ TEST_F(AllocEngine4Test, smallPool4) {
     ASSERT_TRUE(lease);
 
     // We have allocated new lease, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     EXPECT_EQ("192.0.2.17", lease->addr_.toText());
 
@@ -1006,8 +1014,14 @@ TEST_F(AllocEngine4Test, outOfAddresses4) {
                                     "host.example.com.", false);
     ctx.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     Lease4Ptr lease2 = engine->allocateLease4(ctx);
-    EXPECT_FALSE(lease2);
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(lease2);
+    ASSERT_FALSE(ctx.old_lease_);
+
+    EXPECT_EQ(1, getStatistics("v4-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-shared-network"));
+    EXPECT_EQ(1, getStatistics("v4-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-classes"));
 }
 
 /// @brief This test class is dedicated to testing shared networks
@@ -1123,7 +1137,6 @@ TEST_F(SharedNetworkAlloc4Test, discoverSharedNetworkHint) {
     EXPECT_TRUE(subnet2_->inPool(Lease::TYPE_V4, lease->addr_));
 }
 
-
 // This test verifies that the server can offer an address from a
 // different subnet than orginally selected, when the address pool in
 // the first subnet is exhausted.
@@ -1178,7 +1191,7 @@ TEST_F(SharedNetworkAlloc4Test, discoverSharedNetwork) {
 TEST_F(SharedNetworkAlloc4Test, discoverSharedNetworkClassification) {
 
     // Try to offer address from subnet1. There is one address available
-    // so it should be offerred.
+    // so it should be offered.
     AllocEngine::ClientContext4
         ctx(subnet1_, ClientIdPtr(), hwaddr_, IOAddress::IPV4_ZERO_ADDRESS(),
             false, false, "host.example.com.", true);
@@ -1201,7 +1214,7 @@ TEST_F(SharedNetworkAlloc4Test, discoverSharedNetworkClassification) {
     EXPECT_TRUE(subnet2_->inPool(Lease::TYPE_V4, lease->addr_));
 
     // Create reservation for the client in subnet1. Because this subnet is
-    // not allowed for the client the client should still be offerred a
+    // not allowed for the client the client should still be offered a
     // lease from subnet2.
     HostPtr host(new Host(&hwaddr_->hwaddr_[0], hwaddr_->hwaddr_.size(),
                           Host::IDENT_HWADDR, subnet1_->getID(),
@@ -1231,7 +1244,7 @@ TEST_F(SharedNetworkAlloc4Test, discoverSharedNetworkClassification) {
 TEST_F(SharedNetworkAlloc4Test, discoverSharedNetworkPoolClassification) {
 
     // Try to offer address from subnet1. There is one address available
-    // so it should be offerred.
+    // so it should be offered.
     AllocEngine::ClientContext4
         ctx(subnet1_, ClientIdPtr(), hwaddr_, IOAddress::IPV4_ZERO_ADDRESS(),
             false, false, "host.example.com.", true);
@@ -1294,7 +1307,7 @@ TEST_F(SharedNetworkAlloc4Test, discoverSharedNetworkReservations) {
     EXPECT_EQ("10.2.3.23", lease->addr_.toText());
 
     // Let's create a lease for the client to make sure the lease is not
-    // renewed but a reserved lease is offerred.
+    // renewed but a reserved lease is offered.
     Lease4Ptr lease2(new Lease4(IOAddress("192.0.2.17"), hwaddr_, ClientIdPtr(),
                                 501, time(NULL), subnet1_->getID()));
     lease->cltt_ = time(NULL) - 10; // Allocated 10 seconds ago
@@ -1337,7 +1350,7 @@ TEST_F(SharedNetworkAlloc4Test, discoverSharedNetworkReservationsNoColl) {
     EXPECT_EQ("10.2.3.23", lease->addr_.toText());
 
     // Let's create a lease for the client to make sure the lease is not
-    // renewed but a reserved lease is offerred.
+    // renewed but a reserved lease is offered.
     Lease4Ptr lease2(new Lease4(IOAddress("192.0.2.17"), hwaddr_, ClientIdPtr(),
                                 501, time(NULL), subnet1_->getID()));
     lease->cltt_ = time(NULL) - 10; // Allocated 10 seconds ago
@@ -1380,7 +1393,13 @@ TEST_F(SharedNetworkAlloc4Test, runningOut) {
 
     // Ok, we're out. We should not get anything now.
     lease = engine_.allocateLease4(ctx);
-    EXPECT_FALSE(lease);
+    ASSERT_FALSE(lease);
+
+    EXPECT_EQ(1, getStatistics("v4-allocation-fail"));
+    EXPECT_EQ(1, getStatistics("v4-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-classes"));
 }
 
 // This test verifies that the server can offer an address from a
@@ -1462,7 +1481,7 @@ TEST_F(SharedNetworkAlloc4Test, requestSharedNetwork) {
 // the first subnet is exhausted.
 TEST_F(SharedNetworkAlloc4Test, requestSharedNetworkClassification) {
     // Try to offer address from subnet1. There is one address available
-    // so it should be offerred.
+    // so it should be offered.
     AllocEngine::ClientContext4
         ctx(subnet1_, ClientIdPtr(), hwaddr_, IOAddress::IPV4_ZERO_ADDRESS(),
             false, false, "host.example.com.", false);
@@ -1515,7 +1534,7 @@ TEST_F(SharedNetworkAlloc4Test, requestSharedNetworkClassification) {
 // the first subnet requires another class.
 TEST_F(SharedNetworkAlloc4Test, requestSharedNetworkPoolClassification) {
     // Try to offer address from subnet1. There is one address available
-    // so it should be offerred.
+    // so it should be offered.
     AllocEngine::ClientContext4
         ctx(subnet1_, ClientIdPtr(), hwaddr_, IOAddress::IPV4_ZERO_ADDRESS(),
             false, false, "host.example.com.", false);
@@ -1693,8 +1712,8 @@ TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
 
     // CASE 1: Asking for any address
     AllocEngine::ClientContext4 ctx1(subnet_, clientid_, hwaddr_,
-                                    IOAddress("0.0.0.0"), false, false,
-                                    "", true);
+                                     IOAddress("0.0.0.0"), false, false,
+                                     "", true);
     ctx1.query_.reset(new Pkt4(DHCPDISCOVER, 1234));
     lease = engine->allocateLease4(ctx1);
     // Check that we got that single lease
@@ -1712,8 +1731,8 @@ TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
 
     // CASE 2: Asking specifically for this address
     AllocEngine::ClientContext4 ctx2(subnet_, clientid_, hwaddr_,
-                                    IOAddress(addr), false, false,
-                                    "", true);
+                                     IOAddress(addr), false, false,
+                                     "", true);
     ctx2.query_.reset(new Pkt4(DHCPDISCOVER, 1234));
     lease = engine->allocateLease4(ctx2);
     // Check that we got that single lease
@@ -2054,6 +2073,12 @@ TEST_F(AllocEngine4Test, requestOtherClientLease) {
     // Allocation engine should return NULL.
     ASSERT_FALSE(new_lease);
 
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-classes"));
+
     // Now simulate the DHCPDISCOVER case when the provided address is
     // treated as a hint. The engine should return a lease for a
     // different address than requested.
@@ -2105,7 +2130,7 @@ TEST_F(AllocEngine4Test, reservedAddressNoHint) {
 
     // Initially, there was no lease for this client, so the returned old
     // lease should be NULL.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 }
 
 // This test checks behavior of the allocation engine in the following scenario:
@@ -2142,7 +2167,7 @@ TEST_F(AllocEngine4Test,reservedAddressNoHintFakeAllocation) {
 
     // Client had no lease in the database, so the old lease returned should
     // be NULL.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 }
 
 // This test checks the behavior of the allocation engine in the following
@@ -2165,8 +2190,8 @@ TEST_F(AllocEngine4Test, reservedAddressHint) {
     AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 0, false);
 
     AllocEngine::ClientContext4 ctx1(subnet_, clientid_, hwaddr_,
-                                    IOAddress("192.0.2.234"), false, false,
-                                    "", false);
+                                     IOAddress("192.0.2.234"), false, false,
+                                     "", false);
     ctx1.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     AllocEngine::findReservation(ctx1);
     Lease4Ptr lease = engine.allocateLease4(ctx1);
@@ -2177,10 +2202,16 @@ TEST_F(AllocEngine4Test, reservedAddressHint) {
     ASSERT_FALSE(lease);
     ASSERT_FALSE(ctx1.old_lease_);
 
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-classes"));
+
     // Now, request a correct address. The client should obtain it.
     AllocEngine::ClientContext4 ctx2(subnet_, clientid_, hwaddr_,
-                                    IOAddress("192.0.2.123"), false, false,
-                                    "", false);
+                                     IOAddress("192.0.2.123"), false, false,
+                                     "", false);
     ctx2.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     AllocEngine::findReservation(ctx2);
     lease = engine.allocateLease4(ctx2);
@@ -2193,7 +2224,7 @@ TEST_F(AllocEngine4Test, reservedAddressHint) {
     ASSERT_TRUE(from_mgr);
     detailCompareLease(lease, from_mgr);
 
-    EXPECT_FALSE(ctx2.old_lease_);
+    ASSERT_FALSE(ctx2.old_lease_);
 }
 
 // This test checks the behavior of the allocation engine in the following
@@ -2230,7 +2261,7 @@ TEST_F(AllocEngine4Test, reservedAddressHintFakeAllocation) {
     // to the lease database.
     EXPECT_FALSE(LeaseMgrFactory::instance().getLease4(lease->addr_));
 
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 }
 
 // This test checks that the behavior of the allocation engine in the following
@@ -2312,15 +2343,21 @@ TEST_F(AllocEngine4Test, reservedAddressHijacked) {
 
     // Try to allocate the reserved lease to client B.
     AllocEngine::ClientContext4 ctx1(subnet_, clientid_, hwaddr_,
-                                    IOAddress("192.0.2.123"), false, false,
-                                    "", false);
+                                     IOAddress("192.0.2.123"), false, false,
+                                     "", false);
     ctx1.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     AllocEngine::findReservation(ctx1);
     Lease4Ptr allocated_lease = engine.allocateLease4(ctx1);
     // The lease is allocated to someone else, so the allocation should not
     // succeed.
     ASSERT_FALSE(allocated_lease);
-    EXPECT_FALSE(ctx1.old_lease_);
+    ASSERT_FALSE(ctx1.old_lease_);
+
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-classes"));
 
     // Make sure that the allocation engine didn't modify the lease of the
     // client A.
@@ -2331,13 +2368,19 @@ TEST_F(AllocEngine4Test, reservedAddressHijacked) {
     // Try doing the same thing, but this time do not request any specific
     // address. It should have the same effect.
     AllocEngine::ClientContext4 ctx2(subnet_, clientid_, hwaddr_,
-                                    IOAddress("0.0.0.0"), false, false,
-                                    "", false);
+                                     IOAddress("0.0.0.0"), false, false,
+                                     "", false);
     ctx2.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     AllocEngine::findReservation(ctx2);
     allocated_lease = engine.allocateLease4(ctx2);
     ASSERT_FALSE(allocated_lease);
-    EXPECT_FALSE(ctx2.old_lease_);
+    ASSERT_FALSE(ctx2.old_lease_);
+
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-classes"));
 
     from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
     ASSERT_TRUE(from_mgr);
@@ -2371,8 +2414,8 @@ TEST_F(AllocEngine4Test, reservedAddressHijackedFakeAllocation) {
     // The allocation engine is not able to allocate the lease to the client
     // B, because the address is in use by client A.
     AllocEngine::ClientContext4 ctx1(subnet_, clientid_, hwaddr_,
-                                    IOAddress("192.0.2.123"), false, false,
-                                    "", true);
+                                     IOAddress("192.0.2.123"), false, false,
+                                     "", true);
     ctx1.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     AllocEngine::findReservation(ctx1);
     Lease4Ptr allocated_lease = engine.allocateLease4(ctx1);
@@ -2380,16 +2423,15 @@ TEST_F(AllocEngine4Test, reservedAddressHijackedFakeAllocation) {
     // The allocation engine should return a lease but for a different address
     // than requested because this address is in use.
     ASSERT_TRUE(allocated_lease);
-    EXPECT_FALSE(ctx1.old_lease_);
+    ASSERT_FALSE(ctx1.old_lease_);
     EXPECT_NE(allocated_lease->addr_.toText(), "192.0.2.123");
     EXPECT_TRUE(subnet_->inPool(Lease::TYPE_V4, allocated_lease->addr_));
 
-
     // Do the same test. But, this time do not specify any address to be
     // allocated.
     AllocEngine::ClientContext4 ctx2(subnet_, clientid_, hwaddr_,
-                                    IOAddress("0.0.0.0"), false, false,
-                                    "", true);
+                                     IOAddress("0.0.0.0"), false, false,
+                                     "", true);
     ctx2.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     AllocEngine::findReservation(ctx2);
     allocated_lease = engine.allocateLease4(ctx2);
@@ -2397,7 +2439,7 @@ TEST_F(AllocEngine4Test, reservedAddressHijackedFakeAllocation) {
     ASSERT_TRUE(allocated_lease);
     EXPECT_NE(allocated_lease->addr_.toText(), "192.0.2.123");
     EXPECT_TRUE(subnet_->inPool(Lease::TYPE_V4, allocated_lease->addr_));
-    EXPECT_FALSE(ctx2.old_lease_);
+    ASSERT_FALSE(ctx2.old_lease_);
 }
 
 // This test checks that the behavior of the allocation engine in the following
@@ -2430,19 +2472,25 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseInvalidHint) {
     // Try to allocate a lease and specify a different address than reserved
     // and different from the one that client is currently using.
     AllocEngine::ClientContext4 ctx1(subnet_, clientid_, hwaddr_,
-                                    IOAddress("192.0.2.102"), false, false,
-                                    "", false);
+                                     IOAddress("192.0.2.102"), false, false,
+                                     "", false);
     ctx1.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     AllocEngine::findReservation(ctx1);
     Lease4Ptr allocated_lease = engine.allocateLease4(ctx1);
     ASSERT_FALSE(allocated_lease);
     ASSERT_FALSE(ctx1.old_lease_);
 
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-classes"));
+
     // Repeat the test, but this time ask for the address that the client
     // has allocated.
     AllocEngine::ClientContext4 ctx2(subnet_, clientid_, hwaddr_,
-                                    IOAddress("192.0.2.101"), false, false,
-                                    "", false);
+                                     IOAddress("192.0.2.101"), false, false,
+                                     "", false);
     ctx2.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     AllocEngine::findReservation(ctx2);
     allocated_lease = engine.allocateLease4(ctx2);
@@ -2453,8 +2501,14 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseInvalidHint) {
     // for this client. The server doesn't allow for the renewal and
     // responds with DHCPNAK to force the client to return to the
     // DHCP server discovery.
-    EXPECT_FALSE(allocated_lease);
-    EXPECT_FALSE(ctx2.old_lease_);
+    ASSERT_FALSE(allocated_lease);
+    ASSERT_FALSE(ctx2.old_lease_);
+
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-classes"));
 }
 
 // This test checks that the behavior of the allocation engine in the following
@@ -2486,8 +2540,8 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseFakeAllocation) {
     // Try to allocate a lease and use a completely different address
     // as a hint.
     AllocEngine::ClientContext4 ctx1(subnet_, clientid_, hwaddr_,
-                                    IOAddress("192.0.2.102"), false, false,
-                                    "", true);
+                                     IOAddress("192.0.2.102"), false, false,
+                                     "", true);
     ctx1.query_.reset(new Pkt4(DHCPDISCOVER, 1234));
     AllocEngine::findReservation(ctx1);
     Lease4Ptr allocated_lease = engine.allocateLease4(ctx1);
@@ -2506,8 +2560,8 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseFakeAllocation) {
     // Repeat the test but this time ask for the address for which the
     // client has a lease.
     AllocEngine::ClientContext4 ctx2(subnet_, clientid_, hwaddr_,
-                                    IOAddress("192.0.2.101"), false, false,
-                                    "", true);
+                                     IOAddress("192.0.2.101"), false, false,
+                                     "", true);
     ctx2.query_.reset(new Pkt4(DHCPDISCOVER, 1234));
     AllocEngine::findReservation(ctx2);
     allocated_lease = engine.allocateLease4(ctx2);
@@ -2622,8 +2676,6 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseNoHintFakeAllocation) {
     Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
     ASSERT_TRUE(from_mgr);
     detailCompareLease(lease, from_mgr);
-
-
 }
 
 // This test checks that the behavior of the allocation engine in the following
@@ -2664,36 +2716,46 @@ TEST_F(AllocEngine4Test, reservedAddressConflictResolution) {
 
     AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 0, false);
 
-
     // Client B sends a DHCPREQUEST to allocate a reserved lease. The
     // allocation engine can't allocate a reserved lease for this client
     // because this specific address is in use by the Client A.
     AllocEngine::ClientContext4 ctx1(subnet_, ClientIdPtr(), hwaddr2_,
-                                    IOAddress("192.0.2.101"), false, false,
-                                    "", false);
+                                     IOAddress("192.0.2.101"), false, false,
+                                     "", false);
     ctx1.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     AllocEngine::findReservation(ctx1);
     Lease4Ptr offered_lease = engine.allocateLease4(ctx1);
     ASSERT_FALSE(offered_lease);
 
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-classes"));
+
     // Client A tries to renew the lease. The renewal should fail because
     // server detects that Client A doesn't have reservation for this
     // address.
     AllocEngine::ClientContext4 ctx2(subnet_, clientid_, hwaddr_,
-                                    IOAddress("192.0.2.101"), false, false,
-                                    "", false);
+                                     IOAddress("192.0.2.101"), false, false,
+                                     "", false);
     ctx2.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     AllocEngine::findReservation(ctx2);
     ASSERT_FALSE(engine.allocateLease4(ctx2));
-
     ASSERT_FALSE(ctx2.old_lease_);
 
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-classes"));
+
     // Client A returns to DHCPDISCOVER and should be offered a lease.
     // The offered lease address must be different than the one the
     // Client B has reservation for.
     AllocEngine::ClientContext4 ctx3(subnet_, clientid_, hwaddr_,
-                                    IOAddress("192.0.2.101"), false, false,
-                                    "", true);
+                                     IOAddress("192.0.2.101"), false, false,
+                                     "", true);
     ctx3.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     AllocEngine::findReservation(ctx3);
     offered_lease = engine.allocateLease4(ctx3);
@@ -2704,8 +2766,8 @@ TEST_F(AllocEngine4Test, reservedAddressConflictResolution) {
     // the previous lease should be released and become available for the
     // Client B.
     AllocEngine::ClientContext4 ctx4(subnet_, clientid_, hwaddr_,
-                                    offered_lease->addr_, false, false,
-                                    "", false);
+                                     offered_lease->addr_, false, false,
+                                     "", false);
     ctx4.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     AllocEngine::findReservation(ctx4);
     Lease4Ptr allocated_lease = engine.allocateLease4(ctx4);
@@ -2717,7 +2779,7 @@ TEST_F(AllocEngine4Test, reservedAddressConflictResolution) {
     // a reserved lease.
     AllocEngine::ClientContext4 ctx5(subnet_, ClientIdPtr(), hwaddr2_,
                                      IOAddress("0.0.0.0"), false, false,
-                                    "", true);
+                                     "", true);
     ctx5.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     AllocEngine::findReservation(ctx5);
     offered_lease = engine.allocateLease4(ctx5);
@@ -2728,7 +2790,7 @@ TEST_F(AllocEngine4Test, reservedAddressConflictResolution) {
     // Client B requests allocation of the lease and it should succeed.
     AllocEngine::ClientContext4 ctx6(subnet_, ClientIdPtr(), hwaddr2_,
                                      offered_lease->addr_, false, false,
-                                    "", false);
+                                     "", false);
     ctx6.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     allocated_lease = engine.allocateLease4(ctx6);
 
@@ -2753,7 +2815,7 @@ TEST_F(AllocEngine4Test, reservedAddressVsDynamicPool) {
     // dynamic pool, i.e. 192.0.2.100. This address is reserved so we expect
     // that a different address will be allocated.
     AllocEngine::ClientContext4 ctx(subnet_, ClientIdPtr(), hwaddr_,
-                                     IOAddress("0.0.0.0"), false, false,
+                                    IOAddress("0.0.0.0"), false, false,
                                     "", false);
     ctx.query_.reset(new Pkt4(DHCPREQUEST, 1234));
     AllocEngine::findReservation(ctx);
@@ -2791,6 +2853,12 @@ TEST_F(AllocEngine4Test, reservedAddressHintUsedByOtherClient) {
     // The client should get no lease (DHCPNAK).
     ASSERT_FALSE(allocated_lease);
 
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-classes"));
+
     // The same client should get a different lease than requested if
     // if is sending a DHCPDISCOVER (fake allocation is true).
     AllocEngine::ClientContext4 ctx2(subnet_, ClientIdPtr(), hwaddr_,
@@ -2829,7 +2897,13 @@ TEST_F(AllocEngine4Test, reservedAddressShortPool) {
     AllocEngine::findReservation(ctx1);
     Lease4Ptr allocated_lease = engine.allocateLease4(ctx1);
 
-    EXPECT_FALSE(allocated_lease);
+    ASSERT_FALSE(allocated_lease);
+
+    EXPECT_EQ(1, getStatistics("v4-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-shared-network"));
+    EXPECT_EQ(1, getStatistics("v4-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v4-allocation-fail-classes"));
 
     // Now, let's remove the reservation.
     initSubnet(IOAddress("192.0.2.100"), IOAddress("192.0.2.100"));
@@ -2977,7 +3051,7 @@ TEST_F(AllocEngine4Test, simpleAlloc4Stats) {
 
     Lease4Ptr lease = engine->allocateLease4(ctx);
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -3017,7 +3091,7 @@ TEST_F(AllocEngine4Test, fakeAlloc4Stat) {
     Lease4Ptr lease = engine->allocateLease4(ctx);
 
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -3134,7 +3208,7 @@ TEST_F(AllocEngine4Test, globalReservationReservedAddressDiscover) {
 
     // Client had no lease in the database, so the old lease returned should
     // be NULL.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 }
 
 // This test checks the behavior of the allocation engine in the following
@@ -3185,7 +3259,7 @@ TEST_F(AllocEngine4Test, globalReservationReservedAddressRequest) {
 
     // Client had no lease in the database, so the old lease returned should
     // be NULL.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 }
 
 // This test checks the behavior of the allocation engine in the following
@@ -3234,7 +3308,7 @@ TEST_F(AllocEngine4Test, globalReservationDynamicDiscover) {
 
     // Client had no lease in the database, so the old lease returned should
     // be NULL.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 }
 
 // This test checks the behavior of the allocation engine in the following
@@ -3286,7 +3360,7 @@ TEST_F(AllocEngine4Test, globalReservationDynamicRequest) {
 
     // Client had no lease in the database, so the old lease returned should
     // be NULL.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 }
 
 // This test checks the behavior of the allocation engine in the following
@@ -3336,7 +3410,7 @@ TEST_F(AllocEngine4Test, mixedReservationReservedAddressDiscover) {
 
     // Client had no lease in the database, so the old lease returned should
     // be NULL.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 }
 
 // This test checks the behavior of the allocation engine in the following
@@ -3389,7 +3463,7 @@ TEST_F(AllocEngine4Test, mixedReservationReservedAddressRequest) {
 
     // Client had no lease in the database, so the old lease returned should
     // be NULL.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 }
 
 // This test checks the behavior of the allocation engine in the following
@@ -3443,7 +3517,7 @@ TEST_F(AllocEngine4Test, bothReservationReservedAddressDiscover) {
 
     // Client had no lease in the database, so the old lease returned should
     // be NULL.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 }
 
 // This test checks the behavior of the allocation engine in the following
@@ -3500,10 +3574,9 @@ TEST_F(AllocEngine4Test, bothReservationReservedAddressRequest) {
 
     // Client had no lease in the database, so the old lease returned should
     // be NULL.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 }
 
-
 // Exercises AllocEnginer4Test::updateExtendedInfo4() through various
 // permutations of client packet content.
 TEST_F(AllocEngine4Test, updateExtendedInfo4) {
@@ -3565,8 +3638,6 @@ TEST_F(AllocEngine4Test, updateExtendedInfo4) {
     // Create the allocation engine, context and lease.
     NakedAllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 0, false);
 
-
-
     AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
                                     IOAddress::IPV4_ZERO_ADDRESS(),
                                     false, false, "", true);
@@ -4442,7 +4513,7 @@ TEST_F(AllocEngine4Test, bootpDelete) {
 
     Lease4Ptr lease = engine->allocateLease4(ctx);
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -4509,7 +4580,7 @@ TEST_F(MySqlAllocEngine4Test, bootpAlloc4) {
 
     Lease4Ptr lease = engine->allocateLease4(ctx);
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -4571,7 +4642,7 @@ TEST_F(MySqlAllocEngine4Test, bootpRenew4) {
     EXPECT_EQ(infinity_lft, lease->valid_lft_);
 
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Do it again, this should amount to the renew of an existing lease
     Lease4Ptr lease2 = engine->allocateLease4(ctx);
@@ -4612,7 +4683,7 @@ TEST_F(MySqlAllocEngine4Test, bootpDelete) {
 
     Lease4Ptr lease = engine->allocateLease4(ctx);
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -4680,7 +4751,7 @@ TEST_F(PgSqlAllocEngine4Test, bootpAlloc4) {
 
     Lease4Ptr lease = engine->allocateLease4(ctx);
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -4742,7 +4813,7 @@ TEST_F(PgSqlAllocEngine4Test, bootpRenew4) {
     EXPECT_EQ(infinity_lft, lease->valid_lft_);
 
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Do it again, this should amount to the renew of an existing lease
     Lease4Ptr lease2 = engine->allocateLease4(ctx);
@@ -4783,7 +4854,7 @@ TEST_F(PgSqlAllocEngine4Test, bootpDelete) {
 
     Lease4Ptr lease = engine->allocateLease4(ctx);
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -4851,7 +4922,7 @@ TEST_F(CqlAllocEngine4Test, bootpAlloc4) {
 
     Lease4Ptr lease = engine->allocateLease4(ctx);
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -4913,7 +4984,7 @@ TEST_F(CqlAllocEngine4Test, bootpRenew4) {
     EXPECT_EQ(infinity_lft, lease->valid_lft_);
 
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Do it again, this should amount to the renew of an existing lease
     Lease4Ptr lease2 = engine->allocateLease4(ctx);
@@ -4954,7 +5025,7 @@ TEST_F(CqlAllocEngine4Test, bootpDelete) {
 
     Lease4Ptr lease = engine->allocateLease4(ctx);
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(ctx.old_lease_);
+    ASSERT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
index 746ecbcffb8f2b4e8b832b27535626e5cffc5a24..7fee55b8f3bc6a463c7fa89d1d99463664a1dd39 100644 (file)
@@ -264,14 +264,25 @@ TEST_F(AllocEngine6Test, allocateAddress6Nulls) {
     EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx1)));
     ASSERT_FALSE(lease);
 
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-classes"));
+
     // Allocations without DUID are not allowed either
     AllocEngine::ClientContext6 ctx2(subnet_, DuidPtr(), false, false, "", false,
                                      Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234)));
     ctx2.currentIA().iaid_ = iaid_;
     EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx2)));
     ASSERT_FALSE(lease);
-}
 
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-classes"));
+}
 
 // This test verifies that the allocator picks addresses that belong to the
 // pool
@@ -890,11 +901,15 @@ TEST_F(AllocEngine6Test, outOfAddresses6) {
 
     Lease6Ptr lease2;
     EXPECT_NO_THROW(lease2 = expectOneLease(engine->allocateLeases6(ctx)));
-    EXPECT_FALSE(lease2);
+    ASSERT_FALSE(lease2);
 
+    EXPECT_EQ(1, getStatistics("v6-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-shared-network"));
+    EXPECT_EQ(1, getStatistics("v6-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-classes"));
 }
 
-
 // This test checks if an expired lease can be reused in SOLICIT (fake allocation)
 TEST_F(AllocEngine6Test, solicitReuseExpiredLease6) {
     boost::scoped_ptr<AllocEngine> engine;
@@ -938,6 +953,7 @@ TEST_F(AllocEngine6Test, solicitReuseExpiredLease6) {
     ctx1.currentIA().iaid_ = iaid_;
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx1)));
+
     // Check that we got that single lease
     ASSERT_TRUE(lease);
     EXPECT_EQ(addr, lease->addr_);
@@ -1206,6 +1222,8 @@ TEST_F(AllocEngine6Test, requestReuseExpiredLease6) {
 
     // Check that the old lease has been returned.
     Lease6Ptr old_lease = expectOneLease(ctx.currentIA().old_leases_);
+    ASSERT_TRUE(old_lease);
+
     // It should at least have the same IPv6 address.
     EXPECT_EQ(lease->addr_, old_lease->addr_);
     // Check that it carries not updated FQDN data.
@@ -2125,7 +2143,7 @@ TEST_F(AllocEngine6Test, reservedAddress) {
 
     // The default pool is 2001:db8:1::10 to 2001:db8:1::20. There's 17
     // addresses in it. One of them is reserved, so this means that we should
-    // get 16 successes and 14 (20-16) failures.
+    // get 16 successes and 14 (30-16) failures.
     int success = 0;
     int failure = 0;
     for (int i = 0; i < 30; i++) {
@@ -2139,6 +2157,11 @@ TEST_F(AllocEngine6Test, reservedAddress) {
         if (leases.empty()) {
             failure++;
             std::cout << "Alloc for client " << (int)i << " failed." << std::endl;
+            EXPECT_EQ(failure, getStatistics("v6-allocation-fail"));
+            EXPECT_EQ(0, getStatistics("v6-allocation-fail-shared-network"));
+            EXPECT_EQ(failure, getStatistics("v6-allocation-fail-subnet"));
+            EXPECT_EQ(0, getStatistics("v6-allocation-fail-no-pools"));
+            EXPECT_EQ(0, getStatistics("v6-allocation-fail-classes"));
         } else {
             success++;
             std::cout << "Alloc for client " << (int)i << " succeeded:"
@@ -2181,7 +2204,13 @@ TEST_F(AllocEngine6Test, allocateLeasesInvalidData) {
 
     // Subnet is required for allocation, so we should get no leases.
     EXPECT_NO_THROW(leases = engine.allocateLeases6(ctx));
-    EXPECT_TRUE(leases.empty());
+    ASSERT_TRUE(leases.empty());
+
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-classes"));
 
     // Let's fix this and break it in a different way.
     ctx.subnet_ = subnet_;
@@ -2189,8 +2218,13 @@ TEST_F(AllocEngine6Test, allocateLeasesInvalidData) {
 
     // We must know who we're allocating for. No duid = no service.
     EXPECT_NO_THROW(leases = engine.allocateLeases6(ctx));
-    EXPECT_TRUE(leases.empty());
+    ASSERT_TRUE(leases.empty());
 
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-classes"));
 }
 
 // Checks whether an address can be renewed (simple case, no reservation tricks)
@@ -2519,7 +2553,6 @@ TEST_F(AllocEngine6Test, reservedAddressByMacInPoolRequestNoHint) {
     EXPECT_EQ("2001:db8:1::1c", lease->addr_.toText());
 }
 
-
 // Checks that a client gets the address reserved (in-pool case)
 // This test checks the behavior of the allocation engine in the following
 // scenario:
@@ -2655,7 +2688,13 @@ TEST_F(AllocEngine6Test, largeAllocationAttemptsOverride) {
     AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 3);
     Lease6Collection leases = allocateTest(engine, pool_, IOAddress("::"),
                                            false, true);
-    ASSERT_EQ(0, leases.size());
+    ASSERT_TRUE(leases.empty());
+
+    EXPECT_EQ(1, getStatistics("v6-allocation-fail"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-shared-network"));
+    EXPECT_EQ(1, getStatistics("v6-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-classes"));
 
     // This time, lets allow more attempts, and expect that the allocation will
     // be successful.
@@ -2828,7 +2867,6 @@ TEST_F(AllocEngine6Test, requestReuseDeclinedLease6Stats) {
     EXPECT_TRUE(testStatistics("reclaimed-declined-addresses", 1));
     EXPECT_TRUE(testStatistics("declined-addresses", -1, subnet_->getID()));
     EXPECT_TRUE(testStatistics("reclaimed-declined-addresses", 1, subnet_->getID()));
-
 }
 
 // This test checks if an expired-reclaimed lease can be reused by
@@ -2979,7 +3017,6 @@ TEST_F(SharedNetworkAlloc6Test, solicitSharedNetworkSimple) {
     ASSERT_TRUE(subnet1_->inRange(lease->addr_));
 }
 
-
 // This test verifies that the server can pick a subnet from shared subnets
 // based on hints.
 TEST_F(SharedNetworkAlloc6Test, solicitSharedNetworkHint) {
@@ -3002,7 +3039,7 @@ TEST_F(SharedNetworkAlloc6Test, solicitSharedNetworkHint) {
     ASSERT_TRUE(subnet2_->inRange(lease->addr_));
 }
 
-// This test verifies that the client is offerred an address from an
+// This test verifies that the client is offered an address from an
 // alternative subnet within shared network when the address pool is
 // exhausted in the first address pool.
 TEST_F(SharedNetworkAlloc6Test, solicitSharedNetworkOutOfAddresses) {
@@ -3032,7 +3069,7 @@ TEST_F(SharedNetworkAlloc6Test, solicitSharedNetworkOutOfAddresses) {
     ASSERT_TRUE(lease2);
     ASSERT_TRUE(subnet2_->inRange(lease2->addr_));
 
-    // The client having a lease should be offerred this lease, even if
+    // The client having a lease should be offered this lease, even if
     // the client starts allocation from the second subnet. The code should
     // determine that the client has a lease in subnet1 and use this subnet
     // instead.
@@ -3060,7 +3097,7 @@ TEST_F(SharedNetworkAlloc6Test, solicitSharedNetworkOutOfAddresses) {
 // the first subnet is exhausted.
 TEST_F(SharedNetworkAlloc6Test, solicitSharedNetworkClassification) {
     // Try to offer address from subnet1. There is an address available so
-    // it should be offerred.
+    // it should be offered.
     Pkt6Ptr query(new Pkt6(DHCPV6_SOLICIT, 1234));
     AllocEngine::ClientContext6 ctx(subnet1_, duid_, false, false, "", true,
                                     query);
@@ -3122,7 +3159,7 @@ TEST_F(SharedNetworkAlloc6Test, solicitSharedNetworkClassification) {
 // the first subnet requires another class.
 TEST_F(SharedNetworkAlloc6Test, solicitSharedNetworkPoolClassification) {
     // Try to offer address from subnet1. There is an address available so
-    // it should be offerred.
+    // it should be offered.
     Pkt6Ptr query(new Pkt6(DHCPV6_SOLICIT, 1234));
     AllocEngine::ClientContext6 ctx(subnet1_, duid_, false, false, "", true,
                                     query);
@@ -3173,7 +3210,7 @@ TEST_F(SharedNetworkAlloc6Test, solicitSharedNetworkPoolClassification) {
     EXPECT_EQ("2001:db8:1::1", lease->addr_.toText());
 }
 
-// This test verifies that the client is offerred a reserved address
+// This test verifies that the client is offered a reserved address
 // even if this address belongs to another subnet within the same
 // shared network.
 TEST_F(SharedNetworkAlloc6Test, solicitSharedNetworkReservations) {
@@ -3200,7 +3237,7 @@ TEST_F(SharedNetworkAlloc6Test, solicitSharedNetworkReservations) {
     ASSERT_EQ("2001:db8:2::15", lease->addr_.toText());
 }
 
-// This test verifies that the client is offerred a reserved address
+// This test verifies that the client is offered a reserved address
 // even if this address belongs to another subnet within the same
 // shared network. Host lookups returning a collection are disabled.
 // As it is only an optimization the behavior (so the test) must stay
@@ -3387,7 +3424,13 @@ TEST_F(SharedNetworkAlloc6Test, requestRunningOut) {
     Lease6Collection leases = engine_.allocateLeases6(ctx2);
 
     // Bugger off, we're full!
-    EXPECT_TRUE(leases.empty());
+    ASSERT_TRUE(leases.empty());
+
+    EXPECT_EQ(1, getStatistics("v6-allocation-fail"));
+    EXPECT_EQ(1, getStatistics("v6-allocation-fail-shared-network"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-subnet"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-no-pools"));
+    EXPECT_EQ(0, getStatistics("v6-allocation-fail-classes"));
 }
 
 // Verifies that client with a hostname reservation can
@@ -4005,7 +4048,6 @@ public:
     IOAddress duid2_addr_;
 };
 
-
 // Exercises AllocEnginer6Test::updateExtendedInfo6() through various
 // permutations of client packet content.
 TEST_F(AllocEngine6ExtendedInfoTest, updateExtendedInfo6) {
@@ -4395,6 +4437,7 @@ TEST_F(AllocEngine6Test, solicitNoCache) {
     ctx.currentIA().addHint(addr);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(addr, lease->addr_);
     EXPECT_EQ(128, lease->prefixlen_);
 
@@ -4436,6 +4479,7 @@ TEST_F(AllocEngine6Test, requestCacheThreshold6) {
     ctx.currentIA().addHint(addr);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(addr, lease->addr_);
     EXPECT_EQ(128, lease->prefixlen_);
 
@@ -4488,6 +4532,7 @@ TEST_F(AllocEngine6Test, renewCacheThreshold6) {
     ctx.currentIA().addHint(prefix, prefixlen);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->renewLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(prefix, lease->addr_);
     EXPECT_EQ(prefixlen, lease->prefixlen_);
 
@@ -4537,6 +4582,7 @@ TEST_F(AllocEngine6Test, requestCacheMaxAge6) {
     ctx.currentIA().addHint(addr);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(addr, lease->addr_);
     EXPECT_EQ(128, lease->prefixlen_);
 
@@ -4589,6 +4635,7 @@ TEST_F(AllocEngine6Test, renewCacheMaxAge6) {
     ctx.currentIA().addHint(prefix, prefixlen);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->renewLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(prefix, lease->addr_);
     EXPECT_EQ(prefixlen, lease->prefixlen_);
 
@@ -4642,6 +4689,7 @@ TEST_F(AllocEngine6Test, requestCacheBoth6) {
     ctx.currentIA().addHint(addr);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(addr, lease->addr_);
     EXPECT_EQ(128, lease->prefixlen_);
 
@@ -4698,6 +4746,7 @@ TEST_F(AllocEngine6Test, renewCacheBoth6) {
     ctx.currentIA().addHint(prefix, prefixlen);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->renewLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(prefix, lease->addr_);
     EXPECT_EQ(prefixlen, lease->prefixlen_);
 
@@ -4749,6 +4798,7 @@ TEST_F(AllocEngine6Test, requestCacheBadThreshold6) {
     ctx.currentIA().addHint(addr);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(addr, lease->addr_);
     EXPECT_EQ(128, lease->prefixlen_);
 
@@ -4795,6 +4845,7 @@ TEST_F(AllocEngine6Test, renewCacheBadThreshold6) {
     ctx.currentIA().addHint(prefix, prefixlen);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->renewLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(prefix, lease->addr_);
     EXPECT_EQ(prefixlen, lease->prefixlen_);
 
@@ -4838,6 +4889,7 @@ TEST_F(AllocEngine6Test, requestCacheBadMaxAge6) {
     ctx.currentIA().addHint(addr);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(addr, lease->addr_);
     EXPECT_EQ(128, lease->prefixlen_);
 
@@ -4884,6 +4936,7 @@ TEST_F(AllocEngine6Test, renewCacheBadMaxAge6) {
     ctx.currentIA().addHint(prefix, prefixlen);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->renewLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(prefix, lease->addr_);
     EXPECT_EQ(prefixlen, lease->prefixlen_);
 
@@ -4928,6 +4981,7 @@ TEST_F(AllocEngine6Test, renewCacheReducedValid6) {
     ctx.currentIA().addHint(addr);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->renewLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(addr, lease->addr_);
     EXPECT_EQ(128, lease->prefixlen_);
 
@@ -4975,6 +5029,7 @@ TEST_F(AllocEngine6Test, renewCacheReducedPreferred6) {
     ctx.currentIA().addHint(prefix, prefixlen);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->renewLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(prefix, lease->addr_);
     EXPECT_EQ(prefixlen, lease->prefixlen_);
 
@@ -5014,6 +5069,7 @@ TEST_F(AllocEngine6Test, requestCacheFwdDDNS6) {
     ctx.currentIA().addHint(addr);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(addr, lease->addr_);
     EXPECT_EQ(128, lease->prefixlen_);
 
@@ -5056,6 +5112,7 @@ TEST_F(AllocEngine6Test, renewCacheFwdDDNS6) {
     ctx.currentIA().addHint(prefix, prefixlen);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->renewLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(prefix, lease->addr_);
     EXPECT_EQ(prefixlen, lease->prefixlen_);
 
@@ -5095,6 +5152,7 @@ TEST_F(AllocEngine6Test, requestCacheRevDDNS6) {
     ctx.currentIA().addHint(addr);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(addr, lease->addr_);
     EXPECT_EQ(128, lease->prefixlen_);
 
@@ -5137,6 +5195,7 @@ TEST_F(AllocEngine6Test, renewCacheRevDDNS6) {
     ctx.currentIA().addHint(prefix, prefixlen);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->renewLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(prefix, lease->addr_);
     EXPECT_EQ(prefixlen, lease->prefixlen_);
 
@@ -5177,6 +5236,7 @@ TEST_F(AllocEngine6Test, requestCacheHostname6) {
     ctx.currentIA().addHint(addr);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(addr, lease->addr_);
     EXPECT_EQ(128, lease->prefixlen_);
 
@@ -5221,6 +5281,7 @@ TEST_F(AllocEngine6Test, renewCacheHostname6) {
     ctx.currentIA().addHint(prefix, prefixlen);
 
     EXPECT_NO_THROW(lease = expectOneLease(engine->renewLeases6(ctx)));
+    ASSERT_TRUE(lease);
     EXPECT_EQ(prefix, lease->addr_);
     EXPECT_EQ(prefixlen, lease->prefixlen_);