blob: a7f3cf393bc6c2754130d6eadd0a5f7704187afa [file] [log] [blame]
// 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.
import 'dart:async';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/desktop_device.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:meta/meta.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import '../src/common.dart';
import '../src/context.dart';
void main() {
group('Basic info', () {
testWithoutContext('Category is desktop', () async {
final FakeDesktopDevice device = setUpDesktopDevice();
expect(device.category, Category.desktop);
});
testWithoutContext('Not an emulator', () async {
final FakeDesktopDevice device = setUpDesktopDevice();
expect(await device.isLocalEmulator, false);
expect(await device.emulatorId, null);
});
testWithoutContext('Uses OS name as SDK name', () async {
final FakeDesktopDevice device = setUpDesktopDevice();
expect(await device.sdkNameAndVersion, 'Example');
});
});
group('Install', () {
testWithoutContext('Install checks always return true', () async {
final FakeDesktopDevice device = setUpDesktopDevice();
expect(await device.isAppInstalled(null), true);
expect(await device.isLatestBuildInstalled(null), true);
expect(device.category, Category.desktop);
});
testWithoutContext('Install and uninstall are no-ops that report success', () async {
final FakeDesktopDevice device = setUpDesktopDevice();
final FakeAppplicationPackage package = FakeAppplicationPackage();
expect(await device.uninstallApp(package), true);
expect(await device.isAppInstalled(package), true);
expect(await device.isLatestBuildInstalled(package), true);
expect(await device.installApp(package), true);
expect(await device.isAppInstalled(package), true);
expect(await device.isLatestBuildInstalled(package), true);
expect(device.category, Category.desktop);
});
});
group('Starting and stopping application', () {
testWithoutContext('Stop without start is a successful no-op', () async {
final FakeDesktopDevice device = setUpDesktopDevice();
final FakeAppplicationPackage package = FakeAppplicationPackage();
expect(await device.stopApp(package), true);
});
testWithoutContext('Can run from prebuilt application', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final Completer<void> completer = Completer<void>();
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand(
command: const <String>['null'],
stdout: 'Observatory listening on http://127.0.0.1/0\n',
completer: completer,
),
]);
final FakeDesktopDevice device = setUpDesktopDevice(processManager: processManager, fileSystem: fileSystem);
final String executableName = device.executablePathForDevice(null, BuildMode.debug);
fileSystem.file(executableName).writeAsStringSync('\n');
final FakeAppplicationPackage package = FakeAppplicationPackage();
final LaunchResult result = await device.startApp(package, prebuiltApplication: true);
expect(result.started, true);
expect(result.observatoryUri, Uri.parse('http://127.0.0.1/0'));
});
testWithoutContext('Null executable path fails gracefully', () async {
final BufferLogger logger = BufferLogger.test();
final DesktopDevice device = setUpDesktopDevice(nullExecutablePathForDevice: true, logger: logger);
final FakeAppplicationPackage package = FakeAppplicationPackage();
final LaunchResult result = await device.startApp(package, prebuiltApplication: true);
expect(result.started, false);
expect(logger.errorText, contains('Unable to find executable to run'));
});
testWithoutContext('stopApp kills process started by startApp', () async {
final Completer<void> completer = Completer<void>();
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand(
command: const <String>['null'],
stdout: 'Observatory listening on http://127.0.0.1/0\n',
completer: completer,
),
]);
final FakeDesktopDevice device = setUpDesktopDevice(processManager: processManager);
final FakeAppplicationPackage package = FakeAppplicationPackage();
final LaunchResult result = await device.startApp(package, prebuiltApplication: true);
expect(result.started, true);
expect(await device.stopApp(package), true);
});
});
testWithoutContext('Port forwarder is a no-op', () async {
final FakeDesktopDevice device = setUpDesktopDevice();
final DevicePortForwarder portForwarder = device.portForwarder;
final int result = await portForwarder.forward(2);
expect(result, 2);
expect(portForwarder.forwardedPorts.isEmpty, true);
});
}
FakeDesktopDevice setUpDesktopDevice({
FileSystem fileSystem,
Logger logger,
ProcessManager processManager,
OperatingSystemUtils operatingSystemUtils,
bool nullExecutablePathForDevice = false,
}) {
return FakeDesktopDevice(
fileSystem: fileSystem ?? MemoryFileSystem.test(),
logger: logger ?? BufferLogger.test(),
processManager: processManager ?? FakeProcessManager.any(),
operatingSystemUtils: operatingSystemUtils ?? FakeOperatingSystemUtils(),
nullExecutablePathForDevice: nullExecutablePathForDevice,
);
}
/// A trivial subclass of DesktopDevice for testing the shared functionality.
class FakeDesktopDevice extends DesktopDevice {
FakeDesktopDevice({
@required ProcessManager processManager,
@required Logger logger,
@required FileSystem fileSystem,
@required OperatingSystemUtils operatingSystemUtils,
this.nullExecutablePathForDevice,
}) : super(
'dummy',
platformType: PlatformType.linux,
ephemeral: false,
processManager: processManager,
logger: logger,
fileSystem: fileSystem,
operatingSystemUtils: operatingSystemUtils,
);
/// The [mainPath] last passed to [buildForDevice].
String lastBuiltMainPath;
/// The [buildInfo] last passed to [buildForDevice].
BuildInfo lastBuildInfo;
final bool nullExecutablePathForDevice;
@override
String get name => 'dummy';
@override
Future<TargetPlatform> get targetPlatform async => TargetPlatform.tester;
@override
bool isSupported() => true;
@override
bool isSupportedForProject(FlutterProject flutterProject) => true;
@override
Future<void> buildForDevice(
ApplicationPackage package, {
String mainPath,
BuildInfo buildInfo,
}) async {
lastBuiltMainPath = mainPath;
lastBuildInfo = buildInfo;
}
// Dummy implementation that just returns the build mode name.
@override
String executablePathForDevice(ApplicationPackage package, BuildMode buildMode) {
if (nullExecutablePathForDevice) {
return null;
}
return buildMode == null ? 'null' : getNameForBuildMode(buildMode);
}
}
class FakeAppplicationPackage extends Fake implements ApplicationPackage {}
class FakeOperatingSystemUtils extends Fake implements OperatingSystemUtils {
@override
String get name => 'Example';
}