Unverified Commit f5827f0f authored by Zachary Anderson's avatar Zachary Anderson Committed by GitHub

[flutter_tool] Improve Fuchsia 'run' tests (#33263)

parent 7ec9a6fa
......@@ -4,6 +4,7 @@
import '../base/common.dart';
import '../base/process.dart';
import '../globals.dart';
import 'fuchsia_sdk.dart';
// Usage: dev_finder <flags> <subcommand> <subcommand args>
......@@ -31,7 +32,11 @@ class FuchsiaDevFinder {
'-full'
];
final RunResult result = await runAsync(command);
return (result.exitCode == 0) ? result.stdout.split('\n') : null;
if (result.exitCode != 0) {
printError('dev_finder failed: ${result.stderr}');
return null;
}
return result.stdout.split('\n');
}
/// Returns the host address by which the device [deviceName] should use for
......@@ -51,6 +56,10 @@ class FuchsiaDevFinder {
deviceName
];
final RunResult result = await runAsync(command);
return (result.exitCode == 0) ? result.stdout.trim() : null;
if (result.exitCode != 0) {
printError('dev_finder failed: ${result.stderr}');
return null;
}
return result.stdout.trim();
}
}
......@@ -44,9 +44,6 @@ class FuchsiaDeviceTools {
FuchsiaTilesCtl get tilesCtl => _tilesCtl ??= FuchsiaTilesCtl();
}
final FuchsiaAmberCtl _amberCtl = fuchsiaDeviceTools.amberCtl;
final FuchsiaTilesCtl _tilesCtl = fuchsiaDeviceTools.tilesCtl;
final String _ipv4Loopback = InternetAddress.loopbackIPv4.address;
final String _ipv6Loopback = InternetAddress.loopbackIPv6.address;
......@@ -233,6 +230,10 @@ class FuchsiaDevice extends Device {
await stopApp(package);
// Find out who the device thinks we are.
final String host = await fuchsiaSdk.fuchsiaDevFinder.resolve(name);
if (host == null) {
printError('Failed to resolve host for Fuchsia device');
return LaunchResult.failed();
}
final int port = await os.findFreePort();
if (port == 0) {
printError('Failed to find a free port');
......@@ -265,14 +266,14 @@ class FuchsiaDevice extends Device {
}
// Teach amber about the package server.
if (!await _amberCtl.addSrc(this, fuchsiaPackageServer)) {
if (!await fuchsiaDeviceTools.amberCtl.addSrc(this, fuchsiaPackageServer)) {
printError('Failed to teach amber about the package server');
return LaunchResult.failed();
}
serverRegistered = true;
// Tell amber to prefetch the app.
if (!await _amberCtl.getUp(this, appName)) {
if (!await fuchsiaDeviceTools.amberCtl.getUp(this, appName)) {
printError('Failed to get amber to prefetch the package');
return LaunchResult.failed();
}
......@@ -286,14 +287,14 @@ class FuchsiaDevice extends Device {
// Instruct tiles_ctl to start the app.
final String fuchsiaUrl =
'fuchsia-pkg://fuchsia.com/$appName#meta/$appName.cmx';
if (!await _tilesCtl.add(this, fuchsiaUrl, <String>[])) {
if (!await fuchsiaDeviceTools.tilesCtl.add(this, fuchsiaUrl, <String>[])) {
printError('Failed to add the app to tiles');
return LaunchResult.failed();
}
} finally {
// Try to un-teach amber about the package server if needed.
if (serverRegistered) {
await _amberCtl.rmSrc(this, fuchsiaPackageServer);
await fuchsiaDeviceTools.amberCtl.rmSrc(this, fuchsiaPackageServer);
}
// Shutdown the package server and delete the package repo;
fuchsiaPackageServer.stop();
......@@ -308,7 +309,7 @@ class FuchsiaDevice extends Device {
// In a debug or profile build, try to find the observatory uri.
final FuchsiaIsolateDiscoveryProtocol discovery =
FuchsiaIsolateDiscoveryProtocol(this, appName);
getIsolateDiscoveryProtocol(appName);
try {
final Uri observatoryUri = await discovery.uri;
return LaunchResult.succeeded(observatoryUri: observatoryUri);
......@@ -321,7 +322,7 @@ class FuchsiaDevice extends Device {
Future<bool> stopApp(covariant FuchsiaApp app) async {
final int appKey = await FuchsiaTilesCtl.findAppKey(this, app.id);
if (appKey != -1) {
if (!await _tilesCtl.remove(this, appKey)) {
if (!await fuchsiaDeviceTools.tilesCtl.remove(this, appKey)) {
printError('tiles_ctl remove on ${app.id} failed.');
return false;
}
......
......@@ -50,6 +50,9 @@ class FuchsiaSdk {
return null;
}
final List<String> devices = await fuchsiaDevFinder.list();
if (devices == null) {
return null;
}
return devices.isNotEmpty ? devices[0] : null;
}
......
......@@ -407,32 +407,49 @@ void main() {
group('fuchsia app start and stop: ', () {
MemoryFileSystem memoryFileSystem;
MockOperatingSystemUtils osUtils;
MockFuchsiaDeviceTools fuchsiaDeviceTools;
FakeFuchsiaDeviceTools fuchsiaDeviceTools;
MockFuchsiaSdk fuchsiaSdk;
setUp(() {
memoryFileSystem = MemoryFileSystem();
osUtils = MockOperatingSystemUtils();
fuchsiaDeviceTools = MockFuchsiaDeviceTools();
fuchsiaDeviceTools = FakeFuchsiaDeviceTools();
fuchsiaSdk = MockFuchsiaSdk();
when(osUtils.findFreePort()).thenAnswer((_) => Future<int>.value(12345));
});
testUsingContext('start prebuilt app in release mode', () async {
Future<LaunchResult> setupAndStartApp({
@required bool prebuilt,
@required BuildMode mode,
}) async {
const String appName = 'app_name';
final FuchsiaDevice device = FuchsiaDevice('123');
final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123');
fs.directory('fuchsia').createSync(recursive: true);
final File pubspecFile = fs.file('pubspec.yaml')..createSync();
pubspecFile.writeAsStringSync('name: $appName');
FuchsiaApp app;
if (prebuilt) {
final File far = fs.file('app_name-0.far')..createSync();
app = FuchsiaApp.fromPrebuiltApp(far);
} else {
fs.file(fs.path.join('fuchsia', 'meta', '$appName.cmx'))
.createSync(recursive: true);
fs.file('.packages').createSync();
fs.file(fs.path.join('lib', 'main.dart')).createSync(recursive: true);
app = BuildableFuchsiaApp(project: FlutterProject.current().fuchsia);
}
final FuchsiaApp app = FuchsiaApp.fromPrebuiltApp(far);
final DebuggingOptions debuggingOptions =
DebuggingOptions.disabled(const BuildInfo(BuildMode.release, null));
final LaunchResult launchResult = await device.startApp(app,
prebuiltApplication: true,
DebuggingOptions.disabled(BuildInfo(mode, null));
return await device.startApp(app,
prebuiltApplication: prebuilt,
debuggingOptions: debuggingOptions);
}
testUsingContext('start prebuilt in release mode', () async {
final LaunchResult launchResult =
await setupAndStartApp(prebuilt: true, mode: BuildMode.release);
expect(launchResult.started, isTrue);
expect(launchResult.hasObservatory, isFalse);
}, overrides: <Type, Generator>{
......@@ -442,9 +459,9 @@ void main() {
OperatingSystemUtils: () => osUtils,
});
testUsingContext('start and stop prebuilt app in release mode', () async {
testUsingContext('start and stop prebuilt in release mode', () async {
const String appName = 'app_name';
final FuchsiaDevice device = FuchsiaDevice('123');
final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123');
fs.directory('fuchsia').createSync(recursive: true);
final File pubspecFile = fs.file('pubspec.yaml')..createSync();
pubspecFile.writeAsStringSync('name: $appName');
......@@ -456,7 +473,6 @@ void main() {
final LaunchResult launchResult = await device.startApp(app,
prebuiltApplication: true,
debuggingOptions: debuggingOptions);
expect(launchResult.started, isTrue);
expect(launchResult.hasObservatory, isFalse);
expect(await device.stopApp(app), isTrue);
......@@ -466,6 +482,91 @@ void main() {
FuchsiaSdk: () => fuchsiaSdk,
OperatingSystemUtils: () => osUtils,
});
testUsingContext('start prebuilt in debug mode', () async {
final LaunchResult launchResult =
await setupAndStartApp(prebuilt: true, mode: BuildMode.debug);
expect(launchResult.started, isTrue);
expect(launchResult.hasObservatory, isTrue);
}, overrides: <Type, Generator>{
FileSystem: () => memoryFileSystem,
FuchsiaDeviceTools: () => fuchsiaDeviceTools,
FuchsiaSdk: () => fuchsiaSdk,
OperatingSystemUtils: () => osUtils,
});
testUsingContext('start buildable in release mode', () async {
final LaunchResult launchResult =
await setupAndStartApp(prebuilt: false, mode: BuildMode.release);
expect(launchResult.started, isTrue);
expect(launchResult.hasObservatory, isFalse);
}, overrides: <Type, Generator>{
FileSystem: () => memoryFileSystem,
FuchsiaDeviceTools: () => fuchsiaDeviceTools,
FuchsiaSdk: () => fuchsiaSdk,
OperatingSystemUtils: () => osUtils,
});
testUsingContext('start buildable in debug mode', () async {
final LaunchResult launchResult =
await setupAndStartApp(prebuilt: false, mode: BuildMode.debug);
expect(launchResult.started, isTrue);
expect(launchResult.hasObservatory, isTrue);
}, overrides: <Type, Generator>{
FileSystem: () => memoryFileSystem,
FuchsiaDeviceTools: () => fuchsiaDeviceTools,
FuchsiaSdk: () => fuchsiaSdk,
OperatingSystemUtils: () => osUtils,
});
testUsingContext('fail with correct LaunchResult when dev_finder fails', () async {
final LaunchResult launchResult =
await setupAndStartApp(prebuilt: true, mode: BuildMode.release);
expect(launchResult.started, isFalse);
expect(launchResult.hasObservatory, isFalse);
}, overrides: <Type, Generator>{
FileSystem: () => memoryFileSystem,
FuchsiaDeviceTools: () => fuchsiaDeviceTools,
FuchsiaSdk: () => MockFuchsiaSdk(devFinder: FailingDevFinder()),
OperatingSystemUtils: () => osUtils,
});
testUsingContext('fail with correct LaunchResult when pm fails', () async {
final LaunchResult launchResult =
await setupAndStartApp(prebuilt: true, mode: BuildMode.release);
expect(launchResult.started, isFalse);
expect(launchResult.hasObservatory, isFalse);
}, overrides: <Type, Generator>{
FileSystem: () => memoryFileSystem,
FuchsiaDeviceTools: () => fuchsiaDeviceTools,
FuchsiaSdk: () => MockFuchsiaSdk(pm: FailingPM()),
OperatingSystemUtils: () => osUtils,
});
testUsingContext('fail with correct LaunchResult when amber fails', () async {
final LaunchResult launchResult =
await setupAndStartApp(prebuilt: true, mode: BuildMode.release);
expect(launchResult.started, isFalse);
expect(launchResult.hasObservatory, isFalse);
}, overrides: <Type, Generator>{
FileSystem: () => memoryFileSystem,
FuchsiaDeviceTools: () => FakeFuchsiaDeviceTools(amber: FailingAmberCtl()),
FuchsiaSdk: () => fuchsiaSdk,
OperatingSystemUtils: () => osUtils,
});
testUsingContext('fail with correct LaunchResult when tiles fails', () async {
final LaunchResult launchResult =
await setupAndStartApp(prebuilt: true, mode: BuildMode.release);
expect(launchResult.started, isFalse);
expect(launchResult.hasObservatory, isFalse);
}, overrides: <Type, Generator>{
FileSystem: () => memoryFileSystem,
FuchsiaDeviceTools: () => FakeFuchsiaDeviceTools(tiles: FailingTilesCtl()),
FuchsiaSdk: () => fuchsiaSdk,
OperatingSystemUtils: () => osUtils,
});
});
}
......@@ -559,7 +660,24 @@ class MockIsolate extends Mock implements Isolate {
final String name;
}
class MockFuchsiaAmberCtl extends Mock implements FuchsiaAmberCtl {
class FuchsiaDeviceWithFakeDiscovery extends FuchsiaDevice {
FuchsiaDeviceWithFakeDiscovery(String id, {String name}) : super(id, name: name);
@override
FuchsiaIsolateDiscoveryProtocol getIsolateDiscoveryProtocol(
String isolateName) =>
FakeFuchsiaIsolateDiscoveryProtocol();
}
class FakeFuchsiaIsolateDiscoveryProtocol implements FuchsiaIsolateDiscoveryProtocol {
@override
FutureOr<Uri> get uri => Uri.parse('http://[::1]:37');
@override
void dispose() {}
}
class FakeFuchsiaAmberCtl implements FuchsiaAmberCtl {
@override
Future<bool> addSrc(FuchsiaDevice device, FuchsiaPackageServer server) async {
return true;
......@@ -576,7 +694,24 @@ class MockFuchsiaAmberCtl extends Mock implements FuchsiaAmberCtl {
}
}
class MockFuchsiaTilesCtl extends Mock implements FuchsiaTilesCtl {
class FailingAmberCtl implements FuchsiaAmberCtl {
@override
Future<bool> addSrc(FuchsiaDevice device, FuchsiaPackageServer server) async {
return false;
}
@override
Future<bool> rmSrc(FuchsiaDevice device, FuchsiaPackageServer server) async {
return false;
}
@override
Future<bool> getUp(FuchsiaDevice device, String packageName) async {
return false;
}
}
class FakeFuchsiaTilesCtl implements FuchsiaTilesCtl {
final Map<int, String> _runningApps = <int, String>{};
bool _started = false;
int _nextAppId = 1;
......@@ -624,15 +759,48 @@ class MockFuchsiaTilesCtl extends Mock implements FuchsiaTilesCtl {
}
}
class MockFuchsiaDeviceTools extends Mock implements FuchsiaDeviceTools {
class FailingTilesCtl implements FuchsiaTilesCtl {
@override
Future<bool> start(FuchsiaDevice device) async {
return false;
}
@override
Future<Map<int, String>> list(FuchsiaDevice device) async {
return null;
}
@override
Future<bool> add(FuchsiaDevice device, String url, List<String> args) async {
return false;
}
@override
Future<bool> remove(FuchsiaDevice device, int key) async {
return false;
}
@override
Future<bool> quit(FuchsiaDevice device) async {
return false;
}
}
class FakeFuchsiaDeviceTools implements FuchsiaDeviceTools {
FakeFuchsiaDeviceTools({
FuchsiaAmberCtl amber,
FuchsiaTilesCtl tiles,
}) : amberCtl = amber ?? FakeFuchsiaAmberCtl(),
tilesCtl = tiles ?? FakeFuchsiaTilesCtl();
@override
final FuchsiaAmberCtl amberCtl = MockFuchsiaAmberCtl();
final FuchsiaAmberCtl amberCtl;
@override
final FuchsiaTilesCtl tilesCtl = MockFuchsiaTilesCtl();
final FuchsiaTilesCtl tilesCtl;
}
class MockFuchsiaPM extends Mock implements FuchsiaPM {
class FakeFuchsiaPM implements FuchsiaPM {
String _appName;
@override
......@@ -710,7 +878,46 @@ class MockFuchsiaPM extends Mock implements FuchsiaPM {
}
}
class MockFuchsiaKernelCompiler extends Mock implements FuchsiaKernelCompiler {
class FailingPM implements FuchsiaPM {
@override
Future<bool> init(String buildPath, String appName) async {
return false;
}
@override
Future<bool> genkey(String buildPath, String outKeyPath) async {
return false;
}
@override
Future<bool> build(
String buildPath, String keyPath, String manifestPath) async {
return false;
}
@override
Future<bool> archive(
String buildPath, String keyPath, String manifestPath) async {
return false;
}
@override
Future<bool> newrepo(String repoPath) async {
return false;
}
@override
Future<Process> serve(String repoPath, String host, int port) async {
return _createMockProcess(exitCode: 6);
}
@override
Future<bool> publish(String repoPath, String packagePath) async {
return false;
}
}
class FakeFuchsiaKernelCompiler implements FuchsiaKernelCompiler {
@override
Future<void> build({
@required FuchsiaProject fuchsiaProject,
......@@ -724,7 +931,18 @@ class MockFuchsiaKernelCompiler extends Mock implements FuchsiaKernelCompiler {
}
}
class MockFuchsiaDevFinder extends Mock implements FuchsiaDevFinder {
class FailingKernelCompiler implements FuchsiaKernelCompiler {
@override
Future<void> build({
@required FuchsiaProject fuchsiaProject,
@required String target, // E.g., lib/main.dart
BuildInfo buildInfo = BuildInfo.debug,
}) async {
throwToolExit('Build process failed');
}
}
class FakeFuchsiaDevFinder implements FuchsiaDevFinder {
@override
Future<List<String>> list() async {
return <String>['192.168.42.172 scare-cable-skip-joy'];
......@@ -736,14 +954,33 @@ class MockFuchsiaDevFinder extends Mock implements FuchsiaDevFinder {
}
}
class FailingDevFinder implements FuchsiaDevFinder {
@override
Future<List<String>> list() async {
return null;
}
@override
Future<String> resolve(String deviceName) async {
return null;
}
}
class MockFuchsiaSdk extends Mock implements FuchsiaSdk {
MockFuchsiaSdk({
FuchsiaPM pm,
FuchsiaKernelCompiler compiler,
FuchsiaDevFinder devFinder,
}) : fuchsiaPM = pm ?? FakeFuchsiaPM(),
fuchsiaKernelCompiler = compiler ?? FakeFuchsiaKernelCompiler(),
fuchsiaDevFinder = devFinder ?? FakeFuchsiaDevFinder();
@override
final FuchsiaPM fuchsiaPM = MockFuchsiaPM();
final FuchsiaPM fuchsiaPM;
@override
final FuchsiaKernelCompiler fuchsiaKernelCompiler =
MockFuchsiaKernelCompiler();
final FuchsiaKernelCompiler fuchsiaKernelCompiler;
@override
final FuchsiaDevFinder fuchsiaDevFinder = MockFuchsiaDevFinder();
final FuchsiaDevFinder fuchsiaDevFinder;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment