Fix Stream.close() exception suppression logic.

Change-Id: Id68c0cb05beab1f6059bcfd9cb51f9db87a8ddd0
diff --git a/user/super/com/google/gwt/emul/java/util/stream/TerminatableStream.java b/user/super/com/google/gwt/emul/java/util/stream/TerminatableStream.java
index 018331f..b78b41f 100644
--- a/user/super/com/google/gwt/emul/java/util/stream/TerminatableStream.java
+++ b/user/super/com/google/gwt/emul/java/util/stream/TerminatableStream.java
@@ -17,8 +17,6 @@
 package java.util.stream;
 
 import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
 import java.util.List;
 
 // package protected, as not part of jre
@@ -70,33 +68,39 @@
   public void close() {
     if (root == null) {
       terminated = true;
-
-      // TODO this might not be quite right, make sure that it behaves the same way when throwing
-      //      the same exception multiple times as JDK does.
-      LinkedHashSet<Throwable> throwables = new LinkedHashSet<>();
-      onClose.forEach((runnable) -> {
-        try {
-          runnable.run();
-        } catch (Throwable e) {
-          throwables.add(e);
-        }
-      });
-      onClose.clear();
-      if (!throwables.isEmpty()) {
-        Iterator<Throwable> iterator = throwables.iterator();
-        Throwable outer = iterator.next();
-        iterator.forEachRemaining(outer::addSuppressed);
-
-        if (outer instanceof RuntimeException) {
-          throw (RuntimeException) outer;
-        }
-        if (outer instanceof Error) {
-          throw (Error) outer;
-        }
-        assert false : "Couldn't have caught this exception from a Runnable! " + outer;
-      }
+      runClosers();
     } else {
       root.close();
     }
   }
+
+  private void runClosers() {
+    ArrayList<Throwable> throwables = new ArrayList<>();
+    onClose.forEach(runnable -> {
+      try {
+        runnable.run();
+      } catch (Throwable e) {
+        throwables.add(e);
+      }
+    });
+    onClose.clear();
+
+    if (!throwables.isEmpty()) {
+      Throwable e = throwables.get(0);
+      for (int i = 1, size = throwables.size(); i < size; ++i) {
+        Throwable suppressed = throwables.get(i);
+        if (suppressed != e) {
+          e.addSuppressed(suppressed);
+        }
+      }
+
+      if (e instanceof RuntimeException) {
+        throw (RuntimeException) e;
+      }
+      if (e instanceof Error) {
+        throw (Error) e;
+      }
+      assert false : "Couldn't have caught this exception from a Runnable! " + e;
+    }
+  }
 }
\ No newline at end of file
diff --git a/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java b/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java
index d46bfaf..7835e05 100644
--- a/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java
+++ b/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java
@@ -591,6 +591,12 @@
         .onClose(() -> {
           throw b;
         })
+        .onClose(() -> {
+          throw a2;
+        })
+        .onClose(() -> {
+          throw b;
+        })
         .onClose(() -> calledCount[0]++);
 
     try {
@@ -598,9 +604,7 @@
       fail("RuntimeException expected");
     } catch (RuntimeException expected) {
       assertSame(a2, expected);
-      assertEquals(1, expected.getSuppressed().length);
-      Throwable firstSuppressed = expected.getSuppressed()[0];
-      assertSame(b, firstSuppressed);
+      assertEquals(new Throwable[] {b, b}, expected.getSuppressed());
     }
     assertEquals(1, calledCount[0]);