crc_test2.cpp 24 KB

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