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

source code of boost/libs/crc/test/crc_test.cpp