blob: 438d00a6019b9fc9e4da86512d39afeb0b1e6551 [file] [log] [blame]
mtkleinfb8307c2015-04-01 11:21:27 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkRefCnt.h"
9#include "include/core/SkString.h"
10#include "include/private/SkChecksum.h"
11#include "include/private/SkTHash.h"
Herb Derby72ce9be2021-07-26 11:42:37 -040012#include "src/core/SkOpts.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "tests/Test.h"
mtklein979e0ea2015-02-12 13:20:08 -080014
John Stiles7df731b2020-12-22 14:57:16 -050015#include <tuple>
16
mtklein02f46cf2015-03-20 13:48:42 -070017// Tests use of const foreach(). map.count() is of course the better way to do this.
18static int count(const SkTHashMap<int, double>& map) {
19 int n = 0;
20 map.foreach([&n](int, double) { n++; });
21 return n;
22}
mtklein979e0ea2015-02-12 13:20:08 -080023
24DEF_TEST(HashMap, r) {
mtklein02f46cf2015-03-20 13:48:42 -070025 SkTHashMap<int, double> map;
mtklein979e0ea2015-02-12 13:20:08 -080026
27 map.set(3, 4.0);
28 REPORTER_ASSERT(r, map.count() == 1);
29
mtklein469a3fe2015-08-07 09:33:37 -070030 REPORTER_ASSERT(r, map.approxBytesUsed() > 0);
31
mtklein979e0ea2015-02-12 13:20:08 -080032 double* found = map.find(3);
33 REPORTER_ASSERT(r, found);
34 REPORTER_ASSERT(r, *found == 4.0);
35
mtklein02f46cf2015-03-20 13:48:42 -070036 map.foreach([](int key, double* d){ *d = -key; });
37 REPORTER_ASSERT(r, count(map) == 1);
38
mtklein979e0ea2015-02-12 13:20:08 -080039 found = map.find(3);
40 REPORTER_ASSERT(r, found);
41 REPORTER_ASSERT(r, *found == -3.0);
42
43 REPORTER_ASSERT(r, !map.find(2));
44
45 const int N = 20;
46
47 for (int i = 0; i < N; i++) {
48 map.set(i, 2.0*i);
49 }
John Stiles9c0b79a2020-10-08 11:01:00 -040050
John Stiles7df731b2020-12-22 14:57:16 -050051 // Test walking the map with iterators, using preincrement (++iter).
52 for (SkTHashMap<int, double>::Iter iter = map.begin(); iter != map.end(); ++iter) {
53 REPORTER_ASSERT(r, iter->first * 2 == (*iter).second);
54 }
55
56 // Test walking the map with range-based for.
57 for (auto& entry : map) {
58 REPORTER_ASSERT(r, entry.first * 2 == entry.second);
59 }
60
61 // Ensure that iteration works equally well on a const map, using postincrement (iter++).
62 const auto& cmap = map;
63 for (SkTHashMap<int, double>::Iter iter = cmap.begin(); iter != cmap.end(); iter++) {
64 REPORTER_ASSERT(r, iter->first * 2 == (*iter).second);
65 }
66
67 // Ensure that range-based for works equally well on a const map.
68 for (const auto& entry : cmap) {
69 REPORTER_ASSERT(r, entry.first * 2 == entry.second);
70 }
71
72 // Ensure that structured bindings work.
73 for (const auto& [number, timesTwo] : cmap) {
74 REPORTER_ASSERT(r, number * 2 == timesTwo);
75 }
76
John Stiles9c0b79a2020-10-08 11:01:00 -040077 SkTHashMap<int, double> clone = map;
78
mtklein979e0ea2015-02-12 13:20:08 -080079 for (int i = 0; i < N; i++) {
John Stilesb7f22152021-08-11 15:42:39 -040080 found = map.find(i);
mtklein979e0ea2015-02-12 13:20:08 -080081 REPORTER_ASSERT(r, found);
82 REPORTER_ASSERT(r, *found == i*2.0);
John Stiles9c0b79a2020-10-08 11:01:00 -040083
84 found = clone.find(i);
85 REPORTER_ASSERT(r, found);
86 REPORTER_ASSERT(r, *found == i*2.0);
mtklein979e0ea2015-02-12 13:20:08 -080087 }
88 for (int i = N; i < 2*N; i++) {
89 REPORTER_ASSERT(r, !map.find(i));
John Stiles9c0b79a2020-10-08 11:01:00 -040090 REPORTER_ASSERT(r, !clone.find(i));
mtklein979e0ea2015-02-12 13:20:08 -080091 }
92
93 REPORTER_ASSERT(r, map.count() == N);
John Stiles9c0b79a2020-10-08 11:01:00 -040094 REPORTER_ASSERT(r, clone.count() == N);
mtklein2aa1f7e2015-02-20 12:35:32 -080095
mtklein33d73c32015-04-21 06:53:56 -070096 for (int i = 0; i < N/2; i++) {
97 map.remove(i);
98 }
99 for (int i = 0; i < N; i++) {
John Stilesb7f22152021-08-11 15:42:39 -0400100 found = map.find(i);
John Stiles9c0b79a2020-10-08 11:01:00 -0400101 REPORTER_ASSERT(r, (found == nullptr) == (i < N/2));
102
103 found = clone.find(i);
104 REPORTER_ASSERT(r, *found == i*2.0);
mtklein33d73c32015-04-21 06:53:56 -0700105 }
106 REPORTER_ASSERT(r, map.count() == N/2);
John Stiles9c0b79a2020-10-08 11:01:00 -0400107 REPORTER_ASSERT(r, clone.count() == N);
mtklein33d73c32015-04-21 06:53:56 -0700108
mtklein2aa1f7e2015-02-20 12:35:32 -0800109 map.reset();
110 REPORTER_ASSERT(r, map.count() == 0);
John Stiles9c0b79a2020-10-08 11:01:00 -0400111 REPORTER_ASSERT(r, clone.count() == N);
112
113 clone = map;
114 REPORTER_ASSERT(r, clone.count() == 0);
Florin Malita053730d2017-03-10 11:51:07 -0500115
116 {
117 // Test that we don't leave dangling values in empty slots.
118 SkTHashMap<int, sk_sp<SkRefCnt>> refMap;
119 auto ref = sk_make_sp<SkRefCnt>();
120 REPORTER_ASSERT(r, ref->unique());
121
122 refMap.set(0, ref);
123 REPORTER_ASSERT(r, refMap.count() == 1);
124 REPORTER_ASSERT(r, !ref->unique());
125
126 refMap.remove(0);
127 REPORTER_ASSERT(r, refMap.count() == 0);
128 REPORTER_ASSERT(r, ref->unique());
129 }
mtklein979e0ea2015-02-12 13:20:08 -0800130}
131
mtklein979e0ea2015-02-12 13:20:08 -0800132DEF_TEST(HashSet, r) {
mtklein02f46cf2015-03-20 13:48:42 -0700133 SkTHashSet<SkString> set;
mtklein979e0ea2015-02-12 13:20:08 -0800134
135 set.add(SkString("Hello"));
136 set.add(SkString("World"));
mtklein979e0ea2015-02-12 13:20:08 -0800137 REPORTER_ASSERT(r, set.count() == 2);
mtklein979e0ea2015-02-12 13:20:08 -0800138 REPORTER_ASSERT(r, set.contains(SkString("Hello")));
139 REPORTER_ASSERT(r, set.contains(SkString("World")));
140 REPORTER_ASSERT(r, !set.contains(SkString("Goodbye")));
mtkleinfb8307c2015-04-01 11:21:27 -0700141 REPORTER_ASSERT(r, set.find(SkString("Hello")));
142 REPORTER_ASSERT(r, *set.find(SkString("Hello")) == SkString("Hello"));
143
John Stiles7df731b2020-12-22 14:57:16 -0500144 // Test walking the set with iterators, using preincrement (++iter).
145 for (SkTHashSet<SkString>::Iter iter = set.begin(); iter != set.end(); ++iter) {
146 REPORTER_ASSERT(r, iter->equals("Hello") || (*iter).equals("World"));
147 }
148
149 // Test walking the set with iterators, using postincrement (iter++).
150 for (SkTHashSet<SkString>::Iter iter = set.begin(); iter != set.end(); iter++) {
151 REPORTER_ASSERT(r, iter->equals("Hello") || (*iter).equals("World"));
152 }
153
154 // Test walking the set with range-based for.
155 for (auto& entry : set) {
156 REPORTER_ASSERT(r, entry.equals("Hello") || entry.equals("World"));
157 }
158
159 // Ensure that iteration works equally well on a const set.
160 const auto& cset = set;
161 for (SkTHashSet<SkString>::Iter iter = cset.begin(); iter != cset.end(); iter++) {
162 REPORTER_ASSERT(r, iter->equals("Hello") || (*iter).equals("World"));
163 }
164
165 // Ensure that range-based for works equally well on a const set.
166 for (auto& entry : cset) {
167 REPORTER_ASSERT(r, entry.equals("Hello") || entry.equals("World"));
168 }
169
John Stiles9c0b79a2020-10-08 11:01:00 -0400170 SkTHashSet<SkString> clone = set;
171 REPORTER_ASSERT(r, clone.count() == 2);
172 REPORTER_ASSERT(r, clone.contains(SkString("Hello")));
173 REPORTER_ASSERT(r, clone.contains(SkString("World")));
174 REPORTER_ASSERT(r, !clone.contains(SkString("Goodbye")));
175 REPORTER_ASSERT(r, clone.find(SkString("Hello")));
176 REPORTER_ASSERT(r, *clone.find(SkString("Hello")) == SkString("Hello"));
177
mtklein33d73c32015-04-21 06:53:56 -0700178 set.remove(SkString("Hello"));
179 REPORTER_ASSERT(r, !set.contains(SkString("Hello")));
180 REPORTER_ASSERT(r, set.count() == 1);
John Stiles9c0b79a2020-10-08 11:01:00 -0400181 REPORTER_ASSERT(r, clone.contains(SkString("Hello")));
182 REPORTER_ASSERT(r, clone.count() == 2);
mtklein33d73c32015-04-21 06:53:56 -0700183
mtklein2aa1f7e2015-02-20 12:35:32 -0800184 set.reset();
185 REPORTER_ASSERT(r, set.count() == 0);
John Stiles9c0b79a2020-10-08 11:01:00 -0400186
187 clone = set;
188 REPORTER_ASSERT(r, clone.count() == 0);
mtklein979e0ea2015-02-12 13:20:08 -0800189}
fmalita79ca0812015-02-12 17:32:49 -0800190
191namespace {
192
193class CopyCounter {
194public:
halcanary96fcdcc2015-08-27 07:41:13 -0700195 CopyCounter() : fID(0), fCounter(nullptr) {}
fmalita79ca0812015-02-12 17:32:49 -0800196
197 CopyCounter(uint32_t id, uint32_t* counter) : fID(id), fCounter(counter) {}
198
199 CopyCounter(const CopyCounter& other)
200 : fID(other.fID)
201 , fCounter(other.fCounter) {
202 SkASSERT(fCounter);
203 *fCounter += 1;
204 }
205
206 void operator=(const CopyCounter& other) {
207 fID = other.fID;
208 fCounter = other.fCounter;
209 *fCounter += 1;
210 }
211
Mike Kleindb402ca2016-12-13 12:46:05 -0500212 CopyCounter(CopyCounter&& other) { *this = std::move(other); }
213 void operator=(CopyCounter&& other) {
214 fID = other.fID;
215 fCounter = other.fCounter;
216 }
217
218
fmalita79ca0812015-02-12 17:32:49 -0800219 bool operator==(const CopyCounter& other) const {
220 return fID == other.fID;
221 }
222
223private:
224 uint32_t fID;
225 uint32_t* fCounter;
226};
227
mtkleinc8d1dd42015-10-15 12:23:01 -0700228struct HashCopyCounter {
229 uint32_t operator()(const CopyCounter&) const {
230 return 0; // let them collide, what do we care?
231 }
232};
fmalita79ca0812015-02-12 17:32:49 -0800233
John Stilesa6841be2020-08-06 14:11:56 -0400234} // namespace
fmalita79ca0812015-02-12 17:32:49 -0800235
236DEF_TEST(HashSetCopyCounter, r) {
mtkleinc8d1dd42015-10-15 12:23:01 -0700237 SkTHashSet<CopyCounter, HashCopyCounter> set;
fmalita79ca0812015-02-12 17:32:49 -0800238
239 uint32_t globalCounter = 0;
240 CopyCounter copyCounter1(1, &globalCounter);
241 CopyCounter copyCounter2(2, &globalCounter);
242 REPORTER_ASSERT(r, globalCounter == 0);
243
244 set.add(copyCounter1);
245 REPORTER_ASSERT(r, globalCounter == 1);
246 REPORTER_ASSERT(r, set.contains(copyCounter1));
247 REPORTER_ASSERT(r, globalCounter == 1);
248 set.add(copyCounter1);
249 // We allow copies for same-value adds for now.
250 REPORTER_ASSERT(r, globalCounter == 2);
251
252 set.add(copyCounter2);
253 REPORTER_ASSERT(r, globalCounter == 3);
254 REPORTER_ASSERT(r, set.contains(copyCounter1));
255 REPORTER_ASSERT(r, set.contains(copyCounter2));
256 REPORTER_ASSERT(r, globalCounter == 3);
257 set.add(copyCounter1);
258 set.add(copyCounter2);
259 // We allow copies for same-value adds for now.
260 REPORTER_ASSERT(r, globalCounter == 5);
261}
Mike Klein4284ec62019-01-09 13:20:57 -0500262
263
264DEF_TEST(HashFindOrNull, r) {
265 struct Entry {
266 int key = 0;
267 int val = 0;
268 };
269
270 struct HashTraits {
271 static int GetKey(const Entry* e) { return e->key; }
272 static uint32_t Hash(int key) { return key; }
273 };
274
275 SkTHashTable<Entry*, int, HashTraits> table;
276
277 REPORTER_ASSERT(r, nullptr == table.findOrNull(7));
278
279 Entry seven = { 7, 24 };
280 table.set(&seven);
281
282 REPORTER_ASSERT(r, &seven == table.findOrNull(7));
283}
Herb Derby2fc9fa62019-12-12 15:07:11 -0500284
Mike Klein16701ee2020-03-14 10:03:50 -0500285DEF_TEST(HashTableGrowsAndShrinks, r) {
286 SkTHashSet<int> s;
287 auto check_count_cap = [&](int count, int cap) {
288 REPORTER_ASSERT(r, s.count() == count);
289 REPORTER_ASSERT(r, s.approxBytesUsed() == (sizeof(int) + sizeof(uint32_t)) * cap);
290 };
291
292 // Add and remove some elements to test basic growth and shrink patterns.
293 check_count_cap(0,0);
294 s.add(1); check_count_cap(1,4);
295 s.add(2); check_count_cap(2,4);
296 s.add(3); check_count_cap(3,4);
297 s.add(4); check_count_cap(4,8);
298
299 s.remove(4); check_count_cap(3,8);
300 s.remove(3); check_count_cap(2,4);
301 s.remove(2); check_count_cap(1,4);
302 s.remove(1); check_count_cap(0,4);
303
304 s.add(1); check_count_cap(1,4);
305 s.add(2); check_count_cap(2,4);
306 s.add(3); check_count_cap(3,4);
307 s.add(4); check_count_cap(4,8);
308
309 // Add and remove single elements repeatedly to test hysteresis
310 // avoids reallocating these small tables all the time.
311 for (int i = 0; i < 10; i++) {
312 s. add(5); check_count_cap(5,8);
313 s.remove(5); check_count_cap(4,8);
314 }
315
316 s.remove(4); check_count_cap(3,8);
317 for (int i = 0; i < 10; i++) {
318 s. add(4); check_count_cap(4,8);
319 s.remove(4); check_count_cap(3,8);
320 }
321
322 s.remove(3); check_count_cap(2,4);
323 for (int i = 0; i < 10; i++) {
324 s. add(4); check_count_cap(3,4);
325 s.remove(4); check_count_cap(2,4);
326 }
327
328 s.remove(2); check_count_cap(1,4);
329 for (int i = 0; i < 10; i++) {
330 s. add(2); check_count_cap(2,4);
331 s.remove(2); check_count_cap(1,4);
332 }
333}
Herb Derby72ce9be2021-07-26 11:42:37 -0400334
335DEF_TEST(HashCollision, r) {
336
337 // Two different sets of data. Same hash.
338 uint8_t data1[] = {
339 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 2, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 7, 0, 0, 0, 5, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 6, 0, 0, 0, 13, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 6, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 8, 0, 0, 0, 17, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 8, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 27, 0, 0, 0, 16, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 16, 0, 0, 0, 21, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 28, 0, 0, 0, 21, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 16, 0, 0, 0, 21, 0, 0, 0, 22, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 28, 0, 0, 0, 21, 0, 0, 0, 22, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 31, 0, 0, 0, 27, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 32, 0, 0, 0, 27, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 33, 0, 0, 0, 23, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 33, 0, 0, 0, 23, 0, 0, 0, 24, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
340 };
341 uint8_t data2[] = {
342 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 2, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 7, 0, 0, 0, 5, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 6, 0, 0, 0, 13, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 6, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 8, 0, 0, 0, 17, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 8, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 27, 0, 0, 0, 16, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 16, 0, 0, 0, 21, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 28, 0, 0, 0, 21, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 16, 0, 0, 0, 21, 0, 0, 0, 22, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 28, 0, 0, 0, 21, 0, 0, 0, 22, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 31, 0, 0, 0, 27, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 32, 0, 0, 0, 27, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 33, 0, 0, 0, 23, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 33, 0, 0, 0, 23, 0, 0, 0, 24, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
343 };
344
345 REPORTER_ASSERT(r, sizeof(data1) == sizeof(data2));
346 REPORTER_ASSERT(r, memcmp(data1, data2, sizeof(data1)) != 0);
347
348 uint32_t hash1 = SkOpts::hash(data1, sizeof(data1), 0);
349 uint32_t hash2 = SkOpts::hash(data2, sizeof(data2), 0);
350 REPORTER_ASSERT(r, hash1 != hash2);
351}