| // META: timeout=long |
| // META: title=validation tests for WebNN API MLContext::destroy() |
| // META: global=window,worker |
| // META: variant=?cpu |
| // META: variant=?gpu |
| // META: variant=?npu |
| |
| 'use strict'; |
| |
| let contextOptions; |
| |
| promise_setup(async () => { |
| if (navigator.ml === undefined) { |
| return; |
| } |
| contextOptions = {deviceType: location.search.substring(1)}; |
| }, {explicit_timeout: true}); |
| |
| promise_test(async t => { |
| const context = await navigator.ml.createContext(contextOptions); |
| context.destroy(); |
| await context.lost; |
| }, 'Context will be lost by destroyed.'); |
| |
| promise_test(async t => { |
| const context = await navigator.ml.createContext(contextOptions); |
| context.destroy(); |
| context.destroy(); |
| await context.lost; |
| }, 'Context can be destroyed twice.'); |
| |
| promise_test(async t => { |
| const context = await navigator.ml.createContext(contextOptions); |
| const builder = new MLGraphBuilder(context); |
| context.destroy(); |
| assert_throws_dom('InvalidStateError', () => { |
| const operandType = {dataType: 'float32', shape: [1]}; |
| builder.input('input', operandType); |
| }); |
| }, 'Destroyed context can not build operator.'); |
| |
| promise_test(async t => { |
| const context = await navigator.ml.createContext(contextOptions); |
| context.destroy(); |
| assert_throws_dom('InvalidStateError', () => { |
| new MLGraphBuilder(context); |
| }); |
| }, 'Destroyed context can not create graph builder.'); |
| |
| promise_test(async t => { |
| const context = await navigator.ml.createContext(contextOptions); |
| const builder = new MLGraphBuilder(context); |
| const operandType = {dataType: 'float32', shape: [1]}; |
| const input_operand = builder.input('input', operandType); |
| const const_operand = builder.constant(operandType, Float32Array.from([2])); |
| const output_operand = builder.mul(input_operand, const_operand); |
| |
| context.destroy(); |
| promise_rejects_dom( |
| t, 'InvalidStateError', builder.build({'output': output_operand})); |
| }, 'Destroyed context can not build graph.'); |
| |
| promise_test(async t => { |
| const context = await navigator.ml.createContext(contextOptions); |
| const builder = new MLGraphBuilder(context); |
| const operandType = {dataType: 'float32', shape: [1]}; |
| const lhsOperand = builder.input('lhs', operandType); |
| const rhsOperand = builder.input('rhs', operandType); |
| const graph = |
| await builder.build({'output': builder.sub(lhsOperand, rhsOperand)}); |
| |
| const lhsTensor = await context.createTensor(operandType); |
| const rhsTensor = await context.createTensor(operandType); |
| |
| const dispatchOutputs = {'output': await context.createTensor(operandType)}; |
| context.destroy(); |
| assert_throws_dom('InvalidStateError', () => { |
| context.dispatch( |
| graph, { |
| 'lhs': lhsTensor, |
| 'rhs': rhsTensor, |
| }, |
| dispatchOutputs); |
| }); |
| }, 'Destroyed context can not dispatch.'); |
| |
| promise_test(async t => { |
| const context = await navigator.ml.createContext(contextOptions); |
| const builder = new MLGraphBuilder(context); |
| const operandType = {dataType: 'float32', shape: [1]}; |
| const lhsOperand = builder.input('lhs', operandType); |
| const rhsOperand = builder.input('rhs', operandType); |
| const graph = |
| await builder.build({'output': builder.sub(lhsOperand, rhsOperand)}); |
| |
| const lhsTensor = await context.createTensor(operandType); |
| const rhsTensor = await context.createTensor(operandType); |
| |
| const dispatchOutputs = {'output': await context.createTensor(operandType)}; |
| context.dispatch( |
| graph, { |
| 'lhs': lhsTensor, |
| 'rhs': rhsTensor, |
| }, |
| dispatchOutputs); |
| context.destroy(); |
| }, 'Executing dispatch() before context destroyed is OK.'); |
| |
| promise_test(async t => { |
| const context = await navigator.ml.createContext(contextOptions); |
| context.destroy(); |
| promise_rejects_dom( |
| t, 'InvalidStateError', |
| context.createTensor({dataType: 'float32', shape: [1]})); |
| }, 'Destroyed context can not create tensor.'); |
| |
| promise_test(async t => { |
| const context = await navigator.ml.createContext(contextOptions); |
| const tensor = await context.createTensor({ |
| dataType: 'float32', |
| shape: [1], |
| readable: true, |
| }); |
| context.destroy(); |
| promise_rejects_dom(t, 'InvalidStateError', context.readTensor(tensor)); |
| }, 'Destroyed context can not read tensor.'); |
| |
| promise_test(async t => { |
| const context = await navigator.ml.createContext(contextOptions); |
| const tensor = await context.createTensor({ |
| dataType: 'float32', |
| shape: [1], |
| readable: true, |
| }); |
| let promise = context.readTensor(tensor); |
| context.destroy(); |
| promise_rejects_dom(t, 'InvalidStateError', promise); |
| }, 'Pending promise of readtensor() will be rejected immediately when context is destroyed.'); |
| |
| promise_test(async t => { |
| const context = await navigator.ml.createContext(contextOptions); |
| // Destroying another context doesn't impact the first context. |
| const another_context = await navigator.ml.createContext(contextOptions); |
| another_context.destroy(); |
| const tensor = await context.createTensor({ |
| dataType: 'float32', |
| shape: [1], |
| writable: true, |
| }); |
| let arrayBuffer = new ArrayBuffer(4); |
| context.destroy(); |
| assert_throws_dom('InvalidStateError', () => { |
| context.writeTensor(tensor, new Uint8Array(arrayBuffer)); |
| }); |
| }, 'Destroyed context can not write tensor.'); |