504 lines
16 KiB
C++
504 lines
16 KiB
C++
/***
|
|
* ==++==
|
|
*
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
* ==--==
|
|
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
|
*
|
|
* construction_tests.cpp
|
|
*
|
|
* Tests creating JSON values.
|
|
*
|
|
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
****/
|
|
|
|
#include "stdafx.h"
|
|
|
|
using namespace web; using namespace utility;
|
|
|
|
namespace tests { namespace functional { namespace json_tests {
|
|
|
|
SUITE(construction_tests)
|
|
{
|
|
|
|
#if defined(__cplusplus_winrt)
|
|
|
|
TEST(winrt_platform_string)
|
|
{
|
|
Platform::String ^platformStr = "Hello!";
|
|
json::value jstr = json::value::string(platformStr->Data());
|
|
CHECK(jstr.is_string());
|
|
CHECK_EQUAL(jstr.serialize(), U("\"Hello!\""));
|
|
}
|
|
|
|
#endif
|
|
|
|
TEST(assignment_op)
|
|
{
|
|
json::value arr = json::value::array();
|
|
arr[0] = json::value(true);
|
|
|
|
json::value ass_copy = arr;
|
|
VERIFY_IS_TRUE(ass_copy.is_array());
|
|
VERIFY_ARE_EQUAL(U("true"), ass_copy[0].serialize());
|
|
ass_copy[1] = json::value(false);
|
|
VERIFY_ARE_EQUAL(U("false"), ass_copy[1].serialize());
|
|
VERIFY_ARE_EQUAL(U("null"), arr[1].serialize());
|
|
}
|
|
|
|
TEST(copy_ctor_array)
|
|
{
|
|
json::value arr = json::value::array();
|
|
arr[0] = json::value(true);
|
|
|
|
json::value copy(arr);
|
|
VERIFY_IS_TRUE(copy.is_array());
|
|
VERIFY_ARE_EQUAL(U("true"), copy[0].serialize());
|
|
copy[1] = json::value(false);
|
|
VERIFY_ARE_EQUAL(U("false"), copy[1].serialize());
|
|
VERIFY_ARE_EQUAL(U("null"), arr[1].serialize());
|
|
}
|
|
|
|
TEST(copy_ctor_object)
|
|
{
|
|
json::value obj = json::value::object();
|
|
utility::string_t keyName(U("key"));
|
|
obj[keyName] = json::value(false);
|
|
|
|
// Copy object that has values added.
|
|
json::value copy(obj);
|
|
VERIFY_IS_TRUE(copy.is_object());
|
|
VERIFY_ARE_EQUAL(U("false"), copy[keyName].serialize());
|
|
obj[keyName] = json::value(true);
|
|
VERIFY_ARE_EQUAL(U("false"), copy[keyName].serialize());
|
|
VERIFY_ARE_EQUAL(U("true"), obj[keyName].serialize());
|
|
|
|
// Copy object that parses with value, but none additional added.
|
|
obj = json::value::parse(U("{\"key\": true}"));
|
|
json::value copy2(obj);
|
|
VERIFY_IS_TRUE(copy2.is_object());
|
|
obj[keyName] = json::value(false);
|
|
VERIFY_IS_TRUE(copy2.size() == 1);
|
|
VERIFY_ARE_EQUAL(U("false"), obj[keyName].serialize());
|
|
VERIFY_ARE_EQUAL(U("true"), copy2[keyName].serialize());
|
|
}
|
|
|
|
TEST(copy_ctor_string)
|
|
{
|
|
utility::string_t strValue(U("teststr"));
|
|
json::value str = json::value::string(strValue);
|
|
|
|
json::value copy(str);
|
|
VERIFY_IS_TRUE(copy.is_string());
|
|
VERIFY_ARE_EQUAL(strValue, copy.as_string());
|
|
str = json::value::string(U("teststr2"));
|
|
VERIFY_ARE_EQUAL(strValue, copy.as_string());
|
|
VERIFY_ARE_EQUAL(U("teststr2"), str.as_string());
|
|
}
|
|
|
|
TEST(copy_ctor_with_escaped)
|
|
{
|
|
auto str = json::value::parse(U("\"\\n\""));
|
|
VERIFY_ARE_EQUAL(U("\n"), str.as_string());
|
|
|
|
auto copy = str;
|
|
VERIFY_ARE_EQUAL(U("\n"), copy.as_string());
|
|
}
|
|
|
|
TEST(move_ctor)
|
|
{
|
|
json::value obj;
|
|
obj[U("A")] = json::value(true);
|
|
|
|
json::value moved(std::move(obj));
|
|
VERIFY_IS_TRUE(moved.is_object());
|
|
VERIFY_ARE_EQUAL(U("true"), moved[U("A")].serialize());
|
|
moved[U("B")] = json::value(false);
|
|
VERIFY_ARE_EQUAL(U("false"), moved[U("B")].serialize());
|
|
}
|
|
|
|
TEST(move_assignment_op)
|
|
{
|
|
json::value obj;
|
|
obj[U("A")] = json::value(true);
|
|
|
|
json::value moved;
|
|
moved = std::move(obj);
|
|
VERIFY_IS_TRUE(moved.is_object());
|
|
VERIFY_ARE_EQUAL(U("true"), moved[U("A")].serialize());
|
|
moved[U("B")] = json::value(false);
|
|
VERIFY_ARE_EQUAL(U("false"), moved[U("B")].serialize());
|
|
}
|
|
|
|
TEST(constructor_overloads)
|
|
{
|
|
json::value v0;
|
|
json::value v1(17);
|
|
json::value v2(3.1415);
|
|
json::value v3(true);
|
|
const utility::char_t* p4 = U("Hello!");
|
|
json::value v4(p4);
|
|
|
|
json::value v5(U("Hello Again!"));
|
|
json::value v6(U("YES YOU KNOW IT"));
|
|
json::value v7(U("HERE ID IS"));
|
|
|
|
const utility::char_t* p9 = U("Hello not-escaped!");
|
|
json::value v8(p9, true);
|
|
json::value v9(p9, false);
|
|
|
|
VERIFY_ARE_EQUAL(v0.type(), json::value::Null);
|
|
VERIFY_IS_TRUE(v0.is_null());
|
|
VERIFY_ARE_EQUAL(v1.type(), json::value::Number);
|
|
VERIFY_IS_TRUE(v1.is_number());
|
|
VERIFY_IS_TRUE(v1.is_integer());
|
|
VERIFY_IS_FALSE(v1.is_double());
|
|
VERIFY_ARE_EQUAL(v2.type(), json::value::Number);
|
|
VERIFY_IS_TRUE(v2.is_number());
|
|
VERIFY_IS_TRUE(v2.is_double());
|
|
VERIFY_IS_FALSE(v2.is_integer());
|
|
VERIFY_ARE_EQUAL(v3.type(), json::value::Boolean);
|
|
VERIFY_IS_TRUE(v3.is_boolean());
|
|
VERIFY_ARE_EQUAL(v4.type(), json::value::String);
|
|
VERIFY_IS_TRUE(v4.is_string());
|
|
VERIFY_ARE_EQUAL(v5.type(), json::value::String);
|
|
VERIFY_IS_TRUE(v5.is_string());
|
|
VERIFY_ARE_EQUAL(v6.type(), json::value::String);
|
|
VERIFY_IS_TRUE(v6.is_string());
|
|
VERIFY_ARE_EQUAL(v7.type(), json::value::String);
|
|
VERIFY_IS_TRUE(v7.is_string());
|
|
VERIFY_ARE_EQUAL(v8.type(), json::value::String);
|
|
VERIFY_IS_TRUE(v8.is_string());
|
|
VERIFY_ARE_EQUAL(v9.type(), json::value::String);
|
|
VERIFY_IS_TRUE(v9.is_string());
|
|
}
|
|
|
|
TEST(factory_overloads)
|
|
{
|
|
json::value v0 = json::value::null();
|
|
json::value v1 = json::value::number(17);
|
|
json::value v2 = json::value::number(3.1415);
|
|
json::value v3 = json::value::boolean(true);
|
|
json::value v4 = json::value::string(U("Hello!"));
|
|
json::value v5 = json::value::string(U("Hello Again!"));
|
|
json::value v6 = json::value::string(U("Hello!"));
|
|
json::value v7 = json::value::string(U("Hello Again!"));
|
|
json::value v8 = json::value::string(U("Hello not-escaped!"), true);
|
|
json::value v9 = json::value::string(U("Hello not-escaped!"), false);
|
|
json::value v10 = json::value::object();
|
|
json::value v11 = json::value::array();
|
|
|
|
|
|
VERIFY_ARE_EQUAL(v0.type(), json::value::Null);
|
|
VERIFY_ARE_EQUAL(v1.type(), json::value::Number);
|
|
VERIFY_ARE_EQUAL(v2.type(), json::value::Number);
|
|
VERIFY_ARE_EQUAL(v3.type(), json::value::Boolean);
|
|
VERIFY_ARE_EQUAL(v4.type(), json::value::String);
|
|
VERIFY_ARE_EQUAL(v5.type(), json::value::String);
|
|
VERIFY_ARE_EQUAL(v6.type(), json::value::String);
|
|
VERIFY_ARE_EQUAL(v7.type(), json::value::String);
|
|
VERIFY_ARE_EQUAL(v8.type(), json::value::String);
|
|
VERIFY_ARE_EQUAL(v9.type(), json::value::String);
|
|
VERIFY_ARE_EQUAL(v10.type(), json::value::Object);
|
|
VERIFY_IS_TRUE(v10.is_object());
|
|
VERIFY_ARE_EQUAL(v11.type(), json::value::Array);
|
|
VERIFY_IS_TRUE(v11.is_array());
|
|
}
|
|
|
|
TEST(object_construction)
|
|
{
|
|
// Factory which takes a vector.
|
|
std::vector<std::pair<string_t, json::value>> f;
|
|
f.push_back(std::make_pair(U("abc"), json::value(true)));
|
|
f.push_back(std::make_pair(U("xyz"), json::value(44)));
|
|
json::value obj = json::value::object(f);
|
|
|
|
VERIFY_ARE_EQUAL(f.size(), obj.size());
|
|
|
|
obj[U("abc")] = json::value::string(U("str"));
|
|
obj[U("123")] = json::value(false);
|
|
|
|
VERIFY_ARE_NOT_EQUAL(f.size(), obj.size());
|
|
VERIFY_ARE_EQUAL(json::value::string(U("str")).serialize(), obj[U("abc")].serialize());
|
|
VERIFY_ARE_EQUAL(json::value(false).serialize(), obj[U("123")].serialize());
|
|
|
|
// Tests constructing empty and adding.
|
|
auto val1 = json::value::object();
|
|
val1[U("A")] = 44;
|
|
val1[U("hahah")] = json::value(true);
|
|
VERIFY_ARE_EQUAL(2u, val1.size());
|
|
VERIFY_ARE_EQUAL(U("44"), val1[U("A")].serialize());
|
|
VERIFY_ARE_EQUAL(U("true"), val1[U("hahah")].serialize());
|
|
|
|
// Construct as null value, then turn into object.
|
|
json::value val2;
|
|
VERIFY_IS_TRUE(val2.is_null());
|
|
val2[U("A")] = 44;
|
|
val2[U("hahah")] = json::value(true);
|
|
VERIFY_ARE_EQUAL(2u, val2.size());
|
|
VERIFY_ARE_EQUAL(U("44"), val2[U("A")].serialize());
|
|
VERIFY_ARE_EQUAL(U("true"), val2[U("hahah")].serialize());
|
|
}
|
|
|
|
TEST(object_construction_keep_order)
|
|
{
|
|
std::vector<std::pair<string_t, json::value>> f;
|
|
f.push_back(std::make_pair(U("x"), json::value(0)));
|
|
f.push_back(std::make_pair(U("a"), json::value(1)));
|
|
|
|
auto obj1 = json::value::object(f, /*keep_order==*/ true);
|
|
VERIFY_ARE_EQUAL(obj1.as_object().begin()->first, U("x"));
|
|
|
|
auto obj2 = json::value::object(f, /*keep_order==*/ false);
|
|
VERIFY_ARE_EQUAL(obj2.as_object().begin()->first, U("a"));
|
|
}
|
|
|
|
TEST(object_construction_from_null_keep_order)
|
|
{
|
|
struct restore {
|
|
~restore() {
|
|
json::keep_object_element_order(false);
|
|
}
|
|
}_;
|
|
|
|
json::keep_object_element_order(true);
|
|
|
|
auto val1 = json::value::null();
|
|
val1[U("B")] = 1;
|
|
val1[U("A")] = 1;
|
|
VERIFY_ARE_EQUAL(val1.as_object().begin()->first, U("B"));
|
|
|
|
json::keep_object_element_order(false);
|
|
|
|
auto val2 = json::value::null();
|
|
val2[U("B")] = 1;
|
|
val2[U("A")] = 1;
|
|
VERIFY_ARE_EQUAL(val2.as_object().begin()->first, U("A"));
|
|
}
|
|
|
|
TEST(array_construction)
|
|
{
|
|
// Constructor which takes a vector.
|
|
std::vector<json::value> e;
|
|
e.push_back(json::value(false));
|
|
e.push_back(json::value::string(U("hehe")));
|
|
json::value arr = json::value::array(e);
|
|
VERIFY_ARE_EQUAL(e.size(), arr.size());
|
|
VERIFY_ARE_EQUAL(U("false"), arr[0].serialize());
|
|
arr[3] = json::value(22);
|
|
VERIFY_ARE_NOT_EQUAL(e.size(), arr.size());
|
|
VERIFY_ARE_EQUAL(U("22"), arr[3].serialize());
|
|
|
|
// Test empty factory and adding.
|
|
auto arr2 = json::value::array();
|
|
arr2[1] = json::value(false);
|
|
arr2[0] = json::value::object();
|
|
arr2[0][U("A")] = json::value::string(U("HE"));
|
|
VERIFY_ARE_EQUAL(2u, arr2.size());
|
|
VERIFY_ARE_EQUAL(U("false"), arr2[1].serialize());
|
|
VERIFY_ARE_EQUAL(U("\"HE\""), arr2[0][U("A")].serialize());
|
|
|
|
// Construct as null value and then add elements.
|
|
json::value arr3;
|
|
VERIFY_IS_TRUE(arr3.is_null());
|
|
arr3[1] = json::value(false);
|
|
// Element [0] should already behave as an object.
|
|
arr3[0][U("A")] = json::value::string(U("HE"));
|
|
VERIFY_ARE_EQUAL(2u, arr3.size());
|
|
VERIFY_ARE_EQUAL(U("false"), arr3[1].serialize());
|
|
VERIFY_ARE_EQUAL(U("\"HE\""), arr3[0][U("A")].serialize());
|
|
|
|
// Test factory which takes a size.
|
|
auto arr4 = json::value::array(2);
|
|
VERIFY_IS_TRUE(arr4[0].is_null());
|
|
VERIFY_IS_TRUE(arr4[1].is_null());
|
|
arr4[2] = json::value(true);
|
|
arr4[0] = json::value(false);
|
|
VERIFY_ARE_EQUAL(U("false"), arr4[0].serialize());
|
|
VERIFY_ARE_EQUAL(U("true"), arr4[2].serialize());
|
|
}
|
|
|
|
TEST(array_test)
|
|
{
|
|
json::value arr = json::value::array();
|
|
const json::value& carr = arr;
|
|
arr[0] = json::value(3.14);
|
|
arr[1] = json::value(true);
|
|
arr[2] = json::value("Yes");
|
|
int count;
|
|
json::array& array = arr.as_array();
|
|
const json::array& carray = arr.as_array();
|
|
|
|
VERIFY_THROWS(array.at(4), json::json_exception);
|
|
VERIFY_THROWS(carray.at(5), json::json_exception);
|
|
VERIFY_THROWS(arr.at(6), json::json_exception);
|
|
VERIFY_THROWS(carr.at(7), json::json_exception);
|
|
|
|
// The begin and end iterators on non-const instances
|
|
count = 0;
|
|
for(auto iter = array.begin(); iter != array.end(); ++iter)
|
|
{
|
|
VERIFY_IS_TRUE((*iter) == array[count]);
|
|
VERIFY_IS_TRUE((*iter) == array.at(count));
|
|
VERIFY_IS_TRUE((*iter) == carray.at(count));
|
|
count++;
|
|
}
|
|
VERIFY_ARE_EQUAL(array.size(), count);
|
|
|
|
count = 0;
|
|
for(auto iter = array.cbegin(); iter != array.cend(); ++iter)
|
|
{
|
|
VERIFY_IS_TRUE((*iter) == array[count]);
|
|
VERIFY_IS_TRUE((*iter) == array.at(count));
|
|
count++;
|
|
}
|
|
VERIFY_ARE_EQUAL(array.size(), count);
|
|
|
|
count = 0;
|
|
for(auto iter = array.rbegin(); iter != array.rend(); ++iter)
|
|
{
|
|
VERIFY_IS_TRUE((*iter) == array[array.size()-1-count]);
|
|
VERIFY_IS_TRUE((*iter) == array.at(array.size()-1-count));
|
|
VERIFY_IS_TRUE((*iter) == carray.at(array.size()-1-count));
|
|
count++;
|
|
}
|
|
VERIFY_ARE_EQUAL(array.size(), count);
|
|
|
|
count = 0;
|
|
for(auto iter = array.crbegin(); iter != array.crend(); ++iter)
|
|
{
|
|
VERIFY_IS_TRUE((*iter) == array[array.size()-1-count]);
|
|
VERIFY_IS_TRUE((*iter) == arr[array.size()-1-count]);
|
|
VERIFY_IS_TRUE((*iter) == array.at(array.size()-1-count));
|
|
VERIFY_IS_TRUE((*iter) == arr.at(array.size()-1-count));
|
|
count++;
|
|
}
|
|
VERIFY_ARE_EQUAL(array.size(), count);
|
|
|
|
// The begin and end iterators on const instances
|
|
count = 0;
|
|
for(auto iter = carray.begin(); iter != carray.end(); ++iter)
|
|
{
|
|
VERIFY_IS_TRUE((*iter) == carray.at(count));
|
|
VERIFY_IS_TRUE((*iter) == carr.at(count));
|
|
count++;
|
|
}
|
|
VERIFY_ARE_EQUAL(array.size(), count);
|
|
|
|
count = 0;
|
|
for(auto iter = carray.rbegin(); iter != carray.rend(); ++iter)
|
|
{
|
|
VERIFY_IS_TRUE((*iter) == carray.at(array.size()-1-count));
|
|
VERIFY_IS_TRUE((*iter) == carr.at(array.size()-1-count));
|
|
count++;
|
|
}
|
|
VERIFY_ARE_EQUAL(array.size(), count);
|
|
}
|
|
|
|
TEST(object_test)
|
|
{
|
|
json::value obj = json::value::object();
|
|
const json::value& cobj = obj;
|
|
json::object& object = obj.as_object();
|
|
const json::object& cobject = obj.as_object();
|
|
|
|
VERIFY_IS_TRUE(object.empty());
|
|
|
|
obj[U("name")] = json::value(U("John"));
|
|
obj[U("surname")] = json::value(U("Smith"));
|
|
obj[U("height")] = json::value(5.9);
|
|
obj[U("vegetarian")] = json::value(true);
|
|
int count;
|
|
|
|
//Test at()
|
|
VERIFY_ARE_EQUAL(U("John"), obj.at(U("name")).as_string());
|
|
VERIFY_ARE_EQUAL(U("John"), cobj.at(U("name")).as_string());
|
|
VERIFY_ARE_EQUAL(U("Smith"), object.at(U("surname")).as_string());
|
|
VERIFY_ARE_EQUAL(U("Smith"), cobject.at(U("surname")).as_string());
|
|
VERIFY_THROWS(obj.at(U("wrong key")), json::json_exception);
|
|
VERIFY_THROWS(cobj.at(U("wrong key")), json::json_exception);
|
|
|
|
//Test find()
|
|
{
|
|
auto iter = object.find(U("height"));
|
|
VERIFY_ARE_NOT_EQUAL(object.end(), iter);
|
|
VERIFY_IS_TRUE(iter->second.is_number());
|
|
VERIFY_ARE_EQUAL(5.9, iter->second.as_number().to_double());
|
|
VERIFY_ARE_EQUAL(object.end(), object.find(U("wrong_key")));
|
|
}
|
|
|
|
//Test find() const
|
|
auto citer = cobject.find(U("height"));
|
|
VERIFY_ARE_NOT_EQUAL(cobject.end(), citer);
|
|
VERIFY_IS_TRUE(citer->second.is_number());
|
|
VERIFY_ARE_EQUAL(5.9, citer->second.as_number().to_double());
|
|
VERIFY_ARE_EQUAL(cobject.end(), cobject.find(U("wrong_key")));
|
|
|
|
VERIFY_IS_FALSE(object.empty());
|
|
|
|
// The begin and end iterators on non-const instances
|
|
count = 0;
|
|
for(auto iter = object.begin(); iter != object.end(); ++iter)
|
|
{
|
|
VERIFY_ARE_EQUAL(object[iter->first], iter->second);
|
|
count++;
|
|
}
|
|
VERIFY_ARE_EQUAL(object.size(), count);
|
|
|
|
count = 0;
|
|
for(auto iter = object.rbegin(); iter != object.rend(); ++iter)
|
|
{
|
|
VERIFY_ARE_EQUAL(object[iter->first], iter->second);
|
|
count++;
|
|
}
|
|
VERIFY_ARE_EQUAL(object.size(), count);
|
|
|
|
count = 0;
|
|
for(auto iter = object.cbegin(); iter != object.cend(); ++iter)
|
|
{
|
|
VERIFY_ARE_EQUAL(object[iter->first], iter->second);
|
|
count++;
|
|
}
|
|
VERIFY_ARE_EQUAL(object.size(), count);
|
|
|
|
count = 0;
|
|
for(auto iter = object.crbegin(); iter != object.crend(); ++iter)
|
|
{
|
|
VERIFY_ARE_EQUAL(object[iter->first], iter->second);
|
|
count++;
|
|
}
|
|
VERIFY_ARE_EQUAL(object.size(), count);
|
|
|
|
// The begin and end iterators on const instances
|
|
count = 0;
|
|
for(auto iter = cobject.begin(); iter != cobject.end(); ++iter)
|
|
{
|
|
VERIFY_ARE_EQUAL(cobject.find(iter->first)->second, iter->second);
|
|
count++;
|
|
}
|
|
VERIFY_ARE_EQUAL(cobject.size(), count);
|
|
|
|
count = 0;
|
|
for(auto iter = cobject.rbegin(); iter != cobject.rend(); ++iter)
|
|
{
|
|
VERIFY_ARE_EQUAL(cobject.find(iter->first)->second, iter->second);
|
|
count++;
|
|
}
|
|
VERIFY_ARE_EQUAL(cobject.size(), count);
|
|
}
|
|
|
|
} // SUITE(construction_tests)
|
|
|
|
}}}
|
|
|