unit_test_example_12.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // (C) Copyright Gennadiy Rozental 2001-2014.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // See http://www.boost.org/libs/test for the library home page.
  6. // Boost.Test
  7. #include <boost/test/unit_test.hpp>
  8. #include <boost/test/utils/algorithm.hpp>
  9. #include <boost/test/tools/floating_point_comparison.hpp>
  10. #include <boost/test/parameterized_test.hpp>
  11. using namespace boost::unit_test;
  12. // BOOST
  13. #include <boost/functional.hpp>
  14. #include <boost/static_assert.hpp>
  15. #include <boost/mem_fn.hpp>
  16. #include <boost/bind.hpp>
  17. // STL
  18. #include <string>
  19. #include <stdexcept>
  20. #include <algorithm>
  21. #include <functional>
  22. #include <iostream>
  23. #include <memory>
  24. #include <list>
  25. //____________________________________________________________________________//
  26. template<int n>
  27. struct power_of_10 {
  28. BOOST_STATIC_CONSTANT( unsigned long, value = 10*power_of_10<n-1>::value );
  29. };
  30. template<>
  31. struct power_of_10<0> {
  32. BOOST_STATIC_CONSTANT( unsigned long, value = 1 );
  33. };
  34. //____________________________________________________________________________//
  35. template<int AlphabetSize>
  36. class hash_function {
  37. public:
  38. BOOST_STATIC_ASSERT( AlphabetSize <= 5 );
  39. explicit hash_function( std::string const& alphabet )
  40. : m_alphabet( alphabet )
  41. {
  42. if( m_alphabet.size() != AlphabetSize )
  43. throw std::runtime_error( "Wrong alphabet size" );
  44. std::sort( m_alphabet.begin(), m_alphabet.end() );
  45. if( std::adjacent_find( m_alphabet.begin(), m_alphabet.end() ) != m_alphabet.end() )
  46. throw std::logic_error( "Duplicate characters in alphabet" );
  47. }
  48. unsigned long operator()( std::string const& arg )
  49. {
  50. m_result = 0;
  51. if( arg.length() > 8 )
  52. throw std::runtime_error( "Wrong argument size" );
  53. std::string::const_iterator it = std::find_if( arg.begin(), arg.end(),
  54. BOOST_TEST_BIND1ST( boost::mem_fun( &hash_function::helper_ ), this ) );
  55. if( it != arg.end() )
  56. throw std::out_of_range( std::string( "Invalid character " ) + *it );
  57. return m_result;
  58. }
  59. private:
  60. bool helper_( char c )
  61. {
  62. std::string::const_iterator it = std::find( m_alphabet.begin(), m_alphabet.end(), c );
  63. if( it == m_alphabet.end() )
  64. return true;
  65. m_result += power_of_10_( it - m_alphabet.begin() );
  66. return false;
  67. }
  68. unsigned long power_of_10_( int i ) {
  69. switch( i ) {
  70. case 0: return power_of_10<0>::value;
  71. case 1: return power_of_10<1>::value;
  72. case 2: return power_of_10<2>::value;
  73. case 3: return power_of_10<3>::value;
  74. case 4: return power_of_10<4>::value;
  75. default: return 0;
  76. }
  77. }
  78. // Data members
  79. std::string m_alphabet;
  80. unsigned long m_result;
  81. };
  82. //____________________________________________________________________________//
  83. struct hash_function_test_data {
  84. std::string orig_string;
  85. unsigned long exp_value;
  86. friend std::istream& operator>>( std::istream& istr, hash_function_test_data& test_data )
  87. {
  88. std::istream& tmp = istr >> test_data.orig_string;
  89. return !tmp ? tmp : istr >> test_data.exp_value;
  90. }
  91. };
  92. //____________________________________________________________________________//
  93. class hash_function_tester {
  94. public:
  95. explicit hash_function_tester( std::string const& alphabet )
  96. : m_function_under_test( alphabet ) {}
  97. void test( hash_function_test_data const& test_data )
  98. {
  99. if( test_data.exp_value == (unsigned long)-1 )
  100. BOOST_CHECK_THROW( m_function_under_test( test_data.orig_string ), std::runtime_error );
  101. else if( test_data.exp_value == (unsigned long)-2 )
  102. BOOST_CHECK_THROW( m_function_under_test( test_data.orig_string ), std::out_of_range );
  103. else {
  104. BOOST_TEST_MESSAGE( "Testing: " << test_data.orig_string );
  105. BOOST_CHECK_EQUAL( m_function_under_test( test_data.orig_string ), test_data.exp_value );
  106. }
  107. }
  108. private:
  109. hash_function<4> m_function_under_test;
  110. };
  111. //____________________________________________________________________________//
  112. struct massive_hash_function_test : test_suite {
  113. massive_hash_function_test() : test_suite( "massive_hash_function_test" ) {
  114. std::string alphabet;
  115. std::cout << "Enter alphabet (4 characters without delimeters)\n";
  116. std::cin >> alphabet;
  117. boost::shared_ptr<hash_function_tester> instance( new hash_function_tester( alphabet ) );
  118. std::cout << "\nEnter test data in a format [string] [value] to check correct calculation\n";
  119. std::cout << "Enter test data in a format [string] -1 to check long string validation\n";
  120. std::cout << "Enter test data in a format [string] -2 to check invalid argument string validation\n";
  121. std::list<hash_function_test_data> test_data_store;
  122. while( !std::cin.eof() ) {
  123. hash_function_test_data test_data;
  124. if( !(std::cin >> test_data) )
  125. break;
  126. test_data_store.push_back( test_data );
  127. }
  128. add( make_test_case( &hash_function_tester::test,
  129. "hash_function_tester",
  130. __FILE__,
  131. __LINE__,
  132. instance,
  133. test_data_store.begin(),
  134. test_data_store.end() ) );
  135. }
  136. };
  137. //____________________________________________________________________________//
  138. test_suite*
  139. init_unit_test_suite( int, char* [] ) {
  140. framework::master_test_suite().p_name.value = "Unit test example 12";
  141. framework::master_test_suite().add( new massive_hash_function_test );
  142. return 0;
  143. }
  144. //____________________________________________________________________________//
  145. // EOF