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:
parent
7d4b2d31fc
commit
3a17b67353
@ -16,3 +16,9 @@ tags:
|
|||||||
# the --test-randomize-ordering-seed for the suites that have this tag.
|
# the --test-randomize-ordering-seed for the suites that have this tag.
|
||||||
no-shuffle:
|
no-shuffle:
|
||||||
allow_test_randomization: false
|
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: {}
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
import 'package:file_testing/file_testing.dart';
|
import 'package:file_testing/file_testing.dart';
|
||||||
|
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
|
||||||
import '../src/common.dart';
|
import '../src/common.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'package:archive/archive.dart';
|
import 'package:archive/archive.dart';
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
import 'package:file_testing/file_testing.dart';
|
import 'package:file_testing/file_testing.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
import 'package:flutter_tools/src/base/io.dart';
|
import 'package:flutter_tools/src/base/io.dart';
|
||||||
import 'package:process/process.dart';
|
import 'package:process/process.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
|
||||||
import '../src/common.dart';
|
import '../src/common.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
|
||||||
import '../src/common.dart';
|
import '../src/common.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
@ -10,6 +10,7 @@ import 'package:file/file.dart';
|
|||||||
import 'package:flutter_tools/src/base/file_system.dart';
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
import 'package:flutter_tools/src/base/io.dart';
|
import 'package:flutter_tools/src/base/io.dart';
|
||||||
import 'package:flutter_tools/src/base/utils.dart';
|
import 'package:flutter_tools/src/base/utils.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
import 'package:process/process.dart';
|
import 'package:process/process.dart';
|
||||||
import 'package:vm_service/vm_service.dart';
|
import 'package:vm_service/vm_service.dart';
|
||||||
import 'package:vm_service/vm_service_io.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 appStartTimeout = Duration(seconds: 120);
|
||||||
const Duration quitTimeout = Duration(seconds: 10);
|
const Duration quitTimeout = Duration(seconds: 10);
|
||||||
|
|
||||||
abstract class FlutterTestDriver {
|
abstract final class FlutterTestDriver {
|
||||||
FlutterTestDriver(
|
FlutterTestDriver(
|
||||||
this._projectFolder, {
|
this._projectFolder, {
|
||||||
String? logPrefix,
|
String? logPrefix,
|
||||||
@ -86,12 +87,17 @@ abstract class FlutterTestDriver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mustCallSuper
|
||||||
Future<void> _setupProcess(
|
Future<void> _setupProcess(
|
||||||
List<String> arguments, {
|
List<String> arguments, {
|
||||||
String? script,
|
String? script,
|
||||||
bool withDebugger = false,
|
bool withDebugger = false,
|
||||||
bool verbose = false,
|
bool verbose = false,
|
||||||
}) async {
|
}) async {
|
||||||
|
if (_process != null && !_hasExited) {
|
||||||
|
throw StateError('Cannot start another process while the previous runs');
|
||||||
|
}
|
||||||
|
|
||||||
if (withDebugger) {
|
if (withDebugger) {
|
||||||
arguments.add('--start-paused');
|
arguments.add('--start-paused');
|
||||||
}
|
}
|
||||||
@ -120,6 +126,9 @@ abstract class FlutterTestDriver {
|
|||||||
// via a getter for external uses.
|
// via a getter for external uses.
|
||||||
unawaited(_process!.exitCode.then((int code) {
|
unawaited(_process!.exitCode.then((int code) {
|
||||||
_debugPrint('Process exited ($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;
|
_hasExited = true;
|
||||||
}));
|
}));
|
||||||
transformToLines(_process!.stdout).listen(_stdout.add);
|
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 {
|
Future<int> _killGracefully() async {
|
||||||
if (_processPid == null) {
|
if (_processPid == null) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -484,7 +509,7 @@ abstract class FlutterTestDriver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FlutterRunTestDriver extends FlutterTestDriver {
|
final class FlutterRunTestDriver extends FlutterTestDriver {
|
||||||
FlutterRunTestDriver(
|
FlutterRunTestDriver(
|
||||||
super.projectFolder, {
|
super.projectFolder, {
|
||||||
super.logPrefix,
|
super.logPrefix,
|
||||||
@ -770,7 +795,7 @@ class FlutterRunTestDriver extends FlutterTestDriver {
|
|||||||
final bool spawnDdsInstance;
|
final bool spawnDdsInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
class FlutterTestTestDriver extends FlutterTestDriver {
|
final class FlutterTestTestDriver extends FlutterTestDriver {
|
||||||
FlutterTestTestDriver(super.projectFolder, {super.logPrefix});
|
FlutterTestTestDriver(super.projectFolder, {super.logPrefix});
|
||||||
|
|
||||||
Future<void> test({
|
Future<void> test({
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
import 'package:flutter_tools/src/base/file_system.dart';
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
import 'package:vm_service/vm_service.dart';
|
import 'package:vm_service/vm_service.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
|
||||||
import '../integration.shard/test_data/stepping_project.dart';
|
import '../integration.shard/test_data/stepping_project.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
import 'package:vm_service/vm_service.dart';
|
import 'package:vm_service/vm_service.dart';
|
||||||
|
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
import 'package:flutter_tools/src/base/file_system.dart';
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
import 'package:vm_service/vm_service.dart';
|
import 'package:vm_service/vm_service.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
@Tags(<String>['flutter-test-driver'])
|
||||||
|
library;
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
import 'package:flutter_tools/src/base/file_system.dart';
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user