blob: 2bf8d87e9242807bacf61035c48a9c8142e4b85c [file] [log] [blame] [edit]
// 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;
}