OLD | NEW |
(Empty) | |
| 1 #! /usr/bin/env python |
| 2 # |
| 3 # Copyright 2009 Google Inc. All Rights Reserved. |
| 4 # |
| 5 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 # you may not use this file except in compliance with the License. |
| 7 # You may obtain a copy of the License at |
| 8 # |
| 9 # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 # |
| 11 # Unless required by applicable law or agreed to in writing, software |
| 12 # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 # See the License for the specific language governing permissions and |
| 15 # limitations under the License. |
| 16 |
| 17 """Test that FakeFilesystem calls work identically to a real filesystem.""" |
| 18 |
| 19 #pylint: disable-all |
| 20 |
| 21 import os #@UnusedImport |
| 22 import os.path |
| 23 import shutil |
| 24 import sys |
| 25 import tempfile |
| 26 import time |
| 27 import sys |
| 28 if sys.version_info < (2, 7): |
| 29 import unittest2 as unittest |
| 30 else: |
| 31 import unittest |
| 32 |
| 33 import fake_filesystem |
| 34 |
| 35 |
| 36 def Sep(path): |
| 37 """Converts slashes in the path to the architecture's path seperator.""" |
| 38 if isinstance(path, str): |
| 39 return path.replace('/', os.sep) |
| 40 return path |
| 41 |
| 42 |
| 43 class TestCase(unittest.TestCase): |
| 44 is_windows = sys.platform.startswith('win') |
| 45 is_cygwin = sys.platform == 'cygwin' |
| 46 _FAKE_FS_BASE = Sep('/fakefs') |
| 47 |
| 48 |
| 49 class FakeFilesystemVsRealTest(TestCase): |
| 50 |
| 51 def _Paths(self, path): |
| 52 """For a given path, return paths in the real and fake filesystems.""" |
| 53 if not path: |
| 54 return (None, None) |
| 55 return (os.path.join(self.real_base, path), |
| 56 os.path.join(self.fake_base, path)) |
| 57 |
| 58 def _CreateTestFile(self, file_type, path, contents=None): |
| 59 """Create a dir, file, or link in both the real fs and the fake.""" |
| 60 path = Sep(path) |
| 61 self._created_files.append([file_type, path, contents]) |
| 62 real_path, fake_path = self._Paths(path) |
| 63 if file_type == 'd': |
| 64 os.mkdir(real_path) |
| 65 self.fake_os.mkdir(fake_path) |
| 66 if file_type == 'f': |
| 67 fh = open(real_path, 'w') |
| 68 fh.write(contents or '') |
| 69 fh.close() |
| 70 fh = self.fake_open(fake_path, 'w') |
| 71 fh.write(contents or '') |
| 72 fh.close() |
| 73 # b for binary file |
| 74 if file_type == 'b': |
| 75 fh = open(real_path, 'wb') |
| 76 fh.write(contents or '') |
| 77 fh.close() |
| 78 fh = self.fake_open(fake_path, 'wb') |
| 79 fh.write(contents or '') |
| 80 fh.close() |
| 81 # l for symlink, h for hard link |
| 82 if file_type in ('l', 'h'): |
| 83 real_target, fake_target = (contents, contents) |
| 84 # If it begins with '/', make it relative to the base. You can't
go |
| 85 # creating files in / for the real file system. |
| 86 if contents.startswith(os.sep): |
| 87 real_target, fake_target = self._Paths(contents[1:]) |
| 88 if file_type == 'l': |
| 89 os.symlink(real_target, real_path) |
| 90 self.fake_os.symlink(fake_target, fake_path) |
| 91 elif file_type == 'h': |
| 92 os.link(real_target, real_path) |
| 93 self.fake_os.link(fake_target, fake_path) |
| 94 |
| 95 def setUp(self): |
| 96 # Base paths in the real and test file systems. We keep them differe
nt |
| 97 # so that missing features in the fake don't fall through to the base |
| 98 # operations and magically succeed. |
| 99 tsname = 'fakefs.%s' % time.time() |
| 100 # Fully expand the base_path - required on OS X. |
| 101 self.real_base = os.path.realpath( |
| 102 os.path.join(tempfile.gettempdir(), tsname)) |
| 103 os.chdir(tempfile.gettempdir()) |
| 104 if os.path.isdir(self.real_base): |
| 105 shutil.rmtree(self.real_base) |
| 106 os.mkdir(self.real_base) |
| 107 self.fake_base = self._FAKE_FS_BASE |
| 108 |
| 109 # Make sure we can write to the physical testing temp directory. |
| 110 self.assertTrue(os.access(self.real_base, os.W_OK)) |
| 111 |
| 112 self.fake_filesystem = fake_filesystem.FakeFilesystem() |
| 113 self.fake_filesystem.CreateDirectory(self.fake_base) |
| 114 self.fake_os = fake_filesystem.FakeOsModule(self.fake_filesystem) |
| 115 self.fake_open = fake_filesystem.FakeFileOpen(self.fake_filesystem) |
| 116 self._created_files = [] |
| 117 |
| 118 os.chdir(self.real_base) |
| 119 self.fake_os.chdir(self.fake_base) |
| 120 |
| 121 def tearDown(self): |
| 122 # We have to remove all the files from the real FS. Doing the same for t
he |
| 123 # fake FS is optional, but doing it is an extra sanity check. |
| 124 os.chdir(tempfile.gettempdir()) |
| 125 try: |
| 126 rev_files = self._created_files[:] |
| 127 rev_files.reverse() |
| 128 for info in rev_files: |
| 129 real_path, fake_path = self._Paths(info[1]) |
| 130 if info[0] == 'd': |
| 131 try: |
| 132 os.rmdir(real_path) |
| 133 except OSError as e: |
| 134 if 'Directory not empty' in e: |
| 135 self.fail('Real path %s not empty: %s : %s' % ( |
| 136 real_path, e, os.listdir(real_path))) |
| 137 else: |
| 138 raise |
| 139 self.fake_os.rmdir(fake_path) |
| 140 if info[0] == 'f' or info[0] == 'l': |
| 141 os.remove(real_path) |
| 142 self.fake_os.remove(fake_path) |
| 143 finally: |
| 144 shutil.rmtree(self.real_base) |
| 145 |
| 146 def _GetErrno(self, raised_error): |
| 147 try: |
| 148 return (raised_error and raised_error.errno) or None |
| 149 except AttributeError: |
| 150 return None |
| 151 |
| 152 def _CompareBehaviors(self, method_name, path, real, fake, |
| 153 method_returns_path=False): |
| 154 """Invoke an os method in both real and fake contexts and compare result
s. |
| 155 |
| 156 Invoke a real filesystem method with a path to a real file and invoke a
fake |
| 157 filesystem method with a path to a fake file and compare the results.
We |
| 158 expect some calls to throw Exceptions, so we catch those and compare the
m. |
| 159 |
| 160 Args: |
| 161 method_name: Name of method being tested, for use in error messages. |
| 162 path: potential path to a file in the real and fake file systems, pa
ssing |
| 163 an empty tuple indicates that no arguments to pass to method. |
| 164 real: built-in system library or method from the built-in system lib
rary |
| 165 which takes a path as an arg and returns some value. |
| 166 fake: fake_filsystem object or method from a fake_filesystem class |
| 167 which takes a path as an arg and returns some value. |
| 168 method_returns_path: True if the method returns a path, and thus we
must |
| 169 compensate for expected difference between real and fake. |
| 170 |
| 171 Returns: |
| 172 A description of the difference in behavior, or None. |
| 173 """ |
| 174 # pylint: disable=C6403 |
| 175 |
| 176 def _ErrorClass(e): |
| 177 return (e and e.__class__.__name__) or 'None' |
| 178 |
| 179 real_value = None |
| 180 fake_value = None |
| 181 real_err = None |
| 182 fake_err = None |
| 183 method_call = '%s' % method_name |
| 184 method_call += '()' if path == () else '(%s)' % path |
| 185 # Catching Exception below gives a lint warning, but it's what we need. |
| 186 try: |
| 187 args = [] if path == () else [path] |
| 188 real_method = real |
| 189 if not callable(real): |
| 190 real_method = getattr(real, method_name) |
| 191 real_value = str(real_method(*args)) |
| 192 except Exception as e: # pylint: disable-msg=W0703 |
| 193 real_err = e |
| 194 try: |
| 195 fake_method = fake |
| 196 if not callable(fake): |
| 197 fake_method = getattr(fake, method_name) |
| 198 args = [] if path == () else [path] |
| 199 fake_value = str(fake_method(*args)) |
| 200 except Exception as e: # pylint: disable-msg=W0703 |
| 201 fake_err = e |
| 202 # We only compare on the error class because the acutal error contents |
| 203 # is almost always different because of the file paths. |
| 204 if _ErrorClass(real_err) != _ErrorClass(fake_err): |
| 205 if real_err is None: |
| 206 return '%s: real version returned %s, fake raised %s' % ( |
| 207 method_call, real_value, _ErrorClass(fake_err)) |
| 208 if fake_err is None: |
| 209 return '%s: real version raised %s, fake returned %s' % ( |
| 210 method_call, _ErrorClass(real_err), fake_value) |
| 211 return '%s: real version raised %s, fake raised %s' % ( |
| 212 method_call, _ErrorClass(real_err), _ErrorClass(fake_err)) |
| 213 real_errno = self._GetErrno(real_err) |
| 214 fake_errno = self._GetErrno(fake_err) |
| 215 if real_errno != fake_errno: |
| 216 return '%s(%s): both raised %s, real errno %s, fake errno %s' % ( |
| 217 method_name, path, _ErrorClass(real_err), real_errno, fake_e
rrno) |
| 218 # If the method is supposed to return a full path AND both values |
| 219 # begin with the expected full path, then trim it off. |
| 220 if method_returns_path: |
| 221 if (real_value and fake_value |
| 222 and real_value.startswith(self.real_base) |
| 223 and fake_value.startswith(self.fake_base)): |
| 224 real_value = real_value[len(self.real_base):] |
| 225 fake_value = fake_value[len(self.fake_base):] |
| 226 if real_value != fake_value: |
| 227 return '%s: real return %s, fake returned %s' % ( |
| 228 method_call, real_value, fake_value) |
| 229 return None |
| 230 |
| 231 def assertOsMethodBehaviorMatches(self, method_name, path, |
| 232 method_r
eturns_path=False): |
| 233 """Invoke an os method in both real and fake contexts and compare. |
| 234 |
| 235 For a given method name (from the os module) and a path, compare the |
| 236 behavior of the system provided module against the fake_filesytem module
. |
| 237 We expect results and/or Exceptions raised to be identical. |
| 238 |
| 239 Args: |
| 240 method_name: Name of method being tested. |
| 241 path: potential path to a file in the real and fake file systems. |
| 242 method_returns_path: True if the method returns a path, and thus we
must |
| 243 compensate for expected difference between real and fake. |
| 244 |
| 245 Returns: |
| 246 A description of the difference in behavior, or None. |
| 247 """ |
| 248 path = Sep(path) |
| 249 return self._CompareBehaviors(method_name, path, os, self.fake_os, |
| 250 method_retur
ns_path) |
| 251 |
| 252 def DiffOpenMethodBehavior(self, method_name, path, mode, data, |
| 253 method_returns_data=Tru
e): |
| 254 """Invoke an open method in both real and fkae contexts and compare. |
| 255 |
| 256 Args: |
| 257 method_name: Name of method being tested. |
| 258 path: potential path to a file in the real and fake file systems. |
| 259 mode: how to open the file. |
| 260 data: any data to pass to the method. |
| 261 method_returns_data: True if a method returns some sort of data. |
| 262 |
| 263 For a given method name (from builtin open) and a path, compare the |
| 264 behavior of the system provided module against the fake_filesytem module
. |
| 265 We expect results and/or Exceptions raised to be identical. |
| 266 |
| 267 Returns: |
| 268 A description of the difference in behavior, or None. |
| 269 """ |
| 270 with open(path, mode) as real_fh: |
| 271 with self.fake_open(path, mode) as fake_fh: |
| 272 return self._CompareBehaviors(method_name, data, real_fh, fake_f
h, |
| 273 meth
od_returns_data) |
| 274 |
| 275 def DiffOsPathMethodBehavior(self, method_name, path, |
| 276 method_returns_path
=False): |
| 277 """Invoke an os.path method in both real and fake contexts and compare. |
| 278 |
| 279 For a given method name (from the os.path module) and a path, compare th
e |
| 280 behavior of the system provided module against the fake_filesytem module
. |
| 281 We expect results and/or Exceptions raised to be identical. |
| 282 |
| 283 Args: |
| 284 method_name: Name of method being tested. |
| 285 path: potential path to a file in the real and fake file systems. |
| 286 method_returns_path: True if the method returns a path, and thus we
must |
| 287 compensate for expected difference between real and fake. |
| 288 |
| 289 Returns: |
| 290 A description of the difference in behavior, or None. |
| 291 """ |
| 292 return self._CompareBehaviors(method_name, path, os.path, self.fake_os.p
ath, |
| 293 method_retur
ns_path) |
| 294 |
| 295 def assertOsPathMethodBehaviorMatches(self, method_name, path, |
| 296
method_returns_path=False): |
| 297 """Assert that an os.path behaves the same in both real and fake context
s. |
| 298 |
| 299 Wraps DiffOsPathMethodBehavior, raising AssertionError if any difference
s |
| 300 are reported. |
| 301 |
| 302 Args: |
| 303 method_name: Name of method being tested. |
| 304 path: potential path to a file in the real and fake file systems. |
| 305 method_returns_path: True if the method returns a path, and thus we
must |
| 306 compensate for expected difference between real and fake. |
| 307 |
| 308 Raises: |
| 309 AssertionError if there is any difference in behavior. |
| 310 """ |
| 311 path = Sep(path) |
| 312 diff = self.DiffOsPathMethodBehavior(method_name, path, method_returns_p
ath) |
| 313 if diff: |
| 314 self.fail(diff) |
| 315 |
| 316 def assertAllOsBehaviorsMatch(self, path): |
| 317 path = Sep(path) |
| 318 os_method_names = [] if self.is_windows else ['readlink'] |
| 319 os_method_names_no_args = ['getcwd'] |
| 320 if sys.version_info < (3, 0): |
| 321 os_method_names_no_args.append('getcwdu') |
| 322 os_path_method_names = ['isabs', |
| 323 'isdir', |
| 324 'isfile', |
| 325 'exists' |
| 326 ] |
| 327 if not self.is_windows: |
| 328 os_path_method_names.append('islink') |
| 329 os_path_method_names.append('lexists') |
| 330 wrapped_methods = [['access', self._AccessReal, self._AccessFake], |
| 331 ['stat.size', self._StatSizeReal, s
elf._StatSizeFake], |
| 332 ['lstat.size', self._LstatSizeReal,
self._LstatSizeFake] |
| 333 ] |
| 334 |
| 335 differences = [] |
| 336 for method_name in os_method_names: |
| 337 diff = self.assertOsMethodBehaviorMatches(method_name, path) |
| 338 if diff: |
| 339 differences.append(diff) |
| 340 for method_name in os_method_names_no_args: |
| 341 diff = self.assertOsMethodBehaviorMatches(method_name, (), |
| 342
method_returns_path=True) |
| 343 if diff: |
| 344 differences.append(diff) |
| 345 for method_name in os_path_method_names: |
| 346 diff = self.DiffOsPathMethodBehavior(method_name, path) |
| 347 if diff: |
| 348 differences.append(diff) |
| 349 for m in wrapped_methods: |
| 350 diff = self._CompareBehaviors(m[0], path, m[1], m[2]) |
| 351 if diff: |
| 352 differences.append(diff) |
| 353 if differences: |
| 354 self.fail('Behaviors do not match for %s:\n %s' % |
| 355 (path, '\n '.join(differences))) |
| 356 |
| 357 def assertFileHandleBehaviorsMatch(self, path, mode, data): |
| 358 path = Sep(path) |
| 359 write_method_names = ['write', 'writelines'] |
| 360 read_method_names = ['read', 'readlines'] |
| 361 other_method_names = ['truncate', 'flush', 'close'] |
| 362 differences = [] |
| 363 for method_name in write_method_names: |
| 364 diff = self.DiffOpenMethodBehavior(method_name, path, mode, data) |
| 365 if diff: |
| 366 differences.append(diff) |
| 367 for method_name in read_method_names + other_method_names: |
| 368 diff = self.DiffOpenMethodBehavior(method_name, path, mode, ()) |
| 369 if diff: |
| 370 differences.append(diff) |
| 371 if differences: |
| 372 self.fail('Behaviors do not match for %s:\n %s' % |
| 373 (path, '\n '.join(differences))) |
| 374 |
| 375 # Helpers for checks which are not straight method calls. |
| 376 |
| 377 def _AccessReal(self, path): |
| 378 return os.access(path, os.R_OK) |
| 379 |
| 380 def _AccessFake(self, path): |
| 381 return self.fake_os.access(path, os.R_OK) |
| 382 |
| 383 def _StatSizeReal(self, path): |
| 384 real_path, unused_fake_path = self._Paths(path) |
| 385 # fake_filesystem.py does not implement stat().st_size for directories |
| 386 if os.path.isdir(real_path): |
| 387 return None |
| 388 return os.stat(real_path).st_size |
| 389 |
| 390 def _StatSizeFake(self, path): |
| 391 unused_real_path, fake_path = self._Paths(path) |
| 392 # fake_filesystem.py does not implement stat().st_size for directories |
| 393 if self.fake_os.path.isdir(fake_path): |
| 394 return None |
| 395 return self.fake_os.stat(fake_path).st_size |
| 396 |
| 397 def _LstatSizeReal(self, path): |
| 398 real_path, unused_fake_path = self._Paths(path) |
| 399 if os.path.isdir(real_path): |
| 400 return None |
| 401 size = os.lstat(real_path).st_size |
| 402 # Account for the difference in the lengths of the absolute paths. |
| 403 if os.path.islink(real_path): |
| 404 if os.readlink(real_path).startswith(os.sep): |
| 405 size -= len(self.real_base) |
| 406 return size |
| 407 |
| 408 def _LstatSizeFake(self, path): |
| 409 unused_real_path, fake_path = self._Paths(path) |
| 410 #size = 0 |
| 411 if self.fake_os.path.isdir(fake_path): |
| 412 return None |
| 413 size = self.fake_os.lstat(fake_path).st_size |
| 414 # Account for the difference in the lengths of the absolute paths. |
| 415 if self.fake_os.path.islink(fake_path): |
| 416 if self.fake_os.readlink(fake_path).startswith(os.sep): |
| 417 size -= len(self.fake_base) |
| 418 return size |
| 419 |
| 420 def testIsabs(self): |
| 421 # We do not have to create any files for isabs. |
| 422 self.assertOsPathMethodBehaviorMatches('isabs', None) |
| 423 self.assertOsPathMethodBehaviorMatches('isabs', '') |
| 424 self.assertOsPathMethodBehaviorMatches('isabs', '/') |
| 425 self.assertOsPathMethodBehaviorMatches('isabs', '/a') |
| 426 self.assertOsPathMethodBehaviorMatches('isabs', 'a') |
| 427 |
| 428 def testNonePath(self): |
| 429 self.assertAllOsBehaviorsMatch(None) |
| 430 |
| 431 def testEmptyPath(self): |
| 432 self.assertAllOsBehaviorsMatch('') |
| 433 |
| 434 def testRootPath(self): |
| 435 self.assertAllOsBehaviorsMatch('/') |
| 436 |
| 437 def testNonExistantFile(self): |
| 438 self.assertAllOsBehaviorsMatch('foo') |
| 439 |
| 440 def testEmptyFile(self): |
| 441 self._CreateTestFile('f', 'aFile') |
| 442 self.assertAllOsBehaviorsMatch('aFile') |
| 443 |
| 444 def testFileWithContents(self): |
| 445 self._CreateTestFile('f', 'aFile', 'some contents') |
| 446 self.assertAllOsBehaviorsMatch('aFile') |
| 447 |
| 448 def testFileWithBinaryContents(self): |
| 449 self._CreateTestFile('b', 'aFile', b'some contents') |
| 450 self.assertAllOsBehaviorsMatch('aFile') |
| 451 |
| 452 @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows') |
| 453 def testSymLinkToEmptyFile(self): |
| 454 self._CreateTestFile('f', 'aFile') |
| 455 self._CreateTestFile('l', 'link_to_empty', 'aFile') |
| 456 self.assertAllOsBehaviorsMatch('link_to_empty') |
| 457 |
| 458 @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows') |
| 459 def TBD_testHardLinkToEmptyFile(self): |
| 460 self._CreateTestFile('f', 'aFile') |
| 461 self._CreateTestFile('h', 'link_to_empty', 'aFile') |
| 462 self.assertAllOsBehaviorsMatch('link_to_empty') |
| 463 |
| 464 @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows') |
| 465 def testSymLinkToRealFile(self): |
| 466 self._CreateTestFile('f', 'aFile', 'some contents') |
| 467 self._CreateTestFile('l', 'link_to_file', 'aFile') |
| 468 self.assertAllOsBehaviorsMatch('link_to_file') |
| 469 |
| 470 @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows') |
| 471 def TBD_testHardLinkToRealFile(self): |
| 472 self._CreateTestFile('f', 'aFile', 'some contents') |
| 473 self._CreateTestFile('h', 'link_to_file', 'aFile') |
| 474 self.assertAllOsBehaviorsMatch('link_to_file') |
| 475 |
| 476 @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows') |
| 477 def testBrokenSymLink(self): |
| 478 self._CreateTestFile('l', 'broken_link', 'broken') |
| 479 self._CreateTestFile('l', 'loop', '/a/loop') |
| 480 self.assertAllOsBehaviorsMatch('broken_link') |
| 481 |
| 482 def testFileInAFolder(self): |
| 483 self._CreateTestFile('d', 'a') |
| 484 self._CreateTestFile('d', 'a/b') |
| 485 self._CreateTestFile('f', 'a/b/file', 'contents') |
| 486 self.assertAllOsBehaviorsMatch('a/b/file') |
| 487 |
| 488 @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows') |
| 489 def testAbsoluteSymLinkToFolder(self): |
| 490 self._CreateTestFile('d', 'a') |
| 491 self._CreateTestFile('d', 'a/b') |
| 492 self._CreateTestFile('f', 'a/b/file', 'contents') |
| 493 self._CreateTestFile('l', 'a/link', '/a/b') |
| 494 self.assertAllOsBehaviorsMatch('a/link/file') |
| 495 |
| 496 @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows') |
| 497 def testLinkToFolderAfterChdir(self): |
| 498 self._CreateTestFile('d', 'a') |
| 499 self._CreateTestFile('d', 'a/b') |
| 500 self._CreateTestFile('f', 'a/b/file', 'contents') |
| 501 self._CreateTestFile('l', 'a/link', '/a/b') |
| 502 |
| 503 real_dir, fake_dir = self._Paths('a/b') |
| 504 os.chdir(real_dir) |
| 505 self.fake_os.chdir(fake_dir) |
| 506 self.assertAllOsBehaviorsMatch('file') |
| 507 |
| 508 @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows') |
| 509 def testRelativeSymLinkToFolder(self): |
| 510 self._CreateTestFile('d', 'a') |
| 511 self._CreateTestFile('d', 'a/b') |
| 512 self._CreateTestFile('f', 'a/b/file', 'contents') |
| 513 self._CreateTestFile('l', 'a/link', 'b') |
| 514 self.assertAllOsBehaviorsMatch('a/link/file') |
| 515 |
| 516 @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows') |
| 517 def testSymLinkToParent(self): |
| 518 # Soft links on HFS+ / OS X behave differently. |
| 519 if os.uname()[0] != 'Darwin': |
| 520 self._CreateTestFile('d', 'a') |
| 521 self._CreateTestFile('d', 'a/b') |
| 522 self._CreateTestFile('l', 'a/b/c', '..') |
| 523 self.assertAllOsBehaviorsMatch('a/b/c') |
| 524 |
| 525 @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows') |
| 526 def testPathThroughSymLinkToParent(self): |
| 527 self._CreateTestFile('d', 'a') |
| 528 self._CreateTestFile('f', 'a/target', 'contents') |
| 529 self._CreateTestFile('d', 'a/b') |
| 530 self._CreateTestFile('l', 'a/b/c', '..') |
| 531 self.assertAllOsBehaviorsMatch('a/b/c/target') |
| 532 |
| 533 @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows') |
| 534 def testSymLinkToSiblingDirectory(self): |
| 535 self._CreateTestFile('d', 'a') |
| 536 self._CreateTestFile('d', 'a/b') |
| 537 self._CreateTestFile('d', 'a/sibling_of_b') |
| 538 self._CreateTestFile('f', 'a/sibling_of_b/target', 'contents') |
| 539 self._CreateTestFile('l', 'a/b/c', '../sibling_of_b') |
| 540 self.assertAllOsBehaviorsMatch('a/b/c/target') |
| 541 |
| 542 @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows') |
| 543 def testSymLinkToSiblingDirectoryNonExistantFile(self): |
| 544 self._CreateTestFile('d', 'a') |
| 545 self._CreateTestFile('d', 'a/b') |
| 546 self._CreateTestFile('d', 'a/sibling_of_b') |
| 547 self._CreateTestFile('f', 'a/sibling_of_b/target', 'contents') |
| 548 self._CreateTestFile('l', 'a/b/c', '../sibling_of_b') |
| 549 self.assertAllOsBehaviorsMatch('a/b/c/file_does_not_exist') |
| 550 |
| 551 @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows') |
| 552 def testBrokenSymLinkToSiblingDirectory(self): |
| 553 self._CreateTestFile('d', 'a') |
| 554 self._CreateTestFile('d', 'a/b') |
| 555 self._CreateTestFile('d', 'a/sibling_of_b') |
| 556 self._CreateTestFile('f', 'a/sibling_of_b/target', 'contents') |
| 557 self._CreateTestFile('l', 'a/b/c', '../broken_sibling_of_b') |
| 558 self.assertAllOsBehaviorsMatch('a/b/c/target') |
| 559 |
| 560 def testRelativePath(self): |
| 561 self._CreateTestFile('d', 'a') |
| 562 self._CreateTestFile('d', 'a/b') |
| 563 self._CreateTestFile('d', 'a/sibling_of_b') |
| 564 self._CreateTestFile('f', 'a/sibling_of_b/target', 'contents') |
| 565 self.assertAllOsBehaviorsMatch('a/b/../sibling_of_b/target') |
| 566 |
| 567 def testBrokenRelativePath(self): |
| 568 self._CreateTestFile('d', 'a') |
| 569 self._CreateTestFile('d', 'a/b') |
| 570 self._CreateTestFile('d', 'a/sibling_of_b') |
| 571 self._CreateTestFile('f', 'a/sibling_of_b/target', 'contents') |
| 572 self.assertAllOsBehaviorsMatch('a/b/../broken/target') |
| 573 |
| 574 def testBadRelativePath(self): |
| 575 self._CreateTestFile('d', 'a') |
| 576 self._CreateTestFile('f', 'a/target', 'contents') |
| 577 self._CreateTestFile('d', 'a/b') |
| 578 self._CreateTestFile('d', 'a/sibling_of_b') |
| 579 self._CreateTestFile('f', 'a/sibling_of_b/target', 'contents') |
| 580 self.assertAllOsBehaviorsMatch('a/b/../broken/../target') |
| 581 |
| 582 def testGetmtimeNonexistantPath(self): |
| 583 self.assertOsPathMethodBehaviorMatches('getmtime', 'no/such/path') |
| 584 |
| 585 def testBuiltinOpenModes(self): |
| 586 self._CreateTestFile('f', 'read', 'some contents') |
| 587 self._CreateTestFile('f', 'write', 'some contents') |
| 588 self._CreateTestFile('f', 'append', 'some contents') |
| 589 self.assertFileHandleBehaviorsMatch('read', 'r', 'other contents') |
| 590 self.assertFileHandleBehaviorsMatch('write', 'w', 'other contents') |
| 591 self.assertFileHandleBehaviorsMatch('append', 'a', 'other contents') |
| 592 self._CreateTestFile('f', 'readplus', 'some contents') |
| 593 self._CreateTestFile('f', 'writeplus', 'some contents') |
| 594 self.assertFileHandleBehaviorsMatch('readplus', 'r+', 'other contents') |
| 595 self.assertFileHandleBehaviorsMatch('writeplus', 'w+', 'other contents') |
| 596 self._CreateTestFile('b', 'binaryread', b'some contents') |
| 597 self._CreateTestFile('b', 'binarywrite', b'some contents') |
| 598 self._CreateTestFile('b', 'binaryappend', b'some contents') |
| 599 self.assertFileHandleBehaviorsMatch('binaryread', 'rb', b'other contents
') |
| 600 self.assertFileHandleBehaviorsMatch('binarywrite', 'wb', b'other content
s') |
| 601 self.assertFileHandleBehaviorsMatch('binaryappend', 'ab', b'other conten
ts') |
| 602 self.assertFileHandleBehaviorsMatch('read', 'rb', 'other contents') |
| 603 self.assertFileHandleBehaviorsMatch('write', 'wb', 'other contents') |
| 604 self.assertFileHandleBehaviorsMatch('append', 'ab', 'other contents') |
| 605 |
| 606 |
| 607 def main(unused_argv): |
| 608 unittest.main() |
| 609 |
| 610 |
| 611 if __name__ == '__main__': |
| 612 unittest.main() |
OLD | NEW |