1// Copyright 2013 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28// These tests are adapted from Khronos DataView tests
29
30var intArray1 =
31  [0, 1, 2, 3, 100, 101, 102, 103, 128, 129, 130, 131, 252, 253, 254, 255];
32var intArray2 =
33  [31, 32, 33, 0, 1, 2, 3, 100, 101, 102, 103, 128, 129, 130, 131, 252,
34    253, 254, 255];
35var initialArray =
36  [204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
37    204, 204, 204];
38
39var arayBuffer = null;
40var view = null;
41var viewStart = 0;
42var viewLength = 0;
43
44function getElementSize(func) {
45  switch (func) {
46    case "Int8":
47    case "Uint8":
48      return 1;
49    case "Int16":
50    case "Uint16":
51      return 2;
52    case "Int32":
53    case "Uint32":
54    case "Float32":
55      return 4;
56    case "Float64":
57      return 8;
58    default:
59      assertUnreachable(func);
60  }
61}
62
63function checkGet(func, index, expected, littleEndian) {
64  function doGet() {
65    if (littleEndian != undefined)
66      return view["get" + func](index, littleEndian);
67    else
68      return view["get" + func](index);
69  }
70  if (index >=0 && index + getElementSize(func) - 1 < view.byteLength)
71      assertSame(expected, doGet());
72  else
73      assertThrows(doGet, RangeError);
74}
75
76function checkSet(func, index, value, littleEndian) {
77  function doSet() {
78    if (littleEndian != undefined)
79      view["set" + func](index, value, littleEndian);
80    else
81      view["set" + func](index, value);
82  }
83  if (index >= 0 &&
84      index + getElementSize(func) - 1 < view.byteLength) {
85    assertSame(undefined, doSet());
86    checkGet(func, index, value, littleEndian);
87  } else {
88    assertThrows(doSet, RangeError);
89  }
90}
91
92function test(isTestingGet, func, index, value, littleEndian) {
93  if (isTestingGet)
94    checkGet(func, index, value, littleEndian);
95  else
96    checkSet(func, index, value, littleEndian);
97}
98
99function createDataView(
100    array, frontPaddingNum, littleEndian, start, length) {
101  if (!littleEndian)
102    array.reverse();
103  var paddingArray = new Array(frontPaddingNum);
104  arrayBuffer = (new Uint8Array(paddingArray.concat(array))).buffer;
105  view = new DataView(arrayBuffer, viewStart, viewLength);
106  if (!littleEndian)
107    array.reverse(); // restore the array.
108}
109
110function runIntegerTestCases(isTestingGet, array, start, length) {
111  createDataView(array, 0, true, start, length);
112
113  test(isTestingGet, "Int8", 0, 0);
114  test(isTestingGet, "Int8", undefined, 0);
115  test(isTestingGet, "Int8", 8, -128);
116  test(isTestingGet, "Int8", 15, -1);
117  test(isTestingGet, "Int8", 1e12, undefined);
118
119  test(isTestingGet, "Uint8", 0, 0);
120  test(isTestingGet, "Uint8", undefined, 0);
121  test(isTestingGet, "Uint8", 8, 128);
122  test(isTestingGet, "Uint8", 15, 255);
123  test(isTestingGet, "Uint8", 1e12, undefined);
124
125  // Little endian.
126  test(isTestingGet, "Int16", 0, 256, true);
127  test(isTestingGet, "Int16", undefined, 256, true);
128  test(isTestingGet, "Int16", 5, 26213, true);
129  test(isTestingGet, "Int16", 9, -32127, true);
130  test(isTestingGet, "Int16", 14, -2, true);
131  test(isTestingGet, "Int16", 1e12, undefined, true);
132
133  // Big endian.
134  test(isTestingGet, "Int16", 0, 1);
135  test(isTestingGet, "Int16", undefined, 1);
136  test(isTestingGet, "Int16", 5, 25958);
137  test(isTestingGet, "Int16", 9, -32382);
138  test(isTestingGet, "Int16", 14, -257);
139  test(isTestingGet, "Int16", 1e12, undefined);
140
141  // Little endian.
142  test(isTestingGet, "Uint16", 0, 256, true);
143  test(isTestingGet, "Uint16", undefined, 256, true);
144  test(isTestingGet, "Uint16", 5, 26213, true);
145  test(isTestingGet, "Uint16", 9, 33409, true);
146  test(isTestingGet, "Uint16", 14, 65534, true);
147  test(isTestingGet, "Uint16", 1e12, undefined, true);
148
149  // Big endian.
150  test(isTestingGet, "Uint16", 0, 1);
151  test(isTestingGet, "Uint16", undefined, 1);
152  test(isTestingGet, "Uint16", 5, 25958);
153  test(isTestingGet, "Uint16", 9, 33154);
154  test(isTestingGet, "Uint16", 14, 65279);
155  test(isTestingGet, "Uint16", 1e12, undefined);
156
157  // Little endian.
158  test(isTestingGet, "Int32", 0, 50462976, true);
159  test(isTestingGet, "Int32", undefined, 50462976, true);
160  test(isTestingGet, "Int32", 3, 1717920771, true);
161  test(isTestingGet, "Int32", 6, -2122291354, true);
162  test(isTestingGet, "Int32", 9, -58490239, true);
163  test(isTestingGet, "Int32", 12,-66052, true);
164  test(isTestingGet, "Int32", 1e12, undefined, true);
165
166  // Big endian.
167  test(isTestingGet, "Int32", 0, 66051);
168  test(isTestingGet, "Int32", undefined, 66051);
169  test(isTestingGet, "Int32", 3, 56911206);
170  test(isTestingGet, "Int32", 6, 1718059137);
171  test(isTestingGet, "Int32", 9, -2122152964);
172  test(isTestingGet, "Int32", 12, -50462977);
173  test(isTestingGet, "Int32", 1e12, undefined);
174
175  // Little endian.
176  test(isTestingGet, "Uint32", 0, 50462976, true);
177  test(isTestingGet, "Uint32", undefined, 50462976, true);
178  test(isTestingGet, "Uint32", 3, 1717920771, true);
179  test(isTestingGet, "Uint32", 6, 2172675942, true);
180  test(isTestingGet, "Uint32", 9, 4236477057, true);
181  test(isTestingGet, "Uint32", 12,4294901244, true);
182  test(isTestingGet, "Uint32", 1e12, undefined, true);
183
184  // Big endian.
185  test(isTestingGet, "Uint32", 0, 66051);
186  test(isTestingGet, "Uint32", undefined, 66051);
187  test(isTestingGet, "Uint32", 3, 56911206);
188  test(isTestingGet, "Uint32", 6, 1718059137);
189  test(isTestingGet, "Uint32", 9, 2172814332);
190  test(isTestingGet, "Uint32", 12, 4244504319);
191  test(isTestingGet, "Uint32", 1e12, undefined);
192}
193
194function testFloat(isTestingGet, func, array, start, expected) {
195  // Little endian.
196  createDataView(array, 0, true, start);
197  test(isTestingGet, func, 0, expected, true);
198  test(isTestingGet, func, undefined, expected, true);
199  createDataView(array, 3, true, start);
200  test(isTestingGet, func, 3, expected, true);
201  createDataView(array, 7, true, start);
202  test(isTestingGet, func, 7, expected, true);
203  createDataView(array, 10, true, start);
204  test(isTestingGet, func, 10, expected, true);
205  test(isTestingGet, func, 1e12, undefined, true);
206
207  // Big endian.
208  createDataView(array, 0, false);
209  test(isTestingGet, func, 0, expected, false);
210  test(isTestingGet, func, undefined, expected, false);
211  createDataView(array, 3, false);
212  test(isTestingGet, func, 3, expected, false);
213  createDataView(array, 7, false);
214  test(isTestingGet, func, 7, expected, false);
215  createDataView(array, 10, false);
216  test(isTestingGet, func, 10, expected, false);
217  test(isTestingGet, func, 1e12, undefined, false);
218}
219
220function runFloatTestCases(isTestingGet, start) {
221  testFloat(isTestingGet, "Float32",
222    isTestingGet ? [0, 0, 32, 65] : initialArray, start, 10);
223
224  testFloat(isTestingGet, "Float32",
225    isTestingGet ? [164, 112, 157, 63] : initialArray,
226      start, 1.2300000190734863);
227  testFloat(isTestingGet, "Float32",
228    isTestingGet ? [95, 53, 50, 199] : initialArray,
229    start, -45621.37109375);
230  testFloat(isTestingGet, "Float32",
231    isTestingGet ? [255, 255, 255, 127] : initialArray,
232    start, NaN);
233  testFloat(isTestingGet, "Float32",
234    isTestingGet ? [255, 255, 255, 255] : initialArray,
235    start, -NaN);
236
237  testFloat(isTestingGet, "Float64",
238    isTestingGet ? [0, 0, 0, 0, 0, 0, 36, 64] : initialArray,
239    start, 10);
240  testFloat(isTestingGet, "Float64",
241    isTestingGet ? [174, 71, 225, 122, 20, 174, 243, 63] : initialArray,
242    start, 1.23);
243  testFloat(isTestingGet, "Float64",
244    isTestingGet ? [181, 55, 248, 30, 242, 179, 87, 193] : initialArray,
245    start, -6213576.4839);
246  testFloat(isTestingGet, "Float64",
247    isTestingGet ? [255, 255, 255, 255, 255, 255, 255, 127] : initialArray,
248    start, NaN);
249  testFloat(isTestingGet, "Float64",
250    isTestingGet ? [255, 255, 255, 255, 255, 255, 255, 255] : initialArray,
251    start, -NaN);
252}
253
254function runNegativeIndexTests(isTestingGet) {
255  createDataView(intArray1, 0, true, 0, 16);
256
257  test(isTestingGet, "Int8", -1, 0);
258  test(isTestingGet, "Int8", -2, 0);
259
260  test(isTestingGet, "Uint8", -1, 0);
261  test(isTestingGet, "Uint8", -2, 0);
262
263  test(isTestingGet, "Int16", -1, 1);
264  test(isTestingGet, "Int16", -2, 1);
265  test(isTestingGet, "Int16", -3, 1);
266
267  test(isTestingGet, "Uint16", -1, 1);
268  test(isTestingGet, "Uint16", -2, 1);
269  test(isTestingGet, "Uint16", -3, 1);
270
271  test(isTestingGet, "Int32", -1, 66051);
272  test(isTestingGet, "Int32", -3, 66051);
273  test(isTestingGet, "Int32", -5, 66051);
274
275  test(isTestingGet, "Uint32", -1, 66051);
276  test(isTestingGet, "Uint32", -3, 66051);
277  test(isTestingGet, "Uint32", -5, 66051);
278
279  createDataView([0, 0, 0, 0, 0, 0, 0, 0], 0, true, 0, 8);
280
281  test(isTestingGet, "Float32", -1, 0);
282  test(isTestingGet, "Float32", -3, 0);
283  test(isTestingGet, "Float32", -5, 0);
284
285  test(isTestingGet, "Float64", -1, 0);
286  test(isTestingGet, "Float64", -5, 0);
287  test(isTestingGet, "Float64", -9, 0);
288}
289
290
291function TestGetters() {
292  runIntegerTestCases(true, intArray1, 0, 16);
293  runFloatTestCases(true, 0);
294
295  runIntegerTestCases(true, intArray2, 3, 2);
296  runFloatTestCases(true, 3);
297
298  runNegativeIndexTests(true);
299}
300
301function TestSetters() {
302  runIntegerTestCases(false, initialArray, 0, 16);
303  runFloatTestCases(false);
304
305  runIntegerTestCases(false, initialArray, 3, 2);
306  runFloatTestCases(false, 7);
307
308  runNegativeIndexTests(false);
309}
310
311TestGetters();
312TestSetters();
313
314function CheckOutOfRangeInt8(value, expected) {
315  var view = new DataView(new ArrayBuffer(100));
316  assertSame(undefined, view.setInt8(0, value));
317  assertSame(expected, view.getInt8(0));
318  assertSame(undefined, view.setInt8(0, value, true));
319  assertSame(expected, view.getInt8(0, true));
320}
321
322function CheckOutOfRangeUint8(value, expected) {
323  var view = new DataView(new ArrayBuffer(100));
324  assertSame(undefined, view.setUint8(0, value));
325  assertSame(expected, view.getUint8(0));
326  assertSame(undefined, view.setUint8(0, value, true));
327  assertSame(expected, view.getUint8(0, true));
328}
329
330function CheckOutOfRangeInt16(value, expected) {
331  var view = new DataView(new ArrayBuffer(100));
332  assertSame(undefined, view.setInt16(0, value));
333  assertSame(expected, view.getInt16(0));
334  assertSame(undefined, view.setInt16(0, value, true));
335  assertSame(expected, view.getInt16(0, true));
336}
337
338function CheckOutOfRangeUint16(value, expected) {
339  var view = new DataView(new ArrayBuffer(100));
340  assertSame(undefined, view.setUint16(0, value));
341  assertSame(expected, view.getUint16(0));
342  assertSame(undefined, view.setUint16(0, value, true));
343  assertSame(expected, view.getUint16(0, true));
344}
345
346function CheckOutOfRangeInt32(value, expected) {
347  var view = new DataView(new ArrayBuffer(100));
348  assertSame(undefined, view.setInt32(0, value));
349  assertSame(expected, view.getInt32(0));
350  assertSame(undefined, view.setInt32(0, value, true));
351  assertSame(expected, view.getInt32(0, true));
352}
353
354function CheckOutOfRangeUint32(value, expected) {
355  var view = new DataView(new ArrayBuffer(100));
356  assertSame(undefined, view.setUint32(0, value));
357  assertSame(expected, view.getUint32(0));
358  assertSame(undefined, view.setUint32(0, value, true));
359  assertSame(expected, view.getUint32(0, true));
360}
361
362function TestOutOfRange() {
363  CheckOutOfRangeInt8(0x80,   -0x80);
364  CheckOutOfRangeInt8(0x1000, 0);
365  CheckOutOfRangeInt8(-0x81,  0x7F);
366
367  CheckOutOfRangeUint8(0x100,  0);
368  CheckOutOfRangeUint8(0x1000, 0);
369  CheckOutOfRangeUint8(-0x80,  0x80);
370  CheckOutOfRangeUint8(-1,     0xFF);
371  CheckOutOfRangeUint8(-0xFF,  1);
372
373  CheckOutOfRangeInt16(0x8000,  -0x8000);
374  CheckOutOfRangeInt16(0x10000, 0);
375  CheckOutOfRangeInt16(-0x8001, 0x7FFF);
376
377  CheckOutOfRangeUint16(0x10000,  0);
378  CheckOutOfRangeUint16(0x100000, 0);
379  CheckOutOfRangeUint16(-0x8000,  0x8000);
380  CheckOutOfRangeUint16(-1,       0xFFFF);
381  CheckOutOfRangeUint16(-0xFFFF,  1);
382
383  CheckOutOfRangeInt32(0x80000000,  -0x80000000);
384  CheckOutOfRangeInt32(0x100000000, 0);
385  CheckOutOfRangeInt32(-0x80000001, 0x7FFFFFFF);
386
387  CheckOutOfRangeUint32(0x100000000,  0);
388  CheckOutOfRangeUint32(0x1000000000, 0);
389  CheckOutOfRangeUint32(-0x80000000,  0x80000000);
390  CheckOutOfRangeUint32(-1,           0xFFFFFFFF);
391  CheckOutOfRangeUint32(-0xFFFFFFFF,  1);
392}
393
394TestOutOfRange();
395
396function TestGeneralAccessors() {
397  var a = new DataView(new ArrayBuffer(256));
398  function CheckAccessor(name) {
399    var f = a[name];
400    assertThrows(function() { f(); }, TypeError);
401    f.call(a, 0, 0); // should not throw
402    assertThrows(function() { f.call({}, 0, 0); }, TypeError);
403    assertThrows(function() { f.call(a); }, TypeError);
404    if (name.indexOf("set") == 0) {
405      assertThrows(function() { f.call(a, 1); }, TypeError);
406    } else {
407      f.call(a, 1); // should not throw
408    }
409  }
410  CheckAccessor("getUint8");
411  CheckAccessor("setUint8");
412  CheckAccessor("getInt8");
413  CheckAccessor("setInt8");
414  CheckAccessor("getUint16");
415  CheckAccessor("setUint16");
416  CheckAccessor("getInt16");
417  CheckAccessor("setInt16");
418  CheckAccessor("getUint32");
419  CheckAccessor("setUint32");
420  CheckAccessor("getInt32");
421  CheckAccessor("setInt32");
422  CheckAccessor("getFloat32");
423  CheckAccessor("setFloat32");
424  CheckAccessor("getFloat64");
425  CheckAccessor("setFloat64");
426}
427
428TestGeneralAccessors();
429
430function TestInsufficientArguments() {
431  var a = new DataView(new ArrayBuffer(256));
432
433  assertThrows(function() { a.getUint8(); }, TypeError);
434  assertThrows(function() { a.getInt8(); }, TypeError);
435  assertThrows(function() { a.getUint16(); }, TypeError);
436  assertThrows(function() { a.getInt16(); }, TypeError);
437  assertThrows(function() { a.getUint32(); }, TypeError);
438  assertThrows(function() { a.getInt32(); }, TypeError);
439  assertThrows(function() { a.getFloat32(); }, TypeError);
440  assertThrows(function() { a.getFloat64(); }, TypeError);
441
442  assertThrows(function() { a.setUint8(); }, TypeError);
443  assertThrows(function() { a.setInt8(); }, TypeError);
444  assertThrows(function() { a.setUint16(); }, TypeError);
445  assertThrows(function() { a.setInt16(); }, TypeError);
446  assertThrows(function() { a.setUint32(); }, TypeError);
447  assertThrows(function() { a.setInt32(); }, TypeError);
448  assertThrows(function() { a.setFloat32(); }, TypeError);
449  assertThrows(function() { a.setFloat64(); }, TypeError);
450
451  assertThrows(function() { a.setUint8(1) }, TypeError);
452  assertThrows(function() { a.setInt8(1) }, TypeError);
453  assertThrows(function() { a.setUint16(1) }, TypeError);
454  assertThrows(function() { a.setInt16(1) }, TypeError);
455  assertThrows(function() { a.setUint32(1) }, TypeError);
456  assertThrows(function() { a.setInt32(1) }, TypeError);
457  assertThrows(function() { a.setFloat32(1) }, TypeError);
458  assertThrows(function() { a.setFloat64(1) }, TypeError);
459}
460
461TestInsufficientArguments();
462