Add test for yield* of iterator with throwing get:current

Change-Id: Idafa467a5e196d2351b3e5989177b39e959fddc5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/294882
Reviewed-by: Lasse Nielsen <lrn@google.com>
Commit-Queue: Stephen Adams <sra@google.com>
This commit is contained in:
Stephen Adams 2023-04-13 17:34:58 +00:00 committed by Commit Queue
parent d8b53d97ff
commit a34719fdb9
2 changed files with 108 additions and 0 deletions

View file

@ -0,0 +1,53 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:collection';
import 'package:expect/expect.dart';
class ThrowingCurrentIterator implements Iterator<int> {
int _remaining;
ThrowingCurrentIterator(this._remaining);
bool moveNext() => _remaining-- > 0;
int get current => throw 'current';
}
class ThrowingCurrent extends IterableBase<int> {
final int _length;
ThrowingCurrent(this._length);
Iterator<int> get iterator => ThrowingCurrentIterator(_length);
}
Iterable<int> f1() sync* {
yield* ThrowingCurrent(5);
yield* ThrowingCurrent(5);
}
Iterable<int> f2() sync* {
yield* f1();
yield* f1();
}
main() {
// `IterableBase.length` uses only `moveNext()`.
Expect.equals(5, ThrowingCurrent(5).length);
// The spec dictates that `yield*` calls `moveNext()` and `current` for each
// element in order to add the value to the iterable associated with the
// generator.
final i1 = f1().iterator;
Expect.throws(() => i1.moveNext());
// Further calls to `moveNext()` must return false (17.15).
Expect.isFalse(i1.moveNext());
// Same tests but for nested `yield*`.
final i2 = f2().iterator;
Expect.throws(() => i2.moveNext());
Expect.isFalse(i2.moveNext());
// Slighly surprising consequence of the specified behavior.
Expect.throws(() => f1().length);
Expect.throws(() => f2().length);
}

View file

@ -0,0 +1,55 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import 'dart:collection';
import 'package:expect/expect.dart';
class ThrowingCurrentIterator implements Iterator<int> {
int _remaining;
ThrowingCurrentIterator(this._remaining);
bool moveNext() => _remaining-- > 0;
int get current => throw 'current';
}
class ThrowingCurrent extends IterableBase<int> {
final int _length;
ThrowingCurrent(this._length);
Iterator<int> get iterator => ThrowingCurrentIterator(_length);
}
Iterable<int> f1() sync* {
yield* ThrowingCurrent(5);
yield* ThrowingCurrent(5);
}
Iterable<int> f2() sync* {
yield* f1();
yield* f1();
}
main() {
// `IterableBase.length` uses only `moveNext()`.
Expect.equals(5, ThrowingCurrent(5).length);
// The spec dictates that `yield*` calls `moveNext()` and `current` for each
// element in order to add the value to the iterable associated with the
// generator.
final i1 = f1().iterator;
Expect.throws(() => i1.moveNext());
// Further calls to `moveNext()` must return false (17.15).
Expect.isFalse(i1.moveNext());
// Same tests but for nested `yield*`.
final i2 = f2().iterator;
Expect.throws(() => i2.moveNext());
Expect.isFalse(i2.moveNext());
// Slighly surprising consequence of the specified behavior.
Expect.throws(() => f1().length);
Expect.throws(() => f2().length);
}