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