Bug 1554328: Fix minor typos in Raptor's control_server.py r=perftest-reviewers,sparky

Differential Revision: https://phabricator.services.mozilla.com/D43278

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Stephen Donner 2019-08-23 22:17:12 +00:00
Родитель 620c07b2bb
Коммит 3e05e8ace5
1 изменённых файлов: 98 добавлений и 94 удалений

Просмотреть файл

@ -1,3 +1,5 @@
#!/usr/bin/env python
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
@ -17,17 +19,14 @@ import time
from logger.logger import RaptorLogger
LOG = RaptorLogger(component='raptor-control-server')
LOG = RaptorLogger(component="raptor-control-server")
here = os.path.abspath(os.path.dirname(__file__))
def MakeCustomHandlerClass(results_handler,
shutdown_browser,
handle_gecko_profile,
background_app,
foreground_app):
def MakeCustomHandlerClass(
results_handler, shutdown_browser, handle_gecko_profile, background_app, foreground_app
):
class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler, object):
"""
Control server expects messages of the form
@ -40,25 +39,25 @@ def MakeCustomHandlerClass(results_handler,
otherwise
the key is data['type'].
The contol server can be forced to wait before performing an
The control server can be forced to wait before performing an
action requested via POST by sending a special message
{'type': 'wait-set', 'data': key}
where key is the key of the message control server should
where key is the key of the message for which the control server should
perform a wait before processing. The handler will store
this key in the wait_after_messages dict as a True value.
wait_after_messages[key] = True
For subsequent requests the handler will check the key of
the incoming message against wait_for_messages and if it is
found and its value is True, the handler will assign the key
For subsequent requests, the handler will check the key of
the incoming message against wait_for_messages; if found
and its value is True, the handler will assign the key
to waiting_in_state and will loop until the key is removed
or until its value is changed to False.
Control server will stop waiting for a state to be continued
or cleared after wait_timeout seconds after which the wait
The control server will stop waiting for a state to be continued
or cleared after wait_timeout seconds, after which the wait
will be removed and the control server will finish processing
the current POST request. wait_timeout defaults to 60 seconds
but can be set globally for all wait states by sending the
@ -77,13 +76,13 @@ def MakeCustomHandlerClass(results_handler,
key is recorded in wait_after_messages and is waiting before
completing the request.
The control server can be told to stop waiting and to finish
The control server can be told to stop waiting and finish
processing the current request while keeping the wait for
subsequent requests by sending
{'type': 'wait-continue', 'data': ''}
The control server can be told to stop waiting and to finish
The control server can be told to stop waiting and finish
processing the current request while removing the wait for
subsequent requests by sending
@ -101,6 +100,7 @@ def MakeCustomHandlerClass(results_handler,
if the key matches the value in waiting_in_state,
then waiting_in_state is set to None
"""
wait_after_messages = {}
waiting_in_state = None
wait_timeout = 60
@ -113,46 +113,46 @@ def MakeCustomHandlerClass(results_handler,
self.foreground_app = foreground_app
super(MyHandler, self).__init__(*args, **kwargs)
def log_request(self, code='-', size='-'):
def log_request(self, code="-", size="-"):
if code != 200:
super(MyHandler, self).log_request(code, size)
def do_GET(self):
# get handler, received request for test settings from web ext runner
# get handler, received request for test settings from webext runner
self.send_response(200)
head, tail = os.path.split(self.path)
if tail.startswith('raptor') and tail.endswith('.json'):
LOG.info('reading test settings from json/' + tail)
if tail.startswith("raptor") and tail.endswith(".json"):
LOG.info("reading test settings from json/" + tail)
try:
with open("json/{}".format(tail)) as json_settings:
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Content-type', 'application/json')
self.send_header("Access-Control-Allow-Origin", "*")
self.send_header("Content-type", "application/json")
self.end_headers()
self.wfile.write(json.dumps(json.load(json_settings)))
self.wfile.close()
LOG.info('sent test settings to web ext runner')
LOG.info("sent test settings to webext runner")
except Exception as ex:
LOG.info('control server exception')
LOG.info("control server exception")
LOG.info(ex)
else:
LOG.info('received request for unknown file: ' + self.path)
LOG.info("received request for unknown file: " + self.path)
def do_POST(self):
# post handler, received something from webext
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Content-type', 'text/html')
self.send_header("Access-Control-Allow-Origin", "*")
self.send_header("Content-type", "text/html")
self.end_headers()
content_len = int(self.headers.getheader('content-length'))
content_len = int(self.headers.getheader("content-length"))
post_body = self.rfile.read(content_len)
# could have received a status update or test results
data = json.loads(post_body)
if data['type'] == 'webext_status':
wait_key = "%s/%s" % (data['type'], data['data'])
if data["type"] == "webext_status":
wait_key = "%s/%s" % (data["type"], data["data"])
else:
wait_key = data['type']
wait_key = data["type"]
if MyHandler.wait_after_messages.get(wait_key, None):
LOG.info("Waiting in %s" % wait_key)
@ -165,73 +165,75 @@ def MakeCustomHandlerClass(results_handler,
if elapsed_time > datetime.timedelta(seconds=MyHandler.wait_timeout):
del MyHandler.wait_after_messages[wait_key]
MyHandler.waiting_in_state = None
LOG.error("TEST-UNEXPECTED-ERROR | "
"ControlServer wait %s exceeded %s seconds" %
(wait_key, MyHandler.wait_timeout))
LOG.error(
"TEST-UNEXPECTED-ERROR | "
"control server wait %s exceeded %s seconds"
% (wait_key, MyHandler.wait_timeout)
)
if MyHandler.wait_after_messages.get(wait_key, None) is not None:
# If the wait is False, it was continued and we just set it back
# to True for the next time. If it was removed by clear, we
# leave it alone so it will not cause a wait any more.
# If the wait is False, it was continued, so we set it back
# to True for the next time. If removed by clear, we
# leave it alone so it will not cause further waits.
MyHandler.wait_after_messages[wait_key] = True
if data['type'] == "webext_gecko_profile":
if data["type"] == "webext_gecko_profile":
# received file name of the saved gecko profile
filename = str(data['data'])
filename = str(data["data"])
LOG.info("received gecko profile filename: {}".format(filename))
self.handle_gecko_profile(filename)
elif data['type'] == 'webext_results':
LOG.info("received " + data['type'] + ": " + str(data['data']))
self.results_handler.add(data['data'])
elif data['type'] == "webext_raptor-page-timeout":
LOG.info("received " + data['type'] + ": " + str(data['data']))
elif data["type"] == "webext_results":
LOG.info("received " + data["type"] + ": " + str(data["data"]))
self.results_handler.add(data["data"])
elif data["type"] == "webext_raptor-page-timeout":
LOG.info("received " + data["type"] + ": " + str(data["data"]))
if len(data['data']) == 2:
data['data'].append("")
if len(data["data"]) == 2:
data["data"].append("")
# pageload test has timed out; record it as a failure
self.results_handler.add_page_timeout(str(data['data'][0]),
str(data['data'][1]),
dict(data['data'][2]))
elif data['type'] == "webext_shutdownBrowser":
self.results_handler.add_page_timeout(
str(data["data"][0]), str(data["data"][1]), dict(data["data"][2])
)
elif data["type"] == "webext_shutdownBrowser":
LOG.info("received request to shutdown the browser")
self.shutdown_browser()
elif data['type'] == 'webext_start_background':
elif data["type"] == "webext_start_background":
LOG.info("received request to background app")
self.background_app()
elif data['type'] == 'webext_end_background':
elif data["type"] == "webext_end_background":
LOG.info("received request to foreground app")
self.foreground_app()
elif data['type'] == 'webext_screenshot':
LOG.info("received " + data['type'])
self.results_handler.add_image(str(data['data'][0]),
str(data['data'][1]),
str(data['data'][2]))
elif data['type'] == 'webext_status':
LOG.info("received " + data['type'] + ": " + str(data['data']))
elif data['type'] == 'wait-set':
LOG.info("received " + data['type'] + ": " + str(data['data']))
MyHandler.wait_after_messages[str(data['data'])] = True
elif data['type'] == 'wait-timeout':
LOG.info("received " + data['type'] + ": " + str(data['data']))
MyHandler.wait_timeout = data['data']
elif data['type'] == 'wait-get':
elif data["type"] == "webext_screenshot":
LOG.info("received " + data["type"])
self.results_handler.add_image(
str(data["data"][0]), str(data["data"][1]), str(data["data"][2])
)
elif data["type"] == "webext_status":
LOG.info("received " + data["type"] + ": " + str(data["data"]))
elif data["type"] == "wait-set":
LOG.info("received " + data["type"] + ": " + str(data["data"]))
MyHandler.wait_after_messages[str(data["data"])] = True
elif data["type"] == "wait-timeout":
LOG.info("received " + data["type"] + ": " + str(data["data"]))
MyHandler.wait_timeout = data["data"]
elif data["type"] == "wait-get":
self.wfile.write(MyHandler.waiting_in_state)
elif data['type'] == 'wait-continue':
LOG.info("received " + data['type'] + ": " + str(data['data']))
elif data["type"] == "wait-continue":
LOG.info("received " + data["type"] + ": " + str(data["data"]))
if MyHandler.waiting_in_state:
MyHandler.wait_after_messages[MyHandler.waiting_in_state] = False
MyHandler.waiting_in_state = None
elif data['type'] == 'wait-clear':
LOG.info("received " + data['type'] + ": " + str(data['data']))
clear_key = str(data['data'])
if clear_key == '':
elif data["type"] == "wait-clear":
LOG.info("received " + data["type"] + ": " + str(data["data"]))
clear_key = str(data["data"])
if clear_key == "":
if MyHandler.waiting_in_state:
del MyHandler.wait_after_messages[MyHandler.waiting_in_state]
MyHandler.waiting_in_state = None
else:
pass
elif clear_key == 'all':
elif clear_key == "all":
MyHandler.wait_after_messages = {}
MyHandler.waiting_in_state = None
elif clear_key not in MyHandler.wait_after_messages:
@ -241,12 +243,12 @@ def MakeCustomHandlerClass(results_handler,
if MyHandler.waiting_in_state == clear_key:
MyHandler.waiting_in_state = None
else:
LOG.info("received " + data['type'] + ": " + str(data['data']))
LOG.info("received " + data["type"] + ": " + str(data["data"]))
def do_OPTIONS(self):
self.send_response(200, "ok")
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header("Access-Control-Allow-Origin", "*")
self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
self.send_header("Access-Control-Allow-Headers", "X-Requested-With")
self.send_header("Access-Control-Allow-Headers", "Content-Type")
self.end_headers()
@ -258,8 +260,10 @@ class ThreadedHTTPServer(BaseHTTPServer.HTTPServer):
# See
# https://stackoverflow.com/questions/19537132/threaded-basehttpserver-one-thread-per-request#30312766
def process_request(self, request, client_address):
thread = threading.Thread(target=self.__new_request,
args=(self.RequestHandlerClass, request, client_address, self))
thread = threading.Thread(
target=self.__new_request,
args=(self.RequestHandlerClass, request, client_address, self),
)
thread.start()
def __new_request(self, handlerClass, request, address, server):
@ -267,11 +271,11 @@ class ThreadedHTTPServer(BaseHTTPServer.HTTPServer):
self.shutdown_request(request)
class RaptorControlServer():
class RaptorControlServer:
"""Container class for Raptor Control Server"""
def __init__(self, results_handler, debug_mode=False):
self.raptor_venv = os.path.join(os.getcwd(), 'raptor-venv')
self.raptor_venv = os.path.join(os.getcwd(), "raptor-venv")
self.server = None
self._server_thread = None
self.port = None
@ -285,22 +289,24 @@ class RaptorControlServer():
self.user_profile = None
def start(self):
config_dir = os.path.join(here, 'tests')
config_dir = os.path.join(here, "tests")
os.chdir(config_dir)
# pick a free port
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', 0))
sock.bind(("", 0))
self.port = sock.getsockname()[1]
sock.close()
server_address = ('', self.port)
server_address = ("", self.port)
server_class = ThreadedHTTPServer
handler_class = MakeCustomHandlerClass(self.results_handler,
self.shutdown_browser,
self.handle_gecko_profile,
self.background_app,
self.foreground_app)
handler_class = MakeCustomHandlerClass(
self.results_handler,
self.shutdown_browser,
self.handle_gecko_profile,
self.background_app,
self.foreground_app,
)
httpd = server_class(server_address, handler_class)
@ -322,7 +328,7 @@ class RaptorControlServer():
LOG.info("shutting down android app %s" % self.app_name)
else:
LOG.info("shutting down browser (pid: %d)" % self.browser_proc.pid)
self.kill_thread = threading.Thread(target=self.wait_for_quit, kwargs={'timeout': 0})
self.kill_thread = threading.Thread(target=self.wait_for_quit, kwargs={"timeout": 0})
self.kill_thread.daemon = True
self.kill_thread.start()
@ -350,9 +356,7 @@ class RaptorControlServer():
LOG.info("%s was successfully backgrounded" % self.app_name)
def foreground_app(self):
self.device.shell_output(
"am start --activity-single-top %s" % self.app_name
)
self.device.shell_output("am start --activity-single-top %s" % self.app_name)
self.device.shell_output("dumpsys deviceidle enable")
if self.is_app_in_background():
LOG.critical("%s is still in background after foreground request" % self.app_name)
@ -372,12 +376,12 @@ class RaptorControlServer():
self._finished = True
def submit_supporting_data(self, supporting_data):
'''
"""
Allow the submission of supporting data i.e. power data.
This type of data is measured outside of the webext; so
we can submit directly to the control server instead of
doing an http post.
'''
"""
self.results_handler.add_supporting_data(supporting_data)
def stop(self):