OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 2 # |
| 3 # Copyright 2017 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. |
| 6 |
| 7 import os |
| 8 import sys |
| 9 import BaseHTTPServer |
| 10 import subprocess |
| 11 import argparse |
| 12 import datetime |
| 13 import signal |
| 14 import psutil |
| 15 |
| 16 import time |
| 17 |
| 18 import devil_chromium |
| 19 from devil.android import device_utils |
| 20 from devil.utils import run_tests_helper |
| 21 |
| 22 from multiprocessing import Process,Queue |
| 23 from pylib.constants import host_paths |
| 24 |
| 25 START_TRACING_CMD = "third_party/catapult/systrace/systrace/" |
| 26 START_TRACING_ARGS = ['-a', 'com.google.android.gm', 'webview'] |
| 27 |
| 28 def RunTests(device, test_filter=None, title=None): |
| 29 target = ('org.chromium.webview_ui_test.test/android.support.test.runner.' |
| 30 'AndroidJUnitRunner') |
| 31 extras = {} |
| 32 if test_filter is not None: |
| 33 extras.update({'class': test_filter}) |
| 34 if title is not None: |
| 35 extras.update({'title': title}) |
| 36 device.StartInstrumentation(target, extras=extras, timeout=300, retries=0) |
| 37 |
| 38 def ParseArgs(argv): |
| 39 timestring = datetime.datetime.now().strftime('%Y%m%d%H%M%S') |
| 40 parser = argparse.ArgumentParser() |
| 41 parser.add_argument('-t', dest='trace_output', required=False, |
| 42 default='gmail_logs/%s/trace-'+timestring+'-', |
| 43 help='Trace output file') |
| 44 parser.add_argument('-l', dest='logcat_output', required=False, |
| 45 default='gmail_logs/%s/logcat-'+timestring+'.log', |
| 46 help='Logcat output file') |
| 47 parser.add_argument('-s', dest='serial', required=True, help='Device serial') |
| 48 parser.add_argument('-f', dest='test_filter', help='Test filter') |
| 49 parser.add_argument('-e', dest='email_title', default='Long Text', |
| 50 help='Email titles') |
| 51 return parser.parse_args(argv[1:]) |
| 52 |
| 53 def GetDevice(serial): |
| 54 devices = device_utils.DeviceUtils.HealthyDevices() |
| 55 for d in devices: |
| 56 if d.serial == serial: |
| 57 return d |
| 58 raise Exception('No pixel device found') |
| 59 |
| 60 def SetUpDeviceAndGetLogcat(device): |
| 61 device.ForceStop('com.google.android.gm') |
| 62 device.SetProp('log.tag.GmailAnalytics', 'VERBOSE') |
| 63 |
| 64 def StartServer(port, q, trace_output, pipe, serial): |
| 65 server_address = ('', port) |
| 66 handler_class = GmailTracingRequestHandler |
| 67 handler_class.protocol_version = 'HTTP/1.0' |
| 68 httpd = GmailTracingServer( |
| 69 server_address, handler_class, q, trace_output, pipe, serial) |
| 70 sa = httpd.socket.getsockname() |
| 71 print "Serving One HTTP on", sa[0], "port", sa[1], "..." |
| 72 httpd.serve_forever() |
| 73 |
| 74 def StartServerWithProcess(port, trace_output, serial, pipe): |
| 75 q = Queue() |
| 76 p = Process(target=StartServer, args=(port, q, trace_output, pipe, serial)) |
| 77 p.start() |
| 78 return p |
| 79 |
| 80 def WaitAndKill(pid): |
| 81 time.sleep(400) |
| 82 psutil.Process(pid).terminate() |
| 83 |
| 84 def StartTrace(pipe, output_file, serial): |
| 85 cmd_path = os.path.abspath(os.path.join( |
| 86 host_paths.DIR_SOURCE_ROOT, 'third_party', 'catapult', 'systrace', |
| 87 'systrace', 'run_systrace.py')) |
| 88 full_cmd = [cmd_path] + ['-o', output_file, '-e', serial] + START_TRACING_ARGS |
| 89 print(full_cmd) |
| 90 tp = subprocess.Popen(full_cmd, stdin=pipe[0], stdout=None, stderr=None) |
| 91 return tp |
| 92 |
| 93 class GmailTracingRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
| 94 def do_GET(self): |
| 95 queue = self.server.queue |
| 96 if 'start-tracing' in self.path: |
| 97 if (queue.empty()): |
| 98 name = self.path.split('/')[-1] |
| 99 tracing_process = StartTrace( |
| 100 self.server.pipe, self.server.trace_output + name + '.html', |
| 101 self.server.serial) |
| 102 queue.put(tracing_process) |
| 103 self.send_response(200, 'started to trace') |
| 104 else: |
| 105 self.send_error(500, 'tracing process already exist') |
| 106 elif 'end-tracing' in self.path: |
| 107 if (queue.empty()): |
| 108 self.send_error( |
| 109 500, 'tracing process does not exist yet, please request ' |
| 110 '/start-tracing first') |
| 111 else: |
| 112 os.write(self.server.pipe[1], '\n') |
| 113 self.send_response(200, 'ended to trace') |
| 114 tracing_process = queue.get() |
| 115 tracing_process.wait() |
| 116 else: |
| 117 self.send_error(404, 'Only allow /start-tracing or /end-tracing') |
| 118 |
| 119 def main(): |
| 120 run_tests_helper.SetLogLevel(2) |
| 121 arguments = ParseArgs(sys.argv) |
| 122 email_title_no_space = arguments.email_title.replace(' ', '') |
| 123 output_dir = os.path.abspath( |
| 124 os.path.join( |
| 125 host_paths.DIR_SOURCE_ROOT, 'gmail_logs', email_title_no_space)) |
| 126 if not os.path.exists(os.path.abspath(output_dir)): |
| 127 os.mkdir(output_dir) |
| 128 device = GetDevice(arguments.serial) |
| 129 device.adb.Reverse('tcp:7777', 'tcp:7777', allow_rebind=True) |
| 130 # logcat_output = os.path.abspath(os.path.join( |
| 131 # host_paths.DIR_SOURCE_ROOT, |
| 132 # arguments.logcat_output % email_title_no_space)) |
| 133 # logcat_monitor = None |
| 134 p = None |
| 135 kp = None |
| 136 pipe = os.pipe() |
| 137 try: |
| 138 SetUpDeviceAndGetLogcat(device) |
| 139 # logcat_monitor.Start() |
| 140 p = StartServerWithProcess( |
| 141 7777, arguments.trace_output % email_title_no_space, |
| 142 arguments.serial, pipe) |
| 143 RunTests(device, arguments.test_filter, arguments.email_title) |
| 144 finally: |
| 145 # if logcat_monitor is not None: |
| 146 # logcat_monitor.Stop() |
| 147 # logcat_monitor.Close() |
| 148 time.sleep(5) |
| 149 if pipe is not None: |
| 150 os.write(pipe[1], '\n') |
| 151 if kp is not None: |
| 152 kp.terminate() |
| 153 if p is not None: |
| 154 p.terminate() |
| 155 |
| 156 class GmailTracingServer(BaseHTTPServer.HTTPServer): |
| 157 def __init__(self, server_address, RequestHandlerClass, queue, |
| 158 trace_output, pipe, serial): |
| 159 BaseHTTPServer.HTTPServer.__init__( |
| 160 self, server_address, RequestHandlerClass) |
| 161 self._queue = queue |
| 162 self._trace_output = trace_output |
| 163 self._pipe = pipe |
| 164 self._serial = serial |
| 165 |
| 166 @property |
| 167 def serial(self): |
| 168 return self._serial |
| 169 |
| 170 @property |
| 171 def pipe(self): |
| 172 return self._pipe |
| 173 |
| 174 @property |
| 175 def queue(self): |
| 176 return self._queue |
| 177 |
| 178 @property |
| 179 def trace_output(self): |
| 180 return self._trace_output |
| 181 |
| 182 if __name__ == '__main__': |
| 183 sys.exit(main()) |
OLD | NEW |