#include "parser_comparison.hpp" #include std::string ParserComparison::last_error_; ParserComparison::ComparisonResult ParserComparison::compare_parsers(const std::string &json_str) { last_error_.clear(); // Parse with weaseljson parser CommitRequest weasel_request; JsonCommitRequestParser weasel_parser; std::string mutable_json = json_str; // JsonCommitRequestParser needs mutable data auto weasel_result = weasel_parser.parse(weasel_request, mutable_json.data(), mutable_json.size()); bool weasel_success = (weasel_result == CommitRequestParser::ParseResult::Success); // Parse with nlohmann reference parser CommitRequest nlohmann_request; NlohmannReferenceParser nlohmann_parser; auto nlohmann_result = nlohmann_parser.parse(nlohmann_request, json_str); bool nlohmann_success = (nlohmann_result == NlohmannReferenceParser::ParseResult::Success); // Compare results if (weasel_success && nlohmann_success) { // Both succeeded - check if they produce equivalent results if (requests_equal(weasel_request, nlohmann_request)) { return ComparisonResult::BothSuccess; } else { std::ostringstream oss; oss << "Parsers produced different results. "; oss << "Weasel: request_id=" << (weasel_request.request_id().has_value() ? weasel_request.request_id().value() : "none"); oss << ", leader_id='" << weasel_request.leader_id() << "'"; oss << ", read_version=" << weasel_request.read_version(); oss << ", preconditions=" << weasel_request.preconditions().size(); oss << ", operations=" << weasel_request.operations().size() << ". "; oss << "Nlohmann: request_id=" << (nlohmann_request.request_id().has_value() ? nlohmann_request.request_id().value() : "none"); oss << ", leader_id='" << nlohmann_request.leader_id() << "'"; oss << ", read_version=" << nlohmann_request.read_version(); oss << ", preconditions=" << nlohmann_request.preconditions().size(); oss << ", operations=" << nlohmann_request.operations().size(); last_error_ = oss.str(); return ComparisonResult::DifferentResults; } } else if (!weasel_success && !nlohmann_success) { // Both failed - this is expected for invalid JSON return ComparisonResult::BothFailure; } else if (weasel_success && !nlohmann_success) { // Weasel succeeded but nlohmann failed last_error_ = "Weasel parser succeeded but nlohmann failed: " + nlohmann_parser.get_error(); return ComparisonResult::WeaselSuccessNlohmannFail; } else { // Nlohmann succeeded but weasel failed last_error_ = "Nlohmann parser succeeded but weasel failed"; if (weasel_parser.get_parse_error()) { last_error_ += ": " + std::string(weasel_parser.get_parse_error()); } return ComparisonResult::NlohmannSuccessWeaselFail; } } std::string ParserComparison::result_to_string(ComparisonResult result) { switch (result) { case ComparisonResult::BothSuccess: return "Both parsers succeeded with equivalent results"; case ComparisonResult::BothFailure: return "Both parsers failed (as expected)"; case ComparisonResult::WeaselSuccessNlohmannFail: return "Weasel succeeded but nlohmann failed"; case ComparisonResult::NlohmannSuccessWeaselFail: return "Nlohmann succeeded but weasel failed"; case ComparisonResult::DifferentResults: return "Both succeeded but produced different results"; default: return "Unknown result"; } } bool ParserComparison::requests_equal(const CommitRequest &req1, const CommitRequest &req2) { // Compare request_id if (req1.request_id().has_value() != req2.request_id().has_value()) { return false; } if (req1.request_id().has_value() && req1.request_id().value() != req2.request_id().value()) { return false; } // Compare leader_id if (req1.leader_id() != req2.leader_id()) { return false; } // Compare read_version if (req1.read_version() != req2.read_version()) { return false; } // Compare preconditions auto prec1 = req1.preconditions(); auto prec2 = req2.preconditions(); if (prec1.size() != prec2.size()) { return false; } for (size_t i = 0; i < prec1.size(); ++i) { if (!preconditions_equal(prec1[i], prec2[i])) { return false; } } // Compare operations auto ops1 = req1.operations(); auto ops2 = req2.operations(); if (ops1.size() != ops2.size()) { return false; } for (size_t i = 0; i < ops1.size(); ++i) { if (!operations_equal(ops1[i], ops2[i])) { return false; } } return true; } bool ParserComparison::preconditions_equal(const Precondition &p1, const Precondition &p2) { return p1.type == p2.type && p1.version == p2.version && p1.begin == p2.begin && p1.end == p2.end; } bool ParserComparison::operations_equal(const Operation &op1, const Operation &op2) { return op1.type == op2.type && op1.param1 == op2.param1 && op1.param2 == op2.param2; }