/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 bzrlib/tests/test_version_info.py

  • Committer: Vincent Ladeuil
  • Date: 2012-01-18 14:09:19 UTC
  • mto: This revision was merged to the branch mainline in revision 6468.
  • Revision ID: v.ladeuil+lp@free.fr-20120118140919-rlvdrhpc0nq1lbwi
Change set/remove to require a lock for the branch config files.

This means that tests (or any plugin for that matter) do not requires an
explicit lock on the branch anymore to change a single option. This also
means the optimisation becomes "opt-in" and as such won't be as
spectacular as it may be and/or harder to get right (nothing fails
anymore).

This reduces the diff by ~300 lines.

Code/tests that were updating more than one config option is still taking
a lock to at least avoid some IOs and demonstrate the benefits through
the decreased number of hpss calls.

The duplication between BranchStack and BranchOnlyStack will be removed
once the same sharing is in place for local config files, at which point
the Stack class itself may be able to host the changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005-2011 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
"""Tests for version_info"""
 
18
 
 
19
from cStringIO import StringIO
 
20
import imp
 
21
import os
 
22
import sys
 
23
 
 
24
from bzrlib import (
 
25
    errors,
 
26
    registry,
 
27
    tests,
 
28
    version_info_formats,
 
29
    )
 
30
from bzrlib.tests import TestCaseWithTransport
 
31
from bzrlib.rio import read_stanzas
 
32
 
 
33
from bzrlib.version_info_formats.format_custom import CustomVersionInfoBuilder
 
34
from bzrlib.version_info_formats.format_rio import RioVersionInfoBuilder
 
35
from bzrlib.version_info_formats.format_python import PythonVersionInfoBuilder
 
36
 
 
37
 
 
38
class VersionInfoTestCase(TestCaseWithTransport):
 
39
 
 
40
    def create_branch(self):
 
41
        wt = self.make_branch_and_tree('branch')
 
42
 
 
43
        self.build_tree(['branch/a'])
 
44
        wt.add('a')
 
45
        wt.commit('a', rev_id='r1')
 
46
 
 
47
        self.build_tree(['branch/b'])
 
48
        wt.add('b')
 
49
        wt.commit('b', rev_id='r2')
 
50
 
 
51
        self.build_tree_contents([('branch/a', 'new contents\n')])
 
52
        wt.commit(u'\xe52', rev_id='r3')
 
53
 
 
54
        return wt
 
55
 
 
56
    def create_tree_with_dotted_revno(self):
 
57
        wt = self.make_branch_and_tree('branch')
 
58
        self.build_tree(['branch/a'])
 
59
        wt.add('a')
 
60
        wt.commit('a', rev_id='r1')
 
61
 
 
62
        other = wt.bzrdir.sprout('other').open_workingtree()
 
63
        self.build_tree(['other/b.a'])
 
64
        other.add(['b.a'])
 
65
        other.commit('b.a', rev_id='o2')
 
66
 
 
67
        os.chdir('branch')
 
68
        self.run_bzr('merge ../other')
 
69
        wt.commit('merge', rev_id='merge')
 
70
 
 
71
        wt.update(revision='o2')
 
72
 
 
73
        return wt
 
74
 
 
75
 
 
76
class TestVersionInfoRio(VersionInfoTestCase):
 
77
 
 
78
    def test_rio_null(self):
 
79
        wt = self.make_branch_and_tree('branch')
 
80
 
 
81
        sio = StringIO()
 
82
        builder = RioVersionInfoBuilder(wt.branch, working_tree=wt)
 
83
        builder.generate(sio)
 
84
        val = sio.getvalue()
 
85
        self.assertContainsRe(val, 'build-date:')
 
86
        self.assertContainsRe(val, 'revno: 0')
 
87
 
 
88
    def test_rio_dotted_revno(self):
 
89
        wt = self.create_tree_with_dotted_revno()
 
90
 
 
91
        sio = StringIO()
 
92
        builder = RioVersionInfoBuilder(wt.branch, working_tree=wt)
 
93
        builder.generate(sio)
 
94
        val = sio.getvalue()
 
95
        self.assertContainsRe(val, 'revno: 1.1.1')
 
96
 
 
97
    def regen_text(self, wt, **kwargs):
 
