176
164
# creating a dedicated helper to create only the bzrdir
177
165
build_backing_branch(test, 'branch', transport_class, server_class)
178
166
b = branch.Branch.open(test.get_url('branch'))
179
return config.RemoteControlStack(b.controldir)
167
return config.RemoteControlStack(b.bzrdir)
182
168
config.test_stack_builder_registry.register('remote_control',
183
169
build_remote_control_stack)
186
sample_long_alias = "log -r-15..-1 --line"
172
sample_long_alias="log -r-15..-1 --line"
187
173
sample_config_text = u"""
189
175
email=Erik B\u00e5gfors <erik@bagfors.nu>
191
change_editor=vimdiff -of {new_path} {old_path}
177
change_editor=vimdiff -of @new_path @old_path
178
gpg_signing_command=gnome-gpg
192
179
gpg_signing_key=DD4D5088
194
181
validate_signatures_in_log=true
499
486
my_config.username())
500
487
self.assertEqual(['_get_user_id'], my_config._calls)
489
def test_signatures_default(self):
490
my_config = config.Config()
492
self.applyDeprecated(deprecated_in((2, 5, 0)),
493
my_config.signature_needed))
494
self.assertEqual(config.CHECK_IF_POSSIBLE,
495
self.applyDeprecated(deprecated_in((2, 5, 0)),
496
my_config.signature_checking))
497
self.assertEqual(config.SIGN_WHEN_REQUIRED,
498
self.applyDeprecated(deprecated_in((2, 5, 0)),
499
my_config.signing_policy))
501
def test_signatures_template_method(self):
502
my_config = InstrumentedConfig()
503
self.assertEqual(config.CHECK_NEVER,
504
self.applyDeprecated(deprecated_in((2, 5, 0)),
505
my_config.signature_checking))
506
self.assertEqual(['_get_signature_checking'], my_config._calls)
508
def test_signatures_template_method_none(self):
509
my_config = InstrumentedConfig()
510
my_config._signatures = None
511
self.assertEqual(config.CHECK_IF_POSSIBLE,
512
self.applyDeprecated(deprecated_in((2, 5, 0)),
513
my_config.signature_checking))
514
self.assertEqual(['_get_signature_checking'], my_config._calls)
516
def test_gpg_signing_command_default(self):
517
my_config = config.Config()
518
self.assertEqual('gpg',
519
self.applyDeprecated(deprecated_in((2, 5, 0)),
520
my_config.gpg_signing_command))
502
522
def test_get_user_option_default(self):
503
523
my_config = config.Config()
504
524
self.assertEqual(None, my_config.get_user_option('no_option'))
526
def test_post_commit_default(self):
527
my_config = config.Config()
528
self.assertEqual(None, self.applyDeprecated(deprecated_in((2, 5, 0)),
529
my_config.post_commit))
532
def test_log_format_default(self):
533
my_config = config.Config()
534
self.assertEqual('long',
535
self.applyDeprecated(deprecated_in((2, 5, 0)),
536
my_config.log_format))
538
def test_acceptable_keys_default(self):
539
my_config = config.Config()
540
self.assertEqual(None, self.applyDeprecated(deprecated_in((2, 5, 0)),
541
my_config.acceptable_keys))
506
543
def test_validate_signatures_in_log_default(self):
507
544
my_config = config.Config()
508
545
self.assertEqual(False, my_config.validate_signatures_in_log())
512
549
change_editor = my_config.get_change_editor('old_tree', 'new_tree')
513
550
self.assertEqual(['_get_change_editor'], my_config._calls)
514
551
self.assertIs(diff.DiffFromTool, change_editor.__class__)
515
self.assertEqual(['vimdiff', '-fo', '{new_path}', '{old_path}'],
516
change_editor.command_template)
518
def test_get_change_editor_implicit_args(self):
519
# If there are no substitution variables, then assume the
520
# old and new path are the last arguments.
521
my_config = InstrumentedConfig()
522
my_config._change_editor = 'vimdiff -o'
523
change_editor = my_config.get_change_editor('old_tree', 'new_tree')
524
self.assertEqual(['_get_change_editor'], my_config._calls)
525
self.assertIs(diff.DiffFromTool, change_editor.__class__)
526
self.assertEqual(['vimdiff', '-o', '{old_path}', '{new_path}'],
527
change_editor.command_template)
529
def test_get_change_editor_old_style(self):
530
# Test the old style format for the change_editor setting.
531
my_config = InstrumentedConfig()
532
my_config._change_editor = 'vimdiff -o @old_path @new_path'
533
change_editor = my_config.get_change_editor('old_tree', 'new_tree')
534
self.assertEqual(['_get_change_editor'], my_config._calls)
535
self.assertIs(diff.DiffFromTool, change_editor.__class__)
536
self.assertEqual(['vimdiff', '-o', '{old_path}', '{new_path}'],
537
change_editor.command_template)
552
self.assertEqual(['vimdiff', '-fo', '@new_path', '@old_path'],
553
change_editor.command_template)
556
class TestConfigPath(tests.TestCase):
559
super(TestConfigPath, self).setUp()
560
self.overrideEnv('HOME', '/home/bogus')
561
self.overrideEnv('XDG_CACHE_HOME', '')
562
if sys.platform == 'win32':
564
'BZR_HOME', r'C:\Documents and Settings\bogus\Application Data')
566
'C:/Documents and Settings/bogus/Application Data/bazaar/2.0'
568
self.bzr_home = '/home/bogus/.bazaar'
570
def test_config_dir(self):
571
self.assertEqual(config.config_dir(), self.bzr_home)
573
def test_config_dir_is_unicode(self):
574
self.assertIsInstance(config.config_dir(), unicode)
576
def test_config_filename(self):
577
self.assertEqual(config.config_filename(),
578
self.bzr_home + '/bazaar.conf')
580
def test_locations_config_filename(self):
581
self.assertEqual(config.locations_config_filename(),
582
self.bzr_home + '/locations.conf')
584
def test_authentication_config_filename(self):
585
self.assertEqual(config.authentication_config_filename(),
586
self.bzr_home + '/authentication.conf')
588
def test_xdg_cache_dir(self):
589
self.assertEqual(config.xdg_cache_dir(),
590
'/home/bogus/.cache')
593
class TestXDGConfigDir(tests.TestCaseInTempDir):
594
# must be in temp dir because config tests for the existence of the bazaar
595
# subdirectory of $XDG_CONFIG_HOME
598
if sys.platform == 'win32':
599
raise tests.TestNotApplicable(
600
'XDG config dir not used on this platform')
601
super(TestXDGConfigDir, self).setUp()
602
self.overrideEnv('HOME', self.test_home_dir)
603
# BZR_HOME overrides everything we want to test so unset it.
604
self.overrideEnv('BZR_HOME', None)
606
def test_xdg_config_dir_exists(self):
607
"""When ~/.config/bazaar exists, use it as the config dir."""
608
newdir = osutils.pathjoin(self.test_home_dir, '.config', 'bazaar')
610
self.assertEqual(config.config_dir(), newdir)
612
def test_xdg_config_home(self):
613
"""When XDG_CONFIG_HOME is set, use it."""
614
xdgconfigdir = osutils.pathjoin(self.test_home_dir, 'xdgconfig')
615
self.overrideEnv('XDG_CONFIG_HOME', xdgconfigdir)
616
newdir = osutils.pathjoin(xdgconfigdir, 'bazaar')
618
self.assertEqual(config.config_dir(), newdir)
540
621
class TestIniConfig(tests.TestCaseInTempDir):
572
653
self.assertTrue(isinstance(self.uid, int))
573
654
self.assertTrue(isinstance(self.gid, int))
656
def test_get_filename_parameter_is_deprecated_(self):
657
conf = self.callDeprecated([
658
'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
659
' Use file_name instead.'],
660
config.IniBasedConfig, lambda: 'ini.conf')
661
self.assertEqual('ini.conf', conf.file_name)
663
def test_get_parser_file_parameter_is_deprecated_(self):
664
config_file = StringIO(sample_config_text.encode('utf-8'))
665
conf = config.IniBasedConfig.from_string(sample_config_text)
666
conf = self.callDeprecated([
667
'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
668
' Use IniBasedConfig(_content=xxx) instead.'],
669
conf._get_parser, file=config_file)
576
672
class TestIniConfigSaving(tests.TestCaseInTempDir):
835
928
self.assertEqual('c2', c2.get_user_option('one'))
837
930
def test_read_while_writing(self):
839
# We spawn a thread that will pause *during* the write
840
ready_to_write = threading.Event()
841
do_writing = threading.Event()
842
writing_done = threading.Event()
843
c1_orig = c1._write_config_file
845
def c1_write_config_file():
847
# The lock is held. We wait for the main thread to decide when to
852
c1._write_config_file = c1_write_config_file
855
c1.set_user_option('one', 'c1')
856
t1 = threading.Thread(target=c1_set_option)
857
# Collect the thread after the test
858
self.addCleanup(t1.join)
859
# Be ready to unblock the thread if the test goes wrong
860
self.addCleanup(do_writing.set)
862
# Ensure the thread is ready to write
863
ready_to_write.wait()
864
self.assertTrue(c1._lock.is_held)
865
self.assertEqual('c1', c1.get_user_option('one'))
866
# If we read during the write, we get the old value
867
c2 = self.get_existing_config()
868
self.assertEqual('1', c2.get_user_option('one'))
869
# Let the writing occur and ensure it occurred
872
# Now we get the updated value
873
c3 = self.get_existing_config()
874
self.assertEqual('c1', c3.get_user_option('one'))
932
# We spawn a thread that will pause *during* the write
933
ready_to_write = threading.Event()
934
do_writing = threading.Event()
935
writing_done = threading.Event()
936
c1_orig = c1._write_config_file
937
def c1_write_config_file():
939
# The lock is held. We wait for the main thread to decide when to
944
c1._write_config_file = c1_write_config_file
946
c1.set_user_option('one', 'c1')
947
t1 = threading.Thread(target=c1_set_option)
948
# Collect the thread after the test
949
self.addCleanup(t1.join)
950
# Be ready to unblock the thread if the test goes wrong
951
self.addCleanup(do_writing.set)
953
# Ensure the thread is ready to write
954
ready_to_write.wait()
955
self.assertTrue(c1._lock.is_held)
956
self.assertEqual('c1', c1.get_user_option('one'))
957
# If we read during the write, we get the old value
958
c2 = self.get_existing_config()
959
self.assertEqual('1', c2.get_user_option('one'))
960
# Let the writing occur and ensure it occurred
963
# Now we get the updated value
964
c3 = self.get_existing_config()
965
self.assertEqual('c1', c3.get_user_option('one'))
877
968
class TestGetUserOptionAs(TestIniConfig):
911
1001
# automatically cast to list
912
1002
self.assertEqual(['x'], get_list('one_item'))
1004
def test_get_user_option_as_int_from_SI(self):
1005
conf, parser = self.make_config_parser("""
1014
def get_si(s, default=None):
1015
return self.applyDeprecated(
1016
deprecated_in((2, 5, 0)),
1017
conf.get_user_option_as_int_from_SI, s, default)
1018
self.assertEqual(100, get_si('plain'))
1019
self.assertEqual(5000, get_si('si_k'))
1020
self.assertEqual(5000, get_si('si_kb'))
1021
self.assertEqual(5000000, get_si('si_m'))
1022
self.assertEqual(5000000, get_si('si_mb'))
1023
self.assertEqual(5000000000, get_si('si_g'))
1024
self.assertEqual(5000000000, get_si('si_gb'))
1025
self.assertEqual(None, get_si('non-exist'))
1026
self.assertEqual(42, get_si('non-exist-with-default', 42))
915
1029
class TestSupressWarning(TestIniConfig):
1083
1187
my_config = config.GlobalConfig()
1084
1188
self.assertEqual(None, my_config._get_user_id())
1190
def test_signatures_always(self):
1191
my_config = config.GlobalConfig.from_string(sample_always_signatures)
1192
self.assertEqual(config.CHECK_NEVER,
1193
self.applyDeprecated(deprecated_in((2, 5, 0)),
1194
my_config.signature_checking))
1195
self.assertEqual(config.SIGN_ALWAYS,
1196
self.applyDeprecated(deprecated_in((2, 5, 0)),
1197
my_config.signing_policy))
1198
self.assertEqual(True,
1199
self.applyDeprecated(deprecated_in((2, 5, 0)),
1200
my_config.signature_needed))
1202
def test_signatures_if_possible(self):
1203
my_config = config.GlobalConfig.from_string(sample_maybe_signatures)
1204
self.assertEqual(config.CHECK_NEVER,
1205
self.applyDeprecated(deprecated_in((2, 5, 0)),
1206
my_config.signature_checking))
1207
self.assertEqual(config.SIGN_WHEN_REQUIRED,
1208
self.applyDeprecated(deprecated_in((2, 5, 0)),
1209
my_config.signing_policy))
1210
self.assertEqual(False, self.applyDeprecated(deprecated_in((2, 5, 0)),
1211
my_config.signature_needed))
1213
def test_signatures_ignore(self):
1214
my_config = config.GlobalConfig.from_string(sample_ignore_signatures)
1215
self.assertEqual(config.CHECK_ALWAYS,
1216
self.applyDeprecated(deprecated_in((2, 5, 0)),
1217
my_config.signature_checking))
1218
self.assertEqual(config.SIGN_NEVER,
1219
self.applyDeprecated(deprecated_in((2, 5, 0)),
1220
my_config.signing_policy))
1221
self.assertEqual(False, self.applyDeprecated(deprecated_in((2, 5, 0)),
1222
my_config.signature_needed))
1224
def _get_sample_config(self):
1225
my_config = config.GlobalConfig.from_string(sample_config_text)
1228
def test_gpg_signing_command(self):
1229
my_config = self._get_sample_config()
1230
self.assertEqual("gnome-gpg",
1231
self.applyDeprecated(
1232
deprecated_in((2, 5, 0)), my_config.gpg_signing_command))
1233
self.assertEqual(False, self.applyDeprecated(deprecated_in((2, 5, 0)),
1234
my_config.signature_needed))
1236
def test_gpg_signing_key(self):
1237
my_config = self._get_sample_config()
1238
self.assertEqual("DD4D5088",
1239
self.applyDeprecated(deprecated_in((2, 5, 0)),
1240
my_config.gpg_signing_key))
1242
def _get_empty_config(self):
1243
my_config = config.GlobalConfig()
1246
def test_gpg_signing_command_unset(self):
1247
my_config = self._get_empty_config()
1248
self.assertEqual("gpg",
1249
self.applyDeprecated(
1250
deprecated_in((2, 5, 0)), my_config.gpg_signing_command))
1086
1252
def test_get_user_option_default(self):
1087
1253
my_config = self._get_empty_config()
1088
1254
self.assertEqual(None, my_config.get_user_option('no_option'))
1092
1258
self.assertEqual("something",
1093
1259
my_config.get_user_option('user_global_option'))
1261
def test_post_commit_default(self):
1262
my_config = self._get_sample_config()
1263
self.assertEqual(None,
1264
self.applyDeprecated(deprecated_in((2, 5, 0)),
1265
my_config.post_commit))
1267
def test_configured_logformat(self):
1268
my_config = self._get_sample_config()
1269
self.assertEqual("short",
1270
self.applyDeprecated(deprecated_in((2, 5, 0)),
1271
my_config.log_format))
1273
def test_configured_acceptable_keys(self):
1274
my_config = self._get_sample_config()
1275
self.assertEqual("amy",
1276
self.applyDeprecated(deprecated_in((2, 5, 0)),
1277
my_config.acceptable_keys))
1095
1279
def test_configured_validate_signatures_in_log(self):
1096
1280
my_config = self._get_sample_config()
1097
1281
self.assertEqual(True, my_config.validate_signatures_in_log())
1277
1461
self.get_branch_config('http://www.example.com')
1278
1462
self.assertEqual(
1279
1463
self.my_location_config._get_config_policy(
1280
'http://www.example.com', 'normal_option'),
1464
'http://www.example.com', 'normal_option'),
1281
1465
config.POLICY_NONE)
1283
1467
def test__get_option_policy_norecurse(self):
1284
1468
self.get_branch_config('http://www.example.com')
1285
1469
self.assertEqual(
1286
1470
self.my_location_config._get_option_policy(
1287
'http://www.example.com', 'norecurse_option'),
1471
'http://www.example.com', 'norecurse_option'),
1288
1472
config.POLICY_NORECURSE)
1289
1473
# Test old recurse=False setting:
1290
1474
self.assertEqual(
1291
1475
self.my_location_config._get_option_policy(
1292
'http://www.example.com/norecurse', 'normal_option'),
1476
'http://www.example.com/norecurse', 'normal_option'),
1293
1477
config.POLICY_NORECURSE)
1295
1479
def test__get_option_policy_normal(self):
1296
1480
self.get_branch_config('http://www.example.com')
1297
1481
self.assertEqual(
1298
1482
self.my_location_config._get_option_policy(
1299
'http://www.example.com', 'appendpath_option'),
1483
'http://www.example.com', 'appendpath_option'),
1300
1484
config.POLICY_APPENDPATH)
1302
1486
def test__get_options_with_policy(self):
1330
1514
self.assertEqual('Robert Collins <robertc@example.org>',
1331
1515
self.my_config.username())
1517
def test_signatures_not_set(self):
1518
self.get_branch_config('http://www.example.com',
1519
global_config=sample_ignore_signatures)
1520
self.assertEqual(config.CHECK_ALWAYS,
1521
self.applyDeprecated(deprecated_in((2, 5, 0)),
1522
self.my_config.signature_checking))
1523
self.assertEqual(config.SIGN_NEVER,
1524
self.applyDeprecated(deprecated_in((2, 5, 0)),
1525
self.my_config.signing_policy))
1527
def test_signatures_never(self):
1528
self.get_branch_config('/a/c')
1529
self.assertEqual(config.CHECK_NEVER,
1530
self.applyDeprecated(deprecated_in((2, 5, 0)),
1531
self.my_config.signature_checking))
1533
def test_signatures_when_available(self):
1534
self.get_branch_config('/a/', global_config=sample_ignore_signatures)
1535
self.assertEqual(config.CHECK_IF_POSSIBLE,
1536
self.applyDeprecated(deprecated_in((2, 5, 0)),
1537
self.my_config.signature_checking))
1539
def test_signatures_always(self):
1540
self.get_branch_config('/b')
1541
self.assertEqual(config.CHECK_ALWAYS,
1542
self.applyDeprecated(deprecated_in((2, 5, 0)),
1543
self.my_config.signature_checking))
1545
def test_gpg_signing_command(self):
1546
self.get_branch_config('/b')
1547
self.assertEqual("gnome-gpg",
1548
self.applyDeprecated(deprecated_in((2, 5, 0)),
1549
self.my_config.gpg_signing_command))
1551
def test_gpg_signing_command_missing(self):
1552
self.get_branch_config('/a')
1553
self.assertEqual("false",
1554
self.applyDeprecated(deprecated_in((2, 5, 0)),
1555
self.my_config.gpg_signing_command))
1557
def test_gpg_signing_key(self):
1558
self.get_branch_config('/b')
1559
self.assertEqual("DD4D5088", self.applyDeprecated(deprecated_in((2, 5, 0)),
1560
self.my_config.gpg_signing_key))
1562
def test_gpg_signing_key_default(self):
1563
self.get_branch_config('/a')
1564
self.assertEqual("erik@bagfors.nu",
1565
self.applyDeprecated(deprecated_in((2, 5, 0)),
1566
self.my_config.gpg_signing_key))
1333
1568
def test_get_user_option_global(self):
1334
1569
self.get_branch_config('/a')
1335
1570
self.assertEqual('something',
1396
1631
store=config.STORE_LOCATION)
1397
1632
self.assertEqual(
1398
1633
self.my_location_config._get_option_policy(
1399
'http://www.example.com', 'norecurse_option'),
1634
'http://www.example.com', 'norecurse_option'),
1637
def test_set_user_option_recurse_false_section(self):
1638
# The following section has recurse=False set. The test is to
1639
# make sure that a normal option can be added to the section,
1640
# converting recurse=False to the norecurse policy.
1641
self.get_branch_config('http://www.example.com/norecurse')
1642
self.callDeprecated(['The recurse option is deprecated as of 0.14. '
1643
'The section "http://www.example.com/norecurse" '
1644
'has been converted to use policies.'],
1645
self.my_config.set_user_option,
1646
'foo', 'bar', store=config.STORE_LOCATION)
1648
self.my_location_config._get_option_policy(
1649
'http://www.example.com/norecurse', 'foo'),
1651
# The previously existing option is still norecurse:
1653
self.my_location_config._get_option_policy(
1654
'http://www.example.com/norecurse', 'normal_option'),
1655
config.POLICY_NORECURSE)
1657
def test_post_commit_default(self):
1658
self.get_branch_config('/a/c')
1659
self.assertEqual('brzlib.tests.test_config.post_commit',
1660
self.applyDeprecated(deprecated_in((2, 5, 0)),
1661
self.my_config.post_commit))
1402
1663
def get_branch_config(self, location, global_config=None,
1403
1664
location_config=None):
1414
1675
self.my_config = my_config
1415
1676
self.my_location_config = my_config._get_location_config()
1678
def test_set_user_setting_sets_and_saves(self):
1679
self.get_branch_config('/a/c')
1680
record = InstrumentedConfigObj("foo")
1681
self.my_location_config._parser = record
1683
self.callDeprecated(['The recurse option is deprecated as of '
1684
'0.14. The section "/a/c" has been '
1685
'converted to use policies.'],
1686
self.my_config.set_user_option,
1687
'foo', 'bar', store=config.STORE_LOCATION)
1688
self.assertEqual([('reload',),
1689
('__contains__', '/a/c'),
1690
('__contains__', '/a/c/'),
1691
('__setitem__', '/a/c', {}),
1692
('__getitem__', '/a/c'),
1693
('__setitem__', 'foo', 'bar'),
1694
('__getitem__', '/a/c'),
1695
('as_bool', 'recurse'),
1696
('__getitem__', '/a/c'),
1697
('__delitem__', 'recurse'),
1698
('__getitem__', '/a/c'),
1700
('__getitem__', '/a/c'),
1701
('__contains__', 'foo:policy'),
1417
1705
def test_set_user_setting_sets_and_saves2(self):
1418
1706
self.get_branch_config('/a/c')
1419
1707
self.assertIs(self.my_config.get_user_option('foo'), None)
1420
1708
self.my_config.set_user_option('foo', 'bar')
1421
1709
self.assertEqual(
1422
1710
self.my_config.branch.control_files.files['branch.conf'].strip(),
1424
1712
self.assertEqual(self.my_config.get_user_option('foo'), 'bar')
1425
1713
self.my_config.set_user_option('foo', 'baz',
1426
1714
store=config.STORE_LOCATION)
1472
1759
my_config.set_user_option('email',
1473
1760
"Robert Collins <robertc@example.org>")
1474
1761
self.assertEqual("Robert Collins <robertc@example.org>",
1475
my_config.username())
1762
my_config.username())
1477
def test_BRZ_EMAIL_OVERRIDES(self):
1478
self.overrideEnv('BRZ_EMAIL', "Robert Collins <robertc@example.org>")
1764
def test_BZR_EMAIL_OVERRIDES(self):
1765
self.overrideEnv('BZR_EMAIL', "Robert Collins <robertc@example.org>")
1479
1766
branch = FakeBranch()
1480
1767
my_config = config.BranchConfig(branch)
1481
1768
self.assertEqual("Robert Collins <robertc@example.org>",
1482
1769
my_config.username())
1771
def test_signatures_forced(self):
1772
my_config = self.get_branch_config(
1773
global_config=sample_always_signatures)
1774
self.assertEqual(config.CHECK_NEVER,
1775
self.applyDeprecated(deprecated_in((2, 5, 0)),
1776
my_config.signature_checking))
1777
self.assertEqual(config.SIGN_ALWAYS,
1778
self.applyDeprecated(deprecated_in((2, 5, 0)),
1779
my_config.signing_policy))
1780
self.assertTrue(self.applyDeprecated(deprecated_in((2, 5, 0)),
1781
my_config.signature_needed))
1783
def test_signatures_forced_branch(self):
1784
my_config = self.get_branch_config(
1785
global_config=sample_ignore_signatures,
1786
branch_data_config=sample_always_signatures)
1787
self.assertEqual(config.CHECK_NEVER,
1788
self.applyDeprecated(deprecated_in((2, 5, 0)),
1789
my_config.signature_checking))
1790
self.assertEqual(config.SIGN_ALWAYS,
1791
self.applyDeprecated(deprecated_in((2, 5, 0)),
1792
my_config.signing_policy))
1793
self.assertTrue(self.applyDeprecated(deprecated_in((2, 5, 0)),
1794
my_config.signature_needed))
1796
def test_gpg_signing_command(self):
1797
my_config = self.get_branch_config(
1798
global_config=sample_config_text,
1799
# branch data cannot set gpg_signing_command
1800
branch_data_config="gpg_signing_command=pgp")
1801
self.assertEqual('gnome-gpg',
1802
self.applyDeprecated(deprecated_in((2, 5, 0)),
1803
my_config.gpg_signing_command))
1484
1805
def test_get_user_option_global(self):
1485
1806
my_config = self.get_branch_config(global_config=sample_config_text)
1486
1807
self.assertEqual('something',
1487
1808
my_config.get_user_option('user_global_option'))
1810
def test_post_commit_default(self):
1811
my_config = self.get_branch_config(global_config=sample_config_text,
1813
location_config=sample_branches_text)
1814
self.assertEqual(my_config.branch.base, '/a/c')
1815
self.assertEqual('brzlib.tests.test_config.post_commit',
1816
self.applyDeprecated(deprecated_in((2, 5, 0)),
1817
my_config.post_commit))
1818
my_config.set_user_option('post_commit', 'rmtree_root')
1819
# post-commit is ignored when present in branch data
1820
self.assertEqual('brzlib.tests.test_config.post_commit',
1821
self.applyDeprecated(deprecated_in((2, 5, 0)),
1822
my_config.post_commit))
1823
my_config.set_user_option('post_commit', 'rmtree_root',
1824
store=config.STORE_LOCATION)
1825
self.assertEqual('rmtree_root',
1826
self.applyDeprecated(deprecated_in((2, 5, 0)),
1827
my_config.post_commit))
1489
1829
def test_config_precedence(self):
1490
1830
# FIXME: eager test, luckily no persitent config file makes it fail
1491
1831
# -- vila 20100716
1572
1911
def test_load_non_ascii(self):
1573
1912
"""Ensure we display a proper error on non-ascii, non utf-8 content."""
1574
1913
t = self.get_transport()
1575
t.put_bytes('foo.conf', b'user=foo\n#\xff\n')
1914
t.put_bytes('foo.conf', 'user=foo\n#\xff\n')
1576
1915
conf = config.TransportConfig(t, 'foo.conf')
1577
self.assertRaises(config.ConfigContentError, conf._get_configobj)
1916
self.assertRaises(errors.ConfigContentError, conf._get_configobj)
1579
1918
def test_load_erroneous_content(self):
1580
1919
"""Ensure we display a proper error on content that can't be parsed."""
1581
1920
t = self.get_transport()
1582
t.put_bytes('foo.conf', b'[open_section\n')
1921
t.put_bytes('foo.conf', '[open_section\n')
1583
1922
conf = config.TransportConfig(t, 'foo.conf')
1584
self.assertRaises(config.ParseConfigError, conf._get_configobj)
1923
self.assertRaises(errors.ParseConfigError, conf._get_configobj)
1586
1925
def test_load_permission_denied(self):
1587
1926
"""Ensure we get an empty config file if the file is inaccessible."""
1590
1928
def warning(*args):
1591
1929
warnings.append(args[0] % args[1:])
1592
1930
self.overrideAttr(trace, 'warning', warning)
2193
2520
# the option name which indirectly requires that the option name is a
2194
2521
# valid python identifier. We violate that rule here (using a key that
2195
2522
# doesn't match the option name) to test the option name checking.
2196
self.assertRaises(config.IllegalOptionName,
2523
self.assertRaises(errors.IllegalOptionName,
2197
2524
self.registry.register_lazy, ' foo', self.__module__,
2198
2525
'TestOptionRegistry.lazy_option')
2199
self.assertRaises(config.IllegalOptionName,
2526
self.assertRaises(errors.IllegalOptionName,
2200
2527
self.registry.register_lazy, '1,2', self.__module__,
2201
2528
'TestOptionRegistry.lazy_option')
2380
2705
def test_building_delays_load(self):
2381
2706
store = self.get_store(self)
2382
2707
self.assertEqual(False, store.is_loaded())
2383
store._load_from_string(b'')
2708
store._load_from_string('')
2384
2709
self.assertEqual(True, store.is_loaded())
2386
2711
def test_get_no_sections_for_empty(self):
2387
2712
store = self.get_store(self)
2388
store._load_from_string(b'')
2713
store._load_from_string('')
2389
2714
self.assertEqual([], list(store.get_sections()))
2391
2716
def test_get_default_section(self):
2392
2717
store = self.get_store(self)
2393
store._load_from_string(b'foo=bar')
2718
store._load_from_string('foo=bar')
2394
2719
sections = list(store.get_sections())
2395
2720
self.assertLength(1, sections)
2396
2721
self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
2398
2723
def test_get_named_section(self):
2399
2724
store = self.get_store(self)
2400
store._load_from_string(b'[baz]\nfoo=bar')
2725
store._load_from_string('[baz]\nfoo=bar')
2401
2726
sections = list(store.get_sections())
2402
2727
self.assertLength(1, sections)
2403
2728
self.assertSectionContent(('baz', {'foo': 'bar'}), sections[0])
2405
2730
def test_load_from_string_fails_for_non_empty_store(self):
2406
2731
store = self.get_store(self)
2407
store._load_from_string(b'foo=bar')
2408
self.assertRaises(AssertionError, store._load_from_string, b'bar=baz')
2732
store._load_from_string('foo=bar')
2733
self.assertRaises(AssertionError, store._load_from_string, 'bar=baz')
2411
2736
class TestStoreQuoting(TestStore):
2509
2834
def test_load_non_ascii(self):
2510
2835
"""Ensure we display a proper error on non-ascii, non utf-8 content."""
2511
2836
t = self.get_transport()
2512
t.put_bytes('foo.conf', b'user=foo\n#%s\n' % (self.invalid_utf8_char,))
2837
t.put_bytes('foo.conf', 'user=foo\n#%s\n' % (self.invalid_utf8_char,))
2513
2838
store = config.TransportIniFileStore(t, 'foo.conf')
2514
self.assertRaises(config.ConfigContentError, store.load)
2839
self.assertRaises(errors.ConfigContentError, store.load)
2516
2841
def test_load_erroneous_content(self):
2517
2842
"""Ensure we display a proper error on content that can't be parsed."""
2518
2843
t = self.get_transport()
2519
t.put_bytes('foo.conf', b'[open_section\n')
2844
t.put_bytes('foo.conf', '[open_section\n')
2520
2845
store = config.TransportIniFileStore(t, 'foo.conf')
2521
self.assertRaises(config.ParseConfigError, store.load)
2846
self.assertRaises(errors.ParseConfigError, store.load)
2523
2848
def test_load_permission_denied(self):
2524
2849
"""Ensure we get warned when trying to load an inaccessible file."""
2527
2851
def warning(*args):
2528
2852
warnings.append(args[0] % args[1:])
2529
2853
self.overrideAttr(trace, 'warning', warning)
2567
2891
def test_load_badly_encoded_content(self):
2568
2892
"""Ensure we display a proper error on non-ascii, non utf-8 content."""
2569
2893
with open('foo.conf', 'wb') as f:
2570
f.write(b'user=foo\n#%s\n' % (self.invalid_utf8_char,))
2894
f.write('user=foo\n#%s\n' % (self.invalid_utf8_char,))
2571
2895
conf = config.IniBasedConfig(file_name='foo.conf')
2572
self.assertRaises(config.ConfigContentError, conf._get_parser)
2896
self.assertRaises(errors.ConfigContentError, conf._get_parser)
2574
2898
def test_load_erroneous_content(self):
2575
2899
"""Ensure we display a proper error on content that can't be parsed."""
2576
2900
with open('foo.conf', 'wb') as f:
2577
f.write(b'[open_section\n')
2901
f.write('[open_section\n')
2578
2902
conf = config.IniBasedConfig(file_name='foo.conf')
2579
self.assertRaises(config.ParseConfigError, conf._get_parser)
2903
self.assertRaises(errors.ParseConfigError, conf._get_parser)
2582
2906
class TestMutableStore(TestStore):
2850
3171
stack = config.Stack([store.get_sections], store)
2851
3172
stack.set('foo', ' a b c ')
2853
self.assertFileEqual(b'foo = " a b c "' +
2854
os.linesep.encode('ascii'), 'foo.conf')
3174
self.assertFileEqual('foo = " a b c "' + os.linesep, 'foo.conf')
2857
3177
class TestTransportIniFileStore(TestStore):
2859
3179
def test_loading_unknown_file_fails(self):
2860
3180
store = config.TransportIniFileStore(self.get_transport(),
2862
3182
self.assertRaises(errors.NoSuchFile, store.load)
2864
3184
def test_invalid_content(self):
2865
3185
store = config.TransportIniFileStore(self.get_transport(), 'foo.conf')
2866
3186
self.assertEqual(False, store.is_loaded())
2867
3187
exc = self.assertRaises(
2868
config.ParseConfigError, store._load_from_string,
2869
b'this is invalid !')
3188
errors.ParseConfigError, store._load_from_string,
3189
'this is invalid !')
2870
3190
self.assertEndsWith(exc.filename, 'foo.conf')
2871
3191
# And the load failed
2872
3192
self.assertEqual(False, store.is_loaded())
3010
3328
self.assertEqual('c2', c2.get('one'))
3012
3330
def test_read_while_writing(self):
3014
# We spawn a thread that will pause *during* the write
3015
ready_to_write = threading.Event()
3016
do_writing = threading.Event()
3017
writing_done = threading.Event()
3018
# We override the _save implementation so we know the store is locked
3019
c1_save_without_locking_orig = c1.store.save_without_locking
3021
def c1_save_without_locking():
3022
ready_to_write.set()
3023
# The lock is held. We wait for the main thread to decide when to
3026
c1_save_without_locking_orig()
3028
c1.store.save_without_locking = c1_save_without_locking
3032
t1 = threading.Thread(target=c1_set)
3033
# Collect the thread after the test
3034
self.addCleanup(t1.join)
3035
# Be ready to unblock the thread if the test goes wrong
3036
self.addCleanup(do_writing.set)
3038
# Ensure the thread is ready to write
3039
ready_to_write.wait()
3040
self.assertEqual('c1', c1.get('one'))
3041
# If we read during the write, we get the old value
3042
c2 = self.get_stack(self)
3043
self.assertEqual('1', c2.get('one'))
3044
# Let the writing occur and ensure it occurred
3047
# Now we get the updated value
3048
c3 = self.get_stack(self)
3049
self.assertEqual('c1', c3.get('one'))
3332
# We spawn a thread that will pause *during* the write
3333
ready_to_write = threading.Event()
3334
do_writing = threading.Event()
3335
writing_done = threading.Event()
3336
# We override the _save implementation so we know the store is locked
3337
c1_save_without_locking_orig = c1.store.save_without_locking
3338
def c1_save_without_locking():
3339
ready_to_write.set()
3340
# The lock is held. We wait for the main thread to decide when to
3343
c1_save_without_locking_orig()
3345
c1.store.save_without_locking = c1_save_without_locking
3348
t1 = threading.Thread(target=c1_set)
3349
# Collect the thread after the test
3350
self.addCleanup(t1.join)
3351
# Be ready to unblock the thread if the test goes wrong
3352
self.addCleanup(do_writing.set)
3354
# Ensure the thread is ready to write
3355
ready_to_write.wait()
3356
self.assertEqual('c1', c1.get('one'))
3357
# If we read during the write, we get the old value
3358
c2 = self.get_stack(self)
3359
self.assertEqual('1', c2.get('one'))
3360
# Let the writing occur and ensure it occurred
3363
# Now we get the updated value
3364
c3 = self.get_stack(self)
3365
self.assertEqual('c1', c3.get('one'))
3051
3367
# FIXME: It may be worth looking into removing the lock dir when it's not
3052
3368
# needed anymore and look at possible fallouts for concurrent lockers. This
3053
# will matter if/when we use config files outside of breezy directories
3054
# (.config/breezy or .bzr) -- vila 20110-04-111
3369
# will matter if/when we use config files outside of bazaar directories
3370
# (.bazaar or .bzr) -- vila 20110-04-111
3057
3373
class TestSectionMatcher(TestStore):
3059
3375
scenarios = [('location', {'matcher': config.LocationMatcher}),
3060
('id', {'matcher': config.NameMatcher}), ]
3376
('id', {'matcher': config.NameMatcher}),]
3062
3378
def setUp(self):
3063
3379
super(TestSectionMatcher, self).setUp()
3120
3436
section=/quux/quux
3122
3438
self.assertEqual(['/foo', '/foo/baz', '/foo/bar', '/foo/bar/baz',
3124
[section.id for _, section in store.get_sections()])
3440
[section.id for _, section in store.get_sections()])
3125
3441
matcher = config.LocationMatcher(store, '/foo/bar/quux')
3126
3442
sections = [section for _, section in matcher.get_sections()]
3127
3443
self.assertEqual(['/foo/bar', '/foo'],
3128
[section.id for section in sections])
3444
[section.id for section in sections])
3129
3445
self.assertEqual(['quux', 'bar/quux'],
3130
[section.extra_path for section in sections])
3446
[section.extra_path for section in sections])
3132
3448
def test_more_specific_sections_first(self):
3133
3449
store = self.get_store(self)
3134
store._load_from_string(b'''
3450
store._load_from_string('''
3138
3454
section=/foo/bar
3140
3456
self.assertEqual(['/foo', '/foo/bar'],
3141
[section.id for _, section in store.get_sections()])
3457
[section.id for _, section in store.get_sections()])
3142
3458
matcher = config.LocationMatcher(store, '/foo/bar/baz')
3143
3459
sections = [section for _, section in matcher.get_sections()]
3144
3460
self.assertEqual(['/foo/bar', '/foo'],
3145
[section.id for section in sections])
3461
[section.id for section in sections])
3146
3462
self.assertEqual(['baz', 'bar/baz'],
3147
[section.extra_path for section in sections])
3463
[section.extra_path for section in sections])
3149
3465
def test_appendpath_in_no_name_section(self):
3150
3466
# It's a bit weird to allow appendpath in a no-name section, but
3151
3467
# someone may found a use for it
3152
3468
store = self.get_store(self)
3153
store._load_from_string(b'''
3469
store._load_from_string('''
3155
3471
foo:policy = appendpath
3222
3538
def test_local_path_vs_url(self):
3223
3539
# The matcher location is a local path and the section names are urls
3224
3540
self.assertSectionIDs(['file:///foo/bar', 'file:///foo'],
3225
'/foo/bar/baz', b'''\
3541
'/foo/bar/baz', '''\
3227
3543
[file:///foo/bar]
3230
3547
def test_no_name_section_included_when_present(self):
3231
3548
# Note that other tests will cover the case where the no-name section
3232
3549
# is empty and as such, not included.
3233
3550
sections = self.assertSectionIDs(['/foo/bar', '/foo', None],
3234
'/foo/bar/baz', b'''\
3551
'/foo/bar/baz', '''\
3235
3552
option = defined so the no-name section exists
3239
3556
self.assertEqual(['baz', 'bar/baz', '/foo/bar/baz'],
3240
[s.locals['relpath'] for _, s in sections])
3557
[s.locals['relpath'] for _, s in sections])
3242
3559
def test_order_reversed(self):
3243
self.assertSectionIDs(['/foo/bar', '/foo'], '/foo/bar/baz', b'''\
3560
self.assertSectionIDs(['/foo/bar', '/foo'], '/foo/bar/baz', '''\
3248
3565
def test_unrelated_section_excluded(self):
3249
self.assertSectionIDs(['/foo/bar', '/foo'], '/foo/bar/baz', b'''\
3566
self.assertSectionIDs(['/foo/bar', '/foo'], '/foo/bar/baz', '''\
3489
3805
def test_get_default_bool_None(self):
3490
3806
self.register_bool_option('foo')
3491
conf = self.get_conf(b'')
3807
conf = self.get_conf('')
3492
3808
self.assertEqual(None, conf.get('foo'))
3494
3810
def test_get_default_bool_True(self):
3495
3811
self.register_bool_option('foo', u'True')
3496
conf = self.get_conf(b'')
3812
conf = self.get_conf('')
3497
3813
self.assertEqual(True, conf.get('foo'))
3499
3815
def test_get_default_bool_False(self):
3500
3816
self.register_bool_option('foo', False)
3501
conf = self.get_conf(b'')
3817
conf = self.get_conf('')
3502
3818
self.assertEqual(False, conf.get('foo'))
3504
3820
def test_get_default_bool_False_as_string(self):
3505
3821
self.register_bool_option('foo', u'False')
3506
conf = self.get_conf(b'')
3822
conf = self.get_conf('')
3507
3823
self.assertEqual(False, conf.get('foo'))
3509
3825
def test_get_default_bool_from_env_converted(self):
3510
3826
self.register_bool_option('foo', u'True', default_from_env=['FOO'])
3511
3827
self.overrideEnv('FOO', 'False')
3512
conf = self.get_conf(b'')
3828
conf = self.get_conf('')
3513
3829
self.assertEqual(False, conf.get('foo'))
3515
3831
def test_get_default_bool_when_conversion_fails(self):
3516
3832
self.register_bool_option('foo', default='True')
3517
conf = self.get_conf(b'foo=invalid boolean')
3833
conf = self.get_conf('foo=invalid boolean')
3518
3834
self.assertEqual(True, conf.get('foo'))
3520
3836
def register_integer_option(self, name,
3527
3843
def test_get_default_integer_None(self):
3528
3844
self.register_integer_option('foo')
3529
conf = self.get_conf(b'')
3845
conf = self.get_conf('')
3530
3846
self.assertEqual(None, conf.get('foo'))
3532
3848
def test_get_default_integer(self):
3533
3849
self.register_integer_option('foo', 42)
3534
conf = self.get_conf(b'')
3850
conf = self.get_conf('')
3535
3851
self.assertEqual(42, conf.get('foo'))
3537
3853
def test_get_default_integer_as_string(self):
3538
3854
self.register_integer_option('foo', u'42')
3539
conf = self.get_conf(b'')
3855
conf = self.get_conf('')
3540
3856
self.assertEqual(42, conf.get('foo'))
3542
3858
def test_get_default_integer_from_env(self):
3543
3859
self.register_integer_option('foo', default_from_env=['FOO'])
3544
3860
self.overrideEnv('FOO', '18')
3545
conf = self.get_conf(b'')
3861
conf = self.get_conf('')
3546
3862
self.assertEqual(18, conf.get('foo'))
3548
3864
def test_get_default_integer_when_conversion_fails(self):
3549
3865
self.register_integer_option('foo', default='12')
3550
conf = self.get_conf(b'foo=invalid integer')
3866
conf = self.get_conf('foo=invalid integer')
3551
3867
self.assertEqual(12, conf.get('foo'))
3553
3869
def register_list_option(self, name, default=None, default_from_env=None):
3558
3874
def test_get_default_list_None(self):
3559
3875
self.register_list_option('foo')
3560
conf = self.get_conf(b'')
3876
conf = self.get_conf('')
3561
3877
self.assertEqual(None, conf.get('foo'))
3563
3879
def test_get_default_list_empty(self):
3564
3880
self.register_list_option('foo', '')
3565
conf = self.get_conf(b'')
3881
conf = self.get_conf('')
3566
3882
self.assertEqual([], conf.get('foo'))
3568
3884
def test_get_default_list_from_env(self):
3569
3885
self.register_list_option('foo', default_from_env=['FOO'])
3570
3886
self.overrideEnv('FOO', '')
3571
conf = self.get_conf(b'')
3887
conf = self.get_conf('')
3572
3888
self.assertEqual([], conf.get('foo'))
3574
3890
def test_get_with_list_converter_no_item(self):
3575
3891
self.register_list_option('foo', None)
3576
conf = self.get_conf(b'foo=,')
3892
conf = self.get_conf('foo=,')
3577
3893
self.assertEqual([], conf.get('foo'))
3579
3895
def test_get_with_list_converter_many_items(self):
3580
3896
self.register_list_option('foo', None)
3581
conf = self.get_conf(b'foo=m,o,r,e')
3897
conf = self.get_conf('foo=m,o,r,e')
3582
3898
self.assertEqual(['m', 'o', 'r', 'e'], conf.get('foo'))
3584
3900
def test_get_with_list_converter_embedded_spaces_many_items(self):
3585
3901
self.register_list_option('foo', None)
3586
conf = self.get_conf(b'foo=" bar", "baz "')
3902
conf = self.get_conf('foo=" bar", "baz "')
3587
3903
self.assertEqual([' bar', 'baz '], conf.get('foo'))
3589
3905
def test_get_with_list_converter_stripped_spaces_many_items(self):
3590
3906
self.register_list_option('foo', None)
3591
conf = self.get_conf(b'foo= bar , baz ')
3907
conf = self.get_conf('foo= bar , baz ')
3592
3908
self.assertEqual(['bar', 'baz'], conf.get('foo'))
3640
3956
self.assertExpansion('foo', 'foo')
3642
3958
def test_expand_default_value(self):
3643
self.conf.store._load_from_string(b'bar=baz')
3959
self.conf.store._load_from_string('bar=baz')
3644
3960
self.registry.register(config.Option('foo', default=u'{bar}'))
3645
3961
self.assertEqual('baz', self.conf.get('foo', expand=True))
3647
3963
def test_expand_default_from_env(self):
3648
self.conf.store._load_from_string(b'bar=baz')
3964
self.conf.store._load_from_string('bar=baz')
3649
3965
self.registry.register(config.Option('foo', default_from_env=['FOO']))
3650
3966
self.overrideEnv('FOO', '{bar}')
3651
3967
self.assertEqual('baz', self.conf.get('foo', expand=True))
3653
3969
def test_expand_default_on_failed_conversion(self):
3654
self.conf.store._load_from_string(b'baz=bogus\nbar=42\nfoo={baz}')
3970
self.conf.store._load_from_string('baz=bogus\nbar=42\nfoo={baz}')
3655
3971
self.registry.register(
3656
3972
config.Option('foo', default=u'{bar}',
3657
3973
from_unicode=config.int_from_store))
3661
3977
self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3663
3979
def test_env_overriding_options(self):
3664
self.conf.store._load_from_string(b'foo=baz')
3980
self.conf.store._load_from_string('foo=baz')
3665
3981
self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3667
3983
def test_simple_ref(self):
3668
self.conf.store._load_from_string(b'foo=xxx')
3984
self.conf.store._load_from_string('foo=xxx')
3669
3985
self.assertExpansion('xxx', '{foo}')
3671
3987
def test_unknown_ref(self):
3672
self.assertRaises(config.ExpandingUnknownOption,
3988
self.assertRaises(errors.ExpandingUnknownOption,
3673
3989
self.conf.expand_options, '{foo}')
3675
3991
def test_illegal_def_is_ignored(self):
3678
3994
self.assertExpansion('${Foo,f}', '${Foo,f}')
3680
3996
def test_indirect_ref(self):
3681
self.conf.store._load_from_string(b'''
3997
self.conf.store._load_from_string('''
3685
4001
self.assertExpansion('xxx', '{bar}')
3687
4003
def test_embedded_ref(self):
3688
self.conf.store._load_from_string(b'''
4004
self.conf.store._load_from_string('''
3692
4008
self.assertExpansion('xxx', '{{bar}}')
3694
4010
def test_simple_loop(self):
3695
self.conf.store._load_from_string(b'foo={foo}')
3696
self.assertRaises(config.OptionExpansionLoop,
4011
self.conf.store._load_from_string('foo={foo}')
4012
self.assertRaises(errors.OptionExpansionLoop,
3697
4013
self.conf.expand_options, '{foo}')
3699
4015
def test_indirect_loop(self):
3700
self.conf.store._load_from_string(b'''
4016
self.conf.store._load_from_string('''
3704
e = self.assertRaises(config.OptionExpansionLoop,
4020
e = self.assertRaises(errors.OptionExpansionLoop,
3705
4021
self.conf.expand_options, '{foo}')
3706
4022
self.assertEqual('foo->bar->baz', e.refs)
3707
4023
self.assertEqual('{foo}', e.string)
3709
4025
def test_list(self):
3710
self.conf.store._load_from_string(b'''
4026
self.conf.store._load_from_string('''
3855
4171
def test_expand_relpath_unknonw_in_global(self):
3856
4172
g_store = config.GlobalStore()
3857
g_store._load_from_string(b'''
4173
g_store._load_from_string('''
3859
4175
gfoo = {relpath}
3862
4178
stack = config.LocationStack('/home/user/project/branch')
3863
self.assertRaises(config.ExpandingUnknownOption,
4179
self.assertRaises(errors.ExpandingUnknownOption,
3864
4180
stack.get, 'gfoo', expand=True)
3866
4182
def test_expand_local_option_locally(self):
3867
4183
l_store = config.LocationStore()
3868
l_store._load_from_string(b'''
4184
l_store._load_from_string('''
3869
4185
[/home/user/project]
3870
4186
lfoo = loc-foo/{relpath}
3874
4190
g_store = config.GlobalStore()
3875
g_store._load_from_string(b'''
4191
g_store._load_from_string('''
3878
4194
gbar = glob-bar
3961
4276
create_configs(self)
3963
4278
def test_no_variable(self):
3964
# Using branch should query branch, locations and breezy
4279
# Using branch should query branch, locations and bazaar
3965
4280
self.assertOptions([], self.branch_config)
3967
def test_option_in_breezy(self):
3968
self.breezy_config.set_user_option('file', 'breezy')
3969
self.assertOptions([('file', 'breezy', 'DEFAULT', 'breezy')],
4282
def test_option_in_bazaar(self):
4283
self.bazaar_config.set_user_option('file', 'bazaar')
4284
self.assertOptions([('file', 'bazaar', 'DEFAULT', 'bazaar')],
3972
4287
def test_option_in_locations(self):
3973
4288
self.locations_config.set_user_option('file', 'locations')
3980
4295
self.assertOptions([('file', 'branch', 'DEFAULT', 'branch')],
3981
4296
self.branch_config)
3983
def test_option_in_breezy_and_branch(self):
3984
self.breezy_config.set_user_option('file', 'breezy')
4298
def test_option_in_bazaar_and_branch(self):
4299
self.bazaar_config.set_user_option('file', 'bazaar')
3985
4300
self.branch_config.set_user_option('file', 'branch')
3986
4301
self.assertOptions([('file', 'branch', 'DEFAULT', 'branch'),
3987
('file', 'breezy', 'DEFAULT', 'breezy'), ],
4302
('file', 'bazaar', 'DEFAULT', 'bazaar'),],
3988
4303
self.branch_config)
3990
4305
def test_option_in_branch_and_locations(self):
3993
4308
self.branch_config.set_user_option('file', 'branch')
3994
4309
self.assertOptions(
3995
4310
[('file', 'locations', self.tree.basedir, 'locations'),
3996
('file', 'branch', 'DEFAULT', 'branch'), ],
4311
('file', 'branch', 'DEFAULT', 'branch'),],
3997
4312
self.branch_config)
3999
def test_option_in_breezy_locations_and_branch(self):
4000
self.breezy_config.set_user_option('file', 'breezy')
4314
def test_option_in_bazaar_locations_and_branch(self):
4315
self.bazaar_config.set_user_option('file', 'bazaar')
4001
4316
self.locations_config.set_user_option('file', 'locations')
4002
4317
self.branch_config.set_user_option('file', 'branch')
4003
4318
self.assertOptions(
4004
4319
[('file', 'locations', self.tree.basedir, 'locations'),
4005
4320
('file', 'branch', 'DEFAULT', 'branch'),
4006
('file', 'breezy', 'DEFAULT', 'breezy'), ],
4321
('file', 'bazaar', 'DEFAULT', 'bazaar'),],
4007
4322
self.branch_config)
4017
4332
self.locations_config.remove_user_option('file', self.tree.basedir)
4018
4333
self.assertOptions(
4019
4334
[('file', 'branch', 'DEFAULT', 'branch'),
4020
('file', 'breezy', 'DEFAULT', 'breezy'), ],
4335
('file', 'bazaar', 'DEFAULT', 'bazaar'),],
4021
4336
self.branch_config)
4023
4338
def test_remove_in_branch(self):
4024
4339
self.branch_config.remove_user_option('file')
4025
4340
self.assertOptions(
4026
4341
[('file', 'locations', self.tree.basedir, 'locations'),
4027
('file', 'breezy', 'DEFAULT', 'breezy'), ],
4342
('file', 'bazaar', 'DEFAULT', 'bazaar'),],
4028
4343
self.branch_config)
4030
def test_remove_in_breezy(self):
4031
self.breezy_config.remove_user_option('file')
4345
def test_remove_in_bazaar(self):
4346
self.bazaar_config.remove_user_option('file')
4032
4347
self.assertOptions(
4033
4348
[('file', 'locations', self.tree.basedir, 'locations'),
4034
('file', 'branch', 'DEFAULT', 'branch'), ],
4349
('file', 'branch', 'DEFAULT', 'branch'),],
4035
4350
self.branch_config)
4098
4413
self.assertSectionNames([self.tree.basedir, None, 'DEFAULT'],
4099
4414
self.branch_config)
4101
def test_breezy_named_section(self):
4416
def test_bazaar_named_section(self):
4102
4417
# We need to cheat as the API doesn't give direct access to sections
4103
4418
# other than DEFAULT.
4104
self.breezy_config.set_alias('breezy', 'bzr')
4105
self.assertSectionNames(['ALIASES'], self.breezy_config, 'ALIASES')
4419
self.bazaar_config.set_alias('bazaar', 'bzr')
4420
self.assertSectionNames(['ALIASES'], self.bazaar_config, 'ALIASES')
4108
4423
class TestSharedStores(tests.TestCaseInTempDir):
4110
def test_breezy_conf_shared(self):
4425
def test_bazaar_conf_shared(self):
4111
4426
g1 = config.GlobalStack()
4112
4427
g2 = config.GlobalStack()
4113
4428
# The two stacks share the same store
4114
4429
self.assertIs(g1.store, g2.store)
4117
class TestAuthenticationConfigFilePermissions(tests.TestCaseInTempDir):
4118
"""Test warning for permissions of authentication.conf."""
4121
super(TestAuthenticationConfigFilePermissions, self).setUp()
4122
self.path = osutils.pathjoin(self.test_dir, 'authentication.conf')
4123
with open(self.path, 'wb') as f:
4124
f.write(b"""[broken]
4127
port=port # Error: Not an int
4129
self.overrideAttr(bedding, 'authentication_config_path',
4131
osutils.chmod_if_possible(self.path, 0o755)
4133
def test_check_warning(self):
4134
conf = config.AuthenticationConfig()
4135
self.assertEqual(conf._filename, self.path)
4136
self.assertContainsRe(self.get_log(),
4137
'Saved passwords may be accessible by other users.')
4139
def test_check_suppressed_warning(self):
4140
global_config = config.GlobalConfig()
4141
global_config.set_user_option('suppress_warnings',
4142
'insecure_permissions')
4143
conf = config.AuthenticationConfig()
4144
self.assertEqual(conf._filename, self.path)
4145
self.assertNotContainsRe(self.get_log(),
4146
'Saved passwords may be accessible by other users.')
4149
4432
class TestAuthenticationConfigFile(tests.TestCase):
4150
4433
"""Test the authentication.conf file matching"""
4162
4445
self.assertEqual(expected_password, password)
4164
4447
def test_empty_config(self):
4165
conf = config.AuthenticationConfig(_file=BytesIO())
4448
conf = config.AuthenticationConfig(_file=StringIO())
4166
4449
self.assertEqual({}, conf._get_config())
4167
4450
self._got_user_passwd(None, None, conf, 'http', 'foo.net')
4169
4452
def test_non_utf8_config(self):
4170
conf = config.AuthenticationConfig(_file=BytesIO(b'foo = bar\xff'))
4171
self.assertRaises(config.ConfigContentError, conf._get_config)
4453
conf = config.AuthenticationConfig(_file=StringIO(
4455
self.assertRaises(errors.ConfigContentError, conf._get_config)
4173
4457
def test_missing_auth_section_header(self):
4174
conf = config.AuthenticationConfig(_file=BytesIO(b'foo = bar'))
4458
conf = config.AuthenticationConfig(_file=StringIO('foo = bar'))
4175
4459
self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
4177
4461
def test_auth_section_header_not_closed(self):
4178
conf = config.AuthenticationConfig(_file=BytesIO(b'[DEF'))
4179
self.assertRaises(config.ParseConfigError, conf._get_config)
4462
conf = config.AuthenticationConfig(_file=StringIO('[DEF'))
4463
self.assertRaises(errors.ParseConfigError, conf._get_config)
4181
4465
def test_auth_value_not_boolean(self):
4182
conf = config.AuthenticationConfig(_file=BytesIO(b"""\
4466
conf = config.AuthenticationConfig(_file=StringIO(
4186
4470
verify_certificates=askme # Error: Not a boolean
4395
4683
'scheme': scheme, 'host': host, 'port': port,
4396
4684
'user': user, 'realm': realm}
4398
ui.ui_factory = tests.TestUIFactory(stdin=password + '\n')
4686
stdout = tests.StringIOWrapper()
4687
stderr = tests.StringIOWrapper()
4688
ui.ui_factory = tests.TestUIFactory(stdin=password + '\n',
4689
stdout=stdout, stderr=stderr)
4399
4690
# We use an empty conf so that the user is always prompted
4400
4691
conf = config.AuthenticationConfig()
4401
4692
self.assertEqual(password,
4402
conf.get_password(scheme, host, user, port=port,
4403
realm=realm, path=path))
4404
self.assertEqual(expected_prompt, ui.ui_factory.stderr.getvalue())
4405
self.assertEqual('', ui.ui_factory.stdout.getvalue())
4693
conf.get_password(scheme, host, user, port=port,
4694
realm=realm, path=path))
4695
self.assertEqual(expected_prompt, stderr.getvalue())
4696
self.assertEqual('', stdout.getvalue())
4407
4698
def _check_default_username_prompt(self, expected_prompt_format, scheme,
4408
4699
host=None, port=None, realm=None,
4413
4704
expected_prompt = expected_prompt_format % {
4414
4705
'scheme': scheme, 'host': host, 'port': port,
4415
4706
'realm': realm}
4416
ui.ui_factory = tests.TestUIFactory(stdin=username + '\n')
4707
stdout = tests.StringIOWrapper()
4708
stderr = tests.StringIOWrapper()
4709
ui.ui_factory = tests.TestUIFactory(stdin=username+ '\n',
4710
stdout=stdout, stderr=stderr)
4417
4711
# We use an empty conf so that the user is always prompted
4418
4712
conf = config.AuthenticationConfig()
4419
4713
self.assertEqual(username, conf.get_user(scheme, host, port=port,
4420
realm=realm, path=path, ask=True))
4421
self.assertEqual(expected_prompt, ui.ui_factory.stderr.getvalue())
4422
self.assertEqual('', ui.ui_factory.stdout.getvalue())
4714
realm=realm, path=path, ask=True))
4715
self.assertEqual(expected_prompt, stderr.getvalue())
4716
self.assertEqual('', stdout.getvalue())
4424
4718
def test_username_defaults_prompts(self):
4425
4719
# HTTP prompts can't be tested here, see test_http.py
4464
4759
password=jimpass
4466
4761
entered_password = 'typed-by-hand'
4467
ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n')
4762
stdout = tests.StringIOWrapper()
4763
stderr = tests.StringIOWrapper()
4764
ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n',
4765
stdout=stdout, stderr=stderr)
4469
4767
# Since the password defined in the authentication config is ignored,
4470
4768
# the user is prompted
4471
4769
self.assertEqual(entered_password,
4472
conf.get_password('ssh', 'bar.org', user='jim'))
4770
conf.get_password('ssh', 'bar.org', user='jim'))
4473
4771
self.assertContainsRe(
4474
4772
self.get_log(),
4475
'password ignored in section \\[ssh with password\\]')
4773
'password ignored in section \[ssh with password\]')
4477
4775
def test_ssh_without_password_doesnt_emit_warning(self):
4478
conf = config.AuthenticationConfig(_file=BytesIO(b"""
4776
conf = config.AuthenticationConfig(_file=StringIO(
4479
4778
[ssh with password]
4484
4783
entered_password = 'typed-by-hand'
4485
ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n')
4784
stdout = tests.StringIOWrapper()
4785
stderr = tests.StringIOWrapper()
4786
ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n',
4487
4790
# Since the password defined in the authentication config is ignored,
4488
4791
# the user is prompted
4489
4792
self.assertEqual(entered_password,
4490
conf.get_password('ssh', 'bar.org', user='jim'))
4793
conf.get_password('ssh', 'bar.org', user='jim'))
4491
4794
# No warning shoud be emitted since there is no password. We are only
4492
4795
# providing "user".
4493
4796
self.assertNotContainsRe(
4494
4797
self.get_log(),
4495
'password ignored in section \\[ssh with password\\]')
4798
'password ignored in section \[ssh with password\]')
4497
4800
def test_uses_fallback_stores(self):
4498
4801
self.overrideAttr(config, 'credential_store_registry',
4947
class TestAutoUserId(tests.TestCase):
4948
"""Test inferring an automatic user name."""
4950
def test_auto_user_id(self):
4951
"""Automatic inference of user name.
4953
This is a bit hard to test in an isolated way, because it depends on
4954
system functions that go direct to /etc or perhaps somewhere else.
4955
But it's reasonable to say that on Unix, with an /etc/mailname, we ought
4956
to be able to choose a user name with no configuration.
4958
if sys.platform == 'win32':
4959
raise tests.TestSkipped(
4960
"User name inference not implemented on win32")
4961
realname, address = config._auto_user_id()
4962
if os.path.exists('/etc/mailname'):
4963
self.assertIsNot(None, realname)
4964
self.assertIsNot(None, address)
4966
self.assertEqual((None, None), (realname, address))
4969
class TestDefaultMailDomain(tests.TestCaseInTempDir):
4970
"""Test retrieving default domain from mailname file"""
4972
def test_default_mail_domain_simple(self):
4973
f = file('simple', 'w')
4975
f.write("domainname.com\n")
4978
r = config._get_default_mail_domain('simple')
4979
self.assertEqual('domainname.com', r)
4981
def test_default_mail_domain_no_eol(self):
4982
f = file('no_eol', 'w')
4984
f.write("domainname.com")
4987
r = config._get_default_mail_domain('no_eol')
4988
self.assertEqual('domainname.com', r)
4990
def test_default_mail_domain_multiple_lines(self):
4991
f = file('multiple_lines', 'w')
4993
f.write("domainname.com\nsome other text\n")
4996
r = config._get_default_mail_domain('multiple_lines')
4997
self.assertEqual('domainname.com', r)
4644
5000
class EmailOptionTests(tests.TestCase):
4646
def test_default_email_uses_BRZ_EMAIL(self):
4647
conf = config.MemoryStack(b'email=jelmer@debian.org')
4648
# BRZ_EMAIL takes precedence over EMAIL
4649
self.overrideEnv('BRZ_EMAIL', 'jelmer@samba.org')
5002
def test_default_email_uses_BZR_EMAIL(self):
5003
conf = config.MemoryStack('email=jelmer@debian.org')
5004
# BZR_EMAIL takes precedence over EMAIL
5005
self.overrideEnv('BZR_EMAIL', 'jelmer@samba.org')
4650
5006
self.overrideEnv('EMAIL', 'jelmer@apache.org')
4651
5007
self.assertEqual('jelmer@samba.org', conf.get('email'))
4653
5009
def test_default_email_uses_EMAIL(self):
4654
conf = config.MemoryStack(b'')
4655
self.overrideEnv('BRZ_EMAIL', None)
5010
conf = config.MemoryStack('')
5011
self.overrideEnv('BZR_EMAIL', None)
4656
5012
self.overrideEnv('EMAIL', 'jelmer@apache.org')
4657
5013
self.assertEqual('jelmer@apache.org', conf.get('email'))
4659
def test_BRZ_EMAIL_overrides(self):
4660
conf = config.MemoryStack(b'email=jelmer@debian.org')
4661
self.overrideEnv('BRZ_EMAIL', 'jelmer@apache.org')
5015
def test_BZR_EMAIL_overrides(self):
5016
conf = config.MemoryStack('email=jelmer@debian.org')
5017
self.overrideEnv('BZR_EMAIL', 'jelmer@apache.org')
4662
5018
self.assertEqual('jelmer@apache.org', conf.get('email'))
4663
self.overrideEnv('BRZ_EMAIL', None)
5019
self.overrideEnv('BZR_EMAIL', None)
4664
5020
self.overrideEnv('EMAIL', 'jelmer@samba.org')
4665
5021
self.assertEqual('jelmer@debian.org', conf.get('email'))
4668
5024
class MailClientOptionTests(tests.TestCase):
4670
5026
def test_default(self):
4671
conf = config.MemoryStack(b'')
5027
conf = config.MemoryStack('')
4672
5028
client = conf.get('mail_client')
4673
5029
self.assertIs(client, mail_client.DefaultMail)
4675
5031
def test_evolution(self):
4676
conf = config.MemoryStack(b'mail_client=evolution')
5032
conf = config.MemoryStack('mail_client=evolution')
4677
5033
client = conf.get('mail_client')
4678
5034
self.assertIs(client, mail_client.Evolution)
4680
5036
def test_kmail(self):
4681
conf = config.MemoryStack(b'mail_client=kmail')
5037
conf = config.MemoryStack('mail_client=kmail')
4682
5038
client = conf.get('mail_client')
4683
5039
self.assertIs(client, mail_client.KMail)
4685
5041
def test_mutt(self):
4686
conf = config.MemoryStack(b'mail_client=mutt')
5042
conf = config.MemoryStack('mail_client=mutt')
4687
5043
client = conf.get('mail_client')
4688
5044
self.assertIs(client, mail_client.Mutt)
4690
5046
def test_thunderbird(self):
4691
conf = config.MemoryStack(b'mail_client=thunderbird')
5047
conf = config.MemoryStack('mail_client=thunderbird')
4692
5048
client = conf.get('mail_client')
4693
5049
self.assertIs(client, mail_client.Thunderbird)
4695
5051
def test_explicit_default(self):
4696
conf = config.MemoryStack(b'mail_client=default')
5052
conf = config.MemoryStack('mail_client=default')
4697
5053
client = conf.get('mail_client')
4698
5054
self.assertIs(client, mail_client.DefaultMail)
4700
5056
def test_editor(self):
4701
conf = config.MemoryStack(b'mail_client=editor')
5057
conf = config.MemoryStack('mail_client=editor')
4702
5058
client = conf.get('mail_client')
4703
5059
self.assertIs(client, mail_client.Editor)
4705
5061
def test_mapi(self):
4706
conf = config.MemoryStack(b'mail_client=mapi')
5062
conf = config.MemoryStack('mail_client=mapi')
4707
5063
client = conf.get('mail_client')
4708
5064
self.assertIs(client, mail_client.MAPIClient)
4710
5066
def test_xdg_email(self):
4711
conf = config.MemoryStack(b'mail_client=xdg-email')
5067
conf = config.MemoryStack('mail_client=xdg-email')
4712
5068
client = conf.get('mail_client')
4713
5069
self.assertIs(client, mail_client.XDGEmail)
4715
5071
def test_unknown(self):
4716
conf = config.MemoryStack(b'mail_client=firebird')
4717
self.assertRaises(config.ConfigOptionValueError, conf.get,
5072
conf = config.MemoryStack('mail_client=firebird')
5073
self.assertRaises(errors.ConfigOptionValueError, conf.get,