~bzr-pqm/bzr/bzr.dev

1755.3.6 by John Arbash Meinel
Add a test suite for Atomic File, and clean it up so that it really does set the mode properly.
1
# Copyright (C) 2006 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Basic tests for AtomicFile"""
18
19
import os
20
import stat
21
import sys
22
23
from bzrlib import (
24
    atomicfile,
25
    errors,
1755.3.9 by John Arbash Meinel
Make AtomicFile not do anything if not supplied a mode, clean up LocalTransport now that we do the right thing for None
26
    osutils,
1755.3.11 by John Arbash Meinel
Test that AtomicFile.closed is supported, but deprecated
27
    symbol_versioning,
1755.3.6 by John Arbash Meinel
Add a test suite for Atomic File, and clean it up so that it really does set the mode properly.
28
    )
1982.1.1 by Alexander Belchenko
Explicitly skip tests with file attribute manipulations instead of silently pass
29
from bzrlib.tests import TestCaseInTempDir, TestSkipped
1755.3.6 by John Arbash Meinel
Add a test suite for Atomic File, and clean it up so that it really does set the mode properly.
30
31
32
class TestAtomicFile(TestCaseInTempDir):
33
34
    def test_commit(self):
35
        f = atomicfile.AtomicFile('test')
36
        self.failIfExists('test')
37
        f.write('foo\n')
38
        f.commit()
39
40
        self.assertEqual(['test'], os.listdir('.'))
41
        self.check_file_contents('test', 'foo\n')
42
        self.assertRaises(errors.AtomicFileAlreadyClosed, f.commit)
43
        self.assertRaises(errors.AtomicFileAlreadyClosed, f.abort)
44
        # close is re-entrant safe
45
        f.close()
46
47
    def test_abort(self):
48
        f = atomicfile.AtomicFile('test')
49
        f.write('foo\n')
50
        f.abort()
51
        self.assertEqual([], os.listdir('.'))
52
53
        self.assertRaises(errors.AtomicFileAlreadyClosed, f.abort)
54
        self.assertRaises(errors.AtomicFileAlreadyClosed, f.commit)
55
56
        # close is re-entrant safe
57
        f.close()
58
59
    def test_close(self):
60
        f = atomicfile.AtomicFile('test')
61
        f.write('foo\n')
62
        # close on an open file is an abort
63
        f.close()
64
        self.assertEqual([], os.listdir('.'))
65
66
        self.assertRaises(errors.AtomicFileAlreadyClosed, f.abort)
67
        self.assertRaises(errors.AtomicFileAlreadyClosed, f.commit)
68
69
        # close is re-entrant safe
70
        f.close()
71
        
72
    def test_text_mode(self):
73
        f = atomicfile.AtomicFile('test', mode='wt')
74
        f.write('foo\n')
75
        f.commit()
76
77
        contents = open('test', 'rb').read()
78
        if sys.platform == 'win32':
79
            self.assertEqual('foo\r\n', contents)
80
        else:
81
            self.assertEqual('foo\n', contents)
82
83
    def can_sys_preserve_mode(self):
84
        # PLATFORM DEFICIENCY/ TestSkipped
85
        return sys.platform not in ('win32',)
86
87
    def _test_mode(self, mode):
88
        if not self.can_sys_preserve_mode():
1982.1.1 by Alexander Belchenko
Explicitly skip tests with file attribute manipulations instead of silently pass
89
            raise TestSkipped("This test cannot be run on your platform")
1755.3.9 by John Arbash Meinel
Make AtomicFile not do anything if not supplied a mode, clean up LocalTransport now that we do the right thing for None
90
        f = atomicfile.AtomicFile('test', mode='wb', new_mode=mode)
1755.3.6 by John Arbash Meinel
Add a test suite for Atomic File, and clean it up so that it really does set the mode properly.
91
        f.write('foo\n')
92
        f.commit()
93
        st = os.lstat('test')
94
        self.assertEqualMode(mode, stat.S_IMODE(st.st_mode))
95
96
    def test_mode_0666(self):
97
        self._test_mode(0666)
98
99
    def test_mode_0664(self):
100
        self._test_mode(0664)
101
102
    def test_mode_0660(self):
103
        self._test_mode(0660)
104
105
    def test_mode_0660(self):
106
        self._test_mode(0660)
107
108
    def test_mode_0640(self):
109
        self._test_mode(0640)
110
111
    def test_mode_0600(self):
112
        self._test_mode(0600)
113
114
    def test_mode_0400(self):
115
        self._test_mode(0400)
116
        # Make it read-write again so cleanup doesn't complain
117
        os.chmod('test', 0600)
1755.3.9 by John Arbash Meinel
Make AtomicFile not do anything if not supplied a mode, clean up LocalTransport now that we do the right thing for None
118
119
    def test_no_mode(self):
120
        # The default file permissions should be based on umask
121
        umask = osutils.get_umask()
122
        f = atomicfile.AtomicFile('test', mode='wb')
123
        f.write('foo\n')
124
        f.commit()
125
        st = os.lstat('test')
126
        self.assertEqualMode(0666 & ~umask, stat.S_IMODE(st.st_mode))
1755.3.11 by John Arbash Meinel
Test that AtomicFile.closed is supported, but deprecated
127
128
    def test_closed(self):
129
        local_warnings = []
130
        def capture_warnings(msg, cls, stacklevel=None):
131
            self.assertEqual(cls, DeprecationWarning)
132
            local_warnings.append(msg)
133
134
        method = symbol_versioning.warn
135
        try:
136
            symbol_versioning.set_warning_method(capture_warnings)
137
            f = atomicfile.AtomicFile('test', mode='wb')
138
            self.assertEqual(False, f.closed)
139
            f.abort()
140
            self.assertEqual(True, f.closed)
141
142
            f = atomicfile.AtomicFile('test', mode='wb')
143
            f.close()
144
            self.assertEqual(True, f.closed)
145
146
            f = atomicfile.AtomicFile('test', mode='wb')
147
            f.commit()
148
            self.assertEqual(True, f.closed)
149
        finally:
150
            symbol_versioning.set_warning_method(method)
151
152
        txt = 'AtomicFile.closed deprecated in bzr 0.10'
153
        self.assertEqual([txt]*4, local_warnings)