1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// Copyright (C) 2017-2024 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/.

#ifndef TEST_SERVER_UNIX_SOCKET_H
#define TEST_SERVER_UNIX_SOCKET_H

#include <config.h>
#include <asiolink/interval_timer.h>
#include <asiolink/io_service.h>
#include <boost/shared_ptr.hpp><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <gtest/gtest.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <list><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <stdint.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <string><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <mutex><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <condition_variable><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

namespace isc {
namespace asiolink {
namespace test {

class ConnectionPool;

/// @brief Provides unix domain socket functionality for unit tests.
///
/// This class represents a server side socket. It can be used to
/// test client's transmission over the unix domain socket. By default,
/// the server side socket echoes the client's message so the client's
/// message (prefixed with the word "received").
///
/// It is also possible to specify a custom response from the server
/// instead of echoing back the request.
///
/// It is possible to make multiple connections to the server side
/// socket simultaneously.
///
/// The test should perform IOService::runOne until it finds that
/// the number of responses sent by the server is greater than
/// expected. The number of responses sent so far can be retrieved
/// using @ref TestServerUnixSocket::getResponseNum.
///
/// This class uses @c shared_from_this() to pass its instance to the
/// @c std::bind function, thus the caller must store shared pointer
/// to this object.
class TestServerUnixSocket {
public:

    /// @brief Constructor.
    ///
    /// @param io_service IO service.
    /// @param socket_file_path Socket file path.
    /// @param custom_response Custom response to be sent to the client.
    TestServerUnixSocket(const IOServicePtr& io_service,
                         const std::string& socket_file_path,
                         const std::string& custom_response = "");

    /// @brief Destructor.
    ///
    /// Closes active connections.
    ~TestServerUnixSocket();

    /// @brief Starts timer for detecting test timeout.
    ///
    /// @param test_timeout Test timeout in milliseconds.
    void startTimer(const long test_timeout);

    /// @brief Cancels all asynchronous operations.
    void stopServer();

    /// @brief Generates response of a given length.
    ///
    /// Note: The response may be a few bytes larger than requested.
    ///
    /// @param response_size Desired response size.
    void generateCustomResponse(const uint64_t response_size);

    /// @brief Creates and binds server socket.
    ///
    /// @param use_thread Boolean value indicating if the IO service
    /// is running in thread.
    void bindServerSocket(const bool use_thread = false);

    /// @brief Server acceptor handler.
    ///
    /// @param ec Error code.
    void acceptHandler(const boost::system::error_code& ec);

    /// @brief Callback function invoke upon test timeout.
    ///
    /// It stops the IO service and reports test timeout.
    void timeoutHandler();

    /// @brief Return number of responses sent so far to the clients.
    size_t getResponseNum() const;

    /// @brief Indicates if the server has been stopped.
    bool isStopped() {
        return (stopped_);
    }

    /// @brief Waits for the server signal that it is running.
    ///
    /// When the caller starts the service he indicates whether
    /// IO service will be running in thread or not. If threads
    /// are used the caller has to wait for the IO service to
    /// actually run. In such case this function should be invoked
    /// which waits for a posted callback to be executed. When this
    /// happens it means that IO service is running and the main
    /// thread can move forward.
    void waitForRunning();

private:

    /// @brief Asynchronously accept new connections.
    void accept();

    /// @brief Handler invoked to signal that server is running.
    ///
    /// This is used only when thread is used to run IO service.
    void signalRunning();

    /// @brief IO service used by the tests.
    IOServicePtr io_service_;

    /// @brief Server endpoint.
    boost::asio::local::stream_protocol::endpoint server_endpoint_;
    /// @brief Server acceptor.
    boost::asio::local::stream_protocol::acceptor server_acceptor_;

    /// @brief Asynchronous timer service to detect timeouts.
    IntervalTimer test_timer_;

    /// @brief Holds custom response to be sent to the client.
    std::string custom_response_;

    /// @brief Pool of connections.
    boost::shared_ptr<ConnectionPool> connection_pool_;

    /// @brief Indicates if IO service has been stopped as a result of
    /// a timeout.
    bool stopped_;

    /// @brief Indicates if the server in a thread is running.
    bool running_;

    /// @brief Mutex used by the server.
    ///
    /// Mutex is used in situations when server's IO service is being run in a
    /// thread to synchronize this thread with a main thread using
    /// @ref signalRunning and @ref waitForRunning.
    std::mutex mutex_;

    /// @brief Conditional variable used by the server.
    ///
    /// Conditional variable is used in situations when server's IO service is
    /// being run in a thread to synchronize this thread with a main thread
    /// using @ref signalRunning and @ref waitForRunning.
    std::condition_variable condvar_;
};

/// @brief Pointer to the @ref TestServerUnixSocket.
typedef boost::shared_ptr<TestServerUnixSocket> TestServerUnixSocketPtr;

} // end of namespace isc::asiolink::test
} // end of namespace isc::asiolink
} // end of namespace isc

#endif // TEST_SERVER_UNIX_SOCKET_H