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,105 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-2018 FIRST. 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. */
/*----------------------------------------------------------------------------*/
#include "gtest/gtest.h"
#include "llvm/SmallString.h"
#include "support/Base64.h"
namespace wpi {
struct Base64TestParam {
int plain_len;
const char* plain;
const char* encoded;
};
std::ostream& operator<<(std::ostream& os, const Base64TestParam& param) {
os << "Base64TestParam(Len: " << param.plain_len << ", "
<< "Plain: \"" << param.plain << "\", "
<< "Encoded: \"" << param.encoded << "\")";
return os;
}
class Base64Test : public ::testing::TestWithParam<Base64TestParam> {
protected:
llvm::StringRef GetPlain() {
if (GetParam().plain_len < 0)
return llvm::StringRef(GetParam().plain);
else
return llvm::StringRef(GetParam().plain, GetParam().plain_len);
}
};
TEST_P(Base64Test, EncodeStdString) {
std::string s;
Base64Encode(GetPlain(), &s);
ASSERT_EQ(GetParam().encoded, s);
// text already in s
Base64Encode(GetPlain(), &s);
ASSERT_EQ(GetParam().encoded, s);
}
TEST_P(Base64Test, EncodeSmallString) {
llvm::SmallString<128> buf;
ASSERT_EQ(GetParam().encoded, Base64Encode(GetPlain(), buf));
// reuse buf
ASSERT_EQ(GetParam().encoded, Base64Encode(GetPlain(), buf));
}
TEST_P(Base64Test, DecodeStdString) {
std::string s;
llvm::StringRef encoded = GetParam().encoded;
EXPECT_EQ(encoded.size(), Base64Decode(encoded, &s));
ASSERT_EQ(GetPlain(), s);
// text already in s
Base64Decode(encoded, &s);
ASSERT_EQ(GetPlain(), s);
}
TEST_P(Base64Test, DecodeSmallString) {
llvm::SmallString<128> buf;
llvm::StringRef encoded = GetParam().encoded;
size_t len;
llvm::StringRef plain = Base64Decode(encoded, &len, buf);
EXPECT_EQ(encoded.size(), len);
ASSERT_EQ(GetPlain(), plain);
// reuse buf
plain = Base64Decode(encoded, &len, buf);
ASSERT_EQ(GetPlain(), plain);
}
static Base64TestParam sample[] = {
{-1, "Send reinforcements", "U2VuZCByZWluZm9yY2VtZW50cw=="},
{-1, "Now is the time for all good coders\n to learn C++",
"Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKIHRvIGxlYXJuIEMrKw=="},
{-1,
"This is line one\nThis is line two\nThis is line three\nAnd so on...\n",
"VGhpcyBpcyBsaW5lIG9uZQpUaGlzIGlzIGxpbmUgdHdvClRoaXMgaXMgbGluZSB0aHJlZQpBb"
"mQgc28gb24uLi4K"},
};
INSTANTIATE_TEST_CASE_P(Base64Sample, Base64Test,
::testing::ValuesIn(sample), );
static Base64TestParam standard[] = {
{0, "", ""},
{1, "\0", "AA=="},
{2, "\0\0", "AAA="},
{3, "\0\0\0", "AAAA"},
{1, "\377", "/w=="},
{2, "\377\377", "//8="},
{3, "\377\377\377", "////"},
{2, "\xff\xef", "/+8="},
};
INSTANTIATE_TEST_CASE_P(Base64Standard, Base64Test,
::testing::ValuesIn(standard), );
} // namespace wpi

View File

@@ -0,0 +1,20 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2018 FIRST. 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. */
/*----------------------------------------------------------------------------*/
#include "support/hostname.h"
#include "gtest/gtest.h"
#include "llvm/SmallString.h"
#include "llvm/SmallVector.h"
namespace wpi {
TEST(HostNameTest, HostNameNotEmpty) { ASSERT_NE(wpi::GetHostname(), ""); }
TEST(HostNameTest, HostNameNotEmptySmallVector) {
llvm::SmallVector<char, 256> name;
ASSERT_NE(wpi::GetHostname(name), "");
}
} // namespace wpi

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

