google_hash 0.8.1 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog.txt +2 -0
- data/VERSION +1 -1
- data/ext/clean.bat +0 -0
- data/ext/clean.sh +4 -0
- data/ext/extconf.rb +4 -5
- data/ext/go.bat +0 -0
- data/ext/sparsehash-2.0.2/AUTHORS +2 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/COPYING +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/ChangeLog +60 -0
- data/ext/sparsehash-2.0.2/INSTALL +365 -0
- data/ext/sparsehash-2.0.2/Makefile +1336 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/Makefile.am +97 -40
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/Makefile.in +538 -256
- data/ext/sparsehash-2.0.2/NEWS +188 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/README +4 -10
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/README_windows.txt +3 -3
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/TODO +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/aclocal.m4 +266 -166
- data/ext/sparsehash-2.0.2/allocator.patch +31 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/config.guess +235 -234
- data/ext/sparsehash-2.0.2/config.status +1238 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/config.sub +198 -64
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/configure +1118 -1000
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/configure.ac +4 -5
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/depcomp +136 -36
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/dense_hash_map.html +182 -67
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/dense_hash_set.html +173 -74
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/designstyle.css +0 -6
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/implementation.html +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/index.html +4 -5
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/performance.html +1 -1
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/sparse_hash_map.html +190 -58
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/sparse_hash_set.html +180 -65
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/sparsetable.html +1 -1
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/Makefile +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/README +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/example.c +1 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/libchash.c +1 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/libchash.h +1 -0
- data/ext/sparsehash-2.0.2/install-sh +520 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/acx_pthread.m4 +34 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/google_namespace.m4 +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/namespaces.m4 +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/stl_hash.m4 +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/stl_hash_fun.m4 +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/missing +60 -44
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb.sh +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/README +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/changelog +42 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/compat +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/control +1 -1
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/copyright +5 -4
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/docs +0 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/rules +0 -0
- data/ext/sparsehash-2.0.2/packages/deb/sparsehash.dirs +5 -0
- data/ext/sparsehash-2.0.2/packages/deb/sparsehash.install +6 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/rpm.sh +1 -1
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/rpm/rpm.spec +5 -3
- data/ext/{sparsehash-1.8.1/google-sparsehash.sln → sparsehash-2.0.2/sparsehash.sln} +0 -0
- data/ext/sparsehash-2.0.2/src/config.h +132 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/config.h.in +0 -3
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/config.h.include +0 -1
- data/ext/sparsehash-2.0.2/src/google/dense_hash_map +34 -0
- data/ext/sparsehash-2.0.2/src/google/dense_hash_set +34 -0
- data/ext/sparsehash-2.0.2/src/google/sparse_hash_map +34 -0
- data/ext/sparsehash-2.0.2/src/google/sparse_hash_set +34 -0
- data/ext/sparsehash-2.0.2/src/google/sparsehash/densehashtable.h +34 -0
- data/ext/sparsehash-2.0.2/src/google/sparsehash/hashtable-common.h +34 -0
- data/ext/sparsehash-2.0.2/src/google/sparsehash/libc_allocator_with_realloc.h +34 -0
- data/ext/sparsehash-2.0.2/src/google/sparsehash/sparsehashtable.h +34 -0
- data/ext/sparsehash-2.0.2/src/google/sparsetable +34 -0
- data/ext/sparsehash-2.0.2/src/google/template_util.h +34 -0
- data/ext/sparsehash-2.0.2/src/google/type_traits.h +34 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/hash_test_interface.h +64 -37
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/hashtable_test.cc +415 -141
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/libc_allocator_with_realloc_test.cc +16 -23
- data/ext/sparsehash-2.0.2/src/simple_compat_test.cc +106 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/simple_test.cc +8 -5
- data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/dense_hash_map +80 -37
- data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/dense_hash_set +64 -34
- data/ext/{sparsehash-1.8.1/src/google/sparsehash → sparsehash-2.0.2/src/sparsehash/internal}/densehashtable.h +247 -173
- data/ext/sparsehash-2.0.2/src/sparsehash/internal/hashtable-common.h +381 -0
- data/ext/{sparsehash-1.8.1/src/google/sparsehash → sparsehash-2.0.2/src/sparsehash/internal}/libc_allocator_with_realloc.h +5 -7
- data/ext/{sparsehash-1.8.1/src/google/sparsehash → sparsehash-2.0.2/src/sparsehash/internal}/sparsehashtable.h +154 -93
- data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/sparse_hash_map +96 -36
- data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/sparse_hash_set +85 -32
- data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/sparsetable +520 -258
- data/ext/sparsehash-2.0.2/src/sparsehash/template_util.h +134 -0
- data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/type_traits.h +153 -35
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/sparsetable_unittest.cc +108 -22
- data/ext/sparsehash-2.0.2/src/stamp-h1 +1 -0
- data/ext/sparsehash-2.0.2/src/template_util_unittest.cc +134 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/testutil.h +16 -1
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/time_hash_map.cc +259 -94
- data/ext/sparsehash-2.0.2/src/type_traits_unittest.cc +636 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/windows/config.h +4 -4
- data/ext/sparsehash-2.0.2/src/windows/google/sparsehash/sparseconfig.h +49 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/windows/port.cc +1 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/windows/port.h +4 -13
- data/ext/sparsehash-2.0.2/src/windows/sparsehash/internal/sparseconfig.h +49 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/hashtable_test/hashtable_test.vcproj +11 -11
- data/ext/sparsehash-2.0.2/vsprojects/libc_allocator_with_realloc_test/libc_allocator_with_realloc_test.vcproj +161 -0
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/simple_test/simple_test.vcproj +10 -10
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/sparsetable_unittest/sparsetable_unittest.vcproj +4 -4
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/time_hash_map/time_hash_map.vcproj +10 -10
- data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/type_traits_unittest/type_traits_unittest.vcproj +3 -3
- data/ext/spec.bat +0 -0
- data/ext/template/google_hash.cpp.erb +6 -5
- metadata +106 -86
- data/ext/sparsehash-1.8.1/AUTHORS +0 -2
- data/ext/sparsehash-1.8.1/INSTALL +0 -236
- data/ext/sparsehash-1.8.1/NEWS +0 -71
- data/ext/sparsehash-1.8.1/compile +0 -99
- data/ext/sparsehash-1.8.1/install-sh +0 -323
- data/ext/sparsehash-1.8.1/m4/stl_namespace.m4 +0 -25
- data/ext/sparsehash-1.8.1/mkinstalldirs +0 -158
- data/ext/sparsehash-1.8.1/packages/deb/sparsehash.dirs +0 -2
- data/ext/sparsehash-1.8.1/packages/deb/sparsehash.install +0 -2
- data/ext/sparsehash-1.8.1/src/google/sparsehash/hashtable-common.h +0 -178
- data/ext/sparsehash-1.8.1/src/type_traits_unittest.cc +0 -502
- data/ext/sparsehash-1.8.1/src/windows/google/sparsehash/sparseconfig.h +0 -32
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Copyright (c) 2012, Google Inc.
|
|
2
|
+
// All rights reserved.
|
|
3
|
+
//
|
|
4
|
+
// Redistribution and use in source and binary forms, with or without
|
|
5
|
+
// modification, are permitted provided that the following conditions are
|
|
6
|
+
// met:
|
|
7
|
+
//
|
|
8
|
+
// * Redistributions of source code must retain the above copyright
|
|
9
|
+
// notice, this list of conditions and the following disclaimer.
|
|
10
|
+
// * Redistributions in binary form must reproduce the above
|
|
11
|
+
// copyright notice, this list of conditions and the following disclaimer
|
|
12
|
+
// in the documentation and/or other materials provided with the
|
|
13
|
+
// distribution.
|
|
14
|
+
// * Neither the name of Google Inc. nor the names of its
|
|
15
|
+
// contributors may be used to endorse or promote products derived from
|
|
16
|
+
// this software without specific prior written permission.
|
|
17
|
+
//
|
|
18
|
+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
19
|
+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
20
|
+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
21
|
+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
22
|
+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
23
|
+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
24
|
+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
25
|
+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
26
|
+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
27
|
+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
|
+
|
|
30
|
+
// Header files have moved from the google directory to the sparsehash
|
|
31
|
+
// directory. This forwarding file is provided only for backwards
|
|
32
|
+
// compatibility. Use <sparsehash/*> in all new code.
|
|
33
|
+
|
|
34
|
+
#include <sparsehash/template_util.h>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Copyright (c) 2012, Google Inc.
|
|
2
|
+
// All rights reserved.
|
|
3
|
+
//
|
|
4
|
+
// Redistribution and use in source and binary forms, with or without
|
|
5
|
+
// modification, are permitted provided that the following conditions are
|
|
6
|
+
// met:
|
|
7
|
+
//
|
|
8
|
+
// * Redistributions of source code must retain the above copyright
|
|
9
|
+
// notice, this list of conditions and the following disclaimer.
|
|
10
|
+
// * Redistributions in binary form must reproduce the above
|
|
11
|
+
// copyright notice, this list of conditions and the following disclaimer
|
|
12
|
+
// in the documentation and/or other materials provided with the
|
|
13
|
+
// distribution.
|
|
14
|
+
// * Neither the name of Google Inc. nor the names of its
|
|
15
|
+
// contributors may be used to endorse or promote products derived from
|
|
16
|
+
// this software without specific prior written permission.
|
|
17
|
+
//
|
|
18
|
+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
19
|
+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
20
|
+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
21
|
+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
22
|
+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
23
|
+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
24
|
+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
25
|
+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
26
|
+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
27
|
+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
|
+
|
|
30
|
+
// Header files have moved from the google directory to the sparsehash
|
|
31
|
+
// directory. This forwarding file is provided only for backwards
|
|
32
|
+
// compatibility. Use <sparsehash/*> in all new code.
|
|
33
|
+
|
|
34
|
+
#include <sparsehash/type_traits.h>
|
|
@@ -27,8 +27,7 @@
|
|
|
27
27
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
28
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
29
|
|
|
30
|
-
//
|
|
31
|
-
// Author: Craig Silverstein
|
|
30
|
+
// ---
|
|
32
31
|
//
|
|
33
32
|
// This implements a uniform interface for all 6 hash implementations:
|
|
34
33
|
// dense_hashtable, dense_hash_map, dense_hash_set
|
|
@@ -46,15 +45,15 @@
|
|
|
46
45
|
#ifndef UTIL_GTL_HASH_TEST_INTERFACE_H_
|
|
47
46
|
#define UTIL_GTL_HASH_TEST_INTERFACE_H_
|
|
48
47
|
|
|
49
|
-
#include
|
|
50
|
-
#include
|
|
51
|
-
#include <
|
|
52
|
-
#include <
|
|
53
|
-
#include <
|
|
54
|
-
#include <
|
|
55
|
-
#include <
|
|
56
|
-
#include <
|
|
57
|
-
#include
|
|
48
|
+
#include <sparsehash/internal/sparseconfig.h>
|
|
49
|
+
#include <functional> // for equal_to<>
|
|
50
|
+
#include <sparsehash/internal/sparsehashtable.h>
|
|
51
|
+
#include <sparsehash/sparse_hash_map>
|
|
52
|
+
#include <sparsehash/sparse_hash_set>
|
|
53
|
+
#include <sparsehash/internal/densehashtable.h>
|
|
54
|
+
#include <sparsehash/dense_hash_map>
|
|
55
|
+
#include <sparsehash/dense_hash_set>
|
|
56
|
+
#include HASH_FUN_H // for hash<>
|
|
58
57
|
|
|
59
58
|
_START_GOOGLE_NAMESPACE_
|
|
60
59
|
|
|
@@ -271,17 +270,18 @@ class BaseHashtableInterface {
|
|
|
271
270
|
|
|
272
271
|
size_type count(const key_type& key) const { return ht_.count(key); }
|
|
273
272
|
|
|
274
|
-
pair<iterator, iterator> equal_range(const key_type& key) {
|
|
275
|
-
pair<typename HT::iterator, typename HT::iterator> r
|
|
273
|
+
std::pair<iterator, iterator> equal_range(const key_type& key) {
|
|
274
|
+
std::pair<typename HT::iterator, typename HT::iterator> r
|
|
276
275
|
= ht_.equal_range(key);
|
|
277
|
-
return pair<iterator, iterator>(iterator(r.first, this),
|
|
276
|
+
return std::pair<iterator, iterator>(iterator(r.first, this),
|
|
278
277
|
iterator(r.second, this));
|
|
279
278
|
}
|
|
280
|
-
pair<const_iterator, const_iterator> equal_range(const key_type& key)
|
|
281
|
-
|
|
279
|
+
std::pair<const_iterator, const_iterator> equal_range(const key_type& key)
|
|
280
|
+
const {
|
|
281
|
+
std::pair<typename HT::const_iterator, typename HT::const_iterator> r
|
|
282
282
|
= ht_.equal_range(key);
|
|
283
|
-
return pair<const_iterator, const_iterator>(
|
|
284
|
-
|
|
283
|
+
return std::pair<const_iterator, const_iterator>(
|
|
284
|
+
const_iterator(r.first, this), const_iterator(r.second, this));
|
|
285
285
|
}
|
|
286
286
|
|
|
287
287
|
const_iterator random_element(class ACMRandom* r) const {
|
|
@@ -291,9 +291,9 @@ class BaseHashtableInterface {
|
|
|
291
291
|
return iterator(ht_.random_element(r), this);
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
-
pair<iterator, bool> insert(const value_type& obj) {
|
|
295
|
-
pair<typename HT::iterator, bool> r = ht_.insert(obj);
|
|
296
|
-
return pair<iterator, bool>(iterator(r.first, this), r.second);
|
|
294
|
+
std::pair<iterator, bool> insert(const value_type& obj) {
|
|
295
|
+
std::pair<typename HT::iterator, bool> r = ht_.insert(obj);
|
|
296
|
+
return std::pair<iterator, bool>(iterator(r.first, this), r.second);
|
|
297
297
|
}
|
|
298
298
|
template <class InputIterator>
|
|
299
299
|
void insert(InputIterator f, InputIterator l) {
|
|
@@ -328,6 +328,15 @@ class BaseHashtableInterface {
|
|
|
328
328
|
return ht_ != other.ht_;
|
|
329
329
|
}
|
|
330
330
|
|
|
331
|
+
template <typename ValueSerializer, typename OUTPUT>
|
|
332
|
+
bool serialize(ValueSerializer serializer, OUTPUT *fp) {
|
|
333
|
+
return ht_.serialize(serializer, fp);
|
|
334
|
+
}
|
|
335
|
+
template <typename ValueSerializer, typename INPUT>
|
|
336
|
+
bool unserialize(ValueSerializer serializer, INPUT *fp) {
|
|
337
|
+
return ht_.unserialize(serializer, fp);
|
|
338
|
+
}
|
|
339
|
+
|
|
331
340
|
template <typename OUTPUT>
|
|
332
341
|
bool write_metadata(OUTPUT *fp) {
|
|
333
342
|
return ht_.write_metadata(fp);
|
|
@@ -364,6 +373,7 @@ class BaseHashtableInterface {
|
|
|
364
373
|
virtual bool supports_brackets() const = 0; // has a 'real' operator[]
|
|
365
374
|
virtual bool supports_readwrite() const = 0;
|
|
366
375
|
virtual bool supports_num_table_copies() const = 0;
|
|
376
|
+
virtual bool supports_serialization() const = 0;
|
|
367
377
|
|
|
368
378
|
protected:
|
|
369
379
|
HT ht_;
|
|
@@ -378,9 +388,9 @@ class BaseHashtableInterface {
|
|
|
378
388
|
// ---------------------------------------------------------------------
|
|
379
389
|
|
|
380
390
|
template <class Key, class T,
|
|
381
|
-
class HashFcn =
|
|
382
|
-
class EqualKey =
|
|
383
|
-
class Alloc = libc_allocator_with_realloc<pair<const Key, T> > >
|
|
391
|
+
class HashFcn = SPARSEHASH_HASH<Key>,
|
|
392
|
+
class EqualKey = std::equal_to<Key>,
|
|
393
|
+
class Alloc = libc_allocator_with_realloc<std::pair<const Key, T> > >
|
|
384
394
|
class HashtableInterface_SparseHashMap
|
|
385
395
|
: public BaseHashtableInterface< sparse_hash_map<Key, T, HashFcn,
|
|
386
396
|
EqualKey, Alloc> > {
|
|
@@ -421,12 +431,16 @@ class HashtableInterface_SparseHashMap
|
|
|
421
431
|
bool supports_brackets() const { return true; }
|
|
422
432
|
bool supports_readwrite() const { return true; }
|
|
423
433
|
bool supports_num_table_copies() const { return false; }
|
|
434
|
+
bool supports_serialization() const { return true; }
|
|
424
435
|
|
|
425
436
|
void set_empty_key(const typename p::key_type& k) { }
|
|
426
437
|
void clear_empty_key() { }
|
|
427
438
|
typename p::key_type empty_key() const { return typename p::key_type(); }
|
|
439
|
+
|
|
428
440
|
int num_table_copies() const { return 0; }
|
|
429
441
|
|
|
442
|
+
typedef typename ht::NopointerSerializer NopointerSerializer;
|
|
443
|
+
|
|
430
444
|
protected:
|
|
431
445
|
template <class K2, class T2, class H2, class E2, class A2>
|
|
432
446
|
friend void swap(HashtableInterface_SparseHashMap<K2,T2,H2,E2,A2>& a,
|
|
@@ -456,8 +470,8 @@ void swap(HashtableInterface_SparseHashMap<K,T,H,E,A>& a,
|
|
|
456
470
|
// ---------------------------------------------------------------------
|
|
457
471
|
|
|
458
472
|
template <class Value,
|
|
459
|
-
class HashFcn =
|
|
460
|
-
class EqualKey =
|
|
473
|
+
class HashFcn = SPARSEHASH_HASH<Value>,
|
|
474
|
+
class EqualKey = std::equal_to<Value>,
|
|
461
475
|
class Alloc = libc_allocator_with_realloc<Value> >
|
|
462
476
|
class HashtableInterface_SparseHashSet
|
|
463
477
|
: public BaseHashtableInterface< sparse_hash_set<Value, HashFcn,
|
|
@@ -524,12 +538,16 @@ class HashtableInterface_SparseHashSet
|
|
|
524
538
|
bool supports_brackets() const { return false; }
|
|
525
539
|
bool supports_readwrite() const { return true; }
|
|
526
540
|
bool supports_num_table_copies() const { return false; }
|
|
541
|
+
bool supports_serialization() const { return true; }
|
|
527
542
|
|
|
528
543
|
void set_empty_key(const typename p::key_type& k) { }
|
|
529
544
|
void clear_empty_key() { }
|
|
530
545
|
typename p::key_type empty_key() const { return typename p::key_type(); }
|
|
546
|
+
|
|
531
547
|
int num_table_copies() const { return 0; }
|
|
532
548
|
|
|
549
|
+
typedef typename ht::NopointerSerializer NopointerSerializer;
|
|
550
|
+
|
|
533
551
|
protected:
|
|
534
552
|
template <class K2, class H2, class E2, class A2>
|
|
535
553
|
friend void swap(HashtableInterface_SparseHashSet<K2,H2,E2,A2>& a,
|
|
@@ -636,6 +654,7 @@ class HashtableInterface_SparseHashtable
|
|
|
636
654
|
bool supports_brackets() const { return false; }
|
|
637
655
|
bool supports_readwrite() const { return true; }
|
|
638
656
|
bool supports_num_table_copies() const { return true; }
|
|
657
|
+
bool supports_serialization() const { return true; }
|
|
639
658
|
|
|
640
659
|
void set_empty_key(const typename p::key_type& k) { }
|
|
641
660
|
void clear_empty_key() { }
|
|
@@ -647,6 +666,8 @@ class HashtableInterface_SparseHashtable
|
|
|
647
666
|
|
|
648
667
|
// TODO(csilvers): also support/test destructive_begin()/destructive_end()?
|
|
649
668
|
|
|
669
|
+
typedef typename ht::NopointerSerializer NopointerSerializer;
|
|
670
|
+
|
|
650
671
|
protected:
|
|
651
672
|
template <class V2, class K2, class HF2, class EK2, class SK2, class Eq2,
|
|
652
673
|
class A2>
|
|
@@ -684,9 +705,9 @@ void swap(HashtableInterface_SparseHashtable<V,K,HF,EK,SK,Eq,A>& a,
|
|
|
684
705
|
// value saying what the empty key is.
|
|
685
706
|
|
|
686
707
|
template <class Key, class T, const Key& EMPTY_KEY,
|
|
687
|
-
class HashFcn =
|
|
688
|
-
class EqualKey =
|
|
689
|
-
class Alloc = libc_allocator_with_realloc<pair<const Key, T> > >
|
|
708
|
+
class HashFcn = SPARSEHASH_HASH<Key>,
|
|
709
|
+
class EqualKey = std::equal_to<Key>,
|
|
710
|
+
class Alloc = libc_allocator_with_realloc<std::pair<const Key, T> > >
|
|
690
711
|
class HashtableInterface_DenseHashMap
|
|
691
712
|
: public BaseHashtableInterface< dense_hash_map<Key, T, HashFcn,
|
|
692
713
|
EqualKey, Alloc> > {
|
|
@@ -733,9 +754,11 @@ class HashtableInterface_DenseHashMap
|
|
|
733
754
|
bool supports_brackets() const { return true; }
|
|
734
755
|
bool supports_readwrite() const { return false; }
|
|
735
756
|
bool supports_num_table_copies() const { return false; }
|
|
757
|
+
bool supports_serialization() const { return true; }
|
|
736
758
|
|
|
737
|
-
|
|
738
|
-
template <typename
|
|
759
|
+
typedef typename ht::NopointerSerializer NopointerSerializer;
|
|
760
|
+
template <typename OUTPUT> bool write_metadata(OUTPUT *) { return false; }
|
|
761
|
+
template <typename INPUT> bool read_metadata(INPUT *) { return false; }
|
|
739
762
|
template <typename OUTPUT> bool write_nopointer_data(OUTPUT *) {
|
|
740
763
|
return false;
|
|
741
764
|
}
|
|
@@ -776,8 +799,8 @@ void swap(HashtableInterface_DenseHashMap<K,T,Empty,H,E,A>& a,
|
|
|
776
799
|
// value saying what the empty key is.
|
|
777
800
|
|
|
778
801
|
template <class Value, const Value& EMPTY_KEY,
|
|
779
|
-
class HashFcn =
|
|
780
|
-
class EqualKey =
|
|
802
|
+
class HashFcn = SPARSEHASH_HASH<Value>,
|
|
803
|
+
class EqualKey = std::equal_to<Value>,
|
|
781
804
|
class Alloc = libc_allocator_with_realloc<Value> >
|
|
782
805
|
class HashtableInterface_DenseHashSet
|
|
783
806
|
: public BaseHashtableInterface< dense_hash_set<Value, HashFcn,
|
|
@@ -835,9 +858,11 @@ class HashtableInterface_DenseHashSet
|
|
|
835
858
|
bool supports_brackets() const { return false; }
|
|
836
859
|
bool supports_readwrite() const { return false; }
|
|
837
860
|
bool supports_num_table_copies() const { return false; }
|
|
861
|
+
bool supports_serialization() const { return true; }
|
|
838
862
|
|
|
839
|
-
|
|
840
|
-
template <typename
|
|
863
|
+
typedef typename ht::NopointerSerializer NopointerSerializer;
|
|
864
|
+
template <typename OUTPUT> bool write_metadata(OUTPUT *) { return false; }
|
|
865
|
+
template <typename INPUT> bool read_metadata(INPUT *) { return false; }
|
|
841
866
|
template <typename OUTPUT> bool write_nopointer_data(OUTPUT *) {
|
|
842
867
|
return false;
|
|
843
868
|
}
|
|
@@ -960,9 +985,11 @@ class HashtableInterface_DenseHashtable
|
|
|
960
985
|
bool supports_brackets() const { return false; }
|
|
961
986
|
bool supports_readwrite() const { return false; }
|
|
962
987
|
bool supports_num_table_copies() const { return true; }
|
|
988
|
+
bool supports_serialization() const { return true; }
|
|
963
989
|
|
|
964
|
-
|
|
965
|
-
template <typename
|
|
990
|
+
typedef typename ht::NopointerSerializer NopointerSerializer;
|
|
991
|
+
template <typename OUTPUT> bool write_metadata(OUTPUT *) { return false; }
|
|
992
|
+
template <typename INPUT> bool read_metadata(INPUT *) { return false; }
|
|
966
993
|
template <typename OUTPUT> bool write_nopointer_data(OUTPUT *) {
|
|
967
994
|
return false;
|
|
968
995
|
}
|
|
@@ -27,71 +27,86 @@
|
|
|
27
27
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
28
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
29
|
|
|
30
|
-
//
|
|
31
|
-
// Author: Craig Silverstein
|
|
30
|
+
// ---
|
|
32
31
|
//
|
|
33
|
-
// This tests
|
|
34
|
-
// This tests
|
|
35
|
-
// This tests
|
|
36
|
-
// This tests
|
|
37
|
-
// This tests
|
|
38
|
-
// This tests
|
|
32
|
+
// This tests densehashtable
|
|
33
|
+
// This tests dense_hash_set
|
|
34
|
+
// This tests dense_hash_map
|
|
35
|
+
// This tests sparsehashtable
|
|
36
|
+
// This tests sparse_hash_set
|
|
37
|
+
// This tests sparse_hash_map
|
|
39
38
|
//
|
|
40
|
-
// This test
|
|
41
|
-
// unreadable.
|
|
39
|
+
// This test replaces hashtable_unittest.cc, which was becoming
|
|
40
|
+
// unreadable. This file is opaque but hopefully not unreadable -- at
|
|
41
|
+
// least, not the tests!
|
|
42
42
|
//
|
|
43
43
|
// Note that since all these classes are templatized, it's important
|
|
44
44
|
// to call every public method on the class: not just to make sure
|
|
45
45
|
// they work, but to make sure they even compile.
|
|
46
46
|
|
|
47
|
-
#
|
|
48
|
-
|
|
49
|
-
// This causes some "type conversion too small" errors when using this
|
|
50
|
-
// allocator with sparsetable buckets. We're testing to make sure we
|
|
51
|
-
// handle that situation ok, so we don't need the compiler warnings.
|
|
52
|
-
#pragma warning(disable:4244)
|
|
53
|
-
#endif
|
|
54
|
-
|
|
55
|
-
#include "config.h"
|
|
47
|
+
#include <sparsehash/internal/sparseconfig.h>
|
|
48
|
+
#include <config.h>
|
|
56
49
|
#include <math.h>
|
|
50
|
+
#include <stddef.h> // for size_t
|
|
57
51
|
#include <stdlib.h>
|
|
58
52
|
#include <string.h>
|
|
53
|
+
#ifdef HAVE_STDINT_H
|
|
54
|
+
# include <stdint.h>
|
|
55
|
+
#endif // for uintptr_t
|
|
59
56
|
#include <iostream>
|
|
60
57
|
#include <set>
|
|
58
|
+
#include <sstream>
|
|
59
|
+
#include <typeinfo> // for class typeinfo (returned by typeid)
|
|
61
60
|
#include <vector>
|
|
62
|
-
#include <
|
|
63
|
-
#include <
|
|
61
|
+
#include <sparsehash/type_traits.h>
|
|
62
|
+
#include <sparsehash/sparsetable>
|
|
64
63
|
#include "hash_test_interface.h"
|
|
65
64
|
#include "testutil.h"
|
|
65
|
+
namespace testing = GOOGLE_NAMESPACE::testing;
|
|
66
66
|
|
|
67
|
-
using
|
|
68
|
-
using
|
|
69
|
-
using
|
|
67
|
+
using std::cout;
|
|
68
|
+
using std::pair;
|
|
69
|
+
using std::set;
|
|
70
|
+
using std::string;
|
|
71
|
+
using std::vector;
|
|
70
72
|
using GOOGLE_NAMESPACE::dense_hash_map;
|
|
71
73
|
using GOOGLE_NAMESPACE::dense_hash_set;
|
|
74
|
+
using GOOGLE_NAMESPACE::sparse_hash_map;
|
|
75
|
+
using GOOGLE_NAMESPACE::sparse_hash_set;
|
|
76
|
+
using GOOGLE_NAMESPACE::sparsetable;
|
|
72
77
|
using GOOGLE_NAMESPACE::HashtableInterface_SparseHashMap;
|
|
73
78
|
using GOOGLE_NAMESPACE::HashtableInterface_SparseHashSet;
|
|
74
79
|
using GOOGLE_NAMESPACE::HashtableInterface_SparseHashtable;
|
|
75
80
|
using GOOGLE_NAMESPACE::HashtableInterface_DenseHashMap;
|
|
76
81
|
using GOOGLE_NAMESPACE::HashtableInterface_DenseHashSet;
|
|
77
82
|
using GOOGLE_NAMESPACE::HashtableInterface_DenseHashtable;
|
|
78
|
-
namespace
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
namespace sparsehash_internal = GOOGLE_NAMESPACE::sparsehash_internal;
|
|
84
|
+
|
|
85
|
+
typedef unsigned char uint8;
|
|
86
|
+
|
|
87
|
+
#ifdef _MSC_VER
|
|
88
|
+
// Below, we purposefully test having a very small allocator size.
|
|
89
|
+
// This causes some "type conversion too small" errors when using this
|
|
90
|
+
// allocator with sparsetable buckets. We're testing to make sure we
|
|
91
|
+
// handle that situation ok, so we don't need the compiler warnings.
|
|
92
|
+
#pragma warning(disable:4244)
|
|
93
|
+
#endif
|
|
84
94
|
|
|
85
95
|
namespace {
|
|
86
96
|
|
|
87
97
|
#ifndef _MSC_VER // windows defines its own version
|
|
98
|
+
# ifdef __MINGW32__ // mingw has trouble writing to /tmp
|
|
99
|
+
static string TmpFile(const char* basename) {
|
|
100
|
+
return string("./#") + basename;
|
|
101
|
+
}
|
|
102
|
+
# else
|
|
88
103
|
static string TmpFile(const char* basename) {
|
|
89
|
-
|
|
104
|
+
string kTmpdir = "/tmp";
|
|
105
|
+
return kTmpdir + "/" + basename;
|
|
90
106
|
}
|
|
107
|
+
# endif
|
|
91
108
|
#endif
|
|
92
109
|
|
|
93
|
-
typedef unsigned char uint8;
|
|
94
|
-
|
|
95
110
|
// Used as a value in some of the hashtable tests. It's just some
|
|
96
111
|
// arbitrary user-defined type with non-trivial memory management.
|
|
97
112
|
struct ValueType {
|
|
@@ -161,6 +176,10 @@ struct Hasher {
|
|
|
161
176
|
hash = 33 * hash + a[i];
|
|
162
177
|
return hash;
|
|
163
178
|
}
|
|
179
|
+
size_t operator()(const int* a) const {
|
|
180
|
+
num_hashes_++;
|
|
181
|
+
return static_cast<size_t>(reinterpret_cast<uintptr_t>(a));
|
|
182
|
+
}
|
|
164
183
|
bool operator()(int a, int b) const {
|
|
165
184
|
num_compares_++;
|
|
166
185
|
return a == b;
|
|
@@ -257,11 +276,13 @@ struct Alloc {
|
|
|
257
276
|
// be their own inverse: f(f(x)) == x.
|
|
258
277
|
template<class Value>
|
|
259
278
|
struct Negation {
|
|
279
|
+
typedef Value result_type;
|
|
260
280
|
Value operator()(Value& v) { return -v; }
|
|
261
281
|
const Value operator()(const Value& v) const { return -v; }
|
|
262
282
|
};
|
|
263
283
|
|
|
264
284
|
struct Capital {
|
|
285
|
+
typedef string result_type;
|
|
265
286
|
string operator()(string& s) {
|
|
266
287
|
return string(1, s[0] ^ 32) + s.substr(1);
|
|
267
288
|
}
|
|
@@ -271,6 +292,7 @@ struct Capital {
|
|
|
271
292
|
};
|
|
272
293
|
|
|
273
294
|
struct Identity { // lame, I know, but an important case to test.
|
|
295
|
+
typedef const char* result_type;
|
|
274
296
|
const char* operator()(const char* s) const {
|
|
275
297
|
return s;
|
|
276
298
|
}
|
|
@@ -328,8 +350,67 @@ template<> pair<const char* const,ValueType> UniqueObjectHelper(int index) {
|
|
|
328
350
|
UniqueObjectHelper<char*>(index), UniqueObjectHelper<ValueType>(index+1));
|
|
329
351
|
}
|
|
330
352
|
|
|
353
|
+
class ValueSerializer {
|
|
354
|
+
public:
|
|
355
|
+
bool operator()(FILE* fp, const int& value) {
|
|
356
|
+
return fwrite(&value, sizeof(value), 1, fp) == 1;
|
|
357
|
+
}
|
|
358
|
+
bool operator()(FILE* fp, int* value) {
|
|
359
|
+
return fread(value, sizeof(*value), 1, fp) == 1;
|
|
360
|
+
}
|
|
361
|
+
bool operator()(FILE* fp, const string& value) {
|
|
362
|
+
const int size = value.size();
|
|
363
|
+
return (*this)(fp, size) && fwrite(value.c_str(), size, 1, fp) == 1;
|
|
364
|
+
}
|
|
365
|
+
bool operator()(FILE* fp, string* value) {
|
|
366
|
+
int size;
|
|
367
|
+
if (!(*this)(fp, &size)) return false;
|
|
368
|
+
char* buf = new char[size];
|
|
369
|
+
if (fread(buf, size, 1, fp) != 1) {
|
|
370
|
+
delete[] buf;
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
new(value) string(buf, size);
|
|
374
|
+
delete[] buf;
|
|
375
|
+
return true;
|
|
376
|
+
}
|
|
377
|
+
template <typename OUTPUT>
|
|
378
|
+
bool operator()(OUTPUT* fp, const ValueType& v) {
|
|
379
|
+
return (*this)(fp, string(v.s()));
|
|
380
|
+
}
|
|
381
|
+
template <typename INPUT>
|
|
382
|
+
bool operator()(INPUT* fp, ValueType* v) {
|
|
383
|
+
string data;
|
|
384
|
+
if (!(*this)(fp, &data)) return false;
|
|
385
|
+
new(v) ValueType(data.c_str());
|
|
386
|
+
return true;
|
|
387
|
+
}
|
|
388
|
+
template <typename OUTPUT>
|
|
389
|
+
bool operator()(OUTPUT* fp, const char* const& value) {
|
|
390
|
+
// Just store the index.
|
|
391
|
+
return (*this)(fp, atoi(value));
|
|
392
|
+
}
|
|
393
|
+
template <typename INPUT>
|
|
394
|
+
bool operator()(INPUT* fp, const char** value) {
|
|
395
|
+
// Look up via index.
|
|
396
|
+
int index;
|
|
397
|
+
if (!(*this)(fp, &index)) return false;
|
|
398
|
+
*value = UniqueObjectHelper<char*>(index);
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
template <typename OUTPUT, typename First, typename Second>
|
|
402
|
+
bool operator()(OUTPUT* fp, std::pair<const First, Second>* value) {
|
|
403
|
+
return (*this)(fp, const_cast<First*>(&value->first))
|
|
404
|
+
&& (*this)(fp, &value->second);
|
|
405
|
+
}
|
|
406
|
+
template <typename INPUT, typename First, typename Second>
|
|
407
|
+
bool operator()(INPUT* fp, const std::pair<const First, Second>& value) {
|
|
408
|
+
return (*this)(fp, value.first) && (*this)(fp, value.second);
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
|
|
331
412
|
template <typename HashtableType>
|
|
332
|
-
class HashtableTest {
|
|
413
|
+
class HashtableTest : public ::testing::Test {
|
|
333
414
|
public:
|
|
334
415
|
HashtableTest() : ht_() { }
|
|
335
416
|
// Give syntactically-prettier access to UniqueObjectHelper.
|
|
@@ -419,27 +500,58 @@ namespace {
|
|
|
419
500
|
// We need to define the same class 4 times due to limitations in the
|
|
420
501
|
// testing framework. Basically, we associate each class below with
|
|
421
502
|
// the set of types we want to run tests on it with.
|
|
422
|
-
typedef testing::TypeList6<INT_HASHTABLES> IntHashtables;
|
|
423
503
|
template <typename HashtableType> class HashtableIntTest
|
|
424
504
|
: public HashtableTest<HashtableType> { };
|
|
425
|
-
TYPED_TEST_CASE_6(HashtableIntTest, IntHashtables);
|
|
426
|
-
|
|
427
|
-
typedef testing::TypeList6<STRING_HASHTABLES> StringHashtables;
|
|
428
505
|
template <typename HashtableType> class HashtableStringTest
|
|
429
506
|
: public HashtableTest<HashtableType> { };
|
|
430
|
-
TYPED_TEST_CASE_6(HashtableStringTest, StringHashtables);
|
|
431
|
-
|
|
432
|
-
typedef testing::TypeList6<CHARSTAR_HASHTABLES> CharStarHashtables;
|
|
433
507
|
template <typename HashtableType> class HashtableCharStarTest
|
|
434
508
|
: public HashtableTest<HashtableType> { };
|
|
435
|
-
|
|
509
|
+
template <typename HashtableType> class HashtableAllTest
|
|
510
|
+
: public HashtableTest<HashtableType> { };
|
|
436
511
|
|
|
512
|
+
typedef testing::TypeList6<INT_HASHTABLES> IntHashtables;
|
|
513
|
+
typedef testing::TypeList6<STRING_HASHTABLES> StringHashtables;
|
|
514
|
+
typedef testing::TypeList6<CHARSTAR_HASHTABLES> CharStarHashtables;
|
|
437
515
|
typedef testing::TypeList18<INT_HASHTABLES, STRING_HASHTABLES,
|
|
438
516
|
CHARSTAR_HASHTABLES> AllHashtables;
|
|
439
|
-
|
|
440
|
-
|
|
517
|
+
|
|
518
|
+
TYPED_TEST_CASE_6(HashtableIntTest, IntHashtables);
|
|
519
|
+
TYPED_TEST_CASE_6(HashtableStringTest, StringHashtables);
|
|
520
|
+
TYPED_TEST_CASE_6(HashtableCharStarTest, CharStarHashtables);
|
|
441
521
|
TYPED_TEST_CASE_18(HashtableAllTest, AllHashtables);
|
|
442
522
|
|
|
523
|
+
// ------------------------------------------------------------------------
|
|
524
|
+
// First, some testing of the underlying infrastructure.
|
|
525
|
+
|
|
526
|
+
TEST(HashtableCommonTest, HashMunging) {
|
|
527
|
+
const Hasher hasher;
|
|
528
|
+
|
|
529
|
+
// We don't munge the hash value on non-pointer template types.
|
|
530
|
+
{
|
|
531
|
+
const sparsehash_internal::sh_hashtable_settings<int, Hasher, size_t, 1>
|
|
532
|
+
settings(hasher, 0.0, 0.0);
|
|
533
|
+
const int v = 1000;
|
|
534
|
+
EXPECT_EQ(hasher(v), settings.hash(v));
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
{
|
|
538
|
+
// We do munge the hash value on pointer template types.
|
|
539
|
+
const sparsehash_internal::sh_hashtable_settings<int*, Hasher, size_t, 1>
|
|
540
|
+
settings(hasher, 0.0, 0.0);
|
|
541
|
+
int* v = NULL;
|
|
542
|
+
v += 0x10000; // get a non-trivial pointer value
|
|
543
|
+
EXPECT_NE(hasher(v), settings.hash(v));
|
|
544
|
+
}
|
|
545
|
+
{
|
|
546
|
+
const sparsehash_internal::sh_hashtable_settings<const int*, Hasher,
|
|
547
|
+
size_t, 1>
|
|
548
|
+
settings(hasher, 0.0, 0.0);
|
|
549
|
+
const int* v = NULL;
|
|
550
|
+
v += 0x10000; // get a non-trivial pointer value
|
|
551
|
+
EXPECT_NE(hasher(v), settings.hash(v));
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
443
555
|
// ------------------------------------------------------------------------
|
|
444
556
|
// If the first arg to TYPED_TEST is HashtableIntTest, it will run
|
|
445
557
|
// this test on all the hashtable types, with key=int and value=int.
|
|
@@ -624,18 +736,20 @@ TYPED_TEST(HashtableIntTest, Constructors) {
|
|
|
624
736
|
EXPECT_LE(1, alloc_count);
|
|
625
737
|
int old_alloc_count = alloc_count;
|
|
626
738
|
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
TypeParam
|
|
635
|
-
TypeParam
|
|
636
|
-
TypeParam
|
|
637
|
-
TypeParam
|
|
638
|
-
|
|
739
|
+
const typename TypeParam::value_type input[] = {
|
|
740
|
+
this->UniqueObject(1),
|
|
741
|
+
this->UniqueObject(2),
|
|
742
|
+
this->UniqueObject(4),
|
|
743
|
+
this->UniqueObject(8)
|
|
744
|
+
};
|
|
745
|
+
const int num_inputs = sizeof(input) / sizeof(input[0]);
|
|
746
|
+
const typename TypeParam::value_type *begin = &input[0];
|
|
747
|
+
const typename TypeParam::value_type *end = begin + num_inputs;
|
|
748
|
+
TypeParam ht_iter_noarg(begin, end);
|
|
749
|
+
TypeParam ht_iter_onearg(begin, end, 100);
|
|
750
|
+
TypeParam ht_iter_twoarg(begin, end, 100, hasher);
|
|
751
|
+
TypeParam ht_iter_threearg(begin, end, 100, hasher, hasher);
|
|
752
|
+
TypeParam ht_iter_fourarg(begin, end, 100, hasher, hasher, alloc);
|
|
639
753
|
// Now the allocator should have been called more.
|
|
640
754
|
EXPECT_GT(alloc_count, old_alloc_count);
|
|
641
755
|
old_alloc_count = alloc_count;
|
|
@@ -781,7 +895,7 @@ TYPED_TEST(HashtableAllTest, Swap) {
|
|
|
781
895
|
|
|
782
896
|
// We purposefully don't swap allocs -- they're not necessarily swappable.
|
|
783
897
|
|
|
784
|
-
// Now swap back, using the free-function swap
|
|
898
|
+
// Now swap back, using the free-function swap
|
|
785
899
|
// NOTE: MSVC seems to have trouble with this free swap, not quite
|
|
786
900
|
// sure why. I've given up trying to fix it though.
|
|
787
901
|
#ifdef _MSC_VER
|
|
@@ -798,6 +912,20 @@ TYPED_TEST(HashtableAllTest, Swap) {
|
|
|
798
912
|
EXPECT_EQ(1u, other_ht.size());
|
|
799
913
|
EXPECT_EQ(1u, this->ht_.count(this->UniqueKey(111)));
|
|
800
914
|
EXPECT_EQ(0u, other_ht.count(this->UniqueKey(111)));
|
|
915
|
+
|
|
916
|
+
// A user reported a crash with this code using swap to clear.
|
|
917
|
+
// We've since fixed the bug; this prevents a regression.
|
|
918
|
+
TypeParam swap_to_clear_ht;
|
|
919
|
+
swap_to_clear_ht.set_deleted_key(this->UniqueKey(1));
|
|
920
|
+
for (int i = 2; i < 10000; ++i) {
|
|
921
|
+
swap_to_clear_ht.insert(this->UniqueObject(i));
|
|
922
|
+
}
|
|
923
|
+
TypeParam empty_ht;
|
|
924
|
+
empty_ht.swap(swap_to_clear_ht);
|
|
925
|
+
swap_to_clear_ht.set_deleted_key(this->UniqueKey(1));
|
|
926
|
+
for (int i = 2; i < 10000; ++i) {
|
|
927
|
+
swap_to_clear_ht.insert(this->UniqueObject(i));
|
|
928
|
+
}
|
|
801
929
|
}
|
|
802
930
|
|
|
803
931
|
TYPED_TEST(HashtableAllTest, Size) {
|
|
@@ -1073,6 +1201,7 @@ TYPED_TEST(HashtableAllTest, BracketInsert) {
|
|
|
1073
1201
|
EXPECT_EQ(2, ht.hash_funct().num_hashes());
|
|
1074
1202
|
}
|
|
1075
1203
|
|
|
1204
|
+
|
|
1076
1205
|
TYPED_TEST(HashtableAllTest, InsertValue) {
|
|
1077
1206
|
// First, try some straightforward insertions.
|
|
1078
1207
|
EXPECT_TRUE(this->ht_.empty());
|
|
@@ -1111,13 +1240,13 @@ TYPED_TEST(HashtableIntTest, InsertRange) {
|
|
|
1111
1240
|
ht_source.insert(this->UniqueObject(100000));
|
|
1112
1241
|
ht_source.insert(this->UniqueObject(1000000));
|
|
1113
1242
|
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1243
|
+
const typename TypeParam::value_type input[] = {
|
|
1244
|
+
// This is a copy of the first element in ht_source.
|
|
1245
|
+
*ht_source.begin(),
|
|
1246
|
+
this->UniqueObject(2),
|
|
1247
|
+
this->UniqueObject(4),
|
|
1248
|
+
this->UniqueObject(8)
|
|
1249
|
+
};
|
|
1121
1250
|
|
|
1122
1251
|
set<typename TypeParam::value_type> set_input;
|
|
1123
1252
|
set_input.insert(this->UniqueObject(1111111));
|
|
@@ -1152,7 +1281,7 @@ TYPED_TEST(HashtableIntTest, InsertRange) {
|
|
|
1152
1281
|
// Insert from input as well, a separate, random-access iterator.
|
|
1153
1282
|
// The first element of input overlaps with an existing element
|
|
1154
1283
|
// of ht_, so this should only up the size by 2.
|
|
1155
|
-
this->ht_.insert(input
|
|
1284
|
+
this->ht_.insert(&input[0], &input[3]);
|
|
1156
1285
|
EXPECT_EQ(8u, this->ht_.size());
|
|
1157
1286
|
}
|
|
1158
1287
|
|
|
@@ -1298,10 +1427,9 @@ TYPED_TEST(HashtableAllTest, Equals) {
|
|
|
1298
1427
|
}
|
|
1299
1428
|
|
|
1300
1429
|
TEST(HashtableTest, IntIO) {
|
|
1301
|
-
// Since
|
|
1302
|
-
// just
|
|
1303
|
-
//
|
|
1304
|
-
// standard reader and writer.
|
|
1430
|
+
// Since the set case is just a special (easier) case than the map case, I
|
|
1431
|
+
// just test on sparse_hash_map. This handles the easy case where we can
|
|
1432
|
+
// use the standard reader and writer.
|
|
1305
1433
|
sparse_hash_map<int, int> ht_out;
|
|
1306
1434
|
ht_out.set_deleted_key(0);
|
|
1307
1435
|
for (int i = 1; i < 1000; i++) {
|
|
@@ -1310,7 +1438,7 @@ TEST(HashtableTest, IntIO) {
|
|
|
1310
1438
|
ht_out.erase(563); // just to test having some erased keys when we write.
|
|
1311
1439
|
ht_out.erase(22);
|
|
1312
1440
|
|
|
1313
|
-
string file(TmpFile("
|
|
1441
|
+
string file(TmpFile("intio"));
|
|
1314
1442
|
FILE* fp = fopen(file.c_str(), "wb");
|
|
1315
1443
|
EXPECT_TRUE(fp != NULL);
|
|
1316
1444
|
EXPECT_TRUE(ht_out.write_metadata(fp));
|
|
@@ -1333,10 +1461,9 @@ TEST(HashtableTest, IntIO) {
|
|
|
1333
1461
|
}
|
|
1334
1462
|
|
|
1335
1463
|
TEST(HashtableTest, StringIO) {
|
|
1336
|
-
// Since
|
|
1337
|
-
// just
|
|
1338
|
-
//
|
|
1339
|
-
// to write our own custom reader/writer for the data.
|
|
1464
|
+
// Since the set case is just a special (easier) case than the map case,
|
|
1465
|
+
// I just test on sparse_hash_map. This handles the difficult case where
|
|
1466
|
+
// we have to write our own custom reader/writer for the data.
|
|
1340
1467
|
sparse_hash_map<string, string, Hasher, Hasher> ht_out;
|
|
1341
1468
|
ht_out.set_deleted_key(string(""));
|
|
1342
1469
|
for (int i = 32; i < 128; i++) {
|
|
@@ -1346,7 +1473,7 @@ TEST(HashtableTest, StringIO) {
|
|
|
1346
1473
|
ht_out.erase("c"); // just to test having some erased keys when we write.
|
|
1347
1474
|
ht_out.erase("y");
|
|
1348
1475
|
|
|
1349
|
-
string file(TmpFile("
|
|
1476
|
+
string file(TmpFile("stringio"));
|
|
1350
1477
|
FILE* fp = fopen(file.c_str(), "wb");
|
|
1351
1478
|
EXPECT_TRUE(fp != NULL);
|
|
1352
1479
|
EXPECT_TRUE(ht_out.write_metadata(fp));
|
|
@@ -1369,14 +1496,14 @@ TEST(HashtableTest, StringIO) {
|
|
|
1369
1496
|
for (sparse_hash_map<string, string, Hasher, Hasher>::iterator
|
|
1370
1497
|
it = ht_in.begin(); it != ht_in.end(); ++it) {
|
|
1371
1498
|
string::size_type first_size;
|
|
1372
|
-
fread(&first_size, sizeof(first_size), 1, fp);
|
|
1499
|
+
EXPECT_EQ(1u, fread(&first_size, sizeof(first_size), 1, fp));
|
|
1373
1500
|
char* first = new char[first_size];
|
|
1374
|
-
fread(first, first_size, 1, fp);
|
|
1501
|
+
EXPECT_EQ(1u, fread(first, first_size, 1, fp));
|
|
1375
1502
|
|
|
1376
1503
|
string::size_type second_size;
|
|
1377
|
-
fread(&second_size, sizeof(second_size), 1, fp);
|
|
1504
|
+
EXPECT_EQ(1u, fread(&second_size, sizeof(second_size), 1, fp));
|
|
1378
1505
|
char* second = new char[second_size];
|
|
1379
|
-
fread(second, second_size, 1, fp);
|
|
1506
|
+
EXPECT_EQ(1u, fread(second, second_size, 1, fp));
|
|
1380
1507
|
|
|
1381
1508
|
// it points to garbage, so we have to use placement-new to initialize.
|
|
1382
1509
|
// We also have to use const-cast since it->first is const.
|
|
@@ -1393,6 +1520,195 @@ TEST(HashtableTest, StringIO) {
|
|
|
1393
1520
|
EXPECT_EQ(string(""), ht_in["y"]);
|
|
1394
1521
|
}
|
|
1395
1522
|
|
|
1523
|
+
TYPED_TEST(HashtableAllTest, Serialization) {
|
|
1524
|
+
if (!this->ht_.supports_serialization()) return;
|
|
1525
|
+
TypeParam ht_out;
|
|
1526
|
+
ht_out.set_deleted_key(this->UniqueKey(2000));
|
|
1527
|
+
for (int i = 1; i < 100; i++) {
|
|
1528
|
+
ht_out.insert(this->UniqueObject(i));
|
|
1529
|
+
}
|
|
1530
|
+
// just to test having some erased keys when we write.
|
|
1531
|
+
ht_out.erase(this->UniqueKey(56));
|
|
1532
|
+
ht_out.erase(this->UniqueKey(22));
|
|
1533
|
+
|
|
1534
|
+
string file(TmpFile("serialization"));
|
|
1535
|
+
FILE* fp = fopen(file.c_str(), "wb");
|
|
1536
|
+
EXPECT_TRUE(fp != NULL);
|
|
1537
|
+
EXPECT_TRUE(ht_out.serialize(ValueSerializer(), fp));
|
|
1538
|
+
fclose(fp);
|
|
1539
|
+
|
|
1540
|
+
TypeParam ht_in;
|
|
1541
|
+
fp = fopen(file.c_str(), "rb");
|
|
1542
|
+
EXPECT_TRUE(fp != NULL);
|
|
1543
|
+
EXPECT_TRUE(ht_in.unserialize(ValueSerializer(), fp));
|
|
1544
|
+
fclose(fp);
|
|
1545
|
+
|
|
1546
|
+
EXPECT_EQ(this->UniqueObject(1), *ht_in.find(this->UniqueKey(1)));
|
|
1547
|
+
EXPECT_EQ(this->UniqueObject(99), *ht_in.find(this->UniqueKey(99)));
|
|
1548
|
+
EXPECT_FALSE(ht_in.count(this->UniqueKey(100)));
|
|
1549
|
+
EXPECT_EQ(this->UniqueObject(21), *ht_in.find(this->UniqueKey(21)));
|
|
1550
|
+
// should not have been saved
|
|
1551
|
+
EXPECT_FALSE(ht_in.count(this->UniqueKey(22)));
|
|
1552
|
+
EXPECT_FALSE(ht_in.count(this->UniqueKey(56)));
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
TYPED_TEST(HashtableIntTest, NopointerSerialization) {
|
|
1556
|
+
if (!this->ht_.supports_serialization()) return;
|
|
1557
|
+
TypeParam ht_out;
|
|
1558
|
+
ht_out.set_deleted_key(this->UniqueKey(2000));
|
|
1559
|
+
for (int i = 1; i < 100; i++) {
|
|
1560
|
+
ht_out.insert(this->UniqueObject(i));
|
|
1561
|
+
}
|
|
1562
|
+
// just to test having some erased keys when we write.
|
|
1563
|
+
ht_out.erase(this->UniqueKey(56));
|
|
1564
|
+
ht_out.erase(this->UniqueKey(22));
|
|
1565
|
+
|
|
1566
|
+
string file(TmpFile("nopointer_serialization"));
|
|
1567
|
+
FILE* fp = fopen(file.c_str(), "wb");
|
|
1568
|
+
EXPECT_TRUE(fp != NULL);
|
|
1569
|
+
EXPECT_TRUE(ht_out.serialize(typename TypeParam::NopointerSerializer(), fp));
|
|
1570
|
+
fclose(fp);
|
|
1571
|
+
|
|
1572
|
+
TypeParam ht_in;
|
|
1573
|
+
fp = fopen(file.c_str(), "rb");
|
|
1574
|
+
EXPECT_TRUE(fp != NULL);
|
|
1575
|
+
EXPECT_TRUE(ht_in.unserialize(typename TypeParam::NopointerSerializer(), fp));
|
|
1576
|
+
fclose(fp);
|
|
1577
|
+
|
|
1578
|
+
EXPECT_EQ(this->UniqueObject(1), *ht_in.find(this->UniqueKey(1)));
|
|
1579
|
+
EXPECT_EQ(this->UniqueObject(99), *ht_in.find(this->UniqueKey(99)));
|
|
1580
|
+
EXPECT_FALSE(ht_in.count(this->UniqueKey(100)));
|
|
1581
|
+
EXPECT_EQ(this->UniqueObject(21), *ht_in.find(this->UniqueKey(21)));
|
|
1582
|
+
// should not have been saved
|
|
1583
|
+
EXPECT_FALSE(ht_in.count(this->UniqueKey(22)));
|
|
1584
|
+
EXPECT_FALSE(ht_in.count(this->UniqueKey(56)));
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
// We don't support serializing to a string by default, but you can do
|
|
1588
|
+
// it by writing your own custom input/output class.
|
|
1589
|
+
class StringIO {
|
|
1590
|
+
public:
|
|
1591
|
+
explicit StringIO(string* s) : s_(s) {}
|
|
1592
|
+
size_t Write(const void* buf, size_t len) {
|
|
1593
|
+
s_->append(reinterpret_cast<const char*>(buf), len);
|
|
1594
|
+
return len;
|
|
1595
|
+
}
|
|
1596
|
+
size_t Read(void* buf, size_t len) {
|
|
1597
|
+
if (s_->length() < len)
|
|
1598
|
+
len = s_->length();
|
|
1599
|
+
memcpy(reinterpret_cast<char*>(buf), s_->data(), len);
|
|
1600
|
+
s_->erase(0, len);
|
|
1601
|
+
return len;
|
|
1602
|
+
}
|
|
1603
|
+
private:
|
|
1604
|
+
string* const s_;
|
|
1605
|
+
};
|
|
1606
|
+
|
|
1607
|
+
TYPED_TEST(HashtableIntTest, SerializingToString) {
|
|
1608
|
+
if (!this->ht_.supports_serialization()) return;
|
|
1609
|
+
TypeParam ht_out;
|
|
1610
|
+
ht_out.set_deleted_key(this->UniqueKey(2000));
|
|
1611
|
+
for (int i = 1; i < 100; i++) {
|
|
1612
|
+
ht_out.insert(this->UniqueObject(i));
|
|
1613
|
+
}
|
|
1614
|
+
// just to test having some erased keys when we write.
|
|
1615
|
+
ht_out.erase(this->UniqueKey(56));
|
|
1616
|
+
ht_out.erase(this->UniqueKey(22));
|
|
1617
|
+
|
|
1618
|
+
string stringbuf;
|
|
1619
|
+
StringIO stringio(&stringbuf);
|
|
1620
|
+
EXPECT_TRUE(ht_out.serialize(typename TypeParam::NopointerSerializer(),
|
|
1621
|
+
&stringio));
|
|
1622
|
+
|
|
1623
|
+
TypeParam ht_in;
|
|
1624
|
+
EXPECT_TRUE(ht_in.unserialize(typename TypeParam::NopointerSerializer(),
|
|
1625
|
+
&stringio));
|
|
1626
|
+
|
|
1627
|
+
EXPECT_EQ(this->UniqueObject(1), *ht_in.find(this->UniqueKey(1)));
|
|
1628
|
+
EXPECT_EQ(this->UniqueObject(99), *ht_in.find(this->UniqueKey(99)));
|
|
1629
|
+
EXPECT_FALSE(ht_in.count(this->UniqueKey(100)));
|
|
1630
|
+
EXPECT_EQ(this->UniqueObject(21), *ht_in.find(this->UniqueKey(21)));
|
|
1631
|
+
// should not have been saved
|
|
1632
|
+
EXPECT_FALSE(ht_in.count(this->UniqueKey(22)));
|
|
1633
|
+
EXPECT_FALSE(ht_in.count(this->UniqueKey(56)));
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
// An easier way to do the above would be to use the existing stream methods.
|
|
1637
|
+
TYPED_TEST(HashtableIntTest, SerializingToStringStream) {
|
|
1638
|
+
if (!this->ht_.supports_serialization()) return;
|
|
1639
|
+
TypeParam ht_out;
|
|
1640
|
+
ht_out.set_deleted_key(this->UniqueKey(2000));
|
|
1641
|
+
for (int i = 1; i < 100; i++) {
|
|
1642
|
+
ht_out.insert(this->UniqueObject(i));
|
|
1643
|
+
}
|
|
1644
|
+
// just to test having some erased keys when we write.
|
|
1645
|
+
ht_out.erase(this->UniqueKey(56));
|
|
1646
|
+
ht_out.erase(this->UniqueKey(22));
|
|
1647
|
+
|
|
1648
|
+
std::stringstream string_buffer;
|
|
1649
|
+
EXPECT_TRUE(ht_out.serialize(typename TypeParam::NopointerSerializer(),
|
|
1650
|
+
&string_buffer));
|
|
1651
|
+
|
|
1652
|
+
TypeParam ht_in;
|
|
1653
|
+
EXPECT_TRUE(ht_in.unserialize(typename TypeParam::NopointerSerializer(),
|
|
1654
|
+
&string_buffer));
|
|
1655
|
+
|
|
1656
|
+
EXPECT_EQ(this->UniqueObject(1), *ht_in.find(this->UniqueKey(1)));
|
|
1657
|
+
EXPECT_EQ(this->UniqueObject(99), *ht_in.find(this->UniqueKey(99)));
|
|
1658
|
+
EXPECT_FALSE(ht_in.count(this->UniqueKey(100)));
|
|
1659
|
+
EXPECT_EQ(this->UniqueObject(21), *ht_in.find(this->UniqueKey(21)));
|
|
1660
|
+
// should not have been saved
|
|
1661
|
+
EXPECT_FALSE(ht_in.count(this->UniqueKey(22)));
|
|
1662
|
+
EXPECT_FALSE(ht_in.count(this->UniqueKey(56)));
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
// Verify that the metadata serialization is endianness and word size
|
|
1666
|
+
// agnostic.
|
|
1667
|
+
TYPED_TEST(HashtableAllTest, MetadataSerializationAndEndianness) {
|
|
1668
|
+
TypeParam ht_out;
|
|
1669
|
+
string kExpectedDense("\x13W\x86""B\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0",
|
|
1670
|
+
24);
|
|
1671
|
+
string kExpectedSparse("$hu1\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0", 20);
|
|
1672
|
+
|
|
1673
|
+
if (ht_out.supports_readwrite()) {
|
|
1674
|
+
string file(TmpFile("metadata_serialization"));
|
|
1675
|
+
FILE* fp = fopen(file.c_str(), "wb");
|
|
1676
|
+
EXPECT_TRUE(fp != NULL);
|
|
1677
|
+
|
|
1678
|
+
EXPECT_TRUE(ht_out.write_metadata(fp));
|
|
1679
|
+
EXPECT_TRUE(ht_out.write_nopointer_data(fp));
|
|
1680
|
+
|
|
1681
|
+
const size_t num_bytes = ftell(fp);
|
|
1682
|
+
fclose(fp);
|
|
1683
|
+
fp = fopen(file.c_str(), "rb");
|
|
1684
|
+
EXPECT_LE(num_bytes, static_cast<size_t>(24));
|
|
1685
|
+
char contents[24];
|
|
1686
|
+
EXPECT_EQ(num_bytes, fread(contents, 1, num_bytes, fp));
|
|
1687
|
+
EXPECT_EQ(EOF, fgetc(fp)); // check we're *exactly* the right size
|
|
1688
|
+
fclose(fp);
|
|
1689
|
+
// TODO(csilvers): check type of ht_out instead of looking at the 1st byte.
|
|
1690
|
+
if (contents[0] == kExpectedDense[0]) {
|
|
1691
|
+
EXPECT_EQ(kExpectedDense, string(contents, num_bytes));
|
|
1692
|
+
} else {
|
|
1693
|
+
EXPECT_EQ(kExpectedSparse, string(contents, num_bytes));
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
// Do it again with new-style serialization. Here we can use StringIO.
|
|
1698
|
+
if (ht_out.supports_serialization()) {
|
|
1699
|
+
string stringbuf;
|
|
1700
|
+
StringIO stringio(&stringbuf);
|
|
1701
|
+
EXPECT_TRUE(ht_out.serialize(typename TypeParam::NopointerSerializer(),
|
|
1702
|
+
&stringio));
|
|
1703
|
+
if (stringbuf[0] == kExpectedDense[0]) {
|
|
1704
|
+
EXPECT_EQ(kExpectedDense, stringbuf);
|
|
1705
|
+
} else {
|
|
1706
|
+
EXPECT_EQ(kExpectedSparse, stringbuf);
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
|
|
1396
1712
|
// ------------------------------------------------------------------------
|
|
1397
1713
|
// The above tests test the general API for correctness. These tests
|
|
1398
1714
|
// test a few corner cases that have tripped us up in the past, and
|
|
@@ -1594,20 +1910,12 @@ TEST(HashtableTest, NestedHashtables) {
|
|
|
1594
1910
|
|
|
1595
1911
|
TEST(HashtableDeathTest, ResizeOverflow) {
|
|
1596
1912
|
dense_hash_map<int, int> ht;
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
EXPECT_TRUE(false && "dense_hash_map reszie should have failed");
|
|
1600
|
-
} catch (const STL_NAMESPACE::length_error&) {
|
|
1601
|
-
// Good, the resize failed.
|
|
1602
|
-
}
|
|
1913
|
+
EXPECT_DEATH(ht.resize(static_cast<size_t>(-1)),
|
|
1914
|
+
"overflows size_type");
|
|
1603
1915
|
|
|
1604
1916
|
sparse_hash_map<int, int> ht2;
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
EXPECT_TRUE(false && "sparse_hash_map reszie should have failed");
|
|
1608
|
-
} catch (const STL_NAMESPACE::length_error&) {
|
|
1609
|
-
// Good, the resize failed.
|
|
1610
|
-
}
|
|
1917
|
+
EXPECT_DEATH(ht2.resize(static_cast<size_t>(-1)),
|
|
1918
|
+
"overflows size_type");
|
|
1611
1919
|
}
|
|
1612
1920
|
|
|
1613
1921
|
TEST(HashtableDeathTest, InsertSizeTypeOverflow) {
|
|
@@ -1626,18 +1934,10 @@ TEST(HashtableDeathTest, InsertSizeTypeOverflow) {
|
|
|
1626
1934
|
EXPECT_TRUE(dhs.get_allocator().is_custom_alloc());
|
|
1627
1935
|
|
|
1628
1936
|
// Test size_type overflow in insert(it, it)
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
// Good, the operation failed.
|
|
1634
|
-
}
|
|
1635
|
-
try {
|
|
1636
|
-
shs.insert(test_data.begin(), test_data.end());
|
|
1637
|
-
EXPECT_TRUE(false && "sparse_hash_map::insert(it,it) should have overflown");
|
|
1638
|
-
} catch (const STL_NAMESPACE::length_error&) {
|
|
1639
|
-
// Good, the operation failed.
|
|
1640
|
-
}
|
|
1937
|
+
EXPECT_DEATH(dhs.insert(test_data.begin(), test_data.end()),
|
|
1938
|
+
"overflows size_type");
|
|
1939
|
+
EXPECT_DEATH(shs.insert(test_data.begin(), test_data.end()),
|
|
1940
|
+
"overflows size_type");
|
|
1641
1941
|
}
|
|
1642
1942
|
|
|
1643
1943
|
TEST(HashtableDeathTest, InsertMaxSizeOverflow) {
|
|
@@ -1652,18 +1952,10 @@ TEST(HashtableDeathTest, InsertMaxSizeOverflow) {
|
|
|
1652
1952
|
dhs.set_empty_key(-1);
|
|
1653
1953
|
|
|
1654
1954
|
// Test max_size overflow
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
// Good, the operation failed.
|
|
1660
|
-
}
|
|
1661
|
-
try {
|
|
1662
|
-
shs.insert(test_data.begin(), test_data.begin() + 11);
|
|
1663
|
-
EXPECT_TRUE(false && "sparse_hash_map max_size check should have failed");
|
|
1664
|
-
} catch (const STL_NAMESPACE::length_error&) {
|
|
1665
|
-
// Good, the operation failed.
|
|
1666
|
-
}
|
|
1955
|
+
EXPECT_DEATH(dhs.insert(test_data.begin(), test_data.begin() + 11),
|
|
1956
|
+
"exceed max_size");
|
|
1957
|
+
EXPECT_DEATH(shs.insert(test_data.begin(), test_data.begin() + 11),
|
|
1958
|
+
"exceed max_size");
|
|
1667
1959
|
}
|
|
1668
1960
|
|
|
1669
1961
|
TEST(HashtableDeathTest, ResizeSizeTypeOverflow) {
|
|
@@ -1672,18 +1964,8 @@ TEST(HashtableDeathTest, ResizeSizeTypeOverflow) {
|
|
|
1672
1964
|
dense_hash_set<int, Hasher, Hasher, Alloc<int, uint8, 10> > dhs;
|
|
1673
1965
|
dhs.set_empty_key(-1);
|
|
1674
1966
|
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
EXPECT_TRUE(false && "dense_hash_map resize should have seen overflow");
|
|
1678
|
-
} catch (const STL_NAMESPACE::length_error&) {
|
|
1679
|
-
// Good, the operation failed.
|
|
1680
|
-
}
|
|
1681
|
-
try {
|
|
1682
|
-
shs.resize(250);
|
|
1683
|
-
EXPECT_TRUE(false && "sparse_hash_map resize should have seen overflow");
|
|
1684
|
-
} catch (const STL_NAMESPACE::length_error&) {
|
|
1685
|
-
// Good, the operation failed.
|
|
1686
|
-
}
|
|
1967
|
+
EXPECT_DEATH(dhs.resize(250), "overflows size_type"); // 9+250 > 256
|
|
1968
|
+
EXPECT_DEATH(shs.resize(250), "overflows size_type");
|
|
1687
1969
|
}
|
|
1688
1970
|
|
|
1689
1971
|
TEST(HashtableDeathTest, ResizeDeltaOverflow) {
|
|
@@ -1700,18 +1982,10 @@ TEST(HashtableDeathTest, ResizeDeltaOverflow) {
|
|
|
1700
1982
|
dhs.insert(i);
|
|
1701
1983
|
shs.insert(i);
|
|
1702
1984
|
}
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
// Good, the operation failed.
|
|
1708
|
-
}
|
|
1709
|
-
try {
|
|
1710
|
-
shs.insert(test_data.begin(), test_data.begin() + 250);
|
|
1711
|
-
EXPECT_TRUE(false && "sparse_hash_map big insert should have overflowed");
|
|
1712
|
-
} catch (const STL_NAMESPACE::length_error&) {
|
|
1713
|
-
// Good, the operation failed.
|
|
1714
|
-
}
|
|
1985
|
+
EXPECT_DEATH(dhs.insert(test_data.begin(), test_data.begin() + 250),
|
|
1986
|
+
"overflows size_type"); // 9+250 > 256
|
|
1987
|
+
EXPECT_DEATH(shs.insert(test_data.begin(), test_data.begin() + 250),
|
|
1988
|
+
"overflows size_type");
|
|
1715
1989
|
}
|
|
1716
1990
|
|
|
1717
1991
|
// ------------------------------------------------------------------------
|
|
@@ -1719,8 +1993,8 @@ TEST(HashtableDeathTest, ResizeDeltaOverflow) {
|
|
|
1719
1993
|
// Also, benchmarks.
|
|
1720
1994
|
|
|
1721
1995
|
TYPED_TEST(HashtableAllTest, ClassSizes) {
|
|
1722
|
-
cout << "sizeof(" << typeid(TypeParam).name() << "): "
|
|
1723
|
-
|
|
1996
|
+
std::cout << "sizeof(" << typeid(TypeParam).name() << "): "
|
|
1997
|
+
<< sizeof(this->ht_) << "\n";
|
|
1724
1998
|
}
|
|
1725
1999
|
|
|
1726
2000
|
} // unnamed namespace
|