static void TestLiveResourceEvictionAtEndOfTask(Resource* cachedDeadResource, const ResourcePtr<Resource>& cachedLiveResource)
{
    memoryCache()->setDelayBeforeLiveDecodedPrune(0);
    const unsigned totalCapacity = 1;
    const unsigned minDeadCapacity = 0;
    const unsigned maxDeadCapacity = 0;
    memoryCache()->setCapacities(minDeadCapacity, maxDeadCapacity, totalCapacity);
    const char data[6] = "abcde";
    cachedDeadResource->appendData(data, 3u);
    MockImageResourceClient client(cachedLiveResource);
    cachedLiveResource->appendData(data, 4u);

    class Task1 : public WebTaskRunner::Task {
    public:
        Task1(const ResourcePtr<Resource>& live, Resource* dead)
            : m_live(live)
            , m_dead(dead)
        { }

        void run() override
        {
            // The resource size has to be nonzero for this test to be meaningful, but
            // we do not rely on it having any particular value.
            ASSERT_GT(m_live->size(), 0u);
            ASSERT_GT(m_dead->size(), 0u);

            ASSERT_EQ(0u, memoryCache()->deadSize());
            ASSERT_EQ(0u, memoryCache()->liveSize());

            memoryCache()->add(m_dead);
            memoryCache()->add(m_live.get());
            memoryCache()->updateDecodedResource(m_live.get(), UpdateForPropertyChange);
            ASSERT_EQ(m_dead->size(), memoryCache()->deadSize());
            ASSERT_EQ(m_live->size(), memoryCache()->liveSize());
            ASSERT_GT(m_live->decodedSize(), 0u);

            memoryCache()->prune(); // Dead resources are pruned immediately
            ASSERT_EQ(m_dead->size(), memoryCache()->deadSize());
            ASSERT_EQ(m_live->size(), memoryCache()->liveSize());
            ASSERT_GT(m_live->decodedSize(), 0u);
        }

    private:
        ResourcePtr<Resource> m_live;
        Resource* m_dead;
    };

    class Task2 : public WebTaskRunner::Task {
    public:
        Task2(unsigned liveSizeWithoutDecode)
            : m_liveSizeWithoutDecode(liveSizeWithoutDecode) { }

        void run() override
        {
            // Next task: now, the live resource was evicted.
            ASSERT_EQ(0u, memoryCache()->deadSize());
            ASSERT_EQ(m_liveSizeWithoutDecode, memoryCache()->liveSize());
        }

    private:
        unsigned m_liveSizeWithoutDecode;
    };


    Platform::current()->currentThread()->taskRunner()->postTask(FROM_HERE, new Task1(cachedLiveResource, cachedDeadResource));
    Platform::current()->currentThread()->taskRunner()->postTask(FROM_HERE, new Task2(cachedLiveResource->encodedSize() + cachedLiveResource->overheadSize()));
    testing::runPendingTasks();
}
void MemoryCache::dumpLRULists(bool includeLive) const
{
    printf("LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced, isPurgeable, wasPurged):\n");

    int size = m_allResources.size();
    for (int i = size - 1; i >= 0; i--) {
        printf("\n\nList %d: ", i);
        MemoryCacheEntry* current = m_allResources[i].m_tail;
        while (current) {
            ResourcePtr<Resource> currentResource = current->m_resource;
            if (includeLive || !currentResource->hasClients())
                printf("(%.1fK, %.1fK, %uA, %dR, %d, %d); ", currentResource->decodedSize() / 1024.0f, (currentResource->encodedSize() + currentResource->overheadSize()) / 1024.0f, current->m_accessCount, currentResource->hasClients(), currentResource->isPurgeable(), currentResource->wasPurged());

            current = current->m_previousInAllResourcesList;
        }
    }
}