[testing] Migrate pkg/testing to null safety

Change-Id: I64caff0a9163305ff122965105e7484c05b9cafb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/207138
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
Johnni Winther
2021-07-27 19:45:38 +00:00
committed by commit-bot@chromium.org
parent 45ae00676a
commit 0073b55575
19 changed files with 158 additions and 152 deletions
+22 -22
View File
@@ -18,21 +18,21 @@ import 'log.dart' show isVerbose, splitLines;
import 'suite.dart' show Suite;
class Analyze extends Suite {
final Uri analysisOptions;
final Uri? analysisOptions;
final List<Uri> uris;
final List<RegExp> exclude;
final List<String> gitGrepPathspecs;
final List<String>? gitGrepPathspecs;
final List<String> gitGrepPatterns;
final List<String>? gitGrepPatterns;
Analyze(this.analysisOptions, this.uris, this.exclude, this.gitGrepPathspecs,
this.gitGrepPatterns)
: super("analyze", "analyze", null);
Future<Null> run(Uri packages, List<Uri> extraUris) {
Future<Null> run(Uri packages, List<Uri>? extraUris) {
List<Uri> allUris = new List<Uri>.from(uris);
if (extraUris != null) {
allUris.addAll(extraUris);
@@ -43,8 +43,8 @@ class Analyze extends Suite {
static Future<Analyze> fromJsonMap(
Uri base, Map json, List<Suite> suites) async {
String optionsPath = json["options"];
Uri optionsUri = optionsPath == null ? null : base.resolve(optionsPath);
String? optionsPath = json["options"];
Uri? optionsUri = optionsPath == null ? null : base.resolve(optionsPath);
List<Uri> uris = json["uris"].map<Uri>((relative) {
String r = relative;
@@ -54,9 +54,9 @@ class Analyze extends Suite {
List<RegExp> exclude =
json["exclude"].map<RegExp>((p) => new RegExp(p)).toList();
Map gitGrep = json["git grep"];
List<String> gitGrepPathspecs;
List<String> gitGrepPatterns;
Map? gitGrep = json["git grep"];
List<String>? gitGrepPathspecs;
List<String>? gitGrepPatterns;
if (gitGrep != null) {
gitGrepPathspecs = gitGrep["pathspecs"] == null
? const <String>["."]
@@ -73,13 +73,13 @@ class Analyze extends Suite {
}
class AnalyzerDiagnostic {
final String kind;
final String? kind;
final String detailedKind;
final String? detailedKind;
final String code;
final String? code;
final Uri uri;
final Uri? uri;
final int line;
@@ -106,7 +106,7 @@ class AnalyzerDiagnostic {
addPart() {
parts.add(line
.substring(start, index == -1 ? null : index)
.replaceAllMapped(unescapePattern, (Match m) => m[1]));
.replaceAllMapped(unescapePattern, (Match m) => m[1]!));
}
while (index != -1) {
@@ -136,8 +136,8 @@ class AnalyzerDiagnostic {
String toString() {
return kind == null
? "Malformed output from dartanalyzer:\n$message"
: "${uri.toFilePath()}:$line:$startColumn: "
"${kind == 'INFO' ? 'warning: hint' : kind.toLowerCase()}:\n"
: "${uri!.toFilePath()}:$line:$startColumn: "
"${kind == 'INFO' ? 'warning: hint' : kind!.toLowerCase()}:\n"
"[$code] $message";
}
}
@@ -154,12 +154,12 @@ Stream<AnalyzerDiagnostic> parseAnalyzerOutput(
/// Run dartanalyzer on all tests in [uris].
Future<Null> analyzeUris(
Uri analysisOptions,
Uri? analysisOptions,
Uri packages,
List<Uri> uris,
List<RegExp> exclude,
List<String> gitGrepPathspecs,
List<String> gitGrepPatterns) async {
List<String>? gitGrepPathspecs,
List<String>? gitGrepPatterns) async {
if (uris.isEmpty) return;
String topLevel;
try {
@@ -205,7 +205,7 @@ Future<Null> analyzeUris(
arguments.addAll(
gitGrepPatterns.expand((String pattern) => <String>["-e", pattern]));
arguments.add("--");
arguments.addAll(gitGrepPathspecs);
arguments.addAll(gitGrepPathspecs!);
filesToAnalyze.addAll(splitLines(await git("grep", arguments))
.map((String line) => line.trimRight()));
}
@@ -245,7 +245,7 @@ Future<Null> analyzeUris(
processAnalyzerOutput(Stream<AnalyzerDiagnostic> diagnostics) async {
await for (AnalyzerDiagnostic diagnostic in diagnostics) {
if (diagnostic.uri != null) {
String path = toFilePath(diagnostic.uri);
String path = toFilePath(diagnostic.uri!);
if (!filesToAnalyze.contains(path)) continue;
}
String message = "$diagnostic";
@@ -283,7 +283,7 @@ String _findSdkPath() {
}
Future<String> git(String command, Iterable<String> arguments,
{String workingDirectory}) async {
{String? workingDirectory}) async {
ProcessResult result = await Process.run(
Platform.isWindows ? "git.bat" : "git",
<String>[command]..addAll(arguments),
+28 -27
View File
@@ -115,7 +115,7 @@ abstract class ChainContext {
.map((s) => s.substring(0, s.length - 3))
.toList();
TestExpectations expectations = await ReadTestExpectations(
<String>[suite.statusFile.toFilePath()], {}, expectationSet);
<String>[suite.statusFile!.toFilePath()], {}, expectationSet);
Stream<TestDescription> stream = list(suite);
if (suite.processMultitests) {
stream = stream.transform(new MultitestTransformer());
@@ -149,12 +149,12 @@ abstract class ChainContext {
final Set<Expectation> expectedOutcomes = processExpectedOutcomes(
expectations.expectations(description.shortName), description);
final StringBuffer sb = new StringBuffer();
final Step lastStep = steps.isNotEmpty ? steps.last : null;
final Step? lastStep = steps.isNotEmpty ? steps.last : null;
final Iterator<Step> iterator = steps.iterator;
Result result;
Result? result;
// Records the outcome of the last step that was run.
Step lastStepRun;
Step? lastStepRun;
/// Performs one step of [iterator].
///
@@ -194,30 +194,30 @@ abstract class ChainContext {
future = new Future.value(null);
}
future = future.then((_currentResult) async {
Result currentResult = _currentResult;
Result? currentResult = _currentResult;
if (currentResult != null) {
logger.logStepComplete(completed, unexpectedResults.length,
descriptions.length, suite, description, lastStepRun);
descriptions.length, suite, description, lastStepRun!);
result = currentResult;
if (currentResult.outcome == Expectation.Pass) {
// The input to the next step is the output of this step.
return doStep(result.output);
return doStep(result!.output);
}
}
await cleanUp(description, result);
await cleanUp(description, result!);
result =
processTestResult(description, result, lastStep == lastStepRun);
if (!expectedOutcomes.contains(result.outcome) &&
!expectedOutcomes.contains(result.outcome.canonical)) {
result.addLog("$sb");
unexpectedResults[description] = result;
processTestResult(description, result!, lastStep == lastStepRun);
if (!expectedOutcomes.contains(result!.outcome) &&
!expectedOutcomes.contains(result!.outcome.canonical)) {
result!.addLog("$sb");
unexpectedResults[description] = result!;
unexpectedOutcomes[description] = expectedOutcomes;
logger.logUnexpectedResult(
suite, description, result, expectedOutcomes);
suite, description, result!, expectedOutcomes);
exitCode = 1;
} else {
logger.logExpectedResult(
suite, description, result, expectedOutcomes);
suite, description, result!, expectedOutcomes);
logger.logMessage(sb);
}
logger.logTestComplete(++completed, unexpectedResults.length,
@@ -241,7 +241,7 @@ abstract class ChainContext {
if (unexpectedResults.isNotEmpty) {
unexpectedResults.forEach((TestDescription description, Result result) {
logger.logUnexpectedResult(
suite, description, result, unexpectedOutcomes[description]);
suite, description, result, unexpectedOutcomes[description]!);
});
print("${unexpectedResults.length} failed:");
unexpectedResults.forEach((TestDescription description, Result result) {
@@ -278,7 +278,7 @@ abstract class ChainContext {
TestDescription description, Result result, bool last) {
if (description is FileBasedTestDescription &&
description.multitestExpectations != null) {
if (isError(description.multitestExpectations)) {
if (isError(description.multitestExpectations!)) {
result =
toNegativeTestResult(result, description.multitestExpectations);
}
@@ -286,14 +286,14 @@ abstract class ChainContext {
if (result.outcome == Expectation.Pass) {
result.addLog("Negative test didn't report an error.\n");
} else if (result.outcome == Expectation.Fail) {
result.addLog("Negative test reported an error as expeceted.\n");
result.addLog("Negative test reported an error as expected.\n");
}
result = toNegativeTestResult(result);
}
return result;
}
Result toNegativeTestResult(Result result, [Set<String> expectations]) {
Result toNegativeTestResult(Result result, [Set<String>? expectations]) {
Expectation outcome = result.outcome;
if (outcome == Expectation.Pass) {
if (expectations == null) {
@@ -312,9 +312,9 @@ abstract class ChainContext {
return result.copyWithOutcome(outcome);
}
Future<void> cleanUp(TestDescription description, Result result) => null;
Future<void> cleanUp(TestDescription description, Result result) async {}
Future<void> postRun() => null;
Future<void> postRun() async {}
}
abstract class Step<I, O, C extends ChainContext> {
@@ -355,25 +355,25 @@ abstract class Step<I, O, C extends ChainContext> {
Result<O> crash(error, StackTrace trace) => new Result<O>.crash(error, trace);
Result<O> fail(O output, [error, StackTrace trace]) {
Result<O> fail(O output, [error, StackTrace? trace]) {
return new Result<O>.fail(output, error, trace);
}
}
class Result<O> {
final O output;
final O? output;
final Expectation outcome;
final error;
final StackTrace trace;
final StackTrace? trace;
final List<String> logs = <String>[];
/// If set, running the test with '-D$autoFixCommand' will automatically
/// update the test to match new expectations.
final String autoFixCommand;
final String? autoFixCommand;
/// If set, the test can be fixed by running
///
@@ -391,7 +391,7 @@ class Result<O> {
Result.crash(error, StackTrace trace)
: this(null, Expectation.Crash, error, trace: trace);
Result.fail(O output, [error, StackTrace trace])
Result.fail(O output, [error, StackTrace? trace])
: this(output, Expectation.Fail, error, trace: trace);
bool get isPass => outcome == Expectation.Pass;
@@ -420,7 +420,8 @@ class Result<O> {
Future<Null> runChain(CreateContext f, Map<String, String> environment,
Set<String> selectors, String jsonText) {
return withErrorHandling(() async {
Chain suite = new Suite.fromJsonMap(Uri.base, json.decode(jsonText));
Chain suite =
new Suite.fromJsonMap(Uri.base, json.decode(jsonText)) as Chain;
print("Running ${suite.name}");
ChainContext context = await f(suite, environment);
return context.run(suite, selectors);
+8 -7
View File
@@ -20,10 +20,10 @@ List<String> get dartArguments =>
<String>["-c", "--packages=${packageConfig.toFilePath()}"];
Stream<FileBasedTestDescription> listTests(List<Uri> testRoots,
{Pattern pattern}) {
{Pattern? pattern}) {
StreamController<FileBasedTestDescription> controller =
new StreamController<FileBasedTestDescription>();
Map<Uri, StreamSubscription> subscriptions = <Uri, StreamSubscription>{};
Map<Uri, StreamSubscription?> subscriptions = <Uri, StreamSubscription>{};
for (Uri testRootUri in testRoots) {
subscriptions[testRootUri] = null;
Directory testRoot = new Directory.fromUri(testRootUri);
@@ -32,8 +32,9 @@ Stream<FileBasedTestDescription> listTests(List<Uri> testRoots,
Stream<FileSystemEntity> stream =
testRoot.list(recursive: true, followLinks: false);
var subscription = stream.listen((FileSystemEntity entity) {
FileBasedTestDescription description = FileBasedTestDescription
.from(testRootUri, entity, pattern: pattern);
FileBasedTestDescription? description = FileBasedTestDescription.from(
testRootUri, entity,
pattern: pattern);
if (description != null) {
controller.add(description);
}
@@ -59,7 +60,7 @@ Stream<FileBasedTestDescription> listTests(List<Uri> testRoots,
}
Uri computePackageConfig() {
String path = Platform.packageConfig;
String? path = Platform.packageConfig;
if (path != null) return Uri.base.resolve(path);
return Uri.base.resolve(".packages");
}
@@ -72,7 +73,7 @@ const _dartSdk = (String.fromEnvironment("DART_SDK", defaultValue: "1") ==
: null;
Uri computeDartSdk() {
String dartSdkPath = Platform.environment["DART_SDK"] ?? _dartSdk;
String? dartSdkPath = Platform.environment["DART_SDK"] ?? _dartSdk;
if (dartSdkPath != null) {
return Uri.base.resolveUri(new Uri.file(dartSdkPath));
} else {
@@ -83,7 +84,7 @@ Uri computeDartSdk() {
}
Future<Process> startDart(Uri program,
[List<String> arguments, List<String> vmArguments]) {
[List<String>? arguments, List<String>? vmArguments]) {
List<String> allArguments = <String>[];
allArguments.addAll(vmArguments ?? dartArguments);
allArguments.add(program.toFilePath());
+2 -1
View File
@@ -12,13 +12,14 @@ import 'dart:isolate' show ReceivePort;
import 'log.dart';
Future<T> withErrorHandling<T>(Future<T> f(), {Logger logger}) async {
Future<T?> withErrorHandling<T>(Future<T> f(), {Logger? logger}) async {
final ReceivePort port = new ReceivePort();
try {
return await f();
} catch (e, trace) {
exitCode = 1;
stderr.writeln(e);
// ignore: unnecessary_null_comparison
if (trace != null) {
stderr.writeln(trace);
}
+6 -7
View File
@@ -42,7 +42,7 @@ class Expectation {
String toString() => name;
static Expectation fromGroup(ExpectationGroup group) {
static Expectation? fromGroup(ExpectationGroup group) {
switch (group) {
case ExpectationGroup.Crash:
return Expectation.Crash;
@@ -57,7 +57,6 @@ class Expectation {
case ExpectationGroup.Timeout:
return Expectation.Timeout;
}
throw "Unhandled group: '$group'.";
}
}
@@ -89,8 +88,8 @@ class ExpectationSet {
Map<String, Expectation> internalMap =
new Map<String, Expectation>.from(Default.internalMap);
for (Map map in data) {
String name;
String group;
String? name;
String? group;
map.forEach((_key, _value) {
String key = _key;
String value = _value;
@@ -113,12 +112,12 @@ class ExpectationSet {
if (group == null) {
throw "No group provided in '$map'";
}
Expectation expectation = new Expectation(name, groupFromString(group));
name = name.toLowerCase();
Expectation expectation = new Expectation(name!, groupFromString(group!));
name = name!.toLowerCase();
if (internalMap.containsKey(name)) {
throw "Duplicated expectation name: '$name'.";
}
internalMap[name] = expectation;
internalMap[name!] = expectation;
}
return new ExpectationSet(internalMap);
}
+9 -8
View File
@@ -78,19 +78,19 @@ abstract class Logger {
class StdoutLogger implements Logger {
const StdoutLogger();
void logTestStart(int completed, int failed, int total, Suite suite,
TestDescription description) {}
void logTestStart(int completed, int failed, int total, Suite? suite,
TestDescription? description) {}
void logTestComplete(int completed, int failed, int total, Suite suite,
TestDescription description) {
void logTestComplete(int completed, int failed, int total, Suite? suite,
TestDescription? description) {
String message = formatProgress(completed, failed, total);
if (suite != null) {
message += ": ${formatTestDescription(suite, description)}";
message += ": ${formatTestDescription(suite, description!)}";
}
logProgress(message);
}
void logStepStart(int completed, int failed, int total, Suite suite,
void logStepStart(int completed, int failed, int total, Suite? suite,
TestDescription description, Step step) {
String message = formatProgress(completed, failed, total);
if (suite != null) {
@@ -102,7 +102,7 @@ class StdoutLogger implements Logger {
logProgress(message);
}
void logStepComplete(int completed, int failed, int total, Suite suite,
void logStepComplete(int completed, int failed, int total, Suite? suite,
TestDescription description, Step step) {
if (!step.isAsync) return;
String message = formatProgress(completed, failed, total);
@@ -152,7 +152,7 @@ class StdoutLogger implements Logger {
void logUnexpectedResult(Suite suite, TestDescription description,
Result result, Set<Expectation> expectedOutcomes) {
print("${eraseLine}UNEXPECTED: ${suite.name}/${description.shortName}");
Uri statusFile = suite.statusFile;
Uri? statusFile = suite.statusFile;
if (statusFile != null) {
String path = statusFile.toFilePath();
if (result.outcome == Expectation.Pass) {
@@ -186,6 +186,7 @@ class StdoutLogger implements Logger {
void logUncaughtError(error, StackTrace stackTrace) {
logMessage(error);
// ignore: unnecessary_null_comparison
if (stackTrace != null) {
logMessage(stackTrace);
}
+9 -8
View File
@@ -51,8 +51,8 @@ class MultitestTransformer
nextTest:
await for (TestDescription test in stream) {
FileBasedTestDescription multitest;
String contents;
FileBasedTestDescription? multitest;
String? contents;
if (test is FileBasedTestDescription) {
contents = await test.file.readAsString();
if (contents.contains(multitestMarker)) {
@@ -73,11 +73,11 @@ class MultitestTransformer
"none": new Set<String>(),
};
int lineNumber = 0;
for (String line in splitLines(contents)) {
for (String line in splitLines(contents!)) {
lineNumber++;
int index = line.indexOf(multitestMarker);
String subtestName;
List<String> subtestOutcomesList;
String? subtestName;
List<String>? subtestOutcomesList;
if (index != -1) {
String annotationText =
line.substring(index + _multitestMarkerLength).trim();
@@ -102,7 +102,7 @@ class MultitestTransformer
lines.add(line);
Set<String> subtestOutcomes =
outcomes.putIfAbsent(subtestName, () => new Set<String>());
if (subtestOutcomesList.length != 1 ||
if (subtestOutcomesList!.length != 1 ||
subtestOutcomesList.single != "continued") {
for (String outcome in subtestOutcomesList) {
if (validOutcomes.contains(outcome)) {
@@ -125,8 +125,9 @@ class MultitestTransformer
Directory generated =
new Directory.fromUri(root.resolve(multitest.shortName));
generated = await generated.create(recursive: true);
for (String name in testsAsLines.keys) {
List<String> lines = testsAsLines[name];
for (MapEntry<String, List<String>> entry in testsAsLines.entries) {
String name = entry.key;
List<String> lines = entry.value;
Uri uri = generated.uri.resolve("${name}_generated.dart");
FileBasedTestDescription subtest =
new FileBasedTestDescription(root, new File.fromUri(uri));
+17 -17
View File
@@ -34,10 +34,10 @@ import 'zone_helper.dart' show acknowledgeControlMessages;
import 'run_tests.dart' show CommandLine;
Future<TestRoot> computeTestRoot(String configurationPath, Uri base) {
Future<TestRoot> computeTestRoot(String? configurationPath, Uri? base) {
Uri configuration = configurationPath == null
? Uri.base.resolve("testing.json")
: base.resolve(configurationPath);
: base!.resolve(configurationPath);
return TestRoot.fromUri(configuration);
}
@@ -50,8 +50,8 @@ Future<TestRoot> computeTestRoot(String configurationPath, Uri base) {
/// `testing.json` isn't located in the current working directory and is a path
/// relative to [me] which defaults to `Platform.script`.
Future<Null> runMe(List<String> arguments, CreateContext f,
{String configurationPath,
Uri me,
{String? configurationPath,
Uri? me,
int shards = 1,
int shard = 0,
Logger logger: const StdoutLogger()}) {
@@ -98,7 +98,7 @@ Future<Null> runMe(List<String> arguments, CreateContext f,
/// `testing.json` isn't located in the current working directory and is a path
/// relative to `Uri.base`.
Future<Null> run(List<String> arguments, List<String> suiteNames,
[String configurationPath]) {
[String? configurationPath]) {
return withErrorHandling(() async {
TestRoot root = await computeTestRoot(configurationPath, Uri.base);
List<Suite> suites = root.suites
@@ -106,7 +106,7 @@ Future<Null> run(List<String> arguments, List<String> suiteNames,
.toList();
SuiteRunner runner = new SuiteRunner(suites, <String, String>{},
const <String>[], new Set<String>(), new Set<String>());
String program = await runner.generateDartProgram();
String? program = await runner.generateDartProgram();
await runner.analyze(root.packages);
if (program != null) {
await runProgram(program, root.packages);
@@ -125,7 +125,7 @@ Future<Null> runProgram(String program, Uri packages) async {
errorsAreFatal: false,
checked: true,
packageConfig: packages);
List error;
List? error;
var subscription = isolate.errors.listen((data) {
error = data;
exitPort.close();
@@ -137,7 +137,7 @@ Future<Null> runProgram(String program, Uri packages) async {
subscription.cancel();
return error == null
? null
: new Future<Null>.error(error[0], new StackTrace.fromString(error[1]));
: new Future<Null>.error(error![0], new StackTrace.fromString(error![1]));
}
class SuiteRunner {
@@ -162,7 +162,7 @@ class SuiteRunner {
(selectedSuites.isEmpty || selectedSuites.contains(suite.name));
}
Future<String> generateDartProgram() async {
Future<String?> generateDartProgram() async {
testUris.clear();
StringBuffer imports = new StringBuffer();
StringBuffer dart = new StringBuffer();
@@ -238,10 +238,10 @@ Future<Null> main() async {
}
Stream<FileBasedTestDescription> listDescriptions() async* {
for (Dart suite in suites.where((Suite suite) => suite is Dart)) {
for (Dart suite in suites.whereType<Dart>()) {
await for (FileBasedTestDescription description
in listTests(<Uri>[suite.uri], pattern: "")) {
testUris.add(await Isolate.resolvePackageUri(description.uri));
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;
@@ -254,19 +254,19 @@ Future<Null> main() async {
}
Stream<Chain> listChainSuites() async* {
for (Chain suite in suites.where((Suite suite) => suite is Chain)) {
testUris.add(await Isolate.resolvePackageUri(suite.source));
for (Chain suite in suites.whereType<Chain>()) {
testUris.add((await Isolate.resolvePackageUri(suite.source))!);
if (shouldRunSuite(suite)) {
yield suite;
}
}
}
Iterable<Suite> listTestDartSuites() {
return suites.where((Suite suite) => suite is TestDart);
Iterable<TestDart> listTestDartSuites() {
return suites.whereType<TestDart>();
}
Iterable<Suite> listAnalyzerSuites() {
return suites.where((Suite suite) => suite is Analyze);
Iterable<Analyze> listAnalyzerSuites() {
return suites.whereType<Analyze>();
}
}
+5 -5
View File
@@ -64,7 +64,7 @@ class CommandLine {
Iterable<String> get selectors => arguments;
Future<Uri> get configuration async {
Future<Uri?> get configuration async {
const String configPrefix = "--config=";
List<String> configurationPaths = options
.where((String option) => option.startsWith(configPrefix))
@@ -111,7 +111,7 @@ class CommandLine {
}
const StdoutLogger()
.logMessage("Reading configuration file '$configurationPath'.");
Uri configuration =
Uri? configuration =
await Isolate.resolvePackageUri(Uri.base.resolve(configurationPath));
if (configuration == null ||
!await new File.fromUri(configuration).exists()) {
@@ -147,7 +147,7 @@ main(List<String> arguments) => withErrorHandling(() async {
enableVerboseOutput();
}
Map<String, String> environment = cl.environment;
Uri configuration = await cl.configuration;
Uri? configuration = await cl.configuration;
if (configuration == null) return;
if (!isVerbose) {
print("Use --verbose to display more details.");
@@ -155,7 +155,7 @@ main(List<String> arguments) => withErrorHandling(() async {
TestRoot root = await TestRoot.fromUri(configuration);
SuiteRunner runner = new SuiteRunner(
root.suites, environment, cl.selectors, cl.selectedSuites, cl.skip);
String program = await runner.generateDartProgram();
String? program = await runner.generateDartProgram();
bool hasAnalyzerSuites = await runner.analyze(root.packages);
Stopwatch sw = new Stopwatch()..start();
if (program == null) {
@@ -178,7 +178,7 @@ Future<void> runTests(Map<String, Function> tests) =>
try {
await runGuarded(() {
print("Running test $name");
return tests[name]();
return tests[name]!();
}, printLineOnStdout: sb.writeln);
const StdoutLogger().logMessage(sb);
} catch (e) {
+5 -5
View File
@@ -41,13 +41,13 @@ class StdioProcess {
}
static Future<StdioProcess> run(String executable, List<String> arguments,
{String input,
Duration timeout: const Duration(seconds: 60),
{String? input,
Duration? timeout: const Duration(seconds: 60),
bool suppressOutput: true,
bool runInShell: false}) async {
Process process =
await Process.start(executable, arguments, runInShell: runInShell);
Timer timer;
Timer? timer;
StringBuffer sb = new StringBuffer();
if (timeout != null) {
timer = new Timer(timeout, () {
@@ -75,8 +75,8 @@ class StdioProcess {
stdoutStream = stdoutStream.transform(transformToStdio(io.stdout));
stderrStream = stderrStream.transform(transformToStdio(io.stderr));
}
Future<List<String>> stdoutFuture = stdoutStream.toList();
Future<List<String>> stderrFuture = stderrStream.toList();
Future<List<String>> stdoutFuture = stdoutStream.toList() as Future<List<String>>;
Future<List<String>> stderrFuture = stderrStream.toList() as Future<List<String>>;
int exitCode = await process.exitCode;
timer?.cancel();
sb.writeAll(await stdoutFuture);
+1 -1
View File
@@ -14,7 +14,7 @@ abstract class Suite {
final String kind;
final Uri statusFile;
final Uri? statusFile;
Suite(this.name, this.kind, this.statusFile);
+2 -2
View File
@@ -192,7 +192,7 @@ class Path {
Path makeCanonical() {
bool isAbs = isAbsolute;
List segs = segments();
String drive;
String? drive;
if (isAbs && !segs.isEmpty && segs[0].length == 2 && segs[0][1] == ':') {
drive = segs[0];
segs.removeRange(0, 1);
@@ -267,7 +267,7 @@ class Path {
}
List<String> segments() {
List result = _path.split('/');
List<String> result = _path.split('/');
if (isAbsolute) result.removeRange(0, 1);
if (hasTrailingSeparator) result.removeLast();
return result;
@@ -64,7 +64,9 @@ class Tokenizer {
if (!testRegexp.hasMatch(expression)) {
throw new FormatException("Syntax error in '$expression'");
}
for (Match match in regexp.allMatches(expression)) tokens.add(match[0]);
for (Match match in regexp.allMatches(expression)) {
tokens.add(match[0]!);
}
return tokens;
}
}
@@ -179,8 +181,8 @@ class SetConstant implements SetExpression {
// An iterator that allows peeking at the current token.
class Scanner {
List<String> tokens;
Iterator tokenIterator;
String current;
late Iterator tokenIterator;
String? current;
Scanner(this.tokens) {
tokenIterator = tokens.iterator;
@@ -241,11 +243,11 @@ class ExpressionParser {
scanner.advance();
return value;
}
if (!new RegExp(r"^\w+$").hasMatch(scanner.current)) {
if (!new RegExp(r"^\w+$").hasMatch(scanner.current!)) {
throw new FormatException(
"Expected identifier in expression, got ${scanner.current}");
}
SetExpression value = new SetConstant(scanner.current);
SetExpression value = new SetConstant(scanner.current!);
scanner.advance();
return value;
}
@@ -290,21 +292,21 @@ class ExpressionParser {
"Expected \$ in expression, got ${scanner.current}");
}
scanner.advance();
if (!new RegExp(r"^\w+$").hasMatch(scanner.current)) {
if (!new RegExp(r"^\w+$").hasMatch(scanner.current!)) {
throw new FormatException(
"Expected identifier in expression, got ${scanner.current}");
}
TermVariable left = new TermVariable(scanner.current);
TermVariable left = new TermVariable(scanner.current!);
scanner.advance();
if (scanner.current == Token.EQUALS ||
scanner.current == Token.NOT_EQUALS) {
bool negate = scanner.current == Token.NOT_EQUALS;
scanner.advance();
if (!new RegExp(r"^\w+$").hasMatch(scanner.current)) {
if (!new RegExp(r"^\w+$").hasMatch(scanner.current!)) {
throw new FormatException(
"Expected value in expression, got ${scanner.current}");
}
TermConstant right = new TermConstant(scanner.current);
TermConstant right = new TermConstant(scanner.current!);
scanner.advance();
return new Comparison(left, right, negate);
} else {
@@ -29,7 +29,7 @@ class StatusFile {
class Section {
final StatusFile statusFile;
final BooleanExpression condition;
final BooleanExpression? condition;
final List<TestRule> testRules;
final int lineNumber;
@@ -40,7 +40,7 @@ class Section {
: testRules = <TestRule>[];
bool isEnabled(Map<String, String> environment) =>
condition == null || condition.evaluate(environment);
condition == null || condition!.evaluate(environment);
String toString() {
return "Section: $condition";
@@ -93,17 +93,17 @@ void ReadConfigurationInto(Path path, List<Section> sections, void onDone()) {
lines.listen((String line) {
lineNumber++;
Match match = SplitComment.firstMatch(line);
line = (match == null) ? "" : match[1];
Match? match = SplitComment.firstMatch(line);
line = (match == null) ? "" : match[1]!;
line = line.trim();
if (line.isEmpty) return;
// Extract the comment to get the issue number if needed.
String comment = (match == null || match[2] == null) ? "" : match[2];
String comment = (match == null || match[2] == null) ? "" : match[2]!;
match = HeaderPattern.firstMatch(line);
if (match != null) {
String condition_string = match[1].trim();
String condition_string = match[1]!.trim();
List<String> tokens = new Tokenizer(condition_string).tokenize();
ExpressionParser parser = new ExpressionParser(new Scanner(tokens));
currentSection =
@@ -114,21 +114,21 @@ void ReadConfigurationInto(Path path, List<Section> sections, void onDone()) {
match = RulePattern.firstMatch(line);
if (match != null) {
String name = match[1].trim();
String name = match[1]!.trim();
// TODO(whesse): Handle test names ending in a wildcard (*).
String expression_string = match[2].trim();
String expression_string = match[2]!.trim();
List<String> tokens = new Tokenizer(expression_string).tokenize();
SetExpression expression =
new ExpressionParser(new Scanner(tokens)).parseSetExpression();
// Look for issue number in comment.
String issueString = null;
String? issueString = null;
match = IssueNumberPattern.firstMatch(comment);
if (match != null) {
issueString = match[1];
if (issueString == null) issueString = match[2];
}
int issue = issueString != null ? int.parse(issueString) : null;
int? issue = issueString != null ? int.parse(issueString) : null;
currentSection.testRules
.add(new TestRule(name, expression, issue, lineNumber));
return;
@@ -141,7 +141,7 @@ void ReadConfigurationInto(Path path, List<Section> sections, void onDone()) {
class TestRule {
String name;
SetExpression expression;
int issue;
int? issue;
int lineNumber;
TestRule(this.name, this.expression, this.issue, this.lineNumber);
@@ -161,8 +161,8 @@ class TestExpectations {
Map<String, Set<Expectation>> _map;
bool _preprocessed = false;
Map<String, RegExp> _regExpCache;
Map<String, List<RegExp>> _keyToRegExps;
Map<String, RegExp>? _regExpCache;
Map<String, List<RegExp>>? _keyToRegExps;
/**
* Create a TestExpectations object. See the [expectations] method
@@ -203,7 +203,7 @@ class TestExpectations {
_preprocessForMatching();
_map.forEach((key, expectation) {
List regExps = _keyToRegExps[key];
List<RegExp> regExps = _keyToRegExps![key]!;
if (regExps.length > splitFilename.length) return;
for (var i = 0; i < regExps.length; i++) {
if (!regExps[i].hasMatch(splitFilename[i])) return;
@@ -231,20 +231,19 @@ class TestExpectations {
_regExpCache = {};
_map.forEach((key, expectations) {
if (_keyToRegExps[key] != null) return;
if (_keyToRegExps![key] != null) return;
var splitKey = key.split('/');
var regExps = new List<RegExp>.filled(splitKey.length, null);
for (var i = 0; i < splitKey.length; i++) {
var regExps = new List<RegExp>.generate(splitKey.length, (int i) {
var component = splitKey[i];
var regExp = _regExpCache[component];
var regExp = _regExpCache![component];
if (regExp == null) {
var pattern = "^${splitKey[i]}\$".replaceAll('*', '.*');
regExp = new RegExp(pattern);
_regExpCache[component] = regExp;
_regExpCache![component] = regExp;
}
regExps[i] = regExp;
}
_keyToRegExps[key] = regExps;
return regExp;
}, growable: false);
_keyToRegExps![key] = regExps;
});
_regExpCache = null;
+4 -4
View File
@@ -17,11 +17,11 @@ abstract class TestDescription implements Comparable<TestDescription> {
class FileBasedTestDescription extends TestDescription {
final Uri root;
final File file;
final Uri output;
final Uri? output;
/// If non-null, this is a generated multitest, and the set contains the
/// expected outcomes.
Set<String> multitestExpectations;
Set<String>? multitestExpectations;
FileBasedTestDescription(this.root, this.file, {this.output});
@@ -52,8 +52,8 @@ class FileBasedTestDescription extends TestDescription {
sink.writeln('.main,');
}
static FileBasedTestDescription from(Uri root, FileSystemEntity entity,
{Pattern pattern}) {
static FileBasedTestDescription? from(Uri root, FileSystemEntity entity,
{Pattern? pattern}) {
if (entity is! File) return null;
pattern ??= "_test.dart";
String path = entity.uri.path;
+1 -1
View File
@@ -49,7 +49,7 @@ class TestRoot {
TestRoot(this.packages, this.suites);
Analyze get analyze => suites.last;
Analyze get analyze => suites.last as Analyze;
List<Uri> get urisToAnalyze => analyze.uris;
+4 -3
View File
@@ -14,8 +14,8 @@ import 'dart:isolate' show Capability, Isolate, ReceivePort;
import 'log.dart' show StdoutLogger;
Future runGuarded(Future f(),
{void printLineOnStdout(line),
void handleLateError(error, StackTrace stackTrace)}) {
{void Function(String)? printLineOnStdout,
void Function(dynamic, StackTrace)? handleLateError}) {
var printWrapper;
if (printLineOnStdout != null) {
printWrapper = (_1, _2, _3, String line) {
@@ -39,6 +39,7 @@ Future runGuarded(Future f(),
// Ignored.
}
stderr
// ignore: unnecessary_null_comparison
.write("$errorString\n" + (stackTrace == null ? "" : "$stackTrace"));
stderr.flush();
exit(255);
@@ -81,7 +82,7 @@ Future runGuarded(Future f(),
/// Ping [isolate] to ensure control messages have been delivered. Control
/// messages are things like [Isolate.addErrorListener] and
/// [Isolate.addOnExitListener].
Future acknowledgeControlMessages(Isolate isolate, {Capability resume}) {
Future acknowledgeControlMessages(Isolate isolate, {Capability? resume}) {
ReceivePort ping = new ReceivePort();
Isolate.current.ping(ping.sendPort);
if (resume == null) {
+1 -1
View File
@@ -4,4 +4,4 @@ name: testing
# This package is not intended for consumption on pub.dev. DO NOT publish.
publish_to: none
environment:
sdk: '>=2.0.0 <3.0.0'
sdk: '>=2.12.0 <3.0.0'