Chromium Code Reviews| Index: test/mjsunit/array-reduce.js |
| diff --git a/test/mjsunit/array-reduce.js b/test/mjsunit/array-reduce.js |
| new file mode 100755 |
| index 0000000000000000000000000000000000000000..12f060261c9717d8fc3a5a6c8d350aa3530c0e24 |
| --- /dev/null |
| +++ b/test/mjsunit/array-reduce.js |
| @@ -0,0 +1,490 @@ |
| +// Copyright 2009 the V8 project authors. All rights reserved. |
| +// Redistribution and use in source and binary forms, with or without |
| +// modification, are permitted provided that the following conditions are |
| +// met: |
| +// |
| +// * Redistributions of source code must retain the above copyright |
| +// notice, this list of conditions and the following disclaimer. |
| +// * Redistributions in binary form must reproduce the above |
| +// copyright notice, this list of conditions and the following |
| +// disclaimer in the documentation and/or other materials provided |
| +// with the distribution. |
| +// * Neither the name of Google Inc. nor the names of its |
| +// contributors may be used to endorse or promote products derived |
| +// from this software without specific prior written permission. |
| +// |
| +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| + |
| +/** |
| + * @fileoverview Test reduce and reduceRight |
|
Christian Plesner Hansen
2009/04/21 09:39:17
This is an excellent test!
|
| + */ |
| + |
| +function clone(v) { |
| + // Shallow-copies arrays, returns everything else verbatim. |
| + if (v instanceof Array) { |
| + // Shallow-copy an array. |
| + var newArray = new Array(v.length); |
| + for (var i in v) { |
| + newArray[i] = v[i]; |
| + } |
| + return newArray; |
| + } |
| + return v; |
| +} |
| + |
| + |
| +// Creates a callback function for reduce/reduceRight that tests the number |
| +// of arguments and otherwise behaves as "func", but which also |
| +// records all calls in an array on the function (as arrays of arguments |
| +// followed by result). |
| +function makeRecorder(func, testName) { |
| + var record = []; |
| + var f = function recorder(a, b, i, s) { |
| + assertEquals(4, arguments.length, |
| + testName + "(number of arguments: " + arguments.length + ")"); |
| + assertEquals("number", typeof(i), testName + "(index must be number)"); |
| + assertEquals(s[i], b, testName + "(current argument is at index)"); |
| + if (record.length > 0) { |
| + var prevRecord = record[record.length - 1]; |
| + var prevResult = prevRecord[prevRecord.length - 1]; |
| + assertEquals(prevResult, a, |
| + testName + "(prev result -> current input)"); |
| + } |
| + var args = [clone(a), clone(b), i, clone(s)]; |
| + var result = func.apply(this, arguments); |
| + args.push(clone(result)); |
| + record.push(args); |
| + return result; |
| + }; |
| + f.record = record; |
| + return f; |
| +} |
| + |
| + |
| +function testReduce(type, |
| + testName, |
| + expectedResult, |
| + expectedCalls, |
| + array, |
| + combine, |
| + init) { |
| + var rec = makeRecorder(combine); |
| + var result; |
| + var performsCall; |
| + if (arguments.length > 6) { |
| + result = array[type](rec, init); |
| + } else { |
| + result = array[type](rec); |
| + } |
| + var calls = rec.record; |
| + assertEquals(expectedCalls.length, calls.length, |
| + testName + " (number of calls)"); |
| + for (var i = 0; i < expectedCalls.length; i++) { |
| + assertEquals(expectedCalls[i], calls[i], |
| + testName + " (call " + (i + 1) + ")"); |
| + } |
| + assertEquals(expectedResult, result, testName + " (result)"); |
| +} |
| + |
| + |
| +function sum(a, b) { return a + b; } |
| +function prod(a, b) { return a * b; } |
| +function dec(a, b, i, arr) { return a + b * Math.pow(10, arr.length - i - 1); } |
| +function accumulate(acc, elem, i) { acc[i] = elem; return acc; } |
| + |
| +// ---- Test Reduce[Left] |
| + |
| +var simpleArray = [2,4,6] |
| + |
| +testReduce("reduce", "SimpleReduceSum", 12, |
| + [[0, 2, 0, simpleArray, 2], |
| + [2, 4, 1, simpleArray, 6], |
| + [6, 6, 2, simpleArray, 12]], |
| + simpleArray, sum, 0); |
| + |
| +testReduce("reduce", "SimpleReduceProd", 48, |
| + [[1, 2, 0, simpleArray, 2], |
| + [2, 4, 1, simpleArray, 8], |
| + [8, 6, 2, simpleArray, 48]], |
| + simpleArray, prod, 1); |
| + |
| +testReduce("reduce", "SimpleReduceDec", 246, |
| + [[0, 2, 0, simpleArray, 200], |
| + [200, 4, 1, simpleArray, 240], |
| + [240, 6, 2, simpleArray, 246]], |
| + simpleArray, dec, 0); |
| + |
| +testReduce("reduce", "SimpleReduceAccumulate", simpleArray, |
| + [[[], 2, 0, simpleArray, [2]], |
| + [[2], 4, 1, simpleArray, [2, 4]], |
| + [[2,4], 6, 2, simpleArray, simpleArray]], |
| + simpleArray, accumulate, []); |
| + |
| + |
| +testReduce("reduce", "EmptyReduceSum", 0, [], [], sum, 0); |
| +testReduce("reduce", "EmptyReduceProd", 1, [], [], prod, 1); |
| +testReduce("reduce", "EmptyReduceDec", 0, [], [], dec, 0); |
| +testReduce("reduce", "EmptyReduceAccumulate", [], [], [], accumulate, []); |
| + |
| +testReduce("reduce", "EmptyReduceSumNoInit", 0, [], [0], sum); |
| +testReduce("reduce", "EmptyReduceProdNoInit", 1, [], [1], prod); |
| +testReduce("reduce", "EmptyReduceDecNoInit", 0, [], [0], dec); |
| +testReduce("reduce", "EmptyReduceAccumulateNoInit", [], [], [[]], accumulate); |
| + |
| + |
| +var simpleSparseArray = [,,,2,,4,,6,,]; |
| +testReduce("reduce", "SimpleSparseReduceSum", 12, |
| + [[0, 2, 3, simpleSparseArray, 2], |
| + [2, 4, 5, simpleSparseArray, 6], |
| + [6, 6, 7, simpleSparseArray, 12]], |
| + simpleSparseArray, sum, 0); |
| + |
| +testReduce("reduce", "SimpleSparseReduceProd", 48, |
| + [[1, 2, 3, simpleSparseArray, 2], |
| + [2, 4, 5, simpleSparseArray, 8], |
| + [8, 6, 7, simpleSparseArray, 48]], |
| + simpleSparseArray, prod, 1); |
| + |
| +testReduce("reduce", "SimpleSparseReduceDec", 204060, |
| + [[0, 2, 3, simpleSparseArray, 200000], |
| + [200000, 4, 5, simpleSparseArray, 204000], |
| + [204000, 6, 7, simpleSparseArray, 204060]], |
| + simpleSparseArray, dec, 0); |
| + |
| +testReduce("reduce", "SimpleSparseReduceAccumulate", [,,,2,,4,,6], |
| + [[[], 2, 3, simpleSparseArray, [,,,2]], |
| + [[,,,2], 4, 5, simpleSparseArray, [,,,2,,4]], |
| + [[,,,2,,4], 6, 7, simpleSparseArray, [,,,2,,4,,6]]], |
| + simpleSparseArray, accumulate, []); |
| + |
| + |
| +testReduce("reduce", "EmptySparseReduceSumNoInit", 0, [], [,,0,,], sum); |
| +testReduce("reduce", "EmptySparseReduceProdNoInit", 1, [], [,,1,,], prod); |
| +testReduce("reduce", "EmptySparseReduceDecNoInit", 0, [], [,,0,,], dec); |
| +testReduce("reduce", "EmptySparseReduceAccumulateNoInit", |
| + [], [], [,,[],,], accumulate); |
| + |
| + |
| +var verySparseArray = new Array(500000); |
| +verySparseArray[100000] = 2; |
| +verySparseArray[250000] = 4; |
| +verySparseArray[450000] = 6; |
| +var verySparseSlice2 = verySparseArray.slice(0, 100001); |
| +var verySparseSlice4 = verySparseArray.slice(0, 250001); |
| +var verySparseSlice6 = verySparseArray.slice(0, 450001); |
| + |
| +testReduce("reduce", "VerySparseReduceSum", 12, |
| + [[0, 2, 100000, verySparseArray, 2], |
| + [2, 4, 250000, verySparseArray, 6], |
| + [6, 6, 450000, verySparseArray, 12]], |
| + verySparseArray, sum, 0); |
| + |
| +testReduce("reduce", "VerySparseReduceProd", 48, |
| + [[1, 2, 100000, verySparseArray, 2], |
| + [2, 4, 250000, verySparseArray, 8], |
| + [8, 6, 450000, verySparseArray, 48]], |
| + verySparseArray, prod, 1); |
| + |
| +testReduce("reduce", "VerySparseReduceDec", Infinity, |
| + [[0, 2, 100000, verySparseArray, Infinity], |
| + [Infinity, 4, 250000, verySparseArray, Infinity], |
| + [Infinity, 6, 450000, verySparseArray, Infinity]], |
| + verySparseArray, dec, 0); |
| + |
| +testReduce("reduce", "SimpleSparseReduceAccumulate", |
| + verySparseSlice6, |
| + [[[], 2, 100000, verySparseArray, verySparseSlice2], |
| + [verySparseSlice2, 4, 250000, verySparseArray, verySparseSlice4], |
| + [verySparseSlice4, 6, 450000, verySparseArray, verySparseSlice6]], |
| + verySparseArray, accumulate, []); |
| + |
| + |
| +testReduce("reduce", "VerySparseReduceSumNoInit", 12, |
| + [[2, 4, 250000, verySparseArray, 6], |
| + [6, 6, 450000, verySparseArray, 12]], |
| + verySparseArray, sum); |
| + |
| +testReduce("reduce", "VerySparseReduceProdNoInit", 48, |
| + [[2, 4, 250000, verySparseArray, 8], |
| + [8, 6, 450000, verySparseArray, 48]], |
| + verySparseArray, prod); |
| + |
| +testReduce("reduce", "VerySparseReduceDecNoInit", Infinity, |
| + [[2, 4, 250000, verySparseArray, Infinity], |
| + [Infinity, 6, 450000, verySparseArray, Infinity]], |
| + verySparseArray, dec); |
| + |
| +testReduce("reduce", "SimpleSparseReduceAccumulateNoInit", |
| + 2, |
| + [[2, 4, 250000, verySparseArray, 2], |
| + [2, 6, 450000, verySparseArray, 2]], |
| + verySparseArray, accumulate); |
| + |
| + |
| +// ---- Test ReduceRight |
| + |
| +testReduce("reduceRight", "SimpleReduceRightSum", 12, |
| + [[0, 6, 2, simpleArray, 6], |
| + [6, 4, 1, simpleArray, 10], |
| + [10, 2, 0, simpleArray, 12]], |
| + simpleArray, sum, 0); |
| + |
| +testReduce("reduceRight", "SimpleReduceRightProd", 48, |
| + [[1, 6, 2, simpleArray, 6], |
| + [6, 4, 1, simpleArray, 24], |
| + [24, 2, 0, simpleArray, 48]], |
| + simpleArray, prod, 1); |
| + |
| +testReduce("reduceRight", "SimpleReduceRightDec", 246, |
| + [[0, 6, 2, simpleArray, 6], |
| + [6, 4, 1, simpleArray, 46], |
| + [46, 2, 0, simpleArray, 246]], |
| + simpleArray, dec, 0); |
| + |
| +testReduce("reduceRight", "SimpleReduceRightAccumulate", simpleArray, |
| + [[[], 6, 2, simpleArray, [,,6]], |
| + [[,,6], 4, 1, simpleArray, [,4,6]], |
| + [[,4,6], 2, 0, simpleArray, simpleArray]], |
| + simpleArray, accumulate, []); |
| + |
| + |
| +testReduce("reduceRight", "EmptyReduceRightSum", 0, [], [], sum, 0); |
| +testReduce("reduceRight", "EmptyReduceRightProd", 1, [], [], prod, 1); |
| +testReduce("reduceRight", "EmptyReduceRightDec", 0, [], [], dec, 0); |
| +testReduce("reduceRight", "EmptyReduceRightAccumulate", [], |
| + [], [], accumulate, []); |
| + |
| +testReduce("reduceRight", "EmptyReduceRightSumNoInit", 0, [], [0], sum); |
| +testReduce("reduceRight", "EmptyReduceRightProdNoInit", 1, [], [1], prod); |
| +testReduce("reduceRight", "EmptyReduceRightDecNoInit", 0, [], [0], dec); |
| +testReduce("reduceRight", "EmptyReduceRightAccumulateNoInit", |
| + [], [], [[]], accumulate); |
| + |
| + |
| +testReduce("reduceRight", "SimpleSparseReduceRightSum", 12, |
| + [[0, 6, 7, simpleSparseArray, 6], |
| + [6, 4, 5, simpleSparseArray, 10], |
| + [10, 2, 3, simpleSparseArray, 12]], |
| + simpleSparseArray, sum, 0); |
| + |
| +testReduce("reduceRight", "SimpleSparseReduceRightProd", 48, |
| + [[1, 6, 7, simpleSparseArray, 6], |
| + [6, 4, 5, simpleSparseArray, 24], |
| + [24, 2, 3, simpleSparseArray, 48]], |
| + simpleSparseArray, prod, 1); |
| + |
| +testReduce("reduceRight", "SimpleSparseReduceRightDec", 204060, |
| + [[0, 6, 7, simpleSparseArray, 60], |
| + [60, 4, 5, simpleSparseArray, 4060], |
| + [4060, 2, 3, simpleSparseArray, 204060]], |
| + simpleSparseArray, dec, 0); |
| + |
| +testReduce("reduceRight", "SimpleSparseReduceRightAccumulate", [,,,2,,4,,6], |
| + [[[], 6, 7, simpleSparseArray, [,,,,,,,6]], |
| + [[,,,,,,,6], 4, 5, simpleSparseArray, [,,,,,4,,6]], |
| + [[,,,,,4,,6], 2, 3, simpleSparseArray, [,,,2,,4,,6]]], |
| + simpleSparseArray, accumulate, []); |
| + |
| + |
| +testReduce("reduceRight", "EmptySparseReduceRightSumNoInit", |
| + 0, [], [,,0,,], sum); |
| +testReduce("reduceRight", "EmptySparseReduceRightProdNoInit", |
| + 1, [], [,,1,,], prod); |
| +testReduce("reduceRight", "EmptySparseReduceRightDecNoInit", |
| + 0, [], [,,0,,], dec); |
| +testReduce("reduceRight", "EmptySparseReduceRightAccumulateNoInit", |
| + [], [], [,,[],,], accumulate); |
| + |
| + |
| +var verySparseSuffix6 = new Array(450001); |
| +verySparseSuffix6[450000] = 6; |
| +var verySparseSuffix4 = new Array(450001); |
| +verySparseSuffix4[250000] = 4; |
| +verySparseSuffix4[450000] = 6; |
| +var verySparseSuffix2 = verySparseSlice6; |
| + |
| + |
| +testReduce("reduceRight", "VerySparseReduceRightSum", 12, |
| + [[0, 6, 450000, verySparseArray, 6], |
| + [6, 4, 250000, verySparseArray, 10], |
| + [10, 2, 100000, verySparseArray, 12]], |
| + verySparseArray, sum, 0); |
| + |
| +testReduce("reduceRight", "VerySparseReduceRightProd", 48, |
| + [[1, 6, 450000, verySparseArray, 6], |
| + [6, 4, 250000, verySparseArray, 24], |
| + [24, 2, 100000, verySparseArray, 48]], |
| + verySparseArray, prod, 1); |
| + |
| +testReduce("reduceRight", "VerySparseReduceRightDec", Infinity, |
| + [[0, 6, 450000, verySparseArray, Infinity], |
| + [Infinity, 4, 250000, verySparseArray, Infinity], |
| + [Infinity, 2, 100000, verySparseArray, Infinity]], |
| + verySparseArray, dec, 0); |
| + |
| +testReduce("reduceRight", "SimpleSparseReduceRightAccumulate", |
| + verySparseSuffix2, |
| + [[[], 6, 450000, verySparseArray, verySparseSuffix6], |
| + [verySparseSuffix6, 4, 250000, verySparseArray, verySparseSuffix4], |
| + [verySparseSuffix4, 2, 100000, verySparseArray, verySparseSuffix2]], |
| + verySparseArray, accumulate, []); |
| + |
| + |
| +testReduce("reduceRight", "VerySparseReduceRightSumNoInit", 12, |
| + [[6, 4, 250000, verySparseArray, 10], |
| + [10, 2, 100000, verySparseArray, 12]], |
| + verySparseArray, sum); |
| + |
| +testReduce("reduceRight", "VerySparseReduceRightProdNoInit", 48, |
| + [[6, 4, 250000, verySparseArray, 24], |
| + [24, 2, 100000, verySparseArray, 48]], |
| + verySparseArray, prod); |
| + |
| +testReduce("reduceRight", "VerySparseReduceRightDecNoInit", Infinity, |
| + [[6, 4, 250000, verySparseArray, Infinity], |
| + [Infinity, 2, 100000, verySparseArray, Infinity]], |
| + verySparseArray, dec); |
| + |
| +testReduce("reduceRight", "SimpleSparseReduceRightAccumulateNoInit", |
| + 6, |
| + [[6, 4, 250000, verySparseArray, 6], |
| + [6, 2, 100000, verySparseArray, 6]], |
| + verySparseArray, accumulate); |
| + |
| + |
| +// undefined is an element |
| +var undefArray = [,,undefined,,undefined,,]; |
| + |
| +testReduce("reduce", "SparseUndefinedReduceAdd", NaN, |
| + [[0, undefined, 2, undefArray, NaN], |
| + [NaN, undefined, 4, undefArray, NaN], |
| + ], |
| + undefArray, sum, 0); |
| + |
| +testReduce("reduceRight", "SparseUndefinedReduceRightAdd", NaN, |
| + [[0, undefined, 4, undefArray, NaN], |
| + [NaN, undefined, 2, undefArray, NaN], |
| + ], undefArray, sum, 0); |
| + |
| +testReduce("reduce", "SparseUndefinedReduceAddNoInit", NaN, |
| + [[undefined, undefined, 4, undefArray, NaN], |
| + ], undefArray, sum); |
| + |
| +testReduce("reduceRight", "SparseUndefinedReduceRightAddNoInit", NaN, |
| + [[undefined, undefined, 2, undefArray, NaN], |
| + ], undefArray, sum); |
| + |
| + |
| +// Test error conditions |
| + |
| +try { |
| + [1].reduce("not a function"); |
| + fail("Reduce callback not a function not throwing"); |
| +} catch (e) { |
| + assertTrue(e instanceof TypeError, |
| + "reduce callback not a function not throwing TypeError"); |
| + assertEquals("called_non_callable", e.type, |
| + "reduce non function TypeError type"); |
| +} |
| + |
| +try { |
| + [1].reduceRight("not a function"); |
| + fail("ReduceRight callback not a function not throwing"); |
| +} catch (e) { |
| + assertTrue(e instanceof TypeError, |
| + "reduceRight callback not a function not throwing TypeError"); |
| + assertEquals("called_non_callable", e.type, |
| + "reduceRight non function TypeError type"); |
| +} |
| + |
| + |
| +try { |
| + [].reduce(sum); |
| + fail("Reduce no initial value not throwing"); |
| +} catch (e) { |
| + assertTrue(e instanceof TypeError, |
| + "reduce no initial value not throwing TypeError"); |
| + assertEquals("reduce_no_initial", e.type, |
| + "reduce no initial TypeError type"); |
| +} |
| + |
| +try { |
| + [].reduceRight(sum); |
| + fail("ReduceRight no initial value not throwing"); |
| +} catch (e) { |
| + assertTrue(e instanceof TypeError, |
| + "reduceRight no initial value not throwing TypeError"); |
| + assertEquals("reduce_no_initial", e.type, |
| + "reduceRight no initial TypeError type"); |
| +} |
| + |
| +try { |
| + [,,,].reduce(sum); |
| + fail("Reduce sparse no initial value not throwing"); |
| +} catch (e) { |
| + assertTrue(e instanceof TypeError, |
| + "reduce sparse no initial value not throwing TypeError"); |
| + assertEquals("reduce_no_initial", e.type, |
| + "reduce no initial TypeError type"); |
| + |
| +} |
| + |
| +try { |
| + [,,,].reduceRight(sum); |
| + fail("ReduceRight sparse no initial value not throwing"); |
| +} catch (e) { |
| + assertTrue(e instanceof TypeError, |
| + "reduceRight sparse no initial value not throwing TypeError"); |
| + assertEquals("reduce_no_initial", e.type, |
| + "reduceRight no initial TypeError type"); |
| +} |
| + |
| + |
| +// Array changing length |
| + |
| +function manipulator(a, b, i, s) { |
| + if (s.length % 2) { |
| + s[s.length * 3] = i; |
| + } else { |
| + s.length = s.length >> 1; |
| + } |
| + return a + b; |
| +} |
| + |
| +var arr = [1, 2, 3, 4]; |
| +testReduce("reduce", "ArrayManipulationShort", 3, |
| + [[0, 1, 0, [1, 2, 3, 4], 1], |
| + [1, 2, 1, [1, 2], 3], |
| + ], arr, manipulator, 0); |
| + |
| +var arr = [1, 2, 3, 4, 5]; |
| +testReduce("reduce", "ArrayManipulationLonger", 10, |
| + [[0, 1, 0, [1, 2, 3, 4, 5], 1], |
| + [1, 2, 1, [1, 2, 3, 4, 5,,,,,,,,,,, 0], 3], |
| + [3, 3, 2, [1, 2, 3, 4, 5,,,,], 6], |
| + [6, 4, 3, [1, 2, 3, 4], 10], |
| + ], arr, manipulator, 0); |
| + |
| +function extender(a, b, i, s) { |
| + s[s.length] = s.length; |
| + return a + b; |
| +} |
| + |
| +var arr = [1, 2, 3, 4]; |
| +testReduce("reduce", "ArrayManipulationExtender", 10, |
| + [[0, 1, 0, [1, 2, 3, 4], 1], |
| + [1, 2, 1, [1, 2, 3, 4, 4], 3], |
| + [3, 3, 2, [1, 2, 3, 4, 4, 5], 6], |
| + [6, 4, 3, [1, 2, 3, 4, 4, 5, 6], 10], |
| + ], arr, extender, 0); |
| + |