Merge branch 'develop' into feature/iterator_range_parsing

This commit is contained in:
Niels 2016-08-21 23:15:27 +02:00
commit cda84ba323
4 changed files with 199 additions and 16 deletions

View file

@ -28,13 +28,14 @@ SOFTWARE.
#include "catch.hpp"
#define private public
#include "json.hpp"
using nlohmann::json;
// special test case to check if memory is leaked if constructor throws
template<class T>
struct my_allocator : std::allocator<T>
struct bad_allocator : std::allocator<T>
{
template<class... Args>
void construct(T*, Args&& ...)
@ -48,16 +49,186 @@ TEST_CASE("bad_alloc")
SECTION("bad_alloc")
{
// create JSON type using the throwing allocator
using my_json = nlohmann::basic_json<std::map,
using bad_json = nlohmann::basic_json<std::map,
std::vector,
std::string,
bool,
std::int64_t,
std::uint64_t,
double,
my_allocator>;
bad_allocator>;
// creating an object should throw
CHECK_THROWS_AS(my_json j(my_json::value_t::object), std::bad_alloc);
CHECK_THROWS_AS(bad_json j(bad_json::value_t::object), std::bad_alloc);
}
}
bool next_construct_fails = false;
bool next_destroy_fails = false;
bool next_deallocate_fails = false;
template<class T>
struct my_allocator : std::allocator<T>
{
template<class... Args>
void construct(T* p, Args&& ... args)
{
if (next_construct_fails)
{
next_construct_fails = false;
throw std::bad_alloc();
}
else
{
::new(reinterpret_cast<void*>(p)) T(std::forward<Args>(args)...);
}
}
void deallocate(T* p, std::size_t n)
{
if (next_deallocate_fails)
{
next_deallocate_fails = false;
throw std::bad_alloc();
}
else
{
std::allocator<T>::deallocate(p, n);
}
}
void destroy(T* p)
{
if (next_destroy_fails)
{
next_destroy_fails = false;
throw std::bad_alloc();
}
else
{
p->~T();
}
}
};
TEST_CASE("controlled bad_alloc")
{
// create JSON type using the throwing allocator
using my_json = nlohmann::basic_json<std::map,
std::vector,
std::string,
bool,
std::int64_t,
std::uint64_t,
double,
my_allocator>;
SECTION("class json_value")
{
SECTION("json_value(value_t)")
{
SECTION("object")
{
next_construct_fails = false;
auto t = my_json::value_t::object;
CHECK_NOTHROW(my_json::json_value j(t));
next_construct_fails = true;
CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc);
next_construct_fails = false;
}
SECTION("array")
{
next_construct_fails = false;
auto t = my_json::value_t::array;
CHECK_NOTHROW(my_json::json_value j(t));
next_construct_fails = true;
CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc);
next_construct_fails = false;
}
SECTION("string")
{
next_construct_fails = false;
auto t = my_json::value_t::string;
CHECK_NOTHROW(my_json::json_value j(t));
next_construct_fails = true;
CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc);
next_construct_fails = false;
}
}
SECTION("json_value(const string_t&)")
{
next_construct_fails = false;
my_json::string_t v("foo");
CHECK_NOTHROW(my_json::json_value j(v));
next_construct_fails = true;
CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc);
next_construct_fails = false;
}
/*
SECTION("json_value(const object_t&)")
{
next_construct_fails = false;
my_json::object_t v {{"foo", "bar"}};
CHECK_NOTHROW(my_json::json_value j(v));
next_construct_fails = true;
CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc);
next_construct_fails = false;
}
*/
/*
SECTION("json_value(const array_t&)")
{
next_construct_fails = false;
my_json::array_t v = {"foo", "bar", "baz"};
CHECK_NOTHROW(my_json::json_value j(v));
next_construct_fails = true;
CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc);
next_construct_fails = false;
}
*/
}
SECTION("class basic_json")
{
SECTION("basic_json(const CompatibleObjectType&)")
{
next_construct_fails = false;
std::map<std::string, std::string> v {{"foo", "bar"}};
CHECK_NOTHROW(my_json j(v));
next_construct_fails = true;
CHECK_THROWS_AS(my_json j(v), std::bad_alloc);
next_construct_fails = false;
}
SECTION("basic_json(const CompatibleArrayType&)")
{
next_construct_fails = false;
std::vector<std::string> v {"foo", "bar", "baz"};
CHECK_NOTHROW(my_json j(v));
next_construct_fails = true;
CHECK_THROWS_AS(my_json j(v), std::bad_alloc);
next_construct_fails = false;
}
SECTION("basic_json(const typename string_t::value_type*)")
{
next_construct_fails = false;
CHECK_NOTHROW(my_json v("foo"));
next_construct_fails = true;
CHECK_THROWS_AS(my_json v("foo"), std::bad_alloc);
next_construct_fails = false;
}
SECTION("basic_json(const typename string_t::value_type*)")
{
next_construct_fails = false;
std::string s("foo");
CHECK_NOTHROW(my_json v(s));
next_construct_fails = true;
CHECK_THROWS_AS(my_json v(s), std::bad_alloc);
next_construct_fails = false;
}
}
}

View file

@ -447,6 +447,10 @@ TEST_CASE("parser class")
CHECK_THROWS_AS(json::parser("\"\\u0\"").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("\"\\u01\"").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("\"\\u012\"").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("\"\\u").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("\"\\u0").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("\"\\u01").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("\"\\u012").parse(), std::invalid_argument);
CHECK_THROWS_WITH(json::parser("\"").parse(),
"parse error - unexpected '\"'");
CHECK_THROWS_WITH(json::parser("\"\\\"").parse(),
@ -459,6 +463,14 @@ TEST_CASE("parser class")
"parse error - unexpected '\"'");
CHECK_THROWS_WITH(json::parser("\"\\u012\"").parse(),
"parse error - unexpected '\"'");
CHECK_THROWS_WITH(json::parser("\"\\u").parse(),
"parse error - unexpected '\"'");
CHECK_THROWS_WITH(json::parser("\"\\u0").parse(),
"parse error - unexpected '\"'");
CHECK_THROWS_WITH(json::parser("\"\\u01").parse(),
"parse error - unexpected '\"'");
CHECK_THROWS_WITH(json::parser("\"\\u012").parse(),
"parse error - unexpected '\"'");
// invalid escapes
for (int c = 1; c < 128; ++c)