From e50eb8038dbd0a5d347ba1235480ccd27570d0c6 Mon Sep 17 00:00:00 2001 From: Greggman Date: Wed, 22 Jan 2025 18:16:46 -0800 Subject: [PATCH] Skip web_platform tests if API does not exist (#4156) Skip tests if `navigator`, `OffscreenCanvas`, `ImageData`, etc... do not exist. --- .../canvas/getCurrentTexture.spec.ts | 11 +++- .../canvas/getPreferredCanvasFormat.spec.ts | 7 ++- .../copyToTexture/ImageBitmap.spec.ts | 7 ++- .../copyToTexture/ImageData.spec.ts | 4 ++ .../copyToTexture/image_file.spec.ts | 4 +- src/webgpu/web_platform/util.ts | 56 +++++++++---------- 6 files changed, 54 insertions(+), 35 deletions(-) diff --git a/src/webgpu/web_platform/canvas/getCurrentTexture.spec.ts b/src/webgpu/web_platform/canvas/getCurrentTexture.spec.ts index 633d88d2b863..8cb50a46c75d 100644 --- a/src/webgpu/web_platform/canvas/getCurrentTexture.spec.ts +++ b/src/webgpu/web_platform/canvas/getCurrentTexture.spec.ts @@ -172,9 +172,14 @@ g.test('multiple_frames') ) .beforeAllSubcases(t => { const { canvasType } = t.params; - if (canvasType === 'offscreen' && !('transferToImageBitmap' in OffscreenCanvas.prototype)) { - throw new SkipTestCase('transferToImageBitmap not supported'); - } + t.skipIf( + canvasType === 'offscreen' && typeof OffscreenCanvas === 'undefined', + 'OffscreenCanvas does not exist in this environment' + ); + t.skipIf( + canvasType === 'offscreen' && !('transferToImageBitmap' in OffscreenCanvas.prototype), + 'transferToImageBitmap not supported' + ); }) .fn(t => { const { canvasType, clearTexture } = t.params; diff --git a/src/webgpu/web_platform/canvas/getPreferredCanvasFormat.spec.ts b/src/webgpu/web_platform/canvas/getPreferredCanvasFormat.spec.ts index cd582b4f3a69..872a32502da1 100644 --- a/src/webgpu/web_platform/canvas/getPreferredCanvasFormat.spec.ts +++ b/src/webgpu/web_platform/canvas/getPreferredCanvasFormat.spec.ts @@ -2,7 +2,7 @@ export const description = ` Tests for navigator.gpu.getPreferredCanvasFormat. `; -import { Fixture } from '../../../common/framework/fixture.js'; +import { Fixture, SkipTestCase } from '../../../common/framework/fixture.js'; import { makeTestGroup } from '../../../common/framework/test_group.js'; export const g = makeTestGroup(Fixture); @@ -13,6 +13,11 @@ g.test('value') Ensure getPreferredCanvasFormat returns one of the valid values. ` ) + .beforeAllSubcases(t => { + if (typeof navigator === 'undefined') { + throw new SkipTestCase('navigator does not exist in this environment'); + } + }) .fn(t => { const preferredFormat = navigator.gpu.getPreferredCanvasFormat(); t.expect(preferredFormat === 'bgra8unorm' || preferredFormat === 'rgba8unorm'); diff --git a/src/webgpu/web_platform/copyToTexture/ImageBitmap.spec.ts b/src/webgpu/web_platform/copyToTexture/ImageBitmap.spec.ts index 5036c8ef20bc..86ed37ef9e67 100644 --- a/src/webgpu/web_platform/copyToTexture/ImageBitmap.spec.ts +++ b/src/webgpu/web_platform/copyToTexture/ImageBitmap.spec.ts @@ -59,6 +59,7 @@ g.test('from_ImageData') .combine('height', [1, 2, 4, 15, 255, 256]) ) .beforeAllSubcases(t => { + t.skipIf(typeof ImageData === 'undefined', 'ImageData does not exist in this environment'); t.skipIfTextureFormatNotSupported(t.params.dstFormat); }) .fn(async t => { @@ -179,6 +180,7 @@ g.test('from_canvas') .combine('height', [1, 2, 4, 15, 255, 256]) ) .beforeAllSubcases(t => { + t.skipIf(typeof ImageData === 'undefined', 'ImageData does not exist in this environment'); t.skipIfTextureFormatNotSupported(t.params.dstFormat); }) .fn(async t => { @@ -208,7 +210,7 @@ g.test('from_canvas') } else { imageCanvas = new OffscreenCanvas(width, height); } - const imageCanvasContext = imageCanvas.getContext('2d'); + const imageCanvasContext = imageCanvas.getContext('2d') as OffscreenCanvasRenderingContext2D; if (imageCanvasContext === null) { t.skip('OffscreenCanvas "2d" context not available'); return; @@ -326,6 +328,9 @@ g.test('copy_subrect_from_ImageData') .beginSubcases() .combine('copySubRectInfo', kCopySubrectInfo) ) + .beforeAllSubcases(t => { + t.skipIf(typeof ImageData === 'undefined', 'ImageData does not exist in this environment'); + }) .fn(async t => { const { copySubRectInfo, diff --git a/src/webgpu/web_platform/copyToTexture/ImageData.spec.ts b/src/webgpu/web_platform/copyToTexture/ImageData.spec.ts index a9a0a441653a..912c5f69d7f8 100644 --- a/src/webgpu/web_platform/copyToTexture/ImageData.spec.ts +++ b/src/webgpu/web_platform/copyToTexture/ImageData.spec.ts @@ -47,6 +47,7 @@ g.test('from_ImageData') .combine('height', [1, 2, 4, 15, 255, 256]) ) .beforeAllSubcases(t => { + t.skipIf(typeof ImageData === 'undefined', 'ImageData does not exist in this environment'); t.skipIfTextureFormatNotSupported(t.params.dstColorFormat); }) .fn(t => { @@ -152,6 +153,9 @@ g.test('copy_subrect_from_ImageData') .beginSubcases() .combine('copySubRectInfo', kCopySubrectInfo) ) + .beforeAllSubcases(t => { + t.skipIf(typeof ImageData === 'undefined', 'ImageData does not exist in this environment'); + }) .fn(t => { const { copySubRectInfo, dstPremultiplied, srcDoFlipYDuringCopy } = t.params; diff --git a/src/webgpu/web_platform/copyToTexture/image_file.spec.ts b/src/webgpu/web_platform/copyToTexture/image_file.spec.ts index 682e2339d458..4d5a018629b8 100644 --- a/src/webgpu/web_platform/copyToTexture/image_file.spec.ts +++ b/src/webgpu/web_platform/copyToTexture/image_file.spec.ts @@ -6,7 +6,7 @@ import { makeTestGroup } from '../../../common/framework/test_group.js'; import { TextureUploadingUtils } from '../../util/copy_to_texture.js'; import { convertToUnorm8, - GetSourceFromEXIFImageFile, + getSourceFromEXIFImageFile, kImageNames, kImageInfo, kImageExpectedColors, @@ -50,7 +50,7 @@ g.test('from_orientation_metadata_file') const kColorFormat = 'rgba8unorm'; // Load image file. - const source = await GetSourceFromEXIFImageFile(t, imageName, objectTypeFromFile); + const source = await getSourceFromEXIFImageFile(t, imageName, objectTypeFromFile); const width = source.width; const height = source.height; diff --git a/src/webgpu/web_platform/util.ts b/src/webgpu/web_platform/util.ts index 7b5131d4ba89..cc6f3c809b83 100644 --- a/src/webgpu/web_platform/util.ts +++ b/src/webgpu/web_platform/util.ts @@ -470,9 +470,7 @@ export async function getVideoFrameFromVideoElement( test: Fixture, video: HTMLVideoElement ): Promise { - if (video.captureStream === undefined) { - test.skip('HTMLVideoElement.captureStream is not supported'); - } + test.skipIf(video.captureStream === undefined, 'HTMLVideoElement.captureStream is not supported'); return raceWithRejectOnTimeout( new Promise(resolve => { @@ -569,19 +567,17 @@ function callbackHelper( * */ export async function captureCameraFrame(test: GPUTest): Promise { - if ( + test.skipIf(typeof navigator === 'undefined', 'navigator does not exist in this environment'); + test.skipIf( typeof navigator.mediaDevices === 'undefined' || - typeof navigator.mediaDevices.getUserMedia === 'undefined' - ) { - test.skip("Browser doesn't support capture frame from camera."); - } + typeof navigator.mediaDevices.getUserMedia === 'undefined', + "Browser doesn't support capture frame from camera." + ); const stream = await navigator.mediaDevices.getUserMedia({ video: true }); const track = stream.getVideoTracks()[0] as MediaStreamVideoTrack; - if (!track) { - test.skip("Doesn't have valid camera captured stream for testing."); - } + test.skipIf(!track, "Doesn't have valid camera captured stream for testing."); // Use MediaStreamTrackProcessor and ReadableStream to generate video frame directly. if (typeof MediaStreamTrackProcessor !== 'undefined') { @@ -604,9 +600,10 @@ export async function captureCameraFrame(test: GPUTest): Promise { } // Fallback to using HTMLVideoElement to do capture. - if (typeof HTMLVideoElement === 'undefined') { - test.skip('Try to use HTMLVideoElement do capture but HTMLVideoElement not available.'); - } + test.skipIf( + typeof HTMLVideoElement === 'undefined', + 'Try to use HTMLVideoElement do capture but HTMLVideoElement not available.' + ); const video = document.createElement('video'); video.srcObject = stream; @@ -665,7 +662,7 @@ export const kObjectTypeFromFiles = [ * Load image file(e.g. *.jpg) from ImageBitmap, blob or HTMLImageElement. And * convert the result to valid source that GPUCopyExternalImageSource supported. */ -export async function GetSourceFromEXIFImageFile( +export async function getSourceFromEXIFImageFile( test: GPUTest, exifImageName: EXIFImageName, objectTypeFromFile: ObjectTypeFromFile @@ -677,9 +674,14 @@ export async function GetSourceFromEXIFImageFile( // MAINTENANCE_TODO: resource folder path when using service worker is not correct. Return // the correct path to load resource in correct place. // The wrong path: /out/webgpu/webworker/web_platform/copyToTexture/resources - if (globalThis.constructor.name === 'ServiceWorkerGlobalScope') { - test.skip('Try to load image resource from serivce worker but the path is not correct.'); - } + test.skipIf( + globalThis.constructor.name === 'ServiceWorkerGlobalScope', + 'Try to load image resource from serivce worker but the path is not correct.' + ); + test.skipIf( + typeof createImageBitmap === 'undefined', + 'createImageBitmap does not exist in this environment' + ); // Load image file through fetch. const response = await fetch(imageUrl); return createImageBitmap(await response.blob()); @@ -687,11 +689,10 @@ export async function GetSourceFromEXIFImageFile( case 'ImageBitmap-from-Image': case 'Image': { // Skip test if HTMLImageElement is not available, e.g. in worker. - if (typeof HTMLImageElement === 'undefined') { - test.skip( - 'Try to use HTMLImage do image file decoding but HTMLImageElement not available.' - ); - } + test.skipIf( + typeof HTMLImageElement === 'undefined', + 'Try to use HTMLImage do image file decoding but HTMLImageElement not available.' + ); // Load image file through HTMLImageElement. const image = new Image(); @@ -731,11 +732,10 @@ export function loadImageFileAndRun( } })(); // Skip test if HTMLImageElement is not available, e.g. in worker. - if (typeof HTMLImageElement === 'undefined') { - test.skip( - 'Try to use HTMLImage do image file decoding but HTMLImageElement not available.' - ); - } + test.skipIf( + typeof HTMLImageElement === 'undefined', + 'Try to use HTMLImage do image file decoding but HTMLImageElement not available.' + ); const image = new Image(); image.src = getResourcePath(imageName); image.onload = () => {