| // 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:dds/dds.dart'; |
| import 'package:file/memory.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/build_info.dart'; |
| import 'package:flutter_tools/src/device.dart'; |
| import 'package:flutter_tools/src/test/flutter_tester_device.dart'; |
| import 'package:flutter_tools/src/test/font_config_manager.dart'; |
| import 'package:meta/meta.dart'; |
| import 'package:stream_channel/stream_channel.dart'; |
| import 'package:test/fake.dart'; |
| |
| import '../src/common.dart'; |
| import '../src/context.dart'; |
| import '../src/fake_process_manager.dart'; |
| |
| void main() { |
| FakePlatform platform; |
| FileSystem fileSystem; |
| FakeProcessManager processManager; |
| FlutterTesterTestDevice device; |
| |
| setUp(() { |
| fileSystem = MemoryFileSystem.test(); |
| // Not Windows. |
| platform = FakePlatform( |
| operatingSystem: 'linux', |
| environment: <String, String>{}, |
| ); |
| processManager = FakeProcessManager.any(); |
| }); |
| |
| FlutterTesterTestDevice createDevice({ |
| List<String> dartEntrypointArgs = const <String>[], |
| bool enableObservatory = false, |
| }) => |
| TestFlutterTesterDevice( |
| platform: platform, |
| fileSystem: fileSystem, |
| processManager: processManager, |
| enableObservatory: enableObservatory, |
| dartEntrypointArgs: dartEntrypointArgs, |
| ); |
| |
| group('The FLUTTER_TEST environment variable is passed to the test process', () { |
| setUp(() { |
| processManager = FakeProcessManager.empty(); |
| device = createDevice(); |
| |
| fileSystem |
| .file('.dart_tool/package_config.json') |
| ..createSync(recursive: true) |
| ..writeAsStringSync('{"configVersion":2,"packages":[]}'); |
| }); |
| |
| FakeCommand flutterTestCommand(String expectedFlutterTestValue) { |
| return FakeCommand(command: const <String>[ |
| '/', |
| '--disable-observatory', |
| '--ipv6', |
| '--enable-checked-mode', |
| '--verify-entry-points', |
| '--enable-software-rendering', |
| '--skia-deterministic-rendering', |
| '--enable-dart-profiling', |
| '--non-interactive', |
| '--use-test-fonts', |
| '--packages=.dart_tool/package_config.json', |
| 'example.dill' |
| ], environment: <String, String>{ |
| 'FLUTTER_TEST': expectedFlutterTestValue, |
| 'FONTCONFIG_FILE': device.fontConfigManager.fontConfigFile.path, |
| 'SERVER_PORT': '0', |
| 'APP_NAME': '', |
| }); |
| } |
| |
| testUsingContext('as true when not originally set', () async { |
| processManager.addCommand(flutterTestCommand('true')); |
| |
| await device.start('example.dill'); |
| expect(processManager.hasRemainingExpectations, isFalse); |
| }); |
| |
| testUsingContext('as true when set to true', () async { |
| platform.environment = <String, String>{'FLUTTER_TEST': 'true'}; |
| processManager.addCommand(flutterTestCommand('true')); |
| |
| await device.start('example.dill'); |
| expect(processManager.hasRemainingExpectations, isFalse); |
| }); |
| |
| testUsingContext('as false when set to false', () async { |
| platform.environment = <String, String>{'FLUTTER_TEST': 'false'}; |
| processManager.addCommand(flutterTestCommand('false')); |
| |
| await device.start('example.dill'); |
| expect(processManager.hasRemainingExpectations, isFalse); |
| }); |
| |
| testUsingContext('unchanged when set', () async { |
| platform.environment = <String, String>{'FLUTTER_TEST': 'neither true nor false'}; |
| processManager.addCommand(flutterTestCommand('neither true nor false')); |
| |
| await device.start('example.dill'); |
| expect(processManager.hasRemainingExpectations, isFalse); |
| }); |
| |
| testUsingContext('as null when set to null', () async { |
| platform.environment = <String, String>{'FLUTTER_TEST': null}; |
| processManager.addCommand(flutterTestCommand(null)); |
| |
| await device.start('example.dill'); |
| expect(processManager.hasRemainingExpectations, isFalse); |
| }); |
| }); |
| |
| group('Dart Entrypoint Args', () { |
| setUp(() { |
| processManager = FakeProcessManager.list(<FakeCommand>[ |
| const FakeCommand( |
| command: <String>[ |
| '/', |
| '--disable-observatory', |
| '--ipv6', |
| '--enable-checked-mode', |
| '--verify-entry-points', |
| '--enable-software-rendering', |
| '--skia-deterministic-rendering', |
| '--enable-dart-profiling', |
| '--non-interactive', |
| '--use-test-fonts', |
| '--packages=.dart_tool/package_config.json', |
| '--foo', |
| '--bar', |
| 'example.dill' |
| ], |
| stdout: 'success', |
| stderr: 'failure', |
| exitCode: 0, |
| ) |
| ]); |
| device = createDevice(dartEntrypointArgs: <String>['--foo', '--bar']); |
| }); |
| |
| testUsingContext('Can pass additional arguments to tester binary', () async { |
| await device.start('example.dill'); |
| |
| expect(processManager, hasNoRemainingExpectations); |
| }); |
| }); |
| |
| group('DDS', () { |
| setUp(() { |
| processManager = FakeProcessManager.list(<FakeCommand>[ |
| const FakeCommand( |
| command: <String>[ |
| '/', |
| '--observatory-port=0', |
| '--ipv6', |
| '--enable-checked-mode', |
| '--verify-entry-points', |
| '--enable-software-rendering', |
| '--skia-deterministic-rendering', |
| '--enable-dart-profiling', |
| '--non-interactive', |
| '--use-test-fonts', |
| '--packages=.dart_tool/package_config.json', |
| 'example.dill' |
| ], |
| stdout: 'Observatory listening on http://localhost:1234', |
| stderr: 'failure', |
| exitCode: 0, |
| ) |
| ]); |
| device = createDevice(enableObservatory: true); |
| }); |
| |
| testUsingContext('skips setting observatory port and uses the input port for for DDS instead', () async { |
| await device.start('example.dill'); |
| await device.observatoryUri; |
| |
| final Uri uri = await (device as TestFlutterTesterDevice).ddsServiceUriFuture(); |
| expect(uri.port, 1234); |
| }); |
| }); |
| } |
| |
| /// A Flutter Tester device. |
| /// |
| /// Uses a mock HttpServer. We don't want to bind random ports in our CI hosts. |
| class TestFlutterTesterDevice extends FlutterTesterTestDevice { |
| TestFlutterTesterDevice({ |
| @required Platform platform, |
| @required FileSystem fileSystem, |
| @required ProcessManager processManager, |
| @required bool enableObservatory, |
| @required List<String> dartEntrypointArgs, |
| }) : super( |
| id: 999, |
| shellPath: '/', |
| platform: platform, |
| fileSystem: fileSystem, |
| processManager: processManager, |
| logger: BufferLogger.test(), |
| debuggingOptions: DebuggingOptions.enabled( |
| const BuildInfo( |
| BuildMode.debug, |
| '', |
| treeShakeIcons: false, |
| packagesPath: '.dart_tool/package_config.json', |
| ), |
| startPaused: false, |
| enableDds: true, |
| disableServiceAuthCodes: false, |
| hostVmServicePort: 1234, |
| nullAssertions: false, |
| dartEntrypointArgs: dartEntrypointArgs, |
| ), |
| enableObservatory: enableObservatory, |
| machine: false, |
| host: InternetAddress.loopbackIPv6, |
| buildTestAssets: false, |
| flutterProject: null, |
| icudtlPath: null, |
| compileExpression: null, |
| fontConfigManager: FontConfigManager(), |
| ); |
| |
| final Completer<Uri> _ddsServiceUriCompleter = Completer<Uri>(); |
| |
| Future<Uri> ddsServiceUriFuture() => _ddsServiceUriCompleter.future; |
| |
| @override |
| Future<DartDevelopmentService> startDds(Uri uri) async { |
| _ddsServiceUriCompleter.complete(uri); |
| return FakeDartDevelopmentService(Uri.parse('http://localhost:${debuggingOptions.hostVmServicePort}'), Uri.parse('http://localhost:8080')); |
| } |
| |
| @override |
| Future<HttpServer> bind(InternetAddress host, int port) async => FakeHttpServer(); |
| |
| @override |
| Future<StreamChannel<String>> get remoteChannel async => StreamChannelController<String>().foreign; |
| } |
| |
| class FakeDartDevelopmentService extends Fake implements DartDevelopmentService { |
| FakeDartDevelopmentService(this.uri, this.original); |
| |
| final Uri original; |
| |
| @override |
| final Uri uri; |
| |
| @override |
| Uri get remoteVmServiceUri => original; |
| } |
| class FakeHttpServer extends Fake implements HttpServer { |
| @override |
| int get port => 0; |
| } |