From: Michal 'vorner' Vaner Date: Fri, 23 Dec 2011 14:45:05 +0000 (+0100) Subject: [805] Documentation of the fake socket requestor X-Git-Tag: trac2351_base~304^2~16^2~24 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b42300ae4b958bef9ff55eec929a227c4db4b5e3;p=thirdparty%2Fkea.git [805] Documentation of the fake socket requestor --- diff --git a/src/lib/testutils/socket_request.h b/src/lib/testutils/socket_request.h index 500705f874..0ca741f05e 100644 --- a/src/lib/testutils/socket_request.h +++ b/src/lib/testutils/socket_request.h @@ -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 released_tokens_; + /// \brief Tokens returned from requestSocket + /// + /// They are stored here by this class and you can examine them. std::vector 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& real, const char* scope)