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