# Include common libraries being used by shell-based tests.
SHLIBS = dhcp_test_lib.sh.in
-EXTRA_DIST = portconfig.h socket_request.h $(SHLIBS)
+EXTRA_DIST = $(SHLIBS)
CLEANFILES = dhcp_test_lib.sh
+++ /dev/null
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#ifndef ISC_TESTUTILS_PORTCONFIG_H
-#define ISC_TESTUTILS_PORTCONFIG_H
-
-#include <gtest/gtest.h>
-#include <cc/data.h>
-#include <server_common/portconfig.h>
-
-namespace isc {
-namespace testutils {
-/**
- * \brief Bits of tests for server port configuration.
- *
- * These are bits of tests that can be reused by server classes to check if
- * configuration of the listening addresses work.
- *
- * You can put any of these functions into a TEST_F test and pass the server
- * to it.
- *
- * \todo There's quite a lot of common code in the basic server handling.
- * We should refactor it, so both Resolver server and Auth server have
- * a common base class. When this is done, the common parts would be put
- * there and the tests would be at the base class, not here.
- */
-namespace portconfig {
-
-/**
- * \brief Check setting of the listening addresses directly (as a list) works.
- *
- * \param server The server to test against.
- */
-template<class Server>
-void
-listenAddresses(Server& server) {
- using namespace isc::server_common::portconfig;
- // In this test we assume the address list is originally empty.
- EXPECT_TRUE(server.getListenAddresses().empty());
-
- // Try putting there some addresses
- AddressList addresses;
- addresses.push_back(AddressPair("127.0.0.1", 53210));
- addresses.push_back(AddressPair("::1", 53210));
- server.setListenAddresses(addresses);
- EXPECT_EQ(2, server.getListenAddresses().size());
- EXPECT_EQ("::1", server.getListenAddresses()[1].first);
-
- // Is it independent from what we do with the vector later?
- addresses.clear();
- EXPECT_EQ(2, server.getListenAddresses().size());
-
- // If we set to an empty list next, the server configuration should
- // become empty, too.
- server.setListenAddresses(addresses);
- EXPECT_TRUE(server.getListenAddresses().empty());
-}
-
-/**
- * \brief Check setting of the addresses by config value.
- *
- * This passes an listen_on element to the server's updateConfig function.
- * It tries little bit of switching around. It tries both setting a presumably
- * valid addresses and then setting something that cant be bound, rolling back
- * back to original.
- *
- * \param server The server object to test against.
- */
-template<class Server>
-void
-listenAddressConfig(Server& server) {
- using namespace isc::data;
- // Try putting there some address
- ElementPtr config(Element::fromJSON("{"
- "\"listen_on\": ["
- " {"
- " \"address\": \"127.0.0.1\","
- " \"port\": 53210"
- " }"
- "]"
- "}"));
- ConstElementPtr result(server.updateConfig(config));
- EXPECT_EQ(result->toWire(), isc::config::createAnswer()->toWire());
- ASSERT_EQ(1, server.getListenAddresses().size());
- EXPECT_EQ("127.0.0.1", server.getListenAddresses()[0].first);
- EXPECT_EQ(53210, server.getListenAddresses()[0].second);
-
- // This address is rejected by the test socket requestor
- config = Element::fromJSON("{"
- "\"listen_on\": ["
- " {"
- " \"address\": \"192.0.2.2\","
- " \"port\": 53210"
- " }"
- "]"
- "}");
- result = server.updateConfig(config);
- EXPECT_FALSE(result->equals(*isc::config::createAnswer()));
- ASSERT_EQ(1, server.getListenAddresses().size());
- EXPECT_EQ("127.0.0.1", server.getListenAddresses()[0].first);
- EXPECT_EQ(53210, server.getListenAddresses()[0].second);
-
-}
-
-/**
- * \brief Check that given config is rejected.
- *
- * Try if given config is considered invalid by the server and is rejected.
- * The value is converted from JSON to the data elements and passed to server's
- * updateConfig method. It should not crash, but return a negative answer.
- *
- * It is used internally by invalidListenAddressConfig, but you can use it
- * to test any other invalid configs.
- *
- * \todo It might be better to put it to some other namespace, as this is more
- * generic. But right now it is used only here, so until something else
- * needs it, it might as well stay here.
- * \param server The server to test against.
- * \param JSON Config to use.
- * \param name It is used in the output if the test fails.
- */
-template<class Server>
-void
-configRejected(Server& server, const std::string& JSON,
- const std::string& name)
-{
- SCOPED_TRACE(name);
-
- using namespace isc::data;
- ElementPtr config(Element::fromJSON(JSON));
- EXPECT_FALSE(server.updateConfig(config)->
- equals(*isc::config::createAnswer())) <<
- "Accepted invalid config " << JSON;
-}
-
-/**
- * \brief Check some invalid address configs.
- *
- * It tries a series of invalid listen_on configs against the server and checks
- * it is rejected.
- * \param server The server to check against.
- */
-template<class Server>
-void
-invalidListenAddressConfig(Server& server) {
- configRejected(server, "{"
- "\"listen_on\": \"error\""
- "}", "Wrong element type");
- configRejected(server, "{"
- "\"listen_on\": [{}]"
- "}", "Empty address element");
- configRejected(server, "{"
- "\"listen_on\": [{"
- " \"port\": 1.5,"
- " \"address\": \"192.0.2.1\""
- "}]}", "Float port");
- configRejected(server, "{"
- "\"listen_on\": [{"
- " \"port\": -5,"
- " \"address\": \"192.0.2.1\""
- "}]}", "Negative port");
- configRejected(server, "{"
- "\"listen_on\": [{"
- " \"port\": 1000000,"
- " \"address\": \"192.0.2.1\""
- "}]}", "Huge port");
- configRejected(server, "{"
- "\"listen_on\": [{"
- " \"port\": 53,"
- " \"address\": \"bad_address\""
- "}]}", "Bad address");
-}
-
-}
-}
-}
-
-#endif // ISC_TESTUTILS_PORTCONFIG_H
+++ /dev/null
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#ifndef ISC_TESTUTILS_SOCKETREQUEST_H
-#define ISC_TESTUTILS_SOCKETREQUEST_H 1
-
-#include <server_common/socket_request.h>
-#include <server_common/portconfig.h>
-
-#include <asiodns/asiodns.h>
-
-#include <gtest/gtest.h>
-#include <boost/lexical_cast.hpp>
-
-#include <vector>
-#include <string>
-
-namespace isc {
-namespace testutils {
-
-/// \brief A testcase part for faking the SocketRequestor in tests
-///
-/// It's awkward to request real sockets from the real socket creator
-/// during tests (for one, because it would have to be running, for
-/// another, we need to block real ports). If you instantiate this class in
-/// a test case, the socket requestor will be initialized to a test one which
-/// handles fake socket FDs and stores what was requested, etc.
-///
-/// Furthermore, you can check if the code requested or released the correct
-/// list of sockets using the checkTokens() method.
-///
-/// Some member variables are intentionally made public so that test cases
-/// can easily check the value of them. We prefer convenience for tests over
-/// class integrity here.
-class TestSocketRequestor : public isc::server_common::SocketRequestor {
-public:
- /// \brief Constructor
- ///
- /// \param dnss The DNS service. It is expected this gets initialized
- /// after the TestSocketRequestor constructor is called, as the
- /// TestSocketRequestor should be a base class and the service only
- /// a member.
- /// \param store Address store used when cleaning up.
- /// \param expect_port The port which is expected to be requested. If
- /// the application requests a different port, it is considered
- /// a failure.
- /// \param expected_app The share name for which all the requests should
- /// be made. This is not the usual app_name - the requestSocket does
- /// not fall back to this value if its share_name is left empty, if
- /// you want to check the code relies on the requestor to use the
- /// app name, you set this to empty string.
- TestSocketRequestor(asiodns::DNSServiceBase& dnss,
- server_common::portconfig::AddressList& store,
- uint16_t expect_port,
- const std::string& expected_app) :
- last_token_(0), break_rollback_(false), break_release_(false),
- dnss_(dnss), store_(store), expect_port_(expect_port),
- expected_app_(expected_app)
- {
- // Prepare the requestor (us) for the test
- server_common::initTestSocketRequestor(this);
- }
-
- /// \brief Destructor
- ///
- /// Removes the addresses (if any) installed by installListenAddresses,
- /// resets the socket requestor to uninitialized state and turns off
- /// the portconfig test mode.
- virtual ~TestSocketRequestor() {
- // Make sure no sockets are left inside (if installListenAddresses
- // wasn't used, this is NOP, so it won't hurt).
- server_common::portconfig::AddressList list;
- server_common::portconfig::installListenAddresses(list, store_, dnss_);
- // Don't leave invalid pointers here
- server_common::initTestSocketRequestor(NULL);
- }
-
- /// \brief Tokens released by releaseSocket
- ///
- /// They are stored here by this class and you can examine them.
- std::vector<std::string> released_tokens_;
-
- /// \brief Tokens returned from requestSocket
- ///
- /// They are stored here by this class and you can examine them.
- std::vector<std::string> given_tokens_;
-private:
- // Last token number and fd given out
- size_t last_token_;
-public:
- /// \brief Support a broken rollback case
- ///
- /// If this is set to true, the requestSocket will throw when the
- /// ::1 address is requested.
- bool break_rollback_;
-
- /// \brief Throw on releaseSocket
- ///
- /// If this is set to true, the releaseSocket will throw SocketError.
- /// Defaults to false.
- bool break_release_;
-
- /// \brief Release a socket
- ///
- /// This only stores the token passed.
- /// \param token The socket to release
- ///
- /// \throw SocketError in case the break_release_ is set to true. This is
- /// to test exception handling.
- void releaseSocket(const std::string& token) {
- if (break_release_) {
- isc_throw(SocketError, "Fatal test socket error");
- }
- released_tokens_.push_back(token);
- }
-
- /// \brief Request a socket
- ///
- /// This creates a new token and fakes a new socket and returns it.
- /// The token is stored.
- ///
- /// In case the address is 192.0.2.2, it throws SocketAllocateError
- /// or if the break_rollback_ is true and address is ::1, it throws
- /// ShareError. If the address is 192.0.2.3, it throws SocketError.
- ///
- /// The tokens produced are in form of protocol:address:port:fd. The fds
- /// start at 1 and increase by each successfull call.
- ///
- /// \param protocol The protocol to request
- /// \param address to bind to
- /// \param port to bind to
- /// \param mode checked to be SHARE_SAME for now
- /// \param name checked to be the same as expected_app parameter of the
- /// constructor. Note that this class does not provide the fallback
- /// to an app_name if this is empty string. To check the code relies
- /// on the fallback (wants to use the app_name instead of providing
- /// its own share name), you need to create this class with empty
- /// expected_app.
- /// \return The token and FD
- /// \throw SocketAllocateError as described above, to test error handling
- /// \throw ShareError as described above, to test error handling
- /// \throw SocketError as described above, to test error handling
- SocketID requestSocket(Protocol protocol, const std::string& address,
- uint16_t port, ShareMode mode,
- const std::string& name)
- {
- if (address == "192.0.2.2") {
- isc_throw(SocketAllocateError, "This address is not allowed");
- }
- if (address == "192.0.2.3") {
- isc_throw(SocketError, "Fatal test error");
- }
- if (address == "::1" && break_rollback_) {
- // This is valid address, but in case we need to break the
- // rollback, it needs to be busy or whatever
- //
- // We break the second address to see the first one was
- // allocated and then returned
- isc_throw(ShareError,
- "This address is available, but not for you");
- }
- const std::string proto(protocol == TCP ? "TCP" : "UDP");
- const size_t number = ++ last_token_;
- EXPECT_EQ(expect_port_, port);
- EXPECT_EQ(SHARE_SAME, mode);
- EXPECT_EQ(expected_app_, name);
- const std::string token(proto + ":" + address + ":" +
- boost::lexical_cast<std::string>(port) + ":" +
- boost::lexical_cast<std::string>(number));
- given_tokens_.push_back(token);
- return (SocketID(number, token));
- }
-
- /// \brief Check the list of tokens is as expected
- ///
- /// Compares the expected and real tokens.
- ///
- /// \param expected List of the expected tokens, as NULL-terminated array
- /// of C strings (it is more convenient to type as a constant than to
- /// manually push_back all the strings to a vector).
- /// \param real The token list that was produced by this class (usually
- /// either given_tokens_ or released_tokens_).
- /// \param scope Human readable identifier of which checkTokens call it is.
- /// It is printed as a part of failure message.
- void checkTokens(const char** expected,
- const std::vector<std::string>& real,
- const char* scope) const
- {
- SCOPED_TRACE(scope);
- size_t position(0);
- while (expected[position] != NULL) {
- ASSERT_LT(position, real.size());
- EXPECT_EQ(expected[position], real[position]) << position;
- position ++;
- }
- EXPECT_EQ(position, real.size());
- }
-
-private:
- asiodns::DNSServiceBase& dnss_;
- server_common::portconfig::AddressList& store_;
- const uint16_t expect_port_;
- const std::string expected_app_;
-};
-
-}
-}
-#endif // ISC_TESTUTILS_SOCKETREQUEST_H
libkea_util_la_SOURCES = boost_time_utils.h boost_time_utils.cc
libkea_util_la_SOURCES += csv_file.h csv_file.cc
libkea_util_la_SOURCES += filename.h filename.cc
-libkea_util_la_SOURCES += locks.h lru_list.h
libkea_util_la_SOURCES += strutil.h strutil.cc
libkea_util_la_SOURCES += buffer.h io_utilities.h
libkea_util_la_SOURCES += time_utilities.h time_utilities.cc
+++ /dev/null
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-/// This file (right now) provides dummy locks
-/// It also contains code to use boost/threads locks:
-///
-///
-/// All locks are dummy classes that don't actually do anything. At this moment,
-/// only the very minimal set of methods that we actually use is defined.
-///
-/// Note that we need to include <config.h> in our .cc files for that
-/// to be set. we might want to enfore this at compile time with a check
-/// (TODO)
-
-#ifndef LOCKS
-#define LOCKS
-
-namespace isc {
-namespace util {
-namespace locks {
-
-class mutex {
-};
-
-class recursive_mutex {
-};
-
-class upgradable_mutex {
-};
-
-template <typename T>
-class sharable_lock {
-public:
- sharable_lock(T) {}
-};
-
-template <typename T>
-class scoped_lock {
-public:
- scoped_lock(T) {}
-
- // We need to define this explicitly. Some versions of clang++ would
- // complain about this otherwise. See Trac ticket #2340
- ~scoped_lock() {}
-
- void lock() {}
- void unlock() {}
-};
-
-} // namespace locks
-} // namespace util
-} // namespace isc
-
-#endif // LOCKS
+++ /dev/null
-// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#ifndef LRU_LIST_H
-#define LRU_LIST_H
-
-#include <list>
-#include <string>
-
-#include <boost/noncopyable.hpp>
-#include <boost/shared_ptr.hpp>
-
-#include <util/locks.h>
-
-namespace isc {
-namespace util {
-
-/// \brief LRU List
-///
-/// Provides the LRU list for the zone and nameserver objects. The list is
-/// created with a specific size. Entries are added to the back of the list
-/// and removed from the front. It is also possible to pull an element out
-/// of the middle of the list and add it to the end of the list, an action that
-/// should be done when the element is referenced.
-///
-/// It is not intended that the class be copied, and the derivation from
-/// boost::noncopyable enforces this.
-template <typename T>
-class LruList : boost::noncopyable {
-public:
- typedef typename std::list<boost::shared_ptr<T> > lru_list;
- typedef typename lru_list::iterator iterator;
-
- /// \brief Dropped Operation
- ///
- /// When an object is dropped from the LRU list because it has not been
- /// accessed for some time, it is possible that the action should trigger
- /// some other functions. For this reason, it is possible to register
- /// a list-wide functor object to execute in this case.
- ///
- /// Note that the function does not execute as the result of a call to
- /// remove() - that is an explicit call and it is assumed that the caller
- /// will handle any additional operations needed.
- class Dropped {
- public:
- /// \brief Constructor
- Dropped(){}
-
- /// \brief Virtual Destructor
- virtual ~Dropped(){}
-
- /// \brief Dropped Object Handler
- ///
- /// Function object called when the object drops off the end of the
- /// LRU list.
- ///
- /// \param drop Object being dropped.
- virtual void operator()(T* drop) const = 0;
- };
-
- /// \brief Constructor
- ///
- /// \param max_size Maximum size of the list before elements are dropped.
- /// \param dropped Pointer to a function object that will get called as
- /// elements are dropped. This object will be stored using a shared_ptr,
- /// so should be allocated with new().
- LruList(uint32_t max_size = 1000, Dropped* dropped = NULL) :
- max_size_(max_size), count_(0), dropped_(dropped)
- {}
-
- /// \brief Virtual Destructor
- virtual ~LruList()
- {}
-
- /// \brief Add Element
- ///
- /// Add a new element to the end of the list.
- ///
- /// \param element Reference to the element to add.
- ///
- /// \return Handle describing the element in the LRU list.
- virtual void add(boost::shared_ptr<T>& element);
-
- /// \brief Remove Element
- ///
- /// Removes an element from the list. If the element is not present (i.e.
- /// its internal list pointer is invalid), this is a no-op.
- ///
- /// \param element Reference to the element to remove.
- virtual void remove(boost::shared_ptr<T>& element);
-
- /// \brief Touch Element
- ///
- /// The name comes from the Unix "touch" command. All this does is to
- /// move the specified entry from the middle of the list to the end of
- /// the list.
- ///
- /// \param element Reference to the element to touch.
- virtual void touch(boost::shared_ptr<T>& element);
-
- /// \brief Drop All the Elements in the List .
- ///
- /// All the elements will be dropped from the list container, and their
- /// drop handler(if there is one) will be called, when done, the size of
- /// of list will be 0.
- virtual void clear();
-
- /// \brief Return Size of the List
- ///
- /// An independent count is kept of the list size, as list.size() may take
- /// some time if the list is big.
- ///
- /// \return Number of elements in the list
- virtual uint32_t size() const {
-
- // Don't bother to lock the mutex. If an update is in progress, we
- // receive either the value just before the update or just after it.
- // Either way, this call could have come just before or just after
- // that operation, so the value would have been just as uncertain.
- return count_;
- }
-
- /// \brief Return Maximum Size
- ///
- /// \return Maximum size of the list
- virtual uint32_t getMaxSize() const {
- return max_size_;
- }
-
- /// \brief Set Maximum Size
- ///
- /// \param max_size New maximum list size
- virtual void setMaxSize(uint32_t max_size) {
- max_size_ = max_size;
- }
-
-private:
- locks::mutex mutex_; ///< List protection
- std::list<boost::shared_ptr<T> > lru_; ///< The LRU list itself
- uint32_t max_size_; ///< Max size of the list
- uint32_t count_; ///< Count of elements
- boost::shared_ptr<Dropped> dropped_; ///< Dropped object
-};
-
-// Add entry to the list
-template <typename T>
-void LruList<T>::add(boost::shared_ptr<T>& element) {
-
- // Protect list against concurrent access
- locks::scoped_lock<locks::mutex> lock(mutex_);
-
- // Add the entry and set its pointer field to point into the list.
- // insert() is used to get the pointer.
- element->setLruIterator(lru_.insert(lru_.end(), element));
-
- // ... and update the count while we have the mutex.
- ++count_;
-
- // If the count takes us above the maximum size of the list, remove elements
- // from the front. The current list size could be more than one above the
- // maximum size of the list if the maximum size was changed after
- // construction.
- while (count_ > max_size_) {
- if (!lru_.empty()) {
-
- // Run the drop handler (if there is one) on the
-
- // to-be-dropped object.
- if (dropped_) {
- (*dropped_)(lru_.begin()->get());
- }
-
- // ... and get rid of it from the list
- lru_.pop_front();
- --count_;
- }
- else {
-
- // TODO: Log this condition (count_ > 0 when list empty) -
- // it should not happen
- count_ = 0;
- break;
- }
- }
-}
-
-// Remove an element from the list
-template <typename T>
-void LruList<T>::remove(boost::shared_ptr<T>& element) {
-
- // An element can only be removed it its internal pointer is valid.
- // If it is, the pointer can be used to access the list because no matter
- // what other elements are added or removed, the pointer remains valid.
- //
- // If the pointer is not valid, this is a no-op.
- if (element->iteratorValid()) {
-
- // Is valid, so protect list against concurrent access
- locks::scoped_lock<locks::mutex> lock(mutex_);
-
- lru_.erase(element->getLruIterator()); // Remove element from list
- element->invalidateIterator(); // Invalidate pointer
- --count_; // One less element
- }
-}
-
-// Touch an element - remove it from the list and add to the end
-template <typename T>
-void LruList<T>::touch(boost::shared_ptr<T>& element) {
-
- // As before, if the pointer is not valid, this is a no-op.
- if (element->iteratorValid()) {
-
- // Protect list against concurrent access
- locks::scoped_lock<locks::mutex> lock(mutex_);
-
- // Move the element to the end of the list.
- lru_.splice(lru_.end(), lru_, element->getLruIterator());
-
- // Update the iterator in the element to point to it. We can
- // offset from end() as a list has a bidirectional iterator.
- iterator i = lru_.end();
- element->setLruIterator(--i);
- }
-}
-
-// Clear the list- when done, the size of list will be 0.
-template <typename T>
-void LruList<T>::clear() {
- // Protect list against concurrent access
- locks::scoped_lock<locks::mutex> lock(mutex_);
-
- // ... and update the count while we have the mutex.
- count_ = 0;
- typename std::list<boost::shared_ptr<T> >::iterator iter;
- if (dropped_) {
- for (iter = lru_.begin(); iter != lru_.end(); ++iter) {
- // Call the drop handler.
- (*dropped_)(iter->get());
- }
- }
-
- lru_.clear();
-}
-
-} // namespace util
-} // namespace isc
-
-#endif // LRU_LIST_H
run_unittests_SOURCES += filename_unittest.cc
run_unittests_SOURCES += hex_unittest.cc
run_unittests_SOURCES += io_utilities_unittest.cc
-run_unittests_SOURCES += lru_list_unittest.cc
run_unittests_SOURCES += memory_segment_local_unittest.cc
run_unittests_SOURCES += memory_segment_common_unittest.h
run_unittests_SOURCES += memory_segment_common_unittest.cc
+++ /dev/null
-// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <config.h>
-
-#include <stdint.h>
-#include <iostream>
-#include <algorithm>
-#include <string>
-#include <vector>
-
-#include <exceptions/exceptions.h>
-#include <gtest/gtest.h>
-#include <boost/lexical_cast.hpp>
-#include <boost/enable_shared_from_this.hpp>
-
-#include <util/lru_list.h>
-
-using namespace std;
-
-namespace isc {
-namespace util {
-
-/// \brief Invalid Iterator
-///
-/// Thrown if an attempt was made to access the iterator - the pointer into
-/// the LRU list where this element is located - when it is marked as invalid.
-class InvalidLruIterator : public isc::Exception {
-public:
- InvalidLruIterator(const char* file, size_t line, const char* what) :
- Exception(file, line, what)
- {}
-};
-
-template <typename T>
-class TestEntryT : public boost::enable_shared_from_this <T> {
-public:
-
- /// \brief Constructor
- ///
- /// \param name Name that will be used for the object. This will form
- /// part of the key.
- /// \param class_code Class associated with the object.
- TestEntryT() : valid_(false)
- {}
-
- /// \brief Virtual Destructor
- virtual ~TestEntryT()
- {}
-
- /// \brief Sets the iterator of the object
- ///
- /// Sets the iterator of an object and, as a side effect, marks it as valid.
- ///
- /// \param iterator Iterator of this element in the list
- virtual void setLruIterator(typename LruList<T>::iterator iterator) {
- iterator_ = iterator;
- valid_ = true;
- }
-
- /// \brief Return Iterator
- ///
- /// \return iterator Iterator of this element in the list.
- ///
- /// \exception InvalidLruIterator Thrown if the iterator is not valid.
- virtual typename LruList<T>::iterator getLruIterator() const {
- /*if (! valid_) {
- isc_throw(InvalidLruIterator,
- "pointer of element into LRU list was not valid");
- }*/
- return iterator_;
- }
-
- /// \brief Iterator Valid
- ///
- /// \return true if the stored iterator is valid.
- virtual bool iteratorValid() const {
- return valid_;
- }
-
- /// \brief Invalidate Iterator
- ///
- /// Marks the iterator as invalid; it can only be set valid again by a call
- /// to setLruIterator.
- virtual void invalidateIterator() {
- valid_ = false;
- }
-
-private:
- typename LruList<T>::iterator iterator_; ///< Handle into the LRU List
- bool valid_; ///< true if handle is valid
-};
-
-class TestEntry : public TestEntryT<TestEntry> {
-public:
- TestEntry(std::string name, const int & code) :
- name_(name), code_(code)
- {}
-
- /// \brief Get the Name
- ///
- /// \return Name given to this object
- virtual std::string getName() const {
- return name_;
- }
-
- /// \brief Set the Name
- ///
- /// \param name New name of the object
- virtual void setName(const std::string& name) {
- name_ = name;
- }
-
- /// \brief Get the Class
- ///
- /// \return Class code assigned to this object
- virtual const int& getCode() const {
- return code_;
- }
-
- /// \brief Set the Class
- ///
- /// \param code New code of the object
- virtual void setCode(const int& code) {
- code_ = code;
- }
-
-private:
- std::string name_; ///< Name of the object
- int code_; ///< Class of the object
-
-};
-
-/// \brief Dropped Functor Class
-///
-/// Functor object is called when an object is dropped from the LRU list.
-/// To prove that it has run, this function does nothing more than set the
-/// MS bit on the 16-bit code value.
-class Dropped : public LruList<TestEntry>::Dropped {
-public:
- virtual void operator()(TestEntry* entry) const {
- entry->setCode(entry->getCode() | 0x8000);
- }
-};
-
-
-/// \brief Text Fixture Class
-class LruListTest : public ::testing::Test {
-protected:
- LruListTest() :
- entry1_(new TestEntry("alpha", 1)),
- entry2_(new TestEntry("beta", 3)),
- entry3_(new TestEntry("gamma", 4)),
- entry4_(new TestEntry("delta", 1)),
- entry5_(new TestEntry("epsilon", 4)),
- entry6_(new TestEntry("zeta", 3)),
- entry7_(new TestEntry("eta", 1))
- {}
-
- virtual ~LruListTest()
- {}
-
- boost::shared_ptr<TestEntry> entry1_;
- boost::shared_ptr<TestEntry> entry2_;
- boost::shared_ptr<TestEntry> entry3_;
- boost::shared_ptr<TestEntry> entry4_;
- boost::shared_ptr<TestEntry> entry5_;
- boost::shared_ptr<TestEntry> entry6_;
- boost::shared_ptr<TestEntry> entry7_;
-};
-
-
-// Test of the constructor
-TEST_F(LruListTest, Constructor) {
- LruList<TestEntry> lru(100);
- EXPECT_EQ(100, lru.getMaxSize());
- EXPECT_EQ(0, lru.size());
-}
-
-// Test of Get/Set the maximum number of entries
-TEST_F(LruListTest, GetSet) {
- LruList<TestEntry> lru(100);
- EXPECT_EQ(100, lru.getMaxSize());
- lru.setMaxSize(42);
- EXPECT_EQ(42, lru.getMaxSize());
-}
-
-// Test that adding an entry really does add an entry
-TEST_F(LruListTest, Add) {
- LruList<TestEntry> lru(100);
- EXPECT_EQ(0, lru.size());
-
- lru.add(entry1_);
- EXPECT_EQ(1, lru.size());
-
- lru.add(entry2_);
- EXPECT_EQ(2, lru.size());
-}
-
-// Test that removing an entry really does remove it.
-TEST_F(LruListTest, Remove) {
- LruList<TestEntry> lru(100);
- EXPECT_EQ(0, lru.size());
-
- EXPECT_FALSE(entry1_->iteratorValid());
- lru.add(entry1_);
- EXPECT_TRUE(entry1_->iteratorValid());
- EXPECT_EQ(1, lru.size());
-
- EXPECT_FALSE(entry2_->iteratorValid());
- lru.add(entry2_);
- EXPECT_TRUE(entry2_->iteratorValid());
- EXPECT_EQ(2, lru.size());
-
- lru.remove(entry1_);
- EXPECT_FALSE(entry1_->iteratorValid());
- EXPECT_EQ(1, lru.size());
-}
-
-// Check that adding a new entry to a limited size list does delete the
-// oldest entry from the list.
-TEST_F(LruListTest, SizeLimit) {
- LruList<TestEntry> lru(3);
- EXPECT_EQ(0, lru.size());
-
- // Add first entry and check that the shared pointer's reference count
- // has increased. There will be two references: one from the "entry1_"
- // member in the test fixture class, and one from the list.
- EXPECT_EQ(1, entry1_.use_count());
- lru.add(entry1_);
- EXPECT_EQ(2, entry1_.use_count());
- EXPECT_EQ(1, lru.size());
-
- // Same for entry 2.
- EXPECT_EQ(1, entry2_.use_count());
- lru.add(entry2_);
- EXPECT_EQ(2, entry2_.use_count());
- EXPECT_EQ(2, lru.size());
-
- // Same for entry 3.
- EXPECT_EQ(1, entry3_.use_count());
- lru.add(entry3_);
- EXPECT_EQ(2, entry3_.use_count());
- EXPECT_EQ(3, lru.size());
-
- // Adding entry 4 should remove entry 1 from the list. This will
- // delete the list's shared pointer to the entry and will therefore
- // drop the reference count back to one (from the "entry1_" member in
- // the text fixture class).
- EXPECT_EQ(2, entry1_.use_count());
- EXPECT_EQ(1, entry4_.use_count());
- lru.add(entry4_);
- EXPECT_EQ(1, entry1_.use_count());
- EXPECT_EQ(2, entry4_.use_count());
- EXPECT_EQ(3, lru.size());
-
- // Adding entry 5 should remove entry 2 from the list.
- EXPECT_EQ(2, entry2_.use_count());
- EXPECT_EQ(1, entry5_.use_count());
- lru.add(entry5_);
- EXPECT_EQ(1, entry2_.use_count());
- EXPECT_EQ(2, entry5_.use_count());
- EXPECT_EQ(3, lru.size());
-}
-
-// Check that "touching" an entry adds it to the back of the list.
-TEST_F(LruListTest, Touch) {
-
- // Create the list
- LruList<TestEntry> lru(3);
- EXPECT_EQ(0, lru.size());
- lru.add(entry1_);
- lru.add(entry2_);
- lru.add(entry3_);
-
- // Check the reference counts of the entries and the list size
- EXPECT_EQ(2, entry1_.use_count());
- EXPECT_EQ(2, entry2_.use_count());
- EXPECT_EQ(2, entry3_.use_count());
- EXPECT_EQ(1, entry4_.use_count());
- EXPECT_EQ(1, entry5_.use_count());
- EXPECT_EQ(1, entry6_.use_count());
- EXPECT_EQ(1, entry7_.use_count());
- EXPECT_EQ(3, lru.size());
-
- // "Touch" the first entry
- lru.touch(entry1_);
-
- // Adding two more entries should not remove the touched entry.
- lru.add(entry4_);
- lru.add(entry5_);
-
- // Check the status of the entries and the list.
- EXPECT_EQ(2, entry1_.use_count());
- EXPECT_EQ(1, entry2_.use_count());
- EXPECT_EQ(1, entry3_.use_count());
- EXPECT_EQ(2, entry4_.use_count());
- EXPECT_EQ(2, entry5_.use_count());
- EXPECT_EQ(1, entry6_.use_count());
- EXPECT_EQ(1, entry7_.use_count());
- EXPECT_EQ(3, lru.size());
-
- // Now touch the entry again to move it to the back of the list.
- // This checks that the iterator stored in the entry as a result of the
- // last touch operation is valid.
- lru.touch(entry1_);
-
- // Check this by adding two more entries and checking reference counts
- // to see what is stored.
- lru.add(entry6_);
- lru.add(entry7_);
-
- EXPECT_EQ(2, entry1_.use_count());
- EXPECT_EQ(1, entry2_.use_count());
- EXPECT_EQ(1, entry3_.use_count());
- EXPECT_EQ(1, entry4_.use_count());
- EXPECT_EQ(1, entry5_.use_count());
- EXPECT_EQ(2, entry6_.use_count());
- EXPECT_EQ(2, entry7_.use_count());
- EXPECT_EQ(3, lru.size());
-}
-
-// Dropped functor tests: tests that the function object is called when an
-// object expires from the list.
-TEST_F(LruListTest, Dropped) {
-
- // Create an object with an expiration handler.
- LruList<TestEntry> lru(3, new Dropped());
-
- // Fill the list
- lru.add(entry1_);
- lru.add(entry2_);
- lru.add(entry3_);
-
- EXPECT_EQ(1, entry1_->getCode());
- EXPECT_EQ(3, entry2_->getCode());
-
- // Add another entry and check that the handler runs.
- EXPECT_EQ(0, (entry1_->getCode() & 0x8000));
- lru.add(entry4_);
- EXPECT_NE(0, (entry1_->getCode() & 0x8000));
-
- EXPECT_EQ(0, (entry2_->getCode() & 0x8000));
- lru.add(entry5_);
- EXPECT_NE(0, (entry2_->getCode() & 0x8000));
-
- // Delete an entry and check that the handler does not run.
- EXPECT_EQ(0, (entry3_->getCode() & 0x8000));
- lru.remove(entry3_);
- EXPECT_EQ(0, (entry3_->getCode() & 0x8000));
-}
-
-// Clear functor tests: tests whether all the elements in
-// the list are dropped properly and the size of list is
-// set to 0.
-TEST_F(LruListTest, Clear) {
- // Create an object with an expiration handler.
- LruList<TestEntry> lru(3, new Dropped());
-
- // Fill the list
- lru.add(entry1_);
- lru.add(entry2_);
- lru.add(entry3_);
-
- EXPECT_EQ(1, entry1_->getCode());
- EXPECT_EQ(3, entry2_->getCode());
- EXPECT_EQ(4, entry3_->getCode());
-
- EXPECT_EQ(0, (entry1_->getCode() & 0x8000));
- EXPECT_EQ(0, (entry2_->getCode() & 0x8000));
- EXPECT_EQ(0, (entry3_->getCode() & 0x8000));
-
- // Clear the lru list, and check the drop handler run
- lru.clear();
- EXPECT_NE(0, (entry1_->getCode() & 0x8000));
- EXPECT_NE(0, (entry2_->getCode() & 0x8000));
- EXPECT_NE(0, (entry3_->getCode() & 0x8000));
-
- EXPECT_EQ(0, lru.size());
-}
-
-// Miscellaneous tests - pathological conditions
-TEST_F(LruListTest, Miscellaneous) {
-
- // Zero size list should not allow entries to be added
- LruList<TestEntry> lru_1(0);
- lru_1.add(entry1_);
- EXPECT_EQ(0, lru_1.size());
- EXPECT_EQ(1, entry1_.use_count());
-
- // Removing a not-inserted entry should not affect the list.
- LruList<TestEntry> lru_2(100);
- lru_2.add(entry1_);
- lru_2.add(entry2_);
- lru_2.add(entry3_);
- EXPECT_EQ(3, lru_2.size());
-
- lru_2.remove(entry4_);
- EXPECT_EQ(2, entry1_.use_count());
- EXPECT_EQ(2, entry2_.use_count());
- EXPECT_EQ(2, entry3_.use_count());
- EXPECT_EQ(1, entry4_.use_count());
- EXPECT_EQ(1, entry5_.use_count());
- EXPECT_EQ(3, lru_2.size());
-
- // Touching a not-inserted entry should not affect the list.
- lru_2.touch(entry5_);
- EXPECT_EQ(2, entry1_.use_count());
- EXPECT_EQ(2, entry2_.use_count());
- EXPECT_EQ(2, entry3_.use_count());
- EXPECT_EQ(1, entry4_.use_count());
- EXPECT_EQ(1, entry5_.use_count());
- EXPECT_EQ(3, lru_2.size());
-}
-
-} // namespace nsas
-} // namespace isc
AM_CXXFLAGS = $(KEA_CXXFLAGS)
noinst_LTLIBRARIES = libutil_unittests.la
-libutil_unittests_la_SOURCES = fork.h fork.cc resolver.h
+libutil_unittests_la_SOURCES = fork.h fork.cc
libutil_unittests_la_SOURCES += newhook.h newhook.cc
libutil_unittests_la_SOURCES += testdata.h testdata.cc
if HAVE_GTEST
+++ /dev/null
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#ifndef UTIL_UNITTEST_RESOLVER_H
-#define UTIL_UNITTEST_RESOLVER_H
-
-/// \file resolver.h
-/// \brief Fake resolver
-
-#include <map>
-#include <dns/rrset.h>
-#include <dns/question.h>
-#include <dns/message.h>
-#include <dns/opcode.h>
-#include <dns/rcode.h>
-#include <dns/rrttl.h>
-#include <resolve/resolver_interface.h>
-#include <gtest/gtest.h>
-
-namespace isc {
-namespace util {
-namespace unittests {
-
-/// \brief Put rrset into a message as an answer
-inline static isc::dns::MessagePtr
-createResponseMessage(isc::dns::RRsetPtr answer_rrset)
-{
- isc::dns::MessagePtr response(new isc::dns::Message(
- isc::dns::Message::RENDER));
- response->setOpcode(isc::dns::Opcode::QUERY());
- response->setRcode(isc::dns::Rcode::NOERROR());
- response->addRRset(isc::dns::Message::SECTION_ANSWER, answer_rrset);
- return response;
-}
-
-/// \brief Mock resolver
-///
-/// This class pretends to be a resolver. However, it only stores the
-/// requests and can answer them right away by prepared answers. It doesn't
-/// do any real work and is intended for testing purposes.
-class TestResolver : public isc::resolve::ResolverInterface {
- private:
- bool checkIndex(size_t index) {
- return (requests.size() > index);
- }
-
- typedef std::map<isc::dns::Question, isc::dns::RRsetPtr>
- PresetAnswers;
- PresetAnswers answers_;
- public:
- typedef std::pair<isc::dns::QuestionPtr, CallbackPtr> Request;
- /// \brief List of requests the tested class sent through resolve
- std::vector<Request> requests;
-
- /// \brief Destructor
- ///
- /// This is important. All callbacks in the requests vector must be
- /// called to remove them from internal loops. Without this, destroying
- /// the NSAS object will leave memory assigned.
- ~TestResolver() {
- for (size_t i = 0; i < requests.size(); ++i) {
- requests[i].second->failure();
- }
- }
-
- /// \brief Testing version of resolve
- ///
- /// If there's a prepared answer (provided by addPresetAnswer), it
- /// answers it right away. Otherwise it just stores the request in
- /// the requests member so it can be examined later.
- virtual void resolve(const isc::dns::QuestionPtr& q,
- const CallbackPtr& c)
- {
- PresetAnswers::iterator it(answers_.find(*q));
- if (it == answers_.end()) {
- requests.push_back(Request(q, c));
- } else {
- if (it->second) {
- c->success(createResponseMessage(it->second));
- } else {
- c->failure();
- }
- }
- }
-
- /// \brief Add a preset answer.
- ///
- /// Add a preset answer. If shared_ptr() is passed (eg. NULL),
- /// it will generate failure. If the question is not preset,
- /// it goes to requests and you can answer later.
- void addPresetAnswer(const isc::dns::Question& question,
- isc::dns::RRsetPtr answer)
- {
- answers_[question] = answer;
- }
-
- /// \brief Thrown if the query at the given index does not exist.
- class NoSuchRequest : public std::exception { };
-
- /// \brief Thrown if the answer does not match the query
- class DifferentRequest : public std::exception { };
-
- /// \brief Provides the question of request on given answer
- isc::dns::QuestionPtr operator[](size_t index) {
- if (index >= requests.size()) {
- throw NoSuchRequest();
- }
- return (requests[index].first);
- }
- /// \brief Test it asks for IP addresses
- /// Looks if the two provided requests in resolver are A and AAAA.
- /// Sorts them so index1 is A.
- ///
- /// Returns false if there aren't enough elements
- bool asksIPs(const isc::dns::Name& name, size_t index1,
- size_t index2)
- {
- size_t max = (index1 < index2) ? index2 : index1;
- if (!checkIndex(max)) {
- return false;
- }
- EXPECT_EQ(name, (*this)[index1]->getName());
- EXPECT_EQ(name, (*this)[index2]->getName());
- EXPECT_EQ(isc::dns::RRClass::IN(), (*this)[index1]->getClass());
- EXPECT_EQ(isc::dns::RRClass::IN(), (*this)[index2]->getClass());
- // If they are the other way around, swap
- if ((*this)[index1]->getType() == isc::dns::RRType::AAAA() &&
- (*this)[index2]->getType() == isc::dns::RRType::A())
- {
- TestResolver::Request tmp((*this).requests[index1]);
- (*this).requests[index1] =
- (*this).requests[index2];
- (*this).requests[index2] = tmp;
- }
- // Check the correct addresses
- EXPECT_EQ(isc::dns::RRType::A(), (*this)[index1]->getType());
- EXPECT_EQ(isc::dns::RRType::AAAA(), (*this)[index2]->getType());
- return (true);
- }
-
- /// \brief Answer a request
- /// Sends a simple answer to a query.
- /// 1) Provide index of a query and the address(es) to pass.
- /// 2) Provide index of query and components of address to pass.
- void answer(size_t index, isc::dns::RRsetPtr& set) {
- if (index >= requests.size()) {
- throw NoSuchRequest();
- }
- requests[index].second->success(createResponseMessage(set));
- }
-
- void answer(size_t index, const isc::dns::Name& name,
- const isc::dns::RRType& type,
- const isc::dns::rdata::Rdata& rdata, size_t TTL = 100)
- {
- isc::dns::RRsetPtr set(new isc::dns::RRset(name,
- isc::dns::RRClass::IN(),
- type,
- isc::dns::RRTTL(TTL)));
- set->addRdata(rdata);
- answer(index, set);
- }
- /// \Answer the query at index by list of nameservers
- void provideNS(size_t index, isc::dns::RRsetPtr nameservers)
- {
- if (index >= requests.size()) {
- throw NoSuchRequest();
- }
- if (requests[index].first->getName() != nameservers->getName() ||
- requests[index].first->getType() != isc::dns::RRType::NS())
- {
- throw DifferentRequest();
- }
- requests[index].second->success(createResponseMessage(nameservers));
- }
-};
-
-}
-}
-}
-
-#endif