blob: 35969543741f04ad9b43c031fa2d644f6cfb2b27 [file] [log] [blame]
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -07001export const description = `
2Examples of writing CTS tests with various features.
Kai Ninomiyacb13fba2019-10-24 16:59:36 -07003
4Start here when looking for examples of basic framework usage.
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -07005`;
6
Kai Ninomiya9cbb8002020-05-18 15:33:41 -07007import { makeTestGroup } from '../common/framework/test_group.js';
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -07008
9import { GPUTest } from './gpu_test.js';
10
Kai Ninomiyae7561052021-04-29 15:37:09 -070011// To run these tests in the standalone runner, run `npm start` then open:
Kai Ninomiya119b9532021-06-03 19:55:56 -070012// - http://localhost:XXXX/standalone/?runnow=1&q=webgpu:examples:*
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -070013// To run in WPT, copy/symlink the out-wpt/ directory as the webgpu/ directory in WPT, then open:
Kai Ninomiya8ec39402021-11-01 11:25:52 -070014// - (wpt server url)/webgpu/cts.https.html?q=webgpu:examples:
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -070015//
16// Tests here can be run individually or in groups:
Kai Ninomiyae7561052021-04-29 15:37:09 -070017// - ?q=webgpu:examples:basic,async:
18// - ?q=webgpu:examples:basic,async:*
19// - ?q=webgpu:examples:basic,*
20// - ?q=webgpu:examples:*
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -070021
Kai Ninomiya9cbb8002020-05-18 15:33:41 -070022export const g = makeTestGroup(GPUTest);
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -070023
Kai Ninomiyaece4eb32022-05-03 09:48:50 -070024// Note: spaces aren't allowed in test names; use underscores.
Kai Ninomiya9cbb8002020-05-18 15:33:41 -070025g.test('test_name').fn(t => {});
Kai Ninomiya04ec6b62019-10-25 00:35:32 -070026
Kai Ninomiyafba26302020-11-04 13:38:05 -080027g.test('not_implemented_yet,without_plan').unimplemented();
28g.test('not_implemented_yet,with_plan')
29 .desc(
30 `
31Plan for this test. What it tests. Summary of how it tests that functionality.
32- Description of cases, by describing parameters {a, b, c}
33- x= more parameters {x, y, z}
34`
35 )
36 .unimplemented();
37
Kai Ninomiyafb584a52020-04-16 16:43:24 -070038g.test('basic').fn(t => {
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -070039 t.expect(true);
40 t.expect(true, 'true should be true');
41
42 t.shouldThrow(
Kai Ninomiyabb2e71f2019-08-02 16:25:56 -070043 // The expected '.name' of the thrown error.
44 'TypeError',
45 // This function is run inline inside shouldThrow, and is expected to throw.
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -070046 () => {
Kai Ninomiyabb2e71f2019-08-02 16:25:56 -070047 throw new TypeError();
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -070048 },
Kai Ninomiyabb2e71f2019-08-02 16:25:56 -070049 // Log message.
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -070050 'function should throw Error'
51 );
52});
53
Lokbondo Kung2db4fdd2023-01-27 16:40:09 -080054g.test('basic,async').fn(t => {
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -070055 // shouldReject must be awaited to ensure it can wait for the promise before the test ends.
Kai Ninomiyac42e2982019-10-23 15:44:28 -070056 t.shouldReject(
Kai Ninomiyabb2e71f2019-08-02 16:25:56 -070057 // The expected '.name' of the thrown error.
58 'TypeError',
59 // Promise expected to reject.
60 Promise.reject(new TypeError()),
61 // Log message.
62 'Promise.reject should reject'
63 );
64
65 // Promise can also be an IIFE.
Kai Ninomiyac42e2982019-10-23 15:44:28 -070066 t.shouldReject(
Kai Ninomiyabb2e71f2019-08-02 16:25:56 -070067 'TypeError',
Lokbondo Kung2db4fdd2023-01-27 16:40:09 -080068 // eslint-disable-next-line @typescript-eslint/require-await
Kai Ninomiyabb2e71f2019-08-02 16:25:56 -070069 (async () => {
70 throw new TypeError();
71 })(),
72 'Promise.reject should reject'
73 );
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -070074});
75
Kai Ninomiya119b9532021-06-03 19:55:56 -070076g.test('basic,plain_cases')
77 .desc(
78 `
79A test can be parameterized with a simple array of objects using .paramsSimple([ ... ]).
80Each such instance of the test is a "case".
Enrico Galli9bec7342021-01-27 15:58:01 -080081
Kai Ninomiya119b9532021-06-03 19:55:56 -070082In this example, the following cases are generated (identified by their "query string"),
83each with just one subcase:
84 - webgpu:examples:basic,cases:x=2;y=2 runs 1 subcase, with t.params set to:
85 - { x: 2, y: 2 }
86 - webgpu:examples:basic,cases:x=-10;y=-10 runs 1 subcase, with t.params set to:
87 - { x: -10, y: -10 }
88 `
89 )
90 .paramsSimple([
91 { x: 2, y: 2 }, //
92 { x: -10, y: -10 },
93 ])
94 .fn(t => {
95 t.expect(t.params.x === t.params.y);
96 });
97
98g.test('basic,plain_cases_private')
99 .desc(
100 `
101Parameters can be public ("x", "y") which means they're part of the case name.
102They can also be private by starting with an underscore ("_result"), which passes
103them into the test but does not make them part of the case name:
104
105In this example, the following cases are generated, each with just one subcase:
106 - webgpu:examples:basic,cases:x=2;y=4 runs 1 subcase, with t.params set to:
107 - { x: 2, y: 4, _result: 6 }
108 - webgpu:examples:basic,cases:x=-10;y=18 runs 1 subcase, with t.params set to:
109 - { x: -10, y: 18, _result: 8 }
110 `
111 )
112 .paramsSimple([
Kai Ninomiyafb584a52020-04-16 16:43:24 -0700113 { x: 2, y: 4, _result: 6 }, //
114 { x: -10, y: 18, _result: 8 },
115 ])
116 .fn(t => {
117 t.expect(t.params.x + t.params.y === t.params._result);
118 });
Kai Ninomiya13820262019-10-17 15:30:56 -0700119// (note the blank comment above to enforce newlines on autoformat)
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -0700120
Kai Ninomiya119b9532021-06-03 19:55:56 -0700121g.test('basic,builder_cases')
122 .desc(
123 `
124A "CaseParamsBuilder" or "SubcaseParamsBuilder" can be passed to .params() instead.
125The params builder provides facilities for generating tests combinatorially (by cartesian
126product). For convenience, the "unit" CaseParamsBuilder is passed as an argument ("u" below).
Enrico Galli9bec7342021-01-27 15:58:01 -0800127
Kai Ninomiya119b9532021-06-03 19:55:56 -0700128In this example, the following cases are generated, each with just one subcase:
129 - webgpu:examples:basic,cases:x=1,y=1 runs 1 subcase, with t.params set to:
130 - { x: 1, y: 1 }
131 - webgpu:examples:basic,cases:x=1,y=2 runs 1 subcase, with t.params set to:
132 - { x: 1, y: 2 }
133 - webgpu:examples:basic,cases:x=2,y=1 runs 1 subcase, with t.params set to:
134 - { x: 2, y: 1 }
135 - webgpu:examples:basic,cases:x=2,y=2 runs 1 subcase, with t.params set to:
136 - { x: 2, y: 2 }
137 `
138 )
139 .params(u =>
140 u //
141 .combineWithParams([{ x: 1 }, { x: 2 }])
142 .combineWithParams([{ y: 1 }, { y: 2 }])
143 )
144 .fn(() => {});
Enrico Galli9bec7342021-01-27 15:58:01 -0800145
Kai Ninomiya119b9532021-06-03 19:55:56 -0700146g.test('basic,builder_cases_subcases')
147 .desc(
148 `
149Each case sub-parameterized using .beginSubcases().
150Each such instance of the test is a "subcase", which cannot be run independently of other
151subcases. It is somewhat like wrapping the entire fn body in a for-loop.
152
153In this example, the following cases are generated:
154 - webgpu:examples:basic,cases:x=1 runs 2 subcases, with t.params set to:
155 - { x: 1, y: 1 }
156 - { x: 1, y: 2 }
157 - webgpu:examples:basic,cases:x=2 runs 2 subcases, with t.params set to:
158 - { x: 2, y: 1 }
159 - { x: 2, y: 2 }
160 `
161 )
162 .params(u =>
163 u //
164 .combineWithParams([{ x: 1 }, { x: 2 }])
165 .beginSubcases()
166 .combineWithParams([{ y: 1 }, { y: 2 }])
167 )
168 .fn(() => {});
169
170g.test('basic,builder_subcases')
171 .desc(
172 `
173In this example, the following single case is generated:
174 - webgpu:examples:basic,cases: runs 4 subcases, with t.params set to:
175 - { x: 1, y: 1 }
176 - { x: 1, y: 2 }
177 - { x: 2, y: 1 }
178 - { x: 2, y: 2 }
179 `
180 )
181 .params(u =>
182 u //
183 .beginSubcases()
184 .combineWithParams([{ x: 1 }, { x: 2 }])
185 .combineWithParams([{ y: 1 }, { y: 2 }])
186 )
187 .fn(() => {});
188
189g.test('basic,builder_subcases_short')
190 .desc(
191 `
192As a shorthand, .paramsSubcasesOnly() can be used.
193
194In this example, the following single case is generated:
195 - webgpu:examples:basic,cases: runs 4 subcases, with t.params set to:
196 - { x: 1, y: 1 }
197 - { x: 1, y: 2 }
198 - { x: 2, y: 1 }
199 - { x: 2, y: 2 }
200 `
201 )
202 .paramsSubcasesOnly(u =>
203 u //
204 .combineWithParams([{ x: 1 }, { x: 2 }])
205 .combineWithParams([{ y: 1 }, { y: 2 }])
Kai Ninomiyad4c4dde2020-12-08 10:54:28 -0800206 )
207 .fn(() => {});
208
Kai Ninomiya9cbb8002020-05-18 15:33:41 -0700209g.test('gpu,async').fn(async t => {
Kai Ninomiya2f242cf2021-04-14 14:12:03 -0700210 const x = await t.queue.onSubmittedWorkDone();
211 t.expect(x === undefined);
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -0700212});
213
Lokbondo Kung2db4fdd2023-01-27 16:40:09 -0800214g.test('gpu,buffers').fn(t => {
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -0700215 const data = new Uint32Array([0, 1234, 0]);
Kai Ninomiya52d01b22021-08-02 20:15:19 -0700216 const src = t.makeBufferWithContents(data, GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST);
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -0700217
Kai Ninomiya52d01b22021-08-02 20:15:19 -0700218 // Use the expectGPUBufferValuesEqual helper to check the actual contents of a GPUBuffer.
219 // This makes a copy and then asynchronously checks the contents. The test fixture will
220 // wait on that result before reporting whether the test passed or failed.
Kai Ninomiya8de9aa52021-06-23 18:25:51 -0700221 t.expectGPUBufferValuesEqual(src, data);
Kai Ninomiya8e4e5dd2019-08-02 14:00:30 -0700222});
Kai Ninomiyafe0cbfa2020-09-25 10:17:24 -0700223
224// One of the following two tests should be skipped on most platforms.
225
226g.test('gpu,with_texture_compression,bc')
Kai Ninomiyafeb406c2020-11-19 15:11:13 -0800227 .desc(
228 `Example of a test using a device descriptor.
229Tests that a BC format passes validation iff the feature is enabled.`
230 )
Kai Ninomiya119b9532021-06-03 19:55:56 -0700231 .params(u => u.combine('textureCompressionBC', [false, true]))
Kai Ninomiyad7d75442022-05-11 11:50:06 -0700232 .beforeAllSubcases(t => {
Kai Ninomiyafe0cbfa2020-09-25 10:17:24 -0700233 const { textureCompressionBC } = t.params;
234
235 if (textureCompressionBC) {
Kai Ninomiyad7d75442022-05-11 11:50:06 -0700236 t.selectDeviceOrSkipTestCase('texture-compression-bc');
Kai Ninomiyafe0cbfa2020-09-25 10:17:24 -0700237 }
Austin Eng318d3d02022-05-03 07:10:10 -1000238 })
Lokbondo Kung2db4fdd2023-01-27 16:40:09 -0800239 .fn(t => {
Austin Eng318d3d02022-05-03 07:10:10 -1000240 const { textureCompressionBC } = t.params;
Kai Ninomiyafe0cbfa2020-09-25 10:17:24 -0700241 const shouldError = !textureCompressionBC;
Brandon Jones8afdd922022-06-01 11:00:59 -0700242 t.shouldThrow(shouldError ? 'TypeError' : false, () => {
243 t.device.createTexture({
244 format: 'bc1-rgba-unorm',
245 size: [4, 4, 1],
246 usage: GPUTextureUsage.TEXTURE_BINDING,
247 });
248 });
Kai Ninomiyafe0cbfa2020-09-25 10:17:24 -0700249 });
250
Lokbondo Kung0e9ad2d2021-11-16 17:57:05 -0800251g.test('gpu,with_texture_compression,etc2')
Kai Ninomiyafeb406c2020-11-19 15:11:13 -0800252 .desc(
253 `Example of a test using a device descriptor.
Lokbondo Kung0e9ad2d2021-11-16 17:57:05 -0800254Tests that an ETC2 format passes validation iff the feature is enabled.`
Kai Ninomiyafd207592021-11-08 16:18:42 -0800255 )
Lokbondo Kung0e9ad2d2021-11-16 17:57:05 -0800256 .params(u => u.combine('textureCompressionETC2', [false, true]))
Kai Ninomiyad7d75442022-05-11 11:50:06 -0700257 .beforeAllSubcases(t => {
Lokbondo Kung0e9ad2d2021-11-16 17:57:05 -0800258 const { textureCompressionETC2 } = t.params;
Kai Ninomiyafd207592021-11-08 16:18:42 -0800259
Lokbondo Kung0e9ad2d2021-11-16 17:57:05 -0800260 if (textureCompressionETC2) {
Kai Ninomiyad7d75442022-05-11 11:50:06 -0700261 t.selectDeviceOrSkipTestCase('texture-compression-etc2' as GPUFeatureName);
Kai Ninomiyafe0cbfa2020-09-25 10:17:24 -0700262 }
Austin Eng318d3d02022-05-03 07:10:10 -1000263 })
Lokbondo Kung2db4fdd2023-01-27 16:40:09 -0800264 .fn(t => {
Austin Eng318d3d02022-05-03 07:10:10 -1000265 const { textureCompressionETC2 } = t.params;
Kai Ninomiyafe0cbfa2020-09-25 10:17:24 -0700266
Lokbondo Kung0e9ad2d2021-11-16 17:57:05 -0800267 const shouldError = !textureCompressionETC2;
Brandon Jones8afdd922022-06-01 11:00:59 -0700268 t.shouldThrow(shouldError ? 'TypeError' : false, () => {
269 t.device.createTexture({
270 format: 'etc2-rgb8unorm',
271 size: [4, 4, 1],
272 usage: GPUTextureUsage.TEXTURE_BINDING,
273 });
274 });
Kai Ninomiyafe0cbfa2020-09-25 10:17:24 -0700275 });