/src/mozilla-central/toolkit/components/url-classifier/tests/gtest/TestCaching.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #include "Common.h" |
6 | | |
7 | 0 | #define EXPIRED_TIME_SEC (PR_Now() / PR_USEC_PER_SEC - 3600) |
8 | 0 | #define NOTEXPIRED_TIME_SEC (PR_Now() / PR_USEC_PER_SEC + 3600) |
9 | | |
10 | | static void |
11 | | SetupCacheEntry(LookupCacheV2* aLookupCache, |
12 | | const nsCString& aCompletion, |
13 | | bool aNegExpired = false, |
14 | | bool aPosExpired = false) |
15 | 0 | { |
16 | 0 | AddCompleteArray completes; |
17 | 0 | AddCompleteArray emptyCompletes; |
18 | 0 | MissPrefixArray misses; |
19 | 0 | MissPrefixArray emptyMisses; |
20 | 0 |
|
21 | 0 | AddComplete* add = completes.AppendElement(fallible); |
22 | 0 | add->complete.FromPlaintext(aCompletion); |
23 | 0 |
|
24 | 0 | Prefix* prefix = misses.AppendElement(fallible); |
25 | 0 | prefix->FromPlaintext(aCompletion); |
26 | 0 |
|
27 | 0 | // Setup positive cache first otherwise negative cache expiry will be |
28 | 0 | // overwritten. |
29 | 0 | int64_t posExpirySec = aPosExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC; |
30 | 0 | aLookupCache->AddGethashResultToCache(completes, emptyMisses, posExpirySec); |
31 | 0 |
|
32 | 0 | int64_t negExpirySec = aNegExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC; |
33 | 0 | aLookupCache->AddGethashResultToCache(emptyCompletes, misses, negExpirySec); |
34 | 0 | } |
35 | | |
36 | | static void |
37 | | SetupCacheEntry(LookupCacheV4* aLookupCache, |
38 | | const nsCString& aCompletion, |
39 | | bool aNegExpired = false, |
40 | | bool aPosExpired = false) |
41 | 0 | { |
42 | 0 | FullHashResponseMap map; |
43 | 0 |
|
44 | 0 | Prefix prefix; |
45 | 0 | prefix.FromPlaintext(aCompletion); |
46 | 0 |
|
47 | 0 | CachedFullHashResponse* response = map.LookupOrAdd(prefix.ToUint32()); |
48 | 0 |
|
49 | 0 | response->negativeCacheExpirySec = |
50 | 0 | aNegExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC; |
51 | 0 | response->fullHashes.Put(GeneratePrefix(aCompletion, COMPLETE_SIZE), |
52 | 0 | aPosExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC); |
53 | 0 |
|
54 | 0 | aLookupCache->AddFullHashResponseToCache(map); |
55 | 0 | } |
56 | | |
57 | | template<typename T> |
58 | | void |
59 | | TestCache(const Completion aCompletion, |
60 | | bool aExpectedHas, |
61 | | bool aExpectedConfirmed, |
62 | | bool aExpectedInCache, |
63 | | T* aCache = nullptr) |
64 | 0 | { |
65 | 0 | bool has, inCache, confirmed; |
66 | 0 | uint32_t matchLength; |
67 | 0 |
|
68 | 0 | if (aCache) { |
69 | 0 | aCache->Has(aCompletion, &has, &matchLength, &confirmed); |
70 | 0 | inCache = aCache->IsInCache(aCompletion.ToUint32()); |
71 | 0 | } else { |
72 | 0 | _PrefixArray array = { GeneratePrefix(_Fragment("cache.notexpired.com/"), 10), |
73 | 0 | GeneratePrefix(_Fragment("cache.expired.com/"), 8), |
74 | 0 | GeneratePrefix(_Fragment("gound.com/"), 5), |
75 | 0 | GeneratePrefix(_Fragment("small.com/"), 4) |
76 | 0 | }; |
77 | 0 |
|
78 | 0 | RefPtr<T> cache = SetupLookupCache<T>(array); |
79 | 0 |
|
80 | 0 | // Create an expired entry and a non-expired entry |
81 | 0 | SetupCacheEntry(cache, _Fragment("cache.notexpired.com/")); |
82 | 0 | SetupCacheEntry(cache, _Fragment("cache.expired.com/"), true, true); |
83 | 0 |
|
84 | 0 | cache->Has(aCompletion, &has, &matchLength, &confirmed); |
85 | 0 | inCache = cache->IsInCache(aCompletion.ToUint32()); |
86 | 0 | } |
87 | 0 |
|
88 | 0 | EXPECT_EQ(has, aExpectedHas); |
89 | 0 | EXPECT_EQ(confirmed, aExpectedConfirmed); |
90 | 0 | EXPECT_EQ(inCache, aExpectedInCache); |
91 | 0 | } Unexecuted instantiation: void TestCache<mozilla::safebrowsing::LookupCacheV2>(mozilla::safebrowsing::SafebrowsingHash<32u, mozilla::safebrowsing::CompletionComparator>, bool, bool, bool, mozilla::safebrowsing::LookupCacheV2*) Unexecuted instantiation: void TestCache<mozilla::safebrowsing::LookupCacheV4>(mozilla::safebrowsing::SafebrowsingHash<32u, mozilla::safebrowsing::CompletionComparator>, bool, bool, bool, mozilla::safebrowsing::LookupCacheV4*) |
92 | | |
93 | | template<typename T> |
94 | | void |
95 | | TestCache(const _Fragment& aFragment, |
96 | | bool aExpectedHas, |
97 | | bool aExpectedConfirmed, |
98 | | bool aExpectedInCache, |
99 | | T* aCache = nullptr) |
100 | 0 | { |
101 | 0 | Completion lookupHash; |
102 | 0 | lookupHash.FromPlaintext(aFragment); |
103 | 0 |
|
104 | 0 | TestCache<T>(lookupHash, aExpectedHas, aExpectedConfirmed, aExpectedInCache, aCache); |
105 | 0 | } Unexecuted instantiation: void TestCache<mozilla::safebrowsing::LookupCacheV2>(nsTString<char> const&, bool, bool, bool, mozilla::safebrowsing::LookupCacheV2*) Unexecuted instantiation: void TestCache<mozilla::safebrowsing::LookupCacheV4>(nsTString<char> const&, bool, bool, bool, mozilla::safebrowsing::LookupCacheV4*) |
106 | | |
107 | | // This testcase check the returned result of |Has| API if fullhash cannot match |
108 | | // any prefix in the local database. |
109 | | TEST(UrlClassifierCaching, NotFound) |
110 | 0 | { |
111 | 0 | TestCache<LookupCacheV2>(_Fragment("nomatch.com/"), false, false, false); |
112 | 0 | TestCache<LookupCacheV4>(_Fragment("nomatch.com/"), false, false, false); |
113 | 0 | } |
114 | | |
115 | | // This testcase check the returned result of |Has| API if fullhash find a match |
116 | | // in the local database but not in the cache. |
117 | | TEST(UrlClassifierCaching, NotInCache) |
118 | 0 | { |
119 | 0 | TestCache<LookupCacheV2>(_Fragment("gound.com/"), true, false, false); |
120 | 0 | TestCache<LookupCacheV4>(_Fragment("gound.com/"), true, false, false); |
121 | 0 | } |
122 | | |
123 | | // This testcase check the returned result of |Has| API if fullhash matches |
124 | | // a cache entry in positive cache. |
125 | | TEST(UrlClassifierCaching, InPositiveCacheNotExpired) |
126 | 0 | { |
127 | 0 | TestCache<LookupCacheV2>(_Fragment("cache.notexpired.com/"), true, true, true); |
128 | 0 | TestCache<LookupCacheV4>(_Fragment("cache.notexpired.com/"), true, true, true); |
129 | 0 | } |
130 | | |
131 | | // This testcase check the returned result of |Has| API if fullhash matches |
132 | | // a cache entry in positive cache but that it is expired. |
133 | | TEST(UrlClassifierCaching, InPositiveCacheExpired) |
134 | 0 | { |
135 | 0 | TestCache<LookupCacheV2>(_Fragment("cache.expired.com/"), true, false, true); |
136 | 0 | TestCache<LookupCacheV4>(_Fragment("cache.expired.com/"), true, false, true); |
137 | 0 | } |
138 | | |
139 | | // This testcase check the returned result of |Has| API if fullhash matches |
140 | | // a cache entry in negative cache. |
141 | | TEST(UrlClassifierCaching, InNegativeCacheNotExpired) |
142 | 0 | { |
143 | 0 | // Create a fullhash whose prefix matches the prefix in negative cache |
144 | 0 | // but completion doesn't match any fullhash in positive cache. |
145 | 0 |
|
146 | 0 | Completion prefix; |
147 | 0 | prefix.FromPlaintext(_Fragment("cache.notexpired.com/")); |
148 | 0 |
|
149 | 0 | Completion fullhash; |
150 | 0 | fullhash.FromPlaintext(_Fragment("firefox.com/")); |
151 | 0 |
|
152 | 0 | // Overwrite the 4-byte prefix of `fullhash` so that it conflicts with `prefix`. |
153 | 0 | // Since "cache.notexpired.com" is added to database in TestCache as a |
154 | 0 | // 10-byte prefix, we should copy more than 10 bytes to fullhash to ensure |
155 | 0 | // it can match the prefix in database. |
156 | 0 | memcpy(fullhash.buf, prefix.buf, 10); |
157 | 0 |
|
158 | 0 | TestCache<LookupCacheV2>(fullhash, false, false, true); |
159 | 0 | TestCache<LookupCacheV4>(fullhash, false, false, true); |
160 | 0 | } |
161 | | |
162 | | // This testcase check the returned result of |Has| API if fullhash matches |
163 | | // a cache entry in negative cache but that entry is expired. |
164 | | TEST(UrlClassifierCaching, InNegativeCacheExpired) |
165 | 0 | { |
166 | 0 | // Create a fullhash whose prefix is in the cache. |
167 | 0 |
|
168 | 0 | Completion prefix; |
169 | 0 | prefix.FromPlaintext(_Fragment("cache.expired.com/")); |
170 | 0 |
|
171 | 0 | Completion fullhash; |
172 | 0 | fullhash.FromPlaintext(_Fragment("firefox.com/")); |
173 | 0 |
|
174 | 0 | memcpy(fullhash.buf, prefix.buf, 10); |
175 | 0 |
|
176 | 0 | TestCache<LookupCacheV2>(fullhash, true, false, true); |
177 | 0 | TestCache<LookupCacheV4>(fullhash, true, false, true); |
178 | 0 | } |
179 | | |
180 | 0 | #define CACHED_URL _Fragment("cache.com/") |
181 | 0 | #define NEG_CACHE_EXPIRED_URL _Fragment("cache.negExpired.com/") |
182 | 0 | #define POS_CACHE_EXPIRED_URL _Fragment("cache.posExpired.com/") |
183 | 0 | #define BOTH_CACHE_EXPIRED_URL _Fragment("cache.negAndposExpired.com/") |
184 | | |
185 | | // This testcase create 4 cache entries. |
186 | | // 1. unexpired entry. |
187 | | // 2. an entry whose negative cache time is expired but whose positive cache |
188 | | // is not expired. |
189 | | // 3. an entry whose positive cache time is expired |
190 | | // 4. an entry whose negative cache time and positive cache time are expired |
191 | | // After calling |InvalidateExpiredCacheEntry| API, entries with expired |
192 | | // negative time should be removed from cache(2 & 4) |
193 | | template<typename T> |
194 | | void TestInvalidateExpiredCacheEntry() |
195 | 0 | { |
196 | 0 | _PrefixArray array = { GeneratePrefix(CACHED_URL, 10), |
197 | 0 | GeneratePrefix(NEG_CACHE_EXPIRED_URL, 8), |
198 | 0 | GeneratePrefix(POS_CACHE_EXPIRED_URL, 5), |
199 | 0 | GeneratePrefix(BOTH_CACHE_EXPIRED_URL, 4) |
200 | 0 | }; |
201 | 0 | RefPtr<T> cache = SetupLookupCache<T>(array); |
202 | 0 |
|
203 | 0 | SetupCacheEntry(cache, CACHED_URL, false, false); |
204 | 0 | SetupCacheEntry(cache, NEG_CACHE_EXPIRED_URL, true, false); |
205 | 0 | SetupCacheEntry(cache, POS_CACHE_EXPIRED_URL, false, true); |
206 | 0 | SetupCacheEntry(cache, BOTH_CACHE_EXPIRED_URL, true, true); |
207 | 0 |
|
208 | 0 | // Before invalidate |
209 | 0 | TestCache<T>(CACHED_URL, true, true, true, cache.get()); |
210 | 0 | TestCache<T>(NEG_CACHE_EXPIRED_URL, true, true, true, cache.get()); |
211 | 0 | TestCache<T>(POS_CACHE_EXPIRED_URL, true, false, true, cache.get()); |
212 | 0 | TestCache<T>(BOTH_CACHE_EXPIRED_URL, true, false, true, cache.get()); |
213 | 0 |
|
214 | 0 | // Call InvalidateExpiredCacheEntry to remove cache entries whose negative cache |
215 | 0 | // time is expired |
216 | 0 | cache->InvalidateExpiredCacheEntries(); |
217 | 0 |
|
218 | 0 | // After invalidate, NEG_CACHE_EXPIRED_URL & BOTH_CACHE_EXPIRED_URL should |
219 | 0 | // not be found in cache. |
220 | 0 | TestCache<T>(NEG_CACHE_EXPIRED_URL, true, false, false, cache.get()); |
221 | 0 | TestCache<T>(BOTH_CACHE_EXPIRED_URL, true, false, false, cache.get()); |
222 | 0 |
|
223 | 0 | // Other entries should remain the same result. |
224 | 0 | TestCache<T>(CACHED_URL, true, true, true, cache.get()); |
225 | 0 | TestCache<T>(POS_CACHE_EXPIRED_URL, true, false, true, cache.get()); |
226 | 0 | } Unexecuted instantiation: void TestInvalidateExpiredCacheEntry<mozilla::safebrowsing::LookupCacheV2>() Unexecuted instantiation: void TestInvalidateExpiredCacheEntry<mozilla::safebrowsing::LookupCacheV4>() |
227 | | |
228 | | TEST(UrlClassifierCaching, InvalidateExpiredCacheEntryV2) |
229 | 0 | { |
230 | 0 | TestInvalidateExpiredCacheEntry<LookupCacheV2>(); |
231 | 0 | } |
232 | | |
233 | | TEST(UrlClassifierCaching, InvalidateExpiredCacheEntryV4) |
234 | 0 | { |
235 | 0 | TestInvalidateExpiredCacheEntry<LookupCacheV4>(); |
236 | 0 | } |
237 | | |
238 | | // This testcase check if an cache entry whose negative cache time is expired |
239 | | // and it doesn't have any postive cache entries in it, it should be removed |
240 | | // from cache after calling |Has|. |
241 | | TEST(UrlClassifierCaching, NegativeCacheExpireV2) |
242 | 0 | { |
243 | 0 | _PrefixArray array = { GeneratePrefix(NEG_CACHE_EXPIRED_URL, 8) }; |
244 | 0 | RefPtr<LookupCacheV2> cache = SetupLookupCache<LookupCacheV2>(array); |
245 | 0 |
|
246 | 0 | nsCOMPtr<nsICryptoHash> cryptoHash = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID); |
247 | 0 |
|
248 | 0 | MissPrefixArray misses; |
249 | 0 | Prefix* prefix = misses.AppendElement(fallible); |
250 | 0 | prefix->FromPlaintext(NEG_CACHE_EXPIRED_URL); |
251 | 0 |
|
252 | 0 | AddCompleteArray dummy; |
253 | 0 | cache->AddGethashResultToCache(dummy, misses, EXPIRED_TIME_SEC); |
254 | 0 |
|
255 | 0 | // Ensure it is in cache in the first place. |
256 | 0 | EXPECT_EQ(cache->IsInCache(prefix->ToUint32()), true); |
257 | 0 |
|
258 | 0 | // It should be removed after calling Has API. |
259 | 0 | TestCache<LookupCacheV2>(NEG_CACHE_EXPIRED_URL, true, false, false, cache.get()); |
260 | 0 | } |
261 | | |
262 | | TEST(UrlClassifierCaching, NegativeCacheExpireV4) |
263 | 0 | { |
264 | 0 | _PrefixArray array = { GeneratePrefix(NEG_CACHE_EXPIRED_URL, 8) }; |
265 | 0 | RefPtr<LookupCacheV4> cache = SetupLookupCache<LookupCacheV4>(array); |
266 | 0 |
|
267 | 0 | FullHashResponseMap map; |
268 | 0 | Prefix prefix; |
269 | 0 | nsCOMPtr<nsICryptoHash> cryptoHash = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID); |
270 | 0 | prefix.FromPlaintext(NEG_CACHE_EXPIRED_URL); |
271 | 0 | CachedFullHashResponse* response = map.LookupOrAdd(prefix.ToUint32()); |
272 | 0 |
|
273 | 0 | response->negativeCacheExpirySec = EXPIRED_TIME_SEC; |
274 | 0 |
|
275 | 0 | cache->AddFullHashResponseToCache(map); |
276 | 0 |
|
277 | 0 | // Ensure it is in cache in the first place. |
278 | 0 | EXPECT_EQ(cache->IsInCache(prefix.ToUint32()), true); |
279 | 0 |
|
280 | 0 | // It should be removed after calling Has API. |
281 | 0 | TestCache<LookupCacheV4>(NEG_CACHE_EXPIRED_URL, true, false, false, cache.get()); |
282 | 0 | } |