View File

@@ -0,0 +1,112 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-2018 FIRST. 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. */
/*----------------------------------------------------------------------------*/
//===- llvm/unittest/Support/LEB128Test.cpp - LEB128 function tests -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <stdint.h>
#include <string>
#include "gtest/gtest.h"
#include "llvm/SmallString.h"
#include "llvm/StringRef.h"
#include "support/leb128.h"
#include "support/raw_istream.h"
namespace wpi {
TEST(LEB128Test, WriteUleb128) {
#define EXPECT_ULEB128_EQ(EXPECTED, VALUE, PAD) \
do { \
llvm::StringRef expected(EXPECTED, sizeof(EXPECTED) - 1); \
llvm::SmallString<32> buf; \
size_t size = WriteUleb128(buf, VALUE); \
EXPECT_EQ(size, buf.size()); \
EXPECT_EQ(expected, buf.str()); \
} while (0)
// Write ULEB128
EXPECT_ULEB128_EQ("\x00", 0, 0);
EXPECT_ULEB128_EQ("\x01", 1, 0);
EXPECT_ULEB128_EQ("\x3f", 63, 0);
EXPECT_ULEB128_EQ("\x40", 64, 0);
EXPECT_ULEB128_EQ("\x7f", 0x7f, 0);
EXPECT_ULEB128_EQ("\x80\x01", 0x80, 0);
EXPECT_ULEB128_EQ("\x81\x01", 0x81, 0);
EXPECT_ULEB128_EQ("\x90\x01", 0x90, 0);
EXPECT_ULEB128_EQ("\xff\x01", 0xff, 0);
EXPECT_ULEB128_EQ("\x80\x02", 0x100, 0);
EXPECT_ULEB128_EQ("\x81\x02", 0x101, 0);
#undef EXPECT_ULEB128_EQ
}
TEST(LEB128Test, ReadUleb128) {
#define EXPECT_READ_ULEB128_EQ(EXPECTED, VALUE) \
do { \
uint64_t val = 0; \
size_t size = ReadUleb128(VALUE, &val); \
EXPECT_EQ(sizeof(VALUE) - 1, size); \
EXPECT_EQ(EXPECTED, val); \
} while (0)
// Read ULEB128
EXPECT_READ_ULEB128_EQ(0u, "\x00");
EXPECT_READ_ULEB128_EQ(1u, "\x01");
EXPECT_READ_ULEB128_EQ(63u, "\x3f");
EXPECT_READ_ULEB128_EQ(64u, "\x40");
EXPECT_READ_ULEB128_EQ(0x7fu, "\x7f");
EXPECT_READ_ULEB128_EQ(0x80u, "\x80\x01");
EXPECT_READ_ULEB128_EQ(0x81u, "\x81\x01");
EXPECT_READ_ULEB128_EQ(0x90u, "\x90\x01");
EXPECT_READ_ULEB128_EQ(0xffu, "\xff\x01");
EXPECT_READ_ULEB128_EQ(0x100u, "\x80\x02");
EXPECT_READ_ULEB128_EQ(0x101u, "\x81\x02");
EXPECT_READ_ULEB128_EQ(8320u, "\x80\xc1\x80\x80\x10");
#undef EXPECT_READ_ULEB128_EQ
}
TEST(LEB128Test, SizeUleb128) {
// Testing Plan:
// (1) 128 ^ n ............ need (n+1) bytes
// (2) 128 ^ n * 64 ....... need (n+1) bytes
// (3) 128 ^ (n+1) - 1 .... need (n+1) bytes
EXPECT_EQ(1u, SizeUleb128(0)); // special case
EXPECT_EQ(1u, SizeUleb128(0x1UL));
EXPECT_EQ(1u, SizeUleb128(0x40UL));
EXPECT_EQ(1u, SizeUleb128(0x7fUL));
EXPECT_EQ(2u, SizeUleb128(0x80UL));
EXPECT_EQ(2u, SizeUleb128(0x2000UL));
EXPECT_EQ(2u, SizeUleb128(0x3fffUL));
EXPECT_EQ(3u, SizeUleb128(0x4000UL));
EXPECT_EQ(3u, SizeUleb128(0x100000UL));
EXPECT_EQ(3u, SizeUleb128(0x1fffffUL));
EXPECT_EQ(4u, SizeUleb128(0x200000UL));
EXPECT_EQ(4u, SizeUleb128(0x8000000UL));
EXPECT_EQ(4u, SizeUleb128(0xfffffffUL));
EXPECT_EQ(5u, SizeUleb128(0x10000000UL));
EXPECT_EQ(5u, SizeUleb128(0x40000000UL));
EXPECT_EQ(5u, SizeUleb128(0x7fffffffUL));
EXPECT_EQ(5u, SizeUleb128(UINT32_MAX));
}
} // namespace wpi

