// Also pass the corresponding query packet as argument
callout_handle->setArgument("query4", query);
+ // Also pass the corresponding response packet as argument
+ ScopedEnableOptionsCopy<Pkt4> response4_options_copy(rsp);
+ callout_handle->setArgument("response4", rsp);
+
Lease4CollectionPtr new_leases(new Lease4Collection());
// Filter out the new lease if it was reused so not committed.
if (ctx->new_lease_ && (ctx->new_lease_->reuseable_valid_lft_ == 0)) {
// Check if all expected parameters were really received
vector<string> expected_argument_names;
expected_argument_names.push_back("query4");
+ expected_argument_names.push_back("response4");
expected_argument_names.push_back("deleted_leases4");
expected_argument_names.push_back("leases4");
// Check if all expected parameters were really received
vector<string> expected_argument_names;
expected_argument_names.push_back("query4");
+ expected_argument_names.push_back("response4");
expected_argument_names.push_back("deleted_leases4");
expected_argument_names.push_back("leases4");
// Check if all expected parameters were really received
vector<string> expected_argument_names;
expected_argument_names.push_back("query4");
+ expected_argument_names.push_back("response4");
expected_argument_names.push_back("deleted_leases4");
expected_argument_names.push_back("leases4");
// Check if all expected parameters were really received
vector<string> expected_argument_names;
expected_argument_names.push_back("query4");
+ expected_argument_names.push_back("response4");
expected_argument_names.push_back("deleted_leases4");
expected_argument_names.push_back("leases4");
// Check if all expected parameters were really received
vector<string> expected_argument_names;
expected_argument_names.push_back("query4");
+ expected_argument_names.push_back("response4");
expected_argument_names.push_back("deleted_leases4");
expected_argument_names.push_back("leases4");
// Check if all expected parameters were really received
vector<string> expected_argument_names;
expected_argument_names.push_back("query4");
+ expected_argument_names.push_back("response4");
expected_argument_names.push_back("leases4");
expected_argument_names.push_back("offer_lifetime");
expected_argument_names.push_back("old_lease");
// Check if all expected parameters were really received
vector<string> expected_argument_names;
expected_argument_names.push_back("query4");
+ expected_argument_names.push_back("response4");
expected_argument_names.push_back("leases4");
expected_argument_names.push_back("offer_lifetime");
expected_argument_names.push_back("old_lease");
// Check if all expected parameters were really received
vector<string> expected_argument_names;
expected_argument_names.push_back("query4");
+ expected_argument_names.push_back("response4");
expected_argument_names.push_back("leases4");
expected_argument_names.push_back("offer_lifetime");
expected_argument_names.push_back("old_lease");
return (isc->get("relay-info"));
}
- /// @brief leases4-committed hookpoint handler.
+ /// @brief lease4_offer hookpoint handler.
+ ///
+ /// If the offer_lifetime argument is zero, it simply returns. Otherwise
+ /// it evaluates the binding variables (if any), and updates the given lease's
+ /// user-context accordingly. This includes updating the lease in the lease
+ /// back end.
+ ///
+ /// @param handle Callout context - which is expected to contain the query4,
+ /// response4, leases4, offer_lifetime arguments.
+ /// @param mgr Pointer to the BindingVariableMgr singleton.
+ /// @throw Unexpected if there is no active lease or a processing error
+ /// occurs. LeaseCmdsConflict if the update fails because the lease
+ /// no longer exists in the back end.
+ static void lease4Offer(CalloutHandle& callout_handle,
+ BindingVariableMgrPtr mgr);
+
+ /// @brief leases4_committed hookpoint handler.
///
/// Evaluates the binding variables (if any), and updates the given lease's
/// user-context accordingly. This includes updating the lease in the lease
/// back end.
///
- /// @param handle Callout context - which is expected to contain the query4, response4,
- /// and leases4 argumeents.
+ /// @param handle Callout context - which is expected to contain the query4,
+ /// response4, and leases4 arguments.
/// @param mgr Pointer to the BindingVariableMgr singleton.
- /// @throw
- static void leases4Committed(CalloutHandle& callout_handle,
+ /// @throw Unexpected if there is no active lease or a processing error
+ /// occurs. LeaseCmdsConflict if the update fails because the lease
+ /// no longer exists in the back end.
+ static void leases4Committed(CalloutHandle& callout_handle,
BindingVariableMgrPtr mgr);
};
return (0);
}
+void
+LeaseCmdsImpl::lease4Offer(CalloutHandle& callout_handle,
+ BindingVariableMgrPtr mgr) {
+ uint32_t offer_lifetime;
+ callout_handle.getArgument("offer_lifetime", offer_lifetime);
+ if (!offer_lifetime) {
+ // Offers leases are not being persisted, nothing to do.
+ return;
+ }
+
+ // Get the remaining arguments we need.
+ Pkt4Ptr query;
+ Pkt4Ptr response;
+ Lease4CollectionPtr leases;
+
+ callout_handle.getArgument("query4", query);
+ callout_handle.getArgument("response4", response);
+ callout_handle.getArgument("leases4", leases);
+
+ if (leases->empty()) {
+ isc_throw(Unexpected, "lease4Offer - no lease!");
+ }
+
+ Lease4Ptr lease = (*leases)[0];
+ try {
+ if (mgr->evaluateVariables(query, response, lease)) {
+ LeaseMgrFactory::instance().updateLease4(lease);
+ }
+ } catch (const NoSuchLease&) {
+ isc_throw(LeaseCmdsConflict, "failed to update"
+ " the lease with address " << lease->addr_ <<
+ " either because the lease has been"
+ " deleted or it has changed in the database");
+ } catch (const std::exception& ex) {
+ isc_throw(Unexpected, "evaluating binding variables failed for: "
+ << query->getLabel() << ", :" << ex.what());
+ }
+}
+
void
LeaseCmdsImpl::leases4Committed(CalloutHandle& callout_handle,
BindingVariableMgrPtr mgr) {
callout_handle.getArgument("response4", response);
callout_handle.getArgument("leases4", leases);
- // In some cases we may have no leases, e.g. DHCPNAK.
- if (leases->empty()) {
- LOG_DEBUG(lease_cmds_logger, DBGLVL_TRACE_BASIC,
- LEASE_CMDS_LEASES4_COMMITTED_NOTHING_TO_UPDATE)
- .arg(query->getLabel());
+ // In some cases we may have no lease, e.g. DHCPNAK,
+ // or no response e.g. DHCPRELEASE.
+ if (leases->empty() || !response || (response->getType() != DHCPACK)) {
return;
}
}
} catch (const NoSuchLease&) {
isc_throw(LeaseCmdsConflict, "failed to update"
- " the lease with address " << lease->addr_ <<
+ " the lease with address " << lease->addr_ <<
" either because the lease has been"
" deleted or it has changed in the database");
} catch (const std::exception& ex) {
- isc_throw(Unexpected, "evaluating binding variables failed for "
+ isc_throw(Unexpected, "evaluating binding variables failed for: "
<< query->getLabel() << ", :" << ex.what());
}
}
}
+void
+LeaseCmds::lease4Offer(CalloutHandle& callout_handle,
+ BindingVariableMgrPtr mgr) {
+ impl_->lease4Offer(callout_handle, mgr);
+}
+
void
LeaseCmds::leases4Committed(CalloutHandle& callout_handle,
BindingVariableMgrPtr mgr) {
int
leaseWriteHandler(hooks::CalloutHandle& handle);
+ /// @brief lease4_offer hookpoint handler.
+ ///
+ /// If the offer_lifetime callout argument is 0 the handler simply returns.
+ /// Otherwise it will evaluate the binding variables (if any) and update
+ /// the given lease's user-context accordingly. This includes updating the
+ /// lease in the lease back end.
+ ///
+ /// @param handle Callout context - which is expected to contain the query4, response4,
+ /// leases4 arguments, and offer_lifetime.
+ /// @param mgr Pointer to the BindingVariableMgr singleton.
+ void
+ lease4Offer(hooks::CalloutHandle& callout_handle,
+ BindingVariableMgrPtr mgr);
+
/// @brief leases4_committed hookpoint handler.
///
/// Evaluates the binding variables (if any), and updates the given lease's
/// back end.
///
/// @param handle Callout context - which is expected to contain the query4, response4,
- /// and leases4 argumeents.
+ /// and leases4 arguments.
/// @param mgr Pointer to the BindingVariableMgr singleton.
- void
- leases4Committed(hooks::CalloutHandle& callout_handle,
+ void
+ leases4Committed(hooks::CalloutHandle& callout_handle,
BindingVariableMgrPtr mgr);
private:
return (1);
}
+/// @brief lease4_offer callout implementation.
+///
+/// @param handle callout handle.
+int lease4_offer(CalloutHandle& handle) {
+ CalloutHandle::CalloutNextStep status = handle.getStatus();
+ if (status == CalloutHandle::NEXT_STEP_DROP ||
+ status == CalloutHandle::NEXT_STEP_SKIP) {
+ return (0);
+ }
+
+ try {
+ LeaseCmds lease_cmds;
+ lease_cmds.lease4Offer(handle, binding_var_mgr);
+ } catch (const std::exception& ex) {
+ LOG_ERROR(lease_cmds_logger, LEASE_CMDS_LEASE4_OFFER_FAILED)
+ .arg(ex.what());
+ return (1);
+ }
+
+ return (0);
+}
+
/// @brief leases4_committed callout implementation.
///
/// @param handle callout handle.
extern const isc::log::MessageID LEASE_CMDS_GET4_FAILED = "LEASE_CMDS_GET4_FAILED";
extern const isc::log::MessageID LEASE_CMDS_GET6_FAILED = "LEASE_CMDS_GET6_FAILED";
extern const isc::log::MessageID LEASE_CMDS_INIT_OK = "LEASE_CMDS_INIT_OK";
+extern const isc::log::MessageID LEASE_CMDS_LEASE4_OFFER_FAILED = "LEASE_CMDS_LEASE4_OFFER_FAILED";
extern const isc::log::MessageID LEASE_CMDS_LEASES4_COMMITTED_FAILED = "LEASE_CMDS_LEASES4_COMMITTED_FAILED";
-extern const isc::log::MessageID LEASE_CMDS_LEASES4_COMMITTED_NOTHING_TO_UPDATE = "LEASE_CMDS_LEASES4_COMMITTED_NOTHING_TO_UPDATE";
extern const isc::log::MessageID LEASE_CMDS_RESEND_DDNS4 = "LEASE_CMDS_RESEND_DDNS4";
extern const isc::log::MessageID LEASE_CMDS_RESEND_DDNS4_FAILED = "LEASE_CMDS_RESEND_DDNS4_FAILED";
extern const isc::log::MessageID LEASE_CMDS_RESEND_DDNS6 = "LEASE_CMDS_RESEND_DDNS6";
"LEASE_CMDS_GET4_FAILED", "lease4-get command failed (parameters: %1, reason: %2)",
"LEASE_CMDS_GET6_FAILED", "lease6-get command failed (parameters: %1, reason: %2)",
"LEASE_CMDS_INIT_OK", "loading Lease Commands hooks library successful",
- "LEASE_CMDS_LEASES4_COMMITTED_FAILED", "processing error occured evaluating binding variables for %1, %2",
- "LEASE_CMDS_LEASES4_COMMITTED_NOTHING_TO_UPDATE", "query %1, has no active lease.",
+ "LEASE_CMDS_LEASE4_OFFER_FAILED", "processing error occurred evaluating binding variables for %1, %2",
+ "LEASE_CMDS_LEASES4_COMMITTED_FAILED", "processing error occurred evaluating binding variables for %1, %2",
"LEASE_CMDS_RESEND_DDNS4", "lease4-resend-ddns command successful: %1",
"LEASE_CMDS_RESEND_DDNS4_FAILED", "lease4-resend-ddns command failed: %1",
"LEASE_CMDS_RESEND_DDNS6", "lease6-resend-ddns command successful: %1",
extern const isc::log::MessageID LEASE_CMDS_GET4_FAILED;
extern const isc::log::MessageID LEASE_CMDS_GET6_FAILED;
extern const isc::log::MessageID LEASE_CMDS_INIT_OK;
+extern const isc::log::MessageID LEASE_CMDS_LEASE4_OFFER_FAILED;
extern const isc::log::MessageID LEASE_CMDS_LEASES4_COMMITTED_FAILED;
-extern const isc::log::MessageID LEASE_CMDS_LEASES4_COMMITTED_NOTHING_TO_UPDATE;
extern const isc::log::MessageID LEASE_CMDS_RESEND_DDNS4;
extern const isc::log::MessageID LEASE_CMDS_RESEND_DDNS4_FAILED;
extern const isc::log::MessageID LEASE_CMDS_RESEND_DDNS6;
The lease6-wipe command has failed. Both the reason as well as the
parameters passed are logged.
-% LEASE_CMDS_LEASES4_COMMITTED_NOTHING_TO_UPDATE query %1, has no active lease.
-This debug log is emitted when the leaes4-committed handler is invoked and
-there is no active lease associated with the query.
+% LEASE_CMDS_LEASE4_OFFER_FAILED processing error occurred evaluating binding variables for %1, %2
+This debug log is emitted when an error occurs in the lease4_offer
+handler is invoked. The arguments detail the query and the error. This
+error means binding-variable values were not added/updated for the lease.
-% LEASE_CMDS_LEASES4_COMMITTED_FAILED processing error occured evaluating binding variables for %1, %2
-This debug log is emitted when an error occurs in the leaes4-committed
-handler is invoked. The arguemntes detail the query and the error. This
+% LEASE_CMDS_LEASES4_COMMITTED_FAILED processing error occurred evaluating binding variables for %1, %2
+This debug log is emitted when an error occurs in the leases4_committed
+handler is invoked. The arguments detail the query and the error. This
error means binding-variable values were not added/updated for the lease.
unloadLibraries();
}
+ /// @brief Registers hooks in the hook manager.
+ ///
+ /// Normally this is done by the server core code.
+ void registerHooks() {
+ if (isc::dhcp::CfgMgr::instance().getFamily() == AF_INET) {
+ hook_index_lease4_offer_ = HooksManager::registerHook("lease4_offer");
+ hook_index_leasesX_committed_ = HooksManager::registerHook("leases4_committed");
+ } else {
+ hook_index_leasesX_committed_ = HooksManager::registerHook("leases6_committed");
+ }
+ }
+
+ /// @brief Checks that expected callouts are present.
+ void calloutsPresent() {
+ bool result;
+ ASSERT_NO_THROW_LOG(result = HooksManager::calloutsPresent(hook_index_lease4_offer_));
+ EXPECT_EQ(result, (isc::dhcp::CfgMgr::instance().getFamily() == AF_INET));
+
+ /// @todo when v6 is ready, change to always expect true.
+ ASSERT_NO_THROW_LOG(result = HooksManager::calloutsPresent(hook_index_leasesX_committed_));
+ EXPECT_EQ(result, (isc::dhcp::CfgMgr::instance().getFamily() == AF_INET));
+ }
+
/// @brief Creates a set of configuration parameters valid for the library.
/// Note the expressions are protocol agnostic for simplicity.
virtual isc::data::ElementPtr validConfigParams() {
// Convert JSON texts to Element map.
return (Element::fromJSON(valid_config));
}
+
+ /// @brief Hook index values.
+ int hook_index_lease4_offer_;
+ int hook_index_leasesX_committed_;
};
// Simple V4 test that checks the library can be loaded and unloaded several times.
invalidDaemonTest("bogus");
}
+// Verifies that callout functions exist after loading the library.
+TEST_F(LeaseCmdsCbLibLoadTest, verifyCallouts4) {
+ // Set family and daemon's proc name and register hook points.
+ isc::dhcp::CfgMgr::instance().setFamily(AF_INET);
+ isc::process::Daemon::setProcName("kea-dhcp4");
+ registerHooks();
+
+ // Add library to config and load it.
+ ASSERT_NO_THROW_LOG(addLibrary(lib_so_name_, valid_params_));
+ ASSERT_NO_THROW_LOG(loadLibraries());
+
+ // Verify that expected callouts are present.
+ calloutsPresent();
+
+ // Unload the library.
+ ASSERT_NO_THROW_LOG(unloadLibraries());
+}
+
+// Verifies that callout functions exist after loading the library.
+TEST_F(LeaseCmdsCbLibLoadTest, verifyCallouts6) {
+ // Set family and daemon's proc name and register hook points.
+ isc::dhcp::CfgMgr::instance().setFamily(AF_INET6);
+ isc::process::Daemon::setProcName("kea-dhcp6");
+ registerHooks();
+
+ // Add library to config and load it.
+ ASSERT_NO_THROW_LOG(addLibrary(lib_so_name_, valid_params_));
+ ASSERT_NO_THROW_LOG(loadLibraries());
+
+ // Verify that expected callouts are present.
+ calloutsPresent();
+
+ // Unload the library.
+ ASSERT_NO_THROW_LOG(unloadLibraries());
+}
+
} // end of anonymous namespace
/// @brief Check that lease4-write works as expected.
void testLease4Write();
- /// @brief Check that lease4-committed handler works as expected with
+ /// @brief Check that lease4_offer handler works as expected with
+ /// valid inputs.
+ void testValidLease4Offer();
+
+ /// @brief Check that leases4_committed handler works as expected with
/// valid inputs.
void testValidLeases4Committed();
+
+ /// @brief Check that leases4_committed handler does not throw or alter
+ /// the lease under NOP conditions:
+ /// 1. There is no repsonse packet
+ /// 2. Response packet is a DHCPACK
+ /// 3. There is no active lease
+ void testNopLeases4Committed();
};
void Lease4CmdsTest::testLease4AddMissingParams() {
ss << "Scenario at line: " << line; \
SCOPED_TRACE(ss.str());
-void Lease4CmdsTest::testValidLeases4Committed() {
+void
+Lease4CmdsTest::testValidLease4Offer() {
// Initialize lease manager (false = v4, true = add leases)
initLeaseMgr(false, true);
std::string config_;
std::string orig_context_;
std::string exp_context_;
+ uint32_t offer_lifetime_;
};
std::list<Scenario> scenarios = {
__LINE__,
R"({})",
R"({})",
- R"({})"
- },{
+ R"({})",
+ 500
+ },
+ {
// lease context has no binding-variables, two configured
__LINE__,
R"^({"binding-variables":[
"yiaddr": "192.0.2.1"
}
}})",
+ 500
+ },
+ {
+ // lease context has no binding-variables, two configured
+ // offer lifetime is 0.
+ __LINE__,
+ R"^({"binding-variables":[
+ {
+ "name": "hwaddr",
+ "expression": "hexstring(pkt4.mac,':')",
+ "source": "query"
+ },
+ {
+ "name": "yiaddr",
+ "expression": "addrtotext(pkt4.yiaddr)",
+ "source": "response"
+ }]})^",
+ R"({})",
+ R"({})",
+ 0
},
{
// lease context has binding-variables, none configured
"yiaddr": "192.0.2.1"
}
}})",
+ 500
},
{
// Evaluated variable value is an empty string.
"hwaddr": ""
}
}})",
+ 500
}};
// Create packet pair and lease.
IOAddress yiaddr("192.0.2.1");
response->setYiaddr(yiaddr);
+ // Iterater over scenarios.
+ for (auto const& scenario : scenarios) {
+ SCOPED_LINE(scenario.line_);
+
+ // Create and configure the manager.
+ BindingVariableMgrPtr mgr;
+ ASSERT_NO_THROW_LOG(mgr.reset(new BindingVariableMgr(AF_INET)));
+ ConstElementPtr config;
+ ASSERT_NO_THROW_LOG(config = Element::fromJSON(scenario.config_));
+ ASSERT_NO_THROW_LOG(mgr->configure(config));
+
+ // Fetch the lease and set its user-context to the original content.
+ Lease4Ptr orig_lease = lmptr_->getLease4(yiaddr);
+ ASSERT_TRUE(orig_lease);
+ ConstElementPtr orig_context;
+ ASSERT_NO_THROW_LOG(orig_context = Element::fromJSON(scenario.orig_context_));
+ orig_lease->setContext(orig_context);
+ ASSERT_NO_THROW_LOG(lmptr_->updateLease4(orig_lease));
+
+ Lease4CollectionPtr leases(new Lease4Collection());
+ leases->push_back(orig_lease);
+
+ // Create a callout handle and add the expected arguments.
+ CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
+ callout_handle->setArgument("query4", query);
+ callout_handle->setArgument("response4", response);
+ callout_handle->setArgument("leases4", leases);
+ callout_handle->setArgument("offer_lifetime", scenario.offer_lifetime_);
+
+ // Invoke the leases4Committed handler.
+ LeaseCmds cmds;
+ ASSERT_NO_THROW_LOG(cmds.lease4Offer(*callout_handle, mgr));
+
+ // Fetch the lease.
+ Lease4Ptr after_lease = lmptr_->getLease4(yiaddr);
+ ASSERT_TRUE(after_lease);
+
+ // Context contents should match the expected context content.
+ ConstElementPtr exp_context;
+ ASSERT_NO_THROW_LOG(exp_context = Element::fromJSON(scenario.exp_context_));
+ ASSERT_EQ(*(after_lease->getContext()), *exp_context);
+ }
+}
+
+void
+Lease4CmdsTest::testValidLeases4Committed() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ struct Scenario {
+ uint32_t line_;
+ std::string config_;
+ std::string orig_context_;
+ std::string exp_context_;
+ };
+
+ std::list<Scenario> scenarios = {
+ {
+ // No variables configured, nothing in lease context.
+ __LINE__,
+ R"({})",
+ R"({})",
+ R"({})"
+ },
+ {
+ // lease context has no binding-variables, two configured
+ __LINE__,
+ R"^({"binding-variables":[
+ {
+ "name": "hwaddr",
+ "expression": "hexstring(pkt4.mac,':')",
+ "source": "query"
+ },
+ {
+ "name": "yiaddr",
+ "expression": "addrtotext(pkt4.yiaddr)",
+ "source": "response"
+ }]})^",
+ R"({})",
+ R"({"ISC":{
+ "binding-variables":{
+ "hwaddr": "01:02:03:04:05:06",
+ "yiaddr": "192.0.2.1"
+ }
+ }})",
+ },
+ {
+ // lease context has binding-variables, none configured
+ // Current logic leaves lease untouched.
+ __LINE__,
+ R"({})",
+ R"({"ISC":{
+ "binding-variables":{
+ "hwaddr": "01:02:03:04:05:06",
+ "yiaddr": "192.0.2.1"
+ }
+ }})",
+ R"({"ISC":{
+ "binding-variables":{
+ "hwaddr": "01:02:03:04:05:06",
+ "yiaddr": "192.0.2.1"
+ }
+ }})",
+ },
+ {
+ // Evaluated variable value is an empty string.
+ __LINE__,
+ R"^({"binding-variables":[
+ {
+ "name": "hwaddr",
+ "expression": "''",
+ "source": "query"
+ }]})^",
+ R"({"ISC":{
+ "binding-variables":{
+ "hwaddr": "01:02:03:04:05:06"
+ }
+ }})",
+ R"({"ISC":{
+ "binding-variables":{
+ "hwaddr": ""
+ }
+ }})",
+ }};
+
+ // Create packet pair and lease.
+ Pkt4Ptr query(new Pkt4(DHCPREQUEST, 1234));
+ query->setHWAddr(1, 6, { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 });
+
+ Pkt4Ptr response(new Pkt4(DHCPACK, 1234));
+ IOAddress yiaddr("192.0.2.1");
+ response->setYiaddr(yiaddr);
+
// Iterater over scenarios.
for (auto const& scenario : scenarios) {
SCOPED_LINE(scenario.line_);
}
}
+void
+Lease4CmdsTest::testNopLeases4Committed() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ struct Scenario {
+ uint32_t line_;
+ DHCPMessageType response_type_;
+ bool send_lease_;
+ };
+
+ // Configure a single variable.
+ std::string config =
+ R"^({"binding-variables":[
+ {
+ "name": "hwaddr",
+ "expression": "hexstring(pkt4.mac,':')",
+ "source": "query"
+ }]})^";
+
+ // Create and configure the manager.
+ BindingVariableMgrPtr mgr;
+ ASSERT_NO_THROW_LOG(mgr.reset(new BindingVariableMgr(AF_INET)));
+ ASSERT_NO_THROW_LOG(mgr->configure(Element::fromJSON(config)));
+
+ // Scenarios should all result in no change to the lease.
+ std::list<Scenario> scenarios = {
+ {
+ // Response is not a DHCPACK.
+ __LINE__,
+ DHCPNAK,
+ true
+ },
+ {
+ // No active lease.
+ __LINE__,
+ DHCPACK,
+ false
+ },
+ {
+ // No response.
+ __LINE__,
+ DHCP_NOTYPE,
+ false
+ }};
+
+ // Create packet pair and lease.
+ Pkt4Ptr query(new Pkt4(DHCPREQUEST, 1234));
+ query->setHWAddr(1, 6, { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 });
+ IOAddress yiaddr("192.0.2.1");
+ for (auto const& scenario : scenarios) {
+ SCOPED_LINE(scenario.line_);
+
+ Pkt4Ptr response;
+ if (scenario.response_type_ != DHCP_NOTYPE) {
+ response.reset(new Pkt4(scenario.response_type_, 1234));
+ }
+
+ // Fetch the lease and set its user-context to the original content.
+ Lease4Ptr orig_lease = lmptr_->getLease4(yiaddr);
+ ASSERT_TRUE(orig_lease);
+ ASSERT_FALSE(orig_lease->getContext());
+
+ Lease4CollectionPtr leases(new Lease4Collection());
+ if (scenario.send_lease_) {
+ leases->push_back(orig_lease);
+ }
+
+ // Create a callout handle and add the expected arguments.
+ CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
+ callout_handle->setArgument("query4", query);
+ callout_handle->setArgument("response4", response);
+ callout_handle->setArgument("leases4", leases);
+
+ // Invoke the leases4Committed handler.
+ LeaseCmds cmds;
+ ASSERT_NO_THROW_LOG(cmds.leases4Committed(*callout_handle, mgr));
+
+ // Fetch the lease. Context should still be empty.
+ Lease4Ptr after_lease = lmptr_->getLease4(yiaddr);
+ ASSERT_TRUE(after_lease);
+ ASSERT_FALSE(after_lease->getContext());
+ }
+}
+
TEST_F(Lease4CmdsTest, lease4AddMissingParams) {
testLease4AddMissingParams();
}
testLease4Write();
}
+TEST_F(Lease4CmdsTest, validLease4Offer) {
+ testValidLease4Offer();
+}
+
+TEST_F(Lease4CmdsTest, validLease4OfferMultiThreading) {
+ MultiThreadingTest mt(true);
+ testValidLease4Offer();
+}
+
TEST_F(Lease4CmdsTest, validLeases4Committed) {
testValidLeases4Committed();
}
testValidLeases4Committed();
}
+TEST_F(Lease4CmdsTest, nopLeases4Committed) {
+ testNopLeases4Committed();
+}
+
+TEST_F(Lease4CmdsTest, nopLeases4CommittedMultiThreading) {
+ MultiThreadingTest mt(true);
+ testNopLeases4Committed();
+}
} // end of anonymous namespace