Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Errors

<!DOCTYPE HTML>
<html>
<head>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body>
<script>
"use strict";
SimpleTest.waitForExplicitFinish();
async function runTest() {
const tools = SpecialPowers.Cc["@mozilla.org/image/tools;1"].getService(
SpecialPowers.Ci.imgITools
);
tools.getImgCacheForDocument(document).clearCache(false);
const BASE_URL = "big.png?run=" + Math.random() + "&";
const cacheSize = SpecialPowers.getIntPref("image.cache.size");
ok(cacheSize > 0 && cacheSize < 1024 * 1024 * 1024,
`image.cache.size (${cacheSize}) is a valid positive size`);
const headResponse = await fetch("big.png", { method: "HEAD" });
const fileSize = parseInt(headResponse.headers.get("content-length"), 10);
ok(fileSize > 0 && fileSize < cacheSize,
`big.png file size (${fileSize}) is smaller than the cache limit`);
if (cacheSize <= 0 || !(fileSize > 0 && fileSize < cacheSize)) {
SimpleTest.finish();
return;
}
// Load enough copies to exceed the cache limit, with 20 extra for margin.
const COUNT = Math.ceil(cacheSize / fileSize) + 20;
function loadImage(url) {
return new Promise((resolve, reject) => {
const img = document.createElement("img");
img.width = 10;
img.height = 10;
img.src = url;
img.onload = () => resolve(img);
img.onerror = reject;
document.body.appendChild(img);
});
}
// Load images one at a time, clearing each after decode and a frame,
// so that the cache eviction order matches the load order.
for (let i = 0; i < COUNT; i++) {
const img = await loadImage(BASE_URL + i);
await img.decode();
await new Promise(resolve => requestAnimationFrame(resolve));
img.src = "";
}
for (let i = 0; i < 10; i++) {
await new Promise(resolve => requestAnimationFrame(resolve));
}
// Load one more image to ensure all pending cache tasks have been flushed.
await loadImage(BASE_URL + COUNT);
const maxCached = Math.ceil(cacheSize / fileSize);
// Check directly via the image cache API (does not modify cache state).
// Check in reverse load order since recently loaded images are most
// likely to still be cached.
const imgCache = tools.getImgCacheForDocument(document);
let directHitCount = 0;
for (let i = COUNT - 1; i >= 0; i--) {
const uri = SpecialPowers.Services.io.newURI(
new URL(BASE_URL + i, location.href).href
);
if (imgCache.findEntryProperties(uri, document)) {
directHitCount++;
}
}
ok(directHitCount <= maxCached,
`${directHitCount} images in cache (direct check), limit is ${maxCached}`);
// Count how many of the loaded images are still in the cache. Setting
// src on an element makes img.complete true synchronously only for
// cache hits. Check in reverse load order since recently loaded images
// are most likely to still be cached.
let cacheHitCount = 0;
for (let i = COUNT - 1; i >= 0; i--) {
const checkImg = document.createElement("img");
checkImg.width = 10;
checkImg.height = 10;
document.body.appendChild(checkImg);
checkImg.src = BASE_URL + i;
if (checkImg.complete) {
cacheHitCount++;
}
checkImg.src = "";
}
ok(cacheHitCount <= maxCached,
`${cacheHitCount} images remain in cache after eviction, limit is ${maxCached}`);
SimpleTest.finish();
}
runTest();
</script>
</body>
</html>