1# Copyright (c) 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. 4 5# These are fake fetchers that are used for testing and the preview server. 6# They return canned responses for URLs. appengine_wrappers.py uses the fake 7# fetchers if the App Engine imports fail. 8 9import base64 10import json 11import os 12import re 13 14import appengine_wrappers 15from extensions_paths import SERVER2 16from path_util import IsDirectory 17from test_util import ReadFile, ChromiumPath 18import url_constants 19 20 21# TODO(kalman): Investigate why logging in this class implies that the server 22# isn't properly caching some fetched files; often it fetches the same file 23# 10+ times. This may be a test anomaly. 24 25 26def _ReadTestData(*path, **read_args): 27 return ReadFile(SERVER2, 'test_data', *path, **read_args) 28 29 30class _FakeFetcher(object): 31 def _ListDir(self, path): 32 return os.listdir(path) 33 34 def _IsDir(self, path): 35 return os.path.isdir(path) 36 37 def _Stat(self, path): 38 return int(os.stat(path).st_mtime) 39 40 41class _FakeOmahaProxy(_FakeFetcher): 42 def fetch(self, url): 43 return _ReadTestData('branch_utility', 'first.json') 44 45 46class _FakeOmahaHistory(_FakeFetcher): 47 def fetch(self, url): 48 return _ReadTestData('branch_utility', 'second.json') 49 50 51_SVN_URL_TO_PATH_PATTERN = re.compile( 52 r'^.*chrome/.*(trunk|branches/.*)/src/?([^?]*).*?') 53def _ExtractPathFromSvnUrl(url): 54 return _SVN_URL_TO_PATH_PATTERN.match(url).group(2) 55 56 57class _FakeSubversionServer(_FakeFetcher): 58 def fetch(self, url): 59 path = _ExtractPathFromSvnUrl(url) 60 if IsDirectory(path): 61 html = ['<html>Revision 000000'] 62 try: 63 for f in self._ListDir(ChromiumPath(path)): 64 if f.startswith('.'): 65 continue 66 if self._IsDir(ChromiumPath(path, f)): 67 html.append('<a>' + f + '/</a>') 68 else: 69 html.append('<a>' + f + '</a>') 70 html.append('</html>') 71 return '\n'.join(html) 72 except OSError as e: 73 return None 74 try: 75 return ReadFile(path) 76 except IOError: 77 return None 78 79 80_GITILES_BASE_RE = re.escape('%s/%s' % 81 (url_constants.GITILES_BASE, url_constants.GITILES_SRC_ROOT)) 82_GITILES_BRANCH_BASE_RE = re.escape('%s/%s/%s' % 83 (url_constants.GITILES_BASE, 84 url_constants.GITILES_SRC_ROOT, 85 url_constants.GITILES_BRANCHES_PATH)) 86# NOTE: _GITILES_BRANCH_BASE_RE must be first, because _GITILES_BASE_RE is 87# a more general pattern. 88_GITILES_URL_RE = r'(%s|%s)/' % (_GITILES_BRANCH_BASE_RE, _GITILES_BASE_RE) 89_GITILES_URL_TO_COMMIT_PATTERN = re.compile(r'%s[^/]+$' % _GITILES_URL_RE) 90_GITILES_URL_TO_PATH_PATTERN = re.compile(r'%s.+?/(.*)' % _GITILES_URL_RE) 91def _ExtractPathFromGitilesUrl(url): 92 return _GITILES_URL_TO_PATH_PATTERN.match(url).group(2) 93 94 95class _FakeGitilesServer(_FakeFetcher): 96 def fetch(self, url): 97 if _GITILES_URL_TO_COMMIT_PATTERN.match(url) is not None: 98 return json.dumps({'commit': '1' * 40}) 99 path = _ExtractPathFromGitilesUrl(url) 100 chromium_path = ChromiumPath(path) 101 if self._IsDir(chromium_path): 102 jsn = {} 103 dir_stat = self._Stat(chromium_path) 104 jsn['id'] = dir_stat 105 jsn['entries'] = [] 106 for f in self._ListDir(chromium_path): 107 if f.startswith('.'): 108 continue 109 f_path = os.path.join(chromium_path, f) 110 jsn['entries'].append({ 111 'id': self._Stat(f_path), 112 'name': f, 113 'type': 'tree' if self._IsDir(f_path) else 'blob' 114 }) 115 return json.dumps(jsn) 116 try: 117 return base64.b64encode(ReadFile(path)) 118 except IOError: 119 return None 120 121 122class _FakeViewvcServer(_FakeFetcher): 123 def fetch(self, url): 124 path = ChromiumPath(_ExtractPathFromSvnUrl(url)) 125 if self._IsDir(path): 126 html = ['<table><tbody><tr>...</tr>'] 127 # The version of the directory. 128 dir_stat = self._Stat(path) 129 html.append('<tr>') 130 html.append('<td>Directory revision:</td>') 131 html.append('<td><a>%s</a><a></a></td>' % dir_stat) 132 html.append('</tr>') 133 # The version of each file. 134 for f in self._ListDir(path): 135 if f.startswith('.'): 136 continue 137 html.append('<tr>') 138 html.append(' <td><a>%s%s</a></td>' % ( 139 f, '/' if self._IsDir(os.path.join(path, f)) else '')) 140 html.append(' <td><a><strong>%s</strong></a></td>' % 141 self._Stat(os.path.join(path, f))) 142 html.append('<td></td><td></td><td></td>') 143 html.append('</tr>') 144 html.append('</tbody></table>') 145 return '\n'.join(html) 146 try: 147 return ReadFile(path) 148 except IOError: 149 return None 150 151 152class _FakeGithubStat(_FakeFetcher): 153 def fetch(self, url): 154 return '{ "sha": 0 }' 155 156 157class _FakeGithubZip(_FakeFetcher): 158 def fetch(self, url): 159 return _ReadTestData('github_file_system', 'apps_samples.zip', mode='rb') 160 161 162class _FakeRietveldAPI(_FakeFetcher): 163 def __init__(self): 164 self._base_pattern = re.compile(r'.*/(api/.*)') 165 166 def fetch(self, url): 167 return _ReadTestData( 168 'rietveld_patcher', self._base_pattern.match(url).group(1), 'json') 169 170 171class _FakeRietveldTarball(_FakeFetcher): 172 def __init__(self): 173 self._base_pattern = re.compile(r'.*/(tarball/\d+/\d+)') 174 175 def fetch(self, url): 176 return _ReadTestData( 177 'rietveld_patcher', self._base_pattern.match(url).group(1) + '.tar.bz2', 178 mode='rb') 179 180 181def ConfigureFakeFetchers(): 182 '''Configure the fake fetcher paths relative to the docs directory. 183 ''' 184 appengine_wrappers.ConfigureFakeUrlFetch({ 185 url_constants.OMAHA_HISTORY: _FakeOmahaHistory(), 186 url_constants.OMAHA_PROXY_URL: _FakeOmahaProxy(), 187 '%s/.*' % url_constants.SVN_URL: _FakeSubversionServer(), 188 '%s/.*' % url_constants.VIEWVC_URL: _FakeViewvcServer(), 189 '%s/.*/commits/.*' % url_constants.GITHUB_REPOS: _FakeGithubStat(), 190 '%s/.*/zipball' % url_constants.GITHUB_REPOS: _FakeGithubZip(), 191 '%s/api/.*' % url_constants.CODEREVIEW_SERVER: _FakeRietveldAPI(), 192 '%s/tarball/.*' % url_constants.CODEREVIEW_SERVER: _FakeRietveldTarball(), 193 '%s/.*' % _GITILES_BASE_RE: _FakeGitilesServer(), 194 '%s/.*' % _GITILES_BRANCH_BASE_RE: _FakeGitilesServer() 195 }) 196