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 "SkChecksum.h"
9 #include "SkString.h"
10 #include "SkTHash.h"
11 #include "Test.h"
12 
13 // Tests use of const foreach().  map.count() is of course the better way to do this.
count(const SkTHashMap<int,double> & map)14 static int count(const SkTHashMap<int, double>& map) {
15     int n = 0;
16     map.foreach([&n](int, double) { n++; });
17     return n;
18 }
19 
DEF_TEST(HashMap,r)20 DEF_TEST(HashMap, r) {
21     SkTHashMap<int, double> map;
22 
23     map.set(3, 4.0);
24     REPORTER_ASSERT(r, map.count() == 1);
25 
26     REPORTER_ASSERT(r, map.approxBytesUsed() > 0);
27 
28     double* found = map.find(3);
29     REPORTER_ASSERT(r, found);
30     REPORTER_ASSERT(r, *found == 4.0);
31 
32     map.foreach([](int key, double* d){ *d = -key; });
33     REPORTER_ASSERT(r, count(map) == 1);
34 
35     found = map.find(3);
36     REPORTER_ASSERT(r, found);
37     REPORTER_ASSERT(r, *found == -3.0);
38 
39     REPORTER_ASSERT(r, !map.find(2));
40 
41     const int N = 20;
42 
43     for (int i = 0; i < N; i++) {
44         map.set(i, 2.0*i);
45     }
46     for (int i = 0; i < N; i++) {
47         double* found = map.find(i);
48         REPORTER_ASSERT(r, found);
49         REPORTER_ASSERT(r, *found == i*2.0);
50     }
51     for (int i = N; i < 2*N; i++) {
52         REPORTER_ASSERT(r, !map.find(i));
53     }
54 
55     REPORTER_ASSERT(r, map.count() == N);
56 
57     for (int i = 0; i < N/2; i++) {
58         map.remove(i);
59     }
60     for (int i = 0; i < N; i++) {
61         double* found = map.find(i);
62         REPORTER_ASSERT(r, (found == nullptr) ==  (i < N/2));
63     }
64     REPORTER_ASSERT(r, map.count() == N/2);
65 
66     map.reset();
67     REPORTER_ASSERT(r, map.count() == 0);
68 }
69 
DEF_TEST(HashSet,r)70 DEF_TEST(HashSet, r) {
71     SkTHashSet<SkString> set;
72 
73     set.add(SkString("Hello"));
74     set.add(SkString("World"));
75 
76     REPORTER_ASSERT(r, set.count() == 2);
77 
78     REPORTER_ASSERT(r, set.contains(SkString("Hello")));
79     REPORTER_ASSERT(r, set.contains(SkString("World")));
80     REPORTER_ASSERT(r, !set.contains(SkString("Goodbye")));
81 
82     REPORTER_ASSERT(r, set.find(SkString("Hello")));
83     REPORTER_ASSERT(r, *set.find(SkString("Hello")) == SkString("Hello"));
84 
85     set.remove(SkString("Hello"));
86     REPORTER_ASSERT(r, !set.contains(SkString("Hello")));
87     REPORTER_ASSERT(r, set.count() == 1);
88 
89     set.reset();
90     REPORTER_ASSERT(r, set.count() == 0);
91 }
92 
93 namespace {
94 
95 class CopyCounter {
96 public:
CopyCounter()97     CopyCounter() : fID(0), fCounter(nullptr) {}
98 
CopyCounter(uint32_t id,uint32_t * counter)99     CopyCounter(uint32_t id, uint32_t* counter) : fID(id), fCounter(counter) {}
100 
CopyCounter(const CopyCounter & other)101     CopyCounter(const CopyCounter& other)
102         : fID(other.fID)
103         , fCounter(other.fCounter) {
104         SkASSERT(fCounter);
105         *fCounter += 1;
106     }
107 
operator =(const CopyCounter & other)108     void operator=(const CopyCounter& other) {
109         fID = other.fID;
110         fCounter = other.fCounter;
111         *fCounter += 1;
112     }
113 
operator ==(const CopyCounter & other) const114     bool operator==(const CopyCounter& other) const {
115         return fID == other.fID;
116     }
117 
118 private:
119     uint32_t  fID;
120     uint32_t* fCounter;
121 };
122 
123 struct HashCopyCounter {
operator ()__anonbed1977f0311::HashCopyCounter124     uint32_t operator()(const CopyCounter&) const {
125         return 0; // let them collide, what do we care?
126     }
127 };
128 
129 }
130 
DEF_TEST(HashSetCopyCounter,r)131 DEF_TEST(HashSetCopyCounter, r) {
132     SkTHashSet<CopyCounter, HashCopyCounter> set;
133 
134     uint32_t globalCounter = 0;
135     CopyCounter copyCounter1(1, &globalCounter);
136     CopyCounter copyCounter2(2, &globalCounter);
137     REPORTER_ASSERT(r, globalCounter == 0);
138 
139     set.add(copyCounter1);
140     REPORTER_ASSERT(r, globalCounter == 1);
141     REPORTER_ASSERT(r, set.contains(copyCounter1));
142     REPORTER_ASSERT(r, globalCounter == 1);
143     set.add(copyCounter1);
144     // We allow copies for same-value adds for now.
145     REPORTER_ASSERT(r, globalCounter == 2);
146 
147     set.add(copyCounter2);
148     REPORTER_ASSERT(r, globalCounter == 3);
149     REPORTER_ASSERT(r, set.contains(copyCounter1));
150     REPORTER_ASSERT(r, set.contains(copyCounter2));
151     REPORTER_ASSERT(r, globalCounter == 3);
152     set.add(copyCounter1);
153     set.add(copyCounter2);
154     // We allow copies for same-value adds for now.
155     REPORTER_ASSERT(r, globalCounter == 5);
156 }
157