/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/tests/test_decorators.py

  • Committer: Jelmer Vernooij
  • Date: 2017-09-06 04:15:55 UTC
  • mfrom: (6754.8.21 lock-context-2)
  • Revision ID: jelmer@jelmer.uk-20170906041555-jtr5qxli38167gc6
Merge lp:~jelmer/brz/lock-context-2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
    pass
31
31
 
32
32
 
33
 
def create_decorator_sample(style, unlock_error=None, meth=None):
34
 
    """Create a DecoratorSample object, using specific lock operators.
35
 
 
36
 
    :param style: The type of lock decorators to use (fast/pretty/None)
37
 
    :param unlock_error: If specified, an error to raise from unlock.
38
 
    :param meth: a function to be decorated and added as a 'meth_read' and
39
 
        'meth_write' to the object.
40
 
    :return: An instantiated DecoratorSample object.
41
 
    """
42
 
 
43
 
    if style is None:
44
 
        # Default
45
 
        needs_read_lock = decorators.needs_read_lock
46
 
        needs_write_lock = decorators.needs_write_lock
47
 
    elif style == 'pretty':
48
 
        needs_read_lock = decorators._pretty_needs_read_lock
49
 
        needs_write_lock = decorators._pretty_needs_write_lock
50
 
    else:
51
 
        needs_read_lock = decorators._fast_needs_read_lock
52
 
        needs_write_lock = decorators._fast_needs_write_lock
53
 
 
54
 
    class DecoratorSample(object):
55
 
        """Sample class that uses decorators.
56
 
 
57
 
        Log when requests go through lock_read()/unlock() or
58
 
        lock_write()/unlock.
59
 
        """
60
 
 
61
 
        def __init__(self):
62
 
            self.actions = []
63
 
 
64
 
        def lock_read(self):
65
 
            self.actions.append('lock_read')
66
 
            return lock.LogicalLockResult(self.unlock)
67
 
 
68
 
        def lock_write(self):
69
 
            self.actions.append('lock_write')
70
 
            return lock.LogicalLockResult(self.unlock)
71
 
 
72
 
        @decorators.only_raises(SampleUnlockError)
73
 
        def unlock(self):
74
 
            if unlock_error:
75
 
                self.actions.append('unlock_fail')
76
 
                raise unlock_error
77
 
            else:
78
 
                self.actions.append('unlock')
79
 
 
80
 
        @needs_read_lock
81
 
        def frob(self):
82
 
            """Frob the sample object"""
83
 
            self.actions.append('frob')
84
 
            return 'newbie'
85
 
 
86
 
        @needs_write_lock
87
 
        def bank(self, bar, biz=None):
88
 
            """Bank the sample, but using bar and biz."""
89
 
            self.actions.append(('bank', bar, biz))
90
 
            return (bar, biz)
91
 
 
92
 
        @needs_read_lock
93
 
        def fail_during_read(self):
94
 
            self.actions.append('fail_during_read')
95
 
            raise TypeError('during read')
96
 
 
97
 
        @needs_write_lock
98
 
        def fail_during_write(self):
99
 
            self.actions.append('fail_during_write')
100
 
            raise TypeError('during write')
101
 
 
102
 
        if meth is not None:
103
 
            meth_read = needs_read_lock(meth)
104
 
            meth_write = needs_write_lock(meth)
105
 
 
106
 
    return DecoratorSample()
107
 
 
108
 
 
109
 
class TestDecoratorActions(TestCase):
110
 
 
111
 
    _decorator_style = None # default
112
 
 
113
 
    def test_read_lock_locks_and_unlocks(self):
114
 
        sam = create_decorator_sample(self._decorator_style)
115
 
        self.assertEqual('newbie', sam.frob())
116
 
        self.assertEqual(['lock_read', 'frob', 'unlock'], sam.actions)
117
 
 
118
 
    def test_write_lock_locks_and_unlocks(self):
119
 
        sam = create_decorator_sample(self._decorator_style)
120
 
        self.assertEqual(('bar', 'bing'), sam.bank('bar', biz='bing'))
121
 
        self.assertEqual(['lock_write', ('bank', 'bar', 'bing'), 'unlock'],
122
 
                         sam.actions)
123
 
 
124
 
    def test_read_lock_unlocks_during_failure(self):
125
 
        sam = create_decorator_sample(self._decorator_style)
126
 
        self.assertRaises(TypeError, sam.fail_during_read)
127
 
        self.assertEqual(['lock_read', 'fail_during_read', 'unlock'],
128
 
                         sam.actions)
129
 
 
130
 
    def test_write_lock_unlocks_during_failure(self):
131
 
        sam = create_decorator_sample(self._decorator_style)
132
 
        self.assertRaises(TypeError, sam.fail_during_write)
