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

Side by Side Diff: tests/compiler/dart2js/sourcemaps/stacktrace_test.dart

Issue 2654273002: Improve precision of stacktrace_test (Closed)
Patch Set: Created 3 years, 11 months 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:async'; 5 import 'dart:async';
6 import 'dart:convert'; 6 import 'dart:convert';
7 import 'dart:io'; 7 import 'dart:io';
8 8
9 import 'package:async_helper/async_helper.dart'; 9 import 'package:async_helper/async_helper.dart';
10 import 'package:compiler/compiler_new.dart'; 10 import 'package:compiler/compiler_new.dart';
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 } 62 }
63 } 63 }
64 ''', 64 ''',
65 ''' 65 '''
66 import 'package:expect/expect.dart'; 66 import 'package:expect/expect.dart';
67 main() { 67 main() {
68 var c = @{1:main}new Class(); 68 var c = @{1:main}new Class();
69 } 69 }
70 class Class { 70 class Class {
71 @NoInline() 71 @NoInline()
72 Class() { 72 @{2:Class}Class() {
73 @{2:Class}throw '$EXCEPTION_MARKER'; 73 @{3:Class}throw '$EXCEPTION_MARKER';
74 } 74 }
75 } 75 }
76 ''', 76 ''',
77 ''' 77 '''
78 import 'package:expect/expect.dart'; 78 import 'package:expect/expect.dart';
79 main() { 79 main() {
80 @{1:main}test(); 80 @{1:main}test();
81 } 81 }
82 @NoInline() 82 @NoInline()
83 test() { 83 test() {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 @NoInline() 122 @NoInline()
123 test(c) { 123 test(c) {
124 @{2:test}c.field.method(); 124 @{2:test}c.field.method();
125 } 125 }
126 class Class { 126 class Class {
127 var field; 127 var field;
128 } 128 }
129 ''', 129 ''',
130 ''' 130 '''
131 import 'package:expect/expect.dart'; 131 import 'package:expect/expect.dart';
132 class MyType {
133 get length => 3; // ensures we build an interceptor for `.length`
134 }
135
136 main() {
137 confuse('').trim(); // includes some code above the interceptors
138 confuse([]).length;
139 confuse(new MyType()).length;
140 // TODO(johnniwinther): Intercepted access should point to 'length':
141 @{1:main}confuse(null).length; // called through the interceptor
142 }
143
144 @NoInline()
145 confuse(x) => x;''',
146 '''
147 import 'package:expect/expect.dart';
132 main() { 148 main() {
133 // This call is no longer on the stack when the error is thrown. 149 // This call is no longer on the stack when the error is thrown.
134 @{:main}test(); 150 @{:main}test();
135 } 151 }
136 @NoInline() 152 @NoInline()
137 test() async { 153 test() async {
138 @{1:test}throw '$EXCEPTION_MARKER'; 154 @{1:test}throw '$EXCEPTION_MARKER';
139 } 155 }
140 ''', 156 ''',
141 ''' 157 '''
(...skipping 29 matching lines...) Expand all
171 import 'package:expect/expect.dart'; 187 import 'package:expect/expect.dart';
172 main() { 188 main() {
173 // This call is no longer on the stack when the error is thrown. 189 // This call is no longer on the stack when the error is thrown.
174 @{:main}test(); 190 @{:main}test();
175 } 191 }
176 test() async { 192 test() async {
177 var c = @{1:test}new Class(); 193 var c = @{1:test}new Class();
178 } 194 }
179 class Class { 195 class Class {
180 @NoInline() 196 @NoInline()
181 Class() { 197 @{2:Class}Class() {
182 @{2:Class}throw '$EXCEPTION_MARKER'; 198 @{3:Class}throw '$EXCEPTION_MARKER';
183 } 199 }
184 } 200 }
185 ''', 201 ''',
186 ]; 202 ];
187 203
188 class Test { 204 class Test {
189 final String code; 205 final String code;
190 final List<StackTraceLine> expectedLines; 206 final List<StackTraceLine> expectedLines;
191 final List<StackTraceLine> unexpectedLines; 207 final List<StackTraceLine> unexpectedLines;
192 208
(...skipping 25 matching lines...) Expand all
218 List<StackTraceLine> expectedLines = <StackTraceLine>[]; 234 List<StackTraceLine> expectedLines = <StackTraceLine>[];
219 for (int stackTraceIndex in (stackTraceMap.keys.toList()..sort()).reversed) { 235 for (int stackTraceIndex in (stackTraceMap.keys.toList()..sort()).reversed) {
220 expectedLines.add(stackTraceMap[stackTraceIndex]); 236 expectedLines.add(stackTraceMap[stackTraceIndex]);
221 } 237 }
222 return new Test(annotatedCode.sourceCode, expectedLines, unexpectedLines); 238 return new Test(annotatedCode.sourceCode, expectedLines, unexpectedLines);
223 } 239 }
224 240
225 void main(List<String> arguments) { 241 void main(List<String> arguments) {
226 bool verbose = false; 242 bool verbose = false;
227 bool printJs = false; 243 bool printJs = false;
244 bool writeJs = false;
228 List<int> indices; 245 List<int> indices;
229 for (String arg in arguments) { 246 for (String arg in arguments) {
230 if (arg == '-v') { 247 if (arg == '-v') {
231 verbose = true; 248 verbose = true;
232 } else if (arg == '--print-js') { 249 } else if (arg == '--print-js') {
233 printJs = true; 250 printJs = true;
251 } else if (arg == '--write-js') {
252 writeJs = true;
234 } else { 253 } else {
235 int index = int.parse(arg, onError: (_) => null); 254 int index = int.parse(arg, onError: (_) => null);
236 if (index != null) { 255 if (index != null) {
237 indices ??= <int>[]; 256 indices ??= <int>[];
238 if (index < 0 || index >= TESTS.length) { 257 if (index < 0 || index >= TESTS.length) {
239 print('Index $index out of bounds: [0;${TESTS.length - 1}]'); 258 print('Index $index out of bounds: [0;${TESTS.length - 1}]');
240 } else { 259 } else {
241 indices.add(index); 260 indices.add(index);
242 } 261 }
243 } 262 }
244 } 263 }
245 } 264 }
246 if (indices == null) { 265 if (indices == null) {
247 indices = new List<int>.generate(TESTS.length, (i) => i); 266 indices = new List<int>.generate(TESTS.length, (i) => i);
248 } 267 }
249 asyncTest(() async { 268 asyncTest(() async {
250 for (int index in indices) { 269 for (int index in indices) {
251 await runTest(index, processTestCode(TESTS[index]), 270 await runTest(index, processTestCode(TESTS[index]),
252 printJs: printJs, verbose: verbose); 271 printJs: printJs, writeJs: writeJs, verbose: verbose);
253 } 272 }
254 }); 273 });
255 } 274 }
256 275
257 Future runTest(int index, Test test, 276 Future runTest(int index, Test test,
258 {bool printJs: false, bool verbose: false}) async { 277 {bool printJs: false, bool writeJs, bool verbose: false}) async {
259 Directory tmpDir = await createTempDir(); 278 Directory tmpDir = await createTempDir();
260 String input = '${tmpDir.path}/$INPUT_FILE_NAME'; 279 String input = '${tmpDir.path}/$INPUT_FILE_NAME';
261 new File(input).writeAsStringSync(test.code); 280 new File(input).writeAsStringSync(test.code);
262 String output = '${tmpDir.path}/out.js'; 281 String output = '${tmpDir.path}/out.js';
263 List<String> arguments = [ 282 List<String> arguments = [
264 '-o$output', 283 '-o$output',
265 '--library-root=sdk', 284 '--library-root=sdk',
266 '--packages=${Platform.packageConfig}', 285 '--packages=${Platform.packageConfig}',
267 Flags.useNewSourceInfo, 286 Flags.useNewSourceInfo,
268 input, 287 input,
269 ]; 288 ];
270 print("--$index------------------------------------------------------------"); 289 print("--$index------------------------------------------------------------");
271 print("Compiling dart2js ${arguments.join(' ')}\n${test.code}"); 290 print("Compiling dart2js ${arguments.join(' ')}\n${test.code}");
272 CompilationResult compilationResult = await entry.internalMain(arguments); 291 CompilationResult compilationResult = await entry.internalMain(arguments);
273 Expect.isTrue(compilationResult.isSuccess, 292 Expect.isTrue(compilationResult.isSuccess,
274 "Unsuccessful compilation of test:\n${test.code}"); 293 "Unsuccessful compilation of test:\n${test.code}");
275 CompilerImpl compiler = compilationResult.compiler; 294 String sourceMapText = new File('$output.map').readAsStringSync();
276 SingleMapping sourceMap = new SingleMapping.fromJson( 295 SingleMapping sourceMap =
277 JSON.decode(new File('$output.map').readAsStringSync())); 296 new SingleMapping.fromJson(JSON.decode(sourceMapText));
Siggi Cherem (dart-lang) 2017/01/26 19:22:18 nit: you should be able to do: SingleMapping sour
Johnni Winther 2017/01/27 08:08:13 Done.
278 297
279 if (printJs) { 298 if (printJs) {
280 print('JavaScript output:'); 299 print('JavaScript output:');
281 print(new File(output).readAsStringSync()); 300 print(new File(output).readAsStringSync());
282 } 301 }
302 if (writeJs) {
303 new File('out.js').writeAsStringSync(new File(output).readAsStringSync());
304 new File('out.js.map').writeAsStringSync(sourceMapText);
305 }
283 print("Running d8 $output"); 306 print("Running d8 $output");
284 ProcessResult runResult = Process.runSync(d8executable, 307 ProcessResult runResult = Process.runSync(d8executable,
285 ['sdk/lib/_internal/js_runtime/lib/preambles/d8.js', output]); 308 ['sdk/lib/_internal/js_runtime/lib/preambles/d8.js', output]);
286 String out = '${runResult.stderr}\n${runResult.stdout}'; 309 String out = '${runResult.stderr}\n${runResult.stdout}';
287 if (verbose) { 310 if (verbose) {
288 print('d8 output:'); 311 print('d8 output:');
289 print(out); 312 print(out);
290 } 313 }
291 List<String> lines = out.split(new RegExp(r'(\r|\n|\r\n)')); 314 List<String> lines = out.split(new RegExp(r'(\r|\n|\r\n)'));
292 List<StackTraceLine> jsStackTrace = <StackTraceLine>[]; 315 List<StackTraceLine> jsStackTrace = <StackTraceLine>[];
(...skipping 12 matching lines...) Expand all
305 } else { 328 } else {
306 String methodName; 329 String methodName;
307 if (targetEntry.sourceNameId != null) { 330 if (targetEntry.sourceNameId != null) {
308 methodName = sourceMap.names[targetEntry.sourceNameId]; 331 methodName = sourceMap.names[targetEntry.sourceNameId];
309 } 332 }
310 String fileName; 333 String fileName;
311 if (targetEntry.sourceUrlId != null) { 334 if (targetEntry.sourceUrlId != null) {
312 fileName = sourceMap.urls[targetEntry.sourceUrlId]; 335 fileName = sourceMap.urls[targetEntry.sourceUrlId];
313 } 336 }
314 dartStackTrace.add(new StackTraceLine(methodName, fileName, 337 dartStackTrace.add(new StackTraceLine(methodName, fileName,
315 targetEntry.sourceLine + 1, targetEntry.sourceColumn + 1)); 338 targetEntry.sourceLine + 1, targetEntry.sourceColumn + 1,
339 isMapped: true));
316 } 340 }
317 } 341 }
318 342
319 int expectedIndex = 0; 343 int expectedIndex = 0;
320 List<StackTraceLine> unexpectedLines = <StackTraceLine>[]; 344 List<StackTraceLine> unexpectedLines = <StackTraceLine>[];
345 List<StackTraceLine> unexpectedBeforeLines = <StackTraceLine>[];
346 List<StackTraceLine> unexpectedAfterLines = <StackTraceLine>[];
321 for (StackTraceLine line in dartStackTrace) { 347 for (StackTraceLine line in dartStackTrace) {
348 bool found = false;
322 if (expectedIndex < test.expectedLines.length) { 349 if (expectedIndex < test.expectedLines.length) {
323 StackTraceLine expectedLine = test.expectedLines[expectedIndex]; 350 StackTraceLine expectedLine = test.expectedLines[expectedIndex];
324 if (line.methodName == expectedLine.methodName && 351 if (line.methodName == expectedLine.methodName &&
325 line.lineNo == expectedLine.lineNo && 352 line.lineNo == expectedLine.lineNo &&
326 line.columnNo == expectedLine.columnNo) { 353 line.columnNo == expectedLine.columnNo) {
354 found = true;
327 expectedIndex++; 355 expectedIndex++;
328 } 356 }
329 } 357 }
330 for (StackTraceLine unexpectedLine in test.unexpectedLines) { 358 for (StackTraceLine unexpectedLine in test.unexpectedLines) {
331 if (line.methodName == unexpectedLine.methodName && 359 if (line.methodName == unexpectedLine.methodName &&
332 line.lineNo == unexpectedLine.lineNo && 360 line.lineNo == unexpectedLine.lineNo &&
333 line.columnNo == unexpectedLine.columnNo) { 361 line.columnNo == unexpectedLine.columnNo) {
334 unexpectedLines.add(line); 362 unexpectedLines.add(line);
335 } 363 }
336 } 364 }
365 if (line.isMapped && !found) {
366 List<LineException> exceptions =
367 expectedIndex == 0 ? beforeExceptions : afterExceptions;
368 for (LineException exception in exceptions) {
369 if (line.methodName == exception.methodName &&
370 line.fileName.endsWith(exception.fileName)) {
371 found = true;
372 }
373 }
374 if (!found) {
375 if (expectedIndex == 0) {
376 unexpectedBeforeLines.add(line);
377 } else {
378 unexpectedAfterLines.add(line);
379 }
380 }
381 }
337 } 382 }
338 if (verbose) { 383 if (verbose) {
339 print('JavaScript stacktrace:'); 384 print('JavaScript stacktrace:');
340 print(jsStackTrace.join('\n')); 385 print(jsStackTrace.join('\n'));
341 print('Dart stacktrace:'); 386 print('Dart stacktrace:');
342 print(dartStackTrace.join('\n')); 387 print(dartStackTrace.join('\n'));
343 } 388 }
344 Expect.equals( 389 Expect.equals(
345 expectedIndex, 390 expectedIndex,
346 test.expectedLines.length, 391 test.expectedLines.length,
347 "Missing stack trace lines for test:\n${test.code}\n" 392 "Missing stack trace lines for test:\n${test.code}\n"
348 "Actual:\n${dartStackTrace.join('\n')}\n" 393 "Actual:\n${dartStackTrace.join('\n')}\n"
349 "Expected:\n${test.expectedLines.join('\n')}\n"); 394 "Expected:\n${test.expectedLines.join('\n')}\n");
350 Expect.isTrue( 395 Expect.isTrue(
351 unexpectedLines.isEmpty, 396 unexpectedLines.isEmpty,
352 "Unexpected stack trace lines for test:\n${test.code}\n" 397 "Unexpected stack trace lines for test:\n${test.code}\n"
353 "Actual:\n${dartStackTrace.join('\n')}\n" 398 "Actual:\n${dartStackTrace.join('\n')}\n"
354 "Unexpected:\n${test.unexpectedLines.join('\n')}\n"); 399 "Unexpected:\n${test.unexpectedLines.join('\n')}\n");
400 Expect.isTrue(
401 unexpectedBeforeLines.isEmpty && unexpectedAfterLines.isEmpty,
402 "Unexpected stack trace lines:\n${test.code}\n"
403 "Actual:\n${dartStackTrace.join('\n')}\n"
404 "Unexpected before:\n${unexpectedBeforeLines.join('\n')}\n"
405 "Unexpected after:\n${unexpectedAfterLines.join('\n')}\n");
355 406
356 print("Deleting '${tmpDir.path}'."); 407 print("Deleting '${tmpDir.path}'.");
357 tmpDir.deleteSync(recursive: true); 408 tmpDir.deleteSync(recursive: true);
358 } 409 }
359 410
360 class StackTraceLine { 411 class StackTraceLine {
361 String methodName; 412 String methodName;
362 String fileName; 413 String fileName;
363 int lineNo; 414 int lineNo;
364 int columnNo; 415 int columnNo;
416 bool isMapped;
365 417
366 StackTraceLine(this.methodName, this.fileName, this.lineNo, this.columnNo); 418 StackTraceLine(this.methodName, this.fileName, this.lineNo, this.columnNo,
419 {this.isMapped: false});
367 420
368 /// Creates a [StackTraceLine] by parsing a d8 stack trace line [text]. The 421 /// Creates a [StackTraceLine] by parsing a d8 stack trace line [text]. The
369 /// expected formats are 422 /// expected formats are
370 /// 423 ///
371 /// at <methodName>(<fileName>:<lineNo>:<columnNo>) 424 /// at <methodName>(<fileName>:<lineNo>:<columnNo>)
372 /// at <methodName>(<fileName>:<lineNo>) 425 /// at <methodName>(<fileName>:<lineNo>)
373 /// at <methodName>(<fileName>) 426 /// at <methodName>(<fileName>)
374 /// at <fileName>:<lineNo>:<columnNo> 427 /// at <fileName>:<lineNo>:<columnNo>
375 /// at <fileName>:<lineNo> 428 /// at <fileName>:<lineNo>
376 /// at <fileName> 429 /// at <fileName>
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 String get d8executable { 524 String get d8executable {
472 if (Platform.isWindows) { 525 if (Platform.isWindows) {
473 return 'third_party/d8/windows/d8.exe'; 526 return 'third_party/d8/windows/d8.exe';
474 } else if (Platform.isLinux) { 527 } else if (Platform.isLinux) {
475 return 'third_party/d8/linux/d8'; 528 return 'third_party/d8/linux/d8';
476 } else if (Platform.isMacOS) { 529 } else if (Platform.isMacOS) {
477 return 'third_party/d8/macos/d8'; 530 return 'third_party/d8/macos/d8';
478 } 531 }
479 throw new UnsupportedError('Unsupported platform.'); 532 throw new UnsupportedError('Unsupported platform.');
480 } 533 }
534
535 /// A line allowed in the mapped stack trace.
536 class LineException {
537 final String methodName;
538 final String fileName;
539
540 const LineException(this.methodName, this.fileName);
541 }
542
543 /// Lines allowed before the intended stack trace. Typically from helper
544 /// methods.
545 const List<LineException> beforeExceptions = const [
546 const LineException('wrapException', 'js_helper.dart'),
547 ];
548
549 /// Lines allowed after the intended stack trace. Typically from the event
550 /// queue.
551 const List<LineException> afterExceptions = const [
552 const LineException('_wrapJsFunctionForAsync', 'async_patch.dart'),
553 const LineException(
554 '_wrapJsFunctionForAsync.<anonymous function>', 'async_patch.dart'),
555 const LineException(
556 '_awaitOnObject.<anonymous function>', 'async_patch.dart'),
557 const LineException('_RootZone.runUnary', 'zone.dart'),
558 const LineException('_FutureListener.handleValue', 'future_impl.dart'),
559 const LineException(
560 '_Future._propagateToListeners.handleValueCallback', 'future_impl.dart'),
561 const LineException('_Future._propagateToListeners', 'future_impl.dart'),
562 const LineException(
563 '_Future._addListener.<anonymous function>', 'future_impl.dart'),
564 ];
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698