// Copyright 2017, 2018 Peter Dimov. // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt // due to aggressiving inlining effects, it seems we can only reliably silence this warning // in the end TU itself #include #if BOOST_WORKAROUND(BOOST_GCC, >= 110000 && BOOST_GCC < 120000) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wstringop-overread" #endif #if BOOST_WORKAROUND(BOOST_GCC, >= 80000 && BOOST_GCC < 90000) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Warray-bounds" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include template struct is_valid_result: std::integral_constant::value && !std::is_signed::value > { }; template struct is_valid_result< std::array >: std::integral_constant= 8> { }; template struct is_valid_result< boost::hash2::digest >: std::integral_constant= 8> { }; template void test_result_type() { BOOST_TEST_TRAIT_TRUE((is_valid_result)); } template void test_default_constructible() { H h1; typename H::result_type r1 = h1.result(); H h2; typename H::result_type r2 = h2.result(); BOOST_TEST( r1 == r2 ); H h3; h3.update( static_cast( nullptr ), 0 ); typename H::result_type r3 = h3.result(); BOOST_TEST( r1 == r3 ); } template void test_byte_seed_constructible( bool is_hmac ) { { unsigned char const seed[ 3 ] = { 0x01, 0x02, 0x03 }; { H h1; H h2( static_cast( nullptr ), 0 ); BOOST_TEST( h1.result() == h2.result() ); } { H h1; H h2( seed, 0 ); BOOST_TEST( h1.result() == h2.result() ); } { H h1; H h2( seed, 3 ); BOOST_TEST( h1.result() != h2.result() ); } { H h1( seed, 3 ); H h2( seed, 3 ); BOOST_TEST( h1.result() == h2.result() ); } { H h1( seed, 2 ); H h2( seed, 3 ); BOOST_TEST( h1.result() != h2.result() ); } { H h1( seed, 3 ); H h2( seed, 3 ); h2.update( seed, 0 ); BOOST_TEST( h1.result() == h2.result() ); } { H h1( seed, 3 ); H h2( seed, 0 ); h2.update( seed, 3 ); BOOST_TEST( h1.result() != h2.result() ); } { H h1( seed, 3 ); H h2( seed, 2 ); h2.update( seed + 2, 1 ); BOOST_TEST( h1.result() != h2.result() ); } { char const seed2[] = { 0x01, 0x02, 0x03 }; H h1( seed, 3 ); H h2( seed2, 3 ); BOOST_TEST( h1.result() == h2.result() ); } } { unsigned char const seed1[ 1 ] = { 0x01 }; unsigned char const seed2[ 1 ] = { 0x02 }; H h1( seed1, sizeof( seed1 ) ); H h2( seed2, sizeof( seed2 ) ); BOOST_TEST( h1.result() != h2.result() ); } { unsigned char const seed1[ 4 ] = { 0x01 }; unsigned char const seed2[ 4 ] = { 0x02 }; H h1( seed1, sizeof( seed1 ) ); H h2( seed2, sizeof( seed2 ) ); BOOST_TEST( h1.result() != h2.result() ); } { unsigned char const seed1[ 8 ] = { 0x01 }; unsigned char const seed2[ 8 ] = { 0x02 }; H h1( seed1, sizeof( seed1 ) ); H h2( seed2, sizeof( seed2 ) ); BOOST_TEST( h1.result() != h2.result() ); } { unsigned char const seed1[ 256 ] = { 0x01 }; unsigned char const seed2[ 256 ] = { 0x02 }; H h1( seed1, sizeof( seed1 ) ); H h2( seed2, sizeof( seed2 ) ); BOOST_TEST( h1.result() != h2.result() ); } { unsigned char seed1[ 256 ] = {}; unsigned char seed2[ 256 ] = {}; seed1[ 255 ] = 0x01; seed2[ 255 ] = 0x02; H h1( seed1, sizeof( seed1 ) ); H h2( seed2, sizeof( seed2 ) ); BOOST_TEST( h1.result() != h2.result() ); } { std::vector seed1( 256, 0x01 ); std::vector seed2( 256, 0x01 ); H h1( seed1.data(), seed1.size() ); H h2( seed2.data(), seed2.size() ); seed2.clear(); seed2.shrink_to_fit(); BOOST_TEST( h1.result() == h2.result() ); } if( !is_hmac ) { // RFC 2104 mandates null padding of short keys, // so these tests are required to fail for hmac_xxx unsigned char const seed[ 3 ] = { 0x00, 0x00, 0x00 }; { H h1; H h2( seed, 3 ); BOOST_TEST( h1.result() != h2.result() ); } { H h1( seed, 2 ); H h2( seed, 3 ); BOOST_TEST( h1.result() != h2.result() ); } } } template void test_integral_seed_constructible() { typename H::result_type r0, r1, r2, r3; { H h( 0 ); r0 = h.result(); } { H h( 1 ); r1 = h.result(); } BOOST_TEST( r0 != r1 ); { H h( 2 ); r2 = h.result(); } BOOST_TEST( r0 != r2 ); BOOST_TEST( r1 != r2 ); { H h( 1LL << 32 ); r3 = h.result(); } BOOST_TEST( r0 != r3 ); BOOST_TEST( r1 != r3 ); BOOST_TEST( r2 != r3 ); { H h; BOOST_TEST( h.result() == r0 ); } { H h( 0 ); h.update( static_cast( nullptr ), 0 ); BOOST_TEST( h.result() == r0 ); } { H h( 0L ); BOOST_TEST( h.result() == r0 ); } { H h( 1L ); BOOST_TEST( h.result() == r1 ); } { H h( 2L ); BOOST_TEST( h.result() == r2 ); } { H h( 0LL ); BOOST_TEST( h.result() == r0 ); } { H h( 1LL ); BOOST_TEST( h.result() == r1 ); } { H h( 2LL ); BOOST_TEST( h.result() == r2 ); } { H h( static_cast( 0 ) ); BOOST_TEST( h.result() == r0 ); } { H h( static_cast( 1 ) ); BOOST_TEST( h.result() == r1 ); } { H h( static_cast( 2 ) ); BOOST_TEST( h.result() == r2 ); } { H h( static_cast( 0 ) ); BOOST_TEST( h.result() == r0 ); } { H h( static_cast( 1 ) ); BOOST_TEST( h.result() == r1 ); } { H h( static_cast( 2 ) ); BOOST_TEST( h.result() == r2 ); } { H h( static_cast( 0 ) ); BOOST_TEST( h.result() == r0 ); } { H h( static_cast( 1 ) ); BOOST_TEST( h.result() == r1 ); } { H h( static_cast( 2 ) ); BOOST_TEST( h.result() == r2 ); } { H h( static_cast( 1 ) << 32 ); BOOST_TEST( h.result() == r3 ); } } template void test_copy_constructible() { unsigned char const seed[ 3 ] = { 0x01, 0x02, 0x03 }; { H h1; H h2( h1 ); BOOST_TEST( h1.result() == h2.result() ); } { H h1( seed, 3 ); H h2( h1 ); BOOST_TEST( h1.result() == h2.result() ); } { H h1; h1.update( seed, 3 ); H h2( h1 ); BOOST_TEST( h1.result() == h2.result() ); } } template void test_update() { { unsigned char const data[ 3 ] = { 0x01, 0x02, 0x03 }; { H h1; H h2; h2.update( data, 3 ); BOOST_TEST( h1.result() != h2.result() ); } { H h1; h1.update( data, 3 ); H h2; h2.update( data, 3 ); BOOST_TEST( h1.result() == h2.result() ); } { H h1; h1.update( data, 3 ); H h2; h2.update( data, 2 ); BOOST_TEST( h1.result() != h2.result() ); } { H h1; h1.update( data, 3 ); H h2( h1 ); h1.update( data, 3 ); h2.update( data, 3 ); BOOST_TEST( h1.result() == h2.result() ); } { H h1; h1.update( data, 3 ); H h2; h2.update( data + 0, 1 ); h2.update( data + 1, 1 ); h2.update( data + 2, 1 ); BOOST_TEST( h1.result() == h2.result() ); } { H h1; h1.update( data, 3 ); H h2; h2.update( data, 0 ); h2.update( data + 0, 3 ); BOOST_TEST( h1.result() == h2.result() ); } { H h1; h1.update( data, 3 ); H h2; h2.update( data, 1 ); h2.update( data + 1, 2 ); BOOST_TEST( h1.result() == h2.result() ); } { H h1; h1.update( data, 3 ); H h2; h2.update( data, 2 ); h2.update( data + 2, 1 ); BOOST_TEST( h1.result() == h2.result() ); } { H h1; h1.update( data, 3 ); H h2; h2.update( data, 3 ); h2.update( data + 3, 0 ); BOOST_TEST( h1.result() == h2.result() ); } } { int const N = 255; unsigned char const data[ N ] = {}; for( int i = 0; i <= N; ++i ) { H h1; h1.update( data, N ); H h2; h2.update( data, i ); h2.update( data + i, N - i ); BOOST_TEST( h1.result() == h2.result() ); } { H h1; h1.update( data, N ); H h2; for( int i = 0; i < N / 5; ++i ) { h2.update( data + i * 5, 5 ); } BOOST_TEST( h1.result() == h2.result() ); } } } template void test_assignable() { unsigned char const seed[ 3 ] = { 0x01, 0x02, 0x03 }; { H h1; H h2( h1 ); typename H::result_type r1 = h1.result(); BOOST_TEST( h1.result() != r1 ); h1 = h2; BOOST_TEST( h1.result() == r1 ); } { H h1( seed, 3 ); H h2( h1 ); typename H::result_type r1 = h1.result(); BOOST_TEST( h1.result() != r1 ); h1 = h2; BOOST_TEST( h1.result() == r1 ); } { H h1; h1.update( seed, 3 ); H h2( h1 ); typename H::result_type r1 = h1.result(); BOOST_TEST( h1.result() != r1 ); h1 = h2; BOOST_TEST( h1.result() == r1 ); } } template void test( bool is_hmac = false ) { test_result_type(); test_default_constructible(); test_byte_seed_constructible( is_hmac ); test_integral_seed_constructible(); test_copy_constructible(); test_update(); test_assignable(); } int main() { test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test(); test( true ); test( true ); test( true ); test( true ); test( true ); test( true ); test( true ); test( true ); test( true ); test( true ); test( true ); test( true ); test( true ); test( true ); return boost::report_errors(); }