|
| 1 | +#include "testing/json_util.h" |
| 2 | + |
| 3 | +#include <ostream> |
| 4 | +#include <string> |
| 5 | + |
| 6 | +#include "flatbuffers/flatbuffers.h" |
| 7 | +#include "flatbuffers/flexbuffers.h" |
| 8 | +#include "flatbuffers/idl.h" |
| 9 | +#include "flatbuffers/util.h" |
| 10 | + |
| 11 | +namespace firebase { |
| 12 | +namespace testing { |
| 13 | +namespace cppsdk { |
| 14 | +namespace internal { |
| 15 | + |
| 16 | +EqualsJsonMatcher::EqualsJsonMatcher(const std::string& expected_json) |
| 17 | + : expected_json_(expected_json) {} |
| 18 | + |
| 19 | +bool EqualsJsonMatcher::MatchAndExplain( |
| 20 | + const std::string& actual, ::testing::MatchResultListener* listener) const { |
| 21 | + flatbuffers::Parser parser_actual; |
| 22 | + flatbuffers::Parser parser_expected; |
| 23 | + |
| 24 | + flexbuffers::Builder builder_actual; |
| 25 | + flexbuffers::Builder builder_expected; |
| 26 | + |
| 27 | + if (actual.empty() || !parser_actual.ParseFlexBuffer(actual.c_str(), nullptr, |
| 28 | + &builder_actual)) { |
| 29 | + *listener << "Unable to parse actual value (" << parser_actual.error_ |
| 30 | + << ").\n"; |
| 31 | + return false; |
| 32 | + } |
| 33 | + if (expected_json_.empty() || |
| 34 | + !parser_expected.ParseFlexBuffer(expected_json_.c_str(), nullptr, |
| 35 | + &builder_expected)) { |
| 36 | + *listener << "Unable to parse expected value (" << parser_expected.error_ |
| 37 | + << ").\n"; |
| 38 | + return false; |
| 39 | + } |
| 40 | + |
| 41 | + std::vector<uint8_t> buffer_actual = builder_actual.GetBuffer(); |
| 42 | + std::vector<uint8_t> buffer_expected = builder_expected.GetBuffer(); |
| 43 | + |
| 44 | + auto root_actual = flexbuffers::GetRoot(buffer_actual); |
| 45 | + auto root_expected = flexbuffers::GetRoot(buffer_expected); |
| 46 | + return CompareFlexbufferReference(root_actual, root_expected, "root", |
| 47 | + listener); |
| 48 | +} |
| 49 | + |
| 50 | +void EqualsJsonMatcher::DescribeTo(std::ostream* os) const { |
| 51 | + *os << "equals JSON: \n" << expected_json_; |
| 52 | +} |
| 53 | + |
| 54 | +void EqualsJsonMatcher::DescribeNegationTo(std::ostream* os) const { |
| 55 | + *os << "doesn't equal JSON: \n" << expected_json_; |
| 56 | +} |
| 57 | + |
| 58 | +bool EqualsJsonMatcher::CompareFlexbufferReference( |
| 59 | + flexbuffers::Reference reference_actual, |
| 60 | + flexbuffers::Reference reference_expected, std::string key_name, |
| 61 | + ::testing::MatchResultListener* listener) const { |
| 62 | + |
| 63 | + auto type_actual = reference_actual.GetType(); |
| 64 | + auto type_expected = reference_expected.GetType(); |
| 65 | + if (type_actual != type_expected) { |
| 66 | + *listener << "Type Mismatch (" << key_name << ")\n"; |
| 67 | + return false; |
| 68 | + } else if (type_actual == flexbuffers::FBT_MAP) { |
| 69 | + flexbuffers::Map map_actual = reference_actual.AsMap(); |
| 70 | + flexbuffers::Map map_expected = reference_expected.AsMap(); |
| 71 | + |
| 72 | + auto keys_actual = map_actual.Keys(); |
| 73 | + auto keys_expected = map_expected.Keys(); |
| 74 | + if (keys_actual.size() != keys_expected.size()) { |
| 75 | + *listener << "Size of " << key_name |
| 76 | + << " does not match. Expected: " << keys_expected.size() |
| 77 | + << " Actual: " << keys_actual.size() << "\n"; |
| 78 | + return false; |
| 79 | + } |
| 80 | + |
| 81 | + bool map_matches = true; |
| 82 | + for (int i = 0; i < keys_actual.size(); i++) { |
| 83 | + auto key_actual = keys_actual[i]; |
| 84 | + auto key_expected = keys_expected[i]; |
| 85 | + |
| 86 | + if (key_actual.ToString() != key_expected.ToString()) { |
| 87 | + *listener << "Key mismatch in " << key_name |
| 88 | + << " Expected: " << key_expected.ToString() |
| 89 | + << " Actual: " << key_actual.ToString() << "\n"; |
| 90 | + map_matches = false; |
| 91 | + continue; |
| 92 | + } |
| 93 | + |
| 94 | + auto val_actual = map_actual.Values()[i]; |
| 95 | + auto val_expected = map_expected.Values()[i]; |
| 96 | + if (!CompareFlexbufferReference( |
| 97 | + val_actual, val_expected, |
| 98 | + key_name + "[" + key_actual.ToString() + "]", listener)) { |
| 99 | + map_matches = false; |
| 100 | + } |
| 101 | + } |
| 102 | + return map_matches; |
| 103 | + } else if (type_actual == flexbuffers::FBT_VECTOR) { |
| 104 | + flexbuffers::Vector vec_actual = reference_actual.AsVector(); |
| 105 | + flexbuffers::Vector vec_expected = reference_expected.AsVector(); |
| 106 | + |
| 107 | + if (vec_actual.size() != vec_expected.size()) { |
| 108 | + *listener << "Size of " << key_name |
| 109 | + << " does not match. Expected: " << vec_expected.size() |
| 110 | + << " Actual: " << vec_actual.size() << "\n"; |
| 111 | + return false; |
| 112 | + } |
| 113 | + |
| 114 | + bool vectors_match = true; |
| 115 | + for (int i = 0; i < vec_actual.size(); i++) { |
| 116 | + auto vec_element_actual = vec_actual[i]; |
| 117 | + auto vec_element_expected = vec_expected[i]; |
| 118 | + if (!CompareFlexbufferReference(vec_element_actual, vec_element_expected, |
| 119 | + key_name + "[" + std::to_string(i) + "]", |
| 120 | + listener)) { |
| 121 | + vectors_match = false; |
| 122 | + } |
| 123 | + } |
| 124 | + return vectors_match; |
| 125 | + } else { |
| 126 | + auto str_actual = reference_actual.ToString(); |
| 127 | + auto str_expected = reference_expected.ToString(); |
| 128 | + |
| 129 | + if (str_actual != str_expected) { |
| 130 | + *listener << "Values for " << key_name << " do not match.\n" |
| 131 | + << "Expected: " << str_expected << "\n" |
| 132 | + << "Actual: " << str_actual << "\n"; |
| 133 | + return false; |
| 134 | + } |
| 135 | + return true; |
| 136 | + } |
| 137 | +} |
| 138 | + |
| 139 | +} // namespace internal |
| 140 | + |
| 141 | +} // namespace cppsdk |
| 142 | +} // namespace testing |
| 143 | +} // namespace firebase |
0 commit comments