98
        sio = StringIO()
 
99
        builder = RioVersionInfoBuilder(wt.branch, working_tree=wt, **kwargs)
 
100
        builder.generate(sio)
 
101
        val = sio.getvalue()
 
102
        return val
 
103
 
 
104
    def test_simple(self):
 
105
        wt = self.create_branch()
 
106
 
 
107
        val = self.regen_text(wt)
 
108
        self.assertContainsRe(val, 'build-date:')
 
109
        self.assertContainsRe(val, 'date:')
 
110
        self.assertContainsRe(val, 'revno: 3')
 
111
        self.assertContainsRe(val, 'revision-id: r3')
 
112
 
 
113
    def test_clean(self):
 
114
        wt = self.create_branch()
 
115
        val = self.regen_text(wt, check_for_clean=True)
 
116
        self.assertContainsRe(val, 'clean: True')
 
117
 
 
118
    def test_no_clean(self):
 
119
        wt = self.create_branch()
 
120
        self.build_tree(['branch/c'])
 
121
        val = self.regen_text(wt, check_for_clean=True)
 
122
        self.assertContainsRe(val, 'clean: False')
 
123
 
 
124
    def test_history(self):
 
125
        wt = self.create_branch()
 
126
 
 
127
        val = self.regen_text(wt, include_revision_history=True)
 
128
        self.assertContainsRe(val, 'id: r1')
 
129
        self.assertContainsRe(val, 'message: a')
 
130
        self.assertContainsRe(val, 'id: r2')
 
131
        self.assertContainsRe(val, 'message: b')
 
132
        self.assertContainsRe(val, 'id: r3')
 
133
        self.assertContainsRe(val, 'message: \xc3\xa52') # utf8 encoding '\xe5'
 
134
 
 
135
    def regen(self, wt, **kwargs):
 
136
        sio = StringIO()
 
137
        builder = RioVersionInfoBuilder(wt.branch, working_tree=wt, **kwargs)
 
138
        builder.generate(sio)
 
139
        sio.seek(0)
 
140
        stanzas = list(read_stanzas(sio))
 
141
        self.assertEqual(1, len(stanzas))
 
142
        return stanzas[0]
 
143
 
 
144
    def test_rio_version_hook(self):
 
145
        def update_stanza(rev, stanza):
 
146
            stanza.add('bla', 'bloe')
 
147
        RioVersionInfoBuilder.hooks.install_named_hook(
 
148
            'revision', update_stanza, None)
 
149
        wt = self.create_branch()
 
150
 
 
151
        stanza = self.regen(wt)
 
152
        self.assertEqual(['bloe'], stanza.get_all('bla'))
 
153
 
 
154
    def get_one_stanza(self, stanza, key):
 
155
        new_stanzas = list(read_stanzas(StringIO(stanza[key].encode('utf8'))))
 
156
        self.assertEqual(1, len(new_stanzas))
 
157
        return new_stanzas[0]
 
158
 
 
159
    def test_build_date(self):
 
160
        wt = self.create_branch()
 
161
        stanza = self.regen(wt)
 
162
        self.assertTrue('date' in stanza)
 
163
        self.assertTrue('build-date' in stanza)
 
164
        self.assertEqual(['3'], stanza.get_all('revno'))
 
165
        self.assertEqual(['r3'], stanza.get_all('revision-id'))
 
166
 
 
167
    def test_not_clean(self):
 
168
        wt = self.create_branch()
 
169
        self.build_tree(['branch/c'])
 
170
        stanza = self.regen(wt, check_for_clean=True, include_file_revisions=True)
 
171
        self.assertEqual(['False'], stanza.get_all('clean'))
 
172
 
 
173
    def test_file_revisions(self):
 
174
        wt = self.create_branch()
 
175
        self.build_tree(['branch/c'])
 
176
        stanza = self.regen(wt, check_for_clean=True, include_file_revisions=True)
 
177
        # This assumes it's being run against a tree that does not update the
 
178
        # root revision on every commit.
 
179
        file_rev_stanza = self.get_one_stanza(stanza, 'file-revisions')
 
180
        self.assertEqual(['', 'a', 'b', 'c'], file_rev_stanza.get_all('path'))
 
