//------------------------------------------------------------------------------ /* This file is part of rippled: https://github.com/ripple/rippled Copyright (c) 2020 Ripple Labs Inc. Permission to use, copy, modify, and/or 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 #include #include #include #include #include #include #include namespace ripple { namespace test { class ReportingETL_test : public beast::unit_test::suite { // gRPC stuff class GrpcLedgerClient : public GRPCTestClientBase { public: org::xrpl::rpc::v1::GetLedgerRequest request; org::xrpl::rpc::v1::GetLedgerResponse reply; explicit GrpcLedgerClient(std::string const& port) : GRPCTestClientBase(port) { } void GetLedger() { status = stub_->GetLedger(&context, request, &reply); } }; void testGetLedger() { testcase("GetLedger"); using namespace test::jtx; std::unique_ptr config = envconfig(addGrpcConfig); std::string grpcPort = *(*config)["port_grpc"].get("port"); Env env(*this, std::move(config)); env.close(); auto ledger = env.app().getLedgerMaster().getLedgerBySeq(3); BEAST_EXPECT(env.current()->info().seq == 4); auto grpcLedger = [&grpcPort]( auto sequence, bool transactions, bool expand, bool get_objects, bool get_object_neighbors) { GrpcLedgerClient grpcClient{grpcPort}; grpcClient.request.mutable_ledger()->set_sequence(sequence); grpcClient.request.set_transactions(transactions); grpcClient.request.set_expand(expand); grpcClient.request.set_get_objects(get_objects); grpcClient.request.set_get_object_neighbors(get_object_neighbors); grpcClient.GetLedger(); return std::make_pair(grpcClient.status, grpcClient.reply); }; { auto [status, reply] = grpcLedger(3, false, false, false, false); BEAST_EXPECT(status.ok()); BEAST_EXPECT(reply.validated()); BEAST_EXPECT(!reply.has_hashes_list()); BEAST_EXPECT(!reply.has_transactions_list()); BEAST_EXPECT(!reply.skiplist_included()); BEAST_EXPECT(reply.ledger_objects().objects_size() == 0); Serializer s; addRaw(ledger->info(), s, true); BEAST_EXPECT(s.slice() == makeSlice(reply.ledger_header())); } Account const alice{"alice"}; Account const bob{"bob"}; env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); env.close(); ledger = env.app().getLedgerMaster().getLedgerBySeq(4); std::vector hashes; std::vector> transactions; std::vector> metas; for (auto& [sttx, meta] : ledger->txs) { hashes.push_back(sttx->getTransactionID()); transactions.push_back(sttx); metas.push_back(meta); } Serializer s; addRaw(ledger->info(), s, true); { auto [status, reply] = grpcLedger(4, true, false, false, false); BEAST_EXPECT(status.ok()); BEAST_EXPECT(reply.validated()); BEAST_EXPECT(reply.has_hashes_list()); BEAST_EXPECT(reply.hashes_list().hashes_size() == hashes.size()); BEAST_EXPECT( uint256::fromVoid(reply.hashes_list().hashes(0).data()) == hashes[0]); BEAST_EXPECT( uint256::fromVoid(reply.hashes_list().hashes(1).data()) == hashes[1]); BEAST_EXPECT( uint256::fromVoid(reply.hashes_list().hashes(2).data()) == hashes[2]); BEAST_EXPECT( uint256::fromVoid(reply.hashes_list().hashes(3).data()) == hashes[3]); BEAST_EXPECT(!reply.has_transactions_list()); BEAST_EXPECT(!reply.skiplist_included()); BEAST_EXPECT(reply.ledger_objects().objects_size() == 0); BEAST_EXPECT(s.slice() == makeSlice(reply.ledger_header())); } { auto [status, reply] = grpcLedger(4, true, true, false, false); BEAST_EXPECT(status.ok()); BEAST_EXPECT(reply.validated()); BEAST_EXPECT(!reply.has_hashes_list()); BEAST_EXPECT(reply.has_transactions_list()); BEAST_EXPECT(reply.transactions_list().transactions_size() == 4); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(0) .transaction_blob()) == transactions[0]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(0) .metadata_blob()) == metas[0]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(1) .transaction_blob()) == transactions[1]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(1) .metadata_blob()) == metas[1]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(2) .transaction_blob()) == transactions[2]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(2) .metadata_blob()) == metas[2]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(3) .transaction_blob()) == transactions[3]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(3) .metadata_blob()) == metas[3]->getSerializer().slice()); BEAST_EXPECT(!reply.skiplist_included()); BEAST_EXPECT(reply.ledger_objects().objects_size() == 0); BEAST_EXPECT(s.slice() == makeSlice(reply.ledger_header())); } { auto [status, reply] = grpcLedger(4, true, true, true, false); BEAST_EXPECT(status.ok()); BEAST_EXPECT(reply.validated()); BEAST_EXPECT(!reply.has_hashes_list()); BEAST_EXPECT(reply.has_transactions_list()); BEAST_EXPECT(reply.transactions_list().transactions_size() == 4); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(0) .transaction_blob()) == transactions[0]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(0) .metadata_blob()) == metas[0]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(1) .transaction_blob()) == transactions[1]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(1) .metadata_blob()) == metas[1]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(2) .transaction_blob()) == transactions[2]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(2) .metadata_blob()) == metas[2]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(3) .transaction_blob()) == transactions[3]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(3) .metadata_blob()) == metas[3]->getSerializer().slice()); BEAST_EXPECT(reply.skiplist_included()); BEAST_EXPECT(s.slice() == makeSlice(reply.ledger_header())); auto parent = env.app().getLedgerMaster().getLedgerBySeq(3); SHAMap::Delta differences; int maxDifferences = std::numeric_limits::max(); bool res = parent->stateMap().compare( ledger->stateMap(), differences, maxDifferences); BEAST_EXPECT(res); size_t idx = 0; for (auto& [k, v] : differences) { BEAST_EXPECT( k == uint256::fromVoid( reply.ledger_objects().objects(idx).key().data())); if (v.second) { BEAST_EXPECT( v.second->slice() == makeSlice(reply.ledger_objects().objects(idx).data())); } ++idx; } } { auto [status, reply] = grpcLedger(4, true, true, true, true); BEAST_EXPECT(status.ok()); BEAST_EXPECT(reply.validated()); BEAST_EXPECT(!reply.has_hashes_list()); BEAST_EXPECT(reply.object_neighbors_included()); BEAST_EXPECT(reply.has_transactions_list()); BEAST_EXPECT(reply.transactions_list().transactions_size() == 4); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(0) .transaction_blob()) == transactions[0]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(0) .metadata_blob()) == metas[0]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(1) .transaction_blob()) == transactions[1]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(1) .metadata_blob()) == metas[1]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(2) .transaction_blob()) == transactions[2]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(2) .metadata_blob()) == metas[2]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(3) .transaction_blob()) == transactions[3]->getSerializer().slice()); BEAST_EXPECT( makeSlice(reply.transactions_list() .transactions(3) .metadata_blob()) == metas[3]->getSerializer().slice()); BEAST_EXPECT(reply.skiplist_included()); BEAST_EXPECT(s.slice() == makeSlice(reply.ledger_header())); auto parent = env.app().getLedgerMaster().getLedgerBySeq(3); SHAMap::Delta differences; int maxDifferences = std::numeric_limits::max(); bool res = parent->stateMap().compare( ledger->stateMap(), differences, maxDifferences); BEAST_EXPECT(res); size_t idx = 0; for (auto& [k, v] : differences) { auto obj = reply.ledger_objects().objects(idx); BEAST_EXPECT(k == uint256::fromVoid(obj.key().data())); if (v.second) { BEAST_EXPECT(v.second->slice() == makeSlice(obj.data())); } else BEAST_EXPECT(obj.data().size() == 0); if (!(v.first && v.second)) { auto succ = ledger->stateMap().upper_bound(k); auto pred = ledger->stateMap().lower_bound(k); if (succ != ledger->stateMap().end()) BEAST_EXPECT( succ->key() == uint256::fromVoid(obj.successor().data())); else BEAST_EXPECT(obj.successor().size() == 0); if (pred != ledger->stateMap().end()) BEAST_EXPECT( pred->key() == uint256::fromVoid(obj.predecessor().data())); else BEAST_EXPECT(obj.predecessor().size() == 0); } ++idx; } } // Delete an account env(noop(alice)); std::uint32_t const ledgerCount{ env.current()->seq() + 257 - env.seq(alice)}; for (std::uint32_t i = 0; i < ledgerCount; ++i) env.close(); auto const acctDelFee{drops(env.current()->fees().increment)}; env(acctdelete(alice, bob), fee(acctDelFee)); env.close(); { auto [status, reply] = grpcLedger(env.closed()->seq(), true, true, true, true); BEAST_EXPECT(status.ok()); BEAST_EXPECT(reply.validated()); auto base = env.app().getLedgerMaster().getLedgerBySeq(env.closed()->seq()); auto parent = env.app().getLedgerMaster().getLedgerBySeq( env.closed()->seq() - 1); SHAMap::Delta differences; int maxDifferences = std::numeric_limits::max(); bool res = parent->stateMap().compare( base->stateMap(), differences, maxDifferences); BEAST_EXPECT(res); size_t idx = 0; for (auto& [k, v] : differences) { auto obj = reply.ledger_objects().objects(idx); BEAST_EXPECT(k == uint256::fromVoid(obj.key().data())); if (v.second) { BEAST_EXPECT( v.second->slice() == makeSlice(reply.ledger_objects().objects(idx).data())); } else BEAST_EXPECT(obj.data().size() == 0); if (!(v.first && v.second)) { auto succ = base->stateMap().upper_bound(k); auto pred = base->stateMap().lower_bound(k); if (succ != base->stateMap().end()) BEAST_EXPECT( succ->key() == uint256::fromVoid(obj.successor().data())); else BEAST_EXPECT(obj.successor().size() == 0); if (pred != base->stateMap().end()) BEAST_EXPECT( pred->key() == uint256::fromVoid(obj.predecessor().data())); else BEAST_EXPECT(obj.predecessor().size() == 0); } ++idx; } } } // gRPC stuff class GrpcLedgerDataClient : public GRPCTestClientBase { public: org::xrpl::rpc::v1::GetLedgerDataRequest request; org::xrpl::rpc::v1::GetLedgerDataResponse reply; explicit GrpcLedgerDataClient(std::string const& port) : GRPCTestClientBase(port) { } void GetLedgerData() { status = stub_->GetLedgerData(&context, request, &reply); } }; void testGetLedgerData() { testcase("GetLedgerData"); using namespace test::jtx; std::unique_ptr config = envconfig(addGrpcConfig); std::string grpcPort = *(*config)["port_grpc"].get("port"); Env env(*this, std::move(config)); auto grpcLedgerData = [&grpcPort]( auto sequence, std::string marker = "") { GrpcLedgerDataClient grpcClient{grpcPort}; grpcClient.request.mutable_ledger()->set_sequence(sequence); if (marker.size()) { grpcClient.request.set_marker(marker); } grpcClient.GetLedgerData(); return std::make_pair(grpcClient.status, grpcClient.reply); }; Account const alice{"alice"}; env.fund(XRP(100000), alice); int num_accounts = 10; for (auto i = 0; i < num_accounts; i++) { Account const bob{std::string("bob") + std::to_string(i)}; env.fund(XRP(1000), bob); } env.close(); { auto [status, reply] = grpcLedgerData(env.closed()->seq()); BEAST_EXPECT(status.ok()); BEAST_EXPECT( reply.ledger_objects().objects_size() == num_accounts + 3); BEAST_EXPECT(reply.marker().size() == 0); auto ledger = env.closed(); size_t idx = 0; for (auto& sle : ledger->sles) { BEAST_EXPECT( sle->getSerializer().slice() == makeSlice(reply.ledger_objects().objects(idx).data())); ++idx; } } { auto [status, reply] = grpcLedgerData(env.closed()->seq(), "bad marker"); BEAST_EXPECT(!status.ok()); BEAST_EXPECT( status.error_code() == grpc::StatusCode::INVALID_ARGUMENT); } num_accounts = 3000; for (auto i = 0; i < num_accounts; i++) { Account const cat{std::string("cat") + std::to_string(i)}; env.fund(XRP(1000), cat); if (i % 100 == 0) env.close(); } env.close(); { auto [status, reply] = grpcLedgerData(env.closed()->seq()); BEAST_EXPECT(status.ok()); int maxLimit = RPC::Tuning::pageLength(true); BEAST_EXPECT(reply.ledger_objects().objects_size() == maxLimit); BEAST_EXPECT(reply.marker().size() != 0); auto [status2, reply2] = grpcLedgerData(env.closed()->seq(), reply.marker()); BEAST_EXPECT(status2.ok()); BEAST_EXPECT(reply2.marker().size() == 0); auto ledger = env.closed(); size_t idx = 0; for (auto& sle : ledger->sles) { auto& obj = idx < maxLimit ? reply.ledger_objects().objects(idx) : reply2.ledger_objects().objects(idx - maxLimit); BEAST_EXPECT( sle->getSerializer().slice() == makeSlice(obj.data())); ++idx; } BEAST_EXPECT( idx == reply.ledger_objects().objects_size() + reply2.ledger_objects().objects_size()); } } // gRPC stuff class GrpcLedgerDiffClient : public GRPCTestClientBase { public: org::xrpl::rpc::v1::GetLedgerDiffRequest request; org::xrpl::rpc::v1::GetLedgerDiffResponse reply; explicit GrpcLedgerDiffClient(std::string const& port) : GRPCTestClientBase(port) { } void GetLedgerDiff() { status = stub_->GetLedgerDiff(&context, request, &reply); } }; void testGetLedgerDiff() { testcase("GetLedgerDiff"); using namespace test::jtx; std::unique_ptr config = envconfig(addGrpcConfig); std::string grpcPort = *(*config)["port_grpc"].get("port"); Env env(*this, std::move(config)); auto grpcLedgerDiff = [&grpcPort]( auto baseSequence, auto desiredSequence) { GrpcLedgerDiffClient grpcClient{grpcPort}; grpcClient.request.mutable_base_ledger()->set_sequence( baseSequence); grpcClient.request.mutable_desired_ledger()->set_sequence( desiredSequence); grpcClient.request.set_include_blobs(true); grpcClient.GetLedgerDiff(); return std::make_pair(grpcClient.status, grpcClient.reply); }; int num_accounts = 20; for (auto i = 0; i < num_accounts; i++) { Account const cat{std::string("cat") + std::to_string(i)}; env.fund(XRP(1000), cat); if (i % 2 == 0) env.close(); } env.close(); auto compareDiffs = [&](auto baseSequence, auto desiredSequence) { auto [status, reply] = grpcLedgerDiff(baseSequence, desiredSequence); BEAST_EXPECT(status.ok()); auto desired = env.app().getLedgerMaster().getLedgerBySeq(desiredSequence); auto base = env.app().getLedgerMaster().getLedgerBySeq(baseSequence); SHAMap::Delta differences; int maxDifferences = std::numeric_limits::max(); bool res = base->stateMap().compare( desired->stateMap(), differences, maxDifferences); if (!BEAST_EXPECT(res)) return false; size_t idx = 0; for (auto& [k, v] : differences) { if (!BEAST_EXPECT( k == uint256::fromVoid( reply.ledger_objects().objects(idx).key().data()))) return false; if (v.second) { if (!BEAST_EXPECT( v.second->slice() == makeSlice( reply.ledger_objects().objects(idx).data()))) return false; } ++idx; } return true; }; // Adjacent ledgers BEAST_EXPECT( compareDiffs(env.closed()->seq() - 1, env.closed()->seq())); // Adjacent ledgers further in the past BEAST_EXPECT( compareDiffs(env.closed()->seq() - 3, env.closed()->seq() - 2)); // Non-adjacent ledgers BEAST_EXPECT( compareDiffs(env.closed()->seq() - 5, env.closed()->seq() - 1)); // Adjacent ledgers but in reverse order BEAST_EXPECT( compareDiffs(env.closed()->seq(), env.closed()->seq() - 1)); // Non-adjacent ledgers in reverse order BEAST_EXPECT( compareDiffs(env.closed()->seq() - 1, env.closed()->seq() - 5)); } // gRPC stuff class GrpcLedgerEntryClient : public GRPCTestClientBase { public: org::xrpl::rpc::v1::GetLedgerEntryRequest request; org::xrpl::rpc::v1::GetLedgerEntryResponse reply; explicit GrpcLedgerEntryClient(std::string const& port) : GRPCTestClientBase(port) { } void GetLedgerEntry() { status = stub_->GetLedgerEntry(&context, request, &reply); } }; void testGetLedgerEntry() { testcase("GetLedgerDiff"); using namespace test::jtx; std::unique_ptr config = envconfig(addGrpcConfig); std::string grpcPort = *(*config)["port_grpc"].get("port"); Env env(*this, std::move(config)); auto grpcLedgerEntry = [&grpcPort](auto sequence, auto key) { GrpcLedgerEntryClient grpcClient{grpcPort}; grpcClient.request.mutable_ledger()->set_sequence(sequence); grpcClient.request.set_key(key.data(), key.size()); grpcClient.GetLedgerEntry(); return std::make_pair(grpcClient.status, grpcClient.reply); }; Account const alice{"alice"}; env.fund(XRP(1000), alice); env.close(); for (auto& sle : env.closed()->sles) { auto [status, reply] = grpcLedgerEntry(env.closed()->seq(), sle->key()); BEAST_EXPECT(status.ok()); BEAST_EXPECT( uint256::fromVoid(reply.ledger_object().key().data()) == sle->key()); BEAST_EXPECT( makeSlice(reply.ledger_object().data()) == sle->getSerializer().slice()); } } void testNeedCurrentOrClosed() { testcase("NeedCurrentOrClosed"); { org::xrpl::rpc::v1::GetLedgerRequest request; request.mutable_ledger()->set_sequence(1); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_ledger()->set_hash(""); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_UNSPECIFIED); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT); BEAST_EXPECT(needCurrentOrClosed(request)); request.mutable_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED); BEAST_EXPECT(needCurrentOrClosed(request)); } { org::xrpl::rpc::v1::GetLedgerDataRequest request; request.mutable_ledger()->set_sequence(1); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_ledger()->set_hash(""); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_UNSPECIFIED); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT); BEAST_EXPECT(needCurrentOrClosed(request)); request.mutable_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED); BEAST_EXPECT(needCurrentOrClosed(request)); } { org::xrpl::rpc::v1::GetLedgerEntryRequest request; request.mutable_ledger()->set_sequence(1); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_ledger()->set_hash(""); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_UNSPECIFIED); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT); BEAST_EXPECT(needCurrentOrClosed(request)); request.mutable_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED); BEAST_EXPECT(needCurrentOrClosed(request)); } { org::xrpl::rpc::v1::GetLedgerDiffRequest request; // set desired ledger, so desired ledger does not need current or // closed request.mutable_base_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED); request.mutable_base_ledger()->set_sequence(1); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_base_ledger()->set_hash(""); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_base_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_base_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_UNSPECIFIED); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_base_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT); BEAST_EXPECT(needCurrentOrClosed(request)); request.mutable_base_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED); BEAST_EXPECT(needCurrentOrClosed(request)); // reset base ledger, so base ledger doesn't need current or closed request.mutable_base_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED); request.mutable_desired_ledger()->set_sequence(1); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_desired_ledger()->set_hash(""); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_desired_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_desired_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_UNSPECIFIED); BEAST_EXPECT(!needCurrentOrClosed(request)); request.mutable_desired_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT); BEAST_EXPECT(needCurrentOrClosed(request)); request.mutable_desired_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED); BEAST_EXPECT(needCurrentOrClosed(request)); // both base and desired need current or closed request.mutable_base_ledger()->set_shortcut( org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT); BEAST_EXPECT(needCurrentOrClosed(request)); } } void testSecureGateway() { testcase("SecureGateway"); using namespace test::jtx; { std::unique_ptr config = envconfig( addGrpcConfigWithSecureGateway, getEnvLocalhostAddr()); std::string grpcPort = *(*config)["port_grpc"].get("port"); Env env(*this, std::move(config)); env.close(); auto ledger = env.app().getLedgerMaster().getLedgerBySeq(3); BEAST_EXPECT(env.current()->info().seq == 4); auto grpcLedger = [&grpcPort]( auto sequence, std::string const& clientIp, std::string const& user) { GrpcLedgerClient grpcClient{grpcPort}; grpcClient.request.mutable_ledger()->set_sequence(sequence); grpcClient.request.set_client_ip(clientIp); grpcClient.request.set_user(user); grpcClient.GetLedger(); return std::make_pair(grpcClient.status, grpcClient.reply); }; { auto [status, reply] = grpcLedger(env.current()->info().seq, "", ""); BEAST_EXPECT(!reply.is_unlimited()); BEAST_EXPECT(status.ok()); } { auto [status, reply] = grpcLedger(env.current()->info().seq, "", "ETL"); BEAST_EXPECT(reply.is_unlimited()); BEAST_EXPECT(status.ok()); } { auto [status, reply] = grpcLedger(env.current()->info().seq, "", "Reporting"); BEAST_EXPECT(reply.is_unlimited()); BEAST_EXPECT(status.ok()); } { auto [status, reply] = grpcLedger(env.current()->info().seq, "127.0.0.1", "ETL"); BEAST_EXPECT(!reply.is_unlimited()); BEAST_EXPECT(status.ok()); } { auto [status, reply] = grpcLedger(env.current()->info().seq, "127.0.0.1", ""); BEAST_EXPECT(!reply.is_unlimited()); BEAST_EXPECT(status.ok()); } } { std::string secureGatewayIp = "44.124.234.79"; std::unique_ptr config = envconfig(addGrpcConfigWithSecureGateway, secureGatewayIp); std::string grpcPort = *(*config)["port_grpc"].get("port"); Env env(*this, std::move(config)); env.close(); auto ledger = env.app().getLedgerMaster().getLedgerBySeq(3); BEAST_EXPECT(env.current()->info().seq == 4); auto grpcLedger = [&grpcPort]( auto sequence, std::string const& clientIp, std::string const& user) { GrpcLedgerClient grpcClient{grpcPort}; grpcClient.request.mutable_ledger()->set_sequence(sequence); grpcClient.request.set_client_ip(clientIp); grpcClient.request.set_user(user); grpcClient.GetLedger(); return std::make_pair(grpcClient.status, grpcClient.reply); }; { auto [status, reply] = grpcLedger(env.current()->info().seq, "", ""); BEAST_EXPECT(!reply.is_unlimited()); BEAST_EXPECT(status.ok()); } { auto [status, reply] = grpcLedger(env.current()->info().seq, "", "ETL"); BEAST_EXPECT(!reply.is_unlimited()); BEAST_EXPECT(status.ok()); } { auto [status, reply] = grpcLedger( env.current()->info().seq, secureGatewayIp, "ETL"); BEAST_EXPECT(!reply.is_unlimited()); BEAST_EXPECT(status.ok()); } { auto [status, reply] = grpcLedger(env.current()->info().seq, secureGatewayIp, ""); BEAST_EXPECT(!reply.is_unlimited()); BEAST_EXPECT(status.ok()); } } { std::unique_ptr config = envconfig( addGrpcConfigWithSecureGateway, getEnvLocalhostAddr()); std::string grpcPort = *(*config)["port_grpc"].get("port"); Env env(*this, std::move(config)); env.close(); auto ledger = env.app().getLedgerMaster().getLedgerBySeq(3); BEAST_EXPECT(env.current()->info().seq == 4); auto grpcLedgerData = [&grpcPort]( auto sequence, std::string const& clientIp, std::string const& user) { GrpcLedgerDataClient grpcClient{grpcPort}; grpcClient.request.mutable_ledger()->set_sequence(sequence); grpcClient.request.set_client_ip(clientIp); grpcClient.request.set_user(user); grpcClient.GetLedgerData(); return std::make_pair(grpcClient.status, grpcClient.reply); }; { auto [status, reply] = grpcLedgerData(env.current()->info().seq, "", ""); BEAST_EXPECT(!reply.is_unlimited()); BEAST_EXPECT(status.ok()); } { auto [status, reply] = grpcLedgerData(env.current()->info().seq, "", "ETL"); BEAST_EXPECT(reply.is_unlimited()); BEAST_EXPECT(status.ok()); } { auto [status, reply] = grpcLedgerData(env.current()->info().seq, "", "Reporting"); BEAST_EXPECT(reply.is_unlimited()); BEAST_EXPECT(status.ok()); } { auto [status, reply] = grpcLedgerData( env.current()->info().seq, "127.0.0.1", "ETL"); BEAST_EXPECT(!reply.is_unlimited()); BEAST_EXPECT(status.ok()); } { auto [status, reply] = grpcLedgerData(env.current()->info().seq, "127.0.0.1", ""); BEAST_EXPECT(!reply.is_unlimited()); BEAST_EXPECT(status.ok()); } } { std::string secureGatewayIp = "44.124.234.79"; std::unique_ptr config = envconfig(addGrpcConfigWithSecureGateway, secureGatewayIp); std::string grpcPort = *(*config)["port_grpc"].get("port"); Env env(*this, std::move(config)); env.close(); auto ledger = env.app().getLedgerMaster().getLedgerBySeq(3); BEAST_EXPECT(env.current()->info().seq == 4); auto grpcLedgerData = [&grpcPort]( auto sequence, std::string const& clientIp, std::string const& user) { GrpcLedgerDataClient grpcClient{grpcPort}; grpcClient.request.mutable_ledger()->set_sequence(sequence); grpcClient.request.set_client_ip(clientIp); grpcClient.request.set_user(user); grpcClient.GetLedgerData(); return std::make_pair(grpcClient.status, grpcClient.reply); }; { auto [status, reply] = grpcLedgerData(env.current()->info().seq, "", ""); BEAST_EXPECT(!reply.is_unlimited()); BEAST_EXPECT(status.ok()); } { auto [status, reply] = grpcLedgerData(env.current()->info().seq, "", "ETL"); BEAST_EXPECT(!reply.is_unlimited()); BEAST_EXPECT(status.ok()); } { auto [status, reply] = grpcLedgerData( env.current()->info().seq, secureGatewayIp, "ETL"); BEAST_EXPECT(!reply.is_unlimited()); BEAST_EXPECT(status.ok()); } { auto [status, reply] = grpcLedgerData( env.current()->info().seq, secureGatewayIp, ""); BEAST_EXPECT(!reply.is_unlimited()); BEAST_EXPECT(status.ok()); } } } public: void run() override { testGetLedger(); testGetLedgerData(); testGetLedgerDiff(); testGetLedgerEntry(); testNeedCurrentOrClosed(); testSecureGateway(); } }; BEAST_DEFINE_TESTSUITE_PRIO(ReportingETL, app, ripple, 2); } // namespace test } // namespace ripple