Migrated MichaelMap unit test to gtest
[libcds.git] / test / unit / map / test_map_rcu.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_MAP_TEST_MAP_RCU_H
32 #define CDSUNIT_MAP_TEST_MAP_RCU_H
33
34 #include "test_map.h"
35
36 namespace cds_test {
37
38     class container_map_rcu: public container_map
39     {
40         typedef container_map base_class;
41
42     protected:
43         template <class Map>
44         void test( Map& m )
45         {
46             // Precondition: map is empty
47             // Postcondition: map is empty
48
49             base_class::test( m );
50
51             ASSERT_TRUE( m.empty());
52             ASSERT_CONTAINER_SIZE( m, 0 );
53
54             typedef typename Map::value_type map_pair;
55             size_t const kkSize = base_class::kSize;
56
57             std::vector<key_type> arrKeys;
58             for ( int i = 0; i < static_cast<int>(kkSize); ++i )
59                 arrKeys.push_back( key_type( i ));
60             shuffle( arrKeys.begin(), arrKeys.end());
61
62             std::vector< value_type > arrVals;
63             for ( size_t i = 0; i < kkSize; ++i ) {
64                 value_type val;
65                 val.nVal = static_cast<int>( i );
66                 val.strVal = std::to_string( i );
67                 arrVals.push_back( val );
68             }
69
70             for ( auto const& i : arrKeys )
71                 ASSERT_TRUE( m.insert( i ) );
72             ASSERT_FALSE( m.empty() );
73             ASSERT_CONTAINER_SIZE( m, kkSize );
74
75             // iterators
76             size_t nCount = 0;
77             for ( auto it = m.begin(); it != m.end(); ++it ) {
78                 EXPECT_EQ( it->second.nVal, 0 );
79                 it->second.nVal = it->first.nKey * 2;
80                 ++nCount;
81             }
82             EXPECT_EQ( nCount, kkSize );
83
84             nCount = 0;
85             for ( auto it = m.cbegin(); it != m.cend(); ++it ) {
86                 EXPECT_EQ( it->second.nVal, it->first.nKey * 2 );
87                 ++nCount;
88             }
89             EXPECT_EQ( nCount, kkSize );
90
91             typedef typename Map::exempt_ptr exempt_ptr;
92             typedef typename Map::raw_ptr    raw_ptr;
93             typedef typename Map::rcu_lock   rcu_lock;
94
95             // get/extract
96             shuffle( arrKeys.begin(), arrKeys.end() );
97
98             for ( auto const& i : arrKeys ) {
99                 value_type const& val = arrVals.at( i.nKey );
100
101                 {
102                     rcu_lock l;
103                     raw_ptr rp;
104
105                     rp = m.get( i.nKey );
106                     ASSERT_FALSE( !rp );
107                     EXPECT_EQ( rp->first.nKey, i.nKey );
108                     rp->second.nVal = rp->first.nKey * 2;
109
110                     rp = m.get( i );
111                     ASSERT_FALSE( !rp );
112                     EXPECT_EQ( rp->first.nKey, i.nKey );
113                     EXPECT_EQ( rp->second.nVal, rp->first.nKey * 2 );
114                     rp->second.nVal = rp->first.nKey * 3;
115
116                     rp = m.get_with( other_item( i.nKey ), other_less());
117                     ASSERT_FALSE( !rp );
118                     EXPECT_EQ( rp->first.nKey, i.nKey );
119                     EXPECT_EQ( rp->second.nVal, rp->first.nKey * 3 );
120                     rp->second.nVal = rp->first.nKey;
121                 }
122
123                 exempt_ptr xp;
124                 if ( Map::c_bExtractLockExternal ) {
125                     {
126                         rcu_lock l;
127
128                         switch ( i.nKey % 4 ) {
129                         case 0:
130                             xp = m.extract( i.nKey );
131                             break;
132                         case 1:
133                             xp = m.extract( i );
134                             break;
135                         case 2:
136                             xp = m.extract( val.strVal );
137                             break;
138                         case 3:
139                             xp = m.extract_with( other_item( i.nKey ), other_less() );
140                             break;
141                         }
142                         ASSERT_FALSE( !xp );
143                         EXPECT_EQ( xp->first.nKey, i.nKey );
144                         EXPECT_EQ( xp->second.nVal, xp->first.nKey );
145                     }
146                     xp.release();
147
148                     {
149                         rcu_lock l;
150
151                         switch ( i.nKey % 4 ) {
152                         case 0:
153                             xp = m.extract( i.nKey );
154                             break;
155                         case 1:
156                             xp = m.extract( i );
157                             break;
158                         case 2:
159                             xp = m.extract( val.strVal );
160                             break;
161                         case 3:
162                             xp = m.extract_with( other_item( i.nKey ), other_less() );
163                             break;
164                         }
165                         EXPECT_TRUE( !xp );
166                     }
167                 }
168                 else {
169                     switch ( i.nKey % 4 ) {
170                     case 0:
171                         xp = m.extract( i.nKey );
172                         break;
173                     case 1:
174                         xp = m.extract( i );
175                         break;
176                     case 2:
177                         xp = m.extract( val.strVal );
178                         break;
179                     case 3:
180                         xp = m.extract_with( other_item( i.nKey ), other_less());
181                         break;
182                     }
183                     ASSERT_FALSE( !xp );
184                     EXPECT_EQ( xp->first.nKey, i.nKey );
185                     EXPECT_EQ( xp->second.nVal, xp->first.nKey );
186
187                     switch ( i.nKey % 4 ) {
188                     case 0:
189                         xp = m.extract( i.nKey );
190                         break;
191                     case 1:
192                         xp = m.extract( i );
193                         break;
194                     case 2:
195                         xp = m.extract( val.strVal );
196                         break;
197                     case 3:
198                         xp = m.extract_with( other_item( i.nKey ), other_less() );
199                         break;
200                     }
201                     EXPECT_TRUE( !xp );
202                 }
203
204                 {
205                     rcu_lock l;
206                     raw_ptr rp;
207
208                     rp = m.get( i.nKey );
209                     ASSERT_TRUE( !rp );
210                     rp = m.get( i );
211                     ASSERT_TRUE( !rp );
212                     rp = m.get_with( other_item( i.nKey ), other_less() );
213                     ASSERT_TRUE( !rp );
214                 }
215             }
216
217             ASSERT_TRUE( m.empty() );
218             ASSERT_CONTAINER_SIZE( m, 0 );
219         }
220     };
221
222 } // namespace cds_test
223
224 #endif // #ifndef CDSUNIT_MAP_TEST_MAP_H