Parcourir la source

[805] Documentation of the fake socket requestor

Michal 'vorner' Vaner il y a 13 ans
Parent
commit
b42300ae4b
1 fichiers modifiés avec 90 ajouts et 5 suppressions
  1. 90 5
      src/lib/testutils/socket_request.h

+ 90 - 5
src/lib/testutils/socket_request.h

@@ -33,28 +33,89 @@ extern bool test_mode;
 
 
 namespace testutils {
 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,
 class TestSocketRequestor : public isc::server_common::SocketRequestor,
     virtual public ::testing::Test {
     virtual public ::testing::Test {
 protected:
 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,
     TestSocketRequestor(asiodns::DNSService& dnss,
                         server_common::portconfig::AddressList& store,
                         server_common::portconfig::AddressList& store,
                         uint16_t expect_port) :
                         uint16_t expect_port) :
         last_token_(0), break_rollback_(false), dnss_(dnss), store_(store),
         last_token_(0), break_rollback_(false), dnss_(dnss), store_(store),
         expect_port_(expect_port)
         expect_port_(expect_port)
     {}
     {}
+    /// \brief Destructor
     virtual ~ TestSocketRequestor() {}
     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_;
     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_;
     std::vector<std::string> given_tokens_;
+private:
     // Last token number and fd given out
     // Last token number and fd given out
     size_t last_token_;
     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_;
     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) {
     void releaseSocket(const std::string& token) {
         released_tokens_.push_back(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,
     SocketID requestSocket(Protocol protocol, const std::string& address,
                            uint16_t port, ShareMode mode,
                            uint16_t port, ShareMode mode,
                            const std::string& name)
                            const std::string& name)
@@ -82,12 +143,26 @@ protected:
         given_tokens_.push_back(token);
         given_tokens_.push_back(token);
         return (SocketID(number, 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() {
     void SetUp() {
         // Prepare the requestor (us) for the test
         // Prepare the requestor (us) for the test
         SocketRequestor::initTest(this);
         SocketRequestor::initTest(this);
         // Don't manipulate the real sockets
         // Don't manipulate the real sockets
         server_common::portconfig::test_mode = true;
         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() {
     void TearDown() {
         // Make sure no sockets are left inside (if installListenAddresses
         // Make sure no sockets are left inside (if installListenAddresses
         // wasn't used, this is NOP, so it won't hurt).
         // wasn't used, this is NOP, so it won't hurt).
@@ -98,7 +173,17 @@ protected:
         // And return the mode
         // And return the mode
         server_common::portconfig::test_mode = false;
         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,
     void checkTokens(const char** expected,
                      const std::vector<std::string>& real,
                      const std::vector<std::string>& real,
                      const char* scope)
                      const char* scope)