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

Unified Diff: chrome/test/kasko/py/kasko/crash_server.py

Issue 1582613002: [win] Create a SyzyAsan/Chrome/Kasko/Crashpad integration test. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update file permissions. Created 4 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 | « chrome/test/kasko/py/kasko/config.py ('k') | chrome/test/kasko/py/kasko/exceptions.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/test/kasko/py/kasko/crash_server.py
diff --git a/chrome/test/kasko/py/kasko/crash_server.py b/chrome/test/kasko/py/kasko/crash_server.py
new file mode 100755
index 0000000000000000000000000000000000000000..625531be105da1a546230a1d11bb79c96ba282f3
--- /dev/null
+++ b/chrome/test/kasko/py/kasko/crash_server.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+# Copyright 2016 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.
+
+"""Exceptions used by the Kasko integration test module."""
+
+import BaseHTTPServer
+import cgi
+import logging
+import os
+import socket
+import threading
+import time
+import uuid
+
+
+_LOGGER = logging.getLogger(os.path.basename(__file__))
+
+
+class _StoppableHTTPServer(BaseHTTPServer.HTTPServer):
+ """An extension of BaseHTTPServer that uses timeouts and is interruptable."""
+
+ def server_bind(self):
+ BaseHTTPServer.HTTPServer.server_bind(self)
+ self.socket.settimeout(1)
+ self.run_ = True
+
+ def get_request(self):
+ while self.run_:
+ try:
+ sock, addr = self.socket.accept()
+ sock.settimeout(None)
+ return (sock, addr)
+ except socket.timeout:
+ pass
+
+ def stop(self):
+ self.run_ = False
+
+ def serve(self):
+ while self.run_:
+ self.handle_request()
+
+
+class CrashServer(object):
+ """A simple crash server for testing."""
+
+ def __init__(self):
+ self.server_ = None
+ self.lock_ = threading.Lock()
+ self.crashes_ = [] # Under lock_.
+
+ def crash(self, index):
+ """Accessor for the list of crashes."""
+ with self.lock_:
+ if index >= len(self.crashes_):
+ return None
+ return self.crashes_[index]
+
+ @property
+ def port(self):
+ """Returns the port associated with the server."""
+ if not self.server_:
+ return 0
+ return self.server_.server_port
+
+ def start(self):
+ """Starts the server on another thread. Call from main thread only."""
+ page_handler = self.multipart_form_handler()
+ self.server_ = _StoppableHTTPServer(('127.0.0.1', 0), page_handler)
+ self.thread_ = self.server_thread()
+ self.thread_.start()
+
+ def stop(self):
+ """Stops the running server. Call from main thread only."""
+ self.server_.stop()
+ self.thread_.join()
+ self.server_ = None
+ self.thread_ = None
+
+ def wait_for_report(self, timeout):
+ """Waits until the server has received a crash report.
+
+ Returns True if the a report has been received in the given time, or False
+ if a timeout occurred. Since Python condition variables have no notion of
+ timeout this is, sadly, a busy loop on the calling thread.
+ """
+ started = time.time()
+ elapsed = 0
+ while elapsed < timeout:
+ with self.lock_:
+ if len(self.crashes_):
+ return True
+ time.sleep(0.1)
+ elapsed = time.time() - started
+
+ return False
+
+
+ def multipart_form_handler(crash_server):
+ """Returns a multi-part form handler class for use with a BaseHTTPServer."""
+
+ class MultipartFormHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+ """A multi-part form handler that processes crash reports.
+
+ This class only handles multipart form POST messages, with all other
+ requests by default returning a '501 not implemented' error.
+ """
+
+ def __init__(self, request, client_address, socket_server):
+ BaseHTTPServer.BaseHTTPRequestHandler.__init__(
+ self, request, client_address, socket_server)
+
+ def log_message(self, format, *args):
+ _LOGGER.debug(format, *args)
+
+ def do_POST(self):
+ """Handles POST messages contained multipart form data."""
+ content_type, parameters = cgi.parse_header(
+ self.headers.getheader('content-type'))
+ if content_type != 'multipart/form-data':
+ raise Exception('Unsupported Content-Type: ' + content_type)
+ post_multipart = cgi.parse_multipart(self.rfile, parameters)
+
+ # Save the crash report.
+ report = dict(post_multipart.items())
+ report_id = str(uuid.uuid4())
+ report['report-id'] = [report_id]
+ with crash_server.lock_:
+ crash_server.crashes_.append(report)
+
+ # Send the response.
+ self.send_response(200)
+ self.send_header("Content-Type", "text/plain")
+ self.end_headers()
+ self.wfile.write(report_id)
+
+ return MultipartFormHandler
+
+ def server_thread(crash_server):
+ """Returns a thread that hosts the webserver."""
+
+ class ServerThread(threading.Thread):
+ def run(self):
+ crash_server.server_.serve()
+
+ return ServerThread()
« no previous file with comments | « chrome/test/kasko/py/kasko/config.py ('k') | chrome/test/kasko/py/kasko/exceptions.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698