Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(258)

Unified Diff: tools/testing/dart/test_runner.dart

Issue 841193003: cleanup to tools/testing/dart (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: one last bit Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/testing/dart/test_progress.dart ('k') | tools/testing/dart/test_suite.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/testing/dart/test_runner.dart
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 1bdf34e2b4d22e29967d886c11ae23140e30d9e3..77a203df378a47c3e074abad3a0ffd25f6c58219 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -11,29 +11,25 @@
*/
library test_runner;
-import "dart:async";
-import "dart:collection" show Queue;
-import "dart:convert" show LineSplitter, UTF8, JSON;
+import 'dart:async';
+import 'dart:collection' show Queue;
+import 'dart:convert' show LineSplitter, UTF8, JSON;
// We need to use the 'io' prefix here, otherwise io.exitCode will shadow
// CommandOutput.exitCode in subclasses of CommandOutput.
-import "dart:io" as io;
-import "dart:math" as math;
-import 'dependency_graph.dart' as dgraph;
-import "browser_controller.dart";
-import "path.dart";
-import "status_file_parser.dart";
-import "test_progress.dart";
-import "test_suite.dart";
-import "utils.dart";
-import 'record_and_replay.dart';
-
-const int CRASHING_BROWSER_EXITCODE = -10;
-const int SLOW_TIMEOUT_MULTIPLIER = 4;
-
-const MESSAGE_CANNOT_OPEN_DISPLAY = 'Gtk-WARNING **: cannot open display';
-const MESSAGE_FAILED_TO_RUN_COMMAND = 'Failed to run command. return code=1';
-
-typedef void TestCaseEvent(TestCase testCase);
+import 'dart:io' as io;
+import 'dart:math' as math;
+
+import 'lib/browser_controller.dart';
+import 'lib/command.dart';
+import 'lib/dependency_graph.dart' as dgraph;
+import 'lib/path.dart';
+import 'lib/record_and_replay.dart';
+import 'lib/test_case.dart';
+import 'lib/test_information.dart';
+import 'lib/test_progress.dart';
+import 'lib/utils.dart';
+import 'test_suite.dart';
+
typedef void ExitCodeEvent(int exitCode);
typedef void EnqueueMoreWork(ProcessQueue queue);
@@ -43,1651 +39,6 @@ const List<String> EXCLUDED_ENVIRONMENT_VARIABLES =
const ['http_proxy', 'https_proxy', 'no_proxy',
'HTTP_PROXY', 'HTTPS_PROXY', 'NO_PROXY'];
-
-/** A command executed as a step in a test case. */
-class Command {
- /** A descriptive name for this command. */
- String displayName;
-
- /** Number of times this command *can* be retried */
- int get maxNumRetries => 2;
-
- /** Reproduction command */
- String get reproductionCommand => null;
-
- // We compute the Command.hashCode lazily and cache it here, since it might
- // be expensive to compute (and hashCode is called often).
- int _cachedHashCode;
-
- Command._(this.displayName);
-
- int get hashCode {
- if (_cachedHashCode == null) {
- var builder = new HashCodeBuilder();
- _buildHashCode(builder);
- _cachedHashCode = builder.value;
- }
- return _cachedHashCode;
- }
-
- operator ==(other) => identical(this, other) ||
- (runtimeType == other.runtimeType && _equal(other));
-
- void _buildHashCode(HashCodeBuilder builder) {
- builder.addJson(displayName);
- }
-
- bool _equal(Command other) =>
- hashCode == other.hashCode &&
- displayName == other.displayName;
-
- String toString() => reproductionCommand;
-
- Future<bool> get outputIsUpToDate => new Future.value(false);
-}
-
-class ProcessCommand extends Command {
- /** Path to the executable of this command. */
- String executable;
-
- /** Command line arguments to the executable. */
- List<String> arguments;
-
- /** Environment for the command */
- Map<String, String> environmentOverrides;
-
- /** Working directory for the command */
- final String workingDirectory;
-
- ProcessCommand._(String displayName, this.executable,
- this.arguments,
- [this.environmentOverrides = null,
- this.workingDirectory = null])
- : super._(displayName) {
- if (io.Platform.operatingSystem == 'windows') {
- // Windows can't handle the first command if it is a .bat file or the like
- // with the slashes going the other direction.
- // NOTE: Issue 1306
- executable = executable.replaceAll('/', '\\');
- }
- }
-
- void _buildHashCode(HashCodeBuilder builder) {
- super._buildHashCode(builder);
- builder.addJson(executable);
- builder.addJson(workingDirectory);
- builder.addJson(arguments);
- builder.addJson(environmentOverrides);
- }
-
- bool _equal(ProcessCommand other) =>
- super._equal(other) &&
- executable == other.executable &&
- deepJsonCompare(arguments, other.arguments) &&
- workingDirectory == other.workingDirectory &&
- deepJsonCompare(environmentOverrides, other.environmentOverrides);
-
- String get reproductionCommand {
- var command = ([executable]..addAll(arguments))
- .map(escapeCommandLineArgument).join(' ');
- if (workingDirectory != null) {
- command = "$command (working directory: $workingDirectory)";
- }
- return command;
- }
-
- Future<bool> get outputIsUpToDate => new Future.value(false);
-}
-
-class CompilationCommand extends ProcessCommand {
- final String _outputFile;
- final bool _neverSkipCompilation;
- final List<Uri> _bootstrapDependencies;
-
- CompilationCommand._(String displayName,
- this._outputFile,
- this._neverSkipCompilation,
- this._bootstrapDependencies,
- String executable,
- List<String> arguments,
- Map<String, String> environmentOverrides)
- : super._(displayName, executable, arguments, environmentOverrides);
-
- Future<bool> get outputIsUpToDate {
- if (_neverSkipCompilation) return new Future.value(false);
-
- Future<List<Uri>> readDepsFile(String path) {
- var file = new io.File(new Path(path).toNativePath());
- if (!file.existsSync()) {
- return new Future.value(null);
- }
- return file.readAsLines().then((List<String> lines) {
- var dependencies = new List<Uri>();
- for (var line in lines) {
- line = line.trim();
- if (line.length > 0) {
- dependencies.add(Uri.parse(line));
- }
- }
- return dependencies;
- });
- }
-
- return readDepsFile("$_outputFile.deps").then((dependencies) {
- if (dependencies != null) {
- dependencies.addAll(_bootstrapDependencies);
- var jsOutputLastModified = TestUtils.lastModifiedCache.getLastModified(
- new Uri(scheme: 'file', path: _outputFile));
- if (jsOutputLastModified != null) {
- for (var dependency in dependencies) {
- var dependencyLastModified =
- TestUtils.lastModifiedCache.getLastModified(dependency);
- if (dependencyLastModified == null ||
- dependencyLastModified.isAfter(jsOutputLastModified)) {
- return false;
- }
- }
- return true;
- }
- }
- return false;
- });
- }
-
- void _buildHashCode(HashCodeBuilder builder) {
- super._buildHashCode(builder);
- builder.addJson(_outputFile);
- builder.addJson(_neverSkipCompilation);
- builder.addJson(_bootstrapDependencies);
- }
-
- bool _equal(CompilationCommand other) =>
- super._equal(other) &&
- _outputFile == other._outputFile &&
- _neverSkipCompilation == other._neverSkipCompilation &&
- deepJsonCompare(_bootstrapDependencies, other._bootstrapDependencies);
-}
-
-/// This is just a Pair(String, Map) class with hashCode and operator ==
-class AddFlagsKey {
- final String flags;
- final Map env;
- AddFlagsKey(this.flags, this.env);
- // Just use object identity for environment map
- bool operator ==(other) =>
- other is AddFlagsKey && flags == other.flags && env == other.env;
- int get hashCode => flags.hashCode ^ env.hashCode;
-}
-
-class ContentShellCommand extends ProcessCommand {
- ContentShellCommand._(String executable,
- String htmlFile,
- List<String> options,
- List<String> dartFlags,
- Map<String, String> environmentOverrides)
- : super._("content_shell",
- executable,
- _getArguments(options, htmlFile),
- _getEnvironment(environmentOverrides, dartFlags));
-
- // Cache the modified environments in a map from the old environment and
- // the string of Dart flags to the new environment. Avoid creating new
- // environment object for each command object.
- static Map<AddFlagsKey, Map> environments =
- new Map<AddFlagsKey, Map>();
-
- static Map _getEnvironment(Map env, List<String> dartFlags) {
- var needDartFlags = dartFlags != null && dartFlags.length > 0;
- if (needDartFlags) {
- if (env == null) {
- env = const { };
- }
- var flags = dartFlags.join(' ');
- return environments.putIfAbsent(new AddFlagsKey(flags, env),
- () => new Map.from(env)
- ..addAll({'DART_FLAGS': flags, 'DART_FORWARDING_PRINT': '1'}));
- }
- return env;
- }
-
- static List<String> _getArguments(List<String> options, String htmlFile) {
- var arguments = new List.from(options);
- arguments.add(htmlFile);
- return arguments;
- }
-
- int get maxNumRetries => 3;
-}
-
-class BrowserTestCommand extends Command {
- final String browser;
- final String url;
- final Map configuration;
- final bool retry;
-
- BrowserTestCommand._(String _browser,
- this.url,
- this.configuration,
- this.retry)
- : super._(_browser), browser = _browser;
-
- void _buildHashCode(HashCodeBuilder builder) {
- super._buildHashCode(builder);
- builder.addJson(browser);
- builder.addJson(url);
- builder.add(configuration);
- builder.add(retry);
- }
-
- bool _equal(BrowserTestCommand other) =>
- super._equal(other) &&
- browser == other.browser &&
- url == other.url &&
- identical(configuration, other.configuration) &&
- retry == other.retry;
-
- String get reproductionCommand {
- var parts = [TestUtils.dartTestExecutable.toString(),
- 'tools/testing/dart/launch_browser.dart',
- browser,
- url];
- return parts.map(escapeCommandLineArgument).join(' ');
- }
-
- int get maxNumRetries => 4;
-}
-
-class BrowserHtmlTestCommand extends BrowserTestCommand {
- List<String> expectedMessages;
- BrowserHtmlTestCommand._(String browser,
- String url,
- Map configuration,
- this.expectedMessages,
- bool retry)
- : super._(browser, url, configuration, retry);
-
- void _buildHashCode(HashCodeBuilder builder) {
- super._buildHashCode(builder);
- builder.addJson(expectedMessages);
- }
-
- bool _equal(BrowserHtmlTestCommand other) =>
- super._equal(other) &&
- identical(expectedMessages, other.expectedMessages);
-}
-
-class AnalysisCommand extends ProcessCommand {
- final String flavor;
-
- AnalysisCommand._(this.flavor,
- String displayName,
- String executable,
- List<String> arguments,
- Map<String, String> environmentOverrides)
- : super._(displayName, executable, arguments, environmentOverrides);
-
- void _buildHashCode(HashCodeBuilder builder) {
- super._buildHashCode(builder);
- builder.addJson(flavor);
- }
-
- bool _equal(AnalysisCommand other) =>
- super._equal(other) &&
- flavor == other.flavor;
-}
-
-class VmCommand extends ProcessCommand {
- VmCommand._(String executable,
- List<String> arguments,
- Map<String,String> environmentOverrides)
- : super._("vm", executable, arguments, environmentOverrides);
-}
-
-class JSCommandlineCommand extends ProcessCommand {
- JSCommandlineCommand._(String displayName,
- String executable,
- List<String> arguments,
- [Map<String, String> environmentOverrides = null])
- : super._(displayName,
- executable,
- arguments,
- environmentOverrides);
-}
-
-class PubCommand extends ProcessCommand {
- final String command;
-
- PubCommand._(String pubCommand,
- String pubExecutable,
- String pubspecYamlDirectory,
- String pubCacheDirectory)
- : super._('pub_$pubCommand',
- new io.File(pubExecutable).absolute.path,
- [pubCommand],
- {'PUB_CACHE' : pubCacheDirectory},
- pubspecYamlDirectory), command = pubCommand;
-
- void _buildHashCode(HashCodeBuilder builder) {
- super._buildHashCode(builder);
- builder.addJson(command);
- }
-
- bool _equal(PubCommand other) =>
- super._equal(other) &&
- command == other.command;
-}
-
-/* [ScriptCommand]s are executed by dart code. */
-abstract class ScriptCommand extends Command {
- ScriptCommand._(String displayName) : super._(displayName);
-
- Future<ScriptCommandOutputImpl> run();
-}
-
-class CleanDirectoryCopyCommand extends ScriptCommand {
- final String _sourceDirectory;
- final String _destinationDirectory;
-
- CleanDirectoryCopyCommand._(this._sourceDirectory, this._destinationDirectory)
- : super._('dir_copy');
-
- String get reproductionCommand =>
- "Copying '$_sourceDirectory' to '$_destinationDirectory'.";
-
- Future<ScriptCommandOutputImpl> run() {
- var watch = new Stopwatch()..start();
-
- var destination = new io.Directory(_destinationDirectory);
-
- return destination.exists().then((bool exists) {
- var cleanDirectoryFuture;
- if (exists) {
- cleanDirectoryFuture = TestUtils.deleteDirectory(_destinationDirectory);
- } else {
- cleanDirectoryFuture = new Future.value(null);
- }
- return cleanDirectoryFuture.then((_) {
- return TestUtils.copyDirectory(_sourceDirectory, _destinationDirectory);
- });
- }).then((_) {
- return new ScriptCommandOutputImpl(
- this, Expectation.PASS, "", watch.elapsed);
- }).catchError((error) {
- return new ScriptCommandOutputImpl(
- this, Expectation.FAIL, "An error occured: $error.", watch.elapsed);
- });
- }
-
- void _buildHashCode(HashCodeBuilder builder) {
- super._buildHashCode(builder);
- builder.addJson(_sourceDirectory);
- builder.addJson(_destinationDirectory);
- }
-
- bool _equal(CleanDirectoryCopyCommand other) =>
- super._equal(other) &&
- _sourceDirectory == other._sourceDirectory &&
- _destinationDirectory == other._destinationDirectory;
-}
-
-class ModifyPubspecYamlCommand extends ScriptCommand {
- String _pubspecYamlFile;
- String _destinationFile;
- Map<String, Map> _dependencyOverrides;
-
- ModifyPubspecYamlCommand._(this._pubspecYamlFile,
- this._destinationFile,
- this._dependencyOverrides)
- : super._("modify_pubspec") {
- assert(_pubspecYamlFile.endsWith("pubspec.yaml"));
- assert(_destinationFile.endsWith("pubspec.yaml"));
- }
-
- String get reproductionCommand =>
- "Adding necessary dependency overrides to '$_pubspecYamlFile' "
- "(destination = $_destinationFile).";
-
- Future<ScriptCommandOutputImpl> run() {
- var watch = new Stopwatch()..start();
-
- var pubspecLockFile =
- _destinationFile.substring(0, _destinationFile.length - ".yaml".length)
- + ".lock";
-
- var file = new io.File(_pubspecYamlFile);
- var destinationFile = new io.File(_destinationFile);
- var lockfile = new io.File(pubspecLockFile);
- return file.readAsString().then((String yamlString) {
- var dependencyOverrideSection = new StringBuffer();
- if (_dependencyOverrides.isNotEmpty) {
- dependencyOverrideSection.write(
- "\n"
- "# This section was autogenerated by test.py!\n"
- "dependency_overrides:\n");
- _dependencyOverrides.forEach((String packageName, Map override) {
- dependencyOverrideSection.write(" $packageName:\n");
- override.forEach((overrideKey, overrideValue) {
- dependencyOverrideSection.write(
- " $overrideKey: $overrideValue\n");
- });
- });
- }
- var modifiedYamlString = "$yamlString\n$dependencyOverrideSection";
- return destinationFile.writeAsString(modifiedYamlString).then((_) {
- lockfile.exists().then((bool lockfileExists) {
- if (lockfileExists) {
- return lockfile.delete();
- }
- });
- });
- }).then((_) {
- return new ScriptCommandOutputImpl(
- this, Expectation.PASS, "", watch.elapsed);
- }).catchError((error) {
- return new ScriptCommandOutputImpl(
- this, Expectation.FAIL, "An error occured: $error.", watch.elapsed);
- });
- }
-
- void _buildHashCode(HashCodeBuilder builder) {
- super._buildHashCode(builder);
- builder.addJson(_pubspecYamlFile);
- builder.addJson(_destinationFile);
- builder.addJson(_dependencyOverrides);
- }
-
- bool _equal(ModifyPubspecYamlCommand other) =>
- super._equal(other) &&
- _pubspecYamlFile == other._pubspecYamlFile &&
- _destinationFile == other._destinationFile &&
- deepJsonCompare(_dependencyOverrides, other._dependencyOverrides);
-}
-
-/*
- * [MakeSymlinkCommand] makes a symbolic link to another directory.
- */
-class MakeSymlinkCommand extends ScriptCommand {
- String _link;
- String _target;
-
- MakeSymlinkCommand._(this._link, this._target) : super._('make_symlink');
-
- String get reproductionCommand =>
- "Make symbolic link '$_link' (target: $_target)'.";
-
- Future<ScriptCommandOutputImpl> run() {
- var watch = new Stopwatch()..start();
- var targetFile = new io.Directory(_target);
- return targetFile.exists().then((bool targetExists) {
- if (!targetExists) {
- throw new Exception("Target '$_target' does not exist");
- }
- var link = new io.Link(_link);
-
- return link.exists()
- .then((bool exists) { if (exists) return link.delete(); })
- .then((_) => link.create(_target));
- }).then((_) {
- return new ScriptCommandOutputImpl(
- this, Expectation.PASS, "", watch.elapsed);
- }).catchError((error) {
- return new ScriptCommandOutputImpl(
- this, Expectation.FAIL, "An error occured: $error.", watch.elapsed);
- });
- }
-
- void _buildHashCode(HashCodeBuilder builder) {
- super._buildHashCode(builder);
- builder.addJson(_link);
- builder.addJson(_target);
- }
-
- bool _equal(MakeSymlinkCommand other) =>
- super._equal(other) &&
- _link == other._link &&
- _target == other._target;
-}
-
-class CommandBuilder {
- static final CommandBuilder instance = new CommandBuilder._();
-
- bool _cleared = false;
- final _cachedCommands = new Map<Command, Command>();
-
- CommandBuilder._();
-
- void clearCommandCache() {
- _cachedCommands.clear();
- _cleared = true;
- }
-
- ContentShellCommand getContentShellCommand(String executable,
- String htmlFile,
- List<String> options,
- List<String> dartFlags,
- Map<String, String> environment) {
- ContentShellCommand command = new ContentShellCommand._(
- executable, htmlFile, options, dartFlags, environment);
- return _getUniqueCommand(command);
- }
-
- BrowserTestCommand getBrowserTestCommand(String browser,
- String url,
- Map configuration,
- bool retry) {
- var command = new BrowserTestCommand._(browser, url, configuration, retry);
- return _getUniqueCommand(command);
- }
-
- BrowserHtmlTestCommand getBrowserHtmlTestCommand(String browser,
- String url,
- Map configuration,
- List<String> expectedMessages,
- bool retry) {
- var command = new BrowserHtmlTestCommand._(
- browser, url, configuration, expectedMessages, retry);
- return _getUniqueCommand(command);
- }
-
- CompilationCommand getCompilationCommand(String displayName,
- outputFile,
- neverSkipCompilation,
- List<Uri> bootstrapDependencies,
- String executable,
- List<String> arguments,
- Map<String, String> environment) {
- var command =
- new CompilationCommand._(
- displayName, outputFile, neverSkipCompilation,
- bootstrapDependencies, executable, arguments, environment);
- return _getUniqueCommand(command);
- }
-
- AnalysisCommand getAnalysisCommand(
- String displayName, executable, arguments, environmentOverrides,
- {String flavor: 'dartanalyzer'}) {
- var command = new AnalysisCommand._(
- flavor, displayName, executable, arguments, environmentOverrides);
- return _getUniqueCommand(command);
- }
-
- VmCommand getVmCommand(String executable,
- List<String> arguments,
- Map<String, String> environmentOverrides) {
- var command = new VmCommand._(executable, arguments, environmentOverrides);
- return _getUniqueCommand(command);
- }
-
- Command getJSCommandlineCommand(String displayName, executable, arguments,
- [environment = null]) {
- var command = new JSCommandlineCommand._(displayName, executable, arguments,
- environment);
- return _getUniqueCommand(command);
- }
-
- Command getProcessCommand(String displayName, executable, arguments,
- [environment = null, workingDirectory = null]) {
- var command = new ProcessCommand._(displayName, executable, arguments,
- environment, workingDirectory);
- return _getUniqueCommand(command);
- }
-
- Command getCopyCommand(String sourceDirectory, String destinationDirectory) {
- var command = new CleanDirectoryCopyCommand._(sourceDirectory,
- destinationDirectory);
- return _getUniqueCommand(command);
- }
-
- Command getPubCommand(String pubCommand,
- String pubExecutable,
- String pubspecYamlDirectory,
- String pubCacheDirectory) {
- var command = new PubCommand._(pubCommand,
- pubExecutable,
- pubspecYamlDirectory,
- pubCacheDirectory);
- return _getUniqueCommand(command);
- }
-
- Command getMakeSymlinkCommand(String link, String target) {
- return _getUniqueCommand(new MakeSymlinkCommand._(link, target));
- }
-
- Command getModifyPubspecCommand(String pubspecYamlFile, Map depsOverrides,
- {String destinationFile: null}) {
- if (destinationFile == null) destinationFile = pubspecYamlFile;
- return _getUniqueCommand(new ModifyPubspecYamlCommand._(
- pubspecYamlFile, destinationFile, depsOverrides));
- }
-
- Command _getUniqueCommand(Command command) {
- // All Command classes implement hashCode and operator==.
- // We check if this command has already been built.
- // If so, we return the cached one. Otherwise we
- // store the one given as [command] argument.
- if (_cleared) {
- throw new Exception(
- "CommandBuilder.get[type]Command called after cache cleared");
- }
- var cachedCommand = _cachedCommands[command];
- if (cachedCommand != null) {
- return cachedCommand;
- }
- _cachedCommands[command] = command;
- return command;
- }
-}
-
-/**
- * TestCase contains all the information needed to run a test and evaluate
- * its output. Running a test involves starting a separate process, with
- * the executable and arguments given by the TestCase, and recording its
- * stdout and stderr output streams, and its exit code. TestCase only
- * contains static information about the test; actually running the test is
- * performed by [ProcessQueue] using a [RunningProcess] object.
- *
- * The output information is stored in a [CommandOutput] instance contained
- * in TestCase.commandOutputs. The last CommandOutput instance is responsible
- * for evaluating if the test has passed, failed, crashed, or timed out, and the
- * TestCase has information about what the expected result of the test should
- * be.
- *
- * The TestCase has a callback function, [completedHandler], that is run when
- * the test is completed.
- */
-class TestCase extends UniqueObject {
- // Flags set in _expectations from the optional argument info.
- static final int IS_NEGATIVE = 1 << 0;
- static final int HAS_RUNTIME_ERROR = 1 << 1;
- static final int HAS_STATIC_WARNING = 1 << 2;
- static final int IS_NEGATIVE_IF_CHECKED = 1 << 3;
- static final int HAS_COMPILE_ERROR = 1 << 4;
- static final int HAS_COMPILE_ERROR_IF_CHECKED = 1 << 5;
- static final int EXPECT_COMPILE_ERROR = 1 << 6;
- /**
- * A list of commands to execute. Most test cases have a single command.
- * Dart2js tests have two commands, one to compile the source and another
- * to execute it. Some isolate tests might even have three, if they require
- * compiling multiple sources that are run in isolation.
- */
- List<Command> commands;
- Map<Command, CommandOutput> commandOutputs = new Map<Command,CommandOutput>();
-
- Map configuration;
- String displayName;
- int _expectations = 0;
- int hash = 0;
- Set<Expectation> expectedOutcomes;
-
- TestCase(this.displayName,
- this.commands,
- this.configuration,
- this.expectedOutcomes,
- {isNegative: false,
- TestInformation info: null}) {
- if (isNegative || displayName.contains("negative_test")) {
- _expectations |= IS_NEGATIVE;
- }
- if (info != null) {
- _setExpectations(info);
- hash = info.originTestPath.relativeTo(TestUtils.dartDir)
- .toString().hashCode;
- }
- }
-
- void _setExpectations(TestInformation info) {
- // We don't want to keep the entire (large) TestInformation structure,
- // so we copy the needed bools into flags set in a single integer.
- if (info.hasRuntimeError) _expectations |= HAS_RUNTIME_ERROR;
- if (info.hasStaticWarning) _expectations |= HAS_STATIC_WARNING;
- if (info.isNegativeIfChecked) _expectations |= IS_NEGATIVE_IF_CHECKED;
- if (info.hasCompileError) _expectations |= HAS_COMPILE_ERROR;
- if (info.hasCompileErrorIfChecked) {
- _expectations |= HAS_COMPILE_ERROR_IF_CHECKED;
- }
- if (info.hasCompileError ||
- (configuration['checked'] && info.hasCompileErrorIfChecked)) {
- _expectations |= EXPECT_COMPILE_ERROR;
- }
- }
-
- bool get isNegative => _expectations & IS_NEGATIVE != 0;
- bool get hasRuntimeError => _expectations & HAS_RUNTIME_ERROR != 0;
- bool get hasStaticWarning => _expectations & HAS_STATIC_WARNING != 0;
- bool get isNegativeIfChecked => _expectations & IS_NEGATIVE_IF_CHECKED != 0;
- bool get hasCompileError => _expectations & HAS_COMPILE_ERROR != 0;
- bool get hasCompileErrorIfChecked =>
- _expectations & HAS_COMPILE_ERROR_IF_CHECKED != 0;
- bool get expectCompileError => _expectations & EXPECT_COMPILE_ERROR != 0;
-
- bool get unexpectedOutput {
- var outcome = lastCommandOutput.result(this);
- return !expectedOutcomes.any((expectation) {
- return outcome.canBeOutcomeOf(expectation);
- });
- }
-
- Expectation get result => lastCommandOutput.result(this);
-
- CommandOutput get lastCommandOutput {
- if (commandOutputs.length == 0) {
- throw new Exception("CommandOutputs is empty, maybe no command was run? ("
- "displayName: '$displayName', "
- "configurationString: '$configurationString')");
- }
- return commandOutputs[commands[commandOutputs.length - 1]];
- }
-
- Command get lastCommandExecuted {
- if (commandOutputs.length == 0) {
- throw new Exception("CommandOutputs is empty, maybe no command was run? ("
- "displayName: '$displayName', "
- "configurationString: '$configurationString')");
- }
- return commands[commandOutputs.length - 1];
- }
-
- int get timeout {
- if (expectedOutcomes.contains(Expectation.SLOW)) {
- return configuration['timeout'] * SLOW_TIMEOUT_MULTIPLIER;
- } else {
- return configuration['timeout'];
- }
- }
-
- String get configurationString {
- final compiler = configuration['compiler'];
- final runtime = configuration['runtime'];
- final mode = configuration['mode'];
- final arch = configuration['arch'];
- final checked = configuration['checked'] ? '-checked' : '';
- return "$compiler-$runtime$checked ${mode}_$arch";
- }
-
- List<String> get batchTestArguments {
- assert(commands.last is ProcessCommand);
- return (commands.last as ProcessCommand).arguments;
- }
-
- bool get isFlaky {
- if (expectedOutcomes.contains(Expectation.SKIP) ||
- expectedOutcomes.contains(Expectation.SKIP_BY_DESIGN)) {
- return false;
- }
-
- return expectedOutcomes
- .where((expectation) => !expectation.isMetaExpectation).length > 1;
- }
-
- bool get isFinished {
- return commandOutputs.length > 0 &&
- (!lastCommandOutput.successful ||
- commands.length == commandOutputs.length);
- }
-}
-
-
-/**
- * BrowserTestCase has an extra compilation command that is run in a separate
- * process, before the regular test is run as in the base class [TestCase].
- * If the compilation command fails, then the rest of the test is not run.
- */
-class BrowserTestCase extends TestCase {
-
- BrowserTestCase(displayName, commands, configuration,
- expectedOutcomes, info, isNegative, this._testingUrl)
- : super(displayName, commands, configuration,
- expectedOutcomes, isNegative: isNegative, info: info);
-
- String _testingUrl;
-
- String get testingUrl => _testingUrl;
-}
-
-class UnittestSuiteMessagesMixin {
- bool _isAsyncTest(String testOutput) {
- return testOutput.contains("unittest-suite-wait-for-done");
- }
-
- bool _isAsyncTestSuccessful(String testOutput) {
- return testOutput.contains("unittest-suite-success");
- }
-
- Expectation _negateOutcomeIfIncompleteAsyncTest(Expectation outcome,
- String testOutput) {
- // If this is an asynchronous test and the asynchronous operation didn't
- // complete successfully, it's outcome is Expectation.FAIL.
- // TODO: maybe we should introduce a AsyncIncomplete marker or so
- if (outcome == Expectation.PASS) {
- if (_isAsyncTest(testOutput) &&
- !_isAsyncTestSuccessful(testOutput)) {
- return Expectation.FAIL;
- }
- }
- return outcome;
- }
-}
-
-/**
- * CommandOutput records the output of a completed command: the process's exit
- * code, the standard output and standard error, whether the process timed out,
- * and the time the process took to run. It also contains a pointer to the
- * [TestCase] this is the output of.
- */
-abstract class CommandOutput {
- Command get command;
-
- Expectation result(TestCase testCase);
-
- bool get hasCrashed;
-
- bool get hasTimedOut;
-
- bool didFail(testcase);
-
- bool hasFailed(TestCase testCase);
-
- bool get canRunDependendCommands;
-
- bool get successful; // otherwise we might to retry running
-
- Duration get time;
-
- int get exitCode;
-
- int get pid;
-
- List<int> get stdout;
-
- List<int> get stderr;
-
- List<String> get diagnostics;
-
- bool get compilationSkipped;
-}
-
-class CommandOutputImpl extends UniqueObject implements CommandOutput {
- Command command;
- int exitCode;
-
- bool timedOut;
- List<int> stdout;
- List<int> stderr;
- Duration time;
- List<String> diagnostics;
- bool compilationSkipped;
- int pid;
-
- /**
- * A flag to indicate we have already printed a warning about ignoring the VM
- * crash, to limit the amount of output produced per test.
- */
- bool alreadyPrintedWarning = false;
-
- // TODO(kustermann): Remove testCase from this class.
- CommandOutputImpl(Command this.command,
- int this.exitCode,
- bool this.timedOut,
- List<int> this.stdout,
- List<int> this.stderr,
- Duration this.time,
- bool this.compilationSkipped,
- int this.pid) {
- diagnostics = [];
- }
-
- Expectation result(TestCase testCase) {
- if (hasCrashed) return Expectation.CRASH;
- if (hasTimedOut) return Expectation.TIMEOUT;
- return hasFailed(testCase) ? Expectation.FAIL : Expectation.PASS;
- }
-
- bool get hasCrashed {
- // The Java dartc runner and dart2js exits with code 253 in case
- // of unhandled exceptions.
- if (exitCode == 253) return true;
- if (io.Platform.operatingSystem == 'windows') {
- // The VM uses std::abort to terminate on asserts.
- // std::abort terminates with exit code 3 on Windows.
- if (exitCode == 3 || exitCode == CRASHING_BROWSER_EXITCODE) {
- return !timedOut;
- }
- // If a program receives an uncaught system exception, the program
- // terminates with the exception code as exit code.
- // The 0x3FFFFF00 mask here tries to determine if an exception indicates
- // a crash of the program.
- // System exception codes can be found in 'winnt.h', for example
- // "#define STATUS_ACCESS_VIOLATION ((DWORD) 0xC0000005)"
- return (!timedOut && (exitCode < 0) && ((0x3FFFFF00 & exitCode) == 0));
- }
- return !timedOut && ((exitCode < 0));
- }
-
- bool get hasTimedOut => timedOut;
-
- bool didFail(TestCase testCase) {
- return (exitCode != 0 && !hasCrashed);
- }
-
- bool get canRunDependendCommands {
- // FIXME(kustermann): We may need to change this
- return !hasTimedOut && exitCode == 0;
- }
-
- bool get successful {
- // FIXME(kustermann): We may need to change this
- return !hasTimedOut && exitCode == 0;
- }
-
- // Reverse result of a negative test.
- bool hasFailed(TestCase testCase) {
- return testCase.isNegative ? !didFail(testCase) : didFail(testCase);
- }
-
- Expectation _negateOutcomeIfNegativeTest(Expectation outcome,
- bool isNegative) {
- if (!isNegative) return outcome;
-
- if (outcome.canBeOutcomeOf(Expectation.FAIL)) {
- return Expectation.PASS;
- }
- return Expectation.FAIL;
- }
-}
-
-class BrowserCommandOutputImpl extends CommandOutputImpl {
- // Although tests are reported as passing, content shell sometimes exits with
- // a nonzero exitcode which makes our dartium builders extremely falky.
- // See: http://dartbug.com/15139.
- static int WHITELISTED_CONTENTSHELL_EXITCODE = -1073740022;
- static bool isWindows = io.Platform.operatingSystem == 'windows';
-
- bool _failedBecauseOfMissingXDisplay;
-
- BrowserCommandOutputImpl(
- command,
- exitCode,
- timedOut,
- stdout,
- stderr,
- time,
- compilationSkipped) :
- super(command,
- exitCode,
- timedOut,
- stdout,
- stderr,
- time,
- compilationSkipped,
- 0) {
- _failedBecauseOfMissingXDisplay = _didFailBecauseOfMissingXDisplay();
- if (_failedBecauseOfMissingXDisplay) {
- DebugLogger.warning("Warning: Test failure because of missing XDisplay");
- // If we get the X server error, or DRT crashes with a core dump, retry
- // the test.
- }
- }
-
- Expectation result(TestCase testCase) {
- // Handle crashes and timeouts first
- if (hasCrashed) return Expectation.CRASH;
- if (hasTimedOut) return Expectation.TIMEOUT;
-
- var outcome = _getOutcome();
-
- if (testCase.hasRuntimeError) {
- if (!outcome.canBeOutcomeOf(Expectation.RUNTIME_ERROR)) {
- return Expectation.MISSING_RUNTIME_ERROR;
- }
- }
- if (testCase.isNegative) {
- if (outcome.canBeOutcomeOf(Expectation.FAIL)) return Expectation.PASS;
- return Expectation.FAIL;
- }
- return outcome;
- }
-
- bool get successful => canRunDependendCommands;
-
- bool get canRunDependendCommands {
- // We cannot rely on the exit code of content_shell as a method to determine
- // if we were successful or not.
- return super.canRunDependendCommands && !didFail(null);
- }
-
- bool get hasCrashed {
- return super.hasCrashed || _rendererCrashed;
- }
-
- Expectation _getOutcome() {
- if (_failedBecauseOfMissingXDisplay) {
- return Expectation.FAIL;
- }
-
- if (_browserTestFailure) {
- return Expectation.RUNTIME_ERROR;
- }
- return Expectation.PASS;
- }
-
- bool _didFailBecauseOfMissingXDisplay() {
- // Browser case:
- // If the browser test failed, it may have been because content shell
- // and the virtual framebuffer X server didn't hook up, or it crashed with
- // a core dump. Sometimes content shell crashes after it has set the stdout
- // to PASS, so we have to do this check first.
- var stderrLines = decodeUtf8(super.stderr).split("\n");
- for (String line in stderrLines) {
- // TODO(kustermann,ricow): Issue: 7564
- // This seems to happen quite frequently, we need to figure out why.
- if (line.contains(MESSAGE_CANNOT_OPEN_DISPLAY) ||
- line.contains(MESSAGE_FAILED_TO_RUN_COMMAND)) {
- return true;
- }
- }
- return false;
- }
-
- bool get _rendererCrashed =>
- decodeUtf8(super.stdout).contains("#CRASHED - rendere");
-
- bool get _browserTestFailure {
- // Browser tests fail unless stdout contains
- // 'Content-Type: text/plain' followed by 'PASS'.
- bool hasContentType = false;
- var stdoutLines = decodeUtf8(super.stdout).split("\n");
- var containsFail = false;
- var containsPass = false;
- for (String line in stdoutLines) {
- switch (line) {
- case 'Content-Type: text/plain':
- hasContentType = true;
- break;
- case 'FAIL':
- if (hasContentType) {
- containsFail = true;
- }
- break;
- case 'PASS':
- if (hasContentType) {
- containsPass = true;
- }
- break;
- }
- }
- if (hasContentType) {
- if (containsFail && containsPass) {
- DebugLogger.warning("Test had 'FAIL' and 'PASS' in stdout. ($command)");
- }
- if (!containsFail && !containsPass) {
- DebugLogger.warning("Test had neither 'FAIL' nor 'PASS' in stdout. "
- "($command)");
- return true;
- }
- if (containsFail) {
- return true;
- }
- assert(containsPass);
- if (exitCode != 0) {
- var message = "All tests passed, but exitCode != 0. "
- "Actual exitcode: $exitCode. "
- "($command)";
- DebugLogger.warning(message);
- diagnostics.add(message);
- }
- return (!hasCrashed &&
- exitCode != 0 &&
- (!isWindows || exitCode != WHITELISTED_CONTENTSHELL_EXITCODE));
- }
- DebugLogger.warning("Couldn't find 'Content-Type: text/plain' in output. "
- "($command).");
- return true;
- }
-}
-
-class HTMLBrowserCommandOutputImpl extends BrowserCommandOutputImpl {
- HTMLBrowserCommandOutputImpl(
- command,
- exitCode,
- timedOut,
- stdout,
- stderr,
- time,
- compilationSkipped) :
- super(command,
- exitCode,
- timedOut,
- stdout,
- stderr,
- time,
- compilationSkipped);
-
- bool didFail(TestCase testCase) {
- return _getOutcome() != Expectation.PASS;
- }
-
-
- bool get _browserTestFailure {
- // We should not need to convert back and forward.
- var output = decodeUtf8(super.stdout);
- if (output.contains("FAIL")) return true;
- return !output.contains("PASS");
- }
-}
-
-class BrowserTestJsonResult {
- static const ALLOWED_TYPES =
- const ['sync_exception', 'window_onerror', 'script_onerror',
- 'window_compilationerror', 'print', 'message_received', 'dom',
- 'debug'];
-
- final Expectation outcome;
- final String htmlDom;
- final List events;
-
- BrowserTestJsonResult(this.outcome, this.htmlDom, this.events);
-
- static BrowserTestJsonResult parseFromString(String content) {
- void validate(String assertion, bool value) {
- if (!value) {
- throw "InvalidFormat sent from browser driving page: $assertion:\n\n"
- "$content";
- }
- }
-
- var events;
- try {
- events = JSON.decode(content);
- if (events != null) {
- validate("Message must be a List", events is List);
-
- Map<String, List<String>> messagesByType = {};
- ALLOWED_TYPES.forEach((type) => messagesByType[type] = <String>[]);
-
- for (var entry in events) {
- validate("An entry must be a Map", entry is Map);
-
- var type = entry['type'];
- var value = entry['value'];
- var timestamp = entry['timestamp'];
-
- validate("'type' of an entry must be a String",
- type is String);
- validate("'type' has to be in $ALLOWED_TYPES.",
- ALLOWED_TYPES.contains(type));
- validate("'timestamp' of an entry must be a number",
- timestamp is num);
-
- messagesByType[type].add(value);
- }
- validate("The message must have exactly one 'dom' entry.",
- messagesByType['dom'].length == 1);
-
- var dom = messagesByType['dom'][0];
- if (dom.endsWith('\n')) {
- dom = '$dom\n';
- }
-
- return new BrowserTestJsonResult(
- _getOutcome(messagesByType), dom, events);
- }
- } catch(error) {
- // If something goes wrong, we know the content was not in the correct
- // JSON format. So we can't parse it.
- // The caller is responsible for falling back to the old way of
- // determining if a test failed.
- }
-
- return null;
- }
-
- static Expectation _getOutcome(Map<String, List<String>> messagesByType) {
- occured(type) => messagesByType[type].length > 0;
- searchForMsg(types, message) {
- return types.any((type) => messagesByType[type].contains(message));
- }
-
- // FIXME(kustermann,ricow): I think this functionality doesn't work in
- // test_controller.js: So far I haven't seen anything being reported on
- // "window.compilationerror"
- if (occured('window_compilationerror')) {
- return Expectation.COMPILETIME_ERROR;
- }
-
- if (occured('sync_exception') ||
- occured('window_onerror') ||
- occured('script_onerror')) {
- return Expectation.RUNTIME_ERROR;
- }
-
- if (messagesByType['dom'][0].contains('FAIL')) {
- return Expectation.RUNTIME_ERROR;
- }
-
- // We search for these messages in 'print' and 'message_received' because
- // the unittest implementation posts these messages using
- // "window.postMessage()" instead of the normal "print()" them.
-
- var isAsyncTest = searchForMsg(['print', 'message_received'],
- 'unittest-suite-wait-for-done');
- var isAsyncSuccess =
- searchForMsg(['print', 'message_received'], 'unittest-suite-success') ||
- searchForMsg(['print', 'message_received'], 'unittest-suite-done');
-
- if (isAsyncTest) {
- if (isAsyncSuccess) {
- return Expectation.PASS;
- }
- return Expectation.RUNTIME_ERROR;
- }
-
- var mainStarted =
- searchForMsg(['print', 'message_received'], 'dart-calling-main');
- var mainDone =
- searchForMsg(['print', 'message_received'], 'dart-main-done');
-
- if (mainStarted && mainDone) {
- return Expectation.PASS;
- }
- return Expectation.FAIL;
- }
-}
-
-class BrowserControllerTestOutcome extends CommandOutputImpl
- with UnittestSuiteMessagesMixin {
- BrowserTestOutput _result;
- Expectation _rawOutcome;
-
- factory BrowserControllerTestOutcome(Command command,
- BrowserTestOutput result) {
- void validate(String assertion, bool value) {
- if (!value) {
- throw "InvalidFormat sent from browser driving page: $assertion:\n\n"
- "${result.lastKnownMessage}";
- }
- }
-
- String indent(String string, int numSpaces) {
- var spaces = new List.filled(numSpaces, ' ').join('');
- return string.replaceAll('\r\n', '\n')
- .split('\n')
- .map((line) => "$spaces$line")
- .join('\n');
- }
-
- String stdout = "";
- String stderr = "";
- Expectation outcome;
-
- var parsedResult =
- BrowserTestJsonResult.parseFromString(result.lastKnownMessage);
- if (parsedResult != null) {
- outcome = parsedResult.outcome;
- } else {
- // Old way of determining whether a test failed or passed.
- if (result.lastKnownMessage.contains("FAIL")) {
- outcome = Expectation.RUNTIME_ERROR;
- } else if (result.lastKnownMessage.contains("PASS")) {
- outcome = Expectation.PASS;
- } else {
- outcome = Expectation.RUNTIME_ERROR;
- }
- }
-
- if (result.didTimeout) {
- if (result.delayUntilTestStarted != null) {
- stderr = "This test timed out. The delay until the test actually "
- "started was: ${result.delayUntilTestStarted}.";
- } else {
- // TODO(ricow/kustermann) as soon as we record the state periodically,
- // we will have more information and can remove this warning.
- stderr = "This test has not notified test.py that it started running. "
- "This could be a bug in test.py! "
- "Please contact ricow/kustermann";
- }
- }
-
- if (parsedResult != null) {
- stdout = "events:\n${indent(prettifyJson(parsedResult.events), 2)}\n\n";
- } else {
- stdout = "message:\n${indent(result.lastKnownMessage, 2)}\n\n";
- }
-
- stderr =
- '$stderr\n\n'
- 'BrowserOutput while running the test (* EXPERIMENTAL *):\n'
- 'BrowserOutput.stdout:\n'
- '${indent(result.browserOutput.stdout.toString(), 2)}\n'
- 'BrowserOutput.stderr:\n'
- '${indent(result.browserOutput.stderr.toString(), 2)}\n'
- '\n';
- return new BrowserControllerTestOutcome._internal(
- command, result, outcome, encodeUtf8(stdout), encodeUtf8(stderr));
- }
-
- BrowserControllerTestOutcome._internal(
- Command command, BrowserTestOutput result, this._rawOutcome,
- List<int> stdout, List<int> stderr)
- : super(command, 0, result.didTimeout, stdout, stderr, result.duration,
- false, 0) {
- _result = result;
- }
-
- Expectation result(TestCase testCase) {
- // Handle timeouts first
- if (_result.didTimeout) return Expectation.TIMEOUT;
-
- // Multitests are handled specially
- if (testCase.hasRuntimeError) {
- if (_rawOutcome == Expectation.RUNTIME_ERROR) return Expectation.PASS;
- return Expectation.MISSING_RUNTIME_ERROR;
- }
-
- return _negateOutcomeIfNegativeTest(_rawOutcome, testCase.isNegative);
- }
-}
-
-
-class AnalysisCommandOutputImpl extends CommandOutputImpl {
- // An error line has 8 fields that look like:
- // ERROR|COMPILER|MISSING_SOURCE|file:/tmp/t.dart|15|1|24|Missing source.
- final int ERROR_LEVEL = 0;
- final int ERROR_TYPE = 1;
- final int FILENAME = 3;
- final int FORMATTED_ERROR = 7;
-
- AnalysisCommandOutputImpl(command,
- exitCode,
- timedOut,
- stdout,
- stderr,
- time,
- compilationSkipped) :
- super(command,
- exitCode,
- timedOut,
- stdout,
- stderr,
- time,
- compilationSkipped,
- 0);
-
- Expectation result(TestCase testCase) {
- // TODO(kustermann): If we run the analyzer not in batch mode, make sure
- // that command.exitCodes matches 2 (errors), 1 (warnings), 0 (no warnings,
- // no errors)
-
- // Handle crashes and timeouts first
- if (hasCrashed) return Expectation.CRASH;
- if (hasTimedOut) return Expectation.TIMEOUT;
-
- // Get the errors/warnings from the analyzer
- List<String> errors = [];
- List<String> warnings = [];
- parseAnalyzerOutput(errors, warnings);
-
- // Handle errors / missing errors
- if (testCase.expectCompileError) {
- if (errors.length > 0) {
- return Expectation.PASS;
- }
- return Expectation.MISSING_COMPILETIME_ERROR;
- }
- if (errors.length > 0) {
- return Expectation.COMPILETIME_ERROR;
- }
-
- // Handle static warnings / missing static warnings
- if (testCase.hasStaticWarning) {
- if (warnings.length > 0) {
- return Expectation.PASS;
- }
- return Expectation.MISSING_STATIC_WARNING;
- }
- if (warnings.length > 0) {
- return Expectation.STATIC_WARNING;
- }
-
- assert (errors.length == 0 && warnings.length == 0);
- assert (!testCase.hasCompileError &&
- !testCase.hasStaticWarning);
- return Expectation.PASS;
- }
-
- void parseAnalyzerOutput(List<String> outErrors, List<String> outWarnings) {
- // Parse a line delimited by the | character using \ as an escape charager
- // like: FOO|BAR|FOO\|BAR|FOO\\BAZ as 4 fields: FOO BAR FOO|BAR FOO\BAZ
- List<String> splitMachineError(String line) {
- StringBuffer field = new StringBuffer();
- List<String> result = [];
- bool escaped = false;
- for (var i = 0 ; i < line.length; i++) {
- var c = line[i];
- if (!escaped && c == '\\') {
- escaped = true;
- continue;
- }
- escaped = false;
- if (c == '|') {
- result.add(field.toString());
- field = new StringBuffer();
- continue;
- }
- field.write(c);
- }
- result.add(field.toString());
- return result;
- }
-
- for (String line in decodeUtf8(super.stderr).split("\n")) {
- if (line.length == 0) continue;
- List<String> fields = splitMachineError(line);
- // We only consider errors/warnings for files of interest.
- if (fields.length > FORMATTED_ERROR) {
- if (fields[ERROR_LEVEL] == 'ERROR') {
- outErrors.add(fields[FORMATTED_ERROR]);
- } else if (fields[ERROR_LEVEL] == 'WARNING') {
- outWarnings.add(fields[FORMATTED_ERROR]);
- }
- // OK to Skip error output that doesn't match the machine format
- }
- }
- }
-}
-
-class VmCommandOutputImpl extends CommandOutputImpl
- with UnittestSuiteMessagesMixin {
- static const DART_VM_EXITCODE_COMPILE_TIME_ERROR = 254;
- static const DART_VM_EXITCODE_UNCAUGHT_EXCEPTION = 255;
-
- VmCommandOutputImpl(Command command, int exitCode, bool timedOut,
- List<int> stdout, List<int> stderr, Duration time,
- int pid)
- : super(command, exitCode, timedOut, stdout, stderr, time, false, pid);
-
- Expectation result(TestCase testCase) {
- // Handle crashes and timeouts first
- if (hasCrashed) return Expectation.CRASH;
- if (hasTimedOut) return Expectation.TIMEOUT;
-
- // Multitests are handled specially
- if (testCase.expectCompileError) {
- if (exitCode == DART_VM_EXITCODE_COMPILE_TIME_ERROR) {
- return Expectation.PASS;
- }
- return Expectation.MISSING_COMPILETIME_ERROR;
- }
- if (testCase.hasRuntimeError) {
- // TODO(kustermann): Do we consider a "runtimeError" only an uncaught
- // exception or does any nonzero exit code fullfil this requirement?
- if (exitCode != 0) {
- return Expectation.PASS;
- }
- return Expectation.MISSING_RUNTIME_ERROR;
- }
-
- // The actual outcome depends on the exitCode
- Expectation outcome;
- if (exitCode == DART_VM_EXITCODE_COMPILE_TIME_ERROR) {
- outcome = Expectation.COMPILETIME_ERROR;
- } else if (exitCode == DART_VM_EXITCODE_UNCAUGHT_EXCEPTION) {
- outcome = Expectation.RUNTIME_ERROR;
- } else if (exitCode != 0) {
- // This is a general fail, in case we get an unknown nonzero exitcode.
- outcome = Expectation.FAIL;
- } else {
- outcome = Expectation.PASS;
- }
- outcome = _negateOutcomeIfIncompleteAsyncTest(outcome, decodeUtf8(stdout));
- return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative);
- }
-}
-
-class CompilationCommandOutputImpl extends CommandOutputImpl {
- static const DART2JS_EXITCODE_CRASH = 253;
-
- CompilationCommandOutputImpl(Command command, int exitCode, bool timedOut,
- List<int> stdout, List<int> stderr, Duration time,
- bool compilationSkipped)
- : super(command, exitCode, timedOut, stdout, stderr, time,
- compilationSkipped, 0);
-
- Expectation result(TestCase testCase) {
- // Handle general crash/timeout detection.
- if (hasCrashed) return Expectation.CRASH;
- if (hasTimedOut) return Expectation.TIMEOUT;
-
- // Handle dart2js/dart2dart specific crash detection
- if (exitCode == DART2JS_EXITCODE_CRASH ||
- exitCode == VmCommandOutputImpl.DART_VM_EXITCODE_COMPILE_TIME_ERROR ||
- exitCode == VmCommandOutputImpl.DART_VM_EXITCODE_UNCAUGHT_EXCEPTION) {
- return Expectation.CRASH;
- }
-
- // Multitests are handled specially
- if (testCase.expectCompileError) {
- // Nonzero exit code of the compiler means compilation failed
- // TODO(kustermann): Do we have a special exit code in that case???
- if (exitCode != 0) {
- return Expectation.PASS;
- }
- return Expectation.MISSING_COMPILETIME_ERROR;
- }
-
- // TODO(kustermann): This is a hack, remove it
- if (testCase.hasRuntimeError && testCase.commands.length > 1) {
- // We expected to run the test, but we got an compile time error.
- // If the compilation succeeded, we wouldn't be in here!
- assert(exitCode != 0);
- return Expectation.COMPILETIME_ERROR;
- }
-
- Expectation outcome =
- exitCode == 0 ? Expectation.PASS : Expectation.COMPILETIME_ERROR;
- return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative);
- }
-}
-
-class JsCommandlineOutputImpl extends CommandOutputImpl
- with UnittestSuiteMessagesMixin {
- JsCommandlineOutputImpl(Command command, int exitCode, bool timedOut,
- List<int> stdout, List<int> stderr, Duration time)
- : super(command, exitCode, timedOut, stdout, stderr, time, false, 0);
-
- Expectation result(TestCase testCase) {
- // Handle crashes and timeouts first
- if (hasCrashed) return Expectation.CRASH;
- if (hasTimedOut) return Expectation.TIMEOUT;
-
- if (testCase.hasRuntimeError) {
- if (exitCode != 0) return Expectation.PASS;
- return Expectation.MISSING_RUNTIME_ERROR;
- }
-
- var outcome = exitCode == 0 ? Expectation.PASS : Expectation.RUNTIME_ERROR;
- outcome = _negateOutcomeIfIncompleteAsyncTest(outcome, decodeUtf8(stdout));
- return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative);
- }
-}
-
-class PubCommandOutputImpl extends CommandOutputImpl {
- PubCommandOutputImpl(PubCommand command, int exitCode, bool timedOut,
- List<int> stdout, List<int> stderr, Duration time)
- : super(command, exitCode, timedOut, stdout, stderr, time, false, 0);
-
- Expectation result(TestCase testCase) {
- // Handle crashes and timeouts first
- if (hasCrashed) return Expectation.CRASH;
- if (hasTimedOut) return Expectation.TIMEOUT;
-
- if (exitCode == 0) {
- return Expectation.PASS;
- } else if ((command as PubCommand).command == 'get') {
- return Expectation.PUB_GET_ERROR;
- } else {
- return Expectation.FAIL;
- }
- }
-}
-
-class ScriptCommandOutputImpl extends CommandOutputImpl {
- final Expectation _result;
-
- ScriptCommandOutputImpl(ScriptCommand command, this._result,
- String scriptExecutionInformation, Duration time)
- : super(command, 0, false, [], [], time, false, 0) {
- var lines = scriptExecutionInformation.split("\n");
- diagnostics.addAll(lines);
- }
-
- Expectation result(TestCase testCase) => _result;
-
- bool get canRunDependendCommands => _result == Expectation.PASS;
-
- bool get successful => _result == Expectation.PASS;
-
-}
-
-CommandOutput createCommandOutput(Command command,
- int exitCode,
- bool timedOut,
- List<int> stdout,
- List<int> stderr,
- Duration time,
- bool compilationSkipped,
- [int pid = 0]) {
- if (command is ContentShellCommand) {
- return new BrowserCommandOutputImpl(
- command, exitCode, timedOut, stdout, stderr,
- time, compilationSkipped);
- } else if (command is BrowserTestCommand) {
- return new HTMLBrowserCommandOutputImpl(
- command, exitCode, timedOut, stdout, stderr,
- time, compilationSkipped);
- } else if (command is AnalysisCommand) {
- return new AnalysisCommandOutputImpl(
- command, exitCode, timedOut, stdout, stderr,
- time, compilationSkipped);
- } else if (command is VmCommand) {
- return new VmCommandOutputImpl(
- command, exitCode, timedOut, stdout, stderr, time, pid);
- } else if (command is CompilationCommand) {
- return new CompilationCommandOutputImpl(
- command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
- } else if (command is JSCommandlineCommand) {
- return new JsCommandlineOutputImpl(
- command, exitCode, timedOut, stdout, stderr, time);
- } else if (command is PubCommand) {
- return new PubCommandOutputImpl(
- command, exitCode, timedOut, stdout, stderr, time);
- }
-
- return new CommandOutputImpl(
- command, exitCode, timedOut, stdout, stderr,
- time, compilationSkipped, pid);
-}
-
-
/**
* An OutputLog records the output from a test, but truncates it if
* it is longer than MAX_HEAD characters, and just keeps the head and
@@ -2620,50 +971,6 @@ class ReplayingCommandExecutor implements CommandExecutor {
}
}
-bool shouldRetryCommand(CommandOutput output) {
- var command = output.command;
- // We rerun tests on Safari because 6.2 and 7.1 are flaky. Issue 21434.
- if (command is BrowserTestCommand &&
- command.retry &&
- command.browser == 'safari' &&
- output is BrowserControllerTestOutcome &&
- output._rawOutcome != Expectation.PASS) {
- return true;
- }
-
- if (!output.successful) {
- List<String> stdout, stderr;
-
- decodeOutput() {
- if (stdout == null && stderr == null) {
- stdout = decodeUtf8(output.stderr).split("\n");
- stderr = decodeUtf8(output.stderr).split("\n");
- }
- }
-
- if (io.Platform.operatingSystem == 'linux') {
- decodeOutput();
- // No matter which command we ran: If we get failures due to the
- // "xvfb-run" issue 7564, try re-running the test.
- bool containsFailureMsg(String line) {
- return line.contains(MESSAGE_CANNOT_OPEN_DISPLAY) ||
- line.contains(MESSAGE_FAILED_TO_RUN_COMMAND);
- }
- if (stdout.any(containsFailureMsg) || stderr.any(containsFailureMsg)) {
- return true;
- }
- }
-
- // We currently rerun dartium tests, see issue 14074.
- if (command is BrowserTestCommand &&
- command.retry &&
- command.browser == 'dartium') {
- return true;
- }
- }
- return false;
-}
-
/*
* [TestCaseCompleter] will listen for
* NodeState.Processing -> NodeState.{Successful,Failed} state changes and
« no previous file with comments | « tools/testing/dart/test_progress.dart ('k') | tools/testing/dart/test_suite.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698