|
@@ -33,28 +33,89 @@ extern bool test_mode;
|
|
|
|
|
|
namespace testutils {
|
|
|
|
|
|
-// TODO Docs
|
|
|
-
|
|
|
+/// \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 inherit this class,
|
|
|
+/// the socket requestor will be initialized to a test one which handles
|
|
|
+/// fake socket FDs and stores what was requested, etc. Make sure to
|
|
|
+/// call the inherited SetUp and TearDown if you define your own (eg.
|
|
|
+/// chain them instead of override).
|
|
|
+///
|
|
|
+/// Furthermore, you can check if the code requested or released the correct
|
|
|
+/// list of sockets.
|
|
|
+///
|
|
|
+/// \note This class breaks many recommendations about "clean" object
|
|
|
+/// design. It is mostly because the recommendations are too paranoid
|
|
|
+/// and we better use the powerful tools we have, when we have a reason.
|
|
|
+/// We inherit both the testing::Test and SocketRequestor, so we can
|
|
|
+/// access both the testing macros and store the requests conveniently.
|
|
|
+/// The virtual inheritance is necessary, because some tests need more
|
|
|
+/// than one such "component" to be build from.
|
|
|
class TestSocketRequestor : public isc::server_common::SocketRequestor,
|
|
|
virtual public ::testing::Test {
|
|
|
protected:
|
|
|
+ /// \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.
|
|
|
TestSocketRequestor(asiodns::DNSService& dnss,
|
|
|
server_common::portconfig::AddressList& store,
|
|
|
uint16_t expect_port) :
|
|
|
last_token_(0), break_rollback_(false), dnss_(dnss), store_(store),
|
|
|
expect_port_(expect_port)
|
|
|
{}
|
|
|
+ /// \brief Destructor
|
|
|
virtual ~ TestSocketRequestor() {}
|
|
|
- // Store the tokens as they go in and out
|
|
|
+ /// \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_;
|
|
|
- // Should we break the rollback?
|
|
|
+protected:
|
|
|
+ /// \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 Release a socket
|
|
|
+ ///
|
|
|
+ /// This only stores the token passed.
|
|
|
+ /// \param token The socket to release
|
|
|
void releaseSocket(const std::string& token) {
|
|
|
released_tokens_.push_back(token);
|
|
|
}
|
|
|
+ /// \brief Request a socket
|
|
|
+ ///
|
|
|
+ /// This creates a new token and fakes a new socket and returs it.
|
|
|
+ /// The token is stored.
|
|
|
+ ///
|
|
|
+ /// In case the address is 192.0.2.2 or if the break_rollback_ is true
|
|
|
+ /// and address is ::1, it throws.
|
|
|
+ ///
|
|
|
+ /// 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 DONT_SHARE for now
|
|
|
+ /// \param name checked to be dummy_app for now
|
|
|
+ /// \return The token and FD
|
|
|
+ /// \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)
|
|
@@ -82,12 +143,26 @@ protected:
|
|
|
given_tokens_.push_back(token);
|
|
|
return (SocketID(number, token));
|
|
|
}
|
|
|
+ /// \brief Initialize the test
|
|
|
+ ///
|
|
|
+ /// It installs itself as the socket requestor. It also turns on portconfig
|
|
|
+ /// test mode where it doesn't really put the sockets into ASIO (as the FDs
|
|
|
+ /// are fake ones and would get closed).
|
|
|
+ ///
|
|
|
+ /// Make sure you call it in case you need to define your own SetUp.
|
|
|
void SetUp() {
|
|
|
// Prepare the requestor (us) for the test
|
|
|
SocketRequestor::initTest(this);
|
|
|
// Don't manipulate the real sockets
|
|
|
server_common::portconfig::test_mode = true;
|
|
|
}
|
|
|
+ /// \brief Cleanup after the test
|
|
|
+ ///
|
|
|
+ /// Removes the addresses (if any) installed by installListenAddresses,
|
|
|
+ /// resets the socket requestor to uninitialized state and turns off
|
|
|
+ /// the portconfig test mode.
|
|
|
+ ///
|
|
|
+ /// Make sure you call it in case you need to define your own TearDown.
|
|
|
void TearDown() {
|
|
|
// Make sure no sockets are left inside (if installListenAddresses
|
|
|
// wasn't used, this is NOP, so it won't hurt).
|
|
@@ -98,7 +173,17 @@ protected:
|
|
|
// And return the mode
|
|
|
server_common::portconfig::test_mode = false;
|
|
|
}
|
|
|
- // This checks the set of tokens is the same
|
|
|
+ /// \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)
|