View File

@@ -0,0 +1,14 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-2018 FIRST. 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. */
/*----------------------------------------------------------------------------*/
#include "gtest/gtest.h"
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
}

View File

@@ -0,0 +1,300 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. 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. */
/*----------------------------------------------------------------------------*/
#include <support/priority_condition_variable.h>
#include <support/priority_mutex.h>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <thread>
#include "gtest/gtest.h"
namespace wpi {
#ifdef WPI_HAVE_PRIORITY_CONDITION_VARIABLE
// Tests that the condition variable class which we wrote ourselves actually
// does work.
class ConditionVariableTest : public ::testing::Test {
protected:
typedef std::unique_lock<priority_mutex> priority_lock;
// Condition variable to test.
priority_condition_variable m_cond;
// Mutex to pass to condition variable when waiting.
priority_mutex m_mutex;
// flags for testing when threads are completed.
std::atomic<bool> m_done1{false}, m_done2{false};
// Threads to use for testing. We want multiple threads to ensure that it
// behaves correctly when multiple processes are waiting on a signal.
std::thread m_watcher1, m_watcher2;
// Information for when running with predicates.
std::atomic<bool> m_pred_var{false};
void ShortSleep(uint32_t time = 10) {
std::this_thread::sleep_for(std::chrono::milliseconds(time));
}
// Start up the given threads with a wait function. The wait function should
// call some version of m_cond.wait and should take as an argument a reference
// to an std::atomic<bool> which it will set to true when it is ready to have
// join called on it.
template <class Function>
void StartThreads(Function wait) {
m_watcher1 = std::thread(wait, std::ref(m_done1));
m_watcher2 = std::thread(wait, std::ref(m_done2));
// Wait briefly to let the lock be unlocked.
ShortSleep();
bool locked = m_mutex.try_lock();
if (locked) m_mutex.unlock();
EXPECT_TRUE(locked) << "The condition variable failed to unlock the lock.";
}
void NotifyAll() { m_cond.notify_all(); }
void NotifyOne() { m_cond.notify_one(); }
// Test that all the threads are notified by a notify_all() call.
void NotifyAllTest() {
NotifyAll();
// Wait briefly to let the lock be re-locked.
ShortSleep();
EXPECT_TRUE(m_done1) << "watcher1 failed to be notified.";
EXPECT_TRUE(m_done2) << "watcher2 failed to be notified.";
}
// For use when testing predicates. First tries signalling the threads with
// the predicate set to false (and ensures that they do not activate) and then
// tests with the predicate set to true.
void PredicateTest() {
m_pred_var = false;
NotifyAll();
ShortSleep();
EXPECT_FALSE(m_done1) << "watcher1 didn't pay attention to its predicate.";
EXPECT_FALSE(m_done2) << "watcher2 didn't pay attention to its predicate.";
m_pred_var = true;
NotifyAllTest();
}
// Used by the WaitFor and WaitUntil tests to test that, without a predicate,
// the timeout works properly.
void WaitTimeTest(bool wait_for) {
std::atomic<bool> timed_out{true};
auto wait_until = [this, &timed_out, wait_for](std::atomic<bool>& done) {
priority_lock lock(m_mutex);
done = false;
if (wait_for) {
auto wait_time = std::chrono::milliseconds(100);
timed_out = m_cond.wait_for(lock, wait_time) == std::cv_status::timeout;
} else {
auto wait_time =
std::chrono::system_clock::now() + std::chrono::milliseconds(100);
timed_out =
m_cond.wait_until(lock, wait_time) == std::cv_status::timeout;
}
EXPECT_TRUE(lock.owns_lock())
<< "The condition variable should have reacquired the lock.";
done = true;
};
// First, test without timing out.
timed_out = true;
StartThreads(wait_until);
NotifyAllTest();
EXPECT_FALSE(timed_out) << "The watcher should not have timed out.";
TearDown();
// Next, test and time out.
timed_out = false;
StartThreads(wait_until);
ShortSleep(110);
EXPECT_TRUE(m_done1) << "watcher1 should have timed out.";
EXPECT_TRUE(m_done2) << "watcher2 should have timed out.";
EXPECT_TRUE(timed_out) << "The watcher should have timed out.";
}
// For use with tests that have a timeout and a predicate.
void WaitTimePredicateTest(bool wait_for) {
// The condition_variable return value from the wait_for or wait_until
// function should in the case of having a predicate, by a boolean. If the
// predicate is true, then the return value will always be true. If the
// condition times out and, at the time of the timeout, the predicate is
// false, the return value will be false.
std::atomic<bool> retval{true};
auto predicate = [this]() -> bool { return m_pred_var; };
auto wait_until = [this, &retval, predicate,
wait_for](std::atomic<bool>& done) {
priority_lock lock(m_mutex);
done = false;
if (wait_for) {
auto wait_time = std::chrono::milliseconds(100);
retval = m_cond.wait_for(lock, wait_time, predicate);
} else {
auto wait_time =
std::chrono::system_clock::now() + std::chrono::milliseconds(100);
retval = m_cond.wait_until(lock, wait_time, predicate);
}
EXPECT_TRUE(lock.owns_lock())
<< "The condition variable should have reacquired the lock.";
done = true;
};
// Test without timing out and with the predicate set to true.
retval = true;
m_pred_var = true;
StartThreads(wait_until);
NotifyAllTest();
EXPECT_TRUE(retval) << "The watcher should not have timed out.";
TearDown();
// Test with timing out and with the predicate set to true.
retval = false;
m_pred_var = false;
StartThreads(wait_until);
ShortSleep(110);
EXPECT_TRUE(m_done1) << "watcher1 should have finished.";
EXPECT_TRUE(m_done2) << "watcher2 should have finished.";
EXPECT_FALSE(retval) << "The watcher should have timed out.";
TearDown();
// Test without timing out and run the PredicateTest().
retval = false;
StartThreads(wait_until);
PredicateTest();
EXPECT_TRUE(retval) << "The return value should have been true.";
TearDown();
// Test with timing out and the predicate set to true while we are waiting
// for the condition variable to time out.
retval = true;
StartThreads(wait_until);
ShortSleep();
m_pred_var = true;
ShortSleep(110);
EXPECT_TRUE(retval) << "The return value should have been true.";
}
virtual void TearDown() {
// If a thread has not completed, then continuing will cause the tests to
// hang forever and could cause issues. If we don't call detach, then
// std::terminate is called and all threads are terminated.
// Detaching is non-optimal, but should allow the rest of the tests to run
// before anything drastic occurs.
if (m_done1)
m_watcher1.join();
else
m_watcher1.detach();
if (m_done2)
m_watcher2.join();
else
m_watcher2.detach();
}
};
TEST_F(ConditionVariableTest, NotifyAll) {
auto wait = [this](std::atomic<bool>& done) {
priority_lock lock(m_mutex);
done = false;
m_cond.wait(lock);
EXPECT_TRUE(lock.owns_lock())
<< "The condition variable should have reacquired the lock.";
done = true;
};
StartThreads(wait);
NotifyAllTest();
}
TEST_F(ConditionVariableTest, NotifyOne) {
auto wait = [this](std::atomic<bool>& done) {
priority_lock lock(m_mutex);
done = false;
m_cond.wait(lock);
EXPECT_TRUE(lock.owns_lock())
<< "The condition variable should have reacquired the lock.";
done = true;
};
StartThreads(wait);
NotifyOne();
// Wait briefly to let things settle.
ShortSleep();
EXPECT_TRUE(m_done1 ^ m_done2) << "Only one thread should've been notified.";
NotifyOne();
ShortSleep();
EXPECT_TRUE(m_done2 && m_done2) << "Both threads should've been notified.";
}
TEST_F(ConditionVariableTest, WaitWithPredicate) {
auto predicate = [this]() -> bool { return m_pred_var; };
auto wait_predicate = [this, predicate](std::atomic<bool>& done) {
priority_lock lock(m_mutex);
done = false;
m_cond.wait(lock, predicate);
EXPECT_TRUE(lock.owns_lock())
<< "The condition variable should have reacquired the lock.";
done = true;
};
StartThreads(wait_predicate);
PredicateTest();
}
TEST_F(ConditionVariableTest, WaitUntil) { WaitTimeTest(false); }
TEST_F(ConditionVariableTest, WaitUntilWithPredicate) {
WaitTimePredicateTest(false);
}
TEST_F(ConditionVariableTest, WaitFor) { WaitTimeTest(true); }
TEST_F(ConditionVariableTest, WaitForWithPredicate) {
WaitTimePredicateTest(true);
}
TEST_F(ConditionVariableTest, NativeHandle) {
auto wait = [this](std::atomic<bool>& done) {
priority_lock lock(m_mutex);
done = false;
m_cond.wait(lock);
EXPECT_TRUE(lock.owns_lock())
<< "The condition variable should have reacquired the lock.";
done = true;
};
StartThreads(wait);
pthread_cond_t* native_handle = m_cond.native_handle();
pthread_cond_broadcast(native_handle);
ShortSleep();
EXPECT_TRUE(m_done1) << "watcher1 failed to be notified.";
EXPECT_TRUE(m_done2) << "watcher2 failed to be notified.";
}
#endif // WPI_HAVE_PRIORITY_CONDITION_VARIABLE
} // namespace wpi