181
        self.assertEqual(['r1', 'r3', 'r2', 'unversioned'],
 
182
            file_rev_stanza.get_all('revision'))
 
183
 
 
184
    def test_revision_history(self):
 
185
        wt = self.create_branch()
 
186
        stanza = self.regen(wt, include_revision_history=True)
 
187
        revision_stanza = self.get_one_stanza(stanza, 'revisions')
 
188
        self.assertEqual(['r1', 'r2', 'r3'], revision_stanza.get_all('id'))
 
189
        self.assertEqual(['a', 'b', u'\xe52'], revision_stanza.get_all('message'))
 
190
        self.assertEqual(3, len(revision_stanza.get_all('date')))
 
191
 
 
192
    def test_file_revisions_with_rename(self):
 
193
        # a was modified, so it should show up modified again
 
194
        wt = self.create_branch()
 
195
        self.build_tree(['branch/a', 'branch/c'])
 
196
        wt.add('c')
 
197
        wt.rename_one('b', 'd')
 
198
        stanza = self.regen(wt, check_for_clean=True, include_file_revisions=True)
 
199
        file_rev_stanza = self.get_one_stanza(stanza, 'file-revisions')
 
200
        self.assertEqual(['', 'a', 'b', 'c', 'd'],
 
201
                          file_rev_stanza.get_all('path'))
 
202
        self.assertEqual(['r1', 'modified', 'renamed to d', 'new',
 
203
                          'renamed from b'],
 
204
                         file_rev_stanza.get_all('revision'))
 
205
 
 
206
    def test_file_revisions_with_removal(self):
 
207
        wt = self.create_branch()
 
208
        self.build_tree(['branch/a', 'branch/c'])
 
209
        wt.add('c')
 
210
        wt.rename_one('b', 'd')
 
211
 
 
212
        wt.commit('modified', rev_id='r4')
 
213
 
 
214
        wt.remove(['c', 'd'])
 
215
        os.remove('branch/d')
 
216
        stanza = self.regen(wt, check_for_clean=True, include_file_revisions=True)
 
217
        file_rev_stanza = self.get_one_stanza(stanza, 'file-revisions')
 
218
        self.assertEqual(['', 'a', 'c', 'd'], file_rev_stanza.get_all('path'))
 
219
        self.assertEqual(['r1', 'r4', 'unversioned', 'removed'],
 
220
                         file_rev_stanza.get_all('revision'))
 
221
 
 
222
    def test_revision(self):
 
223
        wt = self.create_branch()
 
224
        self.build_tree(['branch/a', 'branch/c'])
 
225
        wt.add('c')
 
226
        wt.rename_one('b', 'd')
 
227
 
 
228
        stanza = self.regen(wt, check_for_clean=True,
 
229
            include_file_revisions=True, revision_id=wt.last_revision())
 
230
        file_rev_stanza = self.get_one_stanza(stanza, 'file-revisions')
 
231
        self.assertEqual(['', 'a', 'b'], file_rev_stanza.get_all('path'))
 
232
        self.assertEqual(['r1', 'r3', 'r2'],
 
233
                         file_rev_stanza.get_all('revision'))
 
234
 
 
235
 
 
236
class PythonVersionInfoTests(VersionInfoTestCase):
 
237
 
 
238
    def test_python_null(self):
 
239
        wt = self.make_branch_and_tree('branch')
 
240
 
 
241
        sio = StringIO()
 
242
        builder = PythonVersionInfoBuilder(wt.branch, working_tree=wt)
 
243
        builder.generate(sio)
 
244
        val = sio.getvalue()
 
245
        self.assertContainsRe(val, "'revision_id': None")
 
246
        self.assertContainsRe(val, "'revno': '0'")
 
247
        self.assertNotContainsString(val, '\n\n\n\n')
 
248
 
 
249
    def test_python_dotted_revno(self):
 
250
        wt = self.create_tree_with_dotted_revno()
 
251
 
 
252
        sio = StringIO()
 
253
        builder = PythonVersionInfoBuilder(wt.branch, working_tree=wt)
 
254
        builder.generate(sio)
 
255
        val = sio.getvalue()
 
256
        self.assertContainsRe(val, "'revno': '1.1.1'")
 
