[package:testing] Various updates
* Delete unused stuff * rename 'path' to 'root' * accept 'includeEndsWith' as a plain text string so we often can avoid using regexp * accept 'subRoots' to filter to directories faster and more precisly than when using regexps in 'pattern' * make 'list' async instead of async* (no more yield stuff which we promptly turn into a list when actually using it) Note that some changes in testing.json is not 100% semantic-preserving, e.g. the "parser_all" suite previously had a pattern "/tests/.*\\.dart$" which was probably meant to include all dart files in the "tests" folder in the root, but in fact included all dart files in a "tests" folder anywhere. The updated version does not. Change-Id: Idd014274f86bf6214dee0753a7738ec80bc6a49e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/358442 Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Jens Johansen <jensj@google.com> Reviewed-by: Nicholas Shahan <nshahan@google.com>
This commit is contained in:
committed by
Commit Queue
parent
25071fc448
commit
2bd74882e2
@@ -8,7 +8,7 @@
|
||||
"name": "sourcemaps",
|
||||
"kind": "Chain",
|
||||
"source": "sourcemaps_suite.dart",
|
||||
"path": "testfiles",
|
||||
"root": "testfiles",
|
||||
"status": "sourcemaps.status",
|
||||
"pattern": [
|
||||
"\\.dart$",
|
||||
@@ -21,7 +21,7 @@
|
||||
"name": "stacktrace",
|
||||
"kind": "Chain",
|
||||
"source": "stacktrace_suite.dart",
|
||||
"path": "stacktrace_testfiles",
|
||||
"root": "stacktrace_testfiles",
|
||||
"status": "stacktrace.status",
|
||||
"pattern": [
|
||||
"\\.dart$"
|
||||
|
||||
@@ -29,12 +29,15 @@ class Context extends ChainContext {
|
||||
];
|
||||
|
||||
@override
|
||||
Stream<DartDocTestTestDescription> list(Chain suite) async* {
|
||||
await for (TestDescription entry in super.list(suite)) {
|
||||
Future<List<DartDocTestTestDescription>> list(Chain suite) async {
|
||||
List<DartDocTestTestDescription> result = [];
|
||||
for (TestDescription entry in await super.list(suite)) {
|
||||
List<Test> tests = await dartDocTest.extractTestsFromUri(entry.uri);
|
||||
if (tests.isEmpty) continue;
|
||||
yield new DartDocTestTestDescription(entry.shortName, entry.uri, tests);
|
||||
result.add(
|
||||
new DartDocTestTestDescription(entry.shortName, entry.uri, tests));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DartDocTest dartDocTest = new DartDocTest();
|
||||
|
||||
@@ -130,8 +130,9 @@ class MessageTestSuite extends ChainContext {
|
||||
/// failure by the [Validate] step that can be suppressed via the status
|
||||
/// file.
|
||||
@override
|
||||
Stream<MessageTestDescription> list(Chain suite) async* {
|
||||
Uri uri = suite.uri.resolve("messages.yaml");
|
||||
Future<List<MessageTestDescription>> list(Chain suite) {
|
||||
List<MessageTestDescription> result = [];
|
||||
Uri uri = suite.root.resolve("messages.yaml");
|
||||
File file = new File.fromUri(uri);
|
||||
String fileContent = file.readAsStringSync();
|
||||
YamlMap messages = loadYamlNode(fileContent, sourceUrl: uri) as YamlMap;
|
||||
@@ -425,81 +426,81 @@ class MessageTestSuite extends ChainContext {
|
||||
|
||||
if (!fastOnly) {
|
||||
for (Example example in examples) {
|
||||
yield createDescription(example.name, example, null);
|
||||
result.add(createDescription(example.name, example, null));
|
||||
}
|
||||
// "Wrap" example as a part.
|
||||
for (Example example in examples) {
|
||||
yield createDescription(
|
||||
result.add(createDescription(
|
||||
"part_wrapped_${example.name}",
|
||||
new PartWrapExample("part_wrapped_${example.name}", name,
|
||||
exampleAllowMoreCodes, example),
|
||||
null);
|
||||
null));
|
||||
}
|
||||
}
|
||||
|
||||
yield createDescription(
|
||||
result.add(createDescription(
|
||||
"knownKeys",
|
||||
null,
|
||||
unknownKeys.isNotEmpty
|
||||
? "Unknown keys: ${unknownKeys.join(' ')}."
|
||||
: null);
|
||||
: null));
|
||||
|
||||
yield createDescription(
|
||||
result.add(createDescription(
|
||||
'hasPublishedDocs',
|
||||
null,
|
||||
badHasPublishedDocsValue.isNotEmpty
|
||||
? "Bad hasPublishedDocs value (only 'true' supported) in:"
|
||||
" ${badHasPublishedDocsValue.join(', ')}"
|
||||
: null);
|
||||
: null));
|
||||
|
||||
yield createDescription(
|
||||
result.add(createDescription(
|
||||
"severity",
|
||||
null,
|
||||
badSeverity != null
|
||||
? "Unknown severity: '${badSeverity.value}'."
|
||||
: null,
|
||||
location: badSeverity?.span.start);
|
||||
location: badSeverity?.span.start));
|
||||
|
||||
yield createDescription(
|
||||
result.add(createDescription(
|
||||
"unnecessarySeverity",
|
||||
null,
|
||||
unnecessarySeverity != null
|
||||
? "The 'ERROR' severity is the default and not necessary."
|
||||
: null,
|
||||
location: unnecessarySeverity?.span.start);
|
||||
location: unnecessarySeverity?.span.start));
|
||||
|
||||
yield createDescription(
|
||||
result.add(createDescription(
|
||||
"spelling",
|
||||
null,
|
||||
spellingMessages != null
|
||||
? spellingMessages.join("\n") + spellingPostMessage
|
||||
: null);
|
||||
: null));
|
||||
|
||||
bool exampleAndAnalyzerCodeRequired = severity != Severity.context &&
|
||||
severity != Severity.internalProblem &&
|
||||
severity != Severity.ignored;
|
||||
|
||||
yield createDescription(
|
||||
result.add(createDescription(
|
||||
"externalExample",
|
||||
null,
|
||||
exampleAndAnalyzerCodeRequired &&
|
||||
externalTest != null &&
|
||||
!(new File.fromUri(suite.uri.resolve(externalTest))
|
||||
!(new File.fromUri(suite.root.resolve(externalTest))
|
||||
.existsSync())
|
||||
? "Given external example for $name points to a nonexisting file "
|
||||
"(${suite.uri.resolve(externalTest)})."
|
||||
: null);
|
||||
"(${suite.root.resolve(externalTest)})."
|
||||
: null));
|
||||
|
||||
yield createDescription(
|
||||
result.add(createDescription(
|
||||
"example",
|
||||
null,
|
||||
exampleAndAnalyzerCodeRequired &&
|
||||
examples.isEmpty &&
|
||||
externalTest == null
|
||||
? "No example for $name, please add at least one example."
|
||||
: null);
|
||||
: null));
|
||||
|
||||
yield createDescription(
|
||||
result.add(createDescription(
|
||||
"analyzerCode",
|
||||
null,
|
||||
exampleAndAnalyzerCodeRequired &&
|
||||
@@ -510,8 +511,9 @@ class MessageTestSuite extends ChainContext {
|
||||
" <BUILDDIR>/dart-sdk/bin/dartanalyzer --format=machine"
|
||||
" on an example to find the code."
|
||||
" The code is printed just before the file name."
|
||||
: null);
|
||||
: null));
|
||||
}
|
||||
return Future.value(result);
|
||||
}
|
||||
|
||||
String formatProblems(
|
||||
|
||||
@@ -491,7 +491,7 @@ class FastaContext extends ChainContext with MatchContext {
|
||||
platformBinaries = '$platformBinaries/';
|
||||
}
|
||||
return new Future.value(new FastaContext(
|
||||
suite.uri,
|
||||
suite.root,
|
||||
vm,
|
||||
platformBinaries == null
|
||||
? computePlatformBinariesLocation(forceBuildDir: true)
|
||||
|
||||
@@ -54,7 +54,7 @@ const List<Map<String, String>> EXPECTATIONS = [
|
||||
];
|
||||
|
||||
Future<Context> createContext(Chain suite, Map<String, String> environment) {
|
||||
return new Future.value(new Context(suite.uri, environment));
|
||||
return new Future.value(new Context(suite.root, environment));
|
||||
}
|
||||
|
||||
void main([List<String> arguments = const []]) => internalMain(
|
||||
|
||||
@@ -511,17 +511,19 @@ class Context extends ChainContext {
|
||||
Context(this.updateExpectations, this.breakBetween, this.skipTests);
|
||||
|
||||
@override
|
||||
Stream<TestDescription> list(Chain suite) {
|
||||
if (skipTests.isEmpty) return super.list(suite);
|
||||
return filterSkipped(super.list(suite));
|
||||
Future<List<TestDescription>> list(Chain suite) async {
|
||||
if (skipTests.isEmpty) return await super.list(suite);
|
||||
return filterSkipped(await super.list(suite));
|
||||
}
|
||||
|
||||
Stream<TestDescription> filterSkipped(Stream<TestDescription> all) async* {
|
||||
await for (TestDescription testDescription in all) {
|
||||
List<TestDescription> filterSkipped(List<TestDescription> all) {
|
||||
List<TestDescription> result = [];
|
||||
for (TestDescription testDescription in all) {
|
||||
if (!skipTests.contains(testDescription.shortName)) {
|
||||
yield testDescription;
|
||||
result.add(testDescription);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
import 'dart:io' show Directory, File, FileSystemEntity;
|
||||
import 'dart:io' show File;
|
||||
import 'dart:typed_data' show Uint8List;
|
||||
|
||||
import 'package:_fe_analyzer_shared/src/parser/listener.dart' show Listener;
|
||||
@@ -23,7 +23,7 @@ import 'package:testing/testing.dart'
|
||||
show Chain, ChainContext, Result, Step, TestDescription;
|
||||
|
||||
import 'fasta/suite_utils.dart';
|
||||
import 'testing_utils.dart' show checkEnvironment, getGitFiles;
|
||||
import 'testing_utils.dart' show checkEnvironment, filterList;
|
||||
|
||||
void main([List<String> arguments = const []]) => internalMain(createContext,
|
||||
arguments: arguments,
|
||||
@@ -82,55 +82,43 @@ class Context extends ChainContext {
|
||||
];
|
||||
|
||||
@override
|
||||
Stream<LintTestDescription> list(Chain suite) async* {
|
||||
late Set<Uri> gitFiles;
|
||||
if (onlyInGit) {
|
||||
gitFiles = await getGitFiles(suite.uri);
|
||||
}
|
||||
Future<List<LintTestDescription>> list(Chain suite) async {
|
||||
String rootString = "${suite.root}";
|
||||
Uri apiUnstableUri =
|
||||
Uri.base.resolve("pkg/front_end/lib/src/api_unstable/");
|
||||
String apiUnstableString = apiUnstableUri.toString();
|
||||
|
||||
Directory testRoot = new Directory.fromUri(suite.uri);
|
||||
if (await testRoot.exists()) {
|
||||
Stream<FileSystemEntity> files =
|
||||
testRoot.list(recursive: true, followLinks: false);
|
||||
await for (FileSystemEntity entity in files) {
|
||||
if (entity is! File) continue;
|
||||
String path = entity.uri.path;
|
||||
if (suite.exclude.any((RegExp r) => path.contains(r))) continue;
|
||||
if (suite.pattern.any((RegExp r) => path.contains(r))) {
|
||||
if (onlyInGit && !gitFiles.contains(entity.uri)) continue;
|
||||
Uri root = suite.uri;
|
||||
String baseName = "${entity.uri}".substring("$root".length);
|
||||
baseName = baseName.substring(0, baseName.length - ".dart".length);
|
||||
LintTestCache cache = new LintTestCache();
|
||||
List<LintTestDescription> result = [];
|
||||
for (TestDescription description
|
||||
in await filterList(suite, onlyInGit, await super.list(suite))) {
|
||||
String baseName = "${description.uri}".substring(rootString.length);
|
||||
baseName = baseName.substring(0, baseName.length - ".dart".length);
|
||||
LintTestCache cache = new LintTestCache();
|
||||
|
||||
yield new LintTestDescription(
|
||||
"$baseName/ExplicitType",
|
||||
entity.uri,
|
||||
cache,
|
||||
new ExplicitTypeLintListener(),
|
||||
);
|
||||
result.add(new LintTestDescription(
|
||||
"$baseName/ExplicitType",
|
||||
description.uri,
|
||||
cache,
|
||||
new ExplicitTypeLintListener(),
|
||||
));
|
||||
|
||||
yield new LintTestDescription(
|
||||
"$baseName/ImportsTwice",
|
||||
entity.uri,
|
||||
cache,
|
||||
new ImportsTwiceLintListener(),
|
||||
);
|
||||
result.add(new LintTestDescription(
|
||||
"$baseName/ImportsTwice",
|
||||
description.uri,
|
||||
cache,
|
||||
new ImportsTwiceLintListener(),
|
||||
));
|
||||
|
||||
String apiUnstableUri = "pkg/front_end/lib/src/api_unstable/";
|
||||
if (!entity.uri.toString().contains(apiUnstableUri.toString())) {
|
||||
yield new LintTestDescription(
|
||||
"$baseName/Exports",
|
||||
entity.uri,
|
||||
cache,
|
||||
new ExportsLintListener(),
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!description.uri.toString().startsWith(apiUnstableString)) {
|
||||
result.add(new LintTestDescription(
|
||||
"$baseName/Exports",
|
||||
description.uri,
|
||||
cache,
|
||||
new ExportsLintListener(),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
throw "${suite.uri} isn't a directory";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@ abstract class SpellContext extends ChainContext {
|
||||
Set<String> reportedWordsDenylisted = {};
|
||||
|
||||
@override
|
||||
Stream<TestDescription> list(Chain suite) {
|
||||
return filterList(suite, onlyInGit, super.list(suite));
|
||||
Future<List<TestDescription>> list(Chain suite) async {
|
||||
return filterList(suite, onlyInGit, await super.list(suite));
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
// 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.
|
||||
|
||||
import 'dart:io' show Directory, File, FileSystemEntity;
|
||||
|
||||
import 'package:testing/testing.dart'
|
||||
show Chain, FileBasedTestDescription, TestDescription, runMe;
|
||||
import 'package:testing/testing.dart' show Chain, runMe;
|
||||
|
||||
import 'spelling_test_base.dart' show SpellContext;
|
||||
|
||||
@@ -40,25 +37,4 @@ class SpellContextExternal extends SpellContext {
|
||||
@override
|
||||
String get repoRelativeSuitePath =>
|
||||
"pkg/front_end/test/spelling_test_external_targets.dart";
|
||||
|
||||
@override
|
||||
Stream<TestDescription> list(Chain suite) async* {
|
||||
for (String subdir in const ["pkg/", "sdk/"]) {
|
||||
Directory testRoot = new Directory.fromUri(suite.uri.resolve(subdir));
|
||||
if (await testRoot.exists()) {
|
||||
Stream<FileSystemEntity> files =
|
||||
testRoot.list(recursive: true, followLinks: false);
|
||||
await for (FileSystemEntity entity in files) {
|
||||
if (entity is! File) continue;
|
||||
String path = entity.uri.path;
|
||||
if (suite.exclude.any((RegExp r) => path.contains(r))) continue;
|
||||
if (suite.pattern.any((RegExp r) => path.contains(r))) {
|
||||
yield new FileBasedTestDescription(suite.uri, entity);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw "${suite.uri} isn't a directory";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,18 +6,22 @@ import 'dart:io' show Directory, Process, ProcessResult;
|
||||
|
||||
import 'package:testing/testing.dart' show Chain, TestDescription;
|
||||
|
||||
Stream<TestDescription> filterList(
|
||||
Chain suite, bool onlyInGit, Stream<TestDescription> base) async* {
|
||||
Set<Uri>? gitFiles;
|
||||
Future<List<TestDescription>> filterList(
|
||||
Chain suite, bool onlyInGit, List<TestDescription> base) async {
|
||||
Set<Uri> gitFiles = {};
|
||||
if (onlyInGit) {
|
||||
gitFiles = await getGitFiles(suite.uri);
|
||||
for (Uri subRoot in suite.subRoots) {
|
||||
gitFiles.addAll(await getGitFiles(subRoot));
|
||||
}
|
||||
}
|
||||
await for (TestDescription description in base) {
|
||||
if (onlyInGit && !gitFiles!.contains(description.uri)) {
|
||||
List<TestDescription> result = [];
|
||||
for (TestDescription description in base) {
|
||||
if (onlyInGit && !gitFiles.contains(description.uri)) {
|
||||
continue;
|
||||
}
|
||||
yield description;
|
||||
result.add(description);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<Set<Uri>> getGitFiles(Uri uri) async {
|
||||
|
||||
+101
-149
@@ -8,20 +8,18 @@
|
||||
"name": "messages",
|
||||
"kind": "Chain",
|
||||
"source": "test/fasta/messages_suite.dart",
|
||||
"path": "./",
|
||||
"status": "messages.status",
|
||||
"pattern": [],
|
||||
"exclude": []
|
||||
"root": "./",
|
||||
"status": "messages.status"
|
||||
},
|
||||
{
|
||||
"name": "textual_outline",
|
||||
"kind": "Chain",
|
||||
"source": "test/fasta/textual_outline_suite.dart",
|
||||
"path": "testcases/",
|
||||
"root": "testcases/",
|
||||
"status": "testcases/textual_outline.status",
|
||||
"pattern": [
|
||||
"\\.dart$",
|
||||
"\\.crash_dart$"
|
||||
"includeEndsWith": [
|
||||
".dart",
|
||||
".crash_dart"
|
||||
],
|
||||
"exclude": [
|
||||
"/testcases/.*_part[0-9]*\\.dart$",
|
||||
@@ -34,11 +32,11 @@
|
||||
"name": "outline",
|
||||
"kind": "Chain",
|
||||
"source": "test/fasta/outline_suite.dart",
|
||||
"path": "testcases/",
|
||||
"root": "testcases/",
|
||||
"status": "testcases/outline.status",
|
||||
"pattern": [
|
||||
"\\.dart$",
|
||||
"\\.crash_dart$"
|
||||
"includeEndsWith": [
|
||||
".dart",
|
||||
".crash_dart"
|
||||
],
|
||||
"exclude": [
|
||||
"/testcases/.*_part[0-9]*\\.dart$",
|
||||
@@ -52,11 +50,11 @@
|
||||
"name": "strong",
|
||||
"kind": "Chain",
|
||||
"source": "test/fasta/strong_suite.dart",
|
||||
"path": "testcases/",
|
||||
"root": "testcases/",
|
||||
"status": "testcases/strong.status",
|
||||
"pattern": [
|
||||
"\\.dart$",
|
||||
"\\.crash_dart$"
|
||||
"includeEndsWith": [
|
||||
".dart",
|
||||
".crash_dart"
|
||||
],
|
||||
"exclude": [
|
||||
"/testcases/.*_part[0-9]*\\.dart$",
|
||||
@@ -70,11 +68,11 @@
|
||||
"name": "modular",
|
||||
"kind": "Chain",
|
||||
"source": "test/fasta/modular_suite.dart",
|
||||
"path": "testcases/",
|
||||
"root": "testcases/",
|
||||
"status": "testcases/modular.status",
|
||||
"pattern": [
|
||||
"\\.dart$",
|
||||
"\\.crash_dart$"
|
||||
"includeEndsWith": [
|
||||
".dart",
|
||||
".crash_dart"
|
||||
],
|
||||
"exclude": [
|
||||
"/testcases/.*_part[0-9]*\\.dart$",
|
||||
@@ -88,11 +86,11 @@
|
||||
"name": "weak",
|
||||
"kind": "Chain",
|
||||
"source": "test/fasta/weak_suite.dart",
|
||||
"path": "testcases/",
|
||||
"root": "testcases/",
|
||||
"status": "testcases/weak.status",
|
||||
"pattern": [
|
||||
"\\.dart$",
|
||||
"\\.crash_dart$"
|
||||
"includeEndsWith": [
|
||||
".dart",
|
||||
".crash_dart"
|
||||
],
|
||||
"exclude": [
|
||||
"/testcases/.*_part[0-9]*\\.dart$",
|
||||
@@ -106,40 +104,37 @@
|
||||
"name": "incremental_dartino",
|
||||
"kind": "Chain",
|
||||
"source": "test/fasta/incremental_dartino_suite.dart",
|
||||
"path": "testcases/dartino",
|
||||
"root": "testcases/dartino",
|
||||
"status": "testcases/incremental_dartino.status",
|
||||
"pattern": [
|
||||
"\\.incremental\\.yaml$"
|
||||
],
|
||||
"exclude": []
|
||||
"includeEndsWith": [
|
||||
".incremental.yaml"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "expression",
|
||||
"kind": "Chain",
|
||||
"source": "test/fasta/expression_suite.dart",
|
||||
"path": "testcases/expression/",
|
||||
"root": "testcases/expression/",
|
||||
"status": "testcases/expression.status",
|
||||
"pattern": [
|
||||
"\\.expression\\.yaml$"
|
||||
],
|
||||
"exclude": []
|
||||
"includeEndsWith": [
|
||||
".expression.yaml"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "incremental",
|
||||
"kind": "Chain",
|
||||
"source": "test/incremental_suite.dart",
|
||||
"path": "testcases/incremental/",
|
||||
"root": "testcases/incremental/",
|
||||
"status": "testcases/incremental.status",
|
||||
"pattern": [
|
||||
"\\.yaml$"
|
||||
],
|
||||
"exclude": []
|
||||
"includeEndsWith": [
|
||||
".yaml"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "incremental_bulk_compiler_smoke",
|
||||
"kind": "Chain",
|
||||
"source": "test/incremental_bulk_compiler_smoke_suite.dart",
|
||||
"path": "../../tests/",
|
||||
"root": "../../tests/",
|
||||
"status": "testcases/incremental_bulk_compiler_smoke.status",
|
||||
"pattern": [
|
||||
"/language/accessor_conflict_export2_test\\.dart$",
|
||||
@@ -160,78 +155,78 @@
|
||||
"/language/script1_negative_test\\.dart$",
|
||||
"/language/script2_negative_test\\.dart$",
|
||||
"/language/unbalanced_brace_test\\.dart$"
|
||||
],
|
||||
"exclude": []
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "incremental_bulk_compiler_full",
|
||||
"kind": "Chain",
|
||||
"source": "test/incremental_bulk_compiler_full.dart",
|
||||
"path": "../../tests/",
|
||||
"root": "../../tests/language/",
|
||||
"status": "testcases/incremental_bulk_compiler_full.status",
|
||||
"pattern": [
|
||||
"language/.*_test\\.dart$"
|
||||
],
|
||||
"exclude": []
|
||||
"includeEndsWith": [
|
||||
"_test.dart"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "parser",
|
||||
"kind": "Chain",
|
||||
"source": "test/parser_suite.dart",
|
||||
"path": "parser_testcases/",
|
||||
"root": "parser_testcases/",
|
||||
"status": "parser_testcases/parser.status",
|
||||
"pattern": [
|
||||
"\\.dart$",
|
||||
"\\.crash_dart$"
|
||||
],
|
||||
"exclude": []
|
||||
"includeEndsWith": [
|
||||
".dart",
|
||||
".crash_dart"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "outline_extractor",
|
||||
"kind": "Chain",
|
||||
"source": "test/outline_extractor_suite.dart",
|
||||
"path": "outline_extraction_testcases/",
|
||||
"root": "outline_extraction_testcases/",
|
||||
"status": "outline_extraction_testcases/outline_extractor.status",
|
||||
"pattern": [
|
||||
"main\\.dart$"
|
||||
],
|
||||
"exclude": []
|
||||
"includeEndsWith": [
|
||||
"main.dart"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "parser_equivalence",
|
||||
"kind": "Chain",
|
||||
"source": "test/parser_equivalence_suite.dart",
|
||||
"path": "parser_testcases/",
|
||||
"root": "parser_testcases/",
|
||||
"status": "parser_testcases/parser_equivalence.status",
|
||||
"pattern": [
|
||||
"\\.equivalence_info$"
|
||||
],
|
||||
"exclude": []
|
||||
"includeEndsWith": [
|
||||
".equivalence_info"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "parser_all",
|
||||
"kind": "Chain",
|
||||
"source": "test/parser_all_suite.dart",
|
||||
"path": "../../",
|
||||
"status": "parser_testcases/parser_all.status",
|
||||
"pattern": [
|
||||
"pkg/front_end/.*\\.dart$",
|
||||
"pkg/front_end/.*\\.crash_dart$",
|
||||
"/tests/.*\\.dart$"
|
||||
"root": "../../",
|
||||
"subRoots": [
|
||||
"pkg/front_end/",
|
||||
"tests/"
|
||||
],
|
||||
"exclude": []
|
||||
"status": "parser_testcases/parser_all.status",
|
||||
"includeEndsWith": [
|
||||
".dart",
|
||||
".crash_dart"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "lint",
|
||||
"kind": "Chain",
|
||||
"source": "test/lint_suite.dart",
|
||||
"path": "../",
|
||||
"root": "../",
|
||||
"subRoots": [
|
||||
"_fe_analyzer_shared/lib/",
|
||||
"kernel/lib/",
|
||||
"front_end/lib/",
|
||||
"frontend_server/"
|
||||
],
|
||||
"status": "test/lint_test.status",
|
||||
"pattern": [
|
||||
"_fe_analyzer_shared/lib/.*\\.dart$",
|
||||
"kernel/lib/.*\\.dart$",
|
||||
"front_end/lib/.*\\.dart$",
|
||||
"frontend_server/.*\\.dart$"
|
||||
"includeEndsWith": [
|
||||
".dart"
|
||||
],
|
||||
"exclude": [
|
||||
"kernel/lib/transformations/.*\\.dart$",
|
||||
@@ -243,28 +238,33 @@
|
||||
"name": "dartdoctest",
|
||||
"kind": "Chain",
|
||||
"source": "test/dartdoctest_suite.dart",
|
||||
"path": "../",
|
||||
"status": "test/dartdoctest_suite.status",
|
||||
"pattern": [
|
||||
"_fe_analyzer_shared/.*\\.dart$",
|
||||
"kernel/.*\\.dart$",
|
||||
"front_end/.*\\.dart$"
|
||||
"root": "../",
|
||||
"subRoots": [
|
||||
"_fe_analyzer_shared/",
|
||||
"kernel/",
|
||||
"front_end/"
|
||||
],
|
||||
"exclude": []
|
||||
"includeEndsWith": [
|
||||
".dart"
|
||||
],
|
||||
"status": "test/dartdoctest_suite.status"
|
||||
},
|
||||
{
|
||||
"name": "spelling_test_src",
|
||||
"kind": "Chain",
|
||||
"source": "test/spelling_test_src_suite.dart",
|
||||
"path": "../",
|
||||
"root": "../",
|
||||
"subRoots": [
|
||||
"_fe_analyzer_shared/lib/",
|
||||
"front_end/lib/",
|
||||
"kernel/lib/",
|
||||
"kernel/bin/",
|
||||
"frontend_server/lib/",
|
||||
"frontend_server/bin/"
|
||||
],
|
||||
"status": "test/spelling_test.status",
|
||||
"pattern": [
|
||||
"_fe_analyzer_shared/lib/.*\\.dart$",
|
||||
"front_end/lib/.*\\.dart$",
|
||||
"kernel/lib/.*\\.dart$",
|
||||
"kernel/bin/.*\\.dart$",
|
||||
"frontend_server/lib/.*\\.dart$",
|
||||
"frontend_server/bin/.*\\.dart$"
|
||||
"includeEndsWith": [
|
||||
".dart"
|
||||
],
|
||||
"exclude": [
|
||||
"_fe_analyzer_shared/lib/src/messages/codes_generated\\.dart$",
|
||||
@@ -275,10 +275,10 @@
|
||||
"name": "spelling_test_not_src",
|
||||
"kind": "Chain",
|
||||
"source": "test/spelling_test_not_src_suite.dart",
|
||||
"path": ".",
|
||||
"root": ".",
|
||||
"status": "test/spelling_test.status",
|
||||
"pattern": [
|
||||
".*\\.dart$"
|
||||
"includeEndsWith": [
|
||||
".dart"
|
||||
],
|
||||
"exclude": [
|
||||
"lib/",
|
||||
@@ -326,62 +326,14 @@
|
||||
"name": "spelling_test_external_targets",
|
||||
"kind": "Chain",
|
||||
"source": "test/spelling_test_external_targets.dart",
|
||||
"path": "../../",
|
||||
"status": "test/spelling_test.status",
|
||||
"pattern": [
|
||||
".*\\.dart$"
|
||||
"root": "../../",
|
||||
"subRoots": [
|
||||
"pkg/",
|
||||
"sdk/"
|
||||
],
|
||||
"exclude": []
|
||||
},
|
||||
{
|
||||
"note": "Tests dart2js fully, excluding browser-only tests.",
|
||||
"name": "dart2js",
|
||||
"kind": "test_dart",
|
||||
"arch": "x64",
|
||||
"mode": "release",
|
||||
"common": "--time -pcolor --report -ax64 -mrelease --write-result-log",
|
||||
"command-lines": [
|
||||
"--checked dart2js",
|
||||
"-cdart2js -rd8 --exclude-suite=observatory_ui",
|
||||
"-cdart2js -rd8 web"
|
||||
]
|
||||
},
|
||||
{
|
||||
"note": "Minimal testing of Fasta.",
|
||||
"name": "fasta_min",
|
||||
"kind": "test_dart",
|
||||
"arch": "x64",
|
||||
"mode": "release",
|
||||
"common": "--time -pcolor --report -ax64 -mrelease --write-result-log",
|
||||
"command-lines": [
|
||||
"-t240 pkg/(kernel|front_end|fasta) --checked",
|
||||
"-t240 web/analyze_test",
|
||||
"-cdartk -rvm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"note": "Tests Fasta fully, including the above dart2js tests.",
|
||||
"name": "fasta_max",
|
||||
"kind": "test_dart",
|
||||
"arch": "x64",
|
||||
"mode": "release",
|
||||
"common": "--time -pcolor --report -ax64 -mrelease --write-result-log",
|
||||
"command-lines": [
|
||||
"-t240 --checked pkg/(kernel|front_end|fasta) dart2js",
|
||||
"-cdartk -rvm",
|
||||
"-cdart2js -rd8 --exclude-suite=observatory_ui",
|
||||
"-cdart2js -rd8 web"
|
||||
]
|
||||
},
|
||||
{
|
||||
"note": "Runs dart2js in a mode where it invokes Fasta.",
|
||||
"name": "dart2js_with_kernel",
|
||||
"kind": "test_dart",
|
||||
"arch": "x64",
|
||||
"mode": "release",
|
||||
"common": "--time -pcolor --report -ax64 -mrelease --write-result-log",
|
||||
"command-lines": [
|
||||
"-cdart2js -rd8 --use-sdk --minified language corelib"
|
||||
"status": "test/spelling_test.status",
|
||||
"includeEndsWith": [
|
||||
".dart"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
library testing.chain;
|
||||
|
||||
import 'dart:async' show Future, Stream;
|
||||
|
||||
import 'dart:convert' show json, JsonEncoder;
|
||||
|
||||
import 'dart:io' show Directory, File, FileSystemEntity, exitCode;
|
||||
@@ -31,27 +29,50 @@ typedef CreateContext = Future<ChainContext> Function(
|
||||
class Chain extends Suite {
|
||||
final Uri source;
|
||||
|
||||
final Uri uri;
|
||||
final Uri root;
|
||||
|
||||
final List<Uri> subRoots;
|
||||
|
||||
final List<String> includeEndsWith;
|
||||
|
||||
final List<RegExp> pattern;
|
||||
|
||||
final List<RegExp> exclude;
|
||||
|
||||
Chain(String name, String kind, this.source, this.uri, Uri statusFile,
|
||||
this.pattern, this.exclude)
|
||||
Chain(String name, String kind, this.source, this.root, this.subRoots,
|
||||
Uri statusFile, this.includeEndsWith, this.pattern, this.exclude)
|
||||
: super(name, kind, statusFile);
|
||||
|
||||
factory Chain.fromJsonMap(Uri base, Map json, String name, String kind) {
|
||||
Uri source = base.resolve(json["source"]);
|
||||
String path = json["path"];
|
||||
if (!path.endsWith("/")) {
|
||||
path += "/";
|
||||
String root = json["root"];
|
||||
if (!root.endsWith("/")) {
|
||||
root += "/";
|
||||
}
|
||||
Uri rootUri = base.resolve(root);
|
||||
List<Uri> subRoots = [];
|
||||
List? subRootsList = json["subRoots"];
|
||||
if (subRootsList != null) {
|
||||
for (String subRoot in subRootsList) {
|
||||
if (!subRoot.endsWith("/")) {
|
||||
subRoot += "/";
|
||||
}
|
||||
subRoots.add(rootUri.resolve(subRoot));
|
||||
}
|
||||
} else {
|
||||
subRoots.add(rootUri);
|
||||
}
|
||||
Uri uri = base.resolve(path);
|
||||
Uri statusFile = base.resolve(json["status"]);
|
||||
List<RegExp> pattern = [for (final p in json['pattern']) RegExp(p)];
|
||||
List<RegExp> exclude = [for (final e in json['exclude']) RegExp(e)];
|
||||
return Chain(name, kind, source, uri, statusFile, pattern, exclude);
|
||||
List<String> includeEndsWith =
|
||||
List<String>.from(json['includeEndsWith'] ?? const []);
|
||||
List<RegExp> pattern = [
|
||||
for (final p in json['pattern'] ?? const []) new RegExp(p)
|
||||
];
|
||||
List<RegExp> exclude = [
|
||||
for (final e in json['exclude'] ?? const []) new RegExp(e)
|
||||
];
|
||||
return Chain(name, kind, source, rootUri, subRoots, statusFile,
|
||||
includeEndsWith, pattern, exclude);
|
||||
}
|
||||
|
||||
void writeImportOn(StringSink sink) {
|
||||
@@ -78,9 +99,10 @@ class Chain extends Suite {
|
||||
"name": name,
|
||||
"kind": kind,
|
||||
"source": "$source",
|
||||
"path": "$uri",
|
||||
"root": "$root",
|
||||
"status": "$statusFile",
|
||||
"pattern": [for (final r in pattern) r.pattern],
|
||||
"includeEndsWith": includeEndsWith,
|
||||
"exclude": [for (final r in exclude) r.pattern],
|
||||
};
|
||||
}
|
||||
@@ -106,8 +128,7 @@ abstract class ChainContext {
|
||||
.toList();
|
||||
TestExpectations expectations = readTestExpectations(
|
||||
<String>[suite.statusFile!.toFilePath()], expectationSet);
|
||||
Stream<TestDescription> stream = list(suite);
|
||||
List<TestDescription> descriptions = await stream.toList();
|
||||
List<TestDescription> descriptions = await list(suite);
|
||||
descriptions.sort();
|
||||
if (shards > 1) {
|
||||
List<TestDescription> shardDescriptions = [];
|
||||
@@ -242,22 +263,35 @@ abstract class ChainContext {
|
||||
await postRun();
|
||||
}
|
||||
|
||||
Stream<TestDescription> list(Chain suite) async* {
|
||||
Directory testRoot = Directory.fromUri(suite.uri);
|
||||
if (await testRoot.exists()) {
|
||||
Stream<FileSystemEntity> files =
|
||||
testRoot.list(recursive: true, followLinks: false);
|
||||
await for (FileSystemEntity entity in files) {
|
||||
if (entity is! File) continue;
|
||||
String path = entity.uri.path;
|
||||
if (suite.exclude.any((RegExp r) => path.contains(r))) continue;
|
||||
if (suite.pattern.any((RegExp r) => path.contains(r))) {
|
||||
yield FileBasedTestDescription(suite.uri, entity);
|
||||
Future<List<TestDescription>> list(Chain suite) async {
|
||||
List<TestDescription> result = [];
|
||||
for (Uri subRoot in suite.subRoots) {
|
||||
Directory testRoot = Directory.fromUri(subRoot);
|
||||
if (testRoot.existsSync()) {
|
||||
for (FileSystemEntity entity
|
||||
in testRoot.listSync(recursive: true, followLinks: false)) {
|
||||
if (entity is! File) continue;
|
||||
// Use `.uri.path` instead of just `.path` to ensure forward slashes.
|
||||
String path = entity.uri.path;
|
||||
|
||||
if (suite.exclude.any((RegExp r) => path.contains(r))) continue;
|
||||
|
||||
bool include = false;
|
||||
if (suite.includeEndsWith.any((String end) => path.endsWith(end))) {
|
||||
include = true;
|
||||
}
|
||||
if (!include && suite.pattern.any((RegExp r) => path.contains(r))) {
|
||||
include = true;
|
||||
}
|
||||
if (include) {
|
||||
result.add(new FileBasedTestDescription(suite.root, entity));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw "$subRoot isn't a directory";
|
||||
}
|
||||
} else {
|
||||
throw "${suite.uri} isn't a directory";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Set<Expectation> processExpectedOutcomes(
|
||||
|
||||
@@ -18,17 +18,14 @@ import 'error_handling.dart' show withErrorHandling;
|
||||
|
||||
import 'chain.dart' show CreateContext;
|
||||
|
||||
import '../testing.dart'
|
||||
show Chain, ChainContext, FileBasedTestDescription, listTests;
|
||||
import '../testing.dart' show Chain, ChainContext;
|
||||
|
||||
import 'analyze.dart' show Analyze;
|
||||
|
||||
import 'log.dart'
|
||||
show enableVerboseOutput, isVerbose, Logger, splitLines, StdoutLogger;
|
||||
|
||||
import 'suite.dart' show Dart, Suite;
|
||||
|
||||
import 'test_dart.dart' show TestDart;
|
||||
import 'suite.dart' show Suite;
|
||||
|
||||
import 'zone_helper.dart' show acknowledgeControlMessages;
|
||||
|
||||
@@ -168,30 +165,12 @@ class SuiteRunner {
|
||||
StringBuffer chain = StringBuffer();
|
||||
bool hasRunnableTests = false;
|
||||
|
||||
await for (FileBasedTestDescription description in listDescriptions()) {
|
||||
hasRunnableTests = true;
|
||||
description.writeImportOn(imports);
|
||||
description.writeClosureOn(dart);
|
||||
}
|
||||
|
||||
await for (Chain suite in listChainSuites()) {
|
||||
hasRunnableTests = true;
|
||||
suite.writeImportOn(imports);
|
||||
suite.writeClosureOn(chain);
|
||||
}
|
||||
|
||||
bool isFirstTestDartSuite = true;
|
||||
for (TestDart suite in listTestDartSuites()) {
|
||||
if (shouldRunSuite(suite)) {
|
||||
hasRunnableTests = true;
|
||||
if (isFirstTestDartSuite) {
|
||||
suite.writeFirstImportOn(imports);
|
||||
}
|
||||
isFirstTestDartSuite = false;
|
||||
suite.writeRunCommandOn(chain);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasRunnableTests) return null;
|
||||
|
||||
return """
|
||||
@@ -234,22 +213,6 @@ Future<Null> main() async {
|
||||
return hasAnalyzerSuites;
|
||||
}
|
||||
|
||||
Stream<FileBasedTestDescription> listDescriptions() async* {
|
||||
for (Dart suite in suites.whereType<Dart>()) {
|
||||
await for (FileBasedTestDescription description
|
||||
in listTests(<Uri>[suite.uri], pattern: "")) {
|
||||
testUris.add((await Isolate.resolvePackageUri(description.uri))!);
|
||||
if (shouldRunSuite(suite)) {
|
||||
String path = description.file.uri.path;
|
||||
if (suite.exclude.any((RegExp r) => path.contains(r))) continue;
|
||||
if (suite.pattern.any((RegExp r) => path.contains(r))) {
|
||||
yield description;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Stream<Chain> listChainSuites() async* {
|
||||
for (Chain suite in suites.whereType<Chain>()) {
|
||||
testUris.add((await Isolate.resolvePackageUri(suite.source))!);
|
||||
@@ -259,10 +222,6 @@ Future<Null> main() async {
|
||||
}
|
||||
}
|
||||
|
||||
Iterable<TestDart> listTestDartSuites() {
|
||||
return suites.whereType<TestDart>();
|
||||
}
|
||||
|
||||
Iterable<Analyze> listAnalyzerSuites() {
|
||||
return suites.whereType<Analyze>();
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ library testing.suite;
|
||||
|
||||
import 'chain.dart' show Chain;
|
||||
|
||||
import 'test_dart.dart' show TestDart;
|
||||
|
||||
/// Records the properties of a test suite.
|
||||
abstract class Suite {
|
||||
final String name;
|
||||
@@ -22,15 +20,9 @@ abstract class Suite {
|
||||
String kind = json["kind"].toLowerCase();
|
||||
String name = json["name"];
|
||||
switch (kind) {
|
||||
case "dart":
|
||||
return Dart.fromJsonMap(base, json, name);
|
||||
|
||||
case "chain":
|
||||
return Chain.fromJsonMap(base, json, name, kind);
|
||||
|
||||
case "test_dart":
|
||||
return TestDart.fromJsonMap(base, json, name, kind);
|
||||
|
||||
default:
|
||||
throw "Suite '$name' has unknown kind '$kind'.";
|
||||
}
|
||||
@@ -39,52 +31,3 @@ abstract class Suite {
|
||||
@override
|
||||
String toString() => "Suite($name, $kind)";
|
||||
}
|
||||
|
||||
/// A suite of standalone tests. The tests are combined and run as one program.
|
||||
///
|
||||
/// A standalone test is a test with a `main` method. The test is considered
|
||||
/// successful if main doesn't throw an error (or if `main` returns a future,
|
||||
/// that future completes without errors).
|
||||
///
|
||||
/// The tests are combined by generating a Dart file which imports all the main
|
||||
/// methods and calls them sequentially.
|
||||
///
|
||||
/// Example JSON configuration:
|
||||
///
|
||||
/// {
|
||||
/// "name": "test",
|
||||
/// "kind": "Dart",
|
||||
/// # Root directory of tests in this suite.
|
||||
/// "path": "test/",
|
||||
/// # Files in `path` that match any of the following regular expressions
|
||||
/// # are considered to be part of this suite.
|
||||
/// "pattern": [
|
||||
/// "_test.dart$"
|
||||
/// ],
|
||||
/// # Except if they match any of the following regular expressions.
|
||||
/// "exclude": [
|
||||
/// "/golden/"
|
||||
/// ]
|
||||
/// }
|
||||
class Dart extends Suite {
|
||||
final Uri uri;
|
||||
|
||||
final List<RegExp> pattern;
|
||||
|
||||
final List<RegExp> exclude;
|
||||
|
||||
Dart(String name, this.uri, this.pattern, this.exclude)
|
||||
: super(name, "dart", null);
|
||||
|
||||
factory Dart.fromJsonMap(Uri base, Map json, String name) {
|
||||
Uri uri = base.resolve(json["path"]);
|
||||
List<RegExp> pattern =
|
||||
List<RegExp>.from(json["pattern"].map((String p) => RegExp(p)));
|
||||
List<RegExp> exclude =
|
||||
List<RegExp>.from(json["exclude"].map((String p) => RegExp(p)));
|
||||
return Dart(name, uri, pattern, exclude);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => "Dart($name, $uri, $pattern, $exclude)";
|
||||
}
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
// Copyright (c) 2016, 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 testing.test_dart;
|
||||
|
||||
import 'dart:convert' show json;
|
||||
|
||||
import 'dart:io' show Platform;
|
||||
|
||||
import 'suite.dart' show Suite;
|
||||
|
||||
/// A suite that runs test.dart.
|
||||
class TestDart extends Suite {
|
||||
final String common;
|
||||
|
||||
final String processes;
|
||||
|
||||
final List<String> commandLines;
|
||||
|
||||
TestDart(String name, this.common, this.processes, this.commandLines)
|
||||
: super(
|
||||
name,
|
||||
"test_dart",
|
||||
// This suite doesn't know what it's status file is because
|
||||
// test.dart doesn't know.
|
||||
null);
|
||||
|
||||
factory TestDart.fromJsonMap(Uri base, Map json, String name, String kind) {
|
||||
String common = json["common"] ?? "";
|
||||
String processes = json["processes"] ?? "-j${Platform.numberOfProcessors}";
|
||||
List<String> commandLines = json["command-lines"] == null
|
||||
? List<String>.from(json["command-lines"])
|
||||
: <String>[];
|
||||
return TestDart(name, common, processes, commandLines);
|
||||
}
|
||||
|
||||
void writeFirstImportOn(StringSink sink) {
|
||||
sink.writeln("import 'dart:io' as io;");
|
||||
sink.writeln(
|
||||
"import 'package:testing/src/stdio_process.dart' show StdioProcess;");
|
||||
}
|
||||
|
||||
void writeRunCommandOn(StringSink sink) {
|
||||
Uri dartVm;
|
||||
if (Platform.isMacOS || Platform.isLinux) {
|
||||
dartVm = Uri.base.resolve("tools/sdks/dart-sdk/bin/dart");
|
||||
} else if (Platform.isWindows) {
|
||||
dartVm = Uri.base.resolve("tools/sdks/dart-sdk/bin/dart.exe");
|
||||
} else {
|
||||
throw "Operating system not supported: ${Platform.operatingSystem}";
|
||||
}
|
||||
List<String> processedArguments = <String>[];
|
||||
processedArguments.add(Uri.base
|
||||
.resolve("pkg/test_runner/bin/package_testing_support.dart")
|
||||
.toFilePath());
|
||||
for (String commandLine in commandLines) {
|
||||
String arguments = common;
|
||||
arguments += " $processes";
|
||||
arguments += " $commandLine";
|
||||
processedArguments.add(arguments);
|
||||
}
|
||||
String executable = json.encode(dartVm.toFilePath());
|
||||
String arguments = json.encode(processedArguments);
|
||||
sink.write("""
|
||||
{
|
||||
print('Running $arguments');
|
||||
StdioProcess process = await StdioProcess.run($executable, $arguments,
|
||||
suppressOutput: false, timeout: null);
|
||||
if (process.exitCode != 0) {
|
||||
print(process.output);
|
||||
io.exitCode = 1;
|
||||
}
|
||||
}
|
||||
""");
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "TestDart($name, ${json.encode(common)}, ${json.encode(processes)},"
|
||||
" ${json.encode(commandLines)})";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user