// Copyright (c) 2023, 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 'dart:io'; import 'package:dds/src/dap/utils.dart'; import 'package:path/path.dart' as path; import 'package:test/test.dart'; main() { group('isResolvableUri', () { test('false for files', () async { expect(isResolvableUri(Uri.parse('file:///foo/bar.dart')), isFalse); expect(isResolvableUri(Uri.parse('file:///c:/foo/bar.dart')), isFalse); }); test('false for http(s)', () async { expect(isResolvableUri(Uri.parse('http://example.org')), isFalse); expect(isResolvableUri(Uri.parse('https://example.org')), isFalse); }); test('true for dart:foo', () async { expect(isResolvableUri(Uri.parse('dart:async')), isTrue); expect(isResolvableUri(Uri.parse('dart:async/foo')), isTrue); }); test('true for package:foo', () async { expect(isResolvableUri(Uri.parse('package:foo')), isTrue); expect(isResolvableUri(Uri.parse('package:foo/foo')), isTrue); }); test('false for foo:', () async { expect(isResolvableUri(Uri.parse('foo:')), isFalse); }); }); group('parseDartStackFrame', () { void expectFrames( List inputs, Uri uri, [ int? line, int? col, ]) { for (var input in inputs) { var frame = parseDartStackFrame(input); expect(frame, isNotNull, reason: 'Failed to parse "$input"'); expect(frame!.uri, uri, reason: 'Failed to parse URI from "$input"'); expect(frame.line, line, reason: 'Failed to parse line from "$input"'); expect(frame.column, col, reason: 'Failed to parse col from "$input"'); } } test('returns null for non-stack frames', () { expect(parseDartStackFrame(''), isNull); expect(parseDartStackFrame('1'), isNull); expect(parseDartStackFrame('test'), isNull); expect(parseDartStackFrame('foo.dart2'), isNull); expect(parseDartStackFrame('foo.darty'), isNull); expect(parseDartStackFrame('.dart'), isNull); }); group('package URIs', () { test('without line/col', () { expectFrames( [ 'package:foo/bar/baz.dart', '(package:foo/bar/baz.dart)', 'package:foo/bar/baz.dart', '#1 package:foo/bar/baz.dart', '#1 package:foo/bar/baz.dart 1 2 3 4 5', '#1 A.b (package:foo/bar/baz.dart) 123', 'flutter: #1 A.b (package:foo/bar/baz.dart)', ], Uri.parse('package:foo/bar/baz.dart'), ); }); test('with line/col', () { expectFrames( [ '(package:foo/bar/baz.dart:1:2)', '#1 package:foo/bar/baz.dart:1:2', '#1 package:foo/bar/baz.dart:1:2 1 2 3 4 5', '#1 A.b (package:foo/bar/baz.dart:1:2) 123', 'flutter: #1 A.b (package:foo/bar/baz.dart:1:2)', '(package:foo/bar/baz.dart 1:2)', '#1 package:foo/bar/baz.dart 1:2', '#1 package:foo/bar/baz.dart 1:2 1 2 3 4 5', '#1 A.b (package:foo/bar/baz.dart 1:2) 123', 'flutter: #1 A.b (package:foo/bar/baz.dart 1:2)', ], Uri.parse('package:foo/bar/baz.dart'), 1, 2, ); }); }); group('dart URIs', () { test('without line/col', () { expectFrames( [ '#1 _delayEntrypointInvocation. (dart:isolate-patch/isolate_patch.dart)', ], Uri.parse('dart:isolate-patch/isolate_patch.dart'), ); }); test('with line/col', () { expectFrames( [ '#1 _delayEntrypointInvocation. (dart:isolate-patch/isolate_patch.dart:1:2)', '#1 _delayEntrypointInvocation. (dart:isolate-patch/isolate_patch.dart 1:2)', ], Uri.parse('dart:isolate-patch/isolate_patch.dart'), 1, 2, ); }); }); group('Posix file URIs', () { test('without line/col', () { expectFrames( [ '#1 A.b (file:///a/b/c/d.dart)', 'flutter: #1 A.b (file:///a/b/c/d.dart)', ], Uri.parse('file:///a/b/c/d.dart'), ); }); test('with line/col', () { expectFrames( [ '#1 A.b (file:///a/b/c/d.dart:1:2)', 'flutter: #1 A.b (file:///a/b/c/d.dart:1:2)', 'flutter: #1 A.b (file:///a/b/c/d.dart 1:2)', ], Uri.parse('file:///a/b/c/d.dart'), 1, 2, ); }); }); group('Posix dart-macro+file URIs', () { test('without line/col', () { expectFrames( [ '#1 A.b (dart-macro+file:///a/b/c/d.dart)', 'flutter: #1 A.b (dart-macro+file:///a/b/c/d.dart)', ], Uri.parse('dart-macro+file:///a/b/c/d.dart'), ); }); test('with line/col', () { expectFrames( [ '#1 A.b (dart-macro+file:///a/b/c/d.dart:1:2)', 'flutter: #1 A.b (dart-macro+file:///a/b/c/d.dart:1:2)', ], Uri.parse('dart-macro+file:///a/b/c/d.dart'), 1, 2, ); }); }); group('Posix relative paths', () { test('without line/col', () { expectFrames( [ 'foo a/b/c/d.dart', '#1 A.b (a/b/c/d.dart)', 'flutter: #1 A.b (a/b/c/d.dart)', ], Uri.file(path.join(Directory.current.path, 'a/b/c/d.dart')), ); }); test('with line/col', () { expectFrames( [ 'foo a/b/c/d.dart:1:2', '#1 A.b (a/b/c/d.dart:1:2)', 'flutter: #1 A.b (a/b/c/d.dart:1:2)', 'flutter: #1 A.b (a/b/c/d.dart 1:2)', ], Uri.file(path.join(Directory.current.path, 'a/b/c/d.dart')), 1, 2, ); }); test('with dots in path', () { expectFrames( [ 'foo a.b.c/d.dart', '#1 A.b (a.b.c/d.dart)', 'flutter: #1 A.b (a.b.c/d.dart)', ], Uri.file(path.join(Directory.current.path, 'a.b.c/d.dart')), ); }); }, skip: Platform.isWindows); group('Windows file URIs', () { test('without line/col', () { expectFrames( [ '#1 A.b (file:///a:/b/c/d.dart)', 'flutter: #1 A.b (file:///a:/b/c/d.dart)', ], Uri.parse('file:///a:/b/c/d.dart'), ); }); test('with line/col', () { expectFrames( [ '#1 A.b (file:///a:/b/c/d.dart:1:2)', 'flutter: #1 A.b (file:///a:/b/c/d.dart:1:2)', ], Uri.parse('file:///a:/b/c/d.dart'), 1, 2, ); }); }); group('Windows dart-macro+file URIs', () { test('without line/col', () { expectFrames( [ '#1 A.b (dart-macro+file:///a:/b/c/d.dart)', 'flutter: #1 A.b (dart-macro+file:///a:/b/c/d.dart)', ], Uri.parse('dart-macro+file:///a:/b/c/d.dart'), ); }); test('with line/col', () { expectFrames( [ '#1 A.b (dart-macro+file:///a:/b/c/d.dart:1:2)', 'flutter: #1 A.b (dart-macro+file:///a:/b/c/d.dart:1:2)', ], Uri.parse('dart-macro+file:///a:/b/c/d.dart'), 1, 2, ); }); }); group('Windows relative paths', () { test('without line/col', () { expectFrames( [ r'foo a\b\c\d.dart', r'#1 A.b (a\b\c\d.dart)', r'flutter: #1 A.b (a\b\c\d.dart)', ], Uri.file(path.join(Directory.current.path, 'a/b/c/d.dart')), ); }); test('with line/col', () { expectFrames( [ r'foo a\b\c\d.dart:1:2', r'#1 A.b (a\b\c\d.dart:1:2)', r'flutter: #1 A.b (a\b\c\d.dart:1:2)', r'flutter: #1 A.b (a\b\c\d.dart 1:2)', ], Uri.file(path.join(Directory.current.path, 'a/b/c/d.dart')), 1, 2, ); }); test('with dots in path', () { expectFrames( [ r'foo a.b.c\d.dart', r'#1 A.b (a.b.c\d.dart)', r'flutter: #1 A.b (a.b.c\d.dart)', ], Uri.file(path.join(Directory.current.path, 'a.b.c/d.dart')), ); }); }, skip: !Platform.isWindows); }); }