Arena debug visualization
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
||||
#include "../benchmarks/test_data.hpp"
|
||||
#include "commit_request.hpp"
|
||||
#include <doctest/doctest.h>
|
||||
#include <sstream>
|
||||
|
||||
TEST_CASE("CommitRequest basic parsing") {
|
||||
CommitRequest request;
|
||||
@@ -645,3 +647,178 @@ TEST_CASE("CommitRequest streaming parsing") {
|
||||
REQUIRE_FALSE(request.is_parse_complete()); // Should fail validation
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("CommitRequest arena debug dump") {
|
||||
CommitRequest request;
|
||||
|
||||
SUBCASE("Arena debug dump with COMPLEX_JSON") {
|
||||
// Parse the complex JSON to populate the arena with various data structures
|
||||
std::string json = weaseldb::test_data::COMPLEX_JSON;
|
||||
|
||||
REQUIRE(request.parse_json(const_cast<char *>(json.data()), json.size()));
|
||||
REQUIRE(request.is_parse_complete());
|
||||
|
||||
// Verify the request was parsed correctly
|
||||
REQUIRE(request.request_id().has_value());
|
||||
REQUIRE(request.request_id().value() == "complex-batch-operation-12345");
|
||||
REQUIRE(request.leader_id() == "leader789abcdef");
|
||||
REQUIRE(request.read_version() == 999999999);
|
||||
REQUIRE(request.preconditions().size() == 3);
|
||||
REQUIRE(request.operations().size() == 5);
|
||||
|
||||
// Check that arena has been used
|
||||
REQUIRE(request.total_allocated() > 0);
|
||||
REQUIRE(request.used_bytes() > 0);
|
||||
|
||||
// Capture debug output to string stream with content visualization
|
||||
std::ostringstream debug_output;
|
||||
request.arena().debug_dump(debug_output, true, true,
|
||||
512); // Include memory map and content
|
||||
|
||||
std::string debug_str = debug_output.str();
|
||||
|
||||
// Verify debug output contains expected information
|
||||
REQUIRE(debug_str.find("=== Arena Debug Dump ===") != std::string::npos);
|
||||
REQUIRE(debug_str.find("Total allocated:") != std::string::npos);
|
||||
REQUIRE(debug_str.find("Currently used:") != std::string::npos);
|
||||
REQUIRE(debug_str.find("Block Chain") != std::string::npos);
|
||||
REQUIRE(debug_str.find("Block addresses") != std::string::npos);
|
||||
REQUIRE(debug_str.find("Memory Contents:") != std::string::npos);
|
||||
REQUIRE(debug_str.find("0x0000:") !=
|
||||
std::string::npos); // Hex dump should be present
|
||||
|
||||
// Print debug output to console for manual inspection
|
||||
MESSAGE("Arena Debug Dump for COMPLEX_JSON:");
|
||||
MESSAGE(debug_str);
|
||||
|
||||
// Test that multiple blocks might be allocated for complex data
|
||||
MESSAGE("Arena statistics:");
|
||||
MESSAGE(" Total allocated: " << request.total_allocated() << " bytes");
|
||||
MESSAGE(" Used: " << request.used_bytes() << " bytes");
|
||||
MESSAGE(" Utilization: "
|
||||
<< (100.0 * request.used_bytes() / request.total_allocated())
|
||||
<< "%");
|
||||
MESSAGE(" Number of blocks: " << request.arena().num_blocks());
|
||||
}
|
||||
|
||||
SUBCASE("Arena debug dump comparison: before and after parsing") {
|
||||
// Debug dump of empty arena
|
||||
std::ostringstream empty_output;
|
||||
request.arena().debug_dump(empty_output);
|
||||
std::string empty_debug = empty_output.str();
|
||||
|
||||
REQUIRE(empty_debug.find("Arena is empty") != std::string::npos);
|
||||
|
||||
// Parse complex JSON
|
||||
std::string json = weaseldb::test_data::COMPLEX_JSON;
|
||||
REQUIRE(request.parse_json(const_cast<char *>(json.data()), json.size()));
|
||||
|
||||
// Debug dump after parsing
|
||||
std::ostringstream used_output;
|
||||
request.arena().debug_dump(used_output, true);
|
||||
std::string used_debug = used_output.str();
|
||||
|
||||
// Compare the outputs - they should be different
|
||||
REQUIRE(empty_debug != used_debug);
|
||||
REQUIRE(used_debug.find("Arena is empty") == std::string::npos);
|
||||
|
||||
MESSAGE("Empty arena debug:");
|
||||
MESSAGE(empty_debug);
|
||||
MESSAGE("After parsing COMPLEX_JSON:");
|
||||
MESSAGE(used_debug);
|
||||
}
|
||||
|
||||
SUBCASE("Arena debug dump after reset") {
|
||||
// Parse complex JSON first
|
||||
std::string json = weaseldb::test_data::COMPLEX_JSON;
|
||||
REQUIRE(request.parse_json(const_cast<char *>(json.data()), json.size()));
|
||||
|
||||
size_t allocated_before_reset = request.total_allocated();
|
||||
size_t used_before_reset = request.used_bytes();
|
||||
|
||||
// Reset the request (this should reset the arena)
|
||||
request.reset();
|
||||
|
||||
// Arena should still have some allocated memory (first block is kept)
|
||||
size_t allocated_after_reset = request.total_allocated();
|
||||
size_t used_after_reset = request.used_bytes();
|
||||
|
||||
// After reset, used bytes should be 0 or very small
|
||||
REQUIRE(used_after_reset < used_before_reset);
|
||||
// Total allocated should be less than or equal to before (extra blocks
|
||||
// freed)
|
||||
REQUIRE(allocated_after_reset <= allocated_before_reset);
|
||||
|
||||
std::ostringstream reset_output;
|
||||
request.arena().debug_dump(reset_output);
|
||||
std::string reset_debug = reset_output.str();
|
||||
|
||||
MESSAGE("Arena after reset:");
|
||||
MESSAGE(reset_debug);
|
||||
|
||||
// Verify debug output shows minimal usage
|
||||
if (allocated_after_reset > 0) {
|
||||
REQUIRE(reset_debug.find("Total allocated:") != std::string::npos);
|
||||
// Should show very low utilization
|
||||
double utilization =
|
||||
allocated_after_reset > 0
|
||||
? (100.0 * used_after_reset / allocated_after_reset)
|
||||
: 0.0;
|
||||
REQUIRE(utilization < 10.0); // Less than 10% utilization after reset
|
||||
} else {
|
||||
REQUIRE(reset_debug.find("Arena is empty") != std::string::npos);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("Arena memory content visualization") {
|
||||
// Parse COMPLEX_JSON to get diverse content in memory
|
||||
std::string json = weaseldb::test_data::COMPLEX_JSON;
|
||||
REQUIRE(request.parse_json(const_cast<char *>(json.data()), json.size()));
|
||||
|
||||
// Test different content visualization options
|
||||
std::ostringstream no_content;
|
||||
request.arena().debug_dump(no_content, false,
|
||||
false); // No content visualization
|
||||
std::string no_content_str = no_content.str();
|
||||
REQUIRE(no_content_str.find("Memory Contents:") == std::string::npos);
|
||||
|
||||
std::ostringstream with_content;
|
||||
request.arena().debug_dump(with_content, true, true,
|
||||
128); // Limited content
|
||||
std::string content_str = with_content.str();
|
||||
REQUIRE(content_str.find("Memory Contents:") != std::string::npos);
|
||||
|
||||
std::ostringstream full_content;
|
||||
request.arena().debug_dump(full_content, true, true, 2048); // Full content
|
||||
std::string full_content_str = full_content.str();
|
||||
|
||||
MESSAGE("Arena with limited content visualization (128 bytes):");
|
||||
MESSAGE(content_str);
|
||||
|
||||
// Verify that hex dump contains some expected strings from COMPLEX_JSON
|
||||
// The arena should contain the parsed strings like request_id, leader_id,
|
||||
// etc.
|
||||
REQUIRE(content_str.find("|") !=
|
||||
std::string::npos); // ASCII section markers
|
||||
|
||||
// Check that we can see some of the parsed data in ASCII representation
|
||||
// Note: The exact strings might be base64 decoded or processed
|
||||
bool found_readable_content =
|
||||
content_str.find("complex") != std::string::npos ||
|
||||
content_str.find("leader") != std::string::npos ||
|
||||
content_str.find("operation") != std::string::npos ||
|
||||
content_str.find("precondition") != std::string::npos;
|
||||
|
||||
if (found_readable_content) {
|
||||
MESSAGE("Found readable content in memory dump - strings are visible!");
|
||||
} else {
|
||||
MESSAGE("Strings may be encoded or fragmented in memory - hex dump shows "
|
||||
"raw allocation patterns");
|
||||
}
|
||||
|
||||
// At minimum, we should see some hex content
|
||||
REQUIRE(content_str.find("0x0000:") != std::string::npos);
|
||||
REQUIRE(content_str.find("0x00") !=
|
||||
std::string::npos); // Should have hex addresses
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user