blob: 48ec17d2d862757b55a411e73a29dfd718288834 [file] [log] [blame]
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
weijia yuan3aa8d2b2018-03-06 15:35:57 -08003 * Copyright (c) 2014-2018, Regents of the University of California.
Alexander Afanasyeve1e6f2a2014-04-25 11:28:12 -07004 *
5 * This file is part of NDN repo-ng (Next generation of NDN repository).
6 * See AUTHORS.md for complete list of repo-ng authors and contributors.
7 *
8 * repo-ng is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * repo-ng is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -070018 */
19
Alexander Afanasyev39d98072014-05-04 12:46:29 -070020#include "handles/tcp-bulk-insert-handle.hpp"
Weiqi Shif0330d52014-07-09 10:54:27 -070021#include "storage/sqlite-storage.hpp"
22#include "../repo-storage-fixture.hpp"
Shuo Chenca329182014-03-19 18:05:18 -070023#include "../dataset-fixtures.hpp"
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -070024
25#include <boost/test/unit_test.hpp>
26
27namespace repo {
28namespace tests {
29
30BOOST_AUTO_TEST_SUITE(TcpBulkInsertHandle)
31
32class TcpClient
33{
34public:
35 TcpClient()
36 : socket(ioService)
37 {
38 }
39
Junxiao Shie1801312017-07-22 19:16:49 +000040 virtual
41 ~TcpClient() = default;
42
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -070043 void
44 start(const std::string& host, const std::string& port)
45 {
46 using namespace boost::asio;
47
48 ip::tcp::resolver resolver(ioService);
49 ip::tcp::resolver::query query(host, port);
50
51 ip::tcp::resolver::iterator endpoint = resolver.resolve(query);
52 ip::tcp::resolver::iterator end;
53
54 if (endpoint == end)
55 BOOST_FAIL("Cannot resolve [" + host + ":" + port + "]");
56
57 ip::tcp::endpoint serverEndpoint = *endpoint;
58
59 socket.async_connect(serverEndpoint,
weijia yuan3aa8d2b2018-03-06 15:35:57 -080060 std::bind(&TcpClient::onSuccessfullConnect, this, _1));
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -070061 }
62
63 virtual void
64 onSuccessfullConnect(const boost::system::error_code& error)
65 {
weijia yuan3aa8d2b2018-03-06 15:35:57 -080066 if (error) {
67 BOOST_FAIL("TCP connection aborted");
68 return;
69 }
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -070070 }
71
72public:
73 boost::asio::io_service ioService;
74 boost::asio::ip::tcp::socket socket;
75};
76
77template<class Dataset>
78class TcpBulkInsertFixture : public TcpClient,
Weiqi Shif0330d52014-07-09 10:54:27 -070079 public RepoStorageFixture,
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -070080 public Dataset
81{
82public:
83 TcpBulkInsertFixture()
84 : scheduler(ioService)
85 , bulkInserter(ioService, *handle)
86 {
87 guardEvent = scheduler.scheduleEvent(ndn::time::seconds(2),
weijia yuan3aa8d2b2018-03-06 15:35:57 -080088 std::bind(&TcpBulkInsertFixture::fail, this, "Test timed out"));
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -070089 }
90
91 virtual void
92 onSuccessfullConnect(const boost::system::error_code& error)
93 {
94 TcpClient::onSuccessfullConnect(error);
95
96 // This value may need to be adjusted if some dataset exceeds 100k
97 socket.set_option(boost::asio::socket_base::send_buffer_size(100000));
98
99 // Initially I wrote the following to use scatter-gather approach (using
100 // std::vector<const_buffer> and a single socket.async_send operation). Unfortunately, as
101 // described in http://www.boost.org/doc/libs/1_48_0/doc/html/boost_asio/overview/implementation.html,
102 // scatter-gather is limited to at most `min(64,IOV_MAX)` buffers to be transmitted
103 // in a single operation
weijia yuan3aa8d2b2018-03-06 15:35:57 -0800104 for (auto i = this->data.begin(); i != this->data.end(); ++i) {
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -0700105
weijia yuan3aa8d2b2018-03-06 15:35:57 -0800106 socket.async_send(boost::asio::buffer((*i)->wireEncode().wire(), (*i)->wireEncode().size()),
107 std::bind(&TcpBulkInsertFixture::onSendFinished, this, _1, false));
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -0700108 }
weijia yuan3aa8d2b2018-03-06 15:35:57 -0800109 onSendFinished(error, true);
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -0700110 }
111
112 void
113 onSendFinished(const boost::system::error_code& error, bool isFinal)
114 {
115 if (error) {
116 BOOST_FAIL("TCP connection aborted");
117 return;
118 }
119
120 if (isFinal) {
121 scheduler.cancelEvent(guardEvent);
122
123 // In case there are some outstanding handlers
124 // ioService.post(bind(&TcpBulkInsertFixture::stop, this));
125 scheduler.scheduleEvent(ndn::time::seconds(1),
weijia yuan3aa8d2b2018-03-06 15:35:57 -0800126 std::bind(&TcpBulkInsertFixture::stop, this));
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -0700127 }
128 }
129
130 void
131 fail(const std::string& info)
132 {
133 ioService.stop();
134 BOOST_FAIL(info);
135 }
136
137 void
138 stop()
139 {
140 // Terminate test
141 socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);
142 socket.close();
143
144 bulkInserter.stop();
145 // may be ioService.stop() as well
146 }
147
148public:
149 Scheduler scheduler;
150 ndn::EventId guardEvent;
151 repo::TcpBulkInsertHandle bulkInserter;
152};
153
154
Alexander Afanasyev595b2bd2014-12-14 12:55:36 -0800155BOOST_FIXTURE_TEST_CASE_TEMPLATE(BulkInsertAndRead, T, CommonDatasets, TcpBulkInsertFixture<T>)
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -0700156{
157 BOOST_TEST_MESSAGE(T::getName());
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -0700158
159 // start bulk inserter
160 this->bulkInserter.listen("localhost", "17376");
161
162 // start test
163 this->start("localhost", "17376");
164
165 // actually run the test
166 this->ioService.run();
167
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -0700168 // Read (all items should exist)
weijia yuan3aa8d2b2018-03-06 15:35:57 -0800169 for (auto i = this->interests.begin(); i != this->interests.end(); ++i) {
170 BOOST_CHECK_EQUAL(*this->handle->readData(i->first), *i->second);
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -0700171 }
172}
173
174
175BOOST_AUTO_TEST_SUITE_END()
176
Alexander Afanasyevb0c78ea2014-04-15 18:12:04 -0700177} // namespace tests
Junxiao Shie1801312017-07-22 19:16:49 +0000178} // namespace repo