133
 
        self.assertEqual(['lock_write', 'fail_during_write', 'unlock'],
134
 
                         sam.actions)
135
 
 
136
 
    def test_read_lock_raises_original_error(self):
137
 
        sam = create_decorator_sample(self._decorator_style,
138
 
                                      unlock_error=SampleUnlockError())
139
 
        self.assertRaises(TypeError, sam.fail_during_read)
140
 
        self.assertEqual(['lock_read', 'fail_during_read', 'unlock_fail'],
141
 
                         sam.actions)
142
 
 
143
 
    def test_write_lock_raises_original_error(self):
144
 
        sam = create_decorator_sample(self._decorator_style,
145
 
                                      unlock_error=SampleUnlockError())
146
 
        self.assertRaises(TypeError, sam.fail_during_write)
147
 
        self.assertEqual(['lock_write', 'fail_during_write', 'unlock_fail'],
148
 
                         sam.actions)
149
 
 
150
 
    def test_read_lock_raises_unlock_error(self):
151
 
        sam = create_decorator_sample(self._decorator_style,
152
 
                                      unlock_error=SampleUnlockError())
153
 
        self.assertRaises(SampleUnlockError, sam.frob)
154
 
        self.assertEqual(['lock_read', 'frob', 'unlock_fail'], sam.actions)
155
 
 
156
 
    def test_write_lock_raises_unlock_error(self):
157
 
        sam = create_decorator_sample(self._decorator_style,
158
 
                                      unlock_error=SampleUnlockError())
159
 
        self.assertRaises(SampleUnlockError, sam.bank, 'bar', biz='bing')
160
 
        self.assertEqual(['lock_write', ('bank', 'bar', 'bing'),
161
 
                          'unlock_fail'], sam.actions)
162
 
 
163
 
    def test_read_lock_preserves_default_str_kwarg_identity(self):
164
 
        a_constant = 'A str used as a constant'
165
 
        def meth(self, param=a_constant):
166
 
            return param
167
 
        sam = create_decorator_sample(self._decorator_style, meth=meth)
168
 
        self.assertIs(a_constant, sam.meth_read())
169
 
 
170
 
    def test_write_lock_preserves_default_str_kwarg_identity(self):
171
 
        a_constant = 'A str used as a constant'
172
 
        def meth(self, param=a_constant):
173
 
            return param
174
 
        sam = create_decorator_sample(self._decorator_style, meth=meth)
175
 
        self.assertIs(a_constant, sam.meth_write())
176
 
 
177
 
 
178
 
class TestFastDecoratorActions(TestDecoratorActions):
179
 
 
180
 
    _decorator_style = 'fast'
181
 
 
182
 
 
183
 
class TestPrettyDecoratorActions(TestDecoratorActions):
184
 
 
185
 
    _decorator_style = 'pretty'
186
 
 
187
 
 
188
 
class TestDecoratorDocs(TestCase):
189
 
    """Test method decorators"""
190
 
 
191
 
    def test_read_lock_passthrough(self):
192
 
        """@needs_read_lock exposes underlying name and doc."""
193
 
        sam = create_decorator_sample(None)
194
 
        self.assertEqual('frob', sam.frob.__name__)
195
 
        self.assertDocstring('Frob the sample object', sam.frob)
196
 
 
197
 
    def test_write_lock_passthrough(self):
198
 
        """@needs_write_lock exposes underlying name and doc."""
199
 
        sam = create_decorator_sample(None)
200
 
        self.assertEqual('bank', sam.bank.__name__)
201
 
        self.assertDocstring('Bank the sample, but using bar and biz.',
202
 
                             sam.bank)
203
 
 
204
 
    def test_argument_passthrough(self):
205
 
        """Test that arguments get passed around properly."""
206
 
        sam = create_decorator_sample(None)
207
 
        sam.bank('1', biz='2')
208
 
        self.assertEqual(['lock_write',
209
 
                          ('bank', '1', '2'),
210
 
                          'unlock',
211
 
                         ], sam.actions)
212
 
 
213
 
 
214
 
class TestPrettyDecorators(TestCase):
215
 
    """Test that pretty decorators generate nice looking wrappers."""
216
 
 
217
 
    def get_formatted_args(self, func):
218
 
        """Return a nicely formatted string for the arguments to a function.
219
 
 
220
 
        This generates something like "(foo, bar=None)".
221
 
        """
222
 
        return inspect.formatargspec(*inspect.getargspec(func))
223
 
 
224
 
    def test__pretty_needs_read_lock(self):
225
 
        """Test that _pretty_needs_read_lock generates a nice wrapper."""
226
 
 
227
 
        @decorators._pretty_needs_read_lock