View File

@@ -0,0 +1,271 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. 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. */
/*----------------------------------------------------------------------------*/
#include <support/priority_mutex.h> // NOLINT(build/include_order)
#include <atomic>
#include <condition_variable>
#include <thread>
#include "gtest/gtest.h"
namespace wpi {
#ifdef WPI_HAVE_PRIORITY_MUTEX
using std::chrono::system_clock;
// Threading primitive used to notify many threads that a condition is now true.
// The condition can not be cleared.
class Notification {
public:
// Efficiently waits until the Notification has been notified once.
void Wait() {
std::unique_lock<priority_mutex> lock(m_mutex);
while (!m_set) {
m_condition.wait(lock);
}
}
// Sets the condition to true, and wakes all waiting threads.
void Notify() {
std::lock_guard<priority_mutex> lock(m_mutex);
m_set = true;
m_condition.notify_all();
}
private:
// priority_mutex used for the notification and to protect the bit.
priority_mutex m_mutex;
// Condition for threads to sleep on.
std::condition_variable_any m_condition;
// Bool which is true when the notification has been notified.
bool m_set = false;
};
void SetProcessorAffinity(int32_t core_id) {
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(core_id, &cpuset);
pthread_t current_thread = pthread_self();
ASSERT_EQ(pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset),
0);
}
void SetThreadRealtimePriorityOrDie(int32_t priority) {
struct sched_param param;
// Set realtime priority for this thread
param.sched_priority = priority + sched_get_priority_min(SCHED_RR);
ASSERT_EQ(pthread_setschedparam(pthread_self(), SCHED_RR, &param), 0)
<< ": Failed to set scheduler priority.";
}
// This thread holds the mutex and spins until signaled to release it and stop.
template <typename MutexType>
class LowPriorityThread {
public:
explicit LowPriorityThread(MutexType* mutex)
: m_mutex(mutex), m_hold_mutex(1), m_success(0) {}
void operator()() {
SetProcessorAffinity(0);
SetThreadRealtimePriorityOrDie(20);
m_mutex->lock();
m_started.Notify();
while (m_hold_mutex.test_and_set()) {
}
m_mutex->unlock();
m_success.store(1);
}
void WaitForStartup() { m_started.Wait(); }
void release_mutex() { m_hold_mutex.clear(); }
bool success() { return m_success.load(); }
private:
// priority_mutex to grab and release.
MutexType* m_mutex;
Notification m_started;
// Atomic type used to signal when the thread should unlock the mutex.
// Using a mutex to protect something could cause other issues, and a delay
// between setting and reading isn't a problem as long as the set is atomic.
std::atomic_flag m_hold_mutex;
std::atomic<int> m_success;
};
// This thread spins forever until signaled to stop.
class BusyWaitingThread {
public:
BusyWaitingThread() : m_run(1), m_success(0) {}
void operator()() {
SetProcessorAffinity(0);
SetThreadRealtimePriorityOrDie(21);
system_clock::time_point start_time = system_clock::now();
m_started.Notify();
while (m_run.test_and_set()) {
// Have the busy waiting thread time out after a while. If it times out,
// the test failed.
if (system_clock::now() - start_time > std::chrono::milliseconds(50)) {
return;
}
}
m_success.store(1);
}
void quit() { m_run.clear(); }
void WaitForStartup() { m_started.Wait(); }
bool success() { return m_success.load(); }
private:
// Use an atomic type to signal if the thread should be running or not. A
// mutex could affect the scheduler, which isn't worth it. A delay between
// setting and reading the new value is fine.
std::atomic_flag m_run;
Notification m_started;
std::atomic<int> m_success;
};
// This thread starts up, grabs the mutex, and then exits.
template <typename MutexType>
class HighPriorityThread {
public:
explicit HighPriorityThread(MutexType* mutex) : m_mutex(mutex) {}
void operator()() {
SetProcessorAffinity(0);
SetThreadRealtimePriorityOrDie(22);
m_started.Notify();
m_mutex->lock();
m_success.store(1);
}
void WaitForStartup() { m_started.Wait(); }
bool success() { return m_success.load(); }
private:
Notification m_started;
MutexType* m_mutex;
std::atomic<int> m_success{0};
};
// Class to test a MutexType to see if it solves the priority inheritance
// problem.
//
// To run the test, we need 3 threads, and then 1 thread to kick the test off.
// The threads must all run on the same core, otherwise they wouldn't starve
// eachother. The threads and their roles are as follows:
//
// Low priority thread:
// Holds a lock that the high priority thread needs, and releases it upon
// request.
// Medium priority thread:
// Hogs the processor so that the low priority thread will never run if it's
// priority doesn't get bumped.
// High priority thread:
// Starts up and then goes to grab the lock that the low priority thread has.
//
// Control thread:
// Sets the deadlock up so that it will happen 100% of the time by making sure
// that each thread in order gets to the point that it needs to be at to cause
// the deadlock.
template <typename MutexType>
class InversionTestRunner {
public:
void operator()() {
// This thread must run at the highest priority or it can't coordinate the
// inversion. This means that it can't busy wait or everything could
// starve.
SetThreadRealtimePriorityOrDie(23);
MutexType m;
// Start the lowest priority thread and wait until it holds the lock.
LowPriorityThread<MutexType> low(&m);
std::thread low_thread(std::ref(low));
low.WaitForStartup();
// Start the busy waiting thread and let it get to the loop.
BusyWaitingThread busy;
std::thread busy_thread(std::ref(busy));
busy.WaitForStartup();
// Start the high priority thread and let it become blocked on the lock.
HighPriorityThread<MutexType> high(&m);
std::thread high_thread(std::ref(high));
high.WaitForStartup();
// Startup and locking the mutex in the high priority thread aren't atomic,
// but pretty close. Wait a bit to let it happen.
std::this_thread::sleep_for(std::chrono::milliseconds(10));
// Release the mutex in the low priority thread. If done right, everything
// should finish now.
low.release_mutex();
// Wait for everything to finish and compute success.
high_thread.join();
busy.quit();
busy_thread.join();
low_thread.join();
m_success = low.success() && busy.success() && high.success();
}
bool success() { return m_success; }
private:
bool m_success = false;
};
// TODO: Fix roborio permissions to run as root.
// Priority inversion test.
TEST(MutexTest, DISABLED_PriorityInversionTest) {
InversionTestRunner<priority_mutex> runner;
std::thread runner_thread(std::ref(runner));
runner_thread.join();
EXPECT_TRUE(runner.success());
}
// Verify that the non-priority inversion mutex doesn't pass the test.
TEST(MutexTest, DISABLED_StdMutexPriorityInversionTest) {
InversionTestRunner<std::mutex> runner;
std::thread runner_thread(std::ref(runner));
runner_thread.join();
EXPECT_FALSE(runner.success());
}
// Smoke test to make sure that mutexes lock and unlock.
TEST(MutexTest, TryLock) {
priority_mutex m;
m.lock();
EXPECT_FALSE(m.try_lock());
m.unlock();
EXPECT_TRUE(m.try_lock());
}
// Priority inversion test.
TEST(MutexTest, DISABLED_ReentrantPriorityInversionTest) {
InversionTestRunner<priority_recursive_mutex> runner;
std::thread runner_thread(std::ref(runner));
runner_thread.join();
EXPECT_TRUE(runner.success());
}
// Smoke test to make sure that mutexes lock and unlock.
TEST(MutexTest, ReentrantTryLock) {
priority_recursive_mutex m;
m.lock();
EXPECT_TRUE(m.try_lock());
m.unlock();
EXPECT_TRUE(m.try_lock());
}
#endif // WPI_HAVE_PRIORITY_MUTEX
} // namespace wpi

