Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 collections | 5 import collections |
| 6 import logging | 6 import logging |
| 7 import re | 7 import re |
| 8 import sys | 8 import sys |
| 9 import urllib | 9 import urllib |
| 10 | 10 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 57 The story_set is expected to include SinglePage instances (class defined | 57 The story_set is expected to include SinglePage instances (class defined |
| 58 below) mapping each page to a browser on which to run. The state | 58 below) mapping each page to a browser on which to run. The state |
| 59 requires at least one page to run on the 'default' browser, i.e. the | 59 requires at least one page to run on the 'default' browser, i.e. the |
| 60 browser selected from the command line by the user. | 60 browser selected from the command line by the user. |
| 61 """ | 61 """ |
| 62 super(MultiBrowserSharedState, self).__init__( | 62 super(MultiBrowserSharedState, self).__init__( |
| 63 test, finder_options, story_set) | 63 test, finder_options, story_set) |
| 64 self._platform = None | 64 self._platform = None |
| 65 self._story_set = story_set | 65 self._story_set = story_set |
| 66 self._possible_browsers = {} | 66 self._possible_browsers = {} |
| 67 # We use an ordered dict to request memory dumps in a deterministic order. | 67 # We use an ordered dict to record the order in which browsers appear on |
| 68 self._browsers = collections.OrderedDict() | 68 # the story set. However, browsers are not created yet. |
| 69 self._browsers_created = False | |
| 70 self._browsers = collections.OrderedDict( | |
| 71 (s.browser_type, None) for s in story_set) | |
| 69 self._current_story = None | 72 self._current_story = None |
| 70 self._current_browser = None | 73 self._current_browser = None |
| 71 self._current_tab = None | 74 self._current_tab = None |
| 72 | 75 |
| 73 possible_browser = self._PrepareBrowser('default', finder_options) | 76 possible_browser = self._PrepareBrowser('default', finder_options) |
| 74 if not possible_browser: | 77 if not possible_browser: |
| 75 raise browser_finder_exceptions.BrowserFinderException( | 78 raise browser_finder_exceptions.BrowserFinderException( |
| 76 'No browser found.\n\nAvailable browsers:\n%s\n' % | 79 'No browser found.\n\nAvailable browsers:\n%s\n' % |
| 77 '\n'.join(browser_finder.GetAllAvailableBrowserTypes(finder_options))) | 80 '\n'.join(browser_finder.GetAllAvailableBrowserTypes(finder_options))) |
| 78 if not finder_options.run_disabled_tests: | 81 if not finder_options.run_disabled_tests: |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 131 if possible_browser is None: | 134 if possible_browser is None: |
| 132 return None | 135 return None |
| 133 | 136 |
| 134 if self._platform is None: | 137 if self._platform is None: |
| 135 self._platform = possible_browser.platform | 138 self._platform = possible_browser.platform |
| 136 else: | 139 else: |
| 137 assert self._platform is possible_browser.platform | 140 assert self._platform is possible_browser.platform |
| 138 self._possible_browsers[browser_type] = (possible_browser, options) | 141 self._possible_browsers[browser_type] = (possible_browser, options) |
| 139 return possible_browser | 142 return possible_browser |
| 140 | 143 |
| 141 def _SetCurrentBrowser(self, browser_type): | 144 def _CreateAllBrowsersIfNeeeded(self): |
| 142 """Select a browser of the given type and bring it to the foreground. | 145 """Launch all browsers needed for the story set, if not already done. |
| 143 | 146 |
| 144 This launches the browser if it does not exist already or, otherwise, moves | 147 This ensures that all browsers are alive during the whole duration of the |
| 145 the existing browser to the foreground. | 148 benchmark and, therefore, e.g. memory dumps are always provided for all |
| 149 of them. | |
| 146 """ | 150 """ |
| 147 if not browser_type in self._browsers: | 151 if self._browsers_created: |
|
nednguyen
2016/06/23 13:13:26
Are we calling _CreateAllBrowsersIfNeeeded twice a
nednguyen
2016/06/23 13:14:06
nvm, I forgot that WillRunStory is called in the l
| |
| 152 return | |
| 153 for browser_type in self._browsers: | |
| 148 possible_browser, options = self._possible_browsers[browser_type] | 154 possible_browser, options = self._possible_browsers[browser_type] |
| 149 self._current_browser = possible_browser.Create(options) | 155 self._browsers[browser_type] = possible_browser.Create(options) |
| 150 self._browsers[browser_type] = self._current_browser | 156 self._browsers_created = True |
| 151 else: | 157 |
| 152 self._current_browser = self._browsers[browser_type] | 158 def _CloseAllBrowsers(self): |
| 153 self._current_browser.Foreground() | 159 """Close all of the browsers that were launched for this benchmark.""" |
| 160 if not self._browsers_created: | |
| 161 return | |
| 162 for browser_type, browser in self._browsers.iteritems(): | |
| 163 try: | |
| 164 browser.Close() | |
| 165 except Exception: | |
| 166 logging.exception('Error while closing %s browser', browser_type) | |
| 167 self._browsers[browser_type] = None | |
| 168 self._browsers_created = False | |
| 154 | 169 |
| 155 def CanRunStory(self, _): | 170 def CanRunStory(self, _): |
| 156 return True | 171 return True |
| 157 | 172 |
| 158 def WillRunStory(self, story): | 173 def WillRunStory(self, story): |
| 159 self._current_story = story | 174 self._current_story = story |
| 160 | 175 |
| 161 self.platform.network_controller.StartReplay( | 176 self.platform.network_controller.StartReplay( |
| 162 self._story_set.WprFilePathForStory(story), | 177 self._story_set.WprFilePathForStory(story), |
| 163 story.make_javascript_deterministic) | 178 story.make_javascript_deterministic) |
| 164 | 179 |
| 165 self._SetCurrentBrowser(self._current_story.browser_type) | 180 # Note: browsers need to be created after replay has been started. |
| 181 self._CreateAllBrowsersIfNeeeded() | |
| 182 self._current_browser = self._browsers[story.browser_type] | |
| 183 self._current_browser.Foreground() | |
| 166 self._current_tab = self._current_browser.foreground_tab | 184 self._current_tab = self._current_browser.foreground_tab |
| 167 | 185 |
| 168 def RunStory(self, _): | 186 def RunStory(self, _): |
| 169 self._current_story.Run(self) | 187 self._current_story.Run(self) |
| 170 | 188 |
| 171 def DidRunStory(self, _): | 189 def DidRunStory(self, _): |
| 172 self._current_story = None | 190 self._current_story = None |
| 173 | 191 |
| 174 def TakeMemoryMeasurement(self): | 192 def TakeMemoryMeasurement(self): |
| 175 self.current_tab.action_runner.ForceGarbageCollection() | 193 self.current_tab.action_runner.ForceGarbageCollection() |
| 176 self.platform.FlushEntireSystemCache() | 194 self.platform.FlushEntireSystemCache() |
| 177 if not self.platform.tracing_controller.is_tracing_running: | 195 if not self.platform.tracing_controller.is_tracing_running: |
| 178 return # Tracing is not running, e.g., when recording a WPR archive. | 196 return # Tracing is not running, e.g., when recording a WPR archive. |
| 179 for browser_type, browser in self._browsers.iteritems(): | 197 for browser_type, browser in self._browsers.iteritems(): |
| 180 if not browser.DumpMemory(): | 198 if not browser.DumpMemory(): |
| 181 logging.error('Unable to dump memory for %s', browser_type) | 199 logging.error('Unable to dump memory for %s', browser_type) |
| 182 | 200 |
| 183 def TearDownState(self): | 201 def TearDownState(self): |
| 184 self.platform.network_controller.Close() | 202 self.platform.network_controller.Close() |
| 185 | 203 self._CloseAllBrowsers() |
| 186 for browser_type, browser in self._browsers.iteritems(): | |
| 187 try: | |
| 188 browser.Close() | |
| 189 except Exception: | |
| 190 logging.exception('Error while closing browser: %s', browser_type) | |
| 191 self._browsers = None # Not usable after tearing down. | |
| 192 | 204 |
| 193 def DumpStateUponFailure(self, unused_story, unused_results): | 205 def DumpStateUponFailure(self, unused_story, unused_results): |
| 194 if self._browsers: | 206 if self._browsers: |
| 195 for browser_type, browser in self._browsers.iteritems(): | 207 for browser_type, browser in self._browsers.iteritems(): |
| 196 logging.info('vvvvv BROWSER STATE BELOW FOR \'%s\' vvvvv', browser_type) | 208 logging.info('vvvvv BROWSER STATE BELOW FOR \'%s\' vvvvv', browser_type) |
| 197 browser.DumpStateUponFailure() | 209 browser.DumpStateUponFailure() |
| 198 else: | 210 else: |
| 199 logging.warning('Cannot dump browser states: No browsers.') | 211 logging.warning('Cannot dump browser states: No browsers.') |
| 200 | 212 |
| 201 | 213 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 246 url=GOOGLE_SEARCH + urllib.urlencode({'q': query}), | 258 url=GOOGLE_SEARCH + urllib.urlencode({'q': query}), |
| 247 browser_type='android-webview', | 259 browser_type='android-webview', |
| 248 phase='on_webview')) | 260 phase='on_webview')) |
| 249 | 261 |
| 250 # Stories that run on the browser selected by command line options. | 262 # Stories that run on the browser selected by command line options. |
| 251 self.AddStory(SinglePage( | 263 self.AddStory(SinglePage( |
| 252 name=re.sub('\W+', '_', url), | 264 name=re.sub('\W+', '_', url), |
| 253 url=url, | 265 url=url, |
| 254 browser_type='default', | 266 browser_type='default', |
| 255 phase='on_chrome')) | 267 phase='on_chrome')) |
| OLD | NEW |