blob: 7bb63e06a55d407955c4320f2ef71289211dc066 [file] [log] [blame]
<!--
/*
** Copyright (c) 2013 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../../../resources/js-test.js"></script>
<script src="resources/webgl-test.js"></script>
<script src="resources/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) {
if (window.initNonKhronosFramework)
window.initNonKhronosFramework(true);
// Start up the worker
var worker = new Worker('resources/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();
}
</script>
</body>
</html>