diff options
Diffstat (limited to 'src/3rdparty/v8/tools/testrunner/server/work_handler.py')
-rw-r--r-- | src/3rdparty/v8/tools/testrunner/server/work_handler.py | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/src/3rdparty/v8/tools/testrunner/server/work_handler.py b/src/3rdparty/v8/tools/testrunner/server/work_handler.py new file mode 100644 index 0000000..6bf7d43 --- /dev/null +++ b/src/3rdparty/v8/tools/testrunner/server/work_handler.py @@ -0,0 +1,150 @@ +# Copyright 2012 the V8 project authors. 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. + + +import os +import SocketServer +import stat +import subprocess +import threading + +from . import compression +from . import constants +from . import signatures +from ..network import endpoint +from ..objects import workpacket + + +class WorkHandler(SocketServer.BaseRequestHandler): + + def handle(self): + rec = compression.Receiver(self.request) + while not rec.IsDone(): + data = rec.Current() + with self.server.job_lock: + self._WorkOnWorkPacket(data) + rec.Advance() + + def _WorkOnWorkPacket(self, data): + server_root = self.server.daemon.root + v8_root = os.path.join(server_root, "v8") + os.chdir(v8_root) + packet = workpacket.WorkPacket.Unpack(data) + self.ctx = packet.context + self.ctx.shell_dir = os.path.join("out", + "%s.%s" % (self.ctx.arch, self.ctx.mode)) + if not os.path.isdir(self.ctx.shell_dir): + os.makedirs(self.ctx.shell_dir) + for binary in packet.binaries: + if not self._UnpackBinary(binary, packet.pubkey_fingerprint): + return + + if not self._CheckoutRevision(packet.base_revision): + return + + if not self._ApplyPatch(packet.patch): + return + + tests = packet.tests + endpoint.Execute(v8_root, self.ctx, tests, self.request, self.server.daemon) + self._SendResponse() + + def _SendResponse(self, error_message=None): + try: + if error_message: + compression.Send([[-1, error_message]], self.request) + compression.Send(constants.END_OF_STREAM, self.request) + return + except Exception, e: + pass # Peer is gone. There's nothing we can do. + # Clean up. + self._Call("git checkout -f") + self._Call("git clean -f -d") + self._Call("rm -rf %s" % self.ctx.shell_dir) + + def _UnpackBinary(self, binary, pubkey_fingerprint): + binary_name = binary["name"] + if binary_name == "libv8.so": + libdir = os.path.join(self.ctx.shell_dir, "lib.target") + if not os.path.exists(libdir): os.makedirs(libdir) + target = os.path.join(libdir, binary_name) + else: + target = os.path.join(self.ctx.shell_dir, binary_name) + pubkeyfile = "../trusted/%s.pem" % pubkey_fingerprint + if not signatures.VerifySignature(target, binary["blob"], + binary["sign"], pubkeyfile): + self._SendResponse("Signature verification failed") + return False + os.chmod(target, stat.S_IRWXU) + return True + + def _CheckoutRevision(self, base_svn_revision): + get_hash_cmd = ( + "git log -1 --format=%%H --remotes --grep='^git-svn-id:.*@%s'" % + base_svn_revision) + try: + base_revision = subprocess.check_output(get_hash_cmd, shell=True) + if not base_revision: raise ValueError + except: + self._Call("git fetch") + try: + base_revision = subprocess.check_output(get_hash_cmd, shell=True) + if not base_revision: raise ValueError + except: + self._SendResponse("Base revision not found.") + return False + code = self._Call("git checkout -f %s" % base_revision) + if code != 0: + self._SendResponse("Error trying to check out base revision.") + return False + code = self._Call("git clean -f -d") + if code != 0: + self._SendResponse("Failed to reset checkout") + return False + return True + + def _ApplyPatch(self, patch): + if not patch: return True # Just skip if the patch is empty. + patchfilename = "_dtest_incoming_patch.patch" + with open(patchfilename, "w") as f: + f.write(patch) + code = self._Call("git apply %s" % patchfilename) + if code != 0: + self._SendResponse("Error applying patch.") + return False + return True + + def _Call(self, cmd): + return subprocess.call(cmd, shell=True) + + +class WorkSocketServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): + def __init__(self, daemon): + address = (daemon.ip, constants.PEER_PORT) + SocketServer.TCPServer.__init__(self, address, WorkHandler) + self.job_lock = threading.Lock() + self.daemon = daemon |