Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(732)

Unified Diff: tests/compiler/dart2js/sourcemaps/stacktrace_test.dart

Issue 2431223006: Add stacktrace_test (Closed)
Patch Set: Updated cf. comments. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tests/compiler/dart2js/sourcemaps/save.dart ('k') | tests/compiler/dart2js/sourcemaps/trace_graph.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart b/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..9fcebdc0c9e2c2c8b3be4a30d42e8611e44cadcb
--- /dev/null
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
@@ -0,0 +1,344 @@
+// Copyright (c) 2016, 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:async';
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/compiler_new.dart';
+import 'package:compiler/src/apiimpl.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/dart2js.dart' as entry;
+import 'package:expect/expect.dart';
+import 'package:source_maps/source_maps.dart';
+import 'package:source_maps/src/utils.dart';
+
+import '../source_map_validator_helper.dart';
+
+const String EXCEPTION_MARKER = '>ExceptionMarker<';
+const String INPUT_FILE_NAME = 'in.dart';
+
+const List<String> TESTS = const <String>[
+ '''
+main() {
+ @{1:main}throw '$EXCEPTION_MARKER';
+}
+''',
+ '''
+main() {
+ @{1:main}test();
+}
+test() {
+ @{2:test}throw '$EXCEPTION_MARKER';
+}
+''',
+ '''
+main() {
+ @{1:main}Class.test();
+}
+class Class {
+ static test() {
+ @{2:Class.test}throw '$EXCEPTION_MARKER';
+ }
+}
+''',
+ '''
+main() {
+ var c = new Class();
+ c.@{1:main}test();
+}
+class Class {
+ test() {
+ @{2:Class.test}throw '$EXCEPTION_MARKER';
+ }
+}
+''',
+ '''
+import 'package:expect/expect.dart';
+main() {
+ var c = @{1:main}new Class();
+}
+class Class {
+ @NoInline()
+ Class() {
+ @{2:Class}throw '$EXCEPTION_MARKER';
+ }
+}
+''',
+];
+
+class Test {
+ final String code;
+ final List<StackTraceLine> expectedLines;
+
+ Test(this.code, this.expectedLines);
+}
+
+const int _LF = 0x0A;
+const int _CR = 0x0D;
+const int _LBRACE = 0x7B;
+
+
+Test processTestCode(String code) {
+ StringBuffer codeBuffer = new StringBuffer();
+ Map<int, StackTraceLine> stackTraceMap = <int, StackTraceLine>{};
+ int index = 0;
+ int lineNo = 1;
+ int columnNo = 1;
+ while (index < code.length) {
+ int charCode = code.codeUnitAt(index);
+ switch (charCode) {
+ case _LF:
+ codeBuffer.write('\n');
+ lineNo++;
+ columnNo = 1;
+ break;
+ case _CR:
+ if (index + 1 < code.length && code.codeUnitAt(index + 1) == _LF) {
+ index++;
+ }
+ codeBuffer.write('\n');
+ lineNo++;
+ columnNo = 1;
+ break;
+ case 0x40:
+ if (index + 1 < code.length && code.codeUnitAt(index + 1) == _LBRACE) {
+ int colonIndex = code.indexOf(':', index);
+ int endIndex = code.indexOf('}', index);
+ int stackTraceIndex =
+ int.parse(code.substring(index + 2, colonIndex));
+ String methodName = code.substring(colonIndex + 1, endIndex);
+ assert(!stackTraceMap.containsKey(stackTraceIndex));
+ stackTraceMap[stackTraceIndex] =
+ new StackTraceLine(methodName, INPUT_FILE_NAME, lineNo, columnNo);
+ index = endIndex;
+ } else {
+ codeBuffer.writeCharCode(charCode);
+ columnNo++;
+ }
+ break;
+ default:
+ codeBuffer.writeCharCode(charCode);
+ columnNo++;
+ }
+ index++;
+ }
+ List<StackTraceLine> expectedLines = <StackTraceLine>[];
+ for (int stackTraceIndex in (stackTraceMap.keys.toList()..sort()).reversed) {
+ expectedLines.add(stackTraceMap[stackTraceIndex]);
+ }
+ return new Test(codeBuffer.toString(), expectedLines);
+}
+
+void main(List<String> arguments) {
+ asyncTest(() async {
+ for (String code in TESTS) {
+ await runTest(processTestCode(code));
+ }
+ });
+}
+
+Future runTest(Test test) async {
+ Directory tmpDir = await createTempDir();
+ String input = '${tmpDir.path}/$INPUT_FILE_NAME';
+ new File(input).writeAsStringSync(test.code);
+ String output = '${tmpDir.path}/out.js';
+ List<String> arguments = [
+ '-o$output',
+ '--library-root=sdk',
+ '--packages=${Platform.packageConfig}',
+ Flags.useNewSourceInfo,
+ input,
+ ];
+ print("--------------------------------------------------------------------");
+ print("Compiling dart2js ${arguments.join(' ')}\n${test.code}");
+ CompilationResult compilationResult = await entry.internalMain(arguments);
+ Expect.isTrue(compilationResult.isSuccess,
+ "Unsuccessful compilation of test:\n${test.code}");
+ CompilerImpl compiler = compilationResult.compiler;
+ SingleMapping sourceMap = new SingleMapping.fromJson(
+ JSON.decode(new File('$output.map').readAsStringSync()));
+
+ print("Running d8 $output");
+ ProcessResult runResult =
+ Process.runSync(d8executable, [output]);
+ String out = '${runResult.stderr}\n${runResult.stdout}';
+ List<String> lines = out.split(new RegExp(r'(\r|\n|\r\n)'));
+ List<StackTraceLine> jsStackTrace = <StackTraceLine>[];
+ bool seenMarker = false;
+ for (String line in lines) {
+ if (seenMarker) {
+ line = line.trim();
+ if (line.startsWith('at ')) {
+ jsStackTrace.add(new StackTraceLine.fromText(line));
+ }
+ } else if (line == EXCEPTION_MARKER) {
+ seenMarker = true;
+ }
+ }
+
+ List<StackTraceLine> dartStackTrace = <StackTraceLine>[];
+ for (StackTraceLine line in jsStackTrace) {
+ TargetEntry targetEntry = _findColumn(line.lineNo - 1, line.columnNo - 1,
+ _findLine(sourceMap, line.lineNo - 1));
+ if (targetEntry == null) {
+ dartStackTrace.add(line);
+ } else {
+ String methodName;
+ if (targetEntry.sourceNameId != 0) {
+ methodName = sourceMap.names[targetEntry.sourceNameId];
+ }
+ String fileName;
+ if (targetEntry.sourceUrlId != 0) {
+ fileName = sourceMap.urls[targetEntry.sourceUrlId];
+ }
+ dartStackTrace.add(new StackTraceLine(methodName, fileName,
+ targetEntry.sourceLine + 1, targetEntry.sourceColumn + 1));
+ }
+ }
+
+ int expectedIndex = 0;
+ for (StackTraceLine line in dartStackTrace) {
+ if (expectedIndex < test.expectedLines.length) {
+ StackTraceLine expectedLine = test.expectedLines[expectedIndex];
+ if (line.methodName == expectedLine.methodName &&
+ line.lineNo == expectedLine.lineNo &&
+ line.columnNo == expectedLine.columnNo) {
+ expectedIndex++;
+ }
+ }
+ }
+ Expect.equals(
+ expectedIndex,
+ test.expectedLines.length,
+ "Missing stack trace lines for test:\n${test.code}\n"
+ "Actual:\n${dartStackTrace.join('\n')}\n"
+ "Expected:\n${test.expectedLines.join('\n')}\n");
+
+ print("Deleting '${tmpDir.path}'.");
+ tmpDir.deleteSync(recursive: true);
+}
+
+class StackTraceLine {
+ String methodName;
+ String fileName;
+ int lineNo;
+ int columnNo;
+
+ StackTraceLine(this.methodName, this.fileName, this.lineNo, this.columnNo);
+
+ /// Creates a [StackTraceLine] by parsing a d8 stack trace line [text]. The
+ /// expected formats are
+ ///
+ /// at <methodName>(<fileName>:<lineNo>:<columnNo>)
+ /// at <methodName>(<fileName>:<lineNo>)
+ /// at <methodName>(<fileName>)
+ /// at <fileName>:<lineNo>:<columnNo>
+ /// at <fileName>:<lineNo>
+ /// at <fileName>
+ ///
+ factory StackTraceLine.fromText(String text) {
+ text = text.trim();
+ assert(text.startsWith('at '));
+ text = text.substring('at '.length);
+ String methodName;
+ if (text.endsWith(')')) {
+ int nameEnd = text.indexOf(' (');
+ methodName = text.substring(0, nameEnd);
+ text = text.substring(nameEnd + 2, text.length - 1);
+ }
+ int lineNo;
+ int columnNo;
+ String fileName;
+ int lastColon = text.lastIndexOf(':');
+ if (lastColon != -1) {
+ int lastValue =
+ int.parse(text.substring(lastColon + 1), onError: (_) => null);
+ if (lastValue != null) {
+ int secondToLastColon = text.lastIndexOf(':', lastColon - 1);
+ if (secondToLastColon != -1) {
+ int secondToLastValue = int.parse(
+ text.substring(secondToLastColon + 1, lastColon),
+ onError: (_) => null);
+ if (secondToLastValue != null) {
+ lineNo = secondToLastValue;
+ columnNo = lastValue;
+ fileName = text.substring(0, secondToLastColon);
+ } else {
+ lineNo = lastValue;
+ fileName = text.substring(0, lastColon);
+ }
+ } else {
+ lineNo = lastValue;
+ fileName = text.substring(0, lastColon);
+ }
+ } else {
+ fileName = text;
+ }
+ } else {
+ fileName = text;
+ }
+ return new StackTraceLine(methodName, fileName, lineNo, columnNo);
+ }
+
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.write(' at ');
+ if (methodName != null) {
+ sb.write(methodName);
+ sb.write(' (');
+ sb.write(fileName ?? '?');
+ sb.write(':');
+ sb.write(lineNo);
+ sb.write(':');
+ sb.write(columnNo);
+ sb.write(')');
+ } else {
+ sb.write(fileName ?? '?');
+ sb.write(':');
+ sb.write(lineNo);
+ sb.write(':');
+ sb.write(columnNo);
+ }
+ return sb.toString();
+ }
+}
+
+/// Returns [TargetLineEntry] which includes the location in the target [line]
+/// number. In particular, the resulting entry is the last entry whose line
+/// number is lower or equal to [line].
+///
+/// Copied from [SingleMapping._findLine].
+TargetLineEntry _findLine(SingleMapping sourceMap, int line) {
+ int index = binarySearch(sourceMap.lines, (e) => e.line > line);
+ return (index <= 0) ? null : sourceMap.lines[index - 1];
+}
+
+/// Returns [TargetEntry] which includes the location denoted by
+/// [line], [column]. If [lineEntry] corresponds to [line], then this will be
+/// the last entry whose column is lower or equal than [column]. If
+/// [lineEntry] corresponds to a line prior to [line], then the result will be
+/// the very last entry on that line.
+///
+/// Copied from [SingleMapping._findColumn].
+TargetEntry _findColumn(int line, int column, TargetLineEntry lineEntry) {
+ if (lineEntry == null || lineEntry.entries.length == 0) return null;
+ if (lineEntry.line != line) return lineEntry.entries.last;
+ var entries = lineEntry.entries;
+ int index = binarySearch(entries, (e) => e.column > column);
+ return (index <= 0) ? null : entries[index - 1];
+}
+
+/// Returns the path of the d8 executable.
+String get d8executable {
+ if (Platform.isWindows) {
+ return 'third_party/d8/windows/d8.exe';
+ } else if (Platform.isLinux) {
+ return 'third_party/d8/linux/d8';
+ } else if (Platform.isMacOS) {
+ return 'third_party/d8/macos/d8';
+ }
+ throw new UnsupportedError('Unsupported platform.');
+}
« no previous file with comments | « tests/compiler/dart2js/sourcemaps/save.dart ('k') | tests/compiler/dart2js/sourcemaps/trace_graph.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698