mirror of
				https://github.com/XRPLF/clio.git
				synced 2025-11-04 11:55:51 +00:00 
			
		
		
		
	Add assertion that terminate clio (#994)
Fixes #893. Also added termination handler to print backtrace on crash, so fixes #929.
This commit is contained in:
		
							
								
								
									
										3
									
								
								CMake/deps/libbacktrace.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								CMake/deps/libbacktrace.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
target_compile_definitions(clio PUBLIC BOOST_STACKTRACE_LINK)
 | 
			
		||||
target_compile_definitions(clio PUBLIC BOOST_STACKTRACE_USE_BACKTRACE)
 | 
			
		||||
find_package(libbacktrace REQUIRED)
 | 
			
		||||
@@ -44,6 +44,7 @@ include (CMake/deps/OpenSSL.cmake)
 | 
			
		||||
include (CMake/deps/Threads.cmake)
 | 
			
		||||
include (CMake/deps/libfmt.cmake)
 | 
			
		||||
include (CMake/deps/cassandra.cmake)
 | 
			
		||||
include (CMake/deps/libbacktrace.cmake)
 | 
			
		||||
 | 
			
		||||
# TODO: Include directory will be wrong when installed.
 | 
			
		||||
target_include_directories (clio PUBLIC src)
 | 
			
		||||
@@ -56,11 +57,14 @@ target_link_libraries (clio
 | 
			
		||||
  PUBLIC Boost::system
 | 
			
		||||
  PUBLIC Boost::log
 | 
			
		||||
  PUBLIC Boost::log_setup
 | 
			
		||||
  PUBLIC Boost::stacktrace_backtrace
 | 
			
		||||
  PUBLIC cassandra-cpp-driver::cassandra-cpp-driver
 | 
			
		||||
  PUBLIC fmt::fmt
 | 
			
		||||
  PUBLIC OpenSSL::Crypto
 | 
			
		||||
  PUBLIC OpenSSL::SSL
 | 
			
		||||
  PUBLIC xrpl::libxrpl
 | 
			
		||||
  PUBLIC dl
 | 
			
		||||
  PUBLIC libbacktrace::libbacktrace
 | 
			
		||||
 | 
			
		||||
  INTERFACE Threads::Threads
 | 
			
		||||
)
 | 
			
		||||
@@ -143,7 +147,9 @@ target_sources (clio PRIVATE
 | 
			
		||||
  src/util/prometheus/Metrics.cpp
 | 
			
		||||
  src/util/prometheus/Prometheus.cpp
 | 
			
		||||
  src/util/Random.cpp
 | 
			
		||||
  src/util/Taggable.cpp)
 | 
			
		||||
  src/util/Taggable.cpp
 | 
			
		||||
  src/util/TerminationHandler.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Clio server
 | 
			
		||||
add_executable (clio_server src/main/Main.cpp)
 | 
			
		||||
@@ -167,6 +173,7 @@ if (tests)
 | 
			
		||||
    unittests/DOSGuardTests.cpp
 | 
			
		||||
    unittests/SubscriptionTests.cpp
 | 
			
		||||
    unittests/SubscriptionManagerTests.cpp
 | 
			
		||||
    unittests/util/AssertTests.cpp
 | 
			
		||||
    unittests/util/TestObject.cpp
 | 
			
		||||
    unittests/util/StringUtils.cpp
 | 
			
		||||
    unittests/util/prometheus/CounterTests.cpp
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
from conan import ConanFile
 | 
			
		||||
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Clio(ConanFile):
 | 
			
		||||
    name = 'clio'
 | 
			
		||||
@@ -11,7 +11,7 @@ class Clio(ConanFile):
 | 
			
		||||
    settings = 'os', 'compiler', 'build_type', 'arch'
 | 
			
		||||
    options = {
 | 
			
		||||
        'fPIC': [True, False],
 | 
			
		||||
        'verbose': [True, False],   
 | 
			
		||||
        'verbose': [True, False],
 | 
			
		||||
        'tests': [True, False],     # build unit tests; create `clio_tests` binary
 | 
			
		||||
        'docs': [True, False],      # doxygen API docs; create custom target 'docs'
 | 
			
		||||
        'packaging': [True, False], # create distribution packages
 | 
			
		||||
@@ -27,6 +27,7 @@ class Clio(ConanFile):
 | 
			
		||||
        'grpc/1.50.1',
 | 
			
		||||
        'openssl/1.1.1u',
 | 
			
		||||
        'xrpl/2.0.0-rc1',
 | 
			
		||||
        'libbacktrace/cci.20210118'
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    default_options = {
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#include <data/BackendCounters.h>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
 | 
			
		||||
#include <util/prometheus/Prometheus.h>
 | 
			
		||||
 | 
			
		||||
@@ -161,7 +162,10 @@ BackendCounters::AsyncOperationCounters::registerStarted(std::uint64_t const cou
 | 
			
		||||
void
 | 
			
		||||
BackendCounters::AsyncOperationCounters::registerFinished(std::uint64_t const count)
 | 
			
		||||
{
 | 
			
		||||
    assert(pendingCounter_.get().value() >= static_cast<std::int64_t>(count));
 | 
			
		||||
    ASSERT(
 | 
			
		||||
        pendingCounter_.get().value() >= static_cast<std::int64_t>(count),
 | 
			
		||||
        "Finished operations can't be more than pending"
 | 
			
		||||
    );
 | 
			
		||||
    pendingCounter_.get() -= count;
 | 
			
		||||
    completedCounter_.get() += count;
 | 
			
		||||
}
 | 
			
		||||
@@ -175,7 +179,9 @@ BackendCounters::AsyncOperationCounters::registerRetry(std::uint64_t count)
 | 
			
		||||
void
 | 
			
		||||
BackendCounters::AsyncOperationCounters::registerError(std::uint64_t count)
 | 
			
		||||
{
 | 
			
		||||
    assert(pendingCounter_.get().value() >= static_cast<std::int64_t>(count));
 | 
			
		||||
    ASSERT(
 | 
			
		||||
        pendingCounter_.get().value() >= static_cast<std::int64_t>(count), "Error operations can't be more than pending"
 | 
			
		||||
    );
 | 
			
		||||
    pendingCounter_.get() -= count;
 | 
			
		||||
    errorCounter_.get() += count;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#include <data/BackendInterface.h>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <util/log/Logger.h>
 | 
			
		||||
 | 
			
		||||
#include <ripple/protocol/Indexes.h>
 | 
			
		||||
@@ -43,7 +44,7 @@ BackendInterface::finishWrites(std::uint32_t const ledgerSequence)
 | 
			
		||||
void
 | 
			
		||||
BackendInterface::writeLedgerObject(std::string&& key, std::uint32_t const seq, std::string&& blob)
 | 
			
		||||
{
 | 
			
		||||
    assert(key.size() == sizeof(ripple::uint256));
 | 
			
		||||
    ASSERT(key.size() == sizeof(ripple::uint256), "Key must be 256 bits");
 | 
			
		||||
    doWriteLedgerObject(std::move(key), seq, std::move(blob));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -188,7 +189,7 @@ BackendInterface::fetchBookOffers(
 | 
			
		||||
            }
 | 
			
		||||
            auto nextKey = ripple::keylet::page(uTipIndex, next);
 | 
			
		||||
            auto nextDir = fetchLedgerObject(nextKey.key, ledgerSequence, yield);
 | 
			
		||||
            assert(nextDir);
 | 
			
		||||
            ASSERT(nextDir.has_value(), "Next dir must exist");
 | 
			
		||||
            offerDir->blob = *nextDir;
 | 
			
		||||
            offerDir->key = nextKey.key;
 | 
			
		||||
        }
 | 
			
		||||
@@ -200,7 +201,7 @@ BackendInterface::fetchBookOffers(
 | 
			
		||||
    for (size_t i = 0; i < keys.size() && i < limit; ++i) {
 | 
			
		||||
        LOG(gLog.trace()) << "Key = " << ripple::strHex(keys[i]) << " blob = " << ripple::strHex(objs[i])
 | 
			
		||||
                          << " ledgerSequence = " << ledgerSequence;
 | 
			
		||||
        assert(!objs[i].empty());
 | 
			
		||||
        ASSERT(!objs[i].empty(), "Ledger object can't be empty");
 | 
			
		||||
        page.offers.push_back({keys[i], objs[i]});
 | 
			
		||||
    }
 | 
			
		||||
    auto end = std::chrono::system_clock::now();
 | 
			
		||||
@@ -234,7 +235,14 @@ void
 | 
			
		||||
BackendInterface::updateRange(uint32_t newMax)
 | 
			
		||||
{
 | 
			
		||||
    std::scoped_lock const lck(rngMtx_);
 | 
			
		||||
    assert(!range || newMax >= range->maxSequence);
 | 
			
		||||
 | 
			
		||||
    ASSERT(
 | 
			
		||||
        !range || newMax >= range->maxSequence,
 | 
			
		||||
        "Range shouldn't exist yet or newMax should be greater. newMax = {}, range->maxSequence = {}",
 | 
			
		||||
        newMax,
 | 
			
		||||
        range->maxSequence
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    if (!range) {
 | 
			
		||||
        range = {newMax, newMax};
 | 
			
		||||
    } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@
 | 
			
		||||
#include <data/cassandra/Schema.h>
 | 
			
		||||
#include <data/cassandra/SettingsProvider.h>
 | 
			
		||||
#include <data/cassandra/impl/ExecutionStrategy.h>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <util/LedgerUtils.h>
 | 
			
		||||
#include <util/Profiler.h>
 | 
			
		||||
#include <util/log/Logger.h>
 | 
			
		||||
@@ -622,7 +623,7 @@ public:
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        assert(numHashes == results.size());
 | 
			
		||||
        ASSERT(numHashes == results.size(), "Number of hashes and results must match");
 | 
			
		||||
        LOG(log_.debug()) << "Fetched " << numHashes << " transactions from Cassandra in " << timeDiff
 | 
			
		||||
                          << " milliseconds";
 | 
			
		||||
        return results;
 | 
			
		||||
@@ -735,8 +736,8 @@ public:
 | 
			
		||||
    {
 | 
			
		||||
        LOG(log_.trace()) << "Writing successor. key = " << key.size() << " bytes. "
 | 
			
		||||
                          << " seq = " << std::to_string(seq) << " successor = " << successor.size() << " bytes.";
 | 
			
		||||
        assert(!key.empty());
 | 
			
		||||
        assert(!successor.empty());
 | 
			
		||||
        ASSERT(!key.empty(), "Key must not be empty");
 | 
			
		||||
        ASSERT(!successor.empty(), "Successor must not be empty");
 | 
			
		||||
 | 
			
		||||
        executor_.write(schema_->insertSuccessor, std::move(key), seq, std::move(successor));
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,8 @@
 | 
			
		||||
/** @file */
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
 | 
			
		||||
#include <ripple/basics/Log.h>
 | 
			
		||||
#include <ripple/basics/StringUtilities.h>
 | 
			
		||||
#include <ripple/protocol/SField.h>
 | 
			
		||||
@@ -233,7 +235,7 @@ getBookBase(T const& key)
 | 
			
		||||
{
 | 
			
		||||
    static constexpr size_t KEY_SIZE = 24;
 | 
			
		||||
 | 
			
		||||
    assert(key.size() == ripple::uint256::size());
 | 
			
		||||
    ASSERT(key.size() == ripple::uint256::size(), "Invalid key size {}", key.size());
 | 
			
		||||
 | 
			
		||||
    ripple::uint256 ret;
 | 
			
		||||
    for (size_t i = 0; i < KEY_SIZE; ++i)
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#include <data/LedgerCache.h>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
 | 
			
		||||
namespace data {
 | 
			
		||||
 | 
			
		||||
@@ -37,7 +38,12 @@ LedgerCache::update(std::vector<LedgerObject> const& objs, uint32_t seq, bool is
 | 
			
		||||
    {
 | 
			
		||||
        std::scoped_lock const lck{mtx_};
 | 
			
		||||
        if (seq > latestSeq_) {
 | 
			
		||||
            assert(seq == latestSeq_ + 1 || latestSeq_ == 0);
 | 
			
		||||
            ASSERT(
 | 
			
		||||
                seq == latestSeq_ + 1 || latestSeq_ == 0,
 | 
			
		||||
                "New sequense must be either next or first. seq = {}, latestSeq_ = {}",
 | 
			
		||||
                seq,
 | 
			
		||||
                latestSeq_
 | 
			
		||||
            );
 | 
			
		||||
            latestSeq_ = seq;
 | 
			
		||||
        }
 | 
			
		||||
        for (auto const& obj : objs) {
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@
 | 
			
		||||
#include <data/cassandra/Handle.h>
 | 
			
		||||
#include <data/cassandra/Types.h>
 | 
			
		||||
#include <data/cassandra/impl/AsyncExecutor.h>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <util/Expected.h>
 | 
			
		||||
#include <util/log/Logger.h>
 | 
			
		||||
 | 
			
		||||
@@ -400,7 +401,7 @@ public:
 | 
			
		||||
        numReadRequestsOutstanding_ -= statements.size();
 | 
			
		||||
 | 
			
		||||
        if (errorsCount > 0) {
 | 
			
		||||
            assert(errorsCount <= statements.size());
 | 
			
		||||
            ASSERT(errorsCount <= statements.size(), "Errors number cannot exceed statements number");
 | 
			
		||||
            counters_->registerReadError(errorsCount);
 | 
			
		||||
            counters_->registerReadFinished(statements.size() - errorsCount);
 | 
			
		||||
            throw DatabaseTimeout{};
 | 
			
		||||
@@ -422,8 +423,18 @@ public:
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        assert(futures.size() == statements.size());
 | 
			
		||||
        assert(results.size() == statements.size());
 | 
			
		||||
        ASSERT(
 | 
			
		||||
            futures.size() == statements.size(),
 | 
			
		||||
            "Futures size must be equal to statements size. Got {} and {}",
 | 
			
		||||
            futures.size(),
 | 
			
		||||
            statements.size()
 | 
			
		||||
        );
 | 
			
		||||
        ASSERT(
 | 
			
		||||
            results.size() == statements.size(),
 | 
			
		||||
            "Results size must be equal to statements size. Got {} and {}",
 | 
			
		||||
            results.size(),
 | 
			
		||||
            statements.size()
 | 
			
		||||
        );
 | 
			
		||||
        return results;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -455,10 +466,7 @@ private:
 | 
			
		||||
    decrementOutstandingRequestCount()
 | 
			
		||||
    {
 | 
			
		||||
        // sanity check
 | 
			
		||||
        if (numWriteRequestsOutstanding_ == 0) {
 | 
			
		||||
            assert(false);
 | 
			
		||||
            throw std::runtime_error("decrementing num outstanding below 0");
 | 
			
		||||
        }
 | 
			
		||||
        ASSERT(numWriteRequestsOutstanding_ > 0, "Decrementing num outstanding below 0");
 | 
			
		||||
        size_t const cur = (--numWriteRequestsOutstanding_);
 | 
			
		||||
        {
 | 
			
		||||
            // mutex lock required to prevent race condition around spurious
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <queue>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
 | 
			
		||||
namespace etl {
 | 
			
		||||
/**
 | 
			
		||||
@@ -209,7 +210,7 @@ public:
 | 
			
		||||
inline std::vector<ripple::uint256>
 | 
			
		||||
getMarkers(size_t numMarkers)
 | 
			
		||||
{
 | 
			
		||||
    assert(numMarkers <= 256);
 | 
			
		||||
    ASSERT(numMarkers <= 256, "Number of markers must be <= 256. Got: {}", numMarkers);
 | 
			
		||||
 | 
			
		||||
    unsigned char const incr = 256 / numMarkers;
 | 
			
		||||
 | 
			
		||||
@@ -222,4 +223,4 @@ getMarkers(size_t numMarkers)
 | 
			
		||||
    }
 | 
			
		||||
    return markers;
 | 
			
		||||
}
 | 
			
		||||
}  // namespace etl
 | 
			
		||||
}  // namespace etl
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#include <etl/ETLService.h>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <util/Constants.h>
 | 
			
		||||
 | 
			
		||||
#include <ripple/protocol/LedgerHeader.h>
 | 
			
		||||
@@ -125,7 +126,7 @@ ETLService::monitor()
 | 
			
		||||
        cacheLoader_.load(rng->maxSequence);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    assert(rng);
 | 
			
		||||
    ASSERT(rng.has_value(), "Ledger range can't be null");
 | 
			
		||||
    uint32_t nextSequence = rng->maxSequence + 1;
 | 
			
		||||
 | 
			
		||||
    LOG(log_.debug()) << "Database is populated. "
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@
 | 
			
		||||
#include <etl/ProbingSource.h>
 | 
			
		||||
#include <etl/Source.h>
 | 
			
		||||
#include <rpc/RPCHelpers.h>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <util/Profiler.h>
 | 
			
		||||
#include <util/Random.h>
 | 
			
		||||
#include <util/log/Logger.h>
 | 
			
		||||
@@ -206,7 +207,7 @@ bool
 | 
			
		||||
LoadBalancer::shouldPropagateTxnStream(Source* in) const
 | 
			
		||||
{
 | 
			
		||||
    for (auto& src : sources_) {
 | 
			
		||||
        assert(src);
 | 
			
		||||
        ASSERT(src != nullptr, "Source is nullptr");
 | 
			
		||||
 | 
			
		||||
        // We pick the first Source encountered that is connected
 | 
			
		||||
        if (src->isConnected())
 | 
			
		||||
 
 | 
			
		||||
@@ -794,7 +794,7 @@ private:
 | 
			
		||||
                uint32_t const sequence = std::stoll(minAndMax[0]);
 | 
			
		||||
                pairs.emplace_back(sequence, sequence);
 | 
			
		||||
            } else {
 | 
			
		||||
                assert(minAndMax.size() == 2);
 | 
			
		||||
                ASSERT(minAndMax.size() == 2, "Min and max should be of size 2. Got size = {}", minAndMax.size());
 | 
			
		||||
                uint32_t const min = std::stoll(minAndMax[0]);
 | 
			
		||||
                uint32_t const max = std::stoll(minAndMax[1]);
 | 
			
		||||
                pairs.emplace_back(min, max);
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@
 | 
			
		||||
 | 
			
		||||
#include <data/BackendInterface.h>
 | 
			
		||||
#include <etl/NFTHelpers.h>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <util/log/Logger.h>
 | 
			
		||||
 | 
			
		||||
#include <ripple/proto/org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h>
 | 
			
		||||
@@ -60,7 +61,12 @@ public:
 | 
			
		||||
                          << " . prefix = " << ripple::strHex(std::string(1, prefix))
 | 
			
		||||
                          << " . nextPrefix_ = " << ripple::strHex(std::string(1, nextPrefix_));
 | 
			
		||||
 | 
			
		||||
        assert(nextPrefix_ > prefix || nextPrefix_ == 0x00);
 | 
			
		||||
        ASSERT(
 | 
			
		||||
            nextPrefix_ > prefix || nextPrefix_ == 0x00,
 | 
			
		||||
            "Next prefix must be greater than current prefix. Got: nextPrefix_ = {}, prefix = {}",
 | 
			
		||||
            nextPrefix_,
 | 
			
		||||
            prefix
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        cur_ = std::make_unique<org::xrpl::rpc::v1::GetLedgerDataResponse>();
 | 
			
		||||
        next_ = std::make_unique<org::xrpl::rpc::v1::GetLedgerDataResponse>();
 | 
			
		||||
 
 | 
			
		||||
@@ -134,10 +134,7 @@ public:
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (cache_.get().isFull()) {
 | 
			
		||||
            assert(false);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        ASSERT(!cache_.get().isFull(), "Cache must not be full. seq = {}", seq);
 | 
			
		||||
 | 
			
		||||
        if (!clioPeers_.empty()) {
 | 
			
		||||
            boost::asio::spawn(ioContext_.get(), [this, seq](boost::asio::yield_context yield) {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <etl/SystemState.h>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <util/Profiler.h>
 | 
			
		||||
#include <util/log/Logger.h>
 | 
			
		||||
 | 
			
		||||
@@ -76,7 +77,7 @@ public:
 | 
			
		||||
    void
 | 
			
		||||
    waitTillFinished()
 | 
			
		||||
    {
 | 
			
		||||
        assert(thread_.joinable());
 | 
			
		||||
        ASSERT(thread_.joinable(), "Extractor thread must be joinable");
 | 
			
		||||
        thread_.join();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@
 | 
			
		||||
#include <etl/NFTHelpers.h>
 | 
			
		||||
#include <etl/SystemState.h>
 | 
			
		||||
#include <etl/impl/LedgerFetcher.h>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <util/LedgerUtils.h>
 | 
			
		||||
#include <util/Profiler.h>
 | 
			
		||||
#include <util/log/Logger.h>
 | 
			
		||||
@@ -152,8 +153,7 @@ public:
 | 
			
		||||
        // check that database is actually empty
 | 
			
		||||
        auto rng = backend_->hardFetchLedgerRangeNoThrow();
 | 
			
		||||
        if (rng) {
 | 
			
		||||
            LOG(log_.fatal()) << "Database is not empty";
 | 
			
		||||
            assert(false);
 | 
			
		||||
            ASSERT(false, "Database is not empty");
 | 
			
		||||
            return {};
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -189,50 +189,48 @@ public:
 | 
			
		||||
                size_t numWrites = 0;
 | 
			
		||||
                backend_->cache().setFull();
 | 
			
		||||
 | 
			
		||||
                auto seconds =
 | 
			
		||||
                    ::util::timed<std::chrono::seconds>([this, edgeKeys = &edgeKeys, sequence, &numWrites]() {
 | 
			
		||||
                        for (auto& key : *edgeKeys) {
 | 
			
		||||
                            LOG(log_.debug()) << "Writing edge key = " << ripple::strHex(key);
 | 
			
		||||
                            auto succ =
 | 
			
		||||
                                backend_->cache().getSuccessor(*ripple::uint256::fromVoidChecked(key), sequence);
 | 
			
		||||
                            if (succ)
 | 
			
		||||
                                backend_->writeSuccessor(std::move(key), sequence, uint256ToString(succ->key));
 | 
			
		||||
                        }
 | 
			
		||||
                auto seconds = ::util::timed<std::chrono::seconds>([this, edgeKeys = &edgeKeys, sequence, &numWrites] {
 | 
			
		||||
                    for (auto& key : *edgeKeys) {
 | 
			
		||||
                        LOG(log_.debug()) << "Writing edge key = " << ripple::strHex(key);
 | 
			
		||||
                        auto succ = backend_->cache().getSuccessor(*ripple::uint256::fromVoidChecked(key), sequence);
 | 
			
		||||
                        if (succ)
 | 
			
		||||
                            backend_->writeSuccessor(std::move(key), sequence, uint256ToString(succ->key));
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                        ripple::uint256 prev = data::firstKey;
 | 
			
		||||
                        while (auto cur = backend_->cache().getSuccessor(prev, sequence)) {
 | 
			
		||||
                            assert(cur);
 | 
			
		||||
                            if (prev == data::firstKey)
 | 
			
		||||
                                backend_->writeSuccessor(uint256ToString(prev), sequence, uint256ToString(cur->key));
 | 
			
		||||
                    ripple::uint256 prev = data::firstKey;
 | 
			
		||||
                    while (auto cur = backend_->cache().getSuccessor(prev, sequence)) {
 | 
			
		||||
                        ASSERT(cur.has_value(), "Succesor for key {} must exist", ripple::strHex(prev));
 | 
			
		||||
                        if (prev == data::firstKey)
 | 
			
		||||
                            backend_->writeSuccessor(uint256ToString(prev), sequence, uint256ToString(cur->key));
 | 
			
		||||
 | 
			
		||||
                            if (isBookDir(cur->key, cur->blob)) {
 | 
			
		||||
                                auto base = getBookBase(cur->key);
 | 
			
		||||
                                // make sure the base is not an actual object
 | 
			
		||||
                                if (!backend_->cache().get(cur->key, sequence)) {
 | 
			
		||||
                                    auto succ = backend_->cache().getSuccessor(base, sequence);
 | 
			
		||||
                                    assert(succ);
 | 
			
		||||
                                    if (succ->key == cur->key) {
 | 
			
		||||
                                        LOG(log_.debug()) << "Writing book successor = " << ripple::strHex(base)
 | 
			
		||||
                                                          << " - " << ripple::strHex(cur->key);
 | 
			
		||||
                        if (isBookDir(cur->key, cur->blob)) {
 | 
			
		||||
                            auto base = getBookBase(cur->key);
 | 
			
		||||
                            // make sure the base is not an actual object
 | 
			
		||||
                            if (!backend_->cache().get(cur->key, sequence)) {
 | 
			
		||||
                                auto succ = backend_->cache().getSuccessor(base, sequence);
 | 
			
		||||
                                ASSERT(succ.has_value(), "Book base {} must have a successor", ripple::strHex(base));
 | 
			
		||||
                                if (succ->key == cur->key) {
 | 
			
		||||
                                    LOG(log_.debug()) << "Writing book successor = " << ripple::strHex(base) << " - "
 | 
			
		||||
                                                      << ripple::strHex(cur->key);
 | 
			
		||||
 | 
			
		||||
                                        backend_->writeSuccessor(
 | 
			
		||||
                                            uint256ToString(base), sequence, uint256ToString(cur->key)
 | 
			
		||||
                                        );
 | 
			
		||||
                                    }
 | 
			
		||||
                                    backend_->writeSuccessor(
 | 
			
		||||
                                        uint256ToString(base), sequence, uint256ToString(cur->key)
 | 
			
		||||
                                    );
 | 
			
		||||
                                }
 | 
			
		||||
 | 
			
		||||
                                ++numWrites;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            prev = cur->key;
 | 
			
		||||
                            static constexpr std::size_t LOG_INTERVAL = 100000;
 | 
			
		||||
                            if (numWrites % LOG_INTERVAL == 0 && numWrites != 0)
 | 
			
		||||
                                LOG(log_.info()) << "Wrote " << numWrites << " book successors";
 | 
			
		||||
                            ++numWrites;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        backend_->writeSuccessor(uint256ToString(prev), sequence, uint256ToString(data::lastKey));
 | 
			
		||||
                        ++numWrites;
 | 
			
		||||
                    });
 | 
			
		||||
                        prev = cur->key;
 | 
			
		||||
                        static constexpr std::size_t LOG_INTERVAL = 100000;
 | 
			
		||||
                        if (numWrites % LOG_INTERVAL == 0 && numWrites != 0)
 | 
			
		||||
                            LOG(log_.info()) << "Wrote " << numWrites << " book successors";
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    backend_->writeSuccessor(uint256ToString(prev), sequence, uint256ToString(data::lastKey));
 | 
			
		||||
                    ++numWrites;
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                LOG(log_.info()) << "Looping through cache and submitting all writes took " << seconds
 | 
			
		||||
                                 << " seconds. numWrites = " << std::to_string(numWrites);
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@
 | 
			
		||||
#include <data/BackendInterface.h>
 | 
			
		||||
#include <etl/SystemState.h>
 | 
			
		||||
#include <feed/SubscriptionManager.h>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <util/LedgerUtils.h>
 | 
			
		||||
#include <util/log/Logger.h>
 | 
			
		||||
 | 
			
		||||
@@ -115,7 +116,7 @@ public:
 | 
			
		||||
                return backend_->fetchLedgerBySequence(ledgerSequence, yield);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            assert(lgr);
 | 
			
		||||
            ASSERT(lgr.has_value(), "Ledger must exist in database. Ledger sequence = {}", ledgerSequence);
 | 
			
		||||
            publish(*lgr);
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
@@ -157,7 +158,7 @@ public:
 | 
			
		||||
                std::optional<ripple::Fees> fees = data::synchronousAndRetryOnTimeout([&](auto yield) {
 | 
			
		||||
                    return backend_->fetchFees(lgrInfo.seq, yield);
 | 
			
		||||
                });
 | 
			
		||||
                assert(fees);
 | 
			
		||||
                ASSERT(fees.has_value(), "Fees must exist for ledger {}", lgrInfo.seq);
 | 
			
		||||
 | 
			
		||||
                std::vector<data::TransactionAndMetadata> transactions =
 | 
			
		||||
                    data::synchronousAndRetryOnTimeout([&](auto yield) {
 | 
			
		||||
@@ -165,7 +166,7 @@ public:
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                auto const ledgerRange = backend_->fetchLedgerRange();
 | 
			
		||||
                assert(ledgerRange);
 | 
			
		||||
                ASSERT(ledgerRange.has_value(), "Ledger range must exist");
 | 
			
		||||
 | 
			
		||||
                std::string const range =
 | 
			
		||||
                    std::to_string(ledgerRange->minSequence) + "-" + std::to_string(ledgerRange->maxSequence);
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@
 | 
			
		||||
#include <etl/SystemState.h>
 | 
			
		||||
#include <etl/impl/AmendmentBlock.h>
 | 
			
		||||
#include <etl/impl/LedgerLoader.h>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <util/LedgerUtils.h>
 | 
			
		||||
#include <util/Profiler.h>
 | 
			
		||||
#include <util/log/Logger.h>
 | 
			
		||||
@@ -113,7 +114,7 @@ public:
 | 
			
		||||
    void
 | 
			
		||||
    waitTillFinished()
 | 
			
		||||
    {
 | 
			
		||||
        assert(thread_.joinable());
 | 
			
		||||
        ASSERT(thread_.joinable(), "Transformer thread must be joinable");
 | 
			
		||||
        thread_.join();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -228,7 +229,7 @@ private:
 | 
			
		||||
 | 
			
		||||
        for (auto& obj : *(rawData.mutable_ledger_objects()->mutable_objects())) {
 | 
			
		||||
            auto key = ripple::uint256::fromVoidChecked(obj.key());
 | 
			
		||||
            assert(key);
 | 
			
		||||
            ASSERT(key.has_value(), "Failed to deserialize key from void");
 | 
			
		||||
 | 
			
		||||
            cacheUpdates.push_back({*key, {obj.mutable_data()->begin(), obj.mutable_data()->end()}});
 | 
			
		||||
            LOG(log_.debug()) << "key = " << ripple::strHex(*key) << " - mod type = " << obj.mod_type();
 | 
			
		||||
@@ -245,7 +246,7 @@ private:
 | 
			
		||||
 | 
			
		||||
                if (isDeleted) {
 | 
			
		||||
                    auto const old = backend_->cache().get(*key, lgrInfo.seq - 1);
 | 
			
		||||
                    assert(old);
 | 
			
		||||
                    ASSERT(old.has_value(), "Deleted object must be in cache");
 | 
			
		||||
                    checkBookBase = isBookDir(*key, *old);
 | 
			
		||||
                } else {
 | 
			
		||||
                    checkBookBase = isBookDir(*key, *blob);
 | 
			
		||||
@@ -256,7 +257,11 @@ private:
 | 
			
		||||
 | 
			
		||||
                    auto const bookBase = getBookBase(*key);
 | 
			
		||||
                    auto const oldFirstDir = backend_->cache().getSuccessor(bookBase, lgrInfo.seq - 1);
 | 
			
		||||
                    assert(oldFirstDir);
 | 
			
		||||
                    ASSERT(
 | 
			
		||||
                        oldFirstDir.has_value(),
 | 
			
		||||
                        "Book base must have a successor for lgrInfo.seq - 1 = {}",
 | 
			
		||||
                        lgrInfo.seq - 1
 | 
			
		||||
                    );
 | 
			
		||||
 | 
			
		||||
                    // We deleted the first directory, or we added a directory prior to the old first
 | 
			
		||||
                    // directory
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@
 | 
			
		||||
#include <feed/SubscriptionManager.h>
 | 
			
		||||
#include <rpc/BookChangesHelper.h>
 | 
			
		||||
#include <rpc/RPCHelpers.h>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
 | 
			
		||||
namespace feed {
 | 
			
		||||
 | 
			
		||||
@@ -77,13 +78,13 @@ SubscriptionManager::subLedger(boost::asio::yield_context yield, SessionPtrType
 | 
			
		||||
    subscribeHelper(session, ledgerSubscribers_, [this](SessionPtrType session) { unsubLedger(session); });
 | 
			
		||||
 | 
			
		||||
    auto ledgerRange = backend_->fetchLedgerRange();
 | 
			
		||||
    assert(ledgerRange);
 | 
			
		||||
    ASSERT(ledgerRange.has_value(), "Ledger range must be valid");
 | 
			
		||||
    auto lgrInfo = backend_->fetchLedgerBySequence(ledgerRange->maxSequence, yield);
 | 
			
		||||
    assert(lgrInfo);
 | 
			
		||||
    ASSERT(lgrInfo.has_value(), "Ledger must be valid");
 | 
			
		||||
 | 
			
		||||
    std::optional<ripple::Fees> fees;
 | 
			
		||||
    fees = backend_->fetchFees(lgrInfo->seq, yield);
 | 
			
		||||
    assert(fees);
 | 
			
		||||
    ASSERT(fees.has_value(), "Fees must be valid");
 | 
			
		||||
 | 
			
		||||
    std::string const range = std::to_string(ledgerRange->minSequence) + "-" + std::to_string(ledgerRange->maxSequence);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@
 | 
			
		||||
#include <rpc/Counters.h>
 | 
			
		||||
#include <rpc/RPCEngine.h>
 | 
			
		||||
#include <rpc/common/impl/HandlerProvider.h>
 | 
			
		||||
#include <util/TerminationHandler.h>
 | 
			
		||||
#include <util/config/Config.h>
 | 
			
		||||
#include <util/prometheus/Prometheus.h>
 | 
			
		||||
#include <web/RPCServerHandler.h>
 | 
			
		||||
@@ -147,6 +148,7 @@ start(io_context& ioc, std::uint32_t numThreads)
 | 
			
		||||
int
 | 
			
		||||
main(int argc, char* argv[])
 | 
			
		||||
try {
 | 
			
		||||
    util::setTerminationHandler();
 | 
			
		||||
    auto const configPath = parseCli(argc, argv);
 | 
			
		||||
    auto const config = ConfigReader::open(configPath);
 | 
			
		||||
    if (!config) {
 | 
			
		||||
@@ -218,4 +220,8 @@ try {
 | 
			
		||||
    return EXIT_SUCCESS;
 | 
			
		||||
} catch (std::exception const& e) {
 | 
			
		||||
    LOG(LogService::fatal()) << "Exit on exception: " << e.what();
 | 
			
		||||
    return EXIT_FAILURE;
 | 
			
		||||
} catch (...) {
 | 
			
		||||
    LOG(LogService::fatal()) << "Exit on exception: unknown";
 | 
			
		||||
    return EXIT_FAILURE;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@
 | 
			
		||||
#include <rpc/RPCHelpers.h>
 | 
			
		||||
#include <rpc/common/Types.h>
 | 
			
		||||
#include <rpc/common/Validators.h>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
 | 
			
		||||
namespace feed {
 | 
			
		||||
class SubscriptionManager;
 | 
			
		||||
@@ -129,7 +130,7 @@ private:
 | 
			
		||||
            } else if (stream == "book_changes") {
 | 
			
		||||
                subscriptions_->unsubBookChanges(session);
 | 
			
		||||
            } else {
 | 
			
		||||
                assert(false);
 | 
			
		||||
                ASSERT(false, "Unknown stream: {}", stream);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										53
									
								
								src/util/Assert.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/util/Assert.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
/*
 | 
			
		||||
    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.
 | 
			
		||||
*/
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <util/SourceLocation.h>
 | 
			
		||||
 | 
			
		||||
#include <boost/stacktrace.hpp>
 | 
			
		||||
#include <fmt/format.h>
 | 
			
		||||
#include <fmt/ostream.h>
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct fmt::formatter<boost::stacktrace::stacktrace> : ostream_formatter {};
 | 
			
		||||
 | 
			
		||||
namespace util {
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
constexpr void
 | 
			
		||||
assertImpl(
 | 
			
		||||
    SourceLocationType const location,
 | 
			
		||||
    char const* expression,
 | 
			
		||||
    bool const condition,
 | 
			
		||||
    fmt::format_string<Args...> format,
 | 
			
		||||
    Args&&... args
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    if (!condition) {
 | 
			
		||||
        fmt::println(stderr, "Assertion '{}' failed at {}:{}:", expression, location.file_name(), location.line());
 | 
			
		||||
        fmt::println(stderr, format, std::forward<Args>(args)...);
 | 
			
		||||
        fmt::println(stderr, "Stacktrace:\n{}\n", boost::stacktrace::stacktrace());
 | 
			
		||||
        std::abort();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace util
 | 
			
		||||
 | 
			
		||||
#define ASSERT(condition, ...) util::assertImpl(CURRENT_SRC_LOCATION, #condition, (condition), __VA_ARGS__)
 | 
			
		||||
@@ -18,6 +18,8 @@
 | 
			
		||||
//==============================================================================
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
 | 
			
		||||
#include <random>
 | 
			
		||||
 | 
			
		||||
namespace util {
 | 
			
		||||
@@ -28,7 +30,7 @@ public:
 | 
			
		||||
    static T
 | 
			
		||||
    uniform(T min, T max)
 | 
			
		||||
    {
 | 
			
		||||
        assert(min <= max);
 | 
			
		||||
        ASSERT(min <= max, "Min cannot be greater than max. min: {}, max: {}", min, max);
 | 
			
		||||
        if constexpr (std::is_floating_point_v<T>) {
 | 
			
		||||
            std::uniform_real_distribution<T> distribution(min, max);
 | 
			
		||||
            return distribution(generator_);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										78
									
								
								src/util/SourceLocation.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/util/SourceLocation.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
/*
 | 
			
		||||
    This file is part of clio: https://github.com/XRPLF/clio
 | 
			
		||||
    Copyright (c) 2022, 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.
 | 
			
		||||
*/
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#if defined(HAS_SOURCE_LOCATION) && __has_builtin(__builtin_source_location)
 | 
			
		||||
// this is used by fully compatible compilers like gcc
 | 
			
		||||
#include <source_location>
 | 
			
		||||
 | 
			
		||||
#elif defined(HAS_EXPERIMENTAL_SOURCE_LOCATION)
 | 
			
		||||
// this is used by clang on linux where source_location is still not out of
 | 
			
		||||
// experimental headers
 | 
			
		||||
#include <experimental/source_location>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace util {
 | 
			
		||||
 | 
			
		||||
#if defined(HAS_SOURCE_LOCATION) && __has_builtin(__builtin_source_location)
 | 
			
		||||
using SourceLocationType = std::source_location;
 | 
			
		||||
 | 
			
		||||
#elif defined(HAS_EXPERIMENTAL_SOURCE_LOCATION)
 | 
			
		||||
using SourceLocationType = std::experimental::source_location;
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
// A workaround for AppleClang that is lacking source_location atm.
 | 
			
		||||
// TODO: remove this workaround when all compilers catch up to c++20
 | 
			
		||||
class SourceLocation {
 | 
			
		||||
    char const* file_;
 | 
			
		||||
    std::size_t line_;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    constexpr SourceLocation(char const* file, std::size_t line) : file_{file}, line_{line}
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    constexpr std::string_view
 | 
			
		||||
    file_name() const
 | 
			
		||||
    {
 | 
			
		||||
        return file_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    constexpr std::size_t
 | 
			
		||||
    line() const
 | 
			
		||||
    {
 | 
			
		||||
        return line_;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
using SourceLocationType = SourceLocation;
 | 
			
		||||
#define SOURCE_LOCATION_OLD_API
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
}  // namespace util
 | 
			
		||||
 | 
			
		||||
#if defined(SOURCE_LOCATION_OLD_API)
 | 
			
		||||
#define CURRENT_SRC_LOCATION util::SourceLocationType(__FILE__, __LINE__)
 | 
			
		||||
#else
 | 
			
		||||
#define CURRENT_SRC_LOCATION util::SourceLocationType::current()
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										50
									
								
								src/util/TerminationHandler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/util/TerminationHandler.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
/*
 | 
			
		||||
    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 <util/TerminationHandler.h>
 | 
			
		||||
#include <util/log/Logger.h>
 | 
			
		||||
 | 
			
		||||
#include <boost/stacktrace.hpp>
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
namespace util {
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
terminationHandler()
 | 
			
		||||
{
 | 
			
		||||
    try {
 | 
			
		||||
        LOG(LogService::fatal()) << "Exit on terminate. Backtrace:\n" << boost::stacktrace::stacktrace();
 | 
			
		||||
    } catch (...) {
 | 
			
		||||
        LOG(LogService::fatal()) << "Exit on terminate. Can't get backtrace.";
 | 
			
		||||
    }
 | 
			
		||||
    std::abort();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
setTerminationHandler()
 | 
			
		||||
{
 | 
			
		||||
    std::set_terminate(terminationHandler);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace util
 | 
			
		||||
							
								
								
									
										27
									
								
								src/util/TerminationHandler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/util/TerminationHandler.h
									
									
									
									
									
										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.
 | 
			
		||||
*/
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
namespace util {
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
setTerminationHandler();
 | 
			
		||||
 | 
			
		||||
}  // namespace util
 | 
			
		||||
@@ -19,6 +19,8 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <util/SourceLocation.h>
 | 
			
		||||
 | 
			
		||||
#include <boost/algorithm/string/predicate.hpp>
 | 
			
		||||
#include <boost/filesystem.hpp>
 | 
			
		||||
#include <boost/json.hpp>
 | 
			
		||||
@@ -35,58 +37,10 @@
 | 
			
		||||
#include <boost/log/utility/setup/file.hpp>
 | 
			
		||||
#include <boost/log/utility/setup/formatter_parser.hpp>
 | 
			
		||||
 | 
			
		||||
#if defined(HAS_SOURCE_LOCATION) && __has_builtin(__builtin_source_location)
 | 
			
		||||
// this is used by fully compatible compilers like gcc
 | 
			
		||||
#include <source_location>
 | 
			
		||||
 | 
			
		||||
#elif defined(HAS_EXPERIMENTAL_SOURCE_LOCATION)
 | 
			
		||||
// this is used by clang on linux where source_location is still not out of
 | 
			
		||||
// experimental headers
 | 
			
		||||
#include <experimental/source_location>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace util {
 | 
			
		||||
 | 
			
		||||
class Config;
 | 
			
		||||
 | 
			
		||||
#if defined(HAS_SOURCE_LOCATION) && __has_builtin(__builtin_source_location)
 | 
			
		||||
using SourceLocationType = std::source_location;
 | 
			
		||||
#define CURRENT_SRC_LOCATION SourceLocationType::current()
 | 
			
		||||
 | 
			
		||||
#elif defined(HAS_EXPERIMENTAL_SOURCE_LOCATION)
 | 
			
		||||
using SourceLocationType = std::experimental::source_location;
 | 
			
		||||
#define CURRENT_SRC_LOCATION SourceLocationType::current()
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
// A workaround for AppleClang that is lacking source_location atm.
 | 
			
		||||
// TODO: remove this workaround when all compilers catch up to c++20
 | 
			
		||||
class SourceLocation {
 | 
			
		||||
    std::string_view file_;
 | 
			
		||||
    std::size_t line_;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    SourceLocation(std::string_view file, std::size_t line) : file_{file}, line_{line}
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string_view
 | 
			
		||||
    file_name() const
 | 
			
		||||
    {
 | 
			
		||||
        return file_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::size_t
 | 
			
		||||
    line() const
 | 
			
		||||
    {
 | 
			
		||||
        return line_;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
using SourceLocationType = SourceLocation;
 | 
			
		||||
#define CURRENT_SRC_LOCATION SourceLocationType(__builtin_FILE(), __builtin_LINE())
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Skips evaluation of expensive argument lists if the given logger is disabled for the required severity level.
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <util/prometheus/Metrics.h>
 | 
			
		||||
#include <util/prometheus/impl/AnyCounterBase.h>
 | 
			
		||||
 | 
			
		||||
@@ -64,7 +65,7 @@ struct AnyCounter : MetricBase, detail::AnyCounterBase<NumberType> {
 | 
			
		||||
    AnyCounter&
 | 
			
		||||
    operator+=(ValueType const value)
 | 
			
		||||
    {
 | 
			
		||||
        assert(value >= 0);
 | 
			
		||||
        ASSERT(value >= 0, "Cannot decrease a counter");
 | 
			
		||||
        this->pimpl_->add(value);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -20,8 +20,6 @@
 | 
			
		||||
#include <util/prometheus/Counter.h>
 | 
			
		||||
#include <util/prometheus/Gauge.h>
 | 
			
		||||
 | 
			
		||||
#include <cassert>
 | 
			
		||||
 | 
			
		||||
namespace util::prometheus {
 | 
			
		||||
 | 
			
		||||
MetricBase::MetricBase(std::string name, std::string labelsString)
 | 
			
		||||
@@ -52,7 +50,7 @@ toString(MetricType type)
 | 
			
		||||
        case MetricType::SUMMARY:
 | 
			
		||||
            return "summary";
 | 
			
		||||
        default:
 | 
			
		||||
            assert(false);
 | 
			
		||||
            ASSERT(false, "Unknown metric type: {}", static_cast<int>(type));
 | 
			
		||||
    }
 | 
			
		||||
    return "";
 | 
			
		||||
}
 | 
			
		||||
@@ -85,7 +83,7 @@ MetricsFamily::MetricBuilder MetricsFamily::defaultMetricBuilder =
 | 
			
		||||
        case MetricType::HISTOGRAM:
 | 
			
		||||
            [[fallthrough]];
 | 
			
		||||
        default:
 | 
			
		||||
            assert(false);
 | 
			
		||||
            ASSERT(false, "Unknown metric type: {}", static_cast<int>(type));
 | 
			
		||||
    }
 | 
			
		||||
    return nullptr;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@
 | 
			
		||||
*/
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <util/prometheus/Prometheus.h>
 | 
			
		||||
 | 
			
		||||
namespace util::prometheus {
 | 
			
		||||
@@ -28,9 +29,7 @@ MetricType&
 | 
			
		||||
convertBaseTo(MetricBase& metricBase)
 | 
			
		||||
{
 | 
			
		||||
    auto result = dynamic_cast<MetricType*>(&metricBase);
 | 
			
		||||
    assert(result != nullptr);
 | 
			
		||||
    if (result == nullptr)
 | 
			
		||||
        throw std::runtime_error("Failed to convert metric type");
 | 
			
		||||
    ASSERT(result != nullptr, "Failed to cast metric {} to the requested type", metricBase.name());
 | 
			
		||||
    return *result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -162,7 +161,7 @@ PrometheusService::replaceInstance(std::unique_ptr<util::prometheus::PrometheusI
 | 
			
		||||
util::prometheus::PrometheusInterface&
 | 
			
		||||
PrometheusService::instance()
 | 
			
		||||
{
 | 
			
		||||
    assert(instance_);
 | 
			
		||||
    ASSERT(instance_ != nullptr, "PrometheusService::instance() called before init()");
 | 
			
		||||
    return *instance_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,8 +23,6 @@
 | 
			
		||||
#include <util/prometheus/Counter.h>
 | 
			
		||||
#include <util/prometheus/Gauge.h>
 | 
			
		||||
 | 
			
		||||
#include <cassert>
 | 
			
		||||
 | 
			
		||||
namespace util::prometheus {
 | 
			
		||||
 | 
			
		||||
class PrometheusInterface {
 | 
			
		||||
 
 | 
			
		||||
@@ -19,8 +19,9 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <concepts>
 | 
			
		||||
 | 
			
		||||
namespace util::prometheus::detail {
 | 
			
		||||
@@ -55,7 +56,7 @@ public:
 | 
			
		||||
    // Move constructor should be used only used during initialization
 | 
			
		||||
    CounterImpl(CounterImpl&& other)
 | 
			
		||||
    {
 | 
			
		||||
        assert(other.value_ == 0);
 | 
			
		||||
        ASSERT(other.value_ == 0, "Move constructor should only be used during initialization");
 | 
			
		||||
        value_ = other.value_.exchange(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <util/config/Config.h>
 | 
			
		||||
#include <util/log/Logger.h>
 | 
			
		||||
#include <web/IntervalSweepHandler.h>
 | 
			
		||||
@@ -172,7 +173,7 @@ public:
 | 
			
		||||
        if (whitelistHandler_.get().isWhiteListed(ip))
 | 
			
		||||
            return;
 | 
			
		||||
        std::scoped_lock const lck{mtx_};
 | 
			
		||||
        assert(ipConnCount_[ip] > 0);
 | 
			
		||||
        ASSERT(ipConnCount_[ip] > 0, "Connection count for ip {} can't be 0", ip);
 | 
			
		||||
        ipConnCount_[ip]--;
 | 
			
		||||
        if (ipConnCount_[ip] == 0)
 | 
			
		||||
            ipConnCount_.erase(ip);
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@
 | 
			
		||||
 | 
			
		||||
#include <web/IntervalSweepHandler.h>
 | 
			
		||||
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <util/Constants.h>
 | 
			
		||||
#include <web/DOSGuard.h>
 | 
			
		||||
 | 
			
		||||
@@ -47,9 +48,9 @@ IntervalSweepHandler::~IntervalSweepHandler()
 | 
			
		||||
void
 | 
			
		||||
IntervalSweepHandler::setup(web::BaseDOSGuard* guard)
 | 
			
		||||
{
 | 
			
		||||
    assert(dosGuard_ == nullptr);
 | 
			
		||||
    ASSERT(dosGuard_ == nullptr, "Cannot setup DOS guard more than once");
 | 
			
		||||
    dosGuard_ = guard;
 | 
			
		||||
    assert(dosGuard_ != nullptr);
 | 
			
		||||
    ASSERT(dosGuard_ != nullptr, "DOS guard must be not null");
 | 
			
		||||
 | 
			
		||||
    createTimer();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <rpc/Errors.h>
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <web/interface/ConnectionBase.h>
 | 
			
		||||
 | 
			
		||||
#include <boost/beast/http.hpp>
 | 
			
		||||
@@ -82,7 +83,9 @@ public:
 | 
			
		||||
                    case rpc::ClioError::rpcMALFORMED_ADDRESS:
 | 
			
		||||
                    case rpc::ClioError::rpcINVALID_HOT_WALLET:
 | 
			
		||||
                    case rpc::ClioError::rpcFIELD_NOT_FOUND_TRANSACTION:
 | 
			
		||||
                        assert(false);  // this should never happen
 | 
			
		||||
                        ASSERT(
 | 
			
		||||
                            false, "Unknown rpc error code {}", static_cast<int>(*clioCode)
 | 
			
		||||
                        );  // this should never happen
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@
 | 
			
		||||
*/
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#include <util/Assert.h>
 | 
			
		||||
#include <util/Fixtures.h>
 | 
			
		||||
#include <util/config/Config.h>
 | 
			
		||||
 | 
			
		||||
@@ -192,7 +193,7 @@ struct Custom {
 | 
			
		||||
    friend Custom
 | 
			
		||||
    tag_invoke(json::value_to_tag<Custom>, json::value const& value)
 | 
			
		||||
    {
 | 
			
		||||
        assert(value.is_object());
 | 
			
		||||
        ASSERT(value.is_object(), "Value must be an object");
 | 
			
		||||
        auto const& obj = value.as_object();
 | 
			
		||||
        return {obj.at("str").as_string().c_str(), obj.at("int").as_int64(), obj.at("bool").as_bool()};
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,8 @@
 | 
			
		||||
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
*/
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#include <util/TerminationHandler.h>
 | 
			
		||||
#include <util/prometheus/Prometheus.h>
 | 
			
		||||
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
@@ -23,6 +25,7 @@
 | 
			
		||||
int
 | 
			
		||||
main(int argc, char** argv)
 | 
			
		||||
{
 | 
			
		||||
    util::setTerminationHandler();
 | 
			
		||||
    PrometheusService::init();
 | 
			
		||||
    testing::InitGoogleTest(&argc, argv);
 | 
			
		||||
    return RUN_ALL_TESTS();
 | 
			
		||||
 
 | 
			
		||||
@@ -225,6 +225,7 @@ TEST_F(BackendCountersMockPrometheusTest, registerWriteFinished)
 | 
			
		||||
        makeMock<GaugeInt>("backend_operations_current_number", "{operation=\"write_async\",status=\"pending\"}");
 | 
			
		||||
    auto& completedCounter =
 | 
			
		||||
        makeMock<CounterInt>("backend_operations_total_number", "{operation=\"write_async\",status=\"completed\"}");
 | 
			
		||||
    EXPECT_CALL(pendingCounter, value()).WillOnce(testing::Return(1));
 | 
			
		||||
    EXPECT_CALL(pendingCounter, add(-1));
 | 
			
		||||
    EXPECT_CALL(completedCounter, add(1));
 | 
			
		||||
    counters->registerWriteFinished();
 | 
			
		||||
@@ -252,6 +253,7 @@ TEST_F(BackendCountersMockPrometheusTest, registerReadFinished)
 | 
			
		||||
        makeMock<GaugeInt>("backend_operations_current_number", "{operation=\"read_async\",status=\"pending\"}");
 | 
			
		||||
    auto& completedCounter =
 | 
			
		||||
        makeMock<CounterInt>("backend_operations_total_number", "{operation=\"read_async\",status=\"completed\"}");
 | 
			
		||||
    EXPECT_CALL(pendingCounter, value()).WillOnce(testing::Return(1));
 | 
			
		||||
    EXPECT_CALL(pendingCounter, add(-1));
 | 
			
		||||
    EXPECT_CALL(completedCounter, add(1));
 | 
			
		||||
    counters->registerReadFinished();
 | 
			
		||||
@@ -271,6 +273,7 @@ TEST_F(BackendCountersMockPrometheusTest, registerReadError)
 | 
			
		||||
        makeMock<GaugeInt>("backend_operations_current_number", "{operation=\"read_async\",status=\"pending\"}");
 | 
			
		||||
    auto& errorCounter =
 | 
			
		||||
        makeMock<CounterInt>("backend_operations_total_number", "{operation=\"read_async\",status=\"error\"}");
 | 
			
		||||
    EXPECT_CALL(pendingCounter, value()).WillOnce(testing::Return(1));
 | 
			
		||||
    EXPECT_CALL(pendingCounter, add(-1));
 | 
			
		||||
    EXPECT_CALL(errorCounter, add(1));
 | 
			
		||||
    counters->registerReadError();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								unittests/util/AssertTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								unittests/util/AssertTests.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
/*
 | 
			
		||||
    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 <util/Assert.h>
 | 
			
		||||
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
 | 
			
		||||
TEST(AssertTests, assertTrue)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_NO_THROW(ASSERT(true, "Should not fail"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(AssertTests, assertFalse)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_DEATH({ ASSERT(false, "failure"); }, "failure");
 | 
			
		||||
}
 | 
			
		||||
@@ -78,8 +78,7 @@ struct MockPrometheusImpl : PrometheusInterface {
 | 
			
		||||
        }
 | 
			
		||||
        auto* basePtr = it->second.get();
 | 
			
		||||
        auto* metricPtr = dynamic_cast<MetricType*>(basePtr);
 | 
			
		||||
        if (metricPtr == nullptr)
 | 
			
		||||
            throw std::runtime_error("Wrong metric type");
 | 
			
		||||
        ASSERT(metricPtr != nullptr, "Wrong metric type");
 | 
			
		||||
        return *metricPtr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -101,8 +100,7 @@ struct MockPrometheusImpl : PrometheusInterface {
 | 
			
		||||
        }
 | 
			
		||||
        auto* ptr = metrics.emplace(key, std::move(metric)).first->second.get();
 | 
			
		||||
        auto metricPtr = dynamic_cast<MetricType*>(ptr);
 | 
			
		||||
        if (metricPtr == nullptr)
 | 
			
		||||
            throw std::runtime_error("Wrong metric type");
 | 
			
		||||
        ASSERT(metricPtr != nullptr, "Wrong metric type");
 | 
			
		||||
        return *metricPtr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -137,8 +135,7 @@ struct WithMockPrometheus : virtual ::testing::Test {
 | 
			
		||||
    mockPrometheus()
 | 
			
		||||
    {
 | 
			
		||||
        auto* ptr = dynamic_cast<MockPrometheusImpl*>(&PrometheusService::instance());
 | 
			
		||||
        if (ptr == nullptr)
 | 
			
		||||
            throw std::runtime_error("Wrong prometheus type");
 | 
			
		||||
        ASSERT(ptr != nullptr, "Wrong prometheus type");
 | 
			
		||||
        return *ptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -147,8 +144,7 @@ struct WithMockPrometheus : virtual ::testing::Test {
 | 
			
		||||
    makeMock(std::string name, std::string labelsString)
 | 
			
		||||
    {
 | 
			
		||||
        auto* mockPrometheusPtr = dynamic_cast<MockPrometheusImpl*>(&PrometheusService::instance());
 | 
			
		||||
        if (mockPrometheusPtr == nullptr)
 | 
			
		||||
            throw std::runtime_error("Wrong prometheus type");
 | 
			
		||||
        ASSERT(mockPrometheusPtr != nullptr, "Wrong prometheus type");
 | 
			
		||||
 | 
			
		||||
        std::string const key = name + labelsString;
 | 
			
		||||
        mockPrometheusPtr->makeMetric<MetricType>(std::move(name), std::move(labelsString));
 | 
			
		||||
@@ -159,7 +155,7 @@ struct WithMockPrometheus : virtual ::testing::Test {
 | 
			
		||||
        } else if constexpr (std::is_same_v<typename MetricType::ValueType, double>) {
 | 
			
		||||
            return mockPrometheusPtr->counterDoubleImpls[key];
 | 
			
		||||
        }
 | 
			
		||||
        throw std::runtime_error("Wrong metric type");
 | 
			
		||||
        ASSERT(false, "Wrong metric type");
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user