AimRT/_deps/boost-src/libs/json/test/monotonic_resource.cpp
2025-01-12 20:40:48 +08:00

314 lines
8.6 KiB
C++

//
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/monotonic_resource.hpp>
#include <boost/json/null_resource.hpp>
#include <boost/json/parse.hpp>
#include <boost/json/serialize.hpp>
#include <boost/core/max_align.hpp>
#include <iostream>
#include "test_suite.hpp"
namespace boost {
namespace json {
BOOST_STATIC_ASSERT( std::is_nothrow_destructible<monotonic_resource>::value );
class monotonic_resource_test
{
private:
bool
in_buffer(
void* ptr,
void* buffer,
std::size_t buffer_size)
{
using ptr_t = const volatile unsigned char*;
return reinterpret_cast<ptr_t>(ptr) >= reinterpret_cast<ptr_t>(buffer) &&
reinterpret_cast<ptr_t>(ptr) < reinterpret_cast<ptr_t>(buffer) + buffer_size;
}
bool
all_alloc_in_same_block(
monotonic_resource& mr,
std::size_t bytes,
std::size_t align)
{
// base of the block
auto first = mr.allocate(align, align);
bool result = true;
for (auto allocs = (bytes - align) / align; allocs; --allocs)
result &= in_buffer(mr.allocate(align, align), first, bytes);
return result;
}
public:
void
testJavadocs()
{
//--------------------------------------
unsigned char buf[4000];
monotonic_resource mr( buf );
// Parse the string, using our memory resource
auto const jv = parse( "[1,2,3]", &mr );
// Print the JSON
std::cout << jv;
//--------------------------------------
}
void
testMembers()
{
// ~monotonic_resource
{
// implied
}
// monotonic_resource(size_t, storage_ptr)
{
{
monotonic_resource mr(1);
}
{
monotonic_resource mr(5000);
}
{
monotonic_resource mr(
1, get_null_resource());
}
{
monotonic_resource mr(
5000, get_null_resource());
}
}
// monotonic_resource(unsigned char*, size_t, storage_ptr)
{
{
unsigned char buf[2000];
monotonic_resource mr(
&buf[0], sizeof(buf));
}
{
unsigned char buf[2000];
monotonic_resource mr(
&buf[0], sizeof(buf),
get_null_resource());
}
}
// monotonic_resource(unsigned char[N], storage_ptr)
{
{
unsigned char buf[2000];
monotonic_resource mr(buf);
}
{
unsigned char buf[2000];
monotonic_resource mr(buf,
get_null_resource());
}
}
#ifdef __cpp_lib_byte
// monotonic_resource(std::byte[N], storage_ptr)
{
{
std::byte buf[2000];
monotonic_resource mr(buf);
}
{
std::byte buf[2000];
monotonic_resource mr(buf,
get_null_resource());
}
}
#endif
// monotonic_resource(unsigned char[N], std::size_t, storage_ptr)
{
{
unsigned char buf[2000];
monotonic_resource mr(buf, 1000);
}
{
unsigned char buf[2000];
monotonic_resource mr(buf, 1000,
get_null_resource());
}
}
#ifdef __cpp_lib_byte
// monotonic_resource(unsigned char[N], std::size_t, storage_ptr)
{
{
std::byte buf[2000];
monotonic_resource mr(buf, 1000);
}
{
std::byte buf[2000];
monotonic_resource mr(buf, 1000,
get_null_resource());
}
}
#endif
// release()
{
unsigned char buf[10];
monotonic_resource mr(
buf, sizeof(buf));
(void)mr.allocate(10,1);
mr.release();
(void)mr.allocate(10,1);
}
// coverage
{
monotonic_resource mr(std::size_t(-1)-2);
}
}
void
testGeneral()
{
// test that each block gets filled to capacity
// and if the growth factor is correct
{
monotonic_resource mr;
BOOST_TEST(all_alloc_in_same_block(mr, 1024, 1));
BOOST_TEST(all_alloc_in_same_block(mr, 2048, 2));
BOOST_TEST(all_alloc_in_same_block(mr, 4096, 1));
BOOST_TEST(all_alloc_in_same_block(mr, 8192, 4));
BOOST_TEST(all_alloc_in_same_block(mr, 16384, 1));
BOOST_TEST(all_alloc_in_same_block(mr, 32768, 8));
BOOST_TEST(all_alloc_in_same_block(mr, 65536, 1));
}
// test if each allocation is aligned correctly
{
monotonic_resource mr;
for (std::size_t i = 0; i < 4096; ++i)
{
const auto size = ((i * 3) % 32) + 1;
std::size_t next = 1;
for (auto mod = i % alignof(core::max_align_t);
mod; mod >>= 1, next <<= 1);
const auto align = (std::max)(next,
std::size_t(1));
BOOST_TEST(!(reinterpret_cast<std::uintptr_t>(mr.allocate(size, align)) % align));
}
}
// test if user provided sizes are correctly rounded
{
{
monotonic_resource mr(10);
BOOST_TEST(all_alloc_in_same_block(mr, 1024, 1));
}
{
monotonic_resource mr(1025);
BOOST_TEST(all_alloc_in_same_block(mr, 2048, 1));
}
{
monotonic_resource mr(4000);
BOOST_TEST(all_alloc_in_same_block(mr, 4096, 1));
}
}
// test if sizes are correctly determined from initial buffers
{
{
unsigned char buf[512];
monotonic_resource mr(buf, 512);
BOOST_TEST(all_alloc_in_same_block(mr, 512, 1));
BOOST_TEST(all_alloc_in_same_block(mr, 1024, 1));
}
{
unsigned char buf[2048];
monotonic_resource mr(buf, 2048);
BOOST_TEST(all_alloc_in_same_block(mr, 2048, 1));
BOOST_TEST(all_alloc_in_same_block(mr, 4096, 1));
}
{
unsigned char buf[4000];
monotonic_resource mr(buf, 4000);
BOOST_TEST(all_alloc_in_same_block(mr, 4000, 1));
BOOST_TEST(all_alloc_in_same_block(mr, 4096, 1));
}
}
// test if allocations that exceed the block size cause rounding to occur
{
{
monotonic_resource mr;
auto p = mr.allocate(2048);
(void)p;
BOOST_TEST(all_alloc_in_same_block(mr, 4096, 1));
}
{
monotonic_resource mr;
void* p;
p = mr.allocate(2000, 1);
p = mr.allocate(48, 1);
(void)p;
BOOST_TEST(all_alloc_in_same_block(mr, 4096, 1));
}
}
}
void
testStorage()
{
auto jv = parse(
R"xx({
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
})xx"
, make_shared_resource<monotonic_resource>());
BOOST_TEST_PASS();
}
void
run()
{
testMembers();
testStorage();
testGeneral();
}
};
TEST_SUITE(monotonic_resource_test, "boost.json.monotonic_resource");
} // namespace json
} // namespace boost