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 |