Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

// META: title=validation tests for WebNN API batchNormalization operation
// META: global=window,dedicatedworker
// META: script=../resources/utils_validation.js
'use strict';
let meanIndex = 0;
let varianceIndex = 0;
const kExampleInputDescriptor = {
dataType: 'float32',
dimensions: [2, 2]
};
// 1D tensor descriptor which may be used for `mean`, `variance`, `scale`, or
// `bias` inputs.
const kExample1DTensorDescriptor = {
dataType: 'float32',
dimensions: [kExampleInputDescriptor.dimensions[/* axis */ 1]]
};
promise_test(async t => {
for (let dataType of allWebNNOperandDataTypes) {
const input = builder.input(`input${++inputIndex}`, {dataType, dimensions: dimensions2D});
const validAxisArray = getAxisArray(dimensions2D);
const invalidAxisArray = generateOutOfRangeValuesArray(unsignedLongType);
for (let axis of validAxisArray) {
let size = dimensions2D[axis];
const mean = builder.input(`mean${++meanIndex}`, {dataType, dimensions: [size]});
const variance = builder.input(`variance${++varianceIndex}`, {dataType, dimensions: [size]});
for (let invalidAxis of invalidAxisArray) {
assert_throws_js(TypeError, () => builder.batchNormalization(input, mean, variance, {axis: invalidAxis}));
}
}
}
}, "[batchNormalization] TypeError is expected if options.axis is outside the 'unsigned long' value range");
promise_test(async t => {
for (let dataType of allWebNNOperandDataTypes) {
const input = builder.input(`input${++inputIndex}`, {dataType, dimensions: dimensions2D});
const validAxisArray = getAxisArray(dimensions2D);
for (let axis of validAxisArray) {
let size = dimensions2D[axis];
const mean = builder.input(`mean${++meanIndex}`, {dataType, dimensions: [size]});
const variance = builder.input(`variance${++varianceIndex}`, {dataType, dimensions: [size]});
assert_throws_dom('DataError', () => builder.batchNormalization(input, mean, variance, {axis: getRank(dimensions2D)}));
}
}
}, "[batchNormalization] DataError is expected if options.axis is 'unsigned long' and it's not in the range 0 to the rank of input, exclusive");
promise_test(async t => {
for (let dataType of allWebNNOperandDataTypes) {
const input = builder.input(`input${++inputIndex}`, {dataType, dimensions: dimensions2D});
const validAxisArray = getAxisArray(dimensions2D);
for (let axis of validAxisArray) {
let size = dimensions2D[axis];
const mean = builder.input(`mean${++meanIndex}`, {dataType, dimensions: [size]});
const variance = builder.input(`variance${++varianceIndex}`, {dataType, dimensions: [size]});
for (let axis of notUnsignedLongAxisArray) {
assert_false(typeof axis === 'number' && Number.isInteger(axis), "[batchNormalization] options.axis should be of 'unsigned long'");
assert_throws_js(TypeError, () => builder.batchNormalization(input, mean, variance, {axis}));
}
}
}
}, '[batchNormalization] TypeError is expected if options.axis is not an unsigned long interger');
promise_test(async t => {
for (let dataType of allWebNNOperandDataTypes) {
const input = builder.input(`input${++inputIndex}`, {dataType, dimensions: dimensions2D});
const validAxisArray = getAxisArray(dimensions2D);
for (let axis of validAxisArray) {
const variance = builder.input(`variance${++varianceIndex}`, {dataType, dimensions: [dimensions2D[axis]]});
for (let dimensions of allWebNNDimensionsArray) {
if (dimensions.length !== 1) {
// set mean not be 1D tensor
const mean = builder.input(`mean${++meanIndex}`, {dataType, dimensions});
assert_throws_dom('DataError', () => builder.batchNormalization(input, mean, variance));
}
}
}
}
}, "[batchNormalization] DataError is expected if the size of mean.dimensions is not 1");
promise_test(async t => {
for (let dataType of allWebNNOperandDataTypes) {
const input = builder.input(`input${++inputIndex}`, {dataType, dimensions: dimensions2D});
const validAxisArray = getAxisArray(dimensions2D);
for (let axis of validAxisArray) {
let size = dimensions2D[axis];
const variance = builder.input(`variance${++varianceIndex}`, {dataType, dimensions: [size]});
for (let offset of adjustOffsetsArray) {
const adjustedSize = size + offset;
const mean = builder.input(`mean${++meanIndex}`, {dataType, dimensions: [adjustedSize]});
assert_throws_dom('DataError', () => builder.batchNormalization(input, mean, variance, {axis}));
}
}
}
}, "[batchNormalization] DataError is expected if mean.dimensions[0] is not equal to input.dimensions[options.axis]");
promise_test(async t => {
for (let dataType of allWebNNOperandDataTypes) {
const input = builder.input(`input${++inputIndex}`, {dataType, dimensions: dimensions2D});
const validAxisArray = getAxisArray(dimensions2D);
for (let axis of validAxisArray) {
const mean = builder.input(`mean${++meanIndex}`, {dataType, dimensions: [dimensions2D[axis]]});
for (let dimensions of allWebNNDimensionsArray) {
if (dimensions.length !== 1) {
// set variance not be 1D tensor
const variance = builder.input(`variance${++varianceIndex}`, {dataType, dimensions});
assert_throws_dom('DataError', () => builder.batchNormalization(input, mean, variance));
}
}
}
}
}, "[batchNormalization] DataError is expected if the size of variance.dimensions is not 1");
promise_test(async t => {
for (let dataType of allWebNNOperandDataTypes) {
const input = builder.input(`input${++inputIndex}`, {dataType, dimensions: dimensions2D});
const validAxisArray = getAxisArray(dimensions2D);
for (let axis of validAxisArray) {
let size = dimensions2D[axis];
const mean = builder.input(`mean${++meanIndex}`, {dataType, dimensions: [size]});
for (let offset of adjustOffsetsArray) {
const adjustedSize = size + offset;
const variance = builder.input(`variance${++varianceIndex}`, {dataType, dimensions: [adjustedSize]});
assert_throws_dom('DataError', () => builder.batchNormalization(input, mean, variance, {axis}));
}
}
}
}, "[batchNormalization] DataError is expected if variance.dimensions[0] is not equal to input.dimensions[options.axis]");
promise_test(async t => {
for (let dataType of allWebNNOperandDataTypes) {
const input = builder.input(`input${++inputIndex}`, {dataType, dimensions: dimensions2D});
const validAxisArray = getAxisArray(dimensions2D);
for (let axis of validAxisArray) {
const mean = builder.input(`mean${++meanIndex}`, {dataType, dimensions: [dimensions2D[axis]]});
const variance = builder.input(`variance${++varianceIndex}`, {dataType, dimensions: [dimensions2D[axis]]});
for (let dimensions of allWebNNDimensionsArray) {
if (dimensions.length !== 1) {
// set scale not be 1D tensor
const scale = builder.input('scale', {dataType, dimensions});
assert_throws_dom('DataError', () => builder.batchNormalization(input, mean, variance, {axis, scale}));
}
}
}
}
}, "[batchNormalization] DataError is expected if the size of scale.dimensions is not 1");
promise_test(async t => {
for (let dataType of allWebNNOperandDataTypes) {
const input = builder.input(`input${++inputIndex}`, {dataType, dimensions: dimensions2D});
const validAxisArray = getAxisArray(dimensions2D);
for (let axis of validAxisArray) {
let size = dimensions2D[axis];
const mean = builder.input(`mean${++meanIndex}`, {dataType, dimensions: [size]});
const variance = builder.input(`variance${++varianceIndex}`, {dataType, dimensions: [size]});
for (let offset of adjustOffsetsArray) {
const adjustedSize = size + offset;
const scale = builder.input('scale', {dataType, dimensions: [adjustedSize]});
assert_throws_dom('DataError', () => builder.batchNormalization(input, mean, variance, {axis, scale}));
}
}
}
}, "[batchNormalization] DataError is expected if scale.dimensions[0] is not equal to input.dimensions[options.axis]");
promise_test(async t => {
for (let dataType of allWebNNOperandDataTypes) {
const input = builder.input(`input${++inputIndex}`, {dataType, dimensions: dimensions2D});
const validAxisArray = getAxisArray(dimensions2D);
for (let axis of validAxisArray) {
const mean = builder.input(`mean${++meanIndex}`, {dataType, dimensions: [dimensions2D[axis]]});
const variance = builder.input(`variance${++varianceIndex}`, {dataType, dimensions: [dimensions2D[axis]]});
for (let dimensions of allWebNNDimensionsArray) {
if (dimensions.length !== 1) {
// set bias not be 1D tensor
const bias = builder.input('bias', {dataType, dimensions});
assert_throws_dom('DataError', () => builder.batchNormalization(input, mean, variance, {axis, bias}));
}
}
}
}
}, "[batchNormalization] DataError is expected if the size of bias.dimensions is not 1");
promise_test(async t => {
for (let dataType of allWebNNOperandDataTypes) {
const input = builder.input(`input${++inputIndex}`, {dataType, dimensions: dimensions2D});
const validAxisArray = getAxisArray(dimensions2D);
for (let axis of validAxisArray) {
let size = dimensions2D[axis];
const mean = builder.input(`mean${++meanIndex}`, {dataType, dimensions: [size]});
const variance = builder.input(`variance${++varianceIndex}`, {dataType, dimensions: [size]});
for (let offset of adjustOffsetsArray) {
const adjustedSize = size + offset;
const bias = builder.input('bias', {dataType, dimensions: [adjustedSize]});
assert_throws_dom('DataError', () => builder.batchNormalization(input, mean, variance, {axis, bias}));
}
}
}
}, "[batchNormalization] DataError is expected if bias.dimensions[0] is not equal to input.dimensions[options.axis]");
multi_builder_test(async (t, builder, otherBuilder) => {
const inputFromOtherBuilder =
otherBuilder.input('input', kExampleInputDescriptor);
const mean = builder.input('mean', kExample1DTensorDescriptor);
const variance = builder.input('variance', kExample1DTensorDescriptor);
assert_throws_js(
TypeError, () => builder.batchNormalization(inputFromOtherBuilder, mean, variance));
}, '[batchNormalization] throw if input is from another builder');
multi_builder_test(async (t, builder, otherBuilder) => {
const meanFromOtherBuilder =
otherBuilder.input('mean', kExample1DTensorDescriptor);
const input = builder.input('input', kExampleInputDescriptor);
const variance = builder.input('variance', kExample1DTensorDescriptor);
assert_throws_js(
TypeError,
() => builder.batchNormalization(input, meanFromOtherBuilder, variance));
}, '[batchNormalization] throw if mean is from another builder');
multi_builder_test(async (t, builder, otherBuilder) => {
const varianceFromOtherBuilder =
otherBuilder.input('variance', kExample1DTensorDescriptor);
const input = builder.input('input', kExampleInputDescriptor);
const mean = builder.input('mean', kExample1DTensorDescriptor);
assert_throws_js(
TypeError,
() => builder.batchNormalization(input, mean, varianceFromOtherBuilder));
}, '[batchNormalization] throw if variance is from another builder');
multi_builder_test(async (t, builder, otherBuilder) => {
const scaleFromOtherBuilder =
otherBuilder.input('scale', kExample1DTensorDescriptor);
const options = {scale: scaleFromOtherBuilder};
const input = builder.input('input', kExampleInputDescriptor);
const mean = builder.input('mean', kExample1DTensorDescriptor);
const variance = builder.input('variance', kExample1DTensorDescriptor);
assert_throws_js(
TypeError,
() => builder.batchNormalization(input, mean, variance, options));
}, '[batchNormalization] throw if scale option is from another builder');
multi_builder_test(async (t, builder, otherBuilder) => {
const biasFromOtherBuilder =
otherBuilder.input('bias', kExample1DTensorDescriptor);
const options = {scale: biasFromOtherBuilder};
const input = builder.input('input', kExampleInputDescriptor);
const mean = builder.input('mean', kExample1DTensorDescriptor);
const variance = builder.input('variance', kExample1DTensorDescriptor);
assert_throws_js(
TypeError,
() => builder.batchNormalization(input, mean, variance, options));
}, '[batchNormalization] throw if bias option is from another builder');
multi_builder_test(async (t, builder, otherBuilder) => {
const activationFromOtherBuilder = otherBuilder.clamp();
const options = {activation: activationFromOtherBuilder};
const input = builder.input('input', kExampleInputDescriptor);
const mean = builder.input('mean', kExample1DTensorDescriptor);
const variance = builder.input('variance', kExample1DTensorDescriptor);
assert_throws_js(
TypeError,
() => builder.batchNormalization(input, mean, variance, options));
}, '[batchNormalization] throw if activation option is from another builder');