Add a tag and assert some state in FlutterTestDriver tests. (#159099)

Towards https://github.com/flutter/flutter/issues/51421.

Asserts some state we would not like to be hit by in integration tests
using `Flutter*TestDriver`.

In addition, adds a tag that can be used to run all tests that currently
use this pattern:

```sh
flutter test --tags flutter-test-driver
```

This showcases processes leaking quite a bit:
<https://gist.github.com/matanlurey/190d9084d3a45bc5737b8406bc05b4cd>.
This commit is contained in:
Matan Lurey 2024-11-18 15:37:05 -08:00 committed by GitHub
parent 7d4b2d31fc
commit 3a17b67353
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 104 additions and 4 deletions

View File

@ -16,3 +16,9 @@ tags:
# the --test-randomize-ordering-seed for the suites that have this tag.
no-shuffle:
allow_test_randomization: false
# Tests that invoke `flutter build apk` for integration.
flutter-build-apk: {}
# Tests that invoke `flutter test ...` or `flutter run ...` for integration.
flutter-test-driver: {}

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'dart:async';
import 'package:file/file.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'dart:async';
import 'package:file/file.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'package:file/file.dart';
import 'package:file_testing/file_testing.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'package:file/file.dart';
import '../src/common.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'package:archive/archive.dart';
import 'package:file/file.dart';
import 'package:file_testing/file_testing.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'dart:convert';
import 'package:file/file.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'dart:convert';
import 'package:file/file.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'package:file/file.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:process/process.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'dart:async';
import 'package:file/file.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'dart:async';
import 'package:file/file.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'package:file/file.dart';
import '../src/common.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'dart:async';
import 'package:file/file.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'dart:async';
import 'package:file/file.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'package:file/file.dart';
import '../src/common.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'dart:async';
import 'package:file/file.dart';

View File

@ -10,6 +10,7 @@ import 'package:file/file.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/utils.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'package:vm_service/vm_service.dart';
import 'package:vm_service/vm_service_io.dart';
@ -35,7 +36,7 @@ const Duration defaultTimeout = Duration(seconds: 5);
const Duration appStartTimeout = Duration(seconds: 120);
const Duration quitTimeout = Duration(seconds: 10);
abstract class FlutterTestDriver {
abstract final class FlutterTestDriver {
FlutterTestDriver(
this._projectFolder, {
String? logPrefix,
@ -86,12 +87,17 @@ abstract class FlutterTestDriver {
}
}
@mustCallSuper
Future<void> _setupProcess(
List<String> arguments, {
String? script,
bool withDebugger = false,
bool verbose = false,
}) async {
if (_process != null && !_hasExited) {
throw StateError('Cannot start another process while the previous runs');
}
if (withDebugger) {
arguments.add('--start-paused');
}
@ -120,6 +126,9 @@ abstract class FlutterTestDriver {
// via a getter for external uses.
unawaited(_process!.exitCode.then((int code) {
_debugPrint('Process exited ($code)');
// The timing of this signal is important to the implementation of the
// "quit" method, so only change how this is implemented by careful
// testing of tests that use FlutterTestDriver.
_hasExited = true;
}));
transformToLines(_process!.stdout).listen(_stdout.add);
@ -183,8 +192,24 @@ abstract class FlutterTestDriver {
);
}
Future<int> quit() => _killGracefully();
/// Quits the currently running process.
@nonVirtual
Future<void> quit() async {
final int result = await _killGracefully();
if (result != 0) {
_debugPrint('Expected process to terminate gracefully, got exit code $result.');
}
// The _hasExited signal could be on the microtask queue. Waiting for a
// Future(...) queues an event similar to Timer.run(Duration.zero), which
// guarantees the current queue has elapsed before moving on.
await Future<void>(() {});
if (!_hasExited) {
throw StateError('Process did not exit');
}
}
@nonVirtual
Future<int> _killGracefully() async {
if (_processPid == null) {
return -1;
@ -484,7 +509,7 @@ abstract class FlutterTestDriver {
}
}
class FlutterRunTestDriver extends FlutterTestDriver {
final class FlutterRunTestDriver extends FlutterTestDriver {
FlutterRunTestDriver(
super.projectFolder, {
super.logPrefix,
@ -770,7 +795,7 @@ class FlutterRunTestDriver extends FlutterTestDriver {
final bool spawnDdsInstance;
}
class FlutterTestTestDriver extends FlutterTestDriver {
final class FlutterTestTestDriver extends FlutterTestDriver {
FlutterTestTestDriver(super.projectFolder, {super.logPrefix});
Future<void> test({

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'dart:async';
import 'package:file/file.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'package:file/file.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:vm_service/vm_service.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'package:file/file.dart';
import '../integration.shard/test_data/stepping_project.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'package:file/file.dart';
import 'package:vm_service/vm_service.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'dart:async';
import 'package:file/file.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'package:file/file.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:vm_service/vm_service.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'dart:async';
import 'package:file/file.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@Tags(<String>['flutter-test-driver'])
library;
import 'package:file/file.dart';
import 'package:flutter_tools/src/base/file_system.dart';