123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- // (C) Copyright Gennadiy Rozental 2001-2014.
- // Distributed under the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- // See http://www.boost.org/libs/test for the library home page.
- // Boost.Test
- #include <boost/test/unit_test.hpp>
- #include <boost/test/utils/algorithm.hpp>
- #include <boost/test/tools/floating_point_comparison.hpp>
- #include <boost/test/parameterized_test.hpp>
- using namespace boost::unit_test;
- // BOOST
- #include <boost/functional.hpp>
- #include <boost/static_assert.hpp>
- #include <boost/mem_fn.hpp>
- #include <boost/bind.hpp>
- // STL
- #include <string>
- #include <stdexcept>
- #include <algorithm>
- #include <functional>
- #include <iostream>
- #include <memory>
- #include <list>
- //____________________________________________________________________________//
- template<int n>
- struct power_of_10 {
- BOOST_STATIC_CONSTANT( unsigned long, value = 10*power_of_10<n-1>::value );
- };
- template<>
- struct power_of_10<0> {
- BOOST_STATIC_CONSTANT( unsigned long, value = 1 );
- };
- //____________________________________________________________________________//
- template<int AlphabetSize>
- class hash_function {
- public:
- BOOST_STATIC_ASSERT( AlphabetSize <= 5 );
- explicit hash_function( std::string const& alphabet )
- : m_alphabet( alphabet )
- {
- if( m_alphabet.size() != AlphabetSize )
- throw std::runtime_error( "Wrong alphabet size" );
- std::sort( m_alphabet.begin(), m_alphabet.end() );
- if( std::adjacent_find( m_alphabet.begin(), m_alphabet.end() ) != m_alphabet.end() )
- throw std::logic_error( "Duplicate characters in alphabet" );
- }
- unsigned long operator()( std::string const& arg )
- {
- m_result = 0;
- if( arg.length() > 8 )
- throw std::runtime_error( "Wrong argument size" );
- std::string::const_iterator it = std::find_if( arg.begin(), arg.end(),
- BOOST_TEST_BIND1ST( boost::mem_fun( &hash_function::helper_ ), this ) );
- if( it != arg.end() )
- throw std::out_of_range( std::string( "Invalid character " ) + *it );
- return m_result;
- }
- private:
- bool helper_( char c )
- {
- std::string::const_iterator it = std::find( m_alphabet.begin(), m_alphabet.end(), c );
- if( it == m_alphabet.end() )
- return true;
- m_result += power_of_10_( it - m_alphabet.begin() );
- return false;
- }
- unsigned long power_of_10_( int i ) {
- switch( i ) {
- case 0: return power_of_10<0>::value;
- case 1: return power_of_10<1>::value;
- case 2: return power_of_10<2>::value;
- case 3: return power_of_10<3>::value;
- case 4: return power_of_10<4>::value;
- default: return 0;
- }
- }
- // Data members
- std::string m_alphabet;
- unsigned long m_result;
- };
- //____________________________________________________________________________//
- struct hash_function_test_data {
- std::string orig_string;
- unsigned long exp_value;
- friend std::istream& operator>>( std::istream& istr, hash_function_test_data& test_data )
- {
- std::istream& tmp = istr >> test_data.orig_string;
- return !tmp ? tmp : istr >> test_data.exp_value;
- }
- };
- //____________________________________________________________________________//
- class hash_function_tester {
- public:
- explicit hash_function_tester( std::string const& alphabet )
- : m_function_under_test( alphabet ) {}
- void test( hash_function_test_data const& test_data )
- {
- if( test_data.exp_value == (unsigned long)-1 )
- BOOST_CHECK_THROW( m_function_under_test( test_data.orig_string ), std::runtime_error );
- else if( test_data.exp_value == (unsigned long)-2 )
- BOOST_CHECK_THROW( m_function_under_test( test_data.orig_string ), std::out_of_range );
- else {
- BOOST_TEST_MESSAGE( "Testing: " << test_data.orig_string );
- BOOST_CHECK_EQUAL( m_function_under_test( test_data.orig_string ), test_data.exp_value );
- }
- }
- private:
- hash_function<4> m_function_under_test;
- };
- //____________________________________________________________________________//
- struct massive_hash_function_test : test_suite {
- massive_hash_function_test() : test_suite( "massive_hash_function_test" ) {
- std::string alphabet;
- std::cout << "Enter alphabet (4 characters without delimeters)\n";
- std::cin >> alphabet;
- boost::shared_ptr<hash_function_tester> instance( new hash_function_tester( alphabet ) );
- std::cout << "\nEnter test data in a format [string] [value] to check correct calculation\n";
- std::cout << "Enter test data in a format [string] -1 to check long string validation\n";
- std::cout << "Enter test data in a format [string] -2 to check invalid argument string validation\n";
- std::list<hash_function_test_data> test_data_store;
- while( !std::cin.eof() ) {
- hash_function_test_data test_data;
- if( !(std::cin >> test_data) )
- break;
- test_data_store.push_back( test_data );
- }
- add( make_test_case( &hash_function_tester::test,
- "hash_function_tester",
- __FILE__,
- __LINE__,
- instance,
- test_data_store.begin(),
- test_data_store.end() ) );
- }
- };
- //____________________________________________________________________________//
- test_suite*
- init_unit_test_suite( int, char* [] ) {
- framework::master_test_suite().p_name.value = "Unit test example 12";
- framework::master_test_suite().add( new massive_hash_function_test );
- return 0;
- }
- //____________________________________________________________________________//
- // EOF
|