Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "Re-enable scenario tests on Android" #33813

Merged
merged 1 commit into from
Jun 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 2 additions & 10 deletions .ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,24 +100,16 @@ targets:
timeout: 60

- name: Linux Android Emulator Tests
bringup: true # Recipe issue https://github.com/flutter/flutter/issues/86427
recipe: engine/scenarios
enabled_branches:
- main
- master
properties:
dependencies: >-
[
{"dependency": "android_virtual_device", "version": "31"},
{"dependency": "goldctl"}
{"dependency": "android_virtual_device", "version": "31"}
]
upload_packages: "true"
clobber: "true"
timeout: 60
runIf:
- DEPS
- .ci.yaml
- testing/**
- shell/platforms/android/**

- name: Linux Benchmarks
enabled_branches:
Expand Down
3 changes: 1 addition & 2 deletions shell/platform/android/android_context_gl_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,7 @@ TEST(AndroidSurfaceGL, CreateSnapshopSurfaceWhenOnscreenSurfaceIsNull) {
EXPECT_NE(android_surface->GetOnscreenSurface(), nullptr);
}

// TODO(https://github.com/flutter/flutter/issues/104463): Flaky test.
TEST(AndroidContextGl, DISABLED_MSAAx4) {
TEST(AndroidContextGl, MSAAx4) {
GrMockOptions main_context_options;
sk_sp<GrDirectContext> main_context =
GrDirectContext::MakeMock(&main_context_options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,6 @@ void AndroidExternalViewEmbedder::SubmitFrame(

for (size_t i = 0; i < current_frame_view_count; i++) {
int64_t view_id = composition_order_[i];
if (picture_recorders_.at(view_id)->getRecordingCanvas() == nullptr) {
continue;
}

sk_sp<SkPicture> picture =
picture_recorders_.at(view_id)->finishRecordingAsPicture();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@ private static class Connection {
}

synchronized void writeFile(String name, byte[] fileContent) throws IOException {
final ByteBuffer buffer = ByteBuffer.allocate(name.length() + fileContent.length + 8);
// See ScreenshotBlobTransformer#bind in screenshot_transformer.dart for consumer side.
final ByteBuffer buffer = ByteBuffer.allocate(name.length() + fileContent.length + 4);
buffer.putInt(name.length());
buffer.putInt(fileContent.length);
buffer.put(name.getBytes());
buffer.put(fileContent);
final byte[] bytes = buffer.array();
Expand Down Expand Up @@ -120,9 +118,6 @@ public static void capture(@NonNull TestableFlutterActivity activity, @NonNull S

final Bitmap bitmap =
InstrumentationRegistry.getInstrumentation().getUiAutomation().takeScreenshot();
if (bitmap == null) {
throw new RuntimeException("failed to capture screenshot");
}
final ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
ScreenshotUtil.writeFile(captureName, out.toByteArray());
Expand Down
3 changes: 3 additions & 0 deletions testing/scenario_app/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize"
android:theme="@style/FullScreenScreenshot"
android:exported="true">
<intent-filter>
<action android:name="com.google.intent.action.TEST_LOOP" />
Expand All @@ -31,6 +32,7 @@
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize"
android:theme="@style/FullScreenScreenshot"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand All @@ -43,6 +45,7 @@
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize"
android:theme="@style/FullScreenScreenshot"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,8 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.Window;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.WindowCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.core.view.WindowInsetsControllerCompat;
import io.flutter.Log;
import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.embedding.engine.loader.FlutterLoader;
Expand All @@ -39,8 +35,6 @@ public abstract class TestActivity extends TestableFlutterActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
hideSystemBars(getWindow());

final Intent launchIntent = getIntent();
if ("com.google.intent.action.TEST_LOOP".equals(launchIntent.getAction())) {
if (Build.VERSION.SDK_INT > 22) {
Expand Down Expand Up @@ -164,12 +158,4 @@ public void run() {
}
});
}

private static void hideSystemBars(Window window) {
final WindowInsetsControllerCompat insetController =
WindowCompat.getInsetsController(window, window.getDecorView());
insetController.setSystemBarsBehavior(
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
insetController.hide(WindowInsetsCompat.Type.systemBars());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,11 @@
<item name="colorAccent">@color/colorAccent</item>
</style>

<style name="FullScreenScreenshot">
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>

</resources>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
108 changes: 15 additions & 93 deletions testing/scenario_app/bin/android_integration_tests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@
// found in the LICENSE file.

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:args/args.dart';
import 'package:path/path.dart';
import 'package:process/process.dart';
import 'package:skia_gold_client/skia_gold_client.dart';

import 'utils/logs.dart';
import 'utils/process_manager_extension.dart';
import 'utils/screenshot_transformer.dart';

const int tcpPort = 3001;

Expand All @@ -35,12 +34,9 @@ void main(List<String> args) async {
panic(<String>['cannot find adb: $adb', 'make sure to run gclient sync']);
}

final String scenarioAppPath = join(outDir.path, 'scenario_app');
final String logcatPath = join(scenarioAppPath, 'logcat.txt');
final String screenshotPath = join(scenarioAppPath, 'screenshots');
final String apkOutPath = join(scenarioAppPath, 'app', 'outputs', 'apk');
final File testApk = File(join(apkOutPath, 'androidTest', 'debug', 'app-debug-androidTest.apk'));
final File appApk = File(join(apkOutPath, 'debug', 'app-debug.apk'));
final String apkOut = join(outDir.path, 'scenario_app', 'app', 'outputs', 'apk');
final File testApk = File(join(apkOut, 'androidTest', 'debug', 'app-debug-androidTest.apk'));
final File appApk = File(join(apkOut, 'debug', 'app-debug.apk'));

if (!testApk.existsSync()) {
panic(<String>['test apk does not exist: ${testApk.path}', 'make sure to build the selected engine variant']);
Expand All @@ -54,97 +50,30 @@ void main(List<String> args) async {
// This allows the test process to start a connection with the host, and write the bytes
// for the screenshots.
// On LUCI, the host uploads the screenshots to Skia Gold.
SkiaGoldClient? skiaGoldClient;
late ServerSocket server;
final List<Future<void>> pendingComparisons = <Future<void>>[];
await step('Starting server...', () async {
server = await ServerSocket.bind(InternetAddress.anyIPv4, tcpPort);
stdout.writeln('listening on host ${server.address.address}:${server.port}');
server.listen((Socket client) {
stdout.writeln('client connected ${client.remoteAddress.address}:${client.remotePort}');
client.transform(const ScreenshotBlobTransformer()).listen((Screenshot screenshot) {
final String fileName = screenshot.filename;
final Uint8List fileContent = screenshot.fileContent;

client.listen((Uint8List data) {
final int fnameLen = data.buffer.asByteData().getInt32(0);
final String fileName = utf8.decode(data.buffer.asUint8List(4, fnameLen));
final Uint8List fileContent = data.buffer.asUint8List(4 + fnameLen);
log('host received ${fileContent.lengthInBytes} bytes for screenshot `$fileName`');
assert(skiaGoldClient != null, 'expected Skia Gold client');
late File goldenFile;
try {
goldenFile = File(join(screenshotPath, fileName))..writeAsBytesSync(fileContent, flush: true);
} on FileSystemException catch (err) {
panic(<String>['failed to create screenshot $fileName: ${err.toString()}']);
}
log('wrote ${goldenFile.absolute.path}');
if (isSkiaGoldClientAvailable) {
final Future<void> comparison = skiaGoldClient!
.addImg(fileName, goldenFile, screenshotSize: fileContent.lengthInBytes)
.catchError((dynamic err) {
panic(<String>['skia gold comparison failed: ${err.toString()}']);
});
pendingComparisons.add(comparison);
}
},
onError: (dynamic err) {
panic(<String>['error while receiving bytes: ${err.toString()}']);
},
cancelOnError: true);
});
});
});

late Process logcatProcess;
final IOSink logcat = File(logcatPath).openWrite();
final StringBuffer logcat = StringBuffer();
try {
await step('Creating screenshot directory...', () async {
Directory(screenshotPath).createSync(recursive: true);
});

await step('Starting logcat...', () async {
final int exitCode = await pm.runAndForward(<String>[adb.path, 'logcat', '-c']);
if (exitCode != 0) {
panic(<String>['could not clear logs']);
}
logcatProcess = await pm.start(<String>[adb.path, 'logcat', '-T', '1']);
logcatProcess = await pm.start(<String>[adb.path, 'logcat', '*:E', '-T', '1']);
unawaited(pipeProcessStreams(logcatProcess, out: logcat));
});

await step('Configuring emulator...', () async {
final int exitCode = await pm.runAndForward(<String>[
adb.path,
'shell',
'settings',
'put',
'secure',
'immersive_mode_confirmations',
'confirmed',
]);
if (exitCode != 0) {
panic(<String>['could not configure emulator']);
}
});

await step('Get API level of connected device...', () async {
final ProcessResult apiLevelProcessResult = await pm.run(<String>[adb.path, 'shell', 'getprop', 'ro.build.version.sdk']);
if (apiLevelProcessResult.exitCode != 0) {
panic(<String>['could not get API level of the connected device']);
}
final String connectedDeviceAPILevel = (apiLevelProcessResult.stdout as String).trim();
log('using API level $connectedDeviceAPILevel');
skiaGoldClient = SkiaGoldClient(
outDir,
dimensions: <String, String>{
'AndroidAPILevel': connectedDeviceAPILevel,
},
);
});

await step('Skia Gold auth...', () async {
if (isSkiaGoldClientAvailable) {
await skiaGoldClient!.auth();
log('skia gold client is available');
} else {
log('skia gold client is unavailable');
}
});

await step('Reverse port...', () async {
final int exitCode = await pm.runAndForward(<String>[adb.path, 'reverse', 'tcp:3000', 'tcp:$tcpPort']);
if (exitCode != 0) {
Expand Down Expand Up @@ -207,18 +136,11 @@ void main(List<String> args) async {
});

await step('Killing logcat process...', () async {
final bool delivered = logcatProcess.kill(ProcessSignal.sigkill);
assert(delivered);
logcatProcess.kill();
});

await step('Wait for Skia gold comparisons...', () async {
await Future.wait(pendingComparisons);
await step('Dumping logcat (Errors only)...', () async {
stdout.write(logcat);
});

await step('Flush logcat...', () async {
await logcat.flush();
});

exit(0);
}
}
29 changes: 7 additions & 22 deletions testing/scenario_app/bin/utils/process_manager_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,31 @@ import 'dart:io';

import 'package:process/process.dart';

/// Pipes the [process] streams and writes them to [out] sink.
/// If [out] is null, then the current [Process.stdout] is used as the sink.
/// If [includePrefix] is true, then the prefix `[stdout]` or `[stderr]` is
/// added before writting to the [out] sink.
Future<int> pipeProcessStreams(
Process process, {
StringSink? out,
bool includePrefix = true,
}) async {
/// Pipes the [process] streams and writes them to [out].
Future<int> pipeProcessStreams(Process process, {StringSink? out}) async {
out ??= stdout;
final Completer<void> stdoutCompleter = Completer<void>();
final StreamSubscription<String> stdoutSub = process.stdout
.transform(utf8.decoder)
.transform<String>(const LineSplitter())
.listen((String line) {
if (includePrefix) {
out!.writeln('[stdout] $line');
} else {
out!.writeln(line);
}
out!.writeln('[stdout] $line');
}, onDone: stdoutCompleter.complete);

final Completer<void> stderrCompleter = Completer<void>();
final StreamSubscription<String> stderrSub = process.stderr
.transform(utf8.decoder)
.transform<String>(const LineSplitter())
.listen((String line) {
if (includePrefix) {
out!.writeln('[stderr] $line');
} else {
out!.writeln(line);
}
out!.writeln('[stderr] $line');
}, onDone: stderrCompleter.complete);

final int exitCode = await process.exitCode;
await stderrSub.cancel();
await stdoutSub.cancel();

await stdoutCompleter.future;
await stderrCompleter.future;

stderrSub.cancel();
stdoutSub.cancel();
return exitCode;
}

Expand Down
Loading