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.os_helper import unlink
      12  
      13  
      14  class ESC[4;38;5;81mFileUtilTestCase(ESC[4;38;5;149msupportESC[4;38;5;149m.ESC[4;38;5;149mTempdirManager, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      15  
      16      def _log(self, msg, *args):
      17          if len(args) > 0:
      18              self._logs.append(msg % args)
      19          else:
      20              self._logs.append(msg)
      21  
      22      def setUp(self):
      23          super(FileUtilTestCase, self).setUp()
      24          self._logs = []
      25          self.old_log = log.info
      26          log.info = self._log
      27          tmp_dir = self.mkdtemp()
      28          self.source = os.path.join(tmp_dir, 'f1')
      29          self.target = os.path.join(tmp_dir, 'f2')
      30          self.target_dir = os.path.join(tmp_dir, 'd1')
      31  
      32      def tearDown(self):
      33          log.info = self.old_log
      34          super(FileUtilTestCase, self).tearDown()
      35  
      36      def test_move_file_verbosity(self):
      37          f = open(self.source, 'w')
      38          try:
      39              f.write('some content')
      40          finally:
      41              f.close()
      42  
      43          move_file(self.source, self.target, verbose=0)
      44          wanted = []
      45          self.assertEqual(self._logs, wanted)
      46  
      47          # back to original state
      48          move_file(self.target, self.source, verbose=0)
      49  
      50          move_file(self.source, self.target, verbose=1)
      51          wanted = ['moving %s -> %s' % (self.source, self.target)]
      52          self.assertEqual(self._logs, wanted)
      53  
      54          # back to original state
      55          move_file(self.target, self.source, verbose=0)
      56  
      57          self._logs = []
      58          # now the target is a dir
      59          os.mkdir(self.target_dir)
      60          move_file(self.source, self.target_dir, verbose=1)
      61          wanted = ['moving %s -> %s' % (self.source, self.target_dir)]
      62          self.assertEqual(self._logs, wanted)
      63  
      64      def test_move_file_exception_unpacking_rename(self):
      65          # see issue 22182
      66          with patch("os.rename", side_effect=OSError("wrong", 1)), \
      67               self.assertRaises(DistutilsFileError):
      68              with open(self.source, 'w') as fobj:
      69                  fobj.write('spam eggs')
      70              move_file(self.source, self.target, verbose=0)
      71  
      72      def test_move_file_exception_unpacking_unlink(self):
      73          # see issue 22182
      74          with patch("os.rename", side_effect=OSError(errno.EXDEV, "wrong")), \
      75               patch("os.unlink", side_effect=OSError("wrong", 1)), \
      76               self.assertRaises(DistutilsFileError):
      77              with open(self.source, 'w') as fobj:
      78                  fobj.write('spam eggs')
      79              move_file(self.source, self.target, verbose=0)
      80  
      81      @unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
      82      def test_copy_file_hard_link(self):
      83          with open(self.source, 'w') as f:
      84              f.write('some content')
      85          # Check first that copy_file() will not fall back on copying the file
      86          # instead of creating the hard link.
      87          try:
      88              os.link(self.source, self.target)
      89          except OSError as e:
      90              self.skipTest('os.link: %s' % e)
      91          else:
      92              unlink(self.target)
      93          st = os.stat(self.source)
      94          copy_file(self.source, self.target, link='hard')
      95          st2 = os.stat(self.source)
      96          st3 = os.stat(self.target)
      97          self.assertTrue(os.path.samestat(st, st2), (st, st2))
      98          self.assertTrue(os.path.samestat(st2, st3), (st2, st3))
      99          with open(self.source, 'r') as f:
     100              self.assertEqual(f.read(), 'some content')
     101  
     102      @unittest.skipUnless(hasattr(os, 'link'), 'requires os.link')
     103      def test_copy_file_hard_link_failure(self):
     104          # If hard linking fails, copy_file() falls back on copying file
     105          # (some special filesystems don't support hard linking even under
     106          #  Unix, see issue #8876).
     107          with open(self.source, 'w') as f:
     108              f.write('some content')
     109          st = os.stat(self.source)
     110          with patch("os.link", side_effect=OSError(0, "linking unsupported")):
     111              copy_file(self.source, self.target, link='hard')
     112          st2 = os.stat(self.source)
     113          st3 = os.stat(self.target)
     114          self.assertTrue(os.path.samestat(st, st2), (st, st2))
     115          self.assertFalse(os.path.samestat(st2, st3), (st2, st3))
     116          for fn in (self.source, self.target):
     117              with open(fn, 'r') as f:
     118                  self.assertEqual(f.read(), 'some content')
     119  
     120  
     121  if __name__ == "__main__":
     122      unittest.main()