257
 
 
258
    def regen(self, wt, **kwargs):
 
259
        """Create a test module, import and return it"""
 
260
        outf = open('test_version_information.py', 'wb')
 
261
        try:
 
262
            builder = PythonVersionInfoBuilder(wt.branch, working_tree=wt,
 
263
                                               **kwargs)
 
264
            builder.generate(outf)
 
265
        finally:
 
266
            outf.close()
 
267
        module_info = imp.find_module('test_version_information',
 
268
                                      [os.getcwdu()])
 
269
        tvi = imp.load_module('tvi', *module_info)
 
270
        # Make sure the module isn't cached
 
271
        sys.modules.pop('tvi', None)
 
272
        sys.modules.pop('test_version_information', None)
 
273
        # Delete the compiled versions, because we are generating
 
274
        # a new file fast enough that python doesn't detect it
 
275
        # needs to recompile, and using sleep() just makes the
 
276
        # test slow
 
277
        if os.path.exists('test_version_information.pyc'):
 
278
            os.remove('test_version_information.pyc')
 
279
        if os.path.exists('test_version_information.pyo'):
 
280
            os.remove('test_version_information.pyo')
 
281
        return tvi
 
282
 
 
283
    def test_python_version(self):
 
284
        wt = self.create_branch()
 
285
 
 
286
        tvi = self.regen(wt)
 
287
        self.assertEqual('3', tvi.version_info['revno'])
 
288
        self.assertEqual('r3', tvi.version_info['revision_id'])
 
289
        self.assertTrue(tvi.version_info.has_key('date'))
 
290
        self.assertEqual(None, tvi.version_info['clean'])
 
291
 
 
292
        tvi = self.regen(wt, check_for_clean=True)
 
293
        self.assertEqual(True, tvi.version_info['clean'])
 
294
 
 
295
        self.build_tree(['branch/c'])
 
296
        tvi = self.regen(wt, check_for_clean=True, include_file_revisions=True)
 
297
        self.assertEqual(False, tvi.version_info['clean'])
 
298
        self.assertEqual(['', 'a', 'b', 'c'],
 
299
                         sorted(tvi.file_revisions.keys()))
 
300
        self.assertEqual('r3', tvi.file_revisions['a'])
 
301
        self.assertEqual('r2', tvi.file_revisions['b'])
 
302
        self.assertEqual('unversioned', tvi.file_revisions['c'])
 
303
        os.remove('branch/c')
 
304
 
 
305
        tvi = self.regen(wt, include_revision_history=True)
 
306
 
 
307
        rev_info = [(rev, message) for rev, message, timestamp, timezone
 
308
                                   in tvi.revisions]
 
309
        self.assertEqual([('r1', 'a'), ('r2', 'b'), ('r3', u'\xe52')], rev_info)
 
310
 
 
311
        # a was modified, so it should show up modified again
 
312
        self.build_tree(['branch/a', 'branch/c'])
 
313
        wt.add('c')
 
314
        wt.rename_one('b', 'd')
 
315
        tvi = self.regen(wt, check_for_clean=True, include_file_revisions=True)
 
316
        self.assertEqual(['', 'a', 'b', 'c', 'd'],
 
317
                          sorted(tvi.file_revisions.keys()))
 
318
        self.assertEqual('modified', tvi.file_revisions['a'])
 
319
        self.assertEqual('renamed to d', tvi.file_revisions['b'])
 
320
        self.assertEqual('new', tvi.file_revisions['c'])
 
321
        self.assertEqual('renamed from b', tvi.file_revisions['d'])
 
322
 
 
323
        wt.commit('modified', rev_id='r4')
 
324
        wt.remove(['c', 'd'])
 
325
        os.remove('branch/d')
 
326
        tvi = self.regen(wt, check_for_clean=True, include_file_revisions=True)
 
327
        self.assertEqual(['', 'a', 'c', 'd'],
 
328
                          sorted(tvi.file_revisions.keys()))
 
329
        self.assertEqual('r4', tvi.file_revisions['a'])
 
330
        self.assertEqual('unversioned', tvi.file_revisions['c'])
 
331
        self.assertEqual('removed', tvi.file_revisions['d'])
 
