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
36namespace {
37
38// Many CRC configurations use the string "123456789" in ASCII as test data.
39unsigned char const std_data[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
40 0x38, 0x39 };
41std::size_t const std_data_len = sizeof( std_data ) / sizeof( std_data[0] );
42
43// Checksums of the standard test data for common configurations
44boost::uint16_t const std_crc_ccitt_false_result = 0x29B1u;
45boost::uint16_t const std_crc_ccitt_true_result = 0x2189u;
46boost::uint16_t const std_crc_xmodem_result = 0x31C3u;
47boost::uint16_t const std_crc_16_result = 0xBB3Du;
48boost::uint32_t const std_crc_32_result = 0xCBF43926ul;
49
50// Conversion functions between native- and big-endian representations
51#if BOOST_ENDIAN_BIG_BYTE
52boost::uint32_t native_to_big( boost::uint32_t x ) { return x; }
53boost::uint32_t big_to_native( boost::uint32_t x ) { return x; }
54#else
55union endian_convert
56{
57 boost::uint32_t w;
58 unsigned char p[ 4 ];
59};
60
61boost::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
72boost::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!
90template < std::size_t Bits >
91class my_crc_rt_traits
92{
93public:
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
104 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
109template < std::size_t Bits, boost::uintmax_t DivisorPolynominal,
110 boost::uintmax_t InitialRemainder, bool ReflectInputBytes,
111 bool ReflectOutputRemainder, boost::uintmax_t FinalXorMask >
112class my_crc_ct_traits
113{
114public:
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
131 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
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
147template < 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 >
151class my_crc_test_traits
152{
153public:
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
176 static computer_ct_type make_crc_optimal()
177 { return ct_traits_type::make_crc_optimal(); }
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
183typedef my_crc_test_traits<16u, 0x8005u, 0u, true, true, 0u, std_crc_16_result>
184 my_crc_16_traits;
185typedef my_crc_test_traits<16u, 0x1021u, 0xFFFFu, false, false, 0u,
186 std_crc_ccitt_false_result> my_crc_ccitt_false_traits;
187typedef my_crc_test_traits<16u, 0x1021u, 0u, true, true, 0u,
188 std_crc_ccitt_true_result> my_crc_ccitt_true_traits;
189typedef my_crc_test_traits<16u, 0x1021u, 0u, false, false, 0u,
190 std_crc_xmodem_result> my_crc_xmodem_traits;
191typedef my_crc_test_traits<32u, 0x04C11DB7ul, 0xFFFFFFFFul, true, true,
192 0xFFFFFFFFul, std_crc_32_result> my_crc_32_traits;
193
194template<class Test>
195void 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>.)
206typedef my_crc_test_traits<6u, 0x19u, 0u, true, false, 0u, 0x19u>
207 my_crc_6_darc_traits;
208typedef my_crc_test_traits<12u, 0x80Fu, 0u, false, true, 0u, 0xDAFu>
209 my_crc_12_3gpp_traits;
210
211template<class Test>
212void 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
226template < std::size_t BitIndex >
227struct high_bit_mask_c
228 : boost::detail::high_bit_mask_c<BitIndex>
229{};
230template < std::size_t BitCount >
231struct low_bits_mask_c
232 : boost::detail::low_bits_mask_c<BitCount>
233{};
234
235} // anonymous namespace
236
237
238// Unit tests ---------------------------------------------------------------//
239
240struct computation_comparison_test {
241template<class CRCPolicy>
242void 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
266struct accessor_and_split_run_test {
267template<class CRCPolicy>
268void 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
313struct reset_and_single_bit_error_test {
314template<class CRCPolicy>
315void 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( first: ran_data, n: ran_length, gen: 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
371void 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( first: run_data, n: data_length, gen: 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 buffer: run_data, byte_count: 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( x: 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( buffer: run_data, byte_count: 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( buffer: run_data, byte_count: 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( x: 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 buffer: &run_crc, byte_count: sizeof(run_crc), initial_remainder: initial_residue );
453
454 BOOST_TEST_NE( initial_residue, 0u );
455 crc_b.reset( new_rem: initial_residue_unaugmented );
456 crc_b.process_bytes( buffer: run_data, byte_count: 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( x: 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>( buffer: run_data,
469 byte_count: sizeof(run_crc) * split_index, initial_remainder: 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( x: 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
486unsigned 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
491void 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( buffer: samples[0], byte_count: 4u );
509 BOOST_TEST_EQ( crc_1.checksum(), 0u );
510
511 crc_1.reset();
512 crc_1.process_bytes( buffer: samples[1], byte_count: 4u );
513 BOOST_TEST_EQ( crc_1.checksum(), 0u );
514
515 crc_1.reset();
516 crc_1.process_bytes( buffer: samples[2], byte_count: 4u );
517 BOOST_TEST_EQ( crc_1.checksum(), 0u );
518
519 crc_1.reset();
520 crc_1.process_bytes( buffer: samples[3], byte_count: 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
534unsigned 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
539void 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( buffer: samples[0], byte_count: 16u );
560 BOOST_TEST_EQ( crc_1.checksum(), results[0] );
561
562 crc_1.reset();
563 crc_1.process_bytes( buffer: samples[1], byte_count: 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
574void 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( buffer: std_data, byte_count: 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( byte: std_data[i] );
590 BOOST_TEST_EQ( crc_2.checksum(), 1u );
591}
592
593struct function_object_test {
594template<class CRCPolicy>
595void 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>
606void 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( 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( byte: 0u );
622 BOOST_TEST_EQ( boost_crc_2.checksum(), expected_result );
623}
624
625int 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

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