Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/crc/crc_test.cpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 24.4 KB
RevLine 
[29]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/test/minimal.hpp>                // for main, etc.
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
50template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
51           CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
52class crc_tester
53{
54public:
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
64private:
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
76unsigned char const  std_data[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
77                      0x38, 0x39 };
78std::size_t const    std_data_len = sizeof( std_data ) / sizeof( std_data[0] );
79
80boost::uint16_t const  std_crc_ccitt_result = 0x29B1;
81boost::uint16_t const  std_crc_16_result = 0xBB3D;
82boost::uint32_t const  std_crc_32_result = 0xCBF43926;
83
84// Function prototypes
85void             timing_test();
86boost::uint32_t  basic_crc32( void const *buffer, std::size_t byte_count );
87boost::uint32_t  optimal_crc32( void const *buffer, std::size_t byte_count );
88boost::uint32_t  quick_crc32( void const *buffer, std::size_t byte_count );
89boost::uint32_t  quick_reflect( boost::uint32_t value, std::size_t bits );
90double           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
94void             augmented_tests();
95boost::uint32_t  native_to_big( boost::uint32_t x );
96boost::uint32_t  big_to_native( boost::uint32_t x );
97
98void  small_crc_test1();
99void  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
106template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
107           CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
108void
109PRIVATE_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_CHECK( fast_crc.checksum() == expected );
124    BOOST_CHECK( slow_crc.checksum() == expected );
125    BOOST_CHECK( func_result == expected );
126}
127
128// Run a test in two runs, and check all the inspectors
129template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
130           CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
131void
132PRIVATE_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_CHECK( 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_CHECK( 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_CHECK( fast_crc2.checksum() == slow_crc2.checksum() );
169    BOOST_CHECK( fast_crc2.checksum() == expected );
170    BOOST_CHECK( slow_crc2.checksum() == expected );
171}
172
173// Run a test to see if a single-bit error is detected
174template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
175           CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
176void
177PRIVATE_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::mask_uint_t<Bits>::sig_bits_fast) )
189    {
190        BOOST_FAIL( "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_CHECK( 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_CHECK( fast_tester.checksum() == slow_tester.checksum() );
219    BOOST_CHECK( fast_tester.checksum() == fast_checksum );
220    BOOST_CHECK( 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_CHECK( fast_tester.checksum() == slow_tester.checksum() );
232    BOOST_CHECK( fast_tester.checksum() != fast_checksum );
233    BOOST_CHECK( slow_tester.checksum() != slow_checksum );
234}
235
236// Run the other CRC object tests
237template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
238           CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
239void
240PRIVATE_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
257boost::uint32_t
258basic_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
273inline
274boost::uint32_t
275optimal_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"
289boost::uint32_t
290quick_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
309boost::uint32_t
310quick_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
372double
373time_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
423void
424timing_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_CHECK( basic_result == optimal_result );
447    BOOST_CHECK( optimal_result == quick_result );
448    BOOST_CHECK( 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 is " << (quick_rate - optimal_rate)
460     / quick_rate * 100.0 << "% slower than the reference version.\n";
461    cout << "\tThe basic Boost version is " << (quick_rate - basic_rate)
462     / quick_rate * 100.0 << "% slower than the reference version.\n";
463    cout << "\tThe basic Boost version is " << (optimal_rate - basic_rate)
464     / optimal_rate * 100.0 << "% slower than the optimal Boost version."
465     << endl;
466}
467
468
469// Reformat an integer to the big-endian storage format
470boost::uint32_t
471native_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
489boost::uint32_t
490big_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
508void
509augmented_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_CHECK( 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_CHECK( fast_tester.checksum() == slow_tester.checksum() );
560    ran_crc = big_to_native( ran_crc );
561    BOOST_CHECK( fast_tester.checksum() == ran_crc );
562    BOOST_CHECK( 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_CHECK( 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_CHECK( 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_CHECK( 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_CHECK( 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)
607void
608small_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_CHECK( tester1.checksum() == 0 );
632
633    tester1.reset();
634    tester1.process_bytes( samples[1], 4 );
635    BOOST_CHECK( tester1.checksum() == 0 );
636
637    tester1.reset();
638    tester1.process_bytes( samples[2], 4 );
639    BOOST_CHECK( tester1.checksum() == 0 );
640
641    tester1.reset();
642    tester1.process_bytes( samples[3], 4 );
643    BOOST_CHECK( 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_CHECK( 0 == PRIVATE_CRC_FUNC(samples[0], 4) );
650    BOOST_CHECK( 0 == PRIVATE_CRC_FUNC(samples[1], 4) );
651    BOOST_CHECK( 0 == PRIVATE_CRC_FUNC(samples[2], 4) );
652    BOOST_CHECK( 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)
661void
662small_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_CHECK( tester1.checksum() == results[0] );
689
690    tester1.reset();
691    tester1.process_bytes( samples[1], 16 );
692    BOOST_CHECK( 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_CHECK( results[0] == PRIVATE_CRC_FUNC(samples[0], 16) );
699    BOOST_CHECK( 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)
711template class crc_tester<16, 0x1021, 0xFFFF, 0, false, false>;
712template class crc_tester<16, 0x8005, 0, 0, true, true>;
713template class crc_tester<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true>;
714#endif
715
716// Main testing function
717int
718test_main
719(
720    int         ,   // "argc" is unused
721    char *      []  // "argv" is unused
722)
723{
724    using std::cout;
725    using std::endl;
726
727    // Run simulations on some CRC types
728    typedef crc_tester<16, 0x1021, 0xFFFF, 0, false, false>  crc_ccitt_tester;
729    typedef crc_tester<16, 0x8005, 0, 0, true, true>         crc_16_tester;
730    typedef crc_tester<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true>
731      crc_32_tester;
732
733    crc_ccitt_tester::master_test( "CRC-CCITT", std_crc_ccitt_result );
734    crc_16_tester::master_test( "CRC-16", std_crc_16_result );
735    crc_32_tester::master_test( "CRC-32", std_crc_32_result );
736
737    // Run a timing comparison test
738    timing_test();
739
740    // Test using augmented messages
741    augmented_tests();
742
743    // Test with CRC types smaller than a byte
744    small_crc_test1();
745    small_crc_test2();
746
747    // Try a CRC based on the (x + 1) polynominal, which is a factor in
748    // many real-life polynominals and doesn't fit evenly in a byte.
749    cout << "Doing one-bit polynominal CRC test." << endl;
750    boost::crc_basic<1>  crc_1( 1 );
751    crc_1.process_bytes( std_data, std_data_len );
752    BOOST_CHECK( crc_1.checksum() == 1 );
753
754    // Test the function object interface
755    cout << "Doing functional object interface test." << endl;
756    boost::crc_optimal<16, 0x8005, 0, 0, true, true>  crc_16;
757    crc_16 = std::for_each( std_data, std_data + std_data_len, crc_16 );
758    BOOST_CHECK( crc_16() == std_crc_16_result );
759
760    return boost::exit_success;
761}
Note: See TracBrowser for help on using the repository browser.