18
18
"""Tests for finding and reading the bzr config file[s]."""
19
19
# import system imports here
20
from ConfigParser import ConfigParser
20
from bzrlib.util.configobj.configobj import ConfigObj, ConfigObjError
21
21
from cStringIO import StringIO
25
25
#import bzrlib specific imports here
26
26
import bzrlib.config as config
27
from bzrlib.selftest import TestCase, TestCaseInTempDir
27
import bzrlib.errors as errors
28
from bzrlib.tests import TestCase, TestCaseInTempDir
30
31
sample_config_text = ("[DEFAULT]\n"
31
32
"email=Robert Collins <robertc@example.com>\n"
33
"gpg_signing_command=gnome-gpg\n")
35
class InstrumentedConfigParser(object):
36
"""A config parser look-enough-alike to record calls made to it."""
34
"gpg_signing_command=gnome-gpg\n"
35
"user_global_option=something\n")
38
sample_always_signatures = ("[DEFAULT]\n"
39
"check_signatures=require\n")
42
sample_ignore_signatures = ("[DEFAULT]\n"
43
"check_signatures=ignore\n")
46
sample_maybe_signatures = ("[DEFAULT]\n"
47
"check_signatures=check-available\n")
50
sample_branches_text = ("[http://www.example.com]\n"
51
"# Top level policy\n"
52
"email=Robert Collins <robertc@example.org>\n"
53
"[http://www.example.com/useglobal]\n"
54
"# different project, forces global lookup\n"
57
"check_signatures=require\n"
58
"# test trailing / matching with no children\n"
60
"check_signatures=check-available\n"
61
"gpg_signing_command=false\n"
62
"user_local_option=local\n"
63
"# test trailing / matching\n"
65
"#subdirs will match but not the parent\n"
68
"check_signatures=ignore\n"
69
"post_commit=bzrlib.tests.test_config.post_commit\n"
70
"#testing explicit beats globs\n")
73
class InstrumentedConfigObj(object):
74
"""A config obj look-enough-alike to record calls made to it."""
76
def __contains__(self, thing):
77
self._calls.append(('__contains__', thing))
80
def __getitem__(self, key):
81
self._calls.append(('__getitem__', key))
84
def __init__(self, input):
85
self._calls = [('__init__', input)]
87
def __setitem__(self, key, value):
88
self._calls.append(('__setitem__', key, value))
91
self._calls.append(('write',))
94
class FakeBranch(object):
97
self.base = "http://example.com/branches/demo"
98
self.control_files = FakeControlFiles()
101
class FakeControlFiles(object):
104
self.email = 'Robert Collins <robertc@example.net>\n'
106
def get_utf8(self, filename):
107
if filename != 'email':
108
raise NotImplementedError
109
if self.email is not None:
110
return StringIO(self.email)
111
raise errors.NoSuchFile(filename)
114
class InstrumentedConfig(config.Config):
115
"""An instrumented config that supplies stubs for template methods."""
118
super(InstrumentedConfig, self).__init__()
41
def read(self, filenames):
42
self._calls.append(('read', filenames))
120
self._signatures = config.CHECK_NEVER
122
def _get_user_id(self):
123
self._calls.append('_get_user_id')
124
return "Robert Collins <robert.collins@example.org>"
126
def _get_signature_checking(self):
127
self._calls.append('_get_signature_checking')
128
return self._signatures
131
class TestConfig(TestCase):
133
def test_constructs(self):
136
def test_no_default_editor(self):
137
self.assertRaises(NotImplementedError, config.Config().get_editor)
139
def test_user_email(self):
140
my_config = InstrumentedConfig()
141
self.assertEqual('robert.collins@example.org', my_config.user_email())
142
self.assertEqual(['_get_user_id'], my_config._calls)
144
def test_username(self):
145
my_config = InstrumentedConfig()
146
self.assertEqual('Robert Collins <robert.collins@example.org>',
147
my_config.username())
148
self.assertEqual(['_get_user_id'], my_config._calls)
150
def test_signatures_default(self):
151
my_config = config.Config()
152
self.assertEqual(config.CHECK_IF_POSSIBLE,
153
my_config.signature_checking())
155
def test_signatures_template_method(self):
156
my_config = InstrumentedConfig()
157
self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
158
self.assertEqual(['_get_signature_checking'], my_config._calls)
160
def test_signatures_template_method_none(self):
161
my_config = InstrumentedConfig()
162
my_config._signatures = None
163
self.assertEqual(config.CHECK_IF_POSSIBLE,
164
my_config.signature_checking())
165
self.assertEqual(['_get_signature_checking'], my_config._calls)
167
def test_gpg_signing_command_default(self):
168
my_config = config.Config()
169
self.assertEqual('gpg', my_config.gpg_signing_command())
171
def test_get_user_option_default(self):
172
my_config = config.Config()
173
self.assertEqual(None, my_config.get_user_option('no_option'))
175
def test_post_commit_default(self):
176
my_config = config.Config()
177
self.assertEqual(None, my_config.post_commit())
45
180
class TestConfigPath(TestCase):
48
183
super(TestConfigPath, self).setUp()
49
self.oldenv = os.environ.get('HOME', None)
184
self.old_home = os.environ.get('HOME', None)
185
self.old_appdata = os.environ.get('APPDATA', None)
50
186
os.environ['HOME'] = '/home/bogus'
187
os.environ['APPDATA'] = \
188
r'C:\Documents and Settings\bogus\Application Data'
52
190
def tearDown(self):
53
os.environ['HOME'] = self.oldenv
191
if self.old_home is None:
192
del os.environ['HOME']
194
os.environ['HOME'] = self.old_home
195
if self.old_appdata is None:
196
del os.environ['APPDATA']
198
os.environ['APPDATA'] = self.old_appdata
199
super(TestConfigPath, self).tearDown()
55
201
def test_config_dir(self):
56
self.assertEqual(config.config_dir(), '/home/bogus/.bazaar')
202
if sys.platform == 'win32':
203
self.assertEqual(config.config_dir(),
204
'C:/Documents and Settings/bogus/Application Data/bazaar/2.0')
206
self.assertEqual(config.config_dir(), '/home/bogus/.bazaar')
58
208
def test_config_filename(self):
59
self.assertEqual(config.config_filename(),
60
'/home/bogus/.bazaar/bazaar.conf')
209
if sys.platform == 'win32':
210
self.assertEqual(config.config_filename(),
211
'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/bazaar.conf')
213
self.assertEqual(config.config_filename(),
214
'/home/bogus/.bazaar/bazaar.conf')
216
def test_branches_config_filename(self):
217
if sys.platform == 'win32':
218
self.assertEqual(config.branches_config_filename(),
219
'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/branches.conf')
221
self.assertEqual(config.branches_config_filename(),
222
'/home/bogus/.bazaar/branches.conf')
224
class TestIniConfig(TestCase):
226
def test_contructs(self):
227
my_config = config.IniBasedConfig("nothing")
229
def test_from_fp(self):
230
config_file = StringIO(sample_config_text)
231
my_config = config.IniBasedConfig(None)
233
isinstance(my_config._get_parser(file=config_file),
236
def test_cached(self):
237
config_file = StringIO(sample_config_text)
238
my_config = config.IniBasedConfig(None)
239
parser = my_config._get_parser(file=config_file)
240
self.failUnless(my_config._get_parser() is parser)
63
243
class TestGetConfig(TestCase):
65
def test_from_fp(self):
66
config_file = StringIO(sample_config_text)
67
self.failUnless(isinstance(config._get_config_parser(file=config_file),
245
def test_constructs(self):
246
my_config = config.GlobalConfig()
70
248
def test_calls_read_filenames(self):
71
# note the monkey patching. if config access was via a class instance,
72
# we would not have to - if this changes in future, be sure to stop
73
# monkey patching RBC 20051011
74
oldparserclass = config.ConfigParser
75
config.ConfigParser = InstrumentedConfigParser
249
# replace the class that is constructured, to check its parameters
250
oldparserclass = config.ConfigObj
251
config.ConfigObj = InstrumentedConfigObj
252
my_config = config.GlobalConfig()
77
parser = config._get_config_parser()
254
parser = my_config._get_parser()
79
config.ConfigParser = oldparserclass
80
self.failUnless(isinstance(parser, InstrumentedConfigParser))
81
self.assertEqual(parser._calls, [('read', [config.config_filename()])])
84
class TestConfigItems(TestCase):
87
super(TestConfigItems, self).setUp()
88
self.bzr_email = os.environ.get('BZREMAIL')
89
if self.bzr_email is not None:
90
del os.environ['BZREMAIL']
91
self.email = os.environ.get('EMAIL')
92
if self.email is not None:
93
del os.environ['EMAIL']
94
self.oldenv = os.environ.get('HOME', None)
95
os.environ['HOME'] = os.getcwd()
98
os.environ['HOME'] = self.oldenv
99
if self.bzr_email is not None:
100
os.environ['BZREMAIL'] = self.bzr_email
101
if self.email is not None:
102
os.environ['EMAIL'] = self.email
103
super(TestConfigItems, self).tearDown()
256
config.ConfigObj = oldparserclass
257
self.failUnless(isinstance(parser, InstrumentedConfigObj))
258
self.assertEqual(parser._calls, [('__init__', config.config_filename())])
261
class TestBranchConfig(TestCaseInTempDir):
263
def test_constructs(self):
264
branch = FakeBranch()
265
my_config = config.BranchConfig(branch)
266
self.assertRaises(TypeError, config.BranchConfig)
268
def test_get_location_config(self):
269
branch = FakeBranch()
270
my_config = config.BranchConfig(branch)
271
location_config = my_config._get_location_config()
272
self.assertEqual(branch.base, location_config.location)
273
self.failUnless(location_config is my_config._get_location_config())
276
class TestGlobalConfigItems(TestCase):
105
278
def test_user_id(self):
106
279
config_file = StringIO(sample_config_text)
107
parser = config._get_config_parser(file=config_file)
280
my_config = config.GlobalConfig()
281
my_config._parser = my_config._get_parser(file=config_file)
108
282
self.assertEqual("Robert Collins <robertc@example.com>",
109
config._get_user_id(parser = parser))
283
my_config._get_user_id())
111
285
def test_absent_user_id(self):
112
286
config_file = StringIO("")
113
parser = config._get_config_parser(file=config_file)
114
self.assertEqual(None,
115
config._get_user_id(parser = parser))
117
def test_configured_edit(self):
118
config_file = StringIO(sample_config_text)
119
parser = config._get_config_parser(file=config_file)
120
self.assertEqual("vim", config.get_editor(parser = parser))
287
my_config = config.GlobalConfig()
288
my_config._parser = my_config._get_parser(file=config_file)
289
self.assertEqual(None, my_config._get_user_id())
291
def test_configured_editor(self):
292
config_file = StringIO(sample_config_text)
293
my_config = config.GlobalConfig()
294
my_config._parser = my_config._get_parser(file=config_file)
295
self.assertEqual("vim", my_config.get_editor())
297
def test_signatures_always(self):
298
config_file = StringIO(sample_always_signatures)
299
my_config = config.GlobalConfig()
300
my_config._parser = my_config._get_parser(file=config_file)
301
self.assertEqual(config.CHECK_ALWAYS,
302
my_config.signature_checking())
303
self.assertEqual(True, my_config.signature_needed())
305
def test_signatures_if_possible(self):
306
config_file = StringIO(sample_maybe_signatures)
307
my_config = config.GlobalConfig()
308
my_config._parser = my_config._get_parser(file=config_file)
309
self.assertEqual(config.CHECK_IF_POSSIBLE,
310
my_config.signature_checking())
311
self.assertEqual(False, my_config.signature_needed())
313
def test_signatures_ignore(self):
314
config_file = StringIO(sample_ignore_signatures)
315
my_config = config.GlobalConfig()
316
my_config._parser = my_config._get_parser(file=config_file)
317
self.assertEqual(config.CHECK_NEVER,
318
my_config.signature_checking())
319
self.assertEqual(False, my_config.signature_needed())
321
def _get_sample_config(self):
322
config_file = StringIO(sample_config_text)
323
my_config = config.GlobalConfig()
324
my_config._parser = my_config._get_parser(file=config_file)
327
def test_gpg_signing_command(self):
328
my_config = self._get_sample_config()
329
self.assertEqual("gnome-gpg", my_config.gpg_signing_command())
330
self.assertEqual(False, my_config.signature_needed())
332
def _get_empty_config(self):
333
config_file = StringIO("")
334
my_config = config.GlobalConfig()
335
my_config._parser = my_config._get_parser(file=config_file)
338
def test_gpg_signing_command_unset(self):
339
my_config = self._get_empty_config()
340
self.assertEqual("gpg", my_config.gpg_signing_command())
342
def test_get_user_option_default(self):
343
my_config = self._get_empty_config()
344
self.assertEqual(None, my_config.get_user_option('no_option'))
346
def test_get_user_option_global(self):
347
my_config = self._get_sample_config()
348
self.assertEqual("something",
349
my_config.get_user_option('user_global_option'))
351
def test_post_commit_default(self):
352
my_config = self._get_sample_config()
353
self.assertEqual(None, my_config.post_commit())
356
class TestLocationConfig(TestCase):
358
def test_constructs(self):
359
my_config = config.LocationConfig('http://example.com')
360
self.assertRaises(TypeError, config.LocationConfig)
362
def test_branch_calls_read_filenames(self):
363
# This is testing the correct file names are provided.
364
# TODO: consolidate with the test for GlobalConfigs filename checks.
366
# replace the class that is constructured, to check its parameters
367
oldparserclass = config.ConfigObj
368
config.ConfigObj = InstrumentedConfigObj
369
my_config = config.LocationConfig('http://www.example.com')
371
parser = my_config._get_parser()
373
config.ConfigObj = oldparserclass
374
self.failUnless(isinstance(parser, InstrumentedConfigObj))
375
self.assertEqual(parser._calls,
376
[('__init__', config.branches_config_filename())])
378
def test_get_global_config(self):
379
my_config = config.LocationConfig('http://example.com')
380
global_config = my_config._get_global_config()
381
self.failUnless(isinstance(global_config, config.GlobalConfig))
382
self.failUnless(global_config is my_config._get_global_config())
384
def test__get_section_no_match(self):
385
self.get_location_config('/')
386
self.assertEqual(None, self.my_config._get_section())
388
def test__get_section_exact(self):
389
self.get_location_config('http://www.example.com')
390
self.assertEqual('http://www.example.com',
391
self.my_config._get_section())
393
def test__get_section_suffix_does_not(self):
394
self.get_location_config('http://www.example.com-com')
395
self.assertEqual(None, self.my_config._get_section())
397
def test__get_section_subdir_recursive(self):
398
self.get_location_config('http://www.example.com/com')
399
self.assertEqual('http://www.example.com',
400
self.my_config._get_section())
402
def test__get_section_subdir_matches(self):
403
self.get_location_config('http://www.example.com/useglobal')
404
self.assertEqual('http://www.example.com/useglobal',
405
self.my_config._get_section())
407
def test__get_section_subdir_nonrecursive(self):
408
self.get_location_config(
409
'http://www.example.com/useglobal/childbranch')
410
self.assertEqual('http://www.example.com',
411
self.my_config._get_section())
413
def test__get_section_subdir_trailing_slash(self):
414
self.get_location_config('/b')
415
self.assertEqual('/b/', self.my_config._get_section())
417
def test__get_section_subdir_child(self):
418
self.get_location_config('/a/foo')
419
self.assertEqual('/a/*', self.my_config._get_section())
421
def test__get_section_subdir_child_child(self):
422
self.get_location_config('/a/foo/bar')
423
self.assertEqual('/a/', self.my_config._get_section())
425
def test__get_section_trailing_slash_with_children(self):
426
self.get_location_config('/a/')
427
self.assertEqual('/a/', self.my_config._get_section())
429
def test__get_section_explicit_over_glob(self):
430
self.get_location_config('/a/c')
431
self.assertEqual('/a/c', self.my_config._get_section())
433
def get_location_config(self, location, global_config=None):
434
if global_config is None:
435
global_file = StringIO(sample_config_text)
437
global_file = StringIO(global_config)
438
branches_file = StringIO(sample_branches_text)
439
self.my_config = config.LocationConfig(location)
440
self.my_config._get_parser(branches_file)
441
self.my_config._get_global_config()._get_parser(global_file)
443
def test_location_without_username(self):
444
self.get_location_config('http://www.example.com/useglobal')
445
self.assertEqual('Robert Collins <robertc@example.com>',
446
self.my_config.username())
448
def test_location_not_listed(self):
449
self.get_location_config('/home/robertc/sources')
450
self.assertEqual('Robert Collins <robertc@example.com>',
451
self.my_config.username())
453
def test_overriding_location(self):
454
self.get_location_config('http://www.example.com/foo')
455
self.assertEqual('Robert Collins <robertc@example.org>',
456
self.my_config.username())
458
def test_signatures_not_set(self):
459
self.get_location_config('http://www.example.com',
460
global_config=sample_ignore_signatures)
461
self.assertEqual(config.CHECK_NEVER,
462
self.my_config.signature_checking())
464
def test_signatures_never(self):
465
self.get_location_config('/a/c')
466
self.assertEqual(config.CHECK_NEVER,
467
self.my_config.signature_checking())
469
def test_signatures_when_available(self):
470
self.get_location_config('/a/', global_config=sample_ignore_signatures)
471
self.assertEqual(config.CHECK_IF_POSSIBLE,
472
self.my_config.signature_checking())
474
def test_signatures_always(self):
475
self.get_location_config('/b')
476
self.assertEqual(config.CHECK_ALWAYS,
477
self.my_config.signature_checking())
479
def test_gpg_signing_command(self):
480
self.get_location_config('/b')
481
self.assertEqual("gnome-gpg", self.my_config.gpg_signing_command())
483
def test_gpg_signing_command_missing(self):
484
self.get_location_config('/a')
485
self.assertEqual("false", self.my_config.gpg_signing_command())
487
def test_get_user_option_global(self):
488
self.get_location_config('/a')
489
self.assertEqual('something',
490
self.my_config.get_user_option('user_global_option'))
492
def test_get_user_option_local(self):
493
self.get_location_config('/a')
494
self.assertEqual('local',
495
self.my_config.get_user_option('user_local_option'))
497
def test_post_commit_default(self):
498
self.get_location_config('/a/c')
499
self.assertEqual('bzrlib.tests.test_config.post_commit',
500
self.my_config.post_commit())
503
class TestLocationConfig(TestCaseInTempDir):
505
def get_location_config(self, location, global_config=None):
506
if global_config is None:
507
global_file = StringIO(sample_config_text)
509
global_file = StringIO(global_config)
510
branches_file = StringIO(sample_branches_text)
511
self.my_config = config.LocationConfig(location)
512
self.my_config._get_parser(branches_file)
513
self.my_config._get_global_config()._get_parser(global_file)
515
def test_set_user_setting_sets_and_saves(self):
516
self.get_location_config('/a/c')
517
record = InstrumentedConfigObj("foo")
518
self.my_config._parser = record
520
real_mkdir = os.mkdir
522
def checked_mkdir(path, mode=0777):
523
self.log('making directory: %s', path)
524
real_mkdir(path, mode)
527
os.mkdir = checked_mkdir
529
self.my_config.set_user_option('foo', 'bar')
531
os.mkdir = real_mkdir
533
self.failUnless(self.created, 'Failed to create ~/.bazaar')
534
self.assertEqual([('__contains__', '/a/c'),
535
('__contains__', '/a/c/'),
536
('__setitem__', '/a/c', {}),
537
('__getitem__', '/a/c'),
538
('__setitem__', 'foo', 'bar'),
543
class TestBranchConfigItems(TestCase):
545
def test_user_id(self):
546
branch = FakeBranch()
547
my_config = config.BranchConfig(branch)
548
self.assertEqual("Robert Collins <robertc@example.net>",
549
my_config._get_user_id())
550
branch.control_files.email = "John"
551
self.assertEqual("John", my_config._get_user_id())
553
def test_not_set_in_branch(self):
554
branch = FakeBranch()
555
my_config = config.BranchConfig(branch)
556
branch.control_files.email = None
557
config_file = StringIO(sample_config_text)
558
(my_config._get_location_config().
559
_get_global_config()._get_parser(config_file))
560
self.assertEqual("Robert Collins <robertc@example.com>",
561
my_config._get_user_id())
562
branch.control_files.email = "John"
563
self.assertEqual("John", my_config._get_user_id())
565
def test_BZREMAIL_OVERRIDES(self):
566
os.environ['BZREMAIL'] = "Robert Collins <robertc@example.org>"
567
branch = FakeBranch()
568
my_config = config.BranchConfig(branch)
569
self.assertEqual("Robert Collins <robertc@example.org>",
570
my_config.username())
572
def test_signatures_forced(self):
573
branch = FakeBranch()
574
my_config = config.BranchConfig(branch)
575
config_file = StringIO(sample_always_signatures)
576
(my_config._get_location_config().
577
_get_global_config()._get_parser(config_file))
578
self.assertEqual(config.CHECK_ALWAYS, my_config.signature_checking())
580
def test_gpg_signing_command(self):
581
branch = FakeBranch()
582
my_config = config.BranchConfig(branch)
583
config_file = StringIO(sample_config_text)
584
(my_config._get_location_config().
585
_get_global_config()._get_parser(config_file))
586
self.assertEqual('gnome-gpg', my_config.gpg_signing_command())
588
def test_get_user_option_global(self):
589
branch = FakeBranch()
590
my_config = config.BranchConfig(branch)
591
config_file = StringIO(sample_config_text)
592
(my_config._get_location_config().
593
_get_global_config()._get_parser(config_file))
594
self.assertEqual('something',
595
my_config.get_user_option('user_global_option'))
597
def test_post_commit_default(self):
598
branch = FakeBranch()
600
my_config = config.BranchConfig(branch)
601
config_file = StringIO(sample_config_text)
602
(my_config._get_location_config().
603
_get_global_config()._get_parser(config_file))
604
branch_file = StringIO(sample_branches_text)
605
my_config._get_location_config()._get_parser(branch_file)
606
self.assertEqual('bzrlib.tests.test_config.post_commit',
607
my_config.post_commit())
610
class TestMailAddressExtraction(TestCase):
612
def test_extract_email_address(self):
613
self.assertEqual('jane@test.com',
614
config.extract_email_address('Jane <jane@test.com>'))
615
self.assertRaises(errors.BzrError,
616
config.extract_email_address, 'Jane Tester')