146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)# Copyright 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import glob
5effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochimport imp
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import inspect
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import logging
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)import os
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import socket
103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochimport sys
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import time
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TimeoutException(Exception):
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pass
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochdef GetBaseDir():
193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  main_module = sys.modules['__main__']
203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if hasattr(main_module, '__file__'):
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return os.path.dirname(os.path.abspath(main_module.__file__))
223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  else:
233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return os.getcwd()
243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)def GetTelemetryDir():
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return os.path.normpath(os.path.join(
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      __file__, os.pardir, os.pardir, os.pardir))
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)def GetUnittestDataDir():
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return os.path.join(GetTelemetryDir(), 'unittest_data')
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)def GetChromiumSrcDir():
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return os.path.normpath(os.path.join(GetTelemetryDir(), os.pardir, os.pardir))
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)def AddDirToPythonPath(*path_parts):
403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  path = os.path.abspath(os.path.join(*path_parts))
413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if os.path.isdir(path) and path not in sys.path:
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    sys.path.insert(0, path)
433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch_counter = [0]
45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochdef _GetUniqueModuleName():
46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  _counter[0] += 1
47effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return "page_set_module_" + str(_counter[0])
48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochdef GetPythonPageSetModule(file_path):
50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return imp.load_source(_GetUniqueModuleName(), file_path)
51effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)def WaitFor(condition, timeout):
541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  """Waits for up to |timeout| secs for the function |condition| to return True.
551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Polling frequency is (elapsed_time / 10), with a min of .1s and max of 5s.
571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Returns:
591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    Result of |condition| function (if present).
601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  """
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  min_poll_interval =   0.1
62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  max_poll_interval =   5
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  output_interval   = 300
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  def GetConditionString():
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if condition.__name__ == '<lambda>':
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      try:
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        return inspect.getsource(condition).strip()
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      except IOError:
70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        pass
71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return condition.__name__
72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  start_time = time.time()
74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  last_output_time = start_time
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while True:
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    res = condition()
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if res:
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return res
79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    now = time.time()
80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    elapsed_time = now - start_time
81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    last_output_elapsed_time = now - last_output_time
821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if elapsed_time > timeout:
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      raise TimeoutException('Timed out while waiting %ds for %s.' %
84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                             (timeout, GetConditionString()))
85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if last_output_elapsed_time > output_interval:
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      logging.info('Continuing to wait %ds for %s. Elapsed: %ds.',
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                   timeout, GetConditionString(), elapsed_time)
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      last_output_time = time.time()
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    poll_interval = min(max(elapsed_time / 10., min_poll_interval),
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                        max_poll_interval)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    time.sleep(poll_interval)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)def GetUnreservedAvailableLocalPort():
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """Returns an available port on the system.
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WARNING: This method does not reserve the port it returns, so it may be used
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  by something else before you get to use it. This can lead to flake.
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tmp = socket.socket()
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tmp.bind(('', 0))
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  port = tmp.getsockname()[1]
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tmp.close()
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return port
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)def CloseConnections(tab):
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  """Closes all TCP sockets held open by the browser."""
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  try:
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    tab.ExecuteJavaScript("""window.chrome && chrome.benchmarking &&
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             chrome.benchmarking.closeConnections()""")
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  except Exception:
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    pass
115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)def GetBuildDirectories():
118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  """Yields all combination of Chromium build output directories."""
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  build_dirs = ['build',
1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                os.path.basename(os.environ.get('CHROMIUM_OUT_DIR', 'out')),
121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                'xcodebuild']
122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  build_types = ['Debug', 'Debug_x64', 'Release', 'Release_x64']
124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for build_dir in build_dirs:
126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    for build_type in build_types:
127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      yield build_dir, build_type
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)def GetSequentialFileName(base_name):
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  """Returns the next sequential file name based on |base_name| and the
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  existing files. base_name should not contain extension.
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  e.g: if base_name is /tmp/test, and /tmp/test_000.json,
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  /tmp/test_001.mp3 exist, this returns /tmp/test_002. In case no
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  other sequential file name exist, this will return /tmp/test_000
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  """
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  name, ext = os.path.splitext(base_name)
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  assert ext == '', 'base_name cannot contain file extension.'
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  index = 0
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  while True:
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    output_name = '%s_%03d' % (name, index)
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if not glob.glob(output_name + '.*'):
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    index = index + 1
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return output_name
145