mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Migrate test/src/common to null safety (#79907)
This commit is contained in:
parent
19930e8754
commit
a2f67720ef
@ -17,7 +17,7 @@ Never throwToolExit(String message, { int? exitCode }) {
|
||||
class ToolExit implements Exception {
|
||||
ToolExit(this.message, { this.exitCode });
|
||||
|
||||
final String message;
|
||||
final String? message;
|
||||
final int? exitCode;
|
||||
|
||||
@override
|
||||
|
@ -24,6 +24,7 @@ import 'package:process/process.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fake_process_manager.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
setUpAll(() {
|
||||
|
@ -19,6 +19,7 @@ import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
import '../../src/testbed.dart';
|
||||
|
||||
void main() {
|
||||
|
@ -29,8 +29,10 @@ import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fake_vm_services.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/mocks.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
final vm_service.Isolate fakeUnpausedIsolate = vm_service.Isolate(
|
||||
id: '1',
|
||||
|
@ -22,6 +22,7 @@ import 'package:test/fake.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
// Defined globally for fakes to use.
|
||||
FileSystem fileSystem;
|
||||
|
@ -15,6 +15,7 @@ import 'package:process/process.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
import '../../src/testbed.dart';
|
||||
|
||||
class FakeXcodeProjectInterpreterWithBuildSettings extends FakeXcodeProjectInterpreter {
|
||||
|
@ -15,6 +15,7 @@ import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
class FakeXcodeProjectInterpreterWithBuildSettings extends FakeXcodeProjectInterpreter {
|
||||
@override
|
||||
|
@ -23,6 +23,7 @@ import 'package:test/fake.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
const String _kTestFlutterRoot = '/flutter';
|
||||
|
||||
|
@ -24,6 +24,7 @@ import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
class FakeXcodeProjectInterpreterWithProfile extends FakeXcodeProjectInterpreter {
|
||||
@override
|
||||
|
@ -10,6 +10,7 @@ import 'package:flutter_tools/src/runner/flutter_command.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
testUsingContext('obfuscate requires split-debug-info', () {
|
||||
|
@ -22,6 +22,7 @@ import 'package:flutter_tools/src/web/compile.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
FileSystem fileSystem;
|
||||
|
@ -20,6 +20,7 @@ import 'package:process/process.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
import '../../src/testbed.dart';
|
||||
|
||||
const String flutterRoot = r'C:\flutter';
|
||||
|
@ -20,6 +20,7 @@ import 'package:test/fake.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
FakeAndroidStudio fakeAndroidStudio;
|
||||
|
@ -16,6 +16,7 @@ import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
import '../../src/testbed.dart';
|
||||
|
||||
void main() {
|
||||
|
@ -24,6 +24,21 @@ import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/mocks.dart';
|
||||
|
||||
/// Runs a callback using FakeAsync.run while continually pumping the
|
||||
/// microtask queue. This avoids a deadlock when tests `await` a Future
|
||||
/// which queues a microtask that will not be processed unless the queue
|
||||
/// is flushed.
|
||||
Future<T> _runFakeAsync<T>(Future<T> Function(FakeAsync time) f) async {
|
||||
return FakeAsync().run((FakeAsync time) async {
|
||||
bool pump = true;
|
||||
final Future<T> future = f(time).whenComplete(() => pump = false);
|
||||
while (pump) {
|
||||
time.flushMicrotasks();
|
||||
}
|
||||
return future;
|
||||
});
|
||||
}
|
||||
|
||||
void main() {
|
||||
Daemon daemon;
|
||||
NotifyingLogger notifyingLogger;
|
||||
@ -426,7 +441,7 @@ void main() {
|
||||
testWithoutContext(
|
||||
'debounces/merges same operation type and returns same result',
|
||||
() async {
|
||||
await runFakeAsync((FakeAsync time) async {
|
||||
await _runFakeAsync((FakeAsync time) async {
|
||||
final List<Future<int>> operations = <Future<int>>[
|
||||
queue.queueAndDebounce('OP1', debounceDuration, () async => 1),
|
||||
queue.queueAndDebounce('OP1', debounceDuration, () async => 2),
|
||||
@ -441,7 +456,7 @@ void main() {
|
||||
|
||||
testWithoutContext('does not merge results outside of the debounce duration',
|
||||
() async {
|
||||
await runFakeAsync((FakeAsync time) async {
|
||||
await _runFakeAsync((FakeAsync time) async {
|
||||
final List<Future<int>> operations = <Future<int>>[
|
||||
queue.queueAndDebounce('OP1', debounceDuration, () async => 1),
|
||||
Future<int>.delayed(debounceDuration * 2).then((_) =>
|
||||
@ -457,7 +472,7 @@ void main() {
|
||||
|
||||
testWithoutContext('does not merge results of different operations',
|
||||
() async {
|
||||
await runFakeAsync((FakeAsync time) async {
|
||||
await _runFakeAsync((FakeAsync time) async {
|
||||
final List<Future<int>> operations = <Future<int>>[
|
||||
queue.queueAndDebounce('OP1', debounceDuration, () async => 1),
|
||||
queue.queueAndDebounce('OP2', debounceDuration, () async => 2),
|
||||
@ -484,7 +499,7 @@ void main() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
await runFakeAsync((FakeAsync time) async {
|
||||
await _runFakeAsync((FakeAsync time) async {
|
||||
final List<Future<int>> operations = <Future<int>>[
|
||||
queue.queueAndDebounce('OP1', debounceDuration, () => f(1)),
|
||||
queue.queueAndDebounce('OP2', debounceDuration, () => f(2)),
|
||||
|
@ -16,6 +16,7 @@ import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fake_devices.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
group('devices', () {
|
||||
|
@ -35,6 +35,7 @@ import 'package:fake_async/fake_async.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
FakePlatform _kNoColorOutputPlatform() => FakePlatform(
|
||||
localeName: 'en_US.UTF-8',
|
||||
|
@ -17,6 +17,7 @@ import 'package:mockito/mockito.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
FileSystem fileSystem;
|
||||
|
@ -17,6 +17,7 @@ import 'package:test/fake.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
FileSystem fileSystem;
|
||||
|
@ -14,6 +14,7 @@ import 'package:flutter_tools/src/commands/generate_localizations.dart';
|
||||
import '../../integration.shard/test_data/basic_project.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
testUsingContext('default l10n settings', () async {
|
||||
|
@ -13,6 +13,7 @@ import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
group('ide_config', () {
|
||||
|
@ -17,6 +17,7 @@ import 'package:mockito/mockito.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/mocks.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
group('install', () {
|
||||
|
@ -13,6 +13,7 @@ import 'package:mockito/mockito.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
MockCache cache;
|
||||
|
@ -16,6 +16,7 @@ import 'package:test/fake.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
FileSystem fileSystem;
|
||||
|
@ -32,6 +32,7 @@ import 'package:vm_service/vm_service.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
group('run', () {
|
||||
|
@ -15,6 +15,7 @@ import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
group('shell_completion', () {
|
||||
|
@ -21,6 +21,7 @@ import 'package:test/fake.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
MemoryFileSystem fileSystem;
|
||||
|
@ -25,6 +25,7 @@ import 'package:process/process.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fake_devices.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
import '../../src/testbed.dart';
|
||||
|
||||
const String _pubspecContents = '''
|
||||
|
@ -23,6 +23,7 @@ import 'package:process/process.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
final Platform _kNoColorTerminalPlatform = FakePlatform(stdoutSupportsAnsi: false);
|
||||
|
||||
|
@ -20,6 +20,7 @@ import 'package:test/fake.dart';
|
||||
import '../../src/android_common.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
Cache.disableLocking();
|
||||
|
@ -23,6 +23,7 @@ import '../../src/android_common.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/mocks.dart' hide MockAndroidSdk;
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
Cache.disableLocking();
|
||||
|
@ -18,6 +18,7 @@ import 'package:test/fake.dart';
|
||||
import '../../src/android_common.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
Cache.disableLocking();
|
||||
|
@ -21,6 +21,7 @@ import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
Cache.disableLocking();
|
||||
|
@ -32,6 +32,7 @@ import '../../src/context.dart';
|
||||
import '../../src/fake_http_client.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/pubspec_schema.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
const String _kNoPlatformsMessage = 'You\'ve created a plugin project that doesn\'t yet support any platforms.\n';
|
||||
const String frameworkRevision = '12345678';
|
||||
|
@ -21,6 +21,7 @@ import 'package:mockito/mockito.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
setUpAll(() {
|
||||
|
@ -12,6 +12,7 @@ import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
group('format', () {
|
||||
|
@ -24,6 +24,7 @@ import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fake_process_manager.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
Cache.disableLocking();
|
||||
|
@ -19,6 +19,7 @@ import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fake_process_manager.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
group('UpgradeCommandRunner', () {
|
||||
|
@ -27,6 +27,7 @@ import 'package:usage/usage_io.dart';
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import '../src/fakes.dart';
|
||||
import '../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
setUpAll(() {
|
||||
|
@ -10,6 +10,7 @@ import 'package:flutter_tools/src/commands/logs.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
group('logs', () {
|
||||
|
@ -14,6 +14,7 @@ import 'package:flutter_tools/src/version.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import '../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
group('channel', () {
|
||||
|
@ -8,6 +8,7 @@ import 'package:flutter_tools/src/test/coverage_collector.dart';
|
||||
import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/fake_vm_services.dart';
|
||||
|
||||
void main() {
|
||||
testWithoutContext('Coverage collector Can handle coverage SentinelException', () async {
|
||||
|
@ -23,6 +23,7 @@ import 'package:package_config/package_config.dart';
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import '../src/fake_http_client.dart';
|
||||
import '../src/fake_vm_services.dart';
|
||||
|
||||
final FakeVmServiceRequest createDevFSRequest = FakeVmServiceRequest(
|
||||
method: '_createDevFS',
|
||||
|
@ -23,6 +23,7 @@ import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fake_vm_services.dart';
|
||||
import '../../src/fakes.dart';
|
||||
|
||||
|
||||
|
@ -18,6 +18,18 @@ import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import '../src/fakes.dart';
|
||||
|
||||
/// Matches a doctor validation result.
|
||||
Matcher _matchDoctorValidation({
|
||||
ValidationType validationType,
|
||||
String statusInfo,
|
||||
dynamic messages
|
||||
}) {
|
||||
return const TypeMatcher<ValidationResult>()
|
||||
.having((ValidationResult result) => result.type, 'type', validationType)
|
||||
.having((ValidationResult result) => result.statusInfo, 'statusInfo', statusInfo)
|
||||
.having((ValidationResult result) => result.messages, 'messages', messages);
|
||||
}
|
||||
|
||||
void main() {
|
||||
testWithoutContext('FlutterValidator shows an error message if gen_snapshot is '
|
||||
'downloaded and exits with code 1', () async {
|
||||
@ -48,7 +60,7 @@ void main() {
|
||||
fileSystem.file(artifacts.getArtifactPath(Artifact.genSnapshot)).createSync(recursive: true);
|
||||
|
||||
|
||||
expect(await flutterValidator.validate(), matchDoctorValidation(
|
||||
expect(await flutterValidator.validate(), _matchDoctorValidation(
|
||||
validationType: ValidationType.partial,
|
||||
statusInfo: 'Channel unknown, 1.0.0, on Linux, locale en_US.UTF-8',
|
||||
messages: containsAll(const <ValidationMessage>[
|
||||
@ -84,7 +96,7 @@ void main() {
|
||||
|
||||
// gen_snapshot is downloaded on demand, and the doctor should not
|
||||
// fail if the gen_snapshot binary is not present.
|
||||
expect(await flutterValidator.validate(), matchDoctorValidation(
|
||||
expect(await flutterValidator.validate(), _matchDoctorValidation(
|
||||
validationType: ValidationType.installed,
|
||||
statusInfo: 'Channel unknown, 1.0.0, on Windows, locale en_US.UTF-8',
|
||||
messages: anything,
|
||||
@ -103,7 +115,7 @@ void main() {
|
||||
flutterRoot: () => 'sdk/flutter',
|
||||
);
|
||||
|
||||
expect(await flutterValidator.validate(), matchDoctorValidation(
|
||||
expect(await flutterValidator.validate(), _matchDoctorValidation(
|
||||
validationType: ValidationType.partial,
|
||||
statusInfo: 'Channel unknown, 0.0.0, on Windows, locale en_US.UTF-8',
|
||||
messages: const <ValidationMessage>[
|
||||
@ -138,7 +150,7 @@ void main() {
|
||||
flutterRoot: () => 'sdk/flutter'
|
||||
);
|
||||
|
||||
expect(await flutterValidator.validate(), matchDoctorValidation(
|
||||
expect(await flutterValidator.validate(), _matchDoctorValidation(
|
||||
validationType: ValidationType.installed,
|
||||
statusInfo: 'Channel unknown, 1.0.0, on Windows, locale en_US.UTF-8',
|
||||
messages: containsAll(const <ValidationMessage>[
|
||||
|
@ -41,6 +41,7 @@ import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fake_vm_services.dart';
|
||||
|
||||
final vm_service.Isolate fakeIsolate = vm_service.Isolate(
|
||||
id: '1',
|
||||
|
@ -23,6 +23,7 @@ import 'package:mockito/mockito.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import '../src/fake_vm_services.dart';
|
||||
|
||||
final vm_service.Isolate fakeUnpausedIsolate = vm_service.Isolate(
|
||||
id: '1',
|
||||
|
@ -16,6 +16,7 @@ import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import '../src/fake_devices.dart';
|
||||
import '../src/fake_vm_services.dart';
|
||||
|
||||
final Map<String, Object> vm = <String, dynamic>{
|
||||
'isolates': <dynamic>[
|
||||
|
@ -21,6 +21,7 @@ import 'package:vm_service/vm_service.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fake_vm_services.dart';
|
||||
|
||||
void main() {
|
||||
FakeProcessManager processManager;
|
||||
|
@ -17,6 +17,7 @@ import 'package:test/fake.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import '../src/fake_vm_services.dart';
|
||||
|
||||
final vm_service.Isolate isolate = vm_service.Isolate(
|
||||
id: '1',
|
||||
|
@ -40,6 +40,7 @@ import 'package:mockito/mockito.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import '../src/fake_vm_services.dart';
|
||||
import '../src/fakes.dart';
|
||||
import '../src/testbed.dart';
|
||||
|
||||
|
@ -34,6 +34,7 @@ import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import '../src/fake_vm_services.dart';
|
||||
import '../src/fakes.dart';
|
||||
|
||||
const List<VmServiceExpectation> kAttachLogExpectations = <VmServiceExpectation>[
|
||||
|
@ -20,6 +20,7 @@ import 'package:flutter_tools/src/version.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
const String _kFlutterRoot = '/flutter/flutter';
|
||||
|
@ -25,6 +25,7 @@ import 'package:mockito/mockito.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
void main() {
|
||||
|
@ -14,6 +14,7 @@ import 'package:flutter_tools/src/vmservice.dart';
|
||||
import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/fake_vm_services.dart';
|
||||
|
||||
final vm_service.Isolate fakeUnpausedIsolate = vm_service.Isolate(
|
||||
id: '1',
|
||||
|
@ -19,6 +19,7 @@ import 'package:fake_async/fake_async.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart' hide testLogger;
|
||||
import '../src/fake_vm_services.dart';
|
||||
|
||||
final Map<String, Object> vm = <String, dynamic>{
|
||||
'type': 'VM',
|
||||
|
@ -18,6 +18,7 @@ import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import '../src/test_flutter_command_runner.dart';
|
||||
|
||||
void main() {
|
||||
Directory tempDir;
|
||||
|
@ -2,40 +2,22 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:args/args.dart';
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:fake_async/fake_async.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/base/common.dart';
|
||||
import 'package:flutter_tools/src/base/context.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/io.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/base/platform.dart';
|
||||
import 'package:flutter_tools/src/base/user_messages.dart';
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
import 'package:flutter_tools/src/commands/create.dart';
|
||||
import 'package:flutter_tools/src/convert.dart';
|
||||
import 'package:flutter_tools/src/doctor_validator.dart';
|
||||
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
|
||||
import 'package:flutter_tools/src/runner/flutter_command.dart';
|
||||
import 'package:flutter_tools/src/runner/flutter_command_runner.dart';
|
||||
import 'package:flutter_tools/src/vmservice.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:path/path.dart' as path; // flutter_ignore: package_path_import
|
||||
import 'package:test_api/test_api.dart' as test_package show test; // ignore: deprecated_member_use
|
||||
import 'package:test_api/test_api.dart' hide test; // ignore: deprecated_member_use
|
||||
import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
|
||||
export 'package:test_api/test_api.dart' hide test, isInstanceOf; // ignore: deprecated_member_use
|
||||
|
||||
/// A matcher that compares the type of the actual value to the type argument T.
|
||||
TypeMatcher<T> isInstanceOf<T>() => isA<T>();
|
||||
|
||||
void tryToDelete(Directory directory) {
|
||||
// This should not be necessary, but it turns out that
|
||||
// on Windows it's common for deletions to fail due to
|
||||
@ -57,7 +39,7 @@ void tryToDelete(Directory directory) {
|
||||
String getFlutterRoot() {
|
||||
const Platform platform = LocalPlatform();
|
||||
if (platform.environment.containsKey('FLUTTER_ROOT')) {
|
||||
return platform.environment['FLUTTER_ROOT'];
|
||||
return platform.environment['FLUTTER_ROOT']!;
|
||||
}
|
||||
|
||||
Error invalidScript() => StateError('Could not determine flutter_tools/ path from script URL (${globals.platform.script}); consider setting FLUTTER_ROOT explicitly.');
|
||||
@ -69,11 +51,11 @@ String getFlutterRoot() {
|
||||
break;
|
||||
case 'data':
|
||||
final RegExp flutterTools = RegExp(r'(file://[^"]*[/\\]flutter_tools[/\\][^"]+\.dart)', multiLine: true);
|
||||
final Match match = flutterTools.firstMatch(Uri.decodeFull(platform.script.path));
|
||||
final Match? match = flutterTools.firstMatch(Uri.decodeFull(platform.script.path));
|
||||
if (match == null) {
|
||||
throw invalidScript();
|
||||
}
|
||||
scriptUri = Uri.parse(match.group(1));
|
||||
scriptUri = Uri.parse(match.group(1)!);
|
||||
break;
|
||||
default:
|
||||
throw invalidScript();
|
||||
@ -88,23 +70,6 @@ String getFlutterRoot() {
|
||||
return path.normalize(path.join(toolsPath, '..', '..'));
|
||||
}
|
||||
|
||||
/// Gets the path to the root of the Android SDK from the environment variable.
|
||||
String getAndroidSdkRoot() {
|
||||
const Platform platform = LocalPlatform();
|
||||
if (platform.environment.containsKey('ANDROID_SDK_ROOT')) {
|
||||
return platform.environment['ANDROID_SDK_ROOT'];
|
||||
}
|
||||
throw StateError('ANDROID_SDK_ROOT environment varible not set');
|
||||
}
|
||||
|
||||
CommandRunner<void> createTestCommandRunner([ FlutterCommand command ]) {
|
||||
final FlutterCommandRunner runner = TestFlutterCommandRunner();
|
||||
if (command != null) {
|
||||
runner.addCommand(command);
|
||||
}
|
||||
return runner;
|
||||
}
|
||||
|
||||
/// Capture console print events into a string buffer.
|
||||
Future<StringBuffer> capturedConsolePrint(Future<void> Function() body) async {
|
||||
final StringBuffer buffer = StringBuffer();
|
||||
@ -121,8 +86,8 @@ Future<StringBuffer> capturedConsolePrint(Future<void> Function() body) async {
|
||||
final Matcher throwsAssertionError = throwsA(isA<AssertionError>());
|
||||
|
||||
/// Matcher for functions that throw [ToolExit].
|
||||
Matcher throwsToolExit({ int exitCode, Pattern message }) {
|
||||
Matcher matcher = isToolExit;
|
||||
Matcher throwsToolExit({ int? exitCode, Pattern? message }) {
|
||||
Matcher matcher = _isToolExit;
|
||||
if (exitCode != null) {
|
||||
matcher = allOf(matcher, (ToolExit e) => e.exitCode == exitCode);
|
||||
}
|
||||
@ -133,33 +98,19 @@ Matcher throwsToolExit({ int exitCode, Pattern message }) {
|
||||
}
|
||||
|
||||
/// Matcher for [ToolExit]s.
|
||||
final TypeMatcher<ToolExit> isToolExit = isA<ToolExit>();
|
||||
final TypeMatcher<ToolExit> _isToolExit = isA<ToolExit>();
|
||||
|
||||
/// Matcher for functions that throw [ProcessException].
|
||||
Matcher throwsProcessException({ Pattern message }) {
|
||||
Matcher matcher = isProcessException;
|
||||
Matcher throwsProcessException({ Pattern? message }) {
|
||||
Matcher matcher = _isProcessException;
|
||||
if (message != null) {
|
||||
matcher = allOf(matcher, (ProcessException e) => e.message?.contains(message));
|
||||
matcher = allOf(matcher, (ProcessException e) => e.message.contains(message));
|
||||
}
|
||||
return throwsA(matcher);
|
||||
}
|
||||
|
||||
/// Matcher for [ProcessException]s.
|
||||
final TypeMatcher<ProcessException> isProcessException = isA<ProcessException>();
|
||||
|
||||
/// Creates a flutter project in the [temp] directory using the
|
||||
/// [arguments] list if specified, or `--no-pub` if not.
|
||||
/// Returns the path to the flutter project.
|
||||
Future<String> createProject(Directory temp, { List<String> arguments }) async {
|
||||
arguments ??= <String>['--no-pub'];
|
||||
final String projectPath = globals.fs.path.join(temp.path, 'flutter_project');
|
||||
final CreateCommand command = CreateCommand();
|
||||
final CommandRunner<void> runner = createTestCommandRunner(command);
|
||||
await runner.run(<String>['create', ...arguments, projectPath]);
|
||||
// Created `.packages` since it's not created when the flag `--no-pub` is passed.
|
||||
globals.fs.file(globals.fs.path.join(projectPath, '.packages')).createSync();
|
||||
return projectPath;
|
||||
}
|
||||
final TypeMatcher<ProcessException> _isProcessException = isA<ProcessException>();
|
||||
|
||||
Future<void> expectToolExitLater(Future<dynamic> future, Matcher messageMatcher) async {
|
||||
try {
|
||||
@ -187,12 +138,12 @@ Matcher containsIgnoringWhitespace(String toSearch) {
|
||||
/// `LocalFileSystem.dispose()`.
|
||||
@isTest
|
||||
void test(String description, FutureOr<void> Function() body, {
|
||||
String testOn,
|
||||
Timeout timeout,
|
||||
String? testOn,
|
||||
Timeout? timeout,
|
||||
dynamic skip,
|
||||
List<String> tags,
|
||||
Map<String, dynamic> onPlatform,
|
||||
int retry,
|
||||
List<String>? tags,
|
||||
Map<String, dynamic>? onPlatform,
|
||||
int? retry,
|
||||
}) {
|
||||
test_package.test(
|
||||
description,
|
||||
@ -221,17 +172,17 @@ void test(String description, FutureOr<void> Function() body, {
|
||||
/// For more information, see https://github.com/flutter/flutter/issues/47161
|
||||
@isTest
|
||||
void testWithoutContext(String description, FutureOr<void> Function() body, {
|
||||
String testOn,
|
||||
Timeout timeout,
|
||||
String? testOn,
|
||||
Timeout? timeout,
|
||||
dynamic skip,
|
||||
List<String> tags,
|
||||
Map<String, dynamic> onPlatform,
|
||||
int retry,
|
||||
List<String>? tags,
|
||||
Map<String, dynamic>? onPlatform,
|
||||
int? retry,
|
||||
}) {
|
||||
return test(
|
||||
description, () async {
|
||||
return runZoned(body, zoneValues: <Object, Object>{
|
||||
contextKey: const NoContext(),
|
||||
contextKey: const _NoContext(),
|
||||
});
|
||||
},
|
||||
timeout: timeout,
|
||||
@ -243,28 +194,13 @@ void testWithoutContext(String description, FutureOr<void> Function() body, {
|
||||
);
|
||||
}
|
||||
|
||||
/// Runs a callback using FakeAsync.run while continually pumping the
|
||||
/// microtask queue. This avoids a deadlock when tests `await` a Future
|
||||
/// which queues a microtask that will not be processed unless the queue
|
||||
/// is flushed.
|
||||
Future<T> runFakeAsync<T>(Future<T> Function(FakeAsync time) f) async {
|
||||
return FakeAsync().run((FakeAsync time) async {
|
||||
bool pump = true;
|
||||
final Future<T> future = f(time).whenComplete(() => pump = false);
|
||||
while (pump) {
|
||||
time.flushMicrotasks();
|
||||
}
|
||||
return future;
|
||||
});
|
||||
}
|
||||
|
||||
/// An implementation of [AppContext] that throws if context.get is called in the test.
|
||||
///
|
||||
/// The intention of the class is to ensure we do not accidentally regress when
|
||||
/// moving towards more explicit dependency injection by accidentally using
|
||||
/// a Zone value in place of a constructor parameter.
|
||||
class NoContext implements AppContext {
|
||||
const NoContext();
|
||||
class _NoContext implements AppContext {
|
||||
const _NoContext();
|
||||
|
||||
@override
|
||||
T get<T>() {
|
||||
@ -280,169 +216,16 @@ class NoContext implements AppContext {
|
||||
|
||||
@override
|
||||
Future<V> run<V>({
|
||||
FutureOr<V> Function() body,
|
||||
String name,
|
||||
Map<Type, Generator> overrides,
|
||||
Map<Type, Generator> fallbacks,
|
||||
ZoneSpecification zoneSpecification,
|
||||
required FutureOr<V> Function() body,
|
||||
String? name,
|
||||
Map<Type, Generator>? overrides,
|
||||
Map<Type, Generator>? fallbacks,
|
||||
ZoneSpecification? zoneSpecification,
|
||||
}) async {
|
||||
return body();
|
||||
}
|
||||
}
|
||||
|
||||
/// A fake implementation of a vm_service that mocks the JSON-RPC request
|
||||
/// and response structure.
|
||||
class FakeVmServiceHost {
|
||||
FakeVmServiceHost({
|
||||
@required List<VmServiceExpectation> requests,
|
||||
Uri httpAddress,
|
||||
Uri wsAddress,
|
||||
}) : _requests = requests {
|
||||
_vmService = FlutterVmService(vm_service.VmService(
|
||||
_input.stream,
|
||||
_output.add,
|
||||
), httpAddress: httpAddress, wsAddress: wsAddress);
|
||||
_applyStreamListen();
|
||||
_output.stream.listen((String data) {
|
||||
final Map<String, Object> request = json.decode(data) as Map<String, Object>;
|
||||
if (_requests.isEmpty) {
|
||||
throw Exception('Unexpected request: $request');
|
||||
}
|
||||
final FakeVmServiceRequest fakeRequest = _requests.removeAt(0) as FakeVmServiceRequest;
|
||||
expect(request, isA<Map<String, Object>>()
|
||||
.having((Map<String, Object> request) => request['method'], 'method', fakeRequest.method)
|
||||
.having((Map<String, Object> request) => request['params'], 'args', fakeRequest.args)
|
||||
);
|
||||
if (fakeRequest.close) {
|
||||
unawaited(_vmService.dispose());
|
||||
expect(_requests, isEmpty);
|
||||
return;
|
||||
}
|
||||
if (fakeRequest.errorCode == null) {
|
||||
_input.add(json.encode(<String, Object>{
|
||||
'jsonrpc': '2.0',
|
||||
'id': request['id'],
|
||||
'result': fakeRequest.jsonResponse ?? <String, Object>{'type': 'Success'},
|
||||
}));
|
||||
} else {
|
||||
_input.add(json.encode(<String, Object>{
|
||||
'jsonrpc': '2.0',
|
||||
'id': request['id'],
|
||||
'error': <String, Object>{
|
||||
'code': fakeRequest.errorCode,
|
||||
}
|
||||
}));
|
||||
}
|
||||
_applyStreamListen();
|
||||
});
|
||||
}
|
||||
|
||||
final List<VmServiceExpectation> _requests;
|
||||
final StreamController<String> _input = StreamController<String>();
|
||||
final StreamController<String> _output = StreamController<String>();
|
||||
|
||||
FlutterVmService get vmService => _vmService;
|
||||
FlutterVmService _vmService;
|
||||
|
||||
|
||||
bool get hasRemainingExpectations => _requests.isNotEmpty;
|
||||
|
||||
// remove FakeStreamResponse objects from _requests until it is empty
|
||||
// or until we hit a FakeRequest
|
||||
void _applyStreamListen() {
|
||||
while (_requests.isNotEmpty && !_requests.first.isRequest) {
|
||||
final FakeVmServiceStreamResponse response = _requests.removeAt(0) as FakeVmServiceStreamResponse;
|
||||
_input.add(json.encode(<String, Object>{
|
||||
'jsonrpc': '2.0',
|
||||
'method': 'streamNotify',
|
||||
'params': <String, Object>{
|
||||
'streamId': response.streamId,
|
||||
'event': response.event.toJson(),
|
||||
},
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class VmServiceExpectation {
|
||||
bool get isRequest;
|
||||
}
|
||||
|
||||
class FakeVmServiceRequest implements VmServiceExpectation {
|
||||
const FakeVmServiceRequest({
|
||||
@required this.method,
|
||||
this.args = const <String, Object>{},
|
||||
this.jsonResponse,
|
||||
this.errorCode,
|
||||
this.close = false,
|
||||
});
|
||||
|
||||
final String method;
|
||||
|
||||
/// When true, the vm service is automatically closed.
|
||||
final bool close;
|
||||
|
||||
/// If non-null, the error code for a [vm_service.RPCError] in place of a
|
||||
/// standard response.
|
||||
final int errorCode;
|
||||
final Map<String, Object> args;
|
||||
final Map<String, Object> jsonResponse;
|
||||
|
||||
@override
|
||||
bool get isRequest => true;
|
||||
}
|
||||
|
||||
class FakeVmServiceStreamResponse implements VmServiceExpectation {
|
||||
const FakeVmServiceStreamResponse({
|
||||
@required this.event,
|
||||
@required this.streamId,
|
||||
});
|
||||
|
||||
final vm_service.Event event;
|
||||
final String streamId;
|
||||
|
||||
@override
|
||||
bool get isRequest => false;
|
||||
}
|
||||
|
||||
class TestFlutterCommandRunner extends FlutterCommandRunner {
|
||||
@override
|
||||
Future<void> runCommand(ArgResults topLevelResults) async {
|
||||
final Logger topLevelLogger = globals.logger;
|
||||
final Map<Type, dynamic> contextOverrides = <Type, dynamic>{
|
||||
if (topLevelResults['verbose'] as bool)
|
||||
Logger: VerboseLogger(topLevelLogger),
|
||||
};
|
||||
return context.run<void>(
|
||||
overrides: contextOverrides.map<Type, Generator>((Type type, dynamic value) {
|
||||
return MapEntry<Type, Generator>(type, () => value);
|
||||
}),
|
||||
body: () {
|
||||
Cache.flutterRoot ??= Cache.defaultFlutterRoot(
|
||||
platform: globals.platform,
|
||||
fileSystem: globals.fs,
|
||||
userMessages: UserMessages(),
|
||||
);
|
||||
// For compatibility with tests that set this to a relative path.
|
||||
Cache.flutterRoot = globals.fs.path.normalize(globals.fs.path.absolute(Cache.flutterRoot));
|
||||
return super.runCommand(topLevelResults);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Matches a doctor validation result.
|
||||
Matcher matchDoctorValidation({
|
||||
ValidationType validationType,
|
||||
String statusInfo,
|
||||
dynamic messages
|
||||
}) {
|
||||
return const TypeMatcher<ValidationResult>()
|
||||
.having((ValidationResult result) => result.type, 'type', validationType)
|
||||
.having((ValidationResult result) => result.statusInfo, 'statusInfo', statusInfo)
|
||||
.having((ValidationResult result) => result.messages, 'messages', messages);
|
||||
}
|
||||
|
||||
/// Allows inserting file system exceptions into certain
|
||||
/// [MemoryFileSystem] operations by tagging path/op combinations.
|
||||
///
|
||||
@ -467,16 +250,16 @@ class FileExceptionHandler {
|
||||
void addError(FileSystemEntity entity, FileSystemOp operation, FileSystemException exception) {
|
||||
final String path = entity.path;
|
||||
_contextErrors[path] ??= <FileSystemOp, FileSystemException>{};
|
||||
_contextErrors[path][operation] = exception;
|
||||
_contextErrors[path]![operation] = exception;
|
||||
}
|
||||
|
||||
// Tear-off this method and pass it to the memory filesystem `opHandle` parameter.
|
||||
void opHandle(String path, FileSystemOp operation) {
|
||||
final Map<FileSystemOp, FileSystemException> exceptions = _contextErrors[path];
|
||||
final Map<FileSystemOp, FileSystemException>? exceptions = _contextErrors[path];
|
||||
if (exceptions == null) {
|
||||
return;
|
||||
}
|
||||
final FileSystemException exception = exceptions[operation];
|
||||
final FileSystemException? exception = exceptions[operation];
|
||||
if (exception == null) {
|
||||
return;
|
||||
}
|
||||
|
131
packages/flutter_tools/test/src/fake_vm_services.dart
Normal file
131
packages/flutter_tools/test/src/fake_vm_services.dart
Normal file
@ -0,0 +1,131 @@
|
||||
// Copyright 2014 The Flutter Authors. 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.8
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_tools/src/base/common.dart';
|
||||
import 'package:flutter_tools/src/convert.dart';
|
||||
import 'package:flutter_tools/src/vmservice.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:test_api/test_api.dart' hide test; // ignore: deprecated_member_use
|
||||
import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
|
||||
export 'package:test_api/test_api.dart' hide test, isInstanceOf; // ignore: deprecated_member_use
|
||||
|
||||
/// A fake implementation of a vm_service that mocks the JSON-RPC request
|
||||
/// and response structure.
|
||||
class FakeVmServiceHost {
|
||||
FakeVmServiceHost({
|
||||
@required List<VmServiceExpectation> requests,
|
||||
Uri httpAddress,
|
||||
Uri wsAddress,
|
||||
}) : _requests = requests {
|
||||
_vmService = FlutterVmService(vm_service.VmService(
|
||||
_input.stream,
|
||||
_output.add,
|
||||
), httpAddress: httpAddress, wsAddress: wsAddress);
|
||||
_applyStreamListen();
|
||||
_output.stream.listen((String data) {
|
||||
final Map<String, Object> request = json.decode(data) as Map<String, Object>;
|
||||
if (_requests.isEmpty) {
|
||||
throw Exception('Unexpected request: $request');
|
||||
}
|
||||
final FakeVmServiceRequest fakeRequest = _requests.removeAt(0) as FakeVmServiceRequest;
|
||||
expect(request, isA<Map<String, Object>>()
|
||||
.having((Map<String, Object> request) => request['method'], 'method', fakeRequest.method)
|
||||
.having((Map<String, Object> request) => request['params'], 'args', fakeRequest.args)
|
||||
);
|
||||
if (fakeRequest.close) {
|
||||
unawaited(_vmService.dispose());
|
||||
expect(_requests, isEmpty);
|
||||
return;
|
||||
}
|
||||
if (fakeRequest.errorCode == null) {
|
||||
_input.add(json.encode(<String, Object>{
|
||||
'jsonrpc': '2.0',
|
||||
'id': request['id'],
|
||||
'result': fakeRequest.jsonResponse ?? <String, Object>{'type': 'Success'},
|
||||
}));
|
||||
} else {
|
||||
_input.add(json.encode(<String, Object>{
|
||||
'jsonrpc': '2.0',
|
||||
'id': request['id'],
|
||||
'error': <String, Object>{
|
||||
'code': fakeRequest.errorCode,
|
||||
}
|
||||
}));
|
||||
}
|
||||
_applyStreamListen();
|
||||
});
|
||||
}
|
||||
|
||||
final List<VmServiceExpectation> _requests;
|
||||
final StreamController<String> _input = StreamController<String>();
|
||||
final StreamController<String> _output = StreamController<String>();
|
||||
|
||||
FlutterVmService get vmService => _vmService;
|
||||
FlutterVmService _vmService;
|
||||
|
||||
|
||||
bool get hasRemainingExpectations => _requests.isNotEmpty;
|
||||
|
||||
// remove FakeStreamResponse objects from _requests until it is empty
|
||||
// or until we hit a FakeRequest
|
||||
void _applyStreamListen() {
|
||||
while (_requests.isNotEmpty && !_requests.first.isRequest) {
|
||||
final FakeVmServiceStreamResponse response = _requests.removeAt(0) as FakeVmServiceStreamResponse;
|
||||
_input.add(json.encode(<String, Object>{
|
||||
'jsonrpc': '2.0',
|
||||
'method': 'streamNotify',
|
||||
'params': <String, Object>{
|
||||
'streamId': response.streamId,
|
||||
'event': response.event.toJson(),
|
||||
},
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class VmServiceExpectation {
|
||||
bool get isRequest;
|
||||
}
|
||||
|
||||
class FakeVmServiceRequest implements VmServiceExpectation {
|
||||
const FakeVmServiceRequest({
|
||||
@required this.method,
|
||||
this.args = const <String, Object>{},
|
||||
this.jsonResponse,
|
||||
this.errorCode,
|
||||
this.close = false,
|
||||
});
|
||||
|
||||
final String method;
|
||||
|
||||
/// When true, the vm service is automatically closed.
|
||||
final bool close;
|
||||
|
||||
/// If non-null, the error code for a [vm_service.RPCError] in place of a
|
||||
/// standard response.
|
||||
final int errorCode;
|
||||
final Map<String, Object> args;
|
||||
final Map<String, Object> jsonResponse;
|
||||
|
||||
@override
|
||||
bool get isRequest => true;
|
||||
}
|
||||
|
||||
class FakeVmServiceStreamResponse implements VmServiceExpectation {
|
||||
const FakeVmServiceStreamResponse({
|
||||
@required this.event,
|
||||
@required this.streamId,
|
||||
});
|
||||
|
||||
final vm_service.Event event;
|
||||
final String streamId;
|
||||
|
||||
@override
|
||||
bool get isRequest => false;
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
// Copyright 2014 The Flutter Authors. 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.8
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:args/args.dart';
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:flutter_tools/src/base/context.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/base/user_messages.dart';
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
import 'package:flutter_tools/src/commands/create.dart';
|
||||
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
|
||||
import 'package:flutter_tools/src/runner/flutter_command.dart';
|
||||
import 'package:flutter_tools/src/runner/flutter_command_runner.dart';
|
||||
|
||||
export 'package:test_api/test_api.dart' hide test, isInstanceOf; // ignore: deprecated_member_use
|
||||
|
||||
CommandRunner<void> createTestCommandRunner([ FlutterCommand command ]) {
|
||||
final FlutterCommandRunner runner = TestFlutterCommandRunner();
|
||||
if (command != null) {
|
||||
runner.addCommand(command);
|
||||
}
|
||||
return runner;
|
||||
}
|
||||
|
||||
/// Creates a flutter project in the [temp] directory using the
|
||||
/// [arguments] list if specified, or `--no-pub` if not.
|
||||
/// Returns the path to the flutter project.
|
||||
Future<String> createProject(Directory temp, { List<String> arguments }) async {
|
||||
arguments ??= <String>['--no-pub'];
|
||||
final String projectPath = globals.fs.path.join(temp.path, 'flutter_project');
|
||||
final CreateCommand command = CreateCommand();
|
||||
final CommandRunner<void> runner = createTestCommandRunner(command);
|
||||
await runner.run(<String>['create', ...arguments, projectPath]);
|
||||
// Created `.packages` since it's not created when the flag `--no-pub` is passed.
|
||||
globals.fs.file(globals.fs.path.join(projectPath, '.packages')).createSync();
|
||||
return projectPath;
|
||||
}
|
||||
|
||||
class TestFlutterCommandRunner extends FlutterCommandRunner {
|
||||
@override
|
||||
Future<void> runCommand(ArgResults topLevelResults) async {
|
||||
final Logger topLevelLogger = globals.logger;
|
||||
final Map<Type, dynamic> contextOverrides = <Type, dynamic>{
|
||||
if (topLevelResults['verbose'] as bool)
|
||||
Logger: VerboseLogger(topLevelLogger),
|
||||
};
|
||||
return context.run<void>(
|
||||
overrides: contextOverrides.map<Type, Generator>((Type type, dynamic value) {
|
||||
return MapEntry<Type, Generator>(type, () => value);
|
||||
}),
|
||||
body: () {
|
||||
Cache.flutterRoot ??= Cache.defaultFlutterRoot(
|
||||
platform: globals.platform,
|
||||
fileSystem: globals.fs,
|
||||
userMessages: UserMessages(),
|
||||
);
|
||||
// For compatibility with tests that set this to a relative path.
|
||||
Cache.flutterRoot = globals.fs.path.normalize(globals.fs.path.absolute(Cache.flutterRoot));
|
||||
return super.runCommand(topLevelResults);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user