OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 'package:async_helper/async_helper.dart'; | 6 import 'package:async_helper/async_helper.dart'; |
7 import 'package:expect/expect.dart'; | 7 import 'package:expect/expect.dart'; |
8 import 'package:compiler/src/io/source_information.dart'; | 8 import 'package:compiler/src/io/source_information.dart'; |
9 import 'package:compiler/src/js/js_debug.dart'; | 9 import 'package:compiler/src/js/js_debug.dart'; |
10 import 'package:js_ast/js_ast.dart'; | 10 import 'package:js_ast/js_ast.dart'; |
11 import 'sourcemap_helper.dart'; | 11 import 'sourcemap_helper.dart'; |
12 | 12 |
13 typedef CodePointWhiteListFunction WhiteListFunction( | 13 typedef CodePointWhiteListFunction WhiteListFunction( |
14 String configuration, String file); | 14 String configuration, String file); |
15 | 15 |
16 typedef bool CodePointWhiteListFunction(CodePoint codePoint); | 16 typedef bool CodePointWhiteListFunction(CodePoint codePoint); |
17 | 17 |
18 CodePointWhiteListFunction emptyWhiteListFunction(String config, String file) { | 18 CodePointWhiteListFunction emptyWhiteListFunction(String config, String file) { |
19 return emptyWhiteList; | 19 return emptyWhiteList; |
20 } | 20 } |
21 | 21 |
22 bool emptyWhiteList(CodePoint codePoint) => false; | 22 bool emptyWhiteList(CodePoint codePoint) => false; |
23 | 23 |
24 main(List<String> arguments) { | 24 main(List<String> arguments) { |
25 test(arguments); | 25 test(arguments); |
26 } | 26 } |
27 | 27 |
28 void test(List<String> arguments, | 28 void test(List<String> arguments, |
29 {WhiteListFunction whiteListFunction: emptyWhiteListFunction}) { | 29 {WhiteListFunction whiteListFunction: emptyWhiteListFunction}) { |
30 Set<String> configurations = new Set<String>(); | 30 Set<String> configurations = new Set<String>(); |
31 Set<String> files = new Set<String>(); | 31 Set<String> files = new Set<String>(); |
32 for (String argument in arguments) { | 32 for (String argument in arguments) { |
33 if (!parseArgument(argument, configurations, files)) { | 33 if (!parseArgument(argument, configurations, files)) { |
34 return; | 34 return; |
35 } | 35 } |
36 } | 36 } |
37 | 37 |
38 if (configurations.isEmpty) { | 38 if (configurations.isEmpty) { |
39 configurations.addAll(TEST_CONFIGURATIONS.keys); | 39 configurations.addAll(TEST_CONFIGURATIONS.keys); |
40 configurations.remove('old'); | 40 configurations.remove('old'); |
41 } | 41 } |
42 if (files.isEmpty) { | 42 if (files.isEmpty) { |
43 files.addAll(TEST_FILES.keys); | 43 files.addAll(TEST_FILES.keys); |
44 } | 44 } |
45 | 45 |
46 asyncTest(() async { | 46 asyncTest(() async { |
47 bool errorsFound = false; | 47 bool errorsFound = false; |
48 for (String config in configurations) { | 48 for (String config in configurations) { |
49 List<String> options = TEST_CONFIGURATIONS[config]; | 49 List<String> options = TEST_CONFIGURATIONS[config]; |
50 for (String file in files) { | 50 for (String file in files) { |
51 String filename = TEST_FILES[file]; | 51 String filename = TEST_FILES[file]; |
52 TestResult result = await runTests( | 52 TestResult result = await runTests(config, filename, options); |
53 config, filename, options); | |
54 if (result.missingCodePointsMap.isNotEmpty) { | 53 if (result.missingCodePointsMap.isNotEmpty) { |
55 errorsFound = result.printMissingCodePoints( | 54 errorsFound = |
56 whiteListFunction(config, file)); | 55 result.printMissingCodePoints(whiteListFunction(config, file)); |
57 true; | 56 true; |
58 } | 57 } |
59 if (result.multipleNodesMap.isNotEmpty) { | 58 if (result.multipleNodesMap.isNotEmpty) { |
60 result.printMultipleNodes(); | 59 result.printMultipleNodes(); |
61 errorsFound = true; | 60 errorsFound = true; |
62 } | 61 } |
63 if (result.multipleOffsetsMap.isNotEmpty) { | 62 if (result.multipleOffsetsMap.isNotEmpty) { |
64 result.printMultipleOffsets(); | 63 result.printMultipleOffsets(); |
65 errorsFound = true; | 64 errorsFound = true; |
66 } | 65 } |
67 } | 66 } |
68 } | 67 } |
69 Expect.isFalse(errorsFound, | 68 Expect.isFalse( |
| 69 errorsFound, |
70 "Errors found. " | 70 "Errors found. " |
71 "Run the test with a URI option, " | 71 "Run the test with a URI option, " |
72 "`source_mapping_test_viewer [--out=<uri>] [configs] [tests]`, to " | 72 "`source_mapping_test_viewer [--out=<uri>] [configs] [tests]`, to " |
73 "create a html visualization of the missing code points."); | 73 "create a html visualization of the missing code points."); |
74 }); | 74 }); |
75 } | 75 } |
76 | 76 |
77 /// Parse [argument] for a valid configuration or test-file option. | 77 /// Parse [argument] for a valid configuration or test-file option. |
78 /// | 78 /// |
79 /// On success, the configuration name is added to [configurations] or the | 79 /// On success, the configuration name is added to [configurations] or the |
80 /// test-file name is added to [files], and `true` is returned. | 80 /// test-file name is added to [files], and `true` is returned. |
81 /// On failure, a message is printed and `false` is returned. | 81 /// On failure, a message is printed and `false` is returned. |
82 /// | 82 /// |
83 bool parseArgument(String argument, | 83 bool parseArgument( |
84 Set<String> configurations, | 84 String argument, Set<String> configurations, Set<String> files) { |
85 Set<String> files) { | |
86 if (TEST_CONFIGURATIONS.containsKey(argument)) { | 85 if (TEST_CONFIGURATIONS.containsKey(argument)) { |
87 configurations.add(argument); | 86 configurations.add(argument); |
88 } else if (TEST_FILES.containsKey(argument)) { | 87 } else if (TEST_FILES.containsKey(argument)) { |
89 files.add(argument); | 88 files.add(argument); |
90 } else { | 89 } else { |
91 print("Unknown configuration or file '$argument'. " | 90 print("Unknown configuration or file '$argument'. " |
92 "Must be one of '${TEST_CONFIGURATIONS.keys.join("', '")}' or " | 91 "Must be one of '${TEST_CONFIGURATIONS.keys.join("', '")}' or " |
93 "'${TEST_FILES.keys.join("', '")}'."); | 92 "'${TEST_FILES.keys.join("', '")}'."); |
94 return false; | 93 return false; |
95 } | 94 } |
96 return true; | 95 return true; |
97 } | 96 } |
98 | 97 |
99 const Map<String, List<String>> TEST_CONFIGURATIONS = const { | 98 const Map<String, List<String>> TEST_CONFIGURATIONS = const { |
100 'ssa': const ['--use-new-source-info', ], | 99 'ssa': const [ |
| 100 '--use-new-source-info', |
| 101 ], |
101 'old': const [], | 102 'old': const [], |
102 }; | 103 }; |
103 | 104 |
104 const Map<String, String> TEST_FILES = const <String, String>{ | 105 const Map<String, String> TEST_FILES = const <String, String>{ |
105 'invokes': 'tests/compiler/dart2js/sourcemaps/invokes_test_file.dart', | 106 'invokes': 'tests/compiler/dart2js/sourcemaps/invokes_test_file.dart', |
106 'operators': 'tests/compiler/dart2js/sourcemaps/operators_test_file.dart', | 107 'operators': 'tests/compiler/dart2js/sourcemaps/operators_test_file.dart', |
107 }; | 108 }; |
108 | 109 |
109 Future<TestResult> runTests( | 110 Future<TestResult> runTests( |
110 String config, | 111 String config, String filename, List<String> options, |
111 String filename, | |
112 List<String> options, | |
113 {bool verbose: true}) async { | 112 {bool verbose: true}) async { |
114 SourceMapProcessor processor = new SourceMapProcessor(filename); | 113 SourceMapProcessor processor = new SourceMapProcessor(filename); |
115 SourceMaps sourceMaps = await processor.process( | 114 SourceMaps sourceMaps = await processor.process( |
116 ['--csp', '--disable-inlining'] | 115 ['--csp', '--disable-inlining']..addAll(options), |
117 ..addAll(options), | |
118 verbose: verbose); | 116 verbose: verbose); |
119 TestResult result = new TestResult(config, filename, processor); | 117 TestResult result = new TestResult(config, filename, processor); |
120 for (SourceMapInfo info in sourceMaps.elementSourceMapInfos.values) { | 118 for (SourceMapInfo info in sourceMaps.elementSourceMapInfos.values) { |
121 if (info.element.library.isPlatformLibrary) continue; | 119 if (info.element.library.isPlatformLibrary) continue; |
122 result.userInfoList.add(info); | 120 result.userInfoList.add(info); |
123 Iterable<CodePoint> missingCodePoints = | 121 Iterable<CodePoint> missingCodePoints = |
124 info.codePoints.where((c) => c.isMissing); | 122 info.codePoints.where((c) => c.isMissing); |
125 if (missingCodePoints.isNotEmpty) { | 123 if (missingCodePoints.isNotEmpty) { |
126 result.missingCodePointsMap[info] = missingCodePoints; | 124 result.missingCodePointsMap[info] = missingCodePoints; |
127 } | 125 } |
128 Map<int, Set<SourceLocation>> offsetToLocationsMap = | 126 Map<int, Set<SourceLocation>> offsetToLocationsMap = |
129 <int, Set<SourceLocation>>{}; | 127 <int, Set<SourceLocation>>{}; |
130 for (Node node in info.nodeMap.nodes) { | 128 for (Node node in info.nodeMap.nodes) { |
131 info.nodeMap[node].forEach( | 129 info.nodeMap[node] |
132 (int targetOffset, List<SourceLocation> sourceLocations) { | 130 .forEach((int targetOffset, List<SourceLocation> sourceLocations) { |
133 if (sourceLocations.length > 1) { | 131 if (sourceLocations.length > 1) { |
134 Map<Node, List<SourceLocation>> multipleMap = | 132 Map<Node, List<SourceLocation>> multipleMap = result.multipleNodesMap |
135 result.multipleNodesMap.putIfAbsent(info, | 133 .putIfAbsent(info, () => <Node, List<SourceLocation>>{}); |
136 () => <Node, List<SourceLocation>>{}); | |
137 multipleMap[node] = sourceLocations; | 134 multipleMap[node] = sourceLocations; |
138 } else { | 135 } else { |
139 offsetToLocationsMap | 136 offsetToLocationsMap |
140 .putIfAbsent(targetOffset, () => new Set<SourceLocation>()) | 137 .putIfAbsent(targetOffset, () => new Set<SourceLocation>()) |
141 .addAll(sourceLocations); | 138 .addAll(sourceLocations); |
142 } | 139 } |
143 }); | 140 }); |
144 } | 141 } |
145 offsetToLocationsMap.forEach( | 142 offsetToLocationsMap |
146 (int targetOffset, Set<SourceLocation> sourceLocations) { | 143 .forEach((int targetOffset, Set<SourceLocation> sourceLocations) { |
147 if (sourceLocations.length > 1) { | 144 if (sourceLocations.length > 1) { |
148 Map<int, Set<SourceLocation>> multipleMap = | 145 Map<int, Set<SourceLocation>> multipleMap = result.multipleOffsetsMap |
149 result.multipleOffsetsMap.putIfAbsent(info, | 146 .putIfAbsent(info, () => <int, Set<SourceLocation>>{}); |
150 () => <int, Set<SourceLocation>>{}); | |
151 multipleMap[targetOffset] = sourceLocations; | 147 multipleMap[targetOffset] = sourceLocations; |
152 } | 148 } |
153 }); | 149 }); |
154 } | 150 } |
155 return result; | 151 return result; |
156 } | 152 } |
157 | 153 |
158 class TestResult { | 154 class TestResult { |
159 final String config; | 155 final String config; |
160 final String file; | 156 final String file; |
(...skipping 12 matching lines...) Expand all Loading... |
173 Map<SourceMapInfo, Map<int, Set<SourceLocation>>> multipleOffsetsMap = | 169 Map<SourceMapInfo, Map<int, Set<SourceLocation>>> multipleOffsetsMap = |
174 <SourceMapInfo, Map<int, Set<SourceLocation>>>{}; | 170 <SourceMapInfo, Map<int, Set<SourceLocation>>>{}; |
175 | 171 |
176 TestResult(this.config, this.file, this.processor); | 172 TestResult(this.config, this.file, this.processor); |
177 | 173 |
178 bool printMissingCodePoints( | 174 bool printMissingCodePoints( |
179 [CodePointWhiteListFunction codePointWhiteList = emptyWhiteList]) { | 175 [CodePointWhiteListFunction codePointWhiteList = emptyWhiteList]) { |
180 bool allWhiteListed = true; | 176 bool allWhiteListed = true; |
181 missingCodePointsMap.forEach((info, missingCodePoints) { | 177 missingCodePointsMap.forEach((info, missingCodePoints) { |
182 print("Missing code points for ${info.element} in '$file' " | 178 print("Missing code points for ${info.element} in '$file' " |
183 "in config '$config':"); | 179 "in config '$config':"); |
184 for (CodePoint codePoint in missingCodePoints) { | 180 for (CodePoint codePoint in missingCodePoints) { |
185 if (codePointWhiteList(codePoint)) { | 181 if (codePointWhiteList(codePoint)) { |
186 print(" $codePoint (white-listed)"); | 182 print(" $codePoint (white-listed)"); |
187 } else { | 183 } else { |
188 print(" $codePoint"); | 184 print(" $codePoint"); |
189 allWhiteListed = false; | 185 allWhiteListed = false; |
190 } | 186 } |
191 } | 187 } |
192 }); | 188 }); |
193 return !allWhiteListed; | 189 return !allWhiteListed; |
194 } | 190 } |
195 | 191 |
196 void printMultipleNodes() { | 192 void printMultipleNodes() { |
197 multipleNodesMap.forEach((info, multipleMap) { | 193 multipleNodesMap.forEach((info, multipleMap) { |
198 multipleMap.forEach((node, sourceLocations) { | 194 multipleMap.forEach((node, sourceLocations) { |
199 print('Multiple source locations:\n ${sourceLocations.join('\n ')}\n' | 195 print('Multiple source locations:\n ${sourceLocations.join('\n ')}\n' |
200 'for `${nodeToString(node)}` in ${info.element} in ' | 196 'for `${nodeToString(node)}` in ${info.element} in ' |
201 '$file.'); | 197 '$file.'); |
202 }); | 198 }); |
203 }); | 199 }); |
204 } | 200 } |
205 | 201 |
206 void printMultipleOffsets() { | 202 void printMultipleOffsets() { |
207 multipleOffsetsMap.forEach((info, multipleMap) { | 203 multipleOffsetsMap.forEach((info, multipleMap) { |
208 multipleMap.forEach((targetOffset, sourceLocations) { | 204 multipleMap.forEach((targetOffset, sourceLocations) { |
209 print( | 205 print('Multiple source locations:\n ${sourceLocations.join('\n ')}\n' |
210 'Multiple source locations:\n ${sourceLocations.join('\n ')}\n' | |
211 'for offset $targetOffset in ${info.element} in $file.'); | 206 'for offset $targetOffset in ${info.element} in $file.'); |
212 }); | 207 }); |
213 }); | 208 }); |
214 } | 209 } |
215 } | 210 } |
OLD | NEW |