228
 
        def my_function(foo, bar, baz=None, biz=1):
229
 
            """Just a function that supplies several arguments."""
230
 
 
231
 
        self.assertEqual('my_function', my_function.__name__)
232
 
        self.assertEqual('my_function_read_locked',
233
 
                         my_function.__code__.co_name)
234
 
        self.assertEqual('(foo, bar, baz=None, biz=1)',
235
 
                         self.get_formatted_args(my_function))
236
 
        self.assertDocstring(
237
 
            'Just a function that supplies several arguments.', my_function)
238
 
 
239
 
    def test__fast_needs_read_lock(self):
240
 
        """Test the output of _fast_needs_read_lock."""
241
 
 
242
 
        @decorators._fast_needs_read_lock
243
 
        def my_function(foo, bar, baz=None, biz=1):
244
 
            """Just a function that supplies several arguments."""
245
 
 
246
 
        self.assertEqual('my_function', my_function.__name__)
247
 
        self.assertEqual('read_locked', my_function.__code__.co_name)
248
 
        self.assertEqual('(self, *args, **kwargs)',
249
 
                         self.get_formatted_args(my_function))
250
 
        self.assertDocstring(
251
 
            'Just a function that supplies several arguments.', my_function)
252
 
 
253
 
    def test__pretty_needs_write_lock(self):
254
 
        """Test that _pretty_needs_write_lock generates a nice wrapper."""
255
 
 
256
 
        @decorators._pretty_needs_write_lock
257
 
        def my_function(foo, bar, baz=None, biz=1):
258
 
            """Just a function that supplies several arguments."""
259
 
 
260
 
        self.assertEqual('my_function', my_function.__name__)
261
 
        self.assertEqual('my_function_write_locked',
262
 
                         my_function.__code__.co_name)
263
 
        self.assertEqual('(foo, bar, baz=None, biz=1)',
264
 
                         self.get_formatted_args(my_function))
265
 
        self.assertDocstring(
266
 
            'Just a function that supplies several arguments.', my_function)
267
 
 
268
 
    def test__fast_needs_write_lock(self):
269
 
        """Test the output of _fast_needs_write_lock."""
270
 
 
271
 
        @decorators._fast_needs_write_lock
272
 
        def my_function(foo, bar, baz=None, biz=1):
273
 
            """Just a function that supplies several arguments."""
274
 
 
275
 
        self.assertEqual('my_function', my_function.__name__)
276
 
        self.assertEqual('write_locked', my_function.__code__.co_name)
277
 
        self.assertEqual('(self, *args, **kwargs)',
278
 
                         self.get_formatted_args(my_function))
279
 
        self.assertDocstring(
280
 
            'Just a function that supplies several arguments.', my_function)
281
 
 
282
 
    def test_use_decorators(self):
283
 
        """Test that you can switch the type of the decorators."""
284
 
        cur_read = decorators.needs_read_lock
285
 
        cur_write = decorators.needs_write_lock
286
 
        try:
287
 
            decorators.use_fast_decorators()
288
 
            self.assertIs(decorators._fast_needs_read_lock,
289
 
                          decorators.needs_read_lock)
290
 
            self.assertIs(decorators._fast_needs_write_lock,
291
 
                          decorators.needs_write_lock)
292
 
 
293
 
            decorators.use_pretty_decorators()
294
 
            self.assertIs(decorators._pretty_needs_read_lock,
295
 
                          decorators.needs_read_lock)
296
 
            self.assertIs(decorators._pretty_needs_write_lock,
297
 
                          decorators.needs_write_lock)
298
 
 
299
 
            # One more switch to make sure it wasn't just good luck that the
300
 
            # functions pointed to the correct version
301
 
            decorators.use_fast_decorators()
302
 
            self.assertIs(decorators._fast_needs_read_lock,
303
 
                          decorators.needs_read_lock)
304
 
            self.assertIs(decorators._fast_needs_write_lock,
305
 
                          decorators.needs_write_lock)
306
 
        finally:
307
 
            decorators.needs_read_lock = cur_read
308
 
            decorators.needs_write_lock = cur_write
309
 
 
310
 
 
311
33
class TestOnlyRaisesDecorator(TestCase):
312
34
 
313
35
    def raise_ZeroDivisionError(self):
314
36
        1/0
315
 
        
 
37
 
316
38
    def test_raises_approved_error(self):
317
39
        decorator = decorators.only_raises(ZeroDivisionError)
318
40
        decorated_meth = decorator(self.raise_ZeroDivisionError)
322
44
        decorator = decorators.only_raises(IOError)
323
45
        decorated_meth = decorator(self.raise_ZeroDivisionError)
324
46
        self.assertLogsError(ZeroDivisionError, decorated_meth)
325
 
        
326