blob: 28ca6e8e7fb29195f12006980a7d11d4bbbf17c2 [file] [log] [blame]
Jeff Thompsona28eed82013-08-22 16:21:10 -07001
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
34template <class T>
35void numeric_extra_tests(typename
36 ndnboost::enable_if_c<ndnboost::hash_detail::limits<T>::is_integer,
37 void*>::type = 0)
38{
39 typedef ndnboost::hash_detail::limits<T> limits;
40
41 if(limits::is_signed ||
42 limits::digits <= ndnboost::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
51template <class T>
52void numeric_extra_tests(typename
53 ndnboost::disable_if_c<ndnboost::hash_detail::limits<T>::is_integer,
54 void*>::type = 0)
55{
56}
57
58template <class T>
59void numeric_test(T*)
60{
61 typedef ndnboost::hash_detail::limits<T> limits;
62
63 compile_time_tests((T*) 0);
64
65 BOOST_HASH_TEST_NAMESPACE::hash<T> x1;
66 BOOST_HASH_TEST_NAMESPACE::hash<T> x2;
67
68 T v1 = (T) -5;
69 BOOST_TEST(x1(v1) == x2(v1));
70 BOOST_TEST(x1(T(-5)) == x2(T(-5)));
71 BOOST_TEST(x1(T(0)) == x2(T(0)));
72 BOOST_TEST(x1(T(10)) == x2(T(10)));
73 BOOST_TEST(x1(T(25)) == x2(T(25)));
74 BOOST_TEST(x1(T(5) - T(5)) == x2(T(0)));
75 BOOST_TEST(x1(T(6) + T(4)) == x2(T(10)));
76
77#if defined(BOOST_HASH_TEST_EXTENSIONS)
78 BOOST_TEST(x1(T(-5)) == BOOST_HASH_TEST_NAMESPACE::hash_value(T(-5)));
79 BOOST_TEST(x1(T(0)) == BOOST_HASH_TEST_NAMESPACE::hash_value(T(0)));
80 BOOST_TEST(x1(T(10)) == BOOST_HASH_TEST_NAMESPACE::hash_value(T(10)));
81 BOOST_TEST(x1(T(25)) == BOOST_HASH_TEST_NAMESPACE::hash_value(T(25)));
82
83 numeric_extra_tests<T>();
84#endif
85}
86
87template <class T>
88void limits_test(T*)
89{
90 typedef ndnboost::hash_detail::limits<T> limits;
91
92 if(limits::is_specialized)
93 {
94 BOOST_HASH_TEST_NAMESPACE::hash<T> x1;
95 BOOST_HASH_TEST_NAMESPACE::hash<T> x2;
96
97 T min_value = (limits::min)();
98 T max_value = (limits::max)();
99
100 BOOST_TEST(x1(min_value) == x2((limits::min)()));
101 BOOST_TEST(x1(max_value) == x2((limits::max)()));
102
103#if defined(BOOST_HASH_TEST_EXTENSIONS)
104 BOOST_TEST(x1(min_value) == BOOST_HASH_TEST_NAMESPACE::hash_value(min_value));
105 BOOST_TEST(x1(max_value) == BOOST_HASH_TEST_NAMESPACE::hash_value(max_value));
106
107 if (limits::is_integer)
108 {
109 BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(min_value)
110 == std::size_t(min_value));
111 BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(max_value)
112 == std::size_t(max_value));
113 }
114#endif
115 }
116}
117
118template <class T>
119void poor_quality_tests(T*)
120{
121 typedef ndnboost::hash_detail::limits<T> limits;
122
123 BOOST_HASH_TEST_NAMESPACE::hash<T> x1;
124 BOOST_HASH_TEST_NAMESPACE::hash<T> x2;
125
126 // A hash function can legally fail these tests, but it'll not be a good
127 // sign.
128 if(T(1) != T(-1))
129 BOOST_TEST(x1(T(1)) != x2(T(-1)));
130 if(T(1) != T(2))
131 BOOST_TEST(x1(T(1)) != x2(T(2)));
132 if((limits::max)() != (limits::max)() - 1)
133 BOOST_TEST(x1(static_cast<T>((limits::max)()))
134 != x2(static_cast<T>((limits::max)() - 1)));
135}
136
137void bool_test()
138{
139 BOOST_HASH_TEST_NAMESPACE::hash<bool> x1;
140 BOOST_HASH_TEST_NAMESPACE::hash<bool> x2;
141
142 BOOST_TEST(x1(true) == x2(true));
143 BOOST_TEST(x1(false) == x2(false));
144 BOOST_TEST(x1(true) != x2(false));
145 BOOST_TEST(x1(false) != x2(true));
146}
147
148#define NUMERIC_TEST(type, name) \
149 std::cerr<<"Testing: " BOOST_STRINGIZE(name) "\n"; \
150 numeric_test((type*) 0); \
151 limits_test((type*) 0); \
152 poor_quality_tests((type*) 0);
153#define NUMERIC_TEST_NO_LIMITS(type, name) \
154 std::cerr<<"Testing: " BOOST_STRINGIZE(name) "\n"; \
155 numeric_test((type*) 0); \
156 poor_quality_tests((type*) 0);
157
158int main()
159{
160 NUMERIC_TEST(char, char)
161 NUMERIC_TEST(signed char, schar)
162 NUMERIC_TEST(unsigned char, uchar)
163#ifndef BOOST_NO_INTRINSIC_WCHAR_T
164 NUMERIC_TEST(wchar_t, wchar)
165#endif
166 NUMERIC_TEST(short, short)
167 NUMERIC_TEST(unsigned short, ushort)
168 NUMERIC_TEST(int, int)
169 NUMERIC_TEST(unsigned int, uint)
170 NUMERIC_TEST(long, hash_long)
171 NUMERIC_TEST(unsigned long, ulong)
172
173#if !defined(BOOST_NO_LONG_LONG)
174 NUMERIC_TEST_NO_LIMITS(ndnboost::long_long_type, long_long)
175 NUMERIC_TEST_NO_LIMITS(ndnboost::ulong_long_type, ulong_long)
176#endif
177
178#if defined(BOOST_HAS_INT128)
179 NUMERIC_TEST_NO_LIMITS(ndnboost::int128_type, int128)
180 NUMERIC_TEST_NO_LIMITS(ndnboost::uint128_type, uint128)
181#endif
182
183 NUMERIC_TEST(float, float)
184 NUMERIC_TEST(double, double)
185
186 NUMERIC_TEST(std::size_t, size_t)
187 NUMERIC_TEST(std::ptrdiff_t, ptrdiff_t)
188
189 bool_test();
190
191 return ndnboost::report_errors();
192}
193
194#if defined(BOOST_MSVC)
195#pragma warning(pop)
196#endif