generic_assoc_test.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Olaf Krzikalla 2004-2006.
  4. // (C) Copyright Ion Gaztanaga 2006-2013.
  5. //
  6. // Distributed under the Boost Software License, Version 1.0.
  7. // (See accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // See http://www.boost.org/libs/intrusive for documentation.
  11. //
  12. /////////////////////////////////////////////////////////////////////////////
  13. #include <boost/container/vector.hpp> //vector
  14. #include <boost/intrusive/detail/config_begin.hpp>
  15. #include "common_functors.hpp"
  16. #include <boost/intrusive/options.hpp>
  17. #include <boost/intrusive/detail/mpl.hpp>
  18. #include <boost/detail/lightweight_test.hpp>
  19. #include "test_macros.hpp"
  20. #include "test_container.hpp"
  21. namespace boost{
  22. namespace intrusive{
  23. namespace test{
  24. BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(has_splay, splay)
  25. BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(has_rebalance, rebalance)
  26. BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(has_insert_before, insert_before)
  27. BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(is_treap, priority_comp)
  28. template<class ContainerDefiner>
  29. struct test_generic_assoc
  30. {
  31. typedef typename ContainerDefiner::value_cont_type value_cont_type;
  32. static void test_all(value_cont_type&);
  33. static void test_root(value_cont_type&);
  34. static void test_clone(value_cont_type&);
  35. static void test_insert_erase_burst();
  36. static void test_container_from_end(value_cont_type&, detail::true_type);
  37. static void test_container_from_end(value_cont_type&, detail::false_type) {}
  38. static void test_splay_up(value_cont_type&, detail::true_type);
  39. static void test_splay_up(value_cont_type&, detail::false_type) {}
  40. static void test_splay_down(value_cont_type&, detail::true_type);
  41. static void test_splay_down(value_cont_type&, detail::false_type) {}
  42. static void test_rebalance(value_cont_type&, detail::true_type);
  43. static void test_rebalance(value_cont_type&, detail::false_type) {}
  44. static void test_insert_before(value_cont_type&, detail::true_type);
  45. static void test_insert_before(value_cont_type&, detail::false_type) {}
  46. static void test_container_from_iterator(value_cont_type&, detail::true_type);
  47. static void test_container_from_iterator(value_cont_type&, detail::false_type) {}
  48. };
  49. template<class ContainerDefiner>
  50. void test_generic_assoc<ContainerDefiner>::
  51. test_container_from_iterator(value_cont_type& values, detail::true_type)
  52. {
  53. typedef typename ContainerDefiner::template container
  54. <>::type assoc_type;
  55. assoc_type testset(values.begin(), values.end());
  56. typedef typename assoc_type::iterator it_type;
  57. typedef typename assoc_type::const_iterator cit_type;
  58. typedef typename assoc_type::size_type sz_type;
  59. sz_type sz = testset.size();
  60. for(it_type b(testset.begin()), e(testset.end()); b != e; ++b)
  61. {
  62. assoc_type &s = assoc_type::container_from_iterator(b);
  63. const assoc_type &cs = assoc_type::container_from_iterator(cit_type(b));
  64. BOOST_TEST(&s == &cs);
  65. BOOST_TEST(&s == &testset);
  66. s.erase(b);
  67. BOOST_TEST(testset.size() == (sz-1));
  68. s.insert(*b);
  69. BOOST_TEST(testset.size() == sz);
  70. }
  71. }
  72. template<class ContainerDefiner>
  73. void test_generic_assoc<ContainerDefiner>::test_insert_erase_burst()
  74. {
  75. //value_cont_type values;
  76. const std::size_t MaxValues = 200;
  77. value_cont_type values(MaxValues);
  78. for(std::size_t i = 0; i != MaxValues; ++i){
  79. (&values[i])->value_ = i;
  80. }
  81. typedef typename ContainerDefiner::template container
  82. <>::type assoc_type;
  83. typedef typename assoc_type::iterator iterator;
  84. { //Ordered insertion + erasure
  85. assoc_type testset (values.begin(), values.begin() + values.size());
  86. TEST_INTRUSIVE_SEQUENCE_EXPECTED(testset, testset.begin());
  87. testset.check();
  88. iterator it(testset.begin()), itend(testset.end());
  89. for(std::size_t i = 0; it != itend; ++i){
  90. BOOST_TEST(&*it == &values[i]);
  91. it = testset.erase(it);
  92. testset.check();
  93. }
  94. BOOST_TEST(testset.empty());
  95. }
  96. { //Now random insertions + erasure
  97. assoc_type testset;
  98. typedef typename value_cont_type::iterator vec_iterator;
  99. boost::container::vector<vec_iterator> it_vector;
  100. //Random insertion
  101. for(vec_iterator it(values.begin()), itend(values.end())
  102. ; it != itend
  103. ; ++it){
  104. it_vector.push_back(it);
  105. }
  106. for(std::size_t i = 0; i != MaxValues; ++i){
  107. testset.insert(*it_vector[i]);
  108. testset.check();
  109. }
  110. TEST_INTRUSIVE_SEQUENCE_EXPECTED(testset, testset.begin());
  111. //Random erasure
  112. random_shuffle(it_vector.begin(), it_vector.end());
  113. for(std::size_t i = 0; i != MaxValues; ++i){
  114. testset.erase(testset.iterator_to(*it_vector[i]));
  115. testset.check();
  116. }
  117. BOOST_TEST(testset.empty());
  118. }
  119. }
  120. template<class ContainerDefiner>
  121. void test_generic_assoc<ContainerDefiner>::test_all(value_cont_type& values)
  122. {
  123. typedef typename ContainerDefiner::template container
  124. <>::type assoc_type;
  125. test_root(values);
  126. test_clone(values);
  127. test_container_from_end(values, detail::bool_< assoc_type::has_container_from_iterator >());
  128. test_splay_up(values, detail::bool_< has_splay< assoc_type >::value >());
  129. test_splay_down(values, detail::bool_< has_splay< assoc_type >::value >());
  130. test_rebalance(values, detail::bool_< has_rebalance< assoc_type >::value >());
  131. test_insert_before(values, detail::bool_< has_insert_before< assoc_type >::value >());
  132. test_insert_erase_burst();
  133. test_container_from_iterator(values, detail::bool_< assoc_type::has_container_from_iterator >());
  134. }
  135. template<class ContainerDefiner>
  136. void test_generic_assoc<ContainerDefiner>::test_root(value_cont_type& values)
  137. {
  138. typedef typename ContainerDefiner::template container<>::type assoc_type;
  139. typedef typename assoc_type::iterator iterator;
  140. typedef typename assoc_type::const_iterator const_iterator;
  141. assoc_type testset1;
  142. const assoc_type &ctestset1 = testset1;;
  143. BOOST_TEST( testset1.root() == testset1.end());
  144. BOOST_TEST(ctestset1.root() == ctestset1.cend());
  145. BOOST_TEST( testset1.croot() == ctestset1.cend());
  146. testset1.insert(values.begin(), values.begin() + values.size());
  147. iterator i = testset1.root();
  148. iterator i2(i);
  149. BOOST_TEST( i.go_parent().go_parent() == i2);
  150. const_iterator ci = ctestset1.root();
  151. const_iterator ci2(ci);
  152. BOOST_TEST( ci.go_parent().go_parent() == ci2);
  153. ci = testset1.croot();
  154. ci2 = ci;
  155. BOOST_TEST( ci.go_parent().go_parent() == ci2);
  156. }
  157. template<class ContainerDefiner>
  158. void test_generic_assoc<ContainerDefiner>::test_clone(value_cont_type& values)
  159. {
  160. {
  161. typedef typename ContainerDefiner::template container
  162. <>::type assoc_type;
  163. typedef typename assoc_type::value_type value_type;
  164. typedef typename assoc_type::size_type size_type;
  165. assoc_type testset1 (values.begin(), values.begin() + values.size());
  166. assoc_type testset2;
  167. size_type const testset1_oldsize = testset1.size();
  168. testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
  169. BOOST_TEST (testset1.size() == testset1_oldsize);
  170. BOOST_TEST (testset2 == testset1);
  171. testset2.clear_and_dispose(test::delete_disposer<value_type>());
  172. BOOST_TEST (testset2.empty());
  173. //Now test move clone
  174. testset2.clone_from(boost::move(testset1), test::new_nonconst_cloner<value_type>(), test::delete_disposer<value_type>());
  175. BOOST_TEST (testset2 == testset1);
  176. testset2.clear_and_dispose(test::delete_disposer<value_type>());
  177. BOOST_TEST (testset2.empty());
  178. }
  179. }
  180. template<class ContainerDefiner>
  181. void test_generic_assoc<ContainerDefiner>
  182. ::test_container_from_end(value_cont_type& values, detail::true_type)
  183. {
  184. typedef typename ContainerDefiner::template container
  185. <>::type assoc_type;
  186. assoc_type testset (values.begin(), values.begin() + values.size());
  187. BOOST_TEST (testset == assoc_type::container_from_end_iterator(testset.end()));
  188. BOOST_TEST (testset == assoc_type::container_from_end_iterator(testset.cend()));
  189. }
  190. template<class ContainerDefiner>
  191. void test_generic_assoc<ContainerDefiner>::test_splay_up
  192. (value_cont_type& values, detail::true_type)
  193. {
  194. typedef typename ContainerDefiner::template container
  195. <>::type assoc_type;
  196. typedef typename assoc_type::iterator iterator;
  197. typedef value_cont_type orig_set_t;
  198. std::size_t num_values;
  199. orig_set_t original_testset;
  200. {
  201. assoc_type testset (values.begin(), values.end());
  202. num_values = testset.size();
  203. original_testset = value_cont_type(testset.begin(), testset.end());
  204. }
  205. for(std::size_t i = 0; i != num_values; ++i){
  206. assoc_type testset (values.begin(), values.end());
  207. {
  208. iterator it = testset.begin();
  209. for(std::size_t j = 0; j != i; ++j, ++it){}
  210. testset.splay_up(it);
  211. }
  212. BOOST_TEST (testset.size() == num_values);
  213. iterator it = testset.begin();
  214. for( typename orig_set_t::const_iterator origit = original_testset.begin()
  215. , origitend = original_testset.end()
  216. ; origit != origitend
  217. ; ++origit, ++it){
  218. BOOST_TEST(*origit == *it);
  219. }
  220. }
  221. }
  222. template<class ContainerDefiner>
  223. void test_generic_assoc<ContainerDefiner>::test_splay_down
  224. (value_cont_type& values, detail::true_type)
  225. {
  226. typedef typename ContainerDefiner::template container
  227. <>::type assoc_type;
  228. typedef typename assoc_type::iterator iterator;
  229. typedef value_cont_type orig_set_t;
  230. std::size_t num_values;
  231. orig_set_t original_testset;
  232. {
  233. assoc_type testset (values.begin(), values.end());
  234. num_values = testset.size();
  235. original_testset = value_cont_type(testset.begin(), testset.end());
  236. }
  237. for(std::size_t i = 0; i != num_values; ++i){
  238. assoc_type testset (values.begin(), values.end());
  239. BOOST_TEST(testset.size() == num_values);
  240. {
  241. iterator it = testset.begin();
  242. for(std::size_t j = 0; j != i; ++j, ++it){}
  243. BOOST_TEST(*it == *testset.splay_down(*it));
  244. }
  245. BOOST_TEST (testset.size() == num_values);
  246. iterator it = testset.begin();
  247. for( typename orig_set_t::const_iterator origit = original_testset.begin()
  248. , origitend = original_testset.end()
  249. ; origit != origitend
  250. ; ++origit, ++it){
  251. BOOST_TEST(*origit == *it);
  252. }
  253. }
  254. }
  255. template<class ContainerDefiner>
  256. void test_generic_assoc<ContainerDefiner>::test_rebalance
  257. (value_cont_type& values, detail::true_type)
  258. {
  259. typedef typename ContainerDefiner::template container
  260. <>::type assoc_type;
  261. typedef value_cont_type orig_set_t;
  262. orig_set_t original_testset;
  263. {
  264. assoc_type testset (values.begin(), values.end());
  265. original_testset.assign(testset.begin(), testset.end());
  266. }
  267. {
  268. assoc_type testset(values.begin(), values.end());
  269. testset.rebalance();
  270. TEST_INTRUSIVE_SEQUENCE_EXPECTED(original_testset, testset.begin());
  271. }
  272. {
  273. std::size_t numdata;
  274. {
  275. assoc_type testset(values.begin(), values.end());
  276. numdata = testset.size();
  277. }
  278. for(int i = 0; i != (int)numdata; ++i){
  279. assoc_type testset(values.begin(), values.end());
  280. typename assoc_type::iterator it = testset.begin();
  281. for(int j = 0; j != i; ++j) ++it;
  282. testset.rebalance_subtree(it);
  283. TEST_INTRUSIVE_SEQUENCE_EXPECTED(original_testset, testset.begin());
  284. }
  285. }
  286. }
  287. template<class ContainerDefiner>
  288. void test_generic_assoc<ContainerDefiner>::test_insert_before
  289. (value_cont_type& values, detail::true_type)
  290. {
  291. typedef typename ContainerDefiner::template container
  292. <>::type assoc_type;
  293. {
  294. assoc_type testset;
  295. typedef typename value_cont_type::iterator vec_iterator;
  296. for(vec_iterator it(values.begin()), itend(values.end())
  297. ; it != itend
  298. ; ++it){
  299. testset.push_back(*it);
  300. }
  301. BOOST_TEST(testset.size() == values.size());
  302. TEST_INTRUSIVE_SEQUENCE_EXPECTED(values, testset.begin());
  303. }
  304. {
  305. assoc_type testset;
  306. typedef typename value_cont_type::iterator vec_iterator;
  307. for(vec_iterator it(--values.end()); true; --it){
  308. testset.push_front(*it);
  309. if(it == values.begin()){
  310. break;
  311. }
  312. }
  313. BOOST_TEST(testset.size() == values.size());
  314. TEST_INTRUSIVE_SEQUENCE_EXPECTED(values, testset.begin());
  315. }
  316. {
  317. assoc_type testset;
  318. typedef typename value_cont_type::iterator vec_iterator;
  319. typename assoc_type::iterator it_pos =
  320. testset.insert_before(testset.end(), *values.rbegin());
  321. testset.insert_before(testset.begin(), *values.begin());
  322. for(vec_iterator it(++values.begin()), itend(--values.end())
  323. ; it != itend
  324. ; ++it){
  325. testset.insert_before(it_pos, *it);
  326. }
  327. BOOST_TEST(testset.size() == values.size());
  328. TEST_INTRUSIVE_SEQUENCE_EXPECTED(values, testset.begin());
  329. }
  330. }
  331. }}} //namespace boost::intrusive::test
  332. #include <boost/intrusive/detail/config_end.hpp>