summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcpsrv/tests/resource_handler_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/dhcpsrv/tests/resource_handler_unittest.cc')
-rw-r--r--src/lib/dhcpsrv/tests/resource_handler_unittest.cc509
1 files changed, 509 insertions, 0 deletions
diff --git a/src/lib/dhcpsrv/tests/resource_handler_unittest.cc b/src/lib/dhcpsrv/tests/resource_handler_unittest.cc
new file mode 100644
index 0000000..41f4d69
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/resource_handler_unittest.cc
@@ -0,0 +1,509 @@
+// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+#include <dhcpsrv/resource_handler.h>
+#include <gtest/gtest.h>
+
+using namespace isc;
+using namespace isc::asiolink;
+using namespace isc::dhcp;
+
+namespace {
+
+// Verifies behavior with empty block.
+TEST(ResourceHandleTest, empty) {
+ try {
+ // Get a resource handler.
+ ResourceHandler resource_handler;
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies behavior with empty block (v4).
+TEST(ResourceHandleTest, empty4) {
+ try {
+ // Get a resource handler.
+ ResourceHandler4 resource_handler;
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies behavior with one handler.
+TEST(ResourceHandleTest, one) {
+ IOAddress addr("2001:db8::1");
+
+ try {
+ // Get a resource handler.
+ ResourceHandler resource_handler;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock(Lease::TYPE_NA, addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies behavior with one IPv4 handler.
+TEST(ResourceHandleTest, one4) {
+ IOAddress addr("192.0.2.1");
+
+ try {
+ // Get a resource handler.
+ ResourceHandler4 resource_handler;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock4(addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies behavior with two handlers.
+TEST(ResourceHandleTest, two) {
+ IOAddress addr("2001:db8::");
+
+ try {
+ // Get a resource handler.
+ ResourceHandler resource_handler;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock(Lease::TYPE_PD, addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+
+ // Get a second resource handler.
+ ResourceHandler resource_handler2;
+
+ // Try to lock it.
+ EXPECT_NO_THROW(busy = !resource_handler2.tryLock(Lease::TYPE_PD, addr));
+
+ // Should return true (busy);
+ EXPECT_TRUE(busy);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies behavior with two IPv4 handlers.
+TEST(ResourceHandleTest, two4) {
+ IOAddress addr("192.0.2.1");
+
+ try {
+ // Get a resource handler.
+ ResourceHandler4 resource_handler;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock4(addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+
+ // Get a second resource handler.
+ ResourceHandler4 resource_handler2;
+
+ // Try to lock it.
+ EXPECT_NO_THROW(busy = !resource_handler2.tryLock4(addr));
+
+ // Should return true (busy);
+ EXPECT_TRUE(busy);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies behavior with two handlers in different blocks (sequence).
+TEST(ResourceHandleTest, sequence) {
+ IOAddress addr("2001:db8::1");
+
+ try {
+ // Get a resource handler.
+ ResourceHandler resource_handler;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock(Lease::TYPE_NA, addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+
+ try {
+ // Get a second resource handler.
+ ResourceHandler resource_handler2;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler2.tryLock(Lease::TYPE_NA, addr));
+
+ // Should return false (free)
+ EXPECT_FALSE(busy);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies behavior with two IPv4 handlers in different blocks (sequence).
+TEST(ResourceHandleTest, sequence4) {
+ IOAddress addr("192.0.2.1");
+
+ try {
+ // Get a resource handler.
+ ResourceHandler4 resource_handler;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock4(addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+
+ try {
+ // Get a second resource handler.
+ ResourceHandler4 resource_handler2;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler2.tryLock4(addr));
+
+ // Should return false (free)
+ EXPECT_FALSE(busy);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies behavior with two handlers for different addresses.
+TEST(ResourceHandleTest, differentAddress) {
+ IOAddress addr("2001:db8::1");
+ IOAddress addr2("2001:db8::2");
+
+ try {
+ // Get a resource handler.
+ ResourceHandler resource_handler;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock(Lease::TYPE_NA, addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+
+ // Get a second resource handler.
+ ResourceHandler resource_handler2;
+
+ // Try to lock it.
+ EXPECT_NO_THROW(busy = !resource_handler2.tryLock(Lease::TYPE_NA, addr2));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies behavior with two IPv4 handlers for different addresses.
+TEST(ResourceHandleTest, differentAddress4) {
+ IOAddress addr("192.0.2.1");
+ IOAddress addr2("192.0.2.2");
+
+ try {
+ // Get a resource handler.
+ ResourceHandler4 resource_handler;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock4(addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+
+ // Get a second resource handler.
+ ResourceHandler4 resource_handler2;
+
+ // Try to lock it.
+ EXPECT_NO_THROW(busy = !resource_handler2.tryLock4(addr2));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies behavior with two handlers for different types.
+TEST(ResourceHandleTest, differentTypes) {
+ IOAddress addr("2001:db8::");
+
+ try {
+ // Get a resource handler.
+ ResourceHandler resource_handler;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock(Lease::TYPE_NA, addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+
+ // Get a second resource handler.
+ ResourceHandler resource_handler2;
+
+ // Try to lock it.
+ EXPECT_NO_THROW(busy = !resource_handler2.tryLock(Lease::TYPE_PD, addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies behavior of the isLocked predicate.
+TEST(ResourceHandleTest, isLocked) {
+ IOAddress addr("2001:db8::1");
+ IOAddress addr2("2001:db8::2");
+ IOAddress addr3("2001:db8::3");
+
+ try {
+ // Get a resource handler.
+ ResourceHandler resource_handler;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock(Lease::TYPE_NA, addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+
+ // Get a second resource handler.
+ ResourceHandler resource_handler2;
+
+ // Try to lock it.
+ EXPECT_NO_THROW(busy = !resource_handler2.tryLock(Lease::TYPE_NA, addr2));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+
+ // Check ownership.
+ EXPECT_TRUE(resource_handler.isLocked(Lease::TYPE_NA, addr));
+ EXPECT_FALSE(resource_handler.isLocked(Lease::TYPE_NA, addr2));
+ EXPECT_FALSE(resource_handler.isLocked(Lease::TYPE_NA, addr3));
+ EXPECT_FALSE(resource_handler.isLocked(Lease::TYPE_PD, addr));
+ EXPECT_FALSE(resource_handler2.isLocked(Lease::TYPE_NA, addr));
+ EXPECT_TRUE(resource_handler2.isLocked(Lease::TYPE_NA, addr2));
+ EXPECT_FALSE(resource_handler2.isLocked(Lease::TYPE_NA, addr3));
+ EXPECT_FALSE(resource_handler2.isLocked(Lease::TYPE_PD, addr2));
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies behavior with two IPv4 handlers.
+TEST(ResourceHandleTest, isLocked4) {
+ IOAddress addr("192.0.2.1");
+ IOAddress addr2("192.0.2.2");
+ IOAddress addr3("192.0.2.3");
+
+ try {
+ // Get a resource handler.
+ ResourceHandler4 resource_handler;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock4(addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+
+ // Get a second resource handler.
+ ResourceHandler4 resource_handler2;
+
+ // Try to lock it.
+ EXPECT_NO_THROW(busy = !resource_handler2.tryLock4(addr2));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+
+ // Check ownership.
+ EXPECT_TRUE(resource_handler.isLocked4(addr));
+ EXPECT_FALSE(resource_handler.isLocked4(addr2));
+ EXPECT_FALSE(resource_handler.isLocked4(addr3));
+ EXPECT_FALSE(resource_handler2.isLocked4(addr));
+ EXPECT_TRUE(resource_handler2.isLocked4(addr2));
+ EXPECT_FALSE(resource_handler2.isLocked4(addr3));
+
+ // ResourceHandler4 derives from ResourceHandler.
+ EXPECT_FALSE(resource_handler.isLocked(Lease::TYPE_NA, addr));
+ EXPECT_FALSE(resource_handler2.isLocked(Lease::TYPE_NA, addr2));
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies that double tryLock call for the same resource returns busy.
+TEST(ResourceHandleTest, doubleTryLock) {
+ IOAddress addr("2001:db8::");
+
+ try {
+ // Get a resource handler.
+ ResourceHandler resource_handler;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock(Lease::TYPE_PD, addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+
+ // Try to lock it again.
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock(Lease::TYPE_PD, addr));
+
+ // Should return true (busy);
+ EXPECT_TRUE(busy);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies that double tryLock call for the same resource returns busy (v4).
+TEST(ResourceHandleTest, doubleTryLock4) {
+ IOAddress addr("192.0.2.1");
+
+ try {
+ // Get a resource handler.
+ ResourceHandler4 resource_handler;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock4(addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+
+ // Try to lock it again.
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock4(addr));
+
+ // Should return true (busy);
+ EXPECT_TRUE(busy);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies behavior of the unLock method.
+TEST(ResourceHandleTest, unLock) {
+ IOAddress addr("2001:db8::1");
+
+ try {
+ // Get a resource handler.
+ ResourceHandler resource_handler;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock(Lease::TYPE_NA, addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+
+ // The resource is owned by us.
+ EXPECT_TRUE(resource_handler.isLocked(Lease::TYPE_NA, addr));
+
+ // Try to unlock it.
+ EXPECT_NO_THROW(resource_handler.unLock(Lease::TYPE_NA, addr));
+
+ // The resource is no longer owned by us.
+ EXPECT_FALSE(resource_handler.isLocked(Lease::TYPE_NA, addr));
+
+ // Get a second resource handler.
+ ResourceHandler resource_handler2;
+
+ // Try to lock it by the second handler.
+ EXPECT_NO_THROW(busy = !resource_handler2.tryLock(Lease::TYPE_NA, addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+
+ // The resource is owned by the second handler.
+ EXPECT_FALSE(resource_handler.isLocked(Lease::TYPE_NA, addr));
+ EXPECT_TRUE(resource_handler2.isLocked(Lease::TYPE_NA, addr));
+
+ // Only the owner is allowed to release a resource.
+ EXPECT_THROW(resource_handler.unLock(Lease::TYPE_NA, addr), NotFound);
+ EXPECT_NO_THROW(resource_handler2.unLock(Lease::TYPE_NA, addr));
+ // Once.
+ EXPECT_THROW(resource_handler2.unLock(Lease::TYPE_NA, addr), NotFound);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+// Verifies behavior of the unLock method.
+TEST(ResourceHandleTest, unLock4) {
+ IOAddress addr("192.0.2.1");
+
+ try {
+ // Get a resource handler.
+ ResourceHandler4 resource_handler;
+
+ // Try to lock it.
+ bool busy = false;
+ EXPECT_NO_THROW(busy = !resource_handler.tryLock4(addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+
+ // The resource is owned by us.
+ EXPECT_TRUE(resource_handler.isLocked4(addr));
+
+ // Try to unlock it.
+ EXPECT_NO_THROW(resource_handler.unLock4(addr));
+
+ // The resource is no longer owned by us.
+ EXPECT_FALSE(resource_handler.isLocked4(addr));
+
+ // Get a second resource handler
+ ResourceHandler4 resource_handler2;
+
+ // Try to lock it by the second handler.
+ EXPECT_NO_THROW(busy = !resource_handler2.tryLock4(addr));
+
+ // Should return false (free).
+ EXPECT_FALSE(busy);
+
+ // The resource is owned by the second handler.
+ EXPECT_FALSE(resource_handler.isLocked4(addr));
+ EXPECT_TRUE(resource_handler2.isLocked4(addr));
+
+ // Only the owner is allowed to release a resource.
+ EXPECT_THROW(resource_handler.unLock4(addr), NotFound);
+ EXPECT_NO_THROW(resource_handler2.unLock4(addr));
+ // Once.
+ EXPECT_THROW(resource_handler2.unLock4(addr), NotFound);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "unexpected exception: " << ex.what();
+ }
+}
+
+} // end of anonymous namespace