summaryrefslogtreecommitdiffstats
path: root/dom/webgpu/tests/cts/checkout/src/webgpu/examples.spec.ts
diff options
context:
space:
mode:
Diffstat (limited to 'dom/webgpu/tests/cts/checkout/src/webgpu/examples.spec.ts')
-rw-r--r--dom/webgpu/tests/cts/checkout/src/webgpu/examples.spec.ts274
1 files changed, 274 insertions, 0 deletions
diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/examples.spec.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/examples.spec.ts
new file mode 100644
index 0000000000..61d18bf7d7
--- /dev/null
+++ b/dom/webgpu/tests/cts/checkout/src/webgpu/examples.spec.ts
@@ -0,0 +1,274 @@
+export const description = `
+Examples of writing CTS tests with various features.
+
+Start here when looking for examples of basic framework usage.
+`;
+
+import { makeTestGroup } from '../common/framework/test_group.js';
+
+import { GPUTest } from './gpu_test.js';
+
+// To run these tests in the standalone runner, run `npm start` then open:
+// - http://localhost:XXXX/standalone/?runnow=1&q=webgpu:examples:*
+// To run in WPT, copy/symlink the out-wpt/ directory as the webgpu/ directory in WPT, then open:
+// - (wpt server url)/webgpu/cts.https.html?q=webgpu:examples:
+//
+// Tests here can be run individually or in groups:
+// - ?q=webgpu:examples:basic,async:
+// - ?q=webgpu:examples:basic,async:*
+// - ?q=webgpu:examples:basic,*
+// - ?q=webgpu:examples:*
+
+export const g = makeTestGroup(GPUTest);
+
+// Note: spaces aren't allowed in test names; use underscores.
+g.test('test_name').fn(t => {});
+
+g.test('not_implemented_yet,without_plan').unimplemented();
+g.test('not_implemented_yet,with_plan')
+ .desc(
+ `
+Plan for this test. What it tests. Summary of how it tests that functionality.
+- Description of cases, by describing parameters {a, b, c}
+- x= more parameters {x, y, z}
+`
+ )
+ .unimplemented();
+
+g.test('basic').fn(t => {
+ t.expect(true);
+ t.expect(true, 'true should be true');
+
+ t.shouldThrow(
+ // The expected '.name' of the thrown error.
+ 'TypeError',
+ // This function is run inline inside shouldThrow, and is expected to throw.
+ () => {
+ throw new TypeError();
+ },
+ // Log message.
+ 'function should throw Error'
+ );
+});
+
+g.test('basic,async').fn(async t => {
+ // shouldReject must be awaited to ensure it can wait for the promise before the test ends.
+ t.shouldReject(
+ // The expected '.name' of the thrown error.
+ 'TypeError',
+ // Promise expected to reject.
+ Promise.reject(new TypeError()),
+ // Log message.
+ 'Promise.reject should reject'
+ );
+
+ // Promise can also be an IIFE.
+ t.shouldReject(
+ 'TypeError',
+ (async () => {
+ throw new TypeError();
+ })(),
+ 'Promise.reject should reject'
+ );
+});
+
+g.test('basic,plain_cases')
+ .desc(
+ `
+A test can be parameterized with a simple array of objects using .paramsSimple([ ... ]).
+Each such instance of the test is a "case".
+
+In this example, the following cases are generated (identified by their "query string"),
+each with just one subcase:
+ - webgpu:examples:basic,cases:x=2;y=2 runs 1 subcase, with t.params set to:
+ - { x: 2, y: 2 }
+ - webgpu:examples:basic,cases:x=-10;y=-10 runs 1 subcase, with t.params set to:
+ - { x: -10, y: -10 }
+ `
+ )
+ .paramsSimple([
+ { x: 2, y: 2 }, //
+ { x: -10, y: -10 },
+ ])
+ .fn(t => {
+ t.expect(t.params.x === t.params.y);
+ });
+
+g.test('basic,plain_cases_private')
+ .desc(
+ `
+Parameters can be public ("x", "y") which means they're part of the case name.
+They can also be private by starting with an underscore ("_result"), which passes
+them into the test but does not make them part of the case name:
+
+In this example, the following cases are generated, each with just one subcase:
+ - webgpu:examples:basic,cases:x=2;y=4 runs 1 subcase, with t.params set to:
+ - { x: 2, y: 4, _result: 6 }
+ - webgpu:examples:basic,cases:x=-10;y=18 runs 1 subcase, with t.params set to:
+ - { x: -10, y: 18, _result: 8 }
+ `
+ )
+ .paramsSimple([
+ { x: 2, y: 4, _result: 6 }, //
+ { x: -10, y: 18, _result: 8 },
+ ])
+ .fn(t => {
+ t.expect(t.params.x + t.params.y === t.params._result);
+ });
+// (note the blank comment above to enforce newlines on autoformat)
+
+g.test('basic,builder_cases')
+ .desc(
+ `
+A "CaseParamsBuilder" or "SubcaseParamsBuilder" can be passed to .params() instead.
+The params builder provides facilities for generating tests combinatorially (by cartesian
+product). For convenience, the "unit" CaseParamsBuilder is passed as an argument ("u" below).
+
+In this example, the following cases are generated, each with just one subcase:
+ - webgpu:examples:basic,cases:x=1,y=1 runs 1 subcase, with t.params set to:
+ - { x: 1, y: 1 }
+ - webgpu:examples:basic,cases:x=1,y=2 runs 1 subcase, with t.params set to:
+ - { x: 1, y: 2 }
+ - webgpu:examples:basic,cases:x=2,y=1 runs 1 subcase, with t.params set to:
+ - { x: 2, y: 1 }
+ - webgpu:examples:basic,cases:x=2,y=2 runs 1 subcase, with t.params set to:
+ - { x: 2, y: 2 }
+ `
+ )
+ .params(u =>
+ u //
+ .combineWithParams([{ x: 1 }, { x: 2 }])
+ .combineWithParams([{ y: 1 }, { y: 2 }])
+ )
+ .fn(() => {});
+
+g.test('basic,builder_cases_subcases')
+ .desc(
+ `
+Each case sub-parameterized using .beginSubcases().
+Each such instance of the test is a "subcase", which cannot be run independently of other
+subcases. It is somewhat like wrapping the entire fn body in a for-loop.
+
+In this example, the following cases are generated:
+ - webgpu:examples:basic,cases:x=1 runs 2 subcases, with t.params set to:
+ - { x: 1, y: 1 }
+ - { x: 1, y: 2 }
+ - webgpu:examples:basic,cases:x=2 runs 2 subcases, with t.params set to:
+ - { x: 2, y: 1 }
+ - { x: 2, y: 2 }
+ `
+ )
+ .params(u =>
+ u //
+ .combineWithParams([{ x: 1 }, { x: 2 }])
+ .beginSubcases()
+ .combineWithParams([{ y: 1 }, { y: 2 }])
+ )
+ .fn(() => {});
+
+g.test('basic,builder_subcases')
+ .desc(
+ `
+In this example, the following single case is generated:
+ - webgpu:examples:basic,cases: runs 4 subcases, with t.params set to:
+ - { x: 1, y: 1 }
+ - { x: 1, y: 2 }
+ - { x: 2, y: 1 }
+ - { x: 2, y: 2 }
+ `
+ )
+ .params(u =>
+ u //
+ .beginSubcases()
+ .combineWithParams([{ x: 1 }, { x: 2 }])
+ .combineWithParams([{ y: 1 }, { y: 2 }])
+ )
+ .fn(() => {});
+
+g.test('basic,builder_subcases_short')
+ .desc(
+ `
+As a shorthand, .paramsSubcasesOnly() can be used.
+
+In this example, the following single case is generated:
+ - webgpu:examples:basic,cases: runs 4 subcases, with t.params set to:
+ - { x: 1, y: 1 }
+ - { x: 1, y: 2 }
+ - { x: 2, y: 1 }
+ - { x: 2, y: 2 }
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combineWithParams([{ x: 1 }, { x: 2 }])
+ .combineWithParams([{ y: 1 }, { y: 2 }])
+ )
+ .fn(() => {});
+
+g.test('gpu,async').fn(async t => {
+ const x = await t.queue.onSubmittedWorkDone();
+ t.expect(x === undefined);
+});
+
+g.test('gpu,buffers').fn(async t => {
+ const data = new Uint32Array([0, 1234, 0]);
+ const src = t.makeBufferWithContents(data, GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST);
+
+ // Use the expectGPUBufferValuesEqual helper to check the actual contents of a GPUBuffer.
+ // This makes a copy and then asynchronously checks the contents. The test fixture will
+ // wait on that result before reporting whether the test passed or failed.
+ t.expectGPUBufferValuesEqual(src, data);
+});
+
+// One of the following two tests should be skipped on most platforms.
+
+g.test('gpu,with_texture_compression,bc')
+ .desc(
+ `Example of a test using a device descriptor.
+Tests that a BC format passes validation iff the feature is enabled.`
+ )
+ .params(u => u.combine('textureCompressionBC', [false, true]))
+ .beforeAllSubcases(t => {
+ const { textureCompressionBC } = t.params;
+
+ if (textureCompressionBC) {
+ t.selectDeviceOrSkipTestCase('texture-compression-bc');
+ }
+ })
+ .fn(async t => {
+ const { textureCompressionBC } = t.params;
+ const shouldError = !textureCompressionBC;
+ t.shouldThrow(shouldError ? 'TypeError' : false, () => {
+ t.device.createTexture({
+ format: 'bc1-rgba-unorm',
+ size: [4, 4, 1],
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ });
+ });
+ });
+
+g.test('gpu,with_texture_compression,etc2')
+ .desc(
+ `Example of a test using a device descriptor.
+Tests that an ETC2 format passes validation iff the feature is enabled.`
+ )
+ .params(u => u.combine('textureCompressionETC2', [false, true]))
+ .beforeAllSubcases(t => {
+ const { textureCompressionETC2 } = t.params;
+
+ if (textureCompressionETC2) {
+ t.selectDeviceOrSkipTestCase('texture-compression-etc2' as GPUFeatureName);
+ }
+ })
+ .fn(async t => {
+ const { textureCompressionETC2 } = t.params;
+
+ const shouldError = !textureCompressionETC2;
+ t.shouldThrow(shouldError ? 'TypeError' : false, () => {
+ t.device.createTexture({
+ format: 'etc2-rgb8unorm',
+ size: [4, 4, 1],
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ });
+ });
+ });