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

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

Issue 2654273002: Improve precision of stacktrace_test (Closed)
Patch Set: Updated cf. comment Created 3 years, 10 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 = parse(sourceMapText);
277 JSON.decode(new File('$output.map').readAsStringSync()));
278 296
279 if (printJs) { 297 if (printJs) {
280 print('JavaScript output:'); 298 print('JavaScript output:');
281 print(new File(output).readAsStringSync()); 299 print(new File(output).readAsStringSync());
282 } 300 }
301 if (writeJs) {
302 new File('out.js').writeAsStringSync(new File(output).readAsStringSync());
303 new File('out.js.map').writeAsStringSync(sourceMapText);
304 }
283 print("Running d8 $output"); 305 print("Running d8 $output");
284 ProcessResult runResult = Process.runSync(d8executable, 306 ProcessResult runResult = Process.runSync(d8executable,
285 ['sdk/lib/_internal/js_runtime/lib/preambles/d8.js', output]); 307 ['sdk/lib/_internal/js_runtime/lib/preambles/d8.js', output]);
286 String out = '${runResult.stderr}\n${runResult.stdout}'; 308 String out = '${runResult.stderr}\n${runResult.stdout}';
287 if (verbose) { 309 if (verbose) {
288 print('d8 output:'); 310 print('d8 output:');
289 print(out); 311 print(out);
290 } 312 }
291 List<String> lines = out.split(new RegExp(r'(\r|\n|\r\n)')); 313 List<String> lines = out.split(new RegExp(r'(\r|\n|\r\n)'));
292 List<StackTraceLine> jsStackTrace = <StackTraceLine>[]; 314 List<StackTraceLine> jsStackTrace = <StackTraceLine>[];
(...skipping 12 matching lines...) Expand all
305 } else { 327 } else {
306 String methodName; 328 String methodName;
307 if (targetEntry.sourceNameId != null) { 329 if (targetEntry.sourceNameId != null) {
308 methodName = sourceMap.names[targetEntry.sourceNameId]; 330 methodName = sourceMap.names[targetEntry.sourceNameId];
309 } 331 }
310 String fileName; 332 String fileName;
311 if (targetEntry.sourceUrlId != null) { 333 if (targetEntry.sourceUrlId != null) {
312 fileName = sourceMap.urls[targetEntry.sourceUrlId]; 334 fileName = sourceMap.urls[targetEntry.sourceUrlId];
313 } 335 }
314 dartStackTrace.add(new StackTraceLine(methodName, fileName, 336 dartStackTrace.add(new StackTraceLine(methodName, fileName,
315 targetEntry.sourceLine + 1, targetEntry.sourceColumn + 1)); 337 targetEntry.sourceLine + 1, targetEntry.sourceColumn + 1,
338 isMapped: true));
316 } 339 }
317 } 340 }
318 341
319 int expectedIndex = 0; 342 int expectedIndex = 0;
320 List<StackTraceLine> unexpectedLines = <StackTraceLine>[]; 343 List<StackTraceLine> unexpectedLines = <StackTraceLine>[];
344 List<StackTraceLine> unexpectedBeforeLines = <StackTraceLine>[];
345 List<StackTraceLine> unexpectedAfterLines = <StackTraceLine>[];
321 for (StackTraceLine line in dartStackTrace) { 346 for (StackTraceLine line in dartStackTrace) {
347 bool found = false;
322 if (expectedIndex < test.expectedLines.length) { 348 if (expectedIndex < test.expectedLines.length) {
323 StackTraceLine expectedLine = test.expectedLines[expectedIndex]; 349 StackTraceLine expectedLine = test.expectedLines[expectedIndex];
324 if (line.methodName == expectedLine.methodName && 350 if (line.methodName == expectedLine.methodName &&
325 line.lineNo == expectedLine.lineNo && 351 line.lineNo == expectedLine.lineNo &&
326 line.columnNo == expectedLine.columnNo) { 352 line.columnNo == expectedLine.columnNo) {
353 found = true;
327 expectedIndex++; 354 expectedIndex++;
328 } 355 }
329 } 356 }
330 for (StackTraceLine unexpectedLine in test.unexpectedLines) { 357 for (StackTraceLine unexpectedLine in test.unexpectedLines) {
331 if (line.methodName == unexpectedLine.methodName && 358 if (line.methodName == unexpectedLine.methodName &&
332 line.lineNo == unexpectedLine.lineNo && 359 line.lineNo == unexpectedLine.lineNo &&
333 line.columnNo == unexpectedLine.columnNo) { 360 line.columnNo == unexpectedLine.columnNo) {
334 unexpectedLines.add(line); 361 unexpectedLines.add(line);
335 } 362 }
336 } 363 }
364 if (line.isMapped && !found) {
365 List<LineException> exceptions =
366 expectedIndex == 0 ? beforeExceptions : afterExceptions;
367 for (LineException exception in exceptions) {
368 if (line.methodName == exception.methodName &&
369 line.fileName.endsWith(exception.fileName)) {
370 found = true;
371 }
372 }
373 if (!found) {
374 if (expectedIndex == 0) {
375 unexpectedBeforeLines.add(line);
376 } else {
377 unexpectedAfterLines.add(line);
378 }
379 }
380 }
337 } 381 }
338 if (verbose) { 382 if (verbose) {
339 print('JavaScript stacktrace:'); 383 print('JavaScript stacktrace:');
340 print(jsStackTrace.join('\n')); 384 print(jsStackTrace.join('\n'));
341 print('Dart stacktrace:'); 385 print('Dart stacktrace:');
342 print(dartStackTrace.join('\n')); 386 print(dartStackTrace.join('\n'));
343 } 387 }
344 Expect.equals( 388 Expect.equals(
345 expectedIndex, 389 expectedIndex,
346 test.expectedLines.length, 390 test.expectedLines.length,
347 "Missing stack trace lines for test:\n${test.code}\n" 391 "Missing stack trace lines for test:\n${test.code}\n"
348 "Actual:\n${dartStackTrace.join('\n')}\n" 392 "Actual:\n${dartStackTrace.join('\n')}\n"
349 "Expected:\n${test.expectedLines.join('\n')}\n"); 393 "Expected:\n${test.expectedLines.join('\n')}\n");
350 Expect.isTrue( 394 Expect.isTrue(
351 unexpectedLines.isEmpty, 395 unexpectedLines.isEmpty,
352 "Unexpected stack trace lines for test:\n${test.code}\n" 396 "Unexpected stack trace lines for test:\n${test.code}\n"
353 "Actual:\n${dartStackTrace.join('\n')}\n" 397 "Actual:\n${dartStackTrace.join('\n')}\n"
354 "Unexpected:\n${test.unexpectedLines.join('\n')}\n"); 398 "Unexpected:\n${test.unexpectedLines.join('\n')}\n");
399 Expect.isTrue(
400 unexpectedBeforeLines.isEmpty && unexpectedAfterLines.isEmpty,
401 "Unexpected stack trace lines:\n${test.code}\n"
402 "Actual:\n${dartStackTrace.join('\n')}\n"
403 "Unexpected before:\n${unexpectedBeforeLines.join('\n')}\n"
404 "Unexpected after:\n${unexpectedAfterLines.join('\n')}\n");
355 405
356 print("Deleting '${tmpDir.path}'."); 406 print("Deleting '${tmpDir.path}'.");
357 tmpDir.deleteSync(recursive: true); 407 tmpDir.deleteSync(recursive: true);
358 } 408 }
359 409
360 class StackTraceLine { 410 class StackTraceLine {
361 String methodName; 411 String methodName;
362 String fileName; 412 String fileName;
363 int lineNo; 413 int lineNo;
364 int columnNo; 414 int columnNo;
415 bool isMapped;
365 416
366 StackTraceLine(this.methodName, this.fileName, this.lineNo, this.columnNo); 417 StackTraceLine(this.methodName, this.fileName, this.lineNo, this.columnNo,
418 {this.isMapped: false});
367 419
368 /// Creates a [StackTraceLine] by parsing a d8 stack trace line [text]. The 420 /// Creates a [StackTraceLine] by parsing a d8 stack trace line [text]. The
369 /// expected formats are 421 /// expected formats are
370 /// 422 ///
371 /// at <methodName>(<fileName>:<lineNo>:<columnNo>) 423 /// at <methodName>(<fileName>:<lineNo>:<columnNo>)
372 /// at <methodName>(<fileName>:<lineNo>) 424 /// at <methodName>(<fileName>:<lineNo>)
373 /// at <methodName>(<fileName>) 425 /// at <methodName>(<fileName>)
374 /// at <fileName>:<lineNo>:<columnNo> 426 /// at <fileName>:<lineNo>:<columnNo>
375 /// at <fileName>:<lineNo> 427 /// at <fileName>:<lineNo>
376 /// at <fileName> 428 /// at <fileName>
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 String get d8executable { 523 String get d8executable {
472 if (Platform.isWindows) { 524 if (Platform.isWindows) {
473 return 'third_party/d8/windows/d8.exe'; 525 return 'third_party/d8/windows/d8.exe';
474 } else if (Platform.isLinux) { 526 } else if (Platform.isLinux) {
475 return 'third_party/d8/linux/d8'; 527 return 'third_party/d8/linux/d8';
476 } else if (Platform.isMacOS) { 528 } else if (Platform.isMacOS) {
477 return 'third_party/d8/macos/d8'; 529 return 'third_party/d8/macos/d8';
478 } 530 }
479 throw new UnsupportedError('Unsupported platform.'); 531 throw new UnsupportedError('Unsupported platform.');
480 } 532 }
533
534 /// A line allowed in the mapped stack trace.
535 class LineException {
536 final String methodName;
537 final String fileName;
538
539 const LineException(this.methodName, this.fileName);
540 }
541
542 /// Lines allowed before the intended stack trace. Typically from helper
543 /// methods.
544 const List<LineException> beforeExceptions = const [
545 const LineException('wrapException', 'js_helper.dart'),
546 ];
547
548 /// Lines allowed after the intended stack trace. Typically from the event
549 /// queue.
550 const List<LineException> afterExceptions = const [
551 const LineException('_wrapJsFunctionForAsync', 'async_patch.dart'),
552 const LineException(
553 '_wrapJsFunctionForAsync.<anonymous function>', 'async_patch.dart'),
554 const LineException(
555 '_awaitOnObject.<anonymous function>', 'async_patch.dart'),
556 const LineException('_RootZone.runUnary', 'zone.dart'),
557 const LineException('_FutureListener.handleValue', 'future_impl.dart'),
558 const LineException(
559 '_Future._propagateToListeners.handleValueCallback', 'future_impl.dart'),
560 const LineException('_Future._propagateToListeners', 'future_impl.dart'),
561 const LineException(
562 '_Future._addListener.<anonymous function>', 'future_impl.dart'),
563 ];
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