1 // 2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) 3 // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com) 4 // 5 // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 // 8 // Official repository: https://github.com/boostorg/json 9 // 10 11 // Test that header file is self-contained. 12 #include <boost/json/monotonic_resource.hpp> 13 14 #include <boost/json/null_resource.hpp> 15 #include <boost/json/parse.hpp> 16 #include <boost/json/serialize.hpp> 17 #include <boost/json/detail/align.hpp> 18 #include <iostream> 19 20 #include "test_suite.hpp" 21 22 BOOST_JSON_NS_BEGIN 23 24 BOOST_STATIC_ASSERT( std::is_nothrow_destructible<monotonic_resource>::value ); 25 26 class monotonic_resource_test 27 { 28 private: 29 bool in_buffer(void * ptr,void * buffer,std::size_t buffer_size)30 in_buffer( 31 void* ptr, 32 void* buffer, 33 std::size_t buffer_size) 34 { 35 using ptr_t = const volatile unsigned char*; 36 return reinterpret_cast<ptr_t>(ptr) >= reinterpret_cast<ptr_t>(buffer) && 37 reinterpret_cast<ptr_t>(ptr) < reinterpret_cast<ptr_t>(buffer) + buffer_size; 38 } 39 40 bool all_alloc_in_same_block(monotonic_resource & mr,std::size_t bytes,std::size_t align)41 all_alloc_in_same_block( 42 monotonic_resource& mr, 43 std::size_t bytes, 44 std::size_t align) 45 { 46 // base of the block 47 auto first = mr.allocate(align, align); 48 bool result = true; 49 for (auto allocs = (bytes - align) / align; allocs; --allocs) 50 result &= in_buffer(mr.allocate(align, align), first, bytes); 51 return result; 52 } 53 54 public: 55 void testJavadocs()56 testJavadocs() 57 { 58 //-------------------------------------- 59 60 unsigned char buf[4000]; 61 monotonic_resource mr( buf ); 62 63 // Parse the string, using our memory resource 64 auto const jv = parse( "[1,2,3]", &mr ); 65 66 // Print the JSON 67 std::cout << jv; 68 69 //-------------------------------------- 70 } 71 72 void testMembers()73 testMembers() 74 { 75 // ~monotonic_resource 76 { 77 // implied 78 } 79 80 // monotonic_resource(size_t, storage_ptr) 81 { 82 { 83 monotonic_resource mr(1); 84 } 85 { 86 monotonic_resource mr(5000); 87 } 88 { 89 monotonic_resource mr( 90 1, get_null_resource()); 91 } 92 { 93 monotonic_resource mr( 94 5000, get_null_resource()); 95 } 96 } 97 98 // monotonic_resource(unsigned char*, size_t, storage_ptr) 99 { 100 { 101 unsigned char buf[2000]; 102 monotonic_resource mr( 103 &buf[0], sizeof(buf)); 104 } 105 { 106 unsigned char buf[2000]; 107 monotonic_resource mr( 108 &buf[0], sizeof(buf), 109 get_null_resource()); 110 } 111 } 112 113 // monotonic_resource(unsigned char[N], storage_ptr) 114 { 115 { 116 unsigned char buf[2000]; 117 monotonic_resource mr(buf); 118 } 119 { 120 unsigned char buf[2000]; 121 monotonic_resource mr(buf, 122 get_null_resource()); 123 } 124 } 125 126 #ifdef __cpp_lib_byte 127 // monotonic_resource(std::byte[N], storage_ptr) 128 { 129 { 130 std::byte buf[2000]; 131 monotonic_resource mr(buf); 132 } 133 134 { 135 std::byte buf[2000]; 136 monotonic_resource mr(buf, 137 get_null_resource()); 138 } 139 } 140 #endif 141 142 // monotonic_resource(unsigned char[N], std::size_t, storage_ptr) 143 { 144 { 145 unsigned char buf[2000]; 146 monotonic_resource mr(buf, 1000); 147 } 148 { 149 unsigned char buf[2000]; 150 monotonic_resource mr(buf, 1000, 151 get_null_resource()); 152 } 153 } 154 155 #ifdef __cpp_lib_byte 156 // monotonic_resource(unsigned char[N], std::size_t, storage_ptr) 157 { 158 { 159 std::byte buf[2000]; 160 monotonic_resource mr(buf, 1000); 161 } 162 { 163 std::byte buf[2000]; 164 monotonic_resource mr(buf, 1000, 165 get_null_resource()); 166 } 167 } 168 #endif 169 170 // release() 171 { 172 unsigned char buf[10]; 173 monotonic_resource mr( 174 buf, sizeof(buf)); 175 (void)mr.allocate(10,1); 176 mr.release(); 177 (void)mr.allocate(10,1); 178 } 179 180 // coverage 181 { 182 monotonic_resource mr(std::size_t(-1)-2); 183 } 184 } 185 186 void testGeneral()187 testGeneral() 188 { 189 // test that each block gets filled to capacity 190 // and if the growth factor is correct 191 { 192 monotonic_resource mr; 193 BOOST_TEST(all_alloc_in_same_block(mr, 1024, 1)); 194 BOOST_TEST(all_alloc_in_same_block(mr, 2048, 2)); 195 BOOST_TEST(all_alloc_in_same_block(mr, 4096, 1)); 196 BOOST_TEST(all_alloc_in_same_block(mr, 8192, 4)); 197 BOOST_TEST(all_alloc_in_same_block(mr, 16384, 1)); 198 BOOST_TEST(all_alloc_in_same_block(mr, 32768, 8)); 199 BOOST_TEST(all_alloc_in_same_block(mr, 65536, 1)); 200 } 201 // test if each allocation is aligned correctly 202 { 203 monotonic_resource mr; 204 for (std::size_t i = 0; i < 4096; ++i) 205 { 206 const auto size = ((i * 3) % 32) + 1; 207 std::size_t next = 1; 208 for (auto mod = i % alignof(detail::max_align_t); 209 mod; mod >>= 1, next <<= 1); 210 const auto align = (std::max)(next, 211 std::size_t(1)); 212 BOOST_TEST(!(reinterpret_cast<std::uintptr_t>(mr.allocate(size, align)) % align)); 213 } 214 } 215 // test if user provided sizes are correctly rounded 216 { 217 { 218 monotonic_resource mr(10); 219 BOOST_TEST(all_alloc_in_same_block(mr, 1024, 1)); 220 } 221 { 222 monotonic_resource mr(1025); 223 BOOST_TEST(all_alloc_in_same_block(mr, 2048, 1)); 224 } 225 { 226 monotonic_resource mr(4000); 227 BOOST_TEST(all_alloc_in_same_block(mr, 4096, 1)); 228 } 229 } 230 // test if sizes are correctly determined from initial buffers 231 { 232 { 233 unsigned char buf[512]; 234 monotonic_resource mr(buf, 512); 235 BOOST_TEST(all_alloc_in_same_block(mr, 512, 1)); 236 BOOST_TEST(all_alloc_in_same_block(mr, 1024, 1)); 237 } 238 { 239 unsigned char buf[2048]; 240 monotonic_resource mr(buf, 2048); 241 BOOST_TEST(all_alloc_in_same_block(mr, 2048, 1)); 242 BOOST_TEST(all_alloc_in_same_block(mr, 4096, 1)); 243 } 244 { 245 unsigned char buf[4000]; 246 monotonic_resource mr(buf, 4000); 247 BOOST_TEST(all_alloc_in_same_block(mr, 4000, 1)); 248 BOOST_TEST(all_alloc_in_same_block(mr, 4096, 1)); 249 } 250 } 251 // test if allocations that exceed the block size cause rounding to occur 252 { 253 { 254 monotonic_resource mr; 255 auto p = mr.allocate(2048); 256 (void)p; 257 BOOST_TEST(all_alloc_in_same_block(mr, 4096, 1)); 258 } 259 { 260 monotonic_resource mr; 261 void* p; 262 p = mr.allocate(2000, 1); 263 p = mr.allocate(48, 1); 264 (void)p; 265 BOOST_TEST(all_alloc_in_same_block(mr, 4096, 1)); 266 } 267 } 268 } 269 270 void testStorage()271 testStorage() 272 { 273 auto jv = parse( 274 R"xx({ 275 "glossary": { 276 "title": "example glossary", 277 "GlossDiv": { 278 "title": "S", 279 "GlossList": { 280 "GlossEntry": { 281 "ID": "SGML", 282 "SortAs": "SGML", 283 "GlossTerm": "Standard Generalized Markup Language", 284 "Acronym": "SGML", 285 "Abbrev": "ISO 8879:1986", 286 "GlossDef": { 287 "para": "A meta-markup language, used to create markup languages such as DocBook.", 288 "GlossSeeAlso": ["GML", "XML"] 289 }, 290 "GlossSee": "markup" 291 } 292 } 293 } 294 } 295 })xx" 296 , make_shared_resource<monotonic_resource>()); 297 BOOST_TEST_PASS(); 298 } 299 300 void run()301 run() 302 { 303 testMembers(); 304 testStorage(); 305 testGeneral(); 306 } 307 }; 308 309 TEST_SUITE(monotonic_resource_test, "boost.json.monotonic_resource"); 310 311 BOOST_JSON_NS_END 312