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 7 8 9def _AddToPathIfNeeded(path): 10 if path not in sys.path: 11 sys.path.insert(0, path) 12 13 14def _IsRunningInAppEngine(): 15 # Cloud workers run on appengine but in a managed vm, which gives them full 16 # access to the filesystem. Since they manage their own checkout of catapult 17 # to do trace processing, they need the paths properly setup. 18 if 'PI_CLOUD_WORKER' in os.environ: 19 return False 20 if 'SERVER_SOFTWARE' not in os.environ: 21 return False 22 if os.environ['SERVER_SOFTWARE'].startswith('Google App Engine/'): 23 return True 24 if os.environ['SERVER_SOFTWARE'].startswith('Development/'): 25 return True 26 return False 27 28 29def UpdateSysPathIfNeeded(): 30 p = PerfInsightsProject() 31 32 _AddToPathIfNeeded(p.perf_insights_third_party_path) 33 34 # TODO(fmeawad): We should add catapult projects even inside 35 # appengine, see issue #1246 36 if not _IsRunningInAppEngine(): 37 _AddToPathIfNeeded(p.catapult_path) 38 _AddToPathIfNeeded(p.tracing_root_path) 39 _AddToPathIfNeeded(p.py_vulcanize_path) 40 41 import tracing_project 42 tracing_project.UpdateSysPathIfNeeded() 43 44 45def _FindAllFilesRecursive(source_paths): 46 assert isinstance(source_paths, list) 47 all_filenames = set() 48 for source_path in source_paths: 49 for dirpath, _, filenames in os.walk(source_path): 50 for f in filenames: 51 if f.startswith('.'): 52 continue 53 x = os.path.abspath(os.path.join(dirpath, f)) 54 all_filenames.add(x) 55 return all_filenames 56 57 58def _IsFilenameATest(x): # pylint: disable=unused-argument 59 if x.endswith('_test.js'): 60 return True 61 62 if x.endswith('_test.html'): 63 return True 64 65 if x.endswith('_unittest.js'): 66 return True 67 68 if x.endswith('_unittest.html'): 69 return True 70 71 # TODO(nduca): Add content test? 72 return False 73 74 75class PerfInsightsProject(object): 76 catapult_path = os.path.abspath( 77 os.path.join(os.path.dirname(__file__), os.path.pardir)) 78 79 perf_insights_root_path = os.path.join(catapult_path, 'perf_insights') 80 perf_insights_src_path = os.path.join( 81 perf_insights_root_path, 'perf_insights') 82 perf_insights_ui_path = os.path.join(perf_insights_src_path, 'ui') 83 perf_insights_test_data_path = os.path.join( 84 perf_insights_root_path, 'test_data') 85 perf_insights_examples_path = os.path.join( 86 perf_insights_root_path, 'perf_insights_examples') 87 88 perf_insights_third_party_path = os.path.join( 89 perf_insights_root_path, 'third_party') 90 91 tracing_root_path = os.path.join(catapult_path, 'tracing') 92 93 py_vulcanize_path = os.path.join(catapult_path, 'third_party', 'py_vulcanize') 94 95 def __init__(self): # pylint: disable=unused-argument 96 self._source_paths = None 97 98 @property 99 def source_paths(self): 100 # We lazily init of source_paths because for perf_insights_project's 101 # UpdateSysPathIfNeeded to run, the PerfInsightsProject must be __init__'d, 102 # because thats where we centralize the various directory names. 103 # And, for source_paths to be set up, we need the UpdateSysPathIfNeeded to 104 # have run! We use laziness to resolve this cyclic dependency. 105 if self._source_paths is None: 106 self._source_paths = [] 107 self._source_paths.append(self.perf_insights_root_path) 108 109 import tracing_project as tracing_project_module 110 tracing_project = tracing_project_module.TracingProject() 111 self._source_paths.extend(tracing_project.source_paths) 112 113 return self._source_paths 114 115 def GetAbsPathFromHRef(self, href): 116 for source_path in self.source_paths: 117 candidate = os.path.abspath(os.path.join(source_path, href[1:])) 118 if os.path.exists(candidate): 119 return candidate 120 return None 121 122 def CreateVulcanizer(self): 123 from py_vulcanize import project as project_module 124 return project_module.Project(self.source_paths) 125 126 def IsD8CompatibleFile(self, filename): 127 if filename.startswith(self.perf_insights_ui_path): 128 return False 129 return True 130 131 def FindAllTestModuleRelPaths(self, pred=None): 132 if pred is None: 133 pred = lambda x: True 134 all_filenames = _FindAllFilesRecursive([self.perf_insights_src_path, 135 self.perf_insights_examples_path]) 136 test_module_filenames = [x for x in all_filenames if 137 _IsFilenameATest(x) and pred(x)] 138 test_module_filenames.sort() 139 140 return [os.path.relpath(x, self.perf_insights_root_path) 141 for x in test_module_filenames] 142 143 def FindAllD8TestModuleRelPaths(self): 144 return self.FindAllTestModuleRelPaths(pred=self.IsD8CompatibleFile) 145