1 //  Boost CRC unit test program file  ----------------------------------------//
2 
3 //  Copyright 2011 Daryle Walker.
4 //  Distributed under the Boost Software License, Version 1.0.  (See the
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 #include <boost/core/lightweight_test.hpp>
11 #include <boost/crc.hpp>   // for boost::crc_basic,crc_optimal,augmented_crc,crc
12 
13 #include <boost/cstdint.hpp>         // for boost::uint16_t, uint32_t, uintmax_t
14 #include <boost/predef/other/endian.h>
15 #include <boost/integer.hpp>                                // for boost::uint_t
16 #include <boost/typeof/typeof.hpp>                             // for BOOST_AUTO
17 #include <boost/random/linear_congruential.hpp>        // for boost::minstd_rand
18 
19 #include <algorithm>  // for std::generate_n, for_each
20 #include <climits>    // for CHAR_BIT
21 #include <cstddef>    // for std::size_t
22 
23 // Sanity check
24 #if CHAR_BIT != 8
25 #error The expected results assume octet-sized bytes.
26 #endif
27 
28 // Control tests at compile-time
29 #ifndef CONTROL_SUB_BYTE_MISMATCHED_REFLECTION_TEST
30 #define CONTROL_SUB_BYTE_MISMATCHED_REFLECTION_TEST  1
31 #endif
32 
33 
34 // Common definitions  -------------------------------------------------------//
35 
36 namespace {
37 
38 // Many CRC configurations use the string "123456789" in ASCII as test data.
39 unsigned char const  std_data[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
40                       0x38, 0x39 };
41 std::size_t const    std_data_len = sizeof( std_data ) / sizeof( std_data[0] );
42 
43 // Checksums of the standard test data for common configurations
44 boost::uint16_t const  std_crc_ccitt_false_result = 0x29B1u;
45 boost::uint16_t const  std_crc_ccitt_true_result = 0x2189u;
46 boost::uint16_t const  std_crc_xmodem_result = 0x31C3u;
47 boost::uint16_t const  std_crc_16_result = 0xBB3Du;
48 boost::uint32_t const  std_crc_32_result = 0xCBF43926ul;
49 
50 // Conversion functions between native- and big-endian representations
51 #if BOOST_ENDIAN_BIG_BYTE
native_to_big(boost::uint32_t x)52 boost::uint32_t  native_to_big( boost::uint32_t x )  { return x; }
big_to_native(boost::uint32_t x)53 boost::uint32_t  big_to_native( boost::uint32_t x )  { return x; }
54 #else
55 union endian_convert
56 {
57     boost::uint32_t  w;
58     unsigned char    p[ 4 ];
59 };
60 
native_to_big(boost::uint32_t x)61 boost::uint32_t  native_to_big( boost::uint32_t x )
62 {
63     endian_convert  e;
64 
65     e.p[ 0 ] = x >> 24;
66     e.p[ 1 ] = x >> 16;
67     e.p[ 2 ] = x >> 8;
68     e.p[ 3 ] = x;
69     return e.w;
70 }
71 
big_to_native(boost::uint32_t x)72 boost::uint32_t  big_to_native( boost::uint32_t x )
73 {
74     endian_convert  e;
75 
76     e.w = x;
77     x = e.p[ 0 ];
78     x <<= 8;
79     x |= e.p[ 1 ];
80     x <<= 8;
81     x |= e.p[ 2 ];
82     x <<= 8;
83     x |= e.p[ 3 ];
84     return x;
85 }
86 #endif
87 
88 // Define CRC parameters inside traits classes.  Probably will use this in a
89 // future version of the CRC libray!
90 template < std::size_t Bits >
91 class my_crc_rt_traits
92 {
93 public:
94     typedef boost::integral_constant<std::size_t, Bits>            register_length_c;
95     typedef typename boost::uint_t<Bits>::fast  register_type;
96     typedef boost::crc_basic<Bits>              computer_type;
97 
98     register_type  divisor_polynominal;
99     register_type  initial_remainder;
100     bool           reflect_input_byte;
101     bool           reflect_output_remainder;
102     register_type  final_xor_mask;
103 
make_crc_basic() const104     computer_type  make_crc_basic() const
105     { return computer_type(divisor_polynominal, initial_remainder,
106      final_xor_mask, reflect_input_byte, reflect_output_remainder); }
107 };
108 
109 template < std::size_t Bits, boost::uintmax_t DivisorPolynominal,
110            boost::uintmax_t InitialRemainder, bool ReflectInputBytes,
111            bool ReflectOutputRemainder, boost::uintmax_t FinalXorMask >
112 class my_crc_ct_traits
113 {
114 public:
115     typedef my_crc_rt_traits<Bits>                           rt_adaptor_type;
116     typedef typename rt_adaptor_type::register_type            register_type;
117     typedef boost::crc_optimal<Bits, DivisorPolynominal, InitialRemainder,
118      FinalXorMask, ReflectInputBytes, ReflectOutputRemainder>  computer_type;
119 
120     typedef boost::integral_constant<std::size_t, Bits>  register_length_c;
121     typedef boost::integral_constant<register_type, DivisorPolynominal>
122       divisor_polynominal_c;
123     typedef boost::integral_constant<register_type, InitialRemainder>
124       initial_remainder_c;
125     typedef boost::integral_constant<bool, ReflectInputBytes>  reflect_input_byte_c;
126     typedef boost::integral_constant<bool, ReflectOutputRemainder>
127       reflect_output_remainder_c;
128     typedef boost::integral_constant<register_type, FinalXorMask>
129       final_xor_mask_c;
130 
operator rt_adaptor_type() const131     operator rt_adaptor_type() const
132     {
133         rt_adaptor_type const  result = { divisor_polynominal_c::value,
134          initial_remainder_c::value, reflect_input_byte_c::value,
135          reflect_output_remainder_c::value, final_xor_mask_c::value };
136 
137         return result;
138     }
139 
make_crc_optimal()140     static  computer_type  make_crc_optimal()
141     { return boost::crc_optimal<register_length_c::value,
142      divisor_polynominal_c::value, initial_remainder_c::value,
143      final_xor_mask_c::value, reflect_input_byte_c::value,
144      reflect_output_remainder_c::value>(); }
145 };
146 
147 template < std::size_t Bits, boost::uintmax_t DivisorPolynominal,
148            boost::uintmax_t InitialRemainder, bool ReflectInputBytes,
149            bool ReflectOutputRemainder, boost::uintmax_t FinalXorMask,
150            boost::uintmax_t StandardTestDataResult >
151 class my_crc_test_traits
152 {
153 public:
154     typedef my_crc_ct_traits<Bits, DivisorPolynominal, InitialRemainder,
155      ReflectInputBytes, ReflectOutputRemainder, FinalXorMask>  ct_traits_type;
156     typedef my_crc_rt_traits<Bits>  rt_traits_type;
157 
158     typedef typename rt_traits_type::register_type  register_type;
159 
160     typedef boost::integral_constant<std::size_t, Bits>  register_length_c;
161     typedef boost::integral_constant<register_type, DivisorPolynominal>
162       divisor_polynominal_c;
163     typedef boost::integral_constant<register_type, InitialRemainder>
164       initial_remainder_c;
165     typedef boost::integral_constant<bool, ReflectInputBytes>  reflect_input_byte_c;
166     typedef boost::integral_constant<bool, ReflectOutputRemainder>
167       reflect_output_remainder_c;
168     typedef boost::integral_constant<register_type, FinalXorMask>
169       final_xor_mask_c;
170     typedef boost::integral_constant<register_type, StandardTestDataResult>
171       standard_test_data_CRC_c;
172 
173     typedef typename ct_traits_type::computer_type  computer_ct_type;
174     typedef typename rt_traits_type::computer_type  computer_rt_type;
175 
make_crc_optimal()176     static  computer_ct_type  make_crc_optimal()
177     { return ct_traits_type::make_crc_optimal(); }
make_crc_basic()178     static  computer_rt_type  make_crc_basic()
179     { return ct_traits_type().operator rt_traits_type().make_crc_basic(); }
180 };
181 
182 // Now make some example CRC profiles
183 typedef my_crc_test_traits<16u, 0x8005u, 0u, true, true, 0u, std_crc_16_result>
184   my_crc_16_traits;
185 typedef my_crc_test_traits<16u, 0x1021u, 0xFFFFu, false, false, 0u,
186  std_crc_ccitt_false_result>  my_crc_ccitt_false_traits;
187 typedef my_crc_test_traits<16u, 0x1021u, 0u, true, true, 0u,
188  std_crc_ccitt_true_result>  my_crc_ccitt_true_traits;
189 typedef my_crc_test_traits<16u, 0x1021u, 0u, false, false, 0u,
190  std_crc_xmodem_result>  my_crc_xmodem_traits;
191 typedef my_crc_test_traits<32u, 0x04C11DB7ul, 0xFFFFFFFFul, true, true,
192  0xFFFFFFFFul, std_crc_32_result>  my_crc_32_traits;
193 
194 template<class Test>
run_crc_test_policies()195 void run_crc_test_policies()
196 {
197     Test()(my_crc_16_traits());
198     Test()(my_crc_ccitt_false_traits());
199     Test()(my_crc_ccitt_true_traits());
200     Test()(my_crc_xmodem_traits());
201     Test()(my_crc_32_traits());
202 }
203 
204 // Need to test when ReflectInputBytes and ReflectOutputRemainder differ
205 // (Grabbed from table at <http://regregex.bbcmicro.net/crc-catalogue.htm>.)
206 typedef my_crc_test_traits<6u, 0x19u, 0u, true, false, 0u, 0x19u>
207   my_crc_6_darc_traits;
208 typedef my_crc_test_traits<12u, 0x80Fu, 0u, false, true, 0u, 0xDAFu>
209   my_crc_12_3gpp_traits;
210 
211 template<class Test>
run_crc_extended_test_policies()212 void run_crc_extended_test_policies()
213 {
214     Test()(my_crc_16_traits());
215     Test()(my_crc_ccitt_false_traits());
216     Test()(my_crc_ccitt_true_traits());
217     Test()(my_crc_xmodem_traits());
218     Test()(my_crc_32_traits());
219 #if CONTROL_SUB_BYTE_MISMATCHED_REFLECTION_TEST
220     Test()(my_crc_6_darc_traits());
221 #endif
222     Test()(my_crc_12_3gpp_traits());
223 }
224 
225 // Bit mask constants
226 template < std::size_t BitIndex >
227 struct high_bit_mask_c
228     : boost::detail::high_bit_mask_c<BitIndex>
229 {};
230 template < std::size_t BitCount >
231 struct low_bits_mask_c
232     : boost::detail::low_bits_mask_c<BitCount>
233 {};
234 
235 }  // anonymous namespace
236 
237 
238 // Unit tests  ---------------------------------------------------------------//
239 
240 struct computation_comparison_test {
241 template<class CRCPolicy>
operator ()computation_comparison_test242 void operator()(CRCPolicy)
243 {
244     BOOST_AUTO( crc_f, CRCPolicy::make_crc_optimal() );
245     BOOST_AUTO( crc_s, CRCPolicy::make_crc_basic() );
246     typename CRCPolicy::register_type const  func_result
247      = boost::crc<CRCPolicy::register_length_c::value,
248         CRCPolicy::divisor_polynominal_c::value,
249         CRCPolicy::initial_remainder_c::value,
250         CRCPolicy::final_xor_mask_c::value,
251         CRCPolicy::reflect_input_byte_c::value,
252         CRCPolicy::reflect_output_remainder_c::value>( std_data, std_data_len );
253 
254     crc_f.process_bytes( std_data, std_data_len );
255     crc_s.process_bytes( std_data, std_data_len );
256 
257     BOOST_TEST_EQ( crc_f.checksum(),
258      CRCPolicy::standard_test_data_CRC_c::value );
259     BOOST_TEST_EQ( crc_s.checksum(),
260      CRCPolicy::standard_test_data_CRC_c::value );
261     BOOST_TEST_EQ( CRCPolicy::standard_test_data_CRC_c::value,
262      func_result );
263 }
264 };
265 
266 struct accessor_and_split_run_test {
267 template<class CRCPolicy>
operator ()accessor_and_split_run_test268 void operator()(CRCPolicy)
269 {
270     typedef typename CRCPolicy::computer_ct_type  optimal_crc_type;
271     typedef typename CRCPolicy::computer_rt_type    basic_crc_type;
272 
273     // Test accessors
274     optimal_crc_type  faster_crc1;
275     basic_crc_type    slower_crc1( faster_crc1.get_truncated_polynominal(),
276      faster_crc1.get_initial_remainder(), faster_crc1.get_final_xor_value(),
277      faster_crc1.get_reflect_input(), faster_crc1.get_reflect_remainder() );
278 
279     BOOST_TEST_EQ( faster_crc1.get_interim_remainder(),
280      slower_crc1.get_initial_remainder() );
281 
282     // Process the first half of the standard data
283     std::size_t const  mid_way = std_data_len / 2u;
284 
285     faster_crc1.process_bytes( std_data, mid_way );
286     slower_crc1.process_bytes( std_data, mid_way );
287 
288     BOOST_TEST_EQ( faster_crc1.checksum(), slower_crc1.checksum() );
289 
290     // Process the second half of the standard data, testing more accessors
291     unsigned char const * const  std_data_end = std_data + std_data_len;
292     boost::crc_optimal<optimal_crc_type::bit_count,
293      optimal_crc_type::truncated_polynominal,
294      optimal_crc_type::initial_remainder, optimal_crc_type::final_xor_value,
295      optimal_crc_type::reflect_input, optimal_crc_type::reflect_remainder>
296       faster_crc2( faster_crc1.get_interim_remainder() );
297     boost::crc_basic<basic_crc_type::bit_count>  slower_crc2(
298      slower_crc1.get_truncated_polynominal(),
299      slower_crc1.get_interim_remainder(), slower_crc1.get_final_xor_value(),
300      slower_crc1.get_reflect_input(), slower_crc1.get_reflect_remainder() );
301 
302     faster_crc2.process_block( std_data + mid_way, std_data_end );
303     slower_crc2.process_block( std_data + mid_way, std_data_end );
304 
305     BOOST_TEST_EQ( slower_crc2.checksum(), faster_crc2.checksum() );
306     BOOST_TEST_EQ( faster_crc2.checksum(),
307      CRCPolicy::standard_test_data_CRC_c::value );
308     BOOST_TEST_EQ( CRCPolicy::standard_test_data_CRC_c::value,
309      slower_crc2.checksum() );
310 }
311 };
312 
313 struct reset_and_single_bit_error_test {
314 template<class CRCPolicy>
operator ()reset_and_single_bit_error_test315 void operator()(CRCPolicy)
316 {
317     // A single-bit error in a CRC can be guaranteed to be detected if the
318     // modulo-2 polynomial divisor has at least two non-zero coefficients.  The
319     // implicit highest coefficient is always one, so that leaves an explicit
320     // coefficient, i.e. at least one of the polynomial's bits is set.
321     BOOST_TEST( CRCPolicy::divisor_polynominal_c::value &
322      low_bits_mask_c<CRCPolicy::register_length_c::value>::value );
323 
324     // Create a random block of data
325     boost::uint32_t    ran_data[ 256 ];
326     std::size_t const  ran_length = sizeof(ran_data) / sizeof(ran_data[0]);
327 
328     std::generate_n( ran_data, ran_length, boost::minstd_rand() );
329 
330     // Create computers and compute the checksum of the data
331     BOOST_AUTO( optimal_tester, CRCPolicy::make_crc_optimal() );
332     BOOST_AUTO( basic_tester, CRCPolicy::make_crc_basic() );
333 
334     optimal_tester.process_bytes( ran_data, sizeof(ran_data) );
335     basic_tester.process_bytes( ran_data, sizeof(ran_data) );
336 
337     BOOST_AUTO( const optimal_checksum, optimal_tester.checksum() );
338     BOOST_AUTO( const basic_checksum, basic_tester.checksum() );
339 
340     BOOST_TEST_EQ( optimal_checksum, basic_checksum );
341 
342     // Do the checksum again, while testing the capability to reset the current
343     // remainder (to either a default or a given value)
344     optimal_tester.reset();
345     basic_tester.reset( CRCPolicy::initial_remainder_c::value );
346 
347     optimal_tester.process_bytes( ran_data, sizeof(ran_data) );
348     basic_tester.process_bytes( ran_data, sizeof(ran_data) );
349 
350     BOOST_TEST_EQ( optimal_tester.checksum(), basic_tester.checksum() );
351     BOOST_TEST_EQ( optimal_tester.checksum(), optimal_checksum );
352     BOOST_TEST_EQ( basic_tester.checksum(), basic_checksum );
353 
354     // Introduce a single-bit error
355     ran_data[ ran_data[0] % ran_length ] ^= ( 1u << (ran_data[ 1 ] % 32u) );
356 
357     // Compute the checksum of the errorenous data, while continuing to test
358     // the remainder-resetting methods
359     optimal_tester.reset( CRCPolicy::initial_remainder_c::value );
360     basic_tester.reset();
361 
362     optimal_tester.process_bytes( ran_data, sizeof(ran_data) );
363     basic_tester.process_bytes( ran_data, sizeof(ran_data) );
364 
365     BOOST_TEST_EQ( basic_tester.checksum(), optimal_tester.checksum() );
366     BOOST_TEST_NE( optimal_checksum, optimal_tester.checksum() );
367     BOOST_TEST_NE( basic_checksum, basic_tester.checksum() );
368 }
369 };
370 
augmented_crc_test()371 void augmented_crc_test()
372 {
373     using std::size_t;
374     using boost::uint32_t;
375     using boost::augmented_crc;
376 
377     // Common CRC parameters, all others are zero/false
378     static  size_t const    bits = 32u;
379     static  uint32_t const  poly = 0x04C11DB7ul;
380 
381     // Create a random block of data, with space at the end for a CRC
382     static  size_t const  data_length = 256u;
383     static  size_t const  run_length = data_length + 1u;
384 
385     uint32_t      run_data[ run_length ];
386     uint32_t &    run_crc = run_data[ data_length ];
387     size_t const  data_size = sizeof( run_data ) - sizeof( run_crc );
388 
389     std::generate_n( run_data, data_length, boost::minstd_rand() );
390     run_crc = 0u;
391 
392     // The augmented-CRC routine needs to push an appropriate number of zero
393     // bits (the register size) through before the checksum can be extracted.
394     // The other CRC methods, which are un-augmented, don't need to do this.
395     uint32_t const  checksum = boost::crc<bits, poly, 0u, 0u, false, false>(
396      run_data, data_size );
397 
398     BOOST_TEST_EQ( (augmented_crc<bits, poly>)(run_data, sizeof( run_data
399      )), checksum );
400 
401     // Now appending a message's CRC to the message should lead to a zero-value
402     // checksum.  Note that the CRC must be read from the largest byte on down,
403     // i.e. big-endian!
404     run_crc = native_to_big( checksum );
405     BOOST_TEST_EQ( (augmented_crc<bits, poly>)(run_data, sizeof( run_data
406      )), 0u );
407 
408     // Check again with the non-augmented methods
409     boost::crc_basic<bits>  crc_b( poly );
410 
411     crc_b.process_bytes( run_data, data_size );
412     BOOST_TEST_EQ( crc_b.checksum(), checksum );
413 
414     // Introduce a single-bit error, now the checksum shouldn't match!
415     uint32_t const  affected_word_index = run_data[ 0 ] % data_length;
416     uint32_t const  affected_bit_index = run_data[ 1 ] % 32u;
417     uint32_t const  affecting_mask = 1ul << affected_bit_index;
418 
419     run_data[ affected_word_index ] ^= affecting_mask;
420 
421     crc_b.reset();
422     crc_b.process_bytes( run_data, data_size );
423     BOOST_TEST_NE( crc_b.checksum(), checksum );
424 
425     BOOST_TEST_NE( (augmented_crc<bits, poly>)(run_data, sizeof( run_data )),
426      0u );
427 
428     run_crc = 0u;
429     BOOST_TEST_NE( (augmented_crc<bits, poly>)(run_data, sizeof( run_data )),
430      checksum );
431 
432     // Now introduce the single error in the checksum instead
433     run_data[ affected_word_index ] ^= affecting_mask;
434     run_crc = native_to_big( checksum ) ^ affecting_mask;
435     BOOST_TEST_NE( (augmented_crc<bits, poly>)(run_data, sizeof( run_data )),
436      0u );
437 
438     // Repeat these tests with a non-zero initial remainder.  Before we can
439     // check the results against a non-augmented CRC computer, realize that they
440     // interpret the inital remainder differently.  However, the two standards
441     // can convert between each other.
442     // (checksum2 initial value is as a scratch pad.  So are the address and new
443     //  value of run_crc, but it's also useful for the next sub-step.)
444     // (TODO: getting the equivalent unaugmented-CRC initial-remainder given an
445     //  augmented-CRC initial-remainder is done by putting said augmented-CRC
446     //  initial-remainder through the augmented-CRC computation with a
447     //  zero-value message.  I don't know how to go the other way, yet.)
448     run_crc = 0u;
449     uint32_t        checksum2 = run_data[ run_data[2] % data_length ];
450     uint32_t const  initial_residue = checksum2 + !checksum2;  // ensure nonzero
451     uint32_t const  initial_residue_unaugmented = augmented_crc<bits, poly>(
452                      &run_crc, sizeof(run_crc), initial_residue );
453 
454     BOOST_TEST_NE( initial_residue, 0u );
455     crc_b.reset( initial_residue_unaugmented );
456     crc_b.process_bytes( run_data, data_size );
457     checksum2 = crc_b.checksum();
458 
459     BOOST_TEST_EQ( run_crc, 0u );
460     BOOST_TEST_EQ( (augmented_crc<bits, poly>)(run_data, sizeof( run_data ),
461      initial_residue), checksum2 );
462     run_crc = native_to_big( checksum2 );
463     BOOST_TEST_EQ( (augmented_crc<bits, poly>)(run_data, sizeof( run_data ),
464      initial_residue), 0u );
465 
466     // Use the inital remainder argument to split a CRC-computing run
467     size_t const    split_index = data_length / 2u;
468     uint32_t const  intermediate = augmented_crc<bits, poly>( run_data,
469                      sizeof(run_crc) * split_index, initial_residue );
470 
471     BOOST_TEST_EQ( (augmented_crc<bits, poly>)(&run_data[ split_index ],
472      sizeof( run_data ) - sizeof( run_crc ) * split_index, intermediate), 0u );
473     run_crc = 0u;
474     BOOST_TEST_EQ( (augmented_crc<bits, poly>)(&run_data[ split_index ],
475      sizeof( run_data ) - sizeof( run_crc ) * split_index, intermediate),
476      checksum2 );
477 
478     // Repeat the single-bit error test, with a non-zero initial-remainder
479     run_data[ run_data[3] % data_length ] ^= ( 1ul << (run_data[4] % 32u) );
480     run_crc = native_to_big( checksum2 );
481     BOOST_TEST_NE( (augmented_crc<bits, poly>)(run_data, sizeof( run_data ),
482      initial_residue), 0u );
483 }
484 
485 // Optimal computer, via the single-run function
crc_f1(const void * buffer,std::size_t byte_count)486 unsigned crc_f1( const void * buffer, std::size_t byte_count )
487 {
488     return boost::crc<3u, 0x03u, 0u, 0u, false, false>( buffer, byte_count );
489 }
490 
sub_nybble_polynominal_test()491 void sub_nybble_polynominal_test()
492 {
493     // The CRC standard is a SDH/SONET Low Order LCAS control word with CRC-3
494     // taken from ITU-T G.707 (12/03) XIII.2.
495 
496     // Four samples, each four bytes; should all have a CRC of zero
497     unsigned char const  samples[4][4]
498       = {
499             { 0x3Au, 0xC4u, 0x08u, 0x06u },
500             { 0x42u, 0xC5u, 0x0Au, 0x41u },
501             { 0x4Au, 0xC5u, 0x08u, 0x22u },
502             { 0x52u, 0xC4u, 0x08u, 0x05u }
503         };
504 
505     // Basic computer
506     boost::crc_basic<3u>  crc_1( 0x03u );
507 
508     crc_1.process_bytes( samples[0], 4u );
509     BOOST_TEST_EQ( crc_1.checksum(), 0u );
510 
511     crc_1.reset();
512     crc_1.process_bytes( samples[1], 4u );
513     BOOST_TEST_EQ( crc_1.checksum(), 0u );
514 
515     crc_1.reset();
516     crc_1.process_bytes( samples[2], 4u );
517     BOOST_TEST_EQ( crc_1.checksum(), 0u );
518 
519     crc_1.reset();
520     crc_1.process_bytes( samples[3], 4u );
521     BOOST_TEST_EQ( crc_1.checksum(), 0u );
522 
523     BOOST_TEST_EQ( crc_f1(samples[ 0 ], 4u), 0u );
524     BOOST_TEST_EQ( crc_f1(samples[ 1 ], 4u), 0u );
525     BOOST_TEST_EQ( crc_f1(samples[ 2 ], 4u), 0u );
526     BOOST_TEST_EQ( crc_f1(samples[ 3 ], 4u), 0u );
527 
528     // TODO: do similar tests with boost::augmented_crc<3, 0x03>
529     // (Now I think that this can't be done right now, since that function reads
530     // byte-wise, so the register size needs to be a multiple of CHAR_BIT.)
531 }
532 
533 // Optimal computer, via the single-run function
crc_f2(const void * buffer,std::size_t byte_count)534 unsigned crc_f2( const void * buffer, std::size_t byte_count )
535 {
536     return boost::crc<7u, 0x09u, 0u, 0u, false, false>( buffer, byte_count );
537 }
538 
sub_octet_polynominal_test()539 void sub_octet_polynominal_test()
540 {
541     // The CRC standard is a SDH/SONET J0/J1/J2/N1/N2/TR TTI (trace message)
542     // with CRC-7, o.a. ITU-T G.707 Annex B, G.832 Annex A.
543 
544     // Two samples, each sixteen bytes
545     // Sample 1 is '\x80' + ASCII("123456789ABCDEF")
546     // Sample 2 is '\x80' + ASCII("TTI UNAVAILABLE")
547     unsigned char const  samples[2][16]
548       = {
549             { 0x80u, 0x31u, 0x32u, 0x33u, 0x34u, 0x35u, 0x36u, 0x37u, 0x38u,
550               0x39u, 0x41u, 0x42u, 0x43u, 0x44u, 0x45u, 0x46u },
551             { 0x80u, 0x54u, 0x54u, 0x49u, 0x20u, 0x55u, 0x4Eu, 0x41u, 0x56u,
552               0x41u, 0x49u, 0x4Cu, 0x41u, 0x42u, 0x4Cu, 0x45u }
553         };
554     unsigned const       results[2] = { 0x62u, 0x23u };
555 
556     // Basic computer
557     boost::crc_basic<7u>  crc_1( 0x09u );
558 
559     crc_1.process_bytes( samples[0], 16u );
560     BOOST_TEST_EQ( crc_1.checksum(), results[0] );
561 
562     crc_1.reset();
563     crc_1.process_bytes( samples[1], 16u );
564     BOOST_TEST_EQ( crc_1.checksum(), results[1] );
565 
566     BOOST_TEST_EQ( crc_f2(samples[ 0 ], 16u), results[0] );
567     BOOST_TEST_EQ( crc_f2(samples[ 1 ], 16u), results[1] );
568 
569     // TODO: do similar tests with boost::augmented_crc<7, 0x09>
570     // (Now I think that this can't be done right now, since that function reads
571     // byte-wise, so the register size needs to be a multiple of CHAR_BIT.)
572 }
573 
one_bit_polynominal_test()574 void one_bit_polynominal_test()
575 {
576     // Try a CRC based on the (x + 1) polynominal, which is a factor in
577     // many real-life polynominals and doesn't fit evenly in a byte.
578     boost::crc_basic<1u>  crc_1( 1u );
579 
580     crc_1.process_bytes( std_data, std_data_len );
581     BOOST_TEST_EQ( crc_1.checksum(), 1u );
582 
583     // Do it again, but using crc_optimal.  The real purpose of this is to test
584     // crc_optimal::process_byte, which doesn't get exercised anywhere else in
585     // this file (directly or indirectly).
586     boost::crc_optimal<1u, 1u, 0u, 0u, false, false>  crc_2;
587 
588     for ( std::size_t  i = 0u ; i < std_data_len ; ++i )
589         crc_2.process_byte( std_data[i] );
590     BOOST_TEST_EQ( crc_2.checksum(), 1u );
591 }
592 
593 struct function_object_test {
594 template<class CRCPolicy>
operator ()function_object_test595 void operator()(CRCPolicy)
596 {
597     typename CRCPolicy::computer_ct_type  crc_c;
598 
599     crc_c = std::for_each( std_data, std_data + std_data_len, crc_c );
600     BOOST_TEST_EQ( crc_c(), CRCPolicy::standard_test_data_CRC_c::value );
601 }
602 };
603 
604 // Ticket #2492: crc_optimal with reversed CRC16
605 // <https://svn.boost.org/trac/boost/ticket/2492>
issue_2492_test()606 void issue_2492_test()
607 {
608     // I'm trusting that the original bug reporter got his/her calculations
609     // correct.
610     boost::uint16_t const  expected_result = 0xF990u;
611 
612     boost::crc_optimal<16, 0x100Bu, 0xFFFFu, 0x0000, true, false>  boost_crc_1;
613     boost::crc_basic<16>  boost_crc_2( 0x100Bu, 0xFFFFu, 0x0000, true, false );
614 
615     // This should be right...
616     boost_crc_1.process_byte( 0u );
617     BOOST_TEST_EQ( boost_crc_1.checksum(), expected_result );
618 
619     // ...but the reporter said this didn't reflect, giving 0x099F as the
620     // (wrong) result.  However, I get the right answer!
621     boost_crc_2.process_byte( 0u );
622     BOOST_TEST_EQ( boost_crc_2.checksum(), expected_result );
623 }
624 
main()625 int main()
626 {
627     run_crc_extended_test_policies<computation_comparison_test>();
628     run_crc_test_policies<accessor_and_split_run_test>();
629     run_crc_test_policies<reset_and_single_bit_error_test>();
630     augmented_crc_test();
631     sub_nybble_polynominal_test();
632     sub_octet_polynominal_test();
633     one_bit_polynominal_test();
634     run_crc_test_policies<function_object_test>();
635     issue_2492_test();
636     return boost::report_errors();
637 }
638