diff options
Diffstat (limited to 'tests/test_project.py')
-rw-r--r-- | tests/test_project.py | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/tests/test_project.py b/tests/test_project.py index 77126dff..6d82da11 100644 --- a/tests/test_project.py +++ b/tests/test_project.py | |||
@@ -25,6 +25,7 @@ import subprocess | |||
25 | import tempfile | 25 | import tempfile |
26 | import unittest | 26 | import unittest |
27 | 27 | ||
28 | import error | ||
28 | import git_config | 29 | import git_config |
29 | import project | 30 | import project |
30 | 31 | ||
@@ -134,3 +135,206 @@ class ReviewableBranchTests(unittest.TestCase): | |||
134 | self.assertFalse(rb.base_exists) | 135 | self.assertFalse(rb.base_exists) |
135 | # Hard to assert anything useful about this. | 136 | # Hard to assert anything useful about this. |
136 | self.assertTrue(rb.date) | 137 | self.assertTrue(rb.date) |
138 | |||
139 | |||
140 | class CopyLinkTestCase(unittest.TestCase): | ||
141 | """TestCase for stub repo client checkouts. | ||
142 | |||
143 | It'll have a layout like: | ||
144 | tempdir/ # self.tempdir | ||
145 | checkout/ # self.topdir | ||
146 | git-project/ # self.worktree | ||
147 | |||
148 | Attributes: | ||
149 | tempdir: A dedicated temporary directory. | ||
150 | worktree: The top of the repo client checkout. | ||
151 | topdir: The top of a project checkout. | ||
152 | """ | ||
153 | |||
154 | def setUp(self): | ||
155 | self.tempdir = tempfile.mkdtemp(prefix='repo_tests') | ||
156 | self.topdir = os.path.join(self.tempdir, 'checkout') | ||
157 | self.worktree = os.path.join(self.topdir, 'git-project') | ||
158 | os.makedirs(self.topdir) | ||
159 | os.makedirs(self.worktree) | ||
160 | |||
161 | def tearDown(self): | ||
162 | shutil.rmtree(self.tempdir, ignore_errors=True) | ||
163 | |||
164 | @staticmethod | ||
165 | def touch(path): | ||
166 | with open(path, 'w') as f: | ||
167 | pass | ||
168 | |||
169 | def assertExists(self, path, msg=None): | ||
170 | """Make sure |path| exists.""" | ||
171 | if os.path.exists(path): | ||
172 | return | ||
173 | |||
174 | if msg is None: | ||
175 | msg = ['path is missing: %s' % path] | ||
176 | while path != '/': | ||
177 | path = os.path.dirname(path) | ||
178 | if not path: | ||
179 | # If we're given something like "foo", abort once we get to "". | ||
180 | break | ||
181 | result = os.path.exists(path) | ||
182 | msg.append('\tos.path.exists(%s): %s' % (path, result)) | ||
183 | if result: | ||
184 | msg.append('\tcontents: %r' % os.listdir(path)) | ||
185 | break | ||
186 | msg = '\n'.join(msg) | ||
187 | |||
188 | raise self.failureException(msg) | ||
189 | |||
190 | |||
191 | class CopyFile(CopyLinkTestCase): | ||
192 | """Check _CopyFile handling.""" | ||
193 | |||
194 | def CopyFile(self, src, dest): | ||
195 | return project._CopyFile(self.worktree, src, self.topdir, dest) | ||
196 | |||
197 | def test_basic(self): | ||
198 | """Basic test of copying a file from a project to the toplevel.""" | ||
199 | src = os.path.join(self.worktree, 'foo.txt') | ||
200 | self.touch(src) | ||
201 | cf = self.CopyFile('foo.txt', 'foo') | ||
202 | cf._Copy() | ||
203 | self.assertExists(os.path.join(self.topdir, 'foo')) | ||
204 | |||
205 | def test_src_subdir(self): | ||
206 | """Copy a file from a subdir of a project.""" | ||
207 | src = os.path.join(self.worktree, 'bar', 'foo.txt') | ||
208 | os.makedirs(os.path.dirname(src)) | ||
209 | self.touch(src) | ||
210 | cf = self.CopyFile('bar/foo.txt', 'new.txt') | ||
211 | cf._Copy() | ||
212 | self.assertExists(os.path.join(self.topdir, 'new.txt')) | ||
213 | |||
214 | def test_dest_subdir(self): | ||
215 | """Copy a file to a subdir of a checkout.""" | ||
216 | src = os.path.join(self.worktree, 'foo.txt') | ||
217 | self.touch(src) | ||
218 | cf = self.CopyFile('foo.txt', 'sub/dir/new.txt') | ||
219 | self.assertFalse(os.path.exists(os.path.join(self.topdir, 'sub'))) | ||
220 | cf._Copy() | ||
221 | self.assertExists(os.path.join(self.topdir, 'sub', 'dir', 'new.txt')) | ||
222 | |||
223 | def test_update(self): | ||
224 | """Make sure changed files get copied again.""" | ||
225 | src = os.path.join(self.worktree, 'foo.txt') | ||
226 | dest = os.path.join(self.topdir, 'bar') | ||
227 | with open(src, 'w') as f: | ||
228 | f.write('1st') | ||
229 | cf = self.CopyFile('foo.txt', 'bar') | ||
230 | cf._Copy() | ||
231 | self.assertExists(dest) | ||
232 | with open(dest) as f: | ||
233 | self.assertEqual(f.read(), '1st') | ||
234 | |||
235 | with open(src, 'w') as f: | ||
236 | f.write('2nd!') | ||
237 | cf._Copy() | ||
238 | with open(dest) as f: | ||
239 | self.assertEqual(f.read(), '2nd!') | ||
240 | |||
241 | def test_src_block_symlink(self): | ||
242 | """Do not allow reading from a symlinked path.""" | ||
243 | src = os.path.join(self.worktree, 'foo.txt') | ||
244 | sym = os.path.join(self.worktree, 'sym') | ||
245 | self.touch(src) | ||
246 | os.symlink('foo.txt', sym) | ||
247 | self.assertExists(sym) | ||
248 | cf = self.CopyFile('sym', 'foo') | ||
249 | self.assertRaises(error.ManifestInvalidPathError, cf._Copy) | ||
250 | |||
251 | def test_src_block_symlink_traversal(self): | ||
252 | """Do not allow reading through a symlink dir.""" | ||
253 | src = os.path.join(self.worktree, 'bar', 'passwd') | ||
254 | os.symlink('/etc', os.path.join(self.worktree, 'bar')) | ||
255 | self.assertExists(src) | ||
256 | cf = self.CopyFile('bar/foo.txt', 'foo') | ||
257 | self.assertRaises(error.ManifestInvalidPathError, cf._Copy) | ||
258 | |||
259 | def test_src_block_dir(self): | ||
260 | """Do not allow copying from a directory.""" | ||
261 | src = os.path.join(self.worktree, 'dir') | ||
262 | os.makedirs(src) | ||
263 | cf = self.CopyFile('dir', 'foo') | ||
264 | self.assertRaises(error.ManifestInvalidPathError, cf._Copy) | ||
265 | |||
266 | def test_dest_block_symlink(self): | ||
267 | """Do not allow writing to a symlink.""" | ||
268 | src = os.path.join(self.worktree, 'foo.txt') | ||
269 | self.touch(src) | ||
270 | os.symlink('dest', os.path.join(self.topdir, 'sym')) | ||
271 | cf = self.CopyFile('foo.txt', 'sym') | ||
272 | self.assertRaises(error.ManifestInvalidPathError, cf._Copy) | ||
273 | |||
274 | def test_dest_block_symlink_traversal(self): | ||
275 | """Do not allow writing through a symlink dir.""" | ||
276 | src = os.path.join(self.worktree, 'foo.txt') | ||
277 | self.touch(src) | ||
278 | os.symlink('/tmp', os.path.join(self.topdir, 'sym')) | ||
279 | cf = self.CopyFile('foo.txt', 'sym/foo.txt') | ||
280 | self.assertRaises(error.ManifestInvalidPathError, cf._Copy) | ||
281 | |||
282 | def test_src_block_dir(self): | ||
283 | """Do not allow copying to a directory.""" | ||
284 | src = os.path.join(self.worktree, 'foo.txt') | ||
285 | self.touch(src) | ||
286 | os.makedirs(os.path.join(self.topdir, 'dir')) | ||
287 | cf = self.CopyFile('foo.txt', 'dir') | ||
288 | self.assertRaises(error.ManifestInvalidPathError, cf._Copy) | ||
289 | |||
290 | |||
291 | class LinkFile(CopyLinkTestCase): | ||
292 | """Check _LinkFile handling.""" | ||
293 | |||
294 | def LinkFile(self, src, dest): | ||
295 | return project._LinkFile(self.worktree, src, self.topdir, dest) | ||
296 | |||
297 | def test_basic(self): | ||
298 | """Basic test of linking a file from a project into the toplevel.""" | ||
299 | src = os.path.join(self.worktree, 'foo.txt') | ||
300 | self.touch(src) | ||
301 | lf = self.LinkFile('foo.txt', 'foo') | ||
302 | lf._Link() | ||
303 | dest = os.path.join(self.topdir, 'foo') | ||
304 | self.assertExists(dest) | ||
305 | self.assertTrue(os.path.islink(dest)) | ||
306 | self.assertEqual('git-project/foo.txt', os.readlink(dest)) | ||
307 | |||
308 | def test_src_subdir(self): | ||
309 | """Link to a file in a subdir of a project.""" | ||
310 | src = os.path.join(self.worktree, 'bar', 'foo.txt') | ||
311 | os.makedirs(os.path.dirname(src)) | ||
312 | self.touch(src) | ||
313 | lf = self.LinkFile('bar/foo.txt', 'foo') | ||
314 | lf._Link() | ||
315 | self.assertExists(os.path.join(self.topdir, 'foo')) | ||
316 | |||
317 | def test_dest_subdir(self): | ||
318 | """Link a file to a subdir of a checkout.""" | ||
319 | src = os.path.join(self.worktree, 'foo.txt') | ||
320 | self.touch(src) | ||
321 | lf = self.LinkFile('foo.txt', 'sub/dir/foo/bar') | ||
322 | self.assertFalse(os.path.exists(os.path.join(self.topdir, 'sub'))) | ||
323 | lf._Link() | ||
324 | self.assertExists(os.path.join(self.topdir, 'sub', 'dir', 'foo', 'bar')) | ||
325 | |||
326 | def test_update(self): | ||
327 | """Make sure changed targets get updated.""" | ||
328 | dest = os.path.join(self.topdir, 'sym') | ||
329 | |||
330 | src = os.path.join(self.worktree, 'foo.txt') | ||
331 | self.touch(src) | ||
332 | lf = self.LinkFile('foo.txt', 'sym') | ||
333 | lf._Link() | ||
334 | self.assertEqual('git-project/foo.txt', os.readlink(dest)) | ||
335 | |||
336 | # Point the symlink somewhere else. | ||
337 | os.unlink(dest) | ||
338 | os.symlink('/', dest) | ||
339 | lf._Link() | ||
340 | self.assertEqual('git-project/foo.txt', os.readlink(dest)) | ||