1 // Copyright (c) 2005, Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
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
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.
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.
31 // Author: Sanjay Ghemawat
33 #include <stdlib.h> // for rand()
38 #include "addressmap-inl.h"
39 #include "base/logging.h"
40 #include "base/commandlineflags.h"
42 DEFINE_int32(iters
, 20, "Number of test iterations");
43 DEFINE_int32(N
, 100000, "Number of elements to test per iteration");
49 using std::random_shuffle
;
51 struct UniformRandomNumberGenerator
{
52 size_t Uniform(size_t max_size
) {
55 return rand() % max_size
; // not a great random-number fn, but portable
58 static UniformRandomNumberGenerator rnd
;
61 // pair of associated value and object size
62 typedef pair
<int, size_t> ValueT
;
67 PtrAndSize(char* p
, size_t s
) : ptr(p
), size(s
) {}
70 size_t SizeFunc(const ValueT
& v
) { return v
.second
; }
72 static void SetCheckCallback(const void* ptr
, ValueT
* val
,
73 set
<pair
<const void*, int> >* check_set
) {
74 check_set
->insert(make_pair(ptr
, val
->first
));
77 int main(int argc
, char** argv
) {
78 // Get a bunch of pointers
79 const int N
= FLAGS_N
;
80 static const int kMaxRealSize
= 49;
81 // 100Mb to stress not finding previous object (AddressMap's cluster is 1Mb):
82 static const size_t kMaxSize
= 100*1000*1000;
83 vector
<PtrAndSize
> ptrs_and_sizes
;
84 for (int i
= 0; i
< N
; ++i
) {
85 size_t s
= rnd
.Uniform(kMaxRealSize
);
86 ptrs_and_sizes
.push_back(PtrAndSize(new char[s
], s
));
89 for (int x
= 0; x
< FLAGS_iters
; ++x
) {
90 RAW_LOG(INFO
, "Iteration %d/%d...\n", x
, FLAGS_iters
);
92 // Permute pointers to get rid of allocation order issues
93 random_shuffle(ptrs_and_sizes
.begin(), ptrs_and_sizes
.end());
95 AddressMap
<ValueT
> map(malloc
, free
);
99 // Insert a bunch of entries
100 for (int i
= 0; i
< N
; ++i
) {
101 char* p
= ptrs_and_sizes
[i
].ptr
;
103 int offs
= rnd
.Uniform(ptrs_and_sizes
[i
].size
);
104 CHECK(!map
.FindInside(&SizeFunc
, kMaxSize
, p
+ offs
, &res_p
));
105 map
.Insert(p
, make_pair(i
, ptrs_and_sizes
[i
].size
));
106 CHECK(result
= map
.Find(p
));
107 CHECK_EQ(result
->first
, i
);
108 CHECK(result
= map
.FindInside(&SizeFunc
, kMaxRealSize
, p
+ offs
, &res_p
));
110 CHECK_EQ(result
->first
, i
);
111 map
.Insert(p
, make_pair(i
+ N
, ptrs_and_sizes
[i
].size
));
112 CHECK(result
= map
.Find(p
));
113 CHECK_EQ(result
->first
, i
+ N
);
116 // Delete the even entries
117 for (int i
= 0; i
< N
; i
+= 2) {
118 void* p
= ptrs_and_sizes
[i
].ptr
;
120 CHECK(map
.FindAndRemove(p
, &removed
));
121 CHECK_EQ(removed
.first
, i
+ N
);
124 // Lookup the odd entries and adjust them
125 for (int i
= 1; i
< N
; i
+= 2) {
126 char* p
= ptrs_and_sizes
[i
].ptr
;
127 CHECK(result
= map
.Find(p
));
128 CHECK_EQ(result
->first
, i
+ N
);
129 int offs
= rnd
.Uniform(ptrs_and_sizes
[i
].size
);
130 CHECK(result
= map
.FindInside(&SizeFunc
, kMaxRealSize
, p
+ offs
, &res_p
));
132 CHECK_EQ(result
->first
, i
+ N
);
133 map
.Insert(p
, make_pair(i
+ 2*N
, ptrs_and_sizes
[i
].size
));
134 CHECK(result
= map
.Find(p
));
135 CHECK_EQ(result
->first
, i
+ 2*N
);
138 // Insert even entries back
139 for (int i
= 0; i
< N
; i
+= 2) {
140 char* p
= ptrs_and_sizes
[i
].ptr
;
141 int offs
= rnd
.Uniform(ptrs_and_sizes
[i
].size
);
142 CHECK(!map
.FindInside(&SizeFunc
, kMaxSize
, p
+ offs
, &res_p
));
143 map
.Insert(p
, make_pair(i
+ 2*N
, ptrs_and_sizes
[i
].size
));
144 CHECK(result
= map
.Find(p
));
145 CHECK_EQ(result
->first
, i
+ 2*N
);
146 CHECK(result
= map
.FindInside(&SizeFunc
, kMaxRealSize
, p
+ offs
, &res_p
));
148 CHECK_EQ(result
->first
, i
+ 2*N
);
152 set
<pair
<const void*, int> > check_set
;
153 map
.Iterate(SetCheckCallback
, &check_set
);
154 CHECK_EQ(check_set
.size(), N
);
155 for (int i
= 0; i
< N
; ++i
) {
156 void* p
= ptrs_and_sizes
[i
].ptr
;
157 check_set
.erase(make_pair(p
, i
+ 2*N
));
158 CHECK(result
= map
.Find(p
));
159 CHECK_EQ(result
->first
, i
+ 2*N
);
161 CHECK_EQ(check_set
.size(), 0);
164 for (int i
= 0; i
< N
; ++i
) {
165 delete[] ptrs_and_sizes
[i
].ptr
;