| 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 'sourcemap_helper.dart'; | 8 import 'sourcemap_helper.dart'; |
| 9 import 'sourcemap_html_helper.dart'; | |
| 10 import 'package:compiler/src/filenames.dart'; | |
| 11 | 9 |
| 12 main(List<String> arguments) { | 10 main(List<String> arguments) { |
| 13 bool showAll = false; | |
| 14 bool measure = false; | |
| 15 Uri outputUri; | |
| 16 Set<String> configurations = new Set<String>(); | 11 Set<String> configurations = new Set<String>(); |
| 12 Set<String> files = new Set<String>(); |
| 17 for (String argument in arguments) { | 13 for (String argument in arguments) { |
| 18 if (argument.startsWith('-')) { | 14 if (!parseArgument(argument, configurations, files)) { |
| 19 if (argument == '-a') { | 15 return; |
| 20 /// Generate visualization for all user methods. | |
| 21 showAll = true; | |
| 22 } else if (argument == '-m') { | |
| 23 /// Measure instead of reporting the number of missing code points. | |
| 24 measure = true; | |
| 25 } else if (argument.startsWith('--out=')) { | |
| 26 /// Generate visualization for the first configuration. | |
| 27 outputUri = Uri.base.resolve( | |
| 28 nativeToUriPath(argument.substring('--out='.length))); | |
| 29 } else if (argument.startsWith('-o')) { | |
| 30 /// Generate visualization for the first configuration. | |
| 31 outputUri = Uri.base.resolve( | |
| 32 nativeToUriPath(argument.substring('-o'.length))); | |
| 33 } else { | |
| 34 print("Unknown option '$argument'."); | |
| 35 return; | |
| 36 } | |
| 37 } else { | |
| 38 if (TEST_CONFIGURATIONS.containsKey(argument)) { | |
| 39 configurations.add(argument); | |
| 40 } else { | |
| 41 print("Unknown configuration '$argument'. " | |
| 42 "Must be one of '${TEST_CONFIGURATIONS.keys.join("', '")}'"); | |
| 43 return; | |
| 44 } | |
| 45 } | 16 } |
| 46 } | 17 } |
| 47 | 18 |
| 48 if (configurations.isEmpty) { | 19 if (configurations.isEmpty) { |
| 49 configurations.addAll(TEST_CONFIGURATIONS.keys); | 20 configurations.addAll(TEST_CONFIGURATIONS.keys); |
| 21 configurations.remove('old'); |
| 50 } | 22 } |
| 51 String outputConfig = configurations.first; | 23 if (files.isEmpty) { |
| 24 files.addAll(TEST_FILES.keys); |
| 25 } |
| 52 | 26 |
| 53 asyncTest(() async { | 27 asyncTest(() async { |
| 54 List<Measurement> measurements = <Measurement>[]; | 28 bool missingCodePointsFound = false; |
| 55 for (String config in configurations) { | 29 for (String config in configurations) { |
| 56 List<String> options = TEST_CONFIGURATIONS[config]; | 30 List<String> options = TEST_CONFIGURATIONS[config]; |
| 57 Measurement measurement = await runTests( | 31 for (String file in files) { |
| 58 config, | 32 String filename = TEST_FILES[file]; |
| 59 options, | 33 TestResult result = await runTests(config, filename, options); |
| 60 showAll: showAll, | 34 if (result.failureMap.isNotEmpty) { |
| 61 measure: measure, | 35 result.failureMap.forEach((info, missingCodePoints) { |
| 62 outputUri: outputConfig == config ? outputUri : null); | 36 print("Missing code points for ${info.element} in '$filename' " |
| 63 if (measurement != null) { | 37 "in config '$config':"); |
| 64 measurements.add(measurement); | 38 for (CodePoint codePoint in missingCodePoints) { |
| 39 print(" $codePoint"); |
| 40 } |
| 41 }); |
| 42 missingCodePointsFound = true; |
| 43 } |
| 65 } | 44 } |
| 66 } | 45 } |
| 67 for (Measurement measurement in measurements) { | 46 Expect.isFalse(missingCodePointsFound, |
| 68 print(measurement); | 47 "Missing code points found. " |
| 69 } | 48 "Run the test with a URI option, " |
| 49 "`source_mapping_test_viewer [--out=<uri>] [configs] [tests]`, to " |
| 50 "create a html visualization of the missing code points."); |
| 70 }); | 51 }); |
| 71 } | 52 } |
| 72 | 53 |
| 54 /// Parse [argument] for a valid configuration or test-file option. |
| 55 /// |
| 56 /// On success, the configuration name is added to [configurations] or the |
| 57 /// test-file name is added to [files], and `true` is returned. |
| 58 /// On failure, a message is printed and `false` is returned. |
| 59 /// |
| 60 bool parseArgument(String argument, |
| 61 Set<String> configurations, |
| 62 Set<String> files) { |
| 63 if (TEST_CONFIGURATIONS.containsKey(argument)) { |
| 64 configurations.add(argument); |
| 65 } else if (TEST_FILES.containsKey(argument)) { |
| 66 files.add(argument); |
| 67 } else { |
| 68 print("Unknown configuration or file '$argument'. " |
| 69 "Must be one of '${TEST_CONFIGURATIONS.keys.join("', '")}' or " |
| 70 "'${TEST_FILES.keys.join("', '")}'."); |
| 71 return false; |
| 72 } |
| 73 return true; |
| 74 } |
| 75 |
| 73 const Map<String, List<String>> TEST_CONFIGURATIONS = const { | 76 const Map<String, List<String>> TEST_CONFIGURATIONS = const { |
| 74 'old': const [], | |
| 75 'ssa': const ['--use-new-source-info', ], | 77 'ssa': const ['--use-new-source-info', ], |
| 76 'cps': const ['--use-new-source-info', '--use-cps-ir'], | 78 'cps': const ['--use-new-source-info', '--use-cps-ir'], |
| 79 'old': const [], |
| 77 }; | 80 }; |
| 78 | 81 |
| 79 Future<Measurement> runTests( | 82 const Map<String, String> TEST_FILES = const <String, String>{ |
| 83 'invokes': 'tests/compiler/dart2js/sourcemaps/invokes_test_file.dart', |
| 84 'operators': 'tests/compiler/dart2js/sourcemaps/operators_test_file.dart', |
| 85 }; |
| 86 |
| 87 Future<TestResult> runTests( |
| 80 String config, | 88 String config, |
| 89 String filename, |
| 81 List<String> options, | 90 List<String> options, |
| 82 {bool showAll: false, | 91 {bool verbose: true}) async { |
| 83 Uri outputUri, | |
| 84 bool measure: false}) async { | |
| 85 if (config == 'old' && !measure) return null; | |
| 86 | |
| 87 String filename = | |
| 88 'tests/compiler/dart2js/sourcemaps/invokes_test_file.dart'; | |
| 89 SourceMapProcessor processor = new SourceMapProcessor(filename); | 92 SourceMapProcessor processor = new SourceMapProcessor(filename); |
| 90 List<SourceMapInfo> infoList = await processor.process( | 93 List<SourceMapInfo> infoList = await processor.process( |
| 91 ['--csp', '--disable-inlining'] | 94 ['--csp', '--disable-inlining'] |
| 92 ..addAll(options), | 95 ..addAll(options), |
| 93 verbose: !measure); | 96 verbose: verbose); |
| 94 List<SourceMapInfo> userInfoList = <SourceMapInfo>[]; | 97 TestResult result = new TestResult(config, filename, processor); |
| 95 List<SourceMapInfo> failureList = <SourceMapInfo>[]; | |
| 96 Measurement measurement = new Measurement(config); | |
| 97 for (SourceMapInfo info in infoList) { | 98 for (SourceMapInfo info in infoList) { |
| 98 if (info.element.library.isPlatformLibrary) continue; | 99 if (info.element.library.isPlatformLibrary) continue; |
| 99 userInfoList.add(info); | 100 result.userInfoList.add(info); |
| 100 Iterable<CodePoint> missingCodePoints = | 101 Iterable<CodePoint> missingCodePoints = |
| 101 info.codePoints.where((c) => c.isMissing); | 102 info.codePoints.where((c) => c.isMissing); |
| 102 measurement.missing += missingCodePoints.length; | 103 if (missingCodePoints.isNotEmpty) { |
| 103 measurement.count += info.codePoints.length; | 104 result.failureMap[info] = missingCodePoints; |
| 104 if (!measure) { | |
| 105 if (!missingCodePoints.isEmpty) { | |
| 106 print("Missing code points for ${info.element} in '$filename':"); | |
| 107 for (CodePoint codePoint in missingCodePoints) { | |
| 108 print(" $codePoint"); | |
| 109 } | |
| 110 failureList.add(info); | |
| 111 } | |
| 112 } | 105 } |
| 113 } | 106 } |
| 114 if (failureList.isNotEmpty) { | 107 return result; |
| 115 if (outputUri == null) { | |
| 116 if (!measure) { | |
| 117 Expect.fail( | |
| 118 "Missing code points found. " | |
| 119 "Run the test with a URI option, " | |
| 120 "`source_mapping_test --out=<uri> $config`, to " | |
| 121 "create a html visualization of the missing code points."); | |
| 122 } | |
| 123 } else { | |
| 124 createTraceSourceMapHtml(outputUri, processor, | |
| 125 showAll ? userInfoList : failureList); | |
| 126 } | |
| 127 } else if (outputUri != null) { | |
| 128 createTraceSourceMapHtml(outputUri, processor, userInfoList); | |
| 129 } | |
| 130 return measurement; | |
| 131 } | 108 } |
| 132 | 109 |
| 133 class Measurement { | 110 class TestResult { |
| 134 final String config; | 111 final String config; |
| 135 int missing = 0; | 112 final String file; |
| 136 int count = 0; | 113 final SourceMapProcessor processor; |
| 114 List<SourceMapInfo> userInfoList = <SourceMapInfo>[]; |
| 115 Map<SourceMapInfo, Iterable<CodePoint>> failureMap = |
| 116 <SourceMapInfo, Iterable<CodePoint>>{}; |
| 137 | 117 |
| 138 Measurement(this.config); | 118 TestResult(this.config, this.file, this.processor); |
| 139 | |
| 140 String toString() { | |
| 141 double percentage = 100 * missing / count; | |
| 142 return "Config '${config}': $missing of $count ($percentage%) missing"; | |
| 143 } | |
| 144 } | 119 } |
| OLD | NEW |