Chromium Code Reviews| 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 | 8 |
| 9 // Multitests are Dart test scripts containing lines of the form | 9 // Multitests are Dart test scripts containing lines of the form |
| 10 // " [some dart code] /// [key]: [error type]" | 10 // " [some dart code] /// [key]: [error type]" |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 70 Set<String> validMultitestOutcomes = new Set<String>.from( | 70 Set<String> validMultitestOutcomes = new Set<String>.from( |
| 71 ['compile-time error', 'runtime error', | 71 ['compile-time error', 'runtime error', |
| 72 'static type error', 'dynamic type error', '']); | 72 'static type error', 'dynamic type error', '']); |
| 73 | 73 |
| 74 List<String> testTemplate = new List<String>(); | 74 List<String> testTemplate = new List<String>(); |
| 75 testTemplate.add('// Test created from multitest named $filename.'); | 75 testTemplate.add('// Test created from multitest named $filename.'); |
| 76 // Create the set of multitests, which will have a new test added each | 76 // Create the set of multitests, which will have a new test added each |
| 77 // time we see a multitest line with a new key. | 77 // time we see a multitest line with a new key. |
| 78 Map<String, List<String>> testsAsLines = new Map<String, List<String>>(); | 78 Map<String, List<String>> testsAsLines = new Map<String, List<String>>(); |
| 79 | 79 |
| 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; | 80 int lineCount = 0; |
| 85 for (String line in lines) { | 81 for (String line in lines) { |
| 86 lineCount++; | 82 lineCount++; |
| 87 if (line.contains('///')) { | 83 if (line.contains('///')) { |
| 88 var parts = line.split('///')[1].split(':'); | 84 var parts = line.split('///')[1].split(':'); |
| 89 var key = parts[0].trim(); | 85 var key = parts[0].trim(); |
| 90 var rest = parts[1].trim(); | 86 var rest = parts[1].trim(); |
| 91 if (testsAsLines.containsKey(key)) { | 87 if (testsAsLines.containsKey(key)) { |
| 92 Expect.equals('continued', rest); | 88 Expect.equals('continued', rest); |
| 93 testsAsLines[key].add(line); | 89 testsAsLines[key].add(line); |
| 94 } else { | 90 } else { |
| 95 (testsAsLines[key] = new List<String>.from(testTemplate)).add(line); | 91 (testsAsLines[key] = new List<String>.from(testTemplate)).add(line); |
| 96 outcomes[key] = rest; | 92 outcomes[key] = rest; |
| 97 if (!validMultitestOutcomes.contains(rest)) { | 93 if (!validMultitestOutcomes.contains(rest)) { |
| 98 Expect.fail("Invalid test directive on line ${lineCount}: $rest "); | 94 Expect.fail("Invalid test directive on line ${lineCount}: $rest "); |
| 99 } | 95 } |
| 100 } | 96 } |
| 101 } else { | 97 } else { |
| 102 testTemplate.add(line); | 98 testTemplate.add(line); |
| 103 for (var test in testsAsLines.getValues()) test.add(line); | 99 for (var test in testsAsLines.getValues()) test.add(line); |
| 104 } | 100 } |
| 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 } | 101 } |
| 111 // Add the template, with no multitest lines, as a test with key 'none'. | 102 // Add the template, with no multitest lines, as a test with key 'none'. |
| 112 testsAsLines['none'] = testTemplate; | 103 testsAsLines['none'] = testTemplate; |
| 113 outcomes['none'] = ''; | 104 outcomes['none'] = ''; |
| 114 | 105 |
| 115 // Copy all the tests into the output map tests, as multiline strings. | 106 // Copy all the tests into the output map tests, as multiline strings. |
| 116 for (String key in testsAsLines.getKeys()) { | 107 for (String key in testsAsLines.getKeys()) { |
| 117 tests[key] = | 108 tests[key] = |
| 118 Strings.join(testsAsLines[key], line_separator) + line_separator; | 109 Strings.join(testsAsLines[key], line_separator) + line_separator; |
| 119 } | 110 } |
| 120 } | 111 } |
| 121 | 112 |
| 113 void _copyFile(File source, File dest) { | |
|
zundel
2012/03/01 06:06:58
is there already a canned way to do this somewhere
Bill Hesse
2012/03/01 15:01:52
Not that I know of, except by calling the shell.
zundel
2012/03/01 18:06:01
Moved to TestUtils class.
| |
| 114 List contents = source.readAsBytesSync(); | |
| 115 RandomAccessFile handle = dest.openSync(FileMode.WRITE); | |
|
Bill Hesse
2012/03/01 15:01:52
This will not work except for files in the same di
zundel
2012/03/01 18:06:01
the generated test files don't go away between tes
| |
| 116 handle.writeListSync(contents, 0, contents.length); | |
| 117 handle.closeSync(); | |
| 118 } | |
| 119 | |
| 120 // Find all relative imports and copy them into the dir that contains | |
| 121 // the generated tests. | |
| 122 Set<String> _findAllRelativeImports(String topLibrary) { | |
| 123 Set<String> toSearch = new Set<String>.from([topLibrary]); | |
| 124 Set<String> foundImports = new HashSet<String>(); | |
| 125 String pathSep = new Platform().pathSeparator(); | |
|
Bill Hesse
2012/03/01 15:01:52
Rather than use pathSeparator, I would use "/" eve
zundel
2012/03/01 18:06:01
Done.
| |
| 126 int end = topLibrary.lastIndexOf(pathSep); | |
| 127 String libraryDir = topLibrary.substring(0, end); | |
| 128 | |
| 129 // Matches #import( or #source( followed by " or ' followed by anything | |
| 130 // except dart: or /, at the beginning of a line. | |
| 131 RegExp relativeImportRegExp1 = | |
| 132 const RegExp('^#(import|source)[(]["\'](?!(dart:|/))'); | |
| 133 // Like the above, but captures the path in the import | |
| 134 RegExp relativeImportRegExp2 = | |
| 135 const RegExp('^#(import|source)[(]["\']([^"\']*)["\']'); | |
| 136 while (!toSearch.isEmpty()) { | |
| 137 var thisPass = toSearch; | |
| 138 toSearch = new HashSet<String>(); | |
| 139 for (String filename in thisPass) { | |
| 140 File f = new File(filename); | |
| 141 for (String line in f.readAsLinesSync()) { | |
| 142 if (relativeImportRegExp1.hasMatch(line)) { | |
|
Bill Hesse
2012/03/01 15:01:52
I think you can combine the two regexp to
'.....
zundel
2012/03/01 18:06:01
i've never used the non-capturing before, but it d
| |
| 143 // remember relative import so we can copy it later | |
| 144 Match match = relativeImportRegExp2.firstMatch(line); | |
| 145 String relativePath = match.group(2); | |
| 146 if (foundImports.contains(relativePath)) { | |
| 147 continue; | |
| 148 } | |
| 149 foundImports.add(relativePath); | |
| 150 toSearch.add('$libraryDir$pathSep$relativePath'); | |
| 151 } | |
| 152 } | |
| 153 } | |
| 154 } | |
| 155 return foundImports; | |
| 156 } | |
| 122 | 157 |
| 123 void DoMultitest(String filename, | 158 void DoMultitest(String filename, |
| 124 String outputDir, | 159 String outputDir, |
| 125 String testDir, | 160 String testDir, |
| 126 Function doTest(String filename, | 161 Function doTest(String filename, |
| 127 bool isNegative, | 162 bool isNegative, |
| 128 [bool isNegativeIfChecked, | 163 [bool isNegativeIfChecked, |
| 129 bool hasFatalTypeErrors, | 164 bool hasFatalTypeErrors, |
| 130 bool hasRuntimeErrors]), | 165 bool hasRuntimeErrors]), |
| 131 Function multitestDone) { | 166 Function multitestDone) { |
| 132 // Each new test is a single String value in the Map tests. | 167 // Each new test is a single String value in the Map tests. |
| 133 Map<String, String> tests = new Map<String, String>(); | 168 Map<String, String> tests = new Map<String, String>(); |
| 134 Map<String, String> outcomes = new Map<String, String>(); | 169 Map<String, String> outcomes = new Map<String, String>(); |
| 170 Set<String> importsToCopy = new Set<String>(); | |
|
Bill Hesse
2012/03/01 15:01:52
This initializer is overwritten - can be omitted.
zundel
2012/03/01 18:06:01
Done.
| |
| 135 ExtractTestsFromMultitest(filename, tests, outcomes); | 171 ExtractTestsFromMultitest(filename, tests, outcomes); |
| 136 | 172 |
| 137 String directory = CreateMultitestDirectory(outputDir, testDir); | 173 String directory = CreateMultitestDirectory(outputDir, testDir); |
|
Bill Hesse
2012/03/01 15:01:52
extra space before testDir?
zundel
2012/03/01 18:06:01
Done.
| |
| 138 String pathSeparator = new Platform().pathSeparator(); | 174 Expect.isNotNull(directory); |
| 139 int start = filename.lastIndexOf(pathSeparator) + 1; | 175 String pathSep = new Platform().pathSeparator(); |
| 176 int start = filename.lastIndexOf(pathSep) + 1; | |
| 140 int end = filename.indexOf('.dart', start); | 177 int end = filename.indexOf('.dart', start); |
| 141 String baseFilename = filename.substring(start, end); | 178 String baseFilename = filename.substring(start, end); |
| 179 String sourceDirectory = filename.substring(0, start - 1); | |
| 180 importsToCopy = _findAllRelativeImports(filename); | |
| 181 for (String import in importsToCopy) { | |
| 182 File source = new File('$sourceDirectory$pathSep$import'); | |
|
Bill Hesse
2012/03/01 15:01:52
Again, no need for $pathSep. "/" works on all pla
zundel
2012/03/01 18:06:01
Done.
| |
| 183 // assumes no subdirs | |
| 184 var dest = new File('$directory$pathSep$import'); | |
| 185 _copyFile(source, dest); | |
| 186 } | |
| 142 for (String key in tests.getKeys()) { | 187 for (String key in tests.getKeys()) { |
| 143 final String filename = '$directory/${baseFilename}_$key.dart'; | 188 final String filename = '$directory/${baseFilename}_$key.dart'; |
| 144 final File file = new File(filename); | 189 final File file = new File(filename); |
| 145 | 190 |
| 146 file.createSync(); | 191 file.createSync(); |
| 147 RandomAccessFile openedFile = file.openSync(FileMode.WRITE); | 192 RandomAccessFile openedFile = file.openSync(FileMode.WRITE); |
| 148 var bytes = tests[key].charCodes(); | 193 var bytes = tests[key].charCodes(); |
| 149 openedFile.writeListSync(bytes, 0, bytes.length); | 194 openedFile.writeListSync(bytes, 0, bytes.length); |
| 150 openedFile.closeSync(); | 195 openedFile.closeSync(); |
| 151 var outcome = outcomes[key]; | 196 var outcome = outcomes[key]; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 176 var split = testDir.split('/'); | 221 var split = testDir.split('/'); |
| 177 var lastComponent = split.removeLast(); | 222 var lastComponent = split.removeLast(); |
| 178 Expect.isTrue(lastComponent == 'src'); | 223 Expect.isTrue(lastComponent == 'src'); |
| 179 String path = '${generatedTestDir.path}/${split.last()}'; | 224 String path = '${generatedTestDir.path}/${split.last()}'; |
| 180 Directory dir = new Directory(path); | 225 Directory dir = new Directory(path); |
| 181 if (!dir.existsSync()) { | 226 if (!dir.existsSync()) { |
| 182 dir.createSync(); | 227 dir.createSync(); |
| 183 } | 228 } |
| 184 return path; | 229 return path; |
| 185 } | 230 } |
| OLD | NEW |