mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-19 19:25:53 +00:00
27
unittests/Main.cpp
Normal file
27
unittests/Main.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2023, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -103,8 +103,8 @@ TEST_F(BackendCassandraFactoryTestWithDB, CreateCassandraBackend)
|
||||
R"({{
|
||||
"database":
|
||||
{{
|
||||
"type" : "cassandra",
|
||||
"cassandra" : {{
|
||||
"type": "cassandra",
|
||||
"cassandra": {{
|
||||
"contact_points": "{}",
|
||||
"keyspace": "{}",
|
||||
"replication_factor": 1
|
||||
@@ -113,19 +113,22 @@ TEST_F(BackendCassandraFactoryTestWithDB, CreateCassandraBackend)
|
||||
}})",
|
||||
contactPoints,
|
||||
keyspace))};
|
||||
// FIXME: this currently throws runtime_error (Could not create keyspace). no idea why
|
||||
auto backend = make_Backend(ctx, cfg);
|
||||
EXPECT_TRUE(backend);
|
||||
|
||||
// empty db does not have ledger range
|
||||
EXPECT_FALSE(backend->fetchLedgerRange());
|
||||
|
||||
// insert range table
|
||||
Backend::Cassandra::Handle handle{contactPoints};
|
||||
EXPECT_TRUE(handle.connect());
|
||||
handle.execute(fmt::format("INSERT INTO {}.ledger_range (is_latest, sequence) VALUES (False, 100)", keyspace));
|
||||
handle.execute(fmt::format("INSERT INTO {}.ledger_range (is_latest, sequence) VALUES (False, 100)", keyspace));
|
||||
handle.execute(fmt::format("INSERT INTO {}.ledger_range (is_latest, sequence) VALUES (True, 500)", keyspace));
|
||||
|
||||
backend = make_Backend(ctx, cfg);
|
||||
EXPECT_TRUE(backend);
|
||||
|
||||
auto const range = backend->fetchLedgerRange();
|
||||
EXPECT_EQ(range->minSequence, 100);
|
||||
EXPECT_EQ(range->maxSequence, 500);
|
||||
|
||||
@@ -45,19 +45,10 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadOneInCoroutineSuccessful)
|
||||
EXPECT_CALL(handle, asyncExecute(An<FakeStatement const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(1);
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statement = FakeStatement{};
|
||||
strat.read(yield, statement);
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadOneInCoroutineThrowsOnTimeoutFailure)
|
||||
@@ -67,26 +58,17 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadOneInCoroutineThrowsOnTimeoutF
|
||||
|
||||
ON_CALL(handle, asyncExecute(An<FakeStatement const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.WillByDefault([](auto const&, auto&& cb) {
|
||||
cb({}); // notify that item is ready
|
||||
return FakeFutureWithCallback{
|
||||
FakeResultOrError{CassandraError{"timeout", CASS_ERROR_LIB_REQUEST_TIMED_OUT}}};
|
||||
auto res = FakeResultOrError{CassandraError{"timeout", CASS_ERROR_LIB_REQUEST_TIMED_OUT}};
|
||||
cb(res); // notify that item is ready
|
||||
return FakeFutureWithCallback{res};
|
||||
});
|
||||
EXPECT_CALL(handle, asyncExecute(An<FakeStatement const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(1);
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statement = FakeStatement{};
|
||||
EXPECT_THROW(strat.read(yield, statement), DatabaseTimeout);
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadOneInCoroutineThrowsOnInvalidQueryFailure)
|
||||
@@ -96,26 +78,17 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadOneInCoroutineThrowsOnInvalidQ
|
||||
|
||||
ON_CALL(handle, asyncExecute(An<FakeStatement const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.WillByDefault([](auto const&, auto&& cb) {
|
||||
cb({}); // notify that item is ready
|
||||
return FakeFutureWithCallback{
|
||||
FakeResultOrError{CassandraError{"invalid", CASS_ERROR_SERVER_INVALID_QUERY}}};
|
||||
auto res = FakeResultOrError{CassandraError{"invalid", CASS_ERROR_SERVER_INVALID_QUERY}};
|
||||
cb(res); // notify that item is ready
|
||||
return FakeFutureWithCallback{res};
|
||||
});
|
||||
EXPECT_CALL(handle, asyncExecute(An<FakeStatement const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(1);
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statement = FakeStatement{};
|
||||
EXPECT_THROW(strat.read(yield, statement), std::runtime_error);
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineSuccessful)
|
||||
@@ -134,19 +107,10 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineSuccessful)
|
||||
handle, asyncExecute(An<std::vector<FakeStatement> const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(1);
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statements = std::vector<FakeStatement>(3);
|
||||
strat.read(yield, statements);
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineThrowsOnTimeoutFailure)
|
||||
@@ -158,27 +122,18 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineThrowsOnTimeou
|
||||
handle, asyncExecute(An<std::vector<FakeStatement> const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.WillByDefault([](auto const& statements, auto&& cb) {
|
||||
EXPECT_EQ(statements.size(), 3);
|
||||
cb({}); // notify that item is ready
|
||||
return FakeFutureWithCallback{
|
||||
FakeResultOrError{CassandraError{"timeout", CASS_ERROR_LIB_REQUEST_TIMED_OUT}}};
|
||||
auto res = FakeResultOrError{CassandraError{"timeout", CASS_ERROR_LIB_REQUEST_TIMED_OUT}};
|
||||
cb(res); // notify that item is ready
|
||||
return FakeFutureWithCallback{res};
|
||||
});
|
||||
EXPECT_CALL(
|
||||
handle, asyncExecute(An<std::vector<FakeStatement> const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(1);
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statements = std::vector<FakeStatement>(3);
|
||||
EXPECT_THROW(strat.read(yield, statements), DatabaseTimeout);
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineThrowsOnInvalidQueryFailure)
|
||||
@@ -190,27 +145,18 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineThrowsOnInvali
|
||||
handle, asyncExecute(An<std::vector<FakeStatement> const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.WillByDefault([](auto const& statements, auto&& cb) {
|
||||
EXPECT_EQ(statements.size(), 3);
|
||||
cb({}); // notify that item is ready
|
||||
return FakeFutureWithCallback{
|
||||
FakeResultOrError{CassandraError{"invalid", CASS_ERROR_SERVER_INVALID_QUERY}}};
|
||||
auto res = FakeResultOrError{CassandraError{"invalid", CASS_ERROR_SERVER_INVALID_QUERY}};
|
||||
cb(res); // notify that item is ready
|
||||
return FakeFutureWithCallback{res};
|
||||
});
|
||||
EXPECT_CALL(
|
||||
handle, asyncExecute(An<std::vector<FakeStatement> const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(1);
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statements = std::vector<FakeStatement>(3);
|
||||
EXPECT_THROW(strat.read(yield, statements), std::runtime_error);
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineMarksBusyIfRequestsOutstandingExceeded)
|
||||
@@ -233,21 +179,12 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineMarksBusyIfReq
|
||||
handle, asyncExecute(An<std::vector<FakeStatement> const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(1);
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
EXPECT_FALSE(strat.isTooBusy()); // 2 was the limit, 0 atm
|
||||
auto statements = std::vector<FakeStatement>(3);
|
||||
strat.read(yield, statements);
|
||||
EXPECT_FALSE(strat.isTooBusy()); // after read completes it's 0 again
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadEachInCoroutineSuccessful)
|
||||
@@ -267,20 +204,11 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadEachInCoroutineSuccessful)
|
||||
An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(3); // once per statement
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statements = std::vector<FakeStatement>(3);
|
||||
auto res = strat.readEach(yield, statements);
|
||||
EXPECT_EQ(res.size(), statements.size());
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadEachInCoroutineThrowsOnFailure)
|
||||
@@ -305,19 +233,10 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadEachInCoroutineThrowsOnFailure
|
||||
An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(3); // once per statement
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statements = std::vector<FakeStatement>(3);
|
||||
EXPECT_THROW(strat.readEach(yield, statements), DatabaseTimeout);
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, WriteSyncFirstTrySuccessful)
|
||||
|
||||
@@ -229,8 +229,6 @@ TEST_F(RPCLedgerDataHandlerTest, NoMarker)
|
||||
"ledger_index":"30",
|
||||
"parent_close_time":0,
|
||||
"parent_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seqNum":"30",
|
||||
"totalCoins":"0",
|
||||
"total_coins":"0",
|
||||
"transaction_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"closed":true
|
||||
@@ -297,8 +295,6 @@ TEST_F(RPCLedgerDataHandlerTest, TypeFilter)
|
||||
"ledger_index":"30",
|
||||
"parent_close_time":0,
|
||||
"parent_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seqNum":"30",
|
||||
"totalCoins":"0",
|
||||
"total_coins":"0",
|
||||
"transaction_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"closed":true
|
||||
@@ -368,8 +364,6 @@ TEST_F(RPCLedgerDataHandlerTest, OutOfOrder)
|
||||
"ledger_index":"30",
|
||||
"parent_close_time":0,
|
||||
"parent_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seqNum":"30",
|
||||
"totalCoins":"0",
|
||||
"total_coins":"0",
|
||||
"transaction_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"closed":true
|
||||
|
||||
@@ -267,8 +267,6 @@ TEST_F(RPCLedgerHandlerTest, Default)
|
||||
"ledger_index":"30",
|
||||
"parent_close_time":0,
|
||||
"parent_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seqNum":"30",
|
||||
"totalCoins":"0",
|
||||
"total_coins":"0",
|
||||
"transaction_hash":"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
@@ -457,8 +455,6 @@ TEST_F(RPCLedgerHandlerTest, TransactionsExpandNotBinary)
|
||||
"ledger_index":"30",
|
||||
"parent_close_time":0,
|
||||
"parent_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seqNum":"30",
|
||||
"totalCoins":"0",
|
||||
"total_coins":"0",
|
||||
"transaction_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"transactions":[
|
||||
@@ -679,8 +675,6 @@ TEST_F(RPCLedgerHandlerTest, OwnerFundsEmtpy)
|
||||
"ledger_index":"30",
|
||||
"parent_close_time":0,
|
||||
"parent_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seqNum":"30",
|
||||
"totalCoins":"0",
|
||||
"total_coins":"0",
|
||||
"transaction_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"transactions":[
|
||||
@@ -771,9 +765,7 @@ TEST_F(RPCLedgerHandlerTest, OwnerFundsTrueBinaryFalse)
|
||||
"ledger_index": "30",
|
||||
"parent_close_time": 0,
|
||||
"parent_hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seqNum": "30",
|
||||
"total_coins": "0",
|
||||
"totalCoins": "0",
|
||||
"transaction_hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"transactions": [
|
||||
{
|
||||
|
||||
@@ -615,6 +615,7 @@ TEST_F(RPCSubscribeHandlerTest, StreamsLedger)
|
||||
auto const handler = AnyHandler{SubscribeHandler{mockBackendPtr, subManager_}};
|
||||
auto const output = handler.process(input, Context{std::ref(yield), session_});
|
||||
ASSERT_TRUE(output);
|
||||
// FIXME: fee_ref is missing now. this is possibly correct. need to confirm:
|
||||
EXPECT_EQ(output->as_object(), json::parse(expectedOutput));
|
||||
std::this_thread::sleep_for(20ms);
|
||||
auto const report = subManager_->report();
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <webserver/interface/ConnectionBase.h>
|
||||
|
||||
#include <boost/asio/spawn.hpp>
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <ripple/basics/base_uint.h>
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <ripple/protocol/LedgerHeader.h>
|
||||
#include <ripple/protocol/Protocol.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -21,7 +21,11 @@
|
||||
|
||||
#include <backend/Types.h>
|
||||
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <ripple/protocol/LedgerHeader.h>
|
||||
#include <ripple/protocol/Protocol.h>
|
||||
#include <ripple/protocol/STBase.h>
|
||||
#include <ripple/protocol/STTx.h>
|
||||
#include <ripple/protocol/TxMeta.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
@@ -788,12 +788,12 @@ TEST_F(WebRPCServerHandlerTest, HTTPTooBusy)
|
||||
TEST_F(WebRPCServerHandlerTest, HTTPRequestNotJson)
|
||||
{
|
||||
static auto constexpr request = "not json";
|
||||
static auto constexpr response = "Unable to parse request: syntax error";
|
||||
static auto constexpr responsePrefix = "Unable to parse request: syntax error";
|
||||
|
||||
EXPECT_CALL(*rpcEngine, notifyBadSyntax).Times(1);
|
||||
|
||||
(*handler)(std::move(request), session);
|
||||
EXPECT_EQ(session->message, response);
|
||||
EXPECT_THAT(session->message, testing::StartsWith(responsePrefix));
|
||||
EXPECT_EQ(session->lastStatus, boost::beast::http::status::bad_request);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user