[nnbd/test] Fix some strong mode tests.

error_stack_trace2_test: As part of the late field spec, we no longer
have a special error for cyclic statics, so they just end up with stack
overflow errors, which don't have a stack trace.

list_..._test: Modify ListMixin<T> in NNBD libs so that addAll,
replaceRange, and insertAll work for non-nullable T.

Change-Id: I0f3f0c30f1aa45ea148eb5cdc954f024b7ba4777
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/141252
Commit-Queue: Liam Appelbe <liama@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Régis Crelier <regis@google.com>
diff --git a/sdk_nnbd/lib/collection/list.dart b/sdk_nnbd/lib/collection/list.dart
index 94124c5..fdf2f8a 100644
--- a/sdk_nnbd/lib/collection/list.dart
+++ b/sdk_nnbd/lib/collection/list.dart
@@ -262,8 +262,7 @@
     int i = this.length;
     for (E element in iterable) {
       assert(this.length == i || (throw ConcurrentModificationError(this)));
-      this.length = i + 1;
-      this[i] = element;
+      add(element);
       i++;
     }
   }
@@ -424,6 +423,10 @@
 
   void replaceRange(int start, int end, Iterable<E> newContents) {
     RangeError.checkValidRange(start, end, this.length);
+    if (start == this.length) {
+      addAll(newContents);
+      return;
+    }
     if (newContents is! EfficientLengthIterable) {
       newContents = newContents.toList();
     }
@@ -435,12 +438,26 @@
       if (removeLength > insertLength) {
         _closeGap(insertEnd, end);
       }
+    } else if (end == this.length) {
+      int i = start;
+      for (E element in newContents) {
+        if (i < end) {
+          this[i] = element;
+        } else {
+          add(element);
+        }
+        i++;
+      }
     } else {
       int delta = insertLength - removeLength;
-      int newLength = this.length + delta;
+      int oldLength = this.length;
       int insertEnd = start + insertLength; // aka. end + delta.
-      this.length = newLength;
-      this.setRange(insertEnd, newLength, this, end);
+      for (int i = oldLength - delta; i < oldLength; ++i) {
+        add(this[i > 0 ? i : 0]);
+      }
+      if (insertEnd < oldLength) {
+        this.setRange(insertEnd, oldLength, this, end);
+      }
       this.setRange(start, insertEnd, newContents);
     }
   }
@@ -505,21 +522,34 @@
 
   void insertAll(int index, Iterable<E> iterable) {
     RangeError.checkValueInInterval(index, 0, length, "index");
+    if (index == length) {
+      addAll(iterable);
+      return;
+    }
     if (iterable is! EfficientLengthIterable || identical(iterable, this)) {
       iterable = iterable.toList();
     }
     int insertionLength = iterable.length;
+    if (insertionLength == 0) {
+      return;
+    }
     // There might be errors after the length change, in which case the list
     // will end up being modified but the operation not complete. Unless we
     // always go through a "toList" we can't really avoid that.
-    this.length += insertionLength;
+    int oldLength = length;
+    for (int i = oldLength - insertionLength; i < oldLength; ++i) {
+      add(this[i > 0 ? i : 0]);
+    }
     if (iterable.length != insertionLength) {
       // If the iterable's length is linked to this list's length somehow,
       // we can't insert one in the other.
       this.length -= insertionLength;
       throw ConcurrentModificationError(iterable);
     }
-    setRange(index + insertionLength, this.length, this, index);
+    int oldCopyStart = index + insertionLength;
+    if (oldCopyStart < oldLength) {
+      setRange(oldCopyStart, oldLength, this, index);
+    }
     setAll(index, iterable);
   }
 
diff --git a/tests/corelib/error_stack_trace2_test.dart b/tests/corelib/error_stack_trace2_test.dart
index 7437651..47f6a7d 100644
--- a/tests/corelib/error_stack_trace2_test.dart
+++ b/tests/corelib/error_stack_trace2_test.dart
@@ -22,8 +22,7 @@
   } catch (e2) {
     var e = e2;
     hasThrown = true;
-    Expect.isTrue(
-        e.stackTrace is StackTrace, "$e doesn't have a non-null stack trace");
+    Expect.isTrue(e is StackOverflowError);
   }
   Expect.isTrue(hasThrown);
 }
diff --git a/tests/corelib/list_insert_all_test.dart b/tests/corelib/list_insert_all_test.dart
index d089dc8..ea0b61f 100644
--- a/tests/corelib/list_insert_all_test.dart
+++ b/tests/corelib/list_insert_all_test.dart
@@ -34,6 +34,10 @@
     list[index] = val;
   }
 
+  void add(T element) {
+    list.add(element);
+  }
+
   toString() => list.toString();
 }
 
@@ -74,6 +78,11 @@
   test(new MyList([1, 2, 3]), 3, [4, 5].map((x) => x));
   test(new MyList([1, 2, 3]), 2, [4].map((x) => x));
   test(new MyList([1, 2, 3]), 3, [].map((x) => x));
+  test(new MyList([]), 0, []);
+  test(new MyList([]), 0, [4]);
+  test(new MyList([]), 0, [4, 5]);
+  test(new MyList([1]), 0, [4, 5]);
+  test(new MyList([1]), 1, [4, 5]);
 
   Expect.throwsRangeError(() => test([1, 2, 3], -1, [4, 5]));
   Expect.throwsUnsupportedError(
diff --git a/tests/corelib/list_replace_range_test.dart b/tests/corelib/list_replace_range_test.dart
index 964ed44..59baafe 100644
--- a/tests/corelib/list_replace_range_test.dart
+++ b/tests/corelib/list_replace_range_test.dart
@@ -35,6 +35,10 @@
     list[index] = val;
   }
 
+  void add(T element) {
+    list.add(element);
+  }
+
   toString() => list.toString();
 }
 
@@ -93,6 +97,11 @@
   test(new MyList([1, 2, 3]), 3, 3, new Iterable.generate(2, (x) => x + 4));
   test(new MyList([1, 2, 3]), 0, 3, new Iterable.generate(2, (x) => x + 4));
   test(new MyList([1, 2, 3]), 2, 3, new Iterable.generate(2, (x) => x + 4));
+  test(new MyList([]), 0, 0, []);
+  test(new MyList([]), 0, 0, [4]);
+  test(new MyList([]), 0, 0, [4, 5]);
+  test(new MyList([1]), 0, 1, [4, 5]);
+  test(new MyList([1]), 1, 1, [4, 5]);
 
   Expect.throwsRangeError(() => test([1, 2, 3], -1, 0, []));
   Expect.throwsRangeError(() => test([1, 2, 3], 2, 1, []));