1245 lines
33 KiB
C++
1245 lines
33 KiB
C++
//
|
|
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
// Official repository: https://github.com/boostorg/json
|
|
//
|
|
|
|
// Test that header file is self-contained.
|
|
#include <boost/json/array.hpp>
|
|
|
|
#include <boost/json/monotonic_resource.hpp>
|
|
|
|
#include "test.hpp"
|
|
#include "test_suite.hpp"
|
|
|
|
BOOST_JSON_NS_BEGIN
|
|
|
|
BOOST_STATIC_ASSERT( std::is_nothrow_destructible<array>::value );
|
|
BOOST_STATIC_ASSERT( std::is_nothrow_move_constructible<array>::value );
|
|
|
|
class array_test
|
|
{
|
|
public:
|
|
using init_list =
|
|
std::initializer_list<value_ref>;
|
|
|
|
string_view const str_;
|
|
|
|
array_test()
|
|
: str_(
|
|
"abcdefghijklmnopqrstuvwxyz")
|
|
{
|
|
// ensure this string does
|
|
// not fit in the SBO area.
|
|
BOOST_ASSERT(str_.size() >
|
|
string().capacity());
|
|
|
|
}
|
|
|
|
void
|
|
check(array const& a)
|
|
{
|
|
BOOST_TEST(a.size() == 3);
|
|
BOOST_TEST(a[0].is_number());
|
|
BOOST_TEST(a[1].is_bool());
|
|
BOOST_TEST(a[2].is_string());
|
|
}
|
|
|
|
void
|
|
check(
|
|
array const& a,
|
|
storage_ptr const& sp)
|
|
{
|
|
check(a);
|
|
check_storage(a, sp);
|
|
}
|
|
|
|
void
|
|
testDestroy()
|
|
{
|
|
{
|
|
monotonic_resource mr;
|
|
array a(&mr);
|
|
a.reserve(3);
|
|
}
|
|
{
|
|
monotonic_resource mr;
|
|
array a(&mr);
|
|
a.resize(3);
|
|
a.clear();
|
|
}
|
|
}
|
|
|
|
void
|
|
testCtors()
|
|
{
|
|
// ~array()
|
|
{
|
|
// implied
|
|
}
|
|
|
|
// array()
|
|
{
|
|
array a;
|
|
BOOST_TEST(a.empty());
|
|
BOOST_TEST(a.size() == 0);
|
|
}
|
|
|
|
// array(storage_ptr)
|
|
{
|
|
array a(storage_ptr{});
|
|
check_storage(a, storage_ptr{});
|
|
}
|
|
|
|
// array(size_type, value, storage)
|
|
{
|
|
// default storage
|
|
{
|
|
array a(3, true);
|
|
BOOST_TEST(a.size() == 3);
|
|
for(auto const& v : a)
|
|
BOOST_TEST(v.is_bool());
|
|
check_storage(a, storage_ptr{});
|
|
}
|
|
|
|
// construct with zero `true` values
|
|
{
|
|
array(0, true);
|
|
}
|
|
|
|
// construct with three `true` values
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a(3, true, sp);
|
|
BOOST_TEST(a.size() == 3);
|
|
check_storage(a, sp);
|
|
});
|
|
}
|
|
|
|
// array(size_type, storage)
|
|
{
|
|
// default storage
|
|
{
|
|
array a(3);
|
|
BOOST_TEST(a.size() == 3);
|
|
for(auto const& v : a)
|
|
BOOST_TEST(v.is_null());
|
|
check_storage(a, storage_ptr{});
|
|
}
|
|
|
|
// zero size
|
|
{
|
|
array a(0);
|
|
BOOST_TEST(a.empty());
|
|
}
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a(3, sp);
|
|
BOOST_TEST(a.size() == 3);
|
|
for(auto const& v : a)
|
|
BOOST_TEST(v.is_null());
|
|
check_storage(a, sp);
|
|
});
|
|
}
|
|
|
|
// array(InputIt, InputIt, storage)
|
|
{
|
|
// default storage
|
|
{
|
|
init_list init{ 0, 1, str_, 3, 4 };
|
|
array a(init.begin(), init.end());
|
|
check_storage(a, storage_ptr{});
|
|
BOOST_TEST(a[0].as_int64() == 0);
|
|
BOOST_TEST(a[1].as_int64() == 1);
|
|
BOOST_TEST(a[2].as_string() == str_);
|
|
BOOST_TEST(a[3].as_int64() == 3);
|
|
BOOST_TEST(a[4].as_int64() == 4);
|
|
}
|
|
|
|
// random iterator
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
init_list init{ 1, true, str_ };
|
|
array a(init.begin(), init.end(), sp);
|
|
check(a);
|
|
check_storage(a, sp);
|
|
});
|
|
|
|
// input iterator
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
init_list init{ 1, true, str_ };
|
|
array a(
|
|
make_input_iterator(init.begin()),
|
|
make_input_iterator(init.end()), sp);
|
|
check(a);
|
|
check_storage(a, sp);
|
|
});
|
|
}
|
|
|
|
// array(array const&)
|
|
{
|
|
{
|
|
array a1;
|
|
array a2(a1);
|
|
}
|
|
|
|
{
|
|
array a1;
|
|
array a2({ 1, true, str_ });
|
|
a2 = a1;
|
|
}
|
|
|
|
{
|
|
init_list init{ 1, true, str_ };
|
|
array a1(init.begin(), init.end());
|
|
array a2(a1);
|
|
check(a2);
|
|
check_storage(a2, storage_ptr{});
|
|
}
|
|
}
|
|
|
|
// array(array const&, storage)
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
init_list init{ 1, true, str_ };
|
|
array a1(init.begin(), init.end());
|
|
array a2(a1, sp);
|
|
check(a2);
|
|
check_storage(a2, sp);
|
|
});
|
|
|
|
// array(pilfered<array>)
|
|
{
|
|
{
|
|
init_list init{ 1, true, str_ };
|
|
array a1(init.begin(), init.end());
|
|
array a2(pilfer(a1));
|
|
BOOST_TEST(a1.empty());
|
|
check(a2);
|
|
check_storage(a2, storage_ptr{});
|
|
}
|
|
|
|
// ensure pilfered-from objects
|
|
// are trivially destructible
|
|
{
|
|
array a1(make_shared_resource<
|
|
monotonic_resource>());
|
|
array a2(pilfer(a1));
|
|
BOOST_TEST(a1.storage().get() ==
|
|
storage_ptr().get());
|
|
}
|
|
}
|
|
|
|
// array(array&&)
|
|
{
|
|
init_list init{ 1, true, str_ };
|
|
array a1(init.begin(), init.end());
|
|
array a2 = std::move(a1);
|
|
BOOST_TEST(a1.empty());
|
|
check(a2);
|
|
check_storage(a2, storage_ptr{});
|
|
}
|
|
|
|
// array(array&&, storage)
|
|
{
|
|
{
|
|
init_list init{ 1, true, str_ };
|
|
array a1(init.begin(), init.end());
|
|
array a2(
|
|
std::move(a1), storage_ptr{});
|
|
BOOST_TEST(a1.empty());
|
|
check(a2);
|
|
check_storage(a1, storage_ptr{});
|
|
check_storage(a2, storage_ptr{});
|
|
}
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
init_list init{ 1, true, str_ };
|
|
array a1(init.begin(), init.end());
|
|
array a2(std::move(a1), sp);
|
|
BOOST_TEST(! a1.empty());
|
|
check(a2);
|
|
check_storage(a1, storage_ptr{});
|
|
check_storage(a2, sp);
|
|
});
|
|
}
|
|
|
|
// array(init_list, storage)
|
|
{
|
|
// default storage
|
|
{
|
|
array a({1, true, str_});
|
|
check(a);
|
|
check_storage(a, storage_ptr{});
|
|
}
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a({1, true, str_}, sp);
|
|
check(a, sp);
|
|
check_storage(a, sp);
|
|
});
|
|
}
|
|
}
|
|
|
|
void
|
|
testAssign()
|
|
{
|
|
// operator=(array const&)
|
|
{
|
|
{
|
|
array a1({1, true, str_});
|
|
array a2({nullptr, object{}, 1.f});
|
|
a2 = a1;
|
|
check(a1);
|
|
check(a2);
|
|
check_storage(a1, storage_ptr{});
|
|
check_storage(a2, storage_ptr{});
|
|
}
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a1({1, true, str_});
|
|
array a2({nullptr, object{}, 1.f}, sp);
|
|
a2 = a1;
|
|
check(a1);
|
|
check(a2);
|
|
check_storage(a1, storage_ptr{});
|
|
check_storage(a2, sp);
|
|
});
|
|
|
|
// self-assign
|
|
{
|
|
array a({1, true, str_});
|
|
auto& a1 = a;
|
|
auto& a2 = a;
|
|
a1 = a2;
|
|
check(a);
|
|
}
|
|
|
|
// copy from child
|
|
{
|
|
array a({1, {1,2,3}, 3});
|
|
a = a.at(1).as_array();
|
|
BOOST_TEST(
|
|
a == array({1, 2, 3}));
|
|
}
|
|
}
|
|
|
|
// operator=(array&&)
|
|
{
|
|
{
|
|
array a1({1, true, str_});
|
|
array a2({nullptr, object{}, 1.f});
|
|
a2 = std::move(a1);
|
|
BOOST_TEST(a1.empty());
|
|
check(a2);
|
|
}
|
|
|
|
// empty
|
|
{
|
|
array a1;
|
|
array a2;
|
|
a2 = std::move(a1);
|
|
BOOST_TEST(a1.empty());
|
|
BOOST_TEST(a2.empty());
|
|
}
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a1({1, true, str_});
|
|
array a2({nullptr, object{}, 1.f}, sp);
|
|
a2 = std::move(a1);
|
|
check(a1);
|
|
check(a2);
|
|
check_storage(a1, storage_ptr{});
|
|
check_storage(a2, sp);
|
|
});
|
|
|
|
// self-move
|
|
{
|
|
array a({1, true, str_});
|
|
auto& a1 = a;
|
|
auto& a2 = a;
|
|
a1 = std::move(a2);
|
|
check(a);
|
|
}
|
|
|
|
// move from child
|
|
{
|
|
array a({1, {1,2,3}, 3});
|
|
a = std::move(a.at(1).as_array());
|
|
BOOST_TEST(
|
|
a == array({1, 2, 3}));
|
|
}
|
|
}
|
|
|
|
// operator=(init_list)
|
|
{
|
|
{
|
|
array a;
|
|
a = {};
|
|
}
|
|
|
|
{
|
|
array a({ 1, true, str_ });
|
|
a = {};
|
|
}
|
|
|
|
{
|
|
init_list init{ 1, true, str_ };
|
|
array a({nullptr, object{}, 1.f});
|
|
a = init;
|
|
check(a);
|
|
check_storage(a, storage_ptr{});
|
|
}
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
init_list init{ 1, true, str_ };
|
|
array a({nullptr, object{}, 1.f}, sp);
|
|
a = init;
|
|
check(a);
|
|
check_storage(a, sp);
|
|
});
|
|
}
|
|
}
|
|
|
|
void
|
|
testGetStorage()
|
|
{
|
|
// storage()
|
|
{
|
|
// implied
|
|
}
|
|
}
|
|
|
|
void
|
|
testAccess()
|
|
{
|
|
// at(pos)
|
|
{
|
|
array a({1, true, str_});
|
|
BOOST_TEST(a.at(0).is_number());
|
|
BOOST_TEST(a.at(1).is_bool());
|
|
BOOST_TEST(a.at(2).is_string());
|
|
try
|
|
{
|
|
a.at(3);
|
|
BOOST_TEST_FAIL();
|
|
}
|
|
catch(std::out_of_range const&)
|
|
{
|
|
BOOST_TEST_PASS();
|
|
}
|
|
}
|
|
|
|
// at(pos) const
|
|
{
|
|
array const a({1, true, str_});
|
|
BOOST_TEST(a.at(0).is_number());
|
|
BOOST_TEST(a.at(1).is_bool());
|
|
BOOST_TEST(a.at(2).is_string());
|
|
try
|
|
{
|
|
a.at(3);
|
|
BOOST_TEST_FAIL();
|
|
}
|
|
catch(std::out_of_range const&)
|
|
{
|
|
BOOST_TEST_PASS();
|
|
}
|
|
}
|
|
|
|
// operator[&](size_type)
|
|
{
|
|
array a({1, true, str_});
|
|
BOOST_TEST(a[0].is_number());
|
|
BOOST_TEST(a[1].is_bool());
|
|
BOOST_TEST(a[2].is_string());
|
|
}
|
|
|
|
// operator[&](size_type) const
|
|
{
|
|
array const a({1, true, str_});
|
|
BOOST_TEST(a[0].is_number());
|
|
BOOST_TEST(a[1].is_bool());
|
|
BOOST_TEST(a[2].is_string());
|
|
}
|
|
|
|
// front()
|
|
{
|
|
array a({1, true, str_});
|
|
BOOST_TEST(a.front().is_number());
|
|
}
|
|
|
|
// front() const
|
|
{
|
|
array const a({1, true, str_});
|
|
BOOST_TEST(a.front().is_number());
|
|
}
|
|
|
|
// back()
|
|
{
|
|
array a({1, true, str_});
|
|
BOOST_TEST(a.back().is_string());
|
|
}
|
|
|
|
// back() const
|
|
{
|
|
array const a({1, true, str_});
|
|
BOOST_TEST(a.back().is_string());
|
|
}
|
|
|
|
// if_contains()
|
|
// if_contains() const
|
|
{
|
|
{
|
|
array a({1, true, str_});
|
|
BOOST_TEST(a.if_contains(1)->is_bool());
|
|
BOOST_TEST(a.if_contains(3) == nullptr);
|
|
}
|
|
{
|
|
array const a({1, true, str_});
|
|
BOOST_TEST(a.if_contains(1)->is_bool());
|
|
BOOST_TEST(a.if_contains(3) == nullptr);
|
|
}
|
|
}
|
|
|
|
// data()
|
|
{
|
|
{
|
|
array a({1, true, str_});
|
|
BOOST_TEST(a.data() == &a[0]);
|
|
}
|
|
{
|
|
array a;
|
|
BOOST_TEST(
|
|
a.data() == a.begin());
|
|
}
|
|
}
|
|
|
|
// data() const
|
|
{
|
|
{
|
|
array const a({1, true, str_});
|
|
BOOST_TEST(a.data() == &a[0]);
|
|
}
|
|
{
|
|
array const a{};
|
|
BOOST_TEST(
|
|
a.data() == a.begin());
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
testIterators()
|
|
{
|
|
array a({1, true, str_});
|
|
auto const& ac(a);
|
|
|
|
{
|
|
auto it = a.begin();
|
|
BOOST_TEST(it->is_number()); ++it;
|
|
BOOST_TEST(it->is_bool()); it++;
|
|
BOOST_TEST(it->is_string()); ++it;
|
|
BOOST_TEST(it == a.end());
|
|
}
|
|
{
|
|
auto it = a.cbegin();
|
|
BOOST_TEST(it->is_number()); ++it;
|
|
BOOST_TEST(it->is_bool()); it++;
|
|
BOOST_TEST(it->is_string()); ++it;
|
|
BOOST_TEST(it == a.cend());
|
|
}
|
|
{
|
|
auto it = ac.begin();
|
|
BOOST_TEST(it->is_number()); ++it;
|
|
BOOST_TEST(it->is_bool()); it++;
|
|
BOOST_TEST(it->is_string()); ++it;
|
|
BOOST_TEST(it == ac.end());
|
|
}
|
|
{
|
|
auto it = a.end();
|
|
--it; BOOST_TEST(it->is_string());
|
|
it--; BOOST_TEST(it->is_bool());
|
|
--it; BOOST_TEST(it->is_number());
|
|
BOOST_TEST(it == a.begin());
|
|
}
|
|
{
|
|
auto it = a.cend();
|
|
--it; BOOST_TEST(it->is_string());
|
|
it--; BOOST_TEST(it->is_bool());
|
|
--it; BOOST_TEST(it->is_number());
|
|
BOOST_TEST(it == a.cbegin());
|
|
}
|
|
{
|
|
auto it = ac.end();
|
|
--it; BOOST_TEST(it->is_string());
|
|
it--; BOOST_TEST(it->is_bool());
|
|
--it; BOOST_TEST(it->is_number());
|
|
BOOST_TEST(it == ac.begin());
|
|
}
|
|
|
|
{
|
|
auto it = a.rbegin();
|
|
BOOST_TEST(it->is_string()); ++it;
|
|
BOOST_TEST(it->is_bool()); it++;
|
|
BOOST_TEST(it->is_number()); ++it;
|
|
BOOST_TEST(it == a.rend());
|
|
}
|
|
{
|
|
auto it = a.crbegin();
|
|
BOOST_TEST(it->is_string()); ++it;
|
|
BOOST_TEST(it->is_bool()); it++;
|
|
BOOST_TEST(it->is_number()); ++it;
|
|
BOOST_TEST(it == a.crend());
|
|
}
|
|
{
|
|
auto it = ac.rbegin();
|
|
BOOST_TEST(it->is_string()); ++it;
|
|
BOOST_TEST(it->is_bool()); it++;
|
|
BOOST_TEST(it->is_number()); ++it;
|
|
BOOST_TEST(it == ac.rend());
|
|
}
|
|
{
|
|
auto it = a.rend();
|
|
--it; BOOST_TEST(it->is_number());
|
|
it--; BOOST_TEST(it->is_bool());
|
|
--it; BOOST_TEST(it->is_string());
|
|
BOOST_TEST(it == a.rbegin());
|
|
}
|
|
{
|
|
auto it = a.crend();
|
|
--it; BOOST_TEST(it->is_number());
|
|
it--; BOOST_TEST(it->is_bool());
|
|
--it; BOOST_TEST(it->is_string());
|
|
BOOST_TEST(it == a.crbegin());
|
|
}
|
|
{
|
|
auto it = ac.rend();
|
|
--it; BOOST_TEST(it->is_number());
|
|
it--; BOOST_TEST(it->is_bool());
|
|
--it; BOOST_TEST(it->is_string());
|
|
BOOST_TEST(it == ac.rbegin());
|
|
}
|
|
|
|
{
|
|
array a2;
|
|
array const& ca2(a2);
|
|
BOOST_TEST(std::distance(
|
|
a2.begin(), a2.end()) == 0);
|
|
BOOST_TEST(std::distance(
|
|
ca2.begin(), ca2.end()) == 0);
|
|
BOOST_TEST(std::distance(
|
|
ca2.cbegin(), ca2.cend()) == 0);
|
|
BOOST_TEST(std::distance(
|
|
a2.rbegin(), a2.rend()) == 0);
|
|
BOOST_TEST(std::distance(
|
|
ca2.rbegin(), ca2.rend()) == 0);
|
|
BOOST_TEST(std::distance(
|
|
ca2.crbegin(), ca2.crend()) == 0);
|
|
}
|
|
}
|
|
|
|
void
|
|
testCapacity()
|
|
{
|
|
// empty()
|
|
{
|
|
{
|
|
array a;
|
|
BOOST_TEST(a.empty());
|
|
a.emplace_back(1);
|
|
BOOST_TEST(! a.empty());
|
|
}
|
|
|
|
{
|
|
array a({1, 2});
|
|
BOOST_TEST(! a.empty());
|
|
a.clear();
|
|
BOOST_TEST(a.empty());
|
|
BOOST_TEST(a.capacity() > 0);
|
|
}
|
|
}
|
|
|
|
// size()
|
|
{
|
|
array a;
|
|
BOOST_TEST(a.size() == 0);
|
|
a.emplace_back(1);
|
|
BOOST_TEST(a.size() == 1);
|
|
}
|
|
|
|
// max_size()
|
|
{
|
|
array a;
|
|
BOOST_TEST(a.max_size() > 0);
|
|
}
|
|
|
|
// reserve()
|
|
{
|
|
{
|
|
array a;
|
|
a.reserve(0);
|
|
}
|
|
|
|
{
|
|
array a(3);
|
|
a.reserve(1);
|
|
}
|
|
|
|
{
|
|
array a(3);
|
|
a.reserve(0);
|
|
}
|
|
|
|
{
|
|
array a;
|
|
a.reserve(50);
|
|
BOOST_TEST(a.capacity() >= 50);
|
|
}
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a(4, 'c', sp);
|
|
a.reserve(a.capacity() + 1);
|
|
auto const new_cap = a.capacity();
|
|
// 1.5x growth
|
|
BOOST_TEST(new_cap == 6);
|
|
a.reserve(new_cap + 1);
|
|
BOOST_TEST(a.capacity() == 9);
|
|
});
|
|
}
|
|
|
|
// capacity()
|
|
{
|
|
array a;
|
|
BOOST_TEST(a.capacity() == 0);
|
|
}
|
|
|
|
// shrink_to_fit()
|
|
{
|
|
{
|
|
array a(1);
|
|
a.shrink_to_fit();
|
|
BOOST_TEST(a.size() == 1);
|
|
BOOST_TEST(a.capacity() >= 1);
|
|
}
|
|
|
|
{
|
|
array a(2, 'c');
|
|
BOOST_TEST(a.capacity() == 2);
|
|
a.erase(a.begin());
|
|
a.shrink_to_fit();
|
|
BOOST_TEST(a.capacity() == 1);
|
|
}
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a(1, sp);
|
|
a.resize(a.capacity());
|
|
a.shrink_to_fit();
|
|
BOOST_TEST(a.size() == a.capacity());
|
|
});
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a(sp);
|
|
a.reserve(10);
|
|
BOOST_TEST(a.capacity() >= 10);
|
|
a.shrink_to_fit();
|
|
BOOST_TEST(a.capacity() == 0);
|
|
});
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a(4, sp);
|
|
a.reserve(a.capacity() * 2);
|
|
BOOST_TEST(a.capacity() >= 4);
|
|
a.shrink_to_fit();
|
|
if(a.capacity() != a.size())
|
|
throw test_failure{};
|
|
});
|
|
}
|
|
}
|
|
|
|
void
|
|
testModifiers()
|
|
{
|
|
// clear
|
|
{
|
|
{
|
|
array a;
|
|
BOOST_TEST(a.size() == 0);
|
|
BOOST_TEST(a.capacity() == 0);
|
|
a.clear();
|
|
BOOST_TEST(a.size() == 0);
|
|
BOOST_TEST(a.capacity() == 0);
|
|
}
|
|
{
|
|
array a({1, true, str_});
|
|
a.clear();
|
|
BOOST_TEST(a.size() == 0);
|
|
BOOST_TEST(a.capacity() > 0);
|
|
}
|
|
}
|
|
|
|
// insert(const_iterator, value_type const&)
|
|
{
|
|
// fast path
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a({1, 2, 3}, sp);
|
|
a.pop_back();
|
|
BOOST_TEST(
|
|
a.capacity() > a.size());
|
|
a.insert(a.begin(), 1);
|
|
BOOST_TEST(
|
|
a == array({1, 1, 2}));
|
|
});
|
|
|
|
// self-insert
|
|
{
|
|
array a = {1, 2, 3};
|
|
a.insert(a.begin(), a[1]);
|
|
BOOST_TEST(
|
|
a == array({2, 1, 2, 3}));
|
|
}
|
|
|
|
// fail
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a({1, str_}, sp);
|
|
value v(true);
|
|
a.insert(a.begin() + 1, v);
|
|
check(a);
|
|
check_storage(a, sp);
|
|
});
|
|
}
|
|
|
|
// insert(const_iterator, value_type&&)
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a({1, str_}, sp);
|
|
value v(true);
|
|
a.insert(
|
|
a.begin() + 1, std::move(v));
|
|
check(a);
|
|
check_storage(a, sp);
|
|
});
|
|
|
|
// insert(const_iterator, size_type, value_type const&)
|
|
{
|
|
// fast path
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a({1, str_}, sp);
|
|
a.reserve(3);
|
|
BOOST_TEST(
|
|
a.capacity() > a.size());
|
|
a.insert(&a[1], 1, true);
|
|
check(a);
|
|
});
|
|
|
|
// zero
|
|
{
|
|
array a(3);
|
|
a.insert(&a[1], 0, true);
|
|
BOOST_TEST(a.size() == 3);
|
|
}
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
value v({1,2,3});
|
|
array a({1, str_}, sp);
|
|
a.insert(a.begin() + 1, 3, v);
|
|
BOOST_TEST(a[0].is_number());
|
|
BOOST_TEST(a[1].as_array().size() == 3);
|
|
BOOST_TEST(a[2].as_array().size() == 3);
|
|
BOOST_TEST(a[3].as_array().size() == 3);
|
|
BOOST_TEST(a[4].is_string());
|
|
});
|
|
}
|
|
|
|
// insert(const_iterator, InputIt, InputIt)
|
|
{
|
|
// random iterator
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
std::initializer_list<
|
|
value> init = {1, true};
|
|
array a({str_}, sp);
|
|
a.insert(a.begin(),
|
|
init.begin(), init.end());
|
|
check(a);
|
|
});
|
|
|
|
// random iterator (multiple growth)
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
std::initializer_list<value_ref> init = {
|
|
1, str_, true, 1, 2, 3, 4, 5, 6,
|
|
7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
|
17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
|
|
27, 28, 29, 30 };
|
|
array a(sp);
|
|
a.insert(a.begin(),
|
|
init.begin(), init.end());
|
|
BOOST_TEST(a.size() == init.size());
|
|
BOOST_TEST(a.capacity() == init.size());
|
|
});
|
|
|
|
// input iterator (empty range)
|
|
{
|
|
std::initializer_list<value_ref> init;
|
|
array a;
|
|
a.insert(a.begin(),
|
|
make_input_iterator(init.begin()),
|
|
make_input_iterator(init.end()));
|
|
BOOST_TEST(a.empty());
|
|
}
|
|
|
|
// input iterator
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
std::initializer_list<
|
|
value> init = {1, true};
|
|
array a({str_}, sp);
|
|
a.insert(a.begin(),
|
|
make_input_iterator(init.begin()),
|
|
make_input_iterator(init.end()));
|
|
check(a);
|
|
});
|
|
|
|
// input iterator (multiple growth)
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
std::initializer_list<value_ref> init =
|
|
{1, true, 1, 2, 3, 4, 5, 6, 7};
|
|
array a({str_}, sp);
|
|
a.insert(a.begin(),
|
|
make_input_iterator(init.begin()),
|
|
make_input_iterator(init.end()));
|
|
BOOST_TEST(a.size() == init.size() + 1);
|
|
});
|
|
|
|
// backward relocate
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
std::initializer_list<value_ref> init = {1, 2};
|
|
array a({"a", "b", "c", "d", "e"}, sp);
|
|
a.insert(
|
|
a.begin() + 1,
|
|
init.begin(), init.end());
|
|
});
|
|
}
|
|
|
|
// insert(const_iterator, init_list)
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a({0, 3, 4}, sp);
|
|
auto it = a.insert(
|
|
a.begin() + 1, {1, str_});
|
|
BOOST_TEST(it == a.begin() + 1);
|
|
BOOST_TEST(a[0].as_int64() == 0);
|
|
BOOST_TEST(a[1].as_int64() == 1);
|
|
BOOST_TEST(a[2].as_string() == str_);
|
|
BOOST_TEST(a[3].as_int64() == 3);
|
|
BOOST_TEST(a[4].as_int64() == 4);
|
|
});
|
|
|
|
// emplace(const_iterator, arg)
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a({0, 2, 3, 4}, sp);
|
|
auto it = a.emplace(
|
|
a.begin() + 1, str_);
|
|
BOOST_TEST(it == a.begin() + 1);
|
|
BOOST_TEST(a[0].as_int64() == 0);
|
|
BOOST_TEST(a[1].as_string() == str_);
|
|
BOOST_TEST(a[2].as_int64() == 2);
|
|
BOOST_TEST(a[3].as_int64() == 3);
|
|
BOOST_TEST(a[4].as_int64() == 4);
|
|
});
|
|
|
|
// erase(pos)
|
|
{
|
|
array a({1, true, nullptr, str_});
|
|
a.erase(a.begin() + 2);
|
|
check(a);
|
|
}
|
|
|
|
// erase(first, last)
|
|
{
|
|
array a({1, true, nullptr, 1.f, str_});
|
|
a.erase(
|
|
a.begin() + 2,
|
|
a.begin() + 4);
|
|
check(a);
|
|
}
|
|
|
|
// push_back(value const&)
|
|
{
|
|
// fast path
|
|
{
|
|
array a = {1, 2, 3};
|
|
a.pop_back();
|
|
BOOST_TEST(
|
|
a.capacity() > a.size());
|
|
a.push_back(1);
|
|
BOOST_TEST(a ==
|
|
array({1, 2, 1}));
|
|
}
|
|
|
|
// self push_back
|
|
{
|
|
array a = {1, 2, 3};
|
|
a.push_back(a[1]);
|
|
BOOST_TEST(a ==
|
|
array({1, 2, 3, 2}));
|
|
}
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a({1, true}, sp);
|
|
value v(str_);
|
|
a.push_back(v);
|
|
BOOST_TEST(
|
|
v.as_string() == str_);
|
|
check(a);
|
|
check_storage(a, sp);
|
|
});
|
|
}
|
|
|
|
// push_back(value&&)
|
|
{
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a({1, true}, sp);
|
|
value v(str_);
|
|
a.push_back(std::move(v));
|
|
check(a);
|
|
check_storage(a, sp);
|
|
});
|
|
}
|
|
|
|
// emplace_back(arg)
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a({1, true}, sp);
|
|
a.emplace_back(str_);
|
|
check(a);
|
|
check_storage(a, sp);
|
|
});
|
|
|
|
// pop_back()
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a({1, true, str_, nullptr}, sp);
|
|
a.pop_back();
|
|
check(a);
|
|
check_storage(a, sp);
|
|
});
|
|
|
|
// resize(size_type)
|
|
{
|
|
value v(array{});
|
|
v.as_array().emplace_back(1);
|
|
v.as_array().emplace_back(true);
|
|
v.as_array().emplace_back(str_);
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a(5, sp);
|
|
a.resize(3);
|
|
BOOST_TEST(a.size() == 3);
|
|
check_storage(a, sp);
|
|
});
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a(sp);
|
|
a.resize(3);
|
|
BOOST_TEST(a.size() == 3);
|
|
check_storage(a, sp);
|
|
});
|
|
}
|
|
|
|
// resize(size_type, value_type const&)
|
|
{
|
|
value v(array{});
|
|
v.as_array().emplace_back(1);
|
|
v.as_array().emplace_back(true);
|
|
v.as_array().emplace_back(str_);
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a(5, v, sp);
|
|
a.resize(3, v);
|
|
BOOST_TEST(a.size() == 3);
|
|
check_storage(a, sp);
|
|
});
|
|
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a(3, v, sp);
|
|
a.resize(5, v);
|
|
BOOST_TEST(a.size() == 5);
|
|
check_storage(a, sp);
|
|
});
|
|
}
|
|
|
|
// swap
|
|
{
|
|
// same storage
|
|
{
|
|
array a1({1, true, str_});
|
|
array a2 = {1.};
|
|
a1.swap(a2);
|
|
check(a2);
|
|
BOOST_TEST(a1.size() == 1);
|
|
BOOST_TEST(a1.front().is_number());
|
|
BOOST_TEST(a1.front().as_double() == 1.);
|
|
}
|
|
|
|
// different storage
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a1({1, true, str_}, sp);
|
|
array a2 = {1.};
|
|
a1.swap(a2);
|
|
check(a2);
|
|
BOOST_TEST(a1.size() == 1);
|
|
});
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a1 = {1.};
|
|
array a2({1, true, str_}, sp);
|
|
a1.swap(a2);
|
|
check(a1);
|
|
BOOST_TEST(a2.size() == 1);
|
|
});
|
|
}
|
|
}
|
|
|
|
void
|
|
testExceptions()
|
|
{
|
|
// operator=(array const&)
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a0({1, true, str_});
|
|
array a1;
|
|
array a(sp);
|
|
a.emplace_back(nullptr);
|
|
a = a0;
|
|
a1 = a;
|
|
check(a1);
|
|
});
|
|
|
|
// operator=(init_list)
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
init_list init{ 1, true, str_ };
|
|
array a1;
|
|
array a(sp);
|
|
a.emplace_back(nullptr);
|
|
a = init;
|
|
a1 = a;
|
|
check(a1);
|
|
});
|
|
|
|
// insert(const_iterator, count, value_type const&)
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a1;
|
|
array a({1, true}, sp);
|
|
a.insert(a.begin() + 1,
|
|
3, nullptr);
|
|
a1 = a;
|
|
BOOST_TEST(a1.size() == 5);
|
|
BOOST_TEST(a1[0].is_number());
|
|
BOOST_TEST(a1[1].is_null());
|
|
BOOST_TEST(a1[2].is_null());
|
|
BOOST_TEST(a1[3].is_null());
|
|
BOOST_TEST(a1[4].is_bool());
|
|
});
|
|
|
|
// insert(const_iterator, InputIt, InputIt)
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
init_list init{ 1, true, str_ };
|
|
array a1;
|
|
array a(sp);
|
|
a.insert(a.end(),
|
|
init.begin(), init.end());
|
|
a1 = a;
|
|
check(a1);
|
|
});
|
|
|
|
// emplace(const_iterator, arg)
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a1;
|
|
array a({1, nullptr}, sp);
|
|
a.emplace(a.begin() + 1, true);
|
|
a1 = a;
|
|
BOOST_TEST(a1.size() == 3);
|
|
BOOST_TEST(a1[0].is_number());
|
|
BOOST_TEST(a1[1].is_bool());
|
|
BOOST_TEST(a1[2].is_null());
|
|
});
|
|
|
|
// emplace(const_iterator, arg)
|
|
fail_loop([&](storage_ptr const& sp)
|
|
{
|
|
array a1;
|
|
array a({1, str_}, sp);
|
|
a.emplace(a.begin() + 1, true);
|
|
a1 = a;
|
|
check(a1);
|
|
BOOST_TEST(a1.size() == 3);
|
|
BOOST_TEST(a1[0].is_number());
|
|
BOOST_TEST(a1[1].is_bool());
|
|
BOOST_TEST(a1[2].is_string());
|
|
});
|
|
}
|
|
|
|
void
|
|
testEquality()
|
|
{
|
|
BOOST_TEST(array({}) == array({}));
|
|
BOOST_TEST(array({}) != array({1,2}));
|
|
BOOST_TEST(array({1,2,3}) == array({1,2,3}));
|
|
BOOST_TEST(array({1,2,3}) != array({1,2}));
|
|
BOOST_TEST(array({1,2,3}) != array({3,2,1}));
|
|
}
|
|
|
|
void
|
|
run()
|
|
{
|
|
testDestroy();
|
|
testCtors();
|
|
testAssign();
|
|
testGetStorage();
|
|
testAccess();
|
|
testIterators();
|
|
testCapacity();
|
|
testModifiers();
|
|
testExceptions();
|
|
testEquality();
|
|
}
|
|
};
|
|
|
|
TEST_SUITE(array_test, "boost.json.array");
|
|
|
|
BOOST_JSON_NS_END
|