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
compute_test(typename PRIVATE_TESTER_NAME::value_type expected)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
interrupt_test(typename PRIVATE_TESTER_NAME::value_type expected)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
error_test()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
master_test(char const * test_name,typename PRIVATE_TESTER_NAME::value_type expected)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
basic_crc32(void const * buffer,std::size_t byte_count)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
optimal_crc32(void const * buffer,std::size_t byte_count)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
quick_reflect(boost::uint32_t value,std::size_t bits)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
quick_crc32(void const * buffer,std::size_t byte_count)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
time_trial(char const * name,boost::uint32_t (* crc_func)(void const *,std::size_t),boost::uint32_t expected,void const * data,std::size_t length)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
timing_test()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
native_to_big(boost::uint32_t x)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
big_to_native(boost::uint32_t x)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
augmented_tests()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
small_crc_test1()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
small_crc_test2()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
main()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 }
757