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