Prepare wpiutil for merge into allwpilib.

This commit is contained in:
Peter Johnson
2017-12-20 19:26:48 -08:00
parent 71d06a1a20
commit 0f947613a9
224 changed files with 0 additions and 354 deletions

View File

@@ -0,0 +1,310 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
#include <algorithm>
class JsonAlgorithmsTest : public ::testing::Test {
protected:
json j_array = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz"};
json j_object = {{"one", 1}, {"two", 2}};
};
// non-modifying sequence operations
TEST_F(JsonAlgorithmsTest, AllOf)
{
EXPECT_TRUE(std::all_of(j_array.begin(), j_array.end(), [](const json & value)
{
return value.size() > 0;
}));
EXPECT_TRUE(std::all_of(j_object.begin(), j_object.end(), [](const json & value)
{
return value.type() == json::value_t::number_integer;
}));
}
TEST_F(JsonAlgorithmsTest, AnyOf)
{
EXPECT_TRUE(std::any_of(j_array.begin(), j_array.end(), [](const json & value)
{
return value.is_string() && value.get<std::string>() == "foo";
}));
EXPECT_TRUE(std::any_of(j_object.begin(), j_object.end(), [](const json & value)
{
return value.get<int>() > 1;
}));
}
TEST_F(JsonAlgorithmsTest, NoneOf)
{
EXPECT_TRUE(std::none_of(j_array.begin(), j_array.end(), [](const json & value)
{
return value.size() == 0;
}));
EXPECT_TRUE(std::none_of(j_object.begin(), j_object.end(), [](const json & value)
{
return value.get<int>() <= 0;
}));
}
TEST_F(JsonAlgorithmsTest, ForEachReading)
{
int sum = 0;
std::for_each(j_array.cbegin(), j_array.cend(), [&sum](const json & value)
{
if (value.is_number())
{
sum += static_cast<int>(value);
}
});
EXPECT_EQ(sum, 45);
}
TEST_F(JsonAlgorithmsTest, ForEachWriting)
{
auto add17 = [](json & value)
{
if (value.is_array())
{
value.push_back(17);
}
};
std::for_each(j_array.begin(), j_array.end(), add17);
EXPECT_EQ(j_array[6], json({1, 2, 3, 17}));
}
TEST_F(JsonAlgorithmsTest, Count)
{
EXPECT_EQ(std::count(j_array.begin(), j_array.end(), json(true)), 1);
}
TEST_F(JsonAlgorithmsTest, CountIf)
{
auto count1 = std::count_if(j_array.begin(), j_array.end(), [](const json & value)
{
return (value.is_number());
});
EXPECT_EQ(count1, 3);
auto count2 = std::count_if(j_array.begin(), j_array.end(), [](const json&)
{
return true;
});
EXPECT_EQ(count2, 9);
}
TEST_F(JsonAlgorithmsTest, Mismatch)
{
json j_array2 = {13, 29, 3, {{"one", 1}, {"two", 2}, {"three", 3}}, true, false, {1, 2, 3}, "foo", "baz"};
auto res = std::mismatch(j_array.begin(), j_array.end(), j_array2.begin());
EXPECT_EQ(*res.first, json({{"one", 1}, {"two", 2}}));
EXPECT_EQ(*res.second, json({{"one", 1}, {"two", 2}, {"three", 3}}));
}
TEST_F(JsonAlgorithmsTest, EqualOperatorEquals)
{
EXPECT_TRUE(std::equal(j_array.begin(), j_array.end(), j_array.begin()));
EXPECT_TRUE(std::equal(j_object.begin(), j_object.end(), j_object.begin()));
EXPECT_FALSE(std::equal(j_array.begin(), j_array.end(), j_object.begin()));
}
TEST_F(JsonAlgorithmsTest, EqualUserComparison)
{
// compare objects only by size of its elements
json j_array2 = {13, 29, 3, {"Hello", "World"}, true, false, {{"one", 1}, {"two", 2}, {"three", 3}}, "foo", "baz"};
EXPECT_FALSE(std::equal(j_array.begin(), j_array.end(), j_array2.begin()));
EXPECT_TRUE(std::equal(j_array.begin(), j_array.end(), j_array2.begin(),
[](const json & a, const json & b)
{
return (a.size() == b.size());
}));
}
TEST_F(JsonAlgorithmsTest, Find)
{
auto it = std::find(j_array.begin(), j_array.end(), json(false));
EXPECT_EQ(std::distance(j_array.begin(), it), 5);
}
TEST_F(JsonAlgorithmsTest, FindIf)
{
auto it = std::find_if(j_array.begin(), j_array.end(),
[](const json & value)
{
return value.is_boolean();
});
EXPECT_EQ(std::distance(j_array.begin(), it), 4);
}
TEST_F(JsonAlgorithmsTest, FindIfNot)
{
auto it = std::find_if_not(j_array.begin(), j_array.end(),
[](const json & value)
{
return value.is_number();
});
EXPECT_EQ(std::distance(j_array.begin(), it), 3);
}
TEST_F(JsonAlgorithmsTest, AdjacentFind)
{
EXPECT_EQ(std::adjacent_find(j_array.begin(), j_array.end()), j_array.end());
auto it = std::adjacent_find(j_array.begin(), j_array.end(),
[](const json & v1, const json & v2)
{
return v1.type() == v2.type();
});
EXPECT_EQ(it, j_array.begin());
}
// modifying sequence operations
TEST_F(JsonAlgorithmsTest, Reverse)
{
std::reverse(j_array.begin(), j_array.end());
EXPECT_EQ(j_array, json({"baz", "foo", {1, 2, 3}, false, true, {{"one", 1}, {"two", 2}}, 3, 29, 13}));
}
TEST_F(JsonAlgorithmsTest, Rotate)
{
std::rotate(j_array.begin(), j_array.begin() + 1, j_array.end());
EXPECT_EQ(j_array, json({29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", 13}));
}
TEST_F(JsonAlgorithmsTest, Partition)
{
auto it = std::partition(j_array.begin(), j_array.end(), [](const json & v)
{
return v.is_string();
});
EXPECT_EQ(std::distance(j_array.begin(), it), 2);
EXPECT_FALSE(it[2].is_string());
}
// sorting operations
TEST_F(JsonAlgorithmsTest, SortOperatorEquals)
{
json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
std::sort(j.begin(), j.end());
EXPECT_EQ(j, json({nullptr, false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
}
TEST_F(JsonAlgorithmsTest, SortUserComparison)
{
json j = {3, {{"one", 1}, {"two", 2}}, {1, 2, 3}, nullptr};
std::sort(j.begin(), j.end(), [](const json & a, const json & b)
{
return a.size() < b.size();
});
EXPECT_EQ(j, json({nullptr, 3, {{"one", 1}, {"two", 2}}, {1, 2, 3}}));
}
TEST_F(JsonAlgorithmsTest, SortObject)
{
json j({{"one", 1}, {"two", 2}});
EXPECT_THROW_MSG(std::sort(j.begin(), j.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
TEST_F(JsonAlgorithmsTest, PartialSort)
{
json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
std::partial_sort(j.begin(), j.begin() + 4, j.end());
EXPECT_EQ(j, json({nullptr, false, true, 3, {{"one", 1}, {"two", 2}}, 29, {1, 2, 3}, "foo", "baz", 13}));
}
// set operations
TEST_F(JsonAlgorithmsTest, Merge)
{
json j1 = {2, 4, 6, 8};
json j2 = {1, 2, 3, 5, 7};
json j3;
std::merge(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
EXPECT_EQ(j3, json({1, 2, 2, 3, 4, 5, 6, 7, 8}));
}
TEST_F(JsonAlgorithmsTest, SetDifference)
{
json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
json j2 = {1, 2, 3, 5, 7};
json j3;
std::set_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
EXPECT_EQ(j3, json({4, 6, 8}));
}
TEST_F(JsonAlgorithmsTest, SetIntersection)
{
json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
json j2 = {1, 2, 3, 5, 7};
json j3;
std::set_intersection(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
EXPECT_EQ(j3, json({1, 2, 3, 5, 7}));
}
TEST_F(JsonAlgorithmsTest, SetUnion)
{
json j1 = {2, 4, 6, 8};
json j2 = {1, 2, 3, 5, 7};
json j3;
std::set_union(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
EXPECT_EQ(j3, json({1, 2, 3, 4, 5, 6, 7, 8}));
}
TEST_F(JsonAlgorithmsTest, SetSymmetricDifference)
{
json j1 = {2, 4, 6, 8};
json j2 = {1, 2, 3, 5, 7};
json j3;
std::set_symmetric_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
EXPECT_EQ(j3, json({1, 3, 4, 5, 6, 7, 8}));
}
TEST_F(JsonAlgorithmsTest, HeapOperations)
{
std::make_heap(j_array.begin(), j_array.end());
EXPECT_TRUE(std::is_heap(j_array.begin(), j_array.end()));
std::sort_heap(j_array.begin(), j_array.end());
EXPECT_EQ(j_array, json({false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
}

View File

@@ -0,0 +1,528 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
TEST(JsonEmptyTest, Boolean)
{
json j = true;
json j_const(j);
// result of empty
{
EXPECT_FALSE(j.empty());
EXPECT_FALSE(j_const.empty());
}
// definition of empty
{
EXPECT_EQ(j.empty(), (j.begin() == j.end()));
EXPECT_EQ(j_const.empty(), (j_const.begin() == j_const.end()));
}
}
TEST(JsonEmptyTest, String)
{
json j = "hello world";
json j_const(j);
// result of empty
{
EXPECT_FALSE(j.empty());
EXPECT_FALSE(j_const.empty());
}
// definition of empty
{
EXPECT_EQ(j.empty(), (j.begin() == j.end()));
EXPECT_EQ(j_const.empty(), (j_const.begin() == j_const.end()));
}
}
TEST(JsonEmptyTest, ArrayEmpty)
{
json j = json::array();
json j_const(j);
// result of empty
{
EXPECT_TRUE(j.empty());
EXPECT_TRUE(j_const.empty());
}
// definition of empty
{
EXPECT_EQ(j.empty(), (j.begin() == j.end()));
EXPECT_EQ(j_const.empty(), (j_const.begin() == j_const.end()));
}
}
TEST(JsonEmptyTest, ArrayFilled)
{
json j = {1, 2, 3};
json j_const(j);
// result of empty
{
EXPECT_FALSE(j.empty());
EXPECT_FALSE(j_const.empty());
}
// definition of empty
{
EXPECT_EQ(j.empty(), (j.begin() == j.end()));
EXPECT_EQ(j_const.empty(), (j_const.begin() == j_const.end()));
}
}
TEST(JsonEmptyTest, ObjectEmpty)
{
json j = json::object();
json j_const(j);
// result of empty
{
EXPECT_TRUE(j.empty());
EXPECT_TRUE(j_const.empty());
}
// definition of empty
{
EXPECT_EQ(j.empty(), (j.begin() == j.end()));
EXPECT_EQ(j_const.empty(), (j_const.begin() == j_const.end()));
}
}
TEST(JsonEmptyTest, ObjectFilled)
{
json j = {{"one", 1}, {"two", 2}, {"three", 3}};
json j_const(j);
// result of empty
{
EXPECT_FALSE(j.empty());
EXPECT_FALSE(j_const.empty());
}
// definition of empty
{
EXPECT_EQ(j.empty(), (j.begin() == j.end()));
EXPECT_EQ(j_const.empty(), (j_const.begin() == j_const.end()));
}
}
TEST(JsonEmptyTest, NumberInteger)
{
json j = 23;
json j_const(j);
// result of empty
{
EXPECT_FALSE(j.empty());
EXPECT_FALSE(j_const.empty());
}
// definition of empty
{
EXPECT_EQ(j.empty(), (j.begin() == j.end()));
EXPECT_EQ(j_const.empty(), (j_const.begin() == j_const.end()));
}
}
TEST(JsonEmptyTest, NumberUnsigned)
{
json j = 23u;
json j_const(j);
// result of empty
{
EXPECT_FALSE(j.empty());
EXPECT_FALSE(j_const.empty());
}
// definition of empty
{
EXPECT_EQ(j.empty(), (j.begin() == j.end()));
EXPECT_EQ(j_const.empty(), (j_const.begin() == j_const.end()));
}
}
TEST(JsonEmptyTest, NumberFloat)
{
json j = 23.42;
json j_const(j);
// result of empty
{
EXPECT_FALSE(j.empty());
EXPECT_FALSE(j_const.empty());
}
// definition of empty
{
EXPECT_EQ(j.empty(), (j.begin() == j.end()));
EXPECT_EQ(j_const.empty(), (j_const.begin() == j_const.end()));
}
}
TEST(JsonEmptyTest, Null)
{
json j = nullptr;
json j_const(j);
// result of empty
{
EXPECT_TRUE(j.empty());
EXPECT_TRUE(j_const.empty());
}
// definition of empty
{
EXPECT_EQ(j.empty(), (j.begin() == j.end()));
EXPECT_EQ(j_const.empty(), (j_const.begin() == j_const.end()));
}
}
TEST(JsonSizeTest, Boolean)
{
json j = true;
json j_const(j);
// result of size
{
EXPECT_EQ(j.size(), 1u);
EXPECT_EQ(j_const.size(), 1u);
}
// definition of size
{
EXPECT_EQ(std::distance(j.begin(), j.end()), static_cast<int>(j.size()));
EXPECT_EQ(std::distance(j_const.begin(), j_const.end()),
static_cast<int>(j_const.size()));
}
}
TEST(JsonSizeTest, String)
{
json j = "hello world";
json j_const(j);
// result of size
{
EXPECT_EQ(j.size(), 1u);
EXPECT_EQ(j_const.size(), 1u);
}
// definition of size
{
EXPECT_EQ(std::distance(j.begin(), j.end()), static_cast<int>(j.size()));
EXPECT_EQ(std::distance(j_const.begin(), j_const.end()),
static_cast<int>(j_const.size()));
}
}
TEST(JsonSizeTest, ArrayEmpty)
{
json j = json::array();
json j_const(j);
// result of size
{
EXPECT_EQ(j.size(), 0u);
EXPECT_EQ(j_const.size(), 0u);
}
// definition of size
{
EXPECT_EQ(std::distance(j.begin(), j.end()), static_cast<int>(j.size()));
EXPECT_EQ(std::distance(j_const.begin(), j_const.end()),
static_cast<int>(j_const.size()));
}
}
TEST(JsonSizeTest, ArrayFilled)
{
json j = {1, 2, 3};
json j_const(j);
// result of size
{
EXPECT_EQ(j.size(), 3u);
EXPECT_EQ(j_const.size(), 3u);
}
// definition of size
{
EXPECT_EQ(std::distance(j.begin(), j.end()), static_cast<int>(j.size()));
EXPECT_EQ(std::distance(j_const.begin(), j_const.end()),
static_cast<int>(j_const.size()));
}
}
TEST(JsonSizeTest, ObjectEmpty)
{
json j = json::object();
json j_const(j);
// result of size
{
EXPECT_EQ(j.size(), 0u);
EXPECT_EQ(j_const.size(), 0u);
}
// definition of size
{
EXPECT_EQ(std::distance(j.begin(), j.end()), static_cast<int>(j.size()));
EXPECT_EQ(std::distance(j_const.begin(), j_const.end()),
static_cast<int>(j_const.size()));
}
}
TEST(JsonSizeTest, ObjectFilled)
{
json j = {{"one", 1}, {"two", 2}, {"three", 3}};
json j_const(j);
// result of size
{
EXPECT_EQ(j.size(), 3u);
EXPECT_EQ(j_const.size(), 3u);
}
// definition of size
{
EXPECT_EQ(std::distance(j.begin(), j.end()), static_cast<int>(j.size()));
EXPECT_EQ(std::distance(j_const.begin(), j_const.end()),
static_cast<int>(j_const.size()));
}
}
TEST(JsonSizeTest, NumberInteger)
{
json j = 23;
json j_const(j);
// result of size
{
EXPECT_EQ(j.size(), 1u);
EXPECT_EQ(j_const.size(), 1u);
}
// definition of size
{
EXPECT_EQ(std::distance(j.begin(), j.end()), static_cast<int>(j.size()));
EXPECT_EQ(std::distance(j_const.begin(), j_const.end()),
static_cast<int>(j_const.size()));
}
}
TEST(JsonSizeTest, NumberUnsigned)
{
json j = 23u;
json j_const(j);
// result of size
{
EXPECT_EQ(j.size(), 1u);
EXPECT_EQ(j_const.size(), 1u);
}
// definition of size
{
EXPECT_EQ(std::distance(j.begin(), j.end()), static_cast<int>(j.size()));
EXPECT_EQ(std::distance(j_const.begin(), j_const.end()),
static_cast<int>(j_const.size()));
}
}
TEST(JsonSizeTest, NumberFloat)
{
json j = 23.42;
json j_const(j);
// result of size
{
EXPECT_EQ(j.size(), 1u);
EXPECT_EQ(j_const.size(), 1u);
}
// definition of size
{
EXPECT_EQ(std::distance(j.begin(), j.end()), static_cast<int>(j.size()));
EXPECT_EQ(std::distance(j_const.begin(), j_const.end()),
static_cast<int>(j_const.size()));
}
}
TEST(JsonSizeTest, Null)
{
json j = nullptr;
json j_const(j);
// result of size
{
EXPECT_EQ(j.size(), 0u);
EXPECT_EQ(j_const.size(), 0u);
}
// definition of size
{
EXPECT_EQ(std::distance(j.begin(), j.end()), static_cast<int>(j.size()));
EXPECT_EQ(std::distance(j_const.begin(), j_const.end()),
static_cast<int>(j_const.size()));
}
}
TEST(JsonMaxSizeTest, Boolean)
{
json j = true;
json j_const(j);
// result of max_size
{
EXPECT_EQ(j.max_size(), 1u);
EXPECT_EQ(j_const.max_size(), 1u);
}
}
TEST(JsonMaxSizeTest, String)
{
json j = "hello world";
json j_const(j);
// result of max_size
{
EXPECT_EQ(j.max_size(), 1u);
EXPECT_EQ(j_const.max_size(), 1u);
}
}
TEST(JsonMaxSizeTest, ArrayEmpty)
{
json j = json::array();
json j_const(j);
// result of max_size
{
EXPECT_GE(j.max_size(), j.size());
EXPECT_GE(j_const.max_size(), j_const.size());
}
}
TEST(JsonMaxSizeTest, ArrayFilled)
{
json j = {1, 2, 3};
json j_const(j);
// result of max_size
{
EXPECT_GE(j.max_size(), j.size());
EXPECT_GE(j_const.max_size(), j_const.size());
}
}
TEST(JsonMaxSizeTest, ObjectEmpty)
{
json j = json::object();
json j_const(j);
// result of max_size
{
EXPECT_GE(j.max_size(), j.size());
EXPECT_GE(j_const.max_size(), j_const.size());
}
}
TEST(JsonMaxSizeTest, ObjectFilled)
{
json j = {{"one", 1}, {"two", 2}, {"three", 3}};
json j_const(j);
// result of max_size
{
EXPECT_GE(j.max_size(), j.size());
EXPECT_GE(j_const.max_size(), j_const.size());
}
}
TEST(JsonMaxSizeTest, NumberInteger)
{
json j = 23;
json j_const(j);
// result of max_size
{
EXPECT_EQ(j.max_size(), 1u);
EXPECT_EQ(j_const.max_size(), 1u);
}
}
TEST(JsonMaxSizeTest, NumberUnsigned)
{
json j = 23u;
json j_const(j);
// result of max_size
{
EXPECT_EQ(j.max_size(), 1u);
EXPECT_EQ(j_const.max_size(), 1u);
}
}
TEST(JsonMaxSizeTest, NumberFloat)
{
json j = 23.42;
json j_const(j);
// result of max_size
{
EXPECT_EQ(j.max_size(), 1u);
EXPECT_EQ(j_const.max_size(), 1u);
}
}
TEST(JsonMaxSizeTest, Null)
{
json j = nullptr;
json j_const(j);
// result of max_size
{
EXPECT_EQ(j.max_size(), 0u);
EXPECT_EQ(j_const.max_size(), 0u);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,250 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
class JsonComparisonTypesTest : public ::testing::Test {
protected:
std::vector<json::value_t> j_types =
{
json::value_t::null,
json::value_t::boolean,
json::value_t::number_integer,
json::value_t::number_unsigned,
json::value_t::number_float,
json::value_t::object,
json::value_t::array,
json::value_t::string
};
};
TEST_F(JsonComparisonTypesTest, Less)
{
static const std::vector<std::vector<bool>> expected =
{
{false, true, true, true, true, true, true, true},
{false, false, true, true, true, true, true, true},
{false, false, false, false, false, true, true, true},
{false, false, false, false, false, true, true, true},
{false, false, false, false, false, true, true, true},
{false, false, false, false, false, false, true, true},
{false, false, false, false, false, false, false, true},
{false, false, false, false, false, false, false, false}
};
for (size_t i = 0; i < j_types.size(); ++i)
{
SCOPED_TRACE(i);
for (size_t j = 0; j < j_types.size(); ++j)
{
SCOPED_TRACE(j);
// check precomputed values
EXPECT_EQ(operator<(j_types[i], j_types[j]), expected[i][j]);
}
}
}
class JsonComparisonValuesTest : public ::testing::Test {
protected:
json j_values =
{
nullptr, nullptr,
17, 42,
8u, 13u,
3.14159, 23.42,
"foo", "bar",
true, false,
{1, 2, 3}, {"one", "two", "three"},
{{"first", 1}, {"second", 2}}, {{"a", "A"}, {"b", {"B"}}}
};
};
TEST_F(JsonComparisonValuesTest, Equal)
{
static const std::vector<std::vector<bool>> expected =
{
{true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
{true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
{false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false},
{false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false},
{false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false},
{false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false},
{false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false},
{false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false},
{false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false},
{false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false},
{false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false},
{false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false},
{false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false},
{false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false},
{false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false},
{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true}
};
for (size_t i = 0; i < j_values.size(); ++i)
{
SCOPED_TRACE(i);
for (size_t j = 0; j < j_values.size(); ++j)
{
SCOPED_TRACE(j);
// check precomputed values
EXPECT_EQ(j_values[i] == j_values[j], expected[i][j]);
}
}
// comparison with discarded elements
json j_discarded(json::value_t::discarded);
for (size_t i = 0; i < j_values.size(); ++i)
{
SCOPED_TRACE(i);
EXPECT_FALSE(j_values[i] == j_discarded);
EXPECT_FALSE(j_discarded == j_values[i]);
EXPECT_FALSE(j_discarded == j_discarded);
}
// compare with null pointer
json j_null;
EXPECT_TRUE(j_null == nullptr);
EXPECT_TRUE(nullptr == j_null);
}
TEST_F(JsonComparisonValuesTest, NotEqual)
{
for (size_t i = 0; i < j_values.size(); ++i)
{
SCOPED_TRACE(i);
for (size_t j = 0; j < j_values.size(); ++j)
{
SCOPED_TRACE(j);
// check definition
EXPECT_EQ(j_values[i] != j_values[j], !(j_values[i] == j_values[j]));
}
}
// compare with null pointer
json j_null;
EXPECT_FALSE(j_null != nullptr);
EXPECT_FALSE(nullptr != j_null);
EXPECT_EQ(j_null != nullptr, !(j_null == nullptr));
EXPECT_EQ(nullptr != j_null, !(nullptr == j_null));
}
TEST_F(JsonComparisonValuesTest, Less)
{
static const std::vector<std::vector<bool>> expected =
{
{false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true},
{false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true},
{false, false, false, true, false, false, false, true, true, true, false, false, true, true, true, true},
{false, false, false, false, false, false, false, false, true, true, false, false, true, true, true, true},
{false, false, true, true, false, true, false, true, true, true, false, false, true, true, true, true},
{false, false, true, true, false, false, false, true, true, true, false, false, true, true, true, true},
{false, false, true, true, true, true, false, true, true, true, false, false, true, true, true, true},
{false, false, false, true, false, false, false, false, true, true, false, false, true, true, true, true},
{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
{false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false},
{false, false, true, true, true, true, true, true, true, true, false, false, true, true, true, true},
{false, false, true, true, true, true, true, true, true, true, true, false, true, true, true, true},
{false, false, false, false, false, false, false, false, true, true, false, false, false, true, false, false},
{false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false},
{false, false, false, false, false, false, false, false, true, true, false, false, true, true, false, false},
{false, false, false, false, false, false, false, false, true, true, false, false, true, true, true, false}
};
for (size_t i = 0; i < j_values.size(); ++i)
{
SCOPED_TRACE(i);
for (size_t j = 0; j < j_values.size(); ++j)
{
SCOPED_TRACE(j);
// check precomputed values
EXPECT_EQ(j_values[i] < j_values[j], expected[i][j]);
}
}
// comparison with discarded elements
json j_discarded(json::value_t::discarded);
for (size_t i = 0; i < j_values.size(); ++i)
{
SCOPED_TRACE(i);
EXPECT_FALSE(j_values[i] < j_discarded);
EXPECT_FALSE(j_discarded < j_values[i]);
EXPECT_FALSE(j_discarded < j_discarded);
}
}
TEST_F(JsonComparisonValuesTest, LessEqual)
{
for (size_t i = 0; i < j_values.size(); ++i)
{
SCOPED_TRACE(i);
for (size_t j = 0; j < j_values.size(); ++j)
{
SCOPED_TRACE(j);
// check definition
EXPECT_EQ(j_values[i] <= j_values[j], !(j_values[j] < j_values[i]));
}
}
}
TEST_F(JsonComparisonValuesTest, Greater)
{
for (size_t i = 0; i < j_values.size(); ++i)
{
SCOPED_TRACE(i);
for (size_t j = 0; j < j_values.size(); ++j)
{
SCOPED_TRACE(j);
// check definition
EXPECT_EQ(j_values[i] > j_values[j], j_values[j] < j_values[i]);
}
}
}
TEST_F(JsonComparisonValuesTest, GreaterEqual)
{
for (size_t i = 0; i < j_values.size(); ++i)
{
SCOPED_TRACE(i);
for (size_t j = 0; j < j_values.size(); ++j)
{
SCOPED_TRACE(j);
// check definition
EXPECT_EQ(j_values[i] >= j_values[j], !(j_values[i] < j_values[j]));
}
}
}

View File

@@ -0,0 +1,166 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
TEST(JsonConceptsTest, ContainerRequirements)
{
// X: container class: json
// T: type of objects: json
// a, b: values of type X: json
// TABLE 96 - Container Requirements
// X::value_type must return T
EXPECT_TRUE((std::is_same<json::value_type, json>::value));
// X::reference must return lvalue of T
EXPECT_TRUE((std::is_same<json::reference, json&>::value));
// X::const_reference must return const lvalue of T
EXPECT_TRUE((std::is_same<json::const_reference, const json&>::value));
// X::iterator must return iterator whose value_type is T
EXPECT_TRUE((std::is_same<json::iterator::value_type, json>::value));
// X::iterator must meet the forward iterator requirements
EXPECT_TRUE((std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<json::iterator>::iterator_category>::value));
// X::iterator must be convertible to X::const_iterator
EXPECT_TRUE((std::is_convertible<json::iterator, json::const_iterator>::value));
// X::const_iterator must return iterator whose value_type is T
EXPECT_TRUE((std::is_same<json::const_iterator::value_type, json>::value));
// X::const_iterator must meet the forward iterator requirements
EXPECT_TRUE((std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<json::const_iterator>::iterator_category>::value));
// X::difference_type must return a signed integer
EXPECT_TRUE((std::is_signed<json::difference_type>::value));
// X::difference_type must be identical to X::iterator::difference_type
EXPECT_TRUE((std::is_same<json::difference_type, json::iterator::difference_type>::value));
// X::difference_type must be identical to X::const_iterator::difference_type
EXPECT_TRUE((std::is_same<json::difference_type, json::const_iterator::difference_type>::value));
// X::size_type must return an unsigned integer
EXPECT_TRUE((std::is_unsigned<json::size_type>::value));
// X::size_type can represent any non-negative value of X::difference_type
EXPECT_TRUE(static_cast<json::size_type>(std::numeric_limits<json::difference_type>::max()) <=
std::numeric_limits<json::size_type>::max());
// the expression "X u" has the post-condition "u.empty()"
{
json u;
EXPECT_TRUE(u.empty());
}
// the expression "X()" has the post-condition "X().empty()"
EXPECT_TRUE(json().empty());
}
TEST(JsonConceptsTest, DefaultConstructible)
{
EXPECT_TRUE(std::is_nothrow_default_constructible<json>::value);
}
TEST(JsonConceptsTest, MoveConstructible)
{
EXPECT_TRUE(std::is_nothrow_move_constructible<json>::value);
}
TEST(JsonConceptsTest, CopyConstructible)
{
EXPECT_TRUE(std::is_copy_constructible<json>::value);
}
TEST(JsonConceptsTest, MoveAssignable)
{
EXPECT_TRUE(std::is_nothrow_move_assignable<json>::value);
}
TEST(JsonConceptsTest, CopyAssignable)
{
EXPECT_TRUE(std::is_copy_assignable<json>::value);
}
TEST(JsonConceptsTest, Destructible)
{
EXPECT_TRUE(std::is_nothrow_destructible<json>::value);
}
TEST(JsonConceptsTest, StandardLayoutType)
{
EXPECT_TRUE(std::is_standard_layout<json>::value);
}
TEST(JsonIteratorConceptsTest, CopyConstructible)
{
EXPECT_TRUE(std::is_nothrow_copy_constructible<json::iterator>::value);
EXPECT_TRUE(std::is_nothrow_copy_constructible<json::const_iterator>::value);
}
TEST(JsonIteratorConceptsTest, CopyAssignable)
{
// STL iterators used by json::iterator don't pass this test in Debug mode
#if !defined(_MSC_VER) || (_ITERATOR_DEBUG_LEVEL == 0)
EXPECT_TRUE(std::is_nothrow_copy_assignable<json::iterator>::value);
EXPECT_TRUE(std::is_nothrow_copy_assignable<json::const_iterator>::value);
#endif
}
TEST(JsonIteratorConceptsTest, Destructible)
{
EXPECT_TRUE(std::is_nothrow_destructible<json::iterator>::value);
EXPECT_TRUE(std::is_nothrow_destructible<json::const_iterator>::value);
}
TEST(JsonIteratorConceptsTest, Swappable)
{
json j {1, 2, 3};
json::iterator it1 = j.begin();
json::iterator it2 = j.end();
std::swap(it1, it2);
EXPECT_EQ(it1, j.end());
EXPECT_EQ(it2, j.begin());
}
TEST(JsonIteratorConceptsTest, SwappableConst)
{
json j {1, 2, 3};
json::const_iterator it1 = j.cbegin();
json::const_iterator it2 = j.cend();
std::swap(it1, it2);
EXPECT_EQ(it1, j.end());
EXPECT_EQ(it2, j.begin());
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,185 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
TEST(JsonCopyConstructorTest, Object)
{
json j {{"foo", 1}, {"bar", false}};
json k(j);
EXPECT_EQ(j, k);
}
TEST(JsonCopyConstructorTest, Array)
{
json j {"foo", 1, 42.23, false};
json k(j);
EXPECT_EQ(j, k);
}
TEST(JsonCopyConstructorTest, Null)
{
json j(nullptr);
json k(j);
EXPECT_EQ(j, k);
}
TEST(JsonCopyConstructorTest, Boolean)
{
json j(true);
json k(j);
EXPECT_EQ(j, k);
}
TEST(JsonCopyConstructorTest, String)
{
json j("Hello world");
json k(j);
EXPECT_EQ(j, k);
}
TEST(JsonCopyConstructorTest, Integer)
{
json j(42);
json k(j);
EXPECT_EQ(j, k);
}
TEST(JsonCopyConstructorTest, Unsigned)
{
json j(42u);
json k(j);
EXPECT_EQ(j, k);
}
TEST(JsonCopyConstructorTest, Float)
{
json j(42.23);
json k(j);
EXPECT_EQ(j, k);
}
TEST(JsonMoveConstructorTest, Case)
{
json j {{"foo", "bar"}, {"baz", {1, 2, 3, 4}}, {"a", 42u}, {"b", 42.23}, {"c", nullptr}};
EXPECT_EQ(j.type(), json::value_t::object);
json k(std::move(j));
EXPECT_EQ(k.type(), json::value_t::object);
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonCopyAssignmentTest, Object)
{
json j {{"foo", 1}, {"bar", false}};
json k;
k = j;
EXPECT_EQ(j, k);
}
TEST(JsonCopyAssignmentTest, Array)
{
json j {"foo", 1, 42.23, false};
json k;
k = j;
EXPECT_EQ(j, k);
}
TEST(JsonCopyAssignmentTest, Null)
{
json j(nullptr);
json k;
k = j;
EXPECT_EQ(j, k);
}
TEST(JsonCopyAssignmentTest, Boolean)
{
json j(true);
json k;
k = j;
EXPECT_EQ(j, k);
}
TEST(JsonCopyAssignmentTest, String)
{
json j("Hello world");
json k;
k = j;
EXPECT_EQ(j, k);
}
TEST(JsonCopyAssignmentTest, Integer)
{
json j(42);
json k;
k = j;
EXPECT_EQ(j, k);
}
TEST(JsonCopyAssignmentTest, Unsigned)
{
json j(42u);
json k;
k = j;
EXPECT_EQ(j, k);
}
TEST(JsonCopyAssignmentTest, Float)
{
json j(42.23);
json k;
k = j;
EXPECT_EQ(j, k);
}
TEST(JsonDestructorTest, Object)
{
auto j = new json {{"foo", 1}, {"bar", false}};
delete j;
}
TEST(JsonDestructorTest, Array)
{
auto j = new json {"foo", 1, 1u, false, 23.42};
delete j;
}
TEST(JsonDestructorTest, String)
{
auto j = new json("Hello world");
delete j;
}

View File

@@ -0,0 +1,121 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "llvm/SmallString.h"
#include "unit-json.h"
#include "support/json_serializer.h"
using wpi::json;
class JsonTypeNameTest
: public ::testing::TestWithParam<std::pair<json::value_t, const char*>> {};
TEST_P(JsonTypeNameTest, Case)
{
EXPECT_EQ(json(GetParam().first).type_name(), GetParam().second);
}
static const std::pair<json::value_t, const char*> type_name_cases[] = {
{json::value_t::null, "null"},
{json::value_t::object, "object"},
{json::value_t::array, "array"},
{json::value_t::number_integer, "number"},
{json::value_t::number_unsigned, "number"},
{json::value_t::number_float, "number"},
{json::value_t::boolean, "boolean"},
{json::value_t::string, "string"},
{json::value_t::discarded, "discarded"},
};
INSTANTIATE_TEST_CASE_P(JsonTypeNameTests, JsonTypeNameTest,
::testing::ValuesIn(type_name_cases), );
class JsonStringEscapeTest
: public ::testing::TestWithParam<std::pair<const char*, const char*>> {};
TEST_P(JsonStringEscapeTest, Case)
{
llvm::SmallString<32> buf;
llvm::raw_svector_ostream ss(buf);
json::serializer s(ss);
s.dump_escaped(GetParam().first);
EXPECT_EQ(ss.str(), llvm::StringRef(GetParam().second));
}
static const std::pair<const char*, const char*> string_escape_cases[] = {
{"\"", "\\\""},
{"\\", "\\\\"},
{"\b", "\\b"},
{"\f", "\\f"},
{"\n", "\\n"},
{"\r", "\\r"},
{"\t", "\\t"},
{"\x01", "\\u0001"},
{"\x02", "\\u0002"},
{"\x03", "\\u0003"},
{"\x04", "\\u0004"},
{"\x05", "\\u0005"},
{"\x06", "\\u0006"},
{"\x07", "\\u0007"},
{"\x08", "\\b"},
{"\x09", "\\t"},
{"\x0a", "\\n"},
{"\x0b", "\\u000b"},
{"\x0c", "\\f"},
{"\x0d", "\\r"},
{"\x0e", "\\u000e"},
{"\x0f", "\\u000f"},
{"\x10", "\\u0010"},
{"\x11", "\\u0011"},
{"\x12", "\\u0012"},
{"\x13", "\\u0013"},
{"\x14", "\\u0014"},
{"\x15", "\\u0015"},
{"\x16", "\\u0016"},
{"\x17", "\\u0017"},
{"\x18", "\\u0018"},
{"\x19", "\\u0019"},
{"\x1a", "\\u001a"},
{"\x1b", "\\u001b"},
{"\x1c", "\\u001c"},
{"\x1d", "\\u001d"},
{"\x1e", "\\u001e"},
{"\x1f", "\\u001f"},
};
INSTANTIATE_TEST_CASE_P(JsonStringEscapeTests, JsonStringEscapeTest,
::testing::ValuesIn(string_escape_cases), );

View File

@@ -0,0 +1,560 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
using wpi::JsonTest;
#include <deque>
//#include <forward_list>
#include <list>
#include <map>
#include <unordered_map>
#include <unordered_set>
template <typename T>
class JsonGetObjectTest : public ::testing::Test {
public:
JsonGetObjectTest() : j(o_reference) {}
protected:
json::object_t o_reference = {{"object", json::object()}, {"array", {1, 2, 3, 4}}, {"number", 42}, {"boolean", false}, {"null", nullptr}, {"string", "Hello world"} };
json j;
};
typedef ::testing::Types<
json::object_t
, std::map<json::string_t, json>
, std::multimap<json::string_t, json>
, std::unordered_map<json::string_t, json>
, std::unordered_multimap<json::string_t, json>
> JsonGetObjectTestTypes;
TYPED_TEST_CASE(JsonGetObjectTest, JsonGetObjectTestTypes);
TYPED_TEST(JsonGetObjectTest, Explicit)
{
TypeParam o = (this->j).template get<TypeParam>();
EXPECT_EQ(json(o), this->j);
}
TYPED_TEST(JsonGetObjectTest, Implicit)
{
TypeParam o = this->j;
EXPECT_EQ(json(o), this->j);
}
// exception in case of a non-object type
TEST(JsonGetObjectExceptionTest, TypeError)
{
EXPECT_THROW_MSG(json(json::value_t::null).get<json::object_t>(), json::type_error,
"[json.exception.type_error.302] type must be object, but is null");
EXPECT_THROW_MSG(json(json::value_t::array).get<json::object_t>(), json::type_error,
"[json.exception.type_error.302] type must be object, but is array");
EXPECT_THROW_MSG(json(json::value_t::string).get<json::object_t>(), json::type_error,
"[json.exception.type_error.302] type must be object, but is string");
EXPECT_THROW_MSG(json(json::value_t::boolean).get<json::object_t>(), json::type_error,
"[json.exception.type_error.302] type must be object, but is boolean");
EXPECT_THROW_MSG(json(json::value_t::number_integer).get<json::object_t>(), json::type_error,
"[json.exception.type_error.302] type must be object, but is number");
EXPECT_THROW_MSG(json(json::value_t::number_unsigned).get<json::object_t>(), json::type_error,
"[json.exception.type_error.302] type must be object, but is number");
EXPECT_THROW_MSG(json(json::value_t::number_float).get<json::object_t>(), json::type_error,
"[json.exception.type_error.302] type must be object, but is number");
}
template <typename T>
class JsonGetArrayTest : public ::testing::Test {
public:
JsonGetArrayTest() : j(a_reference) {}
protected:
json::array_t a_reference {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json j;
};
typedef ::testing::Types<json::array_t, std::list<json>,
/*std::forward_list<json>,*/ std::vector<json>,
std::deque<json>>
JsonGetArrayTestTypes;
TYPED_TEST_CASE(JsonGetArrayTest, JsonGetArrayTestTypes);
TYPED_TEST(JsonGetArrayTest, Explicit)
{
TypeParam a = (this->j).template get<TypeParam>();
EXPECT_EQ(json(a), this->j);
}
TYPED_TEST(JsonGetArrayTest, Implicit)
{
TypeParam a = this->j;
EXPECT_EQ(json(a), this->j);
}
#if !defined(JSON_NOEXCEPTION)
// reserve is called on containers that supports it
TEST(JsonGetArrayAdditionalTest, ExplicitStdVectorReserve)
{
json::array_t a_reference {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json j(a_reference);
// making the call to from_json throw in order to check capacity
std::vector<float> v;
EXPECT_THROW(wpi::from_json(j, v), json::type_error);
EXPECT_EQ(v.capacity(), j.size());
// make sure all values are properly copied
std::vector<int> v2 = json({1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
EXPECT_EQ(v2.size(), 10u);
}
#endif
// built-in arrays
TEST(JsonGetArrayAdditionalTest, ExplicitBuiltinArray)
{
const char str[] = "a string";
const int nbs[] = {0, 1, 2};
json j2 = nbs;
json j3 = str;
auto v = j2.get<std::vector<int>>();
auto s = j3.get<std::string>();
EXPECT_TRUE(std::equal(v.begin(), v.end(), std::begin(nbs)));
EXPECT_EQ(s, str);
}
#if 0
TEST(JsonGetArrayExceptionTest, ForwardList)
{
EXPECT_THROW_MSG(json(json::value_t::null).get<std::forward_list<json>>(), json::type_error,
"[json.exception.type_error.302] type must be array, but is null");
}
#endif
TEST(JsonGetArrayExceptionTest, StdVector)
{
EXPECT_THROW_MSG(json(json::value_t::null).get<std::vector<json>>(), json::type_error,
"[json.exception.type_error.302] type must be array, but is null");
}
// exception in case of a non-array type
TEST(JsonGetArrayExceptionTest, TypeError)
{
EXPECT_THROW_MSG(json(json::value_t::object).get<std::vector<int>>(), json::type_error,
"[json.exception.type_error.302] type must be array, but is object");
EXPECT_THROW_MSG(json(json::value_t::null).get<json::array_t>(), json::type_error,
"[json.exception.type_error.302] type must be array, but is null");
EXPECT_THROW_MSG(json(json::value_t::object).get<json::array_t>(), json::type_error,
"[json.exception.type_error.302] type must be array, but is object");
EXPECT_THROW_MSG(json(json::value_t::string).get<json::array_t>(), json::type_error,
"[json.exception.type_error.302] type must be array, but is string");
EXPECT_THROW_MSG(json(json::value_t::boolean).get<json::array_t>(), json::type_error,
"[json.exception.type_error.302] type must be array, but is boolean");
EXPECT_THROW_MSG(json(json::value_t::number_integer).get<json::array_t>(), json::type_error,
"[json.exception.type_error.302] type must be array, but is number");
EXPECT_THROW_MSG(json(json::value_t::number_unsigned).get<json::array_t>(), json::type_error,
"[json.exception.type_error.302] type must be array, but is number");
EXPECT_THROW_MSG(json(json::value_t::number_float).get<json::array_t>(), json::type_error,
"[json.exception.type_error.302] type must be array, but is number");
}
template <typename T>
class JsonGetStringTest : public ::testing::Test {
public:
JsonGetStringTest() : j(s_reference) {}
protected:
json::string_t s_reference {"Hello world"};
json j;
};
typedef ::testing::Types<json::string_t, std::string> JsonGetStringTestTypes;
TYPED_TEST_CASE(JsonGetStringTest, JsonGetStringTestTypes);
TYPED_TEST(JsonGetStringTest, Explicit)
{
TypeParam s = (this->j).template get<TypeParam>();
EXPECT_EQ(json(s), this->j);
}
TYPED_TEST(JsonGetStringTest, Implicit)
{
TypeParam s = this->j;
EXPECT_EQ(json(s), this->j);
}
// exception in case of a non-string type
TEST(JsonGetStringExceptionTest, TypeError)
{
EXPECT_THROW_MSG(json(json::value_t::null).get<json::string_t>(), json::type_error,
"[json.exception.type_error.302] type must be string, but is null");
EXPECT_THROW_MSG(json(json::value_t::object).get<json::string_t>(), json::type_error,
"[json.exception.type_error.302] type must be string, but is object");
EXPECT_THROW_MSG(json(json::value_t::array).get<json::string_t>(), json::type_error,
"[json.exception.type_error.302] type must be string, but is array");
EXPECT_THROW_MSG(json(json::value_t::boolean).get<json::string_t>(), json::type_error,
"[json.exception.type_error.302] type must be string, but is boolean");
EXPECT_THROW_MSG(json(json::value_t::number_integer).get<json::string_t>(), json::type_error,
"[json.exception.type_error.302] type must be string, but is number");
EXPECT_THROW_MSG(json(json::value_t::number_unsigned).get<json::string_t>(), json::type_error,
"[json.exception.type_error.302] type must be string, but is number");
EXPECT_THROW_MSG(json(json::value_t::number_float).get<json::string_t>(), json::type_error,
"[json.exception.type_error.302] type must be string, but is number");
}
template <typename T>
class JsonGetBooleanTest : public ::testing::Test {
public:
JsonGetBooleanTest() : j(b_reference) {}
protected:
json::boolean_t b_reference {true};
json j;
};
typedef ::testing::Types<json::boolean_t, bool> JsonGetBooleanTestTypes;
TYPED_TEST_CASE(JsonGetBooleanTest, JsonGetBooleanTestTypes);
TYPED_TEST(JsonGetBooleanTest, Explicit)
{
TypeParam b = (this->j).template get<TypeParam>();
EXPECT_EQ(json(b), this->j);
}
TYPED_TEST(JsonGetBooleanTest, Implicit)
{
TypeParam b = this->j;
EXPECT_EQ(json(b), this->j);
}
// exception in case of a non-string type
TEST(JsonGetBooleanExceptionTest, TypeError)
{
EXPECT_THROW_MSG(json(json::value_t::null).get<json::boolean_t>(), json::type_error,
"[json.exception.type_error.302] type must be boolean, but is null");
EXPECT_THROW_MSG(json(json::value_t::object).get<json::boolean_t>(), json::type_error,
"[json.exception.type_error.302] type must be boolean, but is object");
EXPECT_THROW_MSG(json(json::value_t::array).get<json::boolean_t>(), json::type_error,
"[json.exception.type_error.302] type must be boolean, but is array");
EXPECT_THROW_MSG(json(json::value_t::string).get<json::boolean_t>(), json::type_error,
"[json.exception.type_error.302] type must be boolean, but is string");
EXPECT_THROW_MSG(json(json::value_t::number_integer).get<json::boolean_t>(), json::type_error,
"[json.exception.type_error.302] type must be boolean, but is number");
EXPECT_THROW_MSG(json(json::value_t::number_unsigned).get<json::boolean_t>(), json::type_error,
"[json.exception.type_error.302] type must be boolean, but is number");
EXPECT_THROW_MSG(json(json::value_t::number_float).get<json::boolean_t>(), json::type_error,
"[json.exception.type_error.302] type must be boolean, but is number");
}
template <typename T>
class JsonGetIntegerTest : public ::testing::Test {
public:
JsonGetIntegerTest() : j(n_reference), j_unsigned(n_unsigned_reference) {}
protected:
json::number_integer_t n_reference {42};
json j;
json::number_unsigned_t n_unsigned_reference {42u};
json j_unsigned;
};
typedef ::testing::Types<
short
, unsigned short
, int
, unsigned int
, long
, unsigned long
, long long
, unsigned long long
, int8_t
, int16_t
, int32_t
, int64_t
#if 0
, int8_fast_t
, int16_fast_t
, int32_fast_t
, int64_fast_t
, int8_least_t
, int16_least_t
, int32_least_t
, int64_least_t
#endif
, uint8_t
, uint16_t
, uint32_t
, uint64_t
#if 0
, uint8_fast_t
, uint16_fast_t
, uint32_fast_t
, uint64_fast_t
, uint8_least_t
, uint16_least_t
, uint32_least_t
, uint64_least_t
#endif
> JsonGetIntegerTestTypes;
TYPED_TEST_CASE(JsonGetIntegerTest, JsonGetIntegerTestTypes);
TYPED_TEST(JsonGetIntegerTest, Explicit)
{
TypeParam n = (this->j).template get<TypeParam>();
EXPECT_EQ(json(n), this->j);
}
TYPED_TEST(JsonGetIntegerTest, Implicit)
{
if (std::is_unsigned<TypeParam>::value)
{
TypeParam n = this->j_unsigned;
EXPECT_EQ(json(n), this->j_unsigned);
}
else
{
TypeParam n = this->j;
EXPECT_EQ(json(n), this->j);
}
}
// exception in case of a non-number type
TEST(JsonGetIntegerExceptionTest, TypeError)
{
EXPECT_THROW_MSG(json(json::value_t::null).get<json::number_integer_t>(), json::type_error,
"[json.exception.type_error.302] type must be number, but is null");
EXPECT_THROW_MSG(json(json::value_t::object).get<json::number_integer_t>(), json::type_error,
"[json.exception.type_error.302] type must be number, but is object");
EXPECT_THROW_MSG(json(json::value_t::array).get<json::number_integer_t>(), json::type_error,
"[json.exception.type_error.302] type must be number, but is array");
EXPECT_THROW_MSG(json(json::value_t::string).get<json::number_integer_t>(), json::type_error,
"[json.exception.type_error.302] type must be number, but is string");
EXPECT_THROW_MSG(json(json::value_t::boolean).get<json::number_integer_t>(), json::type_error,
"[json.exception.type_error.302] type must be number, but is boolean");
EXPECT_NO_THROW(json(json::value_t::number_float).get<json::number_integer_t>());
EXPECT_NO_THROW(json(json::value_t::number_float).get<json::number_unsigned_t>());
}
template <typename T>
class JsonGetFloatTest : public ::testing::Test {
public:
JsonGetFloatTest() : j(n_reference) {}
protected:
json::number_float_t n_reference {42.23};
json j;
};
typedef ::testing::Types<json::number_float_t, float, double>
JsonGetFloatTestTypes;
TYPED_TEST_CASE(JsonGetFloatTest, JsonGetFloatTestTypes);
TYPED_TEST(JsonGetFloatTest, Explicit)
{
TypeParam n = (this->j).template get<TypeParam>();
EXPECT_LT(std::fabs(JsonTest::GetValue(json(n)).number_float -
JsonTest::GetValue(this->j).number_float), 0.001);
}
TYPED_TEST(JsonGetFloatTest, Implicit)
{
TypeParam n = this->j;
EXPECT_LT(std::fabs(JsonTest::GetValue(json(n)).number_float -
JsonTest::GetValue(this->j).number_float), 0.001);
}
// exception in case of a non-string type
TEST(JsonGetFloatExceptionTest, TypeError)
{
EXPECT_THROW_MSG(json(json::value_t::null).get<json::number_float_t>(), json::type_error,
"[json.exception.type_error.302] type must be number, but is null");
EXPECT_THROW_MSG(json(json::value_t::object).get<json::number_float_t>(), json::type_error,
"[json.exception.type_error.302] type must be number, but is object");
EXPECT_THROW_MSG(json(json::value_t::array).get<json::number_float_t>(), json::type_error,
"[json.exception.type_error.302] type must be number, but is array");
EXPECT_THROW_MSG(json(json::value_t::string).get<json::number_float_t>(), json::type_error,
"[json.exception.type_error.302] type must be number, but is string");
EXPECT_THROW_MSG(json(json::value_t::boolean).get<json::number_float_t>(), json::type_error,
"[json.exception.type_error.302] type must be number, but is boolean");
EXPECT_NO_THROW(json(json::value_t::number_integer).get<json::number_float_t>());
EXPECT_NO_THROW(json(json::value_t::number_unsigned).get<json::number_float_t>());
}
TEST(JsonGetEnumTest, Case)
{
enum c_enum { value_1, value_2 };
enum class cpp_enum { value_1, value_2 };
EXPECT_EQ(json(value_1).get<c_enum>(), value_1);
EXPECT_EQ(json(cpp_enum::value_1).get<cpp_enum>(), cpp_enum::value_1);
}
class JsonObjectConversionTest : public ::testing::Test {
protected:
json j1 = {{"one", 1}, {"two", 2}, {"three", 3}};
json j2 = {{"one", 1u}, {"two", 2u}, {"three", 3u}};
json j3 = {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}};
json j4 = {{"one", true}, {"two", false}, {"three", true}};
json j5 = {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}};
};
TEST_F(JsonObjectConversionTest, StdMap)
{
auto m1 = j1.get<std::map<std::string, int>>();
auto m2 = j2.get<std::map<std::string, unsigned int>>();
auto m3 = j3.get<std::map<std::string, double>>();
auto m4 = j4.get<std::map<std::string, bool>>();
//auto m5 = j5.get<std::map<std::string, std::string>>();
}
TEST_F(JsonObjectConversionTest, StdUnorderedMap)
{
auto m1 = j1.get<std::unordered_map<std::string, int>>();
auto m2 = j2.get<std::unordered_map<std::string, unsigned int>>();
auto m3 = j3.get<std::unordered_map<std::string, double>>();
auto m4 = j4.get<std::unordered_map<std::string, bool>>();
//auto m5 = j5.get<std::unordered_map<std::string, std::string>>();
//CHECK(m5["one"] == "eins");
}
TEST_F(JsonObjectConversionTest, StdMultiMap)
{
auto m1 = j1.get<std::multimap<std::string, int>>();
auto m2 = j2.get<std::multimap<std::string, unsigned int>>();
auto m3 = j3.get<std::multimap<std::string, double>>();
auto m4 = j4.get<std::multimap<std::string, bool>>();
//auto m5 = j5.get<std::multimap<std::string, std::string>>();
//CHECK(m5["one"] == "eins");
}
TEST_F(JsonObjectConversionTest, StdUnorderedMultiMap)
{
auto m1 = j1.get<std::unordered_multimap<std::string, int>>();
auto m2 = j2.get<std::unordered_multimap<std::string, unsigned int>>();
auto m3 = j3.get<std::unordered_multimap<std::string, double>>();
auto m4 = j4.get<std::unordered_multimap<std::string, bool>>();
//auto m5 = j5.get<std::unordered_multimap<std::string, std::string>>();
//CHECK(m5["one"] == "eins");
}
// exception in case of a non-object type
TEST_F(JsonObjectConversionTest, Exception)
{
EXPECT_THROW_MSG((json().get<std::map<std::string, int>>()), json::type_error,
"[json.exception.type_error.302] type must be object, but is null");
}
class JsonArrayConversionTest : public ::testing::Test {
protected:
json j1 = {1, 2, 3, 4};
json j2 = {1u, 2u, 3u, 4u};
json j3 = {1.2, 2.3, 3.4, 4.5};
json j4 = {true, false, true};
json j5 = {"one", "two", "three"};
};
TEST_F(JsonArrayConversionTest, StdList)
{
auto m1 = j1.get<std::list<int>>();
auto m2 = j2.get<std::list<unsigned int>>();
auto m3 = j3.get<std::list<double>>();
auto m4 = j4.get<std::list<bool>>();
auto m5 = j5.get<std::list<std::string>>();
}
#if 0
TEST_F(JsonArrayConversionTest, StdForwardList)
{
auto m1 = j1.get<std::forward_list<int>>();
auto m2 = j2.get<std::forward_list<unsigned int>>();
auto m3 = j3.get<std::forward_list<double>>();
auto m4 = j4.get<std::forward_list<bool>>();
auto m5 = j5.get<std::forward_list<std::string>>();
}
#endif
TEST_F(JsonArrayConversionTest, StdVector)
{
auto m1 = j1.get<std::vector<int>>();
auto m2 = j2.get<std::vector<unsigned int>>();
auto m3 = j3.get<std::vector<double>>();
auto m4 = j4.get<std::vector<bool>>();
auto m5 = j5.get<std::vector<std::string>>();
}
TEST_F(JsonArrayConversionTest, StdDeque)
{
auto m1 = j1.get<std::deque<int>>();
auto m2 = j2.get<std::deque<unsigned int>>();
auto m3 = j2.get<std::deque<double>>();
auto m4 = j4.get<std::deque<bool>>();
auto m5 = j5.get<std::deque<std::string>>();
}
TEST_F(JsonArrayConversionTest, StdSet)
{
auto m1 = j1.get<std::set<int>>();
auto m2 = j2.get<std::set<unsigned int>>();
auto m3 = j3.get<std::set<double>>();
auto m4 = j4.get<std::set<bool>>();
auto m5 = j5.get<std::set<std::string>>();
}
TEST_F(JsonArrayConversionTest, StdUnorderedSet)
{
auto m1 = j1.get<std::unordered_set<int>>();
auto m2 = j2.get<std::unordered_set<unsigned int>>();
auto m3 = j3.get<std::unordered_set<double>>();
auto m4 = j4.get<std::unordered_set<bool>>();
auto m5 = j5.get<std::unordered_set<std::string>>();
}
// exception in case of a non-object type
TEST_F(JsonArrayConversionTest, Exception)
{
EXPECT_THROW_MSG((json().get<std::list<int>>()), json::type_error,
"[json.exception.type_error.302] type must be array, but is null");
EXPECT_THROW_MSG((json().get<std::vector<int>>()), json::type_error,
"[json.exception.type_error.302] type must be array, but is null");
EXPECT_THROW_MSG((json().get<std::vector<json>>()), json::type_error,
"[json.exception.type_error.302] type must be array, but is null");
EXPECT_THROW_MSG((json().get<std::list<json>>()), json::type_error,
"[json.exception.type_error.302] type must be array, but is null");
// does type really must be an array? or it rather must not be null?
// that's what I thought when other test like this one broke
}

View File

@@ -0,0 +1,138 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
#include "support/raw_istream.h"
using wpi::json;
#include <valarray>
TEST(JsonDeserializationTest, SuccessfulStream)
{
std::string s = "[\"foo\",1,2,3,false,{\"one\":1}]";
wpi::raw_mem_istream ss(s.data(), s.size());
json j = json::parse(ss);
ASSERT_EQ(j, json({"foo", 1, 2, 3, false, {{"one", 1}}}));
}
TEST(JsonDeserializationTest, SuccessfulStringLiteral)
{
auto s = "[\"foo\",1,2,3,false,{\"one\":1}]";
json j = json::parse(s);
ASSERT_EQ(j, json({"foo", 1, 2, 3, false, {{"one", 1}}}));
}
TEST(JsonDeserializationTest, SuccessfulStdString)
{
std::string s = "[\"foo\",1,2,3,false,{\"one\":1}]";
json j = json::parse(s);
ASSERT_EQ(j, json({"foo", 1, 2, 3, false, {{"one", 1}}}));
}
TEST(JsonDeserializationTest, SuccessfulStreamOperator)
{
std::string s = "[\"foo\",1,2,3,false,{\"one\":1}]";
wpi::raw_mem_istream ss(s.data(), s.size());
json j;
ss >> j;
ASSERT_EQ(j, json({"foo", 1, 2, 3, false, {{"one", 1}}}));
}
TEST(JsonDeserializationTest, SuccessfulUserStringLiteral)
{
ASSERT_EQ("[\"foo\",1,2,3,false,{\"one\":1}]"_json, json({"foo", 1, 2, 3, false, {{"one", 1}}}));
}
TEST(JsonDeserializationTest, UnsuccessfulStream)
{
std::string s = "[\"foo\",1,2,3,false,{\"one\":1}";
wpi::raw_mem_istream ss(s.data(), s.size());
ASSERT_THROW_MSG(json::parse(ss), json::parse_error,
"[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'");
}
TEST(JsonDeserializationTest, UnsuccessfulStdString)
{
std::string s = "[\"foo\",1,2,3,false,{\"one\":1}";
ASSERT_THROW_MSG(json::parse(s), json::parse_error,
"[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'");
}
TEST(JsonDeserializationTest, UnsuccessfulStreamOperator)
{
std::string s = "[\"foo\",1,2,3,false,{\"one\":1}";
wpi::raw_mem_istream ss(s.data(), s.size());
json j;
ASSERT_THROW_MSG(ss >> j, json::parse_error,
"[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'");
}
TEST(JsonDeserializationTest, UnsuccessfulUserStringLiteral)
{
ASSERT_THROW_MSG("[\"foo\",1,2,3,false,{\"one\":1}"_json, json::parse_error,
"[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'");
}
// these cases are required for 100% line coverage
class JsonDeserializationErrorTest
: public ::testing::TestWithParam<const char*> {};
TEST_P(JsonDeserializationErrorTest, ErrorCase)
{
ASSERT_THROW(json::parse(GetParam()), json::parse_error);
}
static const char* error_cases[] = {
"\"aaaaaa\\u",
"\"aaaaaa\\u1",
"\"aaaaaa\\u11111111",
"\"aaaaaau11111111\\",
"\"\x7F\xC1",
"\"\x7F\xDF\x7F",
"\"\x7F\xDF\xC0",
"\"\x7F\xE0\x9F",
"\"\x7F\xEF\xC0",
"\"\x7F\xED\x7F",
"\"\x7F\xF0\x8F",
"\"\x7F\xF0\xC0",
"\"\x7F\xF3\x7F",
"\"\x7F\xF3\xC0",
"\"\x7F\xF4\x7F",
};
INSTANTIATE_TEST_CASE_P(JsonDeserializationErrorTests,
JsonDeserializationErrorTest,
::testing::ValuesIn(error_cases), );

View File

@@ -0,0 +1,873 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
class JsonElementArrayAccessTestBase {
public:
JsonElementArrayAccessTestBase() : j_const(j) {}
protected:
json j = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
const json j_const;
};
class JsonElementArrayAccessTest : public ::testing::Test,
public JsonElementArrayAccessTestBase {};
TEST_F(JsonElementArrayAccessTest, AtWithinBounds)
{
EXPECT_EQ(j.at(0), json(1));
EXPECT_EQ(j.at(1), json(1u));
EXPECT_EQ(j.at(2), json(true));
EXPECT_EQ(j.at(3), json(nullptr));
EXPECT_EQ(j.at(4), json("string"));
EXPECT_EQ(j.at(5), json(42.23));
EXPECT_EQ(j.at(6), json::object());
EXPECT_EQ(j.at(7), json({1, 2, 3}));
EXPECT_EQ(j_const.at(0), json(1));
EXPECT_EQ(j_const.at(1), json(1u));
EXPECT_EQ(j_const.at(2), json(true));
EXPECT_EQ(j_const.at(3), json(nullptr));
EXPECT_EQ(j_const.at(4), json("string"));
EXPECT_EQ(j_const.at(5), json(42.23));
EXPECT_EQ(j_const.at(6), json::object());
EXPECT_EQ(j_const.at(7), json({1, 2, 3}));
}
TEST_F(JsonElementArrayAccessTest, AtOutsideBounds)
{
EXPECT_THROW_MSG(j.at(8), json::out_of_range,
"[json.exception.out_of_range.401] array index 8 is out of range");
EXPECT_THROW_MSG(j_const.at(8), json::out_of_range,
"[json.exception.out_of_range.401] array index 8 is out of range");
}
TEST(JsonElementNonArrayAtAccessTest, Null)
{
json j_nonarray(json::value_t::null);
const json j_nonarray_const(j_nonarray);
EXPECT_THROW_MSG(j_nonarray.at(0), json::type_error,
"[json.exception.type_error.304] cannot use at() with null");
EXPECT_THROW_MSG(j_nonarray_const.at(0), json::type_error,
"[json.exception.type_error.304] cannot use at() with null");
}
TEST(JsonElementNonArrayAtAccessTest, Boolean)
{
json j_nonarray(json::value_t::boolean);
const json j_nonarray_const(j_nonarray);
EXPECT_THROW_MSG(j_nonarray.at(0), json::type_error,
"[json.exception.type_error.304] cannot use at() with boolean");
EXPECT_THROW_MSG(j_nonarray_const.at(0), json::type_error,
"[json.exception.type_error.304] cannot use at() with boolean");
}
TEST(JsonElementNonArrayAtAccessTest, String)
{
json j_nonarray(json::value_t::string);
const json j_nonarray_const(j_nonarray);
EXPECT_THROW_MSG(j_nonarray.at(0), json::type_error,
"[json.exception.type_error.304] cannot use at() with string");
EXPECT_THROW_MSG(j_nonarray_const.at(0), json::type_error,
"[json.exception.type_error.304] cannot use at() with string");
}
TEST(JsonElementNonArrayAtAccessTest, Object)
{
json j_nonarray(json::value_t::object);
const json j_nonarray_const(j_nonarray);
EXPECT_THROW_MSG(j_nonarray.at(0), json::type_error,
"[json.exception.type_error.304] cannot use at() with object");
EXPECT_THROW_MSG(j_nonarray_const.at(0), json::type_error,
"[json.exception.type_error.304] cannot use at() with object");
}
TEST(JsonElementNonArrayAtAccessTest, Integer)
{
json j_nonarray(json::value_t::number_integer);
const json j_nonarray_const(j_nonarray);
EXPECT_THROW_MSG(j_nonarray.at(0), json::type_error,
"[json.exception.type_error.304] cannot use at() with number");
EXPECT_THROW_MSG(j_nonarray_const.at(0), json::type_error,
"[json.exception.type_error.304] cannot use at() with number");
}
TEST(JsonElementNonArrayAtAccessTest, Unsigned)
{
json j_nonarray(json::value_t::number_unsigned);
const json j_nonarray_const(j_nonarray);
EXPECT_THROW_MSG(j_nonarray.at(0), json::type_error,
"[json.exception.type_error.304] cannot use at() with number");
EXPECT_THROW_MSG(j_nonarray_const.at(0), json::type_error,
"[json.exception.type_error.304] cannot use at() with number");
}
TEST(JsonElementNonArrayAtAccessTest, Float)
{
json j_nonarray(json::value_t::number_float);
const json j_nonarray_const(j_nonarray);
EXPECT_THROW_MSG(j_nonarray.at(0), json::type_error,
"[json.exception.type_error.304] cannot use at() with number");
EXPECT_THROW_MSG(j_nonarray_const.at(0), json::type_error,
"[json.exception.type_error.304] cannot use at() with number");
}
TEST_F(JsonElementArrayAccessTest, FrontAndBack)
{
EXPECT_EQ(j.front(), json(1));
EXPECT_EQ(j_const.front(), json(1));
EXPECT_EQ(j.back(), json({1, 2, 3}));
EXPECT_EQ(j_const.back(), json({1, 2, 3}));
}
TEST_F(JsonElementArrayAccessTest, OperatorWithinBounds)
{
EXPECT_EQ(j[0], json(1));
EXPECT_EQ(j[1], json(1u));
EXPECT_EQ(j[2], json(true));
EXPECT_EQ(j[3], json(nullptr));
EXPECT_EQ(j[4], json("string"));
EXPECT_EQ(j[5], json(42.23));
EXPECT_EQ(j[6], json::object());
EXPECT_EQ(j[7], json({1, 2, 3}));
EXPECT_EQ(j_const[0], json(1));
EXPECT_EQ(j_const[1], json(1u));
EXPECT_EQ(j_const[2], json(true));
EXPECT_EQ(j_const[3], json(nullptr));
EXPECT_EQ(j_const[4], json("string"));
EXPECT_EQ(j_const[5], json(42.23));
EXPECT_EQ(j_const[6], json::object());
EXPECT_EQ(j_const[7], json({1, 2, 3}));
}
TEST(JsonElementNonArrayOperatorAccessTest, NullStandard)
{
json j_nonarray(json::value_t::null);
const json j_nonarray_const(j_nonarray);
EXPECT_NO_THROW(j_nonarray[0]);
EXPECT_THROW_MSG(j_nonarray_const[0], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with null");
}
// implicit transformation to properly filled array
TEST(JsonElementNonArrayOperatorAccessTest, NullImplicitFilled)
{
json j_nonarray;
j_nonarray[3] = 42;
EXPECT_EQ(j_nonarray, json({nullptr, nullptr, nullptr, 42}));
}
TEST(JsonElementNonArrayOperatorAccessTest, Boolean)
{
json j_nonarray(json::value_t::boolean);
const json j_nonarray_const(j_nonarray);
EXPECT_THROW_MSG(j_nonarray[0], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with boolean");
EXPECT_THROW_MSG(j_nonarray_const[0], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with boolean");
}
TEST(JsonElementNonArrayOperatorAccessTest, String)
{
json j_nonarray(json::value_t::string);
const json j_nonarray_const(j_nonarray);
EXPECT_THROW_MSG(j_nonarray[0], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with string");
EXPECT_THROW_MSG(j_nonarray_const[0], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with string");
}
TEST(JsonElementNonArrayOperatorAccessTest, Object)
{
json j_nonarray(json::value_t::object);
const json j_nonarray_const(j_nonarray);
EXPECT_THROW_MSG(j_nonarray[0], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with object");
EXPECT_THROW_MSG(j_nonarray_const[0], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with object");
}
TEST(JsonElementNonArrayOperatorAccessTest, Integer)
{
json j_nonarray(json::value_t::number_integer);
const json j_nonarray_const(j_nonarray);
EXPECT_THROW_MSG(j_nonarray[0], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
EXPECT_THROW_MSG(j_nonarray_const[0], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
}
TEST(JsonElementNonArrayOperatorAccessTest, Unsigned)
{
json j_nonarray(json::value_t::number_unsigned);
const json j_nonarray_const(j_nonarray);
EXPECT_THROW_MSG(j_nonarray[0], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
EXPECT_THROW_MSG(j_nonarray_const[0], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
}
TEST(JsonElementNonArrayOperatorAccessTest, Float)
{
json j_nonarray(json::value_t::number_float);
const json j_nonarray_const(j_nonarray);
EXPECT_THROW_MSG(j_nonarray[0], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
EXPECT_THROW_MSG(j_nonarray_const[0], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
}
class JsonElementArrayRemoveTest : public ::testing::Test,
public JsonElementArrayAccessTestBase {};
// remove element by index
TEST_F(JsonElementArrayRemoveTest, Index0)
{
j.erase(0);
EXPECT_EQ(j, json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
}
TEST_F(JsonElementArrayRemoveTest, Index1)
{
j.erase(1);
EXPECT_EQ(j, json({1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
}
TEST_F(JsonElementArrayRemoveTest, Index2)
{
j.erase(2);
EXPECT_EQ(j, json({1, 1u, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
}
TEST_F(JsonElementArrayRemoveTest, Index3)
{
j.erase(3);
EXPECT_EQ(j, json({1, 1u, true, "string", 42.23, json::object(), {1, 2, 3}}));
}
TEST_F(JsonElementArrayRemoveTest, Index4)
{
j.erase(4);
EXPECT_EQ(j, json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
}
TEST_F(JsonElementArrayRemoveTest, Index5)
{
j.erase(5);
EXPECT_EQ(j, json({1, 1u, true, nullptr, "string", json::object(), {1, 2, 3}}));
}
TEST_F(JsonElementArrayRemoveTest, Index6)
{
j.erase(6);
EXPECT_EQ(j, json({1, 1u, true, nullptr, "string", 42.23, {1, 2, 3}}));
}
TEST_F(JsonElementArrayRemoveTest, Index7)
{
j.erase(7);
EXPECT_EQ(j, json({1, 1u, true, nullptr, "string", 42.23, json::object()}));
}
TEST_F(JsonElementArrayRemoveTest, Index8)
{
EXPECT_THROW_MSG(j.erase(8), json::out_of_range,
"[json.exception.out_of_range.401] array index 8 is out of range");
}
// erase(begin())
TEST_F(JsonElementArrayRemoveTest, Begin)
{
j.erase(j.begin());
EXPECT_EQ(j, json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
}
TEST_F(JsonElementArrayRemoveTest, BeginConst)
{
j.erase(j.cbegin());
EXPECT_EQ(j, json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
}
// erase(begin(), end())
TEST_F(JsonElementArrayRemoveTest, BeginEnd)
{
j.erase(j.begin(), j.end());
EXPECT_EQ(j, json::array());
}
TEST_F(JsonElementArrayRemoveTest, BeginEndConst)
{
j.erase(j.cbegin(), j.cend());
EXPECT_EQ(j, json::array());
}
// erase(begin(), begin())
TEST_F(JsonElementArrayRemoveTest, BeginBegin)
{
j.erase(j.begin(), j.begin());
EXPECT_EQ(j, json({1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
}
TEST_F(JsonElementArrayRemoveTest, BeginBeginConst)
{
j.erase(j.cbegin(), j.cbegin());
EXPECT_EQ(j, json({1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
}
// erase at offset
TEST_F(JsonElementArrayRemoveTest, Offset)
{
json::iterator it = j.begin() + 4;
j.erase(it);
EXPECT_EQ(j, json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
}
TEST_F(JsonElementArrayRemoveTest, OffsetConst)
{
json::const_iterator it = j.cbegin() + 4;
j.erase(it);
EXPECT_EQ(j, json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
}
// erase subrange
TEST_F(JsonElementArrayRemoveTest, Subrange)
{
j.erase(j.begin() + 3, j.begin() + 6);
EXPECT_EQ(j, json({1, 1u, true, json::object(), {1, 2, 3}}));
}
TEST_F(JsonElementArrayRemoveTest, SubrangeConst)
{
j.erase(j.cbegin() + 3, j.cbegin() + 6);
EXPECT_EQ(j, json({1, 1u, true, json::object(), {1, 2, 3}}));
}
// different arrays
TEST_F(JsonElementArrayRemoveTest, Different)
{
json j2 = {"foo", "bar"};
EXPECT_THROW_MSG(j.erase(j2.begin()), json::invalid_iterator,
"[json.exception.invalid_iterator.202] iterator does not fit current value");
EXPECT_THROW_MSG(j.erase(j.begin(), j2.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.203] iterators do not fit current value");
EXPECT_THROW_MSG(j.erase(j2.begin(), j.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.203] iterators do not fit current value");
EXPECT_THROW_MSG(j.erase(j2.begin(), j2.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.203] iterators do not fit current value");
}
TEST_F(JsonElementArrayRemoveTest, DifferentConst)
{
json j2 = {"foo", "bar"};
EXPECT_THROW_MSG(j.erase(j2.cbegin()), json::invalid_iterator,
"[json.exception.invalid_iterator.202] iterator does not fit current value");
EXPECT_THROW_MSG(j.erase(j.cbegin(), j2.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.203] iterators do not fit current value");
EXPECT_THROW_MSG(j.erase(j2.cbegin(), j.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.203] iterators do not fit current value");
EXPECT_THROW_MSG(j.erase(j2.cbegin(), j2.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.203] iterators do not fit current value");
}
// remove element by index in non-array type
TEST(JsonElementNonArrayIndexRemoveTest, Null)
{
json j_nonobject(json::value_t::null);
EXPECT_THROW_MSG(j_nonobject.erase(0), json::type_error,
"[json.exception.type_error.307] cannot use erase() with null");
}
TEST(JsonElementNonArrayIndexRemoveTest, Boolean)
{
json j_nonobject(json::value_t::boolean);
EXPECT_THROW_MSG(j_nonobject.erase(0), json::type_error,
"[json.exception.type_error.307] cannot use erase() with boolean");
}
TEST(JsonElementNonArrayIndexRemoveTest, String)
{
json j_nonobject(json::value_t::string);
EXPECT_THROW_MSG(j_nonobject.erase(0), json::type_error,
"[json.exception.type_error.307] cannot use erase() with string");
}
TEST(JsonElementNonArrayIndexRemoveTest, Object)
{
json j_nonobject(json::value_t::object);
EXPECT_THROW_MSG(j_nonobject.erase(0), json::type_error,
"[json.exception.type_error.307] cannot use erase() with object");
}
TEST(JsonElementNonArrayIndexRemoveTest, Integer)
{
json j_nonobject(json::value_t::number_integer);
EXPECT_THROW_MSG(j_nonobject.erase(0), json::type_error,
"[json.exception.type_error.307] cannot use erase() with number");
}
TEST(JsonElementNonArrayIndexRemoveTest, Unsigned)
{
json j_nonobject(json::value_t::number_unsigned);
EXPECT_THROW_MSG(j_nonobject.erase(0), json::type_error,
"[json.exception.type_error.307] cannot use erase() with number");
}
TEST(JsonElementNonArrayIndexRemoveTest, Float)
{
json j_nonobject(json::value_t::number_float);
EXPECT_THROW_MSG(j_nonobject.erase(0), json::type_error,
"[json.exception.type_error.307] cannot use erase() with number");
}
TEST(JsonElementNonArrayFrontBackAccessTest, Null)
{
json j;
EXPECT_THROW_MSG(j.front(), json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
EXPECT_THROW_MSG(j.back(), json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
}
TEST(JsonElementNonArrayFrontBackAccessTest, NullConst)
{
const json j{};
EXPECT_THROW_MSG(j.front(), json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
EXPECT_THROW_MSG(j.back(), json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
}
TEST(JsonElementNonArrayFrontBackAccessTest, String)
{
json j = "foo";
EXPECT_EQ(j.front(), j);
EXPECT_EQ(j.back(), j);
}
TEST(JsonElementNonArrayFrontBackAccessTest, StringConst)
{
const json j = "bar";
EXPECT_EQ(j.front(), j);
EXPECT_EQ(j.back(), j);
}
TEST(JsonElementNonArrayFrontBackAccessTest, Boolean)
{
json j = false;
EXPECT_EQ(j.front(), j);
EXPECT_EQ(j.back(), j);
}
TEST(JsonElementNonArrayFrontBackAccessTest, BooleanConst)
{
const json j = true;
EXPECT_EQ(j.front(), j);
EXPECT_EQ(j.back(), j);
}
TEST(JsonElementNonArrayFrontBackAccessTest, Integer)
{
json j = 17;
EXPECT_EQ(j.front(), j);
EXPECT_EQ(j.back(), j);
}
TEST(JsonElementNonArrayFrontBackAccessTest, IntegerConst)
{
const json j = 17;
EXPECT_EQ(j.front(), j);
EXPECT_EQ(j.back(), j);
}
TEST(JsonElementNonArrayFrontBackAccessTest, Unsigned)
{
json j = 17u;
EXPECT_EQ(j.front(), j);
EXPECT_EQ(j.back(), j);
}
TEST(JsonElementNonArrayFrontBackAccessTest, UnsignedConst)
{
const json j = 17u;
EXPECT_EQ(j.front(), j);
EXPECT_EQ(j.back(), j);
}
TEST(JsonElementNonArrayFrontBackAccessTest, Float)
{
json j = 23.42;
EXPECT_EQ(j.front(), j);
EXPECT_EQ(j.back(), j);
}
TEST(JsonElementNonArrayFrontBackAccessTest, FloatConst)
{
const json j = 23.42;
EXPECT_EQ(j.front(), j);
EXPECT_EQ(j.back(), j);
}
TEST(JsonElementNonArrayOneValidIteratorRemoveTest, Null)
{
json j;
EXPECT_THROW_MSG(j.erase(j.begin()), json::type_error,
"[json.exception.type_error.307] cannot use erase() with null");
}
TEST(JsonElementNonArrayOneValidIteratorRemoveTest, NullConst)
{
json j;
EXPECT_THROW_MSG(j.erase(j.cbegin()), json::type_error,
"[json.exception.type_error.307] cannot use erase() with null");
}
TEST(JsonElementNonArrayOneValidIteratorRemoveTest, String)
{
json j = "foo";
j.erase(j.begin());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayOneValidIteratorRemoveTest, StringConst)
{
json j = "bar";
j.erase(j.cbegin());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayOneValidIteratorRemoveTest, Boolean)
{
json j = false;
j.erase(j.begin());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayOneValidIteratorRemoveTest, BooleanConst)
{
json j = true;
j.erase(j.cbegin());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayOneValidIteratorRemoveTest, Integer)
{
json j = 17;
j.erase(j.begin());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayOneValidIteratorRemoveTest, IntegerConst)
{
json j = 17;
j.erase(j.cbegin());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayOneValidIteratorRemoveTest, Unsigned)
{
json j = 17u;
j.erase(j.begin());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayOneValidIteratorRemoveTest, UnsignedConst)
{
json j = 17u;
j.erase(j.cbegin());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayOneValidIteratorRemoveTest, Float)
{
json j = 23.42;
j.erase(j.begin());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayOneValidIteratorRemoveTest, FloatConst)
{
json j = 23.42;
j.erase(j.cbegin());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayOneInvalidIteratorRemoveTest, String)
{
json j = "foo";
EXPECT_THROW_MSG(j.erase(j.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.205] iterator out of range");
}
TEST(JsonElementNonArrayOneInvalidIteratorRemoveTest, StringConst)
{
json j = "bar";
EXPECT_THROW_MSG(j.erase(j.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.205] iterator out of range");
}
TEST(JsonElementNonArrayOneInvalidIteratorRemoveTest, Boolean)
{
json j = false;
EXPECT_THROW_MSG(j.erase(j.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.205] iterator out of range");
}
TEST(JsonElementNonArrayOneInvalidIteratorRemoveTest, BooleanConst)
{
json j = true;
EXPECT_THROW_MSG(j.erase(j.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.205] iterator out of range");
}
TEST(JsonElementNonArrayOneInvalidIteratorRemoveTest, Integer)
{
json j = 17;
EXPECT_THROW_MSG(j.erase(j.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.205] iterator out of range");
}
TEST(JsonElementNonArrayOneInvalidIteratorRemoveTest, IntegerConst)
{
json j = 17;
EXPECT_THROW_MSG(j.erase(j.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.205] iterator out of range");
}
TEST(JsonElementNonArrayOneInvalidIteratorRemoveTest, Unsigned)
{
json j = 17u;
EXPECT_THROW_MSG(j.erase(j.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.205] iterator out of range");
}
TEST(JsonElementNonArrayOneInvalidIteratorRemoveTest, UnsignedConst)
{
json j = 17u;
EXPECT_THROW_MSG(j.erase(j.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.205] iterator out of range");
}
TEST(JsonElementNonArrayOneInvalidIteratorRemoveTest, Float)
{
json j = 23.42;
EXPECT_THROW_MSG(j.erase(j.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.205] iterator out of range");
}
TEST(JsonElementNonArrayOneInvalidIteratorRemoveTest, FloatConst)
{
json j = 23.42;
EXPECT_THROW_MSG(j.erase(j.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.205] iterator out of range");
}
TEST(JsonElementNonArrayTwoValidIteratorRemoveTest, Null)
{
json j;
EXPECT_THROW_MSG(j.erase(j.begin(), j.end()), json::type_error,
"[json.exception.type_error.307] cannot use erase() with null");
}
TEST(JsonElementNonArrayTwoValidIteratorRemoveTest, NullConst)
{
json j;
EXPECT_THROW_MSG(j.erase(j.cbegin(), j.cend()), json::type_error,
"[json.exception.type_error.307] cannot use erase() with null");
}
TEST(JsonElementNonArrayTwoValidIteratorRemoveTest, String)
{
json j = "foo";
j.erase(j.begin(), j.end());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayTwoValidIteratorRemoveTest, StringConst)
{
json j = "bar";
j.erase(j.cbegin(), j.cend());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayTwoValidIteratorRemoveTest, Boolean)
{
json j = false;
j.erase(j.begin(), j.end());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayTwoValidIteratorRemoveTest, BooleanConst)
{
json j = true;
j.erase(j.cbegin(), j.cend());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayTwoValidIteratorRemoveTest, Integer)
{
json j = 17;
j.erase(j.begin(), j.end());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayTwoValidIteratorRemoveTest, IntegerConst)
{
json j = 17;
j.erase(j.cbegin(), j.cend());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayTwoValidIteratorRemoveTest, Unsigned)
{
json j = 17u;
j.erase(j.begin(), j.end());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayTwoValidIteratorRemoveTest, UnsignedConst)
{
json j = 17u;
j.erase(j.cbegin(), j.cend());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayTwoValidIteratorRemoveTest, Float)
{
json j = 23.42;
j.erase(j.begin(), j.end());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayTwoValidIteratorRemoveTest, FloatConst)
{
json j = 23.42;
j.erase(j.cbegin(), j.cend());
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonElementNonArrayTwoInvalidIteratorRemoveTest, String)
{
json j = "foo";
EXPECT_THROW_MSG(j.erase(j.end(), j.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
EXPECT_THROW_MSG(j.erase(j.begin(), j.begin()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
}
TEST(JsonElementNonArrayTwoInvalidIteratorRemoveTest, StringConst)
{
json j = "bar";
EXPECT_THROW_MSG(j.erase(j.cend(), j.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
EXPECT_THROW_MSG(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
}
TEST(JsonElementNonArrayTwoInvalidIteratorRemoveTest, Boolean)
{
json j = false;
EXPECT_THROW_MSG(j.erase(j.end(), j.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
EXPECT_THROW_MSG(j.erase(j.begin(), j.begin()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
}
TEST(JsonElementNonArrayTwoInvalidIteratorRemoveTest, BooleanConst)
{
json j = true;
EXPECT_THROW_MSG(j.erase(j.cend(), j.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
EXPECT_THROW_MSG(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
}
TEST(JsonElementNonArrayTwoInvalidIteratorRemoveTest, Integer)
{
json j = 17;
EXPECT_THROW_MSG(j.erase(j.end(), j.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
EXPECT_THROW_MSG(j.erase(j.begin(), j.begin()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
}
TEST(JsonElementNonArrayTwoInvalidIteratorRemoveTest, IntegerConst)
{
json j = 17;
EXPECT_THROW_MSG(j.erase(j.cend(), j.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
EXPECT_THROW_MSG(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
}
TEST(JsonElementNonArrayTwoInvalidIteratorRemoveTest, Unsigned)
{
json j = 17u;
EXPECT_THROW_MSG(j.erase(j.end(), j.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
EXPECT_THROW_MSG(j.erase(j.begin(), j.begin()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
}
TEST(JsonElementNonArrayTwoInvalidIteratorRemoveTest, UnsignedConst)
{
json j = 17u;
EXPECT_THROW_MSG(j.erase(j.cend(), j.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
EXPECT_THROW_MSG(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
}
TEST(JsonElementNonArrayTwoInvalidIteratorRemoveTest, Float)
{
json j = 23.42;
EXPECT_THROW_MSG(j.erase(j.end(), j.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
EXPECT_THROW_MSG(j.erase(j.begin(), j.begin()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
}
TEST(JsonElementNonArrayTwoInvalidIteratorRemoveTest, FloatConst)
{
json j = 23.42;
EXPECT_THROW_MSG(j.erase(j.cend(), j.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
EXPECT_THROW_MSG(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator,
"[json.exception.invalid_iterator.204] iterators out of range");
}

View File

@@ -0,0 +1,923 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
class JsonElementObjectAccessTestBase {
public:
JsonElementObjectAccessTestBase() : j_const(j) {}
protected:
json j = {{"integer", 1}, {"unsigned", 1u}, {"floating", 42.23}, {"null", nullptr}, {"string", "hello world"}, {"boolean", true}, {"object", json::object()}, {"array", {1, 2, 3}}};
const json j_const;
};
class JsonElementObjectAccessTest : public ::testing::Test,
public JsonElementObjectAccessTestBase {};
TEST_F(JsonElementObjectAccessTest, AtWithinBounds)
{
EXPECT_EQ(j.at("integer"), json(1));
EXPECT_EQ(j.at("unsigned"), json(1u));
EXPECT_EQ(j.at("boolean"), json(true));
EXPECT_EQ(j.at("null"), json(nullptr));
EXPECT_EQ(j.at("string"), json("hello world"));
EXPECT_EQ(j.at("floating"), json(42.23));
EXPECT_EQ(j.at("object"), json::object());
EXPECT_EQ(j.at("array"), json({1, 2, 3}));
EXPECT_EQ(j_const.at("integer"), json(1));
EXPECT_EQ(j_const.at("unsigned"), json(1u));
EXPECT_EQ(j_const.at("boolean"), json(true));
EXPECT_EQ(j_const.at("null"), json(nullptr));
EXPECT_EQ(j_const.at("string"), json("hello world"));
EXPECT_EQ(j_const.at("floating"), json(42.23));
EXPECT_EQ(j_const.at("object"), json::object());
EXPECT_EQ(j_const.at("array"), json({1, 2, 3}));
}
TEST_F(JsonElementObjectAccessTest, AtOutsideBounds)
{
EXPECT_THROW_MSG(j.at("foo"), json::out_of_range,
"[json.exception.out_of_range.403] key 'foo' not found");
EXPECT_THROW_MSG(j_const.at("foo"), json::out_of_range,
"[json.exception.out_of_range.403] key 'foo' not found");
}
TEST(JsonElementNonObjectAtAccessTest, Null)
{
json j_nonobject(json::value_t::null);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.at("foo"), json::type_error,
"[json.exception.type_error.304] cannot use at() with null");
EXPECT_THROW_MSG(j_nonobject_const.at("foo"), json::type_error,
"[json.exception.type_error.304] cannot use at() with null");
}
TEST(JsonElementNonObjectAtAccessTest, Boolean)
{
json j_nonobject(json::value_t::boolean);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.at("foo"), json::type_error,
"[json.exception.type_error.304] cannot use at() with boolean");
EXPECT_THROW_MSG(j_nonobject_const.at("foo"), json::type_error,
"[json.exception.type_error.304] cannot use at() with boolean");
}
TEST(JsonElementNonObjectAtAccessTest, String)
{
json j_nonobject(json::value_t::string);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.at("foo"), json::type_error,
"[json.exception.type_error.304] cannot use at() with string");
EXPECT_THROW_MSG(j_nonobject_const.at("foo"), json::type_error,
"[json.exception.type_error.304] cannot use at() with string");
}
TEST(JsonElementNonObjectAtAccessTest, Array)
{
json j_nonobject(json::value_t::array);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.at("foo"), json::type_error,
"[json.exception.type_error.304] cannot use at() with array");
EXPECT_THROW_MSG(j_nonobject_const.at("foo"), json::type_error,
"[json.exception.type_error.304] cannot use at() with array");
}
TEST(JsonElementNonObjectAtAccessTest, Integer)
{
json j_nonobject(json::value_t::number_integer);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.at("foo"), json::type_error,
"[json.exception.type_error.304] cannot use at() with number");
EXPECT_THROW_MSG(j_nonobject_const.at("foo"), json::type_error,
"[json.exception.type_error.304] cannot use at() with number");
}
TEST(JsonElementNonObjectAtAccessTest, Unsigned)
{
json j_nonobject(json::value_t::number_unsigned);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.at("foo"), json::type_error,
"[json.exception.type_error.304] cannot use at() with number");
EXPECT_THROW_MSG(j_nonobject_const.at("foo"), json::type_error,
"[json.exception.type_error.304] cannot use at() with number");
}
TEST(JsonElementNonObjectAtAccessTest, Float)
{
json j_nonobject(json::value_t::number_float);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.at("foo"), json::type_error,
"[json.exception.type_error.304] cannot use at() with number");
EXPECT_THROW_MSG(j_nonobject_const.at("foo"), json::type_error,
"[json.exception.type_error.304] cannot use at() with number");
}
TEST_F(JsonElementObjectAccessTest, KeyValueExist)
{
EXPECT_EQ(j.value("integer", 2), 1);
EXPECT_LT(std::fabs(j.value("integer", 1.0) - 1), 0.001);
EXPECT_EQ(j.value("unsigned", 2), 1);
EXPECT_LT(std::fabs(j.value("unsigned", 1.0) - 1), 0.001);
EXPECT_EQ(j.value("null", json(1)), json());
EXPECT_EQ(j.value("boolean", false), true);
EXPECT_EQ(j.value("string", "bar"), "hello world");
EXPECT_EQ(j.value("string", std::string("bar")), "hello world");
EXPECT_LT(std::fabs(j.value("floating", 12.34) - 42.23), 0.001);
EXPECT_EQ(j.value("floating", 12), 42);
EXPECT_EQ(j.value("object", json({{"foo", "bar"}})), json::object());
EXPECT_EQ(j.value("array", json({10, 100})), json({1, 2, 3}));
EXPECT_EQ(j_const.value("integer", 2), 1);
EXPECT_LT(std::fabs(j_const.value("integer", 1.0) - 1), 0.001);
EXPECT_EQ(j_const.value("unsigned", 2), 1);
EXPECT_LT(std::fabs(j_const.value("unsigned", 1.0) - 1), 0.001);
EXPECT_EQ(j_const.value("boolean", false), true);
EXPECT_EQ(j_const.value("string", "bar"), "hello world");
EXPECT_EQ(j_const.value("string", std::string("bar")), "hello world");
EXPECT_LT(std::fabs(j_const.value("floating", 12.34) - 42.23), 0.001);
EXPECT_EQ(j_const.value("floating", 12), 42);
EXPECT_EQ(j_const.value("object", json({{"foo", "bar"}})), json::object());
EXPECT_EQ(j_const.value("array", json({10, 100})), json({1, 2, 3}));
}
TEST_F(JsonElementObjectAccessTest, KeyValueNotExist)
{
EXPECT_EQ(j.value("_", 2), 2);
EXPECT_EQ(j.value("_", 2u), 2u);
EXPECT_EQ(j.value("_", false), false);
EXPECT_EQ(j.value("_", "bar"), "bar");
EXPECT_LT(std::fabs(j.value("_", 12.34) - 12.34), 0.001);
EXPECT_EQ(j.value("_", json({{"foo", "bar"}})), json({{"foo", "bar"}}));
EXPECT_EQ(j.value("_", json({10, 100})), json({10, 100}));
EXPECT_EQ(j_const.value("_", 2), 2);
EXPECT_EQ(j_const.value("_", 2u), 2u);
EXPECT_EQ(j_const.value("_", false), false);
EXPECT_EQ(j_const.value("_", "bar"), "bar");
EXPECT_LT(std::fabs(j_const.value("_", 12.34) - 12.34), 0.001);
EXPECT_EQ(j_const.value("_", json({{"foo", "bar"}})), json({{"foo", "bar"}}));
EXPECT_EQ(j_const.value("_", json({10, 100})), json({10, 100}));
}
TEST(JsonElementNonObjectKeyValueAccessTest, Null)
{
json j_nonobject(json::value_t::null);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.value("foo", 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with null");
EXPECT_THROW_MSG(j_nonobject_const.value("foo", 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with null");
}
TEST(JsonElementNonObjectKeyValueAccessTest, Boolean)
{
json j_nonobject(json::value_t::boolean);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.value("foo", 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with boolean");
EXPECT_THROW_MSG(j_nonobject_const.value("foo", 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with boolean");
}
TEST(JsonElementNonObjectKeyValueAccessTest, String)
{
json j_nonobject(json::value_t::string);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.value("foo", 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with string");
EXPECT_THROW_MSG(j_nonobject_const.value("foo", 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with string");
}
TEST(JsonElementNonObjectKeyValueAccessTest, Array)
{
json j_nonobject(json::value_t::array);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.value("foo", 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with array");
EXPECT_THROW_MSG(j_nonobject_const.value("foo", 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with array");
}
TEST(JsonElementNonObjectKeyValueAccessTest, Integer)
{
json j_nonobject(json::value_t::number_integer);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.value("foo", 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with number");
EXPECT_THROW_MSG(j_nonobject_const.value("foo", 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with number");
}
TEST(JsonElementNonObjectKeyValueAccessTest, Unsigned)
{
json j_nonobject(json::value_t::number_unsigned);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.value("foo", 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with number");
EXPECT_THROW_MSG(j_nonobject_const.value("foo", 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with number");
}
TEST(JsonElementNonObjectKeyValueAccessTest, Float)
{
json j_nonobject(json::value_t::number_float);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.value("foo", 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with number");
EXPECT_THROW_MSG(j_nonobject_const.value("foo", 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with number");
}
TEST_F(JsonElementObjectAccessTest, PointerValueExist)
{
EXPECT_EQ(j.value("/integer"_json_pointer, 2), 1);
EXPECT_LT(std::fabs(j.value("/integer"_json_pointer, 1.0) - 1), 0.001);
EXPECT_EQ(j.value("/unsigned"_json_pointer, 2), 1);
EXPECT_LT(std::fabs(j.value("/unsigned"_json_pointer, 1.0) - 1), 0.001);
EXPECT_EQ(j.value("/null"_json_pointer, json(1)), json());
EXPECT_EQ(j.value("/boolean"_json_pointer, false), true);
EXPECT_EQ(j.value("/string"_json_pointer, "bar"), "hello world");
EXPECT_EQ(j.value("/string"_json_pointer, std::string("bar")), "hello world");
EXPECT_LT(std::fabs(j.value("/floating"_json_pointer, 12.34) - 42.23), 0.001);
EXPECT_EQ(j.value("/floating"_json_pointer, 12), 42);
EXPECT_EQ(j.value("/object"_json_pointer, json({{"foo", "bar"}})), json::object());
EXPECT_EQ(j.value("/array"_json_pointer, json({10, 100})), json({1, 2, 3}));
EXPECT_EQ(j_const.value("/integer"_json_pointer, 2), 1);
EXPECT_LT(std::fabs(j_const.value("/integer"_json_pointer, 1.0) - 1), 0.001);
EXPECT_EQ(j_const.value("/unsigned"_json_pointer, 2), 1);
EXPECT_LT(std::fabs(j_const.value("/unsigned"_json_pointer, 1.0) - 1), 0.001);
EXPECT_EQ(j_const.value("/boolean"_json_pointer, false), true);
EXPECT_EQ(j_const.value("/string"_json_pointer, "bar"), "hello world");
EXPECT_EQ(j_const.value("/string"_json_pointer, std::string("bar")), "hello world");
EXPECT_LT(std::fabs(j_const.value("/floating"_json_pointer, 12.34) - 42.23), 0.001);
EXPECT_EQ(j_const.value("/floating"_json_pointer, 12), 42);
EXPECT_EQ(j_const.value("/object"_json_pointer, json({{"foo", "bar"}})), json::object());
EXPECT_EQ(j_const.value("/array"_json_pointer, json({10, 100})), json({1, 2, 3}));
}
TEST(JsonElementNonObjectPointerValueAccessTest, Null)
{
json j_nonobject(json::value_t::null);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.value("/foo"_json_pointer, 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with null");
EXPECT_THROW_MSG(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with null");
}
TEST(JsonElementNonObjectPointerValueAccessTest, Boolean)
{
json j_nonobject(json::value_t::boolean);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.value("/foo"_json_pointer, 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with boolean");
EXPECT_THROW_MSG(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with boolean");
}
TEST(JsonElementNonObjectPointerValueAccessTest, String)
{
json j_nonobject(json::value_t::string);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.value("/foo"_json_pointer, 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with string");
EXPECT_THROW_MSG(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with string");
}
TEST(JsonElementNonObjectPointerValueAccessTest, Array)
{
json j_nonobject(json::value_t::array);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.value("/foo"_json_pointer, 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with array");
EXPECT_THROW_MSG(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with array");
}
TEST(JsonElementNonObjectPointerValueAccessTest, Integer)
{
json j_nonobject(json::value_t::number_integer);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.value("/foo"_json_pointer, 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with number");
EXPECT_THROW_MSG(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with number");
}
TEST(JsonElementNonObjectPointerValueAccessTest, Unsigned)
{
json j_nonobject(json::value_t::number_unsigned);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.value("/foo"_json_pointer, 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with number");
EXPECT_THROW_MSG(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with number");
}
TEST(JsonElementNonObjectPointerValueAccessTest, Float)
{
json j_nonobject(json::value_t::number_float);
const json j_nonobject_const(j_nonobject);
EXPECT_THROW_MSG(j_nonobject.value("/foo"_json_pointer, 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with number");
EXPECT_THROW_MSG(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error,
"[json.exception.type_error.306] cannot use value() with number");
}
#if 0
TEST_F(JsonElementObjectAccessTest, FrontAndBack)
{
// "array" is the smallest key
EXPECT_EQ(j.front(), json({1, 2, 3}));
EXPECT_EQ(j_const.front(), json({1, 2, 3}));
// "unsigned" is the largest key
EXPECT_EQ(j.back(), json(1u));
EXPECT_EQ(j_const.back(), json(1u));
}
#endif
TEST_F(JsonElementObjectAccessTest, OperatorWithinBounds)
{
EXPECT_EQ(j["integer"], json(1));
EXPECT_EQ(j[json::object_t::key_type("integer")], j["integer"]);
EXPECT_EQ(j["unsigned"], json(1u));
EXPECT_EQ(j[json::object_t::key_type("unsigned")], j["unsigned"]);
EXPECT_EQ(j["boolean"], json(true));
EXPECT_EQ(j[json::object_t::key_type("boolean")], j["boolean"]);
EXPECT_EQ(j["null"], json(nullptr));
EXPECT_EQ(j[json::object_t::key_type("null")], j["null"]);
EXPECT_EQ(j["string"], json("hello world"));
EXPECT_EQ(j[json::object_t::key_type("string")], j["string"]);
EXPECT_EQ(j["floating"], json(42.23));
EXPECT_EQ(j[json::object_t::key_type("floating")], j["floating"]);
EXPECT_EQ(j["object"], json::object());
EXPECT_EQ(j[json::object_t::key_type("object")], j["object"]);
EXPECT_EQ(j["array"], json({1, 2, 3}));
EXPECT_EQ(j[json::object_t::key_type("array")], j["array"]);
EXPECT_EQ(j_const["integer"], json(1));
EXPECT_EQ(j_const[json::object_t::key_type("integer")], j["integer"]);
EXPECT_EQ(j_const["boolean"], json(true));
EXPECT_EQ(j_const[json::object_t::key_type("boolean")], j["boolean"]);
EXPECT_EQ(j_const["null"], json(nullptr));
EXPECT_EQ(j_const[json::object_t::key_type("null")], j["null"]);
EXPECT_EQ(j_const["string"], json("hello world"));
EXPECT_EQ(j_const[json::object_t::key_type("string")], j["string"]);
EXPECT_EQ(j_const["floating"], json(42.23));
EXPECT_EQ(j_const[json::object_t::key_type("floating")], j["floating"]);
EXPECT_EQ(j_const["object"], json::object());
EXPECT_EQ(j_const[json::object_t::key_type("object")], j["object"]);
EXPECT_EQ(j_const["array"], json({1, 2, 3}));
EXPECT_EQ(j_const[json::object_t::key_type("array")], j["array"]);
}
TEST(JsonElementNonObjectOperatorAccessTest, Null)
{
json j_nonobject(json::value_t::null);
json j_nonobject2(json::value_t::null);
const json j_const_nonobject(j_nonobject);
EXPECT_NO_THROW(j_nonobject["foo"]);
EXPECT_NO_THROW(j_nonobject2[json::object_t::key_type("foo")]);
EXPECT_THROW_MSG(j_const_nonobject["foo"], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with null");
EXPECT_THROW_MSG(j_const_nonobject[json::object_t::key_type("foo")], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with null");
}
TEST(JsonElementNonObjectOperatorAccessTest, Boolean)
{
json j_nonobject(json::value_t::boolean);
const json j_const_nonobject(j_nonobject);
EXPECT_THROW_MSG(j_nonobject["foo"], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with boolean");
EXPECT_THROW_MSG(j_nonobject[json::object_t::key_type("foo")], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with boolean");
EXPECT_THROW_MSG(j_const_nonobject["foo"], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with boolean");
EXPECT_THROW_MSG(j_const_nonobject[json::object_t::key_type("foo")], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with boolean");
}
TEST(JsonElementNonObjectOperatorAccessTest, String)
{
json j_nonobject(json::value_t::string);
const json j_const_nonobject(j_nonobject);
EXPECT_THROW_MSG(j_nonobject["foo"], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with string");
EXPECT_THROW_MSG(j_nonobject[json::object_t::key_type("foo")], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with string");
EXPECT_THROW_MSG(j_const_nonobject["foo"], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with string");
EXPECT_THROW_MSG(j_const_nonobject[json::object_t::key_type("foo")], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with string");
}
TEST(JsonElementNonObjectOperatorAccessTest, Array)
{
json j_nonobject(json::value_t::array);
const json j_const_nonobject(j_nonobject);
EXPECT_THROW_MSG(j_nonobject["foo"], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with array");
EXPECT_THROW_MSG(j_nonobject[json::object_t::key_type("foo")], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with array");
EXPECT_THROW_MSG(j_const_nonobject["foo"], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with array");
EXPECT_THROW_MSG(j_const_nonobject[json::object_t::key_type("foo")], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with array");
}
TEST(JsonElementNonObjectOperatorAccessTest, Integer)
{
json j_nonobject(json::value_t::number_integer);
const json j_const_nonobject(j_nonobject);
EXPECT_THROW_MSG(j_nonobject["foo"], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
EXPECT_THROW_MSG(j_nonobject[json::object_t::key_type("foo")], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
EXPECT_THROW_MSG(j_const_nonobject["foo"], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
EXPECT_THROW_MSG(j_const_nonobject[json::object_t::key_type("foo")], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
}
TEST(JsonElementNonObjectOperatorAccessTest, Unsigned)
{
json j_nonobject(json::value_t::number_unsigned);
const json j_const_nonobject(j_nonobject);
EXPECT_THROW_MSG(j_nonobject["foo"], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
EXPECT_THROW_MSG(j_nonobject[json::object_t::key_type("foo")], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
EXPECT_THROW_MSG(j_const_nonobject["foo"], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
EXPECT_THROW_MSG(j_const_nonobject[json::object_t::key_type("foo")], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
}
TEST(JsonElementNonObjectOperatorAccessTest, Float)
{
json j_nonobject(json::value_t::number_float);
const json j_const_nonobject(j_nonobject);
EXPECT_THROW_MSG(j_nonobject["foo"], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
EXPECT_THROW_MSG(j_nonobject[json::object_t::key_type("foo")], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
EXPECT_THROW_MSG(j_const_nonobject["foo"], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
EXPECT_THROW_MSG(j_const_nonobject[json::object_t::key_type("foo")], json::type_error,
"[json.exception.type_error.305] cannot use operator[] with number");
}
class JsonElementObjectRemoveTest : public ::testing::Test,
public JsonElementObjectAccessTestBase {};
TEST_F(JsonElementObjectRemoveTest, Key)
{
EXPECT_NE(j.find("integer"), j.end());
EXPECT_EQ(j.erase("integer"), 1u);
EXPECT_EQ(j.find("integer"), j.end());
EXPECT_EQ(j.erase("integer"), 0u);
EXPECT_NE(j.find("unsigned"), j.end());
EXPECT_EQ(j.erase("unsigned"), 1u);
EXPECT_EQ(j.find("unsigned"), j.end());
EXPECT_EQ(j.erase("unsigned"), 0u);
EXPECT_NE(j.find("boolean"), j.end());
EXPECT_EQ(j.erase("boolean"), 1u);
EXPECT_EQ(j.find("boolean"), j.end());
EXPECT_EQ(j.erase("boolean"), 0u);
EXPECT_NE(j.find("null"), j.end());
EXPECT_EQ(j.erase("null"), 1u);
EXPECT_EQ(j.find("null"), j.end());
EXPECT_EQ(j.erase("null"), 0u);
EXPECT_NE(j.find("string"), j.end());
EXPECT_EQ(j.erase("string"), 1u);
EXPECT_EQ(j.find("string"), j.end());
EXPECT_EQ(j.erase("string"), 0u);
EXPECT_NE(j.find("floating"), j.end());
EXPECT_EQ(j.erase("floating"), 1u);
EXPECT_EQ(j.find("floating"), j.end());
EXPECT_EQ(j.erase("floating"), 0u);
EXPECT_NE(j.find("object"), j.end());
EXPECT_EQ(j.erase("object"), 1u);
EXPECT_EQ(j.find("object"), j.end());
EXPECT_EQ(j.erase("object"), 0u);
EXPECT_NE(j.find("array"), j.end());
EXPECT_EQ(j.erase("array"), 1u);
EXPECT_EQ(j.find("array"), j.end());
EXPECT_EQ(j.erase("array"), 0u);
}
// erase(begin())
TEST_F(JsonElementObjectRemoveTest, Begin)
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
jobject.erase(jobject.begin());
EXPECT_EQ(jobject, json({{"b", 1}, {"c", 17u}}));
}
TEST_F(JsonElementObjectRemoveTest, BeginConst)
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
jobject.erase(jobject.cbegin());
EXPECT_EQ(jobject, json({{"b", 1}, {"c", 17u}}));
}
// erase(begin(), end())
TEST_F(JsonElementObjectRemoveTest, BeginEnd)
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
#if 0
json::iterator it2 = jobject.erase(jobject.begin(), jobject.end());
EXPECT_EQ(jobject, json::object());
EXPECT_EQ(it2, jobject.end());
#else
EXPECT_THROW(jobject.erase(jobject.begin(), jobject.end()), json::type_error);
#endif
}
TEST_F(JsonElementObjectRemoveTest, BeginEndConst)
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
#if 0
json::const_iterator it2 = jobject.erase(jobject.cbegin(), jobject.cend());
EXPECT_EQ(jobject, json::object());
EXPECT_EQ(it2, jobject.cend());
#else
EXPECT_THROW(jobject.erase(jobject.cbegin(), jobject.cend()), json::type_error);
#endif
}
TEST_F(JsonElementObjectRemoveTest, BeginBegin)
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
#if 0
json::iterator it2 = jobject.erase(jobject.begin(), jobject.begin());
EXPECT_EQ(jobject, json({{"a", "a"}, {"b", 1}, {"c", 17u}}));
EXPECT_EQ(*it2, json("a"));
#else
EXPECT_THROW(jobject.erase(jobject.begin(), jobject.end()), json::type_error);
#endif
}
TEST_F(JsonElementObjectRemoveTest, BeginBeginConst)
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
#if 0
json::const_iterator it2 = jobject.erase(jobject.cbegin(), jobject.cbegin());
EXPECT_EQ(jobject, json({{"a", "a"}, {"b", 1}, {"c", 17u}}));
EXPECT_EQ(*it2, json("a"));
#else
EXPECT_THROW(jobject.erase(jobject.cbegin(), jobject.cbegin()), json::type_error);
#endif
}
TEST_F(JsonElementObjectRemoveTest, Offset)
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
json::iterator it = jobject.find("b");
jobject.erase(it);
EXPECT_EQ(jobject, json({{"a", "a"}, {"c", 17u}}));
}
TEST_F(JsonElementObjectRemoveTest, OffsetConst)
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
json::const_iterator it = jobject.find("b");
jobject.erase(it);
EXPECT_EQ(jobject, json({{"a", "a"}, {"c", 17u}}));
}
TEST_F(JsonElementObjectRemoveTest, Subrange)
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
#if 0
json::iterator it2 = jobject.erase(jobject.find("b"), jobject.find("e"));
EXPECT_EQ(jobject, json({{"a", "a"}, {"e", true}}));
EXPECT_EQ(*it2, json(true));
#else
EXPECT_THROW(jobject.erase(jobject.find("b"), jobject.find("e")), json::type_error);
#endif
}
TEST_F(JsonElementObjectRemoveTest, SubrangeConst)
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
#if 0
json::const_iterator it2 = jobject.erase(jobject.find("b"), jobject.find("e"));
EXPECT_EQ(jobject, json({{"a", "a"}, {"e", true}}));
EXPECT_EQ(*it2, json(true));
#else
EXPECT_THROW(jobject.erase(jobject.find("b"), jobject.find("e")), json::type_error);
#endif
}
TEST_F(JsonElementObjectRemoveTest, Different)
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
EXPECT_THROW_MSG(jobject.erase(jobject2.begin()), json::invalid_iterator,
"[json.exception.invalid_iterator.202] iterator does not fit current value");
EXPECT_THROW_MSG(jobject.erase(jobject.begin(), jobject2.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.203] iterators do not fit current value");
EXPECT_THROW_MSG(jobject.erase(jobject2.begin(), jobject.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.203] iterators do not fit current value");
EXPECT_THROW_MSG(jobject.erase(jobject2.begin(), jobject2.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.203] iterators do not fit current value");
}
TEST_F(JsonElementObjectRemoveTest, DifferentConst)
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
EXPECT_THROW_MSG(jobject.erase(jobject2.cbegin()), json::invalid_iterator,
"[json.exception.invalid_iterator.202] iterator does not fit current value");
EXPECT_THROW_MSG(jobject.erase(jobject.cbegin(), jobject2.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.203] iterators do not fit current value");
EXPECT_THROW_MSG(jobject.erase(jobject2.cbegin(), jobject.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.203] iterators do not fit current value");
EXPECT_THROW_MSG(jobject.erase(jobject2.cbegin(), jobject2.cend()), json::invalid_iterator,
"[json.exception.invalid_iterator.203] iterators do not fit current value");
}
// remove element by key in non-object type
TEST(JsonElementNonObjectKeyRemoveTest, Null)
{
json j_nonobject(json::value_t::null);
EXPECT_THROW_MSG(j_nonobject.erase("foo"), json::type_error,
"[json.exception.type_error.307] cannot use erase() with null");
}
TEST(JsonElementNonObjectKeyRemoveTest, Boolean)
{
json j_nonobject(json::value_t::boolean);
EXPECT_THROW_MSG(j_nonobject.erase("foo"), json::type_error,
"[json.exception.type_error.307] cannot use erase() with boolean");
}
TEST(JsonElementNonObjectKeyRemoveTest, String)
{
json j_nonobject(json::value_t::string);
EXPECT_THROW_MSG(j_nonobject.erase("foo"), json::type_error,
"[json.exception.type_error.307] cannot use erase() with string");
}
TEST(JsonElementNonObjectKeyRemoveTest, Array)
{
json j_nonobject(json::value_t::array);
EXPECT_THROW_MSG(j_nonobject.erase("foo"), json::type_error,
"[json.exception.type_error.307] cannot use erase() with array");
}
TEST(JsonElementNonObjectKeyRemoveTest, Integer)
{
json j_nonobject(json::value_t::number_integer);
EXPECT_THROW_MSG(j_nonobject.erase("foo"), json::type_error,
"[json.exception.type_error.307] cannot use erase() with number");
}
TEST(JsonElementNonObjectKeyRemoveTest, Float)
{
json j_nonobject(json::value_t::number_float);
EXPECT_THROW_MSG(j_nonobject.erase("foo"), json::type_error,
"[json.exception.type_error.307] cannot use erase() with number");
}
TEST_F(JsonElementObjectAccessTest, FindExist)
{
for (auto key :
{"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
})
{
EXPECT_NE(j.find(key), j.end());
EXPECT_EQ(*j.find(key), j.at(key));
EXPECT_NE(j_const.find(key), j_const.end());
EXPECT_EQ(*j_const.find(key), j_const.at(key));
}
}
TEST_F(JsonElementObjectAccessTest, FindNotExist)
{
EXPECT_EQ(j.find("foo"), j.end());
EXPECT_EQ(j_const.find("foo"), j_const.end());
}
TEST(JsonElementNonObjectFindAccessTest, Null)
{
json j_nonarray(json::value_t::null);
const json j_nonarray_const(j_nonarray);
EXPECT_EQ(j_nonarray.find("foo"), j_nonarray.end());
EXPECT_EQ(j_nonarray_const.find("foo"), j_nonarray_const.end());
}
TEST(JsonElementNonObjectFindAccessTest, String)
{
json j_nonarray(json::value_t::string);
const json j_nonarray_const(j_nonarray);
EXPECT_EQ(j_nonarray.find("foo"), j_nonarray.end());
EXPECT_EQ(j_nonarray_const.find("foo"), j_nonarray_const.end());
}
TEST(JsonElementNonObjectFindAccessTest, Object)
{
json j_nonarray(json::value_t::object);
const json j_nonarray_const(j_nonarray);
EXPECT_EQ(j_nonarray.find("foo"), j_nonarray.end());
EXPECT_EQ(j_nonarray_const.find("foo"), j_nonarray_const.end());
}
TEST(JsonElementNonObjectFindAccessTest, Array)
{
json j_nonarray(json::value_t::array);
const json j_nonarray_const(j_nonarray);
EXPECT_EQ(j_nonarray.find("foo"), j_nonarray.end());
EXPECT_EQ(j_nonarray_const.find("foo"), j_nonarray_const.end());
}
TEST(JsonElementNonObjectFindAccessTest, Boolean)
{
json j_nonarray(json::value_t::boolean);
const json j_nonarray_const(j_nonarray);
EXPECT_EQ(j_nonarray.find("foo"), j_nonarray.end());
EXPECT_EQ(j_nonarray_const.find("foo"), j_nonarray_const.end());
}
TEST(JsonElementNonObjectFindAccessTest, Integer)
{
json j_nonarray(json::value_t::number_integer);
const json j_nonarray_const(j_nonarray);
EXPECT_EQ(j_nonarray.find("foo"), j_nonarray.end());
EXPECT_EQ(j_nonarray_const.find("foo"), j_nonarray_const.end());
}
TEST(JsonElementNonObjectFindAccessTest, Unsigned)
{
json j_nonarray(json::value_t::number_unsigned);
const json j_nonarray_const(j_nonarray);
EXPECT_EQ(j_nonarray.find("foo"), j_nonarray.end());
EXPECT_EQ(j_nonarray_const.find("foo"), j_nonarray_const.end());
}
TEST(JsonElementNonObjectFindAccessTest, Float)
{
json j_nonarray(json::value_t::number_float);
const json j_nonarray_const(j_nonarray);
EXPECT_EQ(j_nonarray.find("foo"), j_nonarray.end());
EXPECT_EQ(j_nonarray_const.find("foo"), j_nonarray_const.end());
}
TEST_F(JsonElementObjectAccessTest, CountExist)
{
for (auto key :
{"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
})
{
EXPECT_EQ(j.count(key), 1u);
EXPECT_EQ(j_const.count(key), 1u);
}
}
TEST_F(JsonElementObjectAccessTest, CountNotExist)
{
EXPECT_EQ(j.count("foo"), 0u);
EXPECT_EQ(j_const.count("foo"), 0u);
}
TEST(JsonElementNonObjectCountAccessTest, Null)
{
json j_nonobject(json::value_t::null);
const json j_nonobject_const(j_nonobject);
EXPECT_EQ(j_nonobject.count("foo"), 0u);
EXPECT_EQ(j_nonobject_const.count("foo"), 0u);
}
TEST(JsonElementNonObjectCountAccessTest, String)
{
json j_nonobject(json::value_t::string);
const json j_nonobject_const(j_nonobject);
EXPECT_EQ(j_nonobject.count("foo"), 0u);
EXPECT_EQ(j_nonobject_const.count("foo"), 0u);
}
TEST(JsonElementNonObjectCountAccessTest, Object)
{
json j_nonobject(json::value_t::object);
const json j_nonobject_const(j_nonobject);
EXPECT_EQ(j_nonobject.count("foo"), 0u);
EXPECT_EQ(j_nonobject_const.count("foo"), 0u);
}
TEST(JsonElementNonObjectCountAccessTest, Array)
{
json j_nonobject(json::value_t::array);
const json j_nonobject_const(j_nonobject);
EXPECT_EQ(j_nonobject.count("foo"), 0u);
EXPECT_EQ(j_nonobject_const.count("foo"), 0u);
}
TEST(JsonElementNonObjectCountAccessTest, Boolean)
{
json j_nonobject(json::value_t::boolean);
const json j_nonobject_const(j_nonobject);
EXPECT_EQ(j_nonobject.count("foo"), 0u);
EXPECT_EQ(j_nonobject_const.count("foo"), 0u);
}
TEST(JsonElementNonObjectCountAccessTest, Integer)
{
json j_nonobject(json::value_t::number_integer);
const json j_nonobject_const(j_nonobject);
EXPECT_EQ(j_nonobject.count("foo"), 0u);
EXPECT_EQ(j_nonobject_const.count("foo"), 0u);
}
TEST(JsonElementNonObjectCountAccessTest, Unsigned)
{
json j_nonobject(json::value_t::number_unsigned);
const json j_nonobject_const(j_nonobject);
EXPECT_EQ(j_nonobject.count("foo"), 0u);
EXPECT_EQ(j_nonobject_const.count("foo"), 0u);
}
TEST(JsonElementNonObjectCountAccessTest, Float)
{
json j_nonobject(json::value_t::number_float);
const json j_nonobject_const(j_nonobject);
EXPECT_EQ(j_nonobject.count("foo"), 0u);
EXPECT_EQ(j_nonobject_const.count("foo"), 0u);
}
TEST_F(JsonElementObjectAccessTest, PointerValueNotExist)
{
EXPECT_EQ(j.value("/not/existing"_json_pointer, 2), 2);
EXPECT_EQ(j.value("/not/existing"_json_pointer, 2u), 2u);
EXPECT_EQ(j.value("/not/existing"_json_pointer, false), false);
EXPECT_EQ(j.value("/not/existing"_json_pointer, "bar"), "bar");
EXPECT_LT(std::fabs(j.value("/not/existing"_json_pointer, 12.34) - 12.34), 0.001);
EXPECT_EQ(j.value("/not/existing"_json_pointer, json({{"foo", "bar"}})), json({{"foo", "bar"}}));
EXPECT_EQ(j.value("/not/existing"_json_pointer, json({10, 100})), json({10, 100}));
EXPECT_EQ(j_const.value("/not/existing"_json_pointer, 2), 2);
EXPECT_EQ(j_const.value("/not/existing"_json_pointer, 2u), 2u);
EXPECT_EQ(j_const.value("/not/existing"_json_pointer, false), false);
EXPECT_EQ(j_const.value("/not/existing"_json_pointer, "bar"), "bar");
EXPECT_LT(std::fabs(j_const.value("/not/existing"_json_pointer, 12.34) - 12.34), 0.001);
EXPECT_EQ(j_const.value("/not/existing"_json_pointer, json({{"foo", "bar"}})), json({{"foo", "bar"}}));
EXPECT_EQ(j_const.value("/not/existing"_json_pointer, json({10, 100})), json({10, 100}));
}

View File

@@ -0,0 +1,385 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
TEST(JsonConvTypeCheckTest, Object)
{
json j {{"foo", 1}, {"bar", false}};
EXPECT_FALSE(j.is_null());
EXPECT_FALSE(j.is_boolean());
EXPECT_FALSE(j.is_number());
EXPECT_FALSE(j.is_number_integer());
EXPECT_FALSE(j.is_number_unsigned());
EXPECT_FALSE(j.is_number_float());
EXPECT_TRUE(j.is_object());
EXPECT_FALSE(j.is_array());
EXPECT_FALSE(j.is_string());
EXPECT_FALSE(j.is_discarded());
EXPECT_FALSE(j.is_primitive());
EXPECT_TRUE(j.is_structured());
}
TEST(JsonConvTypeCheckTest, Array)
{
json j {"foo", 1, 1u, 42.23, false};
EXPECT_FALSE(j.is_null());
EXPECT_FALSE(j.is_boolean());
EXPECT_FALSE(j.is_number());
EXPECT_FALSE(j.is_number_integer());
EXPECT_FALSE(j.is_number_unsigned());
EXPECT_FALSE(j.is_number_float());
EXPECT_FALSE(j.is_object());
EXPECT_TRUE(j.is_array());
EXPECT_FALSE(j.is_string());
EXPECT_FALSE(j.is_discarded());
EXPECT_FALSE(j.is_primitive());
EXPECT_TRUE(j.is_structured());
}
TEST(JsonConvTypeCheckTest, Null)
{
json j(nullptr);
EXPECT_TRUE(j.is_null());
EXPECT_FALSE(j.is_boolean());
EXPECT_FALSE(j.is_number());
EXPECT_FALSE(j.is_number_integer());
EXPECT_FALSE(j.is_number_unsigned());
EXPECT_FALSE(j.is_number_float());
EXPECT_FALSE(j.is_object());
EXPECT_FALSE(j.is_array());
EXPECT_FALSE(j.is_string());
EXPECT_FALSE(j.is_discarded());
EXPECT_TRUE(j.is_primitive());
EXPECT_FALSE(j.is_structured());
}
TEST(JsonConvTypeCheckTest, Boolean)
{
json j(true);
EXPECT_FALSE(j.is_null());
EXPECT_TRUE(j.is_boolean());
EXPECT_FALSE(j.is_number());
EXPECT_FALSE(j.is_number_integer());
EXPECT_FALSE(j.is_number_unsigned());
EXPECT_FALSE(j.is_number_float());
EXPECT_FALSE(j.is_object());
EXPECT_FALSE(j.is_array());
EXPECT_FALSE(j.is_string());
EXPECT_FALSE(j.is_discarded());
EXPECT_TRUE(j.is_primitive());
EXPECT_FALSE(j.is_structured());
}
TEST(JsonConvTypeCheckTest, String)
{
json j("Hello world");
EXPECT_FALSE(j.is_null());
EXPECT_FALSE(j.is_boolean());
EXPECT_FALSE(j.is_number());
EXPECT_FALSE(j.is_number_integer());
EXPECT_FALSE(j.is_number_unsigned());
EXPECT_FALSE(j.is_number_float());
EXPECT_FALSE(j.is_object());
EXPECT_FALSE(j.is_array());
EXPECT_TRUE(j.is_string());
EXPECT_FALSE(j.is_discarded());
EXPECT_TRUE(j.is_primitive());
EXPECT_FALSE(j.is_structured());
}
TEST(JsonConvTypeCheckTest, Integer)
{
json j(42);
EXPECT_FALSE(j.is_null());
EXPECT_FALSE(j.is_boolean());
EXPECT_TRUE(j.is_number());
EXPECT_TRUE(j.is_number_integer());
EXPECT_FALSE(j.is_number_unsigned());
EXPECT_FALSE(j.is_number_float());
EXPECT_FALSE(j.is_object());
EXPECT_FALSE(j.is_array());
EXPECT_FALSE(j.is_string());
EXPECT_FALSE(j.is_discarded());
EXPECT_TRUE(j.is_primitive());
EXPECT_FALSE(j.is_structured());
}
TEST(JsonConvTypeCheckTest, Unsigned)
{
json j(42u);
EXPECT_FALSE(j.is_null());
EXPECT_FALSE(j.is_boolean());
EXPECT_TRUE(j.is_number());
EXPECT_TRUE(j.is_number_integer());
EXPECT_TRUE(j.is_number_unsigned());
EXPECT_FALSE(j.is_number_float());
EXPECT_FALSE(j.is_object());
EXPECT_FALSE(j.is_array());
EXPECT_FALSE(j.is_string());
EXPECT_FALSE(j.is_discarded());
EXPECT_TRUE(j.is_primitive());
EXPECT_FALSE(j.is_structured());
}
TEST(JsonConvTypeCheckTest, Float)
{
json j(42.23);
EXPECT_FALSE(j.is_null());
EXPECT_FALSE(j.is_boolean());
EXPECT_TRUE(j.is_number());
EXPECT_FALSE(j.is_number_integer());
EXPECT_FALSE(j.is_number_unsigned());
EXPECT_TRUE(j.is_number_float());
EXPECT_FALSE(j.is_object());
EXPECT_FALSE(j.is_array());
EXPECT_FALSE(j.is_string());
EXPECT_FALSE(j.is_discarded());
EXPECT_TRUE(j.is_primitive());
EXPECT_FALSE(j.is_structured());
}
TEST(JsonConvTypeCheckTest, Discarded)
{
json j(json::value_t::discarded);
EXPECT_FALSE(j.is_null());
EXPECT_FALSE(j.is_boolean());
EXPECT_FALSE(j.is_number());
EXPECT_FALSE(j.is_number_integer());
EXPECT_FALSE(j.is_number_unsigned());
EXPECT_FALSE(j.is_number_float());
EXPECT_FALSE(j.is_object());
EXPECT_FALSE(j.is_array());
EXPECT_FALSE(j.is_string());
EXPECT_TRUE(j.is_discarded());
EXPECT_FALSE(j.is_primitive());
EXPECT_FALSE(j.is_structured());
}
class JsonConvSerializationTest : public ::testing::Test {
protected:
json j {{"object", json::object()}, {"array", {1, 2, 3, 4}}, {"number", 42}, {"boolean", false}, {"null", nullptr}, {"string", "Hello world"} };
};
#if 0
// no indent / indent=-1
TEST_F(JsonConvSerializationTest, NoIndent)
{
EXPECT_EQ(j.dump(),
"{\"array\":[1,2,3,4],\"boolean\":false,\"null\":null,\"number\":42,\"object\":{},\"string\":\"Hello world\"}");
EXPECT_EQ(j.dump(), j.dump(-1));
}
// indent=0
TEST_F(JsonConvSerializationTest, Indent0)
{
EXPECT_EQ(j.dump(0),
"{\n\"array\": [\n1,\n2,\n3,\n4\n],\n\"boolean\": false,\n\"null\": null,\n\"number\": 42,\n\"object\": {},\n\"string\": \"Hello world\"\n}");
}
// indent=1, space='\t'
TEST_F(JsonConvSerializationTest, Indent1)
{
EXPECT_EQ(j.dump(1, '\t'),
"{\n\t\"array\": [\n\t\t1,\n\t\t2,\n\t\t3,\n\t\t4\n\t],\n\t\"boolean\": false,\n\t\"null\": null,\n\t\"number\": 42,\n\t\"object\": {},\n\t\"string\": \"Hello world\"\n}");
}
// indent=4
TEST_F(JsonConvSerializationTest, Indent4)
{
EXPECT_EQ(j.dump(4),
"{\n \"array\": [\n 1,\n 2,\n 3,\n 4\n ],\n \"boolean\": false,\n \"null\": null,\n \"number\": 42,\n \"object\": {},\n \"string\": \"Hello world\"\n}");
}
#endif
// indent=x
TEST_F(JsonConvSerializationTest, IndentX)
{
EXPECT_EQ(j.dump().size(), 94u);
EXPECT_EQ(j.dump(1).size(), 127u);
EXPECT_EQ(j.dump(2).size(), 142u);
EXPECT_EQ(j.dump(512).size(), 7792u);
}
// dump and floating-point numbers
TEST_F(JsonConvSerializationTest, Float)
{
auto s = json(42.23).dump();
EXPECT_NE(s.find("42.23"), std::string::npos);
}
// dump and small floating-point numbers
TEST_F(JsonConvSerializationTest, SmallFloat)
{
auto s = json(1.23456e-78).dump();
EXPECT_NE(s.find("1.23456e-78"), std::string::npos);
}
// dump and non-ASCII characters
TEST_F(JsonConvSerializationTest, NonAscii)
{
EXPECT_EQ(json("ä").dump(), "\"ä\"");
EXPECT_EQ(json("Ö").dump(), "\"Ö\"");
EXPECT_EQ(json("❤️").dump(), "\"❤️\"");
}
// serialization of discarded element
TEST_F(JsonConvSerializationTest, Discarded)
{
json j_discarded(json::value_t::discarded);
EXPECT_EQ(j_discarded.dump(), "<discarded>");
}
TEST(JsonConvRoundTripTest, Case)
{
for (const auto& s :
{"3.141592653589793", "1000000000000000010E5"
})
{
SCOPED_TRACE(s);
json j1 = json::parse(s);
std::string s1 = j1.dump();
json j2 = json::parse(s1);
std::string s2 = j2.dump();
EXPECT_EQ(s1, s2);
}
}
// return the type of the object (explicit)
TEST(JsonConvTypeExplicitTest, Null)
{
json j = nullptr;
EXPECT_EQ(j.type(), json::value_t::null);
}
TEST(JsonConvTypeExplicitTest, Object)
{
json j = {{"foo", "bar"}};
EXPECT_EQ(j.type(), json::value_t::object);
}
TEST(JsonConvTypeExplicitTest, Array)
{
json j = {1, 2, 3, 4};
EXPECT_EQ(j.type(), json::value_t::array);
}
TEST(JsonConvTypeExplicitTest, Boolean)
{
json j = true;
EXPECT_EQ(j.type(), json::value_t::boolean);
}
TEST(JsonConvTypeExplicitTest, String)
{
json j = "Hello world";
EXPECT_EQ(j.type(), json::value_t::string);
}
TEST(JsonConvTypeExplicitTest, Integer)
{
json j = 23;
EXPECT_EQ(j.type(), json::value_t::number_integer);
}
TEST(JsonConvTypeExplicitTest, Unsigned)
{
json j = 23u;
EXPECT_EQ(j.type(), json::value_t::number_unsigned);
}
TEST(JsonConvTypeExplicitTest, Float)
{
json j = 42.23;
EXPECT_EQ(j.type(), json::value_t::number_float);
}
// return the type of the object (implicit)
TEST(JsonConvTypeImplicitTest, Null)
{
json j = nullptr;
json::value_t t = j;
EXPECT_EQ(t, j.type());
}
TEST(JsonConvTypeImplicitTest, Object)
{
json j = {{"foo", "bar"}};
json::value_t t = j;
EXPECT_EQ(t, j.type());
}
TEST(JsonConvTypeImplicitTest, Array)
{
json j = {1, 2, 3, 4};
json::value_t t = j;
EXPECT_EQ(t, j.type());
}
TEST(JsonConvTypeImplicitTest, Boolean)
{
json j = true;
json::value_t t = j;
EXPECT_EQ(t, j.type());
}
TEST(JsonConvTypeImplicitTest, String)
{
json j = "Hello world";
json::value_t t = j;
EXPECT_EQ(t, j.type());
}
TEST(JsonConvTypeImplicitTest, Integer)
{
json j = 23;
json::value_t t = j;
EXPECT_EQ(t, j.type());
}
TEST(JsonConvTypeImplicitTest, Unsigned)
{
json j = 23u;
json::value_t t = j;
EXPECT_EQ(t, j.type());
}
TEST(JsonConvTypeImplicitTest, Float)
{
json j = 42.23;
json::value_t t = j;
EXPECT_EQ(t, j.type());
}

View File

@@ -0,0 +1,745 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
class JsonIteratorWrapperObjectTest : public ::testing::Test {
protected:
json j = {{"A", 1}, {"B", 2}};
};
TEST_F(JsonIteratorWrapperObjectTest, Value)
{
int counter = 1;
for (auto i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "A");
EXPECT_EQ(i.value(), json(1));
break;
}
case 2:
{
EXPECT_EQ(i.key(), "B");
EXPECT_EQ(i.value(), json(2));
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
}
TEST_F(JsonIteratorWrapperObjectTest, Reference)
{
int counter = 1;
for (auto& i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "A");
EXPECT_EQ(i.value(), json(1));
// change the value
i.value() = json(11);
EXPECT_EQ(i.value(), json(11));
break;
}
case 2:
{
EXPECT_EQ(i.key(), "B");
EXPECT_EQ(i.value(), json(2));
// change the value
i.value() = json(22);
EXPECT_EQ(i.value(), json(22));
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
// check if values where changed
EXPECT_EQ(j, json({{"A", 11}, {"B", 22}}));
}
TEST_F(JsonIteratorWrapperObjectTest, ConstValue)
{
int counter = 1;
for (const auto i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "A");
EXPECT_EQ(i.value(), json(1));
break;
}
case 2:
{
EXPECT_EQ(i.key(), "B");
EXPECT_EQ(i.value(), json(2));
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
}
TEST_F(JsonIteratorWrapperObjectTest, ConstReference)
{
json j = {{"A", 1}, {"B", 2}};
int counter = 1;
for (const auto& i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "A");
EXPECT_EQ(i.value(), json(1));
break;
}
case 2:
{
EXPECT_EQ(i.key(), "B");
EXPECT_EQ(i.value(), json(2));
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
}
class JsonIteratorWrapperConstObjectTest : public ::testing::Test {
protected:
const json j = {{"A", 1}, {"B", 2}};
};
TEST_F(JsonIteratorWrapperConstObjectTest, Value)
{
int counter = 1;
for (auto i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "A");
EXPECT_EQ(i.value(), json(1));
break;
}
case 2:
{
EXPECT_EQ(i.key(), "B");
EXPECT_EQ(i.value(), json(2));
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
}
TEST_F(JsonIteratorWrapperConstObjectTest, Reference)
{
int counter = 1;
for (auto& i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "A");
EXPECT_EQ(i.value(), json(1));
break;
}
case 2:
{
EXPECT_EQ(i.key(), "B");
EXPECT_EQ(i.value(), json(2));
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
}
TEST_F(JsonIteratorWrapperConstObjectTest, ConstValue)
{
int counter = 1;
for (const auto i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "A");
EXPECT_EQ(i.value(), json(1));
break;
}
case 2:
{
EXPECT_EQ(i.key(), "B");
EXPECT_EQ(i.value(), json(2));
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
}
TEST_F(JsonIteratorWrapperConstObjectTest, ConstReference)
{
int counter = 1;
for (const auto& i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "A");
EXPECT_EQ(i.value(), json(1));
break;
}
case 2:
{
EXPECT_EQ(i.key(), "B");
EXPECT_EQ(i.value(), json(2));
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
}
class JsonIteratorWrapperArrayTest : public ::testing::Test {
protected:
json j = {"A", "B"};
};
TEST_F(JsonIteratorWrapperArrayTest, Value)
{
int counter = 1;
for (auto i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "0");
EXPECT_EQ(i.value(), "A");
break;
}
case 2:
{
EXPECT_EQ(i.key(), "1");
EXPECT_EQ(i.value(), "B");
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
}
TEST_F(JsonIteratorWrapperArrayTest, Reference)
{
int counter = 1;
for (auto& i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "0");
EXPECT_EQ(i.value(), "A");
// change the value
i.value() = "AA";
EXPECT_EQ(i.value(), "AA");
break;
}
case 2:
{
EXPECT_EQ(i.key(), "1");
EXPECT_EQ(i.value(), "B");
// change the value
i.value() = "BB";
EXPECT_EQ(i.value(), "BB");
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
// check if values where changed
EXPECT_EQ(j, json({"AA", "BB"}));
}
TEST_F(JsonIteratorWrapperArrayTest, ConstValue)
{
int counter = 1;
for (const auto i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "0");
EXPECT_EQ(i.value(), "A");
break;
}
case 2:
{
EXPECT_EQ(i.key(), "1");
EXPECT_EQ(i.value(), "B");
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
}
TEST_F(JsonIteratorWrapperArrayTest, ConstReference)
{
int counter = 1;
for (const auto& i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "0");
EXPECT_EQ(i.value(), "A");
break;
}
case 2:
{
EXPECT_EQ(i.key(), "1");
EXPECT_EQ(i.value(), "B");
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
}
class JsonIteratorWrapperConstArrayTest : public ::testing::Test {
protected:
const json j = {"A", "B"};
};
TEST_F(JsonIteratorWrapperConstArrayTest, Value)
{
int counter = 1;
for (auto i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "0");
EXPECT_EQ(i.value(), "A");
break;
}
case 2:
{
EXPECT_EQ(i.key(), "1");
EXPECT_EQ(i.value(), "B");
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
}
TEST_F(JsonIteratorWrapperConstArrayTest, Reference)
{
int counter = 1;
for (auto& i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "0");
EXPECT_EQ(i.value(), "A");
break;
}
case 2:
{
EXPECT_EQ(i.key(), "1");
EXPECT_EQ(i.value(), "B");
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
}
TEST_F(JsonIteratorWrapperConstArrayTest, ConstValue)
{
int counter = 1;
for (const auto i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "0");
EXPECT_EQ(i.value(), "A");
break;
}
case 2:
{
EXPECT_EQ(i.key(), "1");
EXPECT_EQ(i.value(), "B");
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
}
TEST_F(JsonIteratorWrapperConstArrayTest, ConstReference)
{
int counter = 1;
for (const auto& i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
switch (counter++)
{
case 1:
{
EXPECT_EQ(i.key(), "0");
EXPECT_EQ(i.value(), "A");
break;
}
case 2:
{
EXPECT_EQ(i.key(), "1");
EXPECT_EQ(i.value(), "B");
break;
}
default:
{
break;
}
}
}
EXPECT_EQ(counter, 3);
}
class JsonIteratorWrapperPrimitiveTest : public ::testing::Test {
protected:
json j = 1;
};
TEST_F(JsonIteratorWrapperPrimitiveTest, Value)
{
int counter = 1;
for (auto i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
++counter;
EXPECT_EQ(i.key(), "");
EXPECT_EQ(i.value(), json(1));
}
EXPECT_EQ(counter, 2);
}
TEST_F(JsonIteratorWrapperPrimitiveTest, Reference)
{
int counter = 1;
for (auto& i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
++counter;
EXPECT_EQ(i.key(), "");
EXPECT_EQ(i.value(), json(1));
// change value
i.value() = json(2);
}
EXPECT_EQ(counter, 2);
// check if value has changed
EXPECT_EQ(j, json(2));
}
TEST_F(JsonIteratorWrapperPrimitiveTest, ConstValue)
{
int counter = 1;
for (const auto i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
++counter;
EXPECT_EQ(i.key(), "");
EXPECT_EQ(i.value(), json(1));
}
EXPECT_EQ(counter, 2);
}
TEST_F(JsonIteratorWrapperPrimitiveTest, ConstReference)
{
int counter = 1;
for (const auto& i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
++counter;
EXPECT_EQ(i.key(), "");
EXPECT_EQ(i.value(), json(1));
}
EXPECT_EQ(counter, 2);
}
class JsonIteratorWrapperConstPrimitiveTest : public ::testing::Test {
protected:
const json j = 1;
};
TEST_F(JsonIteratorWrapperConstPrimitiveTest, Value)
{
int counter = 1;
for (auto i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
++counter;
EXPECT_EQ(i.key(), "");
EXPECT_EQ(i.value(), json(1));
}
EXPECT_EQ(counter, 2);
}
TEST_F(JsonIteratorWrapperConstPrimitiveTest, Reference)
{
int counter = 1;
for (auto& i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
++counter;
EXPECT_EQ(i.key(), "");
EXPECT_EQ(i.value(), json(1));
}
EXPECT_EQ(counter, 2);
}
TEST_F(JsonIteratorWrapperConstPrimitiveTest, ConstValue)
{
int counter = 1;
for (const auto i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
++counter;
EXPECT_EQ(i.key(), "");
EXPECT_EQ(i.value(), json(1));
}
EXPECT_EQ(counter, 2);
}
TEST_F(JsonIteratorWrapperConstPrimitiveTest, ConstReference)
{
int counter = 1;
for (const auto& i : json::iterator_wrapper(j))
{
SCOPED_TRACE(counter);
++counter;
EXPECT_EQ(i.key(), "");
EXPECT_EQ(i.value(), json(1));
}
EXPECT_EQ(counter, 2);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,899 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
TEST(JsonIteratorTest, Comparisons)
{
json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
for (json& j : j_values)
{
SCOPED_TRACE(j.dump());
auto it1 = j.begin();
auto it2 = j.begin();
auto it3 = j.begin();
++it2;
++it3;
++it3;
auto it1_c = j.cbegin();
auto it2_c = j.cbegin();
auto it3_c = j.cbegin();
++it2_c;
++it3_c;
++it3_c;
// comparison: equal
{
EXPECT_TRUE(it1 == it1);
EXPECT_FALSE(it1 == it2);
EXPECT_FALSE(it1 == it3);
EXPECT_FALSE(it2 == it3);
EXPECT_TRUE(it1_c == it1_c);
EXPECT_FALSE(it1_c == it2_c);
EXPECT_FALSE(it1_c == it3_c);
EXPECT_FALSE(it2_c == it3_c);
}
// comparison: not equal
{
// check definition
EXPECT_EQ( (it1 != it1), !(it1 == it1) );
EXPECT_EQ( (it1 != it2), !(it1 == it2) );
EXPECT_EQ( (it1 != it3), !(it1 == it3) );
EXPECT_EQ( (it2 != it3), !(it2 == it3) );
EXPECT_EQ( (it1_c != it1_c), !(it1_c == it1_c) );
EXPECT_EQ( (it1_c != it2_c), !(it1_c == it2_c) );
EXPECT_EQ( (it1_c != it3_c), !(it1_c == it3_c) );
EXPECT_EQ( (it2_c != it3_c), !(it2_c == it3_c) );
}
// comparison: smaller
{
if (j.type() == json::value_t::object)
{
EXPECT_THROW_MSG(it1 < it1, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 < it2, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2 < it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 < it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c < it1_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c < it2_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2_c < it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c < it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
}
else
{
EXPECT_FALSE(it1 < it1);
EXPECT_TRUE(it1 < it2);
EXPECT_TRUE(it1 < it3);
EXPECT_TRUE(it2 < it3);
EXPECT_FALSE(it1_c < it1_c);
EXPECT_TRUE(it1_c < it2_c);
EXPECT_TRUE(it1_c < it3_c);
EXPECT_TRUE(it2_c < it3_c);
}
}
// comparison: less than or equal
{
if (j.type() == json::value_t::object)
{
EXPECT_THROW_MSG(it1 <= it1, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 <= it2, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2 <= it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 <= it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c <= it1_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c <= it2_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2_c <= it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c <= it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
}
else
{
// check definition
EXPECT_EQ( (it1 <= it1), !(it1 < it1) );
EXPECT_EQ( (it1 <= it2), !(it2 < it1) );
EXPECT_EQ( (it1 <= it3), !(it3 < it1) );
EXPECT_EQ( (it2 <= it3), !(it3 < it2) );
EXPECT_EQ( (it1_c <= it1_c), !(it1_c < it1_c) );
EXPECT_EQ( (it1_c <= it2_c), !(it2_c < it1_c) );
EXPECT_EQ( (it1_c <= it3_c), !(it3_c < it1_c) );
EXPECT_EQ( (it2_c <= it3_c), !(it3_c < it2_c) );
}
}
// comparison: greater than
{
if (j.type() == json::value_t::object)
{
EXPECT_THROW_MSG(it1 > it1, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 > it2, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2 > it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 > it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c > it1_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c > it2_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2_c > it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c > it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
}
else
{
// check definition
EXPECT_EQ( (it1 > it1), (it1 < it1) );
EXPECT_EQ( (it1 > it2), (it2 < it1) );
EXPECT_EQ( (it1 > it3), (it3 < it1) );
EXPECT_EQ( (it2 > it3), (it3 < it2) );
EXPECT_EQ( (it1_c > it1_c), (it1_c < it1_c) );
EXPECT_EQ( (it1_c > it2_c), (it2_c < it1_c) );
EXPECT_EQ( (it1_c > it3_c), (it3_c < it1_c) );
EXPECT_EQ( (it2_c > it3_c), (it3_c < it2_c) );
}
}
// comparison: greater than or equal
{
if (j.type() == json::value_t::object)
{
EXPECT_THROW_MSG(it1 >= it1, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 >= it2, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2 >= it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 >= it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c >= it1_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c >= it2_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2_c >= it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c >= it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
}
else
{
// check definition
EXPECT_EQ( (it1 >= it1), !(it1 < it1) );
EXPECT_EQ( (it1 >= it2), !(it1 < it2) );
EXPECT_EQ( (it1 >= it3), !(it1 < it3) );
EXPECT_EQ( (it2 >= it3), !(it2 < it3) );
EXPECT_EQ( (it1_c >= it1_c), !(it1_c < it1_c) );
EXPECT_EQ( (it1_c >= it2_c), !(it1_c < it2_c) );
EXPECT_EQ( (it1_c >= it3_c), !(it1_c < it3_c) );
EXPECT_EQ( (it2_c >= it3_c), !(it2_c < it3_c) );
}
}
}
// check exceptions if different objects are compared
for (auto j : j_values)
{
for (auto k : j_values)
{
if (j != k)
{
EXPECT_THROW_MSG(j.begin() == k.begin(), json::invalid_iterator,
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
EXPECT_THROW_MSG(j.cbegin() == k.cbegin(), json::invalid_iterator,
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
EXPECT_THROW_MSG(j.begin() < k.begin(), json::invalid_iterator,
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
EXPECT_THROW_MSG(j.cbegin() < k.cbegin(), json::invalid_iterator,
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
}
}
}
}
class JsonIteratorArithmeticTest : public ::testing::Test {
protected:
json j_object = {{"one", 1}, {"two", 2}, {"three", 3}};
json j_array = {1, 2, 3, 4, 5, 6};
json j_null = nullptr;
json j_value = 42;
};
TEST_F(JsonIteratorArithmeticTest, AddSubObject)
{
{
auto it = j_object.begin();
EXPECT_THROW_MSG(it += 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.cbegin();
EXPECT_THROW_MSG(it += 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.begin();
EXPECT_THROW_MSG(it + 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.cbegin();
EXPECT_THROW_MSG(it + 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.begin();
EXPECT_THROW_MSG(1 + it, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.cbegin();
EXPECT_THROW_MSG(1 + it, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.begin();
EXPECT_THROW_MSG(it -= 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.cbegin();
EXPECT_THROW_MSG(it -= 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.begin();
EXPECT_THROW_MSG(it - 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.cbegin();
EXPECT_THROW_MSG(it - 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.begin();
EXPECT_THROW_MSG(it - it, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.cbegin();
EXPECT_THROW_MSG(it - it, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
}
TEST_F(JsonIteratorArithmeticTest, AddSubArray)
{
auto it = j_array.begin();
it += 3;
EXPECT_EQ((j_array.begin() + 3), it);
EXPECT_EQ(json::iterator(3 + j_array.begin()), it);
EXPECT_EQ((it - 3), j_array.begin());
EXPECT_EQ((it - j_array.begin()), 3);
EXPECT_EQ(*it, json(4));
it -= 2;
EXPECT_EQ(*it, json(2));
}
TEST_F(JsonIteratorArithmeticTest, AddSubArrayConst)
{
auto it = j_array.cbegin();
it += 3;
EXPECT_EQ((j_array.cbegin() + 3), it);
EXPECT_EQ(json::const_iterator(3 + j_array.cbegin()), it);
EXPECT_EQ((it - 3), j_array.cbegin());
EXPECT_EQ((it - j_array.cbegin()), 3);
EXPECT_EQ(*it, json(4));
it -= 2;
EXPECT_EQ(*it, json(2));
}
TEST_F(JsonIteratorArithmeticTest, AddSubNull)
{
auto it = j_null.begin();
it += 3;
EXPECT_EQ((j_null.begin() + 3), it);
EXPECT_EQ(json::iterator(3 + j_null.begin()), it);
EXPECT_EQ((it - 3), j_null.begin());
EXPECT_EQ((it - j_null.begin()), 3);
EXPECT_NE(it, j_null.end());
it -= 3;
EXPECT_EQ(it, j_null.end());
}
TEST_F(JsonIteratorArithmeticTest, AddSubNullConst)
{
auto it = j_null.cbegin();
it += 3;
EXPECT_EQ((j_null.cbegin() + 3), it);
EXPECT_EQ(json::const_iterator(3 + j_null.cbegin()), it);
EXPECT_EQ((it - 3), j_null.cbegin());
EXPECT_EQ((it - j_null.cbegin()), 3);
EXPECT_NE(it, j_null.cend());
it -= 3;
EXPECT_EQ(it, j_null.cend());
}
TEST_F(JsonIteratorArithmeticTest, AddSubValue)
{
auto it = j_value.begin();
it += 3;
EXPECT_EQ((j_value.begin() + 3), it);
EXPECT_EQ(json::iterator(3 + j_value.begin()), it);
EXPECT_EQ((it - 3), j_value.begin());
EXPECT_EQ((it - j_value.begin()), 3);
EXPECT_NE(it, j_value.end());
it -= 3;
EXPECT_EQ(*it, json(42));
}
TEST_F(JsonIteratorArithmeticTest, AddSubValueConst)
{
auto it = j_value.cbegin();
it += 3;
EXPECT_EQ((j_value.cbegin() + 3), it);
EXPECT_EQ(json::const_iterator(3 + j_value.cbegin()), it);
EXPECT_EQ((it - 3), j_value.cbegin());
EXPECT_EQ((it - j_value.cbegin()), 3);
EXPECT_NE(it, j_value.cend());
it -= 3;
EXPECT_EQ(*it, json(42));
}
TEST_F(JsonIteratorArithmeticTest, SubscriptObject)
{
auto it = j_object.begin();
EXPECT_THROW_MSG(it[0], json::invalid_iterator,
"[json.exception.invalid_iterator.208] cannot use operator[] for object iterators");
EXPECT_THROW_MSG(it[1], json::invalid_iterator,
"[json.exception.invalid_iterator.208] cannot use operator[] for object iterators");
}
TEST_F(JsonIteratorArithmeticTest, SubscriptObjectConst)
{
auto it = j_object.cbegin();
EXPECT_THROW_MSG(it[0], json::invalid_iterator,
"[json.exception.invalid_iterator.208] cannot use operator[] for object iterators");
EXPECT_THROW_MSG(it[1], json::invalid_iterator,
"[json.exception.invalid_iterator.208] cannot use operator[] for object iterators");
}
TEST_F(JsonIteratorArithmeticTest, SubscriptArray)
{
auto it = j_array.begin();
EXPECT_EQ(it[0], json(1));
EXPECT_EQ(it[1], json(2));
EXPECT_EQ(it[2], json(3));
EXPECT_EQ(it[3], json(4));
EXPECT_EQ(it[4], json(5));
EXPECT_EQ(it[5], json(6));
}
TEST_F(JsonIteratorArithmeticTest, SubscriptArrayConst)
{
auto it = j_array.cbegin();
EXPECT_EQ(it[0], json(1));
EXPECT_EQ(it[1], json(2));
EXPECT_EQ(it[2], json(3));
EXPECT_EQ(it[3], json(4));
EXPECT_EQ(it[4], json(5));
EXPECT_EQ(it[5], json(6));
}
TEST_F(JsonIteratorArithmeticTest, SubscriptNull)
{
auto it = j_null.begin();
EXPECT_THROW_MSG(it[0], json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
EXPECT_THROW_MSG(it[1], json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
}
TEST_F(JsonIteratorArithmeticTest, SubscriptNullConst)
{
auto it = j_null.cbegin();
EXPECT_THROW_MSG(it[0], json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
EXPECT_THROW_MSG(it[1], json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
}
TEST_F(JsonIteratorArithmeticTest, SubscriptValue)
{
auto it = j_value.begin();
EXPECT_EQ(it[0], json(42));
EXPECT_THROW_MSG(it[1], json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
}
TEST_F(JsonIteratorArithmeticTest, SubscriptValueConst)
{
auto it = j_value.cbegin();
EXPECT_EQ(it[0], json(42));
EXPECT_THROW_MSG(it[1], json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
}
#if 0
TEST(JsonReverseIteratorTest, Comparisons)
{
json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
for (json& j : j_values)
{
SCOPED_TRACE(j.dump());
auto it1 = j.rbegin();
auto it2 = j.rbegin();
auto it3 = j.rbegin();
++it2;
++it3;
++it3;
auto it1_c = j.crbegin();
auto it2_c = j.crbegin();
auto it3_c = j.crbegin();
++it2_c;
++it3_c;
++it3_c;
// comparison: equal
{
EXPECT_TRUE(it1 == it1);
EXPECT_FALSE(it1 == it2);
EXPECT_FALSE(it1 == it3);
EXPECT_FALSE(it2 == it3);
EXPECT_TRUE(it1_c == it1_c);
EXPECT_FALSE(it1_c == it2_c);
EXPECT_FALSE(it1_c == it3_c);
EXPECT_FALSE(it2_c == it3_c);
}
// comparison: not equal
{
// check definition
EXPECT_EQ( (it1 != it1), !(it1 == it1) );
EXPECT_EQ( (it1 != it2), !(it1 == it2) );
EXPECT_EQ( (it1 != it3), !(it1 == it3) );
EXPECT_EQ( (it2 != it3), !(it2 == it3) );
EXPECT_EQ( (it1_c != it1_c), !(it1_c == it1_c) );
EXPECT_EQ( (it1_c != it2_c), !(it1_c == it2_c) );
EXPECT_EQ( (it1_c != it3_c), !(it1_c == it3_c) );
EXPECT_EQ( (it2_c != it3_c), !(it2_c == it3_c) );
}
// comparison: smaller
{
if (j.type() == json::value_t::object)
{
EXPECT_THROW_MSG(it1 < it1, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 < it2, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2 < it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 < it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c < it1_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c < it2_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2_c < it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c < it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
}
else
{
EXPECT_FALSE(it1 < it1);
EXPECT_TRUE(it1 < it2);
EXPECT_TRUE(it1 < it3);
EXPECT_TRUE(it2 < it3);
EXPECT_FALSE(it1_c < it1_c);
EXPECT_TRUE(it1_c < it2_c);
EXPECT_TRUE(it1_c < it3_c);
EXPECT_TRUE(it2_c < it3_c);
}
}
// comparison: less than or equal
{
if (j.type() == json::value_t::object)
{
EXPECT_THROW_MSG(it1 <= it1, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 <= it2, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2 <= it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 <= it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c <= it1_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c <= it2_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2_c <= it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c <= it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
}
else
{
// check definition
EXPECT_EQ( (it1 <= it1), !(it1 < it1) );
EXPECT_EQ( (it1 <= it2), !(it2 < it1) );
EXPECT_EQ( (it1 <= it3), !(it3 < it1) );
EXPECT_EQ( (it2 <= it3), !(it3 < it2) );
EXPECT_EQ( (it1_c <= it1_c), !(it1_c < it1_c) );
EXPECT_EQ( (it1_c <= it2_c), !(it2_c < it1_c) );
EXPECT_EQ( (it1_c <= it3_c), !(it3_c < it1_c) );
EXPECT_EQ( (it2_c <= it3_c), !(it3_c < it2_c) );
}
}
// comparison: greater than
{
if (j.type() == json::value_t::object)
{
EXPECT_THROW_MSG(it1 > it1, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 > it2, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2 > it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 > it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c > it1_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c > it2_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2_c > it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c > it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
}
else
{
// check definition
EXPECT_EQ( (it1 > it1), (it1 < it1) );
EXPECT_EQ( (it1 > it2), (it2 < it1) );
EXPECT_EQ( (it1 > it3), (it3 < it1) );
EXPECT_EQ( (it2 > it3), (it3 < it2) );
EXPECT_EQ( (it1_c > it1_c), (it1_c < it1_c) );
EXPECT_EQ( (it1_c > it2_c), (it2_c < it1_c) );
EXPECT_EQ( (it1_c > it3_c), (it3_c < it1_c) );
EXPECT_EQ( (it2_c > it3_c), (it3_c < it2_c) );
}
}
// comparison: greater than or equal
{
if (j.type() == json::value_t::object)
{
EXPECT_THROW_MSG(it1 >= it1, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 >= it2, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2 >= it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1 >= it3, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c >= it1_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c >= it2_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it2_c >= it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
EXPECT_THROW_MSG(it1_c >= it3_c, json::invalid_iterator,
"[json.exception.invalid_iterator.213] cannot compare order of object iterators");
}
else
{
// check definition
EXPECT_EQ( (it1 >= it1), !(it1 < it1) );
EXPECT_EQ( (it1 >= it2), !(it1 < it2) );
EXPECT_EQ( (it1 >= it3), !(it1 < it3) );
EXPECT_EQ( (it2 >= it3), !(it2 < it3) );
EXPECT_EQ( (it1_c >= it1_c), !(it1_c < it1_c) );
EXPECT_EQ( (it1_c >= it2_c), !(it1_c < it2_c) );
EXPECT_EQ( (it1_c >= it3_c), !(it1_c < it3_c) );
EXPECT_EQ( (it2_c >= it3_c), !(it2_c < it3_c) );
}
}
}
// check exceptions if different objects are compared
for (auto j : j_values)
{
for (auto k : j_values)
{
if (j != k)
{
EXPECT_THROW_MSG(j.rbegin() == k.rbegin(), json::invalid_iterator,
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
EXPECT_THROW_MSG(j.crbegin() == k.crbegin(), json::invalid_iterator,
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
EXPECT_THROW_MSG(j.rbegin() < k.rbegin(), json::invalid_iterator,
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
EXPECT_THROW_MSG(j.crbegin() < k.crbegin(), json::invalid_iterator,
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
}
}
}
}
class JsonReverseIteratorArithmeticTest : public ::testing::Test {
protected:
json j_object = {{"one", 1}, {"two", 2}, {"three", 3}};
json j_array = {1, 2, 3, 4, 5, 6};
json j_null = nullptr;
json j_value = 42;
};
TEST_F(JsonReverseIteratorArithmeticTest, AddSubObject)
{
{
auto it = j_object.rbegin();
EXPECT_THROW_MSG(it += 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.crbegin();
EXPECT_THROW_MSG(it += 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.rbegin();
EXPECT_THROW_MSG(it + 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.crbegin();
EXPECT_THROW_MSG(it + 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.rbegin();
EXPECT_THROW_MSG(1 + it, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.crbegin();
EXPECT_THROW_MSG(1 + it, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.rbegin();
EXPECT_THROW_MSG(it -= 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.crbegin();
EXPECT_THROW_MSG(it -= 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.rbegin();
EXPECT_THROW_MSG(it - 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.crbegin();
EXPECT_THROW_MSG(it - 1, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.rbegin();
EXPECT_THROW_MSG(it - it, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
{
auto it = j_object.crbegin();
EXPECT_THROW_MSG(it - it, json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
}
TEST_F(JsonReverseIteratorArithmeticTest, AddSubArray)
{
auto it = j_array.rbegin();
it += 3;
EXPECT_EQ((j_array.rbegin() + 3), it);
EXPECT_EQ(json::reverse_iterator(3 + j_array.rbegin()), it);
EXPECT_EQ((it - 3), j_array.rbegin());
EXPECT_EQ((it - j_array.rbegin()), 3);
EXPECT_EQ(*it, json(3));
it -= 2;
EXPECT_EQ(*it, json(5));
}
TEST_F(JsonReverseIteratorArithmeticTest, AddSubArrayConst)
{
auto it = j_array.crbegin();
it += 3;
EXPECT_EQ((j_array.crbegin() + 3), it);
EXPECT_EQ(json::const_reverse_iterator(3 + j_array.crbegin()), it);
EXPECT_EQ((it - 3), j_array.crbegin());
EXPECT_EQ((it - j_array.crbegin()), 3);
EXPECT_EQ(*it, json(3));
it -= 2;
EXPECT_EQ(*it, json(5));
}
TEST_F(JsonReverseIteratorArithmeticTest, AddSubNull)
{
auto it = j_null.rbegin();
it += 3;
EXPECT_EQ((j_null.rbegin() + 3), it);
EXPECT_EQ(json::reverse_iterator(3 + j_null.rbegin()), it);
EXPECT_EQ((it - 3), j_null.rbegin());
EXPECT_EQ((it - j_null.rbegin()), 3);
EXPECT_NE(it, j_null.rend());
it -= 3;
EXPECT_EQ(it, j_null.rend());
}
TEST_F(JsonReverseIteratorArithmeticTest, AddSubNullConst)
{
auto it = j_null.crbegin();
it += 3;
EXPECT_EQ((j_null.crbegin() + 3), it);
EXPECT_EQ(json::const_reverse_iterator(3 + j_null.crbegin()), it);
EXPECT_EQ((it - 3), j_null.crbegin());
EXPECT_EQ((it - j_null.crbegin()), 3);
EXPECT_NE(it, j_null.crend());
it -= 3;
EXPECT_EQ(it, j_null.crend());
}
TEST_F(JsonReverseIteratorArithmeticTest, AddSubValue)
{
auto it = j_value.rbegin();
it += 3;
EXPECT_EQ((j_value.rbegin() + 3), it);
EXPECT_EQ(json::reverse_iterator(3 + j_value.rbegin()), it);
EXPECT_EQ((it - 3), j_value.rbegin());
EXPECT_EQ((it - j_value.rbegin()), 3);
EXPECT_NE(it, j_value.rend());
it -= 3;
EXPECT_EQ(*it, json(42));
}
TEST_F(JsonReverseIteratorArithmeticTest, AddSubValueConst)
{
auto it = j_value.crbegin();
it += 3;
EXPECT_EQ((j_value.crbegin() + 3), it);
EXPECT_EQ(json::const_reverse_iterator(3 + j_value.crbegin()), it);
EXPECT_EQ((it - 3), j_value.crbegin());
EXPECT_EQ((it - j_value.crbegin()), 3);
EXPECT_NE(it, j_value.crend());
it -= 3;
EXPECT_EQ(*it, json(42));
}
TEST_F(JsonReverseIteratorArithmeticTest, SubscriptObject)
{
auto it = j_object.rbegin();
EXPECT_THROW_MSG(it[0], json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
EXPECT_THROW_MSG(it[1], json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
TEST_F(JsonReverseIteratorArithmeticTest, SubscriptObjectConst)
{
auto it = j_object.crbegin();
EXPECT_THROW_MSG(it[0], json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
EXPECT_THROW_MSG(it[1], json::invalid_iterator,
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
}
TEST_F(JsonReverseIteratorArithmeticTest, SubscriptArray)
{
auto it = j_array.rbegin();
EXPECT_EQ(it[0], json(6));
EXPECT_EQ(it[1], json(5));
EXPECT_EQ(it[2], json(4));
EXPECT_EQ(it[3], json(3));
EXPECT_EQ(it[4], json(2));
EXPECT_EQ(it[5], json(1));
}
TEST_F(JsonReverseIteratorArithmeticTest, SubscriptArrayConst)
{
auto it = j_array.crbegin();
EXPECT_EQ(it[0], json(6));
EXPECT_EQ(it[1], json(5));
EXPECT_EQ(it[2], json(4));
EXPECT_EQ(it[3], json(3));
EXPECT_EQ(it[4], json(2));
EXPECT_EQ(it[5], json(1));
}
TEST_F(JsonReverseIteratorArithmeticTest, SubscriptNull)
{
auto it = j_null.rbegin();
EXPECT_THROW_MSG(it[0], json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
EXPECT_THROW_MSG(it[1], json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
}
TEST_F(JsonReverseIteratorArithmeticTest, SubscriptNullConst)
{
auto it = j_null.crbegin();
EXPECT_THROW_MSG(it[0], json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
EXPECT_THROW_MSG(it[1], json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
}
TEST_F(JsonReverseIteratorArithmeticTest, SubscriptValue)
{
auto it = j_value.rbegin();
EXPECT_EQ(it[0], json(42));
EXPECT_THROW_MSG(it[1], json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
}
TEST_F(JsonReverseIteratorArithmeticTest, SubscriptValueConst)
{
auto it = j_value.crbegin();
EXPECT_EQ(it[0], json(42));
EXPECT_THROW_MSG(it[1], json::invalid_iterator,
"[json.exception.invalid_iterator.214] cannot get value");
}
#endif

View File

@@ -0,0 +1,88 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/#ifndef UNIT_JSON_H_
#define UNIT_JSON_H_
#include <ostream>
#include "support/json.h"
namespace wpi {
inline
void PrintTo(const json& j, std::ostream* os) {
*os << j.dump();
}
class JsonTest {
public:
static const json::json_value& GetValue(const json& j) {
return j.m_value;
}
static json::pointer GetObject(json::iterator it) {
return it.m_object;
}
static json::const_pointer GetObject(json::const_iterator it) {
return it.m_object;
}
static std::string pop_back(json::json_pointer& p) {
return p.pop_back();
}
static json::json_pointer top(const json::json_pointer& p) {
return p.top();
}
};
} // namespace wpi
// clang warns on TEST_THROW_MSG(x == y, ...) saying the result is unused.
// suppress this warning.
#if defined(__clang__)
#pragma GCC diagnostic ignored "-Wunused-comparison"
#endif
// variant of GTEST_TEST_THROW_ that also checks the exception's message.
#define TEST_THROW_MSG(statement, expected_exception, expected_msg, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::ConstCharPtr gtest_msg = "") { \
bool gtest_caught_expected = false; \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} \
catch (expected_exception const& gtest_ex) { \
gtest_caught_expected = true; \
if (::std::string(gtest_ex.what()) != expected_msg) { \
::testing::AssertionResult gtest_ar = ::testing::AssertionFailure(); \
gtest_ar \
<< "Expected: " #statement " throws an exception with message \"" \
<< expected_msg "\".\n Actual: it throws message \"" \
<< gtest_ex.what() << "\"."; \
fail(gtest_ar.failure_message()); \
} \
} \
catch (...) { \
gtest_msg.value = \
"Expected: " #statement " throws an exception of type " \
#expected_exception ".\n Actual: it throws a different type."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
if (!gtest_caught_expected) { \
gtest_msg.value = \
"Expected: " #statement " throws an exception of type " \
#expected_exception ".\n Actual: it throws nothing."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
fail(gtest_msg.value)
#define EXPECT_THROW_MSG(statement, expected_exception, expected_msg) \
TEST_THROW_MSG(statement, expected_exception, expected_msg, GTEST_NONFATAL_FAILURE_)
#define ASSERT_THROW_MSG(statement, expected_exception, expected_msg) \
TEST_THROW_MSG(statement, expected_exception, expected_msg, GTEST_FATAL_FAILURE_)
#endif

View File

@@ -0,0 +1,402 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
using wpi::JsonTest;
TEST(JsonPointerTest, Errors)
{
EXPECT_THROW_MSG(json::json_pointer("foo"), json::parse_error,
"[json.exception.parse_error.107] parse error at 1: JSON pointer must be empty or begin with '/' - was: 'foo'");
EXPECT_THROW_MSG(json::json_pointer("/~~"), json::parse_error,
"[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'");
EXPECT_THROW_MSG(json::json_pointer("/~"), json::parse_error,
"[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'");
json::json_pointer p;
EXPECT_THROW_MSG(JsonTest::top(p), json::out_of_range,
"[json.exception.out_of_range.405] JSON pointer has no parent");
EXPECT_THROW_MSG(JsonTest::pop_back(p), json::out_of_range,
"[json.exception.out_of_range.405] JSON pointer has no parent");
}
// examples from RFC 6901
TEST(JsonPointerTest, AccessNonConst)
{
json j = R"(
{
"foo": ["bar", "baz"],
"": 0,
"a/b": 1,
"c%d": 2,
"e^f": 3,
"g|h": 4,
"i\\j": 5,
"k\"l": 6,
" ": 7,
"m~n": 8
}
)"_json;
// the whole document
EXPECT_EQ(j[json::json_pointer()], j);
EXPECT_EQ(j[json::json_pointer("")], j);
// array access
EXPECT_EQ(j[json::json_pointer("/foo")], j["foo"]);
EXPECT_EQ(j[json::json_pointer("/foo/0")], j["foo"][0]);
EXPECT_EQ(j[json::json_pointer("/foo/1")], j["foo"][1]);
EXPECT_EQ(j["/foo/1"_json_pointer], j["foo"][1]);
// checked array access
EXPECT_EQ(j.at(json::json_pointer("/foo/0")), j["foo"][0]);
EXPECT_EQ(j.at(json::json_pointer("/foo/1")), j["foo"][1]);
// empty string access
EXPECT_EQ(j[json::json_pointer("/")], j[""]);
// other cases
EXPECT_EQ(j[json::json_pointer("/ ")], j[" "]);
EXPECT_EQ(j[json::json_pointer("/c%d")], j["c%d"]);
EXPECT_EQ(j[json::json_pointer("/e^f")], j["e^f"]);
EXPECT_EQ(j[json::json_pointer("/g|h")], j["g|h"]);
EXPECT_EQ(j[json::json_pointer("/i\\j")], j["i\\j"]);
EXPECT_EQ(j[json::json_pointer("/k\"l")], j["k\"l"]);
// checked access
EXPECT_EQ(j.at(json::json_pointer("/ ")), j[" "]);
EXPECT_EQ(j.at(json::json_pointer("/c%d")), j["c%d"]);
EXPECT_EQ(j.at(json::json_pointer("/e^f")), j["e^f"]);
EXPECT_EQ(j.at(json::json_pointer("/g|h")), j["g|h"]);
EXPECT_EQ(j.at(json::json_pointer("/i\\j")), j["i\\j"]);
EXPECT_EQ(j.at(json::json_pointer("/k\"l")), j["k\"l"]);
// escaped access
EXPECT_EQ(j[json::json_pointer("/a~1b")], j["a/b"]);
EXPECT_EQ(j[json::json_pointer("/m~0n")], j["m~n"]);
// unescaped access
// access to nonexisting values yield object creation
EXPECT_NO_THROW(j[json::json_pointer("/a/b")] = 42);
EXPECT_EQ(j["a"]["b"], json(42));
EXPECT_NO_THROW(j[json::json_pointer("/a/c/1")] = 42);
EXPECT_EQ(j["a"]["c"], json({nullptr, 42}));
EXPECT_NO_THROW(j[json::json_pointer("/a/d/-")] = 42);
EXPECT_EQ(j["a"]["d"], json::array({42}));
// "/a/b" works for JSON {"a": {"b": 42}}
EXPECT_EQ(json({{"a", {{"b", 42}}}})[json::json_pointer("/a/b")], json(42));
// unresolved access
json j_primitive = 1;
EXPECT_THROW_MSG(j_primitive["/foo"_json_pointer], json::out_of_range,
"[json.exception.out_of_range.404] unresolved reference token 'foo'");
EXPECT_THROW_MSG(j_primitive.at("/foo"_json_pointer), json::out_of_range,
"[json.exception.out_of_range.404] unresolved reference token 'foo'");
}
TEST(JsonPointerTest, AccessConst)
{
const json j = R"(
{
"foo": ["bar", "baz"],
"": 0,
"a/b": 1,
"c%d": 2,
"e^f": 3,
"g|h": 4,
"i\\j": 5,
"k\"l": 6,
" ": 7,
"m~n": 8
}
)"_json;
// the whole document
EXPECT_EQ(j[json::json_pointer()], j);
EXPECT_EQ(j[json::json_pointer("")], j);
// array access
EXPECT_EQ(j[json::json_pointer("/foo")], j["foo"]);
EXPECT_EQ(j[json::json_pointer("/foo/0")], j["foo"][0]);
EXPECT_EQ(j[json::json_pointer("/foo/1")], j["foo"][1]);
EXPECT_EQ(j["/foo/1"_json_pointer], j["foo"][1]);
// checked array access
EXPECT_EQ(j.at(json::json_pointer("/foo/0")), j["foo"][0]);
EXPECT_EQ(j.at(json::json_pointer("/foo/1")), j["foo"][1]);
// empty string access
EXPECT_EQ(j[json::json_pointer("/")], j[""]);
// other cases
EXPECT_EQ(j[json::json_pointer("/ ")], j[" "]);
EXPECT_EQ(j[json::json_pointer("/c%d")], j["c%d"]);
EXPECT_EQ(j[json::json_pointer("/e^f")], j["e^f"]);
EXPECT_EQ(j[json::json_pointer("/g|h")], j["g|h"]);
EXPECT_EQ(j[json::json_pointer("/i\\j")], j["i\\j"]);
EXPECT_EQ(j[json::json_pointer("/k\"l")], j["k\"l"]);
// checked access
EXPECT_EQ(j.at(json::json_pointer("/ ")), j[" "]);
EXPECT_EQ(j.at(json::json_pointer("/c%d")), j["c%d"]);
EXPECT_EQ(j.at(json::json_pointer("/e^f")), j["e^f"]);
EXPECT_EQ(j.at(json::json_pointer("/g|h")), j["g|h"]);
EXPECT_EQ(j.at(json::json_pointer("/i\\j")), j["i\\j"]);
EXPECT_EQ(j.at(json::json_pointer("/k\"l")), j["k\"l"]);
// escaped access
EXPECT_EQ(j[json::json_pointer("/a~1b")], j["a/b"]);
EXPECT_EQ(j[json::json_pointer("/m~0n")], j["m~n"]);
// unescaped access
EXPECT_THROW_MSG(j.at(json::json_pointer("/a/b")), json::out_of_range,
"[json.exception.out_of_range.403] key 'a' not found");
// unresolved access
const json j_primitive = 1;
EXPECT_THROW_MSG(j_primitive["/foo"_json_pointer], json::out_of_range,
"[json.exception.out_of_range.404] unresolved reference token 'foo'");
EXPECT_THROW_MSG(j_primitive.at("/foo"_json_pointer), json::out_of_range,
"[json.exception.out_of_range.404] unresolved reference token 'foo'");
}
TEST(JsonPointerTest, UserStringLiteral)
{
json j = R"(
{
"foo": ["bar", "baz"],
"": 0,
"a/b": 1,
"c%d": 2,
"e^f": 3,
"g|h": 4,
"i\\j": 5,
"k\"l": 6,
" ": 7,
"m~n": 8
}
)"_json;
// the whole document
EXPECT_EQ(j[""_json_pointer], j);
// array access
EXPECT_EQ(j["/foo"_json_pointer], j["foo"]);
EXPECT_EQ(j["/foo/0"_json_pointer], j["foo"][0]);
EXPECT_EQ(j["/foo/1"_json_pointer], j["foo"][1]);
}
TEST(JsonPointerTest, ArrayNonConst)
{
json j = {1, 2, 3};
const json j_const = j;
// check reading access
EXPECT_EQ(j["/0"_json_pointer], j[0]);
EXPECT_EQ(j["/1"_json_pointer], j[1]);
EXPECT_EQ(j["/2"_json_pointer], j[2]);
// assign to existing index
j["/1"_json_pointer] = 13;
EXPECT_EQ(j[1], json(13));
// assign to nonexisting index
j["/3"_json_pointer] = 33;
EXPECT_EQ(j[3], json(33));
// assign to nonexisting index (with gap)
j["/5"_json_pointer] = 55;
EXPECT_EQ(j, json({1, 13, 3, 33, nullptr, 55}));
// error with leading 0
EXPECT_THROW_MSG(j["/01"_json_pointer], json::parse_error,
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'");
EXPECT_THROW_MSG(j_const["/01"_json_pointer], json::parse_error,
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'");
EXPECT_THROW_MSG(j.at("/01"_json_pointer), json::parse_error,
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'");
EXPECT_THROW_MSG(j_const.at("/01"_json_pointer), json::parse_error,
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'");
// error with incorrect numbers
EXPECT_THROW_MSG(j["/one"_json_pointer] = 1, json::parse_error,
"[json.exception.parse_error.109] parse error: array index 'one' is not a number");
EXPECT_THROW_MSG(j_const["/one"_json_pointer] == 1, json::parse_error,
"[json.exception.parse_error.109] parse error: array index 'one' is not a number");
EXPECT_THROW_MSG(j.at("/one"_json_pointer) = 1, json::parse_error,
"[json.exception.parse_error.109] parse error: array index 'one' is not a number");
EXPECT_THROW_MSG(j_const.at("/one"_json_pointer) == 1, json::parse_error,
"[json.exception.parse_error.109] parse error: array index 'one' is not a number");
EXPECT_THROW_MSG(json({{"/list/0", 1}, {"/list/1", 2}, {"/list/three", 3}}).unflatten(), json::parse_error,
"[json.exception.parse_error.109] parse error: array index 'three' is not a number");
// assign to "-"
j["/-"_json_pointer] = 99;
EXPECT_EQ(j, json({1, 13, 3, 33, nullptr, 55, 99}));
// error when using "-" in const object
EXPECT_THROW_MSG(j_const["/-"_json_pointer], json::out_of_range,
"[json.exception.out_of_range.402] array index '-' (3) is out of range");
// error when using "-" with at
EXPECT_THROW_MSG(j.at("/-"_json_pointer), json::out_of_range,
"[json.exception.out_of_range.402] array index '-' (7) is out of range");
EXPECT_THROW_MSG(j_const.at("/-"_json_pointer), json::out_of_range,
"[json.exception.out_of_range.402] array index '-' (3) is out of range");
}
TEST(JsonPointerTest, ArrayConst)
{
const json j = {1, 2, 3};
// check reading access
EXPECT_EQ(j["/0"_json_pointer], j[0]);
EXPECT_EQ(j["/1"_json_pointer], j[1]);
EXPECT_EQ(j["/2"_json_pointer], j[2]);
// assign to nonexisting index
EXPECT_THROW_MSG(j.at("/3"_json_pointer), json::out_of_range,
"[json.exception.out_of_range.401] array index 3 is out of range");
// assign to nonexisting index (with gap)
EXPECT_THROW_MSG(j.at("/5"_json_pointer), json::out_of_range,
"[json.exception.out_of_range.401] array index 5 is out of range");
// assign to "-"
EXPECT_THROW_MSG(j["/-"_json_pointer], json::out_of_range,
"[json.exception.out_of_range.402] array index '-' (3) is out of range");
EXPECT_THROW_MSG(j.at("/-"_json_pointer), json::out_of_range,
"[json.exception.out_of_range.402] array index '-' (3) is out of range");
}
TEST(JsonPointerTest, Flatten)
{
json j =
{
{"pi", 3.141},
{"happy", true},
{"name", "Niels"},
{"nothing", nullptr},
{
"answer", {
{"everything", 42}
}
},
{"list", {1, 0, 2}},
{
"object", {
{"currency", "USD"},
{"value", 42.99},
{"", "empty string"},
{"/", "slash"},
{"~", "tilde"},
{"~1", "tilde1"}
}
}
};
json j_flatten =
{
{"/pi", 3.141},
{"/happy", true},
{"/name", "Niels"},
{"/nothing", nullptr},
{"/answer/everything", 42},
{"/list/0", 1},
{"/list/1", 0},
{"/list/2", 2},
{"/object/currency", "USD"},
{"/object/value", 42.99},
{"/object/", "empty string"},
{"/object/~1", "slash"},
{"/object/~0", "tilde"},
{"/object/~01", "tilde1"}
};
// check if flattened result is as expected
EXPECT_EQ(j.flatten(), j_flatten);
// check if unflattened result is as expected
EXPECT_EQ(j_flatten.unflatten(), j);
// error for nonobjects
EXPECT_THROW_MSG(json(1).unflatten(), json::type_error,
"[json.exception.type_error.314] only objects can be unflattened");
// error for nonprimitve values
EXPECT_THROW_MSG(json({{"/1", {1, 2, 3}}}).unflatten(), json::type_error,
"[json.exception.type_error.315] values in object must be primitive");
// error for conflicting values
json j_error = {{"", 42}, {"/foo", 17}};
EXPECT_THROW_MSG(j_error.unflatten(), json::type_error,
"[json.exception.type_error.313] invalid value to unflatten");
// explicit roundtrip check
EXPECT_EQ(j.flatten().unflatten(), j);
// roundtrip for primitive values
json j_null;
EXPECT_EQ(j_null.flatten().unflatten(), j_null);
json j_number = 42;
EXPECT_EQ(j_number.flatten().unflatten(), j_number);
json j_boolean = false;
EXPECT_EQ(j_boolean.flatten().unflatten(), j_boolean);
json j_string = "foo";
EXPECT_EQ(j_string.flatten().unflatten(), j_string);
// roundtrip for empty structured values (will be unflattened to null)
json j_array(json::value_t::array);
EXPECT_EQ(j_array.flatten().unflatten(), json());
json j_object(json::value_t::object);
EXPECT_EQ(j_object.flatten().unflatten(), json());
}
TEST(JsonPointerTest, StringRepresentation)
{
for (auto ptr :
{"", "/foo", "/foo/0", "/", "/a~1b", "/c%d", "/e^f", "/g|h", "/i\\j", "/k\"l", "/ ", "/m~0n"
})
{
SCOPED_TRACE(ptr);
EXPECT_EQ(json::json_pointer(ptr).to_string(), ptr);
}
}

View File

@@ -0,0 +1,54 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
TEST(JsonVersionTest, Meta)
{
json j = json::meta();
EXPECT_EQ(j["name"], "WPI version of JSON for Modern C++");
EXPECT_EQ(j["copyright"], "(C) 2013-2017 Niels Lohmann, (C) 2017 FIRST");
EXPECT_EQ(j["url"], "https://github.com/wpilibsuite/wpiutil");
EXPECT_EQ(j["version"], json(
{
{"string", "2.1.1"},
{"major", 2},
{"minor", 1},
{"patch", 1}
}));
}

View File

@@ -0,0 +1,739 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
TEST(JsonClearTest, Boolean)
{
json j = true;
j.clear();
EXPECT_EQ(j, json(json::value_t::boolean));
}
TEST(JsonClearTest, String)
{
json j = "hello world";
j.clear();
EXPECT_EQ(j, json(json::value_t::string));
}
TEST(JsonClearTest, ArrayEmpty)
{
json j = json::array();
j.clear();
EXPECT_TRUE(j.empty());
EXPECT_EQ(j, json(json::value_t::array));
}
TEST(JsonClearTest, ArrayFilled)
{
json j = {1, 2, 3};
j.clear();
EXPECT_TRUE(j.empty());
EXPECT_EQ(j, json(json::value_t::array));
}
TEST(JsonClearTest, ObjectEmpty)
{
json j = json::object();
j.clear();
EXPECT_TRUE(j.empty());
EXPECT_EQ(j, json(json::value_t::object));
}
TEST(JsonClearTest, ObjectFilled)
{
json j = {{"one", 1}, {"two", 2}, {"three", 3}};
j.clear();
EXPECT_TRUE(j.empty());
EXPECT_EQ(j, json(json::value_t::object));
}
TEST(JsonClearTest, Integer)
{
json j = 23;
j.clear();
EXPECT_EQ(j, json(json::value_t::number_integer));
}
TEST(JsonClearTest, Unsigned)
{
json j = 23u;
j.clear();
EXPECT_EQ(j, json(json::value_t::number_integer));
}
TEST(JsonClearTest, Float)
{
json j = 23.42;
j.clear();
EXPECT_EQ(j, json(json::value_t::number_float));
}
TEST(JsonClearTest, Null)
{
json j = nullptr;
j.clear();
EXPECT_EQ(j, json(json::value_t::null));
}
TEST(JsonPushBackArrayTest, RRefNull)
{
json j;
j.push_back(1);
j.push_back(2);
EXPECT_EQ(j.type(), json::value_t::array);
EXPECT_EQ(j, json({1, 2}));
}
TEST(JsonPushBackArrayTest, RRefArray)
{
json j = {1, 2, 3};
j.push_back("Hello");
EXPECT_EQ(j.type(), json::value_t::array);
EXPECT_EQ(j, json({1, 2, 3, "Hello"}));
}
TEST(JsonPushBackArrayTest, RRefOther)
{
json j = 1;
EXPECT_THROW_MSG(j.push_back("Hello"), json::type_error,
"[json.exception.type_error.308] cannot use push_back() with number");
}
TEST(JsonPushBackArrayTest, LRefNull)
{
json j;
json k(1);
j.push_back(k);
j.push_back(k);
EXPECT_EQ(j.type(), json::value_t::array);
EXPECT_EQ(j, json({1, 1}));
}
TEST(JsonPushBackArrayTest, LRefArray)
{
json j = {1, 2, 3};
json k("Hello");
j.push_back(k);
EXPECT_EQ(j.type(), json::value_t::array);
EXPECT_EQ(j, json({1, 2, 3, "Hello"}));
}
TEST(JsonPushBackArrayTest, LRefOther)
{
json j = 1;
json k("Hello");
EXPECT_THROW_MSG(j.push_back(k), json::type_error,
"[json.exception.type_error.308] cannot use push_back() with number");
}
#if 0
TEST(JsonPushBackObjectTest, Null)
{
json j;
j.push_back(json::object_t::value_type({"one", 1}));
j.push_back(json::object_t::value_type({"two", 2}));
EXPECT_EQ(j.type(), json::value_t::object);
EXPECT_EQ(j.size(), 2u);
EXPECT_EQ(j["one"], json(1));
EXPECT_EQ(j["two"], json(2));
}
TEST(JsonPushBackObjectTest, Object)
{
json j(json::value_t::object);
j.push_back(json::object_t::value_type({"one", 1}));
j.push_back(json::object_t::value_type({"two", 2}));
EXPECT_EQ(j.size(), 2u);
EXPECT_EQ(j["one"], json(1));
EXPECT_EQ(j["two"], json(2));
}
TEST(JsonPushBackObjectTest, Other)
{
json j = 1;
json k("Hello");
EXPECT_THROW_MSG(j.push_back(json::object_t::value_type({"one", 1})), json::type_error,
"[json.exception.type_error.308] cannot use push_back() with number");
}
#endif
TEST(JsonPushBackInitListTest, Null)
{
json j;
j.push_back({"foo", "bar"});
EXPECT_EQ(j, json::array({{"foo", "bar"}}));
json k;
k.push_back({1, 2, 3});
EXPECT_EQ(k, json::array({{1, 2, 3}}));
}
TEST(JsonPushBackInitListTest, Array)
{
json j = {1, 2, 3};
j.push_back({"foo", "bar"});
EXPECT_EQ(j, json({1, 2, 3, {"foo", "bar"}}));
json k = {1, 2, 3};
k.push_back({1, 2, 3});
EXPECT_EQ(k, json({1, 2, 3, {1, 2, 3}}));
}
TEST(JsonPushBackInitListTest, Object)
{
json j = {{"key1", 1}};
j.push_back({"key2", "bar"});
EXPECT_EQ(j, json({{"key1", 1}, {"key2", "bar"}}));
json k = {{"key1", 1}};
EXPECT_THROW_MSG(k.push_back({1, 2, 3, 4}), json::type_error,
"[json.exception.type_error.308] cannot use push_back() with object");
}
TEST(JsonEmplaceBackArrayTest, Null)
{
json j;
j.emplace_back(1);
j.emplace_back(2);
EXPECT_EQ(j.type(), json::value_t::array);
EXPECT_EQ(j, json({1, 2}));
}
TEST(JsonEmplaceBackArrayTest, Array)
{
json j = {1, 2, 3};
j.emplace_back("Hello");
EXPECT_EQ(j.type(), json::value_t::array);
EXPECT_EQ(j, json({1, 2, 3, "Hello"}));
}
TEST(JsonEmplaceBackArrayTest, MultipleValues)
{
json j;
j.emplace_back(3, "foo");
EXPECT_EQ(j.type(), json::value_t::array);
EXPECT_EQ(j, json({{"foo", "foo", "foo"}}));
}
TEST(JsonEmplaceBackArrayTest, Other)
{
json j = 1;
EXPECT_THROW_MSG(j.emplace_back("Hello"), json::type_error,
"[json.exception.type_error.311] cannot use emplace_back() with number");
}
TEST(JsonEmplaceObjectTest, Null)
{
// start with a null value
json j;
// add a new key
auto res1 = j.emplace("foo", "bar");
EXPECT_EQ(res1.second, true);
EXPECT_EQ(*res1.first, "bar");
// the null value is changed to an object
EXPECT_EQ(j.type(), json::value_t::object);
// add a new key
auto res2 = j.emplace("baz", "bam");
EXPECT_EQ(res2.second, true);
EXPECT_EQ(*res2.first, "bam");
// we try to insert at given key - no change
auto res3 = j.emplace("baz", "bad");
EXPECT_EQ(res3.second, false);
EXPECT_EQ(*res3.first, "bam");
// the final object
EXPECT_EQ(j, json({{"baz", "bam"}, {"foo", "bar"}}));
}
TEST(JsonEmplaceObjectTest, Object)
{
// start with an object
json j = {{"foo", "bar"}};
// add a new key
auto res1 = j.emplace("baz", "bam");
EXPECT_EQ(res1.second, true);
EXPECT_EQ(*res1.first, "bam");
// add an existing key
auto res2 = j.emplace("foo", "bad");
EXPECT_EQ(res2.second, false);
EXPECT_EQ(*res2.first, "bar");
// check final object
EXPECT_EQ(j, json({{"baz", "bam"}, {"foo", "bar"}}));
}
TEST(JsonEmplaceObjectTest, Other)
{
json j = 1;
EXPECT_THROW_MSG(j.emplace("foo", "bar"), json::type_error,
"[json.exception.type_error.311] cannot use emplace() with number");
}
TEST(JsonPlusEqualArrayTest, RRefNull)
{
json j;
j += 1;
j += 2;
EXPECT_EQ(j.type(), json::value_t::array);
EXPECT_EQ(j, json({1, 2}));
}
TEST(JsonPlusEqualArrayTest, RRefArray)
{
json j = {1, 2, 3};
j += "Hello";
EXPECT_EQ(j.type(), json::value_t::array);
EXPECT_EQ(j, json({1, 2, 3, "Hello"}));
}
TEST(JsonPlusEqualArrayTest, RRefOther)
{
json j = 1;
EXPECT_THROW_MSG(j += "Hello", json::type_error,
"[json.exception.type_error.308] cannot use push_back() with number");
}
TEST(JsonPlusEqualArrayTest, LRefNull)
{
json j;
json k(1);
j += k;
j += k;
EXPECT_EQ(j.type(), json::value_t::array);
EXPECT_EQ(j, json({1, 1}));
}
TEST(JsonPlusEqualArrayTest, LRefArray)
{
json j = {1, 2, 3};
json k("Hello");
j += k;
EXPECT_EQ(j.type(), json::value_t::array);
EXPECT_EQ(j, json({1, 2, 3, "Hello"}));
}
TEST(JsonPlusEqualArrayTest, LRefOther)
{
json j = 1;
json k("Hello");
EXPECT_THROW_MSG(j += k, json::type_error,
"[json.exception.type_error.308] cannot use push_back() with number");
}
#if 0
TEST(JsonPlusEqualObjectTest, Null)
{
json j;
j += json::object_t::value_type({"one", 1});
j += json::object_t::value_type({"two", 2});
EXPECT_EQ(j.type(), json::value_t::object);
EXPECT_EQ(j.size(), 2u);
EXPECT_EQ(j["one"], json(1));
EXPECT_EQ(j["two"], json(2));
}
TEST(JsonPlusEqualObjectTest, Object)
{
json j(json::value_t::object);
j += json::object_t::value_type({"one", 1});
j += json::object_t::value_type({"two", 2});
EXPECT_EQ(j.size(), 2u);
EXPECT_EQ(j["one"], json(1));
EXPECT_EQ(j["two"], json(2));
}
TEST(JsonPlusEqualObjectTest, Other)
{
json j = 1;
json k("Hello");
EXPECT_THROW_MSG(j += json::object_t::value_type({"one", 1}), json::type_error,
"[json.exception.type_error.308] cannot use push_back() with number");
}
#endif
TEST(JsonPlusEqualInitListTest, Null)
{
json j;
j += {"foo", "bar"};
EXPECT_EQ(j, json::array({{"foo", "bar"}}));
json k;
k += {1, 2, 3};
EXPECT_EQ(k, json::array({{1, 2, 3}}));
}
TEST(JsonPlusEqualInitListTest, Array)
{
json j = {1, 2, 3};
j += {"foo", "bar"};
EXPECT_EQ(j, json({1, 2, 3, {"foo", "bar"}}));
json k = {1, 2, 3};
k += {1, 2, 3};
EXPECT_EQ(k, json({1, 2, 3, {1, 2, 3}}));
}
TEST(JsonPlusEqualInitListTest, Object)
{
json j = {{"key1", 1}};
j += {"key2", "bar"};
EXPECT_EQ(j, json({{"key1", 1}, {"key2", "bar"}}));
json k = {{"key1", 1}};
EXPECT_THROW_MSG((k += {1, 2, 3, 4}), json::type_error,
"[json.exception.type_error.308] cannot use push_back() with object");
}
class JsonInsertTest : public ::testing::Test {
protected:
json j_array = {1, 2, 3, 4};
json j_value = 5;
json j_other_array = {"first", "second"};
json j_object1 = {{"one", "eins"}, {"two", "zwei"}};
json j_object2 = {{"eleven", "elf"}, {"seventeen", "siebzehn"}};
};
TEST_F(JsonInsertTest, ValueBegin)
{
auto it = j_array.insert(j_array.begin(), j_value);
EXPECT_EQ(j_array.size(), 5u);
EXPECT_EQ(*it, j_value);
EXPECT_EQ(j_array.begin(), it);
EXPECT_EQ(j_array, json({5, 1, 2, 3, 4}));
}
TEST_F(JsonInsertTest, ValueMiddle)
{
auto it = j_array.insert(j_array.begin() + 2, j_value);
EXPECT_EQ(j_array.size(), 5u);
EXPECT_EQ(*it, j_value);
EXPECT_EQ((it - j_array.begin()), 2);
EXPECT_EQ(j_array, json({1, 2, 5, 3, 4}));
}
TEST_F(JsonInsertTest, ValueEnd)
{
auto it = j_array.insert(j_array.end(), j_value);
EXPECT_EQ(j_array.size(), 5u);
EXPECT_EQ(*it, j_value);
EXPECT_EQ((j_array.end() - it), 1);
EXPECT_EQ(j_array, json({1, 2, 3, 4, 5}));
}
TEST_F(JsonInsertTest, RvalueBegin)
{
auto it = j_array.insert(j_array.begin(), 5);
EXPECT_EQ(j_array.size(), 5u);
EXPECT_EQ(*it, j_value);
EXPECT_EQ(j_array.begin(), it);
EXPECT_EQ(j_array, json({5, 1, 2, 3, 4}));
}
TEST_F(JsonInsertTest, RvalueMiddle)
{
auto it = j_array.insert(j_array.begin() + 2, 5);
EXPECT_EQ(j_array.size(), 5u);
EXPECT_EQ(*it, j_value);
EXPECT_EQ((it - j_array.begin()), 2);
EXPECT_EQ(j_array, json({1, 2, 5, 3, 4}));
}
TEST_F(JsonInsertTest, RvalueEnd)
{
auto it = j_array.insert(j_array.end(), 5);
EXPECT_EQ(j_array.size(), 5u);
EXPECT_EQ(*it, j_value);
EXPECT_EQ((j_array.end() - it), 1);
EXPECT_EQ(j_array, json({1, 2, 3, 4, 5}));
}
TEST_F(JsonInsertTest, CopyBegin)
{
auto it = j_array.insert(j_array.begin(), 3, 5);
EXPECT_EQ(j_array.size(), 7u);
EXPECT_EQ(*it, j_value);
EXPECT_EQ(j_array.begin(), it);
EXPECT_EQ(j_array, json({5, 5, 5, 1, 2, 3, 4}));
}
TEST_F(JsonInsertTest, CopyMiddle)
{
auto it = j_array.insert(j_array.begin() + 2, 3, 5);
EXPECT_EQ(j_array.size(), 7u);
EXPECT_EQ(*it, j_value);
EXPECT_EQ((it - j_array.begin()), 2);
EXPECT_EQ(j_array, json({1, 2, 5, 5, 5, 3, 4}));
}
TEST_F(JsonInsertTest, CopyEnd)
{
auto it = j_array.insert(j_array.end(), 3, 5);
EXPECT_EQ(j_array.size(), 7u);
EXPECT_EQ(*it, j_value);
EXPECT_EQ((j_array.end() - it), 3);
EXPECT_EQ(j_array, json({1, 2, 3, 4, 5, 5, 5}));
}
TEST_F(JsonInsertTest, CopyNothing)
{
auto it = j_array.insert(j_array.end(), 0, 5);
EXPECT_EQ(j_array.size(), 4u);
// the returned iterator points to the first inserted element;
// there were 4 elements, so it should point to the 5th
EXPECT_EQ(it, j_array.begin() + 4);
EXPECT_EQ(j_array, json({1, 2, 3, 4}));
}
TEST_F(JsonInsertTest, RangeForArrayProper)
{
auto it = j_array.insert(j_array.end(), j_other_array.begin(), j_other_array.end());
EXPECT_EQ(j_array.size(), 6u);
EXPECT_EQ(*it, *j_other_array.begin());
EXPECT_EQ((j_array.end() - it), 2);
EXPECT_EQ(j_array, json({1, 2, 3, 4, "first", "second"}));
}
TEST_F(JsonInsertTest, RangeForArrayEmpty)
{
auto it = j_array.insert(j_array.end(), j_other_array.begin(), j_other_array.begin());
EXPECT_EQ(j_array.size(), 4u);
EXPECT_EQ(it, j_array.end());
EXPECT_EQ(j_array, json({1, 2, 3, 4}));
}
TEST_F(JsonInsertTest, RangeForArrayInvalid)
{
json j_other_array2 = {"first", "second"};
EXPECT_THROW_MSG(j_array.insert(j_array.end(), j_array.begin(), j_array.end()),
json::invalid_iterator,
"[json.exception.invalid_iterator.211] passed iterators may not belong to container");
EXPECT_THROW_MSG(j_array.insert(j_array.end(), j_other_array.begin(), j_other_array2.end()),
json::invalid_iterator,
"[json.exception.invalid_iterator.210] iterators do not fit");
}
TEST_F(JsonInsertTest, RangeForObjectProper)
{
j_object1.insert(j_object2.begin(), j_object2.end());
EXPECT_EQ(j_object1.size(), 4u);
}
TEST_F(JsonInsertTest, RangeForObjectEmpty)
{
j_object1.insert(j_object2.begin(), j_object2.begin());
EXPECT_EQ(j_object1.size(), 2u);
}
TEST_F(JsonInsertTest, RangeForObjectInvalid)
{
json j_other_array2 = {"first", "second"};
EXPECT_THROW_MSG(j_array.insert(j_object2.begin(), j_object2.end()), json::type_error,
"[json.exception.type_error.309] cannot use insert() with array");
EXPECT_THROW_MSG(j_object1.insert(j_object1.begin(), j_object2.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.210] iterators do not fit");
EXPECT_THROW_MSG(j_object1.insert(j_array.begin(), j_array.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.202] iterators first and last must point to objects");
}
TEST_F(JsonInsertTest, InitListBegin)
{
auto it = j_array.insert(j_array.begin(), {7, 8, 9});
EXPECT_EQ(j_array.size(), 7u);
EXPECT_EQ(*it, json(7));
EXPECT_EQ(j_array.begin(), it);
EXPECT_EQ(j_array, json({7, 8, 9, 1, 2, 3, 4}));
}
TEST_F(JsonInsertTest, InitListMiddle)
{
auto it = j_array.insert(j_array.begin() + 2, {7, 8, 9});
EXPECT_EQ(j_array.size(), 7u);
EXPECT_EQ(*it, json(7));
EXPECT_EQ((it - j_array.begin()), 2);
EXPECT_EQ(j_array, json({1, 2, 7, 8, 9, 3, 4}));
}
TEST_F(JsonInsertTest, InitListEnd)
{
auto it = j_array.insert(j_array.end(), {7, 8, 9});
EXPECT_EQ(j_array.size(), 7u);
EXPECT_EQ(*it, json(7));
EXPECT_EQ((j_array.end() - it), 3);
EXPECT_EQ(j_array, json({1, 2, 3, 4, 7, 8, 9}));
}
TEST_F(JsonInsertTest, InvalidIterator)
{
// pass iterator to a different array
json j_another_array = {1, 2};
json j_yet_another_array = {"first", "second"};
EXPECT_THROW_MSG(j_array.insert(j_another_array.end(), 10), json::invalid_iterator,
"[json.exception.invalid_iterator.202] iterator does not fit current value");
EXPECT_THROW_MSG(j_array.insert(j_another_array.end(), j_value), json::invalid_iterator,
"[json.exception.invalid_iterator.202] iterator does not fit current value");
EXPECT_THROW_MSG(j_array.insert(j_another_array.end(), 10, 11), json::invalid_iterator,
"[json.exception.invalid_iterator.202] iterator does not fit current value");
EXPECT_THROW_MSG(j_array.insert(j_another_array.end(), j_yet_another_array.begin(), j_yet_another_array.end()), json::invalid_iterator,
"[json.exception.invalid_iterator.202] iterator does not fit current value");
EXPECT_THROW_MSG(j_array.insert(j_another_array.end(), {1, 2, 3, 4}), json::invalid_iterator,
"[json.exception.invalid_iterator.202] iterator does not fit current value");
}
TEST_F(JsonInsertTest, NonArray)
{
// call insert on a non-array type
json j_nonarray = 3;
json j_yet_another_array = {"first", "second"};
EXPECT_THROW_MSG(j_nonarray.insert(j_nonarray.end(), 10), json::type_error,
"[json.exception.type_error.309] cannot use insert() with number");
EXPECT_THROW_MSG(j_nonarray.insert(j_nonarray.end(), j_value), json::type_error,
"[json.exception.type_error.309] cannot use insert() with number");
EXPECT_THROW_MSG(j_nonarray.insert(j_nonarray.end(), 10, 11), json::type_error,
"[json.exception.type_error.309] cannot use insert() with number");
EXPECT_THROW_MSG(j_nonarray.insert(j_nonarray.end(), j_yet_another_array.begin(),
j_yet_another_array.end()), json::type_error,
"[json.exception.type_error.309] cannot use insert() with number");
EXPECT_THROW_MSG(j_nonarray.insert(j_nonarray.end(), {1, 2, 3, 4}), json::type_error,
"[json.exception.type_error.309] cannot use insert() with number");
}
TEST(JsonSwapTest, JsonMember)
{
json j("hello world");
json k(42.23);
j.swap(k);
EXPECT_EQ(j, json(42.23));
EXPECT_EQ(k, json("hello world"));
}
TEST(JsonSwapTest, JsonNonMember)
{
json j("hello world");
json k(42.23);
std::swap(j, k);
EXPECT_EQ(j, json(42.23));
EXPECT_EQ(k, json("hello world"));
}
TEST(JsonSwapTest, ArrayT)
{
json j = {1, 2, 3, 4};
json::array_t a = {"foo", "bar", "baz"};
j.swap(a);
EXPECT_EQ(j, json({"foo", "bar", "baz"}));
j.swap(a);
EXPECT_EQ(j, json({1, 2, 3, 4}));
}
TEST(JsonSwapTest, NonArrayT)
{
json j = 17;
json::array_t a = {"foo", "bar", "baz"};
EXPECT_THROW_MSG(j.swap(a), json::type_error,
"[json.exception.type_error.310] cannot use swap() with number");
}
TEST(JsonSwapTest, ObjectT)
{
json j = {{"one", 1}, {"two", 2}};
json::object_t o = {{"cow", "Kuh"}, {"chicken", "Huhn"}};
j.swap(o);
EXPECT_EQ(j, json({{"cow", "Kuh"}, {"chicken", "Huhn"}}));
j.swap(o);
EXPECT_EQ(j, json({{"one", 1}, {"two", 2}}));
}
TEST(JsonSwapTest, NonObjectT)
{
json j = 17;
json::object_t o = {{"cow", "Kuh"}, {"chicken", "Huhn"}};
EXPECT_THROW_MSG(j.swap(o), json::type_error,
"[json.exception.type_error.310] cannot use swap() with number");
}
TEST(JsonSwapTest, StringT)
{
json j = "Hello world";
json::string_t s = "Hallo Welt";
j.swap(s);
EXPECT_EQ(j, json("Hallo Welt"));
j.swap(s);
EXPECT_EQ(j, json("Hello world"));
}
TEST(JsonSwapTest, NonStringT)
{
json j = 17;
json::string_t s = "Hallo Welt";
EXPECT_THROW_MSG(j.swap(s), json::type_error,
"[json.exception.type_error.310] cannot use swap() with number");
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,463 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
TEST(JsonPointerTest, TypesCreate)
{
// create a JSON value with different types
json json_types =
{
{"boolean", true},
{
"number", {
{"integer", 42},
{"unsigned", 42u},
{"floating-point", 17.23}
}
},
{"string", "Hello, world!"},
{"array", {1, 2, 3, 4, 5}},
{"null", nullptr}
};
}
// pointer access to object_t
TEST(JsonPointerTest, ObjectT)
{
using test_type = json::object_t;
json value = {{"one", 1}, {"two", 2}};
// check if pointers are returned correctly
test_type* p1 = value.get_ptr<test_type*>();
EXPECT_EQ(p1, value.get_ptr<test_type*>());
EXPECT_EQ(*p1, value.get<test_type>());
const test_type* p2 = value.get_ptr<const test_type*>();
EXPECT_EQ(p1, value.get_ptr<const test_type*>());
EXPECT_EQ(*p2, value.get<test_type>());
const test_type* const p3 = value.get_ptr<const test_type* const>();
EXPECT_EQ(p1, value.get_ptr<const test_type* const>());
EXPECT_EQ(*p3, value.get<test_type>());
// check if null pointers are returned correctly
EXPECT_NE(value.get_ptr<json::object_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::array_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::string_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::boolean_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_integer_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_unsigned_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_float_t*>(), nullptr);
}
// pointer access to const object_t
TEST(JsonPointerTest, ConstObjectT)
{
using test_type = const json::object_t;
const json value = {{"one", 1}, {"two", 2}};
// check if pointers are returned correctly
test_type* p1 = value.get_ptr<test_type*>();
EXPECT_EQ(p1, value.get_ptr<test_type*>());
EXPECT_EQ(*p1, value.get<test_type>());
const test_type* p2 = value.get_ptr<const test_type*>();
EXPECT_EQ(p1, value.get_ptr<const test_type*>());
EXPECT_EQ(*p2, value.get<test_type>());
const test_type* const p3 = value.get_ptr<const test_type* const>();
EXPECT_EQ(p1, value.get_ptr<const test_type* const>());
EXPECT_EQ(*p3, value.get<test_type>());
// check if null pointers are returned correctly
EXPECT_NE(value.get_ptr<const json::object_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::array_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::string_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::boolean_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_integer_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_unsigned_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_float_t*>(), nullptr);
}
// pointer access to array_t
TEST(JsonPointerTest, ArrayT)
{
using test_type = json::array_t;
json value = {1, 2, 3, 4};
// check if pointers are returned correctly
test_type* p1 = value.get_ptr<test_type*>();
EXPECT_EQ(p1, value.get_ptr<test_type*>());
EXPECT_EQ(*p1, value.get<test_type>());
const test_type* p2 = value.get_ptr<const test_type*>();
EXPECT_EQ(p1, value.get_ptr<const test_type*>());
EXPECT_EQ(*p2, value.get<test_type>());
const test_type* const p3 = value.get_ptr<const test_type* const>();
EXPECT_EQ(p1, value.get_ptr<const test_type* const>());
EXPECT_EQ(*p3, value.get<test_type>());
// check if null pointers are returned correctly
EXPECT_EQ(value.get_ptr<json::object_t*>(), nullptr);
EXPECT_NE(value.get_ptr<json::array_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::string_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::boolean_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_integer_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_unsigned_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_float_t*>(), nullptr);
}
// pointer access to const array_t
TEST(JsonPointerTest, ConstArrayT)
{
using test_type = const json::array_t;
const json value = {1, 2, 3, 4};
// check if pointers are returned correctly
test_type* p1 = value.get_ptr<test_type*>();
EXPECT_EQ(p1, value.get_ptr<test_type*>());
EXPECT_EQ(*p1, value.get<test_type>());
const test_type* p2 = value.get_ptr<const test_type*>();
EXPECT_EQ(p1, value.get_ptr<const test_type*>());
EXPECT_EQ(*p2, value.get<test_type>());
const test_type* const p3 = value.get_ptr<const test_type* const>();
EXPECT_EQ(p1, value.get_ptr<const test_type* const>());
EXPECT_EQ(*p3, value.get<test_type>());
// check if null pointers are returned correctly
EXPECT_EQ(value.get_ptr<const json::object_t*>(), nullptr);
EXPECT_NE(value.get_ptr<const json::array_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::string_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::boolean_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_integer_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_unsigned_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_float_t*>(), nullptr);
}
// pointer access to string_t
TEST(JsonPointerTest, StringT)
{
using test_type = json::string_t;
json value = "hello";
// check if pointers are returned correctly
test_type* p1 = value.get_ptr<test_type*>();
EXPECT_EQ(p1, value.get_ptr<test_type*>());
EXPECT_EQ(*p1, value.get<test_type>());
const test_type* p2 = value.get_ptr<const test_type*>();
EXPECT_EQ(p1, value.get_ptr<const test_type*>());
EXPECT_EQ(*p2, value.get<test_type>());
const test_type* const p3 = value.get_ptr<const test_type* const>();
EXPECT_EQ(p1, value.get_ptr<const test_type* const>());
EXPECT_EQ(*p3, value.get<test_type>());
// check if null pointers are returned correctly
EXPECT_EQ(value.get_ptr<json::object_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::array_t*>(), nullptr);
EXPECT_NE(value.get_ptr<json::string_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::boolean_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_integer_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_unsigned_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_float_t*>(), nullptr);
}
// pointer access to const string_t
TEST(JsonPointerTest, ConstStringT)
{
using test_type = const json::string_t;
const json value = "hello";
// check if pointers are returned correctly
test_type* p1 = value.get_ptr<test_type*>();
EXPECT_EQ(p1, value.get_ptr<test_type*>());
EXPECT_EQ(*p1, value.get<test_type>());
const test_type* p2 = value.get_ptr<const test_type*>();
EXPECT_EQ(p1, value.get_ptr<const test_type*>());
EXPECT_EQ(*p2, value.get<test_type>());
const test_type* const p3 = value.get_ptr<const test_type* const>();
EXPECT_EQ(p1, value.get_ptr<const test_type* const>());
EXPECT_EQ(*p3, value.get<test_type>());
// check if null pointers are returned correctly
EXPECT_EQ(value.get_ptr<const json::object_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::array_t*>(), nullptr);
EXPECT_NE(value.get_ptr<const json::string_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::boolean_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_integer_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_unsigned_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_float_t*>(), nullptr);
}
// pointer access to boolean_t
TEST(JsonPointerTest, BooleanT)
{
using test_type = json::boolean_t;
json value = false;
// check if pointers are returned correctly
test_type* p1 = value.get_ptr<test_type*>();
EXPECT_EQ(p1, value.get_ptr<test_type*>());
EXPECT_EQ(*p1, value.get<test_type>());
const test_type* p2 = value.get_ptr<const test_type*>();
EXPECT_EQ(p1, value.get_ptr<const test_type*>());
EXPECT_EQ(*p2, value.get<test_type>());
const test_type* const p3 = value.get_ptr<const test_type* const>();
EXPECT_EQ(p1, value.get_ptr<const test_type* const>());
EXPECT_EQ(*p3, value.get<test_type>());
// check if null pointers are returned correctly
EXPECT_EQ(value.get_ptr<json::object_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::array_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::string_t*>(), nullptr);
EXPECT_NE(value.get_ptr<json::boolean_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_integer_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_unsigned_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_float_t*>(), nullptr);
}
// pointer access to const boolean_t
TEST(JsonPointerTest, ConstBooleanT)
{
using test_type = const json::boolean_t;
const json value = false;
// check if pointers are returned correctly
test_type* p1 = value.get_ptr<test_type*>();
EXPECT_EQ(p1, value.get_ptr<test_type*>());
//EXPECT_EQ(*p1, value.get<test_type>());
//const test_type* p2 = value.get_ptr<const test_type*>();
EXPECT_EQ(p1, value.get_ptr<const test_type*>());
//EXPECT_EQ(*p2, value.get<test_type>());
//const test_type* const p3 = value.get_ptr<const test_type* const>();
EXPECT_EQ(p1, value.get_ptr<const test_type* const>());
//EXPECT_EQ(*p3, value.get<test_type>());
// check if null pointers are returned correctly
EXPECT_EQ(value.get_ptr<const json::object_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::array_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::string_t*>(), nullptr);
EXPECT_NE(value.get_ptr<const json::boolean_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_integer_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_unsigned_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_float_t*>(), nullptr);
}
// pointer access to number_integer_t
TEST(JsonPointerTest, IntegerT)
{
using test_type = json::number_integer_t;
json value = 23;
// check if pointers are returned correctly
test_type* p1 = value.get_ptr<test_type*>();
EXPECT_EQ(p1, value.get_ptr<test_type*>());
EXPECT_EQ(*p1, value.get<test_type>());
const test_type* p2 = value.get_ptr<const test_type*>();
EXPECT_EQ(p1, value.get_ptr<const test_type*>());
EXPECT_EQ(*p2, value.get<test_type>());
const test_type* const p3 = value.get_ptr<const test_type* const>();
EXPECT_EQ(p1, value.get_ptr<const test_type* const>());
EXPECT_EQ(*p3, value.get<test_type>());
// check if null pointers are returned correctly
EXPECT_EQ(value.get_ptr<json::object_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::array_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::string_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::boolean_t*>(), nullptr);
EXPECT_NE(value.get_ptr<json::number_integer_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_unsigned_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_float_t*>(), nullptr);
}
// pointer access to const number_integer_t
TEST(JsonPointerTest, ConstIntegerT)
{
using test_type = const json::number_integer_t;
const json value = 23;
// check if pointers are returned correctly
test_type* p1 = value.get_ptr<test_type*>();
EXPECT_EQ(p1, value.get_ptr<test_type*>());
EXPECT_EQ(*p1, value.get<test_type>());
const test_type* p2 = value.get_ptr<const test_type*>();
EXPECT_EQ(p1, value.get_ptr<const test_type*>());
EXPECT_EQ(*p2, value.get<test_type>());
const test_type* const p3 = value.get_ptr<const test_type* const>();
EXPECT_EQ(p1, value.get_ptr<const test_type* const>());
EXPECT_EQ(*p3, value.get<test_type>());
// check if null pointers are returned correctly
EXPECT_EQ(value.get_ptr<const json::object_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::array_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::string_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::boolean_t*>(), nullptr);
EXPECT_NE(value.get_ptr<const json::number_integer_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_unsigned_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_float_t*>(), nullptr);
}
// pointer access to number_unsigned_t
TEST(JsonPointerTest, UnsignedT)
{
using test_type = json::number_unsigned_t;
json value = 23u;
// check if pointers are returned correctly
test_type* p1 = value.get_ptr<test_type*>();
EXPECT_EQ(p1, value.get_ptr<test_type*>());
EXPECT_EQ(*p1, value.get<test_type>());
const test_type* p2 = value.get_ptr<const test_type*>();
EXPECT_EQ(p1, value.get_ptr<const test_type*>());
EXPECT_EQ(*p2, value.get<test_type>());
const test_type* const p3 = value.get_ptr<const test_type* const>();
EXPECT_EQ(p1, value.get_ptr<const test_type* const>());
EXPECT_EQ(*p3, value.get<test_type>());
// check if null pointers are returned correctly
EXPECT_EQ(value.get_ptr<json::object_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::array_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::string_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::boolean_t*>(), nullptr);
EXPECT_NE(value.get_ptr<json::number_integer_t*>(), nullptr);
EXPECT_NE(value.get_ptr<json::number_unsigned_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_float_t*>(), nullptr);
}
// pointer access to const number_unsigned_t
TEST(JsonPointerTest, ConstUnsignedT)
{
using test_type = const json::number_unsigned_t;
const json value = 23u;
// check if pointers are returned correctly
test_type* p1 = value.get_ptr<test_type*>();
EXPECT_EQ(p1, value.get_ptr<test_type*>());
EXPECT_EQ(*p1, value.get<test_type>());
const test_type* p2 = value.get_ptr<const test_type*>();
EXPECT_EQ(p1, value.get_ptr<const test_type*>());
EXPECT_EQ(*p2, value.get<test_type>());
const test_type* const p3 = value.get_ptr<const test_type* const>();
EXPECT_EQ(p1, value.get_ptr<const test_type* const>());
EXPECT_EQ(*p3, value.get<test_type>());
// check if null pointers are returned correctly
EXPECT_EQ(value.get_ptr<const json::object_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::array_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::string_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::boolean_t*>(), nullptr);
EXPECT_NE(value.get_ptr<const json::number_integer_t*>(), nullptr);
EXPECT_NE(value.get_ptr<const json::number_unsigned_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_float_t*>(), nullptr);
}
// pointer access to number_float_t
TEST(JsonPointerTest, FloatT)
{
using test_type = json::number_float_t;
json value = 42.23;
// check if pointers are returned correctly
test_type* p1 = value.get_ptr<test_type*>();
EXPECT_EQ(p1, value.get_ptr<test_type*>());
EXPECT_LT(std::fabs(*p1 - value.get<test_type>()), 0.001);
const test_type* p2 = value.get_ptr<const test_type*>();
EXPECT_EQ(p1, value.get_ptr<const test_type*>());
EXPECT_LT(std::fabs(*p2 - value.get<test_type>()), 0.001);
const test_type* const p3 = value.get_ptr<const test_type* const>();
EXPECT_EQ(p1, value.get_ptr<const test_type* const>());
EXPECT_LT(std::fabs(*p3 - value.get<test_type>()), 0.001);
// check if null pointers are returned correctly
EXPECT_EQ(value.get_ptr<json::object_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::array_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::string_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::boolean_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_integer_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<json::number_unsigned_t*>(), nullptr);
EXPECT_NE(value.get_ptr<json::number_float_t*>(), nullptr);
}
// pointer access to const number_float_t
TEST(JsonPointerTest, ConstFloatT)
{
using test_type = const json::number_float_t;
const json value = 42.23;
// check if pointers are returned correctly
test_type* p1 = value.get_ptr<test_type*>();
EXPECT_EQ(p1, value.get_ptr<test_type*>());
EXPECT_LT(std::fabs(*p1 - value.get<test_type>()), 0.001);
const test_type* p2 = value.get_ptr<const test_type*>();
EXPECT_EQ(p1, value.get_ptr<const test_type*>());
EXPECT_LT(std::fabs(*p2 - value.get<test_type>()), 0.001);
const test_type* const p3 = value.get_ptr<const test_type* const>();
EXPECT_EQ(p1, value.get_ptr<const test_type* const>());
EXPECT_LT(std::fabs(*p3 - value.get<test_type>()), 0.001);
// check if null pointers are returned correctly
EXPECT_EQ(value.get_ptr<const json::object_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::array_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::string_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::boolean_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_integer_t*>(), nullptr);
EXPECT_EQ(value.get_ptr<const json::number_unsigned_t*>(), nullptr);
EXPECT_NE(value.get_ptr<const json::number_float_t*>(), nullptr);
}

View File

@@ -0,0 +1,325 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
#include <array>
#include <deque>
#include <forward_list>
#include <list>
#include <map>
#include <unordered_map>
#include <unordered_set>
TEST(JsonReadmeTest, Basic)
{
// create an empty structure (null)
json j;
// add a number that is stored as double (note the implicit conversion of j to an object)
j["pi"] = 3.141;
// add a Boolean that is stored as bool
j["happy"] = true;
// add a string that is stored as std::string
j["name"] = "Niels";
// add another null object by passing nullptr
j["nothing"] = nullptr;
// add an object inside the object
j["answer"]["everything"] = 42;
// add an array that is stored as std::vector (using an initializer list)
j["list"] = { 1, 0, 2 };
// add another object (using an initializer list of pairs)
j["object"] = { {"currency", "USD"}, {"value", 42.99} };
// instead, you could also write (which looks very similar to the JSON above)
json j2 =
{
{"pi", 3.141},
{"happy", true},
{"name", "Niels"},
{"nothing", nullptr},
{
"answer", {
{"everything", 42}
}
},
{"list", {1, 0, 2}},
{
"object", {
{"currency", "USD"},
{"value", 42.99}
}
}
};
}
TEST(JsonReadmeTest, Other)
{
// ways to express the empty array []
json empty_array_implicit = {{}};
json empty_array_explicit = json::array();
// a way to express the empty object {}
json empty_object_explicit = json::object();
// a way to express an _array_ of key/value pairs [["currency", "USD"], ["value", 42.99]]
json array_not_object = { json::array({"currency", "USD"}), json::array({"value", 42.99}) };
}
TEST(JsonReadmeTest, FromToString)
{
// create object from string literal
json j = "{ \"happy\": true, \"pi\": 3.141 }"_json;
// or even nicer with a raw string literal
auto j2 = R"(
{
"happy": true,
"pi": 3.141
}
)"_json;
// or explicitly
auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }");
// explicit conversion to string
std::string s;
llvm::raw_string_ostream os(s);
j.dump(os); // {\"happy\":true,\"pi\":3.141}
EXPECT_EQ(os.str(), "{\"happy\":true,\"pi\":3.141}");
// serialization with pretty printing
// pass in the amount of spaces to indent
std::string s2;
llvm::raw_string_ostream os2(s2);
j2.dump(os2, 4);
EXPECT_EQ(os2.str(), "{\n \"happy\": true,\n \"pi\": 3.141\n}");
// {
// "happy": true,
// "pi": 3.141
// }
}
TEST(JsonReadmeTest, Basic2)
{
// create an array using push_back
json j;
j.push_back("foo");
j.push_back(1);
j.push_back(true);
std::string s;
llvm::raw_string_ostream os(s);
// iterate the array
for (json::iterator it = j.begin(); it != j.end(); ++it)
{
os << *it << '\n';
}
// range-based for
for (auto element : j)
{
os << element << '\n';
}
// comparison
bool x = (j == "[\"foo\", 1, true]"_json); // true
EXPECT_EQ(x, true);
// getter/setter
const std::string tmp = j[0];
j[1] = 42;
bool foo = j.at(2);
EXPECT_EQ(foo, true);
// other stuff
EXPECT_EQ(j.size(), 3u); // 3 entries
EXPECT_EQ(j.empty(), false);
EXPECT_EQ(j.type(), json::value_t::array);
j.clear(); // the array is empty again
EXPECT_EQ(j.size(), 0u);
EXPECT_EQ(j.empty(), true);
// create an object
json o;
o["foo"] = 23;
o["bar"] = false;
o["baz"] = 3.141;
// find an entry
if (o.find("foo") != o.end())
{
// there is an entry with key "foo"
}
}
TEST(JsonReadmeTest, OtherContainer)
{
std::vector<int> c_vector {1, 2, 3, 4};
json j_vec(c_vector);
json j_vec2(llvm::makeArrayRef(c_vector));
// [1, 2, 3, 4]
std::deque<float> c_deque {1.2f, 2.3f, 3.4f, 5.6f};
json j_deque(c_deque);
// [1.2, 2.3, 3.4, 5.6]
std::list<bool> c_list {true, true, false, true};
json j_list(c_list);
// [true, true, false, true]
std::forward_list<int64_t> c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543};
json j_flist(c_flist);
// [12345678909876, 23456789098765, 34567890987654, 45678909876543]
std::array<unsigned long, 4> c_array {{1, 2, 3, 4}};
json j_array(c_array);
// [1, 2, 3, 4]
std::set<std::string> c_set {"one", "two", "three", "four", "one"};
json j_set(c_set); // only one entry for "one" is used
// ["four", "one", "three", "two"]
std::unordered_set<std::string> c_uset {"one", "two", "three", "four", "one"};
json j_uset(c_uset); // only one entry for "one" is used
// maybe ["two", "three", "four", "one"]
std::multiset<std::string> c_mset {"one", "two", "one", "four"};
json j_mset(c_mset); // both entries for "one" are used
// maybe ["one", "two", "one", "four"]
std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"};
json j_umset(c_umset); // both entries for "one" are used
// maybe ["one", "two", "one", "four"]
}
TEST(JsonReadmeTest, MapContainer)
{
std::map<std::string, int> c_map { {"one", 1}, {"two", 2}, {"three", 3} };
json j_map(c_map);
// {"one": 1, "two": 2, "three": 3}
#if 0
std::unordered_map<const char*, float> c_umap { {"one", 1.2f}, {"two", 2.3f}, {"three", 3.4f} };
json j_umap(c_umap);
// {"one": 1.2, "two": 2.3, "three": 3.4}
#endif
std::multimap<std::string, bool> c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
json j_mmap(c_mmap); // only one entry for key "three" is used
// maybe {"one": true, "two": true, "three": true}
std::unordered_multimap<std::string, bool> c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
json j_ummap(c_ummap); // only one entry for key "three" is used
// maybe {"one": true, "two": true, "three": true}
}
TEST(JsonReadmeTest, Values)
{
// strings
std::string s1 = "Hello, world!";
json js = s1;
std::string s2 = js;
EXPECT_EQ(s1, s2);
// Booleans
bool b1 = true;
json jb = b1;
bool b2 = jb;
EXPECT_EQ(b1, b2);
// numbers
int i = 42;
json jn = i;
double f = jn;
EXPECT_EQ(i, f);
// etc.
std::string vs = js.get<std::string>();
bool vb = jb.get<bool>();
int vi = jn.get<int>();
EXPECT_EQ(s1, vs);
EXPECT_EQ(b1, vb);
EXPECT_EQ(i, vi);
// etc.
}
#if 0
TEST(JsonReadmeTest, DiffPatch)
{
// a JSON value
json j_original = R"({
"baz": ["one", "two", "three"],
"foo": "bar"
})"_json;
// access members with a JSON pointer (RFC 6901)
j_original["/baz/1"_json_pointer];
// "two"
// a JSON patch (RFC 6902)
json j_patch = R"([
{ "op": "replace", "path": "/baz", "value": "boo" },
{ "op": "add", "path": "/hello", "value": ["world"] },
{ "op": "remove", "path": "/foo"}
])"_json;
// apply the patch
json j_result = j_original.patch(j_patch);
// {
// "baz": "boo",
// "hello": ["world"]
// }
// calculate a JSON patch from two JSON values
json::diff(j_result, j_original);
// [
// { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] },
// { "op":"remove","path":"/hello" },
// { "op":"add","path":"/foo","value":"bar" }
// ]
}
#endif

View File

@@ -0,0 +1,197 @@
/*----------------------------------------------------------------------------*/
/* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "gtest/gtest.h"
#include "unit-json.h"
using wpi::json;
// reference access to object_t
TEST(JsonReferenceTest, ObjectT)
{
using test_type = json::object_t;
json value = {{"one", 1}, {"two", 2}};
// check if references are returned correctly
test_type& p1 = value.get_ref<test_type&>();
EXPECT_EQ(&p1, value.get_ptr<test_type*>());
EXPECT_EQ(p1, value.get<test_type>());
const test_type& p2 = value.get_ref<const test_type&>();
EXPECT_EQ(&p2, value.get_ptr<const test_type*>());
EXPECT_EQ(p2, value.get<test_type>());
// check if mismatching references throw correctly
EXPECT_NO_THROW(value.get_ref<json::object_t&>());
EXPECT_ANY_THROW(value.get_ref<json::array_t&>());
EXPECT_ANY_THROW(value.get_ref<json::string_t&>());
EXPECT_ANY_THROW(value.get_ref<json::boolean_t&>());
EXPECT_ANY_THROW(value.get_ref<json::number_integer_t&>());
EXPECT_ANY_THROW(value.get_ref<json::number_float_t&>());
}
// const reference access to const object_t
TEST(JsonReferenceTest, ConstObjectT)
{
using test_type = json::object_t;
const json value = {{"one", 1}, {"two", 2}};
// this should not compile
// test_type& p1 = value.get_ref<test_type&>();
// check if references are returned correctly
const test_type& p2 = value.get_ref<const test_type&>();
EXPECT_EQ(&p2, value.get_ptr<const test_type*>());
EXPECT_EQ(p2, value.get<test_type>());
}
// reference access to array_t
TEST(JsonReferenceTest, ArrayT)
{
using test_type = json::array_t;
json value = {1, 2, 3, 4};
// check if references are returned correctly
test_type& p1 = value.get_ref<test_type&>();
EXPECT_EQ(&p1, value.get_ptr<test_type*>());
EXPECT_EQ(p1, value.get<test_type>());
const test_type& p2 = value.get_ref<const test_type&>();
EXPECT_EQ(&p2, value.get_ptr<const test_type*>());
EXPECT_EQ(p2, value.get<test_type>());
// check if mismatching references throw correctly
EXPECT_ANY_THROW(value.get_ref<json::object_t&>());
EXPECT_NO_THROW(value.get_ref<json::array_t&>());
EXPECT_ANY_THROW(value.get_ref<json::string_t&>());
EXPECT_ANY_THROW(value.get_ref<json::boolean_t&>());
EXPECT_ANY_THROW(value.get_ref<json::number_integer_t&>());
EXPECT_ANY_THROW(value.get_ref<json::number_float_t&>());
}
// reference access to string_t
TEST(JsonReferenceTest, StringT)
{
using test_type = json::string_t;
json value = "hello";
// check if references are returned correctly
test_type& p1 = value.get_ref<test_type&>();
EXPECT_EQ(&p1, value.get_ptr<test_type*>());
EXPECT_EQ(p1, value.get<test_type>());
const test_type& p2 = value.get_ref<const test_type&>();
EXPECT_EQ(&p2, value.get_ptr<const test_type*>());
EXPECT_EQ(p2, value.get<test_type>());
// check if mismatching references throw correctly
EXPECT_ANY_THROW(value.get_ref<json::object_t&>());
EXPECT_ANY_THROW(value.get_ref<json::array_t&>());
EXPECT_NO_THROW(value.get_ref<json::string_t&>());
EXPECT_ANY_THROW(value.get_ref<json::boolean_t&>());
EXPECT_ANY_THROW(value.get_ref<json::number_integer_t&>());
EXPECT_ANY_THROW(value.get_ref<json::number_float_t&>());
}
// reference access to boolean_t
TEST(JsonReferenceTest, BooleanT)
{
using test_type = json::boolean_t;
json value = false;
// check if references are returned correctly
test_type& p1 = value.get_ref<test_type&>();
EXPECT_EQ(&p1, value.get_ptr<test_type*>());
EXPECT_EQ(p1, value.get<test_type>());
const test_type& p2 = value.get_ref<const test_type&>();
EXPECT_EQ(&p2, value.get_ptr<const test_type*>());
EXPECT_EQ(p2, value.get<test_type>());
// check if mismatching references throw correctly
EXPECT_ANY_THROW(value.get_ref<json::object_t&>());
EXPECT_ANY_THROW(value.get_ref<json::array_t&>());
EXPECT_ANY_THROW(value.get_ref<json::string_t&>());
EXPECT_NO_THROW(value.get_ref<json::boolean_t&>());
EXPECT_ANY_THROW(value.get_ref<json::number_integer_t&>());
EXPECT_ANY_THROW(value.get_ref<json::number_float_t&>());
}
// reference access to number_integer_t
TEST(JsonReferenceTest, IntegerT)
{
using test_type = json::number_integer_t;
json value = 23;
// check if references are returned correctly
test_type& p1 = value.get_ref<test_type&>();
EXPECT_EQ(&p1, value.get_ptr<test_type*>());
EXPECT_EQ(p1, value.get<test_type>());
const test_type& p2 = value.get_ref<const test_type&>();
EXPECT_EQ(&p2, value.get_ptr<const test_type*>());
EXPECT_EQ(p2, value.get<test_type>());
// check if mismatching references throw correctly
EXPECT_ANY_THROW(value.get_ref<json::object_t&>());
EXPECT_ANY_THROW(value.get_ref<json::array_t&>());
EXPECT_ANY_THROW(value.get_ref<json::string_t&>());
EXPECT_ANY_THROW(value.get_ref<json::boolean_t&>());
EXPECT_NO_THROW(value.get_ref<json::number_integer_t&>());
EXPECT_ANY_THROW(value.get_ref<json::number_float_t&>());
}
// reference access to number_float_t
TEST(JsonReferenceTest, FloatT)
{
using test_type = json::number_float_t;
json value = 42.23;
// check if references are returned correctly
test_type& p1 = value.get_ref<test_type&>();
EXPECT_EQ(&p1, value.get_ptr<test_type*>());
EXPECT_EQ(p1, value.get<test_type>());
const test_type& p2 = value.get_ref<const test_type&>();
EXPECT_EQ(&p2, value.get_ptr<const test_type*>());
EXPECT_EQ(p2, value.get<test_type>());
// check if mismatching references throw correctly
EXPECT_ANY_THROW(value.get_ref<json::object_t&>());
EXPECT_ANY_THROW(value.get_ref<json::array_t&>());
EXPECT_ANY_THROW(value.get_ref<json::string_t&>());
EXPECT_ANY_THROW(value.get_ref<json::boolean_t&>());
EXPECT_ANY_THROW(value.get_ref<json::number_integer_t&>());
EXPECT_NO_THROW(value.get_ref<json::number_float_t&>());
}

File diff suppressed because it is too large Load Diff