tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

byob_readtensor.https.any.js (6284B)


      1 // META: title=test WebNN API tensor operations
      2 // META: global=window,worker
      3 // META: variant=?cpu
      4 // META: variant=?gpu
      5 // META: variant=?npu
      6 // META: script=../resources/utils_validation.js
      7 // META: script=../resources/utils.js
      8 // META: timeout=long
      9 
     10 'use strict';
     11 
     12 // Skip tests if WebNN is unimplemented.
     13 promise_setup(async () => {
     14  assert_implements(navigator.ml, 'missing navigator.ml');
     15 });
     16 
     17 // https://www.w3.org/TR/webnn/#api-mltensor
     18 
     19 const testContents = Uint32Array.from([0, 1, 2, 3, 4, 5, 6, 7]);
     20 
     21 let mlContext;
     22 let mlTensor;
     23 promise_setup(async () => {
     24  try {
     25    mlContext = await navigator.ml.createContext(contextOptions);
     26  } catch (e) {
     27    throw new AssertionError(
     28        `Unable to create context for ${variant} variant. ${e}`);
     29  }
     30 
     31  try {
     32    mlTensor = await mlContext.createTensor({
     33      dataType: 'int32',
     34      shape: [2, 4],
     35      readable: true,
     36      writable: true,
     37    });
     38  } catch (e) {
     39    throw new AssertionError(
     40        `Unable to create tensor for ${variant} variant. ${e}`);
     41  }
     42 
     43  mlContext.writeTensor(mlTensor, testContents);
     44 });
     45 
     46 promise_test(async (t) => {
     47  const arrayBuffer = new ArrayBuffer(testContents.byteLength - 4);
     48 
     49  await promise_rejects_js(
     50      t, TypeError, mlContext.readTensor(mlTensor, arrayBuffer));
     51 }, `readTensor() with an ArrayBuffer that is too small should reject`);
     52 
     53 promise_test(async (t) => {
     54  const typedArray = new Uint32Array(testContents.length - 1);
     55 
     56  await promise_rejects_js(
     57      t, TypeError, mlContext.readTensor(mlTensor, typedArray));
     58 }, `readTensor() with a TypedArray that is too small should reject`);
     59 
     60 promise_test(async (t) => {
     61  const arrayBuffer = new ArrayBuffer(testContents.byteLength);
     62  const typedArray = new Uint32Array(arrayBuffer);
     63 
     64  arrayBuffer.transfer();
     65 
     66  await promise_rejects_js(
     67      t, TypeError, mlContext.readTensor(mlTensor, arrayBuffer));
     68 
     69  await promise_rejects_js(
     70      t, TypeError, mlContext.readTensor(mlTensor, typedArray));
     71 }, `readTensor() with a detached ArrayBuffer should reject`);
     72 
     73 promise_test(async (t) => {
     74  const arrayBuffer = new ArrayBuffer(testContents.byteLength);
     75  const typedArray = new Uint32Array(arrayBuffer);
     76 
     77  const checks = Promise.all([
     78    promise_rejects_js(
     79        t, TypeError, mlContext.readTensor(mlTensor, arrayBuffer)),
     80    promise_rejects_js(
     81        t, TypeError, mlContext.readTensor(mlTensor, typedArray)),
     82  ]);
     83 
     84  arrayBuffer.transfer();
     85 
     86  await checks;
     87 }, `Detaching an ArrayBuffer while readTensor() is in progress should reject`);
     88 
     89 promise_test(async () => {
     90  const arrayBuffer = new ArrayBuffer(testContents.byteLength);
     91 
     92  await mlContext.readTensor(mlTensor, arrayBuffer);
     93 
     94  assert_array_equals(new Uint32Array(arrayBuffer), testContents);
     95 }, `readTensor() with an ArrayBuffer`);
     96 
     97 if ('SharedArrayBuffer' in globalThis) {
     98  promise_test(async () => {
     99    const sharedArrayBuffer = new SharedArrayBuffer(testContents.byteLength);
    100 
    101    await mlContext.readTensor(mlTensor, sharedArrayBuffer);
    102 
    103    assert_array_equals(new Uint32Array(sharedArrayBuffer), testContents);
    104  }, `readTensor() with a SharedArrayBuffer`);
    105 
    106  promise_test(async () => {
    107    const sharedArrayBuffer = new SharedArrayBuffer(testContents.byteLength);
    108    const typedArray = new Uint32Array(sharedArrayBuffer);
    109 
    110    await mlContext.readTensor(mlTensor, typedArray);
    111 
    112    assert_array_equals(typedArray, testContents);
    113  }, `readTensor() with a typeArray from a SharedArrayBuffer`);
    114 }
    115 
    116 promise_test(async () => {
    117  // Create a slightly larger ArrayBuffer and set up the TypedArray at an
    118  // offset to make sure the MLTensor contents are written to the correct
    119  // offset.
    120  const arrayBuffer = new ArrayBuffer(testContents.byteLength + 4);
    121  const typedArray = new Uint32Array(arrayBuffer, 4);
    122 
    123  await mlContext.readTensor(mlTensor, typedArray);
    124 
    125  assert_array_equals(typedArray, testContents);
    126 }, `readTensor() with a TypedArray`);
    127 
    128 promise_test(async () => {
    129  const arrayBuffer = new ArrayBuffer(testContents.byteLength * 2);
    130 
    131  await mlContext.readTensor(mlTensor, arrayBuffer);
    132 
    133  assert_array_equals(
    134      new Uint32Array(arrayBuffer).subarray(0, testContents.length),
    135      testContents);
    136  // The rest of the array should remain uninitialized.
    137  assert_array_equals(
    138      new Uint32Array(arrayBuffer)
    139          .subarray(testContents.length, testContents.length * 2),
    140      new Uint32Array(testContents.length));
    141 }, `readTensor() with a larger ArrayBuffer`);
    142 
    143 promise_test(async () => {
    144  // Create a slightly larger ArrayBuffer and set up the TypedArray at an
    145  // offset to make sure the MLTensor contents are written to the correct
    146  // offset.
    147  const arrayBuffer = new ArrayBuffer(testContents.byteLength * 2 + 4);
    148  const typedArray = new Uint32Array(arrayBuffer, 4);
    149 
    150  await mlContext.readTensor(mlTensor, typedArray);
    151 
    152  assert_array_equals(
    153      typedArray.subarray(0, testContents.length), testContents);
    154  // The rest of the array should remain uninitialized.
    155  assert_array_equals(
    156      typedArray.subarray(testContents.length, testContents.length * 2),
    157      new Uint32Array(testContents.length));
    158 }, `readTensor() with a larger TypedArray`);
    159 
    160 promise_test(async (t) => {
    161  const tensor = await mlContext.createTensor({
    162    dataType: 'int32',
    163    shape: [2, 2],
    164    readable: true,
    165  });
    166  const arrayBufferView = new Int32Array(2 * 2);
    167  const arrayBuffer = arrayBufferView.buffer;
    168 
    169  // Reading a destroyed MLTensor should reject.
    170  tensor.destroy();
    171 
    172  await promise_rejects_dom(
    173      t, 'InvalidStateError', mlContext.readTensor(tensor, arrayBuffer));
    174  await promise_rejects_dom(
    175      t, 'InvalidStateError', mlContext.readTensor(tensor, arrayBufferView));
    176 }, `readTensor() rejects on a destroyed MLTensor`);
    177 
    178 promise_test(async (t) => {
    179  const tensor = await mlContext.createTensor({
    180    dataType: 'int32',
    181    shape: [2, 2],
    182    readable: true,
    183  });
    184  const arrayBufferView = new Int32Array(2 * 2);
    185  const arrayBuffer = arrayBufferView.buffer;
    186 
    187  const checks = Promise.all([
    188    promise_rejects_dom(
    189        t, 'InvalidStateError', mlContext.readTensor(tensor, arrayBuffer)),
    190    promise_rejects_dom(
    191        t, 'InvalidStateError', mlContext.readTensor(tensor, arrayBufferView)),
    192  ]);
    193 
    194  tensor.destroy();
    195 
    196  await checks;
    197 }, `readTensor() rejects when the MLTensor is destroyed`);