diff options
Diffstat (limited to '')
-rw-r--r-- | dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-unit-tests.html | 1103 |
1 files changed, 1103 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-unit-tests.html b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-unit-tests.html new file mode 100644 index 0000000000..22f0e452ed --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/typedarrays/array-unit-tests.html @@ -0,0 +1,1103 @@ +<!-- +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"; + +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"); + } +} + +var buffer; +var byteLength; +var subBuffer; +var subArray; +function testSlice() { + function test(subBuf, starts, size) { + byteLength = size; + subBuffer = TestEval(subBuf); + subArray = new Int8Array(subBuffer); + assertEq(subBuf, subBuffer.byteLength, byteLength); + for (var i = 0; i < size; ++i) + assertEq('Element ' + i, starts + i, subArray[i]); + } + + try { + running('testSlice'); + buffer = new ArrayBuffer(32); + var array = new Int8Array(buffer); + for (var i = 0; i < 32; ++i) + array[i] = i; + + test("buffer.slice(0)", 0, 32); + test("buffer.slice(16)", 16, 16); + test("buffer.slice(24)", 24, 8); + test("buffer.slice(32)", 32, 0); + test("buffer.slice(40)", 32, 0); + test("buffer.slice(80)", 32, 0); + + test("buffer.slice(-8)", 24, 8); + test("buffer.slice(-16)", 16, 16); + test("buffer.slice(-24)", 8, 24); + test("buffer.slice(-32)", 0, 32); + test("buffer.slice(-40)", 0, 32); + test("buffer.slice(-80)", 0, 32); + + test("buffer.slice(0, 32)", 0, 32); + test("buffer.slice(0, 16)", 0, 16); + test("buffer.slice(8, 24)", 8, 16); + test("buffer.slice(16, 32)", 16, 16); + test("buffer.slice(24, 16)", 24, 0); + + test("buffer.slice(16, -8)", 16, 8); + test("buffer.slice(-20, 30)", 12, 18); + + test("buffer.slice(-8, -20)", 24, 0); + test("buffer.slice(-20, -8)", 12, 12); + test("buffer.slice(-40, 16)", 0, 16); + test("buffer.slice(-40, 40)", 0, 32); + pass(); + } catch (e) { + fail(e); + } +} + +function testArrayBufferIsViewMethod() { + debug('test ArrayBuffer.isView() with various values'); + + try { + if (!ArrayBuffer.isView) { + testFailed('ArrayBuffer.isView() method does not exist'); + } else { + testPassed('ArrayBuffer.isView() method exists'); + + shouldBe('ArrayBuffer.isView(new Int8Array(1))', 'true'); + shouldBe('ArrayBuffer.isView(new Uint8Array(1))', 'true'); + shouldBe('ArrayBuffer.isView(new Uint8ClampedArray(1))', 'true'); + shouldBe('ArrayBuffer.isView(new Int16Array(1))', 'true'); + shouldBe('ArrayBuffer.isView(new Uint16Array(1))', 'true'); + shouldBe('ArrayBuffer.isView(new Int32Array(1))', 'true'); + shouldBe('ArrayBuffer.isView(new Uint32Array(1))', 'true'); + shouldBe('ArrayBuffer.isView(new Float32Array(1))', 'true'); + shouldBe('ArrayBuffer.isView(new Float64Array(1))', 'true'); + shouldBe('ArrayBuffer.isView(new DataView(new ArrayBuffer(8)))', 'true'); + + shouldBe('ArrayBuffer.isView(undefined)', 'false'); + shouldBe('ArrayBuffer.isView(null)', 'false'); + shouldBe('ArrayBuffer.isView(true)', 'false'); + shouldBe('ArrayBuffer.isView(false)', 'false'); + shouldBe('ArrayBuffer.isView(0)', 'false'); + shouldBe('ArrayBuffer.isView(1)', 'false'); + shouldBe('ArrayBuffer.isView(1.0)', 'false'); + shouldBe('ArrayBuffer.isView("hello")', 'false'); + shouldBe('ArrayBuffer.isView({})', 'false'); + shouldBe('ArrayBuffer.isView(function() {})', 'false'); + shouldBe('ArrayBuffer.isView(new Array(1))', 'false'); + } + } catch (e) { + testFailed('Exception thrown while testing ArrayBuffer.isView method: ' + e); + } +} + +function testInheritanceHierarchy() { + debug('test inheritance hierarchy of typed array views'); + + try { + var foo = ArrayBufferView; + testFailed('ArrayBufferView is a typedef and should not be defined'); + } catch (e) { + testPassed('ArrayBufferView is a typedef and was (correctly) not defined'); + } + + // Uint8ClampedArray inherited from Uint8Array in earlier versions + // of the typed array specification. Since this is no longer the + // case, assert the new behavior. + shouldBe('new Uint8ClampedArray(1) instanceof Uint8Array', 'false'); + + if (Object.getPrototypeOf(Int8Array.prototype) == Object.prototype) { + // ES5 behavior. + shouldBe('Object.getPrototypeOf(Int8Array.prototype)', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Uint8Array.prototype)', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Uint8ClampedArray.prototype)', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Int16Array.prototype)', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Uint16Array.prototype)', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Int32Array.prototype)', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Uint32Array.prototype)', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Float32Array.prototype)', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Float64Array.prototype)', 'Object.prototype'); + } else { + // As of ES6, the prototypes for typed array constructors point to an intrinsic object whose internal + // prototype is Object.prototype. Relevant spec section is 22.2.5.2: TypedArray.prototype. + shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Int8Array.prototype))', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Uint8Array.prototype))', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Uint8ClampedArray.prototype))', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Int16Array.prototype))', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Uint16Array.prototype))', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Int32Array.prototype))', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Uint32Array.prototype))', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Float32Array.prototype))', 'Object.prototype'); + shouldBe('Object.getPrototypeOf(Object.getPrototypeOf(Float64Array.prototype))', 'Object.prototype'); + } + + shouldBe('Object.getPrototypeOf(DataView.prototype)', 'Object.prototype'); +} + +// +// 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 integral types. +// Some JavaScript engines need separate copies of this code in order +// to exercise all of their optimized code paths. +// + +function testIntegralArrayTruncationBehavior(type, name, unsigned) { + running('test integral array truncation behavior for ' + name); + + var sourceData; + var expectedResults; + + if (unsigned) { + sourceData = [0.6, 10.6, 0.2, 10.2, 10.5, 11.5]; + if (type === Uint8ClampedArray) { + expectedResults = [1, 11, 0, 10, 10, 12]; + } else { + expectedResults = [0, 10, 0, 10, 10, 11]; + } + } else { + sourceData = [0.6, 10.6, -0.6, -10.6]; + expectedResults = [0, 10, 0, -10]; + } + + var numIterations = 10; + var array = new type(numIterations); + + // The code block in each of the case statements below is identical, but some + // JavaScript engines need separate copies in order to exercise all of + // their optimized code paths. + + try { + switch (type) { + case Int8Array: + for (var ii = 0; ii < sourceData.length; ++ii) { + for (var jj = 0; jj < numIterations; ++jj) { + array[jj] = sourceData[ii]; + assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]); + } + } + break; + case Int16Array: + for (var ii = 0; ii < sourceData.length; ++ii) { + for (var jj = 0; jj < numIterations; ++jj) { + array[jj] = sourceData[ii]; + assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]); + } + } + break; + case Int32Array: + for (var ii = 0; ii < sourceData.length; ++ii) { + for (var jj = 0; jj < numIterations; ++jj) { + array[jj] = sourceData[ii]; + assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]); + } + } + break; + case Uint8Array: + for (var ii = 0; ii < sourceData.length; ++ii) { + for (var jj = 0; jj < numIterations; ++jj) { + array[jj] = sourceData[ii]; + assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]); + } + } + break; + case Uint8ClampedArray: + for (var ii = 0; ii < sourceData.length; ++ii) { + for (var jj = 0; jj < numIterations; ++jj) { + array[jj] = sourceData[ii]; + assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]); + } + } + break; + case Uint16Array: + for (var ii = 0; ii < sourceData.length; ++ii) { + for (var jj = 0; jj < numIterations; ++jj) { + array[jj] = sourceData[ii]; + assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]); + } + } + break; + case Uint32Array: + for (var ii = 0; ii < sourceData.length; ++ii) { + for (var jj = 0; jj < numIterations; ++jj) { + array[jj] = sourceData[ii]; + assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]); + } + } + break; + default: + fail("Unhandled type"); + break; + } + + 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); + } +} + +var subarray; +function testSubarray(type, name) { + running('test ' + name + ' Subarray'); + try { + var array = new type([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + var subarray = array.subarray(0, 5); + assertEq('subarray.length', 5, subarray.length); + for (var i = 0; i < 5; i++) { + assertEq('Element ' + i, i, subarray[i]); + } + subarray = array.subarray(4, 10); + assertEq('subarray.length', 6, subarray.length); + for (var i = 0; i < 6; i++) { + assertEq('Element ' + i, 4 + i, subarray[i]); + } + pass(); + } catch (e) { + fail(e); + } +} + +function testSubarrayOffsetAndLengthClamping(type, name) { + running('test ' + name + ' Subarray offset and length clamping'); + try { + var array = new type([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + var subarray1 = array.subarray(0, 5); + var subarray2 = subarray1.subarray(-2, 10); + assertEq('subarray2.length', 2, subarray2.length); + assertEq('Element ' + 0, 3, subarray2[0]); + assertEq('Element ' + 1, 4, subarray2[1]); + pass(); + } catch (e) { + fail(e); + } +} + +function negativeTestSubarray(type, name) { + running('negativeTest ' + name + ' Subarray'); + try { + var array = new type([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + subarray = array.subarray(5, 11); + if (subarray.length != 5) { + fail(); + return; + } + subarray = array.subarray(10, 10); + if (subarray.length != 0) { + fail(); + return; + } + pass(); + } catch (e) { + fail(e); + } +} + +function testSetBoundaryConditions(type, name, testValues, expectedValues) { + running('test ' + name + ' SetBoundaryConditions'); + try { + var array = new type(1); + assertEq('Array length', 1, array.length); + for (var ii = 0; ii < testValues.length; ++ii) { + for (var jj = 0; jj < 10; ++jj) { + array[0] = testValues[ii]; + assertEq('Element 0', expectedValues[ii], array[0]); + } + } + pass(); + } catch (e) { + fail(e); + } +} + +function testConstructionBoundaryConditions(type, name, testValues, expectedValues) { + running('test ' + name + ' ConstructionBoundaryConditions'); + try { + var array = new type(testValues); + assertEq('Array length', testValues.length, array.length); + for (var ii = 0; ii < testValues.length; ++ii) { + assertEq('Element ' + ii, expectedValues[ii], array[ii]); + } + pass(); + } catch (e) { + fail(e); + } +} + +function testConstructionWithNullBuffer(type, name) { + var array; + try { + array = new type(null); + assertEq("Length of " + name + " constructed with null", 0, array.length); + testPassed("Construction of " + name + " with null produced a " + name + " of length 0"); + } catch (e) { + // This used to be correct, but TC39 has changed the behavior of these constructors. + testPassed("Construction of " + name + " with null threw exception"); + } + try { + array = new type(null, 0); + assertEq("Length of " + name + " constructed with null", 0, array.length); + testPassed("Construction of " + name + " with null produced a " + name + " of length 0"); + } catch (e) { + // This used to be correct, but TC39 has changed the behavior of these constructors. + testPassed("Construction of " + name + " with (null, 0) threw exception"); + } + try { + array = new type(null, 0, 0); + assertEq("Length of " + name + " constructed with null", 0, array.length); + testPassed("Construction of " + name + " with null produced a " + name + " of length 0"); + } catch (e) { + // This used to be correct, but TC39 has changed the behavior of these constructors. + testPassed("Construction of " + name + " with (null, 0, 0) threw exception"); + } +} + +function testConstructionWithExceptionThrowingObject(type, name) { + var o = {}; + Object.defineProperty(o, "length", { get: function() { throw "bail;" }}); + try { + var array = new type(o); + } catch (e) { + } + testPassed("Construction of " + name + " with exception-throwing array-like object didn't crash unexpectedly"); +} + +function shouldThrowIndexSizeErr(func, text) { + var errorText = text + " should throw an exception"; + try { + func(); + testFailed(errorText); + } catch (e) { + testPassed(text + " threw an exception"); + } +} + +function shouldThrowTypeError(func, text) { + var ok = false; + try { + func(); + } catch (e) { + if (e instanceof TypeError) { + ok = true; + } + } + if (ok) { + testPassed(text + " threw TypeError"); + } else { + testFailed(text + " should throw TypeError"); + } +} + +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 number of elements"); + shouldThrowIndexSizeErr(function() { + var buffer = new ArrayBuffer(4); + var array = new type(buffer, 8); + }, "Construction of " + name + " with out-of-range offset"); +} + +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 testConstructionWithUnalignedLength(type, name, elementSizeInBytes) { + if (elementSizeInBytes > 1) { + shouldThrowIndexSizeErr(function() { + var buffer = new ArrayBuffer(elementSizeInBytes + 1); + var array = new type(buffer, 0); + }, "Construction of " + name + " with unaligned length"); + } +} + +function testConstructionWithBothArrayBufferAndLength(type, name, elementSizeInBytes) { + var bufByteLength = 1000 * elementSizeInBytes; + var buf = new ArrayBuffer(bufByteLength); + var array1 = new type(buf); + var array2 = new type(bufByteLength / elementSizeInBytes); + if (array1.length == array2.length) { + testPassed("Array lengths matched with explicit and implicit creation of ArrayBuffer"); + } else { + testFailed("Array lengths DID NOT MATCH with explicit and implicit creation of ArrayBuffer"); + } +} + +function testConstructionWithSubPortionOfArrayBuffer(type, name, elementSizeInBytes) { + if (elementSizeInBytes > 1) { + // Test construction with a valid sub-portion of an array buffer + // (whose size is not an integral multiple of the element size). + var size = 4 * elementSizeInBytes + (elementSizeInBytes / 2); + var buf = new ArrayBuffer(size); + try { + var array = new type(buf, 0, 2); + testPassed("new " + name + "(new ArrayBuffer(" + size + "), 0, 2) succeeded"); + } catch (e) { + testFailed("new " + name + "(new ArrayBuffer(" + size + "), 0, 2) failed: " + e); + } + } +} + +// These need to be global for shouldBe to see them +var array; +var typeSize; + +function testSubarrayWithOutOfRangeValues(type, name, sz) { + debug("Testing subarray of " + name); + try { + var buffer = new ArrayBuffer(32); + array = new type(buffer); + typeSize = sz; + shouldBe("array.length", "32 / typeSize"); + try { + shouldBe("array.subarray(4, 0x3FFFFFFF).length", "(32 / typeSize) - 4"); + shouldBe("array.subarray(4, -2147483648).length", "0"); + // Test subarray() against overflows. + array = array.subarray(2); + if (sz > 1) { + // Full byte offset is +1 larger than the maximum unsigned long int. + // Make sure subarray() 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.subarray(start, start + 1); + shouldBe("array.length", "0"); + } + } catch (e) { + testFailed("Subarray of " + name + " threw exception"); + } + } catch (e) { + testFailed("Exception: " + e); + } +} + +function testSubarrayWithDefaultValues(type, name, sz) { + debug("Testing subarray 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.subarray(0).length", "(32 / typeSize)"); + shouldBe("array.subarray(2).length", "(32 / typeSize) - 2"); + shouldBe("array.subarray(-2).length", "2"); + shouldBe("array.subarray(-2147483648).length", "(32 / typeSize)"); + } catch (e) { + testFailed("Subarray of " + name + " threw exception"); + } + } catch (e) { + testFailed("Exception: " + e); + } +} + +function setWithInvalidOffset(type, name, length, + sourceType, sourceName, sourceLength, + offset, offsetDescription) { + var webglArray = new type(length); + var sourceArray = new sourceType(sourceLength); + for (var i = 0; i < sourceLength; i++) + sourceArray[i] = 42 + i; + try { + webglArray.set(sourceArray, offset); + testFailed("Setting " + name + " from " + sourceName + " with " + + offsetDescription + " offset was not caught"); + } catch (e) { + testPassed("Setting " + name + " from " + sourceName + " with " + + offsetDescription + " offset was caught"); + } +} + +function setWithValidOffset(type, name, length, + sourceType, sourceName, sourceLength, + offset, offsetDescription) { + running("Setting " + name + " from " + sourceName + " with " + + offsetDescription + " offset"); + var webglArray = new type(length); + var sourceArray = new sourceType(sourceLength); + for (var i = 0; i < sourceLength; i++) + sourceArray[i] = 42 + i; + try { + webglArray.set(sourceArray, offset); + offset = Math.floor(offset); + for (var i = 0; i < sourceLength; i++) { + assertEq("Element " + i + offset, sourceArray[i], webglArray[i + offset]); + } + pass(); + } catch (e) { + fail(e); + } +} + + +function testSettingFromArrayWithOutOfRangeOffset(type, name) { + setWithInvalidOffset(type, name, 32, Array, "array", 16, + 0x7FFFFFF8, "out-of-range"); +} + +function testSettingFromTypedArrayWithOutOfRangeOffset(type, name) { + setWithInvalidOffset(type, name, 32, type, name, 16, + 0x7FFFFFF8, "out-of-range"); +} + +function testSettingFromArrayWithNegativeOffset(type, name) { + setWithInvalidOffset(type, name, 32, Array, "array", 16, + -1, "negative"); +} + +function testSettingFromTypedArrayWithNegativeOffset(type, name) { + setWithInvalidOffset(type, name, 32, type, name, 16, + -1, "negative"); +} + +function testSettingFromArrayWithMinusZeroOffset(type, name) { + setWithValidOffset(type, name, 32, Array, "array", 16, + -0, "-0"); +} + +function testSettingFromTypedArrayWithMinusZeroOffset(type, name) { + setWithValidOffset(type, name, 32, type, name, 16, + -0, "-0"); +} + +function testSettingFromArrayWithBoundaryOffset(type, name) { + setWithValidOffset(type, name, 32, Array, "array", 16, + 16, "boundary"); +} + +function testSettingFromTypedArrayWithBoundaryOffset(type, name) { + setWithValidOffset(type, name, 32, type, name, 16, + 16, "boundary"); +} + +function testSettingFromArrayWithNonIntegerOffset(type, name) { + setWithValidOffset(type, name, 32, Array, "array", 16, + 16.999, "non-integer"); +} + +function testSettingFromTypedArrayWithNonIntegerOffset(type, name) { + setWithValidOffset(type, name, 32, type, name, 16, + 16.999, "non-integer"); +} + +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 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."); + } +} + +function testNaNConversion(type, name) { + running('test storing NaN in ' + name); + + var array = new type([1, 1]); + var results = []; + + // The code block in each of the case statements below is identical, but some + // JavaScript engines need separate copies in order to exercise all of + // their optimized code paths. + try { + switch (type) { + case Float32Array: + for (var i = 0; i < array.length; ++i) { + array[i] = NaN; + results[i] = array[i]; + } + break; + case Float64Array: + for (var i = 0; i < array.length; ++i) { + array[i] = NaN; + results[i] = array[i]; + } + break; + case Int8Array: + for (var i = 0; i < array.length; ++i) { + array[i] = NaN; + results[i] = array[i]; + } + break; + case Int16Array: + for (var i = 0; i < array.length; ++i) { + array[i] = NaN; + results[i] = array[i]; + } + break; + case Int32Array: + for (var i = 0; i < array.length; ++i) { + array[i] = NaN; + results[i] = array[i]; + } + break; + case Uint8Array: + for (var i = 0; i < array.length; ++i) { + array[i] = NaN; + results[i] = array[i]; + } + break; + case Uint8ClampedArray: + for (var i = 0; i < array.length; ++i) { + array[i] = NaN; + results[i] = array[i]; + } + break; + case Uint16Array: + for (var i = 0; i < array.length; ++i) { + array[i] = NaN; + results[i] = array[i]; + } + break; + case Uint32Array: + for (var i = 0; i < array.length; ++i) { + array[i] = NaN; + results[i] = array[i]; + } + break; + default: + fail("Unhandled type"); + break; + } + + // Some types preserve NaN values; all other types convert NaN to zero. + if (type === Float32Array || type === Float64Array) { + assert('initial NaN preserved', isNaN(new type([NaN])[0])); + for (var i = 0; i < array.length; ++i) + assert('NaN preserved via setter', isNaN(results[i])); + } else { + assertEq('initial NaN converted to zero', 0, new type([NaN])[0]); + for (var i = 0; i < array.length; ++i) + assertEq('NaN converted to zero by setter', 0, results[i]); + } + + pass(); + } catch (e) { + fail(e); + } +} + +// +// Test driver +// + +function runTests() { + allPassed = true; + + testSlice(); + testArrayBufferIsViewMethod(); + testInheritanceHierarchy(); + + 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); + } + if (testCase.integral) { + testIntegralArrayTruncationBehavior(type, name, testCase.unsigned); + } + testGetWithOutOfRangeIndices(type, name); + testOffsetsAndSizes(type, name, testCase.elementSizeInBytes); + testSetFromTypedArray(type, name); + negativeTestSetFromTypedArray(type, name); + testSetFromArray(type, name); + negativeTestSetFromArray(type, name); + testSubarray(type, name); + testSubarrayOffsetAndLengthClamping(type, name); + negativeTestSubarray(type, name); + testSetBoundaryConditions(type, + name, + testCase.testValues, + testCase.expectedValues); + testConstructionBoundaryConditions(type, + name, + testCase.testValues, + testCase.expectedValues); + testConstructionWithNullBuffer(type, name); + testConstructionWithExceptionThrowingObject(type, name); + testConstructionWithOutOfRangeValues(type, name); + testConstructionWithNegativeOutOfRangeValues(type, name); + testConstructionWithUnalignedOffset(type, name, testCase.elementSizeInBytes); + testConstructionWithUnalignedLength(type, name, testCase.elementSizeInBytes); + testConstructionWithBothArrayBufferAndLength(type, name, testCase.elementSizeInBytes); + testConstructionWithSubPortionOfArrayBuffer(type, name, testCase.elementSizeInBytes); + testSubarrayWithOutOfRangeValues(type, name, testCase.elementSizeInBytes); + testSubarrayWithDefaultValues(type, name, testCase.elementSizeInBytes); + testSettingFromArrayWithOutOfRangeOffset(type, name); + testSettingFromTypedArrayWithOutOfRangeOffset(type, name); + testSettingFromArrayWithNegativeOffset(type, name); + testSettingFromTypedArrayWithNegativeOffset(type, name); + testSettingFromArrayWithMinusZeroOffset(type, name); + testSettingFromTypedArrayWithMinusZeroOffset(type, name); + testSettingFromArrayWithBoundaryOffset(type, name); + testSettingFromTypedArrayWithBoundaryOffset(type, name); + testSettingFromArrayWithNonIntegerOffset(type, name); + testSettingFromTypedArrayWithNonIntegerOffset(type, name); + testSettingFromFakeArrayWithOutOfRangeLength(type, name); + negativeTestGetAndSetMethods(type, name); + testNaNConversion(type, name); + } + + printSummary(); +} + +runTests(); +var successfullyParsed = true; + +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> |