68c50f7f92
Previously, we were switching test paths to drive `D` at the start of the test, after the `package_config.json` file had already been generated to drive `C`; as a result, it didn't apply. We will need the `package_config.json` to apply when we flip the null safety flag (so that the inputs to the migration tool are considered opted out prior to migration). This CL reworks the test so that the paths are modified as part of test set-up, so `package_config.json` gets put in the right place. Fixes #43883. Bug: https://github.com/dart-lang/sdk/issues/43883 Change-Id: I08f79ddb07d7a5ecf640370a32334a7ceb92ceff Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/169421 Reviewed-by: Samuel Rawlins <srawlins@google.com> Commit-Queue: Paul Berry <paulberry@google.com>
200 lines
7.4 KiB
Dart
200 lines
7.4 KiB
Dart
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import 'package:nnbd_migration/src/front_end/migration_info.dart';
|
|
import 'package:nnbd_migration/src/front_end/path_mapper.dart';
|
|
import 'package:nnbd_migration/src/front_end/region_renderer.dart';
|
|
import 'package:nnbd_migration/src/front_end/web/edit_details.dart';
|
|
import 'package:path/path.dart' as p;
|
|
import 'package:test/test.dart';
|
|
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
|
|
|
import 'nnbd_migration_test_base.dart';
|
|
|
|
void main() {
|
|
defineReflectiveSuite(() {
|
|
defineReflectiveTests(RegionRendererTest);
|
|
defineReflectiveTests(RegionRendererTestDriveD);
|
|
});
|
|
}
|
|
|
|
@reflectiveTest
|
|
class RegionRendererTest extends RegionRendererTestBase {
|
|
/// Returns the basename of [testFile], used in traces.
|
|
String get _testFileBasename =>
|
|
resourceProvider.pathContext.basename(testFile);
|
|
|
|
Future<void> test_informationalRegion_containsTrace() async {
|
|
await buildInfoForSingleTestFile('f(int a) => a.isEven;',
|
|
migratedContent: 'f(int a) => a.isEven;');
|
|
var response = renderRegion(5);
|
|
expect(response.traces, hasLength(1));
|
|
var trace = response.traces[0];
|
|
expect(trace.description, equals('Non-nullability reason'));
|
|
}
|
|
|
|
Future<void> test_informationalRegion_containsTraceEntryDescriptions() async {
|
|
await buildInfoForSingleTestFile('f(int a) => a.isEven;',
|
|
migratedContent: 'f(int a) => a.isEven;');
|
|
var response = renderRegion(5);
|
|
expect(response.traces, hasLength(1));
|
|
var trace = response.traces[0];
|
|
expect(trace.entries, hasLength(2));
|
|
expect(trace.entries[0].description,
|
|
equals('parameter 0 of f ($_testFileBasename:1:3)'));
|
|
expect(trace.entries[1].description, equals('data flow'));
|
|
}
|
|
|
|
Future<void> test_informationalRegion_containsTraceLinks() async {
|
|
await buildInfoForSingleTestFile('f(int a) => a.isEven;',
|
|
migratedContent: 'f(int a) => a.isEven;');
|
|
var response = renderRegion(5);
|
|
expect(response.traces, hasLength(1));
|
|
var trace = response.traces[0];
|
|
var entry = trace.entries[0];
|
|
expect(entry.link, isNotNull);
|
|
var testFileUriPath = resourceProvider.pathContext.toUri(testFile).path;
|
|
expect(entry.link.href,
|
|
equals('$testFileUriPath?offset=2&line=1&authToken=AUTH_TOKEN'));
|
|
expect(entry.link.path,
|
|
equals(resourceProvider.pathContext.toUri(_testFileBasename).path));
|
|
}
|
|
|
|
Future<void> test_modifiedOutput_containsExplanation() async {
|
|
await buildInfoForSingleTestFile('int a = null;',
|
|
migratedContent: 'int? a = null;');
|
|
var response = renderRegion(3);
|
|
expect(response.explanation, equals("Changed type 'int' to be nullable"));
|
|
}
|
|
|
|
Future<void> test_modifiedOutput_containsPath() async {
|
|
await buildInfoForSingleTestFile('int a = null;',
|
|
migratedContent: 'int? a = null;');
|
|
var response = renderRegion(3);
|
|
expect(response.displayPath, equals(testFile));
|
|
expect(response.uriPath, equals(pathMapper.map(testFile)));
|
|
expect(response.line, equals(1));
|
|
}
|
|
|
|
Future<void> test_modifiedOutput_containsTraceForNullabilityReason() async {
|
|
await buildInfoForSingleTestFile('int a = null;',
|
|
migratedContent: 'int? a = null;');
|
|
var response = renderRegion(3);
|
|
expect(response.traces, hasLength(1));
|
|
var trace = response.traces[0];
|
|
expect(trace.description, equals('Nullability reason'));
|
|
expect(trace.entries, hasLength(4));
|
|
expect(trace.entries[0].description, equals('a ($_testFileBasename:1:1)'));
|
|
expect(trace.entries[1].description, equals('data flow'));
|
|
expect(trace.entries[2].description,
|
|
equals('null literal ($_testFileBasename:1:9)'));
|
|
expect(trace.entries[3].description, equals('literal expression'));
|
|
}
|
|
|
|
Future<void> test_unmodifiedOutput_containsExplanation() async {
|
|
await buildInfoForSingleTestFile('f(int a) => a.isEven;',
|
|
migratedContent: 'f(int a) => a.isEven;');
|
|
var response = renderRegion(5);
|
|
expect(response.explanation, equals("Type 'int' was not made nullable"));
|
|
}
|
|
|
|
Future<void> test_unmodifiedOutput_containsPath() async {
|
|
await buildInfoForSingleTestFile('f(int a) => a.isEven;',
|
|
migratedContent: 'f(int a) => a.isEven;');
|
|
var response = renderRegion(5);
|
|
expect(response.displayPath, equals(testFile));
|
|
expect(response.uriPath, equals(pathMapper.map(testFile)));
|
|
expect(response.line, equals(1));
|
|
}
|
|
}
|
|
|
|
class RegionRendererTestBase extends NnbdMigrationTestBase {
|
|
PathMapper pathMapper;
|
|
|
|
/// Render the region at [offset], using a [MigrationInfo] which knows only
|
|
/// about the library at `infos.single`.
|
|
EditDetails renderRegion(int offset) {
|
|
var migrationInfo =
|
|
MigrationInfo(infos, {}, resourceProvider.pathContext, projectPath);
|
|
var unitInfo = infos.single;
|
|
var region = unitInfo.regionAt(offset);
|
|
pathMapper = PathMapper(resourceProvider);
|
|
return RegionRenderer(
|
|
region, unitInfo, migrationInfo, pathMapper, 'AUTH_TOKEN')
|
|
.render();
|
|
}
|
|
}
|
|
|
|
@reflectiveTest
|
|
class RegionRendererTestDriveD extends RegionRendererTestBase {
|
|
@override
|
|
String get homePath => _switchToDriveD(super.homePath);
|
|
|
|
@override
|
|
void setUp() {
|
|
super.setUp();
|
|
}
|
|
|
|
Future<void>
|
|
test_informationalRegion_containsTraceLinks_separateDrive() async {
|
|
// See https://github.com/dart-lang/sdk/issues/43178. Linking from a file on
|
|
// one drive to a file on another drive can cause problems.
|
|
await buildInfoForSingleTestFile(r'''
|
|
f(List<int> a) {
|
|
if (1 == 2) List.from(a);
|
|
}
|
|
g() {
|
|
f(null);
|
|
}
|
|
''', migratedContent: r'''
|
|
f(List<int >? a) {
|
|
if (1 == 2) List.from(a!);
|
|
}
|
|
g() {
|
|
f(null);
|
|
}
|
|
''');
|
|
var response = renderRegion(44); // The inserted null-check.
|
|
expect(response.displayPath,
|
|
equals(_switchToDriveD(convertPath('/home/tests/bin/test.dart'))));
|
|
expect(response.traces, hasLength(2));
|
|
var trace = response.traces[1];
|
|
expect(trace.description, equals('Non-nullability reason'));
|
|
expect(trace.entries, hasLength(1));
|
|
var entry = trace.entries[0];
|
|
expect(entry.link, isNotNull);
|
|
var sdkCoreLib = convertPath('/sdk/lib/core/core.dart');
|
|
var sdkCoreLibUriPath = resourceProvider.pathContext.toUri(sdkCoreLib).path;
|
|
var coreLibText = resourceProvider.getFile(sdkCoreLib).readAsStringSync();
|
|
var expectedOffset =
|
|
'List.from'.allMatches(coreLibText).single.start + 'List.'.length;
|
|
var expectedLine =
|
|
'\n'.allMatches(coreLibText.substring(0, expectedOffset)).length + 1;
|
|
expect(
|
|
entry.link.href,
|
|
equals('$sdkCoreLibUriPath?'
|
|
'offset=$expectedOffset&'
|
|
'line=$expectedLine&'
|
|
'authToken=AUTH_TOKEN'));
|
|
// On Windows, the path will simply be the absolute path to the core
|
|
// library, because there is no relative route from C:\ to D:\. On Posix,
|
|
// the path is relative.
|
|
var expectedLinkPath = resourceProvider.pathContext.style == p.Style.windows
|
|
? sdkCoreLibUriPath
|
|
: '../../..$sdkCoreLibUriPath';
|
|
expect(entry.link.path, equals(expectedLinkPath));
|
|
}
|
|
|
|
/// On Windows, replace the C:\ relative root in [path] with the D:\ relative
|
|
/// root.
|
|
///
|
|
/// On Posix, nothing is be replaced.
|
|
String _switchToDriveD(String path) {
|
|
assert(resourceProvider.pathContext.isAbsolute(path));
|
|
return resourceProvider
|
|
.convertPath(path)
|
|
.replaceFirst(RegExp('^C:\\\\'), 'D:\\');
|
|
}
|
|
}
|