| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 import os | |
| 7 import sys | |
| 8 import time | |
| 9 | |
| 10 import pyauto_functional # Must be imported before pyauto | |
| 11 import pyauto | |
| 12 import test_utils | |
| 13 | |
| 14 | |
| 15 class MemoryTest(pyauto.PyUITest): | |
| 16 """Tests for memory usage of Chrome-related processes. | |
| 17 | |
| 18 These tests are meant to be used manually, not as part of the continuous | |
| 19 test cycle. This is because each test starts up and periodically | |
| 20 measures/records the memory usage of a relevant Chrome process, doing so | |
| 21 repeatedly until the test is manually killed. Currently, this script only | |
| 22 works in Linux and ChromeOS, as it uses a Linux shell command to query the | |
| 23 system for process memory usage info (test_utils.GetMemoryUsageOfProcess()). | |
| 24 | |
| 25 The tests in this suite produce the following output files (relative to the | |
| 26 current working directory): | |
| 27 | |
| 28 testTabRendererProcessMemoryUsage: 'renderer_process_mem.txt' | |
| 29 testExtensionProcessMemoryUsage: 'extension_process_mem.txt' | |
| 30 """ | |
| 31 | |
| 32 # Constants for all tests in this suite. | |
| 33 NUM_SECONDS_BETWEEN_MEASUREMENTS = 10 | |
| 34 MEASUREMENT_LOG_MESSAGE_TEMPLATE = '[%s] %.2f MB (pid: %d)' | |
| 35 LOG_TO_OUTPUT_FILE = True | |
| 36 | |
| 37 # Constants for testTabRendererProcessMemoryUsage. | |
| 38 RENDERER_PROCESS_URL = 'http://chrome.angrybirds.com' | |
| 39 RENDERER_PROCESS_OUTPUT_FILE = 'renderer_process_mem.txt' | |
| 40 | |
| 41 # Constants for testExtensionProcessMemoryUsage. | |
| 42 EXTENSION_LOCATION = os.path.abspath(os.path.join( | |
| 43 pyauto.PyUITest.DataDir(), 'extensions', 'google_talk.crx')) | |
| 44 EXTENSION_PROCESS_NAME = 'Google Talk' | |
| 45 EXTENSION_PROCESS_OUTPUT_FILE = 'extension_process_mem.txt' | |
| 46 | |
| 47 def _GetPidOfExtensionProcessByName(self, name): | |
| 48 """Identifies the process ID of an extension process, given its name. | |
| 49 | |
| 50 Args: | |
| 51 name: The string name of an extension process, as returned by the function | |
| 52 GetBrowserInfo(). | |
| 53 | |
| 54 Returns: | |
| 55 The integer process identifier (PID) for the specified process, or | |
| 56 None if the PID cannot be identified. | |
| 57 """ | |
| 58 info = self.GetBrowserInfo()['extension_views'] | |
| 59 pid = [x['pid'] for x in info if x['name'] == '%s' % name] | |
| 60 if pid: | |
| 61 return pid[0] | |
| 62 return None | |
| 63 | |
| 64 def _LogMessage(self, log_file, msg): | |
| 65 """Logs a message to the screen, and to a log file if necessary. | |
| 66 | |
| 67 Args: | |
| 68 log_file: The string name of a log file to which to write. | |
| 69 msg: The message to log. | |
| 70 """ | |
| 71 print msg | |
| 72 sys.stdout.flush() | |
| 73 if self.LOG_TO_OUTPUT_FILE: | |
| 74 print >>open(log_file, 'a'), msg | |
| 75 | |
| 76 def testTabRendererProcessMemoryUsage(self): | |
| 77 """Test the memory usage of the renderer process for a tab. | |
| 78 | |
| 79 This test periodically queries the system for the current memory usage | |
| 80 of a tab's renderer process. The test will take measurements forever; you | |
| 81 must manually kill the test to terminate it. | |
| 82 """ | |
| 83 if (self.LOG_TO_OUTPUT_FILE and | |
| 84 os.path.exists(self.RENDERER_PROCESS_OUTPUT_FILE)): | |
| 85 os.remove(self.RENDERER_PROCESS_OUTPUT_FILE) | |
| 86 self.NavigateToURL(self.RENDERER_PROCESS_URL) | |
| 87 self._LogMessage( | |
| 88 self.RENDERER_PROCESS_OUTPUT_FILE, | |
| 89 'Memory usage for renderer process of a tab navigated to: "%s"' % ( | |
| 90 self.RENDERER_PROCESS_URL)) | |
| 91 | |
| 92 # A user must manually kill this test to terminate the following loop. | |
| 93 while True: | |
| 94 pid = self.GetBrowserInfo()['windows'][0]['tabs'][0]['renderer_pid'] | |
| 95 usage = test_utils.GetMemoryUsageOfProcess(pid) | |
| 96 current_time = time.asctime(time.localtime(time.time())) | |
| 97 self._LogMessage( | |
| 98 self.RENDERER_PROCESS_OUTPUT_FILE, | |
| 99 self.MEASUREMENT_LOG_MESSAGE_TEMPLATE % (current_time, usage, pid)) | |
| 100 time.sleep(self.NUM_SECONDS_BETWEEN_MEASUREMENTS) | |
| 101 | |
| 102 def testExtensionProcessMemoryUsage(self): | |
| 103 """Test the memory usage of an extension process. | |
| 104 | |
| 105 This test periodically queries the system for the current memory usage | |
| 106 of an extension process. The test will take measurements forever; you | |
| 107 must manually kill the test to terminate it. | |
| 108 """ | |
| 109 if (self.LOG_TO_OUTPUT_FILE and | |
| 110 os.path.exists(self.EXTENSION_PROCESS_OUTPUT_FILE)): | |
| 111 os.remove(self.EXTENSION_PROCESS_OUTPUT_FILE) | |
| 112 self.InstallExtension(self.EXTENSION_LOCATION) | |
| 113 # The PID is 0 until the extension has a chance to start up. | |
| 114 self.WaitUntil( | |
| 115 lambda: self._GetPidOfExtensionProcessByName( | |
| 116 self.EXTENSION_PROCESS_NAME) not in [0, None]) | |
| 117 self._LogMessage( | |
| 118 self.EXTENSION_PROCESS_OUTPUT_FILE, | |
| 119 'Memory usage for extension process with name: "%s"' % ( | |
| 120 self.EXTENSION_PROCESS_NAME)) | |
| 121 | |
| 122 # A user must manually kill this test to terminate the following loop. | |
| 123 while True: | |
| 124 pid = self._GetPidOfExtensionProcessByName(self.EXTENSION_PROCESS_NAME) | |
| 125 usage = test_utils.GetMemoryUsageOfProcess(pid) | |
| 126 current_time = time.asctime(time.localtime(time.time())) | |
| 127 self._LogMessage( | |
| 128 self.EXTENSION_PROCESS_OUTPUT_FILE, | |
| 129 self.MEASUREMENT_LOG_MESSAGE_TEMPLATE % (current_time, usage, pid)) | |
| 130 time.sleep(self.NUM_SECONDS_BETWEEN_MEASUREMENTS) | |
| 131 | |
| 132 | |
| 133 if __name__ == '__main__': | |
| 134 pyauto_functional.Main() | |
| OLD | NEW |