mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
210 lines
5.5 KiB
C++
210 lines
5.5 KiB
C++
#include <xrpl/basics/MallocTrim.h>
|
|
|
|
#include <boost/predef.h>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
using namespace xrpl;
|
|
|
|
// cSpell:ignore statm
|
|
|
|
#if defined(__GLIBC__) && BOOST_OS_LINUX
|
|
namespace xrpl::detail {
|
|
long
|
|
parseStatmRSSkB(std::string const& statm);
|
|
} // namespace xrpl::detail
|
|
#endif
|
|
|
|
TEST(MallocTrimReport, structure)
|
|
{
|
|
// Test default construction
|
|
MallocTrimReport report;
|
|
EXPECT_EQ(report.supported, false);
|
|
EXPECT_EQ(report.trimResult, -1);
|
|
EXPECT_EQ(report.rssBeforeKB, -1);
|
|
EXPECT_EQ(report.rssAfterKB, -1);
|
|
EXPECT_EQ(report.durationUs, std::chrono::microseconds{-1});
|
|
EXPECT_EQ(report.minfltDelta, -1);
|
|
EXPECT_EQ(report.majfltDelta, -1);
|
|
EXPECT_EQ(report.deltaKB(), 0);
|
|
|
|
// Test deltaKB calculation - memory freed
|
|
report.rssBeforeKB = 1000;
|
|
report.rssAfterKB = 800;
|
|
EXPECT_EQ(report.deltaKB(), -200);
|
|
|
|
// Test deltaKB calculation - memory increased
|
|
report.rssBeforeKB = 500;
|
|
report.rssAfterKB = 600;
|
|
EXPECT_EQ(report.deltaKB(), 100);
|
|
|
|
// Test deltaKB calculation - no change
|
|
report.rssBeforeKB = 1234;
|
|
report.rssAfterKB = 1234;
|
|
EXPECT_EQ(report.deltaKB(), 0);
|
|
}
|
|
|
|
#if defined(__GLIBC__) && BOOST_OS_LINUX
|
|
TEST(parseStatmRSSkB, standard_format)
|
|
{
|
|
using xrpl::detail::parseStatmRSSkB;
|
|
|
|
// Test standard format: size resident shared text lib data dt
|
|
// Assuming 4KB page size: resident=1000 pages = 4000 KB
|
|
{
|
|
std::string statm = "25365 1000 2377 0 0 5623 0";
|
|
long result = parseStatmRSSkB(statm);
|
|
// Note: actual result depends on system page size
|
|
// On most systems it's 4KB, so 1000 pages = 4000 KB
|
|
EXPECT_GT(result, 0);
|
|
}
|
|
|
|
// Test with newline
|
|
{
|
|
std::string statm = "12345 2000 1234 0 0 3456 0\n";
|
|
long result = parseStatmRSSkB(statm);
|
|
EXPECT_GT(result, 0);
|
|
}
|
|
|
|
// Test with tabs
|
|
{
|
|
std::string statm = "12345\t2000\t1234\t0\t0\t3456\t0";
|
|
long result = parseStatmRSSkB(statm);
|
|
EXPECT_GT(result, 0);
|
|
}
|
|
|
|
// Test zero resident pages
|
|
{
|
|
std::string statm = "25365 0 2377 0 0 5623 0";
|
|
long result = parseStatmRSSkB(statm);
|
|
EXPECT_EQ(result, 0);
|
|
}
|
|
|
|
// Test with extra whitespace
|
|
{
|
|
std::string statm = " 25365 1000 2377 ";
|
|
long result = parseStatmRSSkB(statm);
|
|
EXPECT_GT(result, 0);
|
|
}
|
|
|
|
// Test empty string
|
|
{
|
|
std::string statm = "";
|
|
long result = parseStatmRSSkB(statm);
|
|
EXPECT_EQ(result, -1);
|
|
}
|
|
|
|
// Test malformed data (only one field)
|
|
{
|
|
std::string statm = "25365";
|
|
long result = parseStatmRSSkB(statm);
|
|
EXPECT_EQ(result, -1);
|
|
}
|
|
|
|
// Test malformed data (non-numeric)
|
|
{
|
|
std::string statm = "abc def ghi";
|
|
long result = parseStatmRSSkB(statm);
|
|
EXPECT_EQ(result, -1);
|
|
}
|
|
|
|
// Test malformed data (second field non-numeric)
|
|
{
|
|
std::string statm = "25365 abc 2377";
|
|
long result = parseStatmRSSkB(statm);
|
|
EXPECT_EQ(result, -1);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
TEST(mallocTrim, without_debug_logging)
|
|
{
|
|
beast::Journal journal{beast::Journal::getNullSink()};
|
|
|
|
MallocTrimReport report = mallocTrim("without_debug", journal);
|
|
|
|
#if defined(__GLIBC__) && BOOST_OS_LINUX
|
|
EXPECT_EQ(report.supported, true);
|
|
EXPECT_GE(report.trimResult, 0);
|
|
EXPECT_EQ(report.durationUs, std::chrono::microseconds{-1});
|
|
EXPECT_EQ(report.minfltDelta, -1);
|
|
EXPECT_EQ(report.majfltDelta, -1);
|
|
#else
|
|
EXPECT_EQ(report.supported, false);
|
|
EXPECT_EQ(report.trimResult, -1);
|
|
EXPECT_EQ(report.rssBeforeKB, -1);
|
|
EXPECT_EQ(report.rssAfterKB, -1);
|
|
EXPECT_EQ(report.durationUs, std::chrono::microseconds{-1});
|
|
EXPECT_EQ(report.minfltDelta, -1);
|
|
EXPECT_EQ(report.majfltDelta, -1);
|
|
#endif
|
|
}
|
|
|
|
TEST(mallocTrim, empty_tag)
|
|
{
|
|
beast::Journal journal{beast::Journal::getNullSink()};
|
|
MallocTrimReport report = mallocTrim("", journal);
|
|
|
|
#if defined(__GLIBC__) && BOOST_OS_LINUX
|
|
EXPECT_EQ(report.supported, true);
|
|
EXPECT_GE(report.trimResult, 0);
|
|
#else
|
|
EXPECT_EQ(report.supported, false);
|
|
#endif
|
|
}
|
|
|
|
TEST(mallocTrim, with_debug_logging)
|
|
{
|
|
struct DebugSink : public beast::Journal::Sink
|
|
{
|
|
DebugSink() : Sink(beast::severities::kDebug, false)
|
|
{
|
|
}
|
|
void
|
|
write(beast::severities::Severity, std::string const&) override
|
|
{
|
|
}
|
|
void
|
|
writeAlways(beast::severities::Severity, std::string const&) override
|
|
{
|
|
}
|
|
};
|
|
|
|
DebugSink sink;
|
|
beast::Journal journal{sink};
|
|
|
|
MallocTrimReport report = mallocTrim("debug_test", journal);
|
|
|
|
#if defined(__GLIBC__) && BOOST_OS_LINUX
|
|
EXPECT_EQ(report.supported, true);
|
|
EXPECT_GE(report.trimResult, 0);
|
|
EXPECT_GE(report.durationUs.count(), 0);
|
|
EXPECT_GE(report.minfltDelta, 0);
|
|
EXPECT_GE(report.majfltDelta, 0);
|
|
#else
|
|
EXPECT_EQ(report.supported, false);
|
|
EXPECT_EQ(report.trimResult, -1);
|
|
EXPECT_EQ(report.durationUs, std::chrono::microseconds{-1});
|
|
EXPECT_EQ(report.minfltDelta, -1);
|
|
EXPECT_EQ(report.majfltDelta, -1);
|
|
#endif
|
|
}
|
|
|
|
TEST(mallocTrim, repeated_calls)
|
|
{
|
|
beast::Journal journal{beast::Journal::getNullSink()};
|
|
|
|
// Call malloc_trim multiple times to ensure it's safe
|
|
for (int i = 0; i < 5; ++i)
|
|
{
|
|
MallocTrimReport report = mallocTrim("iteration_" + std::to_string(i), journal);
|
|
|
|
#if defined(__GLIBC__) && BOOST_OS_LINUX
|
|
EXPECT_EQ(report.supported, true);
|
|
EXPECT_GE(report.trimResult, 0);
|
|
#else
|
|
EXPECT_EQ(report.supported, false);
|
|
#endif
|
|
}
|
|
}
|