1 /*
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 
8 #include "include/core/SkRefCnt.h"
9 #include "include/core/SkString.h"
10 #include "include/core/SkTypes.h"
11 #include "src/core/SkOpts.h"
12 #include "src/core/SkTHash.h"
13 #include "tests/Test.h"
14 
15 #include <cstdint>
16 #include <cstring>
17 #include <initializer_list>
18 #include <string>
19 #include <string_view>
20 #include <utility>
21 
22 // Tests use of const foreach().  map.count() is of course the better way to do this.
count(const SkTHashMap<int,double> & map)23 static int count(const SkTHashMap<int, double>& map) {
24     int n = 0;
25     map.foreach([&n](int, double) { n++; });
26     return n;
27 }
28 
DEF_TEST(HashMap,r)29 DEF_TEST(HashMap, r) {
30     SkTHashMap<int, double> map;
31 
32     map.set(3, 4.0);
33     REPORTER_ASSERT(r, map.count() == 1);
34 
35     REPORTER_ASSERT(r, map.approxBytesUsed() > 0);
36 
37     double* found = map.find(3);
38     REPORTER_ASSERT(r, found);
39     REPORTER_ASSERT(r, *found == 4.0);
40 
41     map.foreach([](int key, double* d){ *d = -key; });
42     REPORTER_ASSERT(r, count(map) == 1);
43 
44     found = map.find(3);
45     REPORTER_ASSERT(r, found);
46     REPORTER_ASSERT(r, *found == -3.0);
47 
48     REPORTER_ASSERT(r, !map.find(2));
49 
50     const int N = 20;
51 
52     for (int i = 0; i < N; i++) {
53         map.set(i, 2.0*i);
54     }
55 
56     // Test walking the map with iterators, using preincrement (++iter).
57     for (SkTHashMap<int, double>::Iter iter = map.begin(); iter != map.end(); ++iter) {
58         REPORTER_ASSERT(r, iter->first * 2 == (*iter).second);
59     }
60 
61     // Test walking the map with range-based for.
62     for (auto& entry : map) {
63         REPORTER_ASSERT(r, entry.first * 2 == entry.second);
64     }
65 
66     // Ensure that iteration works equally well on a const map, using postincrement (iter++).
67     const auto& cmap = map;
68     for (SkTHashMap<int, double>::Iter iter = cmap.begin(); iter != cmap.end(); iter++) {
69         REPORTER_ASSERT(r, iter->first * 2 == (*iter).second);
70     }
71 
72     // Ensure that range-based for works equally well on a const map.
73     for (const auto& entry : cmap) {
74         REPORTER_ASSERT(r, entry.first * 2 == entry.second);
75     }
76 
77     // Ensure that structured bindings work.
78     for (const auto& [number, timesTwo] : cmap) {
79         REPORTER_ASSERT(r, number * 2 == timesTwo);
80     }
81 
82     SkTHashMap<int, double> clone = map;
83 
84     for (int i = 0; i < N; i++) {
85         found = map.find(i);
86         REPORTER_ASSERT(r, found);
87         REPORTER_ASSERT(r, *found == i*2.0);
88 
89         found = clone.find(i);
90         REPORTER_ASSERT(r, found);
91         REPORTER_ASSERT(r, *found == i*2.0);
92     }
93     for (int i = N; i < 2*N; i++) {
94         REPORTER_ASSERT(r, !map.find(i));
95         REPORTER_ASSERT(r, !clone.find(i));
96     }
97 
98     REPORTER_ASSERT(r, map.count() == N);
99     REPORTER_ASSERT(r, clone.count() == N);
100 
101     for (int i = 0; i < N/2; i++) {
102         map.remove(i);
103     }
104     for (int i = 0; i < N; i++) {
105         found = map.find(i);
106         REPORTER_ASSERT(r, (found == nullptr) == (i < N/2));
107 
108         found = clone.find(i);
109         REPORTER_ASSERT(r, *found == i*2.0);
110     }
111     REPORTER_ASSERT(r, map.count() == N/2);
112     REPORTER_ASSERT(r, clone.count() == N);
113 
114     map.reset();
115     REPORTER_ASSERT(r, map.count() == 0);
116     REPORTER_ASSERT(r, clone.count() == N);
117 
118     clone = map;
119     REPORTER_ASSERT(r, clone.count() == 0);
120 
121     {
122         // Test that we don't leave dangling values in empty slots.
123         SkTHashMap<int, sk_sp<SkRefCnt>> refMap;
124         auto ref = sk_make_sp<SkRefCnt>();
125         REPORTER_ASSERT(r, ref->unique());
126 
127         refMap.set(0, ref);
128         REPORTER_ASSERT(r, refMap.count() == 1);
129         REPORTER_ASSERT(r, !ref->unique());
130 
131         refMap.remove(0);
132         REPORTER_ASSERT(r, refMap.count() == 0);
133         REPORTER_ASSERT(r, ref->unique());
134     }
135 }
136 
DEF_TEST(HashMapCtor,r)137 DEF_TEST(HashMapCtor, r) {
138     SkTHashMap<int, std::string_view> map{{1, "one"}, {2, "two"}, {3, "three"}, {4, "four"}};
139     REPORTER_ASSERT(r, map.count() == 4);
140     REPORTER_ASSERT(r, map.approxBytesUsed() >= 4 * (sizeof(int) + sizeof(std::string_view)));
141 
142     std::string_view* found = map.find(1);
143     REPORTER_ASSERT(r, found);
144     REPORTER_ASSERT(r, *found == "one");
145 
146     found = map.find(2);
147     REPORTER_ASSERT(r, found);
148     REPORTER_ASSERT(r, *found == "two");
149 
150     found = map.find(3);
151     REPORTER_ASSERT(r, found);
152     REPORTER_ASSERT(r, *found == "three");
153 
154     found = map.find(4);
155     REPORTER_ASSERT(r, found);
156     REPORTER_ASSERT(r, *found == "four");
157 
158     found = map.find(5);
159     REPORTER_ASSERT(r, !found);
160 
161     found = map.find(6);
162     REPORTER_ASSERT(r, !found);
163 }
164 
DEF_TEST(HashMapCtorOneElem,r)165 DEF_TEST(HashMapCtorOneElem, r) {
166     // Start out with a single element. The initializer list constructor sets the capacity
167     // conservatively. Searching for elements beyond the capacity should succeed.
168     SkTHashMap<int, std::string_view> map{{1, "one"}};
169     REPORTER_ASSERT(r, map.count() == 1);
170     REPORTER_ASSERT(r, map.approxBytesUsed() >= (sizeof(int) + sizeof(std::string_view)));
171 
172     std::string_view* found = map.find(1);
173     REPORTER_ASSERT(r, found);
174     REPORTER_ASSERT(r, *found == "one");
175 
176     found = map.find(2);
177     REPORTER_ASSERT(r, !found);
178 
179     // Grow the collection by one element. Searching for non-existing elements should still succeed.
180     map.set(2, "two");
181     found = map.find(2);
182     REPORTER_ASSERT(r, found);
183     REPORTER_ASSERT(r, *found == "two");
184 
185     found = map.find(3);
186     REPORTER_ASSERT(r, !found);
187 }
188 
DEF_TEST(HashSetCtor,r)189 DEF_TEST(HashSetCtor, r) {
190     SkTHashSet<std::string_view> set{"one", "two", "three", "four"};
191     REPORTER_ASSERT(r, set.count() == 4);
192     REPORTER_ASSERT(r, set.approxBytesUsed() >= 4 * sizeof(std::string_view));
193 
194     REPORTER_ASSERT(r, set.contains("one"));
195     REPORTER_ASSERT(r, set.contains("two"));
196     REPORTER_ASSERT(r, set.contains("three"));
197     REPORTER_ASSERT(r, set.contains("four"));
198     REPORTER_ASSERT(r, !set.contains("five"));
199     REPORTER_ASSERT(r, !set.contains("six"));
200 }
201 
DEF_TEST(HashSetCtorOneElem,r)202 DEF_TEST(HashSetCtorOneElem, r) {
203     // Start out with a single element. The initializer list constructor sets the capacity
204     // conservatively. Searching for elements beyond the capacity should succeed.
205     SkTHashSet<std::string_view> set{"one"};
206     REPORTER_ASSERT(r, set.count() == 1);
207     REPORTER_ASSERT(r, set.approxBytesUsed() >= sizeof(std::string_view));
208 
209     REPORTER_ASSERT(r, set.contains("one"));
210     REPORTER_ASSERT(r, !set.contains("two"));
211 
212     // Grow the collection by one element. Searching for non-existing elements should still succeed.
213     set.add("two");
214     REPORTER_ASSERT(r, set.contains("one"));
215     REPORTER_ASSERT(r, set.contains("two"));
216     REPORTER_ASSERT(r, !set.contains("three"));
217 }
218 
219 template <typename T>
test_hash_set(skiatest::Reporter * r)220 static void test_hash_set(skiatest::Reporter* r) {
221     SkTHashSet<T> set;
222 
223     set.add(T("Hello"));
224     set.add(T("World"));
225     REPORTER_ASSERT(r, set.count() == 2);
226     REPORTER_ASSERT(r, set.contains(T("Hello")));
227     REPORTER_ASSERT(r, set.contains(T("World")));
228     REPORTER_ASSERT(r, !set.contains(T("Goodbye")));
229     REPORTER_ASSERT(r, set.find(T("Hello")));
230     REPORTER_ASSERT(r, *set.find(T("Hello")) == T("Hello"));
231 
232     // Test walking the set with iterators, using preincrement (++iter).
233     for (typename SkTHashSet<T>::Iter iter = set.begin(); iter != set.end(); ++iter) {
234         REPORTER_ASSERT(r, *iter == T("Hello") || *iter == T("World"));
235     }
236 
237     // Test walking the set with iterators, using postincrement (iter++).
238     for (typename SkTHashSet<T>::Iter iter = set.begin(); iter != set.end(); iter++) {
239         REPORTER_ASSERT(r, *iter == T("Hello") || *iter == T("World"));
240     }
241 
242     // Test walking the set with range-based for.
243     for (auto& entry : set) {
244         REPORTER_ASSERT(r, entry == T("Hello") || entry == T("World"));
245     }
246 
247     // Ensure that iteration works equally well on a const set.
248     const auto& cset = set;
249     for (typename SkTHashSet<T>::Iter iter = cset.begin(); iter != cset.end(); iter++) {
250         REPORTER_ASSERT(r, *iter == T("Hello") || *iter == T("World"));
251     }
252 
253     // Ensure that range-based for works equally well on a const set.
254     for (auto& entry : cset) {
255         REPORTER_ASSERT(r, entry == T("Hello") || entry == T("World"));
256     }
257 
258     SkTHashSet<T> clone = set;
259     REPORTER_ASSERT(r, clone.count() == 2);
260     REPORTER_ASSERT(r, clone.contains(T("Hello")));
261     REPORTER_ASSERT(r, clone.contains(T("World")));
262     REPORTER_ASSERT(r, !clone.contains(T("Goodbye")));
263     REPORTER_ASSERT(r, clone.find(T("Hello")));
264     REPORTER_ASSERT(r, *clone.find(T("Hello")) == T("Hello"));
265 
266     set.remove(T("Hello"));
267     REPORTER_ASSERT(r, !set.contains(T("Hello")));
268     REPORTER_ASSERT(r, set.count() == 1);
269     REPORTER_ASSERT(r, clone.contains(T("Hello")));
270     REPORTER_ASSERT(r, clone.count() == 2);
271 
272     set.reset();
273     REPORTER_ASSERT(r, set.count() == 0);
274 
275     clone = set;
276     REPORTER_ASSERT(r, clone.count() == 0);
277 }
278 
DEF_TEST(HashSetWithSkString,r)279 DEF_TEST(HashSetWithSkString, r) {
280     test_hash_set<SkString>(r);
281 }
282 
DEF_TEST(HashSetWithStdString,r)283 DEF_TEST(HashSetWithStdString, r) {
284     test_hash_set<std::string>(r);
285 }
286 
DEF_TEST(HashSetWithStdStringView,r)287 DEF_TEST(HashSetWithStdStringView, r) {
288     test_hash_set<std::string_view>(r);
289 }
290 
291 namespace {
292 
293 class CopyCounter {
294 public:
CopyCounter()295     CopyCounter() : fID(0), fCounter(nullptr) {}
296 
CopyCounter(uint32_t id,uint32_t * counter)297     CopyCounter(uint32_t id, uint32_t* counter) : fID(id), fCounter(counter) {}
298 
CopyCounter(const CopyCounter & other)299     CopyCounter(const CopyCounter& other)
300         : fID(other.fID)
301         , fCounter(other.fCounter) {
302         SkASSERT(fCounter);
303         *fCounter += 1;
304     }
305 
operator =(const CopyCounter & other)306     void operator=(const CopyCounter& other) {
307         fID = other.fID;
308         fCounter = other.fCounter;
309         *fCounter += 1;
310     }
311 
CopyCounter(CopyCounter && other)312     CopyCounter(CopyCounter&& other) { *this = std::move(other); }
operator =(CopyCounter && other)313     void operator=(CopyCounter&& other) {
314         fID = other.fID;
315         fCounter = other.fCounter;
316     }
317 
318 
operator ==(const CopyCounter & other) const319     bool operator==(const CopyCounter& other) const {
320         return fID == other.fID;
321     }
322 
323 private:
324     uint32_t  fID;
325     uint32_t* fCounter;
326 };
327 
328 struct HashCopyCounter {
operator ()__anonb26bbe040311::HashCopyCounter329     uint32_t operator()(const CopyCounter&) const {
330         return 0; // let them collide, what do we care?
331     }
332 };
333 
334 }  // namespace
335 
DEF_TEST(HashSetCopyCounter,r)336 DEF_TEST(HashSetCopyCounter, r) {
337     SkTHashSet<CopyCounter, HashCopyCounter> set;
338 
339     uint32_t globalCounter = 0;
340     CopyCounter copyCounter1(1, &globalCounter);
341     CopyCounter copyCounter2(2, &globalCounter);
342     REPORTER_ASSERT(r, globalCounter == 0);
343 
344     set.add(copyCounter1);
345     REPORTER_ASSERT(r, globalCounter == 1);
346     REPORTER_ASSERT(r, set.contains(copyCounter1));
347     REPORTER_ASSERT(r, globalCounter == 1);
348     set.add(copyCounter1);
349     // We allow copies for same-value adds for now.
350     REPORTER_ASSERT(r, globalCounter == 2);
351 
352     set.add(copyCounter2);
353     REPORTER_ASSERT(r, globalCounter == 3);
354     REPORTER_ASSERT(r, set.contains(copyCounter1));
355     REPORTER_ASSERT(r, set.contains(copyCounter2));
356     REPORTER_ASSERT(r, globalCounter == 3);
357     set.add(copyCounter1);
358     set.add(copyCounter2);
359     // We allow copies for same-value adds for now.
360     REPORTER_ASSERT(r, globalCounter == 5);
361 }
362 
363 
DEF_TEST(HashFindOrNull,r)364 DEF_TEST(HashFindOrNull, r) {
365     struct Entry {
366         int key = 0;
367         int val = 0;
368     };
369 
370     struct HashTraits {
371         static int GetKey(const Entry* e) { return e->key; }
372         static uint32_t Hash(int key) { return key; }
373     };
374 
375     SkTHashTable<Entry*, int, HashTraits> table;
376 
377     REPORTER_ASSERT(r, nullptr == table.findOrNull(7));
378 
379     Entry seven = { 7, 24 };
380     table.set(&seven);
381 
382     REPORTER_ASSERT(r, &seven == table.findOrNull(7));
383 }
384 
DEF_TEST(HashTableGrowsAndShrinks,r)385 DEF_TEST(HashTableGrowsAndShrinks, r) {
386     SkTHashSet<int> s;
387     auto check_count_cap = [&](int count, int cap) {
388         REPORTER_ASSERT(r, s.count() == count);
389         REPORTER_ASSERT(r, s.approxBytesUsed() == (sizeof(int) + sizeof(uint32_t)) * cap);
390     };
391 
392     // Add and remove some elements to test basic growth and shrink patterns.
393                  check_count_cap(0,0);
394     s.add(1);    check_count_cap(1,4);
395     s.add(2);    check_count_cap(2,4);
396     s.add(3);    check_count_cap(3,4);
397     s.add(4);    check_count_cap(4,8);
398 
399     s.remove(4); check_count_cap(3,8);
400     s.remove(3); check_count_cap(2,4);
401     s.remove(2); check_count_cap(1,4);
402     s.remove(1); check_count_cap(0,4);
403 
404     s.add(1);    check_count_cap(1,4);
405     s.add(2);    check_count_cap(2,4);
406     s.add(3);    check_count_cap(3,4);
407     s.add(4);    check_count_cap(4,8);
408 
409     // Add and remove single elements repeatedly to test hysteresis
410     // avoids reallocating these small tables all the time.
411     for (int i = 0; i < 10; i++) {
412         s.   add(5); check_count_cap(5,8);
413         s.remove(5); check_count_cap(4,8);
414     }
415 
416     s.remove(4);     check_count_cap(3,8);
417     for (int i = 0; i < 10; i++) {
418         s.   add(4); check_count_cap(4,8);
419         s.remove(4); check_count_cap(3,8);
420     }
421 
422     s.remove(3);     check_count_cap(2,4);
423     for (int i = 0; i < 10; i++) {
424         s.   add(4); check_count_cap(3,4);
425         s.remove(4); check_count_cap(2,4);
426     }
427 
428     s.remove(2);     check_count_cap(1,4);
429     for (int i = 0; i < 10; i++) {
430         s.   add(2); check_count_cap(2,4);
431         s.remove(2); check_count_cap(1,4);
432     }
433 }
434 
DEF_TEST(HashCollision,r)435 DEF_TEST(HashCollision, r) {
436 
437     // Two different sets of data. Same hash.
438     uint8_t data1[] = {
439         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,
440     };
441     uint8_t data2[] = {
442         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,
443     };
444 
445     REPORTER_ASSERT(r, sizeof(data1) == sizeof(data2));
446     REPORTER_ASSERT(r, memcmp(data1, data2, sizeof(data1)) != 0);
447 
448     uint32_t hash1 = SkOpts::hash(data1, sizeof(data1), 0);
449     uint32_t hash2 = SkOpts::hash(data2, sizeof(data2), 0);
450     REPORTER_ASSERT(r, hash1 != hash2);
451 }
452