From 6ab02caa22e65d1d286e0903c3d01d1aa9b0deb1 Mon Sep 17 00:00:00 2001 From: JCW Date: Tue, 2 Sep 2025 17:22:53 +0100 Subject: [PATCH] Optimise Signed-off-by: JCW --- cmake/RippledCore.cmake | 3 - conanfile.py | 3 +- include/xrpl/beast/utility/Journal.h | 115 +++--- src/libxrpl/beast/utility/beast_Journal.cpp | 26 +- src/tests/libxrpl/CMakeLists.txt | 3 +- src/tests/libxrpl/basics/log.cpp | 365 +++++++++----------- 6 files changed, 263 insertions(+), 252 deletions(-) diff --git a/cmake/RippledCore.cmake b/cmake/RippledCore.cmake index 74e8a0f956..427f678359 100644 --- a/cmake/RippledCore.cmake +++ b/cmake/RippledCore.cmake @@ -51,8 +51,6 @@ target_link_libraries(xrpl.libpb # TODO: Clean up the number of library targets later. add_library(xrpl.imports.main INTERFACE) -find_package(RapidJSON) - target_link_libraries(xrpl.imports.main INTERFACE LibArchive::LibArchive @@ -77,7 +75,6 @@ add_module(xrpl beast) target_link_libraries(xrpl.libxrpl.beast PUBLIC xrpl.imports.main xrpl.libpb - rapidjson ) # Level 02 diff --git a/conanfile.py b/conanfile.py index 30645c325a..fa29b4a064 100644 --- a/conanfile.py +++ b/conanfile.py @@ -29,8 +29,7 @@ class Xrpl(ConanFile): 'nudb/2.0.9', 'openssl/1.1.1w', 'soci/4.0.3', - 'zlib/1.3.1', - "rapidjson/1.1.0" + 'zlib/1.3.1' ] test_requires = [ diff --git a/include/xrpl/beast/utility/Journal.h b/include/xrpl/beast/utility/Journal.h index 452306f2da..5723006f09 100644 --- a/include/xrpl/beast/utility/Journal.h +++ b/include/xrpl/beast/utility/Journal.h @@ -23,9 +23,10 @@ #include #include -#include #include #include +#include +#include #include namespace ripple::log { @@ -88,37 +89,45 @@ public: void startObject() const { - stream_.append("{", 1); + stream_.push_back('{'); } void endObject() const { + using namespace std::string_view_literals; stream_.pop_back(); - stream_.append("},", 2); + stream_.append("},"sv); } void writeKey(std::string_view key) const { writeString(key); - *stream_.rbegin() = ':'; + stream_.back() = ':'; } void startArray() const { - stream_.append("[", 1); + stream_.push_back('['); } void endArray() const { + using namespace std::string_view_literals; stream_.pop_back(); - stream_.append("],", 2); + stream_.append("],"sv); } void writeString(std::string_view str) const { + using namespace std::string_view_literals; stream_.push_back('"'); escape(str, stream_); - stream_.append("\",", 2); + stream_.append("\","sv); + } + std::string_view + writeInt(std::int32_t val) const + { + return pushNumber(val, stream_); } std::string_view writeInt(std::int64_t val) const @@ -126,6 +135,11 @@ public: return pushNumber(val, stream_); } std::string_view + writeUInt(std::uint32_t val) const + { + return pushNumber(val, stream_); + } + std::string_view writeUInt(std::uint64_t val) const { return pushNumber(val, stream_); @@ -138,15 +152,16 @@ public: std::string_view writeBool(bool val) const { - auto str = val ? "true," : "false,"; - stream_.append(str, std::strlen(str)); + using namespace std::string_view_literals; + auto str = val ? "true,"sv : "false,"sv; + stream_.append(str); return str; } void writeNull() const { - stream_.append("null", std::strlen("null")); - stream_.push_back(','); + using namespace std::string_view_literals; + stream_.append("null,"sv); } void writeRaw(std::string_view str) const @@ -154,11 +169,10 @@ public: stream_.append(str); } - [[nodiscard]] std::string + [[nodiscard]] std::string_view finish() { - stream_.pop_back(); - return stream_; + return std::string_view{stream_.c_str(), stream_.size() - 1}; } private: @@ -166,10 +180,11 @@ private: static std::string_view pushNumber(T val, std::string& stream) { - static char buffer[128]; + thread_local char buffer[128]; auto result = std::to_chars(std::begin(buffer), std::end(buffer), val); - *result.ptr = ','; - auto len = result.ptr - std::begin(buffer); + auto ptr = result.ptr; + *ptr = ','; + auto len = ptr - std::begin(buffer); stream.append(buffer, len + 1); return {buffer, static_cast(len)}; } @@ -179,17 +194,19 @@ private: { static constexpr char HEX[] = "0123456789ABCDEF"; - const char* p = str.data(); - const char* end = p + str.size(); - const char* chunk = p; + char const* p = str.data(); + char const* end = p + str.size(); + char const* chunk = p; - while (p < end) { + while (p < end) + { auto c = static_cast(*p); // JSON requires escaping for <0x20 and the two specials below. bool needsEscape = (c < 0x20) || (c == '"') || (c == '\\'); - if (!needsEscape) { + if (!needsEscape) + { ++p; continue; } @@ -198,21 +215,33 @@ private: if (chunk != p) os.append(chunk, p - chunk); - switch (c) { - case '"': os.append("\\\"", 2); break; - case '\\': os.append("\\\\", 2); break; - case '\b': os.append("\\b", 2); break; - case '\f': os.append("\\f", 2); break; - case '\n': os.append("\\n", 2); break; - case '\r': os.append("\\r", 2); break; - case '\t': os.append("\\t", 2); break; + switch (c) + { + case '"': + os.append("\\\"", 2); + break; + case '\\': + os.append("\\\\", 2); + break; + case '\b': + os.append("\\b", 2); + break; + case '\f': + os.append("\\f", 2); + break; + case '\n': + os.append("\\n", 2); + break; + case '\r': + os.append("\\r", 2); + break; + case '\t': + os.append("\\t", 2); + break; default: { // Other C0 controls -> \u00XX (JSON compliant) char buf[6]{ - '\\','u','0','0', - HEX[(c >> 4) & 0xF], - HEX[c & 0xF] - }; + '\\', 'u', '0', '0', HEX[(c >> 4) & 0xF], HEX[c & 0xF]}; os.append(buf, 6); break; } @@ -288,6 +317,7 @@ public: public: JsonLogContext() : messageParamsWriter_(buffer_) { + buffer_.reserve(1024 * 5); } SimpleJsonWriter& @@ -300,7 +330,7 @@ public: reset( std::source_location location, severities::Severity severity, - std::string const& journalAttributesJson) noexcept; + std::string_view journalAttributesJson) noexcept; }; private: @@ -323,7 +353,7 @@ private: std::source_location location, severities::Severity severity) const; - static std::string + static std::string_view formatLog(std::string&& message); public: @@ -830,9 +860,10 @@ namespace ripple::log { namespace detail { template -concept CanToChars = requires (T val) -{ - { to_chars(std::declval(), std::declval(), val) } -> std::convertible_to; +concept CanToChars = requires(T val) { + { + to_chars(std::declval(), std::declval(), val) + } -> std::convertible_to; }; template @@ -901,7 +932,8 @@ setJsonValue( if constexpr (CanToChars) { char buffer[1024]; - std::to_chars_result result = to_chars(std::begin(buffer), std::end(buffer), value); + std::to_chars_result result = + to_chars(std::begin(buffer), std::end(buffer), value); if (result.ec == std::errc{}) { std::string_view sv; @@ -925,7 +957,8 @@ setJsonValue( if (outStream) { - outStream->write(str.c_str(), static_cast(str.size())); + outStream->write( + str.c_str(), static_cast(str.size())); } } } diff --git a/src/libxrpl/beast/utility/beast_Journal.cpp b/src/libxrpl/beast/utility/beast_Journal.cpp index 8cc8a811f6..74a42fb34a 100644 --- a/src/libxrpl/beast/utility/beast_Journal.cpp +++ b/src/libxrpl/beast/utility/beast_Journal.cpp @@ -123,7 +123,7 @@ void Journal::JsonLogContext::reset( std::source_location location, severities::Severity severity, - std::string const& journalAttributesJson) noexcept + std::string_view journalAttributesJson) noexcept { struct ThreadIdStringInitializer { @@ -152,7 +152,9 @@ Journal::JsonLogContext::reset( if (!globalLogAttributesJson_.empty()) { writer().writeKey("GlobalParams"); - writer().writeRaw(globalLogAttributesJson_); + writer().writeRaw(std::string_view{ + std::begin(globalLogAttributesJson_), + std::end(globalLogAttributesJson_)}); writer().endObject(); } @@ -166,7 +168,7 @@ Journal::JsonLogContext::reset( writer().writeString(location.file_name()); writer().writeKey("Line"); - writer().writeInt(location.line()); + writer().writeInt(static_cast(location.line())); writer().writeKey("ThreadId"); writer().writeString(threadId.value); @@ -176,9 +178,9 @@ Journal::JsonLogContext::reset( writer().writeString(severityStr); writer().writeKey("Time"); - writer().writeUInt(std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()) - .count()); + writer().writeInt(std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count()); } void @@ -186,10 +188,14 @@ Journal::initMessageContext( std::source_location location, severities::Severity severity) const { - currentJsonLogContext_.reset(location, severity, m_attributesJson); + currentJsonLogContext_.reset( + location, + severity, + std::string_view{ + std::begin(m_attributesJson), std::end(m_attributesJson)}); } -std::string +std::string_view Journal::formatLog(std::string&& message) { if (!m_jsonLogsEnabled) @@ -288,9 +294,9 @@ Journal::ScopedStream::~ScopedStream() if (!s.empty()) { if (s == "\n") - m_sink.write(m_level, formatLog("")); + m_sink.write(m_level, std::string{formatLog("")}); else - m_sink.write(m_level, formatLog(std::move(s))); + m_sink.write(m_level, std::string{formatLog(std::move(s))}); } } diff --git a/src/tests/libxrpl/CMakeLists.txt b/src/tests/libxrpl/CMakeLists.txt index b1765c5ceb..68c6fa6cb3 100644 --- a/src/tests/libxrpl/CMakeLists.txt +++ b/src/tests/libxrpl/CMakeLists.txt @@ -2,11 +2,10 @@ include(xrpl_add_test) # Test requirements. find_package(doctest REQUIRED) -find_package(RapidJSON REQUIRED) # Common library dependencies for the rest of the tests. add_library(xrpl.imports.test INTERFACE) -target_link_libraries(xrpl.imports.test INTERFACE doctest::doctest rapidjson xrpl.libxrpl) +target_link_libraries(xrpl.imports.test INTERFACE doctest::doctest xrpl.libxrpl) # One test for each module. xrpl_add_test(basics) diff --git a/src/tests/libxrpl/basics/log.cpp b/src/tests/libxrpl/basics/log.cpp index 3f015072fc..9bdb6f49ec 100644 --- a/src/tests/libxrpl/basics/log.cpp +++ b/src/tests/libxrpl/basics/log.cpp @@ -20,7 +20,10 @@ #include #include -#include +#include + +#include +#include using namespace ripple; @@ -51,21 +54,21 @@ private: void write(beast::severities::Severity level, std::string&& text) override { - logs_.logStream_ << text; + logs_.write(level, partition_, text, false); } void writeAlways(beast::severities::Severity level, std::string&& text) override { - logs_.logStream_ << text; + logs_.write(level, partition_, text, false); } }; - std::stringstream& logStream_; + std::string& logStream_; public: - MockLogs(std::stringstream& logStream, beast::severities::Severity level) + MockLogs(std::string& logStream, beast::severities::Severity level) : Logs(level), logStream_(logStream) { } @@ -77,23 +80,35 @@ public: { return std::make_unique(partition, startingLevel, *this); } + + void + write( + beast::severities::Severity level, + std::string const& partition, + std::string const& text, + bool console) + { + std::string s; + format(s, text, level, partition); + logStream_.append(s); + } }; TEST_CASE("Text logs") { - std::stringstream logStream; + std::string logStream; MockLogs logs{logStream, beast::severities::kAll}; logs.journal("Test").debug() << "Test"; - CHECK(logStream.str().find("Test") != std::string::npos); + CHECK(logStream.find("Test") != std::string::npos); - logStream.str(""); + logStream.clear(); logs.journal("Test").debug() << "\n"; - CHECK(logStream.str().find("\n") == std::string::npos); + CHECK(logStream.find("\n") == std::string::npos); } TEST_CASE("Test format output") @@ -118,35 +133,34 @@ TEST_CASE("Test format output when structured logs are enabled") TEST_CASE("Enable json logs") { - std::stringstream logStream; + std::string logStream; MockLogs logs{logStream, beast::severities::kAll}; - logs.journal("Test").debug() << "Test"; + logs.journal("Test ").debug() << "Test123"; - CHECK(logStream.str() == "Test"); + CHECK(logStream.find("Test123") != std::string::npos); - logStream.str(""); + logStream.clear(); beast::Journal::enableStructuredJournal(); logs.journal("Test").debug() << "\n"; - rapidjson::Document doc; - doc.Parse(logStream.str().c_str()); + boost::system::error_code ec; + auto doc = boost::json::parse(logStream, ec); + CHECK(ec == boost::system::errc::success); - CHECK(doc.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK(doc.IsObject()); - CHECK(doc.HasMember("Message")); - CHECK(doc["Message"].IsString()); - CHECK(doc["Message"].GetString() == std::string{""}); + CHECK(doc.is_object()); + CHECK(doc.as_object().contains("Message")); + CHECK(doc.as_object()["Message"].is_string()); + CHECK(doc.as_object()["Message"].get_string() == ""); beast::Journal::disableStructuredJournal(); } TEST_CASE("Global attributes") { - std::stringstream logStream; + std::string logStream; MockLogs logs{logStream, beast::severities::kAll}; @@ -156,25 +170,23 @@ TEST_CASE("Global attributes") logs.journal("Test").debug() << "Test"; - rapidjson::Document jsonLog; - jsonLog.Parse(logStream.str().c_str()); + boost::system::error_code ec; + auto jsonLog = boost::json::parse(logStream, ec); + CHECK(ec == boost::system::errc::success); + CHECK(jsonLog.is_object()); + CHECK(jsonLog.as_object().contains("GlobalParams")); + CHECK(jsonLog.as_object()["GlobalParams"].is_object()); + CHECK(jsonLog.as_object()["GlobalParams"].as_object().contains("Field1")); + CHECK(jsonLog.as_object()["GlobalParams"].as_object()["Field1"].is_string()); CHECK( - jsonLog.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK(jsonLog.IsObject()); - CHECK(jsonLog.HasMember("GlobalParams")); - CHECK(jsonLog["GlobalParams"].IsObject()); - CHECK(jsonLog["GlobalParams"].HasMember("Field1")); - CHECK(jsonLog["GlobalParams"]["Field1"].IsString()); - CHECK( - jsonLog["GlobalParams"]["Field1"].GetString() == std::string{"Value1"}); + jsonLog.as_object()["GlobalParams"].as_object()["Field1"].get_string() == "Value1"); beast::Journal::disableStructuredJournal(); } TEST_CASE("Global attributes inheritable") { - std::stringstream logStream; + std::string logStream; MockLogs logs{logStream, beast::severities::kAll}; @@ -189,23 +201,19 @@ TEST_CASE("Global attributes inheritable") .debug() << "Test"; - rapidjson::Document jsonLog; - jsonLog.Parse(logStream.str().c_str()); + boost::system::error_code ec; + auto jsonLog = boost::json::parse(logStream, ec); + CHECK(ec == boost::system::errc::success); + CHECK(jsonLog.is_object()); + CHECK(jsonLog.as_object()["GlobalParams"].as_object().contains("Field1")); + CHECK(jsonLog.as_object()["GlobalParams"].as_object()["Field1"].is_string()); CHECK( - jsonLog.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK(jsonLog.IsObject()); - CHECK(jsonLog["GlobalParams"].HasMember("Field1")); - CHECK(jsonLog["GlobalParams"]["Field1"].IsString()); + jsonLog.as_object()["GlobalParams"].as_object()["Field1"].get_string() == "Value1"); CHECK( - jsonLog["GlobalParams"]["Field1"].GetString() == std::string{"Value1"}); + jsonLog.as_object()["JournalParams"].as_object()["Field1"].get_string() == "Value3"); CHECK( - jsonLog["JournalParams"]["Field1"].GetString() == - std::string{"Value3"}); - CHECK( - jsonLog["JournalParams"]["Field2"].GetString() == - std::string{"Value2"}); + jsonLog.as_object()["JournalParams"].as_object()["Field2"].get_string() == "Value2"); beast::Journal::disableStructuredJournal(); } @@ -311,35 +319,33 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJsonLogFields") << std::boolalpha << false << log::field("Field3", "Value3"); - rapidjson::Document logValue; - logValue.Parse(stream().str().c_str()); + boost::system::error_code ec; + auto logValue = boost::json::parse(stream().str(), ec); + CHECK(ec == boost::system::errc::success); - CHECK( - logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); + CHECK(logValue.is_object()); + CHECK(logValue.as_object().contains("GlobalParams")); + CHECK(logValue.as_object().contains("JournalParams")); + CHECK(logValue.as_object().contains("MessageParams")); + CHECK(logValue.as_object().contains("Message")); - CHECK(logValue.IsObject()); - CHECK(logValue.HasMember("GlobalParams")); - CHECK(logValue.HasMember("JournalParams")); - CHECK(logValue.HasMember("MessageParams")); - CHECK(logValue.HasMember("Message")); + CHECK(logValue.as_object()["GlobalParams"].is_object()); + CHECK(logValue.as_object()["JournalParams"].is_object()); + CHECK(logValue.as_object()["MessageParams"].is_object()); + CHECK(logValue.as_object()["Message"].is_string()); - CHECK(logValue["GlobalParams"].IsObject()); - CHECK(logValue["JournalParams"].IsObject()); - CHECK(logValue["MessageParams"].IsObject()); - CHECK(logValue["Message"].IsString()); + CHECK(logValue.as_object()["MessageParams"].as_object().contains("Function")); + CHECK(logValue.as_object()["MessageParams"].as_object().contains("File")); + CHECK(logValue.as_object()["MessageParams"].as_object().contains("Line")); + CHECK(logValue.as_object()["MessageParams"].as_object().contains("ThreadId")); + CHECK(logValue.as_object()["MessageParams"].as_object().contains("Level")); + CHECK(logValue.as_object()["MessageParams"].as_object().contains("Time")); - CHECK(logValue["MessageParams"].HasMember("Function")); - CHECK(logValue["MessageParams"].HasMember("File")); - CHECK(logValue["MessageParams"].HasMember("Line")); - CHECK(logValue["MessageParams"].HasMember("ThreadId")); - CHECK(logValue["MessageParams"].HasMember("Level")); - CHECK(logValue["MessageParams"].HasMember("Time")); + CHECK(logValue.as_object()["MessageParams"].as_object()["Function"].is_string()); + CHECK(logValue.as_object()["MessageParams"].as_object()["File"].is_string()); + CHECK(logValue.as_object()["MessageParams"].as_object()["Line"].is_number()); - CHECK(logValue["MessageParams"]["Function"].IsString()); - CHECK(logValue["MessageParams"]["File"].IsString()); - CHECK(logValue["MessageParams"]["Line"].IsNumber()); - - CHECK(logValue["Message"].GetString() == std::string{"true Test false"}); + CHECK(logValue.as_object()["Message"].get_string() == std::string{"true Test false"}); } TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJsonLogLevels") @@ -348,15 +354,12 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJsonLogLevels") stream().str(""); journal().trace() << "Test"; - rapidjson::Document logValue; - logValue.Parse(stream().str().c_str()); + boost::system::error_code ec; + auto logValue = boost::json::parse(stream().str(), ec); + CHECK(ec == boost::system::errc::success); CHECK( - logValue.GetParseError() == - rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK( - logValue["MessageParams"]["Level"].GetString() == + logValue.as_object()["MessageParams"].as_object()["Level"].get_string() == beast::severities::to_string(beast::severities::kTrace)); } @@ -364,15 +367,12 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJsonLogLevels") stream().str(""); journal().debug() << "Test"; - rapidjson::Document logValue; - logValue.Parse(stream().str().c_str()); + boost::system::error_code ec; + auto logValue = boost::json::parse(stream().str(), ec); + CHECK(ec == boost::system::errc::success); CHECK( - logValue.GetParseError() == - rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK( - logValue["MessageParams"]["Level"].GetString() == + logValue.as_object()["MessageParams"].as_object()["Level"].get_string() == beast::severities::to_string(beast::severities::kDebug)); } @@ -380,15 +380,12 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJsonLogLevels") stream().str(""); journal().info() << "Test"; - rapidjson::Document logValue; - logValue.Parse(stream().str().c_str()); + boost::system::error_code ec; + auto logValue = boost::json::parse(stream().str(), ec); + CHECK(ec == boost::system::errc::success); CHECK( - logValue.GetParseError() == - rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK( - logValue["MessageParams"]["Level"].GetString() == + logValue.as_object()["MessageParams"].as_object()["Level"].get_string() == beast::severities::to_string(beast::severities::kInfo)); } @@ -396,15 +393,12 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJsonLogLevels") stream().str(""); journal().warn() << "Test"; - rapidjson::Document logValue; - logValue.Parse(stream().str().c_str()); + boost::system::error_code ec; + auto logValue = boost::json::parse(stream().str(), ec); + CHECK(ec == boost::system::errc::success); CHECK( - logValue.GetParseError() == - rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK( - logValue["MessageParams"]["Level"].GetString() == + logValue.as_object()["MessageParams"].as_object()["Level"].get_string() == beast::severities::to_string(beast::severities::kWarning)); } @@ -412,15 +406,12 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJsonLogLevels") stream().str(""); journal().error() << "Test"; - rapidjson::Document logValue; - logValue.Parse(stream().str().c_str()); + boost::system::error_code ec; + auto logValue = boost::json::parse(stream().str(), ec); + CHECK(ec == boost::system::errc::success); CHECK( - logValue.GetParseError() == - rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK( - logValue["MessageParams"]["Level"].GetString() == + logValue.as_object()["MessageParams"].as_object()["Level"].get_string() == beast::severities::to_string(beast::severities::kError)); } @@ -428,15 +419,12 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJsonLogLevels") stream().str(""); journal().fatal() << "Test"; - rapidjson::Document logValue; - logValue.Parse(stream().str().c_str()); + boost::system::error_code ec; + auto logValue = boost::json::parse(stream().str(), ec); + CHECK(ec == boost::system::errc::success); CHECK( - logValue.GetParseError() == - rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK( - logValue["MessageParams"]["Level"].GetString() == + logValue.as_object()["MessageParams"].as_object()["Level"].get_string() == beast::severities::to_string(beast::severities::kFatal)); } } @@ -445,14 +433,12 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJsonLogStream") { journal().stream(beast::severities::kError) << "Test"; - rapidjson::Document logValue; - logValue.Parse(stream().str().c_str()); + boost::system::error_code ec; + auto logValue = boost::json::parse(stream().str(), ec); + CHECK(ec == boost::system::errc::success); CHECK( - logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK( - logValue["MessageParams"]["Level"].GetString() == + logValue.as_object()["MessageParams"].as_object()["Level"].get_string() == beast::severities::to_string(beast::severities::kError)); } @@ -461,25 +447,28 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJsonLogParams") journal().debug() << "Test: " << log::param("Field1", 1) << ", " << log::param( "Field2", - std::numeric_limits::max()); + std::numeric_limits::max()) + << ", " + << log::param("Field3", std::numbers::pi); - rapidjson::Document logValue; - logValue.Parse(stream().str().c_str()); + boost::system::error_code ec; + auto logValue = boost::json::parse(stream().str(), ec); + CHECK(ec == boost::system::errc::success); + CHECK(logValue.as_object()["MessageParams"].is_object()); + CHECK(logValue.as_object()["MessageParams"].as_object()["Field1"].is_number()); + CHECK(logValue.as_object()["MessageParams"].as_object()["Field1"].get_int64() == 1); + CHECK(logValue.as_object()["MessageParams"].as_object()["Field2"].is_number()); CHECK( - logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK(logValue["MessageParams"].IsObject()); - CHECK(logValue["MessageParams"]["Field1"].IsNumber()); - CHECK(logValue["MessageParams"]["Field1"].GetInt() == 1); - CHECK(logValue["MessageParams"]["Field2"].IsNumber()); - CHECK( - logValue["MessageParams"]["Field2"].GetUint64() == + logValue.as_object()["MessageParams"].as_object()["Field2"].get_uint64() == std::numeric_limits::max()); - CHECK(logValue["Message"].IsString()); CHECK( - logValue["Message"].GetString() == - std::string{"Test: 1, 18446744073709551615"}); + logValue.as_object()["MessageParams"].as_object()["Field3"].get_double() == + 3.141593); + CHECK(logValue.as_object()["Message"].is_string()); + CHECK( + logValue.as_object()["Message"].get_string() == + std::string{"Test: 1, 18446744073709551615, 3.141593"}); } TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJsonLogFields") @@ -489,24 +478,22 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJsonLogFields") "Field2", std::numeric_limits::max()); - rapidjson::Document logValue; - logValue.Parse(stream().str().c_str()); + boost::system::error_code ec; + auto logValue = boost::json::parse(stream().str(), ec); + CHECK(ec == boost::system::errc::success); - CHECK( - logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK(logValue["MessageParams"].IsObject()); - CHECK(logValue["MessageParams"]["Field1"].IsNumber()); - CHECK(logValue["MessageParams"]["Field1"].GetInt() == 1); + CHECK(logValue.as_object()["MessageParams"].is_object()); + CHECK(logValue.as_object()["MessageParams"].as_object()["Field1"].is_number()); + CHECK(logValue.as_object()["MessageParams"].as_object()["Field1"].get_int64() == 1); // UInt64 doesn't fit in Json::Value so it should be converted to a string // NOTE: We should expect it to be an int64 after we make the json library // support in64 and uint64 - CHECK(logValue["MessageParams"]["Field2"].IsNumber()); + CHECK(logValue.as_object()["MessageParams"].as_object()["Field2"].is_number()); CHECK( - logValue["MessageParams"]["Field2"].GetUint64() == + logValue.as_object()["MessageParams"].as_object()["Field2"].get_uint64() == std::numeric_limits::max()); - CHECK(logValue["Message"].IsString()); - CHECK(logValue["Message"].GetString() == std::string{"Test"}); + CHECK(logValue.as_object()["Message"].is_string()); + CHECK(logValue.as_object()["Message"].get_string() == "Test"); } TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJournalAttributes") @@ -517,18 +504,16 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJournalAttributes") j.debug() << "Test"; - rapidjson::Document logValue; - logValue.Parse(stream().str().c_str()); + boost::system::error_code ec; + auto logValue = boost::json::parse(stream().str(), ec); + CHECK(ec == boost::system::errc::success); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field1"].is_string()); CHECK( - logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK(logValue["JournalParams"]["Field1"].IsString()); - CHECK( - logValue["JournalParams"]["Field1"].GetString() == + logValue.as_object()["JournalParams"].as_object()["Field1"].get_string() == std::string{"Value1"}); - CHECK(logValue["JournalParams"]["Field2"].IsNumber()); - CHECK(logValue["JournalParams"]["Field2"].GetInt() == 2); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field2"].is_number()); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field2"].get_int64() == 2); } TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJournalAttributesInheritable") @@ -540,22 +525,20 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJournalAttributesInheritable") j2.debug() << "Test"; - rapidjson::Document logValue; - logValue.Parse(stream().str().c_str()); + boost::system::error_code ec; + auto logValue = boost::json::parse(stream().str(), ec); + CHECK(ec == boost::system::errc::success); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field1"].is_string()); CHECK( - logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK(logValue["JournalParams"]["Field1"].IsString()); - CHECK( - logValue["JournalParams"]["Field1"].GetString() == + logValue.as_object()["JournalParams"].as_object()["Field1"].get_string() == std::string{"Value1"}); - CHECK(logValue["JournalParams"]["Field3"].IsString()); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field3"].is_string()); CHECK( - logValue["JournalParams"]["Field3"].GetString() == + logValue.as_object()["JournalParams"].as_object()["Field3"].get_string() == std::string{"Value3"}); - CHECK(logValue["JournalParams"]["Field2"].IsNumber()); - CHECK(logValue["JournalParams"]["Field2"].GetInt() == 2); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field2"].is_number()); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field2"].get_int64() == 2); } TEST_CASE_FIXTURE( @@ -569,23 +552,21 @@ TEST_CASE_FIXTURE( j2.debug() << "Test"; - rapidjson::Document logValue; - logValue.Parse(stream().str().c_str()); + boost::system::error_code ec; + auto logValue = boost::json::parse(stream().str(), ec); + CHECK(ec == boost::system::errc::success); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field1"].is_string()); CHECK( - logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK(logValue["JournalParams"]["Field1"].IsString()); - CHECK( - logValue["JournalParams"]["Field1"].GetString() == + logValue.as_object()["JournalParams"].as_object()["Field1"].get_string() == std::string{"Value1"}); - CHECK(logValue["JournalParams"]["Field3"].IsString()); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field3"].is_string()); CHECK( - logValue["JournalParams"]["Field3"].GetString() == + logValue.as_object()["JournalParams"].as_object()["Field3"].get_string() == std::string{"Value3"}); // Field2 should be overwritten to 0 - CHECK(logValue["JournalParams"]["Field2"].IsNumber()); - CHECK(logValue["JournalParams"]["Field2"].GetInt() == 2); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field2"].is_number()); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field2"].get_int64() == 2); } TEST_CASE_FIXTURE( @@ -602,18 +583,16 @@ TEST_CASE_FIXTURE( j2.debug() << "Test"; - rapidjson::Document logValue; - logValue.Parse(stream().str().c_str()); + boost::system::error_code ec; + auto logValue = boost::json::parse(stream().str(), ec); + CHECK(ec == boost::system::errc::success); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field1"].is_string()); CHECK( - logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK(logValue["JournalParams"]["Field1"].IsString()); - CHECK( - logValue["JournalParams"]["Field1"].GetString() == + logValue.as_object()["JournalParams"].as_object()["Field1"].get_string() == std::string{"Value1"}); - CHECK(logValue["JournalParams"]["Field2"].IsNumber()); - CHECK(logValue["JournalParams"]["Field2"].GetInt() == 2); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field2"].is_number()); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field2"].get_int64() == 2); } TEST_CASE_FIXTURE( @@ -630,16 +609,14 @@ TEST_CASE_FIXTURE( j2.debug() << "Test"; - rapidjson::Document logValue; - logValue.Parse(stream().str().c_str()); + boost::system::error_code ec; + auto logValue = boost::json::parse(stream().str(), ec); + CHECK(ec == boost::system::errc::success); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field1"].is_string()); CHECK( - logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); - - CHECK(logValue["JournalParams"]["Field1"].IsString()); - CHECK( - logValue["JournalParams"]["Field1"].GetString() == + logValue.as_object()["JournalParams"].as_object()["Field1"].get_string() == std::string{"Value1"}); - CHECK(logValue["JournalParams"]["Field2"].IsNumber()); - CHECK(logValue["JournalParams"]["Field2"].GetInt() == 2); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field2"].is_number()); + CHECK(logValue.as_object()["JournalParams"].as_object()["Field2"].get_int64() == 2); } \ No newline at end of file