Unverified Commit 540c7476 authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

Revert "Keep LLDB connection to iOS device alive while running from CLI. (#36194)" (#36293)

This reverts commit 5501a1c1.
parent e17f8d36
...@@ -129,11 +129,6 @@ Future<Process> runCommand( ...@@ -129,11 +129,6 @@ Future<Process> runCommand(
/// If [filter] is non-null, all lines that do not match it are removed. If /// If [filter] is non-null, all lines that do not match it are removed. If
/// [mapFunction] is present, all lines that match [filter] are also forwarded /// [mapFunction] is present, all lines that match [filter] are also forwarded
/// to [mapFunction] for further processing. /// to [mapFunction] for further processing.
///
/// If [detachFilter] is non-null, the returned future will complete with exit code `0`
/// when the process outputs something matching [detachFilter] to stderr. The process will
/// continue in the background, and the final exit code will not be reported. [filter] is
/// not considered on lines matching [detachFilter].
Future<int> runCommandAndStreamOutput( Future<int> runCommandAndStreamOutput(
List<String> cmd, { List<String> cmd, {
String workingDirectory, String workingDirectory,
...@@ -143,9 +138,7 @@ Future<int> runCommandAndStreamOutput( ...@@ -143,9 +138,7 @@ Future<int> runCommandAndStreamOutput(
RegExp filter, RegExp filter,
StringConverter mapFunction, StringConverter mapFunction,
Map<String, String> environment, Map<String, String> environment,
RegExp detachFilter,
}) async { }) async {
final Completer<int> result = Completer<int>();
final Process process = await runCommand( final Process process = await runCommand(
cmd, cmd,
workingDirectory: workingDirectory, workingDirectory: workingDirectory,
...@@ -155,15 +148,6 @@ Future<int> runCommandAndStreamOutput( ...@@ -155,15 +148,6 @@ Future<int> runCommandAndStreamOutput(
final StreamSubscription<String> stdoutSubscription = process.stdout final StreamSubscription<String> stdoutSubscription = process.stdout
.transform<String>(utf8.decoder) .transform<String>(utf8.decoder)
.transform<String>(const LineSplitter()) .transform<String>(const LineSplitter())
.map((String line) {
if (detachFilter != null && detachFilter.hasMatch(line) && !result.isCompleted) {
// Detach from the process, assuming it will eventually complete successfully.
// Output printed after detaching (incl. stdout and stderr) will still be
// processed by [filter] and [mapFunction].
result.complete(0);
}
return line;
})
.where((String line) => filter == null || filter.hasMatch(line)) .where((String line) => filter == null || filter.hasMatch(line))
.listen((String line) { .listen((String line) {
if (mapFunction != null) if (mapFunction != null)
...@@ -187,10 +171,8 @@ Future<int> runCommandAndStreamOutput( ...@@ -187,10 +171,8 @@ Future<int> runCommandAndStreamOutput(
printError('$prefix$line', wrap: false); printError('$prefix$line', wrap: false);
}); });
// Wait for stdout to be fully processed before completing with the exit code (non-detached case), // Wait for stdout to be fully processed
// because process.exitCode may complete first causing flaky tests. If the process detached, // because process.exitCode may complete first causing flaky tests.
// we at least have a predictable output for stdout, although (unavoidably) not for stderr.
Future<void> readOutput() async {
await waitGroup<void>(<Future<void>>[ await waitGroup<void>(<Future<void>>[
stdoutSubscription.asFuture<void>(), stdoutSubscription.asFuture<void>(),
stderrSubscription.asFuture<void>(), stderrSubscription.asFuture<void>(),
...@@ -201,14 +183,7 @@ Future<int> runCommandAndStreamOutput( ...@@ -201,14 +183,7 @@ Future<int> runCommandAndStreamOutput(
stderrSubscription.cancel(), stderrSubscription.cancel(),
]); ]);
// Complete the future if the we did not detach the process yet. return await process.exitCode;
if (!result.isCompleted) {
result.complete(process.exitCode);
}
}
unawaited(readOutput());
return result.future;
} }
/// Runs the [command] interactively, connecting the stdin/stdout/stderr /// Runs the [command] interactively, connecting the stdin/stdout/stderr
......
...@@ -48,7 +48,7 @@ class IOSDeploy { ...@@ -48,7 +48,7 @@ class IOSDeploy {
'--bundle', '--bundle',
bundlePath, bundlePath,
'--no-wifi', '--no-wifi',
'--noninteractive', '--justlaunch',
]; ];
if (launchArguments.isNotEmpty) { if (launchArguments.isNotEmpty) {
launchCommand.add('--args'); launchCommand.add('--args');
...@@ -66,14 +66,11 @@ class IOSDeploy { ...@@ -66,14 +66,11 @@ class IOSDeploy {
iosDeployEnv['PATH'] = '/usr/bin:${iosDeployEnv['PATH']}'; iosDeployEnv['PATH'] = '/usr/bin:${iosDeployEnv['PATH']}';
iosDeployEnv.addEntries(<MapEntry<String, String>>[cache.dyLdLibEntry]); iosDeployEnv.addEntries(<MapEntry<String, String>>[cache.dyLdLibEntry]);
// Detach from the ios-deploy process once it' outputs 'autoexit', signaling that the
// App has been started and LLDB is in "autopilot" mode.
return await runCommandAndStreamOutput( return await runCommandAndStreamOutput(
launchCommand, launchCommand,
mapFunction: _monitorInstallationFailure, mapFunction: _monitorInstallationFailure,
trace: true, trace: true,
environment: iosDeployEnv, environment: iosDeployEnv,
detachFilter: RegExp('.*autoexit.*')
); );
} }
......
...@@ -2,20 +2,17 @@ ...@@ -2,20 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async';
import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/base/process.dart';
import 'package:flutter_tools/src/base/terminal.dart'; import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/convert.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/context.dart'; import '../../src/context.dart';
import '../../src/mocks.dart' show FakeProcess, MockProcess, MockProcessManager; import '../../src/mocks.dart' show MockProcess, MockProcessManager;
void main() { void main() {
group('process exceptions', () { group('process exceptions', () {
...@@ -93,43 +90,6 @@ void main() { ...@@ -93,43 +90,6 @@ void main() {
Platform: () => FakePlatform.fromPlatform(const LocalPlatform())..stdoutSupportsAnsi = false, Platform: () => FakePlatform.fromPlatform(const LocalPlatform())..stdoutSupportsAnsi = false,
}); });
}); });
group('runCommandAndStreamOutput', () {
ProcessManager mockProcessManager;
const Utf8Encoder utf8 = Utf8Encoder();
setUp(() {
mockProcessManager = PlainMockProcessManager();
});
testUsingContext('detach after detachFilter matches', () async {
// Create a fake process which outputs three lines ("foo", "bar" and "baz")
// to stdout, nothing to stderr, and doesn't exit.
final Process fake = FakeProcess(
exitCode: Completer<int>().future,
stdout: Stream<List<int>>.fromIterable(
<String>['foo\n', 'bar\n', 'baz\n'].map(utf8.convert)),
stderr: const Stream<List<int>>.empty());
when(mockProcessManager.start(<String>['test1'])).thenAnswer((_) => Future<Process>.value(fake));
// Detach when we see "bar", and check that:
// - mapFunction still gets run on "baz",
// - we don't wait for the process to terminate (it never will), and
// - we get an exit-code of 0 back.
bool seenBaz = false;
String mapFunction(String line) {
seenBaz = seenBaz || line == 'baz';
return line;
}
final int exitCode = await runCommandAndStreamOutput(
<String>['test1'], mapFunction: mapFunction, detachFilter: RegExp('.*baz.*'));
expect(exitCode, 0);
expect(seenBaz, true);
}, overrides: <Type, Generator>{ProcessManager: () => mockProcessManager});
});
} }
class PlainMockProcessManager extends Mock implements ProcessManager {} class PlainMockProcessManager extends Mock implements ProcessManager {}
...@@ -199,9 +199,6 @@ class MockStream<T> implements Stream<T> { ...@@ -199,9 +199,6 @@ class MockStream<T> implements Stream<T> {
@override @override
Stream<T> where(bool test(T event)) => MockStream<T>(); Stream<T> where(bool test(T event)) => MockStream<T>();
@override
Stream<S> map<S>(S Function(T) _) => MockStream<S>();
@override @override
StreamSubscription<T> listen(void onData(T event), { Function onError, void onDone(), bool cancelOnError }) { StreamSubscription<T> listen(void onData(T event), { Function onError, void onDone(), bool cancelOnError }) {
return MockStreamSubscription<T>(); return MockStreamSubscription<T>();
......
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