// Copyright 2017, 2018 Peter Dimov. // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #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 ); } template void test_byte_seed_constructible( bool is_hmac ) { { unsigned char const seed[ 3 ] = { 0x01, 0x02, 0x03 }; { H h1; H h2( 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() ); } } 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( 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, 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() ); } } { 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( true ); test( true ); test( true ); test( true ); test( true ); test( true ); test( true ); test( true ); test( true ); test( true ); return boost::report_errors(); }