Mercurial > code
view C++/tests/Json/main.cpp @ 478:c7825b8c6145
Json:
- Finalize iterators,
- Add more tests,
- Add more asserts.
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 10 Nov 2015 14:11:14 +0100 |
parents | b681299e6987 |
children | 3ee3f3e53ee3 |
line wrap: on
line source
/* * main.cpp -- test the jansson wrapper * * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <set> #include <unordered_map> #include <gtest/gtest.h> #include "Json.h" /* * Miscellaneous * ------------------------------------------------------------------ */ TEST(Misc, copy) { json::Value object{json::Type::Object}; object.insert("integer", 123); object.insert("true", true); json::Value object2{object}; ASSERT_TRUE(object2.isObject()); ASSERT_EQ(123, object2["integer"].toInt()); ASSERT_TRUE(object2["true"].toBool()); } TEST(Misc, copyAssign) { json::Value object{json::Type::Object}; { json::Value tmp{json::Type::Object}; tmp.insert("integer", 123); tmp.insert("true", true); object = tmp; } ASSERT_TRUE(object.isObject()); ASSERT_EQ(123, object["integer"].toInt()); ASSERT_TRUE(object["true"].toBool()); } TEST(Misc, move) { json::Value object(123); json::Value object2(std::move(object)); ASSERT_TRUE(object2.isInt()); ASSERT_EQ(123, object2.toInt()); } TEST(Misc, moveAssign) { json::Value object(123); json::Value object2; object2 = std::move(object); ASSERT_TRUE(object2.isInt()); ASSERT_EQ(123, object2.toInt()); } TEST(Misc, escape) { std::string input{"\\/\"\b\f\n\r\t"}; std::string expected{"\\\\\\/\\\"\\b\\f\\n\\r\\t"}; ASSERT_EQ(expected, json::escape(input)); } /* * json::Value constructors * ------------------------------------------------------------------ */ TEST(Constructors, null) { try { json::Value value{nullptr}; ASSERT_TRUE(value.isNull()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(Constructors, boolean) { try { json::Value value{true}; ASSERT_TRUE(value.isBool()); ASSERT_TRUE(value.toBool()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(Constructors, integer) { try { json::Value value{123}; ASSERT_TRUE(value.isInt()); ASSERT_TRUE(value.isNumber()); ASSERT_TRUE(value.isNumber()); ASSERT_EQ(123, value.toInt()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(Constructors, real) { try { json::Value value{9.2}; ASSERT_TRUE(value.isNumber()); ASSERT_TRUE(value.isNumber()); ASSERT_FALSE(value.isInt()); ASSERT_EQ(9.2, value.toReal()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(Constructors, string) { try { json::Value value("hello"); ASSERT_TRUE(value.isString()); ASSERT_EQ("hello", value.toString()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } /* * Object * ------------------------------------------------------------------ */ TEST(Object, set) { try { json::Value object{json::Type::Object}; object.insert("integer", 123); object.insert("string", "hello"); object.insert("true", true); ASSERT_EQ(123, object["integer"].toInt()); ASSERT_EQ("hello", object["string"].toString()); ASSERT_TRUE(object["true"].toBool()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(Object, clear) { try { json::Value object{json::Type::Object}; object.insert("integer", 123); object.insert("string", "hello"); object.insert("true", true); object.clear(); ASSERT_EQ(0, static_cast<int>(object.size())); ASSERT_FALSE(object.contains("integer")); ASSERT_FALSE(object.contains("string")); ASSERT_FALSE(object.contains("true")); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(Object, erase) { try { json::Value object{json::Type::Object}; object.insert("integer", 123); object.insert("string", "hello"); object.insert("true", true); object.erase("integer"); ASSERT_EQ(2, static_cast<int>(object.size())); ASSERT_FALSE(object.contains("integer")); ASSERT_TRUE(object.contains("string")); ASSERT_TRUE(object.contains("true")); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(Object, valueOr) { try { json::Value object = json::object({ { "x", 10 }, { "y", 20 } }); ASSERT_EQ(10, object.valueOr("x", -9999).toInt()); ASSERT_EQ(20, object.valueOr("y", -9999).toInt()); ASSERT_EQ(-9999, object.valueOr("not-found", -9999).toInt()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(ObjectInitializer, simple) { try { json::Value object = json::object({ { "username", "jean" }, { "age", 99 } }); ASSERT_EQ(2, static_cast<int>(object.size())); ASSERT_EQ("jean", object["username"].toString()); ASSERT_EQ(99, object["age"].toInt()); } catch (const std::exception &ex) { FAIL() << ex.what(); } } TEST(ObjectInitializer, deep) { try { json::Value object = json::object({ { "username", "jean" }, { "age", 99 }, { "network", json::object({ { "port", 9999 }, { "host", "localhost" } }) } }); // First ASSERT_EQ(3, static_cast<int>(object.size())); ASSERT_EQ("jean", object["username"].toString()); ASSERT_EQ(99, object["age"].toInt()); // Second const json::Value &network = object["network"]; ASSERT_TRUE(network.isObject()); ASSERT_EQ(2, static_cast<int>(network.size())); ASSERT_EQ(9999, network["port"].toInt()); ASSERT_EQ("localhost", network["host"].toString()); } catch (const std::exception &ex) { FAIL() << ex.what(); } } /* * Array * ------------------------------------------------------------------ */ TEST(Array, push) { try { json::Value array{json::Type::Array}; ASSERT_TRUE(array.isArray()); array.push(1); array.push("hello"); array.push(true); ASSERT_EQ(3, static_cast<int>(array.size())); ASSERT_TRUE(array[0].toBool()); ASSERT_EQ("hello", array[1].toString()); ASSERT_EQ(1, array[2].toInt()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(Array, append) { try { json::Value array{json::Type::Array}; ASSERT_TRUE(array.isArray()); array.append(1); array.append("hello"); array.append(true); ASSERT_EQ(3, static_cast<int>(array.size())); ASSERT_EQ(1, array[0].toInt()); ASSERT_EQ("hello", array[1].toString()); ASSERT_TRUE(array[2].toBool()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(Array, insert) { try { json::Value array{json::Type::Array}; ASSERT_TRUE(array.isArray()); array.insert(0, 1); array.insert(1, "hello"); array.insert(0, true); ASSERT_EQ(3, static_cast<int>(array.size())); ASSERT_TRUE(array[0].toBool()); ASSERT_EQ(1, array[1].toInt()); ASSERT_EQ("hello", array[2].toString()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(Array, clear) { try { json::Value array{json::Type::Array}; array.append(1); array.append("hello"); array.append(true); array.clear(); ASSERT_EQ(0, static_cast<int>(array.size())); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(Array, erase) { try { json::Value array{json::Type::Array}; array.append(1); array.append("hello"); array.append(true); array.erase(0); ASSERT_EQ(2, static_cast<int>(array.size())); ASSERT_EQ("hello", array[0].toString()); ASSERT_TRUE(array[1].toBool()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(Array, valueOr) { try { json::Value array = json::array({-10, -20}); ASSERT_EQ(-10, array.valueOr(0, -9999).toInt()); ASSERT_EQ(-20, array.valueOr(1, -9999).toInt()); ASSERT_EQ(-9999, array.valueOr(2, -9999).toInt()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(ArrayInitializer, simple) { try { json::Value array = json::array({123, true, "hello"}); ASSERT_EQ(3, static_cast<int>(array.size())); ASSERT_EQ(123, array[0].toInt()); ASSERT_TRUE(array[1].toBool()); ASSERT_EQ("hello", array[2].toString()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(ArrayInitializer, deep) { try { json::Value array = json::array({ 123, true, "hello", json::array({ 321, false, "olleh" }) }); // First ASSERT_EQ(4, static_cast<int>(array.size())); ASSERT_EQ(123, array[0].toInt()); ASSERT_TRUE(array[1].toBool()); ASSERT_EQ("hello", array[2].toString()); // Second const json::Value &array2 = array[3]; ASSERT_TRUE(array.isArray()); ASSERT_EQ(3, static_cast<int>(array2.size())); ASSERT_EQ(321, array2[0].toInt()); ASSERT_FALSE(array2[1].toBool()); ASSERT_EQ("olleh", array2[2].toString()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } /* * I/O * ------------------------------------------------------------------ */ TEST(FileRead, simple) { try { json::Value doc(json::File{"Json/simple.json"}); ASSERT_TRUE(doc.isObject()); ASSERT_FALSE(doc.isArray()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(FileRead, fail) { try { json::Value(json::File{"Json/notexist.json"}); FAIL() << "Exception expected"; } catch (const json::Error &) { } } TEST(StringRead, simple) { try { json::Value doc(json::Buffer{"{ \"license\": \"ISC\" }"}); ASSERT_TRUE(doc.isObject()); ASSERT_FALSE(doc.isArray()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST(StringRead, fail) { try { json::Value(json::Buffer{"{ \"license\": ISC }"}); FAIL() << "Exception expected"; } catch (const json::Error &ex) { } } /* * Object read * ------------------------------------------------------------------ */ class ObjectRead : public testing::Test { protected: json::Value m_object; json::Value m_objectAll; public: ObjectRead() : m_object(json::File{"Json/object.json"}) , m_objectAll(json::File{"Json/object-all.json"}) { } }; TEST_F(ObjectRead, simple) { try { json::Value name = m_object["name"]; json::Value description = m_object["description"]; ASSERT_TRUE(name.isString()); ASSERT_TRUE(description.isString()); ASSERT_EQ("simple", name.toString()); ASSERT_EQ("basic JSON file", description.toString()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST_F(ObjectRead, all) { try { ASSERT_TRUE(m_objectAll.contains("integer")); ASSERT_FALSE(m_objectAll.contains("unexistant")); ASSERT_TRUE(m_objectAll["integer"].isInt()); ASSERT_TRUE(m_objectAll["integer"].isNumber()); ASSERT_EQ(123, m_objectAll["integer"].toInt()); ASSERT_TRUE(m_objectAll["real"].isNumber()); ASSERT_TRUE(m_objectAll["real"].isNumber()); ASSERT_EQ(9.2, m_objectAll["real"].toReal()); ASSERT_TRUE(m_objectAll["false"].isBool()); ASSERT_FALSE(m_objectAll["false"].toBool()); ASSERT_FALSE(m_objectAll["false"].toBool()); ASSERT_TRUE(m_objectAll["true"].isBool()); ASSERT_TRUE(m_objectAll["true"].toBool()); ASSERT_TRUE(m_objectAll["true"].toBool()); ASSERT_TRUE(m_objectAll["null"].isNull()); ASSERT_TRUE(m_objectAll["object"].isObject()); ASSERT_TRUE(m_objectAll["array"].isArray()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } /* * Array read * ------------------------------------------------------------------ */ class ArrayRead : public testing::Test { protected: json::Value m_array; json::Value m_arrayAll; public: ArrayRead() : m_array(json::File{"Json/array.json"}) , m_arrayAll(json::File{"Json/array-all.json"}) { } }; TEST_F(ArrayRead, simple) { try { ASSERT_EQ(3, static_cast<int>(m_array.size())); ASSERT_EQ(1, m_array[0].toInt()); ASSERT_EQ(2, m_array[1].toInt()); ASSERT_EQ(3, m_array[2].toInt()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } TEST_F(ArrayRead, all) { try { ASSERT_TRUE(m_arrayAll[0].isInt()); ASSERT_TRUE(m_arrayAll[0].isNumber()); ASSERT_EQ(123, m_arrayAll[0].toInt()); ASSERT_TRUE(m_arrayAll[1].isNumber()); ASSERT_TRUE(m_arrayAll[1].isNumber()); ASSERT_EQ(9.2, m_arrayAll[1].toReal()); ASSERT_TRUE(m_arrayAll[2].isBool()); ASSERT_FALSE(m_arrayAll[2].toBool()); ASSERT_FALSE(m_arrayAll[2].toBool()); ASSERT_TRUE(m_arrayAll[3].isBool()); ASSERT_TRUE(m_arrayAll[3].toBool()); ASSERT_TRUE(m_arrayAll[3].toBool()); ASSERT_TRUE(m_arrayAll[4].isNull()); ASSERT_TRUE(m_arrayAll[5].isObject()); ASSERT_TRUE(m_arrayAll[6].isArray()); } catch (const json::Error &ex) { FAIL() << ex.what(); } } /* * Object iterators * ------------------------------------------------------------------ */ class ObjectIteratorsTest : public testing::Test { protected: json::Value m_object{json::Type::Object}; public: ObjectIteratorsTest() { m_object.insert("integer", 1); m_object.insert("string", "hello"); m_object.insert("boolean", true); } }; TEST_F(ObjectIteratorsTest, operators) { // Read only (non const) { std::set<std::string> expected{"boolean", "integer", "string"}; std::set<std::string> result; std::unordered_map<std::string, json::Value> values; auto it = m_object.begin(); auto end = m_object.end(); while (it != end) { values.insert({it.key(), *it}); result.insert(it.key()); it++; } ASSERT_EQ(expected, result); ASSERT_EQ(1, values["integer"].toInt()); ASSERT_EQ("hello", values["string"].toString()); ASSERT_TRUE(values["boolean"].toBool()); } // Read only (const) { std::set<std::string> expected{"boolean", "integer", "string"}; std::set<std::string> result; std::unordered_map<std::string, json::Value> values; auto it = m_object.cbegin(); auto end = m_object.cend(); while (it != end) { values.insert({it.key(), *it}); result.insert(it.key()); it++; } ASSERT_EQ(expected, result); ASSERT_EQ(1, values["integer"].toInt()); ASSERT_EQ("hello", values["string"].toString()); ASSERT_TRUE(values["boolean"].toBool()); } } TEST_F(ObjectIteratorsTest, assign) { // Assign (non const) { auto it = m_object.begin(); auto key = it.key(); *it = json::Value("CHANGED"); ASSERT_EQ("CHANGED", m_object[key].toString()); ASSERT_EQ("CHANGED", it->toString()); ASSERT_EQ(3, static_cast<int>(m_object.size())); } } TEST_F(ObjectIteratorsTest, find) { auto it = m_object.find("integer"); ASSERT_TRUE(it != m_object.end()); ASSERT_EQ(1, it->toInt()); } TEST_F(ObjectIteratorsTest, find2) { auto it = m_object.find("not exists"); ASSERT_TRUE(it == m_object.end()); } /* * Array iterators * ------------------------------------------------------------------ */ class ArrayIteratorsTest : public testing::Test { protected: json::Value m_array{json::Type::Array}; public: ArrayIteratorsTest() { m_array.append(1); m_array.append("hello"); m_array.append(true); } }; TEST_F(ArrayIteratorsTest, operators) { // Read only (non const) { auto it = m_array.begin(); // 1 ASSERT_EQ(1, (*it).toInt()); ASSERT_EQ(1, it->toInt()); // "hello" it++; ASSERT_EQ("hello", it->toString()); // true it++; ASSERT_TRUE(it->toBool()); } // Read only (const) { auto it = m_array.cbegin(); // 1 ASSERT_EQ(1, (*it).toInt()); ASSERT_EQ(1, it->toInt()); // "hello" it++; ASSERT_EQ("hello", it->toString()); // true it++; ASSERT_TRUE(it->toBool()); } } TEST_F(ArrayIteratorsTest, assign) { // Assign (non const) { auto it = m_array.begin(); *it = json::Value(9999); ASSERT_EQ(3, static_cast<int>(m_array.size())); ASSERT_EQ(9999, it->toInt()); ASSERT_EQ(9999, m_array[0].toInt()); } } TEST_F(ArrayIteratorsTest, castToRef) { json::Value array = json::array({1, 2, 3}); int i = 1; for (const json::Value &v : array) { ASSERT_EQ(i++, v.toInt()); } } int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }