Skip to content

Commit d9b40ce

Browse files
committed
Allow mock testing using the async_resolver and async_connection.
1 parent 44d6943 commit d9b40ce

File tree

6 files changed

+185
-45
lines changed

6 files changed

+185
-45
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ if(CPP-NETLIB_BUILD_TESTS)
136136

137137
set(GMOCK_ROOT ${CPP-NETLIB_SOURCE_DIR}/deps/gmock)
138138
set(GMOCK_FOUND ON)
139-
set(GMOCK_INCLUDE_DIRS ${GTEST_INCLUDE_DIRS} {${GMOCK_DIR}/include)
140-
set(GMOCK_LIBRARY {$GTEST_LIBRARIES} gmock)
139+
set(GMOCK_INCLUDE_DIRS ${GTEST_INCLUDE_DIRS} ${GMOCK_ROOT}/include)
140+
set(GMOCK_LIBRARY ${GTEST_LIBRARIES} gmock)
141141
set(GMOCK_MAIN_LIBRARY gmock_main)
142142
set(GMOCK_BOTH_LIBRARIES ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY})
143143

http/src/http/v2/client/client.cpp

Lines changed: 68 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace network {
2424

2525
struct request_helper {
2626

27-
std::unique_ptr<client_connection::async_connection> connection_;
27+
std::shared_ptr<client_connection::async_connection> connection_;
2828

2929
client::request request_;
3030
client::request_options options_;
@@ -36,23 +36,26 @@ namespace network {
3636

3737
// TODO configure deadline timer for timeouts
3838

39-
request_helper(boost::asio::io_service &io_service,
39+
request_helper(std::shared_ptr<client_connection::async_connection> connection,
4040
client::request request,
4141
client::request_options options)
42-
// TODO factory based on HTTP or HTTPS
43-
: connection_(new client_connection::normal_connection(io_service))
42+
: connection_(connection)
4443
, request_(request)
4544
, options_(options) { }
4645

4746
};
4847

4948
struct client::impl {
5049

51-
explicit impl(client_options options);
50+
explicit impl(client_options options);
51+
52+
impl(std::unique_ptr<client_connection::async_resolver> mock_resolver,
53+
std::unique_ptr<client_connection::async_connection> mock_connection,
54+
client_options options);
5255

53-
~impl() noexcept;
56+
~impl() noexcept;
5457

55-
std::future<response> do_request(std::shared_ptr<request_helper> helper);
58+
std::future<response> execute(std::shared_ptr<request_helper> helper);
5659

5760
void connect(const boost::system::error_code &ec,
5861
tcp::resolver::iterator endpoint_iterator,
@@ -80,30 +83,42 @@ namespace network {
8083
std::shared_ptr<request_helper> helper,
8184
std::shared_ptr<response> res);
8285

83-
client_options options_;
84-
boost::asio::io_service io_service_;
85-
std::unique_ptr<boost::asio::io_service::work> sentinel_;
86+
client_options options_;
87+
boost::asio::io_service io_service_;
88+
std::unique_ptr<boost::asio::io_service::work> sentinel_;
8689
boost::asio::io_service::strand strand_;
8790
std::unique_ptr<client_connection::async_resolver> resolver_;
88-
std::thread lifetime_thread_;
91+
std::shared_ptr<client_connection::async_connection> mock_connection_;
92+
std::thread lifetime_thread_;
8993

9094
};
9195

9296
client::impl::impl(client_options options)
93-
: options_(options)
94-
, sentinel_(new boost::asio::io_service::work(io_service_))
97+
: options_(options)
98+
, sentinel_(new boost::asio::io_service::work(io_service_))
9599
, strand_(io_service_)
96-
, resolver_(new client_connection::tcp_resolver(io_service_, options_.cache_resolved()))
97-
, lifetime_thread_([=] () { io_service_.run(); }) {
100+
, resolver_(new client_connection::tcp_resolver(io_service_, options_.cache_resolved()))
101+
, lifetime_thread_([=] () { io_service_.run(); }) {
102+
103+
}
104+
105+
client::impl::impl(std::unique_ptr<client_connection::async_resolver> mock_resolver,
106+
std::unique_ptr<client_connection::async_connection> mock_connection,
107+
client_options options)
108+
: options_(options)
109+
, sentinel_(new boost::asio::io_service::work(io_service_))
110+
, strand_(io_service_)
111+
, resolver_(std::move(mock_resolver))
112+
, lifetime_thread_([=] () { io_service_.run(); }) {
98113

99114
}
100115

101116
client::impl::~impl() noexcept {
102-
sentinel_.reset();
103-
lifetime_thread_.join();
117+
sentinel_.reset();
118+
lifetime_thread_.join();
104119
}
105120

106-
std::future<client::response> client::impl::do_request(std::shared_ptr<request_helper> helper) {
121+
std::future<client::response> client::impl::execute(std::shared_ptr<request_helper> helper) {
107122
std::future<client::response> res = helper->response_promise_.get_future();
108123

109124
// TODO see linearize.hpp
@@ -131,14 +146,14 @@ namespace network {
131146
uri::string_type(std::begin(*auth.host()), std::end(*auth.host())) : uri::string_type();
132147
auto port = auth.port<std::uint16_t>()? *auth.port<std::uint16_t>() : 80;
133148

134-
resolver_->async_resolve(host, port,
149+
resolver_->async_resolve(host, port,
135150
strand_.wrap(
136151
[=](const boost::system::error_code &ec,
137152
tcp::resolver::iterator endpoint_iterator) {
138153
connect(ec, endpoint_iterator, helper);
139154
}));
140155

141-
return res;
156+
return res;
142157
}
143158

144159
void client::impl::connect(const boost::system::error_code &ec,
@@ -322,42 +337,61 @@ namespace network {
322337
}
323338

324339
client::client(client_options options)
325-
: pimpl_(new impl(options)) {
340+
: pimpl_(new impl(options)) {
341+
342+
}
343+
344+
client::client(std::unique_ptr<client_connection::async_resolver> mock_resolver,
345+
std::unique_ptr<client_connection::async_connection> mock_connection,
346+
client_options options)
347+
: pimpl_(new impl(std::move(mock_resolver), std::move(mock_connection), options)) {
326348

327349
}
328350

329351
client::~client() noexcept {
330-
delete pimpl_;
352+
delete pimpl_;
353+
}
354+
355+
std::future<client::response> client::execute(request req, request_options options) {
356+
std::shared_ptr<client_connection::async_connection> connection;
357+
if (pimpl_->mock_connection_) {
358+
connection = pimpl_->mock_connection_;
359+
}
360+
else {
361+
// TODO factory based on HTTP or HTTPS
362+
connection = std::make_shared<client_connection::normal_connection>(pimpl_->io_service_);
363+
}
364+
return pimpl_->execute(std::make_shared<request_helper>(connection, req, options));
331365
}
332366

333367
std::future<client::response> client::get(request req, request_options options) {
334-
req.method(method::get);
335-
return pimpl_->do_request(std::make_shared<request_helper>(pimpl_->io_service_, req, options));
368+
req.method(method::get);
369+
return execute(req, options);
336370
}
337371

338372
std::future<client::response> client::post(request req, request_options options) {
339-
req.method(method::post);
340-
return pimpl_->do_request(std::make_shared<request_helper>(pimpl_->io_service_, req, options));
373+
req.method(method::post);
374+
return execute(req, options);
341375
}
342376

343377
std::future<client::response> client::put(request req, request_options options) {
344-
req.method(method::put);
345-
return pimpl_->do_request(std::make_shared<request_helper>(pimpl_->io_service_, req, options));
378+
req.method(method::put);
379+
return execute(req, options);
346380
}
347381

348382
std::future<client::response> client::delete_(request req, request_options options) {
349-
req.method(method::delete_);
350-
return pimpl_->do_request(std::make_shared<request_helper>(pimpl_->io_service_, req, options));
383+
req.method(method::delete_);
384+
return execute(req, options);
351385
}
352386

353387
std::future<client::response> client::head(request req, request_options options) {
354-
req.method(method::head);
355-
return pimpl_->do_request(std::make_shared<request_helper>(pimpl_->io_service_, req, options));
388+
req.method(method::head);
389+
return execute(req, options);
356390
}
357391

358392
std::future<client::response> client::options(request req, request_options options) {
359-
req.method(method::options);
360-
return pimpl_->do_request(std::make_shared<request_helper>(pimpl_->io_service_, req, options));
393+
req.method(method::options);
394+
return execute(req, options);
361395
}
362396
} // namespace v2
363397
} // namespace http

http/src/network/http/v2/client/client.hpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
namespace network {
3030
namespace http {
3131
namespace v2 {
32+
namespace client_connection {
33+
class async_resolver;
34+
class async_connection;
35+
} // namespace client_connection
36+
3237
/**
3338
* \ingroup http_client
3439
* \class client_options network/http/v2/client/client.hpp network/http/v2/client.hpp
@@ -240,8 +245,8 @@ namespace network {
240245
*/
241246
class client {
242247

243-
client(client const &) = delete;
244-
client(client &&) = delete;
248+
client(const client&) = delete;
249+
client& operator=(const client&) = delete;
245250

246251
public:
247252

@@ -261,48 +266,59 @@ namespace network {
261266
*/
262267
explicit client(client_options options = client_options());
263268

269+
client(std::unique_ptr<client_connection::async_resolver> mock_resolver,
270+
std::unique_ptr<client_connection::async_connection> mock_connection,
271+
client_options options = client_options());
272+
264273
/**
265274
* \brief Destructor.
266275
*/
267276
~client() noexcept;
268277

269278
/**
270-
* \brief Makes an HTTP GET request.
279+
* \brief Executes an HTTP request.
280+
* \param req The request object.
281+
* \param options The request options.
282+
*/
283+
std::future<response> execute(request req, request_options options = request_options());
284+
285+
/**
286+
* \brief Executes an HTTP GET request.
271287
* \param req The request object.
272288
* \param options The request options.
273289
*/
274290
std::future<response> get(request req, request_options options = request_options());
275291

276292
/**
277-
* \brief Makes an HTTP POST request.
293+
* \brief Executes an HTTP POST request.
278294
* \param req The request object.
279295
* \param options The request options.
280296
*/
281297
std::future<response> post(request req, request_options options = request_options());
282298

283299
/**
284-
* \brief Makes an HTTP PUT request.
300+
* \brief Executes an HTTP PUT request.
285301
* \param req The request object.
286302
* \param options The request options.
287303
*/
288304
std::future<response> put(request req, request_options options = request_options());
289305

290306
/**
291-
* \brief Makes an HTTP DELETE request.
307+
* \brief Executes an HTTP DELETE request.
292308
* \param req The request object.
293309
* \param options The request options.
294310
*/
295311
std::future<response> delete_(request req, request_options options = request_options());
296312

297313
/**
298-
* \brief Makes an HTTP HEAD request.
314+
* \brief Executes an HTTP HEAD request.
299315
* \param req The request object.
300316
* \param options The request options.
301317
*/
302318
std::future<response> head(request req, request_options options = request_options());
303319

304320
/**
305-
* \brief Makes an HTTP OPTIONS request.
321+
* \brief Executes an HTTP OPTIONS request.
306322
* \param req The request object.
307323
* \param options The request options.
308324
*/

http/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ include_directories(
1212
${CPP-NETLIB_SOURCE_DIR}/logging/src
1313
${CPP-NETLIB_SOURCE_DIR}/http/src
1414
${GTEST_INCLUDE_DIRS}
15+
${GMOCK_INCLUDE_DIRS}
1516
${IGLOO_INCLUDE_DIR}
1617
${CPP-NETLIB_SOURCE_DIR})
1718

http/test/v2/client/units/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
set(CPP-NETLIB_CLIENT_TESTS
77
client_options_test
8+
client_resolution_test
89
request_options_test
910
byte_source_test
1011
request_test
@@ -23,7 +24,7 @@ foreach(test ${CPP-NETLIB_CLIENT_TESTS})
2324
network-uri
2425
network-http-v2-client
2526
${Boost_LIBRARIES}
26-
${GTEST_BOTH_LIBRARIES}
27+
${GMOCK_BOTH_LIBRARIES}
2728
${ICU_LIBRARIES} ${ICU_I18N_LIBRARIES}
2829
${CMAKE_THREAD_LIBS_INIT}
2930
)

0 commit comments

Comments
 (0)