Index: tools/testing/dart/multitest.dart |
diff --git a/tools/testing/dart/multitest.dart b/tools/testing/dart/multitest.dart |
deleted file mode 100644 |
index 3aed790d6fc096cfb39cfdfac36b5dc026574772..0000000000000000000000000000000000000000 |
--- a/tools/testing/dart/multitest.dart |
+++ /dev/null |
@@ -1,307 +0,0 @@ |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-library multitest; |
- |
-import "dart:async"; |
-import "dart:io"; |
- |
-import "path.dart"; |
-import "test_suite.dart"; |
-import "utils.dart"; |
- |
-// Multitests are Dart test scripts containing lines of the form |
-// " [some dart code] /// [key]: [error type]" |
-// |
-// For each key in the file, a new test file is made containing all |
-// the normal lines of the file, and all of the multitest lines containing |
-// that key, in the same order as in the source file. The new test is expected |
-// to pass if the error type listed is 'ok', or to fail if there is an error |
-// type of type 'compile-time error', 'runtime error', 'static type warning', or |
-// 'dynamic type error'. The type error tests fail only in checked mode. |
-// There is also a test created from only the untagged lines of the file, |
-// with key "none", which is expected to pass. This library extracts these |
-// tests, writes them into a temporary directory, and passes them to the test |
-// runner. These tests may be referred to in the status files with the |
-// pattern [test name]/[key]. |
-// |
-// For example: file I_am_a_multitest.dart |
-// aaa |
-// bbb /// 02: runtime error |
-// ccc /// 02: continued |
-// ddd /// 07: static type warning |
-// eee /// 10: ok |
-// fff |
-// |
-// should create four tests: |
-// I_am_a_multitest_none.dart |
-// aaa |
-// fff |
-// |
-// I_am_a_multitest_02.dart |
-// aaa |
-// bbb /// 02: runtime error |
-// ccc /// 02: continued |
-// fff |
-// |
-// I_am_a_multitest_07.dart |
-// aaa |
-// ddd /// 07: static type warning |
-// fff |
-// |
-// and I_am_a_multitest_10.dart |
-// aaa |
-// eee /// 10: ok |
-// fff |
-// |
-// Note that it is possible to indicate more than one acceptable outcome |
-// in the case of dynamic and static type warnings |
-// aaa |
-// ddd /// 07: static type warning, dynamic type error |
-// fff |
- |
-void ExtractTestsFromMultitest(Path filePath, |
- Map<String, String> tests, |
- Map<String, Set<String>> outcomes) { |
- // Read the entire file into a byte buffer and transform it to a |
- // String. This will treat the file as ascii but the only parts |
- // we are interested in will be ascii in any case. |
- List bytes = new File(filePath.toNativePath()).readAsBytesSync(); |
- String contents = decodeUtf8(bytes); |
- int first_newline = contents.indexOf('\n'); |
- final String line_separator = |
- (first_newline == 0 || contents[first_newline - 1] != '\r') |
- ? '\n' |
- : '\r\n'; |
- List<String> lines = contents.split(line_separator); |
- if (lines.last == '') lines.removeLast(); |
- bytes = null; |
- contents = null; |
- Set<String> validMultitestOutcomes = new Set<String>.from( |
- ['ok', 'compile-time error', 'runtime error', |
- 'static type warning', 'dynamic type error', |
- 'checked mode compile-time error']); |
- |
- List<String> testTemplate = new List<String>(); |
- testTemplate.add( |
- '// Test created from multitest named ${filePath.toNativePath()}.'); |
- // Create the set of multitests, which will have a new test added each |
- // time we see a multitest line with a new key. |
- Map<String, List<String>> testsAsLines = new Map<String, List<String>>(); |
- |
- int lineCount = 0; |
- for (String line in lines) { |
- lineCount++; |
- var annotation = new _Annotation.from(line); |
- if (annotation != null) { |
- testsAsLines.putIfAbsent(annotation.key, |
- () => new List<String>.from(testTemplate)).add(line); |
- outcomes.putIfAbsent(annotation.key, |
- () => new Set<String>()); |
- if (annotation.rest == 'continued') { |
- continue; |
- } else { |
- for (String nextOutcome in annotation.outcomesList) { |
- if (validMultitestOutcomes.contains(nextOutcome)) { |
- outcomes[annotation.key].add(nextOutcome); |
- } else { |
- DebugLogger.warning( |
- "Warning: Invalid test directive '$nextOutcome' on line " |
- "${lineCount}:\n${annotation.rest} "); |
- } |
- } |
- } |
- } else { |
- testTemplate.add(line); |
- for (var test in testsAsLines.values) test.add(line); |
- } |
- } |
- |
- var keysToDelete = []; |
- // Check that every key (other than the none case) has at least one outcome |
- for (var outcomeKey in outcomes.keys) { |
- if (outcomeKey != 'none' && outcomes[outcomeKey].isEmpty) { |
- DebugLogger.warning( |
- "Warning: Test ${outcomeKey} has no valid annotated outcomes.\n" |
- "Expected one of: ${validMultitestOutcomes.toString()}"); |
- // If this multitest doesn't have an outcome, mark the multitest for |
- // deletion. |
- keysToDelete.add(outcomeKey); |
- } |
- } |
- // If a key/multitest was marked for deletion, do the necessary cleanup. |
- keysToDelete.forEach((key) => outcomes.remove(key)); |
- keysToDelete.forEach((key) => testsAsLines.remove(key)); |
- |
- // Add the template, with no multitest lines, as a test with key 'none'. |
- testsAsLines['none'] = testTemplate; |
- outcomes['none'] = new Set<String>(); |
- |
- // Copy all the tests into the output map tests, as multiline strings. |
- for (String key in testsAsLines.keys) { |
- tests[key] = testsAsLines[key].join(line_separator) + line_separator; |
- } |
-} |
- |
-// Represents a mutlitest annotation in the special /// comment. |
-class _Annotation { |
- String key; |
- String rest; |
- List<String> outcomesList; |
- _Annotation() {} |
- factory _Annotation.from(String line) { |
- // Do an early return with "null" if this is not a valid multitest |
- // annotation. |
- if (!line.contains('///')) { |
- return null; |
- } |
- var parts = line |
- .split('///')[1] |
- .split(':') |
- .map((s) => s.trim()) |
- .where((s) => s.length > 0) |
- .toList(); |
- if (parts.length <= 1) { |
- return null; |
- } |
- |
- var annotation = new _Annotation(); |
- annotation.key = parts[0]; |
- annotation.rest = parts[1]; |
- annotation.outcomesList = annotation.rest.split(',') |
- .map((s) => s.trim()).toList(); |
- return annotation; |
- } |
-} |
- |
-// Find all relative imports and copy them into the dir that contains |
-// the generated tests. |
-Set<String> _findAllRelativeImports(Path topLibrary) { |
- Set<Path> toSearch = new Set<Path>.from([topLibrary]); |
- Set<String> foundImports = new Set<String>(); |
- Path libraryDir = topLibrary.directoryPath; |
- RegExp relativeImportRegExp = new RegExp( |
- '^(?:@.*\\s+)?' // Allow for a meta-data annotation. |
- '(import|part)' |
- '\\s+["\']' |
- '(?!(dart:|dart-ext:|package:|/))' // Look-ahead: not in package. |
- '([^"\']*)' // The path to the imported file. |
- '["\']'); |
- while (!toSearch.isEmpty) { |
- var thisPass = toSearch; |
- toSearch = new Set<Path>(); |
- for (Path filename in thisPass) { |
- File f = new File(filename.toNativePath()); |
- for (String line in f.readAsLinesSync()) { |
- Match match = relativeImportRegExp.firstMatch(line); |
- if (match != null) { |
- Path relativePath = new Path(match.group(3)); |
- if (foundImports.contains(relativePath.toString())) { |
- continue; |
- } |
- if (relativePath.toString().contains('..')) { |
- // This is just for safety reasons, we don't want |
- // to unintentionally clobber files relative to the destination |
- // dir when copying them ove. |
- print("relative paths containing .. are not allowed."); |
- exit(1); |
- } |
- foundImports.add(relativePath.toString()); |
- toSearch.add(libraryDir.join(relativePath)); |
- } |
- } |
- } |
- } |
- return foundImports; |
-} |
- |
-Future doMultitest(Path filePath, String outputDir, Path suiteDir, |
- CreateTest doTest) { |
- void writeFile(String filepath, String content) { |
- final File file = new File(filepath); |
- |
- if (file.existsSync()) { |
- var oldContent = file.readAsStringSync(); |
- if (oldContent == content) { |
- // Don't write to the file if the content is the same |
- return; |
- } |
- } |
- file.writeAsStringSync(content); |
- } |
- |
- // Each new test is a single String value in the Map tests. |
- Map<String, String> tests = new Map<String, String>(); |
- Map<String, Set<String>> outcomes = new Map<String, Set<String>>(); |
- ExtractTestsFromMultitest(filePath, tests, outcomes); |
- |
- Path sourceDir = filePath.directoryPath; |
- Path targetDir = CreateMultitestDirectory(outputDir, suiteDir); |
- assert(targetDir != null); |
- |
- // Copy all the relative imports of the multitest. |
- Set<String> importsToCopy = _findAllRelativeImports(filePath); |
- List<Future> futureCopies = []; |
- for (String relativeImport in importsToCopy) { |
- Path importPath = new Path(relativeImport); |
- // Make sure the target directory exists. |
- Path importDir = importPath.directoryPath; |
- if (!importDir.isEmpty) { |
- TestUtils.mkdirRecursive(targetDir, importDir); |
- } |
- // Copy file. |
- futureCopies.add(TestUtils.copyFile(sourceDir.join(importPath), |
- targetDir.join(importPath))); |
- } |
- |
- // Wait until all imports are copied before scheduling test cases. |
- return Future.wait(futureCopies).then((_) { |
- String baseFilename = filePath.filenameWithoutExtension; |
- for (String key in tests.keys) { |
- final Path multitestFilename = |
- targetDir.append('${baseFilename}_$key.dart'); |
- writeFile(multitestFilename.toNativePath(), tests[key]); |
- Set<String> outcome = outcomes[key]; |
- bool hasStaticWarning = outcome.contains('static type warning'); |
- bool hasRuntimeErrors = outcome.contains('runtime error'); |
- bool hasCompileError = outcome.contains('compile-time error'); |
- bool isNegativeIfChecked = outcome.contains('dynamic type error'); |
- bool hasCompileErrorIfChecked = |
- outcome.contains('checked mode compile-time error'); |
- doTest(multitestFilename, |
- filePath, |
- hasCompileError, |
- hasRuntimeErrors, |
- isNegativeIfChecked: isNegativeIfChecked, |
- hasCompileErrorIfChecked: hasCompileErrorIfChecked, |
- hasStaticWarning: hasStaticWarning, |
- multitestKey: key); |
- } |
- |
- return null; |
- }); |
-} |
- |
- |
-Path CreateMultitestDirectory(String outputDir, Path suiteDir) { |
- Directory generatedTestDir = new Directory('$outputDir/generated_tests'); |
- if (!new Directory(outputDir).existsSync()) { |
- new Directory(outputDir).createSync(); |
- } |
- if (!generatedTestDir.existsSync()) { |
- generatedTestDir.createSync(); |
- } |
- var split = suiteDir.segments(); |
- if (split.last == 'src') { |
- // TODO(sigmund): remove this once all tests are migrated to use |
- // TestSuite.forDirectory. |
- split.removeLast(); |
- } |
- String path = '${generatedTestDir.path}/${split.last}'; |
- Directory dir = new Directory(path); |
- if (!dir.existsSync()) { |
- dir.createSync(); |
- } |
- return new Path(new File(path).absolute.path); |
-} |