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
13
14class TimeoutException(Exception):
15  pass
16
17
18def GetBaseDir():
19  main_module = sys.modules['__main__']
20  if hasattr(main_module, '__file__'):
21    return os.path.dirname(os.path.abspath(main_module.__file__))
22  else:
23    return os.getcwd()
24
25
26def GetTelemetryDir():
27  return os.path.normpath(os.path.join(
28      __file__, os.pardir, os.pardir, os.pardir))
29
30
31def GetUnittestDataDir():
32  return os.path.join(GetTelemetryDir(), 'unittest_data')
33
34
35def GetChromiumSrcDir():
36  return os.path.normpath(os.path.join(GetTelemetryDir(), os.pardir, os.pardir))
37
38
39def AddDirToPythonPath(*path_parts):
40  path = os.path.abspath(os.path.join(*path_parts))
41  if os.path.isdir(path) and path not in sys.path:
42    sys.path.insert(0, path)
43
44_counter = [0]
45def _GetUniqueModuleName():
46  _counter[0] += 1
47  return "page_set_module_" + str(_counter[0])
48
49def GetPythonPageSetModule(file_path):
50  return imp.load_source(_GetUniqueModuleName(), file_path)
51
52
53def WaitFor(condition, timeout):
54  """Waits for up to |timeout| secs for the function |condition| to return True.
55
56  Polling frequency is (elapsed_time / 10), with a min of .1s and max of 5s.
57
58  Returns:
59    Result of |condition| function (if present).
60  """
61  min_poll_interval =   0.1
62  max_poll_interval =   5
63  output_interval   = 300
64
65  def GetConditionString():
66    if condition.__name__ == '<lambda>':
67      try:
68        return inspect.getsource(condition).strip()
69      except IOError:
70        pass
71    return condition.__name__
72
73  start_time = time.time()
74  last_output_time = start_time
75  while True:
76    res = condition()
77    if res:
78      return res
79    now = time.time()
80    elapsed_time = now - start_time
81    last_output_elapsed_time = now - last_output_time
82    if elapsed_time > timeout:
83      raise TimeoutException('Timed out while waiting %ds for %s.' %
84                             (timeout, GetConditionString()))
85    if last_output_elapsed_time > output_interval:
86      logging.info('Continuing to wait %ds for %s. Elapsed: %ds.',
87                   timeout, GetConditionString(), elapsed_time)
88      last_output_time = time.time()
89    poll_interval = min(max(elapsed_time / 10., min_poll_interval),
90                        max_poll_interval)
91    time.sleep(poll_interval)
92
93
94def GetUnreservedAvailableLocalPort():
95  """Returns an available port on the system.
96
97  WARNING: This method does not reserve the port it returns, so it may be used
98  by something else before you get to use it. This can lead to flake.
99  """
100  tmp = socket.socket()
101  tmp.bind(('', 0))
102  port = tmp.getsockname()[1]
103  tmp.close()
104
105  return port
106
107
108def CloseConnections(tab):
109  """Closes all TCP sockets held open by the browser."""
110  try:
111    tab.ExecuteJavaScript("""window.chrome && chrome.benchmarking &&
112                             chrome.benchmarking.closeConnections()""")
113  except Exception:
114    pass
115
116
117def GetBuildDirectories():
118  """Yields all combination of Chromium build output directories."""
119  build_dirs = ['build',
120                os.path.basename(os.environ.get('CHROMIUM_OUT_DIR', 'out')),
121                'xcodebuild']
122
123  build_types = ['Debug', 'Debug_x64', 'Release', 'Release_x64']
124
125  for build_dir in build_dirs:
126    for build_type in build_types:
127      yield build_dir, build_type
128
129def GetSequentialFileName(base_name):
130  """Returns the next sequential file name based on |base_name| and the
131  existing files. base_name should not contain extension.
132  e.g: if base_name is /tmp/test, and /tmp/test_000.json,
133  /tmp/test_001.mp3 exist, this returns /tmp/test_002. In case no
134  other sequential file name exist, this will return /tmp/test_000
135  """
136  name, ext = os.path.splitext(base_name)
137  assert ext == '', 'base_name cannot contain file extension.'
138  index = 0
139  while True:
140    output_name = '%s_%03d' % (name, index)
141    if not glob.glob(output_name + '.*'):
142      break
143    index = index + 1
144  return output_name
145