~bzr-pqm/bzr/bzr.dev

1553.5.42 by Martin Pool
Start to parameterize LockableFiles test cases.
1
# Copyright (C) 2005, 2006 by Canonical Ltd
1185.67.4 by Aaron Bentley
Throw if we try to write to a LockableFiles with no write lock
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
1185.70.2 by Martin Pool
Fix funny mistake
17
from StringIO import StringIO
18
19
from bzrlib.branch import Branch
1185.65.29 by Robert Collins
Implement final review suggestions.
20
from bzrlib.errors import BzrBadParameterNotString, NoSuchFile, ReadOnlyError
1553.5.63 by Martin Pool
Lock type is now mandatory for LockableFiles constructor
21
from bzrlib.lockable_files import LockableFiles, TransportLock
1553.5.44 by Martin Pool
LockableFiles can now call LockDir directly
22
from bzrlib.lockdir import LockDir
1185.67.4 by Aaron Bentley
Throw if we try to write to a LockableFiles with no write lock
23
from bzrlib.tests import TestCaseInTempDir
1594.2.22 by Robert Collins
Ensure that lockable files calls finish() on transactions.:
24
from bzrlib.tests.test_transactions import DummyWeave
1563.2.34 by Robert Collins
Remove the commit and rollback transaction methods as misleading, and implement a WriteTransaction
25
from bzrlib.transactions import (PassThroughTransaction,
26
                                 ReadOnlyTransaction,
27
                                 WriteTransaction,
28
                                 )
1185.67.4 by Aaron Bentley
Throw if we try to write to a LockableFiles with no write lock
29
from bzrlib.transport import get_transport
1185.65.23 by Robert Collins
update tests somewhat
30
1553.5.42 by Martin Pool
Start to parameterize LockableFiles test cases.
31
32
# these tests are applied in each parameterized suite for LockableFiles
33
class _TestLockableFiles_mixin(object):
1185.67.4 by Aaron Bentley
Throw if we try to write to a LockableFiles with no write lock
34
1185.67.6 by Aaron Bentley
Added tests and fixes for LockableFiles.put_utf8(); imported IterableFile
35
    def test_read_write(self):
1185.65.29 by Robert Collins
Implement final review suggestions.
36
        self.assertRaises(NoSuchFile, self.lockable.get, 'foo')
37
        self.assertRaises(NoSuchFile, self.lockable.get_utf8, 'foo')
1185.67.6 by Aaron Bentley
Added tests and fixes for LockableFiles.put_utf8(); imported IterableFile
38
        self.lockable.lock_write()
39
        try:
40
            unicode_string = u'bar\u1234'
41
            self.assertEqual(4, len(unicode_string))
42
            byte_string = unicode_string.encode('utf-8')
43
            self.assertEqual(6, len(byte_string))
44
            self.assertRaises(UnicodeEncodeError, self.lockable.put, 'foo', 
45
                              StringIO(unicode_string))
46
            self.lockable.put('foo', StringIO(byte_string))
47
            self.assertEqual(byte_string,
1185.65.29 by Robert Collins
Implement final review suggestions.
48
                             self.lockable.get('foo').read())
1185.67.6 by Aaron Bentley
Added tests and fixes for LockableFiles.put_utf8(); imported IterableFile
49
            self.assertEqual(unicode_string,
1185.65.29 by Robert Collins
Implement final review suggestions.
50
                             self.lockable.get_utf8('foo').read())
51
            self.assertRaises(BzrBadParameterNotString,
52
                              self.lockable.put_utf8,
53
                              'bar',
54
                              StringIO(unicode_string)
55
                              )
56
            self.lockable.put_utf8('bar', unicode_string)
1185.67.6 by Aaron Bentley
Added tests and fixes for LockableFiles.put_utf8(); imported IterableFile
57
            self.assertEqual(unicode_string, 
1185.65.29 by Robert Collins
Implement final review suggestions.
58
                             self.lockable.get_utf8('bar').read())
1185.67.6 by Aaron Bentley
Added tests and fixes for LockableFiles.put_utf8(); imported IterableFile
59
            self.assertEqual(byte_string, 
1185.65.29 by Robert Collins
Implement final review suggestions.
60
                             self.lockable.get('bar').read())
1185.67.6 by Aaron Bentley
Added tests and fixes for LockableFiles.put_utf8(); imported IterableFile
61
        finally:
62
            self.lockable.unlock()
63
1185.67.4 by Aaron Bentley
Throw if we try to write to a LockableFiles with no write lock
64
    def test_locks(self):
1185.67.8 by Aaron Bentley
Test and fix read locks
65
        self.lockable.lock_read()
1185.65.27 by Robert Collins
Tweak storage towards mergability.
66
        try:
