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 // Test that header file is self-contained.
11 #include <boost/json/object.hpp>
13 #include <boost/json/monotonic_resource.hpp>
14 #include <boost/json/parse.hpp>
15 #include <boost/json/serialize.hpp>
18 #include <forward_list>
21 #include <type_traits>
25 #include "test_suite.hpp"
26 #include "checking_resource.hpp"
30 BOOST_STATIC_ASSERT( std::is_nothrow_destructible
<object
>::value
);
31 BOOST_STATIC_ASSERT( std::is_nothrow_move_constructible
<object
>::value
);
40 detail::small_object_size_
- 2;
47 test_suite::log_type log
;
48 string_view
const str_
;
51 std::initializer_list
<
52 std::pair
<string_view
, value_ref
>>;
54 #define DECLARE_INIT_LISTS \
56 { "0", 0 }, { "1", 1 }, { "2", 2 }, { "3", 3 }, { "4", 4 }, \
57 { "5", 5 }, { "6", 6 }, { "7", 7 }, { "8", 8 }, { "9", 9 }, \
58 { "10", 10 }, { "11", 11 }, { "12", 12 }, { "13", 13 }, { "14", 14 }, \
61 { "0", 0 }, { "1", 1 }, { "2", 2 }, { "3", 3 }, { "4", 4 }, \
62 { "5", 5 }, { "6", 6 }, { "7", 7 }, { "8", 8 }, { "9", 9 }, \
63 { "10", 10 }, { "11", 11 }, { "12", 12 }, { "13", 13 }, { "14", 14 }, \
64 { "15", 15 }, { "16", 16 }, { "17", 17 }, { "18", 18 }, { "19", 19 } }
66 string_view
const s0_
=
67 R
"({"0":0,"1":1,"2":2,"3":3,"4":4,)"
68 R
"("5":5,"6":6,"7":7,"8":8,"9":9,)"
69 R
"("10":10,"11":11,"12":12,"13":13,"14":14,)"
72 string_view
const s1_
=
73 R
"({"0":0,"1":1,"2":2,"3":3,"4":4,)"
74 R
"("5":5,"6":6,"7":7,"8":8,"9":9,)"
75 R
"("10":10,"11":11,"12":12,"13":13,"14":14,)"
76 R
"("15":15,"16":16,"17":17,"18":18,"19":19})";
79 : str_("abcdefghijklmnopqrstuvwxyz")
81 // ensure this string does
82 // not fit in the SBO area.
83 BOOST_ASSERT(str_
.size() >
89 i0_
.size() == size0_
);
91 i1_
.size() == size1_
);
94 template<class T
, class U
, class = void>
95 struct is_equal_comparable
: std::false_type
{};
97 template<class T
, class U
>
98 struct is_equal_comparable
<T
, U
, detail::void_t
<decltype(
99 std::declval
<T
const&>() == std::declval
<U
const&>()
100 )>> : std::true_type
{};
102 template<class T
, class U
, class = void>
103 struct is_unequal_comparable
: std::false_type
{};
105 template<class T
, class U
>
106 struct is_unequal_comparable
<T
, U
, detail::void_t
<decltype(
107 std::declval
<T
const&>() != std::declval
<U
const&>()
108 )>> : std::true_type
{};
110 BOOST_STATIC_ASSERT( std::is_constructible
<object::iterator
, object::iterator
>::value
);
111 BOOST_STATIC_ASSERT(! std::is_constructible
<object::iterator
, object::const_iterator
>::value
);
113 BOOST_STATIC_ASSERT( std::is_constructible
<object::const_iterator
, object::iterator
>::value
);
114 BOOST_STATIC_ASSERT( std::is_constructible
<object::const_iterator
, object::const_iterator
>::value
);
116 BOOST_STATIC_ASSERT( std::is_assignable
<object::iterator
&, object::iterator
>::value
);
117 BOOST_STATIC_ASSERT(! std::is_assignable
<object::iterator
&, object::const_iterator
>::value
);
119 BOOST_STATIC_ASSERT( std::is_assignable
<object::const_iterator
&, object::iterator
>::value
);
120 BOOST_STATIC_ASSERT( std::is_assignable
<object::const_iterator
&, object::const_iterator
>::value
);
122 BOOST_STATIC_ASSERT(is_equal_comparable
<object::iterator
, object::iterator
>::value
);
123 BOOST_STATIC_ASSERT(is_equal_comparable
<object::iterator
, object::const_iterator
>::value
);
125 BOOST_STATIC_ASSERT(is_equal_comparable
<object::const_iterator
, object::iterator
>::value
);
126 BOOST_STATIC_ASSERT(is_equal_comparable
<object::const_iterator
, object::const_iterator
>::value
);
128 BOOST_STATIC_ASSERT(is_unequal_comparable
<object::iterator
, object::iterator
>::value
);
129 BOOST_STATIC_ASSERT(is_unequal_comparable
<object::iterator
, object::const_iterator
>::value
);
131 BOOST_STATIC_ASSERT(is_unequal_comparable
<object::const_iterator
, object::iterator
>::value
);
132 BOOST_STATIC_ASSERT(is_unequal_comparable
<object::const_iterator
, object::const_iterator
>::value
);
134 BOOST_STATIC_ASSERT( std::is_constructible
<object::reverse_iterator
, object::reverse_iterator
>::value
);
135 // std::reverse_iterator ctor is not SFINAEd
136 //BOOST_STATIC_ASSERT(! std::is_constructible<object::reverse_iterator, object::const_reverse_iterator>::value);
138 BOOST_STATIC_ASSERT( std::is_constructible
<object::const_reverse_iterator
, object::reverse_iterator
>::value
);
139 BOOST_STATIC_ASSERT( std::is_constructible
<object::const_reverse_iterator
, object::const_reverse_iterator
>::value
);
141 BOOST_STATIC_ASSERT( std::is_assignable
<object::reverse_iterator
&, object::reverse_iterator
>::value
);
142 // std::reverse_iterator assignment is not SFINAEd
143 //BOOST_STATIC_ASSERT(! std::is_assignable<object::reverse_iterator&, object::const_reverse_iterator>::value);
145 BOOST_STATIC_ASSERT( std::is_assignable
<object::const_reverse_iterator
&, object::reverse_iterator
>::value
);
146 BOOST_STATIC_ASSERT( std::is_assignable
<object::const_reverse_iterator
&, object::const_reverse_iterator
>::value
);
148 BOOST_STATIC_ASSERT(is_equal_comparable
<object::reverse_iterator
, object::reverse_iterator
>::value
);
149 BOOST_STATIC_ASSERT(is_equal_comparable
<object::reverse_iterator
, object::const_reverse_iterator
>::value
);
151 BOOST_STATIC_ASSERT(is_equal_comparable
<object::const_reverse_iterator
, object::reverse_iterator
>::value
);
152 BOOST_STATIC_ASSERT(is_equal_comparable
<object::const_reverse_iterator
, object::const_reverse_iterator
>::value
);
154 BOOST_STATIC_ASSERT(is_unequal_comparable
<object::reverse_iterator
, object::reverse_iterator
>::value
);
155 BOOST_STATIC_ASSERT(is_unequal_comparable
<object::reverse_iterator
, object::const_reverse_iterator
>::value
);
157 BOOST_STATIC_ASSERT(is_unequal_comparable
<object::const_reverse_iterator
, object::reverse_iterator
>::value
);
158 BOOST_STATIC_ASSERT(is_unequal_comparable
<object::const_reverse_iterator
, object::const_reverse_iterator
>::value
);
165 std::size_t capacity
= 0)
168 parse(serialize(o
)).as_object() ==
169 parse(s
).as_object());
171 BOOST_TEST(o
.capacity() == capacity
);
178 std::size_t capacity
)
180 BOOST_TEST(! o
.empty());
181 BOOST_TEST(o
.size() == 3);
183 o
.capacity() == capacity
);
184 BOOST_TEST(o
.at("a").as_int64() == 1);
185 BOOST_TEST(o
.at("b").as_bool());
186 BOOST_TEST(o
.at("c").as_string() == "hello");
187 check_storage(o
, o
.storage());
204 // object(detail::unchecked_object&&)
208 value
const jv
= parse(s0_
);
209 check(jv
.as_object(), s0_
, i0_
.size());
214 value
const jv
= parse(
215 R
"({"0":0,"1":1,"2":2,"3":3,"4":4,)"
216 R
"("5":5,"6":6,"7":7,"8":8,"9":9,)"
217 R
"("10":10,"11":11,"12":12,"13":13,"14":14,)"
218 R
"("15":15,"10":10})");
219 check(jv
.as_object(), s0_
, i0_
.size() + 1);
224 value
const jv
= parse(s1_
);
225 check(jv
.as_object(), s1_
, i1_
.size());
230 value
const jv
= parse(
231 R
"({"0":0,"1":1,"2":2,"3":3,"4":4,)"
232 R
"("5":5,"6":6,"7":7,"8":8,"9":9,)"
233 R
"("10":10,"11":11,"12":12,"13":13,"14":14,)"
234 R
"("15":15,"16":16,"17":17,"18":18,"19":19,"10":10})");
235 check(jv
.as_object(), s1_
, i1_
.size() + 1);
242 BOOST_TEST(o
.empty());
243 BOOST_TEST(o
.size() == 0);
244 BOOST_TEST(o
.capacity() == 0);
247 // object(storage_ptr)
248 fail_loop([&](storage_ptr
const& sp
)
251 check_storage(o
, sp
);
252 BOOST_TEST(o
.empty());
253 BOOST_TEST(o
.size() == 0);
254 BOOST_TEST(o
.capacity() == 0);
257 // object(std::size_t, storage_ptr)
262 BOOST_TEST(o
.empty());
263 BOOST_TEST(o
.size() == 0);
264 BOOST_TEST(o
.capacity() == size0_
);
268 fail_loop([&](storage_ptr
const& sp
)
270 object
o(size0_
, sp
);
271 check_storage(o
, sp
);
272 BOOST_TEST(o
.empty());
273 BOOST_TEST(o
.size() == 0);
274 BOOST_TEST(o
.capacity() == size0_
);
280 BOOST_TEST(o
.empty());
281 BOOST_TEST(o
.size() == 0);
282 BOOST_TEST(o
.capacity() == size1_
);
286 fail_loop([&](storage_ptr
const& sp
)
288 object
o(size1_
, sp
);
289 check_storage(o
, sp
);
290 BOOST_TEST(o
.empty());
291 BOOST_TEST(o
.size() == 0);
292 BOOST_TEST(o
.capacity() == size1_
);
296 // object(InputIt, InputIt, size_type, storage_ptr)
300 // random-access iterator
301 std::vector
<std::pair
<string_view
, value
>> i1
;
302 object
o1(i1
.begin(), i1
.end());
303 BOOST_TEST(o1
.empty());
305 // bidirectional iterator
306 std::map
<string_view
, value
> i2
;
307 object
o2(i2
.begin(), i2
.end());
308 BOOST_TEST(o2
.empty());
311 std::forward_list
<std::pair
<string_view
, value
>> i3
;
312 object
o3(i3
.begin(), i3
.end());
313 BOOST_TEST(o3
.empty());
316 auto const it
= make_input_iterator(i3
.begin());
318 BOOST_TEST(o4
.empty());
323 object
o(i0_
.begin(), i0_
.end());
324 check(o
, s0_
, i0_
.size());
327 // small, ForwardIterator
328 fail_loop([&](storage_ptr
const& sp
)
330 object
o(i0_
.begin(), i0_
.end(), size0_
+ 1, sp
);
331 BOOST_TEST(! o
.empty());
332 check(o
, s0_
, size0_
+ 1);
333 check_storage(o
, sp
);
336 // small, InputIterator
337 fail_loop([&](storage_ptr
const& sp
)
340 make_input_iterator(i0_
.begin()),
341 make_input_iterator(i0_
.end()), size0_
+ 1, sp
);
342 BOOST_TEST(! o
.empty());
343 BOOST_TEST(o
.capacity() == size0_
+ 1);
344 check(o
, s0_
, size0_
+ 1);
345 check_storage(o
, sp
);
350 object
o(i1_
.begin(), i1_
.end());
351 check(o
, s1_
, i1_
.size());
354 // large, ForwardIterator
355 fail_loop([&](storage_ptr
const& sp
)
357 object
o(i1_
.begin(), i1_
.end(), size1_
+ 1, sp
);
358 BOOST_TEST(! o
.empty());
359 BOOST_TEST(o
.capacity() == size1_
+ 1);
360 check(o
, s1_
, size1_
+ 1);
361 check_storage(o
, sp
);
364 // large, InputIterator
365 fail_loop([&](storage_ptr
const& sp
)
368 make_input_iterator(i1_
.begin()),
369 make_input_iterator(i1_
.end()), size1_
+ 1, sp
);
370 BOOST_TEST(! o
.empty());
371 BOOST_TEST(o
.capacity() == size1_
+ 1);
372 check(o
, s1_
, size1_
+ 1);
373 check_storage(o
, sp
);
383 object
o2(std::move(o1
));
384 BOOST_TEST(o1
.empty());
385 BOOST_TEST(o1
.size() == 0);
387 check_storage(o1
, sp
);
388 check_storage(o2
, sp
);
391 // object(object&&, storage_ptr)
394 fail_loop([&](storage_ptr
const& sp
)
397 object
o2(std::move(o1
), sp
);
398 BOOST_TEST(! o1
.empty());
399 check(o2
, s0_
, i0_
.size());
402 check_storage(o2
, sp
);
406 fail_loop([&](storage_ptr
const& sp
)
409 object
o2(std::move(o1
), sp
);
410 BOOST_TEST(! o1
.empty());
411 check(o2
, s1_
, i1_
.size());
414 check_storage(o2
, sp
);
418 // object(pilfered<object>)
422 make_shared_resource
<unique_resource
>();
424 object
o2(pilfer(o1
));
426 o1
.storage() == storage_ptr());
428 *o2
.storage() == *sp
);
429 BOOST_TEST(o1
.empty());
430 check(o2
, s0_
, i0_
.size());
433 // ensure pilfered-from objects
434 // are trivially destructible
436 object
o1(make_shared_resource
<
437 monotonic_resource
>());
438 object
o2(pilfer(o1
));
439 BOOST_TEST(o1
.storage().get() ==
440 storage_ptr().get());
445 make_shared_resource
<
447 auto const sp0
= storage_ptr
{};
449 // object(object const&)
455 BOOST_TEST(! o1
.empty());
456 check(o2
, s0_
, i0_
.size());
463 BOOST_TEST(! o1
.empty());
464 check(o2
, s1_
, i1_
.size());
468 // object(object const&, storage_ptr)
471 fail_loop([&](storage_ptr
const& sp
)
475 BOOST_TEST(! o1
.empty());
476 check(o2
, s0_
, i0_
.size());
477 check_storage(o2
, sp
);
481 fail_loop([&](storage_ptr
const& sp
)
485 BOOST_TEST(! o1
.empty());
486 check(o2
, s1_
, i1_
.size());
487 check_storage(o2
, sp
);
491 // object(initializer_list, storage_ptr)
496 check(o
, s0_
, i0_
.size());
500 fail_loop([&](storage_ptr
const& sp
)
503 check(o
, s0_
, i0_
.size());
504 check_storage(o
, sp
);
510 check(o
, s1_
, i1_
.size());
514 fail_loop([&](storage_ptr
const& sp
)
517 check(o
, s1_
, i1_
.size());
518 check_storage(o
, sp
);
522 // object(initializer_list, std::size_t, storage_ptr)
526 object
o(i0_
, size0_
+ 1);
527 check(o
, s0_
, size0_
+ 1);
531 fail_loop([&](storage_ptr
const& sp
)
533 object
o(i0_
, size0_
+ 1, sp
);
535 *o
.storage() == *sp
);
536 check(o
, s0_
, size0_
+ 1);
540 // operator=(object const&)
546 check(o1
, s0_
, i0_
.size());
547 check(o2
, s0_
, i0_
.size());
554 fail_loop([&](storage_ptr
const& sp
)
559 check(o1
, s0_
, i0_
.size());
560 check(o2
, s0_
, i0_
.size());
563 check_storage(o2
, sp
);
569 object
const& o2(o1
);
571 check(o1
, s0_
, i0_
.size());
578 { {"a", 1}, {"b", true}, {"c", "hello"} }
580 o
= o
["b"].as_object();
585 // operator=(object&&)
595 BOOST_TEST(o1
.empty());
602 fail_loop([&](storage_ptr
const& sp
)
614 check_storage(o2
, sp
);
623 object
const& o2(o1
);
632 { {"a", 1}, {"b", true}, {"c", "hello"} }
634 o
= std::move(o
["b"].as_object());
639 // operator=(initializer_list)
652 fail_loop([&](storage_ptr
const& sp
)
660 *o
.storage() == *sp
);
662 check_storage(o
, sp
);
671 o
= { { "k2", o
["k2"] } };
673 o
== object({ { "k2", 2 } }));
687 auto const& cno
= no
;
691 BOOST_TEST(no
.begin() == no
.end());
692 BOOST_TEST(cno
.begin() == cno
.end());
693 BOOST_TEST(no
.cbegin() == no
.cend());
699 BOOST_TEST(it
->key() == "a"); ++it
;
700 BOOST_TEST(it
->key() == "b"); it
++;
701 BOOST_TEST(it
->key() == "c"); ++it
;
702 BOOST_TEST(it
== o
.end());
707 auto it
= co
.begin();
708 BOOST_TEST(it
->key() == "a"); ++it
;
709 BOOST_TEST(it
->key() == "b"); it
++;
710 BOOST_TEST(it
->key() == "c"); ++it
;
711 BOOST_TEST(it
== co
.end());
716 auto it
= o
.cbegin();
717 BOOST_TEST(it
->key() == "a"); ++it
;
718 BOOST_TEST(it
->key() == "b"); it
++;
719 BOOST_TEST(it
->key() == "c"); ++it
;
720 BOOST_TEST(it
== o
.cend());
726 --it
; BOOST_TEST(it
->key() == "c");
727 it
--; BOOST_TEST(it
->key() == "b");
728 --it
; BOOST_TEST(it
->key() == "a");
729 BOOST_TEST(it
== o
.begin());
735 --it
; BOOST_TEST(it
->key() == "c");
736 it
--; BOOST_TEST(it
->key() == "b");
737 --it
; BOOST_TEST(it
->key() == "a");
738 BOOST_TEST(it
== co
.begin());
744 --it
; BOOST_TEST(it
->key() == "c");
745 it
--; BOOST_TEST(it
->key() == "b");
746 --it
; BOOST_TEST(it
->key() == "a");
747 BOOST_TEST(it
== o
.cbegin());
752 auto it
= o
.rbegin();
753 BOOST_TEST(it
->key() == "c"); ++it
;
754 BOOST_TEST(it
->key() == "b"); it
++;
755 BOOST_TEST(it
->key() == "a"); ++it
;
756 BOOST_TEST(it
== o
.rend());
761 auto it
= co
.rbegin();
762 BOOST_TEST(it
->key() == "c"); ++it
;
763 BOOST_TEST(it
->key() == "b"); it
++;
764 BOOST_TEST(it
->key() == "a"); ++it
;
765 BOOST_TEST(it
== co
.rend());
770 auto it
= o
.crbegin();
771 BOOST_TEST(it
->key() == "c"); ++it
;
772 BOOST_TEST(it
->key() == "b"); it
++;
773 BOOST_TEST(it
->key() == "a"); ++it
;
774 BOOST_TEST(it
== o
.crend());
780 --it
; BOOST_TEST(it
->key() == "a");
781 it
--; BOOST_TEST(it
->key() == "b");
782 --it
; BOOST_TEST(it
->key() == "c");
783 BOOST_TEST(it
== o
.rbegin());
789 --it
; BOOST_TEST(it
->key() == "a");
790 it
--; BOOST_TEST(it
->key() == "b");
791 --it
; BOOST_TEST(it
->key() == "c");
792 BOOST_TEST(it
== co
.rbegin());
798 --it
; BOOST_TEST(it
->key() == "a");
799 it
--; BOOST_TEST(it
->key() == "b");
800 --it
; BOOST_TEST(it
->key() == "c");
801 BOOST_TEST(it
== o
.crbegin());
805 //------------------------------------------------------
811 object
{}.size() < object
{}.max_size());
814 //------------------------------------------------------
827 BOOST_TEST(o
.empty());
833 BOOST_TEST(! o
.empty());
835 BOOST_TEST(o
.empty());
841 BOOST_TEST(! o
.empty());
843 BOOST_TEST(o
.empty());
849 fail_loop([&](storage_ptr
const& sp
)
852 auto result
= o
.insert(
853 std::make_pair("x", 1));
854 BOOST_TEST(result
.second
);
855 BOOST_TEST(result
.first
->key() == "x");
856 BOOST_TEST(result
.first
->value().as_int64() == 1);
859 fail_loop([&](storage_ptr
const& sp
)
862 auto const p
= std::make_pair("x", 1);
863 auto result
= o
.insert(p
);
864 BOOST_TEST(result
.second
);
865 BOOST_TEST(result
.first
->key() == "x");
866 BOOST_TEST(result
.first
->value().as_int64() == 1);
869 fail_loop([&](storage_ptr
const& sp
)
875 auto const result
= o
.insert(
876 std::make_pair("b", 4));
878 result
.first
->value().as_int64() == 2);
879 BOOST_TEST(! result
.second
);
889 string_view
, value
&>(
891 BOOST_TEST(o
== object({
899 // insert(InputIt, InputIt)
904 fail_loop([&](storage_ptr
const& sp
)
907 o
.insert(i0_
.begin(), i0_
.end());
912 fail_loop([&](storage_ptr
const& sp
)
916 make_input_iterator(i0_
.begin()),
917 make_input_iterator(i0_
.end()));
921 // existing duplicate key, ForwardIterator
923 object
o({{"0",0},{"1",1},{"2",2}});
924 init_list i
= {{"2",nullptr},{"3",3}};
925 o
.insert(i
.begin(), i
.end());
926 BOOST_TEST(o
.capacity() <=
927 detail::small_object_size_
);
928 check(o
, R
"({"0":0,"1":1,"2":2,"3":3})");
931 // existing duplicate key, InputIterator
933 object
o({{"0",0},{"1",1},{"2",2}});
934 init_list i
= {{"2",nullptr},{"3",3}};
936 make_input_iterator(i
.begin()),
937 make_input_iterator(i
.end()));
938 BOOST_TEST(o
.capacity() <=
939 detail::small_object_size_
);
940 check(o
, R
"({"0":0,"1":1,"2":2,"3":3})");
943 // new duplicate key, ForwardIterator
945 object
o({{"0",0},{"1",1},{"2",2}});
946 init_list i
= {{"3",3},{"4",4},{"3",5}};
947 o
.insert(i
.begin(), i
.end());
948 BOOST_TEST(o
.capacity() <=
949 detail::small_object_size_
);
950 check(o
, R
"({"0":0,"1":1,"2":2,"3":3,"4":4})");
953 // new duplicate key, InputIterator
955 object
o({{"0",0},{"1",1},{"2",2}});
956 init_list i
= {{"3",3},{"4",4},{"3",5}};
958 make_input_iterator(i
.begin()),
959 make_input_iterator(i
.end()));
960 BOOST_TEST(o
.capacity() <=
961 detail::small_object_size_
);
962 check(o
, R
"({"0":0,"1":1,"2":2,"3":3,"4":4})");
966 // large, ForwardIterator
967 fail_loop([&](storage_ptr
const& sp
)
970 o
.insert(i1_
.begin(), i1_
.end());
974 // large, InputIterator
975 fail_loop([&](storage_ptr
const& sp
)
979 make_input_iterator(i1_
.begin()),
980 make_input_iterator(i1_
.end()));
985 // insert(initializer_list)
988 fail_loop([&](storage_ptr
const& sp
)
995 // small, existing duplicate
996 fail_loop([&](storage_ptr
const& sp
)
998 object
o({{"0",0},{"1",1},/*{"2",2},*/{"3",3},{"4",4}}, sp
);
999 BOOST_TEST(o
.capacity() <= detail::small_object_size_
);
1000 o
.insert({{"2",2},{"3",3}});
1001 BOOST_TEST(o
.capacity() <= detail::small_object_size_
);
1002 check(o
, R
"({"0":0,"1":1,"2":2,"3":3,"4":4})");
1005 // small, new duplicate
1006 fail_loop([&](storage_ptr
const& sp
)
1008 object
o({{"0",0},{"1",1},/*{"2",2},{"3",3},*/{"4",4}}, sp
);
1009 BOOST_TEST(o
.capacity() <= detail::small_object_size_
);
1010 o
.insert({{"2",2},{"3",3},{"2",2}});
1011 BOOST_TEST(o
.capacity() <= detail::small_object_size_
);
1012 check(o
, R
"({"0":0,"1":1,"2":2,"3":3,"4":4})");
1016 fail_loop([&](storage_ptr
const& sp
)
1023 // large, existing duplicate
1024 fail_loop([&](storage_ptr
const& sp
)
1027 {"0",0},{"1",1},{"2",2},{"3",3},{"4",4},
1028 {"5",5},{"6",6},{"7",7},{"8",8},{"9",9},
1029 /*{"10",10},*/{"11",11},{"12",12},{"13",13},{"14",14},
1030 {"15",15},{"16",16},{"17",17},{"18",18},{"19",19}}, sp
);
1031 BOOST_TEST(o
.capacity() > detail::small_object_size_
);
1032 o
.insert({{"10",10},{"11",11}});
1033 BOOST_TEST(o
.capacity() > detail::small_object_size_
);
1037 // large, new duplicate
1038 fail_loop([&](storage_ptr
const& sp
)
1041 {"0",0},{"1",1},{"2",2},{"3",3},{"4",4},
1042 {"5",5},{"6",6},{"7",7},{"8",8},{"9",9},
1043 /*{"10",10},{"11",11},*/{"12",12},{"13",13},{"14",14},
1044 {"15",15},{"16",16},{"17",17},{"18",18},{"19",19}},
1045 detail::small_object_size_
+ 1, sp
);
1046 BOOST_TEST(o
.capacity() > detail::small_object_size_
);
1047 o
.insert({{"10",10},{"11",11},{"10",10}});
1048 BOOST_TEST(o
.capacity() > detail::small_object_size_
);
1052 // do rollback in ~revert_insert
1053 fail_loop([&](storage_ptr
const& sp
)
1057 { "a", { 1, 2, 3, 4 } } });
1067 { "k4", o
["k2"] } });
1068 BOOST_TEST(o
== object({
1076 // insert_or_assign(key, o);
1078 fail_loop([&](storage_ptr
const& sp
)
1080 object
o({{"a", 1}}, sp
);
1081 o
.insert_or_assign("a", str_
);
1082 BOOST_TEST(o
["a"].is_string());
1085 fail_loop([&](storage_ptr
const& sp
)
1091 o
.insert_or_assign("d", str_
);
1092 BOOST_TEST(o
["d"].is_string());
1093 BOOST_TEST(o
.size() == 4);
1096 fail_loop([&](storage_ptr
const& sp
)
1098 object
o({{"a", 1}}, sp
);
1099 o
.insert_or_assign("b", true);
1100 o
.insert_or_assign("c", "hello");
1104 fail_loop([&](storage_ptr
const& sp
)
1106 object
o({{"a", 1}}, sp
);
1108 ! o
.insert_or_assign("a", 2).second
);
1109 BOOST_TEST(o
["a"].as_int64() == 2);
1120 BOOST_TEST(o
== object({
1128 // emplace(key, arg)
1130 fail_loop([&](storage_ptr
const& sp
)
1134 o
.emplace("b", true);
1135 o
.emplace("c", "hello");
1147 BOOST_TEST(o
== object({
1160 auto it
= o
.erase(o
.find("10"));
1161 BOOST_TEST(it
->key() == "15");
1163 it
->value().as_int64() == 15);
1164 BOOST_TEST(serialize(o
) ==
1165 R
"({"0":0,"1":1,"2":2,"3":3,"4":4,)"
1166 R
"("5":5,"6":6,"7":7,"8":8,"9":9,)"
1167 R
"("15":15,"11":11,"12":12,"13":13,"14":14})");
1173 auto it
= o
.erase(o
.find("10"));
1174 BOOST_TEST(it
->key() == "19");
1176 it
->value().as_int64() == 19);
1177 BOOST_TEST(serialize(o
) ==
1178 R
"({"0":0,"1":1,"2":2,"3":3,"4":4,)"
1179 R
"("5":5,"6":6,"7":7,"8":8,"9":9,)"
1180 R
"("19":19,"11":11,"12":12,"13":13,"14":14,)"
1181 R
"("15":15,"16":16,"17":17,"18":18})");
1192 BOOST_TEST(o
.erase("b2") == 0);
1202 BOOST_TEST(o
.erase("b2") == 1);
1210 object o1
= {{"a",1}, {"b",true}, {"c", "hello"}};
1211 object o2
= {{"d",{1,2,3}}};
1213 BOOST_TEST(o1
.size() == 1);
1214 BOOST_TEST(o2
.size() == 3);
1215 BOOST_TEST(o1
.count("d") == 1);
1218 fail_loop([&](storage_ptr
const& sp
)
1220 object o1
= {{"a",1}, {"b",true}, {"c", "hello"}};
1221 object
o2({{"d",{1,2,3}}}, sp
);
1223 BOOST_TEST(o1
.size() == 1);
1224 BOOST_TEST(o2
.size() == 3);
1225 BOOST_TEST(o1
.count("d") == 1);
1228 fail_loop([&](storage_ptr
const& sp
)
1230 object
o1({{"d",{1,2,3}}}, sp
);
1231 object o2
= {{"a",1}, {"b",true}, {"c", "hello"}};
1233 BOOST_TEST(o1
.size() == 3);
1234 BOOST_TEST(o2
.size() == 1);
1235 BOOST_TEST(o2
.count("d") == 1);
1240 //------------------------------------------------------
1250 auto const& co0
= o0
;
1251 auto const& co1
= o1
;
1256 o1
.at("a").is_number());
1257 BOOST_TEST_THROWS((o1
.at("d")),
1264 co1
.at("a").is_number());
1265 BOOST_TEST_THROWS((co1
.at("d")),
1275 BOOST_TEST(o
.count("d") == 0);;
1276 BOOST_TEST(o
["a"].is_number());
1277 BOOST_TEST(o
["d"].is_null());
1278 BOOST_TEST(o
.count("d") == 1);
1283 BOOST_TEST(o1
.count("a") == 1);
1284 BOOST_TEST(o1
.count("d") == 0);
1285 BOOST_TEST(o1
.count("e") == 0);
1292 o0
.find("") == o0
.end());
1294 o1
.find("a")->key() == "a");
1296 o1
.find("e") == o1
.end());
1299 co0
.find("") == co0
.end());
1301 co1
.find("a")->key() == "a");
1303 co1
.find("e") == o1
.end());
1308 BOOST_TEST(o1
.contains("a"));
1309 BOOST_TEST(! o1
.contains("e"));
1310 BOOST_TEST(! object().contains(""));
1314 // if_contains(key) const
1316 BOOST_TEST(o1
.if_contains("a")->is_int64());
1317 BOOST_TEST(o1
.if_contains("e") == nullptr);
1318 BOOST_TEST(co1
.if_contains("a")->is_int64());
1319 BOOST_TEST(co1
.if_contains("e") == nullptr);
1321 *o1
.if_contains("a") = 2;
1322 BOOST_TEST(co1
.if_contains("a")->as_int64() == 2);
1329 // reserve(size_type)
1333 for(std::size_t i
= 0; i
< 10; ++i
)
1334 o
.emplace(std::to_string(i
), i
);
1336 BOOST_TEST(o
.capacity() >= 15);
1338 BOOST_TEST(o
.capacity() >= 20);
1344 BOOST_TEST(o
.capacity() == 3);
1346 BOOST_TEST(o
.capacity() == 7);
1351 //------------------------------------------------------
1354 testImplementation()
1356 // insert duplicate keys
1363 BOOST_TEST(o
.at("a").as_int64() == 1);
1364 BOOST_TEST(o
.at("b").as_bool() == true);
1365 BOOST_TEST(o
.at("c").as_string() == "hello");
1368 // destroy key_value_pair array with need_free=false
1370 monotonic_resource mr
;
1375 {"c", "hello"}}, &mr
);
1385 int constexpr base
= 62;
1386 char const* const alphabet
=
1388 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1389 "abcdefghijklmnopqrstuvwxyz";
1393 *dest
++ = alphabet
[i
%base
];
1397 return { buf
, static_cast<
1398 std::size_t>(dest
-buf
) };
1404 int constexpr buckets
=
1405 detail::small_object_size_
+ 1;
1406 int constexpr collisions
= 3;
1408 //DECLARE_INIT_LISTS;
1410 // find a set of keys that collide
1411 std::vector
<std::string
> v
;
1416 o
.capacity() == buckets
);
1419 o
.t_
->digest("0") % buckets
;
1424 auto s
= make_key(i
, buf
);
1425 if((o
.t_
->digest(s
) %
1428 v
.push_back(std::string(
1429 s
.data(), s
.size()));
1430 if(v
.size() >= collisions
)
1437 // ensure collisions are distinguishable
1441 (o
.t_
->digest(v
[0]) % buckets
) ==
1442 (o
.t_
->digest(v
[1]) % buckets
));
1444 (o
.t_
->digest(v
[1]) % buckets
) ==
1445 (o
.t_
->digest(v
[2]) % buckets
));
1449 BOOST_TEST(o
.at(v
[0]).to_number
<int>() == 1);
1450 BOOST_TEST(o
.at(v
[1]).to_number
<int>() == 2);
1451 BOOST_TEST(o
.at(v
[2]).to_number
<int>() == 3);
1461 BOOST_TEST(o
.at(v
[1]).to_number
<int>() == 2);
1462 BOOST_TEST(o
.at(v
[2]).to_number
<int>() == 3);
1472 BOOST_TEST(o
.at(v
[0]).to_number
<int>() == 1);
1473 BOOST_TEST(o
.at(v
[2]).to_number
<int>() == 3);
1483 BOOST_TEST(o
.at(v
[0]).to_number
<int>() == 1);
1484 BOOST_TEST(o
.at(v
[1]).to_number
<int>() == 2);
1491 BOOST_TEST(object({}) == object({}));
1492 BOOST_TEST(object({}) != object({{"1",1},{"2",2}}));
1493 BOOST_TEST(object({{"1",1},{"2",2},{"3",3}}) == object({{"1",1},{"2",2},{"3",3}}));
1494 BOOST_TEST(object({{"1",1},{"2",2},{"3",3}}) != object({{"1",1},{"2",2}}));
1495 BOOST_TEST(object({{"1",1},{"2",2},{"3",3}}) == object({{"3",3},{"2",2},{"1",1}}));
1502 checking_resource res
;
1508 checking_resource res
;
1514 checking_resource res
;
1515 object
o({std::make_pair("one", 1)}, &res
);
1522 BOOST_TEST(check_hash_equal(
1523 object(), object({})));
1524 BOOST_TEST(expect_hash_not_equal(
1525 object(), object({{"1",1},{"2",2}})));
1526 BOOST_TEST(check_hash_equal(
1527 object({{"a",1}, {"b",2}, {"c",3}}),
1528 object({{"b",2}, {"c",3}, {"a",1}})));
1529 BOOST_TEST(expect_hash_not_equal(
1530 object({{"a",1}, {"b",2}, {"c",3}}),
1531 object({{"b",2}, {"c",3}})));
1544 testImplementation();
1552 TEST_SUITE(object_test
, "boost.json.object");