google_hash 0.6.2 → 0.7.0
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/README +61 -27
- data/Rakefile +4 -1
- data/TODO +5 -0
- data/VERSION +1 -1
- data/changelog +3 -0
- data/ext/extconf.rb +10 -5
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/AUTHORS +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/COPYING +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/ChangeLog +47 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/INSTALL +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/Makefile.am +29 -14
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/Makefile.in +77 -42
- data/ext/sparsehash-1.8.1/NEWS +71 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/README +0 -0
- data/ext/{sparsehash-1.5.2/README.windows → sparsehash-1.8.1/README_windows.txt} +25 -25
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/TODO +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/aclocal.m4 +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/compile +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/config.guess +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/config.sub +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/configure +3690 -4560
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/configure.ac +1 -1
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/depcomp +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/doc/dense_hash_map.html +65 -5
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/doc/dense_hash_set.html +65 -5
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/doc/designstyle.css +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/doc/implementation.html +11 -5
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/doc/index.html +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/doc/performance.html +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/doc/sparse_hash_map.html +65 -5
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/doc/sparse_hash_set.html +65 -5
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/doc/sparsetable.html +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/experimental/Makefile +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/experimental/README +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/experimental/example.c +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/experimental/libchash.c +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/experimental/libchash.h +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/google-sparsehash.sln +17 -1
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/install-sh +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/m4/acx_pthread.m4 +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/m4/google_namespace.m4 +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/m4/namespaces.m4 +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/m4/stl_hash.m4 +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/m4/stl_hash_fun.m4 +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/m4/stl_namespace.m4 +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/missing +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/mkinstalldirs +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/packages/deb.sh +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/packages/deb/README +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/packages/deb/changelog +24 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/packages/deb/compat +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/packages/deb/control +1 -1
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/packages/deb/copyright +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/packages/deb/docs +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/packages/deb/rules +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/packages/deb/sparsehash.dirs +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/packages/deb/sparsehash.install +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/packages/rpm.sh +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/packages/rpm/rpm.spec +1 -1
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/config.h.in +3 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/config.h.include +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/google/dense_hash_map +43 -27
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/google/dense_hash_set +40 -19
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/google/sparse_hash_map +32 -23
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/google/sparse_hash_set +31 -21
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/google/sparsehash/densehashtable.h +481 -298
- data/ext/sparsehash-1.8.1/src/google/sparsehash/hashtable-common.h +178 -0
- data/ext/sparsehash-1.8.1/src/google/sparsehash/libc_allocator_with_realloc.h +121 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/google/sparsehash/sparsehashtable.h +404 -233
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/google/sparsetable +173 -83
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/google/type_traits.h +3 -29
- data/ext/sparsehash-1.8.1/src/hash_test_interface.h +1011 -0
- data/ext/sparsehash-1.8.1/src/hashtable_test.cc +1733 -0
- data/ext/sparsehash-1.8.1/src/libc_allocator_with_realloc_test.cc +129 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/simple_test.cc +1 -1
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/sparsetable_unittest.cc +202 -6
- data/ext/sparsehash-1.8.1/src/testutil.h +251 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/time_hash_map.cc +128 -54
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/type_traits_unittest.cc +30 -20
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/windows/config.h +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/windows/google/sparsehash/sparseconfig.h +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/windows/port.cc +0 -0
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/src/windows/port.h +0 -0
- data/ext/sparsehash-1.8.1/vsprojects/hashtable_test/hashtable_test.vcproj +197 -0
- data/ext/{sparsehash-1.5.2/vsprojects/hashtable_unittest/hashtable_unittest.vcproj → sparsehash-1.8.1/vsprojects/simple_test/simple_test.vcproj} +9 -8
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/vsprojects/sparsetable_unittest/sparsetable_unittest.vcproj +0 -2
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/vsprojects/time_hash_map/time_hash_map.vcproj +3 -2
- data/ext/{sparsehash-1.5.2 → sparsehash-1.8.1}/vsprojects/type_traits_unittest/type_traits_unittest.vcproj +0 -2
- data/ext/template/google_hash.cpp.erb +2 -1
- data/ext/template/main.cpp.erb +1 -1
- data/results.txt +6 -22
- data/spec/benchmark.rb +57 -0
- data/spec/spec.google_hash.rb +1 -8
- metadata +140 -130
- data/ext/benchmark.rb +0 -47
- data/ext/sparsehash-1.5.2/NEWS +0 -0
- data/ext/sparsehash-1.5.2/src/hashtable_unittest.cc +0 -1375
- data/ext/sparsehash-1.5.2/src/words +0 -8944
- data/types.txt +0 -18
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// Copyright (c) 2010, 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
|
+
// ---
|
|
31
|
+
// Author: Guilin Chen
|
|
32
|
+
|
|
33
|
+
#include "config.h"
|
|
34
|
+
#include <google/sparsehash/libc_allocator_with_realloc.h>
|
|
35
|
+
#include <stdlib.h>
|
|
36
|
+
#include <iostream>
|
|
37
|
+
#include <string>
|
|
38
|
+
#include <vector>
|
|
39
|
+
|
|
40
|
+
using std::cerr;
|
|
41
|
+
using std::string;
|
|
42
|
+
using std::basic_string;
|
|
43
|
+
using std::char_traits;
|
|
44
|
+
using std::vector;
|
|
45
|
+
using GOOGLE_NAMESPACE::libc_allocator_with_realloc;
|
|
46
|
+
|
|
47
|
+
#define arraysize(a) ( sizeof(a) / sizeof(*(a)) )
|
|
48
|
+
|
|
49
|
+
#define EXPECT_EQ(a, b) do { \
|
|
50
|
+
if ((a) != (b)) { \
|
|
51
|
+
cerr << "Check failed: EXPECTED: " << #a << " == " << #b << ", " \
|
|
52
|
+
<< "ACTUAL: " << a << " != " << b << "\n"; \
|
|
53
|
+
exit(1); \
|
|
54
|
+
} \
|
|
55
|
+
} while (0)
|
|
56
|
+
|
|
57
|
+
namespace {
|
|
58
|
+
|
|
59
|
+
typedef libc_allocator_with_realloc<int> int_alloc;
|
|
60
|
+
typedef int_alloc::rebind<int*>::other intp_alloc;
|
|
61
|
+
|
|
62
|
+
// cstring allocates from libc_allocator_with_realloc.
|
|
63
|
+
typedef basic_string<char, char_traits<char>,
|
|
64
|
+
libc_allocator_with_realloc<char> > cstring;
|
|
65
|
+
typedef vector<cstring, libc_allocator_with_realloc<cstring> > cstring_vector;
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
void TestAllocate() {
|
|
69
|
+
int_alloc alloc;
|
|
70
|
+
intp_alloc palloc;
|
|
71
|
+
|
|
72
|
+
int** parray = palloc.allocate(1024);
|
|
73
|
+
for (int i = 0; i < 16; ++i) {
|
|
74
|
+
parray[i] = alloc.allocate(i * 1024 + 1);
|
|
75
|
+
}
|
|
76
|
+
for (int i = 0; i < 16; ++i) {
|
|
77
|
+
alloc.deallocate(parray[i], i * 1024 + 1);
|
|
78
|
+
}
|
|
79
|
+
palloc.deallocate(parray, 1024);
|
|
80
|
+
|
|
81
|
+
int* p = alloc.allocate(4096);
|
|
82
|
+
p[0] = 1;
|
|
83
|
+
p[1023] = 2;
|
|
84
|
+
p[4095] = 3;
|
|
85
|
+
p = alloc.reallocate(p, 8192);
|
|
86
|
+
EXPECT_EQ(1, p[0]);
|
|
87
|
+
EXPECT_EQ(2, p[1023]);
|
|
88
|
+
EXPECT_EQ(3, p[4095]);
|
|
89
|
+
p = alloc.reallocate(p, 1024);
|
|
90
|
+
EXPECT_EQ(1, p[0]);
|
|
91
|
+
EXPECT_EQ(2, p[1023]);
|
|
92
|
+
alloc.deallocate(p, 1024);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
void TestSTL() {
|
|
96
|
+
// Test strings copied from base/arena_unittest.cc
|
|
97
|
+
static const char* test_strings[] = {
|
|
98
|
+
"aback", "abaft", "abandon", "abandoned", "abandoning",
|
|
99
|
+
"abandonment", "abandons", "abase", "abased", "abasement",
|
|
100
|
+
"abasements", "abases", "abash", "abashed", "abashes", "abashing",
|
|
101
|
+
"abasing", "abate", "abated", "abatement", "abatements", "abater",
|
|
102
|
+
"abates", "abating", "abbe", "abbey", "abbeys", "abbot", "abbots",
|
|
103
|
+
"abbreviate", "abbreviated", "abbreviates", "abbreviating",
|
|
104
|
+
"abbreviation", "abbreviations", "abdomen", "abdomens", "abdominal",
|
|
105
|
+
"abduct", "abducted", "abduction", "abductions", "abductor", "abductors",
|
|
106
|
+
"abducts", "Abe", "abed", "Abel", "Abelian", "Abelson", "Aberdeen",
|
|
107
|
+
"Abernathy", "aberrant", "aberration", "aberrations", "abet", "abets",
|
|
108
|
+
"abetted", "abetter", "abetting", "abeyance", "abhor", "abhorred",
|
|
109
|
+
"abhorrent", "abhorrer", "abhorring", "abhors", "abide", "abided",
|
|
110
|
+
"abides", "abiding"};
|
|
111
|
+
cstring_vector v;
|
|
112
|
+
for (size_t i = 0; i < arraysize(test_strings); ++i) {
|
|
113
|
+
v.push_back(test_strings[i]);
|
|
114
|
+
}
|
|
115
|
+
for (size_t i = arraysize(test_strings); i > 0; --i) {
|
|
116
|
+
EXPECT_EQ(cstring(test_strings[i-1]), v.back());
|
|
117
|
+
v.pop_back();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
} // namespace
|
|
122
|
+
|
|
123
|
+
int main() {
|
|
124
|
+
TestAllocate();
|
|
125
|
+
TestSTL();
|
|
126
|
+
|
|
127
|
+
cerr << "PASS\n";
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
@@ -45,11 +45,14 @@
|
|
|
45
45
|
#include <unistd.h> // for unlink()
|
|
46
46
|
#include <sys/types.h> // for size_t
|
|
47
47
|
#include <string>
|
|
48
|
+
#include <memory> // for allocator
|
|
48
49
|
#endif
|
|
49
50
|
#include <google/sparsetable>
|
|
50
51
|
|
|
51
52
|
using STL_NAMESPACE::string;
|
|
53
|
+
using STL_NAMESPACE::allocator;
|
|
52
54
|
using GOOGLE_NAMESPACE::sparsetable;
|
|
55
|
+
using GOOGLE_NAMESPACE::DEFAULT_SPARSEGROUP_SIZE;
|
|
53
56
|
|
|
54
57
|
// Many sparsetable operations return a size_t. Rather than have to
|
|
55
58
|
// use PRIuS everywhere, we'll just cast to a "big enough" value.
|
|
@@ -320,12 +323,12 @@ void TestInt() {
|
|
|
320
323
|
|
|
321
324
|
// ----------------------------------------------------------------------
|
|
322
325
|
// Test I/O
|
|
323
|
-
string filestr = "/tmp
|
|
326
|
+
string filestr = "/tmp/.sparsetable.test";
|
|
324
327
|
const char *file = filestr.c_str();
|
|
325
328
|
FILE *fp = fopen(file, "wb");
|
|
326
329
|
if ( fp == NULL ) {
|
|
327
330
|
// maybe we can't write to /tmp/. Try the current directory
|
|
328
|
-
file = "
|
|
331
|
+
file = ".sparsetable.test";
|
|
329
332
|
fp = fopen(file, "wb");
|
|
330
333
|
}
|
|
331
334
|
if ( fp == NULL ) {
|
|
@@ -443,7 +446,182 @@ void TestString() {
|
|
|
443
446
|
out += snprintf(out, LEFT, "y[??] = %s\n", (*--it).c_str());
|
|
444
447
|
}
|
|
445
448
|
|
|
446
|
-
//
|
|
449
|
+
// An instrumented allocator that keeps track of all calls to
|
|
450
|
+
// allocate/deallocate/construct/destroy. It stores the number of times
|
|
451
|
+
// they were called and the values they were called with. Such information is
|
|
452
|
+
// stored in the following global variables.
|
|
453
|
+
|
|
454
|
+
static size_t sum_allocate_bytes;
|
|
455
|
+
static size_t sum_deallocate_bytes;
|
|
456
|
+
|
|
457
|
+
void ResetAllocatorCounters() {
|
|
458
|
+
sum_allocate_bytes = 0;
|
|
459
|
+
sum_deallocate_bytes = 0;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
template <class T> class instrumented_allocator {
|
|
463
|
+
public:
|
|
464
|
+
typedef T value_type;
|
|
465
|
+
typedef u_int16_t size_type;
|
|
466
|
+
typedef ptrdiff_t difference_type;
|
|
467
|
+
|
|
468
|
+
typedef T* pointer;
|
|
469
|
+
typedef const T* const_pointer;
|
|
470
|
+
typedef T& reference;
|
|
471
|
+
typedef const T& const_reference;
|
|
472
|
+
|
|
473
|
+
instrumented_allocator() {}
|
|
474
|
+
instrumented_allocator(const instrumented_allocator&) {}
|
|
475
|
+
~instrumented_allocator() {}
|
|
476
|
+
|
|
477
|
+
pointer address(reference r) const { return &r; }
|
|
478
|
+
const_pointer address(const_reference r) const { return &r; }
|
|
479
|
+
|
|
480
|
+
pointer allocate(size_type n, const_pointer = 0) {
|
|
481
|
+
sum_allocate_bytes += n * sizeof(value_type);
|
|
482
|
+
return static_cast<pointer>(malloc(n * sizeof(value_type)));
|
|
483
|
+
}
|
|
484
|
+
void deallocate(pointer p, size_type n) {
|
|
485
|
+
sum_deallocate_bytes += n * sizeof(value_type);
|
|
486
|
+
free(p);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
size_type max_size() const {
|
|
490
|
+
return static_cast<size_type>(-1) / sizeof(value_type);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
void construct(pointer p, const value_type& val) {
|
|
494
|
+
new(p) value_type(val);
|
|
495
|
+
}
|
|
496
|
+
void destroy(pointer p) {
|
|
497
|
+
p->~value_type();
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
template <class U>
|
|
501
|
+
explicit instrumented_allocator(const instrumented_allocator<U>&) {}
|
|
502
|
+
|
|
503
|
+
template<class U>
|
|
504
|
+
struct rebind {
|
|
505
|
+
typedef instrumented_allocator<U> other;
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
private:
|
|
509
|
+
void operator=(const instrumented_allocator&);
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
template<class T>
|
|
513
|
+
inline bool operator==(const instrumented_allocator<T>&,
|
|
514
|
+
const instrumented_allocator<T>&) {
|
|
515
|
+
return true;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
template<class T>
|
|
519
|
+
inline bool operator!=(const instrumented_allocator<T>&,
|
|
520
|
+
const instrumented_allocator<T>&) {
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Test sparsetable with instrumented_allocator.
|
|
525
|
+
void TestAllocator() {
|
|
526
|
+
out += snprintf(out, LEFT, "allocator test\n");
|
|
527
|
+
|
|
528
|
+
ResetAllocatorCounters();
|
|
529
|
+
|
|
530
|
+
// POD (int32) with instrumented_allocator.
|
|
531
|
+
typedef sparsetable<int, DEFAULT_SPARSEGROUP_SIZE,
|
|
532
|
+
instrumented_allocator<int> > IntSparseTable;
|
|
533
|
+
|
|
534
|
+
IntSparseTable* s1 = new IntSparseTable(10000);
|
|
535
|
+
TEST(sum_allocate_bytes > 0);
|
|
536
|
+
for (int i = 0; i < 10000; ++i) {
|
|
537
|
+
s1->set(i, 0);
|
|
538
|
+
}
|
|
539
|
+
TEST(sum_allocate_bytes >= 10000 * sizeof(int));
|
|
540
|
+
ResetAllocatorCounters();
|
|
541
|
+
delete s1;
|
|
542
|
+
TEST(sum_deallocate_bytes >= 10000 * sizeof(int));
|
|
543
|
+
|
|
544
|
+
IntSparseTable* s2 = new IntSparseTable(1000);
|
|
545
|
+
IntSparseTable* s3 = new IntSparseTable(1000);
|
|
546
|
+
|
|
547
|
+
for (int i = 0; i < 1000; ++i) {
|
|
548
|
+
s2->set(i, 0);
|
|
549
|
+
s3->set(i, 0);
|
|
550
|
+
}
|
|
551
|
+
TEST(sum_allocate_bytes >= 2000 * sizeof(int));
|
|
552
|
+
|
|
553
|
+
ResetAllocatorCounters();
|
|
554
|
+
s3->clear();
|
|
555
|
+
TEST(sum_deallocate_bytes >= 1000 * sizeof(int));
|
|
556
|
+
|
|
557
|
+
ResetAllocatorCounters();
|
|
558
|
+
s2->swap(*s3); // s2 is empty after the swap
|
|
559
|
+
s2->clear();
|
|
560
|
+
TEST(sum_deallocate_bytes < 1000 * sizeof(int));
|
|
561
|
+
for (int i = 0; i < s3->size(); ++i) {
|
|
562
|
+
s3->erase(i);
|
|
563
|
+
}
|
|
564
|
+
TEST(sum_deallocate_bytes >= 1000 * sizeof(int));
|
|
565
|
+
delete s2;
|
|
566
|
+
delete s3;
|
|
567
|
+
|
|
568
|
+
// POD (int) with default allocator.
|
|
569
|
+
sparsetable<int> x, y;
|
|
570
|
+
for (int s = 1000; s <= 40000; s += 1000) {
|
|
571
|
+
x.resize(s);
|
|
572
|
+
for (int i = 0; i < s; ++i) {
|
|
573
|
+
x.set(i, i + 1);
|
|
574
|
+
}
|
|
575
|
+
y = x;
|
|
576
|
+
for (int i = 0; i < s; ++i) {
|
|
577
|
+
y.erase(i);
|
|
578
|
+
}
|
|
579
|
+
y.swap(x);
|
|
580
|
+
}
|
|
581
|
+
TEST(x.num_nonempty() == 0);
|
|
582
|
+
out += snprintf(out, LEFT, "y[0]: %d\n", int(y[0]));
|
|
583
|
+
out += snprintf(out, LEFT, "y[39999]: %d\n", int(y[39999]));
|
|
584
|
+
y.clear();
|
|
585
|
+
|
|
586
|
+
// POD (int) with std allocator.
|
|
587
|
+
sparsetable<int, DEFAULT_SPARSEGROUP_SIZE, allocator<int> > u, v;
|
|
588
|
+
for (int s = 1000; s <= 40000; s += 1000) {
|
|
589
|
+
u.resize(s);
|
|
590
|
+
for (int i = 0; i < s; ++i) {
|
|
591
|
+
u.set(i, i + 1);
|
|
592
|
+
}
|
|
593
|
+
v = u;
|
|
594
|
+
for (int i = 0; i < s; ++i) {
|
|
595
|
+
v.erase(i);
|
|
596
|
+
}
|
|
597
|
+
v.swap(u);
|
|
598
|
+
}
|
|
599
|
+
TEST(u.num_nonempty() == 0);
|
|
600
|
+
out += snprintf(out, LEFT, "v[0]: %d\n", int(v[0]));
|
|
601
|
+
out += snprintf(out, LEFT, "v[39999]: %d\n", int(v[39999]));
|
|
602
|
+
v.clear();
|
|
603
|
+
|
|
604
|
+
// Non-POD (string) with default allocator.
|
|
605
|
+
sparsetable<string> a, b;
|
|
606
|
+
for (int s = 1000; s <= 40000; s += 1000) {
|
|
607
|
+
a.resize(s);
|
|
608
|
+
for (int i = 0; i < s; ++i) {
|
|
609
|
+
a.set(i, "aa");
|
|
610
|
+
}
|
|
611
|
+
b = a;
|
|
612
|
+
for (int i = 0; i < s; ++i) {
|
|
613
|
+
b.erase(i);
|
|
614
|
+
}
|
|
615
|
+
b.swap(a);
|
|
616
|
+
}
|
|
617
|
+
TEST(a.num_nonempty() == 0);
|
|
618
|
+
out += snprintf(out, LEFT, "b[0]: %s\n", b.get(0).c_str());
|
|
619
|
+
out += snprintf(out, LEFT, "b[39999]: %s\n", b.get(39999).c_str());
|
|
620
|
+
b.clear();
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// The expected output from all of the above: TestInt(), TestString() and
|
|
624
|
+
// TestAllocator().
|
|
447
625
|
static const char g_expected[] = (
|
|
448
626
|
"int test\n"
|
|
449
627
|
"x[0]: 0\n"
|
|
@@ -675,17 +853,35 @@ static const char g_expected[] = (
|
|
|
675
853
|
"y[??] = -13\n"
|
|
676
854
|
"y[??] = -11\n"
|
|
677
855
|
"y[??] = -10\n"
|
|
856
|
+
"allocator test\n"
|
|
857
|
+
"sum_allocate_bytes > 0? yes\n"
|
|
858
|
+
"sum_allocate_bytes >= 10000 * sizeof(int)? yes\n"
|
|
859
|
+
"sum_deallocate_bytes >= 10000 * sizeof(int)? yes\n"
|
|
860
|
+
"sum_allocate_bytes >= 2000 * sizeof(int)? yes\n"
|
|
861
|
+
"sum_deallocate_bytes >= 1000 * sizeof(int)? yes\n"
|
|
862
|
+
"sum_deallocate_bytes < 1000 * sizeof(int)? yes\n"
|
|
863
|
+
"sum_deallocate_bytes >= 1000 * sizeof(int)? yes\n"
|
|
864
|
+
"x.num_nonempty() == 0? yes\n"
|
|
865
|
+
"y[0]: 1\n"
|
|
866
|
+
"y[39999]: 40000\n"
|
|
867
|
+
"u.num_nonempty() == 0? yes\n"
|
|
868
|
+
"v[0]: 1\n"
|
|
869
|
+
"v[39999]: 40000\n"
|
|
870
|
+
"a.num_nonempty() == 0? yes\n"
|
|
871
|
+
"b[0]: aa\n"
|
|
872
|
+
"b[39999]: aa\n"
|
|
678
873
|
);
|
|
679
874
|
|
|
680
875
|
// defined at bottom of file for ease of maintainence
|
|
681
|
-
int main(int argc
|
|
876
|
+
int main(int /*argc*/, char ** /*argv*/) {
|
|
682
877
|
TestInt();
|
|
683
878
|
TestString();
|
|
879
|
+
TestAllocator();
|
|
684
880
|
|
|
685
881
|
// Finally, check to see if our output (in out) is what it's supposed to be.
|
|
686
882
|
const size_t r = sizeof(g_expected) - 1;
|
|
687
|
-
if ( r != out - outbuf ||
|
|
688
|
-
memcmp(outbuf, g_expected, r) ) {
|
|
883
|
+
if ( r != static_cast<size_t>(out - outbuf) || // output not the same size
|
|
884
|
+
memcmp(outbuf, g_expected, r) ) { // or bytes differed
|
|
689
885
|
fprintf(stderr, "TESTS FAILED\n\nEXPECTED:\n\n%s\n\nACTUAL:\n\n%s\n\n",
|
|
690
886
|
g_expected, outbuf);
|
|
691
887
|
return 1;
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
// Copyright (c) 2010, 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
|
+
// ---
|
|
31
|
+
// Author: Craig Silverstein
|
|
32
|
+
|
|
33
|
+
// This macro mimics a unittest framework, but is a bit less flexible
|
|
34
|
+
// than most. It requires a superclass to derive from, and does all
|
|
35
|
+
// work in global constructors. The tricky part is implementing
|
|
36
|
+
// TYPED_TEST.
|
|
37
|
+
|
|
38
|
+
#ifndef SPARSEHASH_TEST_UTIL_H_
|
|
39
|
+
#define SPARSEHASH_TEST_UTIL_H_
|
|
40
|
+
|
|
41
|
+
#include "config.h"
|
|
42
|
+
#include <stdio.h>
|
|
43
|
+
|
|
44
|
+
_START_GOOGLE_NAMESPACE_
|
|
45
|
+
|
|
46
|
+
namespace testing {
|
|
47
|
+
|
|
48
|
+
#define EXPECT_TRUE(cond) do { \
|
|
49
|
+
if (!(cond)) { \
|
|
50
|
+
::fputs("Test failed: " #cond "\n", stderr); \
|
|
51
|
+
::exit(1); \
|
|
52
|
+
} \
|
|
53
|
+
} while (0)
|
|
54
|
+
|
|
55
|
+
#define EXPECT_FALSE(a) EXPECT_TRUE(!(a))
|
|
56
|
+
#define EXPECT_EQ(a, b) EXPECT_TRUE((a) == (b))
|
|
57
|
+
#define EXPECT_LT(a, b) EXPECT_TRUE((a) < (b))
|
|
58
|
+
#define EXPECT_GT(a, b) EXPECT_TRUE((a) > (b))
|
|
59
|
+
#define EXPECT_LE(a, b) EXPECT_TRUE((a) <= (b))
|
|
60
|
+
#define EXPECT_GE(a, b) EXPECT_TRUE((a) >= (b))
|
|
61
|
+
|
|
62
|
+
#define TEST(suitename, testname) \
|
|
63
|
+
class TEST_##suitename##_##testname { \
|
|
64
|
+
public: \
|
|
65
|
+
TEST_##suitename##_##testname() { \
|
|
66
|
+
::fputs("Running " #suitename "." #testname "\n", stderr); \
|
|
67
|
+
Run(); \
|
|
68
|
+
} \
|
|
69
|
+
void Run(); \
|
|
70
|
+
}; \
|
|
71
|
+
static TEST_##suitename##_##testname \
|
|
72
|
+
test_instance_##suitename##_##testname; \
|
|
73
|
+
void TEST_##suitename##_##testname::Run()
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
template<typename C1, typename C2, typename C3, typename C4, typename C5,
|
|
77
|
+
typename C6> struct TypeList6 {
|
|
78
|
+
typedef C1 type1;
|
|
79
|
+
typedef C2 type2;
|
|
80
|
+
typedef C3 type3;
|
|
81
|
+
typedef C4 type4;
|
|
82
|
+
typedef C5 type5;
|
|
83
|
+
typedef C6 type6;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// I need to list 18 types here, for code below to compile, though
|
|
87
|
+
// only the first 6 are ever used.
|
|
88
|
+
#define TYPED_TEST_CASE_6(classname, typelist) \
|
|
89
|
+
typedef typelist::type1 classname##_type1; \
|
|
90
|
+
typedef typelist::type2 classname##_type2; \
|
|
91
|
+
typedef typelist::type3 classname##_type3; \
|
|
92
|
+
typedef typelist::type4 classname##_type4; \
|
|
93
|
+
typedef typelist::type5 classname##_type5; \
|
|
94
|
+
typedef typelist::type6 classname##_type6; \
|
|
95
|
+
static const int classname##_numtypes = 6; \
|
|
96
|
+
typedef typelist::type1 classname##_type7; \
|
|
97
|
+
typedef typelist::type1 classname##_type8; \
|
|
98
|
+
typedef typelist::type1 classname##_type9; \
|
|
99
|
+
typedef typelist::type1 classname##_type10; \
|
|
100
|
+
typedef typelist::type1 classname##_type11; \
|
|
101
|
+
typedef typelist::type1 classname##_type12; \
|
|
102
|
+
typedef typelist::type1 classname##_type13; \
|
|
103
|
+
typedef typelist::type1 classname##_type14; \
|
|
104
|
+
typedef typelist::type1 classname##_type15; \
|
|
105
|
+
typedef typelist::type1 classname##_type16; \
|
|
106
|
+
typedef typelist::type1 classname##_type17; \
|
|
107
|
+
typedef typelist::type1 classname##_type18;
|
|
108
|
+
|
|
109
|
+
template<typename C1, typename C2, typename C3, typename C4, typename C5,
|
|
110
|
+
typename C6, typename C7, typename C8, typename C9, typename C10,
|
|
111
|
+
typename C11, typename C12, typename C13, typename C14, typename C15,
|
|
112
|
+
typename C16, typename C17, typename C18> struct TypeList18 {
|
|
113
|
+
typedef C1 type1;
|
|
114
|
+
typedef C2 type2;
|
|
115
|
+
typedef C3 type3;
|
|
116
|
+
typedef C4 type4;
|
|
117
|
+
typedef C5 type5;
|
|
118
|
+
typedef C6 type6;
|
|
119
|
+
typedef C7 type7;
|
|
120
|
+
typedef C8 type8;
|
|
121
|
+
typedef C9 type9;
|
|
122
|
+
typedef C10 type10;
|
|
123
|
+
typedef C11 type11;
|
|
124
|
+
typedef C12 type12;
|
|
125
|
+
typedef C13 type13;
|
|
126
|
+
typedef C14 type14;
|
|
127
|
+
typedef C15 type15;
|
|
128
|
+
typedef C16 type16;
|
|
129
|
+
typedef C17 type17;
|
|
130
|
+
typedef C18 type18;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
#define TYPED_TEST_CASE_18(classname, typelist) \
|
|
134
|
+
typedef typelist::type1 classname##_type1; \
|
|
135
|
+
typedef typelist::type2 classname##_type2; \
|
|
136
|
+
typedef typelist::type3 classname##_type3; \
|
|
137
|
+
typedef typelist::type4 classname##_type4; \
|
|
138
|
+
typedef typelist::type5 classname##_type5; \
|
|
139
|
+
typedef typelist::type6 classname##_type6; \
|
|
140
|
+
typedef typelist::type7 classname##_type7; \
|
|
141
|
+
typedef typelist::type8 classname##_type8; \
|
|
142
|
+
typedef typelist::type9 classname##_type9; \
|
|
143
|
+
typedef typelist::type10 classname##_type10; \
|
|
144
|
+
typedef typelist::type11 classname##_type11; \
|
|
145
|
+
typedef typelist::type12 classname##_type12; \
|
|
146
|
+
typedef typelist::type13 classname##_type13; \
|
|
147
|
+
typedef typelist::type14 classname##_type14; \
|
|
148
|
+
typedef typelist::type15 classname##_type15; \
|
|
149
|
+
typedef typelist::type16 classname##_type16; \
|
|
150
|
+
typedef typelist::type17 classname##_type17; \
|
|
151
|
+
typedef typelist::type18 classname##_type18; \
|
|
152
|
+
static const int classname##_numtypes = 18;
|
|
153
|
+
|
|
154
|
+
#define TYPED_TEST(superclass, testname) \
|
|
155
|
+
template<typename TypeParam> \
|
|
156
|
+
class TEST_onetype_##superclass##_##testname : \
|
|
157
|
+
public superclass<TypeParam> { \
|
|
158
|
+
public: \
|
|
159
|
+
TEST_onetype_##superclass##_##testname() { \
|
|
160
|
+
Run(); \
|
|
161
|
+
} \
|
|
162
|
+
private: \
|
|
163
|
+
void Run(); \
|
|
164
|
+
}; \
|
|
165
|
+
class TEST_typed_##superclass##_##testname { \
|
|
166
|
+
public: \
|
|
167
|
+
explicit TEST_typed_##superclass##_##testname() { \
|
|
168
|
+
if (superclass##_numtypes >= 1) { \
|
|
169
|
+
::fputs("Running " #superclass "." #testname ".1\n", stderr); \
|
|
170
|
+
TEST_onetype_##superclass##_##testname<superclass##_type1> t; \
|
|
171
|
+
} \
|
|
172
|
+
if (superclass##_numtypes >= 2) { \
|
|
173
|
+
::fputs("Running " #superclass "." #testname ".2\n", stderr); \
|
|
174
|
+
TEST_onetype_##superclass##_##testname<superclass##_type2> t; \
|
|
175
|
+
} \
|
|
176
|
+
if (superclass##_numtypes >= 3) { \
|
|
177
|
+
::fputs("Running " #superclass "." #testname ".3\n", stderr); \
|
|
178
|
+
TEST_onetype_##superclass##_##testname<superclass##_type3> t; \
|
|
179
|
+
} \
|
|
180
|
+
if (superclass##_numtypes >= 4) { \
|
|
181
|
+
::fputs("Running " #superclass "." #testname ".4\n", stderr); \
|
|
182
|
+
TEST_onetype_##superclass##_##testname<superclass##_type4> t; \
|
|
183
|
+
} \
|
|
184
|
+
if (superclass##_numtypes >= 5) { \
|
|
185
|
+
::fputs("Running " #superclass "." #testname ".5\n", stderr); \
|
|
186
|
+
TEST_onetype_##superclass##_##testname<superclass##_type5> t; \
|
|
187
|
+
} \
|
|
188
|
+
if (superclass##_numtypes >= 6) { \
|
|
189
|
+
::fputs("Running " #superclass "." #testname ".6\n", stderr); \
|
|
190
|
+
TEST_onetype_##superclass##_##testname<superclass##_type6> t; \
|
|
191
|
+
} \
|
|
192
|
+
if (superclass##_numtypes >= 7) { \
|
|
193
|
+
::fputs("Running " #superclass "." #testname ".7\n", stderr); \
|
|
194
|
+
TEST_onetype_##superclass##_##testname<superclass##_type7> t; \
|
|
195
|
+
} \
|
|
196
|
+
if (superclass##_numtypes >= 8) { \
|
|
197
|
+
::fputs("Running " #superclass "." #testname ".8\n", stderr); \
|
|
198
|
+
TEST_onetype_##superclass##_##testname<superclass##_type8> t; \
|
|
199
|
+
} \
|
|
200
|
+
if (superclass##_numtypes >= 9) { \
|
|
201
|
+
::fputs("Running " #superclass "." #testname ".9\n", stderr); \
|
|
202
|
+
TEST_onetype_##superclass##_##testname<superclass##_type9> t; \
|
|
203
|
+
} \
|
|
204
|
+
if (superclass##_numtypes >= 10) { \
|
|
205
|
+
::fputs("Running " #superclass "." #testname ".10\n", stderr); \
|
|
206
|
+
TEST_onetype_##superclass##_##testname<superclass##_type10> t; \
|
|
207
|
+
} \
|
|
208
|
+
if (superclass##_numtypes >= 11) { \
|
|
209
|
+
::fputs("Running " #superclass "." #testname ".11\n", stderr); \
|
|
210
|
+
TEST_onetype_##superclass##_##testname<superclass##_type11> t; \
|
|
211
|
+
} \
|
|
212
|
+
if (superclass##_numtypes >= 12) { \
|
|
213
|
+
::fputs("Running " #superclass "." #testname ".12\n", stderr); \
|
|
214
|
+
TEST_onetype_##superclass##_##testname<superclass##_type12> t; \
|
|
215
|
+
} \
|
|
216
|
+
if (superclass##_numtypes >= 13) { \
|
|
217
|
+
::fputs("Running " #superclass "." #testname ".13\n", stderr); \
|
|
218
|
+
TEST_onetype_##superclass##_##testname<superclass##_type13> t; \
|
|
219
|
+
} \
|
|
220
|
+
if (superclass##_numtypes >= 14) { \
|
|
221
|
+
::fputs("Running " #superclass "." #testname ".14\n", stderr); \
|
|
222
|
+
TEST_onetype_##superclass##_##testname<superclass##_type14> t; \
|
|
223
|
+
} \
|
|
224
|
+
if (superclass##_numtypes >= 15) { \
|
|
225
|
+
::fputs("Running " #superclass "." #testname ".15\n", stderr); \
|
|
226
|
+
TEST_onetype_##superclass##_##testname<superclass##_type15> t; \
|
|
227
|
+
} \
|
|
228
|
+
if (superclass##_numtypes >= 16) { \
|
|
229
|
+
::fputs("Running " #superclass "." #testname ".16\n", stderr); \
|
|
230
|
+
TEST_onetype_##superclass##_##testname<superclass##_type16> t; \
|
|
231
|
+
} \
|
|
232
|
+
if (superclass##_numtypes >= 17) { \
|
|
233
|
+
::fputs("Running " #superclass "." #testname ".17\n", stderr); \
|
|
234
|
+
TEST_onetype_##superclass##_##testname<superclass##_type17> t; \
|
|
235
|
+
} \
|
|
236
|
+
if (superclass##_numtypes >= 18) { \
|
|
237
|
+
::fputs("Running " #superclass "." #testname ".18\n", stderr); \
|
|
238
|
+
TEST_onetype_##superclass##_##testname<superclass##_type18> t; \
|
|
239
|
+
} \
|
|
240
|
+
} \
|
|
241
|
+
}; \
|
|
242
|
+
static TEST_typed_##superclass##_##testname \
|
|
243
|
+
test_instance_typed_##superclass##_##testname; \
|
|
244
|
+
template<class TypeParam> \
|
|
245
|
+
void TEST_onetype_##superclass##_##testname<TypeParam>::Run()
|
|
246
|
+
|
|
247
|
+
} // namespace testing
|
|
248
|
+
|
|
249
|
+
_END_GOOGLE_NAMESPACE_
|
|
250
|
+
|
|
251
|
+
#endif // SPARSEHASH_TEST_UTIL_H_
|