| 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"; | 
| 11 import "test_suite.dart"; | 11 import "test_suite.dart"; | 
| 12 import "utils.dart"; | 12 import "utils.dart"; | 
| 13 | 13 | 
| 14 // Multitests are Dart test scripts containing lines of the form | 14 // Multitests are Dart test scripts containing lines of the form | 
|  | 15 // " [some dart code] //# [key]: [error type]" | 
|  | 16 // | 
|  | 17 // To support legacy multi tests we also handle lines of the form | 
| 15 // " [some dart code] /// [key]: [error type]" | 18 // " [some dart code] /// [key]: [error type]" | 
| 16 // | 19 // | 
| 17 // For each key in the file, a new test file is made containing all | 20 // For each key in the file, a new test file is made containing all | 
| 18 // the normal lines of the file, and all of the multitest lines containing | 21 // the normal lines of the file, and all of the multitest lines containing | 
| 19 // that key, in the same order as in the source file.  The new test is expected | 22 // that key, in the same order as in the source file.  The new test is expected | 
| 20 // to pass if the error type listed is 'ok', or to fail if there is an error | 23 // to pass if the error type listed is 'ok', or to fail if there is an error | 
| 21 // type of type 'compile-time error', 'runtime error', 'static type warning', or | 24 // type of type 'compile-time error', 'runtime error', 'static type warning', or | 
| 22 // 'dynamic type error'.  The type error tests fail only in checked mode. | 25 // 'dynamic type error'.  The type error tests fail only in checked mode. | 
| 23 // There is also a test created from only the untagged lines of the file, | 26 // There is also a test created from only the untagged lines of the file, | 
| 24 // with key "none", which is expected to pass.  This library extracts these | 27 // with key "none", which is expected to pass.  This library extracts these | 
| 25 // tests, writes them into a temporary directory, and passes them to the test | 28 // tests, writes them into a temporary directory, and passes them to the test | 
| 26 // runner.  These tests may be referred to in the status files with the | 29 // runner.  These tests may be referred to in the status files with the | 
| 27 // pattern [test name]/[key]. | 30 // pattern [test name]/[key]. | 
| 28 // | 31 // | 
| 29 // For example: file I_am_a_multitest.dart | 32 // For example: file I_am_a_multitest.dart | 
| 30 //   aaa | 33 //   aaa | 
| 31 //   bbb /// 02: runtime error | 34 //   bbb //# 02: runtime error | 
| 32 //   ccc /// 02: continued | 35 //   ccc //# 02: continued | 
| 33 //   ddd /// 07: static type warning | 36 //   ddd //# 07: static type warning | 
| 34 //   eee /// 10: ok | 37 //   eee //# 10: ok | 
| 35 //   fff | 38 //   fff | 
| 36 // | 39 // | 
| 37 // should create four tests: | 40 // should create four tests: | 
| 38 // I_am_a_multitest_none.dart | 41 // I_am_a_multitest_none.dart | 
| 39 //   aaa | 42 //   aaa | 
| 40 //   fff | 43 //   fff | 
| 41 // | 44 // | 
| 42 // I_am_a_multitest_02.dart | 45 // I_am_a_multitest_02.dart | 
| 43 //   aaa | 46 //   aaa | 
| 44 //   bbb /// 02: runtime error | 47 //   bbb //# 02: runtime error | 
| 45 //   ccc /// 02: continued | 48 //   ccc //# 02: continued | 
| 46 //   fff | 49 //   fff | 
| 47 // | 50 // | 
| 48 // I_am_a_multitest_07.dart | 51 // I_am_a_multitest_07.dart | 
| 49 //   aaa | 52 //   aaa | 
| 50 //   ddd /// 07: static type warning | 53 //   ddd //# 07: static type warning | 
| 51 //   fff | 54 //   fff | 
| 52 // | 55 // | 
| 53 // and I_am_a_multitest_10.dart | 56 // and I_am_a_multitest_10.dart | 
| 54 //   aaa | 57 //   aaa | 
| 55 //   eee /// 10: ok | 58 //   eee //# 10: ok | 
| 56 //   fff | 59 //   fff | 
| 57 // | 60 // | 
| 58 // Note that it is possible to indicate more than one acceptable outcome | 61 // Note that it is possible to indicate more than one acceptable outcome | 
| 59 // in the case of dynamic and static type warnings | 62 // in the case of dynamic and static type warnings | 
| 60 //   aaa | 63 //   aaa | 
| 61 //   ddd /// 07: static type warning, dynamic type error | 64 //   ddd //# 07: static type warning, dynamic type error | 
| 62 //   fff | 65 //   fff | 
| 63 | 66 | 
|  | 67 /// Until legacy multitests are ported we need to support both /// and //# | 
|  | 68 final _multitestMarker = new RegExp(r"//[/#]"); | 
|  | 69 | 
| 64 void ExtractTestsFromMultitest(Path filePath, Map<String, String> tests, | 70 void ExtractTestsFromMultitest(Path filePath, Map<String, String> tests, | 
| 65     Map<String, Set<String>> outcomes) { | 71     Map<String, Set<String>> outcomes) { | 
| 66   // 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 | 
| 67   // 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 | 
| 68   // we are interested in will be ascii in any case. | 74   // we are interested in will be ascii in any case. | 
| 69   List bytes = new File(filePath.toNativePath()).readAsBytesSync(); | 75   List bytes = new File(filePath.toNativePath()).readAsBytesSync(); | 
| 70   String contents = decodeUtf8(bytes); | 76   String contents = decodeUtf8(bytes); | 
| 71   int first_newline = contents.indexOf('\n'); | 77   int first_newline = contents.indexOf('\n'); | 
| 72   final String line_separator = (first_newline == 0 || | 78   final String line_separator = | 
| 73       contents[first_newline - 1] != '\r') ? '\n' : '\r\n'; | 79       (first_newline == 0 || contents[first_newline - 1] != '\r') | 
|  | 80           ? '\n' | 
|  | 81           : '\r\n'; | 
| 74   List<String> lines = contents.split(line_separator); | 82   List<String> lines = contents.split(line_separator); | 
| 75   if (lines.last == '') lines.removeLast(); | 83   if (lines.last == '') lines.removeLast(); | 
| 76   bytes = null; | 84   bytes = null; | 
| 77   contents = null; | 85   contents = null; | 
| 78   Set<String> validMultitestOutcomes = new Set<String>.from([ | 86   Set<String> validMultitestOutcomes = new Set<String>.from([ | 
| 79     'ok', | 87     'ok', | 
| 80     'compile-time error', | 88     'compile-time error', | 
| 81     'runtime error', | 89     'runtime error', | 
| 82     'static type warning', | 90     'static type warning', | 
| 83     'dynamic type error', | 91     'dynamic type error', | 
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 141   // If a key/multitest was marked for deletion, do the necessary cleanup. | 149   // If a key/multitest was marked for deletion, do the necessary cleanup. | 
| 142   keysToDelete.forEach(outcomes.remove); | 150   keysToDelete.forEach(outcomes.remove); | 
| 143   keysToDelete.forEach(testsAsLines.remove); | 151   keysToDelete.forEach(testsAsLines.remove); | 
| 144 | 152 | 
| 145   // Copy all the tests into the output map tests, as multiline strings. | 153   // Copy all the tests into the output map tests, as multiline strings. | 
| 146   for (String key in testsAsLines.keys) { | 154   for (String key in testsAsLines.keys) { | 
| 147     tests[key] = testsAsLines[key].join(line_separator); | 155     tests[key] = testsAsLines[key].join(line_separator); | 
| 148   } | 156   } | 
| 149 } | 157 } | 
| 150 | 158 | 
| 151 // Represents a mutlitest annotation in the special /// comment. | 159 // Represents a mutlitest annotation in the special //# comment. | 
| 152 class _Annotation { | 160 class _Annotation { | 
| 153   String key; | 161   String key; | 
| 154   String rest; | 162   String rest; | 
| 155   List<String> outcomesList; | 163   List<String> outcomesList; | 
| 156   _Annotation() {} | 164   _Annotation() {} | 
| 157   factory _Annotation.from(String line) { | 165   factory _Annotation.from(String line) { | 
| 158     // Do an early return with "null" if this is not a valid multitest | 166     // Do an early return with "null" if this is not a valid multitest | 
| 159     // annotation. | 167     // annotation. | 
| 160     if (!line.contains('///')) { | 168     if (!line.contains(_multitestMarker)) { | 
| 161       return null; | 169       return null; | 
| 162     } | 170     } | 
| 163     var parts = line | 171     var parts = line | 
| 164         .split('///')[1] | 172         .split(_multitestMarker)[1] | 
| 165         .split(':') | 173         .split(':') | 
| 166         .map((s) => s.trim()) | 174         .map((s) => s.trim()) | 
| 167         .where((s) => s.length > 0) | 175         .where((s) => s.length > 0) | 
| 168         .toList(); | 176         .toList(); | 
| 169     if (parts.length <= 1) { | 177     if (parts.length <= 1) { | 
| 170       return null; | 178       return null; | 
| 171     } | 179     } | 
| 172 | 180 | 
| 173     var annotation = new _Annotation(); | 181     var annotation = new _Annotation(); | 
| 174     annotation.key = parts[0]; | 182     annotation.key = parts[0]; | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 213           } | 221           } | 
| 214           foundImports.add(relativePath.toString()); | 222           foundImports.add(relativePath.toString()); | 
| 215           toSearch.add(libraryDir.join(relativePath)); | 223           toSearch.add(libraryDir.join(relativePath)); | 
| 216         } | 224         } | 
| 217       } | 225       } | 
| 218     } | 226     } | 
| 219   } | 227   } | 
| 220   return foundImports; | 228   return foundImports; | 
| 221 } | 229 } | 
| 222 | 230 | 
| 223 Future doMultitest( | 231 Future doMultitest(Path filePath, String outputDir, Path suiteDir, | 
| 224     Path filePath, | 232     CreateTest doTest, bool hotReload) { | 
| 225     String outputDir, |  | 
| 226     Path suiteDir, |  | 
| 227     CreateTest doTest, |  | 
| 228     bool hotReload) { |  | 
| 229   void writeFile(String filepath, String content) { | 233   void writeFile(String filepath, String content) { | 
| 230     final File file = new File(filepath); | 234     final File file = new File(filepath); | 
| 231 | 235 | 
| 232     if (file.existsSync()) { | 236     if (file.existsSync()) { | 
| 233       var oldContent = file.readAsStringSync(); | 237       var oldContent = file.readAsStringSync(); | 
| 234       if (oldContent == content) { | 238       if (oldContent == content) { | 
| 235         // Don't write to the file if the content is the same | 239         // Don't write to the file if the content is the same | 
| 236         return; | 240         return; | 
| 237       } | 241       } | 
| 238     } | 242     } | 
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 299   var split = suiteDir.segments(); | 303   var split = suiteDir.segments(); | 
| 300   // co19 test suite is at tests/co19/src. | 304   // co19 test suite is at tests/co19/src. | 
| 301   if (split.last == 'src') { | 305   if (split.last == 'src') { | 
| 302     split.removeLast(); | 306     split.removeLast(); | 
| 303   } | 307   } | 
| 304   return split.last; | 308   return split.last; | 
| 305 } | 309 } | 
| 306 | 310 | 
| 307 Path createMultitestDirectory(String outputDir, Path suiteDir, Path sourceDir) { | 311 Path createMultitestDirectory(String outputDir, Path suiteDir, Path sourceDir) { | 
| 308   Path relative = sourceDir.relativeTo(suiteDir); | 312   Path relative = sourceDir.relativeTo(suiteDir); | 
| 309   Path path = new Path(outputDir).append('generated_tests') | 313   Path path = new Path(outputDir) | 
| 310       .append(suiteNameFromPath(suiteDir)).join(relative); | 314       .append('generated_tests') | 
|  | 315       .append(suiteNameFromPath(suiteDir)) | 
|  | 316       .join(relative); | 
| 311   TestUtils.mkdirRecursive(TestUtils.currentWorkingDirectory, path); | 317   TestUtils.mkdirRecursive(TestUtils.currentWorkingDirectory, path); | 
| 312   return new Path(new File(path.toNativePath()).absolute.path); | 318   return new Path(new File(path.toNativePath()).absolute.path); | 
| 313 } | 319 } | 
| OLD | NEW | 
|---|