]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/crc/test/crc_test.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / crc / test / crc_test.cpp
1 // Boost CRC test program file ---------------------------------------------//
2
3 // Copyright 2001, 2003, 2004 Daryle Walker. Use, modification, and
4 // distribution are subject to the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or a copy at
6 // <http://www.boost.org/LICENSE_1_0.txt>.)
7
8 // See <http://www.boost.org/libs/crc/> for the library's home page.
9
10 // Revision History
11 // 28 Aug 2004 Added CRC tests for polynominals shorter than 8 bits
12 // (Daryle Walker, by patch from Bert Klaps)
13 // 23 Aug 2003 Adjust to updated Test framework (Daryle Walker)
14 // 14 May 2001 Initial version (Daryle Walker)
15
16
17 #include <boost/config.hpp> // for BOOST_MSVC, etc.
18 #include <boost/crc.hpp> // for boost::crc_basic, etc.
19 #include <boost/cstdint.hpp> // for boost::uint16_t, etc.
20 #include <boost/cstdlib.hpp> // for boost::exit_success
21 #include <boost/integer.hpp> // for boost::uint_t
22 #include <boost/random/linear_congruential.hpp> // for boost::minstd_rand
23 #include <boost/core/lightweight_test.hpp>
24 #include <boost/timer.hpp> // for boost::timer
25
26 #include <algorithm> // for std::for_each, std::generate_n, std::count
27 #include <climits> // for CHAR_BIT
28 #include <cstddef> // for std::size_t
29 #include <iostream> // for std::cout (std::ostream and std::endl indirectly)
30
31
32 #if CHAR_BIT != 8
33 #error The expected results assume an eight-bit byte.
34 #endif
35
36 #if !(defined(BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS) || (defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)))
37 #define CRC_PARM_TYPE typename boost::uint_t<Bits>::fast
38 #else
39 #define CRC_PARM_TYPE unsigned long
40 #endif
41
42 #if !defined(BOOST_MSVC) && !defined(__GNUC__)
43 #define PRIVATE_DECLARE_BOOST( TypeName ) using boost:: TypeName
44 #else
45 #define PRIVATE_DECLARE_BOOST( TypeName ) typedef boost:: TypeName TypeName
46 #endif
47
48
49 // Types
50 template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
51 CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
52 class crc_tester
53 {
54 public:
55 // All the following were separate function templates, but they have
56 // been moved to class-static member functions of a class template
57 // because MS VC++ 6 can't handle function templates that can't
58 // deduce all their template arguments from their function arguments.
59
60 typedef typename boost::uint_t<Bits>::fast value_type;
61
62 static void master_test( char const *test_name, value_type expected );
63
64 private:
65 typedef boost::crc_optimal<Bits, TrPo, InRe, FiXo, ReIn, ReRe>
66 optimal_crc_type;
67 typedef boost::crc_basic<Bits> basic_crc_type;
68
69 static void compute_test( value_type expected );
70 static void interrupt_test( value_type expected );
71 static void error_test();
72
73 }; // crc_tester
74
75 // Global data
76 unsigned char const std_data[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
77 0x38, 0x39 };
78 std::size_t const std_data_len = sizeof( std_data ) / sizeof( std_data[0] );
79
80 boost::uint16_t const std_crc_ccitt_result = 0x29B1;
81 boost::uint16_t const std_crc_16_result = 0xBB3D;
82 boost::uint32_t const std_crc_32_result = 0xCBF43926;
83
84 // Function prototypes
85 void timing_test();
86 boost::uint32_t basic_crc32( void const *buffer, std::size_t byte_count );
87 boost::uint32_t optimal_crc32( void const *buffer, std::size_t byte_count );
88 boost::uint32_t quick_crc32( void const *buffer, std::size_t byte_count );
89 boost::uint32_t quick_reflect( boost::uint32_t value, std::size_t bits );
90 double time_trial( char const *name,
91 boost::uint32_t (*crc_func)(void const *, std::size_t),
92 boost::uint32_t expected, void const *data, std::size_t length );
93
94 void augmented_tests();
95 boost::uint32_t native_to_big( boost::uint32_t x );
96 boost::uint32_t big_to_native( boost::uint32_t x );
97
98 void small_crc_test1();
99 void small_crc_test2();
100
101
102 // Macro to compact code
103 #define PRIVATE_TESTER_NAME crc_tester<Bits, TrPo, InRe, FiXo, ReIn, ReRe>
104
105 // Run a test on slow and fast CRC computers and function
106 template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
107 CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
108 void
109 PRIVATE_TESTER_NAME::compute_test
110 (
111 typename PRIVATE_TESTER_NAME::value_type expected
112 )
113 {
114 std::cout << "\tDoing computation tests." << std::endl;
115
116 optimal_crc_type fast_crc;
117 basic_crc_type slow_crc( TrPo, InRe, FiXo, ReIn, ReRe );
118 value_type const func_result = boost::crc<Bits, TrPo, InRe, FiXo, ReIn,
119 ReRe>( std_data, std_data_len );
120
121 fast_crc.process_bytes( std_data, std_data_len );
122 slow_crc.process_bytes( std_data, std_data_len );
123 BOOST_TEST_EQ( fast_crc.checksum(), expected );
124 BOOST_TEST_EQ( slow_crc.checksum(), expected );
125 BOOST_TEST_EQ( func_result, expected );
126 }
127
128 // Run a test in two runs, and check all the inspectors
129 template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
130 CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
131 void
132 PRIVATE_TESTER_NAME::interrupt_test
133 (
134 typename PRIVATE_TESTER_NAME::value_type expected
135 )
136 {
137 std::cout << "\tDoing interrupt tests." << std::endl;
138
139 // Process the first half of the data (also test accessors)
140 optimal_crc_type fast_crc1;
141 basic_crc_type slow_crc1( fast_crc1.get_truncated_polynominal(),
142 fast_crc1.get_initial_remainder(), fast_crc1.get_final_xor_value(),
143 fast_crc1.get_reflect_input(), fast_crc1.get_reflect_remainder() );
144
145 BOOST_TEST_EQ( fast_crc1.get_interim_remainder(),
146 slow_crc1.get_initial_remainder() );
147
148 std::size_t const mid_way = std_data_len / 2;
149 unsigned char const * const std_data_end = std_data + std_data_len;
150
151 fast_crc1.process_bytes( std_data, mid_way );
152 slow_crc1.process_bytes( std_data, mid_way );
153 BOOST_TEST_EQ( fast_crc1.checksum(), slow_crc1.checksum() );
154
155 // Process the second half of the data (also test accessors)
156 boost::crc_optimal<optimal_crc_type::bit_count,
157 optimal_crc_type::truncated_polynominal, optimal_crc_type::initial_remainder,
158 optimal_crc_type::final_xor_value, optimal_crc_type::reflect_input,
159 optimal_crc_type::reflect_remainder>
160 fast_crc2( fast_crc1.get_interim_remainder() );
161 boost::crc_basic<basic_crc_type::bit_count> slow_crc2(
162 slow_crc1.get_truncated_polynominal(), slow_crc1.get_interim_remainder(),
163 slow_crc1.get_final_xor_value(), slow_crc1.get_reflect_input(),
164 slow_crc1.get_reflect_remainder() );
165
166 fast_crc2.process_block( std_data + mid_way, std_data_end );
167 slow_crc2.process_block( std_data + mid_way, std_data_end );
168 BOOST_TEST_EQ( fast_crc2.checksum(), slow_crc2.checksum() );
169 BOOST_TEST_EQ( fast_crc2.checksum(), expected );
170 BOOST_TEST_EQ( slow_crc2.checksum(), expected );
171 }
172
173 // Run a test to see if a single-bit error is detected
174 template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
175 CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
176 void
177 PRIVATE_TESTER_NAME::error_test
178 (
179 )
180 {
181 PRIVATE_DECLARE_BOOST( uint32_t );
182
183 // A single-bit error is ensured to be detected if the polynominal
184 // has at least two bits set. The highest bit is what is removed
185 // to give the truncated polynominal, and it is always set. This
186 // means that the truncated polynominal needs at least one of its
187 // bits set, which implies that it cannot be zero.
188 if ( !(TrPo & boost::detail::low_bits_mask_c<Bits>::value) )
189 {
190 BOOST_ERROR( "truncated CRC polymonial is zero" );
191 }
192
193 std::cout << "\tDoing error tests." << std::endl;
194
195 // Create a random block of data
196 uint32_t ran_data[ 256 ];
197 std::size_t const ran_length = sizeof(ran_data) / sizeof(ran_data[0]);
198
199 std::generate_n( ran_data, ran_length, boost::minstd_rand() );
200
201 // Create computers and compute the checksum of the data
202 optimal_crc_type fast_tester;
203 basic_crc_type slow_tester( TrPo, InRe, FiXo, ReIn, ReRe );
204
205 fast_tester.process_bytes( ran_data, sizeof(ran_data) );
206 slow_tester.process_bytes( ran_data, sizeof(ran_data) );
207
208 uint32_t const fast_checksum = fast_tester.checksum();
209 uint32_t const slow_checksum = slow_tester.checksum();
210
211 BOOST_TEST_EQ( fast_checksum, slow_checksum );
212
213 // Do the checksum again (and test resetting ability)
214 fast_tester.reset();
215 slow_tester.reset( InRe );
216 fast_tester.process_bytes( ran_data, sizeof(ran_data) );
217 slow_tester.process_bytes( ran_data, sizeof(ran_data) );
218 BOOST_TEST_EQ( fast_tester.checksum(), slow_tester.checksum() );
219 BOOST_TEST_EQ( fast_tester.checksum(), fast_checksum );
220 BOOST_TEST_EQ( slow_tester.checksum(), slow_checksum );
221
222 // Produce a single-bit error
223 ran_data[ ran_data[0] % ran_length ] ^= ( 1 << (ran_data[1] % 32) );
224
225 // Compute the checksum of the errorenous data
226 // (and continue testing resetting ability)
227 fast_tester.reset( InRe );
228 slow_tester.reset();
229 fast_tester.process_bytes( ran_data, sizeof(ran_data) );
230 slow_tester.process_bytes( ran_data, sizeof(ran_data) );
231 BOOST_TEST_EQ( fast_tester.checksum(), slow_tester.checksum() );
232 BOOST_TEST_NE( fast_tester.checksum(), fast_checksum );
233 BOOST_TEST_NE( slow_tester.checksum(), slow_checksum );
234 }
235
236 // Run the other CRC object tests
237 template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
238 CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
239 void
240 PRIVATE_TESTER_NAME::master_test
241 (
242 char const * test_name,
243 typename PRIVATE_TESTER_NAME::value_type expected
244 )
245 {
246 std::cout << "Doing test suite for " << test_name << '.' << std::endl;
247 compute_test( expected );
248 interrupt_test( expected );
249 error_test();
250 }
251
252 // Undo limited macros
253 #undef PRIVATE_TESTER_NAME
254
255
256 // A CRC-32 computer based on crc_basic, for timing
257 boost::uint32_t
258 basic_crc32
259 (
260 void const * buffer,
261 std::size_t byte_count
262 )
263 {
264 static boost::crc_basic<32> computer( 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF,
265 true, true );
266
267 computer.reset();
268 computer.process_bytes( buffer, byte_count );
269 return computer.checksum();
270 }
271
272 // A CRC-32 computer based on crc_optimal, for timing
273 inline
274 boost::uint32_t
275 optimal_crc32
276 (
277 void const * buffer,
278 std::size_t byte_count
279 )
280 {
281 static boost::crc_32_type computer;
282
283 computer.reset();
284 computer.process_bytes( buffer, byte_count );
285 return computer.checksum();
286 }
287
288 // Reflect the lower "bits" bits of a "value"
289 boost::uint32_t
290 quick_reflect
291 (
292 boost::uint32_t value,
293 std::size_t bits
294 )
295 {
296 boost::uint32_t reflection = 0;
297 for ( std::size_t i = 0 ; i < bits ; ++i )
298 {
299 if ( value & (1u << i) )
300 {
301 reflection |= 1 << ( bits - 1 - i );
302 }
303 }
304
305 return reflection;
306 }
307
308 // A customized CRC-32 computer, for timing
309 boost::uint32_t
310 quick_crc32
311 (
312 void const * buffer,
313 std::size_t byte_count
314 )
315 {
316 PRIVATE_DECLARE_BOOST( uint32_t );
317 typedef unsigned char byte_type;
318
319 // Compute the CRC table (first run only)
320 static bool did_init = false;
321 static uint32_t crc_table[ 1ul << CHAR_BIT ];
322 if ( !did_init )
323 {
324 uint32_t const value_high_bit = static_cast<uint32_t>(1) << 31u;
325
326 byte_type dividend = 0;
327 do
328 {
329 uint32_t remainder = 0;
330 for ( byte_type mask = 1u << (CHAR_BIT - 1u) ; mask ; mask >>= 1 )
331 {
332 if ( dividend & mask )
333 {
334 remainder ^= value_high_bit;
335 }
336
337 if ( remainder & value_high_bit )
338 {
339 remainder <<= 1;
340 remainder ^= 0x04C11DB7u;
341 }
342 else
343 {
344 remainder <<= 1;
345 }
346 }
347
348 crc_table[ quick_reflect(dividend, CHAR_BIT) ]
349 = quick_reflect( remainder, 32 );
350 }
351 while ( ++dividend );
352
353 did_init = true;
354 }
355
356 // Compute the CRC of the data
357 uint32_t rem = 0xFFFFFFFF;
358
359 byte_type const * const b_begin = static_cast<byte_type const *>( buffer );
360 byte_type const * const b_end = b_begin + byte_count;
361 for ( byte_type const *p = b_begin ; p < b_end ; ++p )
362 {
363 byte_type const byte_index = *p ^ rem;
364 rem >>= CHAR_BIT;
365 rem ^= crc_table[ byte_index ];
366 }
367
368 return ~rem;
369 }
370
371 // Run an individual timing trial
372 double
373 time_trial
374 (
375 char const * name,
376 boost::uint32_t (*crc_func)(void const *, std::size_t),
377 boost::uint32_t expected,
378 void const * data,
379 std::size_t length
380 )
381 {
382 PRIVATE_DECLARE_BOOST( uint32_t );
383 using std::cout;
384
385 // Limits of a trial
386 static uint32_t const max_count = 1L << 16; // ~square-root of max
387 static double const max_time = 3.14159; // easy as pi(e)
388
389 // Mark the trial
390 cout << '\t' << name << " CRC-32: ";
391
392 // Trial loop
393 uint32_t trial_count = 0, wrong_count = 0;
394 double elapsed_time = 0.0;
395 boost::timer t;
396
397 do
398 {
399 uint32_t const scratch = (*crc_func)( data, length );
400
401 if ( scratch != expected )
402 {
403 ++wrong_count;
404 }
405 elapsed_time = t.elapsed();
406 ++trial_count;
407 } while ( (trial_count < max_count) && (elapsed_time < max_time) );
408
409 if ( wrong_count )
410 {
411 BOOST_ERROR( "at least one time trial didn't match expected" );
412 }
413
414 // Report results
415 double const rate = trial_count / elapsed_time;
416
417 cout << trial_count << " runs, " << elapsed_time << " s, " << rate
418 << " run/s" << std::endl;
419 return rate;
420 }
421
422 // Time runs of Boost CRCs vs. a customized CRC function
423 void
424 timing_test
425 (
426 )
427 {
428 PRIVATE_DECLARE_BOOST( uint32_t );
429 using std::cout;
430 using std::endl;
431
432 cout << "Doing timing tests." << endl;
433
434 // Create a random block of data
435 boost::int32_t ran_data[ 256 ];
436 std::size_t const ran_length = sizeof(ran_data) / sizeof(ran_data[0]);
437
438 std::generate_n( ran_data, ran_length, boost::minstd_rand() );
439
440 // Use the first runs as a check. This gives a chance for first-
441 // time static initialization to not interfere in the timings.
442 uint32_t const basic_result = basic_crc32( ran_data, sizeof(ran_data) );
443 uint32_t const optimal_result = optimal_crc32( ran_data, sizeof(ran_data) );
444 uint32_t const quick_result = quick_crc32( ran_data, sizeof(ran_data) );
445
446 BOOST_TEST_EQ( basic_result, optimal_result );
447 BOOST_TEST_EQ( optimal_result, quick_result );
448 BOOST_TEST_EQ( quick_result, basic_result );
449
450 // Run trials
451 double const basic_rate = time_trial( "Boost-Basic", basic_crc32,
452 basic_result, ran_data, sizeof(ran_data) );
453 double const optimal_rate = time_trial( "Boost-Optimal", optimal_crc32,
454 optimal_result, ran_data, sizeof(ran_data) );
455 double const quick_rate = time_trial( "Reference", quick_crc32,
456 quick_result, ran_data, sizeof(ran_data) );
457
458 // Report results
459 cout << "\tThe optimal Boost version has " << optimal_rate / quick_rate *
460 100.0 << "% the speed of the reference version.\n";
461 cout << "\tThe basic Boost version has " << basic_rate / quick_rate * 100.0
462 << "% the speed of the reference version.\n";
463 cout << "\tThe basic Boost version has " << basic_rate / optimal_rate *
464 100.0 << "% the speed of the optimal Boost version."
465 << endl;
466 }
467
468
469 // Reformat an integer to the big-endian storage format
470 boost::uint32_t
471 native_to_big
472 (
473 boost::uint32_t x
474 )
475 {
476 boost::uint32_t temp;
477 unsigned char * tp = reinterpret_cast<unsigned char *>( &temp );
478
479 for ( std::size_t i = sizeof(x) ; i > 0 ; --i )
480 {
481 tp[ i - 1 ] = static_cast<unsigned char>( x );
482 x >>= CHAR_BIT;
483 }
484
485 return temp;
486 }
487
488 // Restore an integer from the big-endian storage format
489 boost::uint32_t
490 big_to_native
491 (
492 boost::uint32_t x
493 )
494 {
495 boost::uint32_t temp = 0;
496 unsigned char * xp = reinterpret_cast<unsigned char *>( &x );
497
498 for ( std::size_t i = 0 ; i < sizeof(x) ; ++i )
499 {
500 temp <<= CHAR_BIT;
501 temp |= xp[ i ];
502 }
503
504 return temp;
505 }
506
507 // Run tests on using CRCs on augmented messages
508 void
509 augmented_tests
510 (
511 )
512 {
513 #define PRIVATE_ACRC_FUNC boost::augmented_crc<32, 0x04C11DB7>
514
515 using std::size_t;
516 PRIVATE_DECLARE_BOOST( uint32_t );
517
518 std::cout << "Doing CRC-augmented message tests." << std::endl;
519
520 // Create a random block of data, with space for a CRC.
521 uint32_t ran_data[ 257 ];
522 size_t const ran_length = sizeof(ran_data) / sizeof(ran_data[0]);
523 size_t const data_length = ran_length - 1;
524
525 std::generate_n( ran_data, data_length, boost::minstd_rand() );
526
527 // When creating a CRC for an augmented message, use
528 // zeros in the appended CRC spot for the first run.
529 uint32_t & ran_crc = ran_data[ data_length ];
530
531 ran_crc = 0;
532
533 // Compute the CRC with augmented-CRC computing function
534 typedef boost::uint_t<32>::fast return_type;
535
536 ran_crc = PRIVATE_ACRC_FUNC( ran_data, sizeof(ran_data) );
537
538 // With the appended CRC set, running the checksum again should get zero.
539 // NOTE: CRC algorithm assumes numbers are in big-endian format
540 ran_crc = native_to_big( ran_crc );
541
542 uint32_t ran_crc_check = PRIVATE_ACRC_FUNC( ran_data, sizeof(ran_data) );
543
544 BOOST_TEST_EQ( 0, ran_crc_check );
545
546 // Compare that result with other CRC computing functions
547 // and classes, which don't accept augmented messages.
548 typedef boost::crc_optimal<32, 0x04C11DB7> fast_crc_type;
549 typedef boost::crc_basic<32> slow_crc_type;
550
551 fast_crc_type fast_tester;
552 slow_crc_type slow_tester( 0x04C11DB7 );
553 size_t const data_size = data_length * sizeof(ran_data[0]);
554 uint32_t const func_tester = boost::crc<32, 0x04C11DB7, 0, 0, false,
555 false>( ran_data, data_size );
556
557 fast_tester.process_bytes( ran_data, data_size );
558 slow_tester.process_bytes( ran_data, data_size );
559 BOOST_TEST_EQ( fast_tester.checksum(), slow_tester.checksum() );
560 ran_crc = big_to_native( ran_crc );
561 BOOST_TEST_EQ( fast_tester.checksum(), ran_crc );
562 BOOST_TEST_EQ( func_tester, ran_crc );
563
564 // Do a single-bit error test
565 ran_crc = native_to_big( ran_crc );
566 ran_data[ ran_data[0] % ran_length ] ^= ( 1 << (ran_data[1] % 32) );
567 ran_crc_check = PRIVATE_ACRC_FUNC( ran_data, sizeof(ran_data) );
568 BOOST_TEST_NE( 0, ran_crc_check );
569
570 // Run a version of these tests with a nonzero initial remainder.
571 uint32_t const init_rem = ran_data[ ran_data[2] % ran_length ];
572
573 ran_crc = 0;
574 ran_crc = PRIVATE_ACRC_FUNC( ran_data, sizeof(ran_data), init_rem );
575
576 // Have some fun by processing data in two steps.
577 size_t const mid_index = ran_length / 2;
578
579 ran_crc = native_to_big( ran_crc );
580 ran_crc_check = PRIVATE_ACRC_FUNC( ran_data, mid_index
581 * sizeof(ran_data[0]), init_rem );
582 ran_crc_check = PRIVATE_ACRC_FUNC( &ran_data[mid_index], sizeof(ran_data)
583 - mid_index * sizeof(ran_data[0]), ran_crc_check );
584 BOOST_TEST_EQ( 0, ran_crc_check );
585
586 // This substep translates an augmented-CRC initial
587 // remainder to an unaugmented-CRC initial remainder.
588 uint32_t const zero = 0;
589 uint32_t const new_init_rem = PRIVATE_ACRC_FUNC( &zero, sizeof(zero),
590 init_rem );
591 slow_crc_type slow_tester2( 0x04C11DB7, new_init_rem );
592
593 slow_tester2.process_bytes( ran_data, data_size );
594 ran_crc = big_to_native( ran_crc );
595 BOOST_TEST_EQ( slow_tester2.checksum(), ran_crc );
596
597 // Redo single-bit error test
598 ran_data[ ran_data[3] % ran_length ] ^= ( 1 << (ran_data[4] % 32) );
599 ran_crc_check = PRIVATE_ACRC_FUNC( ran_data, sizeof(ran_data), init_rem );
600 BOOST_TEST_NE( 0, ran_crc_check );
601
602 #undef PRIVATE_ACRC_FUNC
603 }
604
605
606 // Run tests on CRCs below a byte in size (here, 3 bits)
607 void
608 small_crc_test1
609 (
610 )
611 {
612 std::cout << "Doing short-CRC (3-bit augmented) message tests."
613 << std::endl;
614
615 // The CRC standard is a SDH/SONET Low Order LCAS control word with CRC-3
616 // taken from ITU-T G.707 (12/03) XIII.2.
617
618 // Four samples, each four bytes; should all have a CRC of zero
619 unsigned char const samples[4][4]
620 = {
621 { 0x3A, 0xC4, 0x08, 0x06 },
622 { 0x42, 0xC5, 0x0A, 0x41 },
623 { 0x4A, 0xC5, 0x08, 0x22 },
624 { 0x52, 0xC4, 0x08, 0x05 }
625 };
626
627 // Basic computer
628 boost::crc_basic<3> tester1( 0x03 );
629
630 tester1.process_bytes( samples[0], 4 );
631 BOOST_TEST_EQ( tester1.checksum(), 0 );
632
633 tester1.reset();
634 tester1.process_bytes( samples[1], 4 );
635 BOOST_TEST_EQ( tester1.checksum(), 0 );
636
637 tester1.reset();
638 tester1.process_bytes( samples[2], 4 );
639 BOOST_TEST_EQ( tester1.checksum(), 0 );
640
641 tester1.reset();
642 tester1.process_bytes( samples[3], 4 );
643 BOOST_TEST_EQ( tester1.checksum(), 0 );
644
645 // Optimal computer
646 #define PRIVATE_CRC_FUNC boost::crc<3, 0x03, 0, 0, false, false>
647 #define PRIVATE_ACRC_FUNC boost::augmented_crc<3, 0x03>
648
649 BOOST_TEST_EQ( 0, PRIVATE_CRC_FUNC(samples[0], 4) );
650 BOOST_TEST_EQ( 0, PRIVATE_CRC_FUNC(samples[1], 4) );
651 BOOST_TEST_EQ( 0, PRIVATE_CRC_FUNC(samples[2], 4) );
652 BOOST_TEST_EQ( 0, PRIVATE_CRC_FUNC(samples[3], 4) );
653
654 // maybe the fix to CRC functions needs to be applied to augmented CRCs?
655
656 #undef PRIVATE_ACRC_FUNC
657 #undef PRIVATE_CRC_FUNC
658 }
659
660 // Run tests on CRCs below a byte in size (here, 7 bits)
661 void
662 small_crc_test2
663 (
664 )
665 {
666 std::cout << "Doing short-CRC (7-bit augmented) message tests."
667 << std::endl;
668
669 // The CRC standard is a SDH/SONET J0/J1/J2/N1/N2/TR TTI (trace message)
670 // with CRC-7, o.a. ITU-T G.707 Annex B, G.832 Annex A.
671
672 // Two samples, each sixteen bytes
673 // Sample 1 is '\x80' + ASCII("123456789ABCDEF")
674 // Sample 2 is '\x80' + ASCII("TTI UNAVAILABLE")
675 unsigned char const samples[2][16]
676 = {
677 { 0x80, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41,
678 0x42, 0x43, 0x44, 0x45, 0x46 },
679 { 0x80, 0x54, 0x54, 0x49, 0x20, 0x55, 0x4E, 0x41, 0x56, 0x41, 0x49,
680 0x4C, 0x41, 0x42, 0x4C, 0x45 }
681 };
682 unsigned const results[2] = { 0x62, 0x23 };
683
684 // Basic computer
685 boost::crc_basic<7> tester1( 0x09 );
686
687 tester1.process_bytes( samples[0], 16 );
688 BOOST_TEST_EQ( tester1.checksum(), results[0] );
689
690 tester1.reset();
691 tester1.process_bytes( samples[1], 16 );
692 BOOST_TEST_EQ( tester1.checksum(), results[1] );
693
694 // Optimal computer
695 #define PRIVATE_CRC_FUNC boost::crc<7, 0x09, 0, 0, false, false>
696 #define PRIVATE_ACRC_FUNC boost::augmented_crc<7, 0x09>
697
698 BOOST_TEST_EQ( results[0], PRIVATE_CRC_FUNC(samples[0], 16) );
699 BOOST_TEST_EQ( results[1], PRIVATE_CRC_FUNC(samples[1], 16) );
700
701 // maybe the fix to CRC functions needs to be applied to augmented CRCs?
702
703 #undef PRIVATE_ACRC_FUNC
704 #undef PRIVATE_CRC_FUNC
705 }
706
707
708 #ifndef BOOST_MSVC
709 // Explicit template instantiations
710 // (needed to fix a link error in Metrowerks CodeWarrior Pro 5.3)
711 template class crc_tester<16, 0x1021, 0xFFFF, 0, false, false>;
712 template class crc_tester<16, 0x8005, 0, 0, true, true>;
713 template class crc_tester<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true>;
714 #endif
715
716 // Main testing function
717 int main()
718 {
719 using std::cout;
720 using std::endl;
721
722 // Run simulations on some CRC types
723 typedef crc_tester<16, 0x1021, 0xFFFF, 0, false, false> crc_ccitt_tester;
724 typedef crc_tester<16, 0x8005, 0, 0, true, true> crc_16_tester;
725 typedef crc_tester<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true>
726 crc_32_tester;
727
728 crc_ccitt_tester::master_test( "CRC-CCITT", std_crc_ccitt_result );
729 crc_16_tester::master_test( "CRC-16", std_crc_16_result );
730 crc_32_tester::master_test( "CRC-32", std_crc_32_result );
731
732 // Run a timing comparison test
733 timing_test();
734
735 // Test using augmented messages
736 augmented_tests();
737
738 // Test with CRC types smaller than a byte
739 small_crc_test1();
740 small_crc_test2();
741
742 // Try a CRC based on the (x + 1) polynominal, which is a factor in
743 // many real-life polynominals and doesn't fit evenly in a byte.
744 cout << "Doing one-bit polynominal CRC test." << endl;
745 boost::crc_basic<1> crc_1( 1 );
746 crc_1.process_bytes( std_data, std_data_len );
747 BOOST_TEST_EQ( crc_1.checksum(), 1 );
748
749 // Test the function object interface
750 cout << "Doing functional object interface test." << endl;
751 boost::crc_optimal<16, 0x8005, 0, 0, true, true> crc_16;
752 crc_16 = std::for_each( std_data, std_data + std_data_len, crc_16 );
753 BOOST_TEST_EQ( crc_16(), std_crc_16_result );
754
755 return boost::report_errors();
756 }