Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(216)

Side by Side Diff: third_party/WebKit/Source/core/fetch/MemoryCacheTest.cpp

Issue 2584423002: Loading: move core/fetch to platform/loader/fetch (Closed)
Patch Set: rebase Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2013, Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "core/fetch/MemoryCache.h"
32
33 #include "core/fetch/MockResourceClient.h"
34 #include "core/fetch/RawResource.h"
35 #include "platform/network/ResourceRequest.h"
36 #include "platform/testing/UnitTestHelpers.h"
37 #include "public/platform/Platform.h"
38 #include "testing/gtest/include/gtest/gtest.h"
39
40 namespace blink {
41
42 class MemoryCacheTest : public ::testing::Test {
43 public:
44 class FakeDecodedResource final : public Resource {
45 public:
46 static FakeDecodedResource* create(const ResourceRequest& request,
47 Type type) {
48 return new FakeDecodedResource(request, type, ResourceLoaderOptions());
49 }
50
51 virtual void appendData(const char* data, size_t len) {
52 Resource::appendData(data, len);
53 setDecodedSize(this->size());
54 }
55
56 private:
57 FakeDecodedResource(const ResourceRequest& request,
58 Type type,
59 const ResourceLoaderOptions& options)
60 : Resource(request, type, options) {}
61
62 void destroyDecodedDataIfPossible() override { setDecodedSize(0); }
63 };
64
65 class FakeResource final : public Resource {
66 public:
67 static FakeResource* create(const ResourceRequest& request, Type type) {
68 return new FakeResource(request, type, ResourceLoaderOptions());
69 }
70
71 void fakeEncodedSize(size_t size) { setEncodedSize(size); }
72
73 private:
74 FakeResource(const ResourceRequest& request,
75 Type type,
76 const ResourceLoaderOptions& options)
77 : Resource(request, type, options) {}
78 };
79
80 protected:
81 virtual void SetUp() {
82 // Save the global memory cache to restore it upon teardown.
83 m_globalMemoryCache = replaceMemoryCacheForTesting(MemoryCache::create());
84 }
85
86 virtual void TearDown() {
87 replaceMemoryCacheForTesting(m_globalMemoryCache.release());
88 }
89
90 Persistent<MemoryCache> m_globalMemoryCache;
91 };
92
93 // Verifies that setters and getters for cache capacities work correcty.
94 TEST_F(MemoryCacheTest, CapacityAccounting) {
95 const size_t sizeMax = ~static_cast<size_t>(0);
96 const size_t totalCapacity = sizeMax / 4;
97 memoryCache()->setCapacity(totalCapacity);
98 EXPECT_EQ(totalCapacity, memoryCache()->capacity());
99 }
100
101 TEST_F(MemoryCacheTest, VeryLargeResourceAccounting) {
102 const size_t sizeMax = ~static_cast<size_t>(0);
103 const size_t totalCapacity = sizeMax / 4;
104 const size_t resourceSize1 = sizeMax / 16;
105 const size_t resourceSize2 = sizeMax / 20;
106 memoryCache()->setCapacity(totalCapacity);
107 FakeResource* cachedResource = FakeResource::create(
108 ResourceRequest("http://test/resource"), Resource::Raw);
109 cachedResource->fakeEncodedSize(resourceSize1);
110
111 EXPECT_EQ(0u, memoryCache()->size());
112 memoryCache()->add(cachedResource);
113 EXPECT_EQ(cachedResource->size(), memoryCache()->size());
114
115 Persistent<MockResourceClient> client =
116 new MockResourceClient(cachedResource);
117 EXPECT_EQ(cachedResource->size(), memoryCache()->size());
118
119 cachedResource->fakeEncodedSize(resourceSize2);
120 EXPECT_EQ(cachedResource->size(), memoryCache()->size());
121 }
122
123 static void runTask1(Resource* resource1, Resource* resource2) {
124 // The resource size has to be nonzero for this test to be meaningful, but
125 // we do not rely on it having any particular value.
126 EXPECT_GT(resource1->size(), 0u);
127 EXPECT_GT(resource2->size(), 0u);
128
129 EXPECT_EQ(0u, memoryCache()->size());
130
131 memoryCache()->add(resource1);
132 memoryCache()->add(resource2);
133
134 size_t totalSize = resource1->size() + resource2->size();
135 EXPECT_EQ(totalSize, memoryCache()->size());
136 EXPECT_GT(resource1->decodedSize(), 0u);
137 EXPECT_GT(resource2->decodedSize(), 0u);
138
139 // We expect actual pruning doesn't occur here synchronously but deferred
140 // to the end of this task, due to the previous pruning invoked in
141 // testResourcePruningAtEndOfTask().
142 memoryCache()->prune();
143 EXPECT_EQ(totalSize, memoryCache()->size());
144 EXPECT_GT(resource1->decodedSize(), 0u);
145 EXPECT_GT(resource2->decodedSize(), 0u);
146 }
147
148 static void runTask2(unsigned sizeWithoutDecode) {
149 // Next task: now, the resources was pruned.
150 EXPECT_EQ(sizeWithoutDecode, memoryCache()->size());
151 }
152
153 static void testResourcePruningAtEndOfTask(Resource* resource1,
154 Resource* resource2) {
155 memoryCache()->setDelayBeforeLiveDecodedPrune(0);
156
157 // Enforce pruning by adding |dummyResource| and then call prune().
158 Resource* dummyResource =
159 RawResource::create(ResourceRequest("http://dummy"), Resource::Raw);
160 memoryCache()->add(dummyResource);
161 EXPECT_GT(memoryCache()->size(), 1u);
162 const unsigned totalCapacity = 1;
163 memoryCache()->setCapacity(totalCapacity);
164 memoryCache()->prune();
165 memoryCache()->remove(dummyResource);
166 EXPECT_EQ(0u, memoryCache()->size());
167
168 const char data[6] = "abcde";
169 resource1->appendData(data, 3u);
170 resource1->finish();
171 Persistent<MockResourceClient> client = new MockResourceClient(resource2);
172 resource2->appendData(data, 4u);
173 resource2->finish();
174
175 Platform::current()->currentThread()->getWebTaskRunner()->postTask(
176 BLINK_FROM_HERE, WTF::bind(&runTask1, wrapPersistent(resource1),
177 wrapPersistent(resource2)));
178 Platform::current()->currentThread()->getWebTaskRunner()->postTask(
179 BLINK_FROM_HERE,
180 WTF::bind(&runTask2,
181 resource1->encodedSize() + resource1->overheadSize() +
182 resource2->encodedSize() + resource2->overheadSize()));
183 testing::runPendingTasks();
184 }
185
186 // Verified that when ordering a prune in a runLoop task, the prune
187 // is deferred to the end of the task.
188 TEST_F(MemoryCacheTest, ResourcePruningAtEndOfTask_Basic) {
189 Resource* resource1 = FakeDecodedResource::create(
190 ResourceRequest("http://test/resource1"), Resource::Raw);
191 Resource* resource2 = FakeDecodedResource::create(
192 ResourceRequest("http://test/resource2"), Resource::Raw);
193 testResourcePruningAtEndOfTask(resource1, resource2);
194 }
195
196 TEST_F(MemoryCacheTest, ResourcePruningAtEndOfTask_MultipleResourceMaps) {
197 {
198 Resource* resource1 = FakeDecodedResource::create(
199 ResourceRequest("http://test/resource1"), Resource::Raw);
200 Resource* resource2 = FakeDecodedResource::create(
201 ResourceRequest("http://test/resource2"), Resource::Raw);
202 resource1->setCacheIdentifier("foo");
203 testResourcePruningAtEndOfTask(resource1, resource2);
204 memoryCache()->evictResources();
205 }
206 {
207 Resource* resource1 = FakeDecodedResource::create(
208 ResourceRequest("http://test/resource1"), Resource::Raw);
209 Resource* resource2 = FakeDecodedResource::create(
210 ResourceRequest("http://test/resource2"), Resource::Raw);
211 resource1->setCacheIdentifier("foo");
212 resource2->setCacheIdentifier("bar");
213 testResourcePruningAtEndOfTask(resource1, resource2);
214 memoryCache()->evictResources();
215 }
216 }
217
218 // Verifies that
219 // - Resources are not pruned synchronously when ResourceClient is removed.
220 // - size() is updated appropriately when Resources are added to MemoryCache
221 // and garbage collected.
222 static void testClientRemoval(Resource* resource1, Resource* resource2) {
223 const char data[6] = "abcde";
224 Persistent<MockResourceClient> client1 = new MockResourceClient(resource1);
225 resource1->appendData(data, 4u);
226 Persistent<MockResourceClient> client2 = new MockResourceClient(resource2);
227 resource2->appendData(data, 4u);
228
229 memoryCache()->setCapacity(0);
230 memoryCache()->add(resource1);
231 memoryCache()->add(resource2);
232
233 size_t originalTotalSize = resource1->size() + resource2->size();
234
235 // Call prune. There is nothing to prune, but this will initialize
236 // the prune timestamp, allowing future prunes to be deferred.
237 memoryCache()->prune();
238 EXPECT_GT(resource1->decodedSize(), 0u);
239 EXPECT_GT(resource2->decodedSize(), 0u);
240 EXPECT_EQ(originalTotalSize, memoryCache()->size());
241
242 // Removing the client from resource1 should not trigger pruning.
243 client1->removeAsClient();
244 EXPECT_GT(resource1->decodedSize(), 0u);
245 EXPECT_GT(resource2->decodedSize(), 0u);
246 EXPECT_EQ(originalTotalSize, memoryCache()->size());
247 EXPECT_TRUE(memoryCache()->contains(resource1));
248 EXPECT_TRUE(memoryCache()->contains(resource2));
249
250 // Removing the client from resource2 should not trigger pruning.
251 client2->removeAsClient();
252 EXPECT_GT(resource1->decodedSize(), 0u);
253 EXPECT_GT(resource2->decodedSize(), 0u);
254 EXPECT_EQ(originalTotalSize, memoryCache()->size());
255 EXPECT_TRUE(memoryCache()->contains(resource1));
256 EXPECT_TRUE(memoryCache()->contains(resource2));
257
258 WeakPersistent<Resource> resource1Weak = resource1;
259 WeakPersistent<Resource> resource2Weak = resource2;
260
261 ThreadState::current()->collectGarbage(
262 BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, BlinkGC::ForcedGC);
263 // Resources are garbage-collected (WeakMemoryCache) and thus removed
264 // from MemoryCache.
265 EXPECT_FALSE(resource1Weak);
266 EXPECT_FALSE(resource2Weak);
267 EXPECT_EQ(0u, memoryCache()->size());
268 }
269
270 TEST_F(MemoryCacheTest, ClientRemoval_Basic) {
271 Resource* resource1 = FakeDecodedResource::create(
272 ResourceRequest("http://foo.com"), Resource::Raw);
273 Resource* resource2 = FakeDecodedResource::create(
274 ResourceRequest("http://test/resource"), Resource::Raw);
275 testClientRemoval(resource1, resource2);
276 }
277
278 TEST_F(MemoryCacheTest, ClientRemoval_MultipleResourceMaps) {
279 {
280 Resource* resource1 = FakeDecodedResource::create(
281 ResourceRequest("http://foo.com"), Resource::Raw);
282 resource1->setCacheIdentifier("foo");
283 Resource* resource2 = FakeDecodedResource::create(
284 ResourceRequest("http://test/resource"), Resource::Raw);
285 testClientRemoval(resource1, resource2);
286 memoryCache()->evictResources();
287 }
288 {
289 Resource* resource1 = FakeDecodedResource::create(
290 ResourceRequest("http://foo.com"), Resource::Raw);
291 Resource* resource2 = FakeDecodedResource::create(
292 ResourceRequest("http://test/resource"), Resource::Raw);
293 resource2->setCacheIdentifier("foo");
294 testClientRemoval(resource1, resource2);
295 memoryCache()->evictResources();
296 }
297 {
298 Resource* resource1 = FakeDecodedResource::create(
299 ResourceRequest("http://test/resource"), Resource::Raw);
300 resource1->setCacheIdentifier("foo");
301 Resource* resource2 = FakeDecodedResource::create(
302 ResourceRequest("http://test/resource"), Resource::Raw);
303 resource2->setCacheIdentifier("bar");
304 testClientRemoval(resource1, resource2);
305 memoryCache()->evictResources();
306 }
307 }
308
309 TEST_F(MemoryCacheTest, RemoveDuringRevalidation) {
310 FakeResource* resource1 = FakeResource::create(
311 ResourceRequest("http://test/resource"), Resource::Raw);
312 memoryCache()->add(resource1);
313
314 FakeResource* resource2 = FakeResource::create(
315 ResourceRequest("http://test/resource"), Resource::Raw);
316 memoryCache()->remove(resource1);
317 memoryCache()->add(resource2);
318 EXPECT_TRUE(memoryCache()->contains(resource2));
319 EXPECT_FALSE(memoryCache()->contains(resource1));
320
321 FakeResource* resource3 = FakeResource::create(
322 ResourceRequest("http://test/resource"), Resource::Raw);
323 memoryCache()->remove(resource2);
324 memoryCache()->add(resource3);
325 EXPECT_TRUE(memoryCache()->contains(resource3));
326 EXPECT_FALSE(memoryCache()->contains(resource2));
327 }
328
329 TEST_F(MemoryCacheTest, ResourceMapIsolation) {
330 FakeResource* resource1 = FakeResource::create(
331 ResourceRequest("http://test/resource"), Resource::Raw);
332 memoryCache()->add(resource1);
333
334 FakeResource* resource2 = FakeResource::create(
335 ResourceRequest("http://test/resource"), Resource::Raw);
336 resource2->setCacheIdentifier("foo");
337 memoryCache()->add(resource2);
338 EXPECT_TRUE(memoryCache()->contains(resource1));
339 EXPECT_TRUE(memoryCache()->contains(resource2));
340
341 const KURL url = KURL(ParsedURLString, "http://test/resource");
342 EXPECT_EQ(resource1, memoryCache()->resourceForURL(url));
343 EXPECT_EQ(resource1, memoryCache()->resourceForURL(
344 url, memoryCache()->defaultCacheIdentifier()));
345 EXPECT_EQ(resource2, memoryCache()->resourceForURL(url, "foo"));
346 EXPECT_EQ(0, memoryCache()->resourceForURL(KURL()));
347
348 FakeResource* resource3 = FakeResource::create(
349 ResourceRequest("http://test/resource"), Resource::Raw);
350 resource3->setCacheIdentifier("foo");
351 memoryCache()->remove(resource2);
352 memoryCache()->add(resource3);
353 EXPECT_TRUE(memoryCache()->contains(resource1));
354 EXPECT_FALSE(memoryCache()->contains(resource2));
355 EXPECT_TRUE(memoryCache()->contains(resource3));
356
357 HeapVector<Member<Resource>> resources = memoryCache()->resourcesForURL(url);
358 EXPECT_EQ(2u, resources.size());
359
360 memoryCache()->evictResources();
361 EXPECT_FALSE(memoryCache()->contains(resource1));
362 EXPECT_FALSE(memoryCache()->contains(resource3));
363 }
364
365 TEST_F(MemoryCacheTest, FragmentIdentifier) {
366 const KURL url1 = KURL(ParsedURLString, "http://test/resource#foo");
367 FakeResource* resource =
368 FakeResource::create(ResourceRequest(url1), Resource::Raw);
369 memoryCache()->add(resource);
370 EXPECT_TRUE(memoryCache()->contains(resource));
371
372 EXPECT_EQ(resource, memoryCache()->resourceForURL(url1));
373
374 const KURL url2 = MemoryCache::removeFragmentIdentifierIfNeeded(url1);
375 EXPECT_EQ(resource, memoryCache()->resourceForURL(url2));
376 }
377
378 TEST_F(MemoryCacheTest, RemoveURLFromCache) {
379 const KURL url1 = KURL(ParsedURLString, "http://test/resource1");
380 Persistent<FakeResource> resource1 =
381 FakeResource::create(ResourceRequest(url1), Resource::Raw);
382 memoryCache()->add(resource1);
383 EXPECT_TRUE(memoryCache()->contains(resource1));
384
385 memoryCache()->removeURLFromCache(url1);
386 EXPECT_FALSE(memoryCache()->contains(resource1));
387
388 const KURL url2 = KURL(ParsedURLString, "http://test/resource2#foo");
389 FakeResource* resource2 =
390 FakeResource::create(ResourceRequest(url2), Resource::Raw);
391 memoryCache()->add(resource2);
392 EXPECT_TRUE(memoryCache()->contains(resource2));
393
394 memoryCache()->removeURLFromCache(url2);
395 EXPECT_FALSE(memoryCache()->contains(resource2));
396 }
397
398 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698