| 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 |