Merge
authorduke
Wed, 05 Jul 2017 22:22:00 +0200
changeset 41621 a2955679af89
parent 41620 4519c4ace34d (diff)
parent 41613 5ce3497bec41 (current diff)
child 41624 162d24f819a8
Merge
jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetAccess.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/Jlink.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/JlinkPermission.java
jdk/test/sun/net/www/protocol/https/HttpsClient/OriginServer.java
jdk/test/sun/reflect/ReflectionFactory/NewConstructorForSerialization.java
jdk/test/sun/security/tools/jarsigner/ts.sh
--- a/nashorn/.hgtags	Wed Jul 05 22:21:51 2017 +0200
+++ b/nashorn/.hgtags	Wed Jul 05 22:22:00 2017 +0200
@@ -374,3 +374,4 @@
 4a6ee1185fc821df063e4d1537fa7ad2ebe9eb02 jdk-9+138
 e3b11296395b39bfeb3364f26c2ef77fa652e300 jdk-9+139
 785843878cf78d50cc2959ea2c5a4202bbe885b4 jdk-9+140
+a46b7d3867957a868a6cc8ee66c05079b883733a jdk-9+141
--- a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Console.java	Wed Jul 05 22:21:51 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Console.java	Wed Jul 05 22:22:00 2017 +0200
@@ -42,6 +42,8 @@
 import jdk.internal.jline.console.ConsoleReader;
 import jdk.internal.jline.console.KeyMap;
 import jdk.internal.jline.extra.EditingHistory;
