Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/tests/libxrpl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,19 @@ find_package(GTest REQUIRED)
# Custom target for all tests defined in this file
add_custom_target(xrpl.tests)

# Test helpers
add_library(xrpl.helpers.test STATIC)
target_sources(xrpl.helpers.test PRIVATE
helpers/TestSink.cpp
)
target_include_directories(xrpl.helpers.test PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
target_link_libraries(xrpl.helpers.test PRIVATE xrpl.libxrpl)

# Common library dependencies for the rest of the tests.
add_library(xrpl.imports.test INTERFACE)
target_link_libraries(xrpl.imports.test INTERFACE gtest::gtest xrpl.libxrpl)
target_link_libraries(xrpl.imports.test INTERFACE gtest::gtest xrpl.libxrpl xrpl.helpers.test)

# One test for each module.
xrpl_add_test(basics)
Expand Down
127 changes: 127 additions & 0 deletions src/tests/libxrpl/helpers/TestSink.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#include <boost/predef.h>

#include <helpers/TestSink.h>

#include <cstdlib> // for getenv

#if BOOST_OS_WINDOWS
#include <io.h> // for _isatty, _fileno
#include <stdio.h> // for stdout
#else
#include <unistd.h> // for isatty, STDOUT_FILENO
#endif

#include <iostream>

namespace xrpl {

TestSink::TestSink(beast::severities::Severity threshold)
: Sink(threshold, false)
{
}

void
TestSink::write(beast::severities::Severity level, std::string const& text)
{
if (level < threshold())
return;
writeAlways(level, text);
}

void
TestSink::writeAlways(
beast::severities::Severity level,
std::string const& text)
{
auto supportsColor = [] {
// 1. Check for "NO_COLOR" environment variable (Standard convention)
if (std::getenv("NO_COLOR") != nullptr)
{
return false;
}

// 2. Check for "CLICOLOR_FORCE" (Force color)
if (std::getenv("CLICOLOR_FORCE") != nullptr)
{
return true;
}

// 3. Platform-specific check to see if stdout is a terminal
#if BOOST_OS_WINDOWS
// Windows: Check if the output handle is a character device
// _fileno(stdout) is usually 1
// _isatty returns non-zero if the handle is a character device, 0
// otherwise.
return _isatty(_fileno(stdout)) != 0;
#else
// Linux/macOS: Check if file descriptor 1 (stdout) is a TTY
// STDOUT_FILENO is 1
// isatty returns 1 if the file descriptor is a TTY, 0 otherwise.
return isatty(STDOUT_FILENO) != 0;
#endif
}();

auto color = [level]() {
switch (level)
{
case beast::severities::kTrace:
return "\033[34m"; // blue
case beast::severities::kDebug:
return "\033[32m"; // green
case beast::severities::kInfo:
return "\033[36m"; // cyan
case beast::severities::kWarning:
return "\033[33m"; // yellow
case beast::severities::kError:
return "\033[31m"; // red
case beast::severities::kFatal:
default:
break;
}
return "\033[31m"; // red
}();

auto prefix = [level]() {
switch (level)
{
case beast::severities::kTrace:
return "TRC:";
case beast::severities::kDebug:
return "DBG:";
case beast::severities::kInfo:
return "INF:";
case beast::severities::kWarning:
return "WRN:";
case beast::severities::kError:
return "ERR:";
case beast::severities::kFatal:
default:
break;
}
return "FTL:";
}();

auto& stream = [level]() -> std::ostream& {
switch (level)
{
case beast::severities::kError:
case beast::severities::kFatal:
return std::cerr;
default:
return std::cout;
}
}();

constexpr auto reset = "\033[0m";

if (supportsColor)
{
stream << color << prefix << " " << text << reset << std::endl;
}
else
{
stream << prefix << " " << text << std::endl;
}
}

} // namespace xrpl
27 changes: 27 additions & 0 deletions src/tests/libxrpl/helpers/TestSink.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef XRPL_DEBUGSINK_H
#define XRPL_DEBUGSINK_H

#include <xrpl/beast/utility/Journal.h>

namespace xrpl {
class TestSink : public beast::Journal::Sink
{
public:
static TestSink&
instance()
{
static TestSink sink{};
return sink;
}

TestSink(beast::severities::Severity threshold = beast::severities::kDebug);

void
write(beast::severities::Severity level, std::string const& text) override;

void
writeAlways(beast::severities::Severity level, std::string const& text)
override;
};
} // namespace xrpl
#endif // XRPL_DEBUGSINK_H
Loading
Loading