Automatic update from web-platform-tests WebNN: Don't run per-op WPTs in non-window contexts The WebNN tests are written as ".any.js" tests which can run in both Window and Worker contexts. This is great! But we running every test on every combination of (CPU, GPU, NPU) x (Window, Worker) consumes significant cycles for little benefit. While tests and various backend and platform implementations are in flux, it also adds significant burden to gardeners. Scope down to running just the Window variations for op-specific tests. Tests for things like inputs, constants, tensors, and object lifecycles are still run in all contexts, and identity() is retained as a "canary". Change-Id: I1f1c749ea4d002a578d6d2ca89579cec6b0090e2 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6299831 Reviewed-by: Weizhong Xia <weizhong@google.com> Commit-Queue: Weizhong Xia <weizhong@google.com> Auto-Submit: Joshua Bell <jsbell@chromium.org> Reviewed-by: Reilly Grant <reillyg@chromium.org> Cr-Commit-Position: refs/heads/main@{#1424187} -- wpt-commits: 092e1df62b17a27e7658334ee585c102fa25478d wpt-pr: 50919
256 lines
8.1 KiB
JavaScript
256 lines
8.1 KiB
JavaScript
// META: title=validation tests for WebNN API resample2d operation
|
|
// META: global=window
|
|
// META: variant=?cpu
|
|
// META: variant=?gpu
|
|
// META: variant=?npu
|
|
// META: script=../resources/utils_validation.js
|
|
|
|
'use strict';
|
|
|
|
const label = 'resample-2d';
|
|
const regrexp = new RegExp('\\[' + label + '\\]');
|
|
// Tests for resample2d(input, options)
|
|
const tests = [
|
|
{
|
|
name: '[resample2d] Test building resample2d with default options',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
output: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
},
|
|
{
|
|
name: '[resample2d] Test building resample2d with scales=[2.0, 2.0]',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
options: {scales: [2.0, 2.0]},
|
|
output: {dataType: 'float32', shape: [1, 1, 4, 8]},
|
|
},
|
|
{
|
|
name: '[resample2d] Test building resample2d with scales=[0.5, 0.5]',
|
|
input: {dataType: 'float32', shape: [1, 1, 5, 5]},
|
|
options: {scales: [0.5, 0.5]},
|
|
output: {dataType: 'float32', shape: [1, 1, 2, 2]},
|
|
},
|
|
{
|
|
name:
|
|
'[resample2d] Test building resample2d with scales=[0.5, 0.5] and explicit axes=[2, 3]',
|
|
input: {dataType: 'float32', shape: [1, 1, 5, 5]},
|
|
options: {scales: [0.5, 0.5], axes: [2, 3]},
|
|
output: {dataType: 'float32', shape: [1, 1, 2, 2]},
|
|
},
|
|
{
|
|
name:
|
|
'[resample2d] Test building resample2d with scales=[1.0, 2.0] and axes=[0, 1]',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
options: {scales: [1.0, 2.0], axes: [0, 1]},
|
|
output: {dataType: 'float32', shape: [1, 2, 2, 4]},
|
|
},
|
|
{
|
|
name:
|
|
'[resample2d] Test building resample2d with scales=[2.0, 2.0] and axes=[1, 2]',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
options: {scales: [2.0, 2.0], axes: [1, 2]},
|
|
output: {dataType: 'float32', shape: [1, 2, 4, 4]},
|
|
},
|
|
{
|
|
name:
|
|
'[resample2d] Test building resample2d with sizes=[3, 6] ignored scales',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
options: {scales: [2.0, 2.0], sizes: [3, 6]},
|
|
output: {dataType: 'float32', shape: [1, 1, 3, 6]},
|
|
},
|
|
{
|
|
name:
|
|
'[resample2d] Test building resample2d with non consecutive axes=[0,2]',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
options: {
|
|
axes: [0, 2],
|
|
label: label,
|
|
},
|
|
output: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
},
|
|
{
|
|
name:
|
|
'[resample2d] Throw if the dataType of input is not float32 or float16',
|
|
input: {dataType: 'int32', shape: [2, 4]},
|
|
options: {label},
|
|
},
|
|
{
|
|
name: '[resample2d] Throw if the rank of input is not 4',
|
|
input: {dataType: 'float32', shape: [2, 4]},
|
|
options: {label},
|
|
},
|
|
{
|
|
name: '[resample2d] Throw if the length of scales is not 2',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
options: {
|
|
scales: [1.0, 1.0, 2.0, 2.0],
|
|
label: label,
|
|
},
|
|
},
|
|
{
|
|
name: '[resample2d] Throw if any scale value is negative',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
options: {
|
|
scales: [1.0, -2.0],
|
|
label: label,
|
|
},
|
|
},
|
|
{
|
|
name: '[resample2d] Throw if any scale value is 0',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
options: {
|
|
scales: [0, 2.0],
|
|
label: label,
|
|
},
|
|
},
|
|
{
|
|
name: '[resample2d] Throw if the length of sizes is not 2',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
options: {
|
|
sizes: [1, 1, 4, 6],
|
|
label: label,
|
|
},
|
|
},
|
|
{
|
|
name: '[resample2d] Throw if sizes[0] is not a valid dimension',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
options: {
|
|
sizes: [0, 1],
|
|
label: label,
|
|
},
|
|
},
|
|
{
|
|
name: '[resample2d] Throw if sizes[1] is not a valid dimension',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
options: {
|
|
sizes: [1, 0],
|
|
label: label,
|
|
},
|
|
},
|
|
{
|
|
name:
|
|
'[resample2d] Throw if any size value is out of \'unsigned long\' value range',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
options: {sizes: [kMaxUnsignedLong + 1, kMaxUnsignedLong + 1]},
|
|
},
|
|
{
|
|
name:
|
|
'[resample2d] Throw if outputHeight being floor(scaleHeight*inputHeight) is too large',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
// The maximum dimension size is kMaxUnsignedLong (2 ** 32 - 1).
|
|
// Here scaleHeight=kMaxUnsignedLong and inputHeight=2,
|
|
// so outputHeight being kMaxUnsignedLong*2 > kMaxUnsignedLong .
|
|
options: {scales: /*[scaleHeight, scaleWidth]*/[kMaxUnsignedLong, 1]},
|
|
},
|
|
{
|
|
name: '[resample2d] Throw if scaleHeight is too small',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
// Here scaleHeight=0.02 and inputHeight=2,
|
|
// so outputHeight would be 0.
|
|
// Link to https://github.com/webmachinelearning/webnn/issues/391.
|
|
options: {
|
|
scales: /*[scaleHeight, scaleWidth]*/[0.02, 0.8],
|
|
label: label,
|
|
},
|
|
},
|
|
{
|
|
name:
|
|
'[resample2d] Throw if outputWidth being floor(scaleWidth*inputWidth) is too large',
|
|
input: {dataType: 'float32', shape: [1, 1, 4, 2]},
|
|
// The maximum dimension size is kMaxUnsignedLong (2 ** 32 - 1).
|
|
// Here scaleWidth=kMaxUnsignedLong and inputWidth=2,
|
|
// so outputWidth being kMaxUnsignedLong*2 > kMaxUnsignedLong .
|
|
options: {scales: /*[scaleHeight, scaleWidth]*/[1, kMaxUnsignedLong]},
|
|
},
|
|
{
|
|
name: '[resample2d] Throw if scaleWidth is too small',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
// Here scaleWidth=0.1 and inputWidth=4,
|
|
// so outputWidth would be 0.
|
|
// Link to https://github.com/webmachinelearning/webnn/issues/391.
|
|
options: {
|
|
scales: /*[scaleHeight, scaleWidth]*/[0.7, 0.1],
|
|
label: label,
|
|
},
|
|
},
|
|
{
|
|
name: '[resample2d] Throw if the length of axes is not 2',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
options: {
|
|
axes: [0, 1, 2],
|
|
label: label,
|
|
},
|
|
},
|
|
{
|
|
name:
|
|
'[resample2d] Throw if any axis value is greater than or equal to the input rank',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
options: {
|
|
axes: [3, 4],
|
|
label: label,
|
|
},
|
|
},
|
|
{
|
|
name: '[resample2d] Throw if the values of axes are same',
|
|
input: {dataType: 'float32', shape: [1, 1, 2, 4]},
|
|
options: {
|
|
axes: [0, 0],
|
|
label: label,
|
|
},
|
|
},
|
|
];
|
|
|
|
tests.forEach(
|
|
test => promise_test(async t => {
|
|
const builder = new MLGraphBuilder(context);
|
|
const input = builder.input('input', test.input);
|
|
const options = test.options ?? {};
|
|
if (test.output) {
|
|
const output = builder.resample2d(input, options);
|
|
assert_equals(output.dataType, test.output.dataType);
|
|
assert_array_equals(output.shape, test.output.shape);
|
|
} else {
|
|
const options = {...test.options};
|
|
if (options.label) {
|
|
assert_throws_with_label(
|
|
() => builder.resample2d(input, options), regrexp);
|
|
} else {
|
|
assert_throws_js(TypeError, () => builder.resample2d(input, options));
|
|
}
|
|
}
|
|
}, test.name));
|
|
|
|
validateInputFromAnotherBuilder(
|
|
'resample2d', {dataType: 'float32', shape: [2, 2, 2, 2]});
|
|
|
|
promise_test(async t => {
|
|
for (let dataType of allWebNNOperandDataTypes) {
|
|
if (!context.opSupportLimits().input.dataTypes.includes(dataType)) {
|
|
continue;
|
|
}
|
|
const builder = new MLGraphBuilder(context);
|
|
const shape = [1, 1, 2, 4];
|
|
const input = builder.input(`input`, {dataType, shape});
|
|
if (context.opSupportLimits().resample2d.input.dataTypes.includes(
|
|
dataType)) {
|
|
const output = builder.resample2d(input);
|
|
assert_equals(output.dataType, dataType);
|
|
assert_array_equals(output.shape, shape);
|
|
} else {
|
|
assert_throws_js(TypeError, () => builder.resample2d(input));
|
|
}
|
|
}
|
|
}, `[resample2d] Test resample2d with all of the data types.`);
|
|
|
|
promise_test(async t => {
|
|
const builder = new MLGraphBuilder(context);
|
|
|
|
const input = builder.input('input', {
|
|
dataType: 'float32',
|
|
shape: [1, 1, context.opSupportLimits().maxTensorByteLength / 4, 1]});
|
|
|
|
const options = {};
|
|
options.scales = [2.0, 2.0];
|
|
options.label = label;
|
|
assert_throws_with_label(
|
|
() => builder.resample2d(input, options), regrexp);
|
|
}, '[resample2d] throw if the output tensor byte length exceeds limit');
|