View File

@@ -0,0 +1,92 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2018 FIRST. 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. */
/*----------------------------------------------------------------------------*/
/*
test_sha1.cpp - test program of
============
SHA-1 in C++
============
100% Public Domain.
Original C Code
-- Steve Reid <steve@edmweb.com>
Small changes to fit into bglibs
-- Bruce Guenter <bruce@untroubled.org>
Translation to simpler C++ Code
-- Volker Grabsch <vog@notjusthosting.com>
*/
#include <string>
#include "gtest/gtest.h"
#include "support/sha1.h"
namespace wpi {
/*
* The 3 test vectors from FIPS PUB 180-1
*/
TEST(SHA1Test, Standard1) {
SHA1 checksum;
checksum.Update("abc");
ASSERT_EQ(checksum.Final(), "a9993e364706816aba3e25717850c26c9cd0d89d");
}
TEST(SHA1Test, Standard2) {
SHA1 checksum;
checksum.Update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
ASSERT_EQ(checksum.Final(), "84983e441c3bd26ebaae4aa1f95129e5e54670f1");
}
TEST(SHA1Test, Standard3) {
SHA1 checksum;
// A million repetitions of 'a'
for (int i = 0; i < 1000000 / 200; ++i) {
checksum.Update(
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
}
ASSERT_EQ(checksum.Final(), "34aa973cd4c4daa4f61eeb2bdbad27316534016f");
}
/*
* Other tests
*/
TEST(SHA1Test, OtherNoString) {
SHA1 checksum;
ASSERT_EQ(checksum.Final(), "da39a3ee5e6b4b0d3255bfef95601890afd80709");
}
TEST(SHA1Test, OtherEmptyString) {
SHA1 checksum;
checksum.Update("");
ASSERT_EQ(checksum.Final(), "da39a3ee5e6b4b0d3255bfef95601890afd80709");
}
TEST(SHA1Test, OtherABCDE) {
SHA1 checksum;
checksum.Update("abcde");
ASSERT_EQ(checksum.Final(), "03de6c570bfe24bfc328ccd7ca46b76eadaf4334");
}
TEST(SHA1Test, Concurrent) {
// Two concurrent checksum calculations
SHA1 checksum1, checksum2;
checksum1.Update("abc");
ASSERT_EQ(checksum2.Final(),
"da39a3ee5e6b4b0d3255bfef95601890afd80709"); /* "" */
ASSERT_EQ(checksum1.Final(),
"a9993e364706816aba3e25717850c26c9cd0d89d"); /* "abc" */
}
} // namespace wpi