~bzr-pqm/bzr/bzr.dev

1185.70.5 by Martin Pool
Pass through wrapped function name and docstrign
1
# Copyright (C) 2006 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.70.5 by Martin Pool
Pass through wrapped function name and docstrign
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.70.5 by Martin Pool
Pass through wrapped function name and docstrign
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.70.5 by Martin Pool
Pass through wrapped function name and docstrign
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
18
"""Tests for decorator functions"""
19
2230.2.4 by John Arbash Meinel
Add tests that decorators generate useful wrappers.
20
import inspect
21
22
from bzrlib import decorators
23
from bzrlib.decorators import needs_read_lock, needs_write_lock
1185.70.5 by Martin Pool
Pass through wrapped function name and docstrign
24
from bzrlib.tests import TestCase
25
26
27
class DecoratorSample(object):
28
    """Sample class that uses decorators.
29
2230.2.4 by John Arbash Meinel
Add tests that decorators generate useful wrappers.
30
    Log when requests go through lock_read()/unlock() or lock_write()/unlock.
1185.70.5 by Martin Pool
Pass through wrapped function name and docstrign
31
    """
32
2230.2.4 by John Arbash Meinel
Add tests that decorators generate useful wrappers.
33
    def __init__(self):
34
        self.actions = []
35
36
    def lock_read(self):
37
        self.actions.append('lock_read')
38
39
    def lock_write(self):
40
        self.actions.append('lock_write')
41
42
    def unlock(self):
43
        self.actions.append('unlock')
44
1185.70.5 by Martin Pool
Pass through wrapped function name and docstrign
45
    @needs_read_lock
46
    def frob(self):
47
        """Frob the sample object"""
2230.2.4 by John Arbash Meinel
Add tests that decorators generate useful wrappers.
48
        self.actions.append('frob')
49
50
    @needs_write_lock
51
    def bank(self, bar, biz=None):
52
        """Bank the sample, but using bar and biz."""
53
        self.actions.append(('bank', bar, biz))
1185.70.5 by Martin Pool
Pass through wrapped function name and docstrign
54
55
56
class TestDecoratorDocs(TestCase):
57
    """Test method decorators"""
58
59
    def test_read_lock_passthrough(self):
60
        """@needs_read_lock exposes underlying name and doc."""
61
        sam = DecoratorSample()
2230.2.4 by John Arbash Meinel
Add tests that decorators generate useful wrappers.
62
        self.assertEqual('frob', sam.frob.__name__)
63
        self.assertEqual('Frob the sample object', sam.frob.__doc__)
64
65
    def test_write_lock_passthrough(self):
66
        """@needs_write_lock exposes underlying name and doc."""
67
        sam = DecoratorSample()
68
        self.assertEqual('bank', sam.bank.__name__)
69
        self.assertEqual('Bank the sample, but using bar and biz.',
70
                         sam.bank.__doc__)
71
72
    def test_argument_passthrough(self):
73
        """Test that arguments get passed around properly."""
74
        sam = DecoratorSample()
75
        sam.bank('1', biz='2')
76
        self.assertEqual(['lock_write',
77
                          ('bank', '1', '2'),
78
                          'unlock',
79
                         ], sam.actions)
80
81
82
class TestPrettyDecorators(TestCase):
83
    """Test that pretty decorators generate nice looking wrappers."""
84
85
    def get_formatted_args(self, func):
86
        """Return a nicely formatted string for the arguments to a function.
87
88
        This generates something like "(foo, bar=None)".
89
        """
90
        return inspect.formatargspec(*inspect.getargspec(func))
91
92
    def test__pretty_needs_read_lock(self):
93
        """Test that _pretty_needs_read_lock generates a nice wrapper."""
94
95
        @decorators._pretty_needs_read_lock
96
        def my_function(foo, bar, baz=None, biz=1):
97
            """Just a function that supplies several arguments."""
98
99
        self.assertEqual('my_function', my_function.__name__)
100
        self.assertEqual('my_function_read_locked',
101
                         my_function.func_code.co_name)
102
        self.assertEqual('(foo, bar, baz=None, biz=1)',
103
                         self.get_formatted_args(my_function))
104
        self.assertEqual('Just a function that supplies several arguments.',
105
                         inspect.getdoc(my_function))
106
107
    def test__fast_needs_read_lock(self):
108
        """Test the output of _fast_needs_read_lock."""
109
110
        @decorators._fast_needs_read_lock
111
        def my_function(foo, bar, baz=None, biz=1):
112
            """Just a function that supplies several arguments."""
113
114
        self.assertEqual('my_function', my_function.__name__)
115
        self.assertEqual('read_locked', my_function.func_code.co_name)
116
        self.assertEqual('(self, *args, **kwargs)',
117
                         self.get_formatted_args(my_function))
118
        self.assertEqual('Just a function that supplies several arguments.',
119
                         inspect.getdoc(my_function))
120
121
    def test__pretty_needs_write_lock(self):
122
        """Test that _pretty_needs_write_lock generates a nice wrapper."""
123
124
        @decorators._pretty_needs_write_lock
125
        def my_function(foo, bar, baz=None, biz=1):
126
            """Just a function that supplies several arguments."""
127
128
        self.assertEqual('my_function', my_function.__name__)
129
        self.assertEqual('my_function_write_locked',
130
                         my_function.func_code.co_name)
131
        self.assertEqual('(foo, bar, baz=None, biz=1)',
132
                         self.get_formatted_args(my_function))
133
        self.assertEqual('Just a function that supplies several arguments.',
134
                         inspect.getdoc(my_function))
135
136
    def test__fast_needs_write_lock(self):
137
        """Test the output of _fast_needs_write_lock."""
138
139
        @decorators._fast_needs_write_lock
140
        def my_function(foo, bar, baz=None, biz=1):
141
            """Just a function that supplies several arguments."""
142
143
        self.assertEqual('my_function', my_function.__name__)
144
        self.assertEqual('write_locked', my_function.func_code.co_name)
145
        self.assertEqual('(self, *args, **kwargs)',
146
                         self.get_formatted_args(my_function))
147
        self.assertEqual('Just a function that supplies several arguments.',
148
                         inspect.getdoc(my_function))
149
150
    def test_use_decorators(self):
151
        """Test that you can switch the type of the decorators."""
152
        cur_read = decorators.needs_read_lock
153
        cur_write = decorators.needs_write_lock
154
        try:
155
            decorators.use_fast_decorators()
156
            self.assertIs(decorators._fast_needs_read_lock,
157
                          decorators.needs_read_lock)
158
            self.assertIs(decorators._fast_needs_write_lock,
159
                          decorators.needs_write_lock)
160
161
            decorators.use_pretty_decorators()
162
            self.assertIs(decorators._pretty_needs_read_lock,
163
                          decorators.needs_read_lock)
164
            self.assertIs(decorators._pretty_needs_write_lock,
165
                          decorators.needs_write_lock)
166
167
            # One more switch to make sure it wasn't just good luck that the
168
            # functions pointed to the correct version
169
            decorators.use_fast_decorators()
170
            self.assertIs(decorators._fast_needs_read_lock,
171
                          decorators.needs_read_lock)
172
            self.assertIs(decorators._fast_needs_write_lock,
173
                          decorators.needs_write_lock)
174
        finally:
175
            decorators.needs_read_lock = cur_read
176
            decorators.needs_write_lock = cur_write