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

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: Fix so that offline tests will work/Address Nirnimesh's 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 # The environment variable for the usage of Web Page Replay.
68 # It must be parsed before perf.BasePerfTest.setUp()
69 self._use_wpr = self._NeedReplayServer()
70 # Do NOT mannually set WPR_RECORD for the purpose of
71 # making recording archive for endure tests. Run record_endure.py instead.
72 if self._use_wpr:
73 self._is_replay_mode = 'WPR_RECORD' not in os.environ
74
65 # The environment variables for the Deep Memory Profiler must be set 75 # The environment variables for the Deep Memory Profiler must be set
66 # before perf.BasePerfTest.setUp() to inherit them to Chrome. 76 # before perf.BasePerfTest.setUp() to inherit them to Chrome.
67 self._deep_memory_profile = self._GetDeepMemoryProfileEnv( 77 self._deep_memory_profile = self._GetDeepMemoryProfileEnv(
68 'DEEP_MEMORY_PROFILE', bool, self._DEEP_MEMORY_PROFILE) 78 'DEEP_MEMORY_PROFILE', bool, self._DEEP_MEMORY_PROFILE)
69 79
70 self._deep_memory_profile_interval = self._GetDeepMemoryProfileEnv( 80 self._deep_memory_profile_interval = self._GetDeepMemoryProfileEnv(
71 'DEEP_MEMORY_PROFILE_INTERVAL', int, self._DEEP_MEMORY_PROFILE_INTERVAL) 81 'DEEP_MEMORY_PROFILE_INTERVAL', int, self._DEEP_MEMORY_PROFILE_INTERVAL)
72 82
73 if self._deep_memory_profile: 83 if self._deep_memory_profile:
74 if not self.IsLinux(): 84 if not self.IsLinux():
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 self._remote_inspector_client = ( 120 self._remote_inspector_client = (
111 remote_inspector_client.RemoteInspectorClient()) 121 remote_inspector_client.RemoteInspectorClient())
112 logging.info('Connection to remote inspector set up successfully.') 122 logging.info('Connection to remote inspector set up successfully.')
113 123
114 self._test_start_time = 0 124 self._test_start_time = 0
115 self._num_errors = 0 125 self._num_errors = 0
116 self._events_to_output = [] 126 self._events_to_output = []
117 self._deep_memory_profile_json_file = None 127 self._deep_memory_profile_json_file = None
118 self._deep_memory_profile_last_json_filename = '' 128 self._deep_memory_profile_last_json_filename = ''
119 self._deep_memory_profile_proc = None 129 self._deep_memory_profile_proc = None
130 self._StartReplayServerIfNecessary()
120 131
121 def tearDown(self): 132 def tearDown(self):
122 logging.info('Terminating connection to remote inspector...') 133 logging.info('Terminating connection to remote inspector...')
123 self._remote_inspector_client.Stop() 134 self._remote_inspector_client.Stop()
124 logging.info('Connection to remote inspector terminated.') 135 logging.info('Connection to remote inspector terminated.')
125 if self._deep_memory_profile: 136 if self._deep_memory_profile:
126 # TODO(dmikurube): Stop to set HEAP_PROFILE_TIME_INTERVAL in setUp when 137 # TODO(dmikurube): Stop to set HEAP_PROFILE_TIME_INTERVAL in setUp when
127 # PyAuto supports to dump renderer heap profile. 138 # PyAuto supports to dump renderer heap profile.
128 del os.environ['HEAP_PROFILE_TIME_INTERVAL'] 139 del os.environ['HEAP_PROFILE_TIME_INTERVAL']
129 del os.environ['DEEP_HEAP_PROFILE'] 140 del os.environ['DEEP_HEAP_PROFILE']
130 del os.environ['HEAP_PROFILE_MMAP'] 141 del os.environ['HEAP_PROFILE_MMAP']
131 del os.environ['HEAPPROFILE'] 142 del os.environ['HEAPPROFILE']
132 143
133 # Must be done at end of this function except for post-cleaning after 144 # Must be done at end of this function except for post-cleaning after
134 # Chrome finishes. 145 # Chrome finishes.
135 perf.BasePerfTest.tearDown(self) 146 perf.BasePerfTest.tearDown(self)
136 147
137 # Remove the temporary directory after Chrome finishes in tearDown. 148 # Remove the temporary directory after Chrome finishes in tearDown.
138 if (self._deep_memory_profile and 149 if (self._deep_memory_profile and
139 not self._deep_memory_profile_save and 150 not self._deep_memory_profile_save and
140 self._deep_tempdir): 151 self._deep_tempdir):
141 pyauto_utils.RemovePath(self._deep_tempdir) 152 pyauto_utils.RemovePath(self._deep_tempdir)
153 # Must be done after perf.BasePerfTest.tearDown()
154 self._StopReplayServerIfNecessary()
fdeng1 2012/08/02 22:57:30 StopReplayServerIfNecessary()/StartReplayServerIfN
155
156 def _NeedReplayServer(self):
157 """Check whether the test needs to run against Web Page Replay server.
158
159 Override this function to return False if you want to permanently
160 turn off Web Page Replay for a test.
161
162 Returns:
163 True if need replay server otherwise False.
164
165 Environment variable:
166 ENDURE_NO_WPR: if set, do not need replay server
167 """
168 if 'ENDURE_NO_WPR' in os.environ:
169 return False
170 else:
171 return True
172
fdeng1 2012/08/02 22:57:30 Two tests are offline and don't need WPR. These te
173 def _GenArchiveName(self):
174 """Returns the Web Page Replay archive name that corresponds to a test.
175
176 Use test class name as archive name, e.g. ChromeEndureGmailTest.wpr
177 Override this function to allow other names.
178
179 Returns:
180 An archive name generated using test class name.
181 """
182 # Use class name as archive name.
183 return self.id().split('.')[1] + '.wpr'
142 184
fdeng1 2012/08/02 22:57:30 I add a function called _GenArchiveName which uses
143 def _GetDeepMemoryProfileEnv(self, env_name, converter, default): 185 def _GetDeepMemoryProfileEnv(self, env_name, converter, default):
144 """Returns a converted environment variable for the Deep Memory Profiler. 186 """Returns a converted environment variable for the Deep Memory Profiler.
145 187
146 Args: 188 Args:
147 env_name: A string name of an environment variable. 189 env_name: A string name of an environment variable.
148 converter: A function taking a string to convert an environment variable. 190 converter: A function taking a string to convert an environment variable.
149 default: A value used if the environment variable is not specified. 191 default: A value used if the environment variable is not specified.
150 192
151 Returns: 193 Returns:
152 A value converted from the environment variable with 'converter'. 194 A value converted from the environment variable with 'converter'.
(...skipping 20 matching lines...) Expand all
173 # The same with setUp, but need to fetch the environment variable since 215 # The same with setUp, but need to fetch the environment variable since
174 # ExtraChromeFlags is called before setUp. 216 # ExtraChromeFlags is called before setUp.
175 deep_memory_profile = self._GetDeepMemoryProfileEnv( 217 deep_memory_profile = self._GetDeepMemoryProfileEnv(
176 'DEEP_MEMORY_PROFILE', bool, self._DEEP_MEMORY_PROFILE) 218 'DEEP_MEMORY_PROFILE', bool, self._DEEP_MEMORY_PROFILE)
177 219
178 # Ensure Chrome enables remote debugging on port 9222. This is required to 220 # Ensure Chrome enables remote debugging on port 9222. This is required to
179 # interact with Chrome's remote inspector. 221 # interact with Chrome's remote inspector.
180 extra_flags = ['--remote-debugging-port=9222'] 222 extra_flags = ['--remote-debugging-port=9222']
181 if deep_memory_profile: 223 if deep_memory_profile:
182 extra_flags.append('--no-sandbox') 224 extra_flags.append('--no-sandbox')
183 return (perf.BasePerfTest.ExtraChromeFlags(self) + extra_flags) 225 if self._use_wpr:
226 extra_flags.extend(ChromeEndureReplay.CHROME_FLAGS)
227 return perf.BasePerfTest.ExtraChromeFlags(self) + extra_flags
184 228
185 def _OnTimelineEvent(self, event_info): 229 def _OnTimelineEvent(self, event_info):
186 """Invoked by the Remote Inspector Client when a timeline event occurs. 230 """Invoked by the Remote Inspector Client when a timeline event occurs.
187 231
188 Args: 232 Args:
189 event_info: A dictionary containing raw information associated with a 233 event_info: A dictionary containing raw information associated with a
190 timeline event received from Chrome's remote inspector. Refer to 234 timeline event received from Chrome's remote inspector. Refer to
191 chrome/src/third_party/WebKit/Source/WebCore/inspector/Inspector.json 235 chrome/src/third_party/WebKit/Source/WebCore/inspector/Inspector.json
192 for the format of this dictionary. 236 for the format of this dictionary.
193 """ 237 """
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 try: 577 try:
534 element = self._GetElement(driver.find_element_by_xpath, xpath) 578 element = self._GetElement(driver.find_element_by_xpath, xpath)
535 element.click() 579 element.click()
536 except (selenium.common.exceptions.StaleElementReferenceException, 580 except (selenium.common.exceptions.StaleElementReferenceException,
537 selenium.common.exceptions.TimeoutException) as e: 581 selenium.common.exceptions.TimeoutException) as e:
538 logging.exception('WebDriver exception: %s' % e) 582 logging.exception('WebDriver exception: %s' % e)
539 return False 583 return False
540 584
541 return True 585 return True
542 586
587 def _StartReplayServerIfNecessary(self):
588 """Start replay server if necessary.
589
590 This method needs to be called BEFORE any connection (which is supposed
591 to go through the Web Page Replay server) occurs.
592 """
593 if self._use_wpr and self._is_replay_mode:
594 archive_name = self._GenArchiveName()
595 self._wpr_server = ChromeEndureReplay.ReplayServer(archive_name)
596 self._wpr_server.StartServer()
597 logging.info('Web Page Replay server has started in Replay mode.')
598
599 def _StopReplayServerIfNecessary(self):
600 """Stop the Web Page Replay server if necessary.
601
602 This method has to be called AFTER all network connections which go
603 through Web Page Replay server have shut down. Otherwise the
604 Web Page Replay server will hang to wait for them. A good
605 place is to call it at the end of the teardown process.
606 """
607 if self._use_wpr and self._is_replay_mode:
608 self._wpr_server.StopServer()
609 logging.info('The Web Page Replay server stopped.')
610
543 611
544 class ChromeEndureControlTest(ChromeEndureBaseTest): 612 class ChromeEndureControlTest(ChromeEndureBaseTest):
545 """Control tests for Chrome Endure.""" 613 """Control tests for Chrome Endure."""
546 614
547 _WEBAPP_NAME = 'Control' 615 _WEBAPP_NAME = 'Control'
548 _TAB_TITLE_SUBSTRING = 'Chrome Endure Control Test' 616 _TAB_TITLE_SUBSTRING = 'Chrome Endure Control Test'
549 617
618 def _NeedReplayServer(self):
619 """Override parent's function to remove replay support."""
620 return False
621
550 def testControlAttachDetachDOMTree(self): 622 def testControlAttachDetachDOMTree(self):
551 """Continually attach and detach a DOM tree from a basic document.""" 623 """Continually attach and detach a DOM tree from a basic document."""
552 test_description = 'AttachDetachDOMTree' 624 test_description = 'AttachDetachDOMTree'
553 url = self.GetHttpURLForDataPath('chrome_endure', 'endurance_control.html') 625 url = self.GetHttpURLForDataPath('chrome_endure', 'endurance_control.html')
554 self.NavigateToURL(url) 626 self.NavigateToURL(url)
555 loaded_tab_title = self.GetActiveTabTitle() 627 loaded_tab_title = self.GetActiveTabTitle()
556 self.assertTrue(self._TAB_TITLE_SUBSTRING in loaded_tab_title, 628 self.assertTrue(self._TAB_TITLE_SUBSTRING in loaded_tab_title,
557 msg='Loaded tab title does not contain "%s": "%s"' % 629 msg='Loaded tab title does not contain "%s": "%s"' %
558 (self._TAB_TITLE_SUBSTRING, loaded_tab_title)) 630 (self._TAB_TITLE_SUBSTRING, loaded_tab_title))
559 631
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after
1079 1151
1080 url = self.GetHttpURLForDataPath('indexeddb', 'endure', 'app.html') 1152 url = self.GetHttpURLForDataPath('indexeddb', 'endure', 'app.html')
1081 self.NavigateToURL(url) 1153 self.NavigateToURL(url)
1082 loaded_tab_title = self.GetActiveTabTitle() 1154 loaded_tab_title = self.GetActiveTabTitle()
1083 self.assertTrue(self._TAB_TITLE_SUBSTRING in loaded_tab_title, 1155 self.assertTrue(self._TAB_TITLE_SUBSTRING in loaded_tab_title,
1084 msg='Loaded tab title does not contain "%s": "%s"' % 1156 msg='Loaded tab title does not contain "%s": "%s"' %
1085 (self._TAB_TITLE_SUBSTRING, loaded_tab_title)) 1157 (self._TAB_TITLE_SUBSTRING, loaded_tab_title))
1086 1158
1087 self._driver = self.NewWebDriver() 1159 self._driver = self.NewWebDriver()
1088 1160
1161 def _NeedReplayServer(self):
1162 """Override parent's function to remove replay support."""
1163 return False
1164
1089 def testOfflineOnline(self): 1165 def testOfflineOnline(self):
1090 """Simulates user input while offline and sync while online. 1166 """Simulates user input while offline and sync while online.
1091 1167
1092 This test alternates between a simulated "Offline" state (where user 1168 This test alternates between a simulated "Offline" state (where user
1093 input events are queued) and an "Online" state (where user input events 1169 input events are queued) and an "Online" state (where user input events
1094 are dequeued, sync data is staged, and sync data is unstaged). 1170 are dequeued, sync data is staged, and sync data is unstaged).
1095 """ 1171 """
1096 test_description = 'OnlineOfflineSync' 1172 test_description = 'OnlineOfflineSync'
1097 1173
1098 def scenario(): 1174 def scenario():
(...skipping 18 matching lines...) Expand all
1117 except (pyauto_errors.JSONInterfaceError, 1193 except (pyauto_errors.JSONInterfaceError,
1118 pyauto_errors.JavascriptRuntimeError): 1194 pyauto_errors.JavascriptRuntimeError):
1119 self._num_errors += 1 1195 self._num_errors += 1
1120 1196
1121 time.sleep(1) 1197 time.sleep(1)
1122 1198
1123 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, 1199 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING,
1124 test_description, scenario) 1200 test_description, scenario)
1125 1201
1126 1202
1203 class ChromeEndureReplay(object):
1204 """Run Chrome Endure tests with network simulation via Web Page Replay."""
1205
1206 _PATHS = {
1207 'archive':
1208 'src/chrome/test/data/pyauto_private/webpagereplay/{archive_name}',
1209 'scripts':
1210 'src/chrome/test/data/chrome_endure/webpagereplay/wpr_deterministic.js',
1211 }
1212 CHROME_FLAGS = webpagereplay.CHROME_FLAGS
1213
1214 @classmethod
1215 def Path(cls, key, **kwargs):
1216 return perf.FormatChromePath(cls._PATHS[key], **kwargs)
1217
1218 @classmethod
1219 def ReplayServer(cls, archive_name):
1220 """Creat a replay server."""
1221 # Inject customized scripts for Google webapps.
1222 # See the java script file for details.
1223 scripts = cls.Path('scripts')
1224 if not os.path.exists(scripts):
1225 raise webpagereplay.ReplayNotFoundError('injected scripts', scripts)
1226 replay_options = ['--inject_scripts', scripts]
1227 archive_path = cls.Path('archive', archive_name=archive_name)
1228 return webpagereplay.ReplayServer(archive_path, replay_options)
1229
1230
1127 if __name__ == '__main__': 1231 if __name__ == '__main__':
1128 pyauto_functional.Main() 1232 pyauto_functional.Main()
OLDNEW
« no previous file with comments | « chrome/test/data/chrome_endure/webpagereplay/wpr_deterministic.js ('k') | chrome/test/functional/record_endure.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698