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

Side by Side Diff: chrome/test/functional/perf_endure.py

Issue 10803002: Run Chrome Endure tests with network simulation via Web Page Replay. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Dennis' comments Created 8 years, 4 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Performance tests for Chrome Endure (long-running perf tests on Chrome). 6 """Performance tests for Chrome Endure (long-running perf tests on Chrome).
7 7
8 This module accepts the following environment variable inputs: 8 This module accepts the following environment variable inputs:
9 TEST_LENGTH: The number of seconds in which to run each test. 9 TEST_LENGTH: The number of seconds in which to run each test.
10 PERF_STATS_INTERVAL: The number of seconds to wait in-between each sampling 10 PERF_STATS_INTERVAL: The number of seconds to wait in-between each sampling
(...skipping 15 matching lines...) Expand all
26 import time 26 import time
27 27
28 import perf 28 import perf
29 import pyauto_functional # Must be imported before pyauto. 29 import pyauto_functional # Must be imported before pyauto.
30 import pyauto 30 import pyauto
31 import pyauto_errors 31 import pyauto_errors
32 import pyauto_utils 32 import pyauto_utils
33 import remote_inspector_client 33 import remote_inspector_client
34 import selenium.common.exceptions 34 import selenium.common.exceptions
35 from selenium.webdriver.support.ui import WebDriverWait 35 from selenium.webdriver.support.ui import WebDriverWait
36 import webpagereplay
36 37
37 38
38 class NotSupportedEnvironmentError(RuntimeError): 39 class NotSupportedEnvironmentError(RuntimeError):
39 """Represent an error raised since the environment (OS) is not supported.""" 40 """Represent an error raised since the environment (OS) is not supported."""
40 pass 41 pass
41 42
43
42 class ChromeEndureBaseTest(perf.BasePerfTest): 44 class ChromeEndureBaseTest(perf.BasePerfTest):
43 """Implements common functionality for all Chrome Endure tests. 45 """Implements common functionality for all Chrome Endure tests.
44 46
45 All Chrome Endure test classes should inherit from this class. 47 All Chrome Endure test classes should inherit from this class.
46 """ 48 """
47 49
48 _DEFAULT_TEST_LENGTH_SEC = 60 * 60 * 6 # Tests run for 6 hours. 50 _DEFAULT_TEST_LENGTH_SEC = 60 * 60 * 6 # Tests run for 6 hours.
49 _GET_PERF_STATS_INTERVAL = 60 * 5 # Measure perf stats every 5 minutes. 51 _GET_PERF_STATS_INTERVAL = 60 * 5 # Measure perf stats every 5 minutes.
50 # TODO(dennisjeffrey): Do we still need to tolerate errors? 52 # TODO(dennisjeffrey): Do we still need to tolerate errors?
51 _ERROR_COUNT_THRESHOLD = 50 # Number of ChromeDriver errors to tolerate. 53 _ERROR_COUNT_THRESHOLD = 50 # Number of ChromeDriver errors to tolerate.
52 _DEEP_MEMORY_PROFILE = False 54 _DEEP_MEMORY_PROFILE = False
53 _DEEP_MEMORY_PROFILE_INTERVAL = _GET_PERF_STATS_INTERVAL 55 _DEEP_MEMORY_PROFILE_INTERVAL = _GET_PERF_STATS_INTERVAL
54 _DEEP_MEMORY_PROFILE_SAVE = False 56 _DEEP_MEMORY_PROFILE_SAVE = False
55 57
56 _DMPROF_DIR_PATH = os.path.join( 58 _DMPROF_DIR_PATH = os.path.join(
57 os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, 59 os.path.dirname(__file__), os.pardir, os.pardir, os.pardir,
58 'tools', 'deep_memory_profiler') 60 'tools', 'deep_memory_profiler')
59 61
60 _DMPROF_SCRIPT_PATH = os.path.join(_DMPROF_DIR_PATH, 'dmprof') 62 _DMPROF_SCRIPT_PATH = os.path.join(_DMPROF_DIR_PATH, 'dmprof')
61 63
62 _CHROME_BIN_PATH = os.path.join(perf.BasePerfTest.BrowserPath(), 'chrome') 64 _CHROME_BIN_PATH = os.path.join(perf.BasePerfTest.BrowserPath(), 'chrome')
63 65
64 def setUp(self): 66 def setUp(self):
67 # Parse the environment variable for the usage of Web Page Replay.
Nirnimesh 2012/08/06 21:36:45 please move the env parsing to a helper method so
fdeng1 2012/08/07 02:56:56 Done. move it to _ParseReplayEnv()
68 # It must be parsed before perf.BasePerfTest.setUp()
69 if 'ENDURE_NO_WPR' in os.environ:
70 self._use_wpr = False
71 logging.info('Web Page Replay is turned off as ENDURE_NO_WPR is set.')
dennis_jeffrey 2012/08/06 21:33:46 how about this to match slamm's recommended commen
fdeng1 2012/08/07 02:56:56 Done.
72 else:
73 # Do NOT manually set WPR_RECORD for the purpose of
74 # making recording archive for endure tests. Run record_endure.py instead.
75 self._is_record_mode = 'WPR_RECORD' in os.environ
76 archive_path = os.environ.get('WPR_ARCHIVE_PATH',
77 ChromeEndureReplay.Path(
78 'archive', archive_name=self._GenArchiveName()))
79 if self._is_record_mode or os.path.exists(archive_path):
80 self._use_wpr = True
dennis_jeffrey 2012/08/06 21:33:46 log a message in this case saying something like "
fdeng1 2012/08/07 02:56:56 When WPR is successfully launched, _StartReplaySer
81 else:
82 self._use_wpr = False
83 logging.info(
84 'Web Page Replay is turned off as the' +
85 ' archive file %s does not exist.',
slamm_google 2012/08/06 20:58:44 How about the following? Skipping Web Page Replay
fdeng1 2012/08/07 02:56:56 Done.
86 self._GenArchiveName())
65 # The environment variables for the Deep Memory Profiler must be set 87 # The environment variables for the Deep Memory Profiler must be set
66 # before perf.BasePerfTest.setUp() to inherit them to Chrome. 88 # before perf.BasePerfTest.setUp() to inherit them to Chrome.
67 self._deep_memory_profile = self._GetDeepMemoryProfileEnv( 89 self._deep_memory_profile = self._GetDeepMemoryProfileEnv(
68 'DEEP_MEMORY_PROFILE', bool, self._DEEP_MEMORY_PROFILE) 90 'DEEP_MEMORY_PROFILE', bool, self._DEEP_MEMORY_PROFILE)
69 91
70 self._deep_memory_profile_interval = self._GetDeepMemoryProfileEnv( 92 self._deep_memory_profile_interval = self._GetDeepMemoryProfileEnv(
71 'DEEP_MEMORY_PROFILE_INTERVAL', int, self._DEEP_MEMORY_PROFILE_INTERVAL) 93 'DEEP_MEMORY_PROFILE_INTERVAL', int, self._DEEP_MEMORY_PROFILE_INTERVAL)
72 94
73 if self._deep_memory_profile: 95 if self._deep_memory_profile:
74 if not self.IsLinux(): 96 if not self.IsLinux():
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 self._remote_inspector_client = ( 132 self._remote_inspector_client = (
111 remote_inspector_client.RemoteInspectorClient()) 133 remote_inspector_client.RemoteInspectorClient())
112 logging.info('Connection to remote inspector set up successfully.') 134 logging.info('Connection to remote inspector set up successfully.')
113 135
114 self._test_start_time = 0 136 self._test_start_time = 0
115 self._num_errors = 0 137 self._num_errors = 0
116 self._events_to_output = [] 138 self._events_to_output = []
117 self._deep_memory_profile_json_file = None 139 self._deep_memory_profile_json_file = None
118 self._deep_memory_profile_last_json_filename = '' 140 self._deep_memory_profile_last_json_filename = ''
119 self._deep_memory_profile_proc = None 141 self._deep_memory_profile_proc = None
142 self._StartReplayServerIfNecessary()
120 143
121 def tearDown(self): 144 def tearDown(self):
122 logging.info('Terminating connection to remote inspector...') 145 logging.info('Terminating connection to remote inspector...')
123 self._remote_inspector_client.Stop() 146 self._remote_inspector_client.Stop()
124 logging.info('Connection to remote inspector terminated.') 147 logging.info('Connection to remote inspector terminated.')
125 if self._deep_memory_profile: 148 if self._deep_memory_profile:
126 # TODO(dmikurube): Stop to set HEAP_PROFILE_TIME_INTERVAL in setUp when 149 # TODO(dmikurube): Stop to set HEAP_PROFILE_TIME_INTERVAL in setUp when
127 # PyAuto supports to dump renderer heap profile. 150 # PyAuto supports to dump renderer heap profile.
128 del os.environ['HEAP_PROFILE_TIME_INTERVAL'] 151 del os.environ['HEAP_PROFILE_TIME_INTERVAL']
129 del os.environ['DEEP_HEAP_PROFILE'] 152 del os.environ['DEEP_HEAP_PROFILE']
130 del os.environ['HEAP_PROFILE_MMAP'] 153 del os.environ['HEAP_PROFILE_MMAP']
131 del os.environ['HEAPPROFILE'] 154 del os.environ['HEAPPROFILE']
132 155
133 # Must be done at end of this function except for post-cleaning after 156 # Must be done at end of this function except for post-cleaning after
134 # Chrome finishes. 157 # Chrome finishes.
135 perf.BasePerfTest.tearDown(self) 158 perf.BasePerfTest.tearDown(self)
136 159
137 # Remove the temporary directory after Chrome finishes in tearDown. 160 # Remove the temporary directory after Chrome finishes in tearDown.
138 if (self._deep_memory_profile and 161 if (self._deep_memory_profile and
139 not self._deep_memory_profile_save and 162 not self._deep_memory_profile_save and
140 self._deep_tempdir): 163 self._deep_tempdir):
141 pyauto_utils.RemovePath(self._deep_tempdir) 164 pyauto_utils.RemovePath(self._deep_tempdir)
165 # Must be done after perf.BasePerfTest.tearDown()
166 self._StopReplayServerIfNecessary()
167
168 def _GenArchiveName(self):
169 """Returns the Web Page Replay archive name that corresponds to a test.
170
171 Use test class name as archive name, e.g. ChromeEndureGmailTest.wpr,
Nirnimesh 2012/08/06 21:36:45 While this is nifty to auto-generate the archive n
fdeng1 2012/08/07 02:56:56 As discussed offline, I override _GetArchiveName i
172 which means we only have 1 archive file per test class.
173 Override this function to allow other names.
174
175 Returns:
176 An archive name generated using test class name.
177 """
178 # Use class name as archive name.
179 return self.id().split('.')[1] + '.wpr'
142 180
143 def _GetDeepMemoryProfileEnv(self, env_name, converter, default): 181 def _GetDeepMemoryProfileEnv(self, env_name, converter, default):
144 """Returns a converted environment variable for the Deep Memory Profiler. 182 """Returns a converted environment variable for the Deep Memory Profiler.
145 183
146 Args: 184 Args:
147 env_name: A string name of an environment variable. 185 env_name: A string name of an environment variable.
148 converter: A function taking a string to convert an environment variable. 186 converter: A function taking a string to convert an environment variable.
149 default: A value used if the environment variable is not specified. 187 default: A value used if the environment variable is not specified.
150 188
151 Returns: 189 Returns:
(...skipping 21 matching lines...) Expand all
173 # The same with setUp, but need to fetch the environment variable since 211 # The same with setUp, but need to fetch the environment variable since
174 # ExtraChromeFlags is called before setUp. 212 # ExtraChromeFlags is called before setUp.
175 deep_memory_profile = self._GetDeepMemoryProfileEnv( 213 deep_memory_profile = self._GetDeepMemoryProfileEnv(
176 'DEEP_MEMORY_PROFILE', bool, self._DEEP_MEMORY_PROFILE) 214 'DEEP_MEMORY_PROFILE', bool, self._DEEP_MEMORY_PROFILE)
177 215
178 # Ensure Chrome enables remote debugging on port 9222. This is required to 216 # Ensure Chrome enables remote debugging on port 9222. This is required to
179 # interact with Chrome's remote inspector. 217 # interact with Chrome's remote inspector.
180 extra_flags = ['--remote-debugging-port=9222'] 218 extra_flags = ['--remote-debugging-port=9222']
181 if deep_memory_profile: 219 if deep_memory_profile:
182 extra_flags.append('--no-sandbox') 220 extra_flags.append('--no-sandbox')
183 return (perf.BasePerfTest.ExtraChromeFlags(self) + extra_flags) 221 if self._use_wpr:
222 extra_flags.extend(ChromeEndureReplay.CHROME_FLAGS)
223 return perf.BasePerfTest.ExtraChromeFlags(self) + extra_flags
184 224
185 def _OnTimelineEvent(self, event_info): 225 def _OnTimelineEvent(self, event_info):
186 """Invoked by the Remote Inspector Client when a timeline event occurs. 226 """Invoked by the Remote Inspector Client when a timeline event occurs.
187 227
188 Args: 228 Args:
189 event_info: A dictionary containing raw information associated with a 229 event_info: A dictionary containing raw information associated with a
190 timeline event received from Chrome's remote inspector. Refer to 230 timeline event received from Chrome's remote inspector. Refer to
191 chrome/src/third_party/WebKit/Source/WebCore/inspector/Inspector.json 231 chrome/src/third_party/WebKit/Source/WebCore/inspector/Inspector.json
192 for the format of this dictionary. 232 for the format of this dictionary.
193 """ 233 """
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 try: 573 try:
534 element = self._GetElement(driver.find_element_by_xpath, xpath) 574 element = self._GetElement(driver.find_element_by_xpath, xpath)
535 element.click() 575 element.click()
536 except (selenium.common.exceptions.StaleElementReferenceException, 576 except (selenium.common.exceptions.StaleElementReferenceException,
537 selenium.common.exceptions.TimeoutException) as e: 577 selenium.common.exceptions.TimeoutException) as e:
538 logging.exception('WebDriver exception: %s' % e) 578 logging.exception('WebDriver exception: %s' % e)
539 return False 579 return False
540 580
541 return True 581 return True
542 582
583 def _StartReplayServerIfNecessary(self):
584 """Start replay server if necessary.
585
586 This method needs to be called BEFORE any connection (which is supposed
587 to go through the Web Page Replay server) occurs.
588 """
589 if self._use_wpr and not self._is_record_mode:
590 archive_name = self._GenArchiveName()
591 self._wpr_server = ChromeEndureReplay.ReplayServer(archive_name)
592 self._wpr_server.StartServer()
593 logging.info('Web Page Replay server has started in Replay mode.')
594
595 def _StopReplayServerIfNecessary(self):
596 """Stop the Web Page Replay server if necessary.
597
598 This method has to be called AFTER all network connections which go
599 through Web Page Replay server have shut down. Otherwise the
600 Web Page Replay server will hang to wait for them. A good
601 place is to call it at the end of the teardown process.
602 """
603 if self._use_wpr and not self._is_record_mode:
604 self._wpr_server.StopServer()
605 logging.info('The Web Page Replay server stopped.')
606
543 607
544 class ChromeEndureControlTest(ChromeEndureBaseTest): 608 class ChromeEndureControlTest(ChromeEndureBaseTest):
545 """Control tests for Chrome Endure.""" 609 """Control tests for Chrome Endure."""
546 610
547 _WEBAPP_NAME = 'Control' 611 _WEBAPP_NAME = 'Control'
548 _TAB_TITLE_SUBSTRING = 'Chrome Endure Control Test' 612 _TAB_TITLE_SUBSTRING = 'Chrome Endure Control Test'
549 613
550 def testControlAttachDetachDOMTree(self): 614 def testControlAttachDetachDOMTree(self):
551 """Continually attach and detach a DOM tree from a basic document.""" 615 """Continually attach and detach a DOM tree from a basic document."""
552 test_description = 'AttachDetachDOMTree' 616 test_description = 'AttachDetachDOMTree'
(...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after
1116 except (pyauto_errors.JSONInterfaceError, 1180 except (pyauto_errors.JSONInterfaceError,
1117 pyauto_errors.JavascriptRuntimeError): 1181 pyauto_errors.JavascriptRuntimeError):
1118 self._num_errors += 1 1182 self._num_errors += 1
1119 1183
1120 time.sleep(1) 1184 time.sleep(1)
1121 1185
1122 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, 1186 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING,
1123 test_description, scenario) 1187 test_description, scenario)
1124 1188
1125 1189
1190 class ChromeEndureReplay(object):
1191 """Run Chrome Endure tests with network simulation via Web Page Replay."""
1192
1193 _PATHS = {
1194 'archive':
1195 'src/chrome/test/data/pyauto_private/webpagereplay/{archive_name}',
1196 'scripts':
1197 'src/chrome/test/data/chrome_endure/webpagereplay/wpr_deterministic.js',
1198 }
1199 CHROME_FLAGS = webpagereplay.CHROME_FLAGS
1200
1201 @classmethod
1202 def Path(cls, key, **kwargs):
1203 return perf.FormatChromePath(cls._PATHS[key], **kwargs)
1204
1205 @classmethod
1206 def ReplayServer(cls, archive_name):
1207 """Creat a replay server."""
1208 # Inject customized scripts for Google webapps.
1209 # See the java script file for details.
Nirnimesh 2012/08/06 21:36:45 java script -> javascript
fdeng1 2012/08/07 02:56:56 Done.
1210 scripts = cls.Path('scripts')
1211 if not os.path.exists(scripts):
1212 raise webpagereplay.ReplayNotFoundError('injected scripts', scripts)
1213 replay_options = ['--inject_scripts', scripts]
1214 archive_path = cls.Path('archive', archive_name=archive_name)
1215 return webpagereplay.ReplayServer(archive_path, replay_options)
1216
1217
1126 if __name__ == '__main__': 1218 if __name__ == '__main__':
1127 pyauto_functional.Main() 1219 pyauto_functional.Main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698