2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // Official repository: https://github.com/boostorg/json
10 #ifndef BOOST_JSON_TEST_HPP
11 #define BOOST_JSON_TEST_HPP
13 #include <boost/json/basic_parser.hpp>
14 #include <boost/json/value.hpp>
15 #include <boost/json/serializer.hpp>
16 #include <boost/json/storage_ptr.hpp>
17 #include <boost/json/detail/format.hpp>
22 #include <type_traits>
24 #include "test_suite.hpp"
28 //----------------------------------------------------------
30 struct test_failure : std::exception
34 what() const noexcept override
36 return "test failure";
43 std::size_t fail_max = 0;
45 std::size_t nalloc = 0;
46 std::size_t bytes = 0;
50 BOOST_TEST(nalloc == 0);
58 if(++fail == fail_max)
64 auto p = ::operator new(n);
74 std::size_t) noexcept override
76 if(BOOST_TEST(nalloc > 0))
84 memory_resource const& mr) const noexcept override
102 catch(test_failure const&)
108 BOOST_TEST(ss.fail < 200);
111 //----------------------------------------------------------
113 struct unique_resource
116 unique_resource() = default;
121 std::size_t) override
123 return ::operator new(n);
130 std::size_t) noexcept override
132 return ::operator delete(p);
137 memory_resource const& mr) const noexcept override
143 //----------------------------------------------------------
145 // The null parser discards all the data
151 constexpr static std::size_t max_object_size = std::size_t(-1);
152 constexpr static std::size_t max_array_size = std::size_t(-1);
153 constexpr static std::size_t max_key_size = std::size_t(-1);
154 constexpr static std::size_t max_string_size = std::size_t(-1);
156 bool on_document_begin( error_code& ) { return true; }
157 bool on_document_end( error_code& ) { return true; }
158 bool on_object_begin( error_code& ) { return true; }
159 bool on_object_end( std::size_t, error_code& ) { return true; }
160 bool on_array_begin( error_code& ) { return true; }
161 bool on_array_end( std::size_t, error_code& ) { return true; }
162 bool on_key_part( string_view, std::size_t, error_code& ) { return true; }
163 bool on_key( string_view, std::size_t, error_code& ) { return true; }
164 bool on_string_part( string_view, std::size_t, error_code& ) { return true; }
165 bool on_string( string_view, std::size_t, error_code& ) { return true; }
166 bool on_number_part( string_view, error_code&) { return true; }
167 bool on_int64( std::int64_t, string_view, error_code& ) { return true; }
168 bool on_uint64( std::uint64_t, string_view, error_code& ) { return true; }
169 bool on_double( double, string_view, error_code& ) { return true; }
170 bool on_bool( bool, error_code& ) { return true; }
171 bool on_null( error_code& ) { return true; }
172 bool on_comment_part( string_view, error_code& ) { return true; }
173 bool on_comment( string_view, error_code& ) { return true; }
176 basic_parser<handler> p_;
180 : p_(parse_options())
185 null_parser(parse_options po)
202 auto const n = p_.write_some(
203 false, data, size, ec);
205 ec = error::extra_data;
210 //----------------------------------------------------------
216 constexpr static std::size_t max_object_size = std::size_t(-1);
217 constexpr static std::size_t max_array_size = std::size_t(-1);
218 constexpr static std::size_t max_key_size = std::size_t(-1);
219 constexpr static std::size_t max_string_size = std::size_t(-1);
229 maybe_fail(error_code& ec)
233 ec = error::test_failure;
241 return maybe_fail(ec);
248 return maybe_fail(ec);
255 return maybe_fail(ec);
263 return maybe_fail(ec);
270 return maybe_fail(ec);
278 return maybe_fail(ec);
287 return maybe_fail(ec);
296 return maybe_fail(ec);
305 return maybe_fail(ec);
314 return maybe_fail(ec);
322 return maybe_fail(ec);
331 return maybe_fail(ec);
340 return maybe_fail(ec);
349 return maybe_fail(ec);
357 return maybe_fail(ec);
361 on_null(error_code& ec)
363 return maybe_fail(ec);
371 return maybe_fail(ec);
379 return maybe_fail(ec);
383 basic_parser<handler> p_;
387 : p_(parse_options())
394 parse_options po = parse_options())
401 fail_parser(parse_options po)
413 done() const noexcept
425 return p_.write_some(
426 more, data, size, ec);
436 auto const n = p_.write_some(
437 more, data, size, ec);
439 ec = error::extra_data;
444 //----------------------------------------------------------
446 struct test_exception
450 what() const noexcept
452 return "test exception";
456 // Exercises every exception path
461 constexpr static std::size_t max_object_size = std::size_t(-1);
462 constexpr static std::size_t max_array_size = std::size_t(-1);
463 constexpr static std::size_t max_key_size = std::size_t(-1);
464 constexpr static std::size_t max_string_size = std::size_t(-1);
478 throw test_exception{};
485 return maybe_throw();
492 return maybe_throw();
499 return maybe_throw();
507 return maybe_throw();
514 return maybe_throw();
522 return maybe_throw();
531 return maybe_throw();
540 return maybe_throw();
549 return maybe_throw();
558 return maybe_throw();
566 return maybe_throw();
575 return maybe_throw();
584 return maybe_throw();
593 return maybe_throw();
601 return maybe_throw();
607 return maybe_throw();
615 return maybe_throw();
623 return maybe_throw();
627 basic_parser<handler> p_;
631 : p_(parse_options())
638 parse_options po = parse_options())
645 throw_parser(parse_options po)
663 auto const n = p_.write_some(
664 more, data, size, ec);
666 ec = error::extra_data;
671 //----------------------------------------------------------
673 // wrap an iterator to make an input iterator
674 template<class FwdIt>
680 using value_type = typename std::iterator_traits<FwdIt>::value_type;
681 using pointer = typename std::iterator_traits<FwdIt>::pointer;
682 using reference = typename std::iterator_traits<FwdIt>::reference;
683 using difference_type = typename std::iterator_traits<FwdIt>::difference_type;
684 using iterator_category = std::input_iterator_tag;
686 input_iterator() = default;
687 input_iterator(input_iterator const&) = default;
688 input_iterator& operator=(
689 input_iterator const&) = default;
691 input_iterator(FwdIt it)
697 operator++() noexcept
704 operator++(int) noexcept
712 operator->() const noexcept
714 return it_.operator->();
718 operator*() const noexcept
724 operator==(input_iterator other) const noexcept
726 return it_ == other.it_;
730 operator!=(input_iterator other) const noexcept
732 return it_ != other.it_;
736 template<class FwdIt>
737 input_iterator<FwdIt>
738 make_input_iterator(FwdIt it)
740 return input_iterator<FwdIt>(it);
743 //----------------------------------------------------------
749 storage_ptr const& sp);
755 storage_ptr const& sp)
757 if(*o.storage() != *sp)
759 for(auto const& e : o)
760 if(! equal_storage(e.value(), sp))
769 storage_ptr const& sp)
771 if(*a.storage() != *sp)
773 for(auto const& v : a)
774 if(! equal_storage(v, sp))
782 storage_ptr const& sp)
786 case json::kind::object:
787 if(*v.as_object().storage() != *sp)
789 return equal_storage(v.as_object(), sp);
791 case json::kind::array:
792 if(*v.as_array().storage() != *sp)
794 return equal_storage(v.as_array(), sp);
796 case json::kind::string:
797 return *v.as_string().storage() == *sp;
799 case json::kind::int64:
800 case json::kind::uint64:
801 case json::kind::double_:
802 case json::kind::bool_:
803 case json::kind::null:
807 return *v.storage() == *sp;
814 storage_ptr const& sp)
816 BOOST_TEST(equal_storage(o, sp));
823 storage_ptr const& sp)
825 BOOST_TEST(equal_storage(a, sp));
832 storage_ptr const& sp)
834 BOOST_TEST(equal_storage(v, sp));
837 //----------------------------------------------------------
845 json::value const& jv)
854 auto it = obj.begin();
858 while(it != obj.end())
862 dest.push_back('\"');
863 dest.append(it->key());
864 dest.push_back('\"');
880 auto it = arr.begin();
884 while(it != arr.end())
899 // safe, but doesn't handle escsapes
900 dest.push_back('\"');
901 dest.append(jv.get_string());
902 dest.push_back('\"');
904 dest.append(serialize(jv));
910 char buf[detail::max_number_chars];
912 detail::format_int64(
914 dest.append(string_view(buf).substr(0, n));
920 char buf[detail::max_number_chars];
922 detail::format_uint64(
923 buf, jv.as_uint64());
924 dest.append(string_view(buf).substr(0, n));
930 char buf[detail::max_number_chars];
932 detail::format_double(
933 buf, jv.as_double());
934 dest.append(string_view(buf).substr(0, n));
942 dest.append("false");
950 // should never get here
961 json::value const& jv)
965 detail::to_string_test(s, jv);
969 //----------------------------------------------------------
977 if(lhs.kind() != rhs.kind())
987 auto n = obj1.size();
990 auto it1 = obj1.begin();
991 auto it2 = obj2.begin();
1013 auto n = arr1.size();
1014 if(arr2.size() != n)
1016 auto it1 = arr1.begin();
1017 auto it2 = arr2.begin();
1019 if(! equal(*it1++, *it2++))
1056 //----------------------------------------------------------
1062 check_array_impl(int, value const&)
1069 int i, value const& jv,
1072 BOOST_TEST(equal(jv.at(i), arg));
1081 int i, value const& jv,
1084 Argn const&... argn)
1086 BOOST_TEST(equal(jv.at(i), arg0));
1087 BOOST_TEST(equal(jv.at(i + 1), arg1));
1088 check_array_impl(i + 2, jv, argn...);
1093 template<class... Argn>
1098 Argn const&... argn)
1100 if(! BOOST_TEST(jv.is_array()))
1102 if(! BOOST_TEST(sizeof...(argn) ==
1103 jv.get_array().size()))
1105 detail::check_array_impl(0, jv, argn...);
1108 //----------------------------------------------------------