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 |