test_segmented_queue.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // Copyright (c) 2006-2018 Maxim Khizhinsky
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef CDSUNIT_QUEUE_TEST_SEGMENTED_QUEUE_H
  6. #define CDSUNIT_QUEUE_TEST_SEGMENTED_QUEUE_H
  7. #include <cds_test/check_size.h>
  8. namespace cds_test {
  9. class segmented_queue : public ::testing::Test
  10. {
  11. protected:
  12. template <typename Queue>
  13. void test( Queue& q )
  14. {
  15. typedef typename Queue::value_type value_type;
  16. value_type it;
  17. const size_t nSize = 100;
  18. ASSERT_TRUE( q.empty());
  19. ASSERT_CONTAINER_SIZE( q, 0 );
  20. // enqueue/dequeue
  21. for ( size_t i = 0; i < nSize; ++i ) {
  22. it = static_cast<value_type>(i);
  23. ASSERT_TRUE( q.enqueue( it ));
  24. ASSERT_CONTAINER_SIZE( q, i + 1 );
  25. }
  26. ASSERT_FALSE( q.empty());
  27. ASSERT_CONTAINER_SIZE( q, nSize );
  28. for ( size_t i = 0; i < nSize; ++i ) {
  29. it = -1;
  30. ASSERT_TRUE( q.dequeue( it ));
  31. ASSERT_CONTAINER_SIZE( q, nSize - i - 1 );
  32. int nSegment = int( i / q.quasi_factor());
  33. int nMin = nSegment * int( q.quasi_factor());
  34. int nMax = nMin + int( q.quasi_factor()) - 1;
  35. EXPECT_LE( nMin, it );
  36. EXPECT_LE( it, nMax );
  37. }
  38. ASSERT_TRUE( q.empty());
  39. ASSERT_CONTAINER_SIZE( q, 0 );
  40. // push/pop
  41. for ( size_t i = 0; i < nSize; ++i ) {
  42. it = static_cast<value_type>(i);
  43. ASSERT_TRUE( q.push( it ));
  44. ASSERT_CONTAINER_SIZE( q, i + 1 );
  45. }
  46. ASSERT_FALSE( q.empty());
  47. ASSERT_CONTAINER_SIZE( q, nSize );
  48. size_t nPushed = nSize;
  49. size_t nStartSegment = nPushed / q.quasi_factor();
  50. size_t nOffset = nPushed % q.quasi_factor();
  51. for ( size_t i = 0; i < nSize; ++i ) {
  52. it = -1;
  53. ASSERT_TRUE( q.pop( it ));
  54. ASSERT_CONTAINER_SIZE( q, nSize - i - 1 );
  55. int nSegment = static_cast<int>((i + nPushed) / q.quasi_factor() - nStartSegment );
  56. int nMin = nSegment * static_cast<int>( q.quasi_factor());
  57. if ( nSegment )
  58. nMin -= static_cast<int>( nOffset );
  59. int nMax = nMin + static_cast<int>( q.quasi_factor()) - 1;
  60. EXPECT_LE( nMin, it );
  61. EXPECT_LE( it, nMax );
  62. }
  63. ASSERT_TRUE( q.empty());
  64. ASSERT_CONTAINER_SIZE( q, 0 );
  65. // push/pop with lambda
  66. for ( size_t i = 0; i < nSize; ++i ) {
  67. it = static_cast<value_type>(i);
  68. EXPECT_NE( it, -1 );
  69. auto f = [&it]( value_type& dest ) { dest = it; it = -1; };
  70. if ( i & 1 )
  71. ASSERT_TRUE( q.enqueue_with( f ));
  72. else
  73. ASSERT_TRUE( q.push_with( f ));
  74. ASSERT_EQ( it, -1 );
  75. ASSERT_CONTAINER_SIZE( q, i + 1 );
  76. }
  77. ASSERT_FALSE( q.empty());
  78. ASSERT_CONTAINER_SIZE( q, nSize );
  79. nPushed += nSize;
  80. nStartSegment = nPushed / q.quasi_factor();
  81. nOffset = nPushed % q.quasi_factor();
  82. for ( size_t i = 0; i < nSize; ++i ) {
  83. it = -1;
  84. auto f = [&it]( value_type& src ) { it = src; src = -1; };
  85. if ( i & 1 )
  86. ASSERT_TRUE( q.pop_with( f ));
  87. else
  88. ASSERT_TRUE( q.dequeue_with( f ));
  89. ASSERT_CONTAINER_SIZE( q, nSize - i - 1 );
  90. int nSegment = static_cast<int>((i + nPushed) / q.quasi_factor() - nStartSegment);
  91. int nMin = nSegment * static_cast<int>(q.quasi_factor());
  92. if ( nSegment )
  93. nMin -= static_cast<int>(nOffset);
  94. int nMax = nMin + static_cast<int>(q.quasi_factor()) - 1;
  95. EXPECT_LE( nMin, it );
  96. EXPECT_LE( it, nMax );
  97. }
  98. ASSERT_TRUE( q.empty());
  99. ASSERT_CONTAINER_SIZE( q, 0 );
  100. // clear
  101. for ( size_t i = 0; i < nSize; ++i ) {
  102. ASSERT_TRUE( q.push( static_cast<value_type>(i)));
  103. }
  104. ASSERT_FALSE( q.empty());
  105. ASSERT_CONTAINER_SIZE( q, nSize );
  106. q.clear();
  107. ASSERT_TRUE( q.empty());
  108. ASSERT_CONTAINER_SIZE( q, 0 );
  109. // pop from empty queue
  110. it = nSize * 2;
  111. ASSERT_FALSE( q.pop( it ));
  112. ASSERT_EQ( it, static_cast<value_type>( nSize * 2 ));
  113. ASSERT_TRUE( q.empty());
  114. ASSERT_CONTAINER_SIZE( q, 0 );
  115. ASSERT_FALSE( q.dequeue( it ));
  116. ASSERT_EQ( it, static_cast<value_type>( nSize * 2 ));
  117. ASSERT_TRUE( q.empty());
  118. ASSERT_CONTAINER_SIZE( q, 0 );
  119. }
  120. template <class Queue>
  121. void test_string( Queue& q )
  122. {
  123. std::string str[3];
  124. str[0] = "one";
  125. str[1] = "two";
  126. str[2] = "three";
  127. const size_t nSize = sizeof( str ) / sizeof( str[0] );
  128. // emplace
  129. for ( size_t i = 0; i < nSize; ++i ) {
  130. ASSERT_TRUE( q.emplace( str[i].c_str()));
  131. ASSERT_CONTAINER_SIZE( q, i + 1 );
  132. }
  133. ASSERT_FALSE( q.empty());
  134. ASSERT_CONTAINER_SIZE( q, nSize );
  135. {
  136. std::string s;
  137. auto f = [&s]( std::string& src ) {
  138. ASSERT_FALSE( src.empty());
  139. s = std::move( src );
  140. ASSERT_NE( s, src );
  141. };
  142. for ( size_t i = 0; i < nSize; ++i ) {
  143. if ( i & 1 )
  144. ASSERT_TRUE( q.pop_with( f ));
  145. else
  146. ASSERT_TRUE( q.dequeue_with( f ));
  147. ASSERT_CONTAINER_SIZE( q, nSize - i - 1 );
  148. ASSERT_TRUE( s == str[0] || s == str[1] || s == str[2] );
  149. }
  150. }
  151. ASSERT_TRUE( q.empty());
  152. ASSERT_CONTAINER_SIZE( q, 0 );
  153. // move push
  154. for ( size_t i = 0; i < nSize; ++i ) {
  155. std::string s = str[i];
  156. ASSERT_FALSE( s.empty());
  157. if ( i & 1 )
  158. ASSERT_TRUE( q.enqueue( std::move( s )));
  159. else
  160. ASSERT_TRUE( q.push( std::move( s )));
  161. ASSERT_TRUE( s.empty());
  162. ASSERT_CONTAINER_SIZE( q, i + 1 );
  163. }
  164. ASSERT_FALSE( q.empty());
  165. ASSERT_CONTAINER_SIZE( q, nSize );
  166. for ( size_t i = 0; i < nSize; ++i ) {
  167. std::string s;
  168. ASSERT_TRUE( q.pop( s ));
  169. ASSERT_CONTAINER_SIZE( q, nSize - i - 1 );
  170. ASSERT_TRUE( s == str[0] || s == str[1] || s == str[2] );
  171. }
  172. ASSERT_TRUE( q.empty());
  173. ASSERT_CONTAINER_SIZE( q, 0 );
  174. }
  175. };
  176. } // namespace cds_test
  177. #endif // CDSUNIT_QUEUE_TEST_SEGMENTED_QUEUE_H