1# Copyright 2012 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4import glob 5import imp 6import inspect 7import logging 8import os 9import socket 10import sys 11import time 12 13from catapult_base import util as catapult_util # pylint: disable=import-error 14 15from telemetry.core import exceptions 16 17 18IsRunningOnCrosDevice = catapult_util.IsRunningOnCrosDevice 19GetCatapultDir = catapult_util.GetCatapultDir 20 21 22def GetBaseDir(): 23 main_module = sys.modules['__main__'] 24 if hasattr(main_module, '__file__'): 25 return os.path.dirname(os.path.abspath(main_module.__file__)) 26 else: 27 return os.getcwd() 28 29 30def GetCatapultThirdPartyDir(): 31 return os.path.normpath(os.path.join(GetCatapultDir(), 'third_party')) 32 33 34def GetTelemetryDir(): 35 return os.path.normpath(os.path.join( 36 os.path.abspath(__file__), '..', '..', '..')) 37 38 39def GetTelemetryThirdPartyDir(): 40 return os.path.join(GetTelemetryDir(), 'third_party') 41 42 43def GetUnittestDataDir(): 44 return os.path.join(GetTelemetryDir(), 'telemetry', 'internal', 'testing') 45 46 47def GetChromiumSrcDir(): 48 return os.path.normpath(os.path.join(GetTelemetryDir(), '..', '..', '..')) 49 50 51_counter = [0] 52 53 54def _GetUniqueModuleName(): 55 _counter[0] += 1 56 return "page_set_module_" + str(_counter[0]) 57 58 59def GetPythonPageSetModule(file_path): 60 return imp.load_source(_GetUniqueModuleName(), file_path) 61 62 63def WaitFor(condition, timeout): 64 """Waits for up to |timeout| secs for the function |condition| to return True. 65 66 Polling frequency is (elapsed_time / 10), with a min of .1s and max of 5s. 67 68 Returns: 69 Result of |condition| function (if present). 70 """ 71 min_poll_interval = 0.1 72 max_poll_interval = 5 73 output_interval = 300 74 75 def GetConditionString(): 76 if condition.__name__ == '<lambda>': 77 try: 78 return inspect.getsource(condition).strip() 79 except IOError: 80 pass 81 return condition.__name__ 82 83 start_time = time.time() 84 last_output_time = start_time 85 while True: 86 res = condition() 87 if res: 88 return res 89 now = time.time() 90 elapsed_time = now - start_time 91 last_output_elapsed_time = now - last_output_time 92 if elapsed_time > timeout: 93 raise exceptions.TimeoutException('Timed out while waiting %ds for %s.' % 94 (timeout, GetConditionString())) 95 if last_output_elapsed_time > output_interval: 96 logging.info('Continuing to wait %ds for %s. Elapsed: %ds.', timeout, 97 GetConditionString(), elapsed_time) 98 last_output_time = time.time() 99 poll_interval = min( 100 max(elapsed_time / 10., min_poll_interval), max_poll_interval) 101 time.sleep(poll_interval) 102 103 104class PortKeeper(object): 105 """Port keeper hold an available port on the system. 106 107 Before actually use the port, you must call Release(). 108 """ 109 110 def __init__(self): 111 self._temp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 112 self._temp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 113 self._temp_socket.bind(('', 0)) 114 self._port = self._temp_socket.getsockname()[1] 115 116 @property 117 def port(self): 118 return self._port 119 120 def Release(self): 121 assert self._temp_socket, 'Already released' 122 self._temp_socket.close() 123 self._temp_socket = None 124 125 126def GetUnreservedAvailableLocalPort(): 127 """Returns an available port on the system. 128 129 WARNING: This method does not reserve the port it returns, so it may be used 130 by something else before you get to use it. This can lead to flake. 131 """ 132 tmp = socket.socket() 133 tmp.bind(('', 0)) 134 port = tmp.getsockname()[1] 135 tmp.close() 136 137 return port 138 139 140def GetBuildDirectories(chrome_root=None): 141 """Yields all combination of Chromium build output directories.""" 142 # chrome_root can be set to something else via --chrome-root. 143 if not chrome_root: 144 chrome_root = GetChromiumSrcDir() 145 146 # CHROMIUM_OUTPUT_DIR can be set by --chromium-output-directory. 147 output_dir = os.environ.get('CHROMIUM_OUTPUT_DIR') 148 if output_dir: 149 yield os.path.join(chrome_root, output_dir) 150 elif os.path.exists('build.ninja'): 151 yield os.getcwd() 152 else: 153 out_dir = os.environ.get('CHROMIUM_OUT_DIR') 154 if out_dir: 155 build_dirs = [out_dir] 156 else: 157 build_dirs = ['build', 158 'out', 159 'xcodebuild'] 160 161 build_types = ['Debug', 'Debug_x64', 'Release', 'Release_x64', 'Default'] 162 163 for build_dir in build_dirs: 164 for build_type in build_types: 165 yield os.path.join(chrome_root, build_dir, build_type) 166 167 168def GetSequentialFileName(base_name): 169 """Returns the next sequential file name based on |base_name| and the 170 existing files. base_name should not contain extension. 171 e.g: if base_name is /tmp/test, and /tmp/test_000.json, 172 /tmp/test_001.mp3 exist, this returns /tmp/test_002. In case no 173 other sequential file name exist, this will return /tmp/test_000 174 """ 175 name, ext = os.path.splitext(base_name) 176 assert ext == '', 'base_name cannot contain file extension.' 177 index = 0 178 while True: 179 output_name = '%s_%03d' % (name, index) 180 if not glob.glob(output_name + '.*'): 181 break 182 index = index + 1 183 return output_name 184