OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "Test.h" | 8 #include "Test.h" |
| 9 #include "SkRandom.h" |
9 #include "SkTDynamicHash.h" | 10 #include "SkTDynamicHash.h" |
10 | 11 |
11 namespace { | 12 namespace { |
12 | 13 |
13 struct Entry { | 14 struct Entry { |
14 int key; | 15 int key; |
15 double value; | 16 double value; |
16 }; | 17 }; |
17 | 18 |
18 const int& GetKey(const Entry& entry) { return entry.key; } | 19 const int& GetKey(const Entry& entry) { return entry.key; } |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 Hash hash(4); | 117 Hash hash(4); |
117 ASSERT(hash.capacity() == 4); | 118 ASSERT(hash.capacity() == 4); |
118 | 119 |
119 // These collide. | 120 // These collide. |
120 Entry a = { 1, 2.0 }; | 121 Entry a = { 1, 2.0 }; |
121 Entry b = { 5, 3.0 }; | 122 Entry b = { 5, 3.0 }; |
122 Entry c = { 9, 4.0 }; | 123 Entry c = { 9, 4.0 }; |
123 | 124 |
124 hash.add(&a); | 125 hash.add(&a); |
125 hash.add(&b); | 126 hash.add(&b); |
126 hash.remove(1); | 127 hash.remove(&a); |
127 // a should be marked deleted, and b should still be findable. | 128 // a should be marked deleted, and b should still be findable. |
128 | 129 |
129 ASSERT(hash.find(1) == NULL); | 130 ASSERT(hash.find(1) == NULL); |
130 ASSERT(hash.find(5) != NULL); | 131 ASSERT(hash.find(5) != NULL); |
131 ASSERT(hash.find(5)->value == 3.0); | 132 ASSERT(hash.find(5)->value == 3.0); |
132 | 133 |
133 // This will go in the same slot as 'a' did before. | 134 // This will go in the same slot as 'a' did before. |
134 ASSERT(hash.countCollisions(9) == 0); | 135 ASSERT(hash.countCollisions(9) == 0); |
135 hash.add(&c); | 136 hash.add(&c); |
136 ASSERT(hash.find(9) != NULL); | 137 ASSERT(hash.find(9) != NULL); |
137 ASSERT(hash.find(9)->value == 4.0); | 138 ASSERT(hash.find(9)->value == 4.0); |
138 ASSERT(hash.find(5) != NULL); | 139 ASSERT(hash.find(5) != NULL); |
139 ASSERT(hash.find(5)->value == 3.0); | 140 ASSERT(hash.find(5)->value == 3.0); |
140 } | 141 } |
141 | 142 |
| 143 struct MatchInstance { |
| 144 MatchInstance(Entry* toFind) : fToFind(toFind) { } |
| 145 bool operator()(const Entry* v) const { return v == fToFind; } |
| 146 Entry* fToFind; |
| 147 }; |
| 148 |
| 149 static void test_multiple_same_keys(skiatest::Reporter* reporter) { |
| 150 Hash hash(4); |
| 151 ASSERT(hash.capacity() == 4); |
| 152 |
| 153 Entry a = { 1, 2.0 }; |
| 154 Entry b = { 1, 3.0 }; |
| 155 Entry c = { 9, 4.0 }; |
| 156 |
| 157 hash.add(&a); |
| 158 hash.add(&b); |
| 159 hash.remove(&a); |
| 160 // a should be marked deleted, and b should still be findable. |
| 161 |
| 162 ASSERT(hash.find(1)->value == 3.0); |
| 163 |
| 164 hash.add(&c); |
| 165 ASSERT(hash.find(9) != NULL); |
| 166 ASSERT(hash.find(9)->value == 4.0); |
| 167 ASSERT(hash.find(1)->value == 3.0); |
| 168 |
| 169 ASSERT(hash.find(1, MatchInstance(&a)) == NULL); |
| 170 hash.add(&a); |
| 171 ASSERT(hash.find(1, MatchInstance(&a))->value == 2.0); |
| 172 ASSERT(hash.find(1, MatchInstance(&b))->value == 3.0); |
| 173 } |
| 174 |
| 175 static void test_validate(skiatest::Reporter* reporter) { |
| 176 // Test validate after construction for different initial capacitys. |
| 177 { |
| 178 Entry a = { 1, 2.0 }; |
| 179 Entry b = { 1, 3.0 }; |
| 180 Entry c = { 9, 4.0 }; |
| 181 |
| 182 for (int i = 0; i < 77; ++i) { |
| 183 Hash hash(i); |
| 184 hash.validate(); |
| 185 |
| 186 hash.add(&a); |
| 187 hash.validate(); |
| 188 hash.add(&b); |
| 189 hash.validate(); |
| 190 hash.add(&c); |
| 191 hash.validate(); |
| 192 |
| 193 ASSERT(hash.find(1) != NULL); |
| 194 ASSERT(hash.find(9) != NULL); |
| 195 hash.remove(&a); |
| 196 hash.validate(); |
| 197 ASSERT(hash.find(1) == &b); |
| 198 hash.remove(&b); |
| 199 hash.validate(); |
| 200 hash.add(&a); |
| 201 hash.validate(); |
| 202 ASSERT(hash.find(1) == &a); |
| 203 hash.remove(&a); |
| 204 hash.remove(&c); |
| 205 hash.validate(); |
| 206 } |
| 207 } |
| 208 |
| 209 { |
| 210 SkRandom rand; |
| 211 Entry entries[3333]; |
| 212 Hash hash; |
| 213 |
| 214 for (size_t i = 0; i < SK_ARRAY_COUNT(entries); ++i) { |
| 215 entries[i].key = rand.nextU(); |
| 216 entries[i].value = rand.nextF(); |
| 217 hash.add(&entries[i]); |
| 218 } |
| 219 |
| 220 hash.validate(); |
| 221 |
| 222 for (size_t i = 0; i < SK_ARRAY_COUNT(entries); i += 237) { |
| 223 ASSERT(hash.find(entries[i].key) != NULL); |
| 224 hash.remove(&entries[i]); |
| 225 hash.validate(); |
| 226 } |
| 227 } |
| 228 } |
| 229 |
142 static void test_dynamic_hash(skiatest::Reporter* reporter) { | 230 static void test_dynamic_hash(skiatest::Reporter* reporter) { |
143 test_growth(reporter); | 231 test_growth(reporter); |
144 test_add(reporter); | 232 test_add(reporter); |
145 test_lookup(reporter); | 233 test_lookup(reporter); |
146 test_remove(reporter); | 234 test_remove(reporter); |
| 235 test_multiple_same_keys(reporter); |
| 236 test_validate(reporter); |
147 } | 237 } |
148 | 238 |
149 #include "TestClassDef.h" | 239 #include "TestClassDef.h" |
150 DEFINE_TESTCLASS("DynamicHash", DynamicHashTestClass, test_dynamic_hash); | 240 DEFINE_TESTCLASS("DynamicHash", DynamicHashTestClass, test_dynamic_hash); |
OLD | NEW |