test_intrusive_msqueue.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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_INTRUSIVE_MSQUEUE_H
  6. #define CDSUNIT_QUEUE_TEST_INTRUSIVE_MSQUEUE_H
  7. #include <cds_test/check_size.h>
  8. namespace cds_test {
  9. class intrusive_msqueue : public ::testing::Test
  10. {
  11. protected:
  12. template <typename Base>
  13. struct base_hook_item : public Base
  14. {
  15. int nVal;
  16. int nDisposeCount;
  17. base_hook_item()
  18. : nDisposeCount( 0 )
  19. {}
  20. base_hook_item( base_hook_item const& s)
  21. : nVal( s.nVal )
  22. , nDisposeCount( s.nDisposeCount )
  23. {}
  24. };
  25. template <typename Member>
  26. struct member_hook_item
  27. {
  28. int nVal;
  29. int nDisposeCount;
  30. Member hMember;
  31. member_hook_item()
  32. : nDisposeCount( 0 )
  33. {}
  34. member_hook_item( member_hook_item const& s )
  35. : nVal( s.nVal )
  36. , nDisposeCount( s.nDisposeCount )
  37. {}
  38. };
  39. struct mock_disposer
  40. {
  41. template <typename T>
  42. void operator ()( T * p )
  43. {
  44. ++p->nDisposeCount;
  45. }
  46. };
  47. template <typename Queue, typename Data>
  48. void test( Queue& q, Data& arr )
  49. {
  50. typedef typename Queue::value_type value_type;
  51. size_t nSize = arr.size();
  52. value_type * pv;
  53. for ( size_t i = 0; i < nSize; ++i )
  54. arr[i].nVal = static_cast<int>(i);
  55. ASSERT_TRUE( q.empty());
  56. ASSERT_CONTAINER_SIZE( q, 0 );
  57. // pop from empty queue
  58. pv = q.pop();
  59. ASSERT_TRUE( pv == nullptr );
  60. ASSERT_TRUE( q.empty());
  61. ASSERT_CONTAINER_SIZE( q, 0 );
  62. pv =q.dequeue();
  63. ASSERT_TRUE( pv == nullptr );
  64. ASSERT_TRUE( q.empty());
  65. ASSERT_CONTAINER_SIZE( q, 0 );
  66. // push/pop test
  67. for ( size_t i = 0; i < nSize; ++i ) {
  68. if ( i & 1 )
  69. q.push( arr[i] );
  70. else
  71. q.enqueue( arr[i] );
  72. ASSERT_FALSE( q.empty());
  73. ASSERT_CONTAINER_SIZE( q, i + 1 );
  74. }
  75. for ( size_t i = 0; i < nSize; ++i ) {
  76. ASSERT_FALSE( q.empty());
  77. ASSERT_CONTAINER_SIZE( q, nSize - i );
  78. if ( i & 1 )
  79. pv = q.pop();
  80. else
  81. pv = q.dequeue();
  82. ASSERT_FALSE( pv == nullptr );
  83. ASSERT_EQ( pv->nVal, static_cast<int>(i));
  84. }
  85. ASSERT_TRUE( q.empty());
  86. ASSERT_CONTAINER_SIZE( q, 0 );
  87. Queue::gc::scan();
  88. --nSize; // last element of array is in queue yet as a dummy item
  89. for ( size_t i = 0; i < nSize; ++i ) {
  90. ASSERT_EQ( arr[i].nDisposeCount, 1 );
  91. }
  92. ASSERT_EQ( arr[nSize].nDisposeCount, 0 );
  93. // clear test
  94. for ( size_t i = 0; i < nSize; ++i )
  95. q.push( arr[i] );
  96. ASSERT_FALSE( q.empty());
  97. ASSERT_CONTAINER_SIZE( q, nSize );
  98. q.clear();
  99. ASSERT_TRUE( q.empty());
  100. ASSERT_CONTAINER_SIZE( q, 0 );
  101. Queue::gc::scan();
  102. for ( size_t i = 0; i < nSize - 1; ++i ) {
  103. ASSERT_EQ( arr[i].nDisposeCount, 2 ) << "i=" << i;
  104. }
  105. ASSERT_EQ( arr[nSize - 1].nDisposeCount, 1 ); // this element is in the queue yet
  106. ASSERT_EQ( arr[nSize].nDisposeCount, 1 );
  107. }
  108. };
  109. } // namespace cds_test
  110. #endif // CDSUNIT_QUEUE_TEST_INTRUSIVE_MSQUEUE_H