Unverified Commit a1a801a4 authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

[flutter_tools] add debugging to ios/core_devices.dart (#142187)

Add debugging for #141892 to detect when the temp file mysteriously
disappears after running devicectl.
parent e1e1c36d
...@@ -78,8 +78,16 @@ class IOSCoreDeviceControl { ...@@ -78,8 +78,16 @@ class IOSCoreDeviceControl {
]; ];
try { try {
await _processUtils.run(command, throwOnError: true); final RunResult result = await _processUtils.run(command, throwOnError: true);
if (!output.existsSync()) {
_logger.printError('After running the command ${command.join(' ')} the file');
_logger.printError('${output.path} was expected to exist, but it did not.');
_logger.printError('The process exited with code ${result.exitCode} and');
_logger.printError('Stdout:\n\n${result.stdout.trim()}\n');
_logger.printError('Stderr:\n\n${result.stderr.trim()}');
throw StateError('Expected the file ${output.path} to exist but it did not');
}
final String stringOutput = output.readAsStringSync(); final String stringOutput = output.readAsStringSync();
_logger.printTrace(stringOutput); _logger.printTrace(stringOutput);
......
...@@ -87,7 +87,7 @@ void main() { ...@@ -87,7 +87,7 @@ void main() {
setUp(() { setUp(() {
logger = BufferLogger.test(); logger = BufferLogger.test();
fakeProcessManager = FakeProcessManager.empty(); fakeProcessManager = FakeProcessManager.empty();
// TODO(fujino): make this FakeProcessManager.empty() // TODO(fujino): re-use fakeProcessManager
xcode = Xcode.test(processManager: FakeProcessManager.any()); xcode = Xcode.test(processManager: FakeProcessManager.any());
deviceControl = IOSCoreDeviceControl( deviceControl = IOSCoreDeviceControl(
logger: logger, logger: logger,
...@@ -1355,6 +1355,51 @@ invalid JSON ...@@ -1355,6 +1355,51 @@ invalid JSON
expect(fakeProcessManager, hasNoRemainingExpectations); expect(fakeProcessManager, hasNoRemainingExpectations);
}); });
testWithoutContext('Handles json file mysteriously disappearing', () async {
final Directory tempDir = fileSystem.systemTempDirectory
.childDirectory('core_devices.rand0');
final File tempFile = tempDir.childFile('core_device_list.json');
final List<String> args = <String>[
'xcrun',
'devicectl',
'list',
'devices',
'--timeout',
'5',
'--json-output',
tempFile.path,
];
fakeProcessManager.addCommand(FakeCommand(
command: args,
onRun: (_) {
// Simulate that this command deleted tempFile, did not create a
// new one, and exited successfully
expect(tempFile, exists);
tempFile.deleteSync();
expect(tempFile, isNot(exists));
},
));
await expectLater(
() => deviceControl.getCoreDevices(),
throwsA(
isA<StateError>().having(
(StateError e) => e.message,
'message',
contains('Expected the file ${tempFile.path} to exist but it did not'),
),
),
);
expect(
logger.errorText,
contains('After running the command xcrun devicectl list devices '
'--timeout 5 --json-output ${tempFile.path} the file\n'
'${tempFile.path} was expected to exist, but it did not',
),
);
expect(fakeProcessManager, hasNoRemainingExpectations);
});
testWithoutContext('No devices', () async { testWithoutContext('No devices', () async {
const String deviceControlOutput = ''' const String deviceControlOutput = '''
{ {
......
...@@ -66,15 +66,25 @@ void main() { ...@@ -66,15 +66,25 @@ void main() {
tryToDelete(fileSystem.directory(tempDirectory)); tryToDelete(fileSystem.directory(tempDirectory));
} }
}, skip: Platform.isWindows); // [intended] Windows doesn't support sending signals so we don't care if it can store the PID. }, skip: Platform.isWindows); // [intended] Windows doesn't support sending signals so we don't care if it can store the PID.
testWithoutContext('flutter run handle SIGUSR1/2', () async {
testWithoutContext('flutter run handle SIGUSR1/2 run', () async {
final String tempDirectory = fileSystem.systemTempDirectory.createTempSync('flutter_overall_experience_test.').resolveSymbolicLinksSync(); final String tempDirectory = fileSystem.systemTempDirectory.createTempSync('flutter_overall_experience_test.').resolveSymbolicLinksSync();
final String pidFile = fileSystem.path.join(tempDirectory, 'flutter.pid'); final String pidFile = fileSystem.path.join(tempDirectory, 'flutter.pid');
final String testDirectory = fileSystem.path.join(flutterRoot, 'dev', 'integration_tests', 'ui'); final String testDirectory = fileSystem.path.join(flutterRoot, 'dev', 'integration_tests', 'ui');
final String testScript = fileSystem.path.join('lib', 'commands.dart'); final String testScript = fileSystem.path.join('lib', 'commands.dart');
late int pid; late int pid;
final List<String> command = <String>[
'run',
'-dflutter-tester',
'--report-ready',
'--pid-file',
pidFile,
'--no-devtools',
testScript,
];
try { try {
final ProcessTestResult result = await runFlutter( final ProcessTestResult result = await runFlutter(
<String>['run', '-dflutter-tester', '--report-ready', '--pid-file', pidFile, '--no-devtools', testScript], command,
testDirectory, testDirectory,
<Transition>[ <Transition>[
Multiple(<Pattern>['Flutter run key commands.', 'called paint'], handler: (String line) { Multiple(<Pattern>['Flutter run key commands.', 'called paint'], handler: (String line) {
...@@ -108,16 +118,22 @@ void main() { ...@@ -108,16 +118,22 @@ void main() {
'called main', 'called main',
'called paint', 'called paint',
]); ]);
expect(result.stdout.where((String line) => !line.startsWith('called ')), <Object>[ expect(
// logs start after we receive the response to sending SIGUSR1 result.stdout.where((String line) => !line.startsWith('called ')),
'Performing hot reload...'.padRight(progressMessageWidth), <Object>[
startsWith('Reloaded 0 libraries in '), // logs start after we receive the response to sending SIGUSR1
'Performing hot restart...'.padRight(progressMessageWidth), 'Performing hot reload...'.padRight(progressMessageWidth),
startsWith('Restarted application in '), startsWith('Reloaded 0 libraries in '),
'', // this newline is the one for after we hit "q" 'Performing hot restart...'.padRight(progressMessageWidth),
'Application finished.', startsWith('Restarted application in '),
'ready', '', // this newline is the one for after we hit "q"
]); 'Application finished.',
'ready',
],
reason: 'stdout from command ${command.join(' ')} was unexpected, '
'full Stdout:\n\n${result.stdout.join('\n')}\n\n'
'Stderr:\n\n${result.stderr.join('\n')}',
);
expect(result.exitCode, 0); expect(result.exitCode, 0);
} finally { } finally {
tryToDelete(fileSystem.directory(tempDirectory)); tryToDelete(fileSystem.directory(tempDirectory));
...@@ -128,9 +144,16 @@ void main() { ...@@ -128,9 +144,16 @@ void main() {
final String tempDirectory = fileSystem.systemTempDirectory.createTempSync('flutter_overall_experience_test.').resolveSymbolicLinksSync(); final String tempDirectory = fileSystem.systemTempDirectory.createTempSync('flutter_overall_experience_test.').resolveSymbolicLinksSync();
final String testDirectory = fileSystem.path.join(flutterRoot, 'dev', 'integration_tests', 'ui'); final String testDirectory = fileSystem.path.join(flutterRoot, 'dev', 'integration_tests', 'ui');
final String testScript = fileSystem.path.join('lib', 'commands.dart'); final String testScript = fileSystem.path.join('lib', 'commands.dart');
final List<String> command = <String>[
'run',
'-dflutter-tester',
'--report-ready',
'--no-devtools',
testScript,
];
try { try {
final ProcessTestResult result = await runFlutter( final ProcessTestResult result = await runFlutter(
<String>['run', '-dflutter-tester', '--report-ready', '--no-devtools', testScript], command,
testDirectory, testDirectory,
<Transition>[ <Transition>[
Multiple(<Pattern>['Flutter run key commands.', 'called main', 'called paint'], handler: (String line) { Multiple(<Pattern>['Flutter run key commands.', 'called main', 'called paint'], handler: (String line) {
...@@ -171,23 +194,28 @@ void main() { ...@@ -171,23 +194,28 @@ void main() {
// debugPaintSizeEnabled = false: // debugPaintSizeEnabled = false:
'called paint', 'called paint',
]); ]);
expect(result.stdout.where((String line) => !line.startsWith('called ')), <Object>[ expect(
// logs start after we receive the response to hitting "r" result.stdout.where((String line) => !line.startsWith('called ')), <Object>[
'Performing hot reload...'.padRight(progressMessageWidth), // logs start after we receive the response to hitting "r"
startsWith('Reloaded 0 libraries in '), 'Performing hot reload...'.padRight(progressMessageWidth),
'ready', startsWith('Reloaded 0 libraries in '),
'', // this newline is the one for after we hit "R" 'ready',
'Performing hot restart...'.padRight(progressMessageWidth), '', // this newline is the one for after we hit "R"
startsWith('Restarted application in '), 'Performing hot restart...'.padRight(progressMessageWidth),
'ready', startsWith('Restarted application in '),
'', // newline for after we hit "p" the first time 'ready',
'ready', '', // newline for after we hit "p" the first time
'', // newline for after we hit "p" the second time 'ready',
'ready', '', // newline for after we hit "p" the second time
'', // this newline is the one for after we hit "q" 'ready',
'Application finished.', '', // this newline is the one for after we hit "q"
'ready', 'Application finished.',
]); 'ready',
],
reason: 'stdout from command ${command.join(' ')} was unexpected, '
'full Stdout:\n\n${result.stdout.join('\n')}\n\n'
'Stderr:\n\n${result.stderr.join('\n')}',
);
expect(result.exitCode, 0); expect(result.exitCode, 0);
} finally { } finally {
tryToDelete(fileSystem.directory(tempDirectory)); tryToDelete(fileSystem.directory(tempDirectory));
......
...@@ -175,8 +175,8 @@ Future<ProcessTestResult> runFlutter( ...@@ -175,8 +175,8 @@ Future<ProcessTestResult> runFlutter(
bool debug = false, bool debug = false,
bool logging = true, bool logging = true,
Duration expectedMaxDuration = const Duration( Duration expectedMaxDuration = const Duration(
minutes: minutes: 10,
10), // must be less than test timeout of 15 minutes! See ../../dart_test.yaml. ), // must be less than test timeout of 15 minutes! See ../../dart_test.yaml.
}) async { }) async {
const LocalPlatform platform = LocalPlatform(); const LocalPlatform platform = LocalPlatform();
final Stopwatch clock = Stopwatch()..start(); final Stopwatch clock = Stopwatch()..start();
......
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