332
 
 
333
 
 
334
class CustomVersionInfoTests(VersionInfoTestCase):
 
335
 
 
336
    def test_custom_null(self):
 
337
        sio = StringIO()
 
338
        wt = self.make_branch_and_tree('branch')
 
339
        builder = CustomVersionInfoBuilder(wt.branch, working_tree=wt,
 
340
            template='revno: {revno}')
 
341
        builder.generate(sio)
 
342
        self.assertEquals("revno: 0", sio.getvalue())
 
343
 
 
344
        builder = CustomVersionInfoBuilder(wt.branch, working_tree=wt, 
 
345
            template='{revno} revid: {revision_id}')
 
346
        # revision_id is not available yet
 
347
        self.assertRaises(errors.MissingTemplateVariable, 
 
348
            builder.generate, sio)
 
349
 
 
350
    def test_custom_dotted_revno(self):
 
351
        sio = StringIO()
 
352
        wt = self.create_tree_with_dotted_revno()
 
353
        builder = CustomVersionInfoBuilder(wt.branch, working_tree=wt, 
 
354
            template='{revno} revid: {revision_id}')
 
355
        builder.generate(sio)
 
356
        self.assertEquals("1.1.1 revid: o2", sio.getvalue())
 
357
 
 
358
    def regen(self, wt, tpl, **kwargs):
 
359
        sio = StringIO()
 
360
        builder = CustomVersionInfoBuilder(wt.branch, working_tree=wt,
 
361
                                           template=tpl, **kwargs)
 
362
        builder.generate(sio)
 
363
        val = sio.getvalue()
 
364
        return val
 
365
 
 
366
    def test_build_date(self):
 
367
        wt = self.create_branch()
 
368
 
 
369
        val = self.regen(wt, 'build-date: "{build_date}"\ndate: "{date}"')
 
370
        self.assertContainsRe(val, 'build-date: "[0-9-+: ]+"')
 
371
        self.assertContainsRe(val, 'date: "[0-9-+: ]+"')
 
372
 
 
373
    def test_revno(self):
 
374
        wt = self.create_branch()
 
375
        val = self.regen(wt, 'revno: {revno}')
 
376
        self.assertEqual(val, 'revno: 3')
 
377
 
 
378
    def test_revision_id(self):
 
379
        wt = self.create_branch()
 
380
        val = self.regen(wt, 'revision-id: {revision_id}')
 
381
        self.assertEqual(val, 'revision-id: r3')
 
382
 
 
383
    def test_clean(self):
 
384
        wt = self.create_branch()
 
385
        val = self.regen(wt, 'clean: {clean}', check_for_clean=True)
 
386
        self.assertEqual(val, 'clean: 1')
 
387
 
 
388
    def test_not_clean(self):
 
389
        wt = self.create_branch()
 
390
 
 
391
        self.build_tree(['branch/c'])
 
392
        val = self.regen(wt, 'clean: {clean}', check_for_clean=True)
 
393
        self.assertEqual(val, 'clean: 0')
 
394
        os.remove('branch/c')
 
395
 
 
396
    def test_custom_without_template(self):
 
397
        builder = CustomVersionInfoBuilder(None)
 
398
        sio = StringIO()
 
399
        self.assertRaises(errors.NoTemplate, builder.generate, sio)
 
400
 
 
401
 
 
402
class TestBuilder(version_info_formats.VersionInfoBuilder):
 
403
    pass
 
404
 
 
405
 
 
406
class TestVersionInfoFormatRegistry(tests.TestCase):
 
407
 
 
408
    def setUp(self):
 
409
        super(TestVersionInfoFormatRegistry, self).setUp()
 
410
        self.overrideAttr(version_info_formats,
 
411
                          'format_registry', registry.Registry())
 
412
 
 
413
    def test_register_remove(self):
 
414
        registry = version_info_formats.format_registry
 
415
        registry.register('testbuilder',
 
416
            TestBuilder, 'a simple test builder')
 
417
        self.assertIs(TestBuilder, registry.get('testbuilder'))
 
418
        self.assertEqual('a simple test builder',
 
419
                         registry.get_help('testbuilder'))
 
420
        registry.remove('testbuilder')
 
421
        self.assertRaises(KeyError, registry.get, 'testbuilder')