Removed trailing spaces
[libcds.git] / test / unit / queue / test_intrusive_msqueue.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
15     * Redistributions in binary form must reproduce the above copyright notice,
16       this list of conditions and the following disclaimer in the documentation
17       and/or other materials provided with the distribution.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifndef CDSUNIT_QUEUE_TEST_INTRUSIVE_MSQUEUE_H
32 #define CDSUNIT_QUEUE_TEST_INTRUSIVE_MSQUEUE_H
33
34 #include <cds_test/check_size.h>
35
36 namespace cds_test {
37
38     class intrusive_msqueue : public ::testing::Test
39     {
40     protected:
41         template <typename Base>
42         struct base_hook_item : public Base
43         {
44             int nVal;
45             int nDisposeCount;
46
47             base_hook_item()
48                 : nDisposeCount( 0 )
49             {}
50
51             base_hook_item( base_hook_item const& s)
52                 : nVal( s.nVal )
53                 , nDisposeCount( s.nDisposeCount )
54             {}
55         };
56
57         template <typename Member>
58         struct member_hook_item
59         {
60             int nVal;
61             int nDisposeCount;
62             Member hMember;
63
64             member_hook_item()
65                 : nDisposeCount( 0 )
66             {}
67
68             member_hook_item( member_hook_item const& s )
69                 : nVal( s.nVal )
70                 , nDisposeCount( s.nDisposeCount )
71             {}
72         };
73
74         struct mock_disposer
75         {
76             template <typename T>
77             void operator ()( T * p )
78             {
79                 ++p->nDisposeCount;
80             }
81         };
82
83         template <typename Queue, typename Data>
84         void test( Queue& q, Data& arr )
85         {
86             typedef typename Queue::value_type value_type;
87             size_t nSize = arr.size();
88
89             value_type * pv;
90             for ( size_t i = 0; i < nSize; ++i )
91                 arr[i].nVal = static_cast<int>(i);
92
93             ASSERT_TRUE( q.empty() );
94             ASSERT_CONTAINER_SIZE( q, 0 );
95
96             // pop from empty queue
97             pv = q.pop();
98             ASSERT_TRUE( pv == nullptr );
99             ASSERT_TRUE( q.empty() );
100             ASSERT_CONTAINER_SIZE( q, 0 );
101
102             pv =q.dequeue();
103             ASSERT_TRUE( pv == nullptr );
104             ASSERT_TRUE( q.empty() );
105             ASSERT_CONTAINER_SIZE( q, 0 );
106
107             // push/pop test
108             for ( size_t i = 0; i < nSize; ++i ) {
109                 if ( i & 1 )
110                     q.push( arr[i] );
111                 else
112                     q.enqueue( arr[i] );
113                 ASSERT_FALSE( q.empty());
114                 ASSERT_CONTAINER_SIZE( q, i + 1 );
115             }
116
117             for ( size_t i = 0; i < nSize; ++i ) {
118                 ASSERT_FALSE( q.empty() );
119                 ASSERT_CONTAINER_SIZE( q, nSize - i );
120                 if ( i & 1 )
121                     pv = q.pop();
122                 else
123                     pv = q.dequeue();
124                 ASSERT_FALSE( pv == nullptr );
125                 ASSERT_EQ( pv->nVal, static_cast<int>(i));
126             }
127             ASSERT_TRUE( q.empty() );
128             ASSERT_CONTAINER_SIZE( q, 0 );
129
130             Queue::gc::scan();
131             --nSize; // last element of array is in queue yet as a dummy item
132             for ( size_t i = 0; i < nSize; ++i ) {
133                 ASSERT_EQ( arr[i].nDisposeCount, 1 );
134             }
135             ASSERT_EQ( arr[nSize].nDisposeCount, 0 );
136
137             // clear test
138             for ( size_t i = 0; i < nSize; ++i )
139                 q.push( arr[i] );
140
141             ASSERT_FALSE( q.empty() );
142             ASSERT_CONTAINER_SIZE( q, nSize );
143
144             q.clear();
145             ASSERT_TRUE( q.empty() );
146             ASSERT_CONTAINER_SIZE( q, 0 );
147
148             Queue::gc::scan();
149             for ( size_t i = 0; i < nSize - 1; ++i ) {
150                 ASSERT_EQ( arr[i].nDisposeCount, 2 ) << "i=" << i;
151             }
152             ASSERT_EQ( arr[nSize - 1].nDisposeCount, 1 ); // this element is in the queue yet
153             ASSERT_EQ( arr[nSize].nDisposeCount, 1 );
154         }
155     };
156
157 } // namespace cds_test
158
159 #endif // CDSUNIT_QUEUE_TEST_INTRUSIVE_MSQUEUE_H