OLD | NEW |
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 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 | 195 |
196 if event_info['type'] == 'GCEvent': | 196 if event_info['type'] == 'GCEvent': |
197 self._events_to_output.append({ | 197 self._events_to_output.append({ |
198 'type': 'GarbageCollection', | 198 'type': 'GarbageCollection', |
199 'time': elapsed_time, | 199 'time': elapsed_time, |
200 'data': | 200 'data': |
201 {'collected_bytes': event_info['data']['usedHeapSizeDelta']}, | 201 {'collected_bytes': event_info['data']['usedHeapSizeDelta']}, |
202 }) | 202 }) |
203 | 203 |
204 def _RunEndureTest(self, webapp_name, tab_title_substring, test_description, | 204 def _RunEndureTest(self, webapp_name, tab_title_substring, test_description, |
205 do_scenario): | 205 do_scenario, frame_xpath=''): |
206 """The main test harness function to run a general Chrome Endure test. | 206 """The main test harness function to run a general Chrome Endure test. |
207 | 207 |
208 After a test has performed any setup work and has navigated to the proper | 208 After a test has performed any setup work and has navigated to the proper |
209 starting webpage, this function should be invoked to run the endurance test. | 209 starting webpage, this function should be invoked to run the endurance test. |
210 | 210 |
211 Args: | 211 Args: |
212 webapp_name: A string name for the webapp being tested. Should not | 212 webapp_name: A string name for the webapp being tested. Should not |
213 include spaces. For example, 'Gmail', 'Docs', or 'Plus'. | 213 include spaces. For example, 'Gmail', 'Docs', or 'Plus'. |
214 tab_title_substring: A unique substring contained within the title of | 214 tab_title_substring: A unique substring contained within the title of |
215 the tab to use, for identifying the appropriate tab. | 215 the tab to use, for identifying the appropriate tab. |
216 test_description: A string description of what the test does, used for | 216 test_description: A string description of what the test does, used for |
217 outputting results to be graphed. Should not contain spaces. For | 217 outputting results to be graphed. Should not contain spaces. For |
218 example, 'ComposeDiscard' for Gmail. | 218 example, 'ComposeDiscard' for Gmail. |
219 do_scenario: A callable to be invoked that implements the scenario to be | 219 do_scenario: A callable to be invoked that implements the scenario to be |
220 performed by this test. The callable is invoked iteratively for the | 220 performed by this test. The callable is invoked iteratively for the |
221 duration of the test. | 221 duration of the test. |
| 222 frame_xpath: The string xpath of the frame in which to inject javascript |
| 223 to clear chromedriver's cache (a temporary workaround until the |
| 224 WebDriver team changes how they handle their DOM node cache). |
222 """ | 225 """ |
223 self._num_errors = 0 | 226 self._num_errors = 0 |
224 self._test_start_time = time.time() | 227 self._test_start_time = time.time() |
225 last_perf_stats_time = time.time() | 228 last_perf_stats_time = time.time() |
226 self._GetPerformanceStats( | 229 self._GetPerformanceStats( |
227 webapp_name, test_description, tab_title_substring) | 230 webapp_name, test_description, tab_title_substring) |
228 self._iteration_num = 0 # Available to |do_scenario| if needed. | 231 self._iteration_num = 0 # Available to |do_scenario| if needed. |
229 | 232 |
230 self._remote_inspector_client.StartTimelineEventMonitoring( | 233 self._remote_inspector_client.StartTimelineEventMonitoring( |
231 self._OnTimelineEvent) | 234 self._OnTimelineEvent) |
(...skipping 15 matching lines...) Expand all Loading... |
247 self._GetPerformanceStats( | 250 self._GetPerformanceStats( |
248 webapp_name, test_description, tab_title_substring) | 251 webapp_name, test_description, tab_title_substring) |
249 | 252 |
250 if self._iteration_num % 10 == 0: | 253 if self._iteration_num % 10 == 0: |
251 remaining_time = self._test_length_sec - (time.time() - | 254 remaining_time = self._test_length_sec - (time.time() - |
252 self._test_start_time) | 255 self._test_start_time) |
253 logging.info('Chrome interaction #%d. Time remaining in test: %d sec.' % | 256 logging.info('Chrome interaction #%d. Time remaining in test: %d sec.' % |
254 (self._iteration_num, remaining_time)) | 257 (self._iteration_num, remaining_time)) |
255 | 258 |
256 do_scenario() | 259 do_scenario() |
| 260 # Clear ChromeDriver's DOM node cache so its growth doesn't affect the |
| 261 # results of Chrome Endure. |
| 262 # TODO(dennisjeffrey): Once the WebDriver team implements changes to |
| 263 # handle their DOM node cache differently, we need to revisit this. It |
| 264 # may no longer be necessary at that point to forcefully delete the cache. |
| 265 # Additionally, the Javascript below relies on an internal property of |
| 266 # WebDriver that may change at any time. This is only a temporary |
| 267 # workaround to stabilize the Chrome Endure test results. |
| 268 js = """ |
| 269 (function() { |
| 270 delete document.$wdc_; |
| 271 window.domAutomationController.send('done'); |
| 272 })(); |
| 273 """ |
| 274 self.ExecuteJavascript(js, frame_xpath=frame_xpath) |
257 | 275 |
258 self._remote_inspector_client.StopTimelineEventMonitoring() | 276 self._remote_inspector_client.StopTimelineEventMonitoring() |
259 # TODO(dmikurube): Call HeapProfilerDump when PyAuto supports dumping for | 277 # TODO(dmikurube): Call HeapProfilerDump when PyAuto supports dumping for |
260 # renderer processes. | 278 # renderer processes. |
261 | 279 |
262 self._GetPerformanceStats( | 280 self._GetPerformanceStats( |
263 webapp_name, test_description, tab_title_substring, is_last=True) | 281 webapp_name, test_description, tab_title_substring, is_last=True) |
264 | 282 |
265 def _GetProcessInfo(self, tab_title_substring): | 283 def _GetProcessInfo(self, tab_title_substring): |
266 """Gets process info associated with an open browser/tab. | 284 """Gets process info associated with an open browser/tab. |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 discard_button = self._GetElement(self._driver.find_element_by_xpath, | 734 discard_button = self._GetElement(self._driver.find_element_by_xpath, |
717 discard_xpath) | 735 discard_xpath) |
718 discard_button.click() | 736 discard_button.click() |
719 | 737 |
720 # Wait for the message to be discarded, assumed to be true after the | 738 # Wait for the message to be discarded, assumed to be true after the |
721 # "To" field is removed from the webpage DOM. | 739 # "To" field is removed from the webpage DOM. |
722 self._wait.until(lambda _: not self._GetElement( | 740 self._wait.until(lambda _: not self._GetElement( |
723 self._driver.find_element_by_name, 'to')) | 741 self._driver.find_element_by_name, 'to')) |
724 | 742 |
725 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, | 743 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, |
726 test_description, scenario) | 744 test_description, scenario, |
| 745 frame_xpath=self._FRAME_XPATH) |
727 | 746 |
728 # TODO(dennisjeffrey): Remove this test once the Gmail team is done analyzing | 747 # TODO(dennisjeffrey): Remove this test once the Gmail team is done analyzing |
729 # the results after the test runs for a period of time. | 748 # the results after the test runs for a period of time. |
730 def testGmailComposeDiscardSleep(self): | 749 def testGmailComposeDiscardSleep(self): |
731 """Like testGmailComposeDiscard, but sleeps for 30s between iterations. | 750 """Like testGmailComposeDiscard, but sleeps for 30s between iterations. |
732 | 751 |
733 This is a temporary test requested by the Gmail team to compare against the | 752 This is a temporary test requested by the Gmail team to compare against the |
734 results from testGmailComposeDiscard above. | 753 results from testGmailComposeDiscard above. |
735 """ | 754 """ |
736 test_description = 'ComposeDiscardSleep' | 755 test_description = 'ComposeDiscardSleep' |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
771 # "To" field is removed from the webpage DOM. | 790 # "To" field is removed from the webpage DOM. |
772 self._wait.until(lambda _: not self._GetElement( | 791 self._wait.until(lambda _: not self._GetElement( |
773 self._driver.find_element_by_name, 'to')) | 792 self._driver.find_element_by_name, 'to')) |
774 | 793 |
775 # Sleep 2 minutes after every batch of 500 compose/discard iterations. | 794 # Sleep 2 minutes after every batch of 500 compose/discard iterations. |
776 if self._iteration_num % 500 == 0: | 795 if self._iteration_num % 500 == 0: |
777 logging.info('Sleeping 2 minutes.') | 796 logging.info('Sleeping 2 minutes.') |
778 time.sleep(120) | 797 time.sleep(120) |
779 | 798 |
780 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, | 799 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, |
781 test_description, scenario) | 800 test_description, scenario, |
| 801 frame_xpath=self._FRAME_XPATH) |
782 | 802 |
783 def testGmailAlternateThreadlistConversation(self): | 803 def testGmailAlternateThreadlistConversation(self): |
784 """Alternates between threadlist view and conversation view. | 804 """Alternates between threadlist view and conversation view. |
785 | 805 |
786 This test continually clicks between the threadlist (Inbox) and the | 806 This test continually clicks between the threadlist (Inbox) and the |
787 conversation view (e-mail message view), and periodically gathers | 807 conversation view (e-mail message view), and periodically gathers |
788 performance stats that may reveal memory bloat. | 808 performance stats that may reveal memory bloat. |
789 """ | 809 """ |
790 test_description = 'ThreadConversation' | 810 test_description = 'ThreadConversation' |
791 | 811 |
(...skipping 22 matching lines...) Expand all Loading... |
814 self.WaitForDomNode(inbox_xpath, frame_xpath=self._FRAME_XPATH) | 834 self.WaitForDomNode(inbox_xpath, frame_xpath=self._FRAME_XPATH) |
815 inbox = self._GetElement(self._driver.find_element_by_xpath, inbox_xpath) | 835 inbox = self._GetElement(self._driver.find_element_by_xpath, inbox_xpath) |
816 self._ClickElementAndRecordLatency(inbox, test_description, 'Threadlist') | 836 self._ClickElementAndRecordLatency(inbox, test_description, 'Threadlist') |
817 self._wait.until( | 837 self._wait.until( |
818 lambda _: not self._GetElement( | 838 lambda _: not self._GetElement( |
819 self._driver.find_element_by_xpath, | 839 self._driver.find_element_by_xpath, |
820 '//div[text()="Click here to "]')) | 840 '//div[text()="Click here to "]')) |
821 time.sleep(1) | 841 time.sleep(1) |
822 | 842 |
823 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, | 843 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, |
824 test_description, scenario) | 844 test_description, scenario, |
| 845 frame_xpath=self._FRAME_XPATH) |
825 | 846 |
826 def testGmailAlternateTwoLabels(self): | 847 def testGmailAlternateTwoLabels(self): |
827 """Continuously alternates between two labels. | 848 """Continuously alternates between two labels. |
828 | 849 |
829 This test continually clicks between the "Inbox" and "Sent Mail" labels, | 850 This test continually clicks between the "Inbox" and "Sent Mail" labels, |
830 and periodically gathers performance stats that may reveal memory bloat. | 851 and periodically gathers performance stats that may reveal memory bloat. |
831 """ | 852 """ |
832 test_description = 'AlternateLabels' | 853 test_description = 'AlternateLabels' |
833 | 854 |
834 def scenario(): | 855 def scenario(): |
(...skipping 18 matching lines...) Expand all Loading... |
853 self.WaitForDomNode(inbox_xpath, frame_xpath=self._FRAME_XPATH) | 874 self.WaitForDomNode(inbox_xpath, frame_xpath=self._FRAME_XPATH) |
854 inbox = self._GetElement(self._driver.find_element_by_xpath, inbox_xpath) | 875 inbox = self._GetElement(self._driver.find_element_by_xpath, inbox_xpath) |
855 self._ClickElementAndRecordLatency(inbox, test_description, 'Inbox') | 876 self._ClickElementAndRecordLatency(inbox, test_description, 'Inbox') |
856 self.assertTrue( | 877 self.assertTrue( |
857 self.WaitUntil(lambda: 'Inbox' in self.GetActiveTabTitle(), | 878 self.WaitUntil(lambda: 'Inbox' in self.GetActiveTabTitle(), |
858 timeout=60, expect_retval=True, retry_sleep=1), | 879 timeout=60, expect_retval=True, retry_sleep=1), |
859 msg='Timed out waiting for Inbox to appear.') | 880 msg='Timed out waiting for Inbox to appear.') |
860 time.sleep(1) | 881 time.sleep(1) |
861 | 882 |
862 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, | 883 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, |
863 test_description, scenario) | 884 test_description, scenario, |
| 885 frame_xpath=self._FRAME_XPATH) |
864 | 886 |
865 def testGmailExpandCollapseConversation(self): | 887 def testGmailExpandCollapseConversation(self): |
866 """Continuously expands/collapses all messages in a conversation. | 888 """Continuously expands/collapses all messages in a conversation. |
867 | 889 |
868 This test opens up a conversation (e-mail thread) with several messages, | 890 This test opens up a conversation (e-mail thread) with several messages, |
869 then continually alternates between the "Expand all" and "Collapse all" | 891 then continually alternates between the "Expand all" and "Collapse all" |
870 views, while periodically gathering performance stats that may reveal memory | 892 views, while periodically gathering performance stats that may reveal memory |
871 bloat. | 893 bloat. |
872 """ | 894 """ |
873 test_description = 'ExpandCollapse' | 895 test_description = 'ExpandCollapse' |
(...skipping 30 matching lines...) Expand all Loading... |
904 collapse = self._GetElement(self._driver.find_element_by_xpath, | 926 collapse = self._GetElement(self._driver.find_element_by_xpath, |
905 collapse_xpath) | 927 collapse_xpath) |
906 collapse.click() | 928 collapse.click() |
907 self.WaitForDomNode( | 929 self.WaitForDomNode( |
908 '//img[@alt="Collapse all"]/parent::*/parent::*/parent::*' | 930 '//img[@alt="Collapse all"]/parent::*/parent::*/parent::*' |
909 '[@style="display: none; "]', | 931 '[@style="display: none; "]', |
910 frame_xpath=self._FRAME_XPATH) | 932 frame_xpath=self._FRAME_XPATH) |
911 time.sleep(1) | 933 time.sleep(1) |
912 | 934 |
913 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, | 935 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, |
914 test_description, scenario) | 936 test_description, scenario, |
| 937 frame_xpath=self._FRAME_XPATH) |
915 | 938 |
916 | 939 |
917 class ChromeEndureDocsTest(ChromeEndureBaseTest): | 940 class ChromeEndureDocsTest(ChromeEndureBaseTest): |
918 """Long-running performance tests for Chrome using Google Docs.""" | 941 """Long-running performance tests for Chrome using Google Docs.""" |
919 | 942 |
920 _WEBAPP_NAME = 'Docs' | 943 _WEBAPP_NAME = 'Docs' |
921 _TAB_TITLE_SUBSTRING = 'Google Drive' | 944 _TAB_TITLE_SUBSTRING = 'Google Drive' |
922 | 945 |
923 def setUp(self): | 946 def setUp(self): |
924 ChromeEndureBaseTest.setUp(self) | 947 ChromeEndureBaseTest.setUp(self) |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1096 self._num_errors += 1 | 1119 self._num_errors += 1 |
1097 | 1120 |
1098 time.sleep(1) | 1121 time.sleep(1) |
1099 | 1122 |
1100 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, | 1123 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, |
1101 test_description, scenario) | 1124 test_description, scenario) |
1102 | 1125 |
1103 | 1126 |
1104 if __name__ == '__main__': | 1127 if __name__ == '__main__': |
1105 pyauto_functional.Main() | 1128 pyauto_functional.Main() |
OLD | NEW |