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 = {
128  {1, "https://foo:443/1.tar.lz4"},
129  {2, "https://foo:443/2.tar.lz4"},
130  {3, "https://foo:443/3.tar.lz4"}};
131 
132  for (auto const& entry : dl)
133  {
134  parsedURL url;
135  parseUrl(url, entry.second);
136  handler->add(entry.first, {url, entry.second});
137  }
138 
139  {
140  std::lock_guard<std::mutex> lock(handler->m_);
141 
142  auto& session{handler->sqliteDB_->getSession()};
143  soci::rowset<soci::row> rs =
144  (session.prepare << "SELECT * FROM State;");
145 
146  uint64_t pos = 0;
147  for (auto it = rs.begin(); it != rs.end(); ++it, ++pos)
148  {
149  BEAST_EXPECT(it->get<int>(0) == dl[pos].first);
150  BEAST_EXPECT(it->get<std::string>(1) == dl[pos].second);
151  }
152 
153  BEAST_EXPECT(pos == dl.size());
154  }
155 
156  handler->release();
157  }
158 
159  // Destroy the singleton so we start fresh in
160  // the next testcase.
162  }
163 
164  void
166  {
167  testcase("testStateDatabase3");
168 
169  {
170  beast::temp_dir tempDir;
171 
172  auto c = jtx::envconfig();
173  auto& section = c->section(ConfigSection::shardDatabase());
174  section.set("path", tempDir.path());
175  section.set("max_size_gb", "100");
176  c->setupControl(true, true, true);
177 
178  jtx::Env env(*this, std::move(c));
180  env.app(), env.app().getJobQueue());
181  BEAST_EXPECT(handler);
182 
183  BEAST_EXPECT(handler->init());
184 
185  auto server = createServer(env);
186  auto host = server.local_endpoint().address().to_string();
187  auto port = std::to_string(server.local_endpoint().port());
188  server.stop();
189 
190  Downloads const dl = [&host, &port] {
191  Downloads ret;
192 
193  for (int i = 1; i <= 10; ++i)
194  {
195  ret.push_back(
196  {i,
197  (boost::format("https://%s:%d/%d.tar.lz4") % host %
198  port % i)
199  .str()});
200  }
201 
202  return ret;
203  }();
204 
205  for (auto const& entry : dl)
206  {
207  parsedURL url;
208  parseUrl(url, entry.second);
209  handler->add(entry.first, {url, entry.second});
210  }
211 
212  BEAST_EXPECT(handler->start());
213 
215  env.app().config());
216 
217  std::unique_lock<std::mutex> lock(handler->m_);
218 
219  BEAST_EXPECT(
220  boost::filesystem::exists(stateDir) ||
221  handler->archives_.empty());
222 
223  while (!handler->archives_.empty())
224  {
225  lock.unlock();
227  lock.lock();
228  }
229 
230  BEAST_EXPECT(!boost::filesystem::exists(stateDir));
231  }
232 
233  // Destroy the singleton so we start fresh in
234  // the next testcase.
236  }
237 
238  void
240  {
241  testcase("testStateDatabase4");
242 
243  beast::temp_dir tempDir;
244 
245  {
246  auto c = jtx::envconfig();
247  auto& section = c->section(ConfigSection::shardDatabase());
248  section.set("path", tempDir.path());
249  section.set("max_size_gb", "100");
250  c->setupControl(true, true, true);
251 
252  jtx::Env env(*this, std::move(c));
254  env.app(), env.app().getJobQueue());
255  BEAST_EXPECT(handler);
256 
257  BEAST_EXPECT(handler->init());
258 
259  auto server = createServer(env);
260  auto host = server.local_endpoint().address().to_string();
261  auto port = std::to_string(server.local_endpoint().port());
262  server.stop();
263 
264  Downloads const dl = [&host, &port] {
265  Downloads ret;
266 
267  for (int i = 1; i <= 10; ++i)
268  {
269  ret.push_back(
270  {i,
271  (boost::format("https://%s:%d/%d.tar.lz4") % host %
272  port % i)
273  .str()});
274  }
275 
276  return ret;
277  }();
278 
279  for (auto const& entry : dl)
280  {
281  parsedURL url;
282  parseUrl(url, entry.second);
283  handler->add(entry.first, {url, entry.second});
284  }
285 
287  env.app().config());
288 
289  boost::filesystem::copy_file(
290  stateDir / stateDBName,
291  boost::filesystem::path(tempDir.path()) / stateDBName);
292 
293  BEAST_EXPECT(handler->start());
294 
295  std::unique_lock<std::mutex> lock(handler->m_);
296 
297  BEAST_EXPECT(
298  boost::filesystem::exists(stateDir) ||
299  handler->archives_.empty());
300 
301  while (!handler->archives_.empty())
302  {
303  lock.unlock();
305  lock.lock();
306  }
307 
308  BEAST_EXPECT(!boost::filesystem::exists(stateDir));
309 
310  boost::filesystem::create_directory(stateDir);
311 
312  boost::filesystem::copy_file(
313  boost::filesystem::path(tempDir.path()) / stateDBName,
314  stateDir / stateDBName);
315  }
316 
317  // Destroy the singleton so we start fresh in
318  // the new scope.
320 
321  auto c = jtx::envconfig();
322  auto& section = c->section(ConfigSection::shardDatabase());
323  section.set("path", tempDir.path());
324  section.set("max_size_gb", "100");
325  c->setupControl(true, true, true);
326 
327  jtx::Env env(*this, std::move(c));
328 
331 
333 
334  auto handler = RPC::ShardArchiveHandler::getInstance();
335 
336  auto stateDir =
338 
339  std::unique_lock<std::mutex> lock(handler->m_);
340 
341  BEAST_EXPECT(
342  boost::filesystem::exists(stateDir) || handler->archives_.empty());
343 
344  while (!handler->archives_.empty())
345  {
346  lock.unlock();
348  lock.lock();
349  }
350 
351  BEAST_EXPECT(!boost::filesystem::exists(stateDir));
352  }
353 
354  void
355  run() override
356  {
361  }
362 };
363 
364 BEAST_DEFINE_TESTSUITE(ShardArchiveHandler, app, ripple);
365 
366 } // namespace test
367 } // 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:123
std::vector
STL class.
ripple::ConfigSection::shardDatabase
static std::string shardDatabase()
Definition: ConfigSections.h:38
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:250
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:238
ripple::test::jtx::envconfig
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:49
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:126
ripple::Application::config
virtual Config & config()=0
ripple::test::ShardArchiveHandler_test::testStateDatabase3
void testStateDatabase3()
Definition: ShardArchiveHandler_test.cpp:165
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:55
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:66
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:173
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:83
ripple::test::ShardArchiveHandler_test::run
void run() override
Definition: ShardArchiveHandler_test.cpp:355
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:37
ripple::test::ShardArchiveHandler_test::testStateDatabase1
void testStateDatabase1()
Definition: ShardArchiveHandler_test.cpp:53
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:114
ripple::RPC::ShardArchiveHandler::getInstance
static pointer getInstance()
Definition: ShardArchiveHandler.cpp:52
beast::temp_dir
RAII temporary directory.
Definition: temp_dir.h:33
ripple::test::ShardArchiveHandler_test::testStateDatabase4
void testStateDatabase4()
Definition: ShardArchiveHandler_test.cpp:239