Version 1.2.0-dev.2.4
svn merge -c 32111 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 32117 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
R=dgrove@google.com
Review URL: https://codereview.chromium.org//150433003
git-svn-id: http://dart.googlecode.com/svn/trunk@32164 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/tools/VERSION b/tools/VERSION
index d31a8d9..8e5dd3b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
MINOR 2
PATCH 0
PRERELEASE 2
-PRERELEASE_PATCH 3
+PRERELEASE_PATCH 4
diff --git a/tools/archive_crash.py b/tools/archive_crash.py
new file mode 100755
index 0000000..ce2fe02
--- /dev/null
+++ b/tools/archive_crash.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2014, 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.
+#
+
+# A script that copies a core file and binary to GCS
+# We expect the dumps to be located in /tmp/coredump_PID directory
+# After we copy out the core files we delete the dumps localy
+
+import os
+import shutil
+import sys
+import subprocess
+import tarfile
+import utils
+import uuid
+
+GCS_FOLDER = 'dart-crashes'
+
+def CreateTarball(dir, tarname):
+ print 'Creating tar file: %s' % (tarname)
+ tar = tarfile.open(tarname, mode='w:gz')
+ tar.add(dir)
+ tar.close()
+
+def CopyToGCS(filename):
+ gs_location = 'gs://%s/%s/' % (GCS_FOLDER, uuid.uuid4())
+ cmd = ['gsutil', 'cp', filename, gs_location]
+ print 'Running command: %s' % (cmd)
+ subprocess.check_call(cmd)
+ archived_filename = '%s%s' % (gs_location, filename.split('/').pop())
+ print 'Dump now available in %s' % (archived_filename)
+
+def Main():
+ if utils.GuessOS() != 'linux':
+ print 'Currently only archiving crash dumps on linux'
+ return 0
+ print 'Looking for crash dumps'
+ num_dumps = 0
+ for v in os.listdir('/tmp'):
+ if v.startswith('coredump'):
+ fullpath = '/tmp/%s' % (v)
+ if os.path.isdir(fullpath):
+ num_dumps += 1
+ tarname = '%s.tar.gz' % fullpath
+ CreateTarball(fullpath, tarname)
+ CopyToGCS(tarname)
+ os.unlink(tarname)
+ shutil.rmtree(fullpath)
+ print 'Found %s core dumps' % (num_dumps)
+
+if __name__ == '__main__':
+ sys.exit(Main())
diff --git a/tools/test.dart b/tools/test.dart
index 278dc74..27d0370 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -261,6 +261,10 @@
if (firstConf['write_test_outcome_log']) {
eventListener.add(new TestOutcomeLogWriter());
}
+ if (firstConf['copy_coredumps']) {
+ eventListener.add(new UnexpectedCrashDumpArchiver());
+ }
+
eventListener.add(new ExitCodeSetter());
void startProcessQueue() {
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index fa28151..3274d57 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -335,6 +335,15 @@
'bool'
),
new _TestOptionSpecification(
+ 'copy_coredumps',
+ 'If we see a crash that we did not expect, copy the core dumps. '
+ 'to /tmp',
+ ['--copy-coredumps'],
+ [],
+ false,
+ 'bool'
+ ),
+ new _TestOptionSpecification(
'local_ip',
'IP address the http servers should listen on.'
'This address is also used for browsers to connect.',
@@ -616,6 +625,7 @@
print("Cannot have both --use-repository-packages and "
"--use-public-packages");
}
+
return isValid;
}
diff --git a/tools/testing/dart/test_progress.dart b/tools/testing/dart/test_progress.dart
index cf4a808..a2056ab 100644
--- a/tools/testing/dart/test_progress.dart
+++ b/tools/testing/dart/test_progress.dart
@@ -276,6 +276,32 @@
}
}
+
+class UnexpectedCrashDumpArchiver extends EventListener {
+ void done(TestCase test) {
+ if (test.unexpectedOutput && test.result == Expectation.CRASH) {
+ var name = "core.dart.${test.lastCommandOutput.pid}";
+ var file = new File(name);
+ if (file.existsSync()) {
+ // Find the binary - we assume this is the first part of the command
+ var binName = test.lastCommandExecuted.toString().split(' ').first;
+ var binFile = new File(binName);
+ var binBaseName = new Path(binName).filename;
+ if (binFile.existsSync()) {
+ var tmpPath = new Path(Directory.systemTemp.path);
+ var dir = new Path(TestUtils.mkdirRecursive(tmpPath,
+ new Path('coredump_${test.lastCommandOutput.pid}')).path);
+ TestUtils.copyFile(new Path(name), dir.append(name));
+ TestUtils.copyFile(new Path(binName), dir.append(binBaseName));
+ print("\nCopied core dump and binary for unexpected crash to: "
+ "$dir");
+ }
+ }
+ }
+ }
+}
+
+
class SummaryPrinter extends EventListener {
void allTestsKnown() {
if (SummaryReport.total > 0) {
@@ -284,6 +310,7 @@
}
}
+
class TimingPrinter extends EventListener {
final _command2testCases = new Map<Command, List<TestCase>>();
final _commandOutputs = new Set<CommandOutput>();
@@ -456,6 +483,7 @@
}
}
+
class TestFailurePrinter extends EventListener {
bool _printSummary;
var _formatter;
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 9765d463..33382c3 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -744,6 +744,15 @@
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;
@@ -871,6 +880,7 @@
Duration time;
List<String> diagnostics;
bool compilationSkipped;
+ int pid;
/**
* A flag to indicate we have already printed a warning about ignoring the VM
@@ -885,7 +895,8 @@
List<int> this.stdout,
List<int> this.stderr,
Duration this.time,
- bool this.compilationSkipped) {
+ bool this.compilationSkipped,
+ int this.pid) {
diagnostics = [];
}
@@ -971,7 +982,8 @@
stdout,
stderr,
time,
- compilationSkipped) {
+ compilationSkipped,
+ 0) {
_failedBecauseOfMissingXDisplay = _didFailBecauseOfMissingXDisplay();
if (_failedBecauseOfMissingXDisplay) {
DebugLogger.warning("Warning: Test failure because of missing XDisplay");
@@ -1321,7 +1333,7 @@
Command command, BrowserTestOutput result, this._rawOutcome,
List<int> stdout, List<int> stderr)
: super(command, 0, result.didTimeout, stdout, stderr, result.duration,
- false) {
+ false, 0) {
_result = result;
}
@@ -1363,7 +1375,8 @@
stdout,
stderr,
time,
- compilationSkipped);
+ compilationSkipped,
+ 0);
Expectation result(TestCase testCase) {
// TODO(kustermann): If we run the analyzer not in batch mode, make sure
@@ -1456,8 +1469,9 @@
static const DART_VM_EXITCODE_UNCAUGHT_EXCEPTION = 255;
VmCommandOutputImpl(Command command, int exitCode, bool timedOut,
- List<int> stdout, List<int> stderr, Duration time)
- : super(command, exitCode, timedOut, stdout, stderr, time, false);
+ 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
@@ -1507,7 +1521,7 @@
List<int> stdout, List<int> stderr, Duration time,
bool compilationSkipped)
: super(command, exitCode, timedOut, stdout, stderr, time,
- compilationSkipped);
+ compilationSkipped, 0);
Expectation result(TestCase testCase) {
// Handle general crash/timeout detection.
@@ -1551,7 +1565,7 @@
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);
+ : super(command, exitCode, timedOut, stdout, stderr, time, false, 0);
Expectation result(TestCase testCase) {
// Handle crashes and timeouts first
@@ -1572,7 +1586,7 @@
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);
+ : super(command, exitCode, timedOut, stdout, stderr, time, false, 0);
Expectation result(TestCase testCase) {
// Handle crashes and timeouts first
@@ -1594,7 +1608,7 @@
ScriptCommandOutputImpl(ScriptCommand command, this._result,
String scriptExecutionInformation, Duration time)
- : super(command, 0, false, [], [], time, false) {
+ : super(command, 0, false, [], [], time, false, 0) {
var lines = scriptExecutionInformation.split("\n");
diagnostics.addAll(lines);
}
@@ -1613,7 +1627,8 @@
List<int> stdout,
List<int> stderr,
Duration time,
- bool compilationSkipped) {
+ bool compilationSkipped,
+ [int pid = 0]) {
if (command is ContentShellCommand) {
return new BrowserCommandOutputImpl(
command, exitCode, timedOut, stdout, stderr,
@@ -1628,7 +1643,7 @@
time, compilationSkipped);
} else if (command is VmCommand) {
return new VmCommandOutputImpl(
- command, exitCode, timedOut, stdout, stderr, time);
+ command, exitCode, timedOut, stdout, stderr, time, pid);
} else if (command is CompilationCommand) {
return new CompilationCommandOutputImpl(
command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
@@ -1642,7 +1657,7 @@
return new CommandOutputImpl(
command, exitCode, timedOut, stdout, stderr,
- time, compilationSkipped);
+ time, compilationSkipped, pid);
}
@@ -1662,6 +1677,7 @@
bool timedOut = false;
DateTime startTime;
Timer timeoutTimer;
+ int pid;
List<int> stdout = <int>[];
List<int> stderr = <int>[];
bool compilationSkipped = false;
@@ -1699,6 +1715,7 @@
bool stdoutDone = false;
bool stderrDone = false;
+ pid = process.pid;
// This timer is used to close stdio to the subprocess once we got
// the exitCode. Sometimes descendants of the subprocess keep stdio
@@ -1709,7 +1726,6 @@
if (!stdoutDone) {
stdoutCompleter.complete();
stdoutDone = true;
-
if (stderrDone && watchdogTimer != null) {
watchdogTimer.cancel();
}
@@ -1789,7 +1805,8 @@
stdout,
stderr,
new DateTime.now().difference(startTime),
- compilationSkipped);
+ compilationSkipped,
+ pid);
return commandOutput;
}