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/resource_adaptor.hpp>
11#include <boost/core/lightweight_test.hpp>
12#include "propagation_test_allocator.hpp"
13#include "derived_from_memory_resource.hpp"
14#include <boost/container/new_allocator.hpp>
15#include <memory>
16
17using namespace boost::container::pmr;
18
19static const std::size_t max_alignment_value = boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value;
20
21void test_default_constructor()
22{
23 typedef propagation_test_allocator<char, 0> alloc_t;
24 resource_adaptor<alloc_t> ra;
25 BOOST_TEST(ra.get_allocator().m_default_contructed == true);
26}
27
28void test_copy_constructor()
29{
30 typedef propagation_test_allocator<char, 0> alloc_t;
31 resource_adaptor<alloc_t> ra;
32 BOOST_TEST(ra.get_allocator().m_default_contructed == true);
33 resource_adaptor<alloc_t> rb(ra);
34 BOOST_TEST(rb.get_allocator().m_default_contructed == false);
35 BOOST_TEST(rb.get_allocator().m_move_contructed == false);
36}
37
38void test_move_constructor()
39{
40 typedef propagation_test_allocator<char, 0> alloc_t;
41 resource_adaptor<alloc_t> ra;
42 BOOST_TEST(ra.get_allocator().m_default_contructed == true);
43 resource_adaptor<alloc_t> rb(::boost::move(t&: ra));
44 BOOST_TEST(rb.get_allocator().m_default_contructed == false);
45 BOOST_TEST(rb.get_allocator().m_move_contructed == true);
46}
47
48void test_lvalue_alloc_constructor()
49{
50 typedef propagation_test_allocator<char, 0> alloc_t;
51 alloc_t a;
52 resource_adaptor<alloc_t> ra(a);
53 BOOST_TEST(ra.get_allocator().m_default_contructed == false);
54 BOOST_TEST(ra.get_allocator().m_move_contructed == false);
55}
56
57void test_rvalue_alloc_constructor()
58{
59 typedef propagation_test_allocator<char, 0> alloc_t;
60 alloc_t a;
61 resource_adaptor<alloc_t> ra(::boost::move(t&: a));
62 BOOST_TEST(ra.get_allocator().m_default_contructed == false);
63 BOOST_TEST(ra.get_allocator().m_move_contructed == true);
64}
65
66void test_copy_assign()
67{
68 typedef propagation_test_allocator<char, 0> alloc_t;
69 resource_adaptor<alloc_t> ra;
70 BOOST_TEST(ra.get_allocator().m_default_contructed == true);
71 resource_adaptor<alloc_t> rb;
72 BOOST_TEST(ra.get_allocator().m_default_contructed == true);
73 rb = ra;
74 BOOST_TEST(rb.get_allocator().m_move_contructed == false);
75 BOOST_TEST(rb.get_allocator().m_move_assigned == false);
76}
77
78void test_move_assign()
79{
80 typedef propagation_test_allocator<char, 0> alloc_t;
81 resource_adaptor<alloc_t> ra;
82 BOOST_TEST(ra.get_allocator().m_default_contructed == true);
83 resource_adaptor<alloc_t> rb;
84 BOOST_TEST(ra.get_allocator().m_default_contructed == true);
85 rb = ::boost::move(t&: ra);
86 BOOST_TEST(rb.get_allocator().m_move_contructed == false);
87 BOOST_TEST(rb.get_allocator().m_move_assigned == true);
88}
89
90struct stateful
91{
92 public:
93 typedef char value_type;
94
95 template<class U>
96 struct rebind
97 { typedef stateful other; };
98
99 stateful()
100 : m_u(0u)
101 {}
102
103 char *allocate(std::size_t n)
104 { allocate_size = n; return allocate_return; }
105
106 void deallocate(char *p, std::size_t n)
107 { deallocate_p = p; deallocate_size = n; }
108
109 friend bool operator==(const stateful &l, const stateful &r)
110 { return l.m_u == r.m_u; }
111
112 friend bool operator!=(const stateful &l, const stateful &r)
113 { return l.m_u != r.m_u; }
114
115 public:
116 unsigned m_u;
117 std::size_t allocate_size;
118 char *allocate_return;
119 std::size_t deallocate_size;
120 char *deallocate_p;
121};
122
123void test_get_allocator()
124{
125 stateful a;
126 a.m_u = 999;
127 resource_adaptor<stateful> ra(a);
128 const resource_adaptor<stateful> & cra = ra;
129 BOOST_TEST( ra.get_allocator().m_u == 999);
130 BOOST_TEST(cra.get_allocator().m_u == 999);
131}
132
133typedef resource_adaptor<stateful> stateful_resource_adaptor_t;
134
135struct derived_from_resource_adaptor_stateful
136 : public stateful_resource_adaptor_t
137{
138 public:
139 typedef stateful_resource_adaptor_t base_t;
140 using base_t::do_allocate;
141 using base_t::do_deallocate;
142 using base_t::do_is_equal;
143};
144
145void test_do_allocate_deallocate()
146{
147 {
148 derived_from_resource_adaptor_stateful dra;
149 char dummy = 0;
150 dra.get_allocator().allocate_return = &dummy;
151 void *allocate_ret = dra.do_allocate(bytes: 998, alignment: 1);
152 BOOST_TEST(allocate_ret == &dummy);
153 BOOST_TEST(dra.get_allocator().allocate_size == 998);
154 }
155 {
156 derived_from_resource_adaptor_stateful dra;
157 char dummy = 0;
158 dra.do_deallocate(p: &dummy, bytes: 1234, alignment: 1);
159 BOOST_TEST(dra.get_allocator().deallocate_p == &dummy);
160 BOOST_TEST(dra.get_allocator().deallocate_size == 1234);
161 }
162 {
163 //Overaligned allocation
164 derived_from_resource_adaptor_stateful dra;
165 const std::size_t alignment = max_alignment_value*2u;
166 const std::size_t bytes = alignment/2;
167 char dummy[alignment*2u+sizeof(void*)];
168 dra.get_allocator().allocate_return = dummy;
169
170 //First allocate
171 void *allocate_ret = dra.do_allocate(bytes, alignment);
172 BOOST_TEST( (char*)allocate_ret >= (dummy+sizeof(void*)) && (char*)allocate_ret < (dummy + sizeof(dummy)) );
173 BOOST_TEST( (std::size_t(allocate_ret) & (alignment - 1u)) == 0 );
174 BOOST_TEST( dra.get_allocator().allocate_size >= (alignment/2+sizeof(void*)) );
175
176 //Then allocate
177 dra.do_deallocate(p: allocate_ret, bytes, alignment);
178 BOOST_TEST(dra.get_allocator().deallocate_p == dummy);
179 BOOST_TEST(dra.get_allocator().deallocate_size == dra.get_allocator().allocate_size);
180 }
181 {
182 typedef resource_adaptor< boost::container::new_allocator<int> > new_resource_alloc_t;
183 new_resource_alloc_t ra;
184 boost::container::pmr::memory_resource &mr = ra;
185
186 //new_allocator, low alignment
187 mr.deallocate(p: mr.allocate(bytes: 16, alignment: 1), bytes: 16, alignment: 1);
188
189 //new_allocator, high alignment
190 mr.deallocate(p: mr.allocate(bytes: 16, alignment: max_alignment_value*4u), bytes: 16, alignment: max_alignment_value*4u);
191 }
192 {
193 typedef resource_adaptor<std ::allocator<int> > new_resource_alloc_t;
194 new_resource_alloc_t ra;
195 boost::container::pmr::memory_resource &mr = ra;
196
197 //std::allocator, low alignment
198 mr.deallocate(p: mr.allocate(bytes: 16, alignment: 1), bytes: 16, alignment: 1);
199
200 //std::allocator, high alignment
201 mr.deallocate(p: mr.allocate(bytes: 16, alignment: max_alignment_value*4u), bytes: 16, alignment: max_alignment_value*4u);
202 }
203}
204
205void test_do_is_equal()
206{
207 derived_from_resource_adaptor_stateful dra;
208 derived_from_memory_resource dmr;
209 //Different dynamic type must return false
210 BOOST_TEST(dra.do_is_equal(dmr) == false);
211
212 //Same dynamic type with same state must return true
213 derived_from_resource_adaptor_stateful dra2;
214 BOOST_TEST(dra.do_is_equal(dra2) == true);
215
216 //Same dynamic type with different state must return false
217 dra2.get_allocator().m_u = 1234;
218 BOOST_TEST(dra.do_is_equal(dra2) == false);
219}
220
221int main()
222{
223 test_default_constructor();
224 test_copy_constructor();
225 test_move_constructor();
226 test_lvalue_alloc_constructor();
227 test_rvalue_alloc_constructor();
228 test_copy_assign();
229 test_move_assign();
230 test_get_allocator();
231 test_do_allocate_deallocate();
232 test_do_is_equal();
233 return ::boost::report_errors();
234}
235

source code of boost/libs/container/test/resource_adaptor_test.cpp