Unverified Commit 62c9c89d authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] split start app android tests into new file (#52906)

parent 5b956fd8
......@@ -117,7 +117,7 @@ class ProtocolDiscovery {
Uri uri;
try {
uri = _getObservatoryUri(line);
} on FormatException catch(error, stackTrace) {
} on FormatException catch (error, stackTrace) {
_uriStreamController.addError(error, stackTrace);
}
if (uri == null) {
......
// 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 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_device.dart';
import 'package:flutter_tools/src/android/android_sdk.dart';
import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:mockito/mockito.dart';
import '../../src/common.dart';
import '../../src/context.dart';
const FakeCommand kAdbVersionCommand = FakeCommand(
command: <String>['adb', 'version'],
stdout: 'Android Debug Bridge version 1.0.39',
);
const FakeCommand kStartServer = FakeCommand(
command: <String>['adb', 'start-server'],
);
const FakeCommand kShaCommand = FakeCommand(
command: <String>[
'adb',
'-s',
'1234',
'shell',
'echo',
'-n',
'',
'>',
'/data/local/tmp/sky.FlutterApp.sha1',
],
);
void main() {
FileSystem fileSystem;
FakeProcessManager processManager;
AndroidSdk androidSdk;
setUp(() {
processManager = FakeProcessManager.list(<FakeCommand>[]);
fileSystem = MemoryFileSystem.test();
androidSdk = MockAndroidSdk();
when(androidSdk.adbPath).thenReturn('adb');
when(androidSdk.licensesAvailable).thenReturn(false);
});
for (final TargetPlatform targetPlatform in <TargetPlatform>[
TargetPlatform.android_arm,
TargetPlatform.android_arm64,
TargetPlatform.android_x64,
]) {
testUsingContext('AndroidDevice.startApp allows release builds on $targetPlatform', () async {
const String deviceId = '1234';
final String arch = getNameForAndroidArch(
getAndroidArchForName(getNameForTargetPlatform(targetPlatform)));
final AndroidDevice device = AndroidDevice(deviceId, modelID: 'TestModel');
final File apkFile = fileSystem.file('app.apk')..createSync();
final AndroidApk apk = AndroidApk(
id: 'FlutterApp',
file: apkFile,
launchActivity: 'FlutterActivity',
versionCode: 1,
);
processManager.addCommand(kAdbVersionCommand);
processManager.addCommand(kStartServer);
// This configures the target platform of the device.
processManager.addCommand(FakeCommand(
command: const <String>['adb', '-s', '1234', 'shell', 'getprop'],
stdout: '[ro.product.cpu.abi]: [$arch]',
));
processManager.addCommand(const FakeCommand(
command: <String>['adb', '-s', '1234', 'shell', 'am', 'force-stop', 'FlutterApp'],
));
processManager.addCommand(const FakeCommand(
command: <String>['adb', '-s', '1234', 'shell', 'pm', 'list', 'packages', 'FlutterApp'],
));
processManager.addCommand(kAdbVersionCommand);
processManager.addCommand(kStartServer);
processManager.addCommand(const FakeCommand(
command: <String>['adb', '-s', '1234', 'install', '-t', '-r', 'app.apk'],
));
processManager.addCommand(kShaCommand);
processManager.addCommand(const FakeCommand(
command: <String>[
'adb',
'-s',
'1234',
'shell',
'am',
'start',
'-a',
'android.intent.action.RUN',
'-f',
'0x20000000',
'--ez', 'enable-background-compilation', 'true',
'--ez', 'enable-dart-profiling', 'true',
'FlutterActivity',
],
));
final LaunchResult launchResult = await device.startApp(
apk,
prebuiltApplication: true,
debuggingOptions: DebuggingOptions.disabled(
BuildInfo.release,
),
platformArgs: <String, dynamic>{},
);
expect(launchResult.started, true);
expect(processManager.hasRemainingExpectations, false);
}, overrides: <Type, Generator>{
AndroidSdk: () => androidSdk,
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
}
testUsingContext('AndroidDevice.startApp does not allow release builds on x86', () async {
const String deviceId = '1234';
final AndroidDevice device = AndroidDevice(deviceId, modelID: 'TestModel');
final File apkFile = fileSystem.file('app.apk')..createSync();
final AndroidApk apk = AndroidApk(
id: 'FlutterApp',
file: apkFile,
launchActivity: 'FlutterActivity',
versionCode: 1,
);
processManager.addCommand(kAdbVersionCommand);
processManager.addCommand(kStartServer);
// This configures the target platform of the device.
processManager.addCommand(const FakeCommand(
command: <String>['adb', '-s', '1234', 'shell', 'getprop'],
stdout: '[ro.product.cpu.abi]: [x86]',
));
final LaunchResult launchResult = await device.startApp(
apk,
prebuiltApplication: true,
debuggingOptions: DebuggingOptions.disabled(
BuildInfo.release,
),
platformArgs: <String, dynamic>{},
);
expect(launchResult.started, false);
expect(processManager.hasRemainingExpectations, false);
}, overrides: <Type, Generator>{
AndroidSdk: () => androidSdk,
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
testUsingContext('AndroidDevice.startApp forwards all supported debugging options', () async {
const String deviceId = '1234';
final AndroidDevice device = AndroidDevice(deviceId, modelID: 'TestModel');
final File apkFile = fileSystem.file('app.apk')..createSync();
final AndroidApk apk = AndroidApk(
id: 'FlutterApp',
file: apkFile,
launchActivity: 'FlutterActivity',
versionCode: 1,
);
// These commands are required to install and start the app
processManager.addCommand(kAdbVersionCommand);
processManager.addCommand(kStartServer);
processManager.addCommand(const FakeCommand(
command: <String>['adb', '-s', '1234', 'shell', 'getprop'],
));
processManager.addCommand(const FakeCommand(
command: <String>['adb', '-s', '1234', 'shell', 'am', 'force-stop', 'FlutterApp'],
));
processManager.addCommand(const FakeCommand(
command: <String>['adb', '-s', '1234', 'shell', 'pm', 'list', 'packages', 'FlutterApp'],
));
processManager.addCommand(kAdbVersionCommand);
processManager.addCommand(kStartServer);
// TODO(jonahwilliams): investigate why this doesn't work.
// This doesn't work with the current Android log reader implementation.
processManager.addCommand(const FakeCommand(
command: <String>['adb', '-s', '1234', 'install', '-t', '-r', 'app.apk'],
stdout: '\n\nObservatory listening on http://127.0.0.1:456\n\n',
));
processManager.addCommand(kShaCommand);
processManager.addCommand(const FakeCommand(
command: <String>[
'adb',
'-s',
'1234',
'logcat',
'-v',
'time',
],
));
// This command contains all launch arguments.
processManager.addCommand(const FakeCommand(
command: <String>[
'adb',
'-s',
'1234',
'shell',
'am',
'start',
'-a',
'android.intent.action.RUN',
'-f',
'0x20000000',
// The DebuggingOptions arguments go here.
'--ez', 'enable-background-compilation', 'true',
'--ez', 'enable-dart-profiling', 'true',
'--ez', 'enable-software-rendering', 'true',
'--ez', 'skia-deterministic-rendering', 'true',
'--ez', 'trace-skia', 'true',
'--ez', 'trace-whitelist', 'bar,baz',
'--ez', 'trace-systrace', 'true',
'--ez', 'endless-trace-buffer', 'true',
'--ez', 'dump-skp-on-shader-compilation', 'true',
'--ez', 'cache-sksl', 'true',
'--ez', 'enable-checked-mode', 'true',
'--ez', 'verify-entry-points', 'true',
'--ez', 'start-paused', 'true',
'--ez', 'disable-service-auth-codes', 'true',
'--es', 'dart-flags', 'foo',
'--ez', 'use-test-fonts', 'true',
'--ez', 'verbose-logging', 'true',
'FlutterActivity',
],
));
final LaunchResult launchResult = await device.startApp(
apk,
prebuiltApplication: true,
debuggingOptions: DebuggingOptions.enabled(
BuildInfo.debug,
startPaused: true,
disableServiceAuthCodes: true,
dartFlags: 'foo',
enableSoftwareRendering: true,
skiaDeterministicRendering: true,
traceSkia: true,
traceWhitelist: 'bar,baz',
traceSystrace: true,
endlessTraceBuffer: true,
dumpSkpOnShaderCompilation: true,
cacheSkSL: true,
useTestFonts: true,
verboseSystemLogs: true,
),
platformArgs: <String, dynamic>{},
);
// This fails to start due to observatory discovery issues.
expect(launchResult.started, false);
expect(processManager.hasRemainingExpectations, false);
}, overrides: <Type, Generator>{
AndroidSdk: () => androidSdk,
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
}
class MockAndroidSdk extends Mock implements AndroidSdk {}
......@@ -9,7 +9,6 @@ import 'dart:typed_data';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_console.dart';
import 'package:flutter_tools/src/android/android_device.dart';
import 'package:flutter_tools/src/android/android_sdk.dart';
import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
......@@ -23,167 +22,12 @@ import 'package:platform/platform.dart';
import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/mocks.dart';
class MockFile extends Mock implements File {
@override
bool existsSync() {
return true;
}
@override
String get path => '.';
}
class MockAndroidApk extends Mock implements AndroidApk {
@override
String get id => '0';
@override
File get file => MockFile();
}
class MockAndroidSdkVersion extends Mock implements AndroidSdkVersion {}
void main() {
group('android_device', () {
testUsingContext('stores the requested id', () {
const String deviceId = '1234';
final AndroidDevice device = AndroidDevice(deviceId);
expect(device.id, deviceId);
});
group('startApp', () {
MockAndroidApk mockApk;
MockProcessManager mockProcessManager;
MockAndroidSdk mockAndroidSdk;
setUp(() {
mockApk = MockAndroidApk();
mockProcessManager = MockProcessManager();
mockAndroidSdk = MockAndroidSdk();
});
void _setupMockAndroidSdk(AndroidSdk mockAndroidSdk) {
when(mockAndroidSdk.licensesAvailable).thenReturn(true);
when(mockAndroidSdk.latestVersion).thenReturn(MockAndroidSdkVersion());
}
void _setupMockProcessManager(ProcessManager mockProcessManager,
String deviceId, ProcessResult getPropResult) {
final File adbExe = globals.fs.file(getAdbPath(androidSdk));
when(mockProcessManager.run(
<String>[adbExe.path, '-s', deviceId, 'shell', 'getprop'],
stdoutEncoding: latin1,
stderrEncoding: latin1,
)).thenAnswer((_) async {
return getPropResult;
});
when(mockProcessManager.run(any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment')))
.thenAnswer((_) async {
return ProcessResult(0, 0, '', '');
});
when(mockProcessManager.start(any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment')))
.thenAnswer((_) async {
return FakeProcess();
});
}
testUsingContext('succeeds with --cache-sksl', () async {
const String deviceId = '1234';
final AndroidDevice device =
AndroidDevice(deviceId, modelID: 'TestModel');
final Directory sdkDir = MockAndroidSdk.createSdkDirectory();
globals.config.setValue('android-sdk', sdkDir.path);
_setupMockAndroidSdk(mockAndroidSdk);
_setupMockProcessManager(mockProcessManager, deviceId,
ProcessResult(0, 0, '[ro.build.version.sdk]: [24]', ''));
final LaunchResult launchResult = await device.startApp(
mockApk,
prebuiltApplication: true,
debuggingOptions: DebuggingOptions.disabled(
const BuildInfo(BuildMode.release, null, treeShakeIcons: false),
cacheSkSL: true,
),
platformArgs: <String, dynamic>{},
);
expect(launchResult.started, isTrue);
expect(
verify(mockProcessManager.run(captureAny)).captured.last.join(','),
contains(<String>['--ez', 'cache-sksl', 'true'].join(',')));
}, overrides: <Type, Generator>{
AndroidSdk: () => mockAndroidSdk,
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => mockProcessManager,
});
testUsingContext('can run a release build on x64', () async {
const String deviceId = '1234';
final AndroidDevice device =
AndroidDevice(deviceId, modelID: 'TestModel');
final Directory sdkDir = MockAndroidSdk.createSdkDirectory();
globals.config.setValue('android-sdk', sdkDir.path);
_setupMockAndroidSdk(mockAndroidSdk);
_setupMockProcessManager(mockProcessManager, deviceId,
ProcessResult(0, 0, '[ro.build.version.sdk]: [24]', ''));
final LaunchResult launchResult = await device.startApp(
mockApk,
prebuiltApplication: true,
debuggingOptions: DebuggingOptions.disabled(
const BuildInfo(BuildMode.release, null, treeShakeIcons: false),
),
platformArgs: <String, dynamic>{},
);
expect(launchResult.started, true);
}, overrides: <Type, Generator>{
AndroidSdk: () => mockAndroidSdk,
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => mockProcessManager,
});
testUsingContext('test trace whitelist flag', () async {
const String deviceId = '1234';
final AndroidDevice device =
AndroidDevice(deviceId, modelID: 'TestModel');
final Directory sdkDir = MockAndroidSdk.createSdkDirectory();
globals.config.setValue('android-sdk', sdkDir.path);
_setupMockAndroidSdk(mockAndroidSdk);
_setupMockProcessManager(mockProcessManager, deviceId,
ProcessResult(0, 0, '[ro.build.version.sdk]: [24]', ''));
final LaunchResult launchResult = await device.startApp(
mockApk,
prebuiltApplication: true,
debuggingOptions: DebuggingOptions.disabled(
const BuildInfo(BuildMode.profile, null, treeShakeIcons: false),
traceWhitelist: 'foo',
),
platformArgs: <String, dynamic>{},
);
expect(launchResult.started, isTrue);
expect(
verify(mockProcessManager.run(captureAny)).captured.last.join(','),
contains(<String>['--ez', 'trace-whitelist', 'foo'].join(',')));
}, overrides: <Type, Generator>{
AndroidSdk: () => mockAndroidSdk,
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => mockProcessManager,
});
});
testUsingContext('AndroidDevice stores the requested id', () {
const String deviceId = '1234';
final AndroidDevice device = AndroidDevice(deviceId);
expect(device.id, deviceId);
});
group('parseAdbDeviceProperties', () {
......
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