gecko/content/canvas/test/webgl/conformance/array-unit-tests.html

737 lines
21 KiB
HTML

<!--
Copyright (c) 2009 The Chromium Authors. All rights reserved.
Copyright (C) 2009 Apple Computer, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<html>
<head>
<link rel="stylesheet" href="../resources/js-test-style.css"/>
<script src="../resources/js-test-pre.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
description("Verifies the functionality of the new array-like objects in the TypedArray spec");
var currentlyRunning = '';
var allPassed = true;
function running(str) {
currentlyRunning = str;
}
function output(str) {
debug(str);
}
function pass() {
testPassed(currentlyRunning);
}
function fail(str) {
allPassed = false;
var exc;
if (str)
exc = currentlyRunning + ': ' + str;
else
exc = currentlyRunning;
testFailed(exc);
}
function assertEq(prefix, expected, val) {
if (expected != val) {
var str = prefix + ': expected ' + expected + ', got ' + val;
throw str;
}
}
function assert(prefix, expected) {
if (!expected) {
var str = prefix + ': expected value / true';
throw str;
}
}
function printSummary() {
if (allPassed) {
debug("Test passed.");
} else {
debug("TEST FAILED");
}
}
//
// Tests for unsigned array variants
//
function testSetAndGet10To1(type, name) {
running('test ' + name + ' SetAndGet10To1');
try {
var array = new type(10);
for (var i = 0; i < 10; i++) {
array[i] = 10 - i;
}
for (var i = 0; i < 10; i++) {
assertEq('Element ' + i, 10 - i, array[i]);
}
pass();
} catch (e) {
fail(e);
}
}
function testConstructWithArrayOfUnsignedValues(type, name) {
running('test ' + name + ' ConstructWithArrayOfUnsignedValues');
try {
var array = new type([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);
assertEq('Array length', 10, array.length);
for (var i = 0; i < 10; i++) {
assertEq('Element ' + i, 10 - i, array[i]);
}
pass();
} catch (e) {
fail(e);
}
}
function testConstructWithTypedArrayOfUnsignedValues(type, name) {
running('test ' + name + ' ConstructWithTypedArrayOfUnsignedValues');
try {
var tmp = new type([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);
var array = new type(tmp);
assertEq('Array length', 10, array.length);
for (var i = 0; i < 10; i++) {
assertEq('Element ' + i, 10 - i, array[i]);
}
pass();
} catch (e) {
fail(e);
}
}
//
// Tests for signed array variants
//
function testSetAndGetPos10ToNeg10(type, name) {
running('test ' + name + ' SetAndGetPos10ToNeg10');
try {
var array = new type(21);
for (var i = 0; i < 21; i++) {
array[i] = 10 - i;
}
for (var i = 0; i < 21; i++) {
assertEq('Element ' + i, 10 - i, array[i]);
}
pass();
} catch (e) {
fail(e);
}
}
function testConstructWithArrayOfSignedValues(type, name) {
running('test ' + name + ' ConstructWithArrayOfSignedValues');
try {
var array = new type([10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10]);
assertEq('Array length', 21, array.length);
for (var i = 0; i < 21; i++) {
assertEq('Element ' + i, 10 - i, array[i]);
}
pass();
} catch (e) {
fail(e);
}
}
function testConstructWithTypedArrayOfSignedValues(type, name) {
running('test ' + name + ' ConstructWithTypedArrayOfSignedValues');
try {
var tmp = new type([10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10]);
var array = new type(tmp);
assertEq('Array length', 21, array.length);
for (var i = 0; i < 21; i++) {
assertEq('Element ' + i, 10 - i, array[i]);
}
pass();
} catch (e) {
fail(e);
}
}
//
// Test cases for both signed and unsigned types
//
function testGetWithOutOfRangeIndices(type, name) {
debug('Testing ' + name + ' GetWithOutOfRangeIndices');
// See below for declaration of this global variable
array = new type([2, 3]);
shouldBeUndefined("array[2]");
shouldBeUndefined("array[-1]");
shouldBeUndefined("array[0x20000000]");
}
function testOffsetsAndSizes(type, name, elementSizeInBytes) {
running('test ' + name + ' OffsetsAndSizes');
try {
var len = 10;
assertEq('type.BYTES_PER_ELEMENT', elementSizeInBytes, type.BYTES_PER_ELEMENT);
var array = new type(len);
assert('array.buffer', array.buffer);
assertEq('array.byteOffset', 0, array.byteOffset);
assertEq('array.length', len, array.length);
assertEq('array.byteLength', len * elementSizeInBytes, array.byteLength);
array = new type(array.buffer, elementSizeInBytes, len - 1);
assert('array.buffer', array.buffer);
assertEq('array.byteOffset', elementSizeInBytes, array.byteOffset);
assertEq('array.length', len - 1, array.length);
assertEq('array.byteLength', (len - 1) * elementSizeInBytes, array.byteLength);
pass();
} catch (e) {
fail(e);
}
}
function testSetFromTypedArray(type, name) {
running('test ' + name + ' SetFromTypedArray');
try {
var array = new type(10);
var array2 = new type(5);
for (var i = 0; i < 10; i++) {
assertEq('Element ' + i, 0, array[i]);
}
for (var i = 0; i < array2.length; i++) {
array2[i] = i;
}
array.set(array2);
for (var i = 0; i < array2.length; i++) {
assertEq('Element ' + i, i, array[i]);
}
array.set(array2, 5);
for (var i = 0; i < array2.length; i++) {
assertEq('Element ' + i, i, array[5 + i]);
}
pass();
} catch (e) {
fail(e);
}
}
function negativeTestSetFromTypedArray(type, name) {
running('negativeTest ' + name + ' SetFromTypedArray');
try {
var array = new type(5);
var array2 = new type(6);
for (var i = 0; i < 5; i++) {
assertEq('Element ' + i, 0, array[i]);
}
for (var i = 0; i < array2.length; i++) {
array2[i] = i;
}
try {
array.set(array2);
fail('Expected exception from array.set(array2)');
return;
} catch (e) {
}
try {
array2.set(array, 2);
fail('Expected exception from array2.set(array, 2)');
return;
} catch (e) {
}
pass();
} catch (e) {
fail(e);
}
}
function testSetFromArray(type, name) {
running('test ' + name + ' SetFromArray');
try {
var array = new type(10);
var array2 = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
for (var i = 0; i < 10; i++) {
assertEq('Element ' + i, 0, array[i]);
}
array.set(array2, 0);
for (var i = 0; i < array2.length; i++) {
assertEq('Element ' + i, 10 - i, array[i]);
}
pass();
} catch (e) {
fail(e);
}
}
function negativeTestSetFromArray(type, name) {
running('negativeTest ' + name + ' SetFromArray');
try {
var array = new type([2, 3]);
try {
array.set([4, 5], 1);
fail();
return;
} catch (e) {
}
try {
array.set([4, 5, 6]);
fail();
return;
} catch (e) {
}
pass();
} catch (e) {
fail(e);
}
}
function testSlice(type, name) {
running('test ' + name + ' Slice');
try {
var array = new type([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
var slice = array.slice(0, 5);
assertEq('slice.length', 5, slice.length);
for (var i = 0; i < 5; i++) {
assertEq('Element ' + i, i, slice[i]);
}
slice = array.slice(4, 10);
assertEq('slice.length', 6, slice.length);
for (var i = 0; i < 6; i++) {
assertEq('Element ' + i, 4 + i, slice[i]);
}
pass();
} catch (e) {
fail(e);
}
}
function negativeTestSlice(type, name) {
running('negativeTest ' + name + ' Slice');
try {
var array = new type([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
slice = array.slice(5, 11);
if (slice.length != 5) {
fail();
return;
}
slice = array.slice(10, 10);
if (slice.length != 0) {
fail();
return;
}
pass();
} catch (e) {
fail(e);
}
}
function testBoundaryConditions(type, name, lowValue, expectedLowValue, highValue, expectedHighValue) {
running('test ' + name + ' BoundaryConditions(' +
lowValue + ', ' + expectedLowValue + ', ' +
highValue + ', ' + expectedHighValue + ')');
try {
var array = new type(1);
assertEq('Array length', 1, array.length);
array[0] = lowValue;
assertEq('Element 0', expectedLowValue, array[0]);
array[0] = highValue;
assertEq('Element 0', expectedHighValue, array[0]);
pass();
} catch (e) {
fail(e);
}
}
function testConstructionWithNullBuffer(type, name) {
var array;
try {
array = new type(null);
testFailed("Construction of " + name + " with null buffer should throw exception");
} catch (e) {
testPassed("Construction of " + name + " with null buffer threw exception");
}
try {
array = new type(null, 0, 0);
testFailed("Construction of " + name + " with (null buffer, 0) should throw exception");
} catch (e) {
testPassed("Construction of " + name + " with (null buffer, 0) threw exception");
}
try {
array = new type(null, 0, 0);
testFailed("Construction of " + name + " with (null buffer, 0, 0) should throw exception");
} catch (e) {
testPassed("Construction of " + name + " with (null buffer, 0, 0) threw exception");
}
}
function shouldThrowIndexSizeErr(func, text) {
var errorText = text + " should throw INDEX_SIZE_ERR exception";
try {
func();
testFailed(errorText);
} catch (e) {
if (e.code != DOMException.INDEX_SIZE_ERR) {
testFailed(errorText);
} else {
testPassed(text + " threw INDEX_SIZE_ERR exception");
}
}
}
function testConstructionWithOutOfRangeValues(type, name) {
shouldThrowIndexSizeErr(function() {
var buffer = new ArrayBuffer(4);
var array = new type(buffer, 4, 0x3FFFFFFF);
}, "Construction of " + name + " with out-of-range values");
}
function testConstructionWithNegativeOutOfRangeValues(type, name) {
try {
var buffer = new ArrayBuffer(-1);
testFailed("Construction of ArrayBuffer with negative size should throw exception");
} catch (e) {
testPassed("Construction of ArrayBuffer with negative size threw exception");
}
try {
var array = new type(-1);
testFailed("Construction of " + name + " with negative size should throw exception");
} catch (e) {
testPassed("Construction of " + name + " with negative size threw exception");
}
shouldThrowIndexSizeErr(function() {
var buffer = new ArrayBuffer(4);
var array = new type(buffer, 4, -2147483648);
}, "Construction of " + name + " with negative out-of-range values");
}
function testConstructionWithUnalignedOffset(type, name, elementSizeInBytes) {
if (elementSizeInBytes > 1) {
shouldThrowIndexSizeErr(function() {
var buffer = new ArrayBuffer(32);
var array = new type(buffer, 1, elementSizeInBytes);
}, "Construction of " + name + " with unaligned offset");
}
}
function testConstructionOfHugeArray(type, name, sz) {
if (sz == 1)
return;
try {
// Construction of huge arrays must fail because byteLength is
// an unsigned long
array = new type(3000000000);
testFailed("Construction of huge " + name + " should throw exception");
} catch (e) {
testPassed("Construction of huge " + name + " threw exception");
}
}
// These need to be global for shouldBe to see them
var array;
var typeSize;
function testSlicingWithOutOfRangeValues(type, name, sz) {
debug("Testing slicing of " + name);
try {
var buffer = new ArrayBuffer(32);
array = new type(buffer);
typeSize = sz;
shouldBe("array.length", "32 / typeSize");
try {
shouldBe("array.slice(4, 0x3FFFFFFF).length", "(32 / typeSize) - 4");
shouldBe("array.slice(4, -2147483648).length", "0");
// Test slice() against overflows.
array = array.slice(2);
if (sz > 1) {
// Full byte offset is +1 larger than the maximum unsigned long int.
// Make sure slice() still handles it correctly. Otherwise overflow would happen and
// offset would be 0, and array.length array.length would incorrectly be 1.
var start = 4294967296 / sz - 2;
array = array.slice(start, start + 1);
shouldBe("array.length", "0");
}
} catch (e) {
testFailed("Slicing of " + name + " threw exception");
}
} catch (e) {
testFailed("Exception: " + e);
}
}
function testSlicingWithDefaultValues(type, name, sz) {
debug("Testing slicing with default inputs of " + name);
try {
var buffer = new ArrayBuffer(32);
array = new type(buffer);
typeSize = sz;
shouldBe("array.length", "32 / typeSize");
try {
shouldBe("array.slice().length", "(32 / typeSize)");
shouldBe("array.slice(2).length", "(32 / typeSize) - 2");
shouldBe("array.slice(-2).length", "2");
shouldBe("array.slice(-2147483648).length", "(32 / typeSize)");
} catch (e) {
testFailed("Slicing of " + name + " threw exception");
}
} catch (e) {
testFailed("Exception: " + e);
}
}
function testSettingFromArrayWithOutOfRangeOffset(type, name) {
var webglArray = new type(32);
var array = [];
for (var i = 0; i < 16; i++) {
array.push(i);
}
try {
webglArray.set(array, 0x7FFFFFF8);
testFailed("Setting " + name + " from array with out-of-range offset was not caught");
} catch (e) {
testPassed("Setting " + name + " from array with out-of-range offset was caught");
}
}
function testSettingFromFakeArrayWithOutOfRangeLength(type, name) {
var webglArray = new type(32);
var array = {};
array.length = 0x80000000;
try {
webglArray.set(array, 8);
testFailed("Setting " + name + " from fake array with invalid length was not caught");
} catch (e) {
testPassed("Setting " + name + " from fake array with invalid length was caught");
}
}
function testSettingFromTypedArrayWithOutOfRangeOffset(type, name) {
var webglArray = new type(32);
var srcArray = new type(16);
for (var i = 0; i < 16; i++) {
srcArray[i] = i;
}
try {
webglArray.set(srcArray, 0x7FFFFFF8);
testFailed("Setting " + name + " from " + name + " with out-of-range offset was not caught");
} catch (e) {
testPassed("Setting " + name + " from " + name + " with out-of-range offset was caught");
}
}
function negativeTestGetAndSetMethods(type, name) {
array = new type([2, 3]);
shouldBeUndefined("array.get");
var exceptionThrown = false;
// We deliberately check for an exception here rather than using
// shouldThrow here because the precise contents of the syntax
// error are not specified.
try {
webGLArray.set(0, 1);
} catch (e) {
exceptionThrown = true;
}
var output = "array.set(0, 1) ";
if (exceptionThrown) {
testPassed(output + "threw exception.");
} else {
testFailed(output + "did not throw exception.");
}
}
//
// Test driver
//
function runTests() {
allPassed = true;
// The "name" attribute is a concession to browsers which don't
// implement the "name" property on function objects
var testCases =
[ {name: "Float32Array",
unsigned: false,
elementSizeInBytes: 4,
low: -500.5,
expectedLow: -500.5,
high: 500.5,
expectedHigh: 500.5},
{name: "Int8Array",
unsigned: false,
elementSizeInBytes: 1,
low: -128,
expectedLow: -128,
high: 127,
expectedHigh: 127},
{name: "Int16Array",
unsigned: false,
elementSizeInBytes: 2,
low: -32768,
expectedLow: -32768,
high: 32767,
expectedHigh: 32767},
{name: "Int32Array",
unsigned: false,
elementSizeInBytes: 4,
low: -2147483648,
expectedLow: -2147483648,
high: 2147483647,
expectedHigh: 2147483647},
{name: "Uint8Array",
unsigned: true,
elementSizeInBytes: 1,
low: 0,
expectedLow: 0,
high: 255,
expectedHigh: 255},
{name: "Uint16Array",
unsigned: true,
elementSizeInBytes: 2,
low: 0,
expectedLow: 0,
high: 65535,
expectedHigh: 65535},
{name: "Uint32Array",
unsigned: true,
elementSizeInBytes: 4,
low: 0,
expectedLow: 0,
high: 4294967295,
expectedHigh: 4294967295},
// Legacy names of these types. Left here only to catch breakage
// until the WebGLArray aliases are removed completely. (FIXME)
{name: "WebGLByteArray",
unsigned: false,
elementSizeInBytes: 1,
low: -128,
expectedLow: -128,
high: 127,
expectedHigh: 127},
{name: "WebGLFloatArray",
unsigned: false,
elementSizeInBytes: 4,
low: -500.5,
expectedLow: -500.5,
high: 500.5,
expectedHigh: 500.5},
{name: "WebGLIntArray",
unsigned: false,
elementSizeInBytes: 4,
low: -2147483648,
expectedLow: -2147483648,
high: 2147483647,
expectedHigh: 2147483647},
{name: "WebGLShortArray",
unsigned: false,
elementSizeInBytes: 2,
low: -32768,
expectedLow: -32768,
high: 32767,
expectedHigh: 32767},
{name: "WebGLUnsignedByteArray",
unsigned: true,
elementSizeInBytes: 1,
low: 0,
expectedLow: 0,
high: 255,
expectedHigh: 255},
{name: "WebGLUnsignedIntArray",
unsigned: true,
elementSizeInBytes: 4,
low: 0,
expectedLow: 0,
high: 4294967295,
expectedHigh: 4294967295},
{name: "WebGLUnsignedShortArray",
unsigned: true,
elementSizeInBytes: 2,
low: 0,
expectedLow: 0,
high: 65535,
expectedHigh: 65535} ];
for (var i = 0; i < testCases.length; i++) {
var testCase = testCases[i];
running(testCase.name);
if (!(testCase.name in window)) {
fail("does not exist");
continue;
}
var type = window[testCase.name];
var name = testCase.name;
if (testCase.unsigned) {
testSetAndGet10To1(type, name);
testConstructWithArrayOfUnsignedValues(type, name);
testConstructWithTypedArrayOfUnsignedValues(type, name);
} else {
testSetAndGetPos10ToNeg10(type, name);
testConstructWithArrayOfSignedValues(type, name);
testConstructWithTypedArrayOfSignedValues(type, name);
}
testGetWithOutOfRangeIndices(type, name);
testOffsetsAndSizes(type, name, testCase.elementSizeInBytes);
testSetFromTypedArray(type, name);
negativeTestSetFromTypedArray(type, name);
testSetFromArray(type, name);
negativeTestSetFromArray(type, name);
testSlice(type, name);
negativeTestSlice(type, name);
testBoundaryConditions(type,
name,
testCase.low,
testCase.expectedLow,
testCase.high,
testCase.expectedHigh);
testConstructionWithNullBuffer(type, name);
testConstructionWithOutOfRangeValues(type, name);
testConstructionWithNegativeOutOfRangeValues(type, name);
testConstructionWithUnalignedOffset(type, name, testCase.elementSizeInBytes);
testConstructionOfHugeArray(type, name, testCase.elementSizeInBytes);
testSlicingWithOutOfRangeValues(type, name, testCase.elementSizeInBytes);
testSlicingWithDefaultValues(type, name, testCase.elementSizeInBytes);
testSettingFromArrayWithOutOfRangeOffset(type, name);
testSettingFromFakeArrayWithOutOfRangeLength(type, name);
testSettingFromTypedArrayWithOutOfRangeOffset(type, name);
negativeTestGetAndSetMethods(type, name);
}
printSummary();
}
runTests();
successfullyParsed = true;
</script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>