| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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:io"); | 7 #import("dart:io"); |
| 8 #import("test_suite.dart"); |
| 8 | 9 |
| 9 // Multitests are Dart test scripts containing lines of the form | 10 // Multitests are Dart test scripts containing lines of the form |
| 10 // " [some dart code] /// [key]: [error type]" | 11 // " [some dart code] /// [key]: [error type]" |
| 11 // | 12 // |
| 12 // For each key in the file, a new test file is made containing all | 13 // For each key in the file, a new test file is made containing all |
| 13 // the normal lines of the file, and all of the multitest lines containing | 14 // the normal lines of the file, and all of the multitest lines containing |
| 14 // that key, in the same order as in the source file. The new test | 15 // that key, in the same order as in the source file. The new test |
| 15 // is expected to fail if there is a non-empty error type listed, of | 16 // is expected to fail if there is a non-empty error type listed, of |
| 16 // type 'compile-time error', 'runtime error', 'static type error', or | 17 // type 'compile-time error', 'runtime error', 'static type error', or |
| 17 // 'dynamic type error'. The type error tests fail only in checked mode. | 18 // 'dynamic type error'. The type error tests fail only in checked mode. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 Set<String> validMultitestOutcomes = new Set<String>.from( | 71 Set<String> validMultitestOutcomes = new Set<String>.from( |
| 71 ['compile-time error', 'runtime error', | 72 ['compile-time error', 'runtime error', |
| 72 'static type error', 'dynamic type error', '']); | 73 'static type error', 'dynamic type error', '']); |
| 73 | 74 |
| 74 List<String> testTemplate = new List<String>(); | 75 List<String> testTemplate = new List<String>(); |
| 75 testTemplate.add('// Test created from multitest named $filename.'); | 76 testTemplate.add('// Test created from multitest named $filename.'); |
| 76 // Create the set of multitests, which will have a new test added each | 77 // Create the set of multitests, which will have a new test added each |
| 77 // time we see a multitest line with a new key. | 78 // time we see a multitest line with a new key. |
| 78 Map<String, List<String>> testsAsLines = new Map<String, List<String>>(); | 79 Map<String, List<String>> testsAsLines = new Map<String, List<String>>(); |
| 79 | 80 |
| 80 // Matches #import( or #source( followed by " or ' followed by anything | |
| 81 // except dart: or /, at the beginning of a line. | |
| 82 RegExp relativeImportRegExp = | |
| 83 const RegExp('^#(import|source)[(]["\'](?!(dart:|/))'); | |
| 84 int lineCount = 0; | 81 int lineCount = 0; |
| 85 for (String line in lines) { | 82 for (String line in lines) { |
| 86 lineCount++; | 83 lineCount++; |
| 87 if (line.contains('///')) { | 84 if (line.contains('///')) { |
| 88 var parts = line.split('///')[1].split(':'); | 85 var parts = line.split('///')[1].split(':'); |
| 89 var key = parts[0].trim(); | 86 var key = parts[0].trim(); |
| 90 var rest = parts[1].trim(); | 87 var rest = parts[1].trim(); |
| 91 if (testsAsLines.containsKey(key)) { | 88 if (testsAsLines.containsKey(key)) { |
| 92 Expect.equals('continued', rest); | 89 Expect.equals('continued', rest); |
| 93 testsAsLines[key].add(line); | 90 testsAsLines[key].add(line); |
| 94 } else { | 91 } else { |
| 95 (testsAsLines[key] = new List<String>.from(testTemplate)).add(line); | 92 (testsAsLines[key] = new List<String>.from(testTemplate)).add(line); |
| 96 outcomes[key] = rest; | 93 outcomes[key] = rest; |
| 97 if (!validMultitestOutcomes.contains(rest)) { | 94 if (!validMultitestOutcomes.contains(rest)) { |
| 98 Expect.fail("Invalid test directive on line ${lineCount}: $rest "); | 95 Expect.fail("Invalid test directive on line ${lineCount}: $rest "); |
| 99 } | 96 } |
| 100 } | 97 } |
| 101 } else { | 98 } else { |
| 102 testTemplate.add(line); | 99 testTemplate.add(line); |
| 103 for (var test in testsAsLines.getValues()) test.add(line); | 100 for (var test in testsAsLines.getValues()) test.add(line); |
| 104 } | 101 } |
| 105 // Warn if any import or source tags have relative paths. | |
| 106 if (relativeImportRegExp.hasMatch(line)) { | |
| 107 print('Warning: Multitest cannot contain relative imports:'); | |
| 108 print(' $filename: $line'); | |
| 109 } | |
| 110 } | 102 } |
| 111 // Add the template, with no multitest lines, as a test with key 'none'. | 103 // Add the template, with no multitest lines, as a test with key 'none'. |
| 112 testsAsLines['none'] = testTemplate; | 104 testsAsLines['none'] = testTemplate; |
| 113 outcomes['none'] = ''; | 105 outcomes['none'] = ''; |
| 114 | 106 |
| 115 // Copy all the tests into the output map tests, as multiline strings. | 107 // Copy all the tests into the output map tests, as multiline strings. |
| 116 for (String key in testsAsLines.getKeys()) { | 108 for (String key in testsAsLines.getKeys()) { |
| 117 tests[key] = | 109 tests[key] = |
| 118 Strings.join(testsAsLines[key], line_separator) + line_separator; | 110 Strings.join(testsAsLines[key], line_separator) + line_separator; |
| 119 } | 111 } |
| 120 } | 112 } |
| 121 | 113 |
| 114 // Find all relative imports and copy them into the dir that contains |
| 115 // the generated tests. |
| 116 Set<String> _findAllRelativeImports(String topLibrary) { |
| 117 Set<String> toSearch = new Set<String>.from([topLibrary]); |
| 118 Set<String> foundImports = new HashSet<String>(); |
| 119 String pathSep = new Platform().pathSeparator(); |
| 120 int end = topLibrary.lastIndexOf(pathSep); |
| 121 String libraryDir = topLibrary.substring(0, end); |
| 122 |
| 123 // Matches #import( or #source( followed by " or ' followed by anything |
| 124 // except dart: or /, at the beginning of a line. |
| 125 RegExp relativeImportRegExp = |
| 126 const RegExp('^#(import|source)[(]["\'](?!(dart:|/))([^"\']*)["\']'); |
| 127 while (!toSearch.isEmpty()) { |
| 128 var thisPass = toSearch; |
| 129 toSearch = new HashSet<String>(); |
| 130 for (String filename in thisPass) { |
| 131 File f = new File(filename); |
| 132 for (String line in f.readAsLinesSync()) { |
| 133 Match match = relativeImportRegExp.firstMatch(line); |
| 134 if (match != null) { |
| 135 String relativePath = match.group(3); |
| 136 if (foundImports.contains(relativePath)) { |
| 137 continue; |
| 138 } |
| 139 if (relativePath.contains(@'\.\.')) { |
| 140 // This is just for safety reasons, we don't want |
| 141 // to unintentionally clobber files relative to the destination |
| 142 // dir when copying them ove. |
| 143 Expect.fail("relative paths containing .. are not allowed."); |
| 144 } |
| 145 foundImports.add(relativePath); |
| 146 toSearch.add('$libraryDir/$relativePath'); |
| 147 } |
| 148 } |
| 149 } |
| 150 } |
| 151 return foundImports; |
| 152 } |
| 122 | 153 |
| 123 void DoMultitest(String filename, | 154 void DoMultitest(String filename, |
| 124 String outputDir, | 155 String outputDir, |
| 125 String testDir, | 156 String testDir, |
| 126 Function doTest(String filename, | 157 Function doTest(String filename, |
| 127 bool isNegative, | 158 bool isNegative, |
| 128 [bool isNegativeIfChecked, | 159 [bool isNegativeIfChecked, |
| 129 bool hasFatalTypeErrors, | 160 bool hasFatalTypeErrors, |
| 130 bool hasRuntimeErrors]), | 161 bool hasRuntimeErrors]), |
| 131 Function multitestDone) { | 162 Function multitestDone) { |
| 132 // Each new test is a single String value in the Map tests. | 163 // Each new test is a single String value in the Map tests. |
| 133 Map<String, String> tests = new Map<String, String>(); | 164 Map<String, String> tests = new Map<String, String>(); |
| 134 Map<String, String> outcomes = new Map<String, String>(); | 165 Map<String, String> outcomes = new Map<String, String>(); |
| 135 ExtractTestsFromMultitest(filename, tests, outcomes); | 166 ExtractTestsFromMultitest(filename, tests, outcomes); |
| 136 | 167 |
| 137 String directory = CreateMultitestDirectory(outputDir, testDir); | 168 String directory = CreateMultitestDirectory(outputDir, testDir); |
| 138 String pathSeparator = new Platform().pathSeparator(); | 169 Expect.isNotNull(directory); |
| 139 int start = filename.lastIndexOf(pathSeparator) + 1; | 170 String pathSep = new Platform().pathSeparator(); |
| 171 int start = filename.lastIndexOf(pathSep) + 1; |
| 140 int end = filename.indexOf('.dart', start); | 172 int end = filename.indexOf('.dart', start); |
| 141 String baseFilename = filename.substring(start, end); | 173 String baseFilename = filename.substring(start, end); |
| 174 String sourceDirectory = filename.substring(0, start - 1); |
| 175 Set<String> importsToCopy = _findAllRelativeImports(filename); |
| 176 Directory destDir = new Directory("directory"); |
| 177 for (String import in importsToCopy) { |
| 178 File source = new File('$sourceDirectory/$import'); |
| 179 var dest = new File('$directory/$import'); |
| 180 var basenameStart = import.lastIndexOf('/'); |
| 181 if (basenameStart > 0) { |
| 182 // make sure we have a dir for it |
| 183 var importDir = import.substring(0, basenameStart); |
| 184 TestUtils.mkdirRecursive(directory, importDir); |
| 185 } |
| 186 TestUtils.copyFile(source, dest); |
| 187 } |
| 142 for (String key in tests.getKeys()) { | 188 for (String key in tests.getKeys()) { |
| 143 final String filename = '$directory/${baseFilename}_$key.dart'; | 189 final String filename = '$directory/${baseFilename}_$key.dart'; |
| 144 final File file = new File(filename); | 190 final File file = new File(filename); |
| 145 | 191 |
| 146 file.createSync(); | 192 file.createSync(); |
| 147 RandomAccessFile openedFile = file.openSync(FileMode.WRITE); | 193 RandomAccessFile openedFile = file.openSync(FileMode.WRITE); |
| 148 var bytes = tests[key].charCodes(); | 194 var bytes = tests[key].charCodes(); |
| 149 openedFile.writeListSync(bytes, 0, bytes.length); | 195 openedFile.writeListSync(bytes, 0, bytes.length); |
| 150 openedFile.closeSync(); | 196 openedFile.closeSync(); |
| 151 var outcome = outcomes[key]; | 197 var outcome = outcomes[key]; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 176 var split = testDir.split('/'); | 222 var split = testDir.split('/'); |
| 177 var lastComponent = split.removeLast(); | 223 var lastComponent = split.removeLast(); |
| 178 Expect.isTrue(lastComponent == 'src'); | 224 Expect.isTrue(lastComponent == 'src'); |
| 179 String path = '${generatedTestDir.path}/${split.last()}'; | 225 String path = '${generatedTestDir.path}/${split.last()}'; |
| 180 Directory dir = new Directory(path); | 226 Directory dir = new Directory(path); |
| 181 if (!dir.existsSync()) { | 227 if (!dir.existsSync()) { |
| 182 dir.createSync(); | 228 dir.createSync(); |
| 183 } | 229 } |
| 184 return path; | 230 return path; |
| 185 } | 231 } |
| OLD | NEW |