rippled
ShardArchiveHandler_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2020 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/beast/utility/temp_dir.h>
21 #include <ripple/core/ConfigSections.h>
22 #include <ripple/nodestore/DummyScheduler.h>
23 #include <ripple/nodestore/Manager.h>
24 #include <ripple/nodestore/impl/DecodedBlob.h>
25 #include <ripple/protocol/jss.h>
26 #include <ripple/rpc/ShardArchiveHandler.h>
27 #include <test/jtx/Env.h>
28 #include <test/jtx/TrustedPublisherServer.h>
29 #include <test/jtx/envconfig.h>
30 #include <test/nodestore/TestBase.h>
31 
32 namespace ripple {
33 namespace test {
34 
35 class ShardArchiveHandler_test : public beast::unit_test::suite
36 {
38 
40  createServer(jtx::Env& env, bool ssl = true)
41  {
45  env.app().getIOService(),
46  list,
47  env.timeKeeper().now() + std::chrono::seconds{3600},
48  ssl};
49  }
50 
51 public:
52  void
54  {
55  testcase("testStateDatabase1");
56 
57  {
58  beast::temp_dir tempDir;
59 
60  auto c = jtx::envconfig();
61  auto& section = c->section(ConfigSection::shardDatabase());
62  section.set("path", tempDir.path());
63  section.set("max_size_gb", "100");
64  c->setupControl(true, true, true);
65 
66  jtx::Env env(*this, std::move(c));
68  env.app(), env.app().getJobQueue());
69  BEAST_EXPECT(handler);
70 
71  BEAST_EXPECT(handler->init());
72 
73  std::string const rawUrl = "https://foo:443/1.tar.lz4";
74  parsedURL url;
75 
76  parseUrl(url, rawUrl);
77  handler->add(1, {url, rawUrl});
78 
79  {
80  std::lock_guard<std::mutex> lock(handler->m_);
81 
82  auto& session{handler->sqliteDB_->getSession()};
83 
84  soci::rowset<soci::row> rs =
85  (session.prepare << "SELECT * FROM State;");
86 
87  uint64_t rowCount = 0;
88 
89  for (auto it = rs.begin(); it != rs.end(); ++it, ++rowCount)
90  {
91  BEAST_EXPECT(it->get<int>(0) == 1);
92  BEAST_EXPECT(it->get<std::string>(1) == rawUrl);
93  }
94 
95  BEAST_EXPECT(rowCount == 1);
96  }
97 
98  handler->release();
99  }
100 
101  // Destroy the singleton so we start fresh in
102  // the next testcase.
104  }
105 
106  void
108  {
109  testcase("testStateDatabase2");
110 
111  {
112  beast::temp_dir tempDir;
113 
114  auto c = jtx::envconfig();
115  auto& section = c->section(ConfigSection::shardDatabase());
116  section.set("path", tempDir.path());
117  section.set("max_size_gb", "100");
118  c->setupControl(true, true, true);
119 
120  jtx::Env env(*this, std::move(c));
122  env.app(), env.app().getJobQueue());
123  BEAST_EXPECT(handler);
124 
125  BEAST_EXPECT(handler->init());
126 
127  Downloads const dl = {{1, "https://foo:443/1.tar.lz4"},
128  {2, "https://foo:443/2.tar.lz4"},
129  {3, "https://foo:443/3.tar.lz4"}};
130 
131  for (auto const& entry : dl)
132  {
133  parsedURL url;
134  parseUrl(url, entry.second);
135  handler->add(entry.first, {url, entry.second});
136  }
137 
138  {
139  std::lock_guard<std::mutex> lock(handler->m_);
140 
141  auto& session{handler->sqliteDB_->getSession()};
142  soci::rowset<soci::row> rs =
143  (session.prepare << "SELECT * FROM State;");
144 
145  uint64_t pos = 0;
146  for (auto it = rs.begin(); it != rs.end(); ++it, ++pos)
147  {
148  BEAST_EXPECT(it->get<int>(0) == dl[pos].first);
149  BEAST_EXPECT(it->get<std::string>(1) == dl[pos].second);
150  }
151 
152  BEAST_EXPECT(pos == dl.size());
153  }
154 
155  handler->release();
156  }
157 
158  // Destroy the singleton so we start fresh in
159  // the next testcase.
161  }
162 
163  void
165  {
166  testcase("testStateDatabase3");
167 
168  {
169  beast::temp_dir tempDir;
170 
171  auto c = jtx::envconfig();
172  auto& section = c->section(ConfigSection::shardDatabase());
173  section.set("path", tempDir.path());
174  section.set("max_size_gb", "100");
175  c->setupControl(true, true, true);
176 
177  jtx::Env env(*this, std::move(c));
179  env.app(), env.app().getJobQueue());
180  BEAST_EXPECT(handler);
181 
182  BEAST_EXPECT(handler->init());
183 
184  auto server = createServer(env);
185  auto host = server.local_endpoint().address().to_string();
186  auto port = std::to_string(server.local_endpoint().port());
187  server.stop();
188 
189  Downloads const dl = [&host, &port] {
190  Downloads ret;
191 
192  for (int i = 1; i <= 10; ++i)
193  {
194  ret.push_back({i,
195  (boost::format("https://%s:%d/%d.tar.lz4") %
196  host % port % i)
197  .str()});
198  }
199 
200  return ret;
201  }();
202 
203  for (auto const& entry : dl)
204  {
205  parsedURL url;
206  parseUrl(url, entry.second);
207  handler->add(entry.first, {url, entry.second});
208  }
209 
210  BEAST_EXPECT(handler->start());
211 
213  env.app().config());
214 
215  std::unique_lock<std::mutex> lock(handler->m_);
216 
217  BEAST_EXPECT(
218  boost::filesystem::exists(stateDir) ||
219  handler->archives_.empty());
220 
221  while (!handler->archives_.empty())
222  {
223  lock.unlock();
225  lock.lock();
226  }
227 
228  BEAST_EXPECT(!boost::filesystem::exists(stateDir));
229  }
230 
231  // Destroy the singleton so we start fresh in
232  // the next testcase.
234  }
235 
236  void
238  {
239  testcase("testStateDatabase4");
240 
241  beast::temp_dir tempDir;
242 
243  {
244  auto c = jtx::envconfig();
245  auto& section = c->section(ConfigSection::shardDatabase());
246  section.set("path", tempDir.path());
247  section.set("max_size_gb", "100");
248  c->setupControl(true, true, true);
249 
250  jtx::Env env(*this, std::move(c));
252  env.app(), env.app().getJobQueue());
253  BEAST_EXPECT(handler);
254 
255  BEAST_EXPECT(handler->init());
256 
257  auto server = createServer(env);
258  auto host = server.local_endpoint().address().to_string();
259  auto port = std::to_string(server.local_endpoint().port());
260  server.stop();
261 
262  Downloads const dl = [&host, &port] {
263  Downloads ret;
264 
265  for (int i = 1; i <= 10; ++i)
266  {
267  ret.push_back({i,
268  (boost::format("https://%s:%d/%d.tar.lz4") %
269  host % port % i)
270  .str()});
271  }
272 
273  return ret;
274  }();
275 
276  for (auto const& entry : dl)
277  {
278  parsedURL url;
279  parseUrl(url, entry.second);
280  handler->add(entry.first, {url, entry.second});
281  }
282 
284  env.app().config());
285 
286  boost::filesystem::copy_file(
287  stateDir / stateDBName,
288  boost::filesystem::path(tempDir.path()) / stateDBName);
289 
290  BEAST_EXPECT(handler->start());
291 
292  std::unique_lock<std::mutex> lock(handler->m_);
293 
294  BEAST_EXPECT(
295  boost::filesystem::exists(stateDir) ||
296  handler->archives_.empty());
297 
298  while (!handler->archives_.empty())
299  {
300  lock.unlock();
302  lock.lock();
303  }
304 
305  BEAST_EXPECT(!boost::filesystem::exists(stateDir));
306 
307  boost::filesystem::create_directory(stateDir);
308 
309  boost::filesystem::copy_file(
310  boost::filesystem::path(tempDir.path()) / stateDBName,
311  stateDir / stateDBName);
312  }
313 
314  // Destroy the singleton so we start fresh in
315  // the new scope.
317 
318  auto c = jtx::envconfig();
319  auto& section = c->section(ConfigSection::shardDatabase());
320  section.set("path", tempDir.path());
321  section.set("max_size_gb", "100");
322  c->setupControl(true, true, true);
323 
324  jtx::Env env(*this, std::move(c));
325 
328 
330 
331  auto handler = RPC::ShardArchiveHandler::getInstance();
332 
333  auto stateDir =
335 
336  std::unique_lock<std::mutex> lock(handler->m_);
337 
338  BEAST_EXPECT(
339  boost::filesystem::exists(stateDir) || handler->archives_.empty());
340 
341  while (!handler->archives_.empty())
342  {
343  lock.unlock();
345  lock.lock();
346  }
347 
348  BEAST_EXPECT(!boost::filesystem::exists(stateDir));
349  }
350 
351  void
352  run() override
353  {
358  }
359 };
360 
361 BEAST_DEFINE_TESTSUITE(ShardArchiveHandler, app, ripple);
362 
363 } // namespace test
364 } // namespace ripple
ripple::RPC::ShardArchiveHandler::getDownloadDirectory
static boost::filesystem::path getDownloadDirectory(Config const &config)
Definition: ShardArchiveHandler.cpp:41
std::this_thread::sleep_for
T sleep_for(T... args)
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
std::string
STL class.
ripple::parsedURL
Definition: StringUtilities.h:122
std::vector
STL class.
ripple::ConfigSection::shardDatabase
static std::string shardDatabase()
Definition: ConfigSections.h:33
std::chrono::seconds
ripple::test::ShardArchiveHandler_test::testStateDatabase2
void testStateDatabase2()
Definition: ShardArchiveHandler_test.cpp:107
std::lock_guard
STL class.
ripple::test::jtx::Env::timeKeeper
ManualTimeKeeper & timeKeeper()
Definition: Env.h:249
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:237
ripple::test::jtx::envconfig
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:52
std::shared_ptr::reset
T reset(T... args)
std::vector::push_back
T push_back(T... args)
ripple::RPC::ShardArchiveHandler::instance_
static pointer instance_
Definition: ShardArchiveHandler.h:127
ripple::Application::config
virtual Config & config()=0
ripple::test::ShardArchiveHandler_test::testStateDatabase3
void testStateDatabase3()
Definition: ShardArchiveHandler_test.cpp:164
std::unique_lock
STL class.
std::to_string
T to_string(T... args)
ripple::Application::getJobQueue
virtual JobQueue & getJobQueue()=0
ripple::parseUrl
bool parseUrl(parsedURL &pUrl, std::string const &strUrl)
Definition: StringUtilities.cpp:53
ripple::test::TrustedPublisherServer
Definition: TrustedPublisherServer.h:42
ripple::test::TrustedPublisherServer::randomValidator
static Validator randomValidator()
Definition: TrustedPublisherServer.h:128
beast::temp_dir::path
std::string path() const
Get the native path for the temporary directory.
Definition: temp_dir.h:68
ripple::Application::getIOService
virtual boost::asio::io_service & getIOService()=0
ripple::test::ShardArchiveHandler_test::createServer
TrustedPublisherServer createServer(jtx::Env &env, bool ssl=true)
Definition: ShardArchiveHandler_test.cpp:40
ripple::stateDBName
static constexpr auto stateDBName
Definition: DBInit.h:186
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::RPC::ShardArchiveHandler::hasInstance
static bool hasInstance()
Definition: ShardArchiveHandler.cpp:81
ripple::test::ShardArchiveHandler_test::run
void run() override
Definition: ShardArchiveHandler_test.cpp:352
ripple::test::ShardArchiveHandler_test
Definition: ShardArchiveHandler_test.cpp:35
ripple::test::ManualTimeKeeper::now
time_point now() const override
Returns the estimate of wall time, in network time.
Definition: ManualTimeKeeper.cpp:39
ripple::test::ShardArchiveHandler_test::testStateDatabase1
void testStateDatabase1()
Definition: ShardArchiveHandler_test.cpp:53
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:117
ripple::RPC::ShardArchiveHandler::getInstance
static pointer getInstance()
Definition: ShardArchiveHandler.cpp:50
beast::temp_dir
RAII temporary directory.
Definition: temp_dir.h:33
ripple::test::ShardArchiveHandler_test::testStateDatabase4
void testStateDatabase4()
Definition: ShardArchiveHandler_test.cpp:237