Enhance shouldBe()/shouldNotBe() to accept anonymous function arguments
[WebKit-https.git] / LayoutTests / fast / canvas / webgl / array-unit-tests.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <script src="../../../resources/js-test.js"></script>
6 <script src="resources/webgl-test.js"></script>
7 <script src="resources/typed-array-test-cases.js"></script>
8 </head>
9 <body>
10 <div id="description"></div>
11 <div id="console"></div>
12
13 <script>
14 description("Verifies the functionality of the new array-like objects in the TypedArray spec");
15
16 var currentlyRunning = '';
17 var allPassed = true;
18 function running(str) {
19   currentlyRunning = str;
20 }
21
22 function output(str) {
23   debug(str);
24 }
25
26 function pass() {
27   testPassed(currentlyRunning);
28 }
29
30 function fail(str) {
31   allPassed = false;
32   var exc;
33   if (str)
34     exc = currentlyRunning + ': ' + str;
35   else
36     exc = currentlyRunning;
37   testFailed(exc);
38 }
39
40 function assertEq(prefix, expected, val) {
41   if (expected != val) {
42     var str = prefix + ': expected ' + expected + ', got ' + val;
43     throw str;
44   }
45 }
46
47 function assert(prefix, expected) {
48   if (!expected) {
49     var str = prefix + ': expected value / true';
50     throw str;
51   }
52 }
53
54 function printSummary() {
55   if (allPassed) {
56     debug("Test passed.");
57   } else {
58     debug("TEST FAILED");
59   }
60 }
61
62 var buffer;
63 var byteLength;
64 var subBuffer;
65 var subArray;
66 function testSlice() {
67   function test(subBuf, starts, size) {
68     byteLength = size;
69     subBuffer = eval(subBuf);
70     subArray = new Int8Array(subBuffer);
71     assertEq(subBuf, subBuffer.byteLength, byteLength);
72     for (var i = 0; i < size; ++i)
73       assertEq('Element ' + i, starts + i, subArray[i]);
74   }
75
76   try {
77     running('testSlice');
78     buffer = new ArrayBuffer(32);
79     var array = new Int8Array(buffer);
80     for (var i = 0; i < 32; ++i)
81       array[i] = i;
82
83     test("buffer.slice(0)", 0, 32);
84     test("buffer.slice(16)", 16, 16);
85     test("buffer.slice(24)", 24, 8);
86     test("buffer.slice(32)", 32, 0);
87     test("buffer.slice(40)", 32, 0);
88     test("buffer.slice(80)", 32, 0);
89
90     test("buffer.slice(-8)", 24, 8);
91     test("buffer.slice(-16)", 16, 16);
92     test("buffer.slice(-24)", 8, 24);
93     test("buffer.slice(-32)", 0, 32);
94     test("buffer.slice(-40)", 0, 32);
95     test("buffer.slice(-80)", 0, 32);
96
97     test("buffer.slice(0, 32)", 0, 32);
98     test("buffer.slice(0, 16)", 0, 16);
99     test("buffer.slice(8, 24)", 8, 16);
100     test("buffer.slice(16, 32)", 16, 16);
101     test("buffer.slice(24, 16)", 24, 0);
102
103     test("buffer.slice(16, -8)", 16, 8);
104     test("buffer.slice(-20, 30)", 12, 18);
105
106     test("buffer.slice(-8, -20)", 24, 0);
107     test("buffer.slice(-20, -8)", 12, 12);
108     test("buffer.slice(-40, 16)", 0, 16);
109     test("buffer.slice(-40, 40)", 0, 32);
110     pass();
111   } catch (e) {
112     fail(e);
113   }
114 }
115
116 function testInheritanceHierarchy() {
117   debug('test inheritance hierarchy of typed array views');
118
119   try {
120     var foo = ArrayBufferView;
121     testFailed("ArrayBufferView should be undefined but is defined");
122   } catch (e) {
123     testPassed('ArrayBufferView should be undefined and is');
124   }
125
126   shouldBe('new Uint8ClampedArray(1) instanceof Uint8Array', 'false');
127 }
128
129 //
130 // Tests for unsigned array variants
131 //
132
133 function testSetAndGet10To1(type, name) {
134   running('test ' + name + ' SetAndGet10To1');
135   try {
136     var array = new type(10);
137     for (var i = 0; i < 10; i++) {
138       array[i] = 10 - i;
139     }
140     for (var i = 0; i < 10; i++) {
141       assertEq('Element ' + i, 10 - i, array[i]);
142     }
143     pass();
144   } catch (e) {
145     fail(e);
146   }
147 }
148
149 function testConstructWithArrayOfUnsignedValues(type, name) {
150   running('test ' + name + ' ConstructWithArrayOfUnsignedValues');
151   try {
152     var array = new type([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);
153     assertEq('Array length', 10, array.length);
154     for (var i = 0; i < 10; i++) {
155       assertEq('Element ' + i, 10 - i, array[i]);
156     }
157     pass();
158   } catch (e) {
159     fail(e);
160   }
161 }
162
163 function testConstructWithTypedArrayOfUnsignedValues(type, name) {
164   running('test ' + name + ' ConstructWithTypedArrayOfUnsignedValues');
165   try {
166     var tmp = new type([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);
167     var array = new type(tmp);
168     assertEq('Array length', 10, array.length);
169     for (var i = 0; i < 10; i++) {
170       assertEq('Element ' + i, 10 - i, array[i]);
171     }
172     pass();
173   } catch (e) {
174     fail(e);
175   }
176 }
177
178 //
179 // Tests for signed array variants
180 //
181
182 function testSetAndGetPos10ToNeg10(type, name) {
183   running('test ' + name + ' SetAndGetPos10ToNeg10');
184   try {
185     var array = new type(21);
186     for (var i = 0; i < 21; i++) {
187       array[i] = 10 - i;
188     }
189     for (var i = 0; i < 21; i++) {
190       assertEq('Element ' + i, 10 - i, array[i]);
191     }
192     pass();
193   } catch (e) {
194     fail(e);
195   }
196 }
197
198 function testConstructWithArrayOfSignedValues(type, name) {
199   running('test ' + name + ' ConstructWithArrayOfSignedValues');
200   try {
201     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]);
202     assertEq('Array length', 21, array.length);
203     for (var i = 0; i < 21; i++) {
204       assertEq('Element ' + i, 10 - i, array[i]);
205     }
206     pass();
207   } catch (e) {
208     fail(e);
209   }
210 }
211
212 function testConstructWithTypedArrayOfSignedValues(type, name) {
213   running('test ' + name + ' ConstructWithTypedArrayOfSignedValues');
214   try {
215     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]);
216     var array = new type(tmp);
217     assertEq('Array length', 21, array.length);
218     for (var i = 0; i < 21; i++) {
219       assertEq('Element ' + i, 10 - i, array[i]);
220     }
221     pass();
222   } catch (e) {
223     fail(e);
224   }
225 }
226
227 //
228 // Test cases for integral types.
229 // Some JavaScript engines need separate copies of this code in order
230 // to exercise all of their optimized code paths.
231 //
232
233 function testIntegralArrayTruncationBehavior(type, name, unsigned) {
234   running('test integral array truncation behavior for ' + name);
235
236   var sourceData;
237   var expectedResults;
238
239   if (unsigned) {
240     sourceData = [0.6, 10.6, 0.2, 10.2, 10.5, 11.5];
241     if (type === Uint8ClampedArray) {
242       expectedResults = [1, 11, 0, 10, 10, 12];
243     } else {
244       expectedResults = [0, 10, 0, 10, 10, 11];
245     }
246   } else {
247     sourceData = [0.6, 10.6, -0.6, -10.6];
248     expectedResults = [0, 10, 0, -10];
249   }
250
251   var numIterations = 10;
252   var array = new type(numIterations);
253
254   // The code block in each of the case statements below is identical, but some
255   // JavaScript engines need separate copies in order to exercise all of
256   // their optimized code paths.
257
258   try {
259     switch (type) {
260     case Int8Array:
261       for (var ii = 0; ii < sourceData.length; ++ii) {
262         for (var jj = 0; jj < numIterations; ++jj) {
263           array[jj] = sourceData[ii];
264           assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
265         }
266       }
267       break;
268     case Int16Array:
269       for (var ii = 0; ii < sourceData.length; ++ii) {
270         for (var jj = 0; jj < numIterations; ++jj) {
271           array[jj] = sourceData[ii];
272           assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
273         }
274       }
275       break;
276     case Int32Array:
277       for (var ii = 0; ii < sourceData.length; ++ii) {
278         for (var jj = 0; jj < numIterations; ++jj) {
279           array[jj] = sourceData[ii];
280           assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
281         }
282       }
283       break;
284     case Uint8Array:
285       for (var ii = 0; ii < sourceData.length; ++ii) {
286         for (var jj = 0; jj < numIterations; ++jj) {
287           array[jj] = sourceData[ii];
288           assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
289         }
290       }
291       break;
292     case Uint8ClampedArray:
293       for (var ii = 0; ii < sourceData.length; ++ii) {
294         for (var jj = 0; jj < numIterations; ++jj) {
295           array[jj] = sourceData[ii];
296           assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
297         }
298       }
299       break;
300     case Uint16Array:
301       for (var ii = 0; ii < sourceData.length; ++ii) {
302         for (var jj = 0; jj < numIterations; ++jj) {
303           array[jj] = sourceData[ii];
304           assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
305         }
306       }
307       break;
308     case Uint32Array:
309       for (var ii = 0; ii < sourceData.length; ++ii) {
310         for (var jj = 0; jj < numIterations; ++jj) {
311           array[jj] = sourceData[ii];
312           assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
313         }
314       }
315       break;
316     default:
317       fail("Unhandled type");
318       break;
319     }
320
321     pass();
322   } catch (e) {
323     fail(e);
324   }
325 }
326
327
328 //
329 // Test cases for both signed and unsigned types
330 //
331
332 function testGetWithOutOfRangeIndices(type, name) {
333     debug('Testing ' + name + ' GetWithOutOfRangeIndices');
334     // See below for declaration of this global variable
335     array = new type([2, 3]);
336     shouldBeUndefined("array[2]");
337     shouldBeUndefined("array[-1]");
338     shouldBeUndefined("array[0x20000000]");
339 }
340
341 function testOffsetsAndSizes(type, name, elementSizeInBytes) {
342   running('test ' + name + ' OffsetsAndSizes');
343   try {
344     var len = 10;
345     assertEq('type.BYTES_PER_ELEMENT', elementSizeInBytes, type.BYTES_PER_ELEMENT);
346     var array = new type(len);
347     assert('array.buffer', array.buffer);
348     assertEq('array.byteOffset', 0, array.byteOffset);
349     assertEq('array.length', len, array.length);
350     assertEq('array.byteLength', len * elementSizeInBytes, array.byteLength);
351     array = new type(array.buffer, elementSizeInBytes, len - 1);
352     assert('array.buffer', array.buffer);
353     assertEq('array.byteOffset', elementSizeInBytes, array.byteOffset);
354     assertEq('array.length', len - 1, array.length);
355     assertEq('array.byteLength', (len - 1) * elementSizeInBytes, array.byteLength);
356     pass();
357   } catch (e) {
358     fail(e);
359   }
360 }
361
362 function testSetFromTypedArray(type, name) {
363   running('test ' + name + ' SetFromTypedArray');
364   try {
365     var array = new type(10);
366     var array2 = new type(5);
367     for (var i = 0; i < 10; i++) {
368       assertEq('Element ' + i, 0, array[i]);
369     }
370     for (var i = 0; i < array2.length; i++) {
371       array2[i] = i;
372     }
373     array.set(array2);
374     for (var i = 0; i < array2.length; i++) {
375       assertEq('Element ' + i, i, array[i]);
376     }
377     array.set(array2, 5);
378     for (var i = 0; i < array2.length; i++) {
379       assertEq('Element ' + i, i, array[5 + i]);
380     }
381     pass();
382   } catch (e) {
383     fail(e);
384   }
385 }
386
387 function negativeTestSetFromTypedArray(type, name) {
388   running('negativeTest ' + name + ' SetFromTypedArray');
389   try {
390     var array = new type(5);
391     var array2 = new type(6);
392     for (var i = 0; i < 5; i++) {
393       assertEq('Element ' + i, 0, array[i]);
394     }
395     for (var i = 0; i < array2.length; i++) {
396       array2[i] = i;
397     }
398     try {
399       array.set(array2);
400       fail('Expected exception from array.set(array2)');
401       return;
402     } catch (e) {
403     }
404     try {
405       array2.set(array, 2);
406       fail('Expected exception from array2.set(array, 2)');
407       return;
408     } catch (e) {
409     }
410     pass();
411   } catch (e) {
412     fail(e);
413   }
414 }
415
416 function testSetFromArray(type, name) {
417   running('test ' + name + ' SetFromArray');
418   try {
419     var array = new type(10);
420     var array2 = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
421     for (var i = 0; i < 10; i++) {
422       assertEq('Element ' + i, 0, array[i]);
423     }
424     array.set(array2, 0);
425     for (var i = 0; i < array2.length; i++) {
426       assertEq('Element ' + i, 10 - i, array[i]);
427     }
428     pass();
429   } catch (e) {
430     fail(e);
431   }
432 }
433
434 function negativeTestSetFromArray(type, name) {
435   running('negativeTest ' + name + ' SetFromArray');
436   try {
437     var array = new type([2, 3]);
438     try {
439       array.set([4, 5], 1);
440       fail();
441       return;
442     } catch (e) {
443     }
444     try {
445       array.set([4, 5, 6]);
446       fail();
447       return;
448     } catch (e) {
449     }
450     pass();
451   } catch (e) {
452     fail(e);
453   }
454 }
455
456 var subarray;
457 function testSubarray(type, name) {
458   running('test ' + name + ' Subarray');
459   try {
460     var array = new type([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
461     var subarray = array.subarray(0, 5);
462     assertEq('subarray.length', 5, subarray.length);
463     for (var i = 0; i < 5; i++) {
464       assertEq('Element ' + i, i, subarray[i]);
465     }
466     subarray = array.subarray(4, 10);
467     assertEq('subarray.length', 6, subarray.length);
468     for (var i = 0; i < 6; i++) {
469       assertEq('Element ' + i, 4 + i, subarray[i]);
470     }
471     pass();
472   } catch (e) {
473     fail(e);
474   }
475 }
476
477 function testSubarrayOffsetAndLengthClamping(type, name) {
478   running('test ' + name + ' Subarray offset and length clamping');
479   try {
480     var array = new type([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
481     var subarray1 = array.subarray(0, 5);
482     var subarray2 = subarray1.subarray(-2, 10);
483     assertEq('subarray2.length', 2, subarray2.length);
484     assertEq('Element ' + 0, 3, subarray2[0]);
485     assertEq('Element ' + 1, 4, subarray2[1]);
486     pass();
487   } catch (e) {
488     fail(e);
489   }
490 }
491
492 function negativeTestSubarray(type, name) {
493   running('negativeTest ' + name + ' Subarray');
494   try {
495     var array = new type([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
496     subarray = array.subarray(5, 11);
497     if (subarray.length != 5) {
498       fail();
499       return;
500     }
501     subarray = array.subarray(10, 10);
502     if (subarray.length != 0) {
503       fail();
504       return;
505     }
506     pass();
507   } catch (e) {
508     fail(e);
509   }
510 }
511
512 function testSetBoundaryConditions(type, name, testValues, expectedValues) {
513   running('test ' + name + ' SetBoundaryConditions');
514   try {
515     var array = new type(1);
516     assertEq('Array length', 1, array.length);
517     for (var ii = 0; ii < testValues.length; ++ii) {
518       for (var jj = 0; jj < 10; ++jj) {
519         array[0] = testValues[ii];
520         assertEq('Element 0', expectedValues[ii], array[0]);
521       }
522     }
523     pass();
524   } catch (e) {
525     fail(e);
526   }
527 }
528
529 function testConstructionBoundaryConditions(type, name, testValues, expectedValues) {
530   running('test ' + name + ' ConstructionBoundaryConditions');
531   try {
532     var array = new type(testValues);
533     assertEq('Array length', testValues.length, array.length);
534     for (var ii = 0; ii < testValues.length; ++ii) {
535       assertEq('Element ' + ii, expectedValues[ii], array[ii]);
536     }
537     pass();
538   } catch (e) {
539     fail(e);
540   }
541 }
542
543 function testConstructionWithNullBuffer(type, name) {
544     var array;
545     try {
546         array = new type(null);
547         testFailed("Construction of " + name + " with null buffer should throw exception");
548     } catch (e) {
549         testPassed("Construction of " + name + " with null buffer threw exception");
550     }
551     try {
552         array = new type(null, 0, 0);
553         testFailed("Construction of " + name + " with (null buffer, 0) should throw exception");
554     } catch (e) {
555         testPassed("Construction of " + name + " with (null buffer, 0) threw exception");
556     }
557     try {
558         array = new type(null, 0, 0);
559         testFailed("Construction of " + name + " with (null buffer, 0, 0) should throw exception");
560     } catch (e) {
561         testPassed("Construction of " + name + " with (null buffer, 0, 0) threw exception");
562     }
563 }
564
565 function testConstructionWithExceptionThrowingObject(type, name) {
566     var o = {};
567     Object.defineProperty(o, "length", { get: function() { throw "bail;" }});
568     try {
569         var array = new type(o);
570     } catch (e) {
571     }
572     testPassed("Construction of " + name + " with exception-throwing array-like object didn't crash unexpectedly");
573 }
574
575 function shouldThrowIndexSizeErr(func, text) {
576     var errorText = text + " should throw an exception";
577     try {
578         func();
579         testFailed(errorText);
580     } catch (e) {
581         testPassed(text + " threw an exception");
582     }
583 }
584
585 function shouldThrowTypeError(func, text) {
586     var ok = false;
587     try {
588         func();
589     } catch (e) {
590         if (e instanceof TypeError) {
591             ok = true;
592         }
593     }
594     if (ok) {
595         testPassed(text + " threw TypeError");
596     } else {
597         testFailed(text + " should throw TypeError");
598     }
599 }
600
601 function testConstructionWithOutOfRangeValues(type, name) {
602     shouldThrowIndexSizeErr(function() {
603         var buffer = new ArrayBuffer(4);
604         var array = new type(buffer, 4, 0x3FFFFFFF);
605     }, "Construction of " + name + " with out-of-range number of elements");
606     shouldThrowIndexSizeErr(function() {
607         var buffer = new ArrayBuffer(4);
608         var array = new type(buffer, 8);
609     }, "Construction of " + name + " with out-of-range offset");
610 }
611
612 function testConstructionWithNegativeOutOfRangeValues(type, name) {
613     try {
614         var buffer = new ArrayBuffer(-1);
615         testFailed("Construction of ArrayBuffer with negative size should throw exception");
616     } catch (e) {
617         testPassed("Construction of ArrayBuffer with negative size threw exception");
618     }
619     try {
620         var array = new type(-1);
621         testFailed("Construction of " + name + " with negative size should throw exception");
622     } catch (e) {
623         testPassed("Construction of " + name + " with negative size threw exception");
624     }
625     shouldThrowIndexSizeErr(function() {
626         var buffer = new ArrayBuffer(4);
627         var array = new type(buffer, 4, -2147483648);
628     }, "Construction of " + name + " with negative out-of-range values");
629 }
630
631 function testConstructionWithUnalignedOffset(type, name, elementSizeInBytes) {
632     if (elementSizeInBytes > 1) {
633         shouldThrowIndexSizeErr(function() {
634             var buffer = new ArrayBuffer(32);
635             var array = new type(buffer, 1, elementSizeInBytes);
636         }, "Construction of " + name + " with unaligned offset");
637     }
638 }
639
640 function testConstructionWithUnalignedLength(type, name, elementSizeInBytes) {
641     if (elementSizeInBytes > 1) {
642         shouldThrowIndexSizeErr(function() {
643             var buffer = new ArrayBuffer(elementSizeInBytes + 1);
644             var array = new type(buffer, 0);
645         }, "Construction of " + name + " with unaligned length");
646     }
647 }
648
649 function testConstructionOfHugeArray(type, name, sz) {
650     if (sz == 1)
651         return;
652     try {
653         // Construction of huge arrays must fail because byteLength is
654         // an unsigned long
655         array = new type(3000000000);
656         testFailed("Construction of huge " + name + " should throw exception");
657     } catch (e) {
658         testPassed("Construction of huge " + name + " threw exception");
659     }
660 }
661
662 function testConstructionWithBothArrayBufferAndLength(type, name, elementSizeInBytes) {
663     var bufByteLength = 1000 * elementSizeInBytes;
664     var buf = new ArrayBuffer(bufByteLength);
665     var array1 = new type(buf);
666     var array2 = new type(bufByteLength / elementSizeInBytes);
667     if (array1.length == array2.length) {
668         testPassed("Array lengths matched with explicit and implicit creation of ArrayBuffer");
669     } else {
670         testFailed("Array lengths DID NOT MATCH with explicit and implicit creation of ArrayBuffer");
671     }
672 }
673
674 function testConstructionWithSubPortionOfArrayBuffer(type, name, elementSizeInBytes) {
675     if (elementSizeInBytes > 1) {
676         // Test construction with a valid sub-portion of an array buffer
677         // (whose size is not an integral multiple of the element size).
678         var size = 4 * elementSizeInBytes + (elementSizeInBytes / 2);
679         var buf = new ArrayBuffer(size);
680         try {
681             var array = new type(buf, 0, 2);
682             testPassed("new " + name + "(new ArrayBuffer(" + size + "), 0, 2) succeeded");
683         } catch (e) {
684             testFailed("new " + name + "(new ArrayBuffer(" + size + "), 0, 2) failed: " + e);
685         }
686     }
687 }
688
689 // These need to be global for shouldBe to see them
690 var array;
691 var typeSize;
692
693 function testSubarrayWithOutOfRangeValues(type, name, sz) {
694     debug("Testing subarray of " + name);
695     try {
696         var buffer = new ArrayBuffer(32);
697         array = new type(buffer);
698         typeSize = sz;
699         shouldBe("array.length", "32 / typeSize");
700         try {
701             shouldBe("array.subarray(4, 0x3FFFFFFF).length", "(32 / typeSize) - 4");
702             shouldBe("array.subarray(4, -2147483648).length", "0");
703             // Test subarray() against overflows.
704             array = array.subarray(2);
705             if (sz > 1) {
706                 // Full byte offset is +1 larger than the maximum unsigned long int.
707                 // Make sure subarray() still handles it correctly.  Otherwise overflow would happen and
708                 // offset would be 0, and array.length array.length would incorrectly be 1.
709                 var start = 4294967296 / sz - 2;
710                 array = array.subarray(start, start + 1);
711                 shouldBe("array.length", "0");
712             }
713         } catch (e) {
714             testFailed("Subarray of " + name + " threw exception");
715         }
716     } catch (e) {
717         testFailed("Exception: " + e);
718     }
719 }
720
721 function testSubarrayWithDefaultValues(type, name, sz) {
722     debug("Testing subarray with default inputs of " + name);
723     try {
724         var buffer = new ArrayBuffer(32);
725         array = new type(buffer);
726         typeSize = sz;
727         shouldBe("array.length", "32 / typeSize");
728         try {
729             shouldBe("array.subarray(0).length", "(32 / typeSize)");
730             shouldBe("array.subarray(2).length", "(32 / typeSize) - 2");
731             shouldBe("array.subarray(-2).length", "2");
732             shouldBe("array.subarray(-2147483648).length", "(32 / typeSize)");
733         } catch (e) {
734             testFailed("Subarray of " + name + " threw exception");
735         }
736     } catch (e) {
737         testFailed("Exception: " + e);
738     }
739 }
740
741 function setWithInvalidOffset(type, name, length,
742                               sourceType, sourceName, sourceLength,
743                               offset, offsetDescription) {
744     var webglArray = new type(length);
745     var sourceArray = new sourceType(sourceLength);
746     for (var i = 0; i < sourceLength; i++)
747         sourceArray[i] = 42 + i;
748     try {
749         webglArray.set(sourceArray, offset);
750         testFailed("Setting " + name + " from " + sourceName + " with " +
751                    offsetDescription + " offset was not caught");
752     } catch (e) {
753         testPassed("Setting " + name + " from " + sourceName + " with " +
754                    offsetDescription + " offset was caught");
755     }
756 }
757
758 function setWithValidOffset(type, name, length,
759                             sourceType, sourceName, sourceLength,
760                             offset, offsetDescription) {
761     running("Setting " + name + " from " + sourceName + " with " +
762             offsetDescription + " offset");
763     var webglArray = new type(length);
764     var sourceArray = new sourceType(sourceLength);
765     for (var i = 0; i < sourceLength; i++)
766         sourceArray[i] = 42 + i;
767     try {
768         webglArray.set(sourceArray, offset);
769         offset = Math.floor(offset);
770         for (var i = 0; i < sourceLength; i++) {
771             assertEq("Element " + i + offset, sourceArray[i], webglArray[i + offset]);
772         }
773         pass();
774     } catch (e) {
775         fail(e);
776     }
777 }
778
779
780 function testSettingFromArrayWithOutOfRangeOffset(type, name) {
781     setWithInvalidOffset(type, name, 32, Array, "array", 16,
782                          0x7FFFFFF8, "out-of-range");
783 }
784
785 function testSettingFromTypedArrayWithOutOfRangeOffset(type, name) {
786     setWithInvalidOffset(type, name, 32, type, name, 16,
787                          0x7FFFFFF8, "out-of-range");
788 }
789
790 function testSettingFromArrayWithNegativeOffset(type, name) {
791     setWithInvalidOffset(type, name, 32, Array, "array", 16,
792                          -1, "negative");
793 }
794
795 function testSettingFromTypedArrayWithNegativeOffset(type, name) {
796     setWithInvalidOffset(type, name, 32, type, name, 16,
797                          -1, "negative");
798 }
799
800 function testSettingFromArrayWithMinusZeroOffset(type, name) {
801     setWithValidOffset(type, name, 32, Array, "array", 16,
802                        -0, "-0");
803 }
804
805 function testSettingFromTypedArrayWithMinusZeroOffset(type, name) {
806     setWithValidOffset(type, name, 32, type, name, 16,
807                        -0, "-0");
808 }
809
810 function testSettingFromArrayWithBoundaryOffset(type, name) {
811     setWithValidOffset(type, name, 32, Array, "array", 16,
812                        16, "boundary");
813 }
814
815 function testSettingFromTypedArrayWithBoundaryOffset(type, name) {
816     setWithValidOffset(type, name, 32, type, name, 16,
817                        16, "boundary");
818 }
819
820 function testSettingFromArrayWithNonIntegerOffset(type, name) {
821     setWithValidOffset(type, name, 32, Array, "array", 16,
822                        16.999, "non-integer");
823 }
824
825 function testSettingFromTypedArrayWithNonIntegerOffset(type, name) {
826     setWithValidOffset(type, name, 32, type, name, 16,
827                        16.999, "non-integer");
828 }
829
830 function testSettingFromFakeArrayWithOutOfRangeLength(type, name) {
831     var webglArray = new type(32);
832     var array = {};
833     array.length = 0x80000000;
834     try {
835         webglArray.set(array, 8);
836         testFailed("Setting " + name + " from fake array with invalid length was not caught");
837     } catch (e) {
838         testPassed("Setting " + name + " from fake array with invalid length was caught");
839     }
840 }
841
842
843 function negativeTestGetAndSetMethods(type, name) {
844     array = new type([2, 3]);
845     shouldBeUndefined("array.get");
846     var exceptionThrown = false;
847     // We deliberately check for an exception here rather than using
848     // shouldThrow here because the precise contents of the syntax
849     // error are not specified.
850     try {
851         webGLArray.set(0, 1);
852     } catch (e) {
853         exceptionThrown = true;
854     }
855     var output = "array.set(0, 1) ";
856     if (exceptionThrown) {
857         testPassed(output + "threw exception.");
858     } else {
859         testFailed(output + "did not throw exception.");
860     }
861 }
862
863 function testNaNConversion(type, name) {
864   running('test storing NaN in ' + name);
865
866   var array = new type([1, 1]);
867   var results = [];
868
869   // The code block in each of the case statements below is identical, but some
870   // JavaScript engines need separate copies in order to exercise all of
871   // their optimized code paths.
872   try {
873     switch (type) {
874     case Float32Array:
875       for (var i = 0; i < array.length; ++i) {
876         array[i] = NaN;
877         results[i] = array[i];
878       }
879       break;
880     case Float64Array:
881       for (var i = 0; i < array.length; ++i) {
882         array[i] = NaN;
883         results[i] = array[i];
884       }
885       break;
886     case Int8Array:
887       for (var i = 0; i < array.length; ++i) {
888         array[i] = NaN;
889         results[i] = array[i];
890       }
891       break;
892     case Int16Array:
893       for (var i = 0; i < array.length; ++i) {
894         array[i] = NaN;
895         results[i] = array[i];
896       }
897       break;
898     case Int32Array:
899       for (var i = 0; i < array.length; ++i) {
900         array[i] = NaN;
901         results[i] = array[i];
902       }
903       break;
904     case Uint8Array:
905       for (var i = 0; i < array.length; ++i) {
906         array[i] = NaN;
907         results[i] = array[i];
908       }
909       break;
910     case Uint8ClampedArray:
911       for (var i = 0; i < array.length; ++i) {
912         array[i] = NaN;
913         results[i] = array[i];
914       }
915       break;
916     case Uint16Array:
917       for (var i = 0; i < array.length; ++i) {
918         array[i] = NaN;
919         results[i] = array[i];
920       }
921       break;
922     case Uint32Array:
923       for (var i = 0; i < array.length; ++i) {
924         array[i] = NaN;
925         results[i] = array[i];
926       }
927       break;
928     default:
929       fail("Unhandled type");
930       break;
931     }
932
933     // Some types preserve NaN values; all other types convert NaN to zero.
934     if (type === Float32Array || type === Float64Array) {
935       assert('initial NaN preserved', isNaN(new type([NaN])[0]));
936       for (var i = 0; i < array.length; ++i)
937         assert('NaN preserved via setter', isNaN(results[i]));
938     } else {
939       assertEq('initial NaN converted to zero', 0, new type([NaN])[0]);
940       for (var i = 0; i < array.length; ++i)
941         assertEq('NaN converted to zero by setter', 0, results[i]);
942     }
943
944     pass();
945   } catch (e) {
946       fail(e);
947   }
948 }
949
950 //
951 // Test driver
952 //
953
954 function runTests() {
955   allPassed = true;
956
957   testSlice();
958   testInheritanceHierarchy();
959
960   for (var i = 0; i < testCases.length; i++) {
961     var testCase = testCases[i];
962     running(testCase.name);
963     if (!(testCase.name in window)) {
964         fail("does not exist");
965         continue;
966     }
967     var type = window[testCase.name];
968     var name = testCase.name;
969     if (testCase.unsigned) {
970       testSetAndGet10To1(type, name);
971       testConstructWithArrayOfUnsignedValues(type, name);
972       testConstructWithTypedArrayOfUnsignedValues(type, name);
973     } else {
974       testSetAndGetPos10ToNeg10(type, name);
975       testConstructWithArrayOfSignedValues(type, name);
976       testConstructWithTypedArrayOfSignedValues(type, name);
977     }
978     if (testCase.integral) {
979       testIntegralArrayTruncationBehavior(type, name, testCase.unsigned);
980     }
981     testGetWithOutOfRangeIndices(type, name);
982     testOffsetsAndSizes(type, name, testCase.elementSizeInBytes);
983     testSetFromTypedArray(type, name);
984     negativeTestSetFromTypedArray(type, name);
985     testSetFromArray(type, name);
986     negativeTestSetFromArray(type, name);
987     testSubarray(type, name);
988     testSubarrayOffsetAndLengthClamping(type, name);
989     negativeTestSubarray(type, name);
990     testSetBoundaryConditions(type,
991                               name,
992                               testCase.testValues,
993                               testCase.expectedValues);
994     testConstructionBoundaryConditions(type,
995                                        name,
996                                        testCase.testValues,
997                                        testCase.expectedValues);
998     testConstructionWithNullBuffer(type, name);
999     testConstructionWithExceptionThrowingObject(type, name);
1000     testConstructionWithOutOfRangeValues(type, name);
1001     testConstructionWithNegativeOutOfRangeValues(type, name);
1002     testConstructionWithUnalignedOffset(type, name, testCase.elementSizeInBytes);
1003     testConstructionWithUnalignedLength(type, name, testCase.elementSizeInBytes);
1004     testConstructionOfHugeArray(type, name, testCase.elementSizeInBytes);
1005     testConstructionWithBothArrayBufferAndLength(type, name, testCase.elementSizeInBytes);
1006     testConstructionWithSubPortionOfArrayBuffer(type, name, testCase.elementSizeInBytes);
1007     testSubarrayWithOutOfRangeValues(type, name, testCase.elementSizeInBytes);
1008     testSubarrayWithDefaultValues(type, name, testCase.elementSizeInBytes);
1009     testSettingFromArrayWithOutOfRangeOffset(type, name);
1010     testSettingFromTypedArrayWithOutOfRangeOffset(type, name);
1011     testSettingFromArrayWithNegativeOffset(type, name);
1012     testSettingFromTypedArrayWithNegativeOffset(type, name);
1013     testSettingFromArrayWithMinusZeroOffset(type, name);
1014     testSettingFromTypedArrayWithMinusZeroOffset(type, name);
1015     testSettingFromArrayWithBoundaryOffset(type, name);
1016     testSettingFromTypedArrayWithBoundaryOffset(type, name);
1017     testSettingFromArrayWithNonIntegerOffset(type, name);
1018     testSettingFromTypedArrayWithNonIntegerOffset(type, name);
1019     testSettingFromFakeArrayWithOutOfRangeLength(type, name);
1020     negativeTestGetAndSetMethods(type, name);
1021     testNaNConversion(type, name);
1022   }
1023
1024   printSummary();
1025 }
1026
1027 runTests();
1028 </script>
1029 </body>
1030 </html>