1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
// Copyright (c) 2006-2018 Maxim Khizhinsky
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef CDSUNIT_QUEUE_TEST_INTRUSIVE_MSQUEUE_H
#define CDSUNIT_QUEUE_TEST_INTRUSIVE_MSQUEUE_H
#include <cds_test/check_size.h>
namespace cds_test {
class intrusive_msqueue : public ::testing::Test
{
protected:
template <typename Base>
struct base_hook_item : public Base
{
int nVal;
int nDisposeCount;
base_hook_item()
: nDisposeCount( 0 )
{}
base_hook_item( base_hook_item const& s)
: nVal( s.nVal )
, nDisposeCount( s.nDisposeCount )
{}
};
template <typename Member>
struct member_hook_item
{
int nVal;
int nDisposeCount;
Member hMember;
member_hook_item()
: nDisposeCount( 0 )
{}
member_hook_item( member_hook_item const& s )
: nVal( s.nVal )
, nDisposeCount( s.nDisposeCount )
{}
};
struct mock_disposer
{
template <typename T>
void operator ()( T * p )
{
++p->nDisposeCount;
}
};
template <typename Queue, typename Data>
void test( Queue& q, Data& arr )
{
typedef typename Queue::value_type value_type;
size_t nSize = arr.size();
value_type * pv;
for ( size_t i = 0; i < nSize; ++i )
arr[i].nVal = static_cast<int>(i);
ASSERT_TRUE( q.empty());
ASSERT_CONTAINER_SIZE( q, 0 );
// pop from empty queue
pv = q.pop();
ASSERT_TRUE( pv == nullptr );
ASSERT_TRUE( q.empty());
ASSERT_CONTAINER_SIZE( q, 0 );
pv =q.dequeue();
ASSERT_TRUE( pv == nullptr );
ASSERT_TRUE( q.empty());
ASSERT_CONTAINER_SIZE( q, 0 );
// push/pop test
for ( size_t i = 0; i < nSize; ++i ) {
if ( i & 1 )
q.push( arr[i] );
else
q.enqueue( arr[i] );
ASSERT_FALSE( q.empty());
ASSERT_CONTAINER_SIZE( q, i + 1 );
}
for ( size_t i = 0; i < nSize; ++i ) {
ASSERT_FALSE( q.empty());
ASSERT_CONTAINER_SIZE( q, nSize - i );
if ( i & 1 )
pv = q.pop();
else
pv = q.dequeue();
ASSERT_FALSE( pv == nullptr );
ASSERT_EQ( pv->nVal, static_cast<int>(i));
}
ASSERT_TRUE( q.empty());
ASSERT_CONTAINER_SIZE( q, 0 );
Queue::gc::scan();
--nSize; // last element of array is in queue yet as a dummy item
for ( size_t i = 0; i < nSize; ++i ) {
ASSERT_EQ( arr[i].nDisposeCount, 1 );
}
ASSERT_EQ( arr[nSize].nDisposeCount, 0 );
// clear test
for ( size_t i = 0; i < nSize; ++i )
q.push( arr[i] );
ASSERT_FALSE( q.empty());
ASSERT_CONTAINER_SIZE( q, nSize );
q.clear();
ASSERT_TRUE( q.empty());
ASSERT_CONTAINER_SIZE( q, 0 );
Queue::gc::scan();
for ( size_t i = 0; i < nSize - 1; ++i ) {
ASSERT_EQ( arr[i].nDisposeCount, 2 ) << "i=" << i;
}
ASSERT_EQ( arr[nSize - 1].nDisposeCount, 1 ); // this element is in the queue yet
ASSERT_EQ( arr[nSize].nDisposeCount, 1 );
}
};
} // namespace cds_test
#endif // CDSUNIT_QUEUE_TEST_INTRUSIVE_MSQUEUE_H
|