// (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 #include #include #include using namespace boost::unit_test; // BOOST #include #include #include #include // STL #include #include #include #include #include #include #include //____________________________________________________________________________// template struct power_of_10 { BOOST_STATIC_CONSTANT( unsigned long, value = 10*power_of_10::value ); }; template<> struct power_of_10<0> { BOOST_STATIC_CONSTANT( unsigned long, value = 1 ); }; //____________________________________________________________________________// template 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 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 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