Removed old tree unit test
[libcds.git] / tests / test-hdr / misc / split_bitstring.cpp
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 #include "cppunit/cppunit_proxy.h"
32
33 #include <cds/algo/split_bitstring.h>
34
35 class Split_bitstrig : public CppUnitMini::TestCase
36 {
37 private:
38     bool is_big_endian()
39     {
40         union {
41             uint32_t ui;
42             uint8_t  ch;
43         } byte_order;
44         byte_order.ui = 0xFF000001;
45
46         return byte_order.ch != 0x01;
47     }
48 protected:
49
50     void cut_uint()
51     {
52         if ( is_big_endian() )
53             cut_uint_be();
54         else
55             cut_uint_le();
56     }
57
58     void cut_uint16()
59     {
60         if ( is_big_endian() )
61             cut_small_be<uint16_t>();
62         else
63             cut_small_le<uint16_t>();
64     }
65
66     void cut_uint_le()
67     {
68         CPPUNIT_MSG("little-endian byte order");
69
70         typedef cds::algo::split_bitstring< size_t > split_bitstring;
71
72         size_t src = sizeof(src) == 8 ? 0xFEDCBA9876543210 : 0x76543210;
73         split_bitstring splitter(src);
74         size_t res;
75
76         // Trivial case
77         CPPUNIT_ASSERT( !splitter.eos() );
78         CPPUNIT_ASSERT( splitter );
79         res = splitter.cut(sizeof(src) * 8);
80         CPPUNIT_ASSERT_EX( res == src, "src=" << src << ", result=" << res );
81         CPPUNIT_ASSERT( splitter.eos() );
82         CPPUNIT_ASSERT( !splitter );
83         CPPUNIT_ASSERT(splitter.safe_cut(sizeof(src) * 8) == 0 );
84         CPPUNIT_ASSERT( splitter.eos() );
85         CPPUNIT_ASSERT( !splitter );
86         splitter.reset();
87         CPPUNIT_ASSERT( !splitter.eos() );
88         CPPUNIT_ASSERT( splitter );
89         res = splitter.cut(sizeof(src) * 8);
90         CPPUNIT_ASSERT_EX( res == src, "src=" << src << ", result=" << res );
91         CPPUNIT_ASSERT( splitter.eos() );
92         CPPUNIT_ASSERT( !splitter );
93         CPPUNIT_ASSERT(splitter.safe_cut(sizeof(src) * 8) == 0 );
94         CPPUNIT_ASSERT( splitter.eos() );
95         CPPUNIT_ASSERT( !splitter );
96
97         // Cut each hex digit
98         splitter.reset();
99         for ( size_t i = 0; i < sizeof(size_t) * 2; ++i ) {
100             CPPUNIT_ASSERT( !splitter.eos() );
101             CPPUNIT_ASSERT( splitter );
102             CPPUNIT_ASSERT( splitter.cut( 4 ) == i );
103         }
104         CPPUNIT_ASSERT( splitter.eos() );
105         CPPUNIT_ASSERT( !splitter );
106
107         // by one bit
108         {
109             splitter.reset();
110             res = 0;
111             for ( size_t i = 0; i < sizeof(size_t) * 8; ++i ) {
112                 CPPUNIT_ASSERT( !splitter.eos() );
113                 CPPUNIT_ASSERT( splitter );
114                 res = res + (splitter.cut( 1 ) << i);
115             }
116             CPPUNIT_ASSERT( splitter.eos() );
117             CPPUNIT_ASSERT( !splitter );
118             CPPUNIT_ASSERT( res == src );
119         }
120
121         // random cut
122         {
123             for ( size_t k = 0; k < 100; ++k ) {
124                 splitter.reset();
125                 res = 0;
126                 size_t shift = 0;
127                 while ( splitter ) {
128                     CPPUNIT_ASSERT( !splitter.eos() );
129                     CPPUNIT_ASSERT( splitter );
130                     int bits = rand() % 16;
131                     res = res + ( splitter.safe_cut( bits ) << shift );
132                     shift += bits;
133                 }
134                 CPPUNIT_ASSERT( splitter.eos() );
135                 CPPUNIT_ASSERT( !splitter );
136                 CPPUNIT_ASSERT( res == src );
137             }
138         }
139     }
140
141     void cut_uint_be()
142     {
143         CPPUNIT_MSG("big-endian byte order");
144
145         typedef cds::algo::split_bitstring< size_t > split_bitstring;
146
147         size_t src = sizeof(src) == 8 ? 0xFEDCBA9876543210 : 0x76543210;
148         split_bitstring splitter(src);
149         size_t res;
150
151         // Trivial case
152         CPPUNIT_ASSERT( !splitter.eos() );
153         CPPUNIT_ASSERT( splitter );
154         res = splitter.cut(sizeof(src) * 8);
155         CPPUNIT_ASSERT_EX( res == src, "src=" << src << ", result=" << res );
156         CPPUNIT_ASSERT( splitter.eos() );
157         CPPUNIT_ASSERT( !splitter );
158         CPPUNIT_ASSERT(splitter.safe_cut(sizeof(src) * 8) == 0 );
159         CPPUNIT_ASSERT( splitter.eos() );
160         CPPUNIT_ASSERT( !splitter );
161         splitter.reset();
162         CPPUNIT_ASSERT( !splitter.eos() );
163         CPPUNIT_ASSERT( splitter );
164         res = splitter.cut(sizeof(src) * 8);
165         CPPUNIT_ASSERT_EX( res == src, "src=" << src << ", result=" << res );
166         CPPUNIT_ASSERT( splitter.eos() );
167         CPPUNIT_ASSERT( !splitter );
168         CPPUNIT_ASSERT(splitter.safe_cut(sizeof(src) * 8) == 0 );
169         CPPUNIT_ASSERT( splitter.eos() );
170         CPPUNIT_ASSERT( !splitter );
171
172         // Cut each hex digit
173         splitter.reset();
174         for ( size_t i = 0; i < sizeof(size_t) * 2; ++i ) {
175             CPPUNIT_ASSERT( !splitter.eos() );
176             CPPUNIT_ASSERT( splitter );
177             CPPUNIT_ASSERT( splitter.cut( 4 ) == 0x0F - i );
178         }
179         CPPUNIT_ASSERT( splitter.eos() );
180         CPPUNIT_ASSERT( !splitter );
181
182         // by one bit
183         {
184             splitter.reset();
185             res = 0;
186             for ( size_t i = 0; i < sizeof(size_t) * 8; ++i ) {
187                 CPPUNIT_ASSERT( !splitter.eos() );
188                 CPPUNIT_ASSERT( splitter );
189                 res = (res << 1) + splitter.cut( 1 );
190             }
191             CPPUNIT_ASSERT( splitter.eos() );
192             CPPUNIT_ASSERT( !splitter );
193             CPPUNIT_ASSERT( res == src );
194         }
195
196         // random cut
197         {
198             for ( size_t k = 0; k < 100; ++k ) {
199                 splitter.reset();
200                 res = 0;
201                 while ( splitter ) {
202                     CPPUNIT_ASSERT( !splitter.eos() );
203                     CPPUNIT_ASSERT( splitter );
204                     int bits = rand() % 16;
205                     res = (res << bits) + splitter.safe_cut( bits );
206                 }
207                 CPPUNIT_ASSERT( splitter.eos() );
208                 CPPUNIT_ASSERT( !splitter );
209                 CPPUNIT_ASSERT( res == src );
210             }
211         }
212     }
213
214
215 private:
216     template <typename PartUInt>
217     void cut_small_le()
218     {
219         CPPUNIT_MSG("little-endian byte order");
220         typedef PartUInt part_uint;
221
222         typedef cds::algo::split_bitstring< uint64_t, part_uint > split_bitstring;
223
224         uint64_t src = 0xFEDCBA9876543210;
225         split_bitstring splitter(src);
226         uint64_t res;
227
228         // Cut each hex digit
229         splitter.reset();
230         for ( size_t i = 0; i < sizeof(size_t) * 2; ++i ) {
231             CPPUNIT_ASSERT( !splitter.eos() );
232             CPPUNIT_ASSERT( splitter );
233             CPPUNIT_ASSERT( static_cast<size_t>(splitter.cut( 4 )) == i );
234         }
235         CPPUNIT_ASSERT( splitter.eos() );
236         CPPUNIT_ASSERT( !splitter );
237
238         // by one bit
239         {
240             splitter.reset();
241             res = 0;
242             for ( size_t i = 0; i < sizeof(size_t) * 8; ++i ) {
243                 CPPUNIT_ASSERT( !splitter.eos() );
244                 CPPUNIT_ASSERT( splitter );
245                 res = res + ( static_cast<uint64_t>(splitter.cut( 1 )) << i);
246             }
247             CPPUNIT_ASSERT( splitter.eos() );
248             CPPUNIT_ASSERT( !splitter );
249             CPPUNIT_ASSERT( res == src );
250         }
251
252         // random cut
253         {
254             for ( size_t k = 0; k < 100; ++k ) {
255                 splitter.reset();
256                 res = 0;
257                 size_t shift = 0;
258                 while ( splitter ) {
259                     CPPUNIT_ASSERT( !splitter.eos() );
260                     CPPUNIT_ASSERT( splitter );
261                     int bits = rand() % 16;
262                     res = res + ( static_cast<uint64_t>(splitter.safe_cut( bits )) << shift );
263                     shift += bits;
264                 }
265                 CPPUNIT_ASSERT( splitter.eos() );
266                 CPPUNIT_ASSERT( !splitter );
267                 CPPUNIT_ASSERT( res == src );
268             }
269         }
270     }
271
272     template <typename PartUInt>
273     void cut_small_be()
274     {
275         CPPUNIT_MSG("big-endian byte order");
276         typedef PartUInt part_uint;
277
278         typedef cds::algo::split_bitstring< uint64_t, part_uint > split_bitstring;
279
280         uint64_t src = 0xFEDCBA9876543210;
281         split_bitstring splitter(src);
282         uint64_t res;
283
284         // Cut each hex digit
285         splitter.reset();
286         for ( size_t i = 0; i < sizeof(size_t) * 2; ++i ) {
287             CPPUNIT_ASSERT( !splitter.eos() );
288             CPPUNIT_ASSERT( splitter );
289             CPPUNIT_ASSERT( splitter.cut( 4 ) == 0x0F - i );
290         }
291         CPPUNIT_ASSERT( splitter.eos() );
292         CPPUNIT_ASSERT( !splitter );
293
294         // by one bit
295         {
296             splitter.reset();
297             res = 0;
298             for ( size_t i = 0; i < sizeof(size_t) * 8; ++i ) {
299                 CPPUNIT_ASSERT( !splitter.eos() );
300                 CPPUNIT_ASSERT( splitter );
301                 res = (res << 1) + splitter.cut( 1 );
302             }
303             CPPUNIT_ASSERT( splitter.eos() );
304             CPPUNIT_ASSERT( !splitter );
305             CPPUNIT_ASSERT( res == src );
306         }
307
308         // random cut
309         {
310             for ( size_t k = 0; k < 100; ++k ) {
311                 splitter.reset();
312                 res = 0;
313                 while ( splitter ) {
314                     CPPUNIT_ASSERT( !splitter.eos() );
315                     CPPUNIT_ASSERT( splitter );
316                     int bits = rand() % 16;
317                     res = (res << bits) + splitter.safe_cut( bits );
318                 }
319                 CPPUNIT_ASSERT( splitter.eos() );
320                 CPPUNIT_ASSERT( !splitter );
321                 CPPUNIT_ASSERT( res == src );
322             }
323         }
324     }
325
326
327     CPPUNIT_TEST_SUITE(Split_bitstrig);
328         CPPUNIT_TEST(cut_uint)
329         CPPUNIT_TEST(cut_uint16)
330     CPPUNIT_TEST_SUITE_END();
331 };
332
333 CPPUNIT_TEST_SUITE_REGISTRATION(Split_bitstrig);