1# Copyright (c) 2014 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.
4
5import sys
6import os
7import re
8
9
10def _AddToPathIfNeeded(path):
11  if path not in sys.path:
12    sys.path.insert(0, path)
13
14
15def UpdateSysPathIfNeeded():
16  for path in GetDependencyPaths():
17    _AddToPathIfNeeded(path)
18
19
20def GetDependencyPaths():
21  # TODO(#3703): Separate the paths that are only used by the dev server into
22  # another call.
23  p = TracingProject()
24  return [
25      p.catapult_path,
26      p.py_vulcanize_path,
27      p.vinn_path,
28      p.protobuf_path,
29      os.path.join(p.catapult_third_party_path, 'WebOb'),
30      os.path.join(p.catapult_third_party_path, 'Paste'),
31      os.path.join(p.catapult_third_party_path, 'six'),
32      os.path.join(p.catapult_third_party_path, 'webapp2'),
33      os.path.join(p.catapult_path, 'common', 'py_utils'),
34      os.path.join(p.tracing_third_party_path, 'symbols')
35  ]
36
37
38def _FindAllFilesRecursive(source_paths):
39  assert isinstance(source_paths, list)
40  all_filenames = set()
41  for source_path in source_paths:
42    for dirpath, _, filenames in os.walk(source_path):
43      for f in filenames:
44        if f.startswith('.'):
45          continue
46        x = os.path.abspath(os.path.join(dirpath, f))
47        all_filenames.add(x)
48  return all_filenames
49
50def _IsFilenameATest(x):
51  if x.endswith('_test.js'):
52    return True
53
54  if x.endswith('_test.html'):
55    return True
56
57  if x.endswith('_unittest.js'):
58    return True
59
60  if x.endswith('_unittest.html'):
61    return True
62
63  # TODO(nduca): Add content test?
64  return False
65
66
67class TracingProject(object):
68  catapult_path = os.path.abspath(
69      os.path.join(os.path.dirname(__file__), os.path.pardir))
70
71  tracing_root_path = os.path.join(catapult_path, 'tracing')
72  trace_processor_root_path = os.path.join(catapult_path, 'trace_processor')
73  common_root_path = os.path.join(catapult_path, 'common')
74  tracing_src_path = os.path.join(tracing_root_path, 'tracing')
75  extras_path = os.path.join(tracing_src_path, 'extras')
76  ui_extras_path = os.path.join(tracing_src_path, 'ui', 'extras')
77
78  catapult_third_party_path = os.path.join(catapult_path, 'third_party')
79  polymer_path = os.path.join(catapult_third_party_path, 'polymer')
80
81  # We need google.protobuf for tests that use the proto. The dashboard uses
82  # the gae_ts_mon protobuf lib for its tests, so let's do the same for tracing.
83  protobuf_path = os.path.join(
84      catapult_third_party_path, 'gae_ts_mon', 'gae_ts_mon', 'protobuf')
85
86  tracing_third_party_path = os.path.join(tracing_root_path, 'third_party')
87  py_vulcanize_path = os.path.join(common_root_path, 'py_vulcanize')
88  vinn_path = os.path.join(catapult_third_party_path, 'vinn')
89
90  jszip_path = os.path.join(tracing_third_party_path, 'jszip')
91  pako_path = os.path.join(tracing_third_party_path, 'pako')
92  jpegjs_path = os.path.join(tracing_third_party_path, 'jpeg-js')
93
94  glmatrix_path = os.path.join(
95      tracing_third_party_path, 'gl-matrix', 'dist')
96
97  mannwhitneyu_path = os.path.join(
98      tracing_third_party_path, 'mannwhitneyu')
99
100  ui_path = os.path.join(tracing_src_path, 'ui')
101  d3_path = os.path.join(tracing_third_party_path, 'd3')
102  chai_path = os.path.join(tracing_third_party_path, 'chai')
103  mocha_path = os.path.join(tracing_third_party_path, 'mocha')
104  oboe_path = os.path.join(tracing_third_party_path, 'oboe')
105
106  mre_path = os.path.join(tracing_src_path, 'mre')
107
108  metrics_path = os.path.join(tracing_src_path, 'metrics')
109  diagnostics_path = os.path.join(tracing_src_path, 'value', 'diagnostics')
110
111  value_ui_path = os.path.join(tracing_src_path, 'value', 'ui')
112  metrics_ui_path = os.path.join(tracing_src_path, 'metrics', 'ui')
113
114  test_data_path = os.path.join(tracing_root_path, 'test_data')
115  skp_data_path = os.path.join(tracing_root_path, 'skp_data')
116
117  rjsmin_path = os.path.join(
118      tracing_third_party_path, 'tvcm', 'third_party', 'rjsmin')
119  rcssmin_path = os.path.join(
120      tracing_third_party_path, 'tvcm', 'third_party', 'rcssmin')
121
122  def __init__(self):
123    self.source_paths = []
124    self.source_paths.append(self.tracing_root_path)
125    self.source_paths.append(self.polymer_path)
126    self.source_paths.append(self.tracing_third_party_path)
127    self.source_paths.append(self.mre_path)
128    self.source_paths.append(self.jszip_path)
129    self.source_paths.append(self.pako_path)
130    self.source_paths.append(self.jpegjs_path)
131    self.source_paths.append(self.glmatrix_path)
132    self.source_paths.append(self.mannwhitneyu_path)
133    self.source_paths.append(self.d3_path)
134    self.source_paths.append(self.chai_path)
135    self.source_paths.append(self.mocha_path)
136    self.source_paths.append(self.oboe_path)
137
138  def CreateVulcanizer(self):
139    from py_vulcanize import project as project_module
140    return project_module.Project(self.source_paths)
141
142  def IsD8CompatibleFile(self, filename):
143    if filename.startswith(self.ui_path):
144      return False
145
146    if filename.startswith(self.value_ui_path):
147      return False
148
149    if filename.startswith(self.metrics_ui_path):
150      return False
151
152    return True
153
154  def FindAllTestModuleRelPaths(self, pred=None):
155    if pred is None:
156      pred = lambda x: True
157
158    all_filenames = _FindAllFilesRecursive([self.tracing_src_path])
159    test_module_filenames = [x for x in all_filenames if
160                             _IsFilenameATest(x) and pred(x)]
161    test_module_filenames.sort()
162
163    return [os.path.relpath(x, self.tracing_root_path)
164            for x in test_module_filenames]
165
166  def FindAllMetricsModuleRelPaths(self):
167    all_filenames = _FindAllFilesRecursive([self.tracing_src_path])
168    all_metrics_module_filenames = []
169    for x in all_filenames:
170      if x.startswith(self.metrics_path) and not _IsFilenameATest(x):
171        all_metrics_module_filenames.append(x)
172    all_metrics_module_filenames.sort()
173    return [os.path.relpath(x, self.tracing_root_path)
174            for x in all_metrics_module_filenames]
175
176  def FindAllDiagnosticsModuleRelPaths(self):
177    all_filenames = _FindAllFilesRecursive([self.tracing_src_path])
178    all_diagnostics_module_filenames = []
179    for x in all_filenames:
180      if x.startswith(self.diagnostics_path) and not _IsFilenameATest(x):
181        all_diagnostics_module_filenames.append(x)
182    all_diagnostics_module_filenames.sort()
183    return [os.path.relpath(x, self.tracing_root_path)
184            for x in all_diagnostics_module_filenames]
185
186  def FindAllD8TestModuleRelPaths(self):
187    return self.FindAllTestModuleRelPaths(pred=self.IsD8CompatibleFile)
188
189  def GetConfigNames(self):
190    config_files = [
191        os.path.join(self.ui_extras_path, x)
192        for x in os.listdir(self.ui_extras_path)
193        if x.endswith('_config.html')
194    ]
195
196    config_files = [x for x in config_files if os.path.isfile(x)]
197
198    config_basenames = [os.path.basename(x) for x in config_files]
199    config_names = [re.match('(.+)_config.html$', x).group(1)
200                    for x in config_basenames]
201    return config_names
202
203  def GetDefaultConfigName(self):
204    assert 'full' in self.GetConfigNames()
205    return 'full'
206
207  def AddConfigNameOptionToParser(self, parser):
208    choices = self.GetConfigNames()
209    parser.add_argument(
210        '--config', dest='config_name',
211        choices=choices, default=self.GetDefaultConfigName(),
212        help='Picks a browser config. Valid choices: %s' % ', '.join(choices))
213    return choices
214
215  def GetModuleNameForConfigName(self, config_name):
216    return 'tracing.ui.extras.%s_config' % config_name
217
218