Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: tests/fake_repos.py

Issue 2189001: Add real gclient_smoke tests now (Closed)
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tests/gclient_smoketest.py » ('j') | tests/gclient_smoketest.py » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2010 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Generate fake repositories for testing.""" 6 """Generate fake repositories for testing."""
7 7
8 import logging
8 import os 9 import os
10 import re
9 import shutil 11 import shutil
10 import subprocess 12 import subprocess
11 import sys 13 import sys
12 14
13 15
14 def addKill(): 16 def addKill():
15 """Add kill() method to subprocess.Popen for python <2.6""" 17 """Add kill() method to subprocess.Popen for python <2.6"""
16 if getattr(subprocess.Popen, 'kill', None): 18 if getattr(subprocess.Popen, 'kill', None):
17 return 19 return
18 if sys.platform.startswith('win'): 20 if sys.platform.startswith('win'):
(...skipping 13 matching lines...) Expand all
32 if os.path.exists(path): 34 if os.path.exists(path):
33 shutil.rmtree(path) 35 shutil.rmtree(path)
34 36
35 37
36 def write(path, content): 38 def write(path, content):
37 f = open(path, 'wb') 39 f = open(path, 'wb')
38 f.write(content) 40 f.write(content)
39 f.close() 41 f.close()
40 42
41 43
44 join = os.path.join
45
46
47 def call(*args, **kwargs):
48 logging.debug(args[0])
49 subprocess.call(*args, **kwargs)
50
51
52 def check_call(*args, **kwargs):
53 logging.debug(args[0])
54 subprocess.check_call(*args, **kwargs)
55
56
57 def Popen(*args, **kwargs):
58 kwargs.setdefault('stdout', subprocess.PIPE)
59 kwargs.setdefault('stderr', subprocess.STDOUT)
60 logging.debug(args[0])
61 return subprocess.Popen(*args, **kwargs)
62
63
64 def commit_svn(repo):
65 """Commits the changes and returns the new revision number."""
66 # Basic parsing.
67 to_add = []
68 to_remove = []
69 for item in Popen(['svn', 'status'],
70 cwd=repo).communicate()[0].splitlines(False):
71 if item[0] == '?':
72 to_add.append(item[8:])
73 elif item[0] == '!':
74 to_remove.append(item[8:])
75 if to_add:
76 check_call(['svn', 'add', '--no-auto-props', '-q'] + to_add, cwd=repo)
77 if to_remove:
78 check_call(['svn', 'remove', '-q'] + to_remove, cwd=repo)
79 out = Popen(['svn', 'commit', repo, '-m', 'foo', '--non-interactive',
80 '--no-auth-cache', '--username', 'user1', '--password', 'foo'],
81 cwd=repo).communicate()[0]
82 rev = re.search(r'revision (\d+).', out).group(1)
83 st = Popen(['svn', 'status'], cwd=repo).communicate()[0]
84 assert len(st) == 0, st
85 logging.debug('At revision %s' % rev)
86 return rev
87
88
89 def commit_git(repo):
90 """Commits the changes and returns the new hash."""
91 check_call(['git', 'add', '-A', '-f'], cwd=repo)
92 out = Popen(['git', 'commit', '-m', 'foo'], cwd=repo).communicate()[0]
93 rev = re.search(r'^\[.*? ([a-f\d]+)\] ', out).group(1)
94 logging.debug('At revision %s' % rev)
95 return rev
96
97
42 class FakeRepos(object): 98 class FakeRepos(object):
99 """Generate both svn and git repositories to test gclient functionality.
100
101 Many DEPS functionalities need to be tested: Var, File, From, deps_os, hooks,
102 use_relative_paths.
103
104 And types of dependencies: Relative urls, Full urls, both svn and git."""
105
43 def __init__(self, trial_dir, leak, local_only): 106 def __init__(self, trial_dir, leak, local_only):
44 self.trial_dir = trial_dir 107 self.trial_dir = trial_dir
45 self.repos_dir = os.path.join(self.trial_dir, 'repos') 108 self.repos_dir = os.path.join(self.trial_dir, 'repos')
109 self.git_root = join(self.repos_dir, 'git')
110 self.svn_root = join(self.repos_dir, 'svn_checkout')
46 self.leak = leak 111 self.leak = leak
47 self.local_only = local_only 112 self.local_only = local_only
48 self.svnserve = [] 113 self.svnserve = []
49 self.gitdaemon = [] 114 self.gitdaemon = []
50 addKill() 115 addKill()
51 rmtree(self.trial_dir) 116 rmtree(self.trial_dir)
52 os.mkdir(self.trial_dir) 117 os.mkdir(self.trial_dir)
53 os.mkdir(self.repos_dir) 118 os.mkdir(self.repos_dir)
119 # Format is [ None, tree, tree, ...]
120 self.svn_revs = [None]
121 # Format is { repo: [ (hash, tree), (hash, tree), ... ], ... }
122 self.git_hashes = {}
54 123
55 def setUp(self): 124 def setUp(self):
56 self.setUpSVN() 125 self.setUpSVN()
57 self.setUpGIT() 126 self.setUpGIT()
58 127
59 def tearDown(self): 128 def tearDown(self):
60 for i in self.svnserve: 129 for i in self.svnserve:
130 logging.debug('Killing svnserve pid %s' % i.pid)
61 i.kill() 131 i.kill()
62 for i in self.gitdaemon: 132 for i in self.gitdaemon:
133 logging.debug('Killing git-daemon pid %s' % i.pid)
63 i.kill() 134 i.kill()
64 if not self.leak: 135 if not self.leak:
136 logging.debug('Removing %s' % self.trial_dir)
65 rmtree(self.trial_dir) 137 rmtree(self.trial_dir)
66 138
139 def _genTree(self, root, tree_dict):
140 """For a dictionary of file contents, generate a filesystem."""
141 if not os.path.isdir(root):
142 os.makedirs(root)
143 for (k, v) in tree_dict.iteritems():
144 k_os = k.replace('/', os.sep)
145 k_arr = k_os.split(os.sep)
146 if len(k_arr) > 1:
147 p = os.sep.join([root] + k_arr[:-1])
148 if not os.path.isdir(p):
149 os.makedirs(p)
150 if v is None:
151 os.remove(join(root, k))
152 else:
153 write(join(root, k), v)
154
67 def setUpSVN(self): 155 def setUpSVN(self):
68 """Creates subversion repositories and start the servers.""" 156 """Creates subversion repositories and start the servers."""
69 assert not self.svnserve 157 assert not self.svnserve
70 join = os.path.join
71 root = join(self.repos_dir, 'svn') 158 root = join(self.repos_dir, 'svn')
72 rmtree(root) 159 rmtree(root)
73 subprocess.check_call(['svnadmin', 'create', root]) 160 check_call(['svnadmin', 'create', root])
74 write(join(root, 'conf', 'svnserve.conf'), 161 write(join(root, 'conf', 'svnserve.conf'),
75 '[general]\n' 162 '[general]\n'
76 'anon-access = read\n' 163 'anon-access = read\n'
77 'auth-access = write\n' 164 'auth-access = write\n'
78 'password-db = passwd\n') 165 'password-db = passwd\n')
79 write(join(root, 'conf', 'passwd'), 166 write(join(root, 'conf', 'passwd'),
80 '[users]\n' 167 '[users]\n'
81 'user1 = foo\n' 168 'user1 = foo\n'
82 'user2 = bar\n') 169 'user2 = bar\n')
83 170
84 # Repos
85 repo = join(self.repos_dir, 'svn_import')
86 rmtree(repo)
87 os.mkdir(repo)
88 os.mkdir(join(repo, 'trunk'))
89 os.mkdir(join(repo, 'trunk', 'src'))
90 write(join(repo, 'trunk', 'src', 'DEPS'), """
91 # Smoke test DEPS file.
92 # Many DEPS functionalities need to be tested:
93 # Var
94 # File
95 # From
96 # deps_os
97 # hooks
98 # use_relative_paths
99 #
100 # Types of dependencies:
101 # Relative urls
102 # Full urls
103 # svn
104 # git
105
106 deps = {
107 'src/other': 'svn://%(host)s/svn/trunk/other',
108 'src/third_party': '/trunk/third_party',
109 }
110
111 deps_os = {
112 'mac': 'repo_4'
113 }
114 """ % {
115 'host': 'localhost',
116 })
117 write(join(repo, 'trunk', 'src', 'origin'), "svn/trunk/src")
118 os.mkdir(join(repo, 'trunk', 'other'))
119 write(join(repo, 'trunk', 'other', 'origin'), "svn/trunk/other")
120 os.mkdir(join(repo, 'trunk', 'third_party'))
121 write(join(repo, 'trunk', 'third_party', 'origin'), "svn/trunk/third_party")
122
123 # Start the daemon. 171 # Start the daemon.
124 cmd = ['svnserve', '-d', '--foreground', '-r', self.repos_dir] 172 cmd = ['svnserve', '-d', '--foreground', '-r', self.repos_dir]
125 if self.local_only: 173 if self.local_only:
126 cmd.append('--listen-host=127.0.0.1') 174 cmd.append('--listen-host=127.0.0.1')
127 self.svnserve.append(subprocess.Popen(cmd, cwd=root)) 175 logging.debug(cmd)
176 self.svnserve.append(Popen(cmd, cwd=root))
177 self.populateSvn()
128 178
129 # Import the repo. 179 def populateSvn(self):
130 subprocess.check_call(['svn', 'import', repo, 180 """Creates a few revisions of changes including DEPS files."""
131 'svn://127.0.0.1/svn', '-m', 'foo', '-q', 181 # Repos
132 '--no-auto-props', '--non-interactive', '--no-auth-cache', 182 check_call(['svn', 'checkout', 'svn://127.0.0.1/svn', self.svn_root, '-q',
133 '--username', 'user1', '--password', 'foo']) 183 '--non-interactive', '--no-auth-cache',
184 '--username', 'user1', '--password', 'foo'])
185 assert os.path.isdir(join(self.svn_root, '.svn'))
186 def file_system(rev, DEPS):
187 fs = {
188 'origin': 'svn@%(rev)d\n',
189 'trunk/origin': 'svn/trunk@%(rev)d\n',
190 'trunk/src/origin': 'svn/trunk/src@%(rev)d\n',
191 'trunk/src/third_party/origin': 'svn/trunk/src/third_party@%(rev)d\n',
192 'trunk/other/origin': 'src/trunk/other@%(rev)d\n',
193 'trunk/third_party/origin': 'svn/trunk/third_party@%(rev)d\n',
194 'trunk/third_party/foo/origin': 'svn/trunk/third_party/foo@%(rev)d\n',
195 'trunk/third_party/prout/origin': 'svn/trunk/third_party/foo@%(rev)d\n',
196 }
197 for k in fs.iterkeys():
198 fs[k] = fs[k] % { 'rev': rev }
199 fs['trunk/src/DEPS'] = DEPS
200 return fs
201
202 # Testing:
203 # - dependency disapear
204 # - dependency renamed
205 # - versioned and unversioned reference
206 # - relative and full reference
207 # - deps_os
208 # TODO(maruel):
209 # - var
210 # - hooks
211 # - File
212 self._commit_svn(file_system(1, """
213 deps = {
214 'src/other': 'svn://%(host)s/svn/trunk/other',
215 'src/third_party/fpp': '/trunk/third_party/foo',
216 }
217 deps_os = {
218 'mac': {
219 'src/third_party/prout': '/trunk/third_party/prout',
220 },
221 }""" % { 'host': '127.0.0.1' }))
222
223 self._commit_svn(file_system(2, """
224 deps = {
225 'src/other': 'svn://%(host)s/svn/trunk/other',
226 'src/third_party/foo': '/trunk/third_party/foo@1',
227 }
228 """ % { 'host': '127.0.0.1' }))
134 229
135 def setUpGIT(self): 230 def setUpGIT(self):
136 """Creates git repositories and start the servers.""" 231 """Creates git repositories and start the servers."""
137 assert not self.gitdaemon 232 assert not self.gitdaemon
138 join = os.path.join 233 rmtree(self.git_root)
139 root = join(self.repos_dir, 'git') 234 for repo in ['repo_%d' % r for r in range(1, 5)]:
140 rmtree(root) 235 check_call(['git', 'init', '-q', join(self.git_root, repo)])
141 os.mkdir(root) 236 self.git_hashes[repo] = []
142 # Repo 1
143 repo = join(root, 'repo_1')
144 subprocess.check_call(['git', 'init', '-q', repo])
145 write(join(repo, 'DEPS'), """
146 # Smoke test DEPS file.
147 # Many DEPS functionalities need to be tested:
148 # Var
149 # File
150 # From
151 # deps_os
152 # hooks
153 # use_relative_paths
154 #
155 # Types of dependencies:
156 # Relative urls
157 # Full urls
158 # svn
159 # git
160 237
238 # Testing:
239 # - dependency disapear
240 # - dependency renamed
241 # - versioned and unversioned reference
242 # - relative and full reference
243 # - deps_os
244 # TODO(maruel):
245 # - var
246 # - hooks
247 # - File
248 self._commit_git('repo_1', {
249 'DEPS': """
161 deps = { 250 deps = {
162 'repo2': 'git://%(host)s/git/repo_2', 251 'src/repo2': 'git://%(host)s/git/repo_2',
163 'repo2/repo3': '/repo_3', 252 'src/repo2/repo3': '/repo_3',
164 } 253 }
254 deps_os = {
255 'mac': {
256 'src/repo4': '/repo_4',
257 },
258 }""" % { 'host': '127.0.0.1' },
259 'origin': 'git/repo_1@1\n',
260 })
165 261
166 deps_os = { 262 self._commit_git('repo_2', {
167 'mac': 'repo_4' 263 'origin': "git/repo_2@1\n"
264 })
265
266 self._commit_git('repo_2', {
267 'origin': "git/repo_2@2\n"
268 })
269
270 self._commit_git('repo_3', {
271 'origin': "git/repo_3@1\n"
272 })
273
274 self._commit_git('repo_3', {
275 'origin': "git/repo_3@2\n"
276 })
277
278 self._commit_git('repo_4', {
279 'origin': "git/repo_4@1\n"
280 })
281
282 self._commit_git('repo_4', {
283 'origin': "git/repo_4@2\n"
284 })
285
286 self._commit_git('repo_1', {
287 'DEPS': """
288 deps = {
289 'src/repo2': 'git://%(host)s/git/repo_2@%(hash)s',
290 'src/repo2/repo_renamed': '/repo_3',
168 } 291 }
169 """ % { 292 """ % { 'host': '127.0.0.1', 'hash': self.git_hashes['repo_2'][0][0] },
170 'host': 'localhost', 293 'origin': "git/repo_1@2\n"
171 }) 294 })
172 write(join(repo, 'origin'), "git/repo_1")
173 subprocess.check_call(['git', 'add', '-A', '-f'], cwd=repo)
174 subprocess.check_call(['git', 'commit', '-q', '-m', 'foo'], cwd=repo)
175
176 # Repo 2
177 repo = join(root, 'repo_2')
178 subprocess.check_call(['git', 'init', '-q', repo])
179 write(join(repo, 'origin'), "git/repo_2")
180 subprocess.check_call(['git', 'add', '-A', '-f'], cwd=repo)
181 subprocess.check_call(['git', 'commit', '-q', '-m', 'foo'], cwd=repo)
182
183 # Repo 3
184 repo = join(root, 'repo_3')
185 subprocess.check_call(['git', 'init', '-q', repo])
186 write(join(repo, 'origin'), "git/repo_3")
187 subprocess.check_call(['git', 'add', '-A', '-f'], cwd=repo)
188 subprocess.check_call(['git', 'commit', '-q', '-m', 'foo'], cwd=repo)
189 295
190 # Start the daemon. 296 # Start the daemon.
191 cmd = ['git', 'daemon', '--export-all', '--base-path=' + self.repos_dir] 297 cmd = ['git', 'daemon', '--export-all', '--base-path=' + self.repos_dir]
192 if self.local_only: 298 if self.local_only:
193 cmd.append('--listen=127.0.0.1') 299 cmd.append('--listen=127.0.0.1')
194 self.gitdaemon.append(subprocess.Popen(cmd, cwd=self.repos_dir, 300 logging.debug(cmd)
195 stderr=subprocess.PIPE)) 301 self.gitdaemon.append(Popen(cmd, cwd=self.repos_dir))
302
303 def _commit_svn(self, tree):
304 self._genTree(self.svn_root, tree)
305 commit_svn(self.svn_root)
306 if self.svn_revs and self.svn_revs[-1]:
307 new_tree = self.svn_revs[-1].copy()
308 new_tree.update(tree)
309 else:
310 new_tree = tree.copy()
311 self.svn_revs.append(new_tree)
312
313 def _commit_git(self, repo, tree):
314 repo_root = join(self.git_root, repo)
315 self._genTree(repo_root, tree)
316 hash = commit_git(repo_root)
317 if self.git_hashes[repo]:
318 new_tree = self.git_hashes[repo][-1][1].copy()
319 new_tree.update(tree)
320 else:
321 new_tree = tree.copy()
322 self.git_hashes[repo].append((hash, new_tree))
323
324
325 def main(argv):
326 leak = '-l' in argv
327 if leak:
328 argv.remove('-l')
329 verbose = '-v' in argv
330 if verbose:
331 logging.basicConfig(level=logging.DEBUG)
332 argv.remove('-v')
333 assert len(argv) == 1, argv
334 trial_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),
335 '_trial')
336 print 'Using %s' % trial_dir
337 fake = FakeRepos(trial_dir, leak, True)
338 try:
339 fake.setUp()
340 print('Fake setup, press enter to quit or Ctrl-C to keep the checkouts.')
341 sys.stdin.readline()
342 except KeyboardInterrupt:
343 fake.leak = True
344 finally:
345 fake.tearDown()
346 return 0
347
196 348
197 if __name__ == '__main__': 349 if __name__ == '__main__':
198 fake = FakeRepos(os.path.dirname(os.path.abspath(__file__)), False) 350 sys.exit(main(sys.argv))
199 try:
200 fake.setUp()
201 sys.stdin.readline()
202 finally:
203 fake.tearDown()
OLDNEW
« no previous file with comments | « no previous file | tests/gclient_smoketest.py » ('j') | tests/gclient_smoketest.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698