2 * Copyright (c) 2013, Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
32 #include "core/fetch/MemoryCache.h"
34 #include "core/fetch/MockImageResourceClient.h"
35 #include "core/fetch/RawResource.h"
36 #include "core/fetch/ResourcePtr.h"
37 #include "platform/network/ResourceRequest.h"
38 #include "public/platform/Platform.h"
39 #include "wtf/OwnPtr.h"
41 #include <gtest/gtest.h>
45 class MemoryCacheTest : public ::testing::Test {
47 class FakeDecodedResource : public blink::Resource {
49 FakeDecodedResource(const ResourceRequest& request, Type type)
50 : Resource(request, type)
54 virtual void appendData(const char* data, unsigned len)
56 Resource::appendData(data, len);
57 setDecodedSize(this->size());
61 virtual void destroyDecodedDataIfPossible() override
67 class FakeResource : public blink::Resource {
69 FakeResource(const ResourceRequest& request, Type type)
70 : Resource(request, type)
74 void fakeEncodedSize(size_t size)
83 // Save the global memory cache to restore it upon teardown.
84 m_globalMemoryCache = replaceMemoryCacheForTesting(MemoryCache::create());
87 virtual void TearDown()
89 replaceMemoryCacheForTesting(m_globalMemoryCache.release());
92 OwnPtrWillBePersistent<MemoryCache> m_globalMemoryCache;
95 // Verifies that setters and getters for cache capacities work correcty.
96 TEST_F(MemoryCacheTest, CapacityAccounting)
98 const size_t sizeMax = ~static_cast<size_t>(0);
99 const size_t totalCapacity = sizeMax / 4;
100 const size_t minDeadCapacity = sizeMax / 16;
101 const size_t maxDeadCapacity = sizeMax / 8;
102 memoryCache()->setCapacities(minDeadCapacity, maxDeadCapacity, totalCapacity);
103 ASSERT_EQ(totalCapacity, memoryCache()->capacity());
104 ASSERT_EQ(minDeadCapacity, memoryCache()->minDeadCapacity());
105 ASSERT_EQ(maxDeadCapacity, memoryCache()->maxDeadCapacity());
108 TEST_F(MemoryCacheTest, VeryLargeResourceAccounting)
110 const size_t sizeMax = ~static_cast<size_t>(0);
111 const size_t totalCapacity = sizeMax / 4;
112 const size_t minDeadCapacity = sizeMax / 16;
113 const size_t maxDeadCapacity = sizeMax / 8;
114 const size_t resourceSize1 = sizeMax / 16;
115 const size_t resourceSize2 = sizeMax / 20;
116 memoryCache()->setCapacities(minDeadCapacity, maxDeadCapacity, totalCapacity);
117 ResourcePtr<FakeResource> cachedResource =
118 new FakeResource(ResourceRequest("http://test/resource"), Resource::Raw);
119 cachedResource->fakeEncodedSize(resourceSize1);
121 ASSERT_EQ(0u, memoryCache()->deadSize());
122 ASSERT_EQ(0u, memoryCache()->liveSize());
123 memoryCache()->add(cachedResource.get());
124 ASSERT_EQ(cachedResource->size(), memoryCache()->deadSize());
125 ASSERT_EQ(0u, memoryCache()->liveSize());
127 MockImageResourceClient client;
128 cachedResource->addClient(&client);
129 ASSERT_EQ(0u, memoryCache()->deadSize());
130 ASSERT_EQ(cachedResource->size(), memoryCache()->liveSize());
132 cachedResource->fakeEncodedSize(resourceSize2);
133 ASSERT_EQ(0u, memoryCache()->deadSize());
134 ASSERT_EQ(cachedResource->size(), memoryCache()->liveSize());
136 cachedResource->removeClient(&client);
139 // Verifies that dead resources that exceed dead resource capacity are evicted
140 // from cache when pruning.
141 static void TestDeadResourceEviction(Resource* resource1, Resource* resource2)
143 memoryCache()->setDelayBeforeLiveDecodedPrune(0);
144 memoryCache()->setMaxPruneDeferralDelay(0);
145 const unsigned totalCapacity = 1000000;
146 const unsigned minDeadCapacity = 0;
147 const unsigned maxDeadCapacity = 0;
148 memoryCache()->setCapacities(minDeadCapacity, maxDeadCapacity, totalCapacity);
150 const char data[5] = "abcd";
151 resource1->appendData(data, 3u);
152 resource2->appendData(data, 2u);
154 // The resource size has to be nonzero for this test to be meaningful, but
155 // we do not rely on it having any particular value.
156 ASSERT_GT(resource1->size(), 0u);
157 ASSERT_GT(resource2->size(), 0u);
159 ASSERT_EQ(0u, memoryCache()->deadSize());
160 ASSERT_EQ(0u, memoryCache()->liveSize());
162 memoryCache()->add(resource1);
163 ASSERT_EQ(resource1->size(), memoryCache()->deadSize());
164 ASSERT_EQ(0u, memoryCache()->liveSize());
166 memoryCache()->add(resource2);
167 ASSERT_EQ(resource1->size() + resource2->size(), memoryCache()->deadSize());
168 ASSERT_EQ(0u, memoryCache()->liveSize());
170 memoryCache()->prune();
171 ASSERT_EQ(0u, memoryCache()->deadSize());
172 ASSERT_EQ(0u, memoryCache()->liveSize());
175 TEST_F(MemoryCacheTest, DeadResourceEviction_Basic)
177 Resource* resource1 =
178 new Resource(ResourceRequest("http://test/resource1"), Resource::Raw);
179 Resource* resource2 =
180 new Resource(ResourceRequest("http://test/resource2"), Resource::Raw);
181 TestDeadResourceEviction(resource1, resource2);
184 TEST_F(MemoryCacheTest, DeadResourceEviction_MultipleResourceMaps)
186 Resource* resource1 =
187 new Resource(ResourceRequest("http://test/resource1"), Resource::Raw);
188 Resource* resource2 =
189 new Resource(ResourceRequest("http://test/resource2"), Resource::Raw);
190 resource2->setCacheIdentifier("foo");
191 TestDeadResourceEviction(resource1, resource2);
194 static void TestLiveResourceEvictionAtEndOfTask(Resource* cachedDeadResource, const ResourcePtr<Resource>& cachedLiveResource)
196 memoryCache()->setDelayBeforeLiveDecodedPrune(0);
197 const unsigned totalCapacity = 1;
198 const unsigned minDeadCapacity = 0;
199 const unsigned maxDeadCapacity = 0;
200 memoryCache()->setCapacities(minDeadCapacity, maxDeadCapacity, totalCapacity);
201 const char data[6] = "abcde";
202 cachedDeadResource->appendData(data, 3u);
203 MockImageResourceClient client;
204 cachedLiveResource->addClient(&client);
205 cachedLiveResource->appendData(data, 4u);
207 class Task1 : public blink::WebThread::Task {
209 Task1(const ResourcePtr<Resource>& live, Resource* dead)
214 virtual void run() override
216 // The resource size has to be nonzero for this test to be meaningful, but
217 // we do not rely on it having any particular value.
218 ASSERT_GT(m_live->size(), 0u);
219 ASSERT_GT(m_dead->size(), 0u);
221 ASSERT_EQ(0u, memoryCache()->deadSize());
222 ASSERT_EQ(0u, memoryCache()->liveSize());
224 memoryCache()->add(m_dead);
225 memoryCache()->add(m_live.get());
226 memoryCache()->updateDecodedResource(m_live.get(), UpdateForPropertyChange);
227 ASSERT_EQ(m_dead->size(), memoryCache()->deadSize());
228 ASSERT_EQ(m_live->size(), memoryCache()->liveSize());
229 ASSERT_GT(m_live->decodedSize(), 0u);
231 memoryCache()->prune(); // Dead resources are pruned immediately
232 ASSERT_EQ(m_dead->size(), memoryCache()->deadSize());
233 ASSERT_EQ(m_live->size(), memoryCache()->liveSize());
234 ASSERT_GT(m_live->decodedSize(), 0u);
238 ResourcePtr<Resource> m_live;
242 class Task2 : public blink::WebThread::Task {
244 Task2(unsigned liveSizeWithoutDecode)
245 : m_liveSizeWithoutDecode(liveSizeWithoutDecode) { }
247 virtual void run() override
249 // Next task: now, the live resource was evicted.
250 ASSERT_EQ(0u, memoryCache()->deadSize());
251 ASSERT_EQ(m_liveSizeWithoutDecode, memoryCache()->liveSize());
252 blink::Platform::current()->currentThread()->exitRunLoop();
256 unsigned m_liveSizeWithoutDecode;
260 blink::Platform::current()->currentThread()->postTask(new Task1(cachedLiveResource, cachedDeadResource));
261 blink::Platform::current()->currentThread()->postTask(new Task2(cachedLiveResource->encodedSize() + cachedLiveResource->overheadSize()));
262 blink::Platform::current()->currentThread()->enterRunLoop();
263 cachedLiveResource->removeClient(&client);
266 // Verified that when ordering a prune in a runLoop task, the prune
267 // is deferred to the end of the task.
268 TEST_F(MemoryCacheTest, LiveResourceEvictionAtEndOfTask_Basic)
270 Resource* cachedDeadResource =
271 new Resource(ResourceRequest("hhtp://foo"), Resource::Raw);
272 ResourcePtr<Resource> cachedLiveResource =
273 new FakeDecodedResource(ResourceRequest("http://test/resource"), Resource::Raw);
274 TestLiveResourceEvictionAtEndOfTask(cachedDeadResource, cachedLiveResource);
277 TEST_F(MemoryCacheTest, LiveResourceEvictionAtEndOfTask_MultipleResourceMaps)
280 Resource* cachedDeadResource =
281 new Resource(ResourceRequest("hhtp://foo"), Resource::Raw);
282 cachedDeadResource->setCacheIdentifier("foo");
283 ResourcePtr<Resource> cachedLiveResource =
284 new FakeDecodedResource(ResourceRequest("http://test/resource"), Resource::Raw);
285 TestLiveResourceEvictionAtEndOfTask(cachedDeadResource, cachedLiveResource);
286 memoryCache()->evictResources();
289 Resource* cachedDeadResource =
290 new Resource(ResourceRequest("hhtp://foo"), Resource::Raw);
291 ResourcePtr<Resource> cachedLiveResource =
292 new FakeDecodedResource(ResourceRequest("http://test/resource"), Resource::Raw);
293 cachedLiveResource->setCacheIdentifier("foo");
294 TestLiveResourceEvictionAtEndOfTask(cachedDeadResource, cachedLiveResource);
295 memoryCache()->evictResources();
298 Resource* cachedDeadResource =
299 new Resource(ResourceRequest("hhtp://test/resource"), Resource::Raw);
300 cachedDeadResource->setCacheIdentifier("foo");
301 ResourcePtr<Resource> cachedLiveResource =
302 new FakeDecodedResource(ResourceRequest("http://test/resource"), Resource::Raw);
303 cachedLiveResource->setCacheIdentifier("bar");
304 TestLiveResourceEvictionAtEndOfTask(cachedDeadResource, cachedLiveResource);
305 memoryCache()->evictResources();
309 // Verifies that cached resources are evicted immediately after release when
310 // the total dead resource size is more than double the dead resource capacity.
311 static void TestClientRemoval(const ResourcePtr<Resource>& resource1, const ResourcePtr<Resource>& resource2)
313 const char data[6] = "abcde";
314 MockImageResourceClient client1;
315 resource1->addClient(&client1);
316 resource1->appendData(data, 4u);
317 MockImageResourceClient client2;
318 resource2->addClient(&client2);
319 resource2->appendData(data, 4u);
321 const unsigned minDeadCapacity = 0;
322 const unsigned maxDeadCapacity = ((resource1->size() + resource2->size()) / 2) - 1;
323 const unsigned totalCapacity = maxDeadCapacity;
324 memoryCache()->setCapacities(minDeadCapacity, maxDeadCapacity, totalCapacity);
325 memoryCache()->add(resource1.get());
326 memoryCache()->add(resource2.get());
327 // Call prune. There is nothing to prune, but this will initialize
328 // the prune timestamp, allowing future prunes to be deferred.
329 memoryCache()->prune();
330 ASSERT_GT(resource1->decodedSize(), 0u);
331 ASSERT_GT(resource2->decodedSize(), 0u);
332 ASSERT_EQ(memoryCache()->deadSize(), 0u);
333 ASSERT_EQ(memoryCache()->liveSize(), resource1->size() + resource2->size());
335 // Removing the client from resource1 should result in all resources
336 // remaining in cache since the prune is deferred.
337 resource1->removeClient(&client1);
338 ASSERT_GT(resource1->decodedSize(), 0u);
339 ASSERT_GT(resource2->decodedSize(), 0u);
340 ASSERT_EQ(memoryCache()->deadSize(), resource1->size());
341 ASSERT_EQ(memoryCache()->liveSize(), resource2->size());
342 ASSERT_TRUE(memoryCache()->contains(resource1.get()));
343 ASSERT_TRUE(memoryCache()->contains(resource2.get()));
345 // Removing the client from resource2 should result in immediate
346 // eviction of resource2 because we are over the prune deferral limit.
347 resource2->removeClient(&client2);
348 ASSERT_GT(resource1->decodedSize(), 0u);
349 ASSERT_GT(resource2->decodedSize(), 0u);
350 ASSERT_EQ(memoryCache()->deadSize(), resource1->size());
351 ASSERT_EQ(memoryCache()->liveSize(), 0u);
352 ASSERT_TRUE(memoryCache()->contains(resource1.get()));
353 ASSERT_FALSE(memoryCache()->contains(resource2.get()));
356 TEST_F(MemoryCacheTest, ClientRemoval_Basic)
358 ResourcePtr<Resource> resource1 =
359 new FakeDecodedResource(ResourceRequest("http://foo.com"), Resource::Raw);
360 ResourcePtr<Resource> resource2 =
361 new FakeDecodedResource(ResourceRequest("http://test/resource"), Resource::Raw);
362 TestClientRemoval(resource1, resource2);
365 TEST_F(MemoryCacheTest, ClientRemoval_MultipleResourceMaps)
368 ResourcePtr<Resource> resource1 =
369 new FakeDecodedResource(ResourceRequest("http://foo.com"), Resource::Raw);
370 resource1->setCacheIdentifier("foo");
371 ResourcePtr<Resource> resource2 =
372 new FakeDecodedResource(ResourceRequest("http://test/resource"), Resource::Raw);
373 TestClientRemoval(resource1, resource2);
374 memoryCache()->evictResources();
377 ResourcePtr<Resource> resource1 =
378 new FakeDecodedResource(ResourceRequest("http://foo.com"), Resource::Raw);
379 ResourcePtr<Resource> resource2 =
380 new FakeDecodedResource(ResourceRequest("http://test/resource"), Resource::Raw);
381 resource2->setCacheIdentifier("foo");
382 TestClientRemoval(resource1, resource2);
383 memoryCache()->evictResources();
386 ResourcePtr<Resource> resource1 =
387 new FakeDecodedResource(ResourceRequest("http://test/resource"), Resource::Raw);
388 resource1->setCacheIdentifier("foo");
389 ResourcePtr<Resource> resource2 =
390 new FakeDecodedResource(ResourceRequest("http://test/resource"), Resource::Raw);
391 resource2->setCacheIdentifier("bar");
392 TestClientRemoval(resource1, resource2);
393 memoryCache()->evictResources();
397 // Verifies that CachedResources are evicted from the decode cache
398 // according to their DecodeCachePriority.
399 static void TestDecodeCacheOrder(const ResourcePtr<Resource>& cachedImageLowPriority, const ResourcePtr<Resource>& cachedImageHighPriority)
401 memoryCache()->setDelayBeforeLiveDecodedPrune(0);
402 memoryCache()->setMaxPruneDeferralDelay(0);
404 MockImageResourceClient clientLowPriority;
405 MockImageResourceClient clientHighPriority;
406 cachedImageLowPriority->addClient(&clientLowPriority);
407 cachedImageHighPriority->addClient(&clientHighPriority);
409 const char data[5] = "abcd";
410 cachedImageLowPriority->appendData(data, 1u);
411 cachedImageHighPriority->appendData(data, 4u);
412 const unsigned lowPrioritySize = cachedImageLowPriority->size();
413 const unsigned highPrioritySize = cachedImageHighPriority->size();
414 const unsigned lowPriorityMockDecodeSize = cachedImageLowPriority->decodedSize();
415 const unsigned highPriorityMockDecodeSize = cachedImageHighPriority->decodedSize();
416 const unsigned totalSize = lowPrioritySize + highPrioritySize;
418 // Verify that the sizes are different to ensure that we can test eviction order.
419 ASSERT_GT(lowPrioritySize, 0u);
420 ASSERT_NE(lowPrioritySize, highPrioritySize);
421 ASSERT_GT(lowPriorityMockDecodeSize, 0u);
422 ASSERT_NE(lowPriorityMockDecodeSize, highPriorityMockDecodeSize);
424 ASSERT_EQ(memoryCache()->deadSize(), 0u);
425 ASSERT_EQ(memoryCache()->liveSize(), 0u);
427 // Add the items. The item added first would normally be evicted first.
428 memoryCache()->add(cachedImageHighPriority.get());
429 ASSERT_EQ(memoryCache()->deadSize(), 0u);
430 ASSERT_EQ(memoryCache()->liveSize(), highPrioritySize);
432 memoryCache()->add(cachedImageLowPriority.get());
433 ASSERT_EQ(memoryCache()->deadSize(), 0u);
434 ASSERT_EQ(memoryCache()->liveSize(), highPrioritySize + lowPrioritySize);
436 // Insert all items in the decoded items list with the same priority
437 memoryCache()->updateDecodedResource(cachedImageHighPriority.get(), UpdateForPropertyChange);
438 memoryCache()->updateDecodedResource(cachedImageLowPriority.get(), UpdateForPropertyChange);
439 ASSERT_EQ(memoryCache()->deadSize(), 0u);
440 ASSERT_EQ(memoryCache()->liveSize(), totalSize);
442 // Now we will assign their priority and make sure they are moved to the correct buckets.
443 memoryCache()->updateDecodedResource(cachedImageLowPriority.get(), UpdateForPropertyChange, MemoryCacheLiveResourcePriorityLow);
444 memoryCache()->updateDecodedResource(cachedImageHighPriority.get(), UpdateForPropertyChange, MemoryCacheLiveResourcePriorityHigh);
446 // Should first prune the LowPriority item.
447 memoryCache()->setCapacities(memoryCache()->minDeadCapacity(), memoryCache()->liveSize() - 10, memoryCache()->liveSize() - 10);
448 memoryCache()->prune();
449 ASSERT_EQ(memoryCache()->deadSize(), 0u);
450 ASSERT_EQ(memoryCache()->liveSize(), totalSize - lowPriorityMockDecodeSize);
452 // Should prune the HighPriority item.
453 memoryCache()->setCapacities(memoryCache()->minDeadCapacity(), memoryCache()->liveSize() - 10, memoryCache()->liveSize() - 10);
454 memoryCache()->prune();
455 ASSERT_EQ(memoryCache()->deadSize(), 0u);
456 ASSERT_EQ(memoryCache()->liveSize(), totalSize - lowPriorityMockDecodeSize - highPriorityMockDecodeSize);
458 cachedImageLowPriority->removeClient(&clientLowPriority);
459 cachedImageHighPriority->removeClient(&clientHighPriority);
462 TEST_F(MemoryCacheTest, DecodeCacheOrder_Basic)
464 ResourcePtr<FakeDecodedResource> cachedImageLowPriority =
465 new FakeDecodedResource(ResourceRequest("http://foo.com"), Resource::Raw);
466 ResourcePtr<FakeDecodedResource> cachedImageHighPriority =
467 new FakeDecodedResource(ResourceRequest("http://test/resource"), Resource::Raw);
468 TestDecodeCacheOrder(cachedImageLowPriority, cachedImageHighPriority);
471 TEST_F(MemoryCacheTest, DecodeCacheOrder_MultipleResourceMaps)
474 ResourcePtr<FakeDecodedResource> cachedImageLowPriority =
475 new FakeDecodedResource(ResourceRequest("http://foo.com"), Resource::Raw);
476 ResourcePtr<FakeDecodedResource> cachedImageHighPriority =
477 new FakeDecodedResource(ResourceRequest("http://test/resource"), Resource::Raw);
478 cachedImageLowPriority->setCacheIdentifier("foo");
479 TestDecodeCacheOrder(cachedImageLowPriority, cachedImageHighPriority);
480 memoryCache()->evictResources();
483 ResourcePtr<FakeDecodedResource> cachedImageLowPriority =
484 new FakeDecodedResource(ResourceRequest("http://foo.com"), Resource::Raw);
485 ResourcePtr<FakeDecodedResource> cachedImageHighPriority =
486 new FakeDecodedResource(ResourceRequest("http://test/resource"), Resource::Raw);
487 cachedImageHighPriority->setCacheIdentifier("foo");
488 TestDecodeCacheOrder(cachedImageLowPriority, cachedImageHighPriority);
489 memoryCache()->evictResources();
492 ResourcePtr<FakeDecodedResource> cachedImageLowPriority =
493 new FakeDecodedResource(ResourceRequest("http://test/resource"), Resource::Raw);
494 cachedImageLowPriority->setCacheIdentifier("foo");
495 ResourcePtr<FakeDecodedResource> cachedImageHighPriority =
496 new FakeDecodedResource(ResourceRequest("http://test/resource"), Resource::Raw);
497 cachedImageHighPriority->setCacheIdentifier("bar");
498 TestDecodeCacheOrder(cachedImageLowPriority, cachedImageHighPriority);
499 memoryCache()->evictResources();
503 TEST_F(MemoryCacheTest, MultipleReplace)
505 ResourcePtr<FakeResource> resource1 = new FakeResource(ResourceRequest("http://test/resource"), Resource::Raw);
506 memoryCache()->add(resource1.get());
508 ResourcePtr<FakeResource> resource2 = new FakeResource(ResourceRequest("http://test/resource"), Resource::Raw);
509 memoryCache()->replace(resource2.get(), resource1.get());
510 EXPECT_TRUE(memoryCache()->contains(resource2.get()));
511 EXPECT_FALSE(memoryCache()->contains(resource1.get()));
513 ResourcePtr<FakeResource> resource3 = new FakeResource(ResourceRequest("http://test/resource"), Resource::Raw);
514 memoryCache()->replace(resource3.get(), resource2.get());
515 EXPECT_TRUE(memoryCache()->contains(resource3.get()));
516 EXPECT_FALSE(memoryCache()->contains(resource2.get()));
519 TEST_F(MemoryCacheTest, RemoveDuringRevalidation)
521 ResourcePtr<FakeResource> resource1 = new FakeResource(ResourceRequest("http://test/resource"), Resource::Raw);
522 memoryCache()->add(resource1.get());
524 ResourcePtr<FakeResource> resource2 = new FakeResource(ResourceRequest("http://test/resource"), Resource::Raw);
525 memoryCache()->remove(resource1.get());
526 memoryCache()->add(resource2.get());
527 EXPECT_TRUE(memoryCache()->contains(resource2.get()));
528 EXPECT_FALSE(memoryCache()->contains(resource1.get()));
530 ResourcePtr<FakeResource> resource3 = new FakeResource(ResourceRequest("http://test/resource"), Resource::Raw);
531 memoryCache()->remove(resource2.get());
532 memoryCache()->add(resource3.get());
533 EXPECT_TRUE(memoryCache()->contains(resource3.get()));
534 EXPECT_FALSE(memoryCache()->contains(resource2.get()));
536 memoryCache()->replace(resource1.get(), resource2.get());
537 EXPECT_TRUE(memoryCache()->contains(resource1.get()));
538 EXPECT_FALSE(memoryCache()->contains(resource2.get()));
539 EXPECT_FALSE(memoryCache()->contains(resource3.get()));
542 TEST_F(MemoryCacheTest, ResourceMapIsolation)
544 ResourcePtr<FakeResource> resource1 = new FakeResource(ResourceRequest("http://test/resource"), Resource::Raw);
545 memoryCache()->add(resource1.get());
547 ResourcePtr<FakeResource> resource2 = new FakeResource(ResourceRequest("http://test/resource"), Resource::Raw);
548 resource2->setCacheIdentifier("foo");
549 memoryCache()->add(resource2.get());
550 EXPECT_TRUE(memoryCache()->contains(resource1.get()));
551 EXPECT_TRUE(memoryCache()->contains(resource2.get()));
553 const KURL url = KURL(ParsedURLString, "http://test/resource");
554 EXPECT_EQ(resource1.get(), memoryCache()->resourceForURL(url));
555 EXPECT_EQ(resource1.get(), memoryCache()->resourceForURL(url, memoryCache()->defaultCacheIdentifier()));
556 EXPECT_EQ(resource2.get(), memoryCache()->resourceForURL(url, "foo"));
558 ResourcePtr<FakeResource> resource3 = new FakeResource(ResourceRequest("http://test/resource"), Resource::Raw);
559 resource3->setCacheIdentifier("foo");
560 memoryCache()->remove(resource2.get());
561 memoryCache()->add(resource3.get());
562 EXPECT_TRUE(memoryCache()->contains(resource1.get()));
563 EXPECT_FALSE(memoryCache()->contains(resource2.get()));
564 EXPECT_TRUE(memoryCache()->contains(resource3.get()));
566 ResourcePtr<FakeResource> resource4 = new FakeResource(ResourceRequest("http://test/resource"), Resource::Raw);
567 resource4->setCacheIdentifier("foo");
568 memoryCache()->replace(resource4.get(), resource3.get());
569 EXPECT_TRUE(memoryCache()->contains(resource1.get()));
570 EXPECT_FALSE(memoryCache()->contains(resource3.get()));
571 EXPECT_TRUE(memoryCache()->contains(resource4.get()));
573 WillBeHeapVector<Member<Resource>> resources = memoryCache()->resourcesForURL(url);
574 EXPECT_EQ(2u, resources.size());
576 memoryCache()->evictResources();
577 EXPECT_FALSE(memoryCache()->contains(resource1.get()));
578 EXPECT_FALSE(memoryCache()->contains(resource3.get()));