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