Files
ladybird/Tests/LibWeb/Text/input/HTML/media-source-setup.html
Zaggy1024 5ab536b33c Tests: Remove the timeout between steps in media source tests
The goal with these timeouts was to eagerly fail the test and not spend
an excessive amount of time waiting for the full test-web timeout.
However, since CI uses sanitizers, it's plausible that the time it
takes between steps, especially the fetch, could exceed that. Instead,
let's just let test-web time these out.

Hopefully this will make the test green on CI.
2026-04-10 15:30:08 -05:00

127 lines
5.3 KiB
HTML

<!DOCTYPE html>
<video id="video"></video>
<script src="../include.js"></script>
<script>
asyncTest(done => {
function step(name) {
println(`PASS: ${name}`);
}
function fail(name, error) {
println(`FAIL: ${name}: ${error}`);
done();
}
try {
const video = document.getElementById("video");
// Step 1: Check isTypeSupported
const mimeType = 'video/webm;codecs="vp9,opus"';
if (!MediaSource.isTypeSupported(mimeType)) {
fail("isTypeSupported", `${mimeType} not supported`);
return;
}
step("isTypeSupported");
// Step 2: Create MediaSource
const mediaSource = new MediaSource();
step("created MediaSource");
// Step 3: Create object URL and assign to video
const url = URL.createObjectURL(mediaSource);
video.src = url;
step("assigned object URL to video.src");
// Step 4: Wait for sourceopen
mediaSource.addEventListener("sourceopen", async () => {
try {
step("sourceopen fired");
// Step 5: Add a SourceBuffer
const sourceBuffer = mediaSource.addSourceBuffer(mimeType);
step("addSourceBuffer succeeded");
// Step 6: Fetch test media
const response = await fetch("../../../Assets/test-webm.webm");
if (!response.ok) {
fail("fetch media", `HTTP ${response.status}`);
return;
}
const data = await response.arrayBuffer();
step(`loaded media data (${data.byteLength} bytes)`);
// Step 7: Append buffer in slices and print buffered ranges
function printBuffered(label) {
const buffered = sourceBuffer.buffered;
if (!buffered) {
println(`buffered after ${label}: not available`);
return;
}
const ranges = [];
for (let i = 0; i < buffered.length; i++)
ranges.push(`${buffered.start(i)}-${buffered.end(i)}`);
println(`buffered after ${label}: [${ranges.join(", ")}]`);
}
async function appendSlice(slice, label) {
await new Promise((resolve, reject) => {
sourceBuffer.addEventListener("updateend", resolve, { once: true });
sourceBuffer.addEventListener("error", () =>
reject(new Error("error event on SourceBuffer")), { once: true });
sourceBuffer.appendBuffer(slice);
step(`appendBuffer() for ${label}`);
});
printBuffered(label);
}
// Embed the data in a padded buffer and append as typed array views, so that if the view slice is
// ignored by appendBuffer(), it will cause read errors. YouTube uses these typed array views.
const padding = 1024;
const paddedBuffer = new ArrayBuffer(padding + data.byteLength + padding);
new Uint8Array(paddedBuffer).set(new Uint8Array(data), padding);
const dataView = new Uint8Array(paddedBuffer, padding, data.byteLength);
const numSlices = 3;
const sliceSize = Math.ceil(dataView.length / numSlices);
let pos = 0;
for (let i = 0; i < numSlices; i++) {
const end = Math.min(pos + sliceSize, dataView.length);
await appendSlice(dataView.subarray(pos, end), `slice ${i + 1}/${numSlices}`);
step(`slice ${i + 1} appended`);
pos = end;
}
// Step 8: End of stream and wait for sourceended
await new Promise(resolve => {
mediaSource.addEventListener("sourceended", resolve);
mediaSource.endOfStream();
});
step("endOfStream succeeded");
printBuffered("endOfStream");
// Step 9: Play
video.addEventListener("error", () => {
fail("playback", video.error?.message ?? "unknown error");
});
await video.play();
step("play() promise resolved");
await new Promise(resolve => {
if (!video.paused)
resolve();
else
video.addEventListener("playing", resolve);
});
step("playing");
done();
} catch (e) {
fail("sourceopen handler", e);
}
});
} catch (e) {
fail("setup", e);
}
});
</script>