1 | ////////////////////////////////////////////////////////////////////////////// |
---|---|
2 | // |
3 | // (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost |
4 | // Software License, Version 1.0. (See accompanying file |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | // |
7 | // See http://www.boost.org/libs/container for documentation. |
8 | // |
9 | ////////////////////////////////////////////////////////////////////////////// |
10 | #include <boost/container/pmr/global_resource.hpp> |
11 | #include <boost/container/pmr/memory_resource.hpp> |
12 | #include <boost/core/lightweight_test.hpp> |
13 | |
14 | #include "derived_from_memory_resource.hpp" |
15 | |
16 | #include <cstdlib> |
17 | #include <new> |
18 | |
19 | using namespace boost::container; |
20 | using namespace boost::container::pmr; |
21 | |
22 | #ifdef BOOST_MSVC |
23 | #pragma warning (push) |
24 | #pragma warning (disable : 4290) |
25 | #endif |
26 | |
27 | #if __cplusplus >= 201103L |
28 | #define BOOST_CONTAINER_NEW_EXCEPTION_SPECIFIER |
29 | #define BOOST_CONTAINER_DELETE_EXCEPTION_SPECIFIER noexcept |
30 | #else |
31 | #define BOOST_CONTAINER_NEW_EXCEPTION_SPECIFIER throw(std::bad_alloc) |
32 | #define BOOST_CONTAINER_DELETE_EXCEPTION_SPECIFIER throw() |
33 | #endif |
34 | |
35 | #if defined(BOOST_GCC) && (BOOST_GCC >= 50000) |
36 | #pragma GCC diagnostic ignored "-Wsized-deallocation" |
37 | #endif |
38 | |
39 | //ASAN does not support operator new overloading |
40 | #ifndef BOOST_CONTAINER_ASAN |
41 | |
42 | std::size_t allocation_count = 0; |
43 | |
44 | void* operator new[](std::size_t count) BOOST_CONTAINER_NEW_EXCEPTION_SPECIFIER |
45 | { |
46 | ++allocation_count; |
47 | return std::malloc(size: count); |
48 | } |
49 | |
50 | void operator delete[](void *p) BOOST_CONTAINER_DELETE_EXCEPTION_SPECIFIER |
51 | { |
52 | --allocation_count; |
53 | return std::free(ptr: p); |
54 | } |
55 | |
56 | #endif //BOOST_CONTAINER_ASAN |
57 | |
58 | #ifdef BOOST_MSVC |
59 | #pragma warning (pop) |
60 | #endif |
61 | |
62 | #ifndef BOOST_CONTAINER_ASAN |
63 | |
64 | void test_new_delete_resource() |
65 | { |
66 | //Make sure new_delete_resource calls new[]/delete[] |
67 | std::size_t memcount = allocation_count; |
68 | memory_resource *mr = new_delete_resource(); |
69 | //each time should return the same pointer |
70 | BOOST_TEST(mr == new_delete_resource()); |
71 | #if !defined(BOOST_CONTAINER_DYNAMIC_LINKING) //No new delete replacement possible new_delete is a DLL |
72 | BOOST_TEST(memcount == allocation_count); |
73 | #endif |
74 | void *addr = mr->allocate(bytes: 16, alignment: 1); |
75 | #if !defined(BOOST_CONTAINER_DYNAMIC_LINKING) //No new delete replacement possible new_delete is a DLL |
76 | BOOST_TEST((allocation_count - memcount) == 1); |
77 | #endif |
78 | mr->deallocate(p: addr, bytes: 16, alignment: 1); |
79 | BOOST_TEST(memcount == allocation_count); |
80 | } |
81 | |
82 | #endif //BOOST_CONTAINER_ASAN |
83 | |
84 | void test_null_memory_resource() |
85 | { |
86 | //Make sure it throw or returns null |
87 | memory_resource *mr = null_memory_resource(); |
88 | BOOST_TEST(mr != 0); |
89 | |
90 | #if !defined(BOOST_NO_EXCEPTIONS) |
91 | bool bad_allocexception_thrown = false; |
92 | |
93 | BOOST_CONTAINER_TRY{ |
94 | mr->allocate(bytes: 1, alignment: 1); |
95 | } |
96 | BOOST_CONTAINER_CATCH(std::bad_alloc&) { |
97 | bad_allocexception_thrown = true; |
98 | } |
99 | BOOST_CONTAINER_CATCH(...) { |
100 | } |
101 | BOOST_CONTAINER_CATCH_END |
102 | |
103 | BOOST_TEST(bad_allocexception_thrown == true); |
104 | #endif //BOOST_NO_EXCEPTIONS |
105 | } |
106 | |
107 | void test_default_resource() |
108 | { |
109 | //Default resource must be new/delete before set_default_resource |
110 | BOOST_TEST(get_default_resource() == new_delete_resource()); |
111 | //Set default resource and obtain previous |
112 | derived_from_memory_resource d; |
113 | memory_resource *prev_default = set_default_resource(&d); |
114 | BOOST_TEST(get_default_resource() == &d); |
115 | //Set default resource with null, which should be new/delete |
116 | prev_default = set_default_resource(0); |
117 | BOOST_TEST(prev_default == &d); |
118 | BOOST_TEST(get_default_resource() == new_delete_resource()); |
119 | } |
120 | |
121 | int main() |
122 | { |
123 | #ifndef BOOST_CONTAINER_ASAN |
124 | test_new_delete_resource(); |
125 | #endif |
126 | test_null_memory_resource(); |
127 | test_default_resource(); |
128 | return ::boost::report_errors(); |
129 | } |
130 |