Line data Source code
1 : //
2 : // Author: Vladimir Migashko <migashko@gmail.com>, (C) 2012
3 : //
4 : // Copyright: See COPYING file that comes with this distribution
5 : //
6 :
7 : #include <fas/testing.hpp>
8 : #include <vset/vtree/vtree.hpp>
9 : #include <vset/vtree/strategy.hpp>
10 :
11 : #include <stdexcept>
12 : #include <sstream>
13 : #include <set>
14 : #include <list>
15 : #include <stack>
16 : #include <vector>
17 :
18 1 : std::stack<std::string> test_stack;
19 1 : std::stringstream output_buffer;
20 :
21 : void raise(const std::string& text, const std::string& file = __FILE__, int pos = __LINE__ );
22 0 : void raise(const std::string& text, const std::string& file, int pos )
23 : {
24 0 : std::cout << output_buffer.str();
25 0 : while ( !test_stack.empty() )
26 : {
27 0 : std::cout << test_stack.top() << std::endl;
28 0 : test_stack.pop();
29 : }
30 0 : std::stringstream ss;
31 0 : ss << file << ":" << pos << " " << std::endl << text;
32 0 : throw std::logic_error(ss.str());
33 : }
34 :
35 0 : struct init_sequence
36 : {
37 : int count;
38 : int first;
39 : int last;
40 :
41 : std::vector<int> vect;
42 :
43 0 : init_sequence(int c, int f, int l)
44 : : count(c)
45 : , first(f)
46 0 : , last(l)
47 : {
48 0 : double step = double(last - first)/count;
49 0 : double curr = first;
50 :
51 0 : for (; count != 0; curr += step, --count)
52 : {
53 0 : vect.push_back( static_cast<int>(curr) );
54 : }
55 0 : }
56 :
57 : template<typename Container>
58 0 : void operator()(Container& cnt) const
59 : {
60 0 : std::copy(vect.begin(), vect.end(), std::back_inserter(cnt));
61 0 : }
62 : };
63 :
64 0 : struct init_random
65 : {
66 : int count;
67 : int first;
68 : int last;
69 :
70 : std::vector<int> vect;
71 :
72 0 : init_random(int c, int f, int l)
73 : : count(c)
74 : , first(f)
75 0 : , last(l)
76 : {
77 0 : int dist = last - first;
78 0 : for (; count != 0; --count)
79 : {
80 0 : vect.push_back( first + std::rand()%dist );
81 : }
82 0 : }
83 :
84 : template<typename Container>
85 0 : void operator()(Container& cnt) const
86 : {
87 0 : std::copy(vect.begin(), vect.end(), std::back_inserter(cnt));
88 0 : }
89 : };
90 :
91 :
92 : template<typename Container1, typename Container2>
93 0 : bool equal( const Container1& cnt1, const Container2& cnt2)
94 : {
95 0 : if (cnt1.size() != cnt2.size() )
96 : {
97 0 : return false;
98 : }
99 :
100 0 : typename Container1::const_iterator cur1 = cnt1.begin();
101 0 : typename Container2::const_iterator cur2 = cnt2.begin();
102 0 : for (size_t i=0; i < cnt1.size(); ++i, ++cur1, ++cur2)
103 : {
104 0 : if ( *cur1 != *cur2 )
105 : {
106 0 : return false;
107 : }
108 : }
109 0 : return true;
110 : }
111 :
112 : template<size_t ArraySize>
113 : class persist_container
114 : {
115 : public:
116 :
117 : typedef vset::vtree::vtree< vset::vtree::strategy::vtree_fsb_mmap<int, std::less<int>, ArraySize> > set_type;
118 : typedef typename set_type::iterator iterator;
119 : typedef typename set_type::const_iterator const_iterator;
120 :
121 0 : persist_container(const std::string& filename, bool clear)
122 : {
123 0 : output_buffer << "persist_container::persist_container() clear = " << clear << std::endl;
124 :
125 0 : _vset = new set_type;
126 :
127 0 : _vset->get_allocator().memory().buffer().open( filename.c_str() );
128 0 : _vset->get_allocator().memory().buffer().reserve( 1024*1024);
129 0 : output_buffer << "persist_container size after open: " << _vset->size() << std::endl;
130 0 : if ( clear )
131 : {
132 0 : _vset->clear();
133 0 : output_buffer << "persist_container size after clear: " << _vset->size() << std::endl;
134 : }
135 0 : }
136 :
137 0 : ~persist_container()
138 : {
139 0 : output_buffer << "~persist_container() " << _vset->size() << std::endl;
140 0 : output_buffer << "~persist_container() " << _vset->get_allocator().memory().buffer().size() << std::endl;
141 :
142 : typedef typename set_type::allocator_type::memory_type::pointer pointer;
143 0 : pointer beg = _vset->get_allocator().memory().begin();
144 0 : pointer end = _vset->get_allocator().memory().end();
145 0 : size_t count = 0;
146 0 : for (;beg != end; ++beg)
147 : {
148 0 : count += beg->size();
149 : }
150 0 : output_buffer << "~persist_container() " << count << std::endl;
151 :
152 0 : _vset->get_allocator().memory().buffer().sync();
153 0 : _vset->get_allocator().memory().buffer().close();
154 0 : delete _vset;
155 0 : }
156 :
157 0 : set_type& operator*() const
158 : {
159 0 : return *_vset;
160 : }
161 :
162 0 : set_type* operator->() const
163 : {
164 0 : return _vset;
165 : }
166 :
167 : persist_container(const persist_container& );
168 : private:
169 :
170 : set_type* _vset;
171 : };
172 :
173 : template<size_t ArraySize>
174 : class non_persist_container
175 : {
176 : non_persist_container(const non_persist_container&);
177 : non_persist_container& operator=(const non_persist_container&);
178 : public:
179 :
180 : typedef vset::vtree::vtree< vset::vtree::strategy::vtree_fsb_mmap<int, std::less<int>, ArraySize> > set_type;
181 : typedef typename set_type::iterator iterator;
182 :
183 :
184 : non_persist_container(const std::string& filename, bool /*clear*/)
185 : {
186 : _vset = new set_type;
187 : _vset->get_allocator().memory().buffer().open(filename.c_str());
188 : }
189 :
190 : ~non_persist_container()
191 : {
192 : delete _vset;
193 : }
194 :
195 : set_type& operator*() const
196 : {
197 : return *_vset;
198 : }
199 :
200 : set_type* operator->() const
201 : {
202 : return _vset;
203 : }
204 :
205 : private:
206 : set_type* _vset;
207 : };
208 :
209 :
210 : template<typename T, typename Container, typename F>
211 0 : void test_insert1(T& /*t*/, const Container& cnt, const F& init, bool onlyCheck)
212 : {
213 0 : output_buffer << "test_insert1 onlyCheck=" << onlyCheck << "{" << std::endl;
214 : //std::stringstream ss;
215 0 : if ( onlyCheck )
216 : {
217 0 : test_stack.push("test_insert1 onlyCheck");
218 : }
219 : else
220 : {
221 0 : test_stack.push("test_insert1");
222 : }
223 0 : std::vector<int> values;
224 0 : init(values);
225 0 : if ( !onlyCheck )
226 : {
227 0 : cnt->insert( values.begin(), values.end() );
228 : }
229 0 : output_buffer << "<<<--- 1" << std::endl;
230 0 : if ( values.size() != cnt->size() )
231 : {
232 0 : output_buffer << "----------------------" << std::endl;
233 0 : output_buffer << values.size() << std::endl;
234 0 : output_buffer << cnt->size() << std::endl;
235 0 : output_buffer << "======================" << std::endl;
236 0 : raise("values1.size() != cnt->size()", __FILE__, __LINE__);
237 : }
238 0 : output_buffer << "<<<--- 2" << std::endl;
239 0 : std::sort(values.begin(), values.end());
240 0 : output_buffer << "<<<--- 3" << std::endl;
241 0 : if (!equal(*cnt, values))
242 : {
243 0 : typename Container::iterator itr = cnt->begin();
244 0 : for (size_t i = 0; i < values.size(); ++i, ++itr )
245 : {
246 0 : output_buffer << "<<<--- X" << std::endl;
247 0 : output_buffer << "[" << values[i] << "=" << "=" << *itr<< "],";
248 0 : if ( values[i] != *itr )
249 : {
250 0 : output_buffer << "<<<";
251 : }
252 : }
253 :
254 0 : output_buffer << std::endl << "END CHECK" << std::endl;
255 0 : raise("test_insert1", __FILE__, __LINE__);
256 :
257 : }
258 0 : test_stack.pop();
259 0 : output_buffer << "}test_insert1"<< std::endl;
260 0 : }
261 :
262 :
263 : template<typename Container, typename T>
264 0 : void test_insert(T& t)
265 : {
266 0 : output_buffer << "test_insert {" << std::endl;
267 :
268 0 : test_stack.push("test_insert");
269 :
270 0 : test_insert1(t, Container("test_insert.bin", true), init_sequence(1, 1, 1), false );
271 0 : test_insert1(t, Container("test_insert.bin", false), init_sequence(1, 1, 1), true );
272 :
273 0 : test_insert1(t, Container("test_insert.bin", true), init_sequence(10, 1, 5), false );
274 0 : test_insert1(t, Container("test_insert.bin", false), init_sequence(10, 1, 5), true );
275 :
276 0 : test_insert1(t, Container("test_insert.bin", true), init_sequence(256, 1, 5), false );
277 0 : test_insert1(t, Container("test_insert.bin", false), init_sequence(256, 1, 5), true );
278 :
279 0 : test_insert1(t, Container("test_insert.bin", true), init_sequence(2048, 1, 500), false );
280 0 : test_insert1(t, Container("test_insert.bin", false), init_sequence(2048, 1, 500), true );
281 :
282 0 : init_random rnd(100000, 1, 1000);
283 0 : output_buffer << "------------1-----------" << std::endl;
284 0 : test_insert1(t, Container("test_insert1.bin", true), rnd, false );
285 0 : output_buffer << "------------2-----------" << std::endl;
286 0 : test_insert1(t, Container("test_insert1.bin", false), rnd, true );
287 :
288 0 : test_stack.pop();
289 0 : output_buffer << "}test_insert" << std::endl;
290 0 : }
291 :
292 : template<typename T, typename Container, typename F>
293 0 : void test_erase1(T& /*t*/, const Container& cnt, const F& init, bool onlyCheck)
294 : {
295 0 : output_buffer << "void test_erase1(const Container& cnt, const F& init, bool onlyCheck) " << init.count << std::endl;
296 0 : if ( onlyCheck )
297 : {
298 0 : test_stack.push("test_insert1 onlyCheck");
299 : }
300 : else
301 : {
302 0 : test_stack.push("test_erase1");
303 : }
304 0 : std::list<int> values1, values2;
305 0 : init(values1);
306 :
307 0 : if ( !onlyCheck )
308 : {
309 0 : cnt->insert( values1.begin(), values1.end() );
310 : }
311 :
312 0 : std::list<int>::iterator beg = values1.begin();
313 0 : std::list<int>::iterator end = values1.end();
314 :
315 : // Перемещаем каждый второй
316 0 : for ( ;beg!=end; ++beg)
317 : {
318 0 : values2.push_back(*beg);
319 : try
320 : {
321 0 : values1.erase(beg++);
322 : }
323 : catch(const std::exception& e)
324 : {
325 : raise( e.what(), __FILE__, __LINE__);
326 : }
327 : }
328 :
329 0 : if ( !onlyCheck )
330 : {
331 0 : for ( std::list<int>::iterator beg2 = values2.begin(); beg2!=values2.end(); ++beg2 )
332 : {
333 : try
334 : {
335 0 : if ( cnt->find( *beg2 ) == cnt->end() )
336 : {
337 0 : output_buffer << "fatal " << *beg2 << std::endl ;
338 0 : raise( "Cannot find value while iterating", __FILE__, __LINE__);
339 : }
340 :
341 0 : typename Container::iterator upper = cnt->upper_bound(*beg2);
342 0 : if ( upper != cnt->end() )
343 : {
344 0 : if ( *upper == *beg2 )
345 : {
346 0 : output_buffer << "fatal2" << *upper << std::endl ;
347 : }
348 : else
349 : {
350 0 : output_buffer << "UPPER " << *upper << std::endl ;
351 : }
352 : }
353 0 : cnt->erase( *beg2 );
354 : }
355 0 : catch(const std::exception& e)
356 : {
357 0 : raise( e.what(), __FILE__, __LINE__);
358 : }
359 : }
360 : }
361 :
362 0 : if ( values1.size() != cnt->size() )
363 : {
364 0 : output_buffer << values1.size() << std::endl;
365 0 : output_buffer << values2.size() << std::endl;
366 0 : output_buffer << cnt->size() << std::endl;
367 0 : raise("values1.size() != cnt->size()", __FILE__, __LINE__);
368 : }
369 :
370 0 : if (!equal(*cnt, values1))
371 : {
372 0 : typename Container::iterator itr = cnt->begin();
373 0 : beg = values1.begin();
374 0 : for (size_t i = 0; i < values1.size(); ++i, ++itr, ++beg )
375 : {
376 0 : output_buffer << "[" << *beg << "=" << "=" << *itr<< "],";
377 0 : if ( *beg != *itr )
378 : {
379 0 : output_buffer << "<<<";
380 : }
381 : }
382 :
383 0 : output_buffer << std::endl;
384 :
385 0 : raise("test_erase1", __FILE__, __LINE__);
386 : }
387 0 : test_stack.pop();
388 0 : }
389 :
390 : template<typename Container, typename T>
391 0 : void test_erase(T& t)
392 : {
393 0 : test_stack.push("test_erase");
394 :
395 0 : test_erase1( t, Container("test_erase.bin", true), init_sequence(1, 1, 1), false );
396 :
397 0 : test_erase1(t, Container("test_erase.bin", false), init_sequence(1, 1, 1), true );
398 :
399 0 : test_erase1( t, Container("test_erase.bin", true), init_sequence(10, 1, 20), false );
400 0 : test_erase1(t, Container("test_erase.bin", false), init_sequence(10, 1, 20), true );
401 :
402 0 : test_erase1( t, Container("test_erase.bin", true), init_sequence(256, 1, 512), false );
403 0 : test_erase1(t, Container("test_erase.bin", false), init_sequence(256, 1, 512), true );
404 :
405 0 : test_erase1( t, Container("test_erase.bin", true), init_sequence(2048, 0, 2048), false );
406 0 : test_erase1(t, Container("test_erase.bin", false), init_sequence(2048, 0, 2048), true );
407 :
408 0 : init_sequence init(10000, 0, 100000);
409 0 : test_erase1( t, Container("test_erase.bin", true), init, false );
410 0 : test_erase1(t, Container("test_erase.bin", false), init, true );
411 :
412 0 : test_stack.pop();
413 0 : }
414 :
415 :
416 : template<typename Container, typename T>
417 0 : void test_all(T& t)
418 : {
419 0 : test_stack.push("test_all");
420 0 : output_buffer << "test_all insert {" << std::endl;
421 0 : test_insert<Container>(t);
422 0 : output_buffer << "}test_all insert" << std::endl;
423 0 : output_buffer << "test_all erase {" << std::endl;
424 0 : test_erase<Container>(t);
425 0 : output_buffer << "}test_all erase" << std::endl;
426 0 : test_stack.pop();
427 0 : }
428 :
429 : template<size_t BlockSize, typename T>
430 1 : void test_persist(T& t)
431 : {
432 1 : if ( -1 == ::truncate( "./test_erase.bin", 0) )
433 1 : return;
434 0 : if ( -1 == ::truncate( "./test_insert.bin", 0) )
435 0 : return;
436 0 : if ( -1 == ::truncate( "./test_insert1.bin", 0) )
437 0 : return;
438 0 : output_buffer << "------------------- test_persist ------------------- " << BlockSize << std::endl;
439 0 : test_stack.push("test_persist");
440 : typedef persist_container<BlockSize> container;
441 0 : test_all<container>(t);
442 0 : test_stack.pop();
443 : }
444 :
445 : template<typename T>
446 1 : void test_all_persist(T& t)
447 : {
448 1 : output_buffer << "------------------- test_all_persist -------------------" << std::endl;
449 1 : test_stack.push("test_all_persist");
450 :
451 1 : test_persist<3>(t);
452 : /*
453 : test_persist<4>(t);
454 : test_persist<5>(t);
455 : test_persist<7>(t);
456 : test_persist<13>(t);
457 : */
458 : /*test_persist<64>(t);
459 : test_persist<256>(t);
460 : test_persist<500>(t);
461 : test_persist<1000>(t);
462 : test_persist<1024>(t);
463 : test_persist<4000>(t);*/
464 :
465 1 : test_stack.pop();
466 :
467 1 : t << fas::testing::nothing;
468 1 : }
469 :
470 3 : UNIT(vtree_mmap_test, "")
471 : {
472 : using namespace fas::testing;
473 : #if ( ! (__GNUC__==4 && __GNUC_MINOR__==6) )
474 1 : test_all_persist(t); // internal compiler error
475 : #endif
476 1 : t << nothing;
477 1 : }
478 :
479 1 : BEGIN_SUITE(vtree_mmap_suite, "")
480 : ADD_UNIT(vtree_mmap_test)
481 7 : END_SUITE(vtree_mmap_suite)
|