diff --git a/LibTest/async/Stream/Stream.multi_A01_t01.dart b/LibTest/async/Stream/Stream.multi_A01_t01.dart new file mode 100644 index 0000000000..92dfc7a7ff --- /dev/null +++ b/LibTest/async/Stream/Stream.multi_A01_t01.dart @@ -0,0 +1,66 @@ +// Copyright (c) 2024, 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. + +/// @assertion @Since("2.9") +/// Stream.multi( +/// void onListen( MultiStreamController ), { +/// bool isBroadcast = false, +/// }) +/// Creates a multi-subscription stream. +/// +/// Each time the created stream is listened to, the `onListen` callback is +/// invoked with a new [MultiStreamController], which forwards events to the +/// [StreamSubscription] returned by that [listen] call. +/// +/// This allows each listener to be treated as an individual stream. +/// +/// The [MultiStreamController] does not support reading its +/// [StreamController.stream]. Setting its [StreamController.onListen] has no +/// effect since the `onListen` callback is called instead, and the +/// [StreamController.onListen] won't be called later. The controller acts like +/// an asynchronous controller, but provides extra methods for delivering events +/// synchronously. +/// +/// If `isBroadcast` is set to true, the returned stream's [Stream.isBroadcast] +/// will be true. This has no effect on the stream behavior, it is up to the +/// `onListen` function to act like a broadcast stream if it claims to be one. +/// +/// A multi-subscription stream can behave like any other stream. If the +/// `onListen` callback throws on every call after the first, the stream behaves +/// like a single-subscription stream. If the stream emits the same events to +/// all current listeners, it behaves like a broadcast stream. +/// +/// @description Checks that `Stream.multi()` constructor creates a +/// multi-subscription stream. +/// @author sgrekhov22@gmail.com + +import "dart:async"; +import "../../../Utils/expect.dart"; + +main() { + asyncStart(2); + var stream = Stream.multi((controller) { + for (var v in [1, 2, 3, 4, 5]) { + controller.add(v); + } + controller.close(); + }); + Expect.isFalse(stream.isBroadcast); + + int i = 1; + stream.listen((v) { + Expect.equals(v, i++); + }, onDone: () { + Expect.equals(6, i); + asyncEnd(); + }); + + int j = 1; + stream.listen((v) { + Expect.equals(v, j++); + }, onDone: () { + Expect.equals(6, j); + asyncEnd(); + }); +} diff --git a/LibTest/async/Stream/Stream.multi_A02_t01.dart b/LibTest/async/Stream/Stream.multi_A02_t01.dart new file mode 100644 index 0000000000..267b369df4 --- /dev/null +++ b/LibTest/async/Stream/Stream.multi_A02_t01.dart @@ -0,0 +1,63 @@ +// Copyright (c) 2024, 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. + +/// @assertion @Since("2.9") +/// Stream.multi( +/// void onListen( MultiStreamController ), { +/// bool isBroadcast = false, +/// }) +/// Creates a multi-subscription stream. +/// +/// Each time the created stream is listened to, the `onListen` callback is +/// invoked with a new [MultiStreamController], which forwards events to the +/// [StreamSubscription] returned by that [listen] call. +/// +/// This allows each listener to be treated as an individual stream. +/// +/// The [MultiStreamController] does not support reading its +/// [StreamController.stream]. Setting its [StreamController.onListen] has no +/// effect since the `onListen` callback is called instead, and the +/// [StreamController.onListen] won't be called later. The controller acts like +/// an asynchronous controller, but provides extra methods for delivering events +/// synchronously. +/// +/// If `isBroadcast` is set to true, the returned stream's [Stream.isBroadcast] +/// will be true. This has no effect on the stream behavior, it is up to the +/// `onListen` function to act like a broadcast stream if it claims to be one. +/// +/// A multi-subscription stream can behave like any other stream. If the +/// `onListen` callback throws on every call after the first, the stream behaves +/// like a single-subscription stream. If the stream emits the same events to +/// all current listeners, it behaves like a broadcast stream. +/// +/// @description Checks that each time the created stream is listened to, the +/// `onListen` callback is invoked with a new instance of +/// [MultiStreamController]. +/// @author sgrekhov22@gmail.com + +import "dart:async"; +import "../../../Utils/expect.dart"; + +main() { + asyncStart(); + MultiStreamController? c1, c2; + var stream = Stream.multi((MultiStreamController controller) { + if (c1 == null) { + c1 = controller; + } else { + c2 = controller; + } + for (var v in [1, 2, 3, 4, 5]) { + controller.add(v); + } + controller.close(); + }); + + stream.listen((v) {}, onDone: () { + stream.listen((v) {}, onDone: () { + Expect.notIdentical(c1, c2); + asyncEnd(); + }); + }); +} diff --git a/LibTest/async/Stream/Stream.multi_A03_t01.dart b/LibTest/async/Stream/Stream.multi_A03_t01.dart new file mode 100644 index 0000000000..51f749b4ed --- /dev/null +++ b/LibTest/async/Stream/Stream.multi_A03_t01.dart @@ -0,0 +1,60 @@ +// Copyright (c) 2024, 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. + +/// @assertion @Since("2.9") +/// Stream.multi( +/// void onListen( MultiStreamController ), { +/// bool isBroadcast = false, +/// }) +/// Creates a multi-subscription stream. +/// +/// Each time the created stream is listened to, the `onListen` callback is +/// invoked with a new [MultiStreamController], which forwards events to the +/// [StreamSubscription] returned by that [listen] call. +/// +/// This allows each listener to be treated as an individual stream. +/// +/// The [MultiStreamController] does not support reading its +/// [StreamController.stream]. Setting its [StreamController.onListen] has no +/// effect since the `onListen` callback is called instead, and the +/// [StreamController.onListen] won't be called later. The controller acts like +/// an asynchronous controller, but provides extra methods for delivering events +/// synchronously. +/// +/// If `isBroadcast` is set to true, the returned stream's [Stream.isBroadcast] +/// will be true. This has no effect on the stream behavior, it is up to the +/// `onListen` function to act like a broadcast stream if it claims to be one. +/// +/// A multi-subscription stream can behave like any other stream. If the +/// `onListen` callback throws on every call after the first, the stream behaves +/// like a single-subscription stream. If the stream emits the same events to +/// all current listeners, it behaves like a broadcast stream. +/// +/// @description Checks that reading of [MultiStreamController.stream] is not +/// supported. +/// @author sgrekhov22@gmail.com + +import "dart:async"; +import "../../../Utils/expect.dart"; + +main() { + asyncStart(); + var stream = Stream.multi((MultiStreamController controller) { + Expect.throws(() { + controller.stream; + }); + for (var v in [1, 2, 3, 4, 5]) { + controller.add(v); + } + Expect.throws(() { + controller.stream; + }); + controller.close(); + Expect.throws(() { + controller.stream; + }); + }); + + stream.listen((v) {}, onDone: asyncEnd); +} diff --git a/LibTest/async/Stream/Stream.multi_A04_t01.dart b/LibTest/async/Stream/Stream.multi_A04_t01.dart new file mode 100644 index 0000000000..a670862309 --- /dev/null +++ b/LibTest/async/Stream/Stream.multi_A04_t01.dart @@ -0,0 +1,53 @@ +// Copyright (c) 2024, 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. + +/// @assertion @Since("2.9") +/// Stream.multi( +/// void onListen( MultiStreamController ), { +/// bool isBroadcast = false, +/// }) +/// Creates a multi-subscription stream. +/// +/// Each time the created stream is listened to, the `onListen` callback is +/// invoked with a new [MultiStreamController], which forwards events to the +/// [StreamSubscription] returned by that [listen] call. +/// +/// This allows each listener to be treated as an individual stream. +/// +/// The [MultiStreamController] does not support reading its +/// [StreamController.stream]. Setting its [StreamController.onListen] has no +/// effect since the `onListen` callback is called instead, and the +/// [StreamController.onListen] won't be called later. The controller acts like +/// an asynchronous controller, but provides extra methods for delivering events +/// synchronously. +/// +/// If `isBroadcast` is set to true, the returned stream's [Stream.isBroadcast] +/// will be true. This has no effect on the stream behavior, it is up to the +/// `onListen` function to act like a broadcast stream if it claims to be one. +/// +/// A multi-subscription stream can behave like any other stream. If the +/// `onListen` callback throws on every call after the first, the stream behaves +/// like a single-subscription stream. If the stream emits the same events to +/// all current listeners, it behaves like a broadcast stream. +/// +/// @description Checks that setting of [MultiStreamController.onListen] has no +/// effect. +/// @author sgrekhov22@gmail.com + +import "dart:async"; +import "../../../Utils/expect.dart"; + +main() { + asyncStart(); + var stream = Stream.multi((MultiStreamController controller) { + controller.onListen = () { + Expect.fail("MultiStreamController.onListen invoked"); + }; + for (var v in [1, 2, 3, 4, 5]) { + controller.add(v); + } + controller.close(); + }); + stream.listen((v) {}, onDone: asyncEnd); +} diff --git a/LibTest/async/Stream/Stream.multi_A05_t01.dart b/LibTest/async/Stream/Stream.multi_A05_t01.dart new file mode 100644 index 0000000000..5a9382dbca --- /dev/null +++ b/LibTest/async/Stream/Stream.multi_A05_t01.dart @@ -0,0 +1,49 @@ +// Copyright (c) 2024, 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. + +/// @assertion @Since("2.9") +/// Stream.multi( +/// void onListen( MultiStreamController ), { +/// bool isBroadcast = false, +/// }) +/// Creates a multi-subscription stream. +/// +/// Each time the created stream is listened to, the `onListen` callback is +/// invoked with a new [MultiStreamController], which forwards events to the +/// [StreamSubscription] returned by that [listen] call. +/// +/// This allows each listener to be treated as an individual stream. +/// +/// The [MultiStreamController] does not support reading its +/// [StreamController.stream]. Setting its [StreamController.onListen] has no +/// effect since the `onListen` callback is called instead, and the +/// [StreamController.onListen] won't be called later. The controller acts like +/// an asynchronous controller, but provides extra methods for delivering events +/// synchronously. +/// +/// If `isBroadcast` is set to true, the returned stream's [Stream.isBroadcast] +/// will be true. This has no effect on the stream behavior, it is up to the +/// `onListen` function to act like a broadcast stream if it claims to be one. +/// +/// A multi-subscription stream can behave like any other stream. If the +/// `onListen` callback throws on every call after the first, the stream behaves +/// like a single-subscription stream. If the stream emits the same events to +/// all current listeners, it behaves like a broadcast stream. +/// +/// @description Checks that if `isBroadcast` is set to true, the returned +/// stream's [Stream.isBroadcast] is true. +/// @author sgrekhov22@gmail.com + +import "dart:async"; +import "../../../Utils/expect.dart"; + +main() { + var stream = Stream.multi((controller) { + for (var v in [1, 2, 3, 4, 5]) { + controller.add(v); + } + controller.close(); + }, isBroadcast: true); + Expect.isTrue(stream.isBroadcast); +} diff --git a/LibTest/async/Stream/Stream.multi_all_t01.dart b/LibTest/async/Stream/Stream.multi_all_t01.dart new file mode 100644 index 0000000000..923c2f68f6 --- /dev/null +++ b/LibTest/async/Stream/Stream.multi_all_t01.dart @@ -0,0 +1,47 @@ +// Copyright (c) 2024, 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. + +/// @assertion @Since("2.9") +/// Stream.multi( +/// void onListen( MultiStreamController ), { +/// bool isBroadcast = false, +/// }) +/// Creates a multi-subscription stream. +/// +/// Each time the created stream is listened to, the `onListen` callback is +/// invoked with a new [MultiStreamController], which forwards events to the +/// [StreamSubscription] returned by that [listen] call. +/// +/// This allows each listener to be treated as an individual stream. +/// +/// The [MultiStreamController] does not support reading its +/// [StreamController.stream]. Setting its [StreamController.onListen] has no +/// effect since the `onListen` callback is called instead, and the +/// [StreamController.onListen] won't be called later. The controller acts like +/// an asynchronous controller, but provides extra methods for delivering events +/// synchronously. +/// +/// If `isBroadcast` is set to true, the returned stream's [Stream.isBroadcast] +/// will be true. This has no effect on the stream behavior, it is up to the +/// `onListen` function to act like a broadcast stream if it claims to be one. +/// +/// A multi-subscription stream can behave like any other stream. If the +/// `onListen` callback throws on every call after the first, the stream behaves +/// like a single-subscription stream. If the stream emits the same events to +/// all current listeners, it behaves like a broadcast stream. +/// +/// @description Checks Stream interface methods. +/// @author sgrekhov22@gmail.com + +import "dart:async"; +import "allTests_A01.lib.dart" as all; + +main() { + all.test((Iterable data) => Stream.multi((controller) { + for (var v in data) { + controller.add(v); + } + controller.close(); + })); +} diff --git a/Utils/expect_common.dart b/Utils/expect_common.dart index 6cc8cd4aa5..45f17f87fd 100644 --- a/Utils/expect_common.dart +++ b/Utils/expect_common.dart @@ -54,6 +54,15 @@ class Expect { } } + /// Checks whether the expected and actual values are identical (using + /// `identical`). + static void notIdentical(var expected, var actual, [String reason = '']) { + if (_identical(expected, actual)) { + _fail('Expect.notIdentical(expected: <$expected>, ' + 'actual: <$actual>$reason) fails.'); + } + } + /// Unconditional failure. static void fail(String reason) { _fail('Expect.fail($reason)'); diff --git a/Utils/tests/Expect/notIdentical_A01_t01.dart b/Utils/tests/Expect/notIdentical_A01_t01.dart new file mode 100644 index 0000000000..ed39d45365 --- /dev/null +++ b/Utils/tests/Expect/notIdentical_A01_t01.dart @@ -0,0 +1,26 @@ +// Copyright (c) 2024, 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. + +/// @assertion static void notIdentical( +/// var expected, var actual, [String reason = '']) +/// Checks whether the expected and actual values are not identical. +/// +/// @description Checks that no exception is thrown when the arguments are not +/// identical. +/// @author sgrekhov22@gmail.com + +import "../../../Utils/expect.dart"; + +class C { + final value; + const C(this.value); +} + +main() { + Expect.notIdentical("x", String.fromCharCode("x".codeUnitAt(0))); + Expect.notIdentical(Object(), Object()); + Expect.notIdentical(Object(), const Object()); + Expect.notIdentical(C(42), C(42)); + Expect.notIdentical(C(42), const C(42)); +} diff --git a/Utils/tests/Expect/notIdentical_A01_t02.dart b/Utils/tests/Expect/notIdentical_A01_t02.dart new file mode 100644 index 0000000000..25667749e9 --- /dev/null +++ b/Utils/tests/Expect/notIdentical_A01_t02.dart @@ -0,0 +1,35 @@ +// Copyright (c) 2024, 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. + +/// @assertion static void notIdentical( +/// var expected, var actual, [String reason = '']) +/// Checks whether the expected and actual values are not identical. +/// +/// @description Checks that an `ExpectException` is thrown when the arguments +/// are identical. +/// @author sgrekhov22@gmail.com + +import "../../../Utils/expect.dart"; + +class C { + final value; + const C(this.value); +} + +void check(var arg1, var arg2, [String reason = '']) { + try { + Expect.notIdentical(arg1, arg2, reason); + throw new Exception("ExpectException expected"); + } on ExpectException catch(_) { + } +} + +main() { + int one = 1; + String x = "x"; + check(x, x); + check(const Object(), const Object()); + check(const C(42), const C(42)); + check(1, one); +}