Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / objectstore / Allocator_test.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * In memory space allocator test cases.
5  * Author: Ramesh Chander, Ramesh.Chander@sandisk.com
6  */
7 #include <iostream>
8 #include <boost/scoped_ptr.hpp>
9 #include <gtest/gtest.h>
10
11 #include "common/Mutex.h"
12 #include "common/Cond.h"
13 #include "common/errno.h"
14 #include "include/stringify.h"
15 #include "include/Context.h"
16 #include "os/bluestore/Allocator.h"
17 #include "os/bluestore/BitAllocator.h"
18
19
20 #if GTEST_HAS_PARAM_TEST
21
22 class AllocTest : public ::testing::TestWithParam<const char*> {
23 public:
24     boost::scoped_ptr<Allocator> alloc;
25     AllocTest(): alloc(0) { }
26     void init_alloc(int64_t size, uint64_t min_alloc_size) {
27       std::cout << "Creating alloc type " << string(GetParam()) << " \n";
28       alloc.reset(Allocator::create(g_ceph_context, string(GetParam()), size,
29                                     min_alloc_size));
30     }
31
32     void init_close() {
33       alloc.reset(0);
34     }
35 };
36
37 TEST_P(AllocTest, test_alloc_init)
38 {
39   int64_t blocks = BmapEntry::size();
40   init_alloc(blocks, 1);
41   ASSERT_EQ(0U, alloc->get_free());
42   alloc->shutdown(); 
43   blocks = BitMapZone::get_total_blocks() * 2 + 16;
44   init_alloc(blocks, 1);
45   ASSERT_EQ(0U, alloc->get_free());
46   alloc->shutdown(); 
47   blocks = BitMapZone::get_total_blocks() * 2;
48   init_alloc(blocks, 1);
49   ASSERT_EQ(alloc->get_free(), (uint64_t) 0);
50 }
51
52 TEST_P(AllocTest, test_alloc_min_alloc)
53 {
54   int64_t block_size = 1024;
55   int64_t blocks = BitMapZone::get_total_blocks() * 2 * block_size;
56
57   {
58     init_alloc(blocks, block_size);
59     alloc->init_add_free(block_size, block_size);
60     EXPECT_EQ(alloc->reserve(block_size), 0);
61     AllocExtentVector extents;
62     EXPECT_EQ(block_size, alloc->allocate(block_size, block_size,
63                                           0, (int64_t) 0, &extents));
64   }
65
66   /*
67    * Allocate extent and make sure all comes in single extent.
68    */   
69   {
70     alloc->init_add_free(0, block_size * 4);
71     EXPECT_EQ(alloc->reserve(block_size * 4), 0);
72     AllocExtentVector extents;
73     EXPECT_EQ(4*block_size,
74               alloc->allocate(4 * (uint64_t)block_size, (uint64_t) block_size,
75                               0, (int64_t) 0, &extents));
76     EXPECT_EQ(1u, extents.size());
77     EXPECT_EQ(extents[0].length, 4 * block_size);
78   }
79
80   /*
81    * Allocate extent and make sure we get two different extents.
82    */
83   {
84     alloc->init_add_free(0, block_size * 2);
85     alloc->init_add_free(3 * block_size, block_size * 2);
86     EXPECT_EQ(alloc->reserve(block_size * 4), 0);
87     AllocExtentVector extents;
88   
89     EXPECT_EQ(4*block_size,
90               alloc->allocate(4 * (uint64_t)block_size, (uint64_t) block_size,
91                               0, (int64_t) 0, &extents));
92     EXPECT_EQ(2u, extents.size());
93     EXPECT_EQ(extents[0].length, 2 * block_size);
94     EXPECT_EQ(extents[1].length, 2 * block_size);
95   }
96   alloc->shutdown();
97 }
98
99 TEST_P(AllocTest, test_alloc_min_max_alloc)
100 {
101   int64_t block_size = 1024;
102   int64_t blocks = BitMapZone::get_total_blocks() * 2 * block_size;
103
104   init_alloc(blocks, block_size);
105
106   /*
107    * Make sure we get all extents different when
108    * min_alloc_size == max_alloc_size
109    */
110   {
111     alloc->init_add_free(0, block_size * 4);
112     EXPECT_EQ(alloc->reserve(block_size * 4), 0);
113     AllocExtentVector extents;
114     EXPECT_EQ(4*block_size,
115               alloc->allocate(4 * (uint64_t)block_size, (uint64_t) block_size,
116                               block_size, (int64_t) 0, &extents));
117     for (auto e : extents) {
118       EXPECT_EQ(e.length, block_size);
119     }
120     EXPECT_EQ(4u, extents.size());
121   }
122
123
124   /*
125    * Make sure we get extents of length max_alloc size
126    * when max alloc size > min_alloc size
127    */
128   {
129     alloc->init_add_free(0, block_size * 4);
130     EXPECT_EQ(alloc->reserve(block_size * 4), 0);
131     AllocExtentVector extents;
132     EXPECT_EQ(4*block_size,
133               alloc->allocate(4 * (uint64_t)block_size, (uint64_t) block_size,
134                               2 * block_size, (int64_t) 0, &extents));
135     EXPECT_EQ(2u, extents.size());
136     for (auto& e : extents) {
137       EXPECT_EQ(e.length, block_size * 2);
138     }
139   }
140
141   /*
142    * Make sure allocations are of min_alloc_size when min_alloc_size > block_size.
143    */
144   {
145     alloc->init_add_free(0, block_size * 1024);
146     EXPECT_EQ(alloc->reserve(block_size * 1024), 0);
147     AllocExtentVector extents;
148     EXPECT_EQ(1024 * block_size,
149               alloc->allocate(1024 * (uint64_t)block_size,
150                               (uint64_t) block_size * 4,
151                               block_size * 4, (int64_t) 0, &extents));
152     for (auto& e : extents) {
153       EXPECT_EQ(e.length, block_size * 4);
154     }
155     EXPECT_EQ(1024u/4, extents.size());
156   }
157
158   /*
159    * Allocate and free.
160    */
161   {
162     alloc->init_add_free(0, block_size * 16);
163     EXPECT_EQ(alloc->reserve(block_size * 16), 0);
164     AllocExtentVector extents;
165     EXPECT_EQ(16 * block_size,
166               alloc->allocate(16 * (uint64_t)block_size, (uint64_t) block_size,
167                               2 * block_size, (int64_t) 0, &extents));
168
169     EXPECT_EQ(extents.size(), 8u);
170     for (auto& e : extents) {
171       EXPECT_EQ(e.length, 2 * block_size);
172     }
173   }
174 }
175
176 TEST_P(AllocTest, test_alloc_failure)
177 {
178   int64_t block_size = 1024;
179   int64_t blocks = BitMapZone::get_total_blocks() * block_size;
180
181   init_alloc(blocks, block_size);
182   {
183     alloc->init_add_free(0, block_size * 256);
184     alloc->init_add_free(block_size * 512, block_size * 256);
185
186     EXPECT_EQ(alloc->reserve(block_size * 512), 0);
187     AllocExtentVector extents;
188     EXPECT_EQ(512 * block_size,
189               alloc->allocate(512 * (uint64_t)block_size,
190                               (uint64_t) block_size * 256,
191                               block_size * 256, (int64_t) 0, &extents));
192     alloc->init_add_free(0, block_size * 256);
193     alloc->init_add_free(block_size * 512, block_size * 256);
194     extents.clear();
195     EXPECT_EQ(alloc->reserve(block_size * 512), 0);
196     EXPECT_EQ(-ENOSPC,
197               alloc->allocate(512 * (uint64_t)block_size,
198                               (uint64_t) block_size * 512,
199                               block_size * 512, (int64_t) 0, &extents));
200   }
201 }
202
203 TEST_P(AllocTest, test_alloc_big)
204 {
205   int64_t block_size = 4096;
206   int64_t blocks = 104857600;
207   int64_t mas = 4096;
208   init_alloc(blocks*block_size, block_size);
209   alloc->init_add_free(2*block_size, (blocks-2)*block_size);
210   for (int64_t big = mas; big < 1048576*128; big*=2) {
211     cout << big << std::endl;
212     EXPECT_EQ(alloc->reserve(big), 0);
213     AllocExtentVector extents;
214     EXPECT_EQ(big,
215               alloc->allocate(big, mas, 0, &extents));
216   }
217 }
218
219 TEST_P(AllocTest, test_alloc_hint_bmap)
220 {
221   if (GetParam() == std::string("stupid")) {
222     return;
223   }
224   int64_t blocks = BitMapArea::get_level_factor(g_ceph_context, 2) * 4;
225   int64_t allocated = 0;
226   int64_t zone_size = 1024;
227   g_conf->set_val("bluestore_bitmapallocator_blocks_per_zone",
228                   std::to_string(zone_size));
229
230   init_alloc(blocks, 1);
231   alloc->init_add_free(0, blocks);
232
233   AllocExtentVector extents;
234   alloc->reserve(blocks);
235
236   allocated = alloc->allocate(1, 1, 1, zone_size, &extents);
237   ASSERT_EQ(1, allocated);
238   ASSERT_EQ(1u, extents.size());
239   ASSERT_EQ(extents[0].offset, (uint64_t) zone_size);
240
241   extents.clear();
242   allocated = alloc->allocate(1, 1, 1, zone_size * 2 - 1, &extents);
243   EXPECT_EQ(1, allocated);
244   ASSERT_EQ(1u, extents.size());
245   EXPECT_EQ((int64_t) extents[0].offset, zone_size * 2 - 1);
246
247   /*
248    * Wrap around with hint
249    */
250   extents.clear();
251   allocated = alloc->allocate(zone_size * 2, 1, 1,  blocks - zone_size * 2,
252                               &extents);
253   ASSERT_EQ(zone_size * 2, allocated);
254   EXPECT_EQ(zone_size * 2, (int)extents.size());
255   EXPECT_EQ((int64_t)extents[0].offset, blocks - zone_size * 2);
256
257   extents.clear();
258   allocated = alloc->allocate(zone_size, 1, 1, blocks - zone_size, &extents);
259   ASSERT_EQ(zone_size, allocated);
260   EXPECT_EQ(zone_size, (int)extents.size());
261   EXPECT_EQ(extents[0].offset, (uint64_t) 0);
262   /*
263    * Verify out-of-bound hint
264    */
265   extents.clear();
266   allocated = alloc->allocate(1, 1, 1, blocks, &extents);
267   ASSERT_EQ(1, allocated);
268   EXPECT_EQ(1, (int)extents.size());
269
270   extents.clear();
271   allocated = alloc->allocate(1, 1, 1, blocks * 3 + 1 , &extents);
272   ASSERT_EQ(1, allocated);
273   EXPECT_EQ(1, (int)extents.size());
274 }
275
276 TEST_P(AllocTest, test_alloc_non_aligned_len)
277 {
278   int64_t block_size = 1 << 12;
279   int64_t blocks = (1 << 20) * 100;
280   int64_t want_size = 1 << 22;
281   int64_t alloc_unit = 1 << 20;
282   
283   init_alloc(blocks*block_size, block_size);
284   alloc->init_add_free(0, 2097152);
285   alloc->init_add_free(2097152, 1064960);
286   alloc->init_add_free(3670016, 2097152);
287
288   EXPECT_EQ(0, alloc->reserve(want_size));
289   AllocExtentVector extents;
290   EXPECT_EQ(want_size, alloc->allocate(want_size, alloc_unit, 0, &extents));
291 }
292
293
294 INSTANTIATE_TEST_CASE_P(
295   Allocator,
296   AllocTest,
297   ::testing::Values("stupid", "bitmap"));
298
299 #else
300
301 TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {}
302 #endif