OLD | NEW |
---|---|
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'; |
11 import 'package:compiler/src/apiimpl.dart'; | 11 import 'package:compiler/src/apiimpl.dart'; |
12 import 'package:compiler/src/commandline_options.dart'; | 12 import 'package:compiler/src/commandline_options.dart'; |
13 import 'package:compiler/src/dart2js.dart' as entry; | 13 import 'package:compiler/src/dart2js.dart' as entry; |
14 import 'package:expect/expect.dart'; | 14 import 'package:expect/expect.dart'; |
15 import 'package:source_maps/source_maps.dart'; | 15 import 'package:source_maps/source_maps.dart'; |
16 import 'package:source_maps/src/utils.dart'; | 16 import 'package:source_maps/src/utils.dart'; |
17 | 17 |
18 import '../source_map_validator_helper.dart'; | 18 import '../source_map_validator_helper.dart'; |
19 | 19 |
20 const String EXCEPTION_MARKER = '>ExceptionMarker<'; | 20 const String EXCEPTION_MARKER = '>ExceptionMarker<'; |
21 const String INPUT_FILE_NAME = 'in.dart'; | 21 const String INPUT_FILE_NAME = 'in.dart'; |
22 | 22 |
23 const List<String> TESTS = const <String>[ | 23 const List<String> TESTS = const <String>[ |
24 ''' | 24 ''' |
25 main() { | 25 main() { |
26 @{1:main}throw '$EXCEPTION_MARKER'; | 26 @{1:main}throw '$EXCEPTION_MARKER'; |
27 } | 27 } |
28 ''', | 28 ''', |
29 ''' | 29 ''' |
30 import 'package:expect/expect.dart'; | |
30 main() { | 31 main() { |
31 @{1:main}test(); | 32 @{1:main}test(); |
32 } | 33 } |
34 @NoInline() | |
33 test() { | 35 test() { |
34 @{2:test}throw '$EXCEPTION_MARKER'; | 36 @{2:test}throw '$EXCEPTION_MARKER'; |
35 } | 37 } |
36 ''', | 38 ''', |
37 ''' | 39 ''' |
40 import 'package:expect/expect.dart'; | |
38 main() { | 41 main() { |
39 @{1:main}Class.test(); | 42 @{1:main}Class.test(); |
40 } | 43 } |
41 class Class { | 44 class Class { |
45 @NoInline() | |
42 static test() { | 46 static test() { |
43 @{2:Class.test}throw '$EXCEPTION_MARKER'; | 47 @{2:Class.test}throw '$EXCEPTION_MARKER'; |
44 } | 48 } |
45 } | 49 } |
46 ''', | 50 ''', |
47 ''' | 51 ''' |
52 import 'package:expect/expect.dart'; | |
48 main() { | 53 main() { |
49 var c = new Class(); | 54 var c = new Class(); |
50 c.@{1:main}test(); | 55 c.@{1:main}test(); |
51 } | 56 } |
52 class Class { | 57 class Class { |
58 @NoInline() | |
53 test() { | 59 test() { |
54 @{2:Class.test}throw '$EXCEPTION_MARKER'; | 60 @{2:Class.test}throw '$EXCEPTION_MARKER'; |
55 } | 61 } |
56 } | 62 } |
57 ''', | 63 ''', |
58 ''' | 64 ''' |
59 import 'package:expect/expect.dart'; | 65 import 'package:expect/expect.dart'; |
60 main() { | 66 main() { |
61 var c = @{1:main}new Class(); | 67 var c = @{1:main}new Class(); |
62 } | 68 } |
63 class Class { | 69 class Class { |
64 @NoInline() | 70 @NoInline() |
65 Class() { | 71 Class() { |
66 @{2:Class}throw '$EXCEPTION_MARKER'; | 72 @{2:Class}throw '$EXCEPTION_MARKER'; |
67 } | 73 } |
68 } | 74 } |
69 ''', | 75 ''', |
76 ''' | |
77 import 'package:expect/expect.dart'; | |
78 main() { | |
79 @{1:main}test(); | |
80 } | |
81 @NoInline() | |
82 test() { | |
83 try { | |
84 @{2:test}throw '$EXCEPTION_MARKER'; | |
85 } finally { | |
86 } | |
87 } | |
88 ''', | |
89 ''' | |
90 import 'package:expect/expect.dart'; | |
91 main() { | |
92 @{1:main}test(); | |
93 } | |
94 @NoInline() | |
95 test() { | |
96 try { | |
97 @{2:test}throw '$EXCEPTION_MARKER'; | |
98 } on Error catch (e) { | |
99 } | |
100 } | |
101 ''', | |
102 ''' | |
103 import 'package:expect/expect.dart'; | |
104 main() { | |
105 @{1:main}test(); | |
106 } | |
107 @NoInline() | |
108 test() { | |
109 try { | |
110 @{2:test}throw '$EXCEPTION_MARKER'; | |
111 } on String catch (e) { | |
112 rethrow; | |
113 } | |
114 } | |
115 ''', | |
116 ''' | |
117 import 'package:expect/expect.dart'; | |
118 main() { | |
119 test(); // This call is no longer on the stack when the error is thrown. | |
120 } | |
121 @NoInline() | |
122 test() async { | |
123 @{1:test}throw '$EXCEPTION_MARKER'; | |
124 } | |
125 ''', | |
126 ''' | |
127 import 'package:expect/expect.dart'; | |
128 main() { | |
129 test1(); | |
130 } | |
131 @NoInline() | |
132 test1() async { | |
133 // This call is no longer on the stack when the error is thrown. | |
Siggi Cherem (dart-lang)
2016/11/17 15:20:54
if you are relying on this, consider adding one ex
Johnni Winther
2016/11/18 08:22:08
I'd rather have the test fail if this changes. Hav
Siggi Cherem (dart-lang)
2016/11/18 15:31:38
At that point we would be only testing exceptions
Johnni Winther
2016/11/21 08:44:20
Yes. I realize that the test wouldn't break from s
| |
134 await test2(); | |
135 } | |
136 @NoInline() | |
137 test2() async { | |
138 @{1:test2}throw '$EXCEPTION_MARKER'; | |
139 } | |
140 ''', | |
141 ''' | |
142 import 'package:expect/expect.dart'; | |
143 main() { | |
144 test1(); | |
145 } | |
146 @NoInline() | |
147 test1() async { | |
148 @{1:test1}test2(); | |
149 } | |
150 @NoInline() | |
151 test2() { | |
152 @{2:test2}throw '$EXCEPTION_MARKER'; | |
153 } | |
154 ''', | |
70 ]; | 155 ]; |
71 | 156 |
72 class Test { | 157 class Test { |
73 final String code; | 158 final String code; |
74 final List<StackTraceLine> expectedLines; | 159 final List<StackTraceLine> expectedLines; |
75 | 160 |
76 Test(this.code, this.expectedLines); | 161 Test(this.code, this.expectedLines); |
77 } | 162 } |
78 | 163 |
79 const int _LF = 0x0A; | 164 const int _LF = 0x0A; |
80 const int _CR = 0x0D; | 165 const int _CR = 0x0D; |
81 const int _LBRACE = 0x7B; | 166 const int _LBRACE = 0x7B; |
82 | 167 |
83 | |
84 Test processTestCode(String code) { | 168 Test processTestCode(String code) { |
85 StringBuffer codeBuffer = new StringBuffer(); | 169 StringBuffer codeBuffer = new StringBuffer(); |
86 Map<int, StackTraceLine> stackTraceMap = <int, StackTraceLine>{}; | 170 Map<int, StackTraceLine> stackTraceMap = <int, StackTraceLine>{}; |
87 int index = 0; | 171 int index = 0; |
88 int lineNo = 1; | 172 int lineNo = 1; |
89 int columnNo = 1; | 173 int columnNo = 1; |
90 while (index < code.length) { | 174 while (index < code.length) { |
91 int charCode = code.codeUnitAt(index); | 175 int charCode = code.codeUnitAt(index); |
92 switch (charCode) { | 176 switch (charCode) { |
93 case _LF: | 177 case _LF: |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
128 List<StackTraceLine> expectedLines = <StackTraceLine>[]; | 212 List<StackTraceLine> expectedLines = <StackTraceLine>[]; |
129 for (int stackTraceIndex in (stackTraceMap.keys.toList()..sort()).reversed) { | 213 for (int stackTraceIndex in (stackTraceMap.keys.toList()..sort()).reversed) { |
130 expectedLines.add(stackTraceMap[stackTraceIndex]); | 214 expectedLines.add(stackTraceMap[stackTraceIndex]); |
131 } | 215 } |
132 return new Test(codeBuffer.toString(), expectedLines); | 216 return new Test(codeBuffer.toString(), expectedLines); |
133 } | 217 } |
134 | 218 |
135 void main(List<String> arguments) { | 219 void main(List<String> arguments) { |
136 asyncTest(() async { | 220 asyncTest(() async { |
137 for (String code in TESTS) { | 221 for (String code in TESTS) { |
138 await runTest(processTestCode(code)); | 222 await runTest(processTestCode(code), verbose: arguments.contains('-v')); |
139 } | 223 } |
140 }); | 224 }); |
141 } | 225 } |
142 | 226 |
143 Future runTest(Test test) async { | 227 Future runTest(Test test, {bool verbose: false}) async { |
144 Directory tmpDir = await createTempDir(); | 228 Directory tmpDir = await createTempDir(); |
145 String input = '${tmpDir.path}/$INPUT_FILE_NAME'; | 229 String input = '${tmpDir.path}/$INPUT_FILE_NAME'; |
146 new File(input).writeAsStringSync(test.code); | 230 new File(input).writeAsStringSync(test.code); |
147 String output = '${tmpDir.path}/out.js'; | 231 String output = '${tmpDir.path}/out.js'; |
148 List<String> arguments = [ | 232 List<String> arguments = [ |
149 '-o$output', | 233 '-o$output', |
150 '--library-root=sdk', | 234 '--library-root=sdk', |
151 '--packages=${Platform.packageConfig}', | 235 '--packages=${Platform.packageConfig}', |
152 Flags.useNewSourceInfo, | 236 Flags.useNewSourceInfo, |
153 input, | 237 input, |
154 ]; | 238 ]; |
155 print("--------------------------------------------------------------------"); | 239 print("--------------------------------------------------------------------"); |
156 print("Compiling dart2js ${arguments.join(' ')}\n${test.code}"); | 240 print("Compiling dart2js ${arguments.join(' ')}\n${test.code}"); |
157 CompilationResult compilationResult = await entry.internalMain(arguments); | 241 CompilationResult compilationResult = await entry.internalMain(arguments); |
158 Expect.isTrue(compilationResult.isSuccess, | 242 Expect.isTrue(compilationResult.isSuccess, |
159 "Unsuccessful compilation of test:\n${test.code}"); | 243 "Unsuccessful compilation of test:\n${test.code}"); |
160 CompilerImpl compiler = compilationResult.compiler; | 244 CompilerImpl compiler = compilationResult.compiler; |
161 SingleMapping sourceMap = new SingleMapping.fromJson( | 245 SingleMapping sourceMap = new SingleMapping.fromJson( |
162 JSON.decode(new File('$output.map').readAsStringSync())); | 246 JSON.decode(new File('$output.map').readAsStringSync())); |
163 | 247 |
164 print("Running d8 $output"); | 248 print("Running d8 $output"); |
165 ProcessResult runResult = | 249 ProcessResult runResult = Process.runSync(d8executable, |
166 Process.runSync(d8executable, [output]); | 250 ['sdk/lib/_internal/js_runtime/lib/preambles/d8.js', output]); |
167 String out = '${runResult.stderr}\n${runResult.stdout}'; | 251 String out = '${runResult.stderr}\n${runResult.stdout}'; |
252 if (verbose) { | |
253 print('d8 output:'); | |
254 print(out); | |
255 } | |
168 List<String> lines = out.split(new RegExp(r'(\r|\n|\r\n)')); | 256 List<String> lines = out.split(new RegExp(r'(\r|\n|\r\n)')); |
169 List<StackTraceLine> jsStackTrace = <StackTraceLine>[]; | 257 List<StackTraceLine> jsStackTrace = <StackTraceLine>[]; |
170 bool seenMarker = false; | 258 bool seenMarker = false; |
171 for (String line in lines) { | 259 for (String line in lines) { |
172 if (seenMarker) { | 260 if (seenMarker) { |
173 line = line.trim(); | 261 line = line.trim(); |
174 if (line.startsWith('at ')) { | 262 if (line.startsWith('at ')) { |
175 jsStackTrace.add(new StackTraceLine.fromText(line)); | 263 jsStackTrace.add(new StackTraceLine.fromText(line)); |
176 } | 264 } |
177 } else if (line == EXCEPTION_MARKER) { | 265 } else if (line == EXCEPTION_MARKER) { |
(...skipping 25 matching lines...) Expand all Loading... | |
203 for (StackTraceLine line in dartStackTrace) { | 291 for (StackTraceLine line in dartStackTrace) { |
204 if (expectedIndex < test.expectedLines.length) { | 292 if (expectedIndex < test.expectedLines.length) { |
205 StackTraceLine expectedLine = test.expectedLines[expectedIndex]; | 293 StackTraceLine expectedLine = test.expectedLines[expectedIndex]; |
206 if (line.methodName == expectedLine.methodName && | 294 if (line.methodName == expectedLine.methodName && |
207 line.lineNo == expectedLine.lineNo && | 295 line.lineNo == expectedLine.lineNo && |
208 line.columnNo == expectedLine.columnNo) { | 296 line.columnNo == expectedLine.columnNo) { |
209 expectedIndex++; | 297 expectedIndex++; |
210 } | 298 } |
211 } | 299 } |
212 } | 300 } |
301 if (verbose) { | |
302 print('JavaScript stacktrace:'); | |
303 print(jsStackTrace.join('\n')); | |
304 print('Dart stacktrace:'); | |
305 print(dartStackTrace.join('\n')); | |
306 } | |
213 Expect.equals( | 307 Expect.equals( |
214 expectedIndex, | 308 expectedIndex, |
215 test.expectedLines.length, | 309 test.expectedLines.length, |
216 "Missing stack trace lines for test:\n${test.code}\n" | 310 "Missing stack trace lines for test:\n${test.code}\n" |
217 "Actual:\n${dartStackTrace.join('\n')}\n" | 311 "Actual:\n${dartStackTrace.join('\n')}\n" |
218 "Expected:\n${test.expectedLines.join('\n')}\n"); | 312 "Expected:\n${test.expectedLines.join('\n')}\n"); |
219 | 313 |
220 print("Deleting '${tmpDir.path}'."); | 314 print("Deleting '${tmpDir.path}'."); |
221 tmpDir.deleteSync(recursive: true); | 315 tmpDir.deleteSync(recursive: true); |
222 } | 316 } |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
334 /// Returns the path of the d8 executable. | 428 /// Returns the path of the d8 executable. |
335 String get d8executable { | 429 String get d8executable { |
336 if (Platform.isWindows) { | 430 if (Platform.isWindows) { |
337 return 'third_party/d8/windows/d8.exe'; | 431 return 'third_party/d8/windows/d8.exe'; |
338 } else if (Platform.isLinux) { | 432 } else if (Platform.isLinux) { |
339 return 'third_party/d8/linux/d8'; | 433 return 'third_party/d8/linux/d8'; |
340 } else if (Platform.isMacOS) { | 434 } else if (Platform.isMacOS) { |
341 return 'third_party/d8/macos/d8'; | 435 return 'third_party/d8/macos/d8'; |
342 } | 436 } |
343 throw new UnsupportedError('Unsupported platform.'); | 437 throw new UnsupportedError('Unsupported platform.'); |
344 } | 438 } |
OLD | NEW |