An SDK directory that exists but cannot be read passed discovery, and the analyzer then died with a raw FileSystemException stack trace. This happens for real under macOS privacy protection: a Flutter SDK under ~/Documents stats fine but every open fails, and every app whose package_config.json names that flutterRoot crashed: Unhandled exception: FileSystemException(path=.../dart-sdk/lib/_internal/allowed_experiments.json; ...) The chosen SDK is now probed before the analysis collection is built, and an unreadable one is a PipeException naming the path, where it was discovered from, and the --sdk remedy. The last-resort fallback to the running Dart SDK took the executable's directory (<sdk>/bin) as the SDK root, which never contains lib/libraries.json, so it could never succeed. sdkFromExecutable now maps <sdk>/bin/dart to <sdk>.
61 lines
2.1 KiB
Dart
61 lines
2.1 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:pipe/pipe.dart';
|
|
import 'package:pipe/src/sdk.dart';
|
|
import 'package:test/test.dart';
|
|
|
|
/// A directory laid out like a Dart SDK: `bin/dart`, `lib/libraries.json`,
|
|
/// `version`.
|
|
Directory _fakeSdk(String label) {
|
|
final sdk = Directory.systemTemp.createTempSync('pipe-$label');
|
|
File('${sdk.path}/version').writeAsStringSync('3.13.0\n');
|
|
File('${sdk.path}/lib/libraries.json')
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('{}');
|
|
File('${sdk.path}/bin/dart').createSync(recursive: true);
|
|
return sdk;
|
|
}
|
|
|
|
void main() {
|
|
test('an SDK that exists but cannot be read is a clear error', () {
|
|
// macOS privacy protection (a Flutter SDK under ~/Documents) lets stat
|
|
// succeed while every open fails, so discovery accepted the SDK and the
|
|
// analyzer later died with a raw FileSystemException stack trace.
|
|
final sdk = _fakeSdk('unreadable-sdk');
|
|
final version = File('${sdk.path}/version');
|
|
Process.runSync('chmod', ['000', version.path]);
|
|
try {
|
|
version.readAsStringSync();
|
|
markTestSkipped('chmod 000 does not restrict this process');
|
|
return;
|
|
} on FileSystemException {
|
|
// Expected: the restriction is real, so the check below is meaningful.
|
|
}
|
|
|
|
final resolution = resolveSdk(explicit: sdk.path);
|
|
expect(
|
|
() => requireReadableSdk(resolution),
|
|
throwsA(
|
|
isA<PipeException>()
|
|
.having((e) => e.message, 'message', contains(sdk.path))
|
|
.having((e) => e.remedy, 'remedy', contains('--sdk')),
|
|
),
|
|
);
|
|
});
|
|
|
|
test('a readable SDK passes the check', () {
|
|
final sdk = _fakeSdk('readable-sdk');
|
|
expect(
|
|
() => requireReadableSdk(resolveSdk(explicit: sdk.path)),
|
|
returnsNormally,
|
|
);
|
|
});
|
|
|
|
test('the running dart binary maps to its SDK root, not to bin/', () {
|
|
// dirname(<sdk>/bin/dart) is <sdk>/bin, which never contains
|
|
// lib/libraries.json, so this fallback could never succeed.
|
|
final sdk = _fakeSdk('runtime-sdk');
|
|
expect(sdkFromExecutable('${sdk.path}/bin/dart'), sdk.path);
|
|
expect(sdkFromExecutable('${sdk.path}/version'), isNull);
|
|
});
|
|
}
|