1
# (C) 2005 Canonical Ltd
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.
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.
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
17
"""Tests for the BzrDir facility and any format specific tests.
19
For interface contract tests, see tests/bzr_dir_implementations.
22
from StringIO import StringIO
25
import bzrlib.bzrdir as bzrdir
26
import bzrlib.errors as errors
27
from bzrlib.errors import (NotBranchError,
29
UnsupportedFormatError,
31
import bzrlib.repository as repository
32
from bzrlib.tests import TestCase, TestCaseWithTransport
33
from bzrlib.transport import get_transport
34
from bzrlib.transport.http import HttpServer
35
from bzrlib.transport.memory import MemoryServer
36
import bzrlib.workingtree as workingtree
39
class TestDefaultFormat(TestCase):
41
def test_get_set_default_format(self):
42
old_format = bzrdir.BzrDirFormat.get_default_format()
43
# default is BzrDirFormat6
44
self.failUnless(isinstance(old_format, bzrdir.BzrDirFormat6))
45
bzrdir.BzrDirFormat.set_default_format(SampleBzrDirFormat())
46
# creating a bzr dir should now create an instrumented dir.
48
result = bzrdir.BzrDir.create('memory:/')
49
self.failUnless(isinstance(result, SampleBzrDir))
51
bzrdir.BzrDirFormat.set_default_format(old_format)
52
self.assertEqual(old_format, bzrdir.BzrDirFormat.get_default_format())
55
class SampleBranch(bzrlib.branch.Branch):
56
"""A dummy branch for guess what, dummy use."""
58
def __init__(self, dir):
62
class SampleBzrDir(bzrdir.BzrDir):
63
"""A sample BzrDir implementation to allow testing static methods."""
65
def create_repository(self):
66
"""See BzrDir.create_repository."""
69
def open_repository(self):
70
"""See BzrDir.open_repository."""
73
def create_branch(self):
74
"""See BzrDir.create_branch."""
75
return SampleBranch(self)
77
def create_workingtree(self):
78
"""See BzrDir.create_workingtree."""
82
class SampleBzrDirFormat(bzrdir.BzrDirFormat):
85
this format is initializable, unsupported to aid in testing the
86
open and open_downlevel routines.
89
def get_format_string(self):
90
"""See BzrDirFormat.get_format_string()."""
91
return "Sample .bzr dir format."
93
def initialize(self, url):
94
"""Create a bzr dir."""
95
t = get_transport(url)
97
t.put('.bzr/branch-format', StringIO(self.get_format_string()))
98
return SampleBzrDir(t, self)
100
def is_supported(self):
103
def open(self, transport, _found=None):
104
return "opened branch."
107
class TestBzrDirFormat(TestCaseWithTransport):
108
"""Tests for the BzrDirFormat facility."""
110
def test_find_format(self):
111
# is the right format object found for a branch?
112
# create a branch with a few known format objects.
113
# this is not quite the same as
114
t = get_transport(self.get_url())
115
self.build_tree(["foo/", "bar/"], transport=t)
116
def check_format(format, url):
117
format.initialize(url)
118
t = get_transport(url)
119
found_format = bzrdir.BzrDirFormat.find_format(t)
120
self.failUnless(isinstance(found_format, format.__class__))
121
check_format(bzrdir.BzrDirFormat5(), "foo")
122
check_format(bzrdir.BzrDirFormat6(), "bar")
124
def test_find_format_nothing_there(self):
125
self.assertRaises(NotBranchError,
126
bzrdir.BzrDirFormat.find_format,
129
def test_find_format_unknown_format(self):
130
t = get_transport(self.get_url())
132
t.put('.bzr/branch-format', StringIO())
133
self.assertRaises(UnknownFormatError,
134
bzrdir.BzrDirFormat.find_format,
137
def test_register_unregister_format(self):
138
format = SampleBzrDirFormat()
141
format.initialize(url)
142
# register a format for it.
143
bzrdir.BzrDirFormat.register_format(format)
144
# which bzrdir.Open will refuse (not supported)
145
self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open, url)
146
# but open_downlevel will work
147
t = get_transport(url)
148
self.assertEqual(format.open(t), bzrdir.BzrDir.open_unsupported(url))
149
# unregister the format
150
bzrdir.BzrDirFormat.unregister_format(format)
151
# now open_downlevel should fail too.
152
self.assertRaises(UnknownFormatError, bzrdir.BzrDir.open_unsupported, url)
154
def test_create_repository(self):
155
format = SampleBzrDirFormat()
156
old_format = bzrdir.BzrDirFormat.get_default_format()
157
bzrdir.BzrDirFormat.set_default_format(format)
159
repo = bzrdir.BzrDir.create_repository(self.get_url())
160
self.assertEqual('A repository', repo)
162
bzrdir.BzrDirFormat.set_default_format(old_format)
164
def test_create_repository_under_shared(self):
165
# an explicit create_repository always does so.
166
# we trust the format is right from the 'create_repository test'
167
old_format = bzrdir.BzrDirFormat.get_default_format()
168
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
170
self.make_repository('.', shared=True)
171
repo = bzrdir.BzrDir.create_repository(self.get_url('child'))
172
self.assertTrue(isinstance(repo, repository.Repository))
173
self.assertTrue(repo.bzrdir.root_transport.base.endswith('child/'))
175
bzrdir.BzrDirFormat.set_default_format(old_format)
177
def test_create_branch_and_repo_uses_default(self):
178
format = SampleBzrDirFormat()
179
old_format = bzrdir.BzrDirFormat.get_default_format()
180
bzrdir.BzrDirFormat.set_default_format(format)
182
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url())
183
self.assertTrue(isinstance(branch, SampleBranch))
185
bzrdir.BzrDirFormat.set_default_format(old_format)
187
def test_create_branch_and_repo_under_shared(self):
188
# creating a branch and repo in a shared repo uses the
190
old_format = bzrdir.BzrDirFormat.get_default_format()
191
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
193
self.make_repository('.', shared=True)
194
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url('child'))
195
self.assertRaises(errors.NoRepositoryPresent,
196
branch.bzrdir.open_repository)
198
bzrdir.BzrDirFormat.set_default_format(old_format)
200
def test_create_branch_and_repo_under_shared_force_new(self):
201
# creating a branch and repo in a shared repo can be forced to
203
old_format = bzrdir.BzrDirFormat.get_default_format()
204
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
206
self.make_repository('.', shared=True)
207
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url('child'),
209
branch.bzrdir.open_repository()
211
bzrdir.BzrDirFormat.set_default_format(old_format)
213
def test_create_standalone_working_tree(self):
214
format = SampleBzrDirFormat()
215
old_format = bzrdir.BzrDirFormat.get_default_format()
216
bzrdir.BzrDirFormat.set_default_format(format)
218
# note this is deliberately readonly, as this failure should
219
# occur before any writes.
220
self.assertRaises(errors.NotLocalUrl,
221
bzrdir.BzrDir.create_standalone_workingtree,
222
self.get_readonly_url())
223
tree = bzrdir.BzrDir.create_standalone_workingtree('.')
224
self.assertEqual('A tree', tree)
226
bzrdir.BzrDirFormat.set_default_format(old_format)
228
def test_create_standalone_working_tree_under_shared_repo(self):
229
# create standalone working tree always makes a repo.
230
old_format = bzrdir.BzrDirFormat.get_default_format()
231
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
233
self.make_repository('.', shared=True)
234
# note this is deliberately readonly, as this failure should
235
# occur before any writes.
236
self.assertRaises(errors.NotLocalUrl,
237
bzrdir.BzrDir.create_standalone_workingtree,
238
self.get_readonly_url('child'))
239
tree = bzrdir.BzrDir.create_standalone_workingtree('child')
240
tree.bzrdir.open_repository()
242
bzrdir.BzrDirFormat.set_default_format(old_format)
244
def test_create_branch_convenience(self):
245
# outside a repo the default conveniencec output is a repo+branch_tree
246
old_format = bzrdir.BzrDirFormat.get_default_format()
247
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
249
branch = bzrdir.BzrDir.create_branch_convenience('.')
250
branch.bzrdir.open_workingtree()
251
branch.bzrdir.open_repository()
253
bzrdir.BzrDirFormat.set_default_format(old_format)
255
def test_create_branch_convenience_under_shared_repo(self):
256
# inside a repo the default convenience output is a branch+ follow the
258
old_format = bzrdir.BzrDirFormat.get_default_format()
259
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
261
self.make_repository('.', shared=True)
262
branch = bzrdir.BzrDir.create_branch_convenience('child')
263
branch.bzrdir.open_workingtree()
264
self.assertRaises(errors.NoRepositoryPresent,
265
branch.bzrdir.open_repository)
267
bzrdir.BzrDirFormat.set_default_format(old_format)
269
def test_create_branch_convenience_under_shared_repo_force_no_tree(self):
270
# inside a repo the default convenience output is a branch+ follow the
271
# repo tree policy but we can override that
272
old_format = bzrdir.BzrDirFormat.get_default_format()
273
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
275
self.make_repository('.', shared=True)
276
branch = bzrdir.BzrDir.create_branch_convenience('child',
277
force_new_tree=False)
278
self.assertRaises(errors.NoWorkingTree,
279
branch.bzrdir.open_workingtree)
280
self.assertRaises(errors.NoRepositoryPresent,
281
branch.bzrdir.open_repository)
283
bzrdir.BzrDirFormat.set_default_format(old_format)
285
def test_create_branch_convenience_under_shared_repo_no_tree_policy(self):
286
# inside a repo the default convenience output is a branch+ follow the
288
old_format = bzrdir.BzrDirFormat.get_default_format()
289
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
291
repo = self.make_repository('.', shared=True)
292
repo.set_make_working_trees(False)
293
branch = bzrdir.BzrDir.create_branch_convenience('child')
294
self.assertRaises(errors.NoWorkingTree,
295
branch.bzrdir.open_workingtree)
296
self.assertRaises(errors.NoRepositoryPresent,
297
branch.bzrdir.open_repository)
299
bzrdir.BzrDirFormat.set_default_format(old_format)
301
def test_create_branch_convenience_under_shared_repo_no_tree_policy_force_tree(self):
302
# inside a repo the default convenience output is a branch+ follow the
303
# repo tree policy but we can override that
304
old_format = bzrdir.BzrDirFormat.get_default_format()
305
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
307
repo = self.make_repository('.', shared=True)
308
repo.set_make_working_trees(False)
309
branch = bzrdir.BzrDir.create_branch_convenience('child',
311
branch.bzrdir.open_workingtree()
312
self.assertRaises(errors.NoRepositoryPresent,
313
branch.bzrdir.open_repository)
315
bzrdir.BzrDirFormat.set_default_format(old_format)
317
def test_create_branch_convenience_under_shared_repo_force_new_repo(self):
318
# inside a repo the default convenience output is overridable to give
320
old_format = bzrdir.BzrDirFormat.get_default_format()
321
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
323
self.make_repository('.', shared=True)
324
branch = bzrdir.BzrDir.create_branch_convenience('child',
326
branch.bzrdir.open_repository()
327
branch.bzrdir.open_workingtree()
329
bzrdir.BzrDirFormat.set_default_format(old_format)
332
class ChrootedTests(TestCaseWithTransport):
333
"""A support class that provides readonly urls outside the local namespace.
335
This is done by checking if self.transport_server is a MemoryServer. if it
336
is then we are chrooted already, if it is not then an HttpServer is used
341
super(ChrootedTests, self).setUp()
342
if not self.transport_server == MemoryServer:
343
self.transport_readonly_server = HttpServer
345
def test_open_containing(self):
346
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
347
self.get_readonly_url(''))
348
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
349
self.get_readonly_url('g/p/q'))
350
control = bzrdir.BzrDir.create(self.get_url())
351
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url(''))
352
self.assertEqual('', relpath)
353
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url('g/p/q'))
354
self.assertEqual('g/p/q', relpath)
356
def test_open_containing_from_transport(self):
357
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
358
get_transport(self.get_readonly_url('')))
359
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
360
get_transport(self.get_readonly_url('g/p/q')))
361
control = bzrdir.BzrDir.create(self.get_url())
362
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
363
get_transport(self.get_readonly_url('')))
364
self.assertEqual('', relpath)
365
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
366
get_transport(self.get_readonly_url('g/p/q')))
367
self.assertEqual('g/p/q', relpath)
370
class TestMeta1DirFormat(TestCaseWithTransport):
371
"""Tests specific to the meta1 dir format."""
373
def test_right_base_dirs(self):
374
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
376
branch_base = t.clone('branch').base
377
self.assertEqual(branch_base, dir.get_branch_transport(None).base)
378
self.assertEqual(branch_base,
379
dir.get_branch_transport(bzrlib.branch.BzrBranchFormat5()).base)
380
repository_base = t.clone('repository').base
381
self.assertEqual(repository_base, dir.get_repository_transport(None).base)
382
self.assertEqual(repository_base,
383
dir.get_repository_transport(repository.RepositoryFormat7()).base)
384
checkout_base = t.clone('checkout').base
385
self.assertEqual(checkout_base, dir.get_workingtree_transport(None).base)
386
self.assertEqual(checkout_base,
387
dir.get_workingtree_transport(workingtree.WorkingTreeFormat3()).base)
390
class TestFormat5(TestCaseWithTransport):
391
"""Tests specific to the version 5 bzrdir format."""
393
def test_same_lockfiles_between_tree_repo_branch(self):
394
# this checks that only a single lockfiles instance is created
395
# for format 5 objects
396
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
397
def check_dir_components_use_same_lock(dir):
398
ctrl_1 = dir.open_repository().control_files
399
ctrl_2 = dir.open_branch().control_files
400
ctrl_3 = dir.open_workingtree()._control_files
401
self.assertTrue(ctrl_1 is ctrl_2)
402
self.assertTrue(ctrl_2 is ctrl_3)
403
check_dir_components_use_same_lock(dir)
404
# and if we open it normally.
405
dir = bzrdir.BzrDir.open(self.get_url())
406
check_dir_components_use_same_lock(dir)
408
def test_can_convert(self):
409
# format 5 dirs are convertable
410
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
411
self.assertTrue(dir.can_convert_format())
413
def test_needs_conversion(self):
414
# format 5 dirs need a conversion if they are not the default.
415
# and they start of not the default.
416
old_format = bzrdir.BzrDirFormat.get_default_format()
417
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirFormat5())
419
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
420
self.assertFalse(dir.needs_format_conversion())
422
bzrdir.BzrDirFormat.set_default_format(old_format)
423
self.assertTrue(dir.needs_format_conversion())
426
class TestFormat6(TestCaseWithTransport):
427
"""Tests specific to the version 6 bzrdir format."""
429
def test_same_lockfiles_between_tree_repo_branch(self):
430
# this checks that only a single lockfiles instance is created
431
# for format 6 objects
432
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
433
def check_dir_components_use_same_lock(dir):
434
ctrl_1 = dir.open_repository().control_files
435
ctrl_2 = dir.open_branch().control_files
436
ctrl_3 = dir.open_workingtree()._control_files
437
self.assertTrue(ctrl_1 is ctrl_2)
438
self.assertTrue(ctrl_2 is ctrl_3)
439
check_dir_components_use_same_lock(dir)
440
# and if we open it normally.
441
dir = bzrdir.BzrDir.open(self.get_url())
442
check_dir_components_use_same_lock(dir)
444
def test_can_convert(self):
445
# format 6 dirs are convertable
446
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
447
self.assertTrue(dir.can_convert_format())
449
def test_needs_conversion(self):
450
# format 6 dirs need an conversion if they are not the default.
451
old_format = bzrdir.BzrDirFormat.get_default_format()
452
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
454
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
455
self.assertTrue(dir.needs_format_conversion())
457
bzrdir.BzrDirFormat.set_default_format(old_format)
458
self.assertFalse(dir.needs_format_conversion())