blob: 6390b6c8ee50da4a3cb70de3b47b5a5ff1e1cfe3 [file] [log] [blame]
// Copyright 2020 The Dart Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.9
import 'package:dwds/dwds.dart';
import 'package:dwds/src/debugging/location.dart';
import 'package:dwds/src/debugging/modules.dart';
import 'package:dwds/src/loaders/strategy.dart';
import 'package:dwds/src/utilities/dart_uri.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:test/test.dart';
import 'debugger_test.dart';
void main() {
const lines = 100;
const lineLength = 150;
globalLoadStrategy = MockLoadStrategy();
final dartUri = DartUri('org-dartlang://web/main.dart');
final assetReader = FakeAssetReader();
final modules = MockModules();
final locations = Locations(assetReader, modules, '');
locations.initialize('fake_entrypoint');
group('JS locations |', () {
group('location |', () {
test('is zero based', () async {
final loc = JsLocation.fromZeroBased(_module, 0, 0);
expect(loc, _matchJsLocation(0, 0));
});
test('can compare to other location', () async {
final loc00 = JsLocation.fromZeroBased(_module, 0, 0);
final loc01 = JsLocation.fromZeroBased(_module, 0, 1);
final loc10 = JsLocation.fromZeroBased(_module, 1, 0);
final loc11 = JsLocation.fromZeroBased(_module, 1, 1);
expect(loc00.compareTo(loc01), isNegative);
expect(loc00.compareTo(loc10), isNegative);
expect(loc00.compareTo(loc10), isNegative);
expect(loc00.compareTo(loc11), isNegative);
expect(loc00.compareTo(loc00), isZero);
expect(loc11.compareTo(loc00), isPositive);
});
});
group('best location |', () {
test('does not return location for setup code', () async {
final location = await locations.locationForJs(_module, 0, 0);
expect(location, isNull);
});
test('prefers precise match', () async {
final location = await locations.locationForJs(_module, 37, 0);
expect(location, _matchLocationForJs(37, 0));
});
test('finds a match in the beginning of the line', () async {
final location = await locations.locationForJs(_module, 39, 4);
expect(location, _matchLocationForJs(39, 0));
});
test('finds a match in the middle of the line', () async {
final location = await locations.locationForJs(_module, 39, 10);
expect(location, _matchLocationForJs(39, 6));
});
test('finds a match on a previous line', () async {
final location = await locations.locationForJs(_module, 44, 0);
expect(location, _matchLocationForJs(43, 18));
});
test('finds a match on a previous line with a closer match after',
() async {
final location =
await locations.locationForJs(_module, 44, lineLength - 1);
expect(location, _matchLocationForJs(43, 18));
});
test('finds a match on the last line', () async {
final location =
await locations.locationForJs(_module, lines - 1, lineLength - 1);
expect(location, _matchLocationForJs(50, 2));
});
test('finds a match on invalid line', () async {
final location =
await locations.locationForJs(_module, lines, lineLength - 1);
expect(location, _matchLocationForJs(50, 2));
});
test('finds a match on invalid column on the same line', () async {
final location = await locations.locationForJs(_module, 50, lineLength);
expect(location, _matchLocationForJs(50, 2));
});
test('finds a match on invalid column on a previous line', () async {
final location =
await locations.locationForJs(_module, lines - 1, lineLength);
expect(location, _matchLocationForJs(50, 2));
});
});
});
group('Dart locations |', () {
group('location |', () {
test('is one based', () async {
final loc = DartLocation.fromZeroBased(dartUri, 0, 0);
expect(loc, _matchDartLocation(1, 1));
});
test('can compare to other locations', () async {
final loc00 = DartLocation.fromZeroBased(dartUri, 0, 0);
final loc01 = DartLocation.fromZeroBased(dartUri, 0, 1);
final loc10 = DartLocation.fromZeroBased(dartUri, 1, 0);
final loc11 = DartLocation.fromZeroBased(dartUri, 1, 1);
expect(loc00.compareTo(loc01), isNegative);
expect(loc00.compareTo(loc10), isNegative);
expect(loc00.compareTo(loc10), isNegative);
expect(loc00.compareTo(loc11), isNegative);
expect(loc00.compareTo(loc00), isZero);
expect(loc11.compareTo(loc00), isPositive);
});
});
group('best location |', () {
test('does not return location for dart lines not mapped to JS',
() async {
final location = await locations.locationForDart(dartUri, 0, 0);
expect(location, isNull);
});
test('returns location after on the same line', () async {
final location = await locations.locationForDart(dartUri, 11, 0);
expect(location, _matchLocationForDart(11, 3));
});
test('return null on invalid line', () async {
final location = await locations.locationForDart(dartUri, lines, 0);
expect(location, isNull);
});
test('return null on invalid column', () async {
final location =
await locations.locationForDart(dartUri, lines - 1, lineLength);
expect(location, isNull);
});
});
});
}
Matcher _matchLocationForDart(int line, int column) => isA<Location>().having(
(l) => l.dartLocation, 'dartLocation', _matchDartLocation(line, column));
Matcher _matchLocationForJs(int line, int column) => isA<Location>()
.having((l) => l.jsLocation, 'jsLocation', _matchJsLocation(line, column));
Matcher _matchDartLocation(int line, int column) => isA<DartLocation>()
.having((l) => l.line, 'line', line)
.having((l) => l.column, 'column', column);
Matcher _matchJsLocation(int line, int column) => isA<JsLocation>()
.having((l) => l.line, 'line', line)
.having((l) => l.column, 'column', column);
const _module = 'packages/module';
const _serverPath = 'package/module.js';
const _sourceMapPath = 'packages/module.js.map';
class MockLoadStrategy implements LoadStrategy {
@override
Future<String> bootstrapFor(String entrypoint) async => 'dummy_bootstrap';
@override
shelf.Handler get handler =>
(request) => (request.url.path == 'someDummyPath')
? shelf.Response.ok('some dummy response')
: null;
@override
String get id => 'dummy-id';
@override
String get moduleFormat => 'dummy-format';
@override
String get loadLibrariesModule => '';
@override
String get loadLibrariesSnippet => '';
@override
String loadLibrarySnippet(String libraryUri) => '';
@override
String get loadModuleSnippet => '';
@override
ReloadConfiguration get reloadConfiguration => ReloadConfiguration.none;
@override
String loadClientSnippet(String clientScript) => 'dummy-load-client-snippet';
@override
Future<String> moduleForServerPath(
String entrypoint, String serverPath) async =>
_module;
@override
Future<String> serverPathForModule(String entrypoint, String module) async =>
_serverPath;
@override
Future<String> sourceMapPathForModule(
String entrypoint, String module) async =>
_sourceMapPath;
@override
String serverPathForAppUri(String appUri) => _serverPath;
@override
MetadataProvider metadataProviderFor(String entrypoint) => null;
@override
void trackEntrypoint(String entrypoint) {}
@override
Future<Map<String, ModuleInfo>> moduleInfoForEntrypoint(String entrypoint) =>
throw UnimplementedError();
}
class MockModules implements Modules {
@override
void initialize(String entrypoint) {}
@override
Future<Uri> libraryForSource(String serverPath) {
throw UnimplementedError();
}
@override
Future<String> moduleForSource(String serverPath) async => _module;
@override
Future<Map<String, String>> modules() {
throw UnimplementedError();
}
@override
Future<String> moduleForlibrary(String libraryUri) {
throw UnimplementedError();
}
}