| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 library multitest; | 5 library multitest; |
| 6 | 6 |
| 7 import "dart:async"; | 7 import "dart:async"; |
| 8 import "dart:io"; | 8 import "dart:io"; |
| 9 | 9 |
| 10 import "path.dart"; | 10 import "path.dart"; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 // fff | 65 // fff |
| 66 | 66 |
| 67 /// Until legacy multitests are ported we need to support both /// and //# | 67 /// Until legacy multitests are ported we need to support both /// and //# |
| 68 final _multitestMarker = new RegExp(r"//[/#]"); | 68 final _multitestMarker = new RegExp(r"//[/#]"); |
| 69 | 69 |
| 70 void ExtractTestsFromMultitest(Path filePath, Map<String, String> tests, | 70 void ExtractTestsFromMultitest(Path filePath, Map<String, String> tests, |
| 71 Map<String, Set<String>> outcomes) { | 71 Map<String, Set<String>> outcomes) { |
| 72 // Read the entire file into a byte buffer and transform it to a | 72 // Read the entire file into a byte buffer and transform it to a |
| 73 // String. This will treat the file as ascii but the only parts | 73 // String. This will treat the file as ascii but the only parts |
| 74 // we are interested in will be ascii in any case. | 74 // we are interested in will be ascii in any case. |
| 75 List bytes = new File(filePath.toNativePath()).readAsBytesSync(); | 75 var bytes = new File(filePath.toNativePath()).readAsBytesSync(); |
| 76 String contents = decodeUtf8(bytes); | 76 var contents = decodeUtf8(bytes); |
| 77 int first_newline = contents.indexOf('\n'); | 77 var firstNewline = contents.indexOf('\n'); |
| 78 final String line_separator = | 78 var lineSeparator = |
| 79 (first_newline == 0 || contents[first_newline - 1] != '\r') | 79 (firstNewline == 0 || contents[firstNewline - 1] != '\r') ? '\n' : '\r\n'; |
| 80 ? '\n' | 80 var lines = contents.split(lineSeparator); |
| 81 : '\r\n'; | |
| 82 List<String> lines = contents.split(line_separator); | |
| 83 if (lines.last == '') lines.removeLast(); | 81 if (lines.last == '') lines.removeLast(); |
| 84 bytes = null; | 82 bytes = null; |
| 85 contents = null; | 83 contents = null; |
| 86 Set<String> validMultitestOutcomes = new Set<String>.from([ | 84 var validMultitestOutcomes = [ |
| 87 'ok', | 85 'ok', |
| 88 'compile-time error', | 86 'compile-time error', |
| 89 'runtime error', | 87 'runtime error', |
| 90 'static type warning', | 88 'static type warning', |
| 91 'dynamic type error', | 89 'dynamic type error', |
| 92 'checked mode compile-time error' | 90 'checked mode compile-time error' |
| 93 ]); | 91 ].toSet(); |
| 94 | 92 |
| 95 // Create the set of multitests, which will have a new test added each | 93 // Create the set of multitests, which will have a new test added each |
| 96 // time we see a multitest line with a new key. | 94 // time we see a multitest line with a new key. |
| 97 Map<String, List<String>> testsAsLines = new Map<String, List<String>>(); | 95 var testsAsLines = <String, List<String>>{}; |
| 98 | 96 |
| 99 // Add the default case with key "none". | 97 // Add the default case with key "none". |
| 100 testsAsLines['none'] = new List<String>(); | 98 testsAsLines['none'] = <String>[]; |
| 101 outcomes['none'] = new Set<String>(); | 99 outcomes['none'] = new Set<String>(); |
| 102 | 100 |
| 103 int lineCount = 0; | 101 var lineCount = 0; |
| 104 for (String line in lines) { | 102 for (var line in lines) { |
| 105 lineCount++; | 103 lineCount++; |
| 106 var annotation = new _Annotation.from(line); | 104 var annotation = new _Annotation.from(line); |
| 107 if (annotation != null) { | 105 if (annotation != null) { |
| 108 testsAsLines.putIfAbsent( | 106 testsAsLines.putIfAbsent( |
| 109 annotation.key, () => new List<String>.from(testsAsLines["none"])); | 107 annotation.key, () => new List<String>.from(testsAsLines["none"])); |
| 110 // Add line to test with annotation.key as key, empty line to the rest. | 108 // Add line to test with annotation.key as key, empty line to the rest. |
| 111 for (var key in testsAsLines.keys) { | 109 for (var key in testsAsLines.keys) { |
| 112 testsAsLines[key].add(annotation.key == key ? line : ""); | 110 testsAsLines[key].add(annotation.key == key ? line : ""); |
| 113 } | 111 } |
| 114 outcomes.putIfAbsent(annotation.key, () => new Set<String>()); | 112 outcomes.putIfAbsent(annotation.key, () => new Set<String>()); |
| 115 if (annotation.rest != 'continued') { | 113 if (annotation.rest != 'continued') { |
| 116 for (String nextOutcome in annotation.outcomesList) { | 114 for (String nextOutcome in annotation.outcomesList) { |
| 117 if (validMultitestOutcomes.contains(nextOutcome)) { | 115 if (validMultitestOutcomes.contains(nextOutcome)) { |
| 118 outcomes[annotation.key].add(nextOutcome); | 116 outcomes[annotation.key].add(nextOutcome); |
| 119 } else { | 117 } else { |
| 120 DebugLogger.warning( | 118 DebugLogger.warning( |
| 121 "Warning: Invalid test directive '$nextOutcome' on line " | 119 "Warning: Invalid test directive '$nextOutcome' on line " |
| 122 "${lineCount}:\n${annotation.rest} "); | 120 "${lineCount}:\n${annotation.rest} "); |
| 123 } | 121 } |
| 124 } | 122 } |
| 125 } | 123 } |
| 126 } else { | 124 } else { |
| 127 for (var test in testsAsLines.values) test.add(line); | 125 for (var test in testsAsLines.values) test.add(line); |
| 128 } | 126 } |
| 129 } | 127 } |
| 130 // End marker, has a final line separator so we don't need to add it after | 128 // End marker, has a final line separator so we don't need to add it after |
| 131 // joining the lines. | 129 // joining the lines. |
| 132 var marker = | 130 var marker = |
| 133 '// Test created from multitest named ${filePath.toNativePath()}.' | 131 '// Test created from multitest named ${filePath.toNativePath()}.' |
| 134 '$line_separator'; | 132 '$lineSeparator'; |
| 135 for (var test in testsAsLines.values) test.add(marker); | 133 for (var test in testsAsLines.values) test.add(marker); |
| 136 | 134 |
| 137 var keysToDelete = []; | 135 var keysToDelete = <String>[]; |
| 138 // Check that every key (other than the none case) has at least one outcome | 136 // Check that every key (other than the none case) has at least one outcome |
| 139 for (var outcomeKey in outcomes.keys) { | 137 for (var outcomeKey in outcomes.keys) { |
| 140 if (outcomeKey != 'none' && outcomes[outcomeKey].isEmpty) { | 138 if (outcomeKey != 'none' && outcomes[outcomeKey].isEmpty) { |
| 141 DebugLogger.warning( | 139 DebugLogger.warning( |
| 142 "Warning: Test ${outcomeKey} has no valid annotated outcomes.\n" | 140 "Warning: Test ${outcomeKey} has no valid annotated outcomes.\n" |
| 143 "Expected one of: ${validMultitestOutcomes.toString()}"); | 141 "Expected one of: ${validMultitestOutcomes.toString()}"); |
| 144 // If this multitest doesn't have an outcome, mark the multitest for | 142 // If this multitest doesn't have an outcome, mark the multitest for |
| 145 // deletion. | 143 // deletion. |
| 146 keysToDelete.add(outcomeKey); | 144 keysToDelete.add(outcomeKey); |
| 147 } | 145 } |
| 148 } | 146 } |
| 149 // If a key/multitest was marked for deletion, do the necessary cleanup. | 147 // If a key/multitest was marked for deletion, do the necessary cleanup. |
| 150 keysToDelete.forEach(outcomes.remove); | 148 keysToDelete.forEach(outcomes.remove); |
| 151 keysToDelete.forEach(testsAsLines.remove); | 149 keysToDelete.forEach(testsAsLines.remove); |
| 152 | 150 |
| 153 // Copy all the tests into the output map tests, as multiline strings. | 151 // Copy all the tests into the output map tests, as multiline strings. |
| 154 for (String key in testsAsLines.keys) { | 152 for (var key in testsAsLines.keys) { |
| 155 tests[key] = testsAsLines[key].join(line_separator); | 153 tests[key] = testsAsLines[key].join(lineSeparator); |
| 156 } | 154 } |
| 157 } | 155 } |
| 158 | 156 |
| 159 // Represents a mutlitest annotation in the special //# comment. | 157 // Represents a mutlitest annotation in the special //# comment. |
| 160 class _Annotation { | 158 class _Annotation { |
| 161 String key; | 159 String key; |
| 162 String rest; | 160 String rest; |
| 163 List<String> outcomesList; | 161 List<String> outcomesList; |
| 164 _Annotation() {} | 162 _Annotation() {} |
| 165 factory _Annotation.from(String line) { | 163 factory _Annotation.from(String line) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 183 annotation.rest = parts[1]; | 181 annotation.rest = parts[1]; |
| 184 annotation.outcomesList = | 182 annotation.outcomesList = |
| 185 annotation.rest.split(',').map((s) => s.trim()).toList(); | 183 annotation.rest.split(',').map((s) => s.trim()).toList(); |
| 186 return annotation; | 184 return annotation; |
| 187 } | 185 } |
| 188 } | 186 } |
| 189 | 187 |
| 190 // Find all relative imports and copy them into the dir that contains | 188 // Find all relative imports and copy them into the dir that contains |
| 191 // the generated tests. | 189 // the generated tests. |
| 192 Set<String> _findAllRelativeImports(Path topLibrary) { | 190 Set<String> _findAllRelativeImports(Path topLibrary) { |
| 193 Set<Path> toSearch = new Set<Path>.from([topLibrary]); | 191 var toSearch = [topLibrary].toSet(); |
| 194 Set<String> foundImports = new Set<String>(); | 192 var foundImports = new Set<String>(); |
| 195 Path libraryDir = topLibrary.directoryPath; | 193 var libraryDir = topLibrary.directoryPath; |
| 196 RegExp relativeImportRegExp = new RegExp( | 194 var relativeImportRegExp = new RegExp( |
| 197 '^(?:@.*\\s+)?' // Allow for a meta-data annotation. | 195 '^(?:@.*\\s+)?' // Allow for a meta-data annotation. |
| 198 '(import|part)' | 196 '(import|part)' |
| 199 '\\s+["\']' | 197 '\\s+["\']' |
| 200 '(?!(dart:|dart-ext:|data:|package:|/))' // Look-ahead: not in package. | 198 '(?!(dart:|dart-ext:|data:|package:|/))' // Look-ahead: not in package. |
| 201 '([^"\']*)' // The path to the imported file. | 199 '([^"\']*)' // The path to the imported file. |
| 202 '["\']'); | 200 '["\']'); |
| 203 while (!toSearch.isEmpty) { | 201 while (!toSearch.isEmpty) { |
| 204 var thisPass = toSearch; | 202 var thisPass = toSearch; |
| 205 toSearch = new Set<Path>(); | 203 toSearch = new Set<Path>(); |
| 206 for (Path filename in thisPass) { | 204 for (Path filename in thisPass) { |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 | 308 |
| 311 Path createMultitestDirectory(String outputDir, Path suiteDir, Path sourceDir) { | 309 Path createMultitestDirectory(String outputDir, Path suiteDir, Path sourceDir) { |
| 312 Path relative = sourceDir.relativeTo(suiteDir); | 310 Path relative = sourceDir.relativeTo(suiteDir); |
| 313 Path path = new Path(outputDir) | 311 Path path = new Path(outputDir) |
| 314 .append('generated_tests') | 312 .append('generated_tests') |
| 315 .append(suiteNameFromPath(suiteDir)) | 313 .append(suiteNameFromPath(suiteDir)) |
| 316 .join(relative); | 314 .join(relative); |
| 317 TestUtils.mkdirRecursive(TestUtils.currentWorkingDirectory, path); | 315 TestUtils.mkdirRecursive(TestUtils.currentWorkingDirectory, path); |
| 318 return new Path(new File(path.toNativePath()).absolute.path); | 316 return new Path(new File(path.toNativePath()).absolute.path); |
| 319 } | 317 } |
| OLD | NEW |