OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import atexit | 5 import atexit |
6 import collections | 6 import collections |
7 import copy | 7 import copy |
8 import datetime | 8 import datetime |
9 import hashlib | 9 import hashlib |
10 import os | 10 import os |
11 import shutil | 11 import shutil |
12 import subprocess | 12 import subprocess |
| 13 import sys |
13 import tempfile | 14 import tempfile |
14 import unittest | 15 import unittest |
15 | 16 |
| 17 from cStringIO import StringIO |
| 18 |
16 | 19 |
17 def git_hash_data(data, typ='blob'): | 20 def git_hash_data(data, typ='blob'): |
18 """Calculate the git-style SHA1 for some data. | 21 """Calculate the git-style SHA1 for some data. |
19 | 22 |
20 Only supports 'blob' type data at the moment. | 23 Only supports 'blob' type data at the moment. |
21 """ | 24 """ |
22 assert typ == 'blob', 'Only support blobs for now' | 25 assert typ == 'blob', 'Only support blobs for now' |
23 return hashlib.sha1('blob %s\0%s' % (len(data), data)).hexdigest() | 26 return hashlib.sha1('blob %s\0%s' % (len(data), data)).hexdigest() |
24 | 27 |
25 | 28 |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 """ | 254 """ |
252 self.repo_path = tempfile.mkdtemp(dir=self.BASE_TEMP_DIR) | 255 self.repo_path = tempfile.mkdtemp(dir=self.BASE_TEMP_DIR) |
253 self.commit_map = {} | 256 self.commit_map = {} |
254 self._date = datetime.datetime(1970, 1, 1) | 257 self._date = datetime.datetime(1970, 1, 1) |
255 | 258 |
256 self.git('init') | 259 self.git('init') |
257 for commit in schema.walk(): | 260 for commit in schema.walk(): |
258 self._add_schema_commit(commit, schema.data_for(commit.name)) | 261 self._add_schema_commit(commit, schema.data_for(commit.name)) |
259 self.last_commit = self[commit.name] | 262 self.last_commit = self[commit.name] |
260 if schema.master: | 263 if schema.master: |
261 self.git('update-ref', 'master', self[schema.master]) | 264 self.git('update-ref', 'refs/heads/master', self[schema.master]) |
262 | 265 |
263 def __getitem__(self, commit_name): | 266 def __getitem__(self, commit_name): |
264 """Gets the hash of a commit by its schema name. | 267 """Gets the hash of a commit by its schema name. |
265 | 268 |
266 >>> r = GitRepo(GitRepoSchema('A B C')) | 269 >>> r = GitRepo(GitRepoSchema('A B C')) |
267 >>> r['B'] | 270 >>> r['B'] |
268 '7381febe1da03b09da47f009963ab7998a974935' | 271 '7381febe1da03b09da47f009963ab7998a974935' |
269 """ | 272 """ |
270 return self.commit_map[commit_name] | 273 return self.commit_map[commit_name] |
271 | 274 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 """Run a python function with the given args and kwargs with the cwd set to | 350 """Run a python function with the given args and kwargs with the cwd set to |
348 the git repo.""" | 351 the git repo.""" |
349 assert self.repo_path is not None | 352 assert self.repo_path is not None |
350 curdir = os.getcwd() | 353 curdir = os.getcwd() |
351 try: | 354 try: |
352 os.chdir(self.repo_path) | 355 os.chdir(self.repo_path) |
353 return fn(*args, **kwargs) | 356 return fn(*args, **kwargs) |
354 finally: | 357 finally: |
355 os.chdir(curdir) | 358 os.chdir(curdir) |
356 | 359 |
| 360 def capture_stdio(self, fn, *args, **kwargs): |
| 361 """Run a python function with the given args and kwargs with the cwd set to |
| 362 the git repo. |
| 363 |
| 364 Returns the (stdout, stderr) of whatever ran, instead of the what |fn| |
| 365 returned. |
| 366 """ |
| 367 stdout = sys.stdout |
| 368 stderr = sys.stderr |
| 369 try: |
| 370 sys.stdout = StringIO() |
| 371 sys.stderr = StringIO() |
| 372 self.run(fn, *args, **kwargs) |
| 373 return sys.stdout.getvalue(), sys.stderr.getvalue() |
| 374 finally: |
| 375 sys.stdout = stdout |
| 376 sys.stderr = stderr |
| 377 |
357 | 378 |
358 class GitRepoSchemaTestBase(unittest.TestCase): | 379 class GitRepoSchemaTestBase(unittest.TestCase): |
359 """A TestCase with a built-in GitRepoSchema. | 380 """A TestCase with a built-in GitRepoSchema. |
360 | 381 |
361 Expects a class variable REPO to be a GitRepoSchema string in the form | 382 Expects a class variable REPO_SCHEMA to be a GitRepoSchema string in the form |
362 described by that class. | 383 described by that class. |
363 | 384 |
364 You may also set class variables in the form COMMIT_%(commit_name)s, which | 385 You may also set class variables in the form COMMIT_%(commit_name)s, which |
365 provide the content for the given commit_name commits. | 386 provide the content for the given commit_name commits. |
366 | 387 |
367 You probably will end up using either GitRepoReadOnlyTestBase or | 388 You probably will end up using either GitRepoReadOnlyTestBase or |
368 GitRepoReadWriteTestBase for real tests. | 389 GitRepoReadWriteTestBase for real tests. |
369 """ | 390 """ |
370 REPO = None | 391 REPO_SCHEMA = None |
371 | 392 |
372 @classmethod | 393 @classmethod |
373 def getRepoContent(cls, commit): | 394 def getRepoContent(cls, commit): |
374 return getattr(cls, 'COMMIT_%s' % commit, None) | 395 return getattr(cls, 'COMMIT_%s' % commit, None) |
375 | 396 |
376 @classmethod | 397 @classmethod |
377 def setUpClass(cls): | 398 def setUpClass(cls): |
378 super(GitRepoSchemaTestBase, cls).setUpClass() | 399 super(GitRepoSchemaTestBase, cls).setUpClass() |
379 assert cls.REPO is not None | 400 assert cls.REPO_SCHEMA is not None |
380 cls.r_schema = GitRepoSchema(cls.REPO, cls.getRepoContent) | 401 cls.r_schema = GitRepoSchema(cls.REPO_SCHEMA, cls.getRepoContent) |
381 | 402 |
382 | 403 |
383 class GitRepoReadOnlyTestBase(GitRepoSchemaTestBase): | 404 class GitRepoReadOnlyTestBase(GitRepoSchemaTestBase): |
384 """Injects a GitRepo object given the schema and content from | 405 """Injects a GitRepo object given the schema and content from |
385 GitRepoSchemaTestBase into TestCase classes which subclass this. | 406 GitRepoSchemaTestBase into TestCase classes which subclass this. |
386 | 407 |
387 This GitRepo will appear as self.repo, and will be deleted and recreated once | 408 This GitRepo will appear as self.repo, and will be deleted and recreated once |
388 for the duration of all the tests in the subclass. | 409 for the duration of all the tests in the subclass. |
389 """ | 410 """ |
390 REPO = None | 411 REPO_SCHEMA = None |
391 | 412 |
392 @classmethod | 413 @classmethod |
393 def setUpClass(cls): | 414 def setUpClass(cls): |
394 super(GitRepoReadOnlyTestBase, cls).setUpClass() | 415 super(GitRepoReadOnlyTestBase, cls).setUpClass() |
395 assert cls.REPO is not None | 416 assert cls.REPO_SCHEMA is not None |
396 cls.repo = cls.r_schema.reify() | 417 cls.repo = cls.r_schema.reify() |
397 | 418 |
398 def setUp(self): | 419 def setUp(self): |
399 self.repo.git('checkout', '-f', self.repo.last_commit) | 420 self.repo.git('checkout', '-f', self.repo.last_commit) |
400 | 421 |
401 @classmethod | 422 @classmethod |
402 def tearDownClass(cls): | 423 def tearDownClass(cls): |
403 cls.repo.nuke() | 424 cls.repo.nuke() |
404 super(GitRepoReadOnlyTestBase, cls).tearDownClass() | 425 super(GitRepoReadOnlyTestBase, cls).tearDownClass() |
405 | 426 |
406 | 427 |
407 class GitRepoReadWriteTestBase(GitRepoSchemaTestBase): | 428 class GitRepoReadWriteTestBase(GitRepoSchemaTestBase): |
408 """Injects a GitRepo object given the schema and content from | 429 """Injects a GitRepo object given the schema and content from |
409 GitRepoSchemaTestBase into TestCase classes which subclass this. | 430 GitRepoSchemaTestBase into TestCase classes which subclass this. |
410 | 431 |
411 This GitRepo will appear as self.repo, and will be deleted and recreated for | 432 This GitRepo will appear as self.repo, and will be deleted and recreated for |
412 each test function in the subclass. | 433 each test function in the subclass. |
413 """ | 434 """ |
414 REPO = None | 435 REPO_SCHEMA = None |
415 | 436 |
416 def setUp(self): | 437 def setUp(self): |
417 super(GitRepoReadWriteTestBase, self).setUp() | 438 super(GitRepoReadWriteTestBase, self).setUp() |
418 self.repo = self.r_schema.reify() | 439 self.repo = self.r_schema.reify() |
419 | 440 |
420 def tearDown(self): | 441 def tearDown(self): |
421 self.repo.nuke() | 442 self.repo.nuke() |
422 super(GitRepoReadWriteTestBase, self).tearDown() | 443 super(GitRepoReadWriteTestBase, self).tearDown() |
OLD | NEW |