Source code

Revision control

Copy as Markdown

Other Tools

<!--
Copyright (c) 2019 The Khronos Group Inc.
Use of this source code is governed by an MIT-style license that can be
found in the LICENSE.txt file.
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/test-eval.js"></script>
<script src="../../js/tests/typed-array-test-cases.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
var testQueue = [];
var transferSupported = true;
function nextTest() {
if (testQueue[0].subTests.length > 0) {
testQueue[0].subTests.shift();
}
while (testQueue.length > 0 && testQueue[0].subTests.length == 0) {
testQueue.shift();
}
if (testQueue.length == 0) {
finishTest();
return;
}
testQueue[0].subTests[0].runner();
}
function handleMessage(event) {
if (testQueue.length == 0)
return;
if (testQueue[0].subTests.length == 0)
return;
testQueue[0].subTests[0].checker(event);
nextTest();
}
function setupTest(testCase, runner, checker) {
testCase.subTests.push({ runner: runner.bind(null, testCase), checker: checker.bind(null, testCase) });
}
function arrayToString(arr) {
var result = "[ ";
for (var ii = 0; ii < arr.length; ++ii) {
if (ii > 0)
result += ", ";
result += arr[ii];
}
return result + " ]";
}
function constructTypedArray(type, data) {
if (type == 'Int8Array') {
return new Int8Array(data);
} else if (type == 'Uint8Array') {
return new Uint8Array(data);
} else if (type == 'Uint8ClampedArray') {
return new Uint8ClampedArray(data);
} else if (type == 'Int16Array') {
return new Int16Array(data);
} else if (type == 'Uint16Array') {
return new Uint16Array(data);
} else if (type == 'Int32Array') {
return new Int32Array(data);
} else if (type == 'Uint32Array') {
return new Uint32Array(data);
} else if (type == 'Float32Array') {
return new Float32Array(data);
} else if (type == 'Float64Array') {
return new Float64Array(data);
}
}
// Test runner / checker pairs
function runTestWithData(command, testCase) {
worker.postMessage({command: command, type: testCase.name, subType: testCase.subType, elementSizeInBytes: testCase.elementSizeInBytes, data: testCase.testValues});
}
function checkArraysEqual(testKind, testCase, event) {
var array = event.data;
var testName = testKind + " " + testCase.name + " from worker to main thread";
if (areArraysEqual(array, testCase.expectedValues)) {
testPassed(testName);
} else {
testFailed(testName + ": expected " + arrayToString(testCase.expectedValues) + ", received " + arrayToString(array));
}
}
function checkBufferContentsEqual(testKind, testCase, event) {
var array = constructTypedArray(testCase.name, event.data);
var testName = testKind + " containing " + testCase.name + " values from worker to main thread";
if (areArraysEqual(array, testCase.expectedValues)) {
testPassed(testName);
} else {
testFailed(testName + ": expected " + arrayToString(testCase.expectedValues) + ", received " + arrayToString(array));
}
}
function checkDataViewContents(testKind, testCase, event) {
var dataView = event.data;
var testName = testKind + " " + testCase.name + " containing " + testCase.subType + " from worker to main thread";
var byteOffset = 0;
var allPassed = true;
for (var ii = 0; ii < testCase.expectedValues.length; ++ii) {
var expected = testCase.expectedValues[ii];
var received = dataView['get' + testCase.subType](byteOffset);
if (received != expected) {
allPassed = false;
testFailed(testName + ": at byte offset " + byteOffset + ": expected " + expected + ", received " + received);
}
byteOffset += testCase.elementSizeInBytes;
}
if (allPassed) {
testPassed(testName);
}
}
// Missing test: copy or transfer ArrayBuffer, wrap in DataView on this end, verify contents.
function noop() {
}
function checkArraysEqualAndPingPong(testKind, transfer, testCase, event) {
checkArraysEqual(testKind, testCase, event);
var transferables = [];
if (transfer) {
transferables.push(event.data.buffer);
}
try {
worker.postMessage({ command: 'pong', data: event.data, transferables: transferables }, transferables);
} catch (e) {
testFailed("unexpected exception: " + e);
}
}
function checkBufferContentsEqualAndPingPong(testKind, transfer, testCase, event) {
checkBufferContentsEqual(testKind, testCase, event);
var transferables = [];
if (transfer) {
transferables.push(event.data);
}
try {
worker.postMessage({ command: 'pong', data: event.data, transferables: transferables }, transferables);
} catch (e) {
testFailed("unexpected exception: " + e);
}
}
function checkDataViewContentsAndPingPong(testKind, transfer, testCase, event) {
checkDataViewContents(testKind, testCase, event);
var transferables = [];
if (transfer) {
transferables.push(event.data.buffer);
}
try {
worker.postMessage({ command: 'pong', data: event.data, transferables: transferables }, transferables);
} catch (e) {
testFailed("unexpected exception: " + e);
}
}
description("Tests copying and transferring typed arrays and ArrayBuffers to and from workers");
// See whether workers are supported at all
if (window.Worker) {
// Start up the worker
var worker = new Worker('../../js/tests/typed-array-worker.js');
worker.onmessage = handleMessage;
// See whether transferables are supported
var buffer = new ArrayBuffer(16);
try {
worker.postMessage({ command: 'ignore', data: buffer }, [buffer]);
if (buffer.byteLength > 0)
transferSupported = false;
} catch (e) {
transferSupported = false;
}
// Iterate down the tests, queueing them up
for (var ii = 0; ii < testCases.length; ++ii) {
var testCase = testCases[ii];
testCase.subTests = [];
setupTest(testCase, runTestWithData.bind(null, 'copy'), checkArraysEqual.bind(null, 'copy'));
setupTest(testCase, runTestWithData.bind(null, 'copyBuffer'), checkBufferContentsEqual.bind(null, 'copy ArrayBuffer'));
setupTest(testCase, runTestWithData.bind(null, 'transfer'), checkArraysEqual.bind(null, 'transfer'));
setupTest(testCase, runTestWithData.bind(null, 'transferBuffer'), checkBufferContentsEqual.bind(null, 'transfer ArrayBuffer'));
// These two must run back-to-back
setupTest(testCase, runTestWithData.bind(null, 'copy'), checkArraysEqualAndPingPong.bind(null, 'copy', false));
setupTest(testCase, noop, checkArraysEqual.bind(null, 'ping-pong with copy'));
// These two must run back-to-back
setupTest(testCase, runTestWithData.bind(null, 'copyBuffer'), checkBufferContentsEqualAndPingPong.bind(null, 'copy ArrayBuffer', false));
setupTest(testCase, noop, checkBufferContentsEqual.bind(null, 'ping-pong with copy'));
// These two must run back-to-back
setupTest(testCase, runTestWithData.bind(null, 'transfer'), checkArraysEqualAndPingPong.bind(null, 'transfer', true));
setupTest(testCase, noop, checkArraysEqual.bind(null, 'ping-pong with transfer'));
// These two must run back-to-back
setupTest(testCase, runTestWithData.bind(null, 'transferBuffer'), checkBufferContentsEqualAndPingPong.bind(null, 'transfer ArrayBuffer', false));
setupTest(testCase, noop, checkBufferContentsEqual.bind(null, 'ping-pong with transfer'));
testQueue.push(testCase);
// Add just a couple of DataView tests; the behavior of that view type is thoroughly tested elsewhere
if (testCase.name == "Float32Array" || testCase.name == "Int32Array") {
var subTypeName = (testCase.name == "Float32Array" ? "Float32" : "Int32");
var dataViewTestCase = { name: "DataView",
subType: subTypeName,
elementSizeInBytes: testCase.elementSizeInBytes,
testValues: testCase.testValues,
expectedValues: testCase.expectedValues,
subTests: [] };
setupTest(dataViewTestCase, runTestWithData.bind(null, 'copy'), checkDataViewContents.bind(null, 'copy'));
setupTest(dataViewTestCase, runTestWithData.bind(null, 'transfer'), checkDataViewContents.bind(null, 'transfer'));
// These two must run back-to-back
setupTest(dataViewTestCase, runTestWithData.bind(null, 'copy'), checkDataViewContentsAndPingPong.bind(null, 'copy', false));
setupTest(dataViewTestCase, noop, checkDataViewContents.bind(null, 'ping-pong with copy'));
// These two must run back-to-back
setupTest(dataViewTestCase, runTestWithData.bind(null, 'transfer'), checkDataViewContentsAndPingPong.bind(null, 'transfer', false));
setupTest(dataViewTestCase, noop, checkDataViewContents.bind(null, 'ping-pong with transfer'));
testQueue.push(dataViewTestCase);
}
}
// Kick things off
testQueue[0].subTests[0].runner();
} else {
debug("Workers not supported -- skipping test");
finishTest();
}
var successfullyParsed = true;
</script>
</body>
</html>