From 76fc29312fe0f1f9fc5fc5d8aef311778e022e0a Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 2 Jan 2024 10:34:04 -0800 Subject: [PATCH] Make sure to finish the suite if all tests are skipped (flutter/engine#49339) Fixes https://github.com/flutter/flutter/issues/140481 Before this fix, if all tests are skipped, the `onDone` callback never fires, which means the recieve port never closes, which means the process just hangs indefinitely (and the success message is never printed). --- .../testing/litetest/lib/src/test_suite.dart | 23 +++++++++++++------ .../testing/litetest/test/litetest_test.dart | 23 +++++++++++++++++++ 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/engine/src/flutter/testing/litetest/lib/src/test_suite.dart b/engine/src/flutter/testing/litetest/lib/src/test_suite.dart index f701a9f360..7ea0f4505e 100644 --- a/engine/src/flutter/testing/litetest/lib/src/test_suite.dart +++ b/engine/src/flutter/testing/litetest/lib/src/test_suite.dart @@ -40,12 +40,22 @@ class TestSuite { ); } if (skip) { - _logger.writeln('Test $name: Skipped'); + _logger.writeln('Test "$name": Skipped'); + _primeQueue(); return; } _pushTest(name, body); } + void _primeQueue() { + if (!_testQueuePrimed) { + // All tests() must be added synchronously with main, so we can enqueue an + // event to start all tests to run after main() is done. + Timer.run(_startAllTests); + _testQueuePrimed = true; + } + } + void _pushTest( String name, dynamic Function() body, @@ -53,12 +63,7 @@ class TestSuite { final Test newTest = Test(name, body, logger: _logger); _testQueue.add(newTest); newTest.state = TestState.queued; - if (!_testQueuePrimed) { - // All tests() must be added synchronously with main, so we can enqueue an - // event to start all tests to run after main() is done. - Timer.run(_startAllTests); - _testQueuePrimed = true; - } + _primeQueue(); } void _startAllTests() { @@ -72,6 +77,10 @@ class TestSuite { }); } _lifecycle.onStart(); + if (_testQueue.isEmpty) { + _logger.writeln('All tests skipped.'); + _lifecycle.onDone(_testQueue); + } } } diff --git a/engine/src/flutter/testing/litetest/test/litetest_test.dart b/engine/src/flutter/testing/litetest/test/litetest_test.dart index c8e61a2b15..3a42d8328f 100644 --- a/engine/src/flutter/testing/litetest/test/litetest_test.dart +++ b/engine/src/flutter/testing/litetest/test/litetest_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; import 'dart:collection'; +import 'dart:isolate'; import 'package:async_helper/async_helper.dart'; import 'package:async_helper/async_minitest.dart'; @@ -13,6 +14,25 @@ import 'package:litetest/src/test_suite.dart'; Future main() async { asyncStart(); + test('skip', () async { + final StringBuffer buffer = StringBuffer(); + final TestLifecycle lifecycle = TestLifecycle(); + final TestSuite ts = TestSuite( + logger: buffer, + lifecycle: lifecycle, + ); + + ts.test('Test', () { + expect(1, equals(1)); + }, skip: true); + final bool result = await lifecycle.result; + + expect(result, true); + expect(buffer.toString(), equals( + 'Test "Test": Skipped\nAll tests skipped.\n', + )); + }); + test('test', () async { final StringBuffer buffer = StringBuffer(); final TestLifecycle lifecycle = TestLifecycle(); @@ -211,6 +231,8 @@ Test "Test3": Passed } class TestLifecycle implements Lifecycle { + final ReceivePort port = ReceivePort(); + final Completer _testCompleter = Completer(); Future get result => _testCompleter.future; @@ -225,5 +247,6 @@ class TestLifecycle implements Lifecycle { testsSucceeded = testsSucceeded && (t.state == TestState.succeeded); } _testCompleter.complete(testsSucceeded); + port.close(); } }