]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | |
2 | // Copyright 2005-2009 Daniel James. | |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | #include "./config.hpp" | |
7 | ||
8 | #ifdef BOOST_HASH_TEST_STD_INCLUDES | |
9 | # include <functional> | |
10 | #else | |
11 | # include <boost/functional/hash.hpp> | |
12 | #endif | |
13 | ||
14 | #include <iostream> | |
15 | #include <boost/detail/lightweight_test.hpp> | |
16 | ||
17 | #include <boost/preprocessor/cat.hpp> | |
18 | #include <boost/functional/hash/detail/limits.hpp> | |
19 | #include <boost/utility/enable_if.hpp> | |
20 | ||
21 | #include "./compile_time.hpp" | |
22 | ||
23 | #if defined(BOOST_MSVC) | |
24 | #pragma warning(push) | |
25 | #pragma warning(disable:4127) // conditional expression is constant | |
26 | #pragma warning(disable:4309) // truncation of constant value | |
27 | #pragma warning(disable:4310) // cast truncates constant value | |
28 | #endif | |
29 | ||
30 | #if defined(__GNUC__) && !defined(BOOST_INTEL_CXX_VERSION) | |
31 | #pragma GCC diagnostic ignored "-Wfloat-equal" | |
32 | #endif | |
33 | ||
34 | template <class T> | |
35 | void numeric_extra_tests(typename | |
36 | boost::enable_if_c<boost::hash_detail::limits<T>::is_integer, | |
37 | void*>::type = 0) | |
38 | { | |
39 | typedef boost::hash_detail::limits<T> limits; | |
40 | ||
41 | if(limits::is_signed || | |
42 | limits::digits <= boost::hash_detail::limits<std::size_t>::digits) | |
43 | { | |
44 | BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(T(-5)) == (std::size_t)T(-5)); | |
45 | } | |
46 | BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(T(0)) == (std::size_t)T(0u)); | |
47 | BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(T(10)) == (std::size_t)T(10u)); | |
48 | BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(T(25)) == (std::size_t)T(25u)); | |
49 | } | |
50 | ||
51 | template <class T> | |
52 | void numeric_extra_tests(typename | |
53 | boost::disable_if_c<boost::hash_detail::limits<T>::is_integer, | |
54 | void*>::type = 0) | |
55 | { | |
56 | } | |
57 | ||
58 | template <class T> | |
59 | void numeric_test(T*) | |
60 | { | |
61 | compile_time_tests((T*) 0); | |
62 | ||
63 | BOOST_HASH_TEST_NAMESPACE::hash<T> x1; | |
64 | BOOST_HASH_TEST_NAMESPACE::hash<T> x2; | |
65 | ||
66 | T v1 = (T) -5; | |
67 | BOOST_TEST(x1(v1) == x2(v1)); | |
68 | BOOST_TEST(x1(T(-5)) == x2(T(-5))); | |
69 | BOOST_TEST(x1(T(0)) == x2(T(0))); | |
70 | BOOST_TEST(x1(T(10)) == x2(T(10))); | |
71 | BOOST_TEST(x1(T(25)) == x2(T(25))); | |
72 | BOOST_TEST(x1(T(5) - T(5)) == x2(T(0))); | |
73 | BOOST_TEST(x1(T(6) + T(4)) == x2(T(10))); | |
74 | ||
75 | #if defined(BOOST_HASH_TEST_EXTENSIONS) | |
76 | BOOST_TEST(x1(T(-5)) == BOOST_HASH_TEST_NAMESPACE::hash_value(T(-5))); | |
77 | BOOST_TEST(x1(T(0)) == BOOST_HASH_TEST_NAMESPACE::hash_value(T(0))); | |
78 | BOOST_TEST(x1(T(10)) == BOOST_HASH_TEST_NAMESPACE::hash_value(T(10))); | |
79 | BOOST_TEST(x1(T(25)) == BOOST_HASH_TEST_NAMESPACE::hash_value(T(25))); | |
80 | ||
81 | numeric_extra_tests<T>(); | |
82 | #endif | |
83 | } | |
84 | ||
85 | template <class T> | |
86 | void limits_test(T*) | |
87 | { | |
88 | typedef boost::hash_detail::limits<T> limits; | |
89 | ||
90 | if(limits::is_specialized) | |
91 | { | |
92 | BOOST_HASH_TEST_NAMESPACE::hash<T> x1; | |
93 | BOOST_HASH_TEST_NAMESPACE::hash<T> x2; | |
94 | ||
95 | T min_value = (limits::min)(); | |
96 | T max_value = (limits::max)(); | |
97 | ||
98 | BOOST_TEST(x1(min_value) == x2((limits::min)())); | |
99 | BOOST_TEST(x1(max_value) == x2((limits::max)())); | |
100 | ||
101 | #if defined(BOOST_HASH_TEST_EXTENSIONS) | |
102 | BOOST_TEST(x1(min_value) == BOOST_HASH_TEST_NAMESPACE::hash_value(min_value)); | |
103 | BOOST_TEST(x1(max_value) == BOOST_HASH_TEST_NAMESPACE::hash_value(max_value)); | |
104 | ||
105 | if (limits::is_integer) | |
106 | { | |
107 | BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(min_value) | |
108 | == std::size_t(min_value)); | |
109 | BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(max_value) | |
110 | == std::size_t(max_value)); | |
111 | } | |
112 | #endif | |
113 | } | |
114 | } | |
115 | ||
116 | template <class T> | |
117 | void poor_quality_tests(T*) | |
118 | { | |
119 | typedef boost::hash_detail::limits<T> limits; | |
120 | ||
121 | BOOST_HASH_TEST_NAMESPACE::hash<T> x1; | |
122 | BOOST_HASH_TEST_NAMESPACE::hash<T> x2; | |
123 | ||
124 | // A hash function can legally fail these tests, but it'll not be a good | |
125 | // sign. | |
126 | if(T(1) != T(-1)) | |
127 | BOOST_TEST(x1(T(1)) != x2(T(-1))); | |
128 | if(T(1) != T(2)) | |
129 | BOOST_TEST(x1(T(1)) != x2(T(2))); | |
b32b8144 FG |
130 | |
131 | // TODO: This test is useless for floating point numbers. | |
132 | T max_number = static_cast<T>((limits::max)()); | |
133 | T max_minus_one = static_cast<T>(max_number - 1); | |
134 | if (max_number != max_minus_one) { | |
135 | BOOST_TEST(x1(max_number) != x1(max_minus_one)); | |
136 | } | |
7c673cae FG |
137 | } |
138 | ||
139 | void bool_test() | |
140 | { | |
141 | BOOST_HASH_TEST_NAMESPACE::hash<bool> x1; | |
142 | BOOST_HASH_TEST_NAMESPACE::hash<bool> x2; | |
143 | ||
144 | BOOST_TEST(x1(true) == x2(true)); | |
145 | BOOST_TEST(x1(false) == x2(false)); | |
146 | BOOST_TEST(x1(true) != x2(false)); | |
147 | BOOST_TEST(x1(false) != x2(true)); | |
148 | } | |
149 | ||
150 | #define NUMERIC_TEST(type, name) \ | |
151 | std::cerr<<"Testing: " BOOST_STRINGIZE(name) "\n"; \ | |
152 | numeric_test((type*) 0); \ | |
153 | limits_test((type*) 0); \ | |
154 | poor_quality_tests((type*) 0); | |
155 | #define NUMERIC_TEST_NO_LIMITS(type, name) \ | |
156 | std::cerr<<"Testing: " BOOST_STRINGIZE(name) "\n"; \ | |
157 | numeric_test((type*) 0); \ | |
158 | poor_quality_tests((type*) 0); | |
159 | ||
160 | int main() | |
161 | { | |
162 | NUMERIC_TEST(char, char) | |
163 | NUMERIC_TEST(signed char, schar) | |
164 | NUMERIC_TEST(unsigned char, uchar) | |
165 | #ifndef BOOST_NO_INTRINSIC_WCHAR_T | |
166 | NUMERIC_TEST(wchar_t, wchar) | |
b32b8144 FG |
167 | #endif |
168 | #ifndef BOOST_NO_CXX11_CHAR16_T | |
169 | NUMERIC_TEST(char16_t, char16) | |
170 | #endif | |
171 | #ifndef BOOST_NO_CXX11_CHAR32_T | |
172 | NUMERIC_TEST(char32_t, char32) | |
7c673cae FG |
173 | #endif |
174 | NUMERIC_TEST(short, short) | |
175 | NUMERIC_TEST(unsigned short, ushort) | |
176 | NUMERIC_TEST(int, int) | |
177 | NUMERIC_TEST(unsigned int, uint) | |
178 | NUMERIC_TEST(long, hash_long) | |
179 | NUMERIC_TEST(unsigned long, ulong) | |
180 | ||
181 | #if !defined(BOOST_NO_LONG_LONG) | |
182 | NUMERIC_TEST_NO_LIMITS(boost::long_long_type, long_long) | |
183 | NUMERIC_TEST_NO_LIMITS(boost::ulong_long_type, ulong_long) | |
184 | #endif | |
185 | ||
186 | #if defined(BOOST_HAS_INT128) | |
187 | NUMERIC_TEST_NO_LIMITS(boost::int128_type, int128) | |
188 | NUMERIC_TEST_NO_LIMITS(boost::uint128_type, uint128) | |
189 | #endif | |
190 | ||
191 | NUMERIC_TEST(float, float) | |
192 | NUMERIC_TEST(double, double) | |
193 | ||
194 | NUMERIC_TEST(std::size_t, size_t) | |
195 | NUMERIC_TEST(std::ptrdiff_t, ptrdiff_t) | |
196 | ||
197 | bool_test(); | |
198 | ||
199 | return boost::report_errors(); | |
200 | } | |
201 | ||
202 | #if defined(BOOST_MSVC) | |
203 | #pragma warning(pop) | |
204 | #endif |