json_binder_object_test.cxx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. //
  2. // json_binder_object.t.h
  3. // json
  4. //
  5. // Created by Sam Jaffe on 2/27/17.
  6. //
  7. #include "json/json_binder.hpp"
  8. #include <gmock/gmock.h>
  9. using namespace json::binder;
  10. using namespace json::parser;
  11. using vec_t = std::vector<int>;
  12. using map_t = std::map<std::string, vec_t>;
  13. struct TestObject {
  14. int count;
  15. double average;
  16. map_t data;
  17. };
  18. bool operator==(TestObject const & lhs, TestObject const & rhs) {
  19. return lhs.count == rhs.count && lhs.average == rhs.average &&
  20. lhs.data == rhs.data;
  21. }
  22. class JsonBinderObjectTest : public ::testing::Test {
  23. protected:
  24. static object_binder<TestObject> & GetBinder() {
  25. static object_binder<TestObject> val = object_binder<TestObject>()(
  26. "count", &TestObject::count)("average", &TestObject::average)(
  27. "data", direct_binder<TestObject, map_t>(&TestObject::data));
  28. return val;
  29. }
  30. };
  31. TEST_F(JsonBinderObjectTest, ParsesSuccessfully) {
  32. char data[] = "{ \"count\":10, \"average\":1.0, "
  33. "\"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }}";
  34. TestObject out = {0, 0.0, {}};
  35. TestObject expected = {10, 1.0, {{"key1", {1, 2}}, {"key2", {3, 4}}}};
  36. EXPECT_NO_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all));
  37. EXPECT_THAT(out, expected);
  38. }
  39. TEST_F(JsonBinderObjectTest, IgnoresUnknownKeysByDefault) {
  40. char data[] = "{ \"count\":10, \"average\":1.0, "
  41. "\"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }, "
  42. "\"lemon\":true}";
  43. TestObject out = {0, 0.0, {}};
  44. TestObject expected = {10, 1.0, {{"key1", {1, 2}}, {"key2", {3, 4}}}};
  45. EXPECT_NO_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all));
  46. EXPECT_THAT(out, expected);
  47. }
  48. TEST_F(JsonBinderObjectTest, ThrowsOnUnknownKeyWithSetting) {
  49. char data[] = "{ \"count\":10, \"average\":1.0, "
  50. "\"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }, "
  51. "\"lemon\":true}";
  52. TestObject out = {0, 0.0, {}};
  53. EXPECT_THROW(
  54. parse(json::binder::bind(out, GetBinder()), data, disable_unknown_keys),
  55. json::malformed_json_exception);
  56. }
  57. TEST_F(JsonBinderObjectTest, AllowsMissingExpectedKeysByDefault) {
  58. char data[] = "{ \"count\":10, \"average\":1.0 }";
  59. TestObject out = {0, 0.0, {}};
  60. TestObject expected = {10, 1.0, {}};
  61. EXPECT_NO_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all));
  62. EXPECT_THAT(out, expected);
  63. }
  64. TEST_F(JsonBinderObjectTest, ThrowsOnMissingExpectedKeyWithSetting) {
  65. char data[] = "{ \"count\":10, \"average\":1.0 }";
  66. TestObject out = {0, 0.0, {}};
  67. EXPECT_THROW(
  68. parse(json::binder::bind(out, GetBinder()), data, disable_missing_keys),
  69. json::malformed_json_exception);
  70. }
  71. TEST_F(JsonBinderObjectTest, ThrowsMalformedObjectKey) {
  72. char data[] = "{ count\":10, \"average\":1.0 }";
  73. TestObject out = {0, 0.0, {}};
  74. EXPECT_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all),
  75. json::malformed_json_exception);
  76. }
  77. TEST_F(JsonBinderObjectTest, ThrowsMalformedObjectAssoc) {
  78. char data[] = "{ \"count\"=10, \"average\":1.0 }";
  79. TestObject out = {0, 0.0, {}};
  80. EXPECT_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all),
  81. json::malformed_json_exception);
  82. }
  83. TEST_F(JsonBinderObjectTest, ThrowsOnMissingStartToken) {
  84. char data[] = "\"count\":10, \"average\":1.0, "
  85. "\"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] } }";
  86. TestObject out = {0, 0.0, {}};
  87. EXPECT_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all),
  88. json::malformed_json_exception);
  89. }
  90. TEST_F(JsonBinderObjectTest, ThrowsIfMissingValueForKey) {
  91. char data[] = "{ \"count\":10, \"average\":1.0, \"data\": }";
  92. TestObject out = {0, 0.0, {}};
  93. EXPECT_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all),
  94. json::malformed_json_exception);
  95. }
  96. TEST_F(JsonBinderObjectTest, ThrowsOnMissingEndToken) {
  97. char data[] = "{ \"count\":10, \"average\":1.0, "
  98. "\"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }";
  99. TestObject out = {0, 0.0, {}};
  100. EXPECT_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all),
  101. json::unterminated_json_exception);
  102. }
  103. TEST_F(JsonBinderObjectTest, ThrowsOnMissingEndTokenAfterUnknownKey) {
  104. char data[] = "{ \"count\":10, \"average\":1.0, "
  105. "\"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }, "
  106. "\"lemon\":{\"key\":false }";
  107. TestObject out = {0, 0.0, {}};
  108. EXPECT_THROW(parse(json::binder::bind(out, GetBinder()), data, allow_all),
  109. json::unterminated_json_exception);
  110. }
  111. std::string ify(double value) {
  112. std::stringstream ss;
  113. ss << std::fixed << value;
  114. return ss.str();
  115. }
  116. TEST_F(JsonBinderObjectTest, WritesBackOriginalObject) {
  117. std::string const dbl = ify(1.0);
  118. std::string const expected = "{\"average\":1.000000,\"count\":10,"
  119. "\"data\":{\"key1\":[1,2],\"key2\":[3,4]}}";
  120. std::stringstream ss;
  121. TestObject const in = {10, 1.0, {{"key1", {1, 2}}, {"key2", {3, 4}}}};
  122. EXPECT_NO_THROW(write(json::binder::bind(in, GetBinder()), ss));
  123. EXPECT_THAT(ss.str(), expected);
  124. }