#include #include #include 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 } }