summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xtools/valgrind/chrome_tests.py12
-rwxr-xr-xtools/valgrind/chrome_tests.sh2
-rwxr-xr-xtools/valgrind/common.py112
-rwxr-xr-xtools/valgrind/valgrind_test.py3
4 files changed, 116 insertions, 13 deletions
diff --git a/tools/valgrind/chrome_tests.py b/tools/valgrind/chrome_tests.py
index 86d4280..7d9fc1a 100755
--- a/tools/valgrind/chrome_tests.py
+++ b/tools/valgrind/chrome_tests.py
@@ -5,11 +5,7 @@
# chrome_tests.py
-''' Runs various chrome tests through valgrind_test.py.
-
-This file is a copy of ../purify/chrome_tests.py. Eventually, it would be nice
-to merge these two files.
-'''
+''' Runs various chrome tests through valgrind_test.py.'''
import glob
import logging
@@ -30,7 +26,6 @@ import google.path_utils
# package. http://crbug.com/6164
import layout_package.path_utils
-import common
import valgrind_test
class TestNotFound(Exception): pass
@@ -70,9 +65,6 @@ def FindDirContainingNewestFile(dirs, file):
return newest_dir
class ChromeTests:
- '''This class is derived from the chrome_tests.py file in ../purify/.
- '''
-
def __init__(self, options, args, test):
# The known list of tests.
# Recognise the original abbreviations as well as full executable names.
@@ -336,7 +328,7 @@ class ChromeTests:
# runs a slice of the layout tests of size chunk_size that increments with
# each run. Since tests can be added and removed from the layout tests at
# any time, this is not going to give exact coverage, but it will allow us
- # to continuously run small slices of the layout tests under purify rather
+ # to continuously run small slices of the layout tests under valgrind rather
# than having to run all of them in one shot.
chunk_size = self._options.num_tests
if (chunk_size == 0):
diff --git a/tools/valgrind/chrome_tests.sh b/tools/valgrind/chrome_tests.sh
index 6fe4bc5..1d75e7f 100755
--- a/tools/valgrind/chrome_tests.sh
+++ b/tools/valgrind/chrome_tests.sh
@@ -29,4 +29,4 @@ echo "Using ${CHROME_VALGRIND_BIN}/valgrind"
PATH="${CHROME_VALGRIND_BIN}:$PATH"
export THISDIR=`dirname $0`
-PYTHONPATH=$THISDIR/../../webkit/tools/layout_tests/:$THISDIR/../purify:$THISDIR/../python "$THISDIR/chrome_tests.py" "$@"
+PYTHONPATH=$THISDIR/../../webkit/tools/layout_tests/:$THISDIR/../python "$THISDIR/chrome_tests.py" "$@"
diff --git a/tools/valgrind/common.py b/tools/valgrind/common.py
new file mode 100755
index 0000000..d273bf7
--- /dev/null
+++ b/tools/valgrind/common.py
@@ -0,0 +1,112 @@
+# Copyright (c) 2009 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import signal
+import subprocess
+import sys
+import time
+
+
+class TimeoutError(Exception):
+ pass
+
+
+def _print_line(line, flush=True):
+ # Printing to a text file (including stdout) on Windows always winds up
+ # using \r\n automatically. On buildbot, this winds up being read by a master
+ # running on Linux, so we manually convert crlf to '\n'
+ print line.rstrip() + '\n',
+ if flush:
+ sys.stdout.flush()
+
+
+def RunSubprocess(proc, timeout=0, detach=False):
+ """ Runs a subprocess, until it finishes or |timeout| is exceeded and the
+ process is killed with taskkill. A |timeout| <= 0 means no timeout.
+
+ Args:
+ proc: list of process components (exe + args)
+ timeout: how long to wait before killing, <= 0 means wait forever
+ detach: Whether to pass the DETACHED_PROCESS argument to CreateProcess
+ on Windows. This is used by Purify subprocesses on buildbot which
+ seem to get confused by the parent console that buildbot sets up.
+ """
+
+ logging.info("running %s, timeout %d sec" % (" ".join(proc), timeout))
+ if detach:
+ # see MSDN docs for "Process Creation Flags"
+ DETACHED_PROCESS = 0x8
+ p = subprocess.Popen(proc, creationflags=DETACHED_PROCESS)
+ else:
+ # For non-detached processes, manually read and print out stdout and stderr.
+ # By default, the subprocess is supposed to inherit these from its parent,
+ # however when run under buildbot, it seems unable to read data from a
+ # grandchild process, so we have to read the child and print the data as if
+ # it came from us for buildbot to read it. We're not sure why this is
+ # necessary.
+ # TODO(erikkay): should we buffer stderr and stdout separately?
+ p = subprocess.Popen(proc, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+ logging.info("started subprocess")
+
+ # How long to wait (in seconds) before printing progress log messages.
+ progress_delay = 300
+ progress_delay_time = time.time() + progress_delay
+ did_timeout = False
+ if timeout > 0:
+ wait_until = time.time() + timeout
+ while p.poll() is None and not did_timeout:
+ if not detach:
+ line = p.stdout.readline()
+ while line and not did_timeout:
+ _print_line(line)
+ line = p.stdout.readline()
+ if timeout > 0:
+ did_timeout = time.time() > wait_until
+ else:
+ # When we detach, blocking on reading stdout doesn't work, so we sleep
+ # a short time and poll.
+ time.sleep(0.5)
+ if time.time() >= progress_delay_time:
+ # Force output on a periodic basis to avoid getting killed off by the
+ # buildbot.
+ # TODO(erikkay): I'd prefer a less obtrusive 'print ".",' with a flush
+ # but because of how we're doing subprocesses, this doesn't appear to
+ # work reliably.
+ logging.info("%s still running..." % os.path.basename(proc[0]))
+ progress_delay_time = time.time() + progress_delay
+ if timeout > 0:
+ did_timeout = time.time() > wait_until
+
+ if did_timeout:
+ logging.info("process timed out")
+ else:
+ logging.info("process ended, did not time out")
+
+ if did_timeout:
+ if sys.platform == "win32":
+ subprocess.call(["taskkill", "/T", "/F", "/PID", str(p.pid)])
+ else:
+ # Does this kill all children, too?
+ os.kill(p.pid, signal.SIGINT)
+ logging.error("KILLED %d" % p.pid)
+ # Give the process a chance to actually die before continuing
+ # so that cleanup can happen safely.
+ time.sleep(1.0)
+ logging.error("TIMEOUT waiting for %s" % proc[0])
+ raise TimeoutError(proc[0])
+ elif not detach:
+ for line in p.stdout.readlines():
+ _print_line(line, False)
+ if sys.platform != 'darwin': # stdout flush fails on Mac
+ logging.info("flushing stdout")
+ p.stdout.flush()
+
+ logging.info("collecting result code")
+ result = p.poll()
+ if result:
+ logging.error("%s exited with non-zero result code %d" % (proc[0], result))
+ return result
diff --git a/tools/valgrind/valgrind_test.py b/tools/valgrind/valgrind_test.py
index 1c331ab..ecc504d 100755
--- a/tools/valgrind/valgrind_test.py
+++ b/tools/valgrind/valgrind_test.py
@@ -263,8 +263,7 @@ class ValgrindTool(object):
common.RunSubprocess(proc, self._timeout)
# Always return true, even if running the subprocess failed. We depend on
- # Analyze to determine if the run was valid. (This behaviour copied from
- # the purify_test.py script.)
+ # Analyze to determine if the run was valid.
return True
def Analyze(self):