1 """Tests for distutils.file_util.""" 2 import unittest 3 import os 4 import errno 5 from unittest.mock import patch 6 7 from distutils.file_util import move_file, copy_file 8 from distutils import log 9 from distutils.tests import support 10 from distutils.errors import DistutilsFileError 11 from test.support import run_unittest 12 13 class FileUtilTestCase(support.TempdirManager, unittest.TestCase): 14 15 def _log(self, msg, *args): 16 if len(args) > 0: 17 self._logs.append(msg % args) 18 else: 19 self._logs.append(msg) 20 21 def setUp(self): 22 super(FileUtilTestCase, self).setUp() 23 self._logs = [] 24 self.old_log = log.info 25 log.info = self._log 26 tmp_dir = self.mkdtemp() 27 self.source = os.path.join(tmp_dir, 'f1') 28 self.target = os.path.join(tmp_dir, 'f2') 29 self.target_dir = os.path.join(tmp_dir, 'd1') 30 31 def tearDown(self): 32 log.info = self.old_log 33 super(FileUtilTestCase, self).tearDown() 34 35 def test_move_file_verbosity(self): 36 f = open(self.source, 'w') 37 try: 38 f.write('some content') 39 finally: 40 f.close() 41 42 move_file(self.source, self.target, verbose=0) 43 wanted = [] 44 self.assertEqual(self._logs, wanted) 45 46 # back to original state 47 move_file(self.target, self.source, verbose=0) 48 49 move_file(self.source, self.target, verbose=1) 50 wanted = ['moving %s -> %s' % (self.source, self.target)] 51 self.assertEqual(self._logs, wanted) 52 53 # back to original state 54 move_file(self.target, self.source, verbose=0) 55 56 self._logs = [] 57 # now the target is a dir 58 os.mkdir(self.target_dir) 59 move_file(self.source, self.target_dir, verbose=1) 60 wanted = ['moving %s -> %s' % (self.source, self.target_dir)] 61 self.assertEqual(self._logs, wanted) 62 63 def test_move_file_exception_unpacking_rename(self): 64 # see issue 22182 65 with patch("os.rename", side_effect=OSError("wrong", 1)), \ 66 self.assertRaises(DistutilsFileError): 67 with open(self.source, 'w') as fobj: 68 fobj.write('spam eggs') 69 move_file(self.source, self.target, verbose=0) 70 71 def test_move_file_exception_unpacking_unlink(self): 72 # see issue 22182 73 with patch("os.rename", side_effect=OSError(errno.EXDEV, "wrong")), \ 74 patch("os.unlink", side_effect=OSError("wrong", 1)), \ 75 self.assertRaises(DistutilsFileError): 76 with open(self.source, 'w') as fobj: 77 fobj.write('spam eggs') 78 move_file(self.source, self.target, verbose=0) 79 80 def test_copy_file_hard_link(self): 81 with open(self.source, 'w') as f: 82 f.write('some content') 83 st = os.stat(self.source) 84 copy_file(self.source, self.target, link='hard') 85 st2 = os.stat(self.source) 86 st3 = os.stat(self.target) 87 self.assertTrue(os.path.samestat(st, st2), (st, st2)) 88 self.assertTrue(os.path.samestat(st2, st3), (st2, st3)) 89 with open(self.source, 'r') as f: 90 self.assertEqual(f.read(), 'some content') 91 92 def test_copy_file_hard_link_failure(self): 93 # If hard linking fails, copy_file() falls back on copying file 94 # (some special filesystems don't support hard linking even under 95 # Unix, see issue #8876). 96 with open(self.source, 'w') as f: 97 f.write('some content') 98 st = os.stat(self.source) 99 with patch("os.link", side_effect=OSError(0, "linking unsupported")): 100 copy_file(self.source, self.target, link='hard') 101 st2 = os.stat(self.source) 102 st3 = os.stat(self.target) 103 self.assertTrue(os.path.samestat(st, st2), (st, st2)) 104 self.assertFalse(os.path.samestat(st2, st3), (st2, st3)) 105 for fn in (self.source, self.target): 106 with open(fn, 'r') as f: 107 self.assertEqual(f.read(), 'some content') 108 109 110 def test_suite(): 111 return unittest.makeSuite(FileUtilTestCase) 112 113 if __name__ == "__main__": 114 run_unittest(test_suite()) 115