~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/fixtures.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-03-28 06:58:22 UTC
  • mfrom: (2379.2.3 hpss-chroot)
  • Revision ID: pqm@pqm.ubuntu.com-20070328065822-999550a858a3ced3
(robertc) Fix chroot urls to not expose the url of the transport they are protecting, allowing regular url operations to work on them. (Robert Collins, Andrew Bennetts)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
 
18
 
"""Fixtures that can be used within tests.
19
 
 
20
 
Fixtures can be created during a test as a way to separate out creation of
21
 
objects to test.  Fixture objects can hold some state so that different 
22
 
objects created during a test instance can be related.  Normally a fixture
23
 
should live only for the duration of a single test, and its tearDown method
24
 
should be passed to `addCleanup` on the test.
25
 
"""
26
 
 
27
 
 
28
 
import itertools
29
 
 
30
 
 
31
 
def generate_unicode_names():
32
 
    """Generate a sequence of arbitrary unique unicode names.
33
 
    
34
 
    By default they are not representable in ascii.
35
 
    
36
 
    >>> gen = generate_unicode_names()
37
 
    >>> n1 = gen.next()
38
 
    >>> n2 = gen.next()
39
 
    >>> type(n1)
40
 
    <type 'unicode'>
41
 
    >>> n1 == n2
42
 
    False
43
 
    >>> n1.encode('ascii', 'replace') == n1
44
 
    False
45
 
    """
46
 
    # include a mathematical symbol unlikely to be in 8-bit encodings
47
 
    return (u"\N{SINE WAVE}%d" % x for x in itertools.count())
48
 
 
49
 
 
50
 
interesting_encodings = [
51
 
    ('iso-8859-1', False),
52
 
    ('ascii', False),
53
 
    ('cp850', False),
54
 
    ('utf-8', True),
55
 
    ('ucs-2', True),
56
 
    ]
57
 
 
58
 
 
59
 
def generate_unicode_encodings(universal_encoding=None):
60
 
    """Return a generator of unicode encoding names.
61
 
 
62
 
    These can be passed to Python encode/decode/etc.
63
 
    
64
 
    :param universal_encoding: True/False/None tristate to say whether the
65
 
        generated encodings either can or cannot encode all unicode 
66
 
        strings.
67
 
 
68
 
    >>> n1 = generate_unicode_names().next()
69
 
    >>> enc = generate_unicode_encodings(universal_encoding=True).next()
70
 
    >>> enc2 = generate_unicode_encodings(universal_encoding=False).next()
71
 
    >>> n1.encode(enc).decode(enc) == n1
72
 
    True
73
 
    >>> try:
74
 
    ...   n1.encode(enc2).decode(enc2)
75
 
    ... except UnicodeError:
76
 
    ...   print 'fail'
77
 
    fail
78
 
    """
79
 
    # TODO: check they're supported on this platform?
80
 
    if universal_encoding is not None:
81
 
        e = [n for (n, u) in interesting_encodings if u == universal_encoding]
82
 
    else:
83
 
        e = [n for (n, u) in interesting_encodings]
84
 
    return itertools.cycle(iter(e))
85
 
 
86
 
 
87
 
class RecordingContextManager(object):
88
 
    """A context manager that records."""
89
 
 
90
 
    def __init__(self):
91
 
        self._calls = []
92
 
 
93
 
    def __enter__(self):
94
 
        self._calls.append('__enter__')
95
 
        return self # This is bound to the 'as' clause in a with statement.
96
 
 
97
 
    def __exit__(self, exc_type, exc_val, exc_tb):
98
 
        self._calls.append('__exit__')
99
 
        return False # propogate exceptions.
100
 
 
101
 
 
102
 
def build_branch_with_non_ancestral_rev(branch_builder):
103
 
    """Builds a branch with a rev not in the ancestry of the tip.
104
 
 
105
 
    This is the revision graph::
106
 
 
107
 
      rev-2
108
 
        |
109
 
      rev-1
110
 
        |
111
 
      (null)
112
 
 
113
 
    The branch tip is 'rev-1'.  'rev-2' is present in the branch's repository,
114
 
    but is not part of rev-1's ancestry.
115
 
 
116
 
    :param branch_builder: A BranchBuilder (e.g. from
117
 
        TestCaseWithMemoryTransport.make_branch_builder).
118
 
    :returns: the new branch
119
 
    """
120
 
    # Make a sequence of two commits
121
 
    branch_builder.build_commit(message="Rev 1", rev_id='rev-1')
122
 
    branch_builder.build_commit(message="Rev 2", rev_id='rev-2')
123
 
    # Move the branch tip back to the first commit
124
 
    source = branch_builder.get_branch()
125
 
    source.set_last_revision_info(1, 'rev-1')
126
 
    return source
127
 
 
128
 
 
129
 
def make_branch_and_populated_tree(testcase):
130
 
    """Make a simple branch and tree.
131
 
 
132
 
    The tree holds some added but uncommitted files.
133
 
    """
134
 
    # TODO: Either accept or return the names of the files, so the caller
135
 
    # doesn't need to be bound to the particular files created? -- mbp
136
 
    # 20110705
137
 
    tree = testcase.make_branch_and_tree('t')
138
 
    testcase.build_tree_contents([('t/hello', 'hello world')])
139
 
    tree.add(['hello'], ['hello-id'])
140
 
    return tree
141
 
 
142
 
 
143
 
class TimeoutFixture(object):
144
 
    """Kill a test with sigalarm if it runs too long.
145
 
    
146
 
    Only works on Unix at present.
147
 
    """
148
 
 
149
 
    def __init__(self, timeout_secs):
150
 
        import signal
151
 
        self.timeout_secs = timeout_secs
152
 
        self.alarm_fn = getattr(signal, 'alarm', None)
153
 
 
154
 
    def setUp(self):
155
 
        if self.alarm_fn is not None:
156
 
            self.alarm_fn(self.timeout_secs)
157
 
 
158
 
    def cleanUp(self):
159
 
        if self.alarm_fn is not None:
160
 
            self.alarm_fn(0)