deque_test.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2004-2013. 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/detail/config_begin.hpp>
  11. #include <memory>
  12. #include <deque>
  13. #include <iostream>
  14. #include <list>
  15. #include <boost/container/deque.hpp>
  16. #include <boost/container/allocator.hpp>
  17. #include "print_container.hpp"
  18. #include "check_equal_containers.hpp"
  19. #include "dummy_test_allocator.hpp"
  20. #include "movable_int.hpp"
  21. #include <boost/move/utility_core.hpp>
  22. #include <boost/move/iterator.hpp>
  23. #include <boost/container/detail/mpl.hpp>
  24. #include <boost/container/detail/type_traits.hpp>
  25. #include <string>
  26. #include "emplace_test.hpp"
  27. #include "propagate_allocator_test.hpp"
  28. #include "vector_test.hpp"
  29. #include "default_init_test.hpp"
  30. #include <boost/core/no_exceptions_support.hpp>
  31. #include "../../intrusive/test/iterator_test.hpp"
  32. using namespace boost::container;
  33. //Function to check if both sets are equal
  34. template<class V1, class V2>
  35. bool deque_copyable_only(V1 &, V2 &, dtl::false_type)
  36. {
  37. return true;
  38. }
  39. //Function to check if both sets are equal
  40. template<class V1, class V2>
  41. bool deque_copyable_only(V1 &cntdeque, V2 &stddeque, dtl::true_type)
  42. {
  43. typedef typename V1::value_type IntType;
  44. std::size_t size = cntdeque.size();
  45. stddeque.insert(stddeque.end(), 50, 1);
  46. cntdeque.insert(cntdeque.end(), 50, IntType(1));
  47. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  48. {
  49. IntType move_me(1);
  50. stddeque.insert(stddeque.begin()+size/2, 50, 1);
  51. cntdeque.insert(cntdeque.begin()+size/2, 50, boost::move(move_me));
  52. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  53. }
  54. {
  55. IntType move_me(2);
  56. cntdeque.assign(cntdeque.size()/2, boost::move(move_me));
  57. stddeque.assign(stddeque.size()/2, 2);
  58. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  59. }
  60. {
  61. IntType move_me(1);
  62. stddeque.clear();
  63. cntdeque.clear();
  64. stddeque.insert(stddeque.begin(), 50, 1);
  65. cntdeque.insert(cntdeque.begin(), 50, boost::move(move_me));
  66. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  67. stddeque.insert(stddeque.begin()+20, 50, 1);
  68. cntdeque.insert(cntdeque.begin()+20, 50, boost::move(move_me));
  69. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  70. stddeque.insert(stddeque.begin()+20, 20, 1);
  71. cntdeque.insert(cntdeque.begin()+20, 20, boost::move(move_me));
  72. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  73. }
  74. {
  75. IntType move_me(1);
  76. stddeque.clear();
  77. cntdeque.clear();
  78. stddeque.insert(stddeque.end(), 50, 1);
  79. cntdeque.insert(cntdeque.end(), 50, boost::move(move_me));
  80. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  81. stddeque.insert(stddeque.end()-20, 50, 1);
  82. cntdeque.insert(cntdeque.end()-20, 50, boost::move(move_me));
  83. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  84. stddeque.insert(stddeque.end()-20, 20, 1);
  85. cntdeque.insert(cntdeque.end()-20, 20, boost::move(move_me));
  86. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  87. }
  88. return true;
  89. }
  90. //Test recursive structures
  91. class recursive_deque
  92. {
  93. public:
  94. recursive_deque & operator=(const recursive_deque &x)
  95. { this->deque_ = x.deque_; return *this; }
  96. int id_;
  97. deque<recursive_deque> deque_;
  98. deque<recursive_deque>::iterator it_;
  99. deque<recursive_deque>::const_iterator cit_;
  100. deque<recursive_deque>::reverse_iterator rit_;
  101. deque<recursive_deque>::const_reverse_iterator crit_;
  102. };
  103. template<class IntType>
  104. bool do_test()
  105. {
  106. //Test for recursive types
  107. {
  108. deque<recursive_deque> recursive_deque_deque;
  109. }
  110. {
  111. //Now test move semantics
  112. deque<recursive_deque> original;
  113. deque<recursive_deque> move_ctor(boost::move(original));
  114. deque<recursive_deque> move_assign;
  115. move_assign = boost::move(move_ctor);
  116. move_assign.swap(original);
  117. }
  118. //Alias deque types
  119. typedef deque<IntType> MyCntDeque;
  120. typedef std::deque<int> MyStdDeque;
  121. const int max = 100;
  122. {
  123. ::boost::movelib::unique_ptr<MyCntDeque> const pcntdeque = ::boost::movelib::make_unique<MyCntDeque>();
  124. ::boost::movelib::unique_ptr<MyStdDeque> const pstddeque = ::boost::movelib::make_unique<MyStdDeque>();
  125. MyCntDeque &cntdeque = *pcntdeque;
  126. MyStdDeque &stddeque = *pstddeque;
  127. for(int i = 0; i < max*100; ++i){
  128. IntType move_me(i);
  129. cntdeque.insert(cntdeque.end(), boost::move(move_me));
  130. stddeque.insert(stddeque.end(), i);
  131. }
  132. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  133. cntdeque.clear();
  134. stddeque.clear();
  135. for(int i = 0; i < max*100; ++i){
  136. IntType move_me(i);
  137. cntdeque.push_back(boost::move(move_me));
  138. stddeque.push_back(i);
  139. }
  140. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  141. cntdeque.clear();
  142. stddeque.clear();
  143. for(int i = 0; i < max*100; ++i){
  144. IntType move_me(i);
  145. cntdeque.push_front(boost::move(move_me));
  146. stddeque.push_front(i);
  147. }
  148. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  149. typename MyCntDeque::iterator it;
  150. typename MyCntDeque::const_iterator cit = it;
  151. (void)cit;
  152. cntdeque.erase(cntdeque.begin()++);
  153. stddeque.erase(stddeque.begin()++);
  154. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  155. cntdeque.erase(cntdeque.begin());
  156. stddeque.erase(stddeque.begin());
  157. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  158. {
  159. //Initialize values
  160. IntType aux_vect[50];
  161. for(int i = 0; i < 50; ++i){
  162. IntType move_me (-1);
  163. aux_vect[i] = boost::move(move_me);
  164. }
  165. int aux_vect2[50];
  166. for(int i = 0; i < 50; ++i){
  167. aux_vect2[i] = -1;
  168. }
  169. cntdeque.insert(cntdeque.end()
  170. ,boost::make_move_iterator(&aux_vect[0])
  171. ,boost::make_move_iterator(aux_vect + 50));
  172. stddeque.insert(stddeque.end(), aux_vect2, aux_vect2 + 50);
  173. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  174. for(int i = 0; i < 50; ++i){
  175. IntType move_me (i);
  176. aux_vect[i] = boost::move(move_me);
  177. }
  178. for(int i = 0; i < 50; ++i){
  179. aux_vect2[i] = i;
  180. }
  181. cntdeque.insert(cntdeque.begin()+cntdeque.size()
  182. ,boost::make_move_iterator(&aux_vect[0])
  183. ,boost::make_move_iterator(aux_vect + 50));
  184. stddeque.insert(stddeque.begin()+stddeque.size(), aux_vect2, aux_vect2 + 50);
  185. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  186. for(int i = 0, j = static_cast<int>(cntdeque.size()); i < j; ++i){
  187. cntdeque.erase(cntdeque.begin());
  188. stddeque.erase(stddeque.begin());
  189. }
  190. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  191. }
  192. {
  193. IntType aux_vect[50];
  194. for(int i = 0; i < 50; ++i){
  195. IntType move_me(-1);
  196. aux_vect[i] = boost::move(move_me);
  197. }
  198. int aux_vect2[50];
  199. for(int i = 0; i < 50; ++i){
  200. aux_vect2[i] = -1;
  201. }
  202. cntdeque.insert(cntdeque.begin()
  203. ,boost::make_move_iterator(&aux_vect[0])
  204. ,boost::make_move_iterator(aux_vect + 50));
  205. stddeque.insert(stddeque.begin(), aux_vect2, aux_vect2 + 50);
  206. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  207. }
  208. if(!deque_copyable_only(cntdeque, stddeque
  209. ,dtl::bool_<boost::container::test::is_copyable<IntType>::value>())){
  210. return false;
  211. }
  212. cntdeque.erase(cntdeque.begin());
  213. stddeque.erase(stddeque.begin());
  214. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  215. for(int i = 0; i < max; ++i){
  216. IntType move_me(i);
  217. cntdeque.insert(cntdeque.begin(), boost::move(move_me));
  218. stddeque.insert(stddeque.begin(), i);
  219. }
  220. if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
  221. //Test insertion from list
  222. {
  223. std::list<int> l(50, int(1));
  224. cntdeque.insert(cntdeque.begin(), l.begin(), l.end());
  225. stddeque.insert(stddeque.begin(), l.begin(), l.end());
  226. if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1;
  227. cntdeque.assign(l.begin(), l.end());
  228. stddeque.assign(l.begin(), l.end());
  229. if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1;
  230. }
  231. cntdeque.resize(100);
  232. stddeque.resize(100);
  233. if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1;
  234. cntdeque.resize(200);
  235. stddeque.resize(200);
  236. if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1;
  237. }
  238. #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
  239. //Check Constructor Template Auto Deduction
  240. {
  241. auto gold = MyStdDeque{ 1, 2, 3 };
  242. auto test = deque(gold.begin(), gold.end());
  243. if(!test::CheckEqualContainers(gold, test)) return false;
  244. }
  245. {
  246. auto gold = MyStdDeque{ 1, 2, 3 };
  247. auto test = deque(gold.begin(), gold.end(), new_allocator<int>());
  248. if(!test::CheckEqualContainers(gold, test)) return false;
  249. }
  250. #endif
  251. std::cout << std::endl << "Test OK!" << std::endl;
  252. return true;
  253. }
  254. template<class VoidAllocator>
  255. struct GetAllocatorCont
  256. {
  257. template<class ValueType>
  258. struct apply
  259. {
  260. typedef deque< ValueType
  261. , typename allocator_traits<VoidAllocator>
  262. ::template portable_rebind_alloc<ValueType>::type
  263. > type;
  264. };
  265. };
  266. template<class VoidAllocator>
  267. int test_cont_variants()
  268. {
  269. typedef typename GetAllocatorCont<VoidAllocator>::template apply<int>::type MyCont;
  270. typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
  271. typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
  272. typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
  273. if(test::vector_test<MyCont>())
  274. return 1;
  275. if(test::vector_test<MyMoveCont>())
  276. return 1;
  277. if(test::vector_test<MyCopyMoveCont>())
  278. return 1;
  279. if(test::vector_test<MyCopyCont>())
  280. return 1;
  281. return 0;
  282. }
  283. struct boost_container_deque;
  284. namespace boost { namespace container { namespace test {
  285. template<>
  286. struct alloc_propagate_base<boost_container_deque>
  287. {
  288. template <class T, class Allocator>
  289. struct apply
  290. {
  291. typedef boost::container::deque<T, Allocator> type;
  292. };
  293. };
  294. }}} //namespace boost::container::test
  295. int main ()
  296. {
  297. if(!do_test<int>())
  298. return 1;
  299. if(!do_test<test::movable_int>())
  300. return 1;
  301. if(!do_test<test::movable_and_copyable_int>())
  302. return 1;
  303. if(!do_test<test::copyable_int>())
  304. return 1;
  305. //Test non-copy-move operations
  306. {
  307. deque<test::non_copymovable_int> d;
  308. d.emplace_back();
  309. d.emplace_front(1);
  310. d.resize(10);
  311. d.resize(1);
  312. }
  313. ////////////////////////////////////
  314. // Allocator implementations
  315. ////////////////////////////////////
  316. // std:allocator
  317. if(test_cont_variants< std::allocator<void> >()){
  318. std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl;
  319. return 1;
  320. }
  321. // boost::container::allocator
  322. if(test_cont_variants< allocator<void> >()){
  323. std::cerr << "test_cont_variants< allocator<void> > failed" << std::endl;
  324. return 1;
  325. }
  326. ////////////////////////////////////
  327. // Default init test
  328. ////////////////////////////////////
  329. if(!test::default_init_test< deque<int, test::default_init_allocator<int> > >()){
  330. std::cerr << "Default init test failed" << std::endl;
  331. return 1;
  332. }
  333. ////////////////////////////////////
  334. // Emplace testing
  335. ////////////////////////////////////
  336. const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_FRONT | test::EMPLACE_BEFORE);
  337. if(!boost::container::test::test_emplace
  338. < deque<test::EmplaceInt>, Options>())
  339. return 1;
  340. ////////////////////////////////////
  341. // Allocator propagation testing
  342. ////////////////////////////////////
  343. if(!boost::container::test::test_propagate_allocator<boost_container_deque>())
  344. return 1;
  345. ////////////////////////////////////
  346. // Initializer lists testing
  347. ////////////////////////////////////
  348. if(!boost::container::test::test_vector_methods_with_initializer_list_as_argument_for
  349. < boost::container::deque<int> >()) {
  350. return 1;
  351. }
  352. ////////////////////////////////////
  353. // Iterator testing
  354. ////////////////////////////////////
  355. {
  356. typedef boost::container::deque<int> cont_int;
  357. cont_int a; a.push_back(0); a.push_back(1); a.push_back(2);
  358. boost::intrusive::test::test_iterator_random< cont_int >(a);
  359. if(boost::report_errors() != 0) {
  360. return 1;
  361. }
  362. }
  363. ////////////////////////////////////
  364. // has_trivial_destructor_after_move testing
  365. ////////////////////////////////////
  366. // default allocator
  367. {
  368. typedef boost::container::deque<int> cont;
  369. typedef cont::allocator_type allocator_type;
  370. typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
  371. if (boost::has_trivial_destructor_after_move<cont>::value !=
  372. boost::has_trivial_destructor_after_move<allocator_type>::value &&
  373. boost::has_trivial_destructor_after_move<pointer>::value) {
  374. std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl;
  375. return 1;
  376. }
  377. }
  378. // std::allocator
  379. {
  380. typedef boost::container::deque<int, std::allocator<int> > cont;
  381. typedef cont::allocator_type allocator_type;
  382. typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
  383. if (boost::has_trivial_destructor_after_move<cont>::value !=
  384. boost::has_trivial_destructor_after_move<allocator_type>::value &&
  385. boost::has_trivial_destructor_after_move<pointer>::value) {
  386. std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl;
  387. return 1;
  388. }
  389. }
  390. return 0;
  391. }
  392. #include <boost/container/detail/config_end.hpp>