67
            self.assertRaises(ReadOnlyError, self.lockable.put, 'foo', 
68
                              StringIO('bar\u1234'))
69
        finally:
70
            self.lockable.unlock()
1185.68.1 by Aaron Bentley
test transactions
71
72
    def test_transactions(self):
73
        self.assertIs(self.lockable.get_transaction().__class__,
74
                      PassThroughTransaction)
75
        self.lockable.lock_read()
76
        try:
77
            self.assertIs(self.lockable.get_transaction().__class__,
78
                          ReadOnlyTransaction)
79
        finally:
80
            self.lockable.unlock()
81
        self.assertIs(self.lockable.get_transaction().__class__,
82
                      PassThroughTransaction)
83
        self.lockable.lock_write()
84
        self.assertIs(self.lockable.get_transaction().__class__,
1563.2.34 by Robert Collins
Remove the commit and rollback transaction methods as misleading, and implement a WriteTransaction
85
                      WriteTransaction)
1594.2.22 by Robert Collins
Ensure that lockable files calls finish() on transactions.:
86
        # check that finish is called:
87
        vf = DummyWeave('a')
88
        self.lockable.get_transaction().register_dirty(vf)
1185.68.1 by Aaron Bentley
test transactions
89
        self.lockable.unlock()
1594.2.22 by Robert Collins
Ensure that lockable files calls finish() on transactions.:
90
        self.assertTrue(vf.finished)
1185.65.23 by Robert Collins
update tests somewhat
91
92
    def test__escape(self):
93
        self.assertEqual('%25', self.lockable._escape('%'))
94
        
95
    def test__escape_empty(self):
96
        self.assertEqual('', self.lockable._escape(''))
97
1553.5.42 by Martin Pool
Start to parameterize LockableFiles test cases.
98
99
# This method of adapting tests to parameters is different to 
100
# the TestProviderAdapters used elsewhere, but seems simpler for this 
101
# case.  
1553.5.45 by Martin Pool
Clean up Transport-based locks for old branches
102
class TestLockableFiles_TransportLock(TestCaseInTempDir,
103
                                      _TestLockableFiles_mixin):
1553.5.42 by Martin Pool
Start to parameterize LockableFiles test cases.
104
105
    def setUp(self):
1553.5.45 by Martin Pool
Clean up Transport-based locks for old branches
106
        super(TestLockableFiles_TransportLock, self).setUp()
1553.5.42 by Martin Pool
Start to parameterize LockableFiles test cases.
107
        transport = get_transport('.')
108
        transport.mkdir('.bzr')
1553.5.43 by Martin Pool
Get LockableFiles tests running against LockDir
109
        sub_transport = transport.clone('.bzr')
1553.5.63 by Martin Pool
Lock type is now mandatory for LockableFiles constructor
110
        self.lockable = LockableFiles(sub_transport, 'my-lock', TransportLock)
1553.5.61 by Martin Pool
Locks protecting LockableFiles must now be explicitly created before use.
111
        self.lockable.create_lock()
1553.5.43 by Martin Pool
Get LockableFiles tests running against LockDir
112
        
113
114
class TestLockableFiles_LockDir(TestCaseInTempDir,
115
                              _TestLockableFiles_mixin):
116
    """LockableFile tests run with LockDir underneath"""
117
118
    def setUp(self):
119
        super(TestLockableFiles_LockDir, self).setUp()
1553.5.61 by Martin Pool
Locks protecting LockableFiles must now be explicitly created before use.
120
        self.transport = get_transport('.')
121
        self.lockable = LockableFiles(self.transport, 'my-lock', LockDir)
122
        self.lockable.create_lock()
1553.5.43 by Martin Pool
Get LockableFiles tests running against LockDir
123
124
    def test_lock_is_lockdir(self):
125
        """Created instance should use a LockDir.
126
        
127
        This primarily tests the mixin adapter works properly.
128
        """
129
        ## self.assertIsInstance(self.lockable, LockableFiles)
130
        ## self.assertIsInstance(self.lockable._lock_strategy,
131
                              ## LockDirStrategy)
1553.5.60 by Martin Pool
New LockableFiles.create_lock() method
132
133
    def test_lock_created(self):
1553.5.61 by Martin Pool
Locks protecting LockableFiles must now be explicitly created before use.
134
        self.assertTrue(self.transport.has('my-lock'))
135
        self.lockable.lock_write()
136
        self.assertTrue(self.transport.has('my-lock/held/info'))
137
        self.lockable.unlock()
138
        self.assertFalse(self.transport.has('my-lock/held/info'))
139
        self.assertTrue(self.transport.has('my-lock'))
140
141
142
    # TODO: Test the lockdir inherits the right file and directory permissions
143
    # from the LockableFiles.