+import jdk.internal.misc.Signal;
+import jdk.internal.misc.Signal.Handler;
 
 class Console implements AutoCloseable {
     private static final String DOCUMENTATION_SHORTCUT = "\033\133\132"; //Shift-TAB
@@ -68,6 +70,21 @@
         in.addCompleter(completer);
         Runtime.getRuntime().addShutdownHook(new Thread((Runnable)this::saveHistory));
         bind(DOCUMENTATION_SHORTCUT, (ActionListener)evt -> showDocumentation(docHelper));
+        try {
+            Signal.handle(new Signal("CONT"), new Handler() {
+                @Override public void handle(Signal sig) {
+                    try {
+                        in.getTerminal().reset();
+                        in.redrawLine();
+                        in.flush();
+                    } catch (Exception ex) {
+                        ex.printStackTrace();
+                    }
+                }
+            });
+        } catch (IllegalArgumentException ignored) {
+            //the CONT signal does not exist on this platform
+        }
     }
 
     String readLine(final String prompt) throws IOException {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java	Wed Jul 05 22:21:51 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java	Wed Jul 05 22:22:00 2017 +0200
@@ -129,10 +129,11 @@
 
     @Override
     public String getProgram(final String... statements) {
+        Objects.requireNonNull(statements);
         final StringBuilder sb = new StringBuilder();
 
         for (final String statement : statements) {
-            sb.append(statement).append(';');
+            sb.append(Objects.requireNonNull(statement)).append(';');
         }
 
         return sb.toString();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayIterator.java	Wed Jul 05 22:21:51 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayIterator.java	Wed Jul 05 22:22:00 2017 +0200
@@ -47,13 +47,25 @@
     private final Global global;
 
 
-    ArrayIterator(final Object iteratedObject, final IterationKind iterationKind, final Global global) {
+    private ArrayIterator(final Object iteratedObject, final IterationKind iterationKind, final Global global) {
         super(global.getArrayIteratorPrototype(), $nasgenmap$);
         this.iteratedObject = iteratedObject instanceof ScriptObject ? (ScriptObject) iteratedObject : null;
         this.iterationKind = iterationKind;
         this.global = global;
     }
 
+    static ArrayIterator newArrayValueIterator(final Object iteratedObject) {
+        return new ArrayIterator(Global.toObject(iteratedObject), IterationKind.VALUE, Global.instance());
+    }
+
+    static ArrayIterator newArrayKeyIterator(final Object iteratedObject) {
+        return new ArrayIterator(Global.toObject(iteratedObject), IterationKind.KEY, Global.instance());
+    }
+
+    static ArrayIterator newArrayKeyValueIterator(final Object iteratedObject) {
+        return new ArrayIterator(Global.toObject(iteratedObject), IterationKind.KEY_VALUE, Global.instance());
+    }
+
     /**
      * 22.1.5.2.1 %ArrayIteratorPrototype%.next()
      *
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java	Wed Jul 05 22:21:51 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java	Wed Jul 05 22:22:00 2017 +0200
@@ -1726,7 +1726,7 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static Object entries(final Object self) {
-        return new ArrayIterator(Global.toObject(self), AbstractIterator.IterationKind.KEY_VALUE, Global.instance());
+        return ArrayIterator.newArrayKeyValueIterator(self);
     }
 
     /**
@@ -1737,7 +1737,7 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static Object keys(final Object self) {
-        return new ArrayIterator(Global.toObject(self), AbstractIterator.IterationKind.KEY, Global.instance());
+        return ArrayIterator.newArrayKeyIterator(self);
     }
 
     /**
@@ -1748,7 +1748,7 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static Object values(final Object self) {
-        return new ArrayIterator(Global.toObject(self), AbstractIterator.IterationKind.VALUE, Global.instance());
+        return ArrayIterator.newArrayValueIterator(self);
     }
 
     /**
@@ -1759,7 +1759,7 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
     public static Object getIterator(final Object self) {
-        return new ArrayIterator(Global.toObject(self), AbstractIterator.IterationKind.VALUE, Global.instance());
+        return ArrayIterator.newArrayValueIterator(self);
     }
 
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat32Array.java	Wed Jul 05 22:21:51 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat32Array.java	Wed Jul 05 22:22:00 2017 +0200
@@ -232,6 +232,17 @@
         return (NativeFloat32Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
+    /**
+     * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+     *
+     * @param self the self reference
+     * @return an iterator over the array's values
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+    public static Object getIterator(final Object self) {
+        return ArrayIterator.newArrayValueIterator(self);
+    }
+
     @Override
     protected ScriptObject getPrototype(final Global global) {
         return global.getFloat32ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat64Array.java	Wed Jul 05 22:21:51 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat64Array.java	Wed Jul 05 22:22:00 2017 +0200
@@ -232,6 +232,17 @@
         return (NativeFloat64Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
+    /**
+     * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+     *
+     * @param self the self reference
+     * @return an iterator over the array's values
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+    public static Object getIterator(final Object self) {
+        return ArrayIterator.newArrayValueIterator(self);
+    }
+
     @Override
     protected ScriptObject getPrototype(final Global global) {
         return global.getFloat64ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt16Array.java	Wed Jul 05 22:21:51 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt16Array.java	Wed Jul 05 22:22:00 2017 +0200
@@ -225,6 +225,17 @@
         return (NativeInt16Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
+    /**
+     * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+     *
+     * @param self the self reference
+     * @return an iterator over the array's values
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+    public static Object getIterator(final Object self) {
+        return ArrayIterator.newArrayValueIterator(self);
+    }
+
     @Override
     protected ScriptObject getPrototype(final Global global) {
         return global.getInt16ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt32Array.java	Wed Jul 05 22:21:51 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt32Array.java	Wed Jul 05 22:22:00 2017 +0200
@@ -224,6 +224,17 @@
         return (NativeInt32Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
+    /**
+     * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+     *
+     * @param self the self reference
+     * @return an iterator over the array's values
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+    public static Object getIterator(final Object self) {
+        return ArrayIterator.newArrayValueIterator(self);
+    }
+
     @Override
     protected ScriptObject getPrototype(final Global global) {
         return global.getInt32ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt8Array.java	Wed Jul 05 22:21:51 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt8Array.java	Wed Jul 05 22:22:00 2017 +0200
@@ -224,6 +224,17 @@
         return (NativeInt8Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
+    /**
+     * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+     *
+     * @param self the self reference
+     * @return an iterator over the array's values
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+    public static Object getIterator(final Object self) {
+        return ArrayIterator.newArrayValueIterator(self);
+    }
+
     @Override
     protected ScriptObject getPrototype(final Global global) {
         return global.getInt8ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java	Wed Jul 05 22:21:51 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java	Wed Jul 05 22:22:00 2017 +0200
@@ -701,13 +701,9 @@
             }
 
             thisIndex = matcher.end();
-            if (thisIndex == string.length() && matcher.start() == matcher.end()) {
-                // Avoid getting empty match at end of string twice
-                break;
-            }
 
-            // ECMA 15.5.4.10 String.prototype.match(regexp)
-            if (thisIndex == previousLastIndex) {
+            // ECMA6 21.2.5.6 step 8.g.iv.5: If matchStr is empty advance index by one
+            if (matcher.start() == matcher.end()) {
                 setLastIndex(thisIndex + 1);
                 previousLastIndex = thisIndex + 1;
             } else {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint16Array.java	Wed Jul 05 22:21:51 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint16Array.java	Wed Jul 05 22:22:00 2017 +0200
@@ -229,6 +229,17 @@
         return (NativeUint16Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
+    /**
+     * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+     *
+     * @param self the self reference
+     * @return an iterator over the array's values
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+    public static Object getIterator(final Object self) {
+        return ArrayIterator.newArrayValueIterator(self);
+    }
+
     @Override
     protected ScriptObject getPrototype(final Global global) {
         return global.getUint16ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint32Array.java	Wed Jul 05 22:21:51 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint32Array.java	Wed Jul 05 22:22:00 2017 +0200
@@ -244,6 +244,17 @@
         return (NativeUint32Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
+    /**
+     * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+     *
+     * @param self the self reference
+     * @return an iterator over the array's values
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+    public static Object getIterator(final Object self) {
+        return ArrayIterator.newArrayValueIterator(self);
+    }
+
     @Override
     protected ScriptObject getPrototype(final Global global) {
         return global.getUint32ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8Array.java	Wed Jul 05 22:21:51 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8Array.java	Wed Jul 05 22:22:00 2017 +0200
@@ -230,6 +230,17 @@
         return (NativeUint8Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
+    /**
+     * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+     *
+     * @param self the self reference
+     * @return an iterator over the array's values
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+    public static Object getIterator(final Object self) {
+        return ArrayIterator.newArrayValueIterator(self);
+    }
+
     @Override
     protected ScriptObject getPrototype(final Global global) {
         return global.getUint8ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java	Wed Jul 05 22:21:51 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java	Wed Jul 05 22:22:00 2017 +0200
@@ -82,7 +82,6 @@
         private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
         private static final MethodHandle RINT_D   = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "rint", double.class, double.class).methodHandle();
         private static final MethodHandle RINT_O   = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "rint", Object.class, Object.class).methodHandle();
-        private static final MethodHandle CLAMP_LONG = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "clampLong", long.class, long.class).methodHandle();
 
         private Uint8ClampedArrayData(final ByteBuffer nb, final int start, final int end) {
             super((nb.position(start).limit(end)).slice(), end - start);
@@ -124,8 +123,6 @@
                     return MH.filterArguments(setter, 2, RINT_O);
                 } else if (elementType == double.class) {
                     return MH.filterArguments(setter, 2, RINT_D);
-                } else if (elementType == long.class) {
-                    return MH.filterArguments(setter, 2, CLAMP_LONG);
                 }
             }
             return setter;
@@ -195,7 +192,7 @@
 
         @Override
         public ArrayData set(final int index, final double value, final boolean strict) {
-            return set(index, rint(value), strict);
+            return set(index, (int) rint(value), strict);
         }
 
         private static double rint(final double rint) {
@@ -207,15 +204,6 @@
             return rint(JSType.toNumber(rint));
         }
 
-        @SuppressWarnings("unused")
-        private static long clampLong(final long l) {
-            if(l < 0L) {
-                return 0L;
-            } else if(l > 0xffL) {
-                return 0xffL;
-            }
-            return l;
-        }
     }
 
     /**
@@ -278,6 +266,17 @@
         return (NativeUint8ClampedArray)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
+    /**
+     * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+     *
+     * @param self the self reference
+     * @return an iterator over the array's values
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+    public static Object getIterator(final Object self) {
+        return ArrayIterator.newArrayValueIterator(self);
+    }
+
     @Override
     protected ScriptObject getPrototype(final Global global) {
         return global.getUint8ClampedArrayPrototype();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8164708.js	Wed Jul 05 22:22:00 2017 +0200
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8164708: String.prototype.replace replaces empty match twice
+ *
+ * @test
+ * @run
+ */
+
+Assert.assertEquals("4005".replace(/\B(?=(\d{3})+(?!\d))/g, ","), "4,005");
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8168146.js	Wed Jul 05 22:22:00 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8168146: Infinite recursion in Uint8ClampedArray.set
+ *
+ * @test
+ * @run
+ */
+
+
+var a = new Uint8ClampedArray(10);
+
+for (var i = 0; i < 10; i++) {
+    a[i] = i;
+    Assert.assertTrue(a[i] === i);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/JDK-8168140.js	Wed Jul 05 22:22:00 2017 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8168140: TypedArrays should implement ES6 iterator protocol
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+let TypedArrayTypes = [
+    Int8Array,
+    Uint8Array,
+    Uint8ClampedArray,
+    Int16Array,
+    Uint16Array,
+    Int32Array,
+    Uint32Array,
+    Float32Array,
+    Float64Array
+];
+
+let arrays = [];
+let sum = 0;
+
+TypedArrayTypes.forEach(function(ArrayType) {
+    var a = new ArrayType(10);
+    for (let i = 0; i < a.length; i++) {
+        a[i] = i;
+    }
+    arrays.push(a);
+});
+
+Assert.assertTrue(arrays.length === 9);
+
+for (let array of arrays) {
+
+    Assert.assertTrue(array.length === 10);
+    let count = 0;
+
+    for (let value of array) {
+        Assert.assertTrue(value === count++);
+        sum += value;
+    }
+}
+
+Assert.assertTrue(sum === 405);