Merge pull request #915 from 0xflotus/patch-1
[git-cola.git] / test / git_test.py
blobf016f6d078e2f991f8d49664895451ec753daf44
1 #!/usr/bin/env python
2 """Tests various operations using the cola.git module
3 """
4 from __future__ import absolute_import, division, unicode_literals
5 import unittest
7 try:
8 from unittest.mock import patch
9 except ImportError:
10 from mock import patch
12 from cola import git
13 from cola.git import STDOUT
16 class GitModuleTestCase(unittest.TestCase):
18 @patch('cola.git.is_git_dir')
19 def test_find_git_dir_None(self, is_git_dir):
21 paths = git.find_git_directory(None)
23 self.assertFalse(is_git_dir.called)
24 self.assertEqual(None, paths.git_dir)
25 self.assertEqual(None, paths.git_file)
26 self.assertEqual(None, paths.worktree)
28 @patch('cola.git.is_git_dir')
29 def test_find_git_dir_empty_string(self, is_git_dir):
31 paths = git.find_git_directory('')
33 self.assertFalse(is_git_dir.called)
34 self.assertEqual(None, paths.git_dir)
35 self.assertEqual(None, paths.git_file)
36 self.assertEqual(None, paths.worktree)
38 @patch('cola.git.is_git_dir')
39 def test_find_git_dir_never_found(self, is_git_dir):
40 is_git_dir.return_value = False
42 paths = git.find_git_directory('/does/not/exist')
44 self.assertTrue(is_git_dir.called)
45 self.assertEqual(None, paths.git_dir)
46 self.assertEqual(None, paths.git_file)
47 self.assertEqual(None, paths.worktree)
49 self.assertEqual(8, is_git_dir.call_count)
50 kwargs = {}
51 is_git_dir.assert_has_calls([
52 (('/does/not/exist',), kwargs),
53 (('/does/not/exist/.git',), kwargs),
54 (('/does/not',), kwargs),
55 (('/does/not/.git',), kwargs),
56 (('/does',), kwargs),
57 (('/does/.git',), kwargs),
58 (('/',), kwargs),
59 (('/.git',), kwargs),
62 @patch('cola.git.is_git_dir')
63 def test_find_git_dir_found_right_away(self, is_git_dir):
64 git_dir = '/seems/to/exist/.git'
65 worktree = '/seems/to/exist'
66 is_git_dir.return_value = True
68 paths = git.find_git_directory(git_dir)
70 self.assertTrue(is_git_dir.called)
71 self.assertEqual(git_dir, paths.git_dir)
72 self.assertEqual(None, paths.git_file)
73 self.assertEqual(worktree, paths.worktree)
75 @patch('cola.git.is_git_dir')
76 def test_find_git_does_discovery(self, is_git_dir):
77 git_dir = '/the/root/.git'
78 worktree = '/the/root'
79 is_git_dir.side_effect = lambda x: x == git_dir
81 paths = git.find_git_directory('/the/root/sub/dir')
83 self.assertEqual(git_dir, paths.git_dir)
84 self.assertEqual(None, paths.git_file)
85 self.assertEqual(worktree, paths.worktree)
87 @patch('cola.git.read_git_file')
88 @patch('cola.git.is_git_file')
89 @patch('cola.git.is_git_dir')
90 def test_find_git_honors_git_files(self,
91 is_git_dir,
92 is_git_file,
93 read_git_file):
94 git_file = '/the/root/.git'
95 worktree = '/the/root'
96 git_dir = '/super/module/.git/modules/root'
98 is_git_dir.side_effect = lambda x: x == git_file
99 is_git_file.side_effect = lambda x: x == git_file
100 read_git_file.return_value = git_dir
102 paths = git.find_git_directory('/the/root/sub/dir')
104 self.assertEqual(git_dir, paths.git_dir)
105 self.assertEqual(git_file, paths.git_file)
106 self.assertEqual(worktree, paths.worktree)
108 kwargs = {}
109 self.assertEqual(6, is_git_dir.call_count)
110 is_git_dir.assert_has_calls([
111 (('/the/root/sub/dir',), kwargs),
112 (('/the/root/sub/dir/.git',), kwargs),
113 (('/the/root/sub',), kwargs),
114 (('/the/root/sub/.git',), kwargs),
115 (('/the/root',), kwargs),
116 (('/the/root/.git',), kwargs),
118 read_git_file.assert_called_once_with('/the/root/.git')
120 @patch('cola.core.getenv')
121 @patch('cola.git.is_git_dir')
122 def test_find_git_honors_ceiling_dirs(self, is_git_dir, getenv):
124 git_dir = '/ceiling/.git'
125 ceiling = '/tmp:/ceiling:/other/ceiling'
126 is_git_dir.side_effect = lambda x: x == git_dir
128 def mock_getenv(k, v=None):
129 if k == 'GIT_CEILING_DIRECTORIES':
130 return ceiling
131 return v
133 getenv.side_effect = mock_getenv
135 paths = git.find_git_directory('/ceiling/sub/dir')
137 self.assertEqual(None, paths.git_dir)
138 self.assertEqual(None, paths.git_file)
139 self.assertEqual(None, paths.worktree)
141 self.assertEqual(4, is_git_dir.call_count)
142 kwargs = {}
143 is_git_dir.assert_has_calls([
144 (('/ceiling/sub/dir',), kwargs),
145 (('/ceiling/sub/dir/.git',), kwargs),
146 (('/ceiling/sub',), kwargs),
147 (('/ceiling/sub/.git',), kwargs),
150 @patch('cola.core.islink')
151 @patch('cola.core.isdir')
152 @patch('cola.core.isfile')
153 def test_is_git_dir_finds_linked_repository(self, isfile, isdir, islink):
154 dirs = set([
155 '/foo',
156 '/foo/.git',
157 '/foo/.git/refs',
158 '/foo/.git/objects',
159 '/foo/.git/worktrees',
160 '/foo/.git/worktrees/foo',
162 files = set([
163 '/foo/.git/HEAD',
164 '/foo/.git/worktrees/foo/HEAD',
165 '/foo/.git/worktrees/foo/index',
166 '/foo/.git/worktrees/foo/commondir',
167 '/foo/.git/worktrees/foo/gitdir',
169 islink.return_value = False
170 isfile.side_effect = lambda x: x in files
171 isdir.side_effect = lambda x: x in dirs
173 self.assertTrue(git.is_git_dir('/foo/.git/worktrees/foo'))
174 self.assertTrue(git.is_git_dir('/foo/.git'))
177 class GitCommandTest(unittest.TestCase):
178 """Runs tests using a git.Git instance"""
180 def setUp(self):
181 """Creates a git.Git instance for later use"""
182 self.git = git.Git()
184 def test_transform_kwargs_empty(self):
185 expect = []
186 actual = git.transform_kwargs(foo=None, bar=False)
187 self.assertEqual(expect, actual)
189 def test_transform_kwargs_single_dash_from_True(self):
190 """Single dash for one-character True"""
191 expect = ['-a']
192 actual = git.transform_kwargs(a=True)
193 self.assertEqual(expect, actual)
195 def test_transform_kwargs_no_single_dash_from_False(self):
196 """No single-dash for False"""
197 expect = []
198 actual = git.transform_kwargs(a=False)
199 self.assertEqual(expect, actual)
201 def test_transform_kwargs_double_dash_from_True(self):
202 """Double-dash for longer True"""
203 expect = ['--abc']
204 actual = git.transform_kwargs(abc=True)
205 self.assertEqual(expect, actual)
207 def test_transform_kwargs_no_double_dash_from_True(self):
208 """No double-dash for False"""
209 expect = []
210 actual = git.transform_kwargs(abc=False)
211 self.assertEqual(expect, actual)
213 def test_transform_kwargs_single_dash_int(self):
214 expect = ['-a1']
215 actual = git.transform_kwargs(a=1)
216 self.assertEqual(expect, actual)
218 def test_transform_kwargs_double_dash_int(self):
219 expect = ['--abc=1']
220 actual = git.transform_kwargs(abc=1)
221 self.assertEqual(expect, actual)
223 def test_transform_kwargs_single_dash_float(self):
224 expect = ['-a1.5']
225 actual = git.transform_kwargs(a=1.5)
226 self.assertEqual(expect, actual)
228 def test_transform_kwargs_double_dash_float(self):
229 expect = ['--abc=1.5']
230 actual = git.transform_kwargs(abc=1.5)
231 self.assertEqual(expect, actual)
233 def test_transform_kwargs_single_dash_string(self):
234 expect = ['-abc']
235 actual = git.transform_kwargs(a='bc')
236 self.assertEqual(expect, actual)
238 def test_transform_double_single_dash_string(self):
239 expect = ['--abc=def']
240 actual = git.transform_kwargs(abc='def')
241 self.assertEqual(expect, actual)
243 def test_version(self):
244 """Test running 'git version'"""
245 version = self.git.version()[STDOUT]
246 self.assertTrue(version.startswith('git version'))
248 def test_stdout(self):
249 """Test overflowing the stdout buffer"""
250 # Write to stdout only
251 code = ('import sys;'
252 's = "\\0" * (1024 * 16 + 1);'
253 'sys.stdout.write(s);')
254 status, out, err = git.Git.execute(['python', '-c', code], _raw=True)
255 self.assertEqual(status, 0)
256 self.assertEqual(len(out), 1024 * 16 + 1)
257 self.assertEqual(len(err), 0)
259 def test_stderr(self):
260 """Test that stderr is seen"""
261 # Write to stderr and capture it
262 code = ('import sys;'
263 's = "\\0" * (1024 * 16 + 1);'
264 'sys.stderr.write(s);')
265 status, out, err = git.Git.execute(['python', '-c', code], _raw=True)
266 self.assertEqual(status, 0)
267 self.assertEqual(len(out), 0)
268 self.assertEqual(len(err), 1024 * 16 + 1)
270 def test_stdout_and_stderr(self):
271 """Test ignoring stderr when stdout+stderr are provided (v2)"""
272 # Write to stdout and stderr but only capture stdout
273 code = ('import sys;'
274 's = "\\0" * (1024 * 16 + 1);'
275 'sys.stdout.write(s);'
276 'sys.stderr.write(s);')
277 status, out, err = git.Git.execute(['python', '-c', code], _raw=True)
278 self.assertEqual(status, 0)
279 self.assertEqual(len(out), 1024 * 16 + 1)
280 self.assertEqual(len(err), 1024 * 16 + 1)
282 def test_it_doesnt_deadlock(self):
283 """Test that we don't deadlock with both stderr and stdout"""
284 # 16k+1 bytes to exhaust any output buffers
285 code = ('import sys;'
286 's = "\\0" * (1024 * 16 + 1);'
287 'sys.stderr.write(s);'
288 'sys.stdout.write(s);')
289 status, out, err = git.Git.execute(['python', '-c', code], _raw=True)
290 self.assertEqual(status, 0)
291 self.assertEqual(out, '\0' * (1024 * 16 + 1))
292 self.assertEqual(err, '\0' * (1024 * 16 + 1))
295 if __name__ == '__main__':
296 unittest.main()