Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/env python | |
| 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 """Unit tests for git_common.py""" | |
| 7 | |
| 8 import binascii | |
| 9 import collections | |
| 10 import os | |
| 11 import signal | |
| 12 import sys | |
| 13 import tempfile | |
| 14 import time | |
| 15 import unittest | |
| 16 | |
| 17 DEPOT_TOOLS_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
| 18 sys.path.insert(0, DEPOT_TOOLS_ROOT) | |
| 19 | |
| 20 from testing_support import git_test_utils | |
|
M-A Ruel
2013/11/17 19:54:58
sort
iannucci
2013/11/18 05:38:56
Dangit! Why don't we have pylint do this....
| |
| 21 from testing_support import coverage_utils | |
| 22 | |
| 23 | |
| 24 class GitCommonTestBase(unittest.TestCase): | |
| 25 @classmethod | |
| 26 def setUpClass(cls): | |
| 27 super(GitCommonTestBase, cls).setUpClass() | |
| 28 import git_common | |
| 29 cls.gc = git_common | |
| 30 | |
| 31 | |
| 32 class Support(GitCommonTestBase): | |
| 33 def _testMemoizeOneBody(self, threadsafe): | |
| 34 calls = collections.defaultdict(int) | |
| 35 def double_if_even(val): | |
| 36 calls[val] += 1 | |
| 37 return val * 2 if val % 2 == 0 else None | |
| 38 # Use this explicitly as a wrapper fn instead of a decorator. Otherwise | |
| 39 # pylint crashes (!!) | |
| 40 double_if_even = self.gc.memoize_one(threadsafe=threadsafe)(double_if_even) | |
| 41 | |
| 42 self.assertEqual(4, double_if_even(2)) | |
| 43 self.assertEqual(4, double_if_even(2)) | |
| 44 self.assertEqual(None, double_if_even(1)) | |
| 45 self.assertEqual(None, double_if_even(1)) | |
| 46 self.assertDictEqual({1: 2, 2: 1}, calls) | |
| 47 | |
| 48 double_if_even.set(10, 20) | |
| 49 self.assertEqual(20, double_if_even(10)) | |
| 50 self.assertDictEqual({1: 2, 2: 1}, calls) | |
| 51 | |
| 52 double_if_even.clear() | |
| 53 self.assertEqual(4, double_if_even(2)) | |
| 54 self.assertEqual(4, double_if_even(2)) | |
| 55 self.assertEqual(None, double_if_even(1)) | |
| 56 self.assertEqual(None, double_if_even(1)) | |
| 57 self.assertEqual(20, double_if_even(10)) | |
| 58 self.assertDictEqual({1: 4, 2: 2, 10: 1}, calls) | |
| 59 | |
| 60 def testMemoizeOne(self): | |
| 61 self._testMemoizeOneBody(threadsafe=False) | |
| 62 | |
| 63 def testMemoizeOneThreadsafe(self): | |
| 64 self._testMemoizeOneBody(threadsafe=True) | |
| 65 | |
| 66 | |
| 67 def slow_square(i): | |
| 68 """Helper for ScopedPoolTest. | |
| 69 | |
| 70 Must be global because non top-level functions aren't pickleable. | |
| 71 """ | |
| 72 time.sleep(0.2) | |
| 73 return i ** 2 | |
| 74 | |
| 75 | |
| 76 class ScopedPoolTest(GitCommonTestBase): | |
| 77 if sys.platform.startswith('win'): | |
| 78 CTRL_C = signal.CTRL_C_EVENT | |
| 79 else: | |
| 80 CTRL_C = signal.SIGINT | |
|
M-A Ruel
2013/11/17 19:54:58
CTRL_C = signal.CTRL_C_EVENT if sys.platform == 'w
iannucci
2013/11/18 05:38:56
Yeah, I know... it's weird. Done.
| |
| 81 | |
| 82 def testThreads(self): | |
| 83 result = [] | |
| 84 with self.gc.ScopedPool(kind='threads') as pool: | |
| 85 for i in pool.imap(slow_square, xrange(10)): | |
|
M-A Ruel
2013/11/17 19:54:58
result = list(pool.imap(slow_square, xrange(10)))
iannucci
2013/11/18 05:38:56
Lol, done.
| |
| 86 result.append(i) | |
| 87 self.assertEqual([0, 1, 4, 9, 16, 25, 36, 49, 64, 81], result) | |
| 88 | |
| 89 def testThreadsCtrlC(self): | |
| 90 result = [] | |
| 91 with self.assertRaises(KeyboardInterrupt): | |
| 92 with self.gc.ScopedPool(kind='threads') as pool: | |
| 93 # Make sure this pool is interrupted in mid-swing | |
| 94 for i in pool.imap(slow_square, xrange(1000000)): | |
|
M-A Ruel
2013/11/17 19:54:58
One thing I prefer is to use a list of threading.E
iannucci
2013/11/18 05:38:56
Tried it. Surprise! Python signal-handling is brok
| |
| 95 if i > 32: | |
| 96 os.kill(os.getpid(), self.CTRL_C) | |
| 97 result.append(i) | |
| 98 self.assertEqual([0, 1, 4, 9, 16, 25], result) | |
| 99 | |
| 100 def testProcs(self): | |
| 101 result = [] | |
| 102 with self.gc.ScopedPool() as pool: | |
| 103 for i in pool.imap(slow_square, xrange(10)): | |
|
M-A Ruel
2013/11/17 19:54:58
same
iannucci
2013/11/18 05:38:56
Done.
| |
| 104 result.append(i) | |
| 105 self.assertEqual([0, 1, 4, 9, 16, 25, 36, 49, 64, 81], result) | |
| 106 | |
| 107 def testProcsCtrlC(self): | |
| 108 result = [] | |
| 109 with self.assertRaises(KeyboardInterrupt): | |
| 110 with self.gc.ScopedPool() as pool: | |
| 111 # Make sure this pool is interrupted in mid-swing | |
| 112 for i in pool.imap(slow_square, xrange(1000000)): | |
| 113 if i > 32: | |
| 114 os.kill(os.getpid(), self.CTRL_C) | |
| 115 result.append(i) | |
| 116 self.assertEqual([0, 1, 4, 9, 16, 25], result) | |
| 117 | |
| 118 | |
| 119 class ProgressPrinterTest(GitCommonTestBase): | |
| 120 class FakeStream(object): | |
| 121 def __init__(self): | |
| 122 self.data = set() | |
| 123 self.count = 0 | |
| 124 | |
| 125 def write(self, line): | |
| 126 self.data.add(line) | |
| 127 | |
| 128 def flush(self): | |
| 129 self.count += 1 | |
| 130 | |
| 131 @unittest.expectedFailure | |
| 132 def testBasic(self): | |
| 133 """This test is probably racy, but I don't have a better alternative.""" | |
| 134 fmt = '%(count)d/10' | |
| 135 stream = self.FakeStream() | |
| 136 | |
| 137 pp = self.gc.ProgressPrinter(fmt, enabled=True, stream=stream, period=0.01) | |
| 138 with pp as inc: | |
| 139 for _ in xrange(10): | |
| 140 time.sleep(0.02) | |
| 141 inc() | |
| 142 | |
| 143 filtered = set(x.strip() for x in stream.data) | |
| 144 rslt = set(fmt % {'count': i} for i in xrange(11)) | |
| 145 self.assertSetEqual(filtered, rslt) | |
| 146 self.assertGreaterEqual(stream.count, 10) | |
| 147 | |
| 148 | |
| 149 class GitReadOnlyFunctionsTest(git_test_utils.GitRepoReadOnlyTestBase, | |
| 150 GitCommonTestBase): | |
| 151 REPO = """ | |
| 152 A B C D | |
| 153 B E D | |
| 154 """ | |
| 155 | |
| 156 COMMIT_A = { | |
| 157 'some/files/file1': {'data': 'file1'}, | |
| 158 'some/files/file2': {'data': 'file2'}, | |
| 159 'some/files/file3': {'data': 'file3'}, | |
| 160 'some/other/file': {'data': 'otherfile'}, | |
| 161 } | |
| 162 | |
| 163 COMMIT_C = { | |
| 164 'some/files/file2': { | |
| 165 'mode': 0755, | |
| 166 'data': 'file2 - vanilla'}, | |
| 167 } | |
| 168 | |
| 169 COMMIT_E = { | |
| 170 'some/files/file2': {'data': 'file2 - merged'}, | |
| 171 } | |
| 172 | |
| 173 COMMIT_D = { | |
| 174 'some/files/file2': {'data': 'file2 - vanilla\nfile2 - merged'}, | |
| 175 } | |
| 176 | |
| 177 def testHashes(self): | |
| 178 ret = self.repo.run( | |
| 179 self.gc.hashes, *[ | |
| 180 'master', | |
| 181 'master~3', | |
| 182 self.repo['E']+'~', | |
| 183 self.repo['D']+'^2', | |
| 184 'tag_C^{}', | |
| 185 ] | |
| 186 ) | |
| 187 self.assertEqual([ | |
| 188 self.repo['D'], | |
| 189 self.repo['A'], | |
| 190 self.repo['B'], | |
| 191 self.repo['E'], | |
| 192 self.repo['C'], | |
| 193 ], ret) | |
| 194 | |
| 195 def testParseCommitrefs(self): | |
| 196 ret = self.repo.run( | |
| 197 self.gc.parse_commitrefs, *[ | |
| 198 'master', | |
| 199 'master~3', | |
| 200 self.repo['E']+'~', | |
| 201 self.repo['D']+'^2', | |
| 202 'tag_C^{}', | |
| 203 ] | |
| 204 ) | |
| 205 self.assertEqual(ret, map(binascii.unhexlify, [ | |
| 206 self.repo['D'], | |
| 207 self.repo['A'], | |
| 208 self.repo['B'], | |
| 209 self.repo['E'], | |
| 210 self.repo['C'], | |
| 211 ])) | |
| 212 | |
| 213 with self.assertRaisesRegexp(Exception, r"one of \('master', 'bananas'\)"): | |
| 214 self.repo.run(self.gc.parse_commitrefs, 'master', 'bananas') | |
| 215 | |
| 216 def testTree(self): | |
| 217 tree = self.repo.run(self.gc.tree, 'master:some/files') | |
| 218 file1 = self.COMMIT_A['some/files/file1']['data'] | |
| 219 file2 = self.COMMIT_D['some/files/file2']['data'] | |
| 220 file3 = self.COMMIT_A['some/files/file3']['data'] | |
| 221 self.assertEquals(tree['file1'], | |
| 222 ('100644', 'blob', git_test_utils.git_hash_data(file1))) | |
| 223 self.assertEquals(tree['file2'], | |
| 224 ('100755', 'blob', git_test_utils.git_hash_data(file2))) | |
| 225 self.assertEquals(tree['file3'], | |
| 226 ('100644', 'blob', git_test_utils.git_hash_data(file3))) | |
| 227 | |
| 228 tree = self.repo.run(self.gc.tree, 'master:some') | |
| 229 self.assertEquals(len(tree), 2) | |
| 230 # Don't check the tree hash because we're lazy :) | |
| 231 self.assertEquals(tree['files'][:2], ('040000', 'tree')) | |
| 232 | |
| 233 tree = self.repo.run(self.gc.tree, 'master:wat') | |
| 234 self.assertEqual(tree, None) | |
| 235 | |
| 236 def testTreeRecursive(self): | |
| 237 tree = self.repo.run(self.gc.tree, 'master:some', recurse=True) | |
| 238 file1 = self.COMMIT_A['some/files/file1']['data'] | |
| 239 file2 = self.COMMIT_D['some/files/file2']['data'] | |
| 240 file3 = self.COMMIT_A['some/files/file3']['data'] | |
| 241 other = self.COMMIT_A['some/other/file']['data'] | |
| 242 self.assertEquals(tree['files/file1'], | |
| 243 ('100644', 'blob', git_test_utils.git_hash_data(file1))) | |
| 244 self.assertEquals(tree['files/file2'], | |
| 245 ('100755', 'blob', git_test_utils.git_hash_data(file2))) | |
| 246 self.assertEquals(tree['files/file3'], | |
| 247 ('100644', 'blob', git_test_utils.git_hash_data(file3))) | |
| 248 self.assertEquals(tree['other/file'], | |
| 249 ('100644', 'blob', git_test_utils.git_hash_data(other))) | |
| 250 | |
| 251 | |
| 252 class GitMutableFunctionsTest(git_test_utils.GitRepoReadWriteTestBase, | |
| 253 GitCommonTestBase): | |
| 254 REPO = '' | |
| 255 | |
| 256 def _intern_data(self, data): | |
| 257 with tempfile.TemporaryFile() as f: | |
| 258 f.write(data) | |
| 259 f.seek(0) | |
| 260 return self.repo.run(self.gc.intern_f, f) | |
| 261 | |
| 262 def testInternF(self): | |
| 263 data = 'CoolBobcatsBro' | |
| 264 data_hash = self._intern_data(data) | |
| 265 self.assertEquals(git_test_utils.git_hash_data(data), data_hash) | |
| 266 self.assertEquals(data, self.repo.git('cat-file', 'blob', data_hash).stdout) | |
| 267 | |
| 268 def testMkTree(self): | |
| 269 tree = {} | |
| 270 for i in 1, 2, 3: | |
| 271 name = 'file%d' % i | |
| 272 tree[name] = ('100644', 'blob', self._intern_data(name)) | |
| 273 tree_hash = self.repo.run(self.gc.mktree, tree) | |
| 274 self.assertEquals('37b61866d6e061c4ba478e7eb525be7b5752737d', tree_hash) | |
| 275 | |
| 276 | |
| 277 if __name__ == '__main__': | |
| 278 sys.exit(coverage_utils.covered_main( | |
| 279 os.path.join(DEPOT_TOOLS_ROOT, 'git_common.py') | |
| 280 )) | |
| OLD | NEW |