Unverified Commit 9369bd32 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Wait for ios-deploy stdout before closing logLine stream (#99041)

parent f0d44472
...@@ -395,11 +395,11 @@ class IOSDeployDebugger { ...@@ -395,11 +395,11 @@ class IOSDeployDebugger {
_monitorIOSDeployFailure(line, _logger); _monitorIOSDeployFailure(line, _logger);
_logger.printTrace(line); _logger.printTrace(line);
}); });
unawaited(_iosDeployProcess!.exitCode.then((int status) { unawaited(_iosDeployProcess!.exitCode.then((int status) async {
_logger.printTrace('ios-deploy exited with code $exitCode'); _logger.printTrace('ios-deploy exited with code $exitCode');
_debuggerState = _IOSDeployDebuggerState.detached; _debuggerState = _IOSDeployDebuggerState.detached;
unawaited(stdoutSubscription.cancel()); await stdoutSubscription.cancel();
unawaited(stderrSubscription.cancel()); await stderrSubscription.cancel();
}).whenComplete(() async { }).whenComplete(() async {
if (_debuggerOutput.hasListener) { if (_debuggerOutput.hasListener) {
// Tell listeners the process died. // Tell listeners the process died.
......
...@@ -75,8 +75,9 @@ void main () { ...@@ -75,8 +75,9 @@ void main () {
interfaceType: IOSDeviceConnectionInterface.network, interfaceType: IOSDeviceConnectionInterface.network,
); );
expect(iosDeployDebugger.logLines, emits('Did finish launching.'));
expect(await iosDeployDebugger.launchAndAttach(), isTrue); expect(await iosDeployDebugger.launchAndAttach(), isTrue);
expect(await iosDeployDebugger.logLines.toList(), <String>['Did finish launching.']); await iosDeployDebugger.logLines.drain();
expect(processManager, hasNoRemainingExpectations); expect(processManager, hasNoRemainingExpectations);
expect(appDeltaDirectory, exists); expect(appDeltaDirectory, exists);
}); });
...@@ -92,7 +93,6 @@ void main () { ...@@ -92,7 +93,6 @@ void main () {
testWithoutContext('debugger attached and stopped', () async { testWithoutContext('debugger attached and stopped', () async {
final StreamController<List<int>> stdin = StreamController<List<int>>(); final StreamController<List<int>> stdin = StreamController<List<int>>();
final Stream<String> stdinStream = stdin.stream.transform<String>(const Utf8Decoder());
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand( FakeCommand(
command: const <String>['ios-deploy'], command: const <String>['ios-deploy'],
...@@ -108,24 +108,47 @@ void main () { ...@@ -108,24 +108,47 @@ void main () {
final Stream<String> logLines = iosDeployDebugger.logLines final Stream<String> logLines = iosDeployDebugger.logLines
..listen(receivedLogLines.add); ..listen(receivedLogLines.add);
expect(await iosDeployDebugger.launchAndAttach(), isTrue); expect(iosDeployDebugger.logLines, emitsInOrder(<String>[
await logLines.toList();
expect(receivedLogLines, <String>[
'success', // ignore first "success" from lldb, but log subsequent ones from real logging. 'success', // ignore first "success" from lldb, but log subsequent ones from real logging.
'Log on attach1', 'Log on attach1',
'Log on attach2', 'Log on attach2',
'', '',
'', '',
'Log after process stop' 'Log after process stop'
]); ]));
expect(logger.traceText, contains('PROCESS_STOPPED')); expect(stdin.stream.transform<String>(const Utf8Decoder()), emitsInOrder(<String>[
expect(logger.traceText, contains('thread backtrace all'));
expect(logger.traceText, contains('* thread #1'));
expect(await stdinStream.take(3).toList(), <String>[
'thread backtrace all', 'thread backtrace all',
'\n', '\n',
'process detach', 'process detach',
]));
expect(await iosDeployDebugger.launchAndAttach(), isTrue);
await logLines.drain();
expect(logger.traceText, contains('PROCESS_STOPPED'));
expect(logger.traceText, contains('thread backtrace all'));
expect(logger.traceText, contains('* thread #1'));
});
testWithoutContext('handle processing logging after process exit', () async {
final StreamController<List<int>> stdin = StreamController<List<int>>();
// Make sure we don't hit a race where logging processed after the process exits
// causes listeners to receive logging on the closed logLines stream.
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand(
command: const <String>['ios-deploy'],
stdout: 'stdout: "(lldb) run\r\nsuccess\r\n',
stdin: IOSink(stdin.sink),
outputFollowsExit: true,
),
]); ]);
final IOSDeployDebugger iosDeployDebugger = IOSDeployDebugger.test(
processManager: processManager,
logger: logger,
);
expect(iosDeployDebugger.logLines, emitsDone);
expect(await iosDeployDebugger.launchAndAttach(), isFalse);
await iosDeployDebugger.logLines.drain();
}); });
testWithoutContext('app exit', () async { testWithoutContext('app exit', () async {
...@@ -139,21 +162,17 @@ void main () { ...@@ -139,21 +162,17 @@ void main () {
processManager: processManager, processManager: processManager,
logger: logger, logger: logger,
); );
final List<String> receivedLogLines = <String>[]; expect(iosDeployDebugger.logLines, emitsInOrder(<String>[
final Stream<String> logLines = iosDeployDebugger.logLines
..listen(receivedLogLines.add);
expect(await iosDeployDebugger.launchAndAttach(), isTrue);
await logLines.toList();
expect(receivedLogLines, <String>[
'Log on attach', 'Log on attach',
'Log after process exit', 'Log after process exit',
]); ]));
expect(await iosDeployDebugger.launchAndAttach(), isTrue);
await iosDeployDebugger.logLines.drain();
}); });
testWithoutContext('app crash', () async { testWithoutContext('app crash', () async {
final StreamController<List<int>> stdin = StreamController<List<int>>(); final StreamController<List<int>> stdin = StreamController<List<int>>();
final Stream<String> stdinStream = stdin.stream.transform<String>(const Utf8Decoder());
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand( FakeCommand(
command: const <String>['ios-deploy'], command: const <String>['ios-deploy'],
...@@ -166,24 +185,24 @@ void main () { ...@@ -166,24 +185,24 @@ void main () {
processManager: processManager, processManager: processManager,
logger: logger, logger: logger,
); );
final List<String> receivedLogLines = <String>[];
final Stream<String> logLines = iosDeployDebugger.logLines
..listen(receivedLogLines.add);
expect(await iosDeployDebugger.launchAndAttach(), isTrue); expect(iosDeployDebugger.logLines, emitsInOrder(<String>[
await logLines.toList();
expect(receivedLogLines, <String>[
'Log on attach', 'Log on attach',
'* thread #1, stop reason = Assertion failed:', '* thread #1, stop reason = Assertion failed:',
]); ]));
expect(logger.traceText, contains('Process 6156 stopped'));
expect(logger.traceText, contains('thread backtrace all')); expect(stdin.stream.transform<String>(const Utf8Decoder()), emitsInOrder(<String>[
expect(logger.traceText, contains('* thread #1'));
expect(await stdinStream.take(3).toList(), <String>[
'thread backtrace all', 'thread backtrace all',
'\n', '\n',
'process detach', 'process detach',
]); ]));
expect(await iosDeployDebugger.launchAndAttach(), isTrue);
await iosDeployDebugger.logLines.drain();
expect(logger.traceText, contains('Process 6156 stopped'));
expect(logger.traceText, contains('thread backtrace all'));
expect(logger.traceText, contains('* thread #1'));
}); });
testWithoutContext('attach failed', () async { testWithoutContext('attach failed', () async {
...@@ -198,15 +217,12 @@ void main () { ...@@ -198,15 +217,12 @@ void main () {
processManager: processManager, processManager: processManager,
logger: logger, logger: logger,
); );
final List<String> receivedLogLines = <String>[];
final Stream<String> logLines = iosDeployDebugger.logLines
..listen(receivedLogLines.add);
expect(await iosDeployDebugger.launchAndAttach(), isFalse);
await logLines.toList();
// Debugger lines are double spaced, separated by an extra \r\n. Skip the extra lines. // Debugger lines are double spaced, separated by an extra \r\n. Skip the extra lines.
// Still include empty lines other than the extra added newlines. // Still include empty lines other than the extra added newlines.
expect(receivedLogLines, isEmpty); expect(iosDeployDebugger.logLines, emitsDone);
expect(await iosDeployDebugger.launchAndAttach(), isFalse);
await iosDeployDebugger.logLines.drain();
}); });
testWithoutContext('no provisioning profile 1, stdout', () async { testWithoutContext('no provisioning profile 1, stdout', () async {
...@@ -273,7 +289,6 @@ void main () { ...@@ -273,7 +289,6 @@ void main () {
testWithoutContext('detach', () async { testWithoutContext('detach', () async {
final StreamController<List<int>> stdin = StreamController<List<int>>(); final StreamController<List<int>> stdin = StreamController<List<int>>();
final Stream<String> stdinStream = stdin.stream.transform<String>(const Utf8Decoder());
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand( FakeCommand(
command: const <String>[ command: const <String>[
...@@ -286,9 +301,9 @@ void main () { ...@@ -286,9 +301,9 @@ void main () {
final IOSDeployDebugger iosDeployDebugger = IOSDeployDebugger.test( final IOSDeployDebugger iosDeployDebugger = IOSDeployDebugger.test(
processManager: processManager, processManager: processManager,
); );
expect(stdin.stream.transform<String>(const Utf8Decoder()), emits('process detach'));
await iosDeployDebugger.launchAndAttach(); await iosDeployDebugger.launchAndAttach();
iosDeployDebugger.detach(); iosDeployDebugger.detach();
expect(await stdinStream.first, 'process detach');
}); });
testWithoutContext('stop with backtrace', () async { testWithoutContext('stop with backtrace', () async {
......
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