// // json_binder_object.t.h // json // // Created by Sam Jaffe on 2/27/17. // #pragma once #include #include "json/json_binder.hpp" using namespace json::binder; using namespace json::parser; class json_binder_object_TestSuite : public CxxTest::TestSuite { public: using vec_t = std::vector; using map_t = std::map; struct TestObject { int count; double average; std::map> data; bool operator==(TestObject const & other) const { return count == other.count && average == other.average && data == other.data; } }; static object_binder GetImpl() { return object_binder() ("count", &TestObject::count) ("average", &TestObject::average) ("data", direct_binder(&TestObject::data)); } static object_binder & Get() { static object_binder val = GetImpl(); return val; } void test_construct_object_from_json() { char data[] = "{ \"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }}"; TestObject out = { 0, 0.0, {} }; TestObject expected = { 10, 1.0, {{"key1", {1, 2}},{"key2", {3, 4}}} }; TS_ASSERT_THROWS_NOTHING(parse(json::binder::bind(out, Get()), data, allow_all)); TS_ASSERT_EQUALS(out, expected); } void test_permits_extra_keys() { char data[] = "{ \"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }, \"lemon\":true}"; TestObject out = { 0, 0.0, {} }; TestObject expected = { 10, 1.0, {{"key1", {1, 2}},{"key2", {3, 4}}} }; TS_ASSERT_THROWS_NOTHING(parse(json::binder::bind(out, Get()), data, allow_all)); TS_ASSERT_EQUALS(out, expected); } void test_throws_on_extra_keys_with_flag() { char data[] = "{ \"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }, \"lemon\":true}"; TestObject out = { 0, 0.0, {} }; TS_ASSERT_THROWS(parse(json::binder::bind(out, Get()), data, disable_unknown_keys), json::malformed_json_exception); } void test_permits_missing_keys() { char data[] = "{ \"count\":10, \"average\":1.0 }"; TestObject out = { 0, 0.0, {} }; TestObject expected = { 10, 1.0, {} }; TS_ASSERT_THROWS_NOTHING(parse(json::binder::bind(out, Get()), data, allow_all)); TS_ASSERT_EQUALS(out, expected); } void test_throws_if_missing_keys_with_flag() { char data[] = "{ \"count\":10, \"average\":1.0 }"; TestObject out = { 0, 0.0, {} }; TS_ASSERT_THROWS(parse(json::binder::bind(out, Get()), data, disable_missing_keys), json::malformed_json_exception); } void test_throws_if_object_unstarted() { char data[] = "\"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] } }"; TestObject out = { 0, 0.0, {} }; TS_ASSERT_THROWS(parse(json::binder::bind(out, Get()), data, allow_all), json::malformed_json_exception); } void test_throws_if_object_missing_associative_token() { char data[] = "{ \"count\":10, \"average\":1.0, \"data\": }"; TestObject out = { 0, 0.0, {} }; TS_ASSERT_THROWS(parse(json::binder::bind(out, Get()), data, allow_all), json::malformed_json_exception); } void test_throws_if_object_unterminated() { char data[] = "{ \"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }"; TestObject out = { 0, 0.0, {} }; TS_ASSERT_THROWS(parse(json::binder::bind(out, Get()), data, allow_all), json::unterminated_json_exception); } void test_throws_if_object_missing_associative_token_discard_t() { char data[] = "{ \"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }, \"lemon\":{\"key\": } }"; TestObject out = { 0, 0.0, {} }; TS_ASSERT_THROWS(parse(json::binder::bind(out, Get()), data, allow_all), json::malformed_json_exception); } void test_throws_if_object_unterminated_array_discard_t() { char data[] = "{ \"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }, \"lemon\":[1.0 }"; TestObject out = { 0, 0.0, {} }; TS_ASSERT_THROWS(parse(json::binder::bind(out, Get()), data, allow_all), json::unterminated_json_exception); } void test_throws_if_object_unterminated_object_discard_t() { char data[] = "{ \"count\":10, \"average\":1.0, \"data\":{ \"key1\":[1, 2], \"key2\":[3, 4] }, \"lemon\":{\"key\":false }"; TestObject out = { 0, 0.0, {} }; TS_ASSERT_THROWS(parse(json::binder::bind(out, Get()), data, allow_all), json::unterminated_json_exception); } std::string ify(double value) { std::stringstream ss; ss << std::fixed << value; return ss.str(); } void test_write_object_is_composed_of_correct_data() { std::string const dbl = ify(1.0); std::string const expected = "{\"average\":"+dbl+",\"count\":10,\"data\":{\"key1\":[1,2],\"key2\":[3,4]}}"; std::stringstream ss; TestObject const in = { 10, 1.0, { { "key1", {1, 2} }, { "key2", {3, 4} } } }; TS_ASSERT_THROWS_NOTHING(write(json::binder::bind(in, Get()), ss)); TS_ASSERT_EQUALS(ss.str(), expected); } };