summaryrefslogtreecommitdiffstats
path: root/WebKitTools/Scripts/webkitpy/layout_tests/layout_package
diff options
context:
space:
mode:
authorIain Merrick <husky@google.com>2010-09-13 16:35:48 +0100
committerIain Merrick <husky@google.com>2010-09-16 12:10:42 +0100
commit5abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306 (patch)
treeddce1aa5e3b6967a69691892e500897558ff8ab6 /WebKitTools/Scripts/webkitpy/layout_tests/layout_package
parent12bec63ec71e46baba27f0bd9bd9d8067683690a (diff)
downloadexternal_webkit-5abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306.zip
external_webkit-5abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306.tar.gz
external_webkit-5abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306.tar.bz2
Merge WebKit at r67178 : Initial merge by git.
Change-Id: I57e01163b6866cb029cdadf405a0394a3918bc18
Diffstat (limited to 'WebKitTools/Scripts/webkitpy/layout_tests/layout_package')
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py42
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread_unittest.py49
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py50
3 files changed, 125 insertions, 16 deletions
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py
index ec33086..9b963ca 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py
@@ -47,6 +47,7 @@ import sys
import thread
import threading
import time
+import traceback
import test_failures
@@ -54,6 +55,23 @@ _log = logging.getLogger("webkitpy.layout_tests.layout_package."
"dump_render_tree_thread")
+def find_thread_stack(id):
+ """Returns a stack object that can be used to dump a stack trace for
+ the given thread id (or None if the id is not found)."""
+ for thread_id, stack in sys._current_frames().items():
+ if thread_id == id:
+ return stack
+ return None
+
+
+def log_stack(stack):
+ """Log a stack trace to log.error()."""
+ for filename, lineno, name, line in traceback.extract_stack(stack):
+ _log.error('File: "%s", line %d, in %s' % (filename, lineno, name))
+ if line:
+ _log.error(' %s' % line.strip())
+
+
def _process_output(port, test_info, test_types, test_args, configuration,
output_dir, crash, timeout, test_run_time, actual_checksum,
output, error):
@@ -167,6 +185,7 @@ class SingleTestThread(threading.Thread):
self._test_args = test_args
self._configuration = configuration
self._output_dir = output_dir
+ self._driver = None
def run(self):
self._covered_run()
@@ -175,18 +194,19 @@ class SingleTestThread(threading.Thread):
# FIXME: this is a separate routine to work around a bug
# in coverage: see http://bitbucket.org/ned/coveragepy/issue/85.
test_info = self._test_info
- driver = self._port.create_driver(self._image_path, self._shell_args)
- driver.start()
+ self._driver = self._port.create_driver(self._image_path,
+ self._shell_args)
+ self._driver.start()
start = time.time()
crash, timeout, actual_checksum, output, error = \
- driver.run_test(test_info.uri.strip(), test_info.timeout,
- test_info.image_hash())
+ self._driver.run_test(test_info.uri.strip(), test_info.timeout,
+ test_info.image_hash())
end = time.time()
self._test_result = _process_output(self._port,
test_info, self._test_types, self._test_args,
self._configuration, self._output_dir, crash, timeout, end - start,
actual_checksum, output, error)
- driver.stop()
+ self._driver.stop()
def get_test_result(self):
return self._test_result
@@ -312,9 +332,7 @@ class TestShellThread(WatchableThread):
# Save the exception for our caller to see.
self._exception_info = sys.exc_info()
self._stop_time = time.time()
- # Re-raise it and die.
- _log.error('%s dying, exception raised: %s' % (self.getName(),
- self._exception_info))
+ _log.error('%s dying, exception raised' % self.getName())
self._stop_time = time.time()
@@ -426,7 +444,7 @@ class TestShellThread(WatchableThread):
worker.start()
thread_timeout = _milliseconds_to_seconds(
- _pad_timeout(test_info.timeout))
+ _pad_timeout(int(test_info.timeout)))
thread._next_timeout = time.time() + thread_timeout
worker.join(thread_timeout)
if worker.isAlive():
@@ -439,11 +457,13 @@ class TestShellThread(WatchableThread):
# that tradeoff in order to avoid losing the rest of this
# thread's results.
_log.error('Test thread hung: killing all DumpRenderTrees')
- worker._driver.stop()
+ if worker._driver:
+ worker._driver.stop()
try:
result = worker.get_test_result()
except AttributeError, e:
+ # This gets raised if the worker thread has already exited.
failures = []
_log.error('Cannot get results of test: %s' %
test_info.filename)
@@ -476,7 +496,7 @@ class TestShellThread(WatchableThread):
start = time.time()
thread_timeout = _milliseconds_to_seconds(
- _pad_timeout(test_info.timeout))
+ _pad_timeout(int(test_info.timeout)))
self._next_timeout = start + thread_timeout
crash, timeout, actual_checksum, output, error = \
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread_unittest.py
new file mode 100644
index 0000000..63f86d9
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread_unittest.py
@@ -0,0 +1,49 @@
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+""""Tests code paths not covered by the regular unit tests."""
+
+import sys
+import unittest
+
+import dump_render_tree_thread
+
+
+class Test(unittest.TestCase):
+ def test_find_thread_stack_found(self):
+ id, stack = sys._current_frames().items()[0]
+ found_stack = dump_render_tree_thread.find_thread_stack(id)
+ self.assertNotEqual(found_stack, None)
+
+ def test_find_thread_stack_not_found(self):
+ found_stack = dump_render_tree_thread.find_thread_stack(0)
+ self.assertEqual(found_stack, None)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py
index 15eceee..765b4d8 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py
@@ -37,6 +37,8 @@ import time
import urllib2
import xml.dom.minidom
+from webkitpy.layout_tests.layout_package import test_results_uploader
+
import webkitpy.thirdparty.simplejson as simplejson
# A JSON results generator for generic tests.
@@ -85,13 +87,14 @@ class JSONResultsGeneratorBase(object):
INCREMENTAL_RESULTS_FILENAME = "incremental_results.json"
URL_FOR_TEST_LIST_JSON = \
- "http://%s/testfile?builder=%s&name=%s&testlistjson=1"
+ "http://%s/testfile?builder=%s&name=%s&testlistjson=1&testtype=%s"
def __init__(self, builder_name, build_name, build_number,
results_file_base_path, builder_base_url,
test_results_map, svn_repositories=None,
generate_incremental_results=False,
- test_results_server=None):
+ test_results_server=None,
+ test_type=""):
"""Modifies the results.json file. Grabs it off the archive directory
if it is not found locally.
@@ -129,6 +132,7 @@ class JSONResultsGeneratorBase(object):
self._svn_repositories = {}
self._test_results_server = test_results_server
+ self._test_type = test_type
self._json = None
self._archived_results = None
@@ -287,7 +291,8 @@ class JSONResultsGeneratorBase(object):
results_file_url = (self.URL_FOR_TEST_LIST_JSON %
(urllib2.quote(self._test_results_server),
urllib2.quote(self._builder_name),
- self.RESULTS_FILENAME))
+ self.RESULTS_FILENAME,
+ urllib2.quote(self._test_type)))
else:
# Check if we have the archived JSON file on the buildbot
# server.
@@ -518,9 +523,33 @@ class JSONResultsGenerator(JSONResultsGeneratorBase):
# The flag is for backward compatibility.
output_json_in_init = True
+ def _upload_json_files(self):
+ if not self._test_results_server or not self._test_type:
+ return
+
+ _log.info("Uploading JSON files for %s to the server: %s",
+ self._builder_name, self._test_results_server)
+ attrs = [("builder", self._builder_name), ("testtype", self._test_type)]
+ json_files = [self.INCREMENTAL_RESULTS_FILENAME]
+
+ files = [(file, os.path.join(self._results_directory, file))
+ for file in json_files]
+ uploader = test_results_uploader.TestResultsUploader(
+ self._test_results_server)
+ try:
+ # Set uploading timeout in case appengine server is having problem.
+ # 120 seconds are more than enough to upload test results.
+ uploader.upload(attrs, files, 120)
+ except Exception, err:
+ _log.error("Upload failed: %s" % err)
+ return
+
+ _log.info("JSON files uploaded.")
+
def __init__(self, port, builder_name, build_name, build_number,
results_file_base_path, builder_base_url,
- test_timings, failures, passed_tests, skipped_tests, all_tests):
+ test_timings, failures, passed_tests, skipped_tests, all_tests,
+ test_results_server=None, test_type=None):
"""Generates a JSON results file.
Args
@@ -536,8 +565,13 @@ class JSONResultsGenerator(JSONResultsGeneratorBase):
skipped_tests: A set containing all the skipped tests.
all_tests: List of all the tests that were run. This should not
include skipped tests.
+ test_results_server: server that hosts test results json.
+ test_type: the test type.
"""
+ self._test_type = test_type
+ self._results_directory = results_file_base_path
+
# Create a map of (name, TestResult).
test_results_map = dict()
get = test_results_map.get
@@ -557,10 +591,16 @@ class JSONResultsGenerator(JSONResultsGeneratorBase):
if test not in test_results_map:
test_results_map[test] = TestResult(test)
+ # Generate the JSON with incremental flag enabled.
+ # (This should also output the full result for now.)
super(JSONResultsGenerator, self).__init__(
builder_name, build_name, build_number,
results_file_base_path, builder_base_url, test_results_map,
- svn_repositories=port.test_repository_paths())
+ svn_repositories=port.test_repository_paths(),
+ generate_incremental_results=True,
+ test_results_server=test_results_server,
+ test_type=test_type)
if self.__class__.output_json_in_init:
self.generate_json_output()
+ self._upload_json_files()