blob: 667f8ea4c00b8695d7c4e7b01545d08c6b833502 [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
mtklein979e0ea2015-02-12 13:20:08 -08008#include "SkChecksum.h"
Florin Malita053730d2017-03-10 11:51:07 -05009#include "SkRefCnt.h"
mtklein979e0ea2015-02-12 13:20:08 -080010#include "SkString.h"
11#include "SkTHash.h"
12#include "Test.h"
13
mtklein02f46cf2015-03-20 13:48:42 -070014// Tests use of const foreach(). map.count() is of course the better way to do this.
15static int count(const SkTHashMap<int, double>& map) {
16 int n = 0;
17 map.foreach([&n](int, double) { n++; });
18 return n;
19}
mtklein979e0ea2015-02-12 13:20:08 -080020
21DEF_TEST(HashMap, r) {
mtklein02f46cf2015-03-20 13:48:42 -070022 SkTHashMap<int, double> map;
mtklein979e0ea2015-02-12 13:20:08 -080023
24 map.set(3, 4.0);
25 REPORTER_ASSERT(r, map.count() == 1);
26
mtklein469a3fe2015-08-07 09:33:37 -070027 REPORTER_ASSERT(r, map.approxBytesUsed() > 0);
28
mtklein979e0ea2015-02-12 13:20:08 -080029 double* found = map.find(3);
30 REPORTER_ASSERT(r, found);
31 REPORTER_ASSERT(r, *found == 4.0);
32
mtklein02f46cf2015-03-20 13:48:42 -070033 map.foreach([](int key, double* d){ *d = -key; });
34 REPORTER_ASSERT(r, count(map) == 1);
35
mtklein979e0ea2015-02-12 13:20:08 -080036 found = map.find(3);
37 REPORTER_ASSERT(r, found);
38 REPORTER_ASSERT(r, *found == -3.0);
39
40 REPORTER_ASSERT(r, !map.find(2));
41
42 const int N = 20;
43
44 for (int i = 0; i < N; i++) {
45 map.set(i, 2.0*i);
46 }
47 for (int i = 0; i < N; i++) {
tfarina567ff2f2015-04-27 07:01:44 -070048 double* found = map.find(i);
mtklein979e0ea2015-02-12 13:20:08 -080049 REPORTER_ASSERT(r, found);
50 REPORTER_ASSERT(r, *found == i*2.0);
51 }
52 for (int i = N; i < 2*N; i++) {
53 REPORTER_ASSERT(r, !map.find(i));
54 }
55
56 REPORTER_ASSERT(r, map.count() == N);
mtklein2aa1f7e2015-02-20 12:35:32 -080057
mtklein33d73c32015-04-21 06:53:56 -070058 for (int i = 0; i < N/2; i++) {
59 map.remove(i);
60 }
61 for (int i = 0; i < N; i++) {
62 double* found = map.find(i);
63 REPORTER_ASSERT(r, (found == nullptr) == (i < N/2));
64 }
65 REPORTER_ASSERT(r, map.count() == N/2);
66
mtklein2aa1f7e2015-02-20 12:35:32 -080067 map.reset();
68 REPORTER_ASSERT(r, map.count() == 0);
Florin Malita053730d2017-03-10 11:51:07 -050069
70 {
71 // Test that we don't leave dangling values in empty slots.
72 SkTHashMap<int, sk_sp<SkRefCnt>> refMap;
73 auto ref = sk_make_sp<SkRefCnt>();
74 REPORTER_ASSERT(r, ref->unique());
75
76 refMap.set(0, ref);
77 REPORTER_ASSERT(r, refMap.count() == 1);
78 REPORTER_ASSERT(r, !ref->unique());
79
80 refMap.remove(0);
81 REPORTER_ASSERT(r, refMap.count() == 0);
82 REPORTER_ASSERT(r, ref->unique());
83 }
mtklein979e0ea2015-02-12 13:20:08 -080084}
85
mtklein979e0ea2015-02-12 13:20:08 -080086DEF_TEST(HashSet, r) {
mtklein02f46cf2015-03-20 13:48:42 -070087 SkTHashSet<SkString> set;
mtklein979e0ea2015-02-12 13:20:08 -080088
89 set.add(SkString("Hello"));
90 set.add(SkString("World"));
91
92 REPORTER_ASSERT(r, set.count() == 2);
93
94 REPORTER_ASSERT(r, set.contains(SkString("Hello")));
95 REPORTER_ASSERT(r, set.contains(SkString("World")));
96 REPORTER_ASSERT(r, !set.contains(SkString("Goodbye")));
mtklein2aa1f7e2015-02-20 12:35:32 -080097
mtkleinfb8307c2015-04-01 11:21:27 -070098 REPORTER_ASSERT(r, set.find(SkString("Hello")));
99 REPORTER_ASSERT(r, *set.find(SkString("Hello")) == SkString("Hello"));
100
mtklein33d73c32015-04-21 06:53:56 -0700101 set.remove(SkString("Hello"));
102 REPORTER_ASSERT(r, !set.contains(SkString("Hello")));
103 REPORTER_ASSERT(r, set.count() == 1);
104
mtklein2aa1f7e2015-02-20 12:35:32 -0800105 set.reset();
106 REPORTER_ASSERT(r, set.count() == 0);
mtklein979e0ea2015-02-12 13:20:08 -0800107}
fmalita79ca0812015-02-12 17:32:49 -0800108
109namespace {
110
111class CopyCounter {
112public:
halcanary96fcdcc2015-08-27 07:41:13 -0700113 CopyCounter() : fID(0), fCounter(nullptr) {}
fmalita79ca0812015-02-12 17:32:49 -0800114
115 CopyCounter(uint32_t id, uint32_t* counter) : fID(id), fCounter(counter) {}
116
117 CopyCounter(const CopyCounter& other)
118 : fID(other.fID)
119 , fCounter(other.fCounter) {
120 SkASSERT(fCounter);
121 *fCounter += 1;
122 }
123
124 void operator=(const CopyCounter& other) {
125 fID = other.fID;
126 fCounter = other.fCounter;
127 *fCounter += 1;
128 }
129
Mike Kleindb402ca2016-12-13 12:46:05 -0500130 CopyCounter(CopyCounter&& other) { *this = std::move(other); }
131 void operator=(CopyCounter&& other) {
132 fID = other.fID;
133 fCounter = other.fCounter;
134 }
135
136
fmalita79ca0812015-02-12 17:32:49 -0800137 bool operator==(const CopyCounter& other) const {
138 return fID == other.fID;
139 }
140
141private:
142 uint32_t fID;
143 uint32_t* fCounter;
144};
145
mtkleinc8d1dd42015-10-15 12:23:01 -0700146struct HashCopyCounter {
147 uint32_t operator()(const CopyCounter&) const {
148 return 0; // let them collide, what do we care?
149 }
150};
fmalita79ca0812015-02-12 17:32:49 -0800151
152}
153
154DEF_TEST(HashSetCopyCounter, r) {
mtkleinc8d1dd42015-10-15 12:23:01 -0700155 SkTHashSet<CopyCounter, HashCopyCounter> set;
fmalita79ca0812015-02-12 17:32:49 -0800156
157 uint32_t globalCounter = 0;
158 CopyCounter copyCounter1(1, &globalCounter);
159 CopyCounter copyCounter2(2, &globalCounter);
160 REPORTER_ASSERT(r, globalCounter == 0);
161
162 set.add(copyCounter1);
163 REPORTER_ASSERT(r, globalCounter == 1);
164 REPORTER_ASSERT(r, set.contains(copyCounter1));
165 REPORTER_ASSERT(r, globalCounter == 1);
166 set.add(copyCounter1);
167 // We allow copies for same-value adds for now.
168 REPORTER_ASSERT(r, globalCounter == 2);
169
170 set.add(copyCounter2);
171 REPORTER_ASSERT(r, globalCounter == 3);
172 REPORTER_ASSERT(r, set.contains(copyCounter1));
173 REPORTER_ASSERT(r, set.contains(copyCounter2));
174 REPORTER_ASSERT(r, globalCounter == 3);
175 set.add(copyCounter1);
176 set.add(copyCounter2);
177 // We allow copies for same-value adds for now.
178 REPORTER_ASSERT(r, globalCounter == 5);
179}