1# -*- coding: utf-8 -*- 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"""Unit tests for fake_filesystem.FakeOsModule.""" 18 19import errno 20import io 21import locale 22import os 23import stat 24import sys 25import time 26import unittest 27 28from pyfakefs import fake_filesystem 29from pyfakefs.fake_filesystem import is_root, PERM_READ, FakeIoModule 30from pyfakefs.fake_filesystem_unittest import PatchMode 31from pyfakefs.tests.test_utils import RealFsTestCase 32 33 34class FakeFileOpenTestBase(RealFsTestCase): 35 def setUp(self): 36 super(FakeFileOpenTestBase, self).setUp() 37 if self.use_real_fs(): 38 self.open = io.open 39 else: 40 self.fake_io_module = FakeIoModule(self.filesystem) 41 self.open = self.fake_io_module.open 42 43 def path_separator(self): 44 return '!' 45 46 47class FakeFileOpenTest(FakeFileOpenTestBase): 48 def setUp(self): 49 super(FakeFileOpenTest, self).setUp() 50 self.orig_time = time.time 51 52 def tearDown(self): 53 super(FakeFileOpenTest, self).tearDown() 54 time.time = self.orig_time 55 56 def test_open_no_parent_dir(self): 57 """Expect raise when opening a file in a missing directory.""" 58 file_path = self.make_path('foo', 'bar.txt') 59 self.assert_raises_os_error(errno.ENOENT, self.open, file_path, 'w') 60 61 def test_delete_on_close(self): 62 self.skip_real_fs() 63 file_dir = 'boo' 64 file_path = 'boo!far' 65 self.os.mkdir(file_dir) 66 self.open = fake_filesystem.FakeFileOpen(self.filesystem, 67 delete_on_close=True) 68 with self.open(file_path, 'w'): 69 self.assertTrue(self.filesystem.exists(file_path)) 70 self.assertFalse(self.filesystem.exists(file_path)) 71 72 def test_no_delete_on_close_by_default(self): 73 file_path = self.make_path('czar') 74 with self.open(file_path, 'w'): 75 self.assertTrue(self.os.path.exists(file_path)) 76 self.assertTrue(self.os.path.exists(file_path)) 77 78 def test_compatibility_of_with_statement(self): 79 self.skip_real_fs() 80 self.open = fake_filesystem.FakeFileOpen(self.filesystem, 81 delete_on_close=True) 82 file_path = 'foo' 83 self.assertFalse(self.os.path.exists(file_path)) 84 with self.open(file_path, 'w'): 85 self.assertTrue(self.os.path.exists(file_path)) 86 # After the 'with' statement, the close() method should have been 87 # called. 88 self.assertFalse(self.os.path.exists(file_path)) 89 90 def test_unicode_contents(self): 91 file_path = self.make_path('foo') 92 # note that this will work only if the string can be represented 93 # by the locale preferred encoding - which under Windows is 94 # usually not UTF-8, but something like Latin1, depending on the locale 95 text_fractions = 'Ümläüts' 96 try: 97 with self.open(file_path, 'w') as f: 98 f.write(text_fractions) 99 except UnicodeEncodeError: 100 # see https://github.com/jmcgeheeiv/pyfakefs/issues/623 101 self.skipTest("This test does not work with an ASCII locale") 102 103 with self.open(file_path) as f: 104 contents = f.read() 105 self.assertEqual(contents, text_fractions) 106 107 def test_byte_contents(self): 108 file_path = self.make_path('foo') 109 byte_fractions = b'\xe2\x85\x93 \xe2\x85\x94 \xe2\x85\x95 \xe2\x85\x96' 110 with self.open(file_path, 'wb') as f: 111 f.write(byte_fractions) 112 # the encoding has to be specified, otherwise the locale default 113 # is used which can be different on different systems 114 with self.open(file_path, encoding='utf-8') as f: 115 contents = f.read() 116 self.assertEqual(contents, byte_fractions.decode('utf-8')) 117 118 def test_write_str_read_bytes(self): 119 file_path = self.make_path('foo') 120 str_contents = 'Äsgül' 121 try: 122 with self.open(file_path, 'w') as f: 123 f.write(str_contents) 124 except UnicodeEncodeError: 125 # see https://github.com/jmcgeheeiv/pyfakefs/issues/623 126 self.skipTest("This test does not work with an ASCII locale") 127 with self.open(file_path, 'rb') as f: 128 contents = f.read() 129 self.assertEqual(str_contents, contents.decode( 130 locale.getpreferredencoding(False))) 131 132 def test_open_valid_file(self): 133 contents = [ 134 'I am he as\n', 135 'you are he as\n', 136 'you are me and\n', 137 'we are all together\n' 138 ] 139 file_path = self.make_path('bar.txt') 140 self.create_file(file_path, contents=''.join(contents)) 141 with self.open(file_path) as fake_file: 142 self.assertEqual(contents, fake_file.readlines()) 143 144 def test_open_valid_args(self): 145 contents = [ 146 "Bang bang Maxwell's silver hammer\n", 147 'Came down on her head', 148 ] 149 file_path = self.make_path('abbey_road', 'maxwell') 150 self.create_file(file_path, contents=''.join(contents)) 151 152 with self.open(file_path, buffering=1) as f: 153 self.assertEqual(contents, f.readlines()) 154 with self.open(file_path, buffering=1, 155 errors='strict', newline='\n', opener=None) as f: 156 expected_contents = [contents[0][:-1] + self.os.linesep, 157 contents[1]] 158 self.assertEqual(expected_contents, f.readlines()) 159 160 def test_open_valid_file_with_cwd(self): 161 contents = [ 162 'I am he as\n', 163 'you are he as\n', 164 'you are me and\n', 165 'we are all together\n' 166 ] 167 file_path = self.make_path('bar.txt') 168 self.create_file(file_path, contents=''.join(contents)) 169 self.os.chdir(self.base_path) 170 with self.open(file_path) as f: 171 self.assertEqual(contents, f.readlines()) 172 173 def test_iterate_over_file(self): 174 contents = [ 175 "Bang bang Maxwell's silver hammer", 176 'Came down on her head', 177 ] 178 file_path = self.make_path('abbey_road', 'maxwell') 179 self.create_file(file_path, contents='\n'.join(contents)) 180 with self.open(file_path) as fake_file: 181 result = [line.rstrip() for line in fake_file] 182 self.assertEqual(contents, result) 183 184 def test_next_over_file(self): 185 contents = [ 186 'Live long\n', 187 'and prosper\n' 188 ] 189 result = [] 190 file_path = self.make_path('foo.txt') 191 self.create_file(file_path, contents=''.join(contents)) 192 with self.open(file_path) as fake_file: 193 result.append(next(fake_file)) 194 result.append(next(fake_file)) 195 self.assertEqual(contents, result) 196 197 def test_open_directory_error(self): 198 directory_path = self.make_path('foo') 199 self.os.mkdir(directory_path) 200 if self.is_windows: 201 self.assert_raises_os_error(errno.EACCES, self.open.__call__, 202 directory_path) 203 else: 204 self.assert_raises_os_error(errno.EISDIR, self.open.__call__, 205 directory_path) 206 207 def test_create_file_with_write(self): 208 contents = [ 209 "Here comes the sun, little darlin'", 210 'Here comes the sun, and I say,', 211 "It's alright", 212 ] 213 file_dir = self.make_path('abbey_road') 214 file_path = self.os.path.join(file_dir, 'here_comes_the_sun') 215 self.os.mkdir(file_dir) 216 with self.open(file_path, 'w') as fake_file: 217 for line in contents: 218 fake_file.write(line + '\n') 219 with self.open(file_path) as fake_file: 220 result = [line.rstrip() for line in fake_file] 221 self.assertEqual(contents, result) 222 223 def test_create_file_with_append(self): 224 contents = [ 225 "Here comes the sun, little darlin'", 226 'Here comes the sun, and I say,', 227 "It's alright", 228 ] 229 file_dir = self.make_path('abbey_road') 230 file_path = self.os.path.join(file_dir, 'here_comes_the_sun') 231 self.os.mkdir(file_dir) 232 with self.open(file_path, 'a') as fake_file: 233 for line in contents: 234 fake_file.write(line + '\n') 235 with self.open(file_path) as fake_file: 236 result = [line.rstrip() for line in fake_file] 237 self.assertEqual(contents, result) 238 239 def test_exclusive_create_file_failure(self): 240 self.skip_if_symlink_not_supported() 241 file_path = self.make_path('bar') 242 self.create_file(file_path) 243 self.assert_raises_os_error(errno.EEXIST, self.open, file_path, 'x') 244 self.assert_raises_os_error(errno.EEXIST, self.open, file_path, 'xb') 245 246 def test_exclusive_create_file(self): 247 file_dir = self.make_path('foo') 248 file_path = self.os.path.join(file_dir, 'bar') 249 self.os.mkdir(file_dir) 250 contents = 'String contents' 251 with self.open(file_path, 'x') as fake_file: 252 fake_file.write(contents) 253 with self.open(file_path) as fake_file: 254 self.assertEqual(contents, fake_file.read()) 255 256 def test_exclusive_create_binary_file(self): 257 file_dir = self.make_path('foo') 258 file_path = self.os.path.join(file_dir, 'bar') 259 self.os.mkdir(file_dir) 260 contents = b'Binary contents' 261 with self.open(file_path, 'xb') as fake_file: 262 fake_file.write(contents) 263 with self.open(file_path, 'rb') as fake_file: 264 self.assertEqual(contents, fake_file.read()) 265 266 def test_overwrite_existing_file(self): 267 file_path = self.make_path('overwite') 268 self.create_file(file_path, contents='To disappear') 269 new_contents = [ 270 'Only these lines', 271 'should be in the file.', 272 ] 273 with self.open(file_path, 'w') as fake_file: 274 for line in new_contents: 275 fake_file.write(line + '\n') 276 with self.open(file_path) as fake_file: 277 result = [line.rstrip() for line in fake_file] 278 self.assertEqual(new_contents, result) 279 280 def test_append_existing_file(self): 281 file_path = self.make_path('appendfile') 282 contents = [ 283 'Contents of original file' 284 'Appended contents', 285 ] 286 287 self.create_file(file_path, contents=contents[0]) 288 with self.open(file_path, 'a') as fake_file: 289 for line in contents[1:]: 290 fake_file.write(line + '\n') 291 with self.open(file_path) as fake_file: 292 result = [line.rstrip() for line in fake_file] 293 self.assertEqual(contents, result) 294 295 def test_open_with_wplus(self): 296 # set up 297 file_path = self.make_path('wplus_file') 298 self.create_file(file_path, contents='old contents') 299 self.assertTrue(self.os.path.exists(file_path)) 300 with self.open(file_path, 'r') as fake_file: 301 self.assertEqual('old contents', fake_file.read()) 302 # actual tests 303 with self.open(file_path, 'w+') as fake_file: 304 fake_file.write('new contents') 305 fake_file.seek(0) 306 self.assertTrue('new contents', fake_file.read()) 307 308 def test_open_with_wplus_truncation(self): 309 # set up 310 file_path = self.make_path('wplus_file') 311 self.create_file(file_path, contents='old contents') 312 self.assertTrue(self.os.path.exists(file_path)) 313 with self.open(file_path, 'r') as fake_file: 314 self.assertEqual('old contents', fake_file.read()) 315 # actual tests 316 with self.open(file_path, 'w+') as fake_file: 317 fake_file.seek(0) 318 self.assertEqual('', fake_file.read()) 319 320 def test_open_with_append_flag(self): 321 contents = [ 322 'I am he as\n', 323 'you are he as\n', 324 'you are me and\n', 325 'we are all together\n' 326 ] 327 additional_contents = [ 328 'These new lines\n', 329 'like you a lot.\n' 330 ] 331 file_path = self.make_path('appendfile') 332 self.create_file(file_path, contents=''.join(contents)) 333 with self.open(file_path, 'a') as fake_file: 334 with self.assertRaises(io.UnsupportedOperation): 335 fake_file.read(0) 336 with self.assertRaises(io.UnsupportedOperation): 337 fake_file.readline() 338 expected_len = len(''.join(contents)) 339 expected_len += len(contents) * (len(self.os.linesep) - 1) 340 self.assertEqual(expected_len, fake_file.tell()) 341 fake_file.seek(0) 342 self.assertEqual(0, fake_file.tell()) 343 fake_file.writelines(additional_contents) 344 with self.open(file_path) as fake_file: 345 self.assertEqual( 346 contents + additional_contents, fake_file.readlines()) 347 348 def check_append_with_aplus(self): 349 file_path = self.make_path('aplus_file') 350 self.create_file(file_path, contents='old contents') 351 self.assertTrue(self.os.path.exists(file_path)) 352 with self.open(file_path, 'r') as fake_file: 353 self.assertEqual('old contents', fake_file.read()) 354 355 if self.filesystem: 356 # need to recreate FakeFileOpen for OS specific initialization 357 self.open = fake_filesystem.FakeFileOpen(self.filesystem, 358 delete_on_close=True) 359 with self.open(file_path, 'a+') as fake_file: 360 self.assertEqual(12, fake_file.tell()) 361 fake_file.write('new contents') 362 self.assertEqual(24, fake_file.tell()) 363 fake_file.seek(0) 364 self.assertEqual('old contentsnew contents', fake_file.read()) 365 366 def test_append_with_aplus_mac_os(self): 367 self.check_macos_only() 368 self.check_append_with_aplus() 369 370 def test_append_with_aplus_linux_windows(self): 371 self.check_linux_and_windows() 372 self.check_append_with_aplus() 373 374 def test_append_with_aplus_read_with_loop(self): 375 # set up 376 file_path = self.make_path('aplus_file') 377 self.create_file(file_path, contents='old contents') 378 self.assertTrue(self.os.path.exists(file_path)) 379 with self.open(file_path, 'r') as fake_file: 380 self.assertEqual('old contents', fake_file.read()) 381 # actual tests 382 with self.open(file_path, 'a+') as fake_file: 383 fake_file.seek(0) 384 fake_file.write('new contents') 385 fake_file.seek(0) 386 for line in fake_file: 387 self.assertEqual('old contentsnew contents', line) 388 389 def test_read_empty_file_with_aplus(self): 390 file_path = self.make_path('aplus_file') 391 with self.open(file_path, 'a+') as fake_file: 392 self.assertEqual('', fake_file.read()) 393 394 def test_read_with_rplus(self): 395 # set up 396 file_path = self.make_path('rplus_file') 397 self.create_file(file_path, contents='old contents here') 398 self.assertTrue(self.os.path.exists(file_path)) 399 with self.open(file_path, 'r') as fake_file: 400 self.assertEqual('old contents here', fake_file.read()) 401 # actual tests 402 with self.open(file_path, 'r+') as fake_file: 403 self.assertEqual('old contents here', fake_file.read()) 404 fake_file.seek(0) 405 fake_file.write('new contents') 406 fake_file.seek(0) 407 self.assertEqual('new contents here', fake_file.read()) 408 409 def create_with_permission(self, file_path, perm_bits): 410 self.create_file(file_path) 411 self.os.chmod(file_path, perm_bits) 412 if perm_bits & PERM_READ: 413 st = self.os.stat(file_path) 414 self.assert_mode_equal(perm_bits, st.st_mode) 415 self.assertTrue(st.st_mode & stat.S_IFREG) 416 self.assertFalse(st.st_mode & stat.S_IFDIR) 417 418 def test_open_flags700(self): 419 # set up 420 self.check_posix_only() 421 file_path = self.make_path('target_file') 422 self.create_with_permission(file_path, 0o700) 423 # actual tests 424 self.open(file_path, 'r').close() 425 self.open(file_path, 'w').close() 426 self.open(file_path, 'w+').close() 427 with self.assertRaises(ValueError): 428 self.open(file_path, 'INV') 429 430 def test_open_flags400(self): 431 # set up 432 self.check_posix_only() 433 file_path = self.make_path('target_file') 434 self.create_with_permission(file_path, 0o400) 435 # actual tests 436 self.open(file_path, 'r').close() 437 if not is_root(): 438 self.assert_raises_os_error( 439 errno.EACCES, self.open, file_path, 'w') 440 self.assert_raises_os_error( 441 errno.EACCES, self.open, file_path, 'w+') 442 else: 443 self.open(file_path, 'w').close() 444 self.open(file_path, 'w+').close() 445 446 def test_open_flags200(self): 447 # set up 448 self.check_posix_only() 449 file_path = self.make_path('target_file') 450 self.create_with_permission(file_path, 0o200) 451 # actual tests 452 self.open(file_path, 'w').close() 453 if not is_root(): 454 with self.assertRaises(OSError): 455 self.open(file_path, 'r') 456 with self.assertRaises(OSError): 457 self.open(file_path, 'w+') 458 else: 459 self.open(file_path, 'r').close() 460 self.open(file_path, 'w+').close() 461 462 def test_open_flags100(self): 463 # set up 464 self.check_posix_only() 465 file_path = self.make_path('target_file') 466 self.create_with_permission(file_path, 0o100) 467 # actual tests 468 if not is_root(): 469 with self.assertRaises(OSError): 470 self.open(file_path, 'r') 471 with self.assertRaises(OSError): 472 self.open(file_path, 'w') 473 with self.assertRaises(OSError): 474 self.open(file_path, 'w+') 475 else: 476 self.open(file_path, 'r').close() 477 self.open(file_path, 'w').close() 478 self.open(file_path, 'w+').close() 479 480 def test_follow_link_read(self): 481 self.skip_if_symlink_not_supported() 482 link_path = self.make_path('foo', 'bar', 'baz') 483 target = self.make_path('tarJAY') 484 target_contents = 'real baz contents' 485 self.create_file(target, contents=target_contents) 486 self.create_symlink(link_path, target) 487 self.assert_equal_paths(target, self.os.readlink(link_path)) 488 fh = self.open(link_path, 'r') 489 got_contents = fh.read() 490 fh.close() 491 self.assertEqual(target_contents, got_contents) 492 493 def test_follow_link_write(self): 494 self.skip_if_symlink_not_supported() 495 link_path = self.make_path('foo', 'bar', 'TBD') 496 target = self.make_path('tarJAY') 497 target_contents = 'real baz contents' 498 self.create_symlink(link_path, target) 499 self.assertFalse(self.os.path.exists(target)) 500 501 with self.open(link_path, 'w') as fh: 502 fh.write(target_contents) 503 with self.open(target, 'r') as fh: 504 got_contents = fh.read() 505 self.assertEqual(target_contents, got_contents) 506 507 def test_follow_intra_path_link_write(self): 508 # Test a link in the middle of of a file path. 509 self.skip_if_symlink_not_supported() 510 link_path = self.os.path.join( 511 self.base_path, 'foo', 'build', 'local_machine', 'output', '1') 512 target = self.make_path('tmp', 'output', '1') 513 self.create_dir(self.make_path('tmp', 'output')) 514 self.create_symlink(self.os.path.join( 515 self.base_path, 'foo', 'build', 'local_machine'), 516 self.make_path('tmp')) 517 518 self.assertFalse(self.os.path.exists(link_path)) 519 self.assertFalse(self.os.path.exists(target)) 520 521 target_contents = 'real baz contents' 522 with self.open(link_path, 'w') as fh: 523 fh.write(target_contents) 524 with self.open(target, 'r') as fh: 525 got_contents = fh.read() 526 self.assertEqual(target_contents, got_contents) 527 528 def test_open_raises_on_symlink_loop(self): 529 # Regression test for #274 530 self.check_posix_only() 531 file_dir = self.make_path('foo') 532 self.os.mkdir(file_dir) 533 file_path = self.os.path.join(file_dir, 'baz') 534 self.os.symlink(file_path, file_path) 535 self.assert_raises_os_error(errno.ELOOP, self.open, file_path) 536 537 def test_file_descriptors_for_different_files(self): 538 first_path = self.make_path('some_file1') 539 self.create_file(first_path, contents='contents here1') 540 second_path = self.make_path('some_file2') 541 self.create_file(second_path, contents='contents here2') 542 third_path = self.make_path('some_file3') 543 self.create_file(third_path, contents='contents here3') 544 545 with self.open(first_path) as fake_file1: 546 with self.open(second_path) as fake_file2: 547 with self.open(third_path) as fake_file3: 548 fileno2 = fake_file2.fileno() 549 self.assertGreater(fileno2, fake_file1.fileno()) 550 self.assertGreater(fake_file3.fileno(), fileno2) 551 552 def test_file_descriptors_for_the_same_file_are_different(self): 553 first_path = self.make_path('some_file1') 554 self.create_file(first_path, contents='contents here1') 555 second_path = self.make_path('some_file2') 556 self.create_file(second_path, contents='contents here2') 557 with self.open(first_path) as fake_file1: 558 with self.open(second_path) as fake_file2: 559 with self.open(first_path) as fake_file1a: 560 fileno2 = fake_file2.fileno() 561 self.assertGreater(fileno2, fake_file1.fileno()) 562 self.assertGreater(fake_file1a.fileno(), fileno2) 563 564 def test_reused_file_descriptors_do_not_affect_others(self): 565 first_path = self.make_path('some_file1') 566 self.create_file(first_path, contents='contents here1') 567 second_path = self.make_path('some_file2') 568 self.create_file(second_path, contents='contents here2') 569 third_path = self.make_path('some_file3') 570 self.create_file(third_path, contents='contents here3') 571 572 with self.open(first_path, 'r') as fake_file1: 573 with self.open(second_path, 'r') as fake_file2: 574 fake_file3 = self.open(third_path, 'r') 575 fake_file1a = self.open(first_path, 'r') 576 fileno1 = fake_file1.fileno() 577 fileno2 = fake_file2.fileno() 578 fileno3 = fake_file3.fileno() 579 fileno4 = fake_file1a.fileno() 580 581 with self.open(second_path, 'r') as fake_file2: 582 with self.open(first_path, 'r') as fake_file1b: 583 self.assertEqual(fileno1, fake_file2.fileno()) 584 self.assertEqual(fileno2, fake_file1b.fileno()) 585 self.assertEqual(fileno3, fake_file3.fileno()) 586 self.assertEqual(fileno4, fake_file1a.fileno()) 587 fake_file3.close() 588 fake_file1a.close() 589 590 def test_intertwined_read_write(self): 591 file_path = self.make_path('some_file') 592 self.create_file(file_path) 593 594 with self.open(file_path, 'a') as writer: 595 with self.open(file_path, 'r') as reader: 596 writes = ['hello', 'world\n', 'somewhere\nover', 'the\n', 597 'rainbow'] 598 reads = [] 599 # when writes are flushes, they are piped to the reader 600 for write in writes: 601 writer.write(write) 602 writer.flush() 603 reads.append(reader.read()) 604 reader.flush() 605 self.assertEqual(writes, reads) 606 writes = ['nothing', 'to\nsee', 'here'] 607 reads = [] 608 # when writes are not flushed, the reader doesn't read 609 # anything new 610 for write in writes: 611 writer.write(write) 612 reads.append(reader.read()) 613 self.assertEqual(['' for _ in writes], reads) 614 615 def test_intertwined_read_write_python3_str(self): 616 file_path = self.make_path('some_file') 617 self.create_file(file_path) 618 619 with self.open(file_path, 'a', encoding='utf-8') as writer: 620 with self.open(file_path, 'r', encoding='utf-8') as reader: 621 writes = ['привет', 'мир\n', 'где-то\nза', 'радугой'] 622 reads = [] 623 # when writes are flushes, they are piped to the reader 624 for write in writes: 625 writer.write(write) 626 writer.flush() 627 reads.append(reader.read()) 628 reader.flush() 629 self.assertEqual(writes, reads) 630 writes = ['ничего', 'не\nвидно'] 631 reads = [] 632 # when writes are not flushed, the reader doesn't 633 # read anything new 634 for write in writes: 635 writer.write(write) 636 reads.append(reader.read()) 637 self.assertEqual(['' for _ in writes], reads) 638 639 def test_open_io_errors(self): 640 file_path = self.make_path('some_file') 641 self.create_file(file_path) 642 643 with self.open(file_path, 'a') as fh: 644 with self.assertRaises(OSError): 645 fh.read() 646 with self.assertRaises(OSError): 647 fh.readlines() 648 with self.open(file_path, 'w') as fh: 649 with self.assertRaises(OSError): 650 fh.read() 651 with self.assertRaises(OSError): 652 fh.readlines() 653 with self.open(file_path, 'r') as fh: 654 with self.assertRaises(OSError): 655 fh.truncate() 656 with self.assertRaises(OSError): 657 fh.write('contents') 658 with self.assertRaises(OSError): 659 fh.writelines(['con', 'tents']) 660 661 def _iterator_open(mode): 662 with self.open(file_path, mode) as f: 663 for _ in f: 664 pass 665 666 with self.assertRaises(OSError): 667 _iterator_open('w') 668 with self.assertRaises(OSError): 669 _iterator_open('a') 670 671 def test_open_raises_io_error_if_parent_is_file_posix(self): 672 self.check_posix_only() 673 file_path = self.make_path('bar') 674 self.create_file(file_path) 675 file_path = self.os.path.join(file_path, 'baz') 676 self.assert_raises_os_error(errno.ENOTDIR, self.open, file_path, 'w') 677 678 def test_open_raises_io_error_if_parent_is_file_windows(self): 679 self.check_windows_only() 680 file_path = self.make_path('bar') 681 self.create_file(file_path) 682 file_path = self.os.path.join(file_path, 'baz') 683 self.assert_raises_os_error(errno.ENOENT, self.open, file_path, 'w') 684 685 def check_open_with_trailing_sep(self, error_nr): 686 # regression test for #362 687 path = self.make_path('foo') + self.os.path.sep 688 self.assert_raises_os_error(error_nr, self.open, path, 'w') 689 690 def test_open_with_trailing_sep_linux(self): 691 self.check_linux_only() 692 self.check_open_with_trailing_sep(errno.EISDIR) 693 694 def test_open_with_trailing_sep_macos(self): 695 self.check_macos_only() 696 self.check_open_with_trailing_sep(errno.ENOENT) 697 698 def test_open_with_trailing_sep_windows(self): 699 self.check_windows_only() 700 self.check_open_with_trailing_sep(errno.EINVAL) 701 702 def test_can_read_from_block_device(self): 703 self.skip_real_fs() 704 device_path = 'device' 705 self.filesystem.create_file(device_path, stat.S_IFBLK 706 | fake_filesystem.PERM_ALL) 707 with self.open(device_path, 'r') as fh: 708 self.assertEqual('', fh.read()) 709 710 def test_truncate_flushes_contents(self): 711 # Regression test for #285 712 file_path = self.make_path('baz') 713 self.create_file(file_path) 714 with self.open(file_path, 'w') as f0: 715 f0.write('test') 716 f0.truncate() 717 self.assertEqual(4, self.os.path.getsize(file_path)) 718 719 def test_update_other_instances_of_same_file_on_flush(self): 720 # Regression test for #302 721 file_path = self.make_path('baz') 722 with self.open(file_path, 'w') as f0: 723 with self.open(file_path, 'w') as f1: 724 f0.write('test') 725 f0.truncate() 726 f1.flush() 727 self.assertEqual(4, self.os.path.getsize(file_path)) 728 729 def test_getsize_after_truncate(self): 730 # Regression test for #412 731 file_path = self.make_path('foo') 732 with self.open(file_path, 'a') as f: 733 f.write('a') 734 f.seek(0) 735 f.truncate() 736 f.write('b') 737 f.truncate() 738 self.assertEqual(1, self.os.path.getsize(file_path)) 739 self.assertEqual(1, self.os.stat(file_path).st_size) 740 741 def test_st_size_after_truncate(self): 742 # Regression test for #412 743 file_path = self.make_path('foo') 744 with self.open(file_path, 'a') as f: 745 f.write('a') 746 f.truncate() 747 f.write('b') 748 f.truncate() 749 self.assertEqual(2, self.os.stat(file_path).st_size) 750 751 def test_that_read_over_end_does_not_reset_position(self): 752 # Regression test for #286 753 file_path = self.make_path('baz') 754 self.create_file(file_path) 755 with self.open(file_path) as f0: 756 f0.seek(2) 757 f0.read() 758 self.assertEqual(2, f0.tell()) 759 760 def test_accessing_closed_file_raises(self): 761 # Regression test for #275, #280 762 if self.is_pypy: 763 raise unittest.SkipTest('Different exceptions with PyPy') 764 file_path = self.make_path('foo') 765 self.create_file(file_path, contents=b'test') 766 fake_file = self.open(file_path, 'r') 767 fake_file.close() 768 with self.assertRaises(ValueError): 769 fake_file.read(1) 770 with self.assertRaises(ValueError): 771 fake_file.write('a') 772 with self.assertRaises(ValueError): 773 fake_file.readline() 774 with self.assertRaises(ValueError): 775 fake_file.truncate() 776 with self.assertRaises(ValueError): 777 fake_file.tell() 778 with self.assertRaises(ValueError): 779 fake_file.seek(1) 780 with self.assertRaises(ValueError): 781 fake_file.flush() 782 783 def test_accessing_open_file_with_another_handle_raises(self): 784 # Regression test for #282 785 if self.is_pypy: 786 raise unittest.SkipTest('Different exceptions with PyPy') 787 file_path = self.make_path('foo') 788 f0 = self.os.open(file_path, os.O_CREAT | os.O_WRONLY | os.O_TRUNC) 789 fake_file = self.open(file_path, 'r') 790 fake_file.close() 791 with self.assertRaises(ValueError): 792 fake_file.read(1) 793 with self.assertRaises(ValueError): 794 fake_file.write('a') 795 self.os.close(f0) 796 797 def test_tell_flushes_under_mac_os(self): 798 # Regression test for #288 799 self.check_macos_only() 800 file_path = self.make_path('foo') 801 with self.open(file_path, 'w') as f0: 802 f0.write('test') 803 self.assertEqual(4, f0.tell()) 804 self.assertEqual(4, self.os.path.getsize(file_path)) 805 806 def test_tell_flushes_in_python3(self): 807 # Regression test for #288 808 self.check_linux_and_windows() 809 file_path = self.make_path('foo') 810 with self.open(file_path, 'w') as f0: 811 f0.write('test') 812 self.assertEqual(4, f0.tell()) 813 self.assertEqual(4, self.os.path.getsize(file_path)) 814 815 def test_read_flushes_under_posix(self): 816 # Regression test for #278 817 self.check_posix_only() 818 file_path = self.make_path('foo') 819 with self.open(file_path, 'a+') as f0: 820 f0.write('test') 821 self.assertEqual('', f0.read()) 822 self.assertEqual(4, self.os.path.getsize(file_path)) 823 824 def test_read_flushes_under_windows_in_python3(self): 825 # Regression test for #278 826 self.check_windows_only() 827 file_path = self.make_path('foo') 828 with self.open(file_path, 'w+') as f0: 829 f0.write('test') 830 f0.read() 831 self.assertEqual(4, self.os.path.getsize(file_path)) 832 833 def test_seek_flushes(self): 834 # Regression test for #290 835 file_path = self.make_path('foo') 836 with self.open(file_path, 'w') as f0: 837 f0.write('test') 838 self.assertEqual(0, self.os.path.getsize(file_path)) 839 f0.seek(3) 840 self.assertEqual(4, self.os.path.getsize(file_path)) 841 842 def test_truncate_flushes(self): 843 # Regression test for #291 844 file_path = self.make_path('foo') 845 with self.open(file_path, 'a') as f0: 846 f0.write('test') 847 self.assertEqual(0, self.os.path.getsize(file_path)) 848 f0.truncate() 849 self.assertEqual(4, self.os.path.getsize(file_path)) 850 851 def check_seek_outside_and_truncate_sets_size(self, mode): 852 # Regression test for #294 and #296 853 file_path = self.make_path('baz') 854 with self.open(file_path, mode) as f0: 855 f0.seek(1) 856 f0.truncate() 857 self.assertEqual(1, f0.tell()) 858 self.assertEqual(1, self.os.path.getsize(file_path)) 859 f0.seek(1) 860 self.assertEqual(1, self.os.path.getsize(file_path)) 861 self.assertEqual(1, self.os.path.getsize(file_path)) 862 863 def test_seek_outside_and_truncate_sets_size_in_write_mode(self): 864 # Regression test for #294 865 self.check_seek_outside_and_truncate_sets_size('w') 866 867 def test_seek_outside_and_truncate_sets_size_in_append_mode(self): 868 # Regression test for #295 869 self.check_seek_outside_and_truncate_sets_size('a') 870 871 def test_closed(self): 872 file_path = self.make_path('foo') 873 f = self.open(file_path, 'w') 874 self.assertFalse(f.closed) 875 f.close() 876 self.assertTrue(f.closed) 877 f = self.open(file_path) 878 self.assertFalse(f.closed) 879 f.close() 880 self.assertTrue(f.closed) 881 882 def test_closing_closed_file_does_nothing(self): 883 # Regression test for #299 884 file_path = self.make_path('baz') 885 f0 = self.open(file_path, 'w') 886 f0.close() 887 with self.open(file_path) as f1: 888 # would close f1 if not handled 889 f0.close() 890 self.assertEqual('', f1.read()) 891 892 def test_closing_file_with_different_close_mode(self): 893 self.skip_real_fs() 894 filename = self.make_path('test.txt') 895 fd = self.os.open(filename, os.O_CREAT | os.O_RDWR) 896 file_obj = self.filesystem.get_object(filename) 897 with self.open(fd, 'wb', closefd=False) as fp: 898 fp.write(b'test') 899 self.assertTrue(self.filesystem.has_open_file(file_obj)) 900 self.os.close(fd) 901 self.assertFalse(self.filesystem.has_open_file(file_obj)) 902 903 def test_truncate_flushes_zeros(self): 904 # Regression test for #301 905 file_path = self.make_path('baz') 906 with self.open(file_path, 'w') as f0: 907 with self.open(file_path) as f1: 908 f0.seek(1) 909 f0.truncate() 910 self.assertEqual('\0', f1.read()) 911 912 def test_byte_filename(self): 913 file_path = self.make_path(b'test') 914 with self.open(file_path, 'wb') as f: 915 f.write(b'test') 916 with self.open(file_path, 'rb') as f: 917 self.assertEqual(b'test', f.read()) 918 919 def test_unicode_filename(self): 920 file_path = self.make_path('тест') 921 with self.open(file_path, 'wb') as f: 922 f.write(b'test') 923 with self.open(file_path, 'rb') as f: 924 self.assertEqual(b'test', f.read()) 925 926 def test_write_devnull(self): 927 for mode in ('r+', 'w', 'w+', 'a', 'a+'): 928 with self.open(self.os.devnull, mode) as f: 929 f.write('test') 930 with self.open(self.os.devnull) as f: 931 self.assertEqual('', f.read()) 932 933 def test_utf16_text(self): 934 # regression test for #574 935 file_path = self.make_path('foo') 936 with self.open(file_path, "w", encoding='utf-16') as f: 937 assert f.write("1") == 1 938 939 with self.open(file_path, "a", encoding='utf-16') as f: 940 assert f.write("2") == 1 941 942 with self.open(file_path, "r", encoding='utf-16') as f: 943 text = f.read() 944 assert text == "12" 945 946 947class RealFileOpenTest(FakeFileOpenTest): 948 def use_real_fs(self): 949 return True 950 951 952@unittest.skipIf(sys.version_info < (3, 8), 953 'open_code only present since Python 3.8') 954class FakeFilePatchedOpenCodeTest(FakeFileOpenTestBase): 955 956 def setUp(self): 957 super(FakeFilePatchedOpenCodeTest, self).setUp() 958 if self.use_real_fs(): 959 self.open_code = io.open_code 960 else: 961 self.filesystem.patch_open_code = PatchMode.ON 962 self.open_code = self.fake_io_module.open_code 963 964 def tearDown(self): 965 if not self.use_real_fs(): 966 self.filesystem.patch_open_code = False 967 super(FakeFilePatchedOpenCodeTest, self).tearDown() 968 969 def test_invalid_path(self): 970 with self.assertRaises(TypeError): 971 self.open_code(4) 972 973 def test_byte_contents_open_code(self): 974 byte_fractions = b'\xe2\x85\x93 \xe2\x85\x94 \xe2\x85\x95 \xe2\x85\x96' 975 file_path = self.make_path('foo') 976 self.create_file(file_path, contents=byte_fractions) 977 with self.open_code(file_path) as f: 978 contents = f.read() 979 self.assertEqual(contents, byte_fractions) 980 981 def test_open_code_in_real_fs(self): 982 self.skip_real_fs() 983 file_path = __file__ 984 with self.assertRaises(OSError): 985 self.open_code(file_path) 986 987 988class RealPatchedFileOpenCodeTest(FakeFilePatchedOpenCodeTest): 989 def use_real_fs(self): 990 return True 991 992 993@unittest.skipIf(sys.version_info < (3, 8), 994 'open_code only present since Python 3.8') 995class FakeFileUnpatchedOpenCodeTest(FakeFileOpenTestBase): 996 997 def setUp(self): 998 super(FakeFileUnpatchedOpenCodeTest, self).setUp() 999 if self.use_real_fs(): 1000 self.open_code = io.open_code 1001 else: 1002 self.open_code = self.fake_io_module.open_code 1003 1004 def test_invalid_path(self): 1005 with self.assertRaises(TypeError): 1006 self.open_code(4) 1007 1008 def test_open_code_in_real_fs(self): 1009 file_path = __file__ 1010 1011 with self.open_code(file_path) as f: 1012 contents = f.read() 1013 self.assertTrue(len(contents) > 100) 1014 1015 1016class RealUnpatchedFileOpenCodeTest(FakeFileUnpatchedOpenCodeTest): 1017 def use_real_fs(self): 1018 return True 1019 1020 def test_byte_contents_open_code(self): 1021 byte_fractions = b'\xe2\x85\x93 \xe2\x85\x94 \xe2\x85\x95 \xe2\x85\x96' 1022 file_path = self.make_path('foo') 1023 self.create_file(file_path, contents=byte_fractions) 1024 with self.open_code(file_path) as f: 1025 contents = f.read() 1026 self.assertEqual(contents, byte_fractions) 1027 1028 1029class BufferingModeTest(FakeFileOpenTestBase): 1030 def test_no_buffering(self): 1031 file_path = self.make_path("buffertest.bin") 1032 with self.open(file_path, 'wb', buffering=0) as f: 1033 f.write(b'a' * 128) 1034 with self.open(file_path, "rb") as r: 1035 x = r.read() 1036 self.assertEqual(b'a' * 128, x) 1037 1038 def test_no_buffering_not_allowed_in_textmode(self): 1039 file_path = self.make_path("buffertest.txt") 1040 with self.assertRaises(ValueError): 1041 self.open(file_path, 'w', buffering=0) 1042 1043 def test_default_buffering_no_flush(self): 1044 file_path = self.make_path("buffertest.bin") 1045 with self.open(file_path, 'wb') as f: 1046 f.write(b'a' * 2048) 1047 with self.open(file_path, "rb") as r: 1048 x = r.read() 1049 self.assertEqual(b'', x) 1050 with self.open(file_path, "rb") as r: 1051 x = r.read() 1052 self.assertEqual(b'a' * 2048, x) 1053 1054 def test_default_buffering_flush(self): 1055 file_path = self.make_path("buffertest.bin") 1056 with self.open(file_path, 'wb') as f: 1057 f.write(b'a' * 2048) 1058 f.flush() 1059 with self.open(file_path, "rb") as r: 1060 x = r.read() 1061 self.assertEqual(b'a' * 2048, x) 1062 1063 def test_writing_with_specific_buffer(self): 1064 file_path = self.make_path("buffertest.bin") 1065 with self.open(file_path, 'wb', buffering=512) as f: 1066 f.write(b'a' * 500) 1067 with self.open(file_path, "rb") as r: 1068 x = r.read() 1069 # buffer not filled - not written 1070 self.assertEqual(0, len(x)) 1071 f.write(b'a' * 400) 1072 with self.open(file_path, "rb") as r: 1073 x = r.read() 1074 # buffer exceeded, but new buffer (400) not - previous written 1075 self.assertEqual(500, len(x)) 1076 f.write(b'a' * 100) 1077 with self.open(file_path, "rb") as r: 1078 x = r.read() 1079 # buffer not full (500) not written 1080 self.assertEqual(500, len(x)) 1081 f.write(b'a' * 100) 1082 with self.open(file_path, "rb") as r: 1083 x = r.read() 1084 # buffer exceeded (600) -> write previous 1085 # new buffer not full (100) - not written 1086 self.assertEqual(1000, len(x)) 1087 f.write(b'a' * 600) 1088 with self.open(file_path, "rb") as r: 1089 x = r.read() 1090 # new buffer exceeded (600) -> all written 1091 self.assertEqual(1700, len(x)) 1092 1093 def test_writing_text_with_line_buffer(self): 1094 file_path = self.make_path("buffertest.bin") 1095 with self.open(file_path, 'w', buffering=1) as f: 1096 f.write('test' * 100) 1097 with self.open(file_path, "r") as r: 1098 x = r.read() 1099 # no new line - not written 1100 self.assertEqual(0, len(x)) 1101 f.write('\ntest') 1102 with self.open(file_path, "r") as r: 1103 x = r.read() 1104 # new line - buffer written 1105 self.assertEqual(405, len(x)) 1106 f.write('test' * 10) 1107 with self.open(file_path, "r") as r: 1108 x = r.read() 1109 # buffer not filled - not written 1110 self.assertEqual(405, len(x)) 1111 f.write('\ntest') 1112 with self.open(file_path, "r") as r: 1113 x = r.read() 1114 # new line - buffer written 1115 self.assertEqual(450, len(x)) 1116 1117 def test_writing_large_text_with_line_buffer(self): 1118 file_path = self.make_path("buffertest.bin") 1119 with self.open(file_path, 'w', buffering=1) as f: 1120 f.write('test' * 4000) 1121 with self.open(file_path, "r") as r: 1122 x = r.read() 1123 # buffer larger than default - written 1124 self.assertEqual(16000, len(x)) 1125 f.write('test') 1126 with self.open(file_path, "r") as r: 1127 x = r.read() 1128 # buffer not filled - not written 1129 self.assertEqual(16000, len(x)) 1130 f.write('\ntest') 1131 with self.open(file_path, "r") as r: 1132 x = r.read() 1133 # new line - buffer written 1134 self.assertEqual(16009, len(x)) 1135 f.write('\ntest') 1136 with self.open(file_path, "r") as r: 1137 x = r.read() 1138 # another new line - buffer written 1139 self.assertEqual(16014, len(x)) 1140 1141 def test_writing_text_with_default_buffer(self): 1142 file_path = self.make_path("buffertest.txt") 1143 with self.open(file_path, 'w') as f: 1144 f.write('test' * 5) 1145 with self.open(file_path, "r") as r: 1146 x = r.read() 1147 # buffer not filled - not written 1148 self.assertEqual(0, len(x)) 1149 f.write('\ntest') 1150 with self.open(file_path, "r") as r: 1151 x = r.read() 1152 # buffer exceeded, but new buffer (400) not - previous written 1153 self.assertEqual(0, len(x)) 1154 f.write('test' * 10) 1155 with self.open(file_path, "r") as r: 1156 x = r.read() 1157 # buffer not filled - not written 1158 self.assertEqual(0, len(x)) 1159 f.write('\ntest') 1160 with self.open(file_path, "r") as r: 1161 x = r.read() 1162 self.assertEqual(0, len(x)) 1163 1164 def test_writing_text_with_specific_buffer(self): 1165 file_path = self.make_path("buffertest.txt") 1166 with self.open(file_path, 'w', buffering=2) as f: 1167 f.write('a' * 8000) 1168 with self.open(file_path, "r") as r: 1169 x = r.read() 1170 # buffer not filled - not written 1171 self.assertEqual(0, len(x)) 1172 f.write('test') 1173 with self.open(file_path, "r") as r: 1174 x = r.read() 1175 # buffer exceeded, but new buffer (400) not - previous written 1176 self.assertEqual(0, len(x)) 1177 f.write('test') 1178 with self.open(file_path, "r") as r: 1179 x = r.read() 1180 # buffer not filled - not written 1181 self.assertEqual(0, len(x)) 1182 f.write('test') 1183 with self.open(file_path, "r") as r: 1184 x = r.read() 1185 self.assertEqual(0, len(x)) 1186 # with self.open(file_path, "r") as r: 1187 # x = r.read() 1188 # self.assertEqual(35, len(x)) 1189 1190 def test_append_with_specific_buffer(self): 1191 file_path = self.make_path("buffertest.bin") 1192 with self.open(file_path, 'wb', buffering=512) as f: 1193 f.write(b'a' * 500) 1194 with self.open(file_path, 'ab', buffering=512) as f: 1195 f.write(b'a' * 500) 1196 with self.open(file_path, "rb") as r: 1197 x = r.read() 1198 # buffer not filled - not written 1199 self.assertEqual(500, len(x)) 1200 f.write(b'a' * 400) 1201 with self.open(file_path, "rb") as r: 1202 x = r.read() 1203 # buffer exceeded, but new buffer (400) not - previous written 1204 self.assertEqual(1000, len(x)) 1205 f.write(b'a' * 100) 1206 with self.open(file_path, "rb") as r: 1207 x = r.read() 1208 # buffer not full (500) not written 1209 self.assertEqual(1000, len(x)) 1210 f.write(b'a' * 100) 1211 with self.open(file_path, "rb") as r: 1212 x = r.read() 1213 # buffer exceeded (600) -> write previous 1214 # new buffer not full (100) - not written 1215 self.assertEqual(1500, len(x)) 1216 f.write(b'a' * 600) 1217 with self.open(file_path, "rb") as r: 1218 x = r.read() 1219 # new buffer exceeded (600) -> all written 1220 self.assertEqual(2200, len(x)) 1221 1222 def test_failed_flush_does_not_truncate_file(self): 1223 # regression test for #548 1224 self.skip_real_fs() # cannot set fs size in real fs 1225 self.filesystem.set_disk_usage(100) 1226 self.os.makedirs("foo") 1227 file_path = self.os.path.join('foo', 'bar.txt') 1228 with self.open(file_path, 'wb') as f: 1229 f.write(b'a' * 50) 1230 f.flush() 1231 with self.open(file_path, "rb") as r: 1232 x = r.read() 1233 self.assertTrue(x.startswith(b'a' * 50)) 1234 with self.assertRaises(OSError): 1235 f.write(b'b' * 200) 1236 f.flush() 1237 with self.open(file_path, "rb") as r: 1238 x = r.read() 1239 self.assertTrue(x.startswith(b'a' * 50)) 1240 f.truncate(50) 1241 1242 def test_failed_write_does_not_truncate_file(self): 1243 # test the same with no buffering and no flush 1244 self.skip_real_fs() # cannot set fs size in real fs 1245 self.filesystem.set_disk_usage(100) 1246 self.os.makedirs("foo") 1247 file_path = self.os.path.join('foo', 'bar.txt') 1248 with self.open(file_path, 'wb', buffering=0) as f: 1249 f.write(b'a' * 50) 1250 with self.open(file_path, "rb") as r: 1251 x = r.read() 1252 self.assertEqual(b'a' * 50, x) 1253 with self.assertRaises(OSError): 1254 f.write(b'b' * 200) 1255 with self.open(file_path, "rb") as r: 1256 x = r.read() 1257 self.assertEqual(b'a' * 50, x) 1258 1259 1260class RealBufferingTest(BufferingModeTest): 1261 def use_real_fs(self): 1262 return True 1263 1264 1265class OpenFileWithEncodingTest(FakeFileOpenTestBase): 1266 """Tests that are similar to some open file tests above but using 1267 an explicit text encoding.""" 1268 1269 def setUp(self): 1270 super(OpenFileWithEncodingTest, self).setUp() 1271 self.file_path = self.make_path('foo') 1272 1273 def test_write_str_read_bytes(self): 1274 str_contents = u'علي بابا' 1275 with self.open(self.file_path, 'w', encoding='arabic') as f: 1276 f.write(str_contents) 1277 with self.open(self.file_path, 'rb') as f: 1278 contents = f.read() 1279 self.assertEqual(str_contents, contents.decode('arabic')) 1280 1281 def test_write_str_error_modes(self): 1282 str_contents = u'علي بابا' 1283 with self.open(self.file_path, 'w', encoding='cyrillic') as f: 1284 with self.assertRaises(UnicodeEncodeError): 1285 f.write(str_contents) 1286 1287 with self.open(self.file_path, 'w', encoding='ascii', 1288 errors='xmlcharrefreplace') as f: 1289 f.write(str_contents) 1290 with self.open(self.file_path, 'r', encoding='ascii') as f: 1291 contents = f.read() 1292 self.assertEqual('علي بابا', 1293 contents) 1294 1295 with self.open(self.file_path, 'w', encoding='ascii', 1296 errors='namereplace') as f: 1297 f.write(str_contents) 1298 with self.open(self.file_path, 'r', encoding='ascii') as f: 1299 contents = f.read() 1300 self.assertEqual( 1301 r'\N{ARABIC LETTER AIN}\N{ARABIC LETTER LAM}\N' 1302 r'{ARABIC LETTER YEH} \N{ARABIC LETTER BEH}\N' 1303 r'{ARABIC LETTER ALEF}\N{ARABIC LETTER BEH}' 1304 r'\N{ARABIC LETTER ALEF}', contents) 1305 1306 def test_read_str_error_modes(self): 1307 str_contents = u'علي بابا' 1308 with self.open(self.file_path, 'w', encoding='arabic') as f: 1309 f.write(str_contents) 1310 1311 # default strict encoding 1312 with self.open(self.file_path, encoding='ascii') as f: 1313 with self.assertRaises(UnicodeDecodeError): 1314 f.read() 1315 with self.open(self.file_path, encoding='ascii', 1316 errors='replace') as f: 1317 contents = f.read() 1318 self.assertNotEqual(str_contents, contents) 1319 1320 with self.open(self.file_path, encoding='ascii', 1321 errors='backslashreplace') as f: 1322 contents = f.read() 1323 self.assertEqual(r'\xd9\xe4\xea \xc8\xc7\xc8\xc7', contents) 1324 1325 def test_write_and_read_str(self): 1326 str_contents = u'علي بابا' 1327 with self.open(self.file_path, 'w', encoding='arabic') as f: 1328 f.write(str_contents) 1329 with self.open(self.file_path, 'r', encoding='arabic') as f: 1330 contents = f.read() 1331 self.assertEqual(str_contents, contents) 1332 1333 def test_create_file_with_append(self): 1334 contents = [ 1335 u'Allons enfants de la Patrie,' 1336 u'Le jour de gloire est arrivé!', 1337 u'Contre nous de la tyrannie,', 1338 u'L’étendard sanglant est levé.', 1339 ] 1340 with self.open(self.file_path, 'a', encoding='utf-8') as fake_file: 1341 for line in contents: 1342 fake_file.write(line + '\n') 1343 with self.open(self.file_path, encoding='utf-8') as fake_file: 1344 result = [line.rstrip() for line in fake_file] 1345 self.assertEqual(contents, result) 1346 1347 def test_append_existing_file(self): 1348 contents = [ 1349 u'Оригинальное содержание' 1350 u'Дополнительное содержание', 1351 ] 1352 self.create_file(self.file_path, contents=contents[0], 1353 encoding='cyrillic') 1354 with self.open(self.file_path, 'a', encoding='cyrillic') as fake_file: 1355 for line in contents[1:]: 1356 fake_file.write(line + '\n') 1357 with self.open(self.file_path, encoding='cyrillic') as fake_file: 1358 result = [line.rstrip() for line in fake_file] 1359 self.assertEqual(contents, result) 1360 1361 def test_open_with_wplus(self): 1362 self.create_file(self.file_path, 1363 contents=u'старое содержание', 1364 encoding='cyrillic') 1365 with self.open(self.file_path, 'r', encoding='cyrillic') as fake_file: 1366 self.assertEqual(u'старое содержание', fake_file.read()) 1367 1368 with self.open(self.file_path, 'w+', encoding='cyrillic') as fake_file: 1369 fake_file.write(u'новое содержание') 1370 fake_file.seek(0) 1371 self.assertTrue(u'новое содержание', fake_file.read()) 1372 1373 def test_open_with_append_flag(self): 1374 contents = [ 1375 u'Калинка,\n', 1376 u'калинка,\n', 1377 u'калинка моя,\n' 1378 ] 1379 additional_contents = [ 1380 u'В саду ягода-малинка,\n', 1381 u'малинка моя.\n' 1382 ] 1383 self.create_file(self.file_path, contents=''.join(contents), 1384 encoding='cyrillic') 1385 with self.open(self.file_path, 'a', encoding='cyrillic') as fake_file: 1386 with self.assertRaises(io.UnsupportedOperation): 1387 fake_file.read(0) 1388 with self.assertRaises(io.UnsupportedOperation): 1389 fake_file.readline() 1390 self.assertEqual(len(''.join(contents)), fake_file.tell()) 1391 fake_file.seek(0) 1392 self.assertEqual(0, fake_file.tell()) 1393 fake_file.writelines(additional_contents) 1394 with self.open(self.file_path, encoding='cyrillic') as fake_file: 1395 self.assertEqual(contents + additional_contents, 1396 fake_file.readlines()) 1397 1398 def test_append_with_aplus(self): 1399 self.create_file(self.file_path, 1400 contents=u'старое содержание', 1401 encoding='cyrillic') 1402 fake_file = self.open(self.file_path, 'r', encoding='cyrillic') 1403 fake_file.close() 1404 1405 with self.open(self.file_path, 'a+', encoding='cyrillic') as fake_file: 1406 self.assertEqual(17, fake_file.tell()) 1407 fake_file.write(u'новое содержание') 1408 self.assertEqual(33, fake_file.tell()) 1409 fake_file.seek(0) 1410 self.assertEqual(u'старое содержаниеновое содержание', 1411 fake_file.read()) 1412 1413 def test_read_with_rplus(self): 1414 self.create_file(self.file_path, 1415 contents=u'старое содержание здесь', 1416 encoding='cyrillic') 1417 fake_file = self.open(self.file_path, 'r', encoding='cyrillic') 1418 fake_file.close() 1419 1420 with self.open(self.file_path, 'r+', encoding='cyrillic') as fake_file: 1421 self.assertEqual(u'старое содержание здесь', fake_file.read()) 1422 fake_file.seek(0) 1423 fake_file.write(u'новое содержание') 1424 fake_file.seek(0) 1425 self.assertEqual(u'новое содержание здесь', fake_file.read()) 1426 1427 1428class OpenRealFileWithEncodingTest(OpenFileWithEncodingTest): 1429 def use_real_fs(self): 1430 return True 1431 1432 1433class FakeFileOpenLineEndingTest(FakeFileOpenTestBase): 1434 def setUp(self): 1435 super(FakeFileOpenLineEndingTest, self).setUp() 1436 1437 def test_read_default_newline_mode(self): 1438 file_path = self.make_path('some_file') 1439 for contents in (b'1\n2', b'1\r\n2', b'1\r2'): 1440 self.create_file(file_path, contents=contents) 1441 with self.open(file_path, mode='r') as f: 1442 self.assertEqual(['1\n', '2'], f.readlines()) 1443 with self.open(file_path, mode='r') as f: 1444 self.assertEqual('1\n2', f.read()) 1445 with self.open(file_path, mode='rb') as f: 1446 self.assertEqual(contents, f.read()) 1447 1448 def test_write_universal_newline_mode(self): 1449 file_path = self.make_path('some_file') 1450 with self.open(file_path, 'w') as f: 1451 f.write('1\n2') 1452 with self.open(file_path, mode='rb') as f: 1453 self.assertEqual(b'1' + self.os.linesep.encode() + b'2', 1454 f.read()) 1455 1456 with self.open(file_path, 'w') as f: 1457 f.write('1\r\n2') 1458 with self.open(file_path, mode='rb') as f: 1459 self.assertEqual(b'1\r' + self.os.linesep.encode() + b'2', 1460 f.read()) 1461 1462 def test_read_with_newline_arg(self): 1463 file_path = self.make_path('some_file') 1464 file_contents = b'1\r\n2\n3\r4' 1465 self.create_file(file_path, contents=file_contents) 1466 with self.open(file_path, mode='r', newline='') as f: 1467 self.assertEqual('1\r\n2\n3\r4', f.read()) 1468 with self.open(file_path, mode='r', newline='\r') as f: 1469 self.assertEqual('1\r\n2\n3\r4', f.read()) 1470 with self.open(file_path, mode='r', newline='\n') as f: 1471 self.assertEqual('1\r\n2\n3\r4', f.read()) 1472 with self.open(file_path, mode='r', newline='\r\n') as f: 1473 self.assertEqual('1\r\n2\n3\r4', f.read()) 1474 1475 def test_readlines_with_newline_arg(self): 1476 file_path = self.make_path('some_file') 1477 file_contents = b'1\r\n2\n3\r4' 1478 self.create_file(file_path, contents=file_contents) 1479 with self.open(file_path, mode='r', newline='') as f: 1480 self.assertEqual(['1\r\n', '2\n', '3\r', '4'], 1481 f.readlines()) 1482 with self.open(file_path, mode='r', newline='\r') as f: 1483 self.assertEqual(['1\r', '\n2\n3\r', '4'], f.readlines()) 1484 with self.open(file_path, mode='r', newline='\n') as f: 1485 self.assertEqual(['1\r\n', '2\n', '3\r4'], f.readlines()) 1486 with self.open(file_path, mode='r', newline='\r\n') as f: 1487 self.assertEqual(['1\r\n', '2\n3\r4'], f.readlines()) 1488 1489 def test_read_with_ignored_universal_newlines_flag(self): 1490 file_path = self.make_path('some_file') 1491 file_contents = b'1\r\n2\n3\r4' 1492 self.create_file(file_path, contents=file_contents) 1493 with self.open(file_path, mode='r', newline='\r') as f: 1494 self.assertEqual('1\r\n2\n3\r4', f.read()) 1495 with self.open(file_path, mode='r', newline='\r') as f: 1496 self.assertEqual('1\r\n2\n3\r4', f.read()) 1497 with self.open(file_path, mode='U', newline='\r') as f: 1498 self.assertEqual('1\r\n2\n3\r4', f.read()) 1499 1500 def test_write_with_newline_arg(self): 1501 file_path = self.make_path('some_file') 1502 with self.open(file_path, 'w', newline='') as f: 1503 f.write('1\r\n2\n3\r4') 1504 with self.open(file_path, mode='rb') as f: 1505 self.assertEqual(b'1\r\n2\n3\r4', f.read()) 1506 1507 with self.open(file_path, 'w', newline='\n') as f: 1508 f.write('1\r\n2\n3\r4') 1509 with self.open(file_path, mode='rb') as f: 1510 self.assertEqual(b'1\r\n2\n3\r4', f.read()) 1511 1512 with self.open(file_path, 'w', newline='\r\n') as f: 1513 f.write('1\r\n2\n3\r4') 1514 with self.open(file_path, mode='rb') as f: 1515 self.assertEqual(b'1\r\r\n2\r\n3\r4', f.read()) 1516 1517 with self.open(file_path, 'w', newline='\r') as f: 1518 f.write('1\r\n2\n3\r4') 1519 with self.open(file_path, mode='rb') as f: 1520 self.assertEqual(b'1\r\r2\r3\r4', f.read()) 1521 1522 def test_binary_readline(self): 1523 file_path = self.make_path('some_file') 1524 file_contents = b'\x80\n\x80\r\x80\r\n\x80' 1525 1526 def chunk_line(): 1527 px = 0 1528 while px < len(file_contents): 1529 ix = file_contents.find(b'\n', px) 1530 if ix == -1: 1531 yield file_contents[px:] 1532 return 1533 yield file_contents[px:ix + 1] 1534 px = ix + 1 1535 1536 chunked_contents = list(chunk_line()) 1537 self.create_file(file_path, contents=file_contents) 1538 with self.open(file_path, mode='rb') as f: 1539 self.assertEqual(chunked_contents, list(f)) 1540 1541 1542class RealFileOpenLineEndingTest(FakeFileOpenLineEndingTest): 1543 def use_real_fs(self): 1544 return True 1545 1546 1547class FakeFileOpenLineEndingWithEncodingTest(FakeFileOpenTestBase): 1548 def setUp(self): 1549 super(FakeFileOpenLineEndingWithEncodingTest, self).setUp() 1550 1551 def test_read_standard_newline_mode(self): 1552 file_path = self.make_path('some_file') 1553 for contents in (u'раз\nдва', u'раз\r\nдва', u'раз\rдва'): 1554 self.create_file(file_path, contents=contents, encoding='cyrillic') 1555 with self.open(file_path, mode='r', 1556 encoding='cyrillic') as fake_file: 1557 self.assertEqual([u'раз\n', u'два'], fake_file.readlines()) 1558 with self.open(file_path, mode='r', 1559 encoding='cyrillic') as fake_file: 1560 self.assertEqual(u'раз\nдва', fake_file.read()) 1561 1562 def test_write_universal_newline_mode(self): 1563 file_path = self.make_path('some_file') 1564 with self.open(file_path, 'w', encoding='cyrillic') as f: 1565 f.write(u'раз\nдва') 1566 with self.open(file_path, mode='rb') as f: 1567 self.assertEqual(u'раз'.encode('cyrillic') + 1568 self.os.linesep.encode() 1569 + u'два'.encode('cyrillic'), f.read()) 1570 1571 with self.open(file_path, 'w', encoding='cyrillic') as f: 1572 f.write(u'раз\r\nдва') 1573 with self.open(file_path, mode='rb') as f: 1574 self.assertEqual(u'раз\r'.encode('cyrillic') + 1575 self.os.linesep.encode() + 1576 u'два'.encode('cyrillic'), f.read()) 1577 1578 def test_read_with_newline_arg(self): 1579 file_path = self.make_path('some_file') 1580 file_contents = u'раз\r\nдва\nтри\rчетыре' 1581 self.create_file(file_path, contents=file_contents, 1582 encoding='cyrillic') 1583 with self.open(file_path, mode='r', newline='', 1584 encoding='cyrillic') as f: 1585 self.assertEqual(u'раз\r\nдва\nтри\rчетыре', f.read()) 1586 with self.open(file_path, mode='r', newline='\r', 1587 encoding='cyrillic') as f: 1588 self.assertEqual(u'раз\r\nдва\nтри\rчетыре', f.read()) 1589 with self.open(file_path, mode='r', newline='\n', 1590 encoding='cyrillic') as f: 1591 self.assertEqual(u'раз\r\nдва\nтри\rчетыре', f.read()) 1592 with self.open(file_path, mode='r', newline='\r\n', 1593 encoding='cyrillic') as f: 1594 self.assertEqual(u'раз\r\nдва\nтри\rчетыре', f.read()) 1595 1596 def test_readlines_with_newline_arg(self): 1597 file_path = self.make_path('some_file') 1598 file_contents = u'раз\r\nдва\nтри\rчетыре' 1599 self.create_file(file_path, contents=file_contents, 1600 encoding='cyrillic') 1601 with self.open(file_path, mode='r', newline='', 1602 encoding='cyrillic') as f: 1603 self.assertEqual([u'раз\r\n', u'два\n', u'три\r', u'четыре'], 1604 f.readlines()) 1605 with self.open(file_path, mode='r', newline='\r', 1606 encoding='cyrillic') as f: 1607 self.assertEqual([u'раз\r', u'\nдва\nтри\r', u'четыре'], 1608 f.readlines()) 1609 with self.open(file_path, mode='r', newline='\n', 1610 encoding='cyrillic') as f: 1611 self.assertEqual([u'раз\r\n', u'два\n', u'три\rчетыре'], 1612 f.readlines()) 1613 with self.open(file_path, mode='r', newline='\r\n', 1614 encoding='cyrillic') as f: 1615 self.assertEqual([u'раз\r\n', u'два\nтри\rчетыре'], 1616 f.readlines()) 1617 1618 def test_write_with_newline_arg(self): 1619 file_path = self.make_path('some_file') 1620 with self.open(file_path, 'w', newline='', 1621 encoding='cyrillic') as f: 1622 f.write(u'раз\r\nдва\nтри\rчетыре') 1623 with self.open(file_path, mode='rb') as f: 1624 self.assertEqual(u'раз\r\nдва\nтри\rчетыре'.encode('cyrillic'), 1625 f.read()) 1626 1627 with self.open(file_path, 'w', newline='\n', 1628 encoding='cyrillic') as f: 1629 f.write('раз\r\nдва\nтри\rчетыре') 1630 with self.open(file_path, mode='rb') as f: 1631 self.assertEqual(u'раз\r\nдва\nтри\rчетыре'.encode('cyrillic'), 1632 f.read()) 1633 1634 with self.open(file_path, 'w', newline='\r\n', 1635 encoding='cyrillic') as f: 1636 f.write('раз\r\nдва\nтри\rчетыре') 1637 with self.open(file_path, mode='rb') as f: 1638 self.assertEqual(u'раз\r\r\nдва\r\nтри\rчетыре'.encode('cyrillic'), 1639 f.read()) 1640 1641 with self.open(file_path, 'w', newline='\r', 1642 encoding='cyrillic') as f: 1643 f.write('раз\r\nдва\nтри\rчетыре') 1644 with self.open(file_path, mode='rb') as f: 1645 self.assertEqual(u'раз\r\rдва\rтри\rчетыре'.encode('cyrillic'), 1646 f.read()) 1647 1648 1649class RealFileOpenLineEndingWithEncodingTest( 1650 FakeFileOpenLineEndingWithEncodingTest): 1651 def use_real_fs(self): 1652 return True 1653 1654 1655class OpenWithFileDescriptorTest(FakeFileOpenTestBase): 1656 def test_open_with_file_descriptor(self): 1657 file_path = self.make_path('this', 'file') 1658 self.create_file(file_path) 1659 fd = self.os.open(file_path, os.O_CREAT) 1660 self.assertEqual(fd, self.open(fd, 'r').fileno()) 1661 1662 def test_closefd_with_file_descriptor(self): 1663 file_path = self.make_path('this', 'file') 1664 self.create_file(file_path) 1665 fd = self.os.open(file_path, os.O_CREAT) 1666 fh = self.open(fd, 'r', closefd=False) 1667 fh.close() 1668 self.assertIsNotNone(self.filesystem.open_files[fd]) 1669 fh = self.open(fd, 'r', closefd=True) 1670 fh.close() 1671 self.assertIsNone(self.filesystem.open_files[fd]) 1672 1673 1674class OpenWithRealFileDescriptorTest(FakeFileOpenTestBase): 1675 def use_real_fs(self): 1676 return True 1677 1678 1679class OpenWithFlagsTestBase(FakeFileOpenTestBase): 1680 def setUp(self): 1681 super(OpenWithFlagsTestBase, self).setUp() 1682 self.file_path = self.make_path('some_file') 1683 self.file_contents = None 1684 1685 def open_file(self, mode): 1686 return self.open(self.file_path, mode=mode) 1687 1688 def open_file_and_seek(self, mode): 1689 fake_file = self.open(self.file_path, mode=mode) 1690 fake_file.seek(0, 2) 1691 return fake_file 1692 1693 def write_and_reopen_file(self, fake_file, mode='r', encoding=None): 1694 fake_file.write(self.file_contents) 1695 fake_file.close() 1696 args = {'mode': mode} 1697 if encoding: 1698 args['encoding'] = encoding 1699 return self.open(self.file_path, **args) 1700 1701 1702class OpenWithBinaryFlagsTest(OpenWithFlagsTestBase): 1703 def setUp(self): 1704 super(OpenWithBinaryFlagsTest, self).setUp() 1705 self.file_contents = b'real binary contents: \x1f\x8b' 1706 self.create_file(self.file_path, contents=self.file_contents) 1707 1708 def test_read_binary(self): 1709 with self.open_file('rb') as fake_file: 1710 self.assertEqual(self.file_contents, fake_file.read()) 1711 1712 def test_write_binary(self): 1713 with self.open_file_and_seek('wb') as f: 1714 self.assertEqual(0, f.tell()) 1715 with self.write_and_reopen_file(f, mode='rb') as f1: 1716 self.assertEqual(self.file_contents, f1.read()) 1717 # Attempt to reopen the file in text mode 1718 with self.open_file('wb') as f2: 1719 with self.write_and_reopen_file(f2, mode='r', 1720 encoding='ascii') as f3: 1721 with self.assertRaises(UnicodeDecodeError): 1722 f3.read() 1723 1724 def test_write_and_read_binary(self): 1725 with self.open_file_and_seek('w+b') as f: 1726 self.assertEqual(0, f.tell()) 1727 with self.write_and_reopen_file(f, mode='rb') as f1: 1728 self.assertEqual(self.file_contents, f1.read()) 1729 1730 1731class RealOpenWithBinaryFlagsTest(OpenWithBinaryFlagsTest): 1732 def use_real_fs(self): 1733 return True 1734 1735 1736class OpenWithTextModeFlagsTest(OpenWithFlagsTestBase): 1737 def setUp(self): 1738 super(OpenWithTextModeFlagsTest, self).setUp() 1739 self.setUpFileSystem() 1740 1741 def setUpFileSystem(self): 1742 self.file_path = self.make_path('some_file') 1743 self.file_contents = b'two\r\nlines' 1744 self.original_contents = 'two\r\nlines' 1745 self.converted_contents = 'two\nlines' 1746 self.create_file(self.file_path, contents=self.file_contents) 1747 1748 def test_read_text(self): 1749 """Test that text mode flag is ignored""" 1750 self.check_windows_only() 1751 with self.open_file('r') as f: 1752 self.assertEqual(self.converted_contents, f.read()) 1753 with self.open_file('rt') as f: 1754 self.assertEqual(self.converted_contents, f.read()) 1755 1756 def test_mixed_text_and_binary_flags(self): 1757 with self.assertRaises(ValueError): 1758 self.open_file_and_seek('w+bt') 1759 1760 1761class RealOpenWithTextModeFlagsTest(OpenWithTextModeFlagsTest): 1762 def use_real_fs(self): 1763 return True 1764 1765 1766class OpenWithInvalidFlagsTest(FakeFileOpenTestBase): 1767 def test_capital_r(self): 1768 with self.assertRaises(ValueError): 1769 self.open('some_file', 'R') 1770 1771 def test_capital_w(self): 1772 with self.assertRaises(ValueError): 1773 self.open('some_file', 'W') 1774 1775 def test_capital_a(self): 1776 with self.assertRaises(ValueError): 1777 self.open('some_file', 'A') 1778 1779 def test_lower_u(self): 1780 with self.assertRaises(ValueError): 1781 self.open('some_file', 'u') 1782 1783 def test_lower_rw(self): 1784 with self.assertRaises(ValueError): 1785 self.open('some_file', 'rw') 1786 1787 1788class OpenWithInvalidFlagsRealFsTest(OpenWithInvalidFlagsTest): 1789 def use_real_fs(self): 1790 return True 1791 1792 1793class ResolvePathTest(FakeFileOpenTestBase): 1794 def write_to_file(self, file_name): 1795 with self.open(file_name, 'w') as fh: 1796 fh.write('x') 1797 1798 def test_none_filepath_raises_type_error(self): 1799 with self.assertRaises(TypeError): 1800 self.open(None, 'w') 1801 1802 def test_empty_filepath_raises_io_error(self): 1803 with self.assertRaises(OSError): 1804 self.open('', 'w') 1805 1806 def test_normal_path(self): 1807 file_path = self.make_path('foo') 1808 self.write_to_file(file_path) 1809 self.assertTrue(self.os.path.exists(file_path)) 1810 1811 def test_link_within_same_directory(self): 1812 self.skip_if_symlink_not_supported() 1813 final_target = self.make_path('foo', 'baz') 1814 link_path = self.make_path('foo', 'bar') 1815 self.create_symlink(link_path, 'baz') 1816 self.write_to_file(link_path) 1817 self.assertTrue(self.os.path.exists(final_target)) 1818 self.assertEqual(1, self.os.stat(final_target)[stat.ST_SIZE]) 1819 1820 def test_link_to_sub_directory(self): 1821 self.skip_if_symlink_not_supported() 1822 final_target = self.make_path('foo', 'baz', 'bip') 1823 dir_path = self.make_path('foo', 'baz') 1824 self.create_dir(dir_path) 1825 link_path = self.make_path('foo', 'bar') 1826 target_path = self.os.path.join('baz', 'bip') 1827 self.create_symlink(link_path, target_path) 1828 self.write_to_file(link_path) 1829 self.assertTrue(self.os.path.exists(final_target)) 1830 self.assertEqual(1, self.os.stat(final_target)[stat.ST_SIZE]) 1831 self.assertTrue(self.os.path.exists(dir_path)) 1832 # Make sure that intermediate directory got created. 1833 self.assertTrue(self.os.stat(dir_path)[stat.ST_MODE] & stat.S_IFDIR) 1834 1835 def test_link_to_parent_directory(self): 1836 self.skip_if_symlink_not_supported() 1837 final_target = self.make_path('baz', 'bip') 1838 self.create_dir(self.make_path('foo')) 1839 self.create_dir(self.make_path('baz')) 1840 link_path = self.make_path('foo', 'bar') 1841 self.create_symlink(link_path, self.os.path.join('..', 'baz')) 1842 self.write_to_file(self.make_path('foo', 'bar', 'bip')) 1843 self.assertTrue(self.os.path.exists(final_target)) 1844 self.assertEqual(1, self.os.stat(final_target)[stat.ST_SIZE]) 1845 self.assertTrue(self.os.path.exists(link_path)) 1846 1847 def test_link_to_absolute_path(self): 1848 self.skip_if_symlink_not_supported() 1849 final_target = self.make_path('foo', 'baz', 'bip') 1850 self.create_dir(self.make_path('foo', 'baz')) 1851 link_path = self.make_path('foo', 'bar') 1852 self.create_symlink(link_path, final_target) 1853 self.write_to_file(link_path) 1854 self.assertTrue(self.os.path.exists(final_target)) 1855 1856 def test_relative_links_work_after_chdir(self): 1857 self.skip_if_symlink_not_supported() 1858 final_target = self.make_path('foo', 'baz', 'bip') 1859 self.create_dir(self.make_path('foo', 'baz')) 1860 link_path = self.make_path('foo', 'bar') 1861 self.create_symlink(link_path, self.os.path.join('.', 'baz', 'bip')) 1862 if not self.is_windows: 1863 self.assert_equal_paths( 1864 final_target, self.os.path.realpath(link_path)) 1865 1866 self.assertTrue(self.os.path.islink(link_path)) 1867 self.os.chdir(self.make_path('foo')) 1868 self.assert_equal_paths(self.make_path('foo'), self.os.getcwd()) 1869 self.assertTrue(self.os.path.islink('bar')) 1870 if not self.is_windows: 1871 self.assert_equal_paths(final_target, self.os.path.realpath('bar')) 1872 1873 self.write_to_file(link_path) 1874 self.assertTrue(self.os.path.exists(final_target)) 1875 1876 def test_absolute_links_work_after_chdir(self): 1877 self.skip_if_symlink_not_supported() 1878 final_target = self.make_path('foo', 'baz', 'bip') 1879 self.create_dir(self.make_path('foo', 'baz')) 1880 link_path = self.make_path('foo', 'bar') 1881 self.create_symlink(link_path, final_target) 1882 if not self.is_windows: 1883 self.assert_equal_paths( 1884 final_target, self.os.path.realpath(link_path)) 1885 1886 self.assertTrue(self.os.path.islink(link_path)) 1887 self.os.chdir(self.make_path('foo')) 1888 self.assert_equal_paths(self.make_path('foo'), self.os.getcwd()) 1889 self.assertTrue(self.os.path.islink('bar')) 1890 if not self.is_windows: 1891 self.assert_equal_paths(final_target, self.os.path.realpath('bar')) 1892 1893 self.write_to_file(link_path) 1894 self.assertTrue(self.os.path.exists(final_target)) 1895 1896 def test_chdir_through_relative_link(self): 1897 self.check_posix_only() 1898 dir1_path = self.make_path('x', 'foo') 1899 dir2_path = self.make_path('x', 'bar') 1900 self.create_dir(dir1_path) 1901 self.create_dir(dir2_path) 1902 link_path = self.make_path('x', 'foo', 'bar') 1903 self.create_symlink(link_path, 1904 self.os.path.join('..', 'bar')) 1905 self.assert_equal_paths(dir2_path, self.os.path.realpath(link_path)) 1906 1907 self.os.chdir(dir1_path) 1908 self.assert_equal_paths(dir1_path, self.os.getcwd()) 1909 self.assert_equal_paths(dir2_path, self.os.path.realpath('bar')) 1910 1911 self.os.chdir('bar') 1912 self.assert_equal_paths(dir2_path, self.os.getcwd()) 1913 1914 def test_chdir_uses_open_fd_as_path(self): 1915 self.check_posix_only() 1916 if self.is_pypy: 1917 # unclear behavior with PyPi 1918 self.skip_real_fs() 1919 self.assert_raises_os_error( 1920 [errno.ENOTDIR, errno.EBADF], self.os.chdir, 500) 1921 dir_path = self.make_path('foo', 'bar') 1922 self.create_dir(dir_path) 1923 1924 path_des = self.os.open(dir_path, os.O_RDONLY) 1925 self.os.chdir(path_des) 1926 self.os.close(path_des) 1927 self.assert_equal_paths(dir_path, self.os.getcwd()) 1928 1929 def test_read_link_to_link(self): 1930 # Write into the final link target and read back from a file which will 1931 # point to that. 1932 self.skip_if_symlink_not_supported() 1933 link_path = self.make_path('foo', 'bar') 1934 self.create_symlink(link_path, 'link') 1935 self.create_symlink(self.make_path('foo', 'link'), 'baz') 1936 self.write_to_file(self.make_path('foo', 'baz')) 1937 fh = self.open(link_path, 'r') 1938 self.assertEqual('x', fh.read()) 1939 1940 def test_write_link_to_link(self): 1941 self.skip_if_symlink_not_supported() 1942 final_target = self.make_path('foo', 'baz') 1943 link_path = self.make_path('foo', 'bar') 1944 self.create_symlink(link_path, 'link') 1945 self.create_symlink(self.make_path('foo', 'link'), 'baz') 1946 self.write_to_file(link_path) 1947 self.assertTrue(self.os.path.exists(final_target)) 1948 1949 def test_multiple_links(self): 1950 self.skip_if_symlink_not_supported() 1951 self.os.makedirs(self.make_path('a', 'link1', 'c', 'link2')) 1952 1953 self.create_symlink(self.make_path('a', 'b'), 'link1') 1954 1955 if not self.is_windows: 1956 self.assert_equal_paths(self.make_path('a', 'link1'), 1957 self.os.path.realpath( 1958 self.make_path('a', 'b'))) 1959 self.assert_equal_paths(self.make_path('a', 'link1', 'c'), 1960 self.os.path.realpath( 1961 self.make_path('a', 'b', 'c'))) 1962 1963 link_path = self.make_path('a', 'link1', 'c', 'd') 1964 self.create_symlink(link_path, 'link2') 1965 self.assertTrue(self.os.path.exists(link_path)) 1966 self.assertTrue(self.os.path.exists( 1967 self.make_path('a', 'b', 'c', 'd'))) 1968 1969 final_target = self.make_path('a', 'link1', 'c', 'link2', 'e') 1970 self.assertFalse(self.os.path.exists(final_target)) 1971 self.write_to_file(self.make_path('a', 'b', 'c', 'd', 'e')) 1972 self.assertTrue(self.os.path.exists(final_target)) 1973 1974 def test_utime_link(self): 1975 """os.utime() and os.stat() via symbolic link (issue #49)""" 1976 self.skip_if_symlink_not_supported() 1977 self.create_dir(self.make_path('foo', 'baz')) 1978 target_path = self.make_path('foo', 'baz', 'bip') 1979 self.write_to_file(target_path) 1980 link_name = self.make_path('foo', 'bar') 1981 self.create_symlink(link_name, target_path) 1982 1983 self.os.utime(link_name, (1, 2)) 1984 st = self.os.stat(link_name) 1985 self.assertEqual(1, st.st_atime) 1986 self.assertEqual(2, st.st_mtime) 1987 self.os.utime(link_name, (3, 4)) 1988 st = self.os.stat(link_name) 1989 self.assertEqual(3, st.st_atime) 1990 self.assertEqual(4, st.st_mtime) 1991 1992 def test_too_many_links(self): 1993 self.check_posix_only() 1994 link_path = self.make_path('a', 'loop') 1995 self.create_symlink(link_path, 'loop') 1996 self.assertFalse(self.os.path.exists(link_path)) 1997 1998 def test_that_drive_letters_are_preserved(self): 1999 self.check_windows_only() 2000 self.skip_real_fs() 2001 self.assertEqual('C:!foo!bar', 2002 self.filesystem.resolve_path('C:!foo!!bar')) 2003 2004 def test_that_unc_paths_are_preserved(self): 2005 self.check_windows_only() 2006 self.skip_real_fs() 2007 self.assertEqual('!!foo!bar!baz', 2008 self.filesystem.resolve_path('!!foo!bar!baz!!')) 2009 2010 2011class RealResolvePathTest(ResolvePathTest): 2012 def use_real_fs(self): 2013 return True 2014 2015 2016if __name__ == '__main__': 2017 unittest.main() 2018