mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
[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.
This commit is contained in:
parent
e1e1c36d49
commit
a1a801a48d
@ -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() {
|
|||||||
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
|
|||||||
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() {
|
|||||||
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() {
|
|||||||
'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() {
|
|||||||
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() {
|
|||||||
// 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(
|
|||||||
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();
|
||||||
|
Loading…
Reference in New Issue
Block a user