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

Side by Side Diff: tools/chrome_proxy/webdriver/common.py

Issue 2578713002: Add logging to TestDriver (Closed)
Patch Set: Created 4 years 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2016 The Chromium Authors. All rights reserved. 1 # Copyright 2016 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import argparse 5 import argparse
6 import json 6 import json
7 import logging
7 import os 8 import os
8 import re 9 import re
9 import socket 10 import socket
10 import shlex 11 import shlex
11 import sys 12 import sys
12 import time 13 import time
13 import traceback 14 import traceback
14 import unittest 15 import unittest
15 16
16 sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, 17 sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
17 os.pardir, 'third_party', 'webdriver', 'pylib')) 18 os.pardir, 'third_party', 'webdriver', 'pylib'))
18 from selenium import webdriver 19 from selenium import webdriver
19 from selenium.webdriver.chrome.options import Options 20 from selenium.webdriver.chrome.options import Options
20 21
21 # TODO(robertogden): Add logging.
22 22
RyanSturm 2016/12/14 23:04:28 remove extra vertical whitespace.
Robert Ogden 2016/12/15 17:15:09 Done.
23 23
24 def ParseFlags(): 24 def ParseFlags():
25 """Parses the given command line arguments. 25 """Parses the given command line arguments.
26 26
27 Returns: 27 Returns:
28 A new Namespace object with class properties for each argument added below. 28 A new Namespace object with class properties for each argument added below.
29 See pydoc for argparse. 29 See pydoc for argparse.
30 """ 30 """
31 parser = argparse.ArgumentParser() 31 parser = argparse.ArgumentParser()
32 parser.add_argument('--browser_args', type=str, help='Override browser flags ' 32 parser.add_argument('--browser_args', type=str, help='Override browser flags '
33 'in code with these flags') 33 'in code with these flags')
34 parser.add_argument('--via_header_value', 34 parser.add_argument('--via_header_value',
35 default='1.1 Chrome-Compression-Proxy', help='What the via should match to ' 35 default='1.1 Chrome-Compression-Proxy', help='What the via should match to '
36 'be considered valid') 36 'be considered valid')
37 parser.add_argument('--android', help='If given, attempts to run the test on ' 37 parser.add_argument('--android', help='If given, attempts to run the test on '
38 'Android via adb. Ignores usage of --chrome_exec', action='store_true') 38 'Android via adb. Ignores usage of --chrome_exec', action='store_true')
39 parser.add_argument('--android_package', 39 parser.add_argument('--android_package',
40 default='com.android.chrome', help='Set the android package for Chrome') 40 default='com.android.chrome', help='Set the android package for Chrome')
41 parser.add_argument('--chrome_exec', type=str, help='The path to ' 41 parser.add_argument('--chrome_exec', type=str, help='The path to '
42 'the Chrome or Chromium executable') 42 'the Chrome or Chromium executable')
43 parser.add_argument('chrome_driver', type=str, help='The path to ' 43 parser.add_argument('chrome_driver', type=str, help='The path to '
44 'the ChromeDriver executable. If not given, the default system chrome ' 44 'the ChromeDriver executable. If not given, the default system chrome '
45 'will be used.') 45 'will be used.')
46 parser.add_argument('--disable_buffer', help='Causes stdout and stderr from ' 46 parser.add_argument('--disable_buffer', help='Causes stdout and stderr from '
47 'tests to output normally. Otherwise, the standard output and standard ' 47 'tests to output normally. Otherwise, the standard output and standard '
48 'error streams are buffered during the test run, and output during a ' 48 'error streams are buffered during the test run, and output from a '
49 'passing test is discarded. Output will always be echoed normally on test ' 49 'passing test is discarded. Output will always be echoed normally on test '
50 'fail or error and is added to the failure messages.', action='store_true') 50 'fail or error and is added to the failure messages.', action='store_true')
51 parser.add_argument('-c', '--catch', help='Control-C during the test run ' 51 parser.add_argument('-c', '--catch', help='Control-C during the test run '
52 'waits for the current test to end and then reports all the results so ' 52 'waits for the current test to end and then reports all the results so '
53 'far. A second Control-C raises the normal KeyboardInterrupt exception.', 53 'far. A second Control-C raises the normal KeyboardInterrupt exception.',
54 action='store_true') 54 action='store_true')
55 parser.add_argument('-f', '--failfast', help='Stop the test run on the first ' 55 parser.add_argument('-f', '--failfast', help='Stop the test run on the first '
56 'error or failure.', action='store_true') 56 'error or failure.', action='store_true')
57 # TODO(robertogden): Log sys.argv here. 57 parser.add_argument('--logging_level', choices=['DEBUG', 'INFO', 'WARN',
58 'ERROR', 'CRIT'], default='ERROR', help='The logging level for log '
RyanSturm 2016/12/14 23:04:28 s/level/threshold/ or "verbosity"
Robert Ogden 2016/12/15 17:15:09 Done.
59 'message, printed to stderr. To see stderr logging output during a '
60 'successful test run, also pass --disable_buffer. Default=ERROR')
61 parser.add_argument('--log_file', help='If given, write logging statements '
62 'to the given file instead of stderr.')
58 return parser.parse_args(sys.argv[1:]) 63 return parser.parse_args(sys.argv[1:])
59 64
65 def GetLogger(name='common'):
66 """Creates a Logger instance with the given name and returns it.
67
68 If a logger has already been created with the same name, that instance is
69 returned instead.
70
71 Args:
72 name: The name of the logger to return.
73 Returns:
74 A logger with the given name.
75 """
76 logger = logging.getLogger(name)
77 if hasattr(logger, "initialized"):
78 return logger
79 logging_level = ParseFlags().logging_level
80 if logging_level == 'DEBUG':
81 logger.setLevel(logging.DEBUG)
82 elif logging_level == 'INFO':
83 logger.setLevel(logging.INFO)
84 elif logging_level == 'WARN':
85 logger.setLevel(logging.WARNING)
86 elif logging_level == 'ERROR':
87 logger.setLevel(logging.ERROR)
88 elif logging_level == 'CRIT':
89 logger.setLevel(logging.CRITICAL)
90 else:
91 logger.setLevel(logging.NOTSET)
92 formatter = logging.Formatter('%(asctime)s %(funcName)s() %(levelname)s: '
93 '%(message)s')
94 if ParseFlags().log_file:
95 fh = logging.FileHandler(ParseFlags().log_file)
96 fh.setFormatter(formatter)
97 logger.addHandler(fh)
98 else:
99 ch = logging.StreamHandler(sys.stderr)
100 ch.setFormatter(formatter)
101 logger.addHandler(ch)
102 logger.initialized = True
103 return logger
60 104
61 class TestDriver: 105 class TestDriver:
62 """The main driver for an integration test. 106 """The main driver for an integration test.
63 107
64 This class is the tool that is used by every integration test to interact with 108 This class is the tool that is used by every integration test to interact with
65 the Chromium browser and validate proper functionality. This class sits on top 109 the Chromium browser and validate proper functionality. This class sits on top
66 of the Selenium Chrome Webdriver with added utility and helper functions for 110 of the Selenium Chrome Webdriver with added utility and helper functions for
67 Chrome-Proxy. This class should be used with Python's 'with' operator. 111 Chrome-Proxy. This class should be used with Python's 'with' operator.
68 112
69 Attributes: 113 Attributes:
70 _flags: A Namespace object from the call to ParseFlags() 114 _flags: A Namespace object from the call to ParseFlags()
71 _driver: A reference to the driver object from the Chrome Driver library. 115 _driver: A reference to the driver object from the Chrome Driver library.
72 _chrome_args: A set of string arguments to start Chrome with. 116 _chrome_args: A set of string arguments to start Chrome with.
73 _url: The string URL that Chrome will navigate to for this test. 117 _url: The string URL that Chrome will navigate to for this test.
74 """ 118 """
75 119
76 def __init__(self): 120 def __init__(self):
77 self._flags = ParseFlags() 121 self._flags = ParseFlags()
78 self._driver = None 122 self._driver = None
79 self._chrome_args = set() 123 self._chrome_args = set()
80 self._url = '' 124 self._url = ''
125 self._logger = GetLogger(name='TestDriver')
81 126
82 def __enter__(self): 127 def __enter__(self):
83 return self 128 return self
84 129
85 def __exit__(self, exc_type, exc_value, tb): 130 def __exit__(self, exc_type, exc_value, tb):
86 if self._driver: 131 if self._driver:
87 self._StopDriver() 132 self._StopDriver()
88 133
89 def _OverrideChromeArgs(self): 134 def _OverrideChromeArgs(self):
90 """Overrides any given arguments in the code with those given on the command 135 """Overrides any given arguments in the code with those given on the command
91 line. 136 line.
92 137
93 Arguments that need to be overridden may contain different values for 138 Arguments that need to be overridden may contain different values for
94 a flag given in the code. In that case, check by the flag whether to 139 a flag given in the code. In that case, check by the flag whether to
95 override the argument. 140 override the argument.
96 """ 141 """
97 def GetDictKey(argument): 142 def GetDictKey(argument):
98 return argument.split('=', 1)[0] 143 return argument.split('=', 1)[0]
99 if self._flags.browser_args and len(self._flags.browser_args) > 0: 144 if self._flags.browser_args and len(self._flags.browser_args) > 0:
100 # Build a dict of flags mapped to the whole argument. 145 # Build a dict of flags mapped to the whole argument.
101 original_args = {} 146 original_args = {}
102 for arg in self._chrome_args: 147 for arg in self._chrome_args:
103 original_args[GetDictKey(arg)] = arg 148 original_args[GetDictKey(arg)] = arg
104 # Override flags given in code with any command line arguments. 149 # Override flags given in code with any command line arguments.
105 for override_arg in shlex.split(self._flags.browser_args): 150 for override_arg in shlex.split(self._flags.browser_args):
106 arg_key = GetDictKey(override_arg) 151 arg_key = GetDictKey(override_arg)
107 if arg_key in original_args: 152 if arg_key in original_args:
108 self._chrome_args.remove(original_args[arg_key]) 153 self._chrome_args.remove(original_args[arg_key])
154 self._logger.info('Removed Chrome flag. %s', original_args[arg_key])
109 self._chrome_args.add(override_arg) 155 self._chrome_args.add(override_arg)
156 self._logger.info('Added Chrome flag. %s', override_arg)
110 # Always add the flag that allows histograms to be queried in javascript. 157 # Always add the flag that allows histograms to be queried in javascript.
111 self._chrome_args.add('--enable-stats-collection-bindings') 158 self._chrome_args.add('--enable-stats-collection-bindings')
112 159
113 def _StartDriver(self): 160 def _StartDriver(self):
114 """Parses the flags to pass to Chromium, then starts the ChromeDriver. 161 """Parses the flags to pass to Chromium, then starts the ChromeDriver.
115 162
116 If running Android, the Android package name is passed to ChromeDriver here. 163 If running Android, the Android package name is passed to ChromeDriver here.
117 """ 164 """
118 self._OverrideChromeArgs() 165 self._OverrideChromeArgs()
119 capabilities = { 166 capabilities = {
120 'loggingPrefs': {'performance': 'INFO'}, 167 'loggingPrefs': {'performance': 'INFO'},
121 'chromeOptions': { 168 'chromeOptions': {
122 'args': list(self._chrome_args) 169 'args': list(self._chrome_args)
123 } 170 }
124 } 171 }
125 if self._flags.android: 172 if self._flags.android:
126 capabilities['chromeOptions'].update({ 173 capabilities['chromeOptions'].update({
127 'androidPackage': self._flags.android_package, 174 'androidPackage': self._flags.android_package,
128 }) 175 })
176 self._logger.debug('Will use Chrome on Android')
129 elif self._flags.chrome_exec: 177 elif self._flags.chrome_exec:
130 capabilities['chrome.binary'] = self._flags.chrome_exec 178 capabilities['chrome.binary'] = self._flags.chrome_exec
179 self._logger.info('Using the Chrome binary at this path: %s',
180 self._flags.chrome_exec)
181 self._logger.info('Starting Chrome with these flags: %s',
182 str(self._chrome_args))
183 self._logger.debug('Starting ChromeDriver with these capabilities: %s',
184 json.dumps(capabilities))
131 driver = webdriver.Chrome(executable_path=self._flags.chrome_driver, 185 driver = webdriver.Chrome(executable_path=self._flags.chrome_driver,
132 desired_capabilities=capabilities) 186 desired_capabilities=capabilities)
133 driver.command_executor._commands.update({ 187 driver.command_executor._commands.update({
134 'getAvailableLogTypes': ('GET', '/session/$sessionId/log/types'), 188 'getAvailableLogTypes': ('GET', '/session/$sessionId/log/types'),
135 'getLog': ('POST', '/session/$sessionId/log')}) 189 'getLog': ('POST', '/session/$sessionId/log')})
136 self._driver = driver 190 self._driver = driver
137 191
138 def _StopDriver(self): 192 def _StopDriver(self):
139 """Nicely stops the ChromeDriver. 193 """Nicely stops the ChromeDriver.
140 """ 194 """
195 self._logger.debug('Stopping ChromeDriver')
141 self._driver.quit() 196 self._driver.quit()
142 self._driver = None 197 self._driver = None
143 198
144 def AddChromeArgs(self, args): 199 def AddChromeArgs(self, args):
145 """Adds multiple arguments that will be passed to Chromium at start. 200 """Adds multiple arguments that will be passed to Chromium at start.
146 201
147 Args: 202 Args:
148 args: An iterable of strings, each an argument to pass to Chrome at start. 203 args: An iterable of strings, each an argument to pass to Chrome at start.
149 """ 204 """
150 for arg in args: 205 for arg in args:
151 self._chrome_args.add(arg) 206 self._chrome_args.add(arg)
152 207
153 def AddChromeArg(self, arg): 208 def AddChromeArg(self, arg):
154 """Adds a single argument that will be passed to Chromium at start. 209 """Adds a single argument that will be passed to Chromium at start.
155 210
156 Args: 211 Args:
157 arg: a string argument to pass to Chrome at start 212 arg: a string argument to pass to Chrome at start
158 """ 213 """
159 self._chrome_args.add(arg) 214 self._chrome_args.add(arg)
215 self._logger.debug('Adding Chrome arg: %s', arg)
160 216
161 def RemoveChromeArgs(self, args): 217 def RemoveChromeArgs(self, args):
162 """Removes multiple arguments that will no longer be passed to Chromium at 218 """Removes multiple arguments that will no longer be passed to Chromium at
163 start. 219 start.
164 220
165 Args: 221 Args:
166 args: An iterable of strings to no longer use the next time Chrome 222 args: An iterable of strings to no longer use the next time Chrome
167 starts. 223 starts.
168 """ 224 """
169 for arg in args: 225 for arg in args:
170 self._chrome_args.discard(arg) 226 self._chrome_args.discard(arg)
171 227
172 def RemoveChromeArg(self, arg): 228 def RemoveChromeArg(self, arg):
173 """Removes a single argument that will no longer be passed to Chromium at 229 """Removes a single argument that will no longer be passed to Chromium at
174 start. 230 start.
175 231
176 Args: 232 Args:
177 arg: A string flag to no longer use the next time Chrome starts. 233 arg: A string flag to no longer use the next time Chrome starts.
178 """ 234 """
179 self._chrome_args.discard(arg) 235 self._chrome_args.discard(arg)
236 self._logger.debug('Removing Chrome arg: %s', arg)
180 237
181 def ClearChromeArgs(self): 238 def ClearChromeArgs(self):
182 """Removes all arguments from Chromium at start. 239 """Removes all arguments from Chromium at start.
183 """ 240 """
184 self._chrome_args.clear() 241 self._chrome_args.clear()
242 self._logger.debug('Clearing all Chrome args')
185 243
186 def ClearCache(self): 244 def ClearCache(self):
187 """Clears the browser cache. 245 """Clears the browser cache.
188 246
189 Important note: ChromeDriver automatically starts 247 Important note: ChromeDriver automatically starts
190 a clean copy of Chrome on every instantiation. 248 a clean copy of Chrome on every instantiation.
191 """ 249 """
192 self.ExecuteJavascript('if(window.chrome && chrome.benchmarking && ' 250 res = self.ExecuteJavascript('if(window.chrome && chrome.benchmarking && '
193 'chrome.benchmarking.clearCache){chrome.benchmarking.clearCache(); ' 251 'chrome.benchmarking.clearCache){chrome.benchmarking.clearCache(); '
194 'chrome.benchmarking.clearPredictorCache();chrome.benchmarking.' 252 'chrome.benchmarking.clearPredictorCache();chrome.benchmarking.'
195 'clearHostResolverCache();}') 253 'clearHostResolverCache();}')
254 self._logger.info('Cleared browser cache. Returned=%s', str(res))
196 255
197 def LoadURL(self, url, timeout=30): 256 def LoadURL(self, url, timeout=30):
198 """Starts Chromium with any arguments previously given and navigates to the 257 """Starts Chromium with any arguments previously given and navigates to the
199 given URL. 258 given URL.
200 259
201 Args: 260 Args:
202 url: The URL to navigate to. 261 url: The URL to navigate to.
203 timeout: The time in seconds to load the page before timing out. 262 timeout: The time in seconds to load the page before timing out.
204 """ 263 """
205 self._url = url 264 self._url = url
206 if not self._driver: 265 if not self._driver:
207 self._StartDriver() 266 self._StartDriver()
208 self._driver.set_page_load_timeout(timeout) 267 self._driver.set_page_load_timeout(timeout)
268 self._logger.debug('Set page load timeout to %f seconds', timeout)
209 self._driver.get(self._url) 269 self._driver.get(self._url)
270 self._logger.debug('Loaded page %s', url)
210 271
211 def ExecuteJavascript(self, script, timeout=30): 272 def ExecuteJavascript(self, script, timeout=30):
212 """Executes the given javascript in the browser's current page in an 273 """Executes the given javascript in the browser's current page in an
213 anonymous function. 274 anonymous function.
214 275
215 If you expect a result and don't get one, try adding a return statement or 276 If you expect a result and don't get one, try adding a return statement or
216 using ExecuteJavascriptStatement() below. 277 using ExecuteJavascriptStatement() below.
217 278
218 Args: 279 Args:
219 script: A string of Javascript code. 280 script: A string of Javascript code.
220 timeout: Timeout for the Javascript code to return in seconds. 281 timeout: Timeout for the Javascript code to return in seconds.
221 Returns: 282 Returns:
222 A string of the verbatim output from the Javascript execution. 283 A string of the verbatim output from the Javascript execution.
223 """ 284 """
224 if not self._driver: 285 if not self._driver:
225 self._StartDriver() 286 self._StartDriver()
226 # TODO(robertogden): Use 'driver.set_script_timeout(timeout)' instead after 287 # TODO(robertogden): Use 'driver.set_script_timeout(timeout)' instead after
227 # crbug/672114 is fixed. 288 # crbug/672114 is fixed.
228 default_timeout = socket.getdefaulttimeout() 289 default_timeout = socket.getdefaulttimeout()
229 socket.setdefaulttimeout(timeout) 290 socket.setdefaulttimeout(timeout)
291 self._logger.debug('Set socket timeout to %f seconds', timeout)
230 script_result = self._driver.execute_script(script) 292 script_result = self._driver.execute_script(script)
293 self._logger.debug('Executed Javascript in browser: %s', script)
231 socket.setdefaulttimeout(default_timeout) 294 socket.setdefaulttimeout(default_timeout)
295 self._logger.debug('Set socket timeout to %s', str(default_timeout))
232 return script_result 296 return script_result
233 297
234 def ExecuteJavascriptStatement(self, script, timeout=30): 298 def ExecuteJavascriptStatement(self, script, timeout=30):
235 """Wraps ExecuteJavascript() for use with a single statement. 299 """Wraps ExecuteJavascript() for use with a single statement.
236 300
237 Behavior is analogous to 'function(){ return <script> }();' 301 Behavior is analogous to 'function(){ return <script> }();'
238 302
239 Args: 303 Args:
240 script: A string of Javascript code. 304 script: A string of Javascript code.
241 timeout: Timeout for the Javascript code to return in seconds. 305 timeout: Timeout for the Javascript code to return in seconds.
242 Returns: 306 Returns:
243 A string of the verbatim output from the Javascript execution. 307 A string of the verbatim output from the Javascript execution.
244 """ 308 """
245 return self.ExecuteJavascript("return " + script, timeout) 309 return self.ExecuteJavascript("return " + script, timeout)
246 310
247 def GetHistogram(self, histogram): 311 def GetHistogram(self, histogram):
248 js_query = 'statsCollectionController.getBrowserHistogram("%s")' % histogram 312 js_query = 'statsCollectionController.getBrowserHistogram("%s")' % histogram
249 string_response = self.ExecuteJavascriptStatement(js_query) 313 string_response = self.ExecuteJavascriptStatement(js_query)
314 self._logger.debug('Got %s histogram=%s', histogram, string_response)
250 return json.loads(string_response) 315 return json.loads(string_response)
251 316
252 def WaitForJavascriptExpression(self, expression, timeout, min_poll=0.1, 317 def WaitForJavascriptExpression(self, expression, timeout, min_poll=0.1,
253 max_poll=1): 318 max_poll=1):
254 """Waits for the given Javascript expression to evaluate to True within the 319 """Waits for the given Javascript expression to evaluate to True within the
255 given timeout. This method polls the Javascript expression within the range 320 given timeout. This method polls the Javascript expression within the range
256 of |min_poll| and |max_poll|. 321 of |min_poll| and |max_poll|.
257 322
258 Args: 323 Args:
259 expression: The Javascript expression to poll, as a string. 324 expression: The Javascript expression to poll, as a string.
260 min_poll: The most frequently to poll as a float. 325 min_poll: The most frequently to poll as a float.
261 max_poll: The least frequently to poll as a float. 326 max_poll: The least frequently to poll as a float.
262 Returns: The result of the expression. 327 Returns: The result of the expression.
263 """ 328 """
264 poll_interval = max(min(max_poll, float(timeout) / 10.0), min_poll) 329 poll_interval = max(min(max_poll, float(timeout) / 10.0), min_poll)
330 self._logger.debug('Poll interval=%f seconds', poll_interval)
265 result = self.ExecuteJavascriptStatement(expression) 331 result = self.ExecuteJavascriptStatement(expression)
266 total_waited_time = 0 332 total_waited_time = 0
267 while not result and total_waited_time < timeout: 333 while not result and total_waited_time < timeout:
268 time.sleep(poll_interval) 334 time.sleep(poll_interval)
269 total_waited_time += poll_interval 335 total_waited_time += poll_interval
270 result = self.ExecuteJavascriptStatement(expression) 336 result = self.ExecuteJavascriptStatement(expression)
271 if not result: 337 if not result:
338 self._logger.error('%s not true after %f seconds' % (expression, timeout))
272 raise Exception('%s not true after %f seconds' % (expression, timeout)) 339 raise Exception('%s not true after %f seconds' % (expression, timeout))
273 return result 340 return result
274 341
275 def GetPerformanceLogs(self, method_filter=r'Network\.responseReceived'): 342 def GetPerformanceLogs(self, method_filter=r'Network\.responseReceived'):
276 """Returns all logged Performance events from Chrome. 343 """Returns all logged Performance events from Chrome.
277 344
278 Args: 345 Args:
279 method_filter: A regex expression to match the method of logged events 346 method_filter: A regex expression to match the method of logged events
280 against. Only logs who's method matches the regex will be returned. 347 against. Only logs who's method matches the regex will be returned.
281 Returns: 348 Returns:
282 Performance logs as a list of dicts, since the last time this function was 349 Performance logs as a list of dicts, since the last time this function was
283 called. 350 called.
284 """ 351 """
285 all_messages = [] 352 all_messages = []
286 for log in self._driver.execute('getLog', {'type': 'performance'})['value']: 353 for log in self._driver.execute('getLog', {'type': 'performance'})['value']:
287 message = json.loads(log['message'])['message'] 354 message = json.loads(log['message'])['message']
355 self._logger.debug('Got Performance log: %s', log['message'])
288 if re.match(method_filter, message['method']): 356 if re.match(method_filter, message['method']):
289 all_messages.append(message) 357 all_messages.append(message)
358 self._logger.info('Got %d performance logs with filter method=%s',
359 len(all_messages), method_filter)
290 return all_messages 360 return all_messages
291 361
292 def GetHTTPResponses(self, include_favicon=False): 362 def GetHTTPResponses(self, include_favicon=False):
293 """Parses the Performance Logs and returns a list of HTTPResponse objects. 363 """Parses the Performance Logs and returns a list of HTTPResponse objects.
294 364
295 Use caution when calling this function multiple times. Only responses 365 Use caution when calling this function multiple times. Only responses
296 since the last time this function was called are returned (or since Chrome 366 since the last time this function was called are returned (or since Chrome
297 started, whichever is later). 367 started, whichever is later).
298 368
299 Args: 369 Args:
(...skipping 15 matching lines...) Expand all
315 else '', 385 else '',
316 'port': response_dict['remotePort'] if 'remotePort' in response_dict 386 'port': response_dict['remotePort'] if 'remotePort' in response_dict
317 else -1, 387 else -1,
318 'status': response_dict['status'] if 'status' in response_dict else -1, 388 'status': response_dict['status'] if 'status' in response_dict else -1,
319 'request_type': params['type'] if 'type' in params else '' 389 'request_type': params['type'] if 'type' in params else ''
320 } 390 }
321 return HTTPResponse(**http_response_dict) 391 return HTTPResponse(**http_response_dict)
322 all_responses = [] 392 all_responses = []
323 for message in self.GetPerformanceLogs(): 393 for message in self.GetPerformanceLogs():
324 response = MakeHTTPResponse(message) 394 response = MakeHTTPResponse(message)
395 self._logger.debug('New HTTPResponse: %s', str(response))
325 is_favicon = response.url.endswith('favicon.ico') 396 is_favicon = response.url.endswith('favicon.ico')
326 if not is_favicon or include_favicon: 397 if not is_favicon or include_favicon:
327 all_responses.append(response) 398 all_responses.append(response)
399 self._logger.info('%d new HTTPResponse objects found in the logs %s '
400 'favicons', len(all_responses), ('including' if include_favicon else
401 'not including'))
328 return all_responses 402 return all_responses
329 403
330 class HTTPResponse: 404 class HTTPResponse:
331 """This class represents a single HTTP transaction (request and response) by 405 """This class represents a single HTTP transaction (request and response) by
332 Chrome. 406 Chrome.
333 407
334 This class also includes several convenience functions for ChromeProxy 408 This class also includes several convenience functions for ChromeProxy
335 specific assertions. 409 specific assertions.
336 410
337 Attributes: 411 Attributes:
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 expected_via_header = ParseFlags().via_header_value 514 expected_via_header = ParseFlags().via_header_value
441 self.assertNotIn('via', http_response.response_headers) 515 self.assertNotIn('via', http_response.response_headers)
442 if 'via' in http_response.response_headers: 516 if 'via' in http_response.response_headers:
443 self.assertNotIn(expected_via_header, 517 self.assertNotIn(expected_via_header,
444 http_response.response_headers['via']) 518 http_response.response_headers['via'])
445 519
446 @staticmethod 520 @staticmethod
447 def RunAllTests(): 521 def RunAllTests():
448 """A simple helper method to run all tests using unittest.main(). 522 """A simple helper method to run all tests using unittest.main().
449 """ 523 """
524 flags = ParseFlags()
525 logger = GetLogger()
526 logger.debug('Command line args: %s', str(sys.argv))
527 logger.info('sys.argv parsed to %s', str(flags))
450 # The unittest library uses sys.argv itself and is easily confused by our 528 # The unittest library uses sys.argv itself and is easily confused by our
451 # command line options. Pass it a simpler argv instead, while working in the 529 # command line options. Pass it a simpler argv instead, while working in the
452 # unittest command line args functionality. 530 # unittest command line args functionality.
453 flags = ParseFlags()
454 unittest.main(argv=[sys.argv[0]], verbosity=2, failfast=flags.failfast, 531 unittest.main(argv=[sys.argv[0]], verbosity=2, failfast=flags.failfast,
455 catchbreak=flags.catch, buffer=(not flags.disable_buffer)) 532 catchbreak=flags.catch, buffer=(not flags.disable_buffer))
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698