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 15 matching lines...) Expand all Loading... | |
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 |
42 class ChromeEndureBaseTest(perf.BasePerfTest): | 43 class ChromeEndureBaseTest(perf.BasePerfTest): |
43 """Implements common functionality for all Chrome Endure tests. | 44 """Implements common functionality for all Chrome Endure tests. |
44 | 45 |
45 All Chrome Endure test classes should inherit from this class. | 46 All Chrome Endure test classes should inherit from this class. |
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
572 test_description, lambda: scenario(driver)) | 573 test_description, lambda: scenario(driver)) |
573 | 574 |
574 | 575 |
575 class ChromeEndureGmailTest(ChromeEndureBaseTest): | 576 class ChromeEndureGmailTest(ChromeEndureBaseTest): |
576 """Long-running performance tests for Chrome using Gmail.""" | 577 """Long-running performance tests for Chrome using Gmail.""" |
577 | 578 |
578 _WEBAPP_NAME = 'Gmail' | 579 _WEBAPP_NAME = 'Gmail' |
579 _TAB_TITLE_SUBSTRING = 'Gmail' | 580 _TAB_TITLE_SUBSTRING = 'Gmail' |
580 _FRAME_XPATH = 'id("canvas_frame")' | 581 _FRAME_XPATH = 'id("canvas_frame")' |
581 | 582 |
582 def setUp(self): | 583 def ExtraChromeFlags(self): |
Nirnimesh
2012/07/18 19:41:18
I wish you add this functionality to ChromeEndureB
fdeng1
2012/07/24 00:05:50
Done.
I also moved the code that starts/shuts do
| |
583 ChromeEndureBaseTest.setUp(self) | 584 flags = super(ChromeEndureGmailTest, self).ExtraChromeFlags() |
585 # Add flags for the Web Page Replay server. | |
586 if 'USE_WPR_FOR_ENDURE' in os.environ: | |
587 return flags + ChromeEndureWebPageReplay.CHROME_FLAGS | |
588 return flags | |
584 | 589 |
590 def _GmailSetUp(self, test_name): | |
591 # Start the Web Page Replay server. | |
592 if 'USE_WPR_FOR_ENDURE' in os.environ: | |
593 mode = 'Record' if 'ENDURE_WPR_RECORD' in os.environ else 'Replay' | |
594 logging.info('Starting the Web Page Replay server: in %s mode', mode) | |
595 | |
596 self.wpr_server = ChromeEndureWebPageReplay().GetReplayServer(test_name) | |
597 self.wpr_server.StartServer() | |
598 logging.info('The Web Page Replay server started.') | |
585 # Log into a test Google account and open up Gmail. | 599 # Log into a test Google account and open up Gmail. |
586 self._LoginToGoogleAccount(account_key='test_google_account_gmail') | 600 self._LoginToGoogleAccount(account_key='test_google_account_gmail') |
587 self.NavigateToURL('http://www.gmail.com') | 601 self.NavigateToURL('http://www.gmail.com') |
588 loaded_tab_title = self.GetActiveTabTitle() | 602 loaded_tab_title = self.GetActiveTabTitle() |
589 self.assertTrue(self._TAB_TITLE_SUBSTRING in loaded_tab_title, | 603 self.assertTrue(self._TAB_TITLE_SUBSTRING in loaded_tab_title, |
590 msg='Loaded tab title does not contain "%s": "%s"' % | 604 msg='Loaded tab title does not contain "%s": "%s"' % |
591 (self._TAB_TITLE_SUBSTRING, loaded_tab_title)) | 605 (self._TAB_TITLE_SUBSTRING, loaded_tab_title)) |
592 | 606 |
593 self._driver = self.NewWebDriver() | 607 self._driver = self.NewWebDriver() |
594 # Any call to wait.until() will raise an exception if the timeout is hit. | 608 # Any call to wait.until() will raise an exception if the timeout is hit. |
595 # TODO(dennisjeffrey): Remove the need for webdriver's wait using the new | 609 # TODO(dennisjeffrey): Remove the need for webdriver's wait using the new |
596 # DOM mutation observer mechanism. | 610 # DOM mutation observer mechanism. |
597 self._wait = WebDriverWait(self._driver, timeout=60) | 611 self._wait = WebDriverWait(self._driver, timeout=60) |
598 | 612 |
599 # Wait until Gmail's 'canvas_frame' loads and the 'Inbox' link is present. | 613 # Wait until Gmail's 'canvas_frame' loads and the 'Inbox' link is present. |
600 # TODO(dennisjeffrey): Check with the Gmail team to see if there's a better | 614 # TODO(dennisjeffrey): Check with the Gmail team to see if there's a better |
601 # way to tell when the webpage is ready for user interaction. | 615 # way to tell when the webpage is ready for user interaction. |
602 self._wait.until( | 616 self._wait.until( |
603 self._SwitchToCanvasFrame) # Raises exception if the timeout is hit. | 617 self._SwitchToCanvasFrame) # Raises exception if the timeout is hit. |
604 # Wait for the inbox to appear. | 618 # Wait for the inbox to appear. |
605 self.WaitForDomNode('//a[starts-with(@title, "Inbox")]', | 619 self.WaitForDomNode('//a[starts-with(@title, "Inbox")]', |
606 frame_xpath=self._FRAME_XPATH) | 620 frame_xpath=self._FRAME_XPATH) |
607 | 621 |
622 def tearDown(self): | |
623 super(ChromeEndureGmailTest, self).tearDown() | |
624 # Stop the Web Page Replay server. This has to be done AFTER | |
625 # the parent's tearDown has run. Otherwise the Web Page Replay server | |
626 # will hang to wait for all connection to close. | |
627 if 'USE_WPR_FOR_ENDURE' in os.environ: | |
628 logging.info('Stopping The Web Page Replay server.') | |
629 self.wpr_server.StopServer() | |
630 logging.info('The Web Page Replay server stopped.') | |
631 | |
608 def _SwitchToCanvasFrame(self, driver): | 632 def _SwitchToCanvasFrame(self, driver): |
609 """Switch the WebDriver to Gmail's 'canvas_frame', if it's available. | 633 """Switch the WebDriver to Gmail's 'canvas_frame', if it's available. |
610 | 634 |
611 Args: | 635 Args: |
612 driver: A selenium.webdriver.remote.webdriver.WebDriver object. | 636 driver: A selenium.webdriver.remote.webdriver.WebDriver object. |
613 | 637 |
614 Returns: | 638 Returns: |
615 True, if the switch to Gmail's 'canvas_frame' is successful, or | 639 True, if the switch to Gmail's 'canvas_frame' is successful, or |
616 False if not. | 640 False if not. |
617 """ | 641 """ |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
677 else: | 701 else: |
678 logging.warning('Could not identify latency value.') | 702 logging.warning('Could not identify latency value.') |
679 | 703 |
680 def testGmailComposeDiscard(self): | 704 def testGmailComposeDiscard(self): |
681 """Continuously composes/discards an e-mail before sending. | 705 """Continuously composes/discards an e-mail before sending. |
682 | 706 |
683 This test continually composes/discards an e-mail using Gmail, and | 707 This test continually composes/discards an e-mail using Gmail, and |
684 periodically gathers performance stats that may reveal memory bloat. | 708 periodically gathers performance stats that may reveal memory bloat. |
685 """ | 709 """ |
686 test_description = 'ComposeDiscard' | 710 test_description = 'ComposeDiscard' |
711 self._GmailSetUp(test_description) | |
687 | 712 |
688 # TODO(dennisjeffrey): Remove following line once crosbug.com/32357 is | 713 # TODO(dennisjeffrey): Remove following line once crosbug.com/32357 is |
689 # fixed. | 714 # fixed. |
690 self._test_length_sec = 60 * 60 * 5 # Run test for 5 hours. | 715 self._test_length_sec = 60 * 60 * 5 # Run test for 5 hours. |
691 | 716 |
692 def scenario(): | 717 def scenario(): |
693 # Click the "Compose" button, enter some text into the "To" field, enter | 718 # Click the "Compose" button, enter some text into the "To" field, enter |
694 # some text into the "Subject" field, then click the "Discard" button to | 719 # some text into the "Subject" field, then click the "Discard" button to |
695 # discard the message. | 720 # discard the message. |
696 compose_xpath = '//div[text()="COMPOSE"]' | 721 compose_xpath = '//div[text()="COMPOSE"]' |
(...skipping 30 matching lines...) Expand all Loading... | |
727 | 752 |
728 # TODO(dennisjeffrey): Remove this test once the Gmail team is done analyzing | 753 # TODO(dennisjeffrey): Remove this test once the Gmail team is done analyzing |
729 # the results after the test runs for a period of time. | 754 # the results after the test runs for a period of time. |
730 def testGmailComposeDiscardSleep(self): | 755 def testGmailComposeDiscardSleep(self): |
731 """Like testGmailComposeDiscard, but sleeps for 30s between iterations. | 756 """Like testGmailComposeDiscard, but sleeps for 30s between iterations. |
732 | 757 |
733 This is a temporary test requested by the Gmail team to compare against the | 758 This is a temporary test requested by the Gmail team to compare against the |
734 results from testGmailComposeDiscard above. | 759 results from testGmailComposeDiscard above. |
735 """ | 760 """ |
736 test_description = 'ComposeDiscardSleep' | 761 test_description = 'ComposeDiscardSleep' |
762 self._GmailSetUp(test_description) | |
737 | 763 |
738 # TODO(dennisjeffrey): Remove following line once crosbug.com/32357 is | 764 # TODO(dennisjeffrey): Remove following line once crosbug.com/32357 is |
739 # fixed. | 765 # fixed. |
740 self._test_length_sec = 60 * 60 * 5 # Run test for 5 hours. | 766 self._test_length_sec = 60 * 60 * 5 # Run test for 5 hours. |
741 | 767 |
742 def scenario(): | 768 def scenario(): |
743 # Click the "Compose" button, enter some text into the "To" field, enter | 769 # Click the "Compose" button, enter some text into the "To" field, enter |
744 # some text into the "Subject" field, then click the "Discard" button to | 770 # some text into the "Subject" field, then click the "Discard" button to |
745 # discard the message. Finally, sleep for 30 seconds. | 771 # discard the message. Finally, sleep for 30 seconds. |
746 compose_xpath = '//div[text()="COMPOSE"]' | 772 compose_xpath = '//div[text()="COMPOSE"]' |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 test_description, scenario) | 807 test_description, scenario) |
782 | 808 |
783 def testGmailAlternateThreadlistConversation(self): | 809 def testGmailAlternateThreadlistConversation(self): |
784 """Alternates between threadlist view and conversation view. | 810 """Alternates between threadlist view and conversation view. |
785 | 811 |
786 This test continually clicks between the threadlist (Inbox) and the | 812 This test continually clicks between the threadlist (Inbox) and the |
787 conversation view (e-mail message view), and periodically gathers | 813 conversation view (e-mail message view), and periodically gathers |
788 performance stats that may reveal memory bloat. | 814 performance stats that may reveal memory bloat. |
789 """ | 815 """ |
790 test_description = 'ThreadConversation' | 816 test_description = 'ThreadConversation' |
817 self._GmailSetUp(test_description) | |
791 | 818 |
792 def scenario(): | 819 def scenario(): |
793 # Click an e-mail to see the conversation view, wait 1 second, click the | 820 # Click an e-mail to see the conversation view, wait 1 second, click the |
794 # "Inbox" link to see the threadlist, wait 1 second. | 821 # "Inbox" link to see the threadlist, wait 1 second. |
795 | 822 |
796 # Find the first thread (e-mail) identified by a "span" tag that contains | 823 # Find the first thread (e-mail) identified by a "span" tag that contains |
797 # an "email" attribute. Then click it and wait for the conversation view | 824 # an "email" attribute. Then click it and wait for the conversation view |
798 # to appear (assumed to be visible when a particular div exists on the | 825 # to appear (assumed to be visible when a particular div exists on the |
799 # page). | 826 # page). |
800 thread_xpath = '//span[@email]' | 827 thread_xpath = '//span[@email]' |
(...skipping 22 matching lines...) Expand all Loading... | |
823 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, | 850 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, |
824 test_description, scenario) | 851 test_description, scenario) |
825 | 852 |
826 def testGmailAlternateTwoLabels(self): | 853 def testGmailAlternateTwoLabels(self): |
827 """Continuously alternates between two labels. | 854 """Continuously alternates between two labels. |
828 | 855 |
829 This test continually clicks between the "Inbox" and "Sent Mail" labels, | 856 This test continually clicks between the "Inbox" and "Sent Mail" labels, |
830 and periodically gathers performance stats that may reveal memory bloat. | 857 and periodically gathers performance stats that may reveal memory bloat. |
831 """ | 858 """ |
832 test_description = 'AlternateLabels' | 859 test_description = 'AlternateLabels' |
860 self._GmailSetUp(test_description) | |
833 | 861 |
834 def scenario(): | 862 def scenario(): |
835 # Click the "Sent Mail" label, wait for 1 second, click the "Inbox" label, | 863 # Click the "Sent Mail" label, wait for 1 second, click the "Inbox" label, |
836 # wait for 1 second. | 864 # wait for 1 second. |
837 | 865 |
838 # Click the "Sent Mail" label, then wait for the tab title to be updated | 866 # Click the "Sent Mail" label, then wait for the tab title to be updated |
839 # with the substring "sent". | 867 # with the substring "sent". |
840 sent_xpath = '//a[starts-with(text(), "Sent Mail")]' | 868 sent_xpath = '//a[starts-with(text(), "Sent Mail")]' |
841 self.WaitForDomNode(sent_xpath, frame_xpath=self._FRAME_XPATH) | 869 self.WaitForDomNode(sent_xpath, frame_xpath=self._FRAME_XPATH) |
842 sent = self._GetElement(self._driver.find_element_by_xpath, sent_xpath) | 870 sent = self._GetElement(self._driver.find_element_by_xpath, sent_xpath) |
(...skipping 21 matching lines...) Expand all Loading... | |
864 | 892 |
865 def testGmailExpandCollapseConversation(self): | 893 def testGmailExpandCollapseConversation(self): |
866 """Continuously expands/collapses all messages in a conversation. | 894 """Continuously expands/collapses all messages in a conversation. |
867 | 895 |
868 This test opens up a conversation (e-mail thread) with several messages, | 896 This test opens up a conversation (e-mail thread) with several messages, |
869 then continually alternates between the "Expand all" and "Collapse all" | 897 then continually alternates between the "Expand all" and "Collapse all" |
870 views, while periodically gathering performance stats that may reveal memory | 898 views, while periodically gathering performance stats that may reveal memory |
871 bloat. | 899 bloat. |
872 """ | 900 """ |
873 test_description = 'ExpandCollapse' | 901 test_description = 'ExpandCollapse' |
902 self._GmailSetUp(test_description) | |
874 | 903 |
875 # Enter conversation view for a particular thread. | 904 # Enter conversation view for a particular thread. |
876 thread_xpath = '//span[@email]' | 905 thread_xpath = '//span[@email]' |
877 self.WaitForDomNode(thread_xpath, frame_xpath=self._FRAME_XPATH) | 906 self.WaitForDomNode(thread_xpath, frame_xpath=self._FRAME_XPATH) |
878 thread = self._GetElement(self._driver.find_element_by_xpath, thread_xpath) | 907 thread = self._GetElement(self._driver.find_element_by_xpath, thread_xpath) |
879 thread.click() | 908 thread.click() |
880 self.WaitForDomNode('//div[text()="Click here to "]', | 909 self.WaitForDomNode('//div[text()="Click here to "]', |
881 frame_xpath=self._FRAME_XPATH) | 910 frame_xpath=self._FRAME_XPATH) |
882 | 911 |
883 def scenario(): | 912 def scenario(): |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1094 except (pyauto_errors.JSONInterfaceError, | 1123 except (pyauto_errors.JSONInterfaceError, |
1095 pyauto_errors.JavascriptRuntimeError): | 1124 pyauto_errors.JavascriptRuntimeError): |
1096 self._num_errors += 1 | 1125 self._num_errors += 1 |
1097 | 1126 |
1098 time.sleep(1) | 1127 time.sleep(1) |
1099 | 1128 |
1100 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, | 1129 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, |
1101 test_description, scenario) | 1130 test_description, scenario) |
1102 | 1131 |
1103 | 1132 |
1133 class ChromeEndureWebPageReplay(perf.WebPageReplay): | |
1134 """Set up Web Page Replay server. | |
1135 | |
1136 This class inherits from perf.WebPageReplay to allow different settings | |
1137 for the Web Page Replay server. | |
1138 | |
1139 Environment Variables: | |
1140 ENDURE_WPR_RECORD: If set, puts Web Page Replay in record mode | |
1141 instead of replay. | |
1142 ENDURE_WPR_REPLAY_DIR: Path to alternate Web Page Replay source | |
1143 (for development). | |
1144 ENDUER_ WPR_ARCHIVE_PATH: Path to alternate archive file. | |
1145 E.g. '/tmp/foo.wpr'. | |
1146 """ | |
1147 _PATHS = { | |
1148 'archive': 'src/data/endure/webpagereplay/{test_name}.wpr', | |
1149 'replay': 'src/third_party/webpagereplay', | |
1150 'logs': 'src/chrome_endure_webpagereplay_logs', | |
1151 'scripts': 'src/chrome/test/data/chrome_endure/deterministic.js' | |
1152 } | |
1153 | |
1154 CHROME_FLAGS = [ | |
1155 '--host-resolver-rules=MAP * %s' % webpagereplay.REPLAY_HOST, | |
Nirnimesh
2012/07/18 19:41:18
If it works with it, I think you should retain the
fdeng1
2012/07/24 00:05:50
I restructured perf.WebPageReplay. Now we have per
| |
1156 '--testing-fixed-http-port=%s' % webpagereplay.HTTP_PORT, | |
1157 '--testing-fixed-https-port=%s' % webpagereplay.HTTPS_PORT, | |
1158 '--log-level=0', | |
Nirnimesh
2012/07/18 19:41:18
remove this and other flags that are not necessary
fdeng1
2012/07/24 00:05:50
Done.
Please take a look at __init__ in perf.BaseW
| |
1159 '--disable-background-networking', | |
1160 '--enable-logging', | |
1161 '--ignore-certificate-errors', | |
1162 '--no-first-run', | |
1163 '--no-proxy-server', | |
1164 ] | |
1165 | |
1166 def __init__(self): | |
1167 self.archive_path = os.environ.get('ENDURE_WPR_ARCHIVE_PATH') | |
1168 self.replay_dir = os.environ.get('ENDURE_WPR_REPLAY_DIR', | |
1169 self.Path('replay')) | |
1170 self.is_record_mode = 'ENDURE_WPR_RECORD' in os.environ | |
1171 if self.is_record_mode: | |
1172 self._num_iterations = 1 | |
1173 | |
1174 def GetReplayServer(self, test_name): | |
1175 """Create the Web Page Replay server. | |
1176 | |
1177 This function overrides the one in perf.WebpageReplay to pass a customized | |
1178 deterministic.js to Web Page Replay server. This one differs from the | |
1179 default one as it uses a different value for time_seed. See the file | |
1180 (src/chrome/test/data/chrome_endure/deterministic.js) for | |
1181 how time_seed works. | |
1182 | |
1183 Args: | |
1184 test_name: the test name, should be identical for each test. | |
1185 Returns: | |
1186 An instance of webpagereplay.ReplayServer. | |
1187 """ | |
1188 | |
1189 replay_options = [] | |
1190 replay_options.append('--no-dns_forwarding') | |
1191 if self.is_record_mode: | |
1192 replay_options.append('--record') | |
1193 | |
1194 assert os.path.exists(self.Path('scripts')), \ | |
1195 'The scripts to be injected do not exist: %s' % self.Path('scripts') | |
1196 replay_options.append('--inject_scripts=%s' % self.Path('scripts')) | |
1197 | |
1198 return webpagereplay.ReplayServer( | |
1199 self.replay_dir, | |
1200 self._ArchivePath(test_name), | |
1201 self.Path('logs'), | |
1202 replay_options) | |
1203 | |
1204 | |
1104 if __name__ == '__main__': | 1205 if __name__ == '__main__': |
1105 pyauto_functional.Main() | 1206 pyauto_functional.Main() |
OLD | NEW |