blob: 576fbd477a1c3f68bd259f9f6e1e058a10ab825b [file] [log] [blame]
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/ export const description = `
Error scope validation tests.
Note these must create their own device, not use GPUTest (that one already has error scopes on it).
TODO: shorten test names; detail should move to the description.)
TODO: consider slightly revising these tests to make sure they're complete. {
- push 0, pop 1
- push validation, push oom, pop, pop, pop
- push oom, push validation, pop, pop, pop
- push validation, pop, pop
- push oom, pop, pop
- push various x100000 (or some other large number), pop x100000, pop
- }
`;
import { Fixture } from '../../../common/framework/fixture.js';
import { makeTestGroup } from '../../../common/framework/test_group.js';
import { assert, raceWithRejectOnTimeout } from '../../../common/framework/util/util.js';
import { getGPU } from '../../util/navigator_gpu.js';
class F extends Fixture {
_device = undefined;
get device() {
assert(this._device !== undefined);
return this._device;
}
async init() {
super.init();
const gpu = getGPU();
const adapter = await gpu.requestAdapter();
assert(adapter !== null);
const device = await adapter.requestDevice();
assert(device !== null);
this._device = device;
}
createErrorBuffer() {
this.device.createBuffer({
size: 1024,
usage: 0xffff, // Invalid GPUBufferUsage
});
// TODO: Remove when chrome does it automatically.
this.device.defaultQueue.submit([]);
}
// Expect an uncapturederror event to occur. Note: this MUST be awaited, because
// otherwise it could erroneously pass by capturing an error from later in the test.
async expectUncapturedError(fn) {
return this.immediateAsyncExpectation(() => {
// TODO: Make arbitrary timeout value a test runner variable
const TIMEOUT_IN_MS = 1000;
const promise = new Promise(resolve => {
const eventListener = event => {
this.debug(`Got uncaptured error event with ${event.error}`);
resolve(event);
};
this.device.addEventListener('uncapturederror', eventListener, { once: true });
});
fn();
return raceWithRejectOnTimeout(
promise,
TIMEOUT_IN_MS,
'Timeout occurred waiting for uncaptured error'
);
});
}
}
export const g = makeTestGroup(F);
g.test('simple_case_where_the_error_scope_catches_an_error').fn(async t => {
t.device.pushErrorScope('validation');
t.createErrorBuffer();
const error = await t.device.popErrorScope();
t.expect(error instanceof GPUValidationError);
});
g.test('errors_bubble_to_the_parent_scope_if_not_handled_by_the_current_scope').fn(async t => {
t.device.pushErrorScope('validation');
t.device.pushErrorScope('out-of-memory');
t.createErrorBuffer();
{
const error = await t.device.popErrorScope();
t.expect(error === null);
}
{
const error = await t.device.popErrorScope();
t.expect(error instanceof GPUValidationError);
}
});
g.test('if_an_error_scope_matches_an_error_it_does_not_bubble_to_the_parent_scope').fn(async t => {
t.device.pushErrorScope('validation');
t.device.pushErrorScope('validation');
t.createErrorBuffer();
{
const error = await t.device.popErrorScope();
t.expect(error instanceof GPUValidationError);
}
{
const error = await t.device.popErrorScope();
t.expect(error === null);
}
});
g.test('if_no_error_scope_handles_an_error_it_fires_an_uncapturederror_event').fn(async t => {
t.device.pushErrorScope('out-of-memory');
const uncapturedErrorEvent = await t.expectUncapturedError(() => {
t.createErrorBuffer();
});
t.expect(uncapturedErrorEvent.error instanceof GPUValidationError);
const error = await t.device.popErrorScope();
t.expect(error === null);
});
g.test('push,popping_sibling_error_scopes_must_be_balanced').fn(async t => {
{
const promise = t.device.popErrorScope();
t.shouldReject('OperationError', promise);
}
const promises = [];
for (let i = 0; i < 1000; i++) {
t.device.pushErrorScope('validation');
promises.push(t.device.popErrorScope());
}
const errors = await Promise.all(promises);
t.expect(errors.every(e => e === null));
{
const promise = t.device.popErrorScope();
t.shouldReject('OperationError', promise);
}
});
g.test('push,popping_nested_error_scopes_must_be_balanced').fn(async t => {
{
const promise = t.device.popErrorScope();
t.shouldReject('OperationError', promise);
}
const promises = [];
for (let i = 0; i < 1000; i++) {
t.device.pushErrorScope('validation');
}
for (let i = 0; i < 1000; i++) {
promises.push(t.device.popErrorScope());
}
const errors = await Promise.all(promises);
t.expect(errors.every(e => e === null));
{
const promise = t.device.popErrorScope();
t.shouldReject('OperationError', promise);
}
});