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

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: Created 8 years, 5 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
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
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
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
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
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
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
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
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()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698