~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_config.py

(gz) Fix deprecations of win32utils path function unicode wrappers (Martin
 Packman)

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
    errors,
34
34
    osutils,
35
35
    mail_client,
36
 
    mergetools,
37
36
    ui,
38
37
    urlutils,
39
 
    registry,
40
38
    remote,
41
39
    tests,
42
40
    trace,
43
 
    transport,
44
41
    )
45
42
from bzrlib.symbol_versioning import (
46
43
    deprecated_in,
47
 
    deprecated_method,
48
44
    )
49
45
from bzrlib.transport import remote as transport_remote
50
46
from bzrlib.tests import (
71
67
 
72
68
# Register helpers to build stores
73
69
config.test_store_builder_registry.register(
74
 
    'configobj', lambda test: config.IniFileStore(test.get_transport(),
75
 
                                                  'configobj.conf'))
 
70
    'configobj', lambda test: config.TransportIniFileStore(
 
71
        test.get_transport(), 'configobj.conf'))
76
72
config.test_store_builder_registry.register(
77
73
    'bazaar', lambda test: config.GlobalStore())
78
74
config.test_store_builder_registry.register(
116
112
config.test_store_builder_registry.register('branch', build_branch_store)
117
113
 
118
114
 
 
115
def build_control_store(test):
 
116
    build_backing_branch(test, 'branch')
 
117
    b = bzrdir.BzrDir.open('branch')
 
118
    return config.ControlStore(b)
 
119
config.test_store_builder_registry.register('control', build_control_store)
 
120
 
 
121
 
119
122
def build_remote_branch_store(test):
120
123
    # There is only one permutation (but we won't be able to handle more with
121
124
    # this design anyway)
148
151
     server_class) = transport_remote.get_test_permutations()[0]
149
152
    build_backing_branch(test, 'branch', transport_class, server_class)
150
153
    b = branch.Branch.open(test.get_url('branch'))
151
 
    return config.BranchStack(b)
 
154
    return config.RemoteBranchStack(b)
152
155
config.test_stack_builder_registry.register('remote_branch',
153
156
                                            build_remote_branch_stack)
154
157
 
 
158
def build_remote_control_stack(test):
 
159
    # There is only one permutation (but we won't be able to handle more with
 
160
    # this design anyway)
 
161
    (transport_class,
 
162
     server_class) = transport_remote.get_test_permutations()[0]
 
163
    # We need only a bzrdir for this, not a full branch, but it's not worth
 
164
    # creating a dedicated helper to create only the bzrdir
 
165
    build_backing_branch(test, 'branch', transport_class, server_class)
 
166
    b = branch.Branch.open(test.get_url('branch'))
 
167
    return config.RemoteControlStack(b.bzrdir)
 
168
config.test_stack_builder_registry.register('remote_control',
 
169
                                            build_remote_control_stack)
 
170
 
155
171
 
156
172
sample_long_alias="log -r-15..-1 --line"
157
173
sample_config_text = u"""
160
176
editor=vim
161
177
change_editor=vimdiff -of @new_path @old_path
162
178
gpg_signing_command=gnome-gpg
 
179
gpg_signing_key=DD4D5088
163
180
log_format=short
164
181
validate_signatures_in_log=true
165
182
acceptable_keys=amy
166
183
user_global_option=something
167
184
bzr.mergetool.sometool=sometool {base} {this} {other} -o {result}
168
185
bzr.mergetool.funkytool=funkytool "arg with spaces" {this_temp}
 
186
bzr.mergetool.newtool='"newtool with spaces" {this_temp}'
169
187
bzr.default_mergetool=sometool
170
188
[ALIASES]
171
189
h=help
214
232
[/a/]
215
233
check_signatures=check-available
216
234
gpg_signing_command=false
 
235
gpg_signing_key=default
217
236
user_local_option=local
218
237
# test trailing / matching
219
238
[/a/*]
309
328
 
310
329
class FakeBranch(object):
311
330
 
312
 
    def __init__(self, base=None, user_id=None):
 
331
    def __init__(self, base=None):
313
332
        if base is None:
314
333
            self.base = "http://example.com/branches/demo"
315
334
        else:
316
335
            self.base = base
317
336
        self._transport = self.control_files = \
318
 
            FakeControlFilesAndTransport(user_id=user_id)
 
337
            FakeControlFilesAndTransport()
319
338
 
320
339
    def _get_config(self):
321
340
        return config.TransportConfig(self._transport, 'branch.conf')
329
348
 
330
349
class FakeControlFilesAndTransport(object):
331
350
 
332
 
    def __init__(self, user_id=None):
 
351
    def __init__(self):
333
352
        self.files = {}
334
 
        if user_id:
335
 
            self.files['email'] = user_id
336
353
        self._transport = self
337
354
 
338
 
    def get_utf8(self, filename):
339
 
        # from LockableFiles
340
 
        raise AssertionError("get_utf8 should no longer be used")
341
 
 
342
355
    def get(self, filename):
343
356
        # from Transport
344
357
        try:
481
494
 
482
495
    def test_signatures_default(self):
483
496
        my_config = config.Config()
484
 
        self.assertFalse(my_config.signature_needed())
 
497
        self.assertFalse(
 
498
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
499
                my_config.signature_needed))
485
500
        self.assertEqual(config.CHECK_IF_POSSIBLE,
486
 
                         my_config.signature_checking())
 
501
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
502
                my_config.signature_checking))
487
503
        self.assertEqual(config.SIGN_WHEN_REQUIRED,
488
 
                         my_config.signing_policy())
 
504
                self.applyDeprecated(deprecated_in((2, 5, 0)),
 
505
                    my_config.signing_policy))
489
506
 
490
507
    def test_signatures_template_method(self):
491
508
        my_config = InstrumentedConfig()
492
 
        self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
 
509
        self.assertEqual(config.CHECK_NEVER,
 
510
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
511
                my_config.signature_checking))
493
512
        self.assertEqual(['_get_signature_checking'], my_config._calls)
494
513
 
495
514
    def test_signatures_template_method_none(self):
496
515
        my_config = InstrumentedConfig()
497
516
        my_config._signatures = None
498
517
        self.assertEqual(config.CHECK_IF_POSSIBLE,
499
 
                         my_config.signature_checking())
 
518
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
519
                             my_config.signature_checking))
500
520
        self.assertEqual(['_get_signature_checking'], my_config._calls)
501
521
 
502
522
    def test_gpg_signing_command_default(self):
503
523
        my_config = config.Config()
504
 
        self.assertEqual('gpg', my_config.gpg_signing_command())
 
524
        self.assertEqual('gpg',
 
525
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
526
                my_config.gpg_signing_command))
505
527
 
506
528
    def test_get_user_option_default(self):
507
529
        my_config = config.Config()
509
531
 
510
532
    def test_post_commit_default(self):
511
533
        my_config = config.Config()
512
 
        self.assertEqual(None, my_config.post_commit())
 
534
        self.assertEqual(None, self.applyDeprecated(deprecated_in((2, 5, 0)),
 
535
                                                    my_config.post_commit))
 
536
 
513
537
 
514
538
    def test_log_format_default(self):
515
539
        my_config = config.Config()
516
 
        self.assertEqual('long', my_config.log_format())
 
540
        self.assertEqual('long',
 
541
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
542
                                              my_config.log_format))
517
543
 
518
544
    def test_acceptable_keys_default(self):
519
545
        my_config = config.Config()
520
 
        self.assertEqual(None, my_config.acceptable_keys())
 
546
        self.assertEqual(None, self.applyDeprecated(deprecated_in((2, 5, 0)),
 
547
            my_config.acceptable_keys))
521
548
 
522
549
    def test_validate_signatures_in_log_default(self):
523
550
        my_config = config.Config()
817
844
        self.assertEquals(['{foo', '}', '{', 'bar}'],
818
845
                          conf.get_user_option('hidden', expand=True))
819
846
 
 
847
 
820
848
class TestLocationConfigOptionExpansion(tests.TestCaseInTempDir):
821
849
 
822
850
    def get_config(self, location, string=None):
1033
1061
        # automatically cast to list
1034
1062
        self.assertEqual(['x'], get_list('one_item'))
1035
1063
 
 
1064
    def test_get_user_option_as_int_from_SI(self):
 
1065
        conf, parser = self.make_config_parser("""
 
1066
plain = 100
 
1067
si_k = 5k,
 
1068
si_kb = 5kb,
 
1069
si_m = 5M,
 
1070
si_mb = 5MB,
 
1071
si_g = 5g,
 
1072
si_gb = 5gB,
 
1073
""")
 
1074
        def get_si(s, default=None):
 
1075
            return self.applyDeprecated(
 
1076
                deprecated_in((2, 5, 0)),
 
1077
                conf.get_user_option_as_int_from_SI, s, default)
 
1078
        self.assertEqual(100, get_si('plain'))
 
1079
        self.assertEqual(5000, get_si('si_k'))
 
1080
        self.assertEqual(5000, get_si('si_kb'))
 
1081
        self.assertEqual(5000000, get_si('si_m'))
 
1082
        self.assertEqual(5000000, get_si('si_mb'))
 
1083
        self.assertEqual(5000000000, get_si('si_g'))
 
1084
        self.assertEqual(5000000000, get_si('si_gb'))
 
1085
        self.assertEqual(None, get_si('non-exist'))
 
1086
        self.assertEqual(42, get_si('non-exist-with-default',  42))
 
1087
 
1036
1088
 
1037
1089
class TestSupressWarning(TestIniConfig):
1038
1090
 
1195
1247
    def test_signatures_always(self):
1196
1248
        my_config = config.GlobalConfig.from_string(sample_always_signatures)
1197
1249
        self.assertEqual(config.CHECK_NEVER,
1198
 
                         my_config.signature_checking())
 
1250
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1251
                             my_config.signature_checking))
1199
1252
        self.assertEqual(config.SIGN_ALWAYS,
1200
 
                         my_config.signing_policy())
1201
 
        self.assertEqual(True, my_config.signature_needed())
 
1253
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1254
                             my_config.signing_policy))
 
1255
        self.assertEqual(True,
 
1256
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1257
                my_config.signature_needed))
1202
1258
 
1203
1259
    def test_signatures_if_possible(self):
1204
1260
        my_config = config.GlobalConfig.from_string(sample_maybe_signatures)
1205
1261
        self.assertEqual(config.CHECK_NEVER,
1206
 
                         my_config.signature_checking())
 
1262
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1263
                             my_config.signature_checking))
1207
1264
        self.assertEqual(config.SIGN_WHEN_REQUIRED,
1208
 
                         my_config.signing_policy())
1209
 
        self.assertEqual(False, my_config.signature_needed())
 
1265
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1266
                             my_config.signing_policy))
 
1267
        self.assertEqual(False, self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1268
            my_config.signature_needed))
1210
1269
 
1211
1270
    def test_signatures_ignore(self):
1212
1271
        my_config = config.GlobalConfig.from_string(sample_ignore_signatures)
1213
1272
        self.assertEqual(config.CHECK_ALWAYS,
1214
 
                         my_config.signature_checking())
 
1273
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1274
                             my_config.signature_checking))
1215
1275
        self.assertEqual(config.SIGN_NEVER,
1216
 
                         my_config.signing_policy())
1217
 
        self.assertEqual(False, my_config.signature_needed())
 
1276
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1277
                             my_config.signing_policy))
 
1278
        self.assertEqual(False, self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1279
            my_config.signature_needed))
1218
1280
 
1219
1281
    def _get_sample_config(self):
1220
1282
        my_config = config.GlobalConfig.from_string(sample_config_text)
1222
1284
 
1223
1285
    def test_gpg_signing_command(self):
1224
1286
        my_config = self._get_sample_config()
1225
 
        self.assertEqual("gnome-gpg", my_config.gpg_signing_command())
1226
 
        self.assertEqual(False, my_config.signature_needed())
 
1287
        self.assertEqual("gnome-gpg",
 
1288
            self.applyDeprecated(
 
1289
                deprecated_in((2, 5, 0)), my_config.gpg_signing_command))
 
1290
        self.assertEqual(False, self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1291
            my_config.signature_needed))
 
1292
 
 
1293
    def test_gpg_signing_key(self):
 
1294
        my_config = self._get_sample_config()
 
1295
        self.assertEqual("DD4D5088",
 
1296
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1297
                my_config.gpg_signing_key))
1227
1298
 
1228
1299
    def _get_empty_config(self):
1229
1300
        my_config = config.GlobalConfig()
1231
1302
 
1232
1303
    def test_gpg_signing_command_unset(self):
1233
1304
        my_config = self._get_empty_config()
1234
 
        self.assertEqual("gpg", my_config.gpg_signing_command())
 
1305
        self.assertEqual("gpg",
 
1306
            self.applyDeprecated(
 
1307
                deprecated_in((2, 5, 0)), my_config.gpg_signing_command))
1235
1308
 
1236
1309
    def test_get_user_option_default(self):
1237
1310
        my_config = self._get_empty_config()
1244
1317
 
1245
1318
    def test_post_commit_default(self):
1246
1319
        my_config = self._get_sample_config()
1247
 
        self.assertEqual(None, my_config.post_commit())
 
1320
        self.assertEqual(None,
 
1321
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1322
                                              my_config.post_commit))
1248
1323
 
1249
1324
    def test_configured_logformat(self):
1250
1325
        my_config = self._get_sample_config()
1251
 
        self.assertEqual("short", my_config.log_format())
 
1326
        self.assertEqual("short",
 
1327
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1328
                                              my_config.log_format))
1252
1329
 
1253
1330
    def test_configured_acceptable_keys(self):
1254
1331
        my_config = self._get_sample_config()
1255
 
        self.assertEqual("amy", my_config.acceptable_keys())
 
1332
        self.assertEqual("amy",
 
1333
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1334
                my_config.acceptable_keys))
1256
1335
 
1257
1336
    def test_configured_validate_signatures_in_log(self):
1258
1337
        my_config = self._get_sample_config()
1296
1375
        self.log(repr(tools))
1297
1376
        self.assertEqual(
1298
1377
            {u'funkytool' : u'funkytool "arg with spaces" {this_temp}',
1299
 
            u'sometool' : u'sometool {base} {this} {other} -o {result}'},
 
1378
            u'sometool' : u'sometool {base} {this} {other} -o {result}',
 
1379
            u'newtool' : u'"newtool with spaces" {this_temp}'},
1300
1380
            tools)
1301
1381
 
1302
1382
    def test_get_merge_tools_empty(self):
1493
1573
        self.get_branch_config('http://www.example.com',
1494
1574
                                 global_config=sample_ignore_signatures)
1495
1575
        self.assertEqual(config.CHECK_ALWAYS,
1496
 
                         self.my_config.signature_checking())
 
1576
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1577
                             self.my_config.signature_checking))
1497
1578
        self.assertEqual(config.SIGN_NEVER,
1498
 
                         self.my_config.signing_policy())
 
1579
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1580
                             self.my_config.signing_policy))
1499
1581
 
1500
1582
    def test_signatures_never(self):
1501
1583
        self.get_branch_config('/a/c')
1502
1584
        self.assertEqual(config.CHECK_NEVER,
1503
 
                         self.my_config.signature_checking())
 
1585
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1586
                             self.my_config.signature_checking))
1504
1587
 
1505
1588
    def test_signatures_when_available(self):
1506
1589
        self.get_branch_config('/a/', global_config=sample_ignore_signatures)
1507
1590
        self.assertEqual(config.CHECK_IF_POSSIBLE,
1508
 
                         self.my_config.signature_checking())
 
1591
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1592
                             self.my_config.signature_checking))
1509
1593
 
1510
1594
    def test_signatures_always(self):
1511
1595
        self.get_branch_config('/b')
1512
1596
        self.assertEqual(config.CHECK_ALWAYS,
1513
 
                         self.my_config.signature_checking())
 
1597
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1598
                         self.my_config.signature_checking))
1514
1599
 
1515
1600
    def test_gpg_signing_command(self):
1516
1601
        self.get_branch_config('/b')
1517
 
        self.assertEqual("gnome-gpg", self.my_config.gpg_signing_command())
 
1602
        self.assertEqual("gnome-gpg",
 
1603
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1604
                self.my_config.gpg_signing_command))
1518
1605
 
1519
1606
    def test_gpg_signing_command_missing(self):
1520
1607
        self.get_branch_config('/a')
1521
 
        self.assertEqual("false", self.my_config.gpg_signing_command())
 
1608
        self.assertEqual("false",
 
1609
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1610
                self.my_config.gpg_signing_command))
 
1611
 
 
1612
    def test_gpg_signing_key(self):
 
1613
        self.get_branch_config('/b')
 
1614
        self.assertEqual("DD4D5088", self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1615
            self.my_config.gpg_signing_key))
 
1616
 
 
1617
    def test_gpg_signing_key_default(self):
 
1618
        self.get_branch_config('/a')
 
1619
        self.assertEqual("erik@bagfors.nu",
 
1620
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1621
                self.my_config.gpg_signing_key))
1522
1622
 
1523
1623
    def test_get_user_option_global(self):
1524
1624
        self.get_branch_config('/a')
1612
1712
    def test_post_commit_default(self):
1613
1713
        self.get_branch_config('/a/c')
1614
1714
        self.assertEqual('bzrlib.tests.test_config.post_commit',
1615
 
                         self.my_config.post_commit())
 
1715
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1716
                                              self.my_config.post_commit))
1616
1717
 
1617
1718
    def get_branch_config(self, location, global_config=None,
1618
1719
                          location_config=None):
1708
1809
        return my_config
1709
1810
 
1710
1811
    def test_user_id(self):
1711
 
        branch = FakeBranch(user_id='Robert Collins <robertc@example.net>')
 
1812
        branch = FakeBranch()
1712
1813
        my_config = config.BranchConfig(branch)
1713
 
        self.assertEqual("Robert Collins <robertc@example.net>",
1714
 
                         my_config.username())
 
1814
        self.assertIsNot(None, my_config.username())
1715
1815
        my_config.branch.control_files.files['email'] = "John"
1716
1816
        my_config.set_user_option('email',
1717
1817
                                  "Robert Collins <robertc@example.org>")
1718
 
        self.assertEqual("John", my_config.username())
1719
 
        del my_config.branch.control_files.files['email']
1720
1818
        self.assertEqual("Robert Collins <robertc@example.org>",
1721
 
                         my_config.username())
1722
 
 
1723
 
    def test_not_set_in_branch(self):
1724
 
        my_config = self.get_branch_config(global_config=sample_config_text)
1725
 
        self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
1726
 
                         my_config._get_user_id())
1727
 
        my_config.branch.control_files.files['email'] = "John"
1728
 
        self.assertEqual("John", my_config._get_user_id())
 
1819
                        my_config.username())
1729
1820
 
1730
1821
    def test_BZR_EMAIL_OVERRIDES(self):
1731
1822
        self.overrideEnv('BZR_EMAIL', "Robert Collins <robertc@example.org>")
1737
1828
    def test_signatures_forced(self):
1738
1829
        my_config = self.get_branch_config(
1739
1830
            global_config=sample_always_signatures)
1740
 
        self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
1741
 
        self.assertEqual(config.SIGN_ALWAYS, my_config.signing_policy())
1742
 
        self.assertTrue(my_config.signature_needed())
 
1831
        self.assertEqual(config.CHECK_NEVER,
 
1832
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1833
                my_config.signature_checking))
 
1834
        self.assertEqual(config.SIGN_ALWAYS,
 
1835
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1836
                my_config.signing_policy))
 
1837
        self.assertTrue(self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1838
            my_config.signature_needed))
1743
1839
 
1744
1840
    def test_signatures_forced_branch(self):
1745
1841
        my_config = self.get_branch_config(
1746
1842
            global_config=sample_ignore_signatures,
1747
1843
            branch_data_config=sample_always_signatures)
1748
 
        self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
1749
 
        self.assertEqual(config.SIGN_ALWAYS, my_config.signing_policy())
1750
 
        self.assertTrue(my_config.signature_needed())
 
1844
        self.assertEqual(config.CHECK_NEVER,
 
1845
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1846
                my_config.signature_checking))
 
1847
        self.assertEqual(config.SIGN_ALWAYS,
 
1848
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1849
                my_config.signing_policy))
 
1850
        self.assertTrue(self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1851
            my_config.signature_needed))
1751
1852
 
1752
1853
    def test_gpg_signing_command(self):
1753
1854
        my_config = self.get_branch_config(
1754
1855
            global_config=sample_config_text,
1755
1856
            # branch data cannot set gpg_signing_command
1756
1857
            branch_data_config="gpg_signing_command=pgp")
1757
 
        self.assertEqual('gnome-gpg', my_config.gpg_signing_command())
 
1858
        self.assertEqual('gnome-gpg',
 
1859
            self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1860
                my_config.gpg_signing_command))
1758
1861
 
1759
1862
    def test_get_user_option_global(self):
1760
1863
        my_config = self.get_branch_config(global_config=sample_config_text)
1767
1870
                                      location_config=sample_branches_text)
1768
1871
        self.assertEqual(my_config.branch.base, '/a/c')
1769
1872
        self.assertEqual('bzrlib.tests.test_config.post_commit',
1770
 
                         my_config.post_commit())
 
1873
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1874
                                              my_config.post_commit))
1771
1875
        my_config.set_user_option('post_commit', 'rmtree_root')
1772
1876
        # post-commit is ignored when present in branch data
1773
1877
        self.assertEqual('bzrlib.tests.test_config.post_commit',
1774
 
                         my_config.post_commit())
 
1878
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1879
                                              my_config.post_commit))
1775
1880
        my_config.set_user_option('post_commit', 'rmtree_root',
1776
1881
                                  store=config.STORE_LOCATION)
1777
 
        self.assertEqual('rmtree_root', my_config.post_commit())
 
1882
        self.assertEqual('rmtree_root',
 
1883
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1884
                                              my_config.post_commit))
1778
1885
 
1779
1886
    def test_config_precedence(self):
1780
1887
        # FIXME: eager test, luckily no persitent config file makes it fail
1914
2021
        conf = config.TransportConfig(t, 'foo.conf')
1915
2022
        self.assertRaises(errors.ParseConfigError, conf._get_configobj)
1916
2023
 
 
2024
    def test_load_permission_denied(self):
 
2025
        """Ensure we get an empty config file if the file is inaccessible."""
 
2026
        warnings = []
 
2027
        def warning(*args):
 
2028
            warnings.append(args[0] % args[1:])
 
2029
        self.overrideAttr(trace, 'warning', warning)
 
2030
 
 
2031
        class DenyingTransport(object):
 
2032
 
 
2033
            def __init__(self, base):
 
2034
                self.base = base
 
2035
 
 
2036
            def get_bytes(self, relpath):
 
2037
                raise errors.PermissionDenied(relpath, "")
 
2038
 
 
2039
        cfg = config.TransportConfig(
 
2040
            DenyingTransport("nonexisting://"), 'control.conf')
 
2041
        self.assertIs(None, cfg.get_option('non-existant', 'SECTION'))
 
2042
        self.assertEquals(
 
2043
            warnings,
 
2044
            [u'Permission denied while trying to open configuration file '
 
2045
             u'nonexisting:///control.conf.'])
 
2046
 
1917
2047
    def test_get_value(self):
1918
2048
        """Test that retreiving a value from a section is possible"""
1919
2049
        bzrdir_config = config.TransportConfig(self.get_transport('.'),
2199
2329
        opt = config.Option('foo', default='bar')
2200
2330
        self.assertEquals('bar', opt.get_default())
2201
2331
 
 
2332
    def test_callable_default_value(self):
 
2333
        def bar_as_unicode():
 
2334
            return u'bar'
 
2335
        opt = config.Option('foo', default=bar_as_unicode)
 
2336
        self.assertEquals('bar', opt.get_default())
 
2337
 
 
2338
    def test_default_value_from_env(self):
 
2339
        opt = config.Option('foo', default='bar', default_from_env=['FOO'])
 
2340
        self.overrideEnv('FOO', 'quux')
 
2341
        # Env variable provides a default taking over the option one
 
2342
        self.assertEquals('quux', opt.get_default())
 
2343
 
 
2344
    def test_first_default_value_from_env_wins(self):
 
2345
        opt = config.Option('foo', default='bar',
 
2346
                            default_from_env=['NO_VALUE', 'FOO', 'BAZ'])
 
2347
        self.overrideEnv('FOO', 'foo')
 
2348
        self.overrideEnv('BAZ', 'baz')
 
2349
        # The first env var set wins
 
2350
        self.assertEquals('foo', opt.get_default())
 
2351
 
 
2352
    def test_not_supported_list_default_value(self):
 
2353
        self.assertRaises(AssertionError, config.Option, 'foo', default=[1])
 
2354
 
 
2355
    def test_not_supported_object_default_value(self):
 
2356
        self.assertRaises(AssertionError, config.Option, 'foo',
 
2357
                          default=object())
 
2358
 
 
2359
    def test_not_supported_callable_default_value_not_unicode(self):
 
2360
        def bar_not_unicode():
 
2361
            return 'bar'
 
2362
        opt = config.Option('foo', default=bar_not_unicode)
 
2363
        self.assertRaises(AssertionError, opt.get_default)
 
2364
 
 
2365
 
 
2366
class TestOptionConverterMixin(object):
 
2367
 
 
2368
    def assertConverted(self, expected, opt, value):
 
2369
        self.assertEquals(expected, opt.convert_from_unicode(value),
 
2370
                          'Expecting %s, got %s' % (expected, value,))
 
2371
 
 
2372
    def assertWarns(self, opt, value):
 
2373
        warnings = []
 
2374
        def warning(*args):
 
2375
            warnings.append(args[0] % args[1:])
 
2376
        self.overrideAttr(trace, 'warning', warning)
 
2377
        self.assertEquals(None, opt.convert_from_unicode(value))
 
2378
        self.assertLength(1, warnings)
 
2379
        self.assertEquals(
 
2380
            'Value "%s" is not valid for "%s"' % (value, opt.name),
 
2381
            warnings[0])
 
2382
 
 
2383
    def assertErrors(self, opt, value):
 
2384
        self.assertRaises(errors.ConfigOptionValueError,
 
2385
                          opt.convert_from_unicode, value)
 
2386
 
 
2387
    def assertConvertInvalid(self, opt, invalid_value):
 
2388
        opt.invalid = None
 
2389
        self.assertEquals(None, opt.convert_from_unicode(invalid_value),
 
2390
                          '%s is not None' % (invalid_value,))
 
2391
        opt.invalid = 'warning'
 
2392
        self.assertWarns(opt, invalid_value)
 
2393
        opt.invalid = 'error'
 
2394
        self.assertErrors(opt, invalid_value)
 
2395
 
 
2396
 
 
2397
class TestOptionWithBooleanConverter(tests.TestCase, TestOptionConverterMixin):
 
2398
 
 
2399
    def get_option(self):
 
2400
        return config.Option('foo', help='A boolean.',
 
2401
                             from_unicode=config.bool_from_store)
 
2402
 
 
2403
    def test_convert_invalid(self):
 
2404
        opt = self.get_option()
 
2405
        # A string that is not recognized as a boolean
 
2406
        self.assertConvertInvalid(opt, u'invalid-boolean')
 
2407
        # A list of strings is never recognized as a boolean
 
2408
        self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
 
2409
 
 
2410
    def test_convert_valid(self):
 
2411
        opt = self.get_option()
 
2412
        self.assertConverted(True, opt, u'True')
 
2413
        self.assertConverted(True, opt, u'1')
 
2414
        self.assertConverted(False, opt, u'False')
 
2415
 
 
2416
 
 
2417
class TestOptionWithIntegerConverter(tests.TestCase, TestOptionConverterMixin):
 
2418
 
 
2419
    def get_option(self):
 
2420
        return config.Option('foo', help='An integer.',
 
2421
                             from_unicode=config.int_from_store)
 
2422
 
 
2423
    def test_convert_invalid(self):
 
2424
        opt = self.get_option()
 
2425
        # A string that is not recognized as an integer
 
2426
        self.assertConvertInvalid(opt, u'forty-two')
 
2427
        # A list of strings is never recognized as an integer
 
2428
        self.assertConvertInvalid(opt, [u'a', u'list'])
 
2429
 
 
2430
    def test_convert_valid(self):
 
2431
        opt = self.get_option()
 
2432
        self.assertConverted(16, opt, u'16')
 
2433
 
 
2434
 
 
2435
class TestOptionWithSIUnitConverter(tests.TestCase, TestOptionConverterMixin):
 
2436
 
 
2437
    def get_option(self):
 
2438
        return config.Option('foo', help='An integer in SI units.',
 
2439
                             from_unicode=config.int_SI_from_store)
 
2440
 
 
2441
    def test_convert_invalid(self):
 
2442
        opt = self.get_option()
 
2443
        self.assertConvertInvalid(opt, u'not-a-unit')
 
2444
        self.assertConvertInvalid(opt, u'Gb') # Forgot the int
 
2445
        self.assertConvertInvalid(opt, u'1b') # Forgot the unit
 
2446
        self.assertConvertInvalid(opt, u'1GG')
 
2447
        self.assertConvertInvalid(opt, u'1Mbb')
 
2448
        self.assertConvertInvalid(opt, u'1MM')
 
2449
 
 
2450
    def test_convert_valid(self):
 
2451
        opt = self.get_option()
 
2452
        self.assertConverted(int(5e3), opt, u'5kb')
 
2453
        self.assertConverted(int(5e6), opt, u'5M')
 
2454
        self.assertConverted(int(5e6), opt, u'5MB')
 
2455
        self.assertConverted(int(5e9), opt, u'5g')
 
2456
        self.assertConverted(int(5e9), opt, u'5gB')
 
2457
        self.assertConverted(100, opt, u'100')
 
2458
 
 
2459
 
 
2460
class TestOptionWithListConverter(tests.TestCase, TestOptionConverterMixin):
 
2461
 
 
2462
    def get_option(self):
 
2463
        return config.Option('foo', help='A list.',
 
2464
                             from_unicode=config.list_from_store)
 
2465
 
 
2466
    def test_convert_invalid(self):
 
2467
        # No string is invalid as all forms can be converted to a list
 
2468
        pass
 
2469
 
 
2470
    def test_convert_valid(self):
 
2471
        opt = self.get_option()
 
2472
        # An empty string is an empty list
 
2473
        self.assertConverted([], opt, '') # Using a bare str() just in case
 
2474
        self.assertConverted([], opt, u'')
 
2475
        # A boolean
 
2476
        self.assertConverted([u'True'], opt, u'True')
 
2477
        # An integer
 
2478
        self.assertConverted([u'42'], opt, u'42')
 
2479
        # A single string
 
2480
        self.assertConverted([u'bar'], opt, u'bar')
 
2481
        # A list remains a list (configObj will turn a string containing commas
 
2482
        # into a list, but that's not what we're testing here)
 
2483
        self.assertConverted([u'foo', u'1', u'True'],
 
2484
                             opt, [u'foo', u'1', u'True'])
 
2485
 
 
2486
 
 
2487
class TestOptionConverterMixin(object):
 
2488
 
 
2489
    def assertConverted(self, expected, opt, value):
 
2490
        self.assertEquals(expected, opt.convert_from_unicode(value))
 
2491
 
 
2492
    def assertWarns(self, opt, value):
 
2493
        warnings = []
 
2494
        def warning(*args):
 
2495
            warnings.append(args[0] % args[1:])
 
2496
        self.overrideAttr(trace, 'warning', warning)
 
2497
        self.assertEquals(None, opt.convert_from_unicode(value))
 
2498
        self.assertLength(1, warnings)
 
2499
        self.assertEquals(
 
2500
            'Value "%s" is not valid for "%s"' % (value, opt.name),
 
2501
            warnings[0])
 
2502
 
 
2503
    def assertErrors(self, opt, value):
 
2504
        self.assertRaises(errors.ConfigOptionValueError,
 
2505
                          opt.convert_from_unicode, value)
 
2506
 
 
2507
    def assertConvertInvalid(self, opt, invalid_value):
 
2508
        opt.invalid = None
 
2509
        self.assertEquals(None, opt.convert_from_unicode(invalid_value))
 
2510
        opt.invalid = 'warning'
 
2511
        self.assertWarns(opt, invalid_value)
 
2512
        opt.invalid = 'error'
 
2513
        self.assertErrors(opt, invalid_value)
 
2514
 
 
2515
 
 
2516
class TestOptionWithBooleanConverter(tests.TestCase, TestOptionConverterMixin):
 
2517
 
 
2518
    def get_option(self):
 
2519
        return config.Option('foo', help='A boolean.',
 
2520
                             from_unicode=config.bool_from_store)
 
2521
 
 
2522
    def test_convert_invalid(self):
 
2523
        opt = self.get_option()
 
2524
        # A string that is not recognized as a boolean
 
2525
        self.assertConvertInvalid(opt, u'invalid-boolean')
 
2526
        # A list of strings is never recognized as a boolean
 
2527
        self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
 
2528
 
 
2529
    def test_convert_valid(self):
 
2530
        opt = self.get_option()
 
2531
        self.assertConverted(True, opt, u'True')
 
2532
        self.assertConverted(True, opt, u'1')
 
2533
        self.assertConverted(False, opt, u'False')
 
2534
 
 
2535
 
 
2536
class TestOptionWithIntegerConverter(tests.TestCase, TestOptionConverterMixin):
 
2537
 
 
2538
    def get_option(self):
 
2539
        return config.Option('foo', help='An integer.',
 
2540
                             from_unicode=config.int_from_store)
 
2541
 
 
2542
    def test_convert_invalid(self):
 
2543
        opt = self.get_option()
 
2544
        # A string that is not recognized as an integer
 
2545
        self.assertConvertInvalid(opt, u'forty-two')
 
2546
        # A list of strings is never recognized as an integer
 
2547
        self.assertConvertInvalid(opt, [u'a', u'list'])
 
2548
 
 
2549
    def test_convert_valid(self):
 
2550
        opt = self.get_option()
 
2551
        self.assertConverted(16, opt, u'16')
 
2552
 
 
2553
 
 
2554
class TestOptionWithListConverter(tests.TestCase, TestOptionConverterMixin):
 
2555
 
 
2556
    def get_option(self):
 
2557
        return config.Option('foo', help='A list.',
 
2558
                             from_unicode=config.list_from_store)
 
2559
 
 
2560
    def test_convert_invalid(self):
 
2561
        opt = self.get_option()
 
2562
        # We don't even try to convert a list into a list, we only expect
 
2563
        # strings
 
2564
        self.assertConvertInvalid(opt, [1])
 
2565
        # No string is invalid as all forms can be converted to a list
 
2566
 
 
2567
    def test_convert_valid(self):
 
2568
        opt = self.get_option()
 
2569
        # An empty string is an empty list
 
2570
        self.assertConverted([], opt, '') # Using a bare str() just in case
 
2571
        self.assertConverted([], opt, u'')
 
2572
        # A boolean
 
2573
        self.assertConverted([u'True'], opt, u'True')
 
2574
        # An integer
 
2575
        self.assertConverted([u'42'], opt, u'42')
 
2576
        # A single string
 
2577
        self.assertConverted([u'bar'], opt, u'bar')
 
2578
 
2202
2579
 
2203
2580
class TestOptionRegistry(tests.TestCase):
2204
2581
 
2205
2582
    def setUp(self):
2206
2583
        super(TestOptionRegistry, self).setUp()
2207
2584
        # Always start with an empty registry
2208
 
        self.overrideAttr(config, 'option_registry', registry.Registry())
 
2585
        self.overrideAttr(config, 'option_registry', config.OptionRegistry())
2209
2586
        self.registry = config.option_registry
2210
2587
 
2211
2588
    def test_register(self):
2212
2589
        opt = config.Option('foo')
2213
 
        self.registry.register('foo', opt)
 
2590
        self.registry.register(opt)
2214
2591
        self.assertIs(opt, self.registry.get('foo'))
2215
2592
 
2216
 
    lazy_option = config.Option('lazy_foo')
2217
 
 
2218
 
    def test_register_lazy(self):
2219
 
        self.registry.register_lazy('foo', self.__module__,
2220
 
                                    'TestOptionRegistry.lazy_option')
2221
 
        self.assertIs(self.lazy_option, self.registry.get('foo'))
2222
 
 
2223
2593
    def test_registered_help(self):
2224
 
        opt = config.Option('foo')
2225
 
        self.registry.register('foo', opt, help='A simple option')
 
2594
        opt = config.Option('foo', help='A simple option')
 
2595
        self.registry.register(opt)
2226
2596
        self.assertEquals('A simple option', self.registry.get_help('foo'))
2227
2597
 
 
2598
    lazy_option = config.Option('lazy_foo', help='Lazy help')
 
2599
 
 
2600
    def test_register_lazy(self):
 
2601
        self.registry.register_lazy('lazy_foo', self.__module__,
 
2602
                                    'TestOptionRegistry.lazy_option')
 
2603
        self.assertIs(self.lazy_option, self.registry.get('lazy_foo'))
 
2604
 
 
2605
    def test_registered_lazy_help(self):
 
2606
        self.registry.register_lazy('lazy_foo', self.__module__,
 
2607
                                    'TestOptionRegistry.lazy_option')
 
2608
        self.assertEquals('Lazy help', self.registry.get_help('lazy_foo'))
 
2609
 
2228
2610
 
2229
2611
class TestRegisteredOptions(tests.TestCase):
2230
2612
    """All registered options should verify some constraints."""
2244
2626
    def test_help_is_set(self):
2245
2627
        option_help = self.registry.get_help(self.option_name)
2246
2628
        self.assertNotEquals(None, option_help)
2247
 
        # Come on, think about the user, he really wants to know whst the
 
2629
        # Come on, think about the user, he really wants to know what the
2248
2630
        # option is about
 
2631
        self.assertIsNot(None, option_help)
2249
2632
        self.assertNotEquals('', option_help)
2250
2633
 
2251
2634
 
2273
2656
 
2274
2657
class TestMutableSection(tests.TestCase):
2275
2658
 
2276
 
    # FIXME: Parametrize so that all sections (including os.environ and the
2277
 
    # ones produced by Stores) run these tests -- vila 2011-04-01
 
2659
    scenarios = [('mutable',
 
2660
                  {'get_section':
 
2661
                       lambda opts: config.MutableSection('myID', opts)},),
 
2662
        ]
2278
2663
 
2279
2664
    def test_set(self):
2280
2665
        a_dict = dict(foo='bar')
2281
 
        section = config.MutableSection('myID', a_dict)
 
2666
        section = self.get_section(a_dict)
2282
2667
        section.set('foo', 'new_value')
2283
2668
        self.assertEquals('new_value', section.get('foo'))
2284
2669
        # The change appears in the shared section
2289
2674
 
2290
2675
    def test_set_preserve_original_once(self):
2291
2676
        a_dict = dict(foo='bar')
2292
 
        section = config.MutableSection('myID', a_dict)
 
2677
        section = self.get_section(a_dict)
2293
2678
        section.set('foo', 'first_value')
2294
2679
        section.set('foo', 'second_value')
2295
2680
        # We keep track of the original value
2298
2683
 
2299
2684
    def test_remove(self):
2300
2685
        a_dict = dict(foo='bar')
2301
 
        section = config.MutableSection('myID', a_dict)
 
2686
        section = self.get_section(a_dict)
2302
2687
        section.remove('foo')
2303
2688
        # We get None for unknown options via the default value
2304
2689
        self.assertEquals(None, section.get('foo'))
2311
2696
 
2312
2697
    def test_remove_new_option(self):
2313
2698
        a_dict = dict()
2314
 
        section = config.MutableSection('myID', a_dict)
 
2699
        section = self.get_section(a_dict)
2315
2700
        section.set('foo', 'bar')
2316
2701
        section.remove('foo')
2317
2702
        self.assertFalse('foo' in section.options)
2321
2706
        self.assertEquals(config._NewlyCreatedOption, section.orig['foo'])
2322
2707
 
2323
2708
 
 
2709
class TestCommandLineStore(tests.TestCase):
 
2710
 
 
2711
    def setUp(self):
 
2712
        super(TestCommandLineStore, self).setUp()
 
2713
        self.store = config.CommandLineStore()
 
2714
 
 
2715
    def get_section(self):
 
2716
        """Get the unique section for the command line overrides."""
 
2717
        sections = list(self.store.get_sections())
 
2718
        self.assertLength(1, sections)
 
2719
        store, section = sections[0]
 
2720
        self.assertEquals(self.store, store)
 
2721
        return section
 
2722
 
 
2723
    def test_no_override(self):
 
2724
        self.store._from_cmdline([])
 
2725
        section = self.get_section()
 
2726
        self.assertLength(0, list(section.iter_option_names()))
 
2727
 
 
2728
    def test_simple_override(self):
 
2729
        self.store._from_cmdline(['a=b'])
 
2730
        section = self.get_section()
 
2731
        self.assertEqual('b', section.get('a'))
 
2732
 
 
2733
    def test_list_override(self):
 
2734
        self.store._from_cmdline(['l=1,2,3'])
 
2735
        val = self.get_section().get('l')
 
2736
        self.assertEqual('1,2,3', val)
 
2737
        # Reminder: lists should be registered as such explicitely, otherwise
 
2738
        # the conversion needs to be done afterwards.
 
2739
        self.assertEqual(['1', '2', '3'], config.list_from_store(val))
 
2740
 
 
2741
    def test_multiple_overrides(self):
 
2742
        self.store._from_cmdline(['a=b', 'x=y'])
 
2743
        section = self.get_section()
 
2744
        self.assertEquals('b', section.get('a'))
 
2745
        self.assertEquals('y', section.get('x'))
 
2746
 
 
2747
    def test_wrong_syntax(self):
 
2748
        self.assertRaises(errors.BzrCommandError,
 
2749
                          self.store._from_cmdline, ['a=b', 'c'])
 
2750
 
 
2751
 
2324
2752
class TestStore(tests.TestCaseWithTransport):
2325
2753
 
2326
 
    def assertSectionContent(self, expected, section):
 
2754
    def assertSectionContent(self, expected, (store, section)):
2327
2755
        """Assert that some options have the proper values in a section."""
2328
2756
        expected_name, expected_options = expected
2329
2757
        self.assertEquals(expected_name, section.id)
2337
2765
    scenarios = [(key, {'get_store': builder}) for key, builder
2338
2766
                 in config.test_store_builder_registry.iteritems()]
2339
2767
 
2340
 
    def setUp(self):
2341
 
        super(TestReadonlyStore, self).setUp()
2342
 
 
2343
2768
    def test_building_delays_load(self):
2344
2769
        store = self.get_store(self)
2345
2770
        self.assertEquals(False, store.is_loaded())
2372
2797
 
2373
2798
 
2374
2799
class TestIniFileStoreContent(tests.TestCaseWithTransport):
2375
 
    """Simulate loading a config store without content of various encodings.
 
2800
    """Simulate loading a config store with content of various encodings.
2376
2801
 
2377
2802
    All files produced by bzr are in utf8 content.
2378
2803
 
2391
2816
        utf8_content = unicode_content.encode('utf8')
2392
2817
        # Store the raw content in the config file
2393
2818
        t.put_bytes('foo.conf', utf8_content)
2394
 
        store = config.IniFileStore(t, 'foo.conf')
 
2819
        store = config.TransportIniFileStore(t, 'foo.conf')
2395
2820
        store.load()
2396
2821
        stack = config.Stack([store.get_sections], store)
2397
2822
        self.assertEquals(unicode_user, stack.get('user'))
2400
2825
        """Ensure we display a proper error on non-ascii, non utf-8 content."""
2401
2826
        t = self.get_transport()
2402
2827
        t.put_bytes('foo.conf', 'user=foo\n#%s\n' % (self.invalid_utf8_char,))
2403
 
        store = config.IniFileStore(t, 'foo.conf')
 
2828
        store = config.TransportIniFileStore(t, 'foo.conf')
2404
2829
        self.assertRaises(errors.ConfigContentError, store.load)
2405
2830
 
2406
2831
    def test_load_erroneous_content(self):
2407
2832
        """Ensure we display a proper error on content that can't be parsed."""
2408
2833
        t = self.get_transport()
2409
2834
        t.put_bytes('foo.conf', '[open_section\n')
2410
 
        store = config.IniFileStore(t, 'foo.conf')
 
2835
        store = config.TransportIniFileStore(t, 'foo.conf')
2411
2836
        self.assertRaises(errors.ParseConfigError, store.load)
2412
2837
 
 
2838
    def test_load_permission_denied(self):
 
2839
        """Ensure we get warned when trying to load an inaccessible file."""
 
2840
        warnings = []
 
2841
        def warning(*args):
 
2842
            warnings.append(args[0] % args[1:])
 
2843
        self.overrideAttr(trace, 'warning', warning)
 
2844
 
 
2845
        t = self.get_transport()
 
2846
 
 
2847
        def get_bytes(relpath):
 
2848
            raise errors.PermissionDenied(relpath, "")
 
2849
        t.get_bytes = get_bytes
 
2850
        store = config.TransportIniFileStore(t, 'foo.conf')
 
2851
        self.assertRaises(errors.PermissionDenied, store.load)
 
2852
        self.assertEquals(
 
2853
            warnings,
 
2854
            [u'Permission denied while trying to load configuration store %s.'
 
2855
             % store.external_url()])
 
2856
 
2413
2857
 
2414
2858
class TestIniConfigContent(tests.TestCaseWithTransport):
2415
 
    """Simulate loading a IniBasedConfig without content of various encodings.
 
2859
    """Simulate loading a IniBasedConfig with content of various encodings.
2416
2860
 
2417
2861
    All files produced by bzr are in utf8 content.
2418
2862
 
2563
3007
        self.assertEquals((store,), calls[0])
2564
3008
 
2565
3009
 
2566
 
class TestIniFileStore(TestStore):
 
3010
class TestTransportIniFileStore(TestStore):
2567
3011
 
2568
3012
    def test_loading_unknown_file_fails(self):
2569
 
        store = config.IniFileStore(self.get_transport(), 'I-do-not-exist')
 
3013
        store = config.TransportIniFileStore(self.get_transport(),
 
3014
            'I-do-not-exist')
2570
3015
        self.assertRaises(errors.NoSuchFile, store.load)
2571
3016
 
2572
3017
    def test_invalid_content(self):
2573
 
        store = config.IniFileStore(self.get_transport(), 'foo.conf', )
 
3018
        store = config.TransportIniFileStore(self.get_transport(), 'foo.conf')
2574
3019
        self.assertEquals(False, store.is_loaded())
2575
3020
        exc = self.assertRaises(
2576
3021
            errors.ParseConfigError, store._load_from_string,
2584
3029
        # option names share the same name space...)
2585
3030
        # FIXME: This should be fixed by forbidding dicts as values ?
2586
3031
        # -- vila 2011-04-05
2587
 
        store = config.IniFileStore(self.get_transport(), 'foo.conf', )
 
3032
        store = config.TransportIniFileStore(self.get_transport(), 'foo.conf')
2588
3033
        store._load_from_string('''
2589
3034
foo=bar
2590
3035
l=1,2
2600
3045
        sections = list(store.get_sections())
2601
3046
        self.assertLength(4, sections)
2602
3047
        # The default section has no name.
2603
 
        # List values are provided as lists
2604
 
        self.assertSectionContent((None, {'foo': 'bar', 'l': ['1', '2']}),
 
3048
        # List values are provided as strings and need to be explicitly
 
3049
        # converted by specifying from_unicode=list_from_store at option
 
3050
        # registration
 
3051
        self.assertSectionContent((None, {'foo': 'bar', 'l': u'1,2'}),
2605
3052
                                  sections[0])
2606
3053
        self.assertSectionContent(
2607
3054
            ('DEFAULT', {'foo_in_DEFAULT': 'foo_DEFAULT'}), sections[1])
2637
3084
 
2638
3085
    def setUp(self):
2639
3086
        super(TestConcurrentStoreUpdates, self).setUp()
2640
 
        self._content = 'one=1\ntwo=2\n'
2641
3087
        self.stack = self.get_stack(self)
2642
3088
        if not isinstance(self.stack, config._CompatibleStack):
2643
3089
            raise tests.TestNotApplicable(
2644
3090
                '%s is not meant to be compatible with the old config design'
2645
3091
                % (self.stack,))
2646
 
        self.stack.store._load_from_string(self._content)
 
3092
        self.stack.set('one', '1')
 
3093
        self.stack.set('two', '2')
2647
3094
        # Flush the store
2648
3095
        self.stack.store.save()
2649
3096
 
2753
3200
    # FIXME: It may be worth looking into removing the lock dir when it's not
2754
3201
    # needed anymore and look at possible fallouts for concurrent lockers. This
2755
3202
    # will matter if/when we use config files outside of bazaar directories
2756
 
    # (.bazaar or .bzr) -- vila 20110-04-11
 
3203
    # (.bazaar or .bzr) -- vila 20110-04-111
2757
3204
 
2758
3205
 
2759
3206
class TestSectionMatcher(TestStore):
2760
3207
 
2761
 
    scenarios = [('location', {'matcher': config.LocationMatcher})]
 
3208
    scenarios = [('location', {'matcher': config.LocationMatcher}),
 
3209
                 ('id', {'matcher': config.NameMatcher}),]
2762
3210
 
2763
 
    def get_store(self, file_name):
2764
 
        return config.IniFileStore(self.get_readonly_transport(), file_name)
 
3211
    def setUp(self):
 
3212
        super(TestSectionMatcher, self).setUp()
 
3213
        # Any simple store is good enough
 
3214
        self.get_store = config.test_store_builder_registry.get('configobj')
2765
3215
 
2766
3216
    def test_no_matches_for_empty_stores(self):
2767
 
        store = self.get_store('foo.conf')
 
3217
        store = self.get_store(self)
2768
3218
        store._load_from_string('')
2769
3219
        matcher = self.matcher(store, '/bar')
2770
3220
        self.assertEquals([], list(matcher.get_sections()))
2771
3221
 
2772
3222
    def test_build_doesnt_load_store(self):
2773
 
        store = self.get_store('foo.conf')
 
3223
        store = self.get_store(self)
2774
3224
        matcher = self.matcher(store, '/bar')
2775
3225
        self.assertFalse(store.is_loaded())
2776
3226
 
2800
3250
 
2801
3251
class TestLocationMatcher(TestStore):
2802
3252
 
2803
 
    def get_store(self, file_name):
2804
 
        return config.IniFileStore(self.get_readonly_transport(), file_name)
 
3253
    def setUp(self):
 
3254
        super(TestLocationMatcher, self).setUp()
 
3255
        # Any simple store is good enough
 
3256
        self.get_store = config.test_store_builder_registry.get('configobj')
 
3257
 
 
3258
    def test_unrelated_section_excluded(self):
 
3259
        store = self.get_store(self)
 
3260
        store._load_from_string('''
 
3261
[/foo]
 
3262
section=/foo
 
3263
[/foo/baz]
 
3264
section=/foo/baz
 
3265
[/foo/bar]
 
3266
section=/foo/bar
 
3267
[/foo/bar/baz]
 
3268
section=/foo/bar/baz
 
3269
[/quux/quux]
 
3270
section=/quux/quux
 
3271
''')
 
3272
        self.assertEquals(['/foo', '/foo/baz', '/foo/bar', '/foo/bar/baz',
 
3273
                           '/quux/quux'],
 
3274
                          [section.id for _, section in store.get_sections()])
 
3275
        matcher = config.LocationMatcher(store, '/foo/bar/quux')
 
3276
        sections = [section for s, section in matcher.get_sections()]
 
3277
        self.assertEquals([3, 2],
 
3278
                          [section.length for section in sections])
 
3279
        self.assertEquals(['/foo/bar', '/foo'],
 
3280
                          [section.id for section in sections])
 
3281
        self.assertEquals(['quux', 'bar/quux'],
 
3282
                          [section.extra_path for section in sections])
2805
3283
 
2806
3284
    def test_more_specific_sections_first(self):
2807
 
        store = self.get_store('foo.conf')
 
3285
        store = self.get_store(self)
2808
3286
        store._load_from_string('''
2809
3287
[/foo]
2810
3288
section=/foo
2812
3290
section=/foo/bar
2813
3291
''')
2814
3292
        self.assertEquals(['/foo', '/foo/bar'],
2815
 
                          [section.id for section in store.get_sections()])
 
3293
                          [section.id for _, section in store.get_sections()])
2816
3294
        matcher = config.LocationMatcher(store, '/foo/bar/baz')
2817
 
        sections = list(matcher.get_sections())
 
3295
        sections = [section for s, section in matcher.get_sections()]
2818
3296
        self.assertEquals([3, 2],
2819
3297
                          [section.length for section in sections])
2820
3298
        self.assertEquals(['/foo/bar', '/foo'],
2825
3303
    def test_appendpath_in_no_name_section(self):
2826
3304
        # It's a bit weird to allow appendpath in a no-name section, but
2827
3305
        # someone may found a use for it
2828
 
        store = self.get_store('foo.conf')
 
3306
        store = self.get_store(self)
2829
3307
        store._load_from_string('''
2830
3308
foo=bar
2831
3309
foo:policy = appendpath
2833
3311
        matcher = config.LocationMatcher(store, 'dir/subdir')
2834
3312
        sections = list(matcher.get_sections())
2835
3313
        self.assertLength(1, sections)
2836
 
        self.assertEquals('bar/dir/subdir', sections[0].get('foo'))
 
3314
        self.assertEquals('bar/dir/subdir', sections[0][1].get('foo'))
2837
3315
 
2838
3316
    def test_file_urls_are_normalized(self):
2839
 
        store = self.get_store('foo.conf')
 
3317
        store = self.get_store(self)
2840
3318
        if sys.platform == 'win32':
2841
3319
            expected_url = 'file:///C:/dir/subdir'
2842
3320
            expected_location = 'C:/dir/subdir'
2847
3325
        self.assertEquals(expected_location, matcher.location)
2848
3326
 
2849
3327
 
 
3328
class TestNameMatcher(TestStore):
 
3329
 
 
3330
    def setUp(self):
 
3331
        super(TestNameMatcher, self).setUp()
 
3332
        self.matcher = config.NameMatcher
 
3333
        # Any simple store is good enough
 
3334
        self.get_store = config.test_store_builder_registry.get('configobj')
 
3335
 
 
3336
    def get_matching_sections(self, name):
 
3337
        store = self.get_store(self)
 
3338
        store._load_from_string('''
 
3339
[foo]
 
3340
option=foo
 
3341
[foo/baz]
 
3342
option=foo/baz
 
3343
[bar]
 
3344
option=bar
 
3345
''')
 
3346
        matcher = self.matcher(store, name)
 
3347
        return list(matcher.get_sections())
 
3348
 
 
3349
    def test_matching(self):
 
3350
        sections = self.get_matching_sections('foo')
 
3351
        self.assertLength(1, sections)
 
3352
        self.assertSectionContent(('foo', {'option': 'foo'}), sections[0])
 
3353
 
 
3354
    def test_not_matching(self):
 
3355
        sections = self.get_matching_sections('baz')
 
3356
        self.assertLength(0, sections)
 
3357
 
 
3358
 
2850
3359
class TestStackGet(tests.TestCase):
2851
3360
 
2852
3361
    # FIXME: This should be parametrized for all known Stack or dedicated
2853
3362
    # paramerized tests created to avoid bloating -- vila 2011-03-31
2854
3363
 
 
3364
    def overrideOptionRegistry(self):
 
3365
        self.overrideAttr(config, 'option_registry', config.OptionRegistry())
 
3366
 
2855
3367
    def test_single_config_get(self):
2856
3368
        conf = dict(foo='bar')
2857
3369
        conf_stack = config.Stack([conf])
2860
3372
    def test_get_with_registered_default_value(self):
2861
3373
        conf_stack = config.Stack([dict()])
2862
3374
        opt = config.Option('foo', default='bar')
2863
 
        self.overrideAttr(config, 'option_registry', registry.Registry())
 
3375
        self.overrideOptionRegistry()
2864
3376
        config.option_registry.register('foo', opt)
2865
3377
        self.assertEquals('bar', conf_stack.get('foo'))
2866
3378
 
2867
3379
    def test_get_without_registered_default_value(self):
2868
3380
        conf_stack = config.Stack([dict()])
2869
3381
        opt = config.Option('foo')
2870
 
        self.overrideAttr(config, 'option_registry', registry.Registry())
 
3382
        self.overrideOptionRegistry()
2871
3383
        config.option_registry.register('foo', opt)
2872
3384
        self.assertEquals(None, conf_stack.get('foo'))
2873
3385
 
2874
3386
    def test_get_without_default_value_for_not_registered(self):
2875
3387
        conf_stack = config.Stack([dict()])
2876
3388
        opt = config.Option('foo')
2877
 
        self.overrideAttr(config, 'option_registry', registry.Registry())
 
3389
        self.overrideOptionRegistry()
2878
3390
        self.assertEquals(None, conf_stack.get('foo'))
2879
3391
 
2880
3392
    def test_get_first_definition(self):
2914
3426
 
2915
3427
class TestStackGet(TestStackWithTransport):
2916
3428
 
 
3429
    def setUp(self):
 
3430
        super(TestStackGet, self).setUp()
 
3431
        self.conf = self.get_stack(self)
 
3432
 
2917
3433
    def test_get_for_empty_stack(self):
2918
 
        conf = self.get_stack(self)
2919
 
        self.assertEquals(None, conf.get('foo'))
 
3434
        self.assertEquals(None, self.conf.get('foo'))
2920
3435
 
2921
3436
    def test_get_hook(self):
2922
 
        conf = self.get_stack(self)
2923
 
        conf.store._load_from_string('foo=bar')
 
3437
        self.conf.set('foo', 'bar')
2924
3438
        calls = []
2925
3439
        def hook(*args):
2926
3440
            calls.append(args)
2927
3441
        config.ConfigHooks.install_named_hook('get', hook, None)
2928
3442
        self.assertLength(0, calls)
2929
 
        value = conf.get('foo')
 
3443
        value = self.conf.get('foo')
2930
3444
        self.assertEquals('bar', value)
2931
3445
        self.assertLength(1, calls)
2932
 
        self.assertEquals((conf, 'foo', 'bar'), calls[0])
 
3446
        self.assertEquals((self.conf, 'foo', 'bar'), calls[0])
 
3447
 
 
3448
 
 
3449
class TestStackGetWithConverter(tests.TestCaseWithTransport):
 
3450
 
 
3451
    def setUp(self):
 
3452
        super(TestStackGetWithConverter, self).setUp()
 
3453
        self.overrideAttr(config, 'option_registry', config.OptionRegistry())
 
3454
        self.registry = config.option_registry
 
3455
        # We just want a simple stack with a simple store so we can inject
 
3456
        # whatever content the tests need without caring about what section
 
3457
        # names are valid for a given store/stack.
 
3458
        store = config.TransportIniFileStore(self.get_transport(), 'foo.conf')
 
3459
        self.conf = config.Stack([store.get_sections], store)
 
3460
 
 
3461
    def register_bool_option(self, name, default=None, default_from_env=None):
 
3462
        b = config.Option(name, help='A boolean.',
 
3463
                          default=default, default_from_env=default_from_env,
 
3464
                          from_unicode=config.bool_from_store)
 
3465
        self.registry.register(b)
 
3466
 
 
3467
    def test_get_default_bool_None(self):
 
3468
        self.register_bool_option('foo')
 
3469
        self.assertEquals(None, self.conf.get('foo'))
 
3470
 
 
3471
    def test_get_default_bool_True(self):
 
3472
        self.register_bool_option('foo', u'True')
 
3473
        self.assertEquals(True, self.conf.get('foo'))
 
3474
 
 
3475
    def test_get_default_bool_False(self):
 
3476
        self.register_bool_option('foo', False)
 
3477
        self.assertEquals(False, self.conf.get('foo'))
 
3478
 
 
3479
    def test_get_default_bool_False_as_string(self):
 
3480
        self.register_bool_option('foo', u'False')
 
3481
        self.assertEquals(False, self.conf.get('foo'))
 
3482
 
 
3483
    def test_get_default_bool_from_env_converted(self):
 
3484
        self.register_bool_option('foo', u'True', default_from_env=['FOO'])
 
3485
        self.overrideEnv('FOO', 'False')
 
3486
        self.assertEquals(False, self.conf.get('foo'))
 
3487
 
 
3488
    def test_get_default_bool_when_conversion_fails(self):
 
3489
        self.register_bool_option('foo', default='True')
 
3490
        self.conf.store._load_from_string('foo=invalid boolean')
 
3491
        self.assertEquals(True, self.conf.get('foo'))
 
3492
 
 
3493
    def register_integer_option(self, name,
 
3494
                                default=None, default_from_env=None):
 
3495
        i = config.Option(name, help='An integer.',
 
3496
                          default=default, default_from_env=default_from_env,
 
3497
                          from_unicode=config.int_from_store)
 
3498
        self.registry.register(i)
 
3499
 
 
3500
    def test_get_default_integer_None(self):
 
3501
        self.register_integer_option('foo')
 
3502
        self.assertEquals(None, self.conf.get('foo'))
 
3503
 
 
3504
    def test_get_default_integer(self):
 
3505
        self.register_integer_option('foo', 42)
 
3506
        self.assertEquals(42, self.conf.get('foo'))
 
3507
 
 
3508
    def test_get_default_integer_as_string(self):
 
3509
        self.register_integer_option('foo', u'42')
 
3510
        self.assertEquals(42, self.conf.get('foo'))
 
3511
 
 
3512
    def test_get_default_integer_from_env(self):
 
3513
        self.register_integer_option('foo', default_from_env=['FOO'])
 
3514
        self.overrideEnv('FOO', '18')
 
3515
        self.assertEquals(18, self.conf.get('foo'))
 
3516
 
 
3517
    def test_get_default_integer_when_conversion_fails(self):
 
3518
        self.register_integer_option('foo', default='12')
 
3519
        self.conf.store._load_from_string('foo=invalid integer')
 
3520
        self.assertEquals(12, self.conf.get('foo'))
 
3521
 
 
3522
    def register_list_option(self, name, default=None, default_from_env=None):
 
3523
        l = config.Option(name, help='A list.',
 
3524
                          default=default, default_from_env=default_from_env,
 
3525
                          from_unicode=config.list_from_store)
 
3526
        self.registry.register(l)
 
3527
 
 
3528
    def test_get_default_list_None(self):
 
3529
        self.register_list_option('foo')
 
3530
        self.assertEquals(None, self.conf.get('foo'))
 
3531
 
 
3532
    def test_get_default_list_empty(self):
 
3533
        self.register_list_option('foo', '')
 
3534
        self.assertEquals([], self.conf.get('foo'))
 
3535
 
 
3536
    def test_get_default_list_from_env(self):
 
3537
        self.register_list_option('foo', default_from_env=['FOO'])
 
3538
        self.overrideEnv('FOO', '')
 
3539
        self.assertEquals([], self.conf.get('foo'))
 
3540
 
 
3541
    def test_get_with_list_converter_no_item(self):
 
3542
        self.register_list_option('foo', None)
 
3543
        self.conf.store._load_from_string('foo=,')
 
3544
        self.assertEquals([], self.conf.get('foo'))
 
3545
 
 
3546
    def test_get_with_list_converter_many_items(self):
 
3547
        self.register_list_option('foo', None)
 
3548
        self.conf.store._load_from_string('foo=m,o,r,e')
 
3549
        self.assertEquals(['m', 'o', 'r', 'e'], self.conf.get('foo'))
 
3550
 
 
3551
    def test_get_with_list_converter_embedded_spaces_many_items(self):
 
3552
        self.register_list_option('foo', None)
 
3553
        self.conf.store._load_from_string('foo=" bar", "baz "')
 
3554
        self.assertEquals([' bar', 'baz '], self.conf.get('foo'))
 
3555
 
 
3556
    def test_get_with_list_converter_stripped_spaces_many_items(self):
 
3557
        self.register_list_option('foo', None)
 
3558
        self.conf.store._load_from_string('foo= bar ,  baz ')
 
3559
        self.assertEquals(['bar', 'baz'], self.conf.get('foo'))
 
3560
 
 
3561
 
 
3562
class TestIterOptionRefs(tests.TestCase):
 
3563
    """iter_option_refs is a bit unusual, document some cases."""
 
3564
 
 
3565
    def assertRefs(self, expected, string):
 
3566
        self.assertEquals(expected, list(config.iter_option_refs(string)))
 
3567
 
 
3568
    def test_empty(self):
 
3569
        self.assertRefs([(False, '')], '')
 
3570
 
 
3571
    def test_no_refs(self):
 
3572
        self.assertRefs([(False, 'foo bar')], 'foo bar')
 
3573
 
 
3574
    def test_single_ref(self):
 
3575
        self.assertRefs([(False, ''), (True, '{foo}'), (False, '')], '{foo}')
 
3576
 
 
3577
    def test_broken_ref(self):
 
3578
        self.assertRefs([(False, '{foo')], '{foo')
 
3579
 
 
3580
    def test_embedded_ref(self):
 
3581
        self.assertRefs([(False, '{'), (True, '{foo}'), (False, '}')],
 
3582
                        '{{foo}}')
 
3583
 
 
3584
    def test_two_refs(self):
 
3585
        self.assertRefs([(False, ''), (True, '{foo}'),
 
3586
                         (False, ''), (True, '{bar}'),
 
3587
                         (False, ''),],
 
3588
                        '{foo}{bar}')
 
3589
 
 
3590
    def test_newline_in_refs_are_not_matched(self):
 
3591
        self.assertRefs([(False, '{\nxx}{xx\n}{{\n}}')], '{\nxx}{xx\n}{{\n}}')
 
3592
 
 
3593
 
 
3594
class TestStackExpandOptions(tests.TestCaseWithTransport):
 
3595
 
 
3596
    def setUp(self):
 
3597
        super(TestStackExpandOptions, self).setUp()
 
3598
        self.overrideAttr(config, 'option_registry', config.OptionRegistry())
 
3599
        self.registry = config.option_registry
 
3600
        self.conf = build_branch_stack(self)
 
3601
 
 
3602
    def assertExpansion(self, expected, string, env=None):
 
3603
        self.assertEquals(expected, self.conf.expand_options(string, env))
 
3604
 
 
3605
    def test_no_expansion(self):
 
3606
        self.assertExpansion('foo', 'foo')
 
3607
 
 
3608
    def test_expand_default_value(self):
 
3609
        self.conf.store._load_from_string('bar=baz')
 
3610
        self.registry.register(config.Option('foo', default=u'{bar}'))
 
3611
        self.assertEquals('baz', self.conf.get('foo', expand=True))
 
3612
 
 
3613
    def test_expand_default_from_env(self):
 
3614
        self.conf.store._load_from_string('bar=baz')
 
3615
        self.registry.register(config.Option('foo', default_from_env=['FOO']))
 
3616
        self.overrideEnv('FOO', '{bar}')
 
3617
        self.assertEquals('baz', self.conf.get('foo', expand=True))
 
3618
 
 
3619
    def test_expand_default_on_failed_conversion(self):
 
3620
        self.conf.store._load_from_string('baz=bogus\nbar=42\nfoo={baz}')
 
3621
        self.registry.register(
 
3622
            config.Option('foo', default=u'{bar}',
 
3623
                          from_unicode=config.int_from_store))
 
3624
        self.assertEquals(42, self.conf.get('foo', expand=True))
 
3625
 
 
3626
    def test_env_adding_options(self):
 
3627
        self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
 
3628
 
 
3629
    def test_env_overriding_options(self):
 
3630
        self.conf.store._load_from_string('foo=baz')
 
3631
        self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
 
3632
 
 
3633
    def test_simple_ref(self):
 
3634
        self.conf.store._load_from_string('foo=xxx')
 
3635
        self.assertExpansion('xxx', '{foo}')
 
3636
 
 
3637
    def test_unknown_ref(self):
 
3638
        self.assertRaises(errors.ExpandingUnknownOption,
 
3639
                          self.conf.expand_options, '{foo}')
 
3640
 
 
3641
    def test_indirect_ref(self):
 
3642
        self.conf.store._load_from_string('''
 
3643
foo=xxx
 
3644
bar={foo}
 
3645
''')
 
3646
        self.assertExpansion('xxx', '{bar}')
 
3647
 
 
3648
    def test_embedded_ref(self):
 
3649
        self.conf.store._load_from_string('''
 
3650
foo=xxx
 
3651
bar=foo
 
3652
''')
 
3653
        self.assertExpansion('xxx', '{{bar}}')
 
3654
 
 
3655
    def test_simple_loop(self):
 
3656
        self.conf.store._load_from_string('foo={foo}')
 
3657
        self.assertRaises(errors.OptionExpansionLoop,
 
3658
                          self.conf.expand_options, '{foo}')
 
3659
 
 
3660
    def test_indirect_loop(self):
 
3661
        self.conf.store._load_from_string('''
 
3662
foo={bar}
 
3663
bar={baz}
 
3664
baz={foo}''')
 
3665
        e = self.assertRaises(errors.OptionExpansionLoop,
 
3666
                              self.conf.expand_options, '{foo}')
 
3667
        self.assertEquals('foo->bar->baz', e.refs)
 
3668
        self.assertEquals('{foo}', e.string)
 
3669
 
 
3670
    def test_list(self):
 
3671
        self.conf.store._load_from_string('''
 
3672
foo=start
 
3673
bar=middle
 
3674
baz=end
 
3675
list={foo},{bar},{baz}
 
3676
''')
 
3677
        self.registry.register(
 
3678
            config.Option('list', from_unicode=config.list_from_store))
 
3679
        self.assertEquals(['start', 'middle', 'end'],
 
3680
                           self.conf.get('list', expand=True))
 
3681
 
 
3682
    def test_cascading_list(self):
 
3683
        self.conf.store._load_from_string('''
 
3684
foo=start,{bar}
 
3685
bar=middle,{baz}
 
3686
baz=end
 
3687
list={foo}
 
3688
''')
 
3689
        self.registry.register(
 
3690
            config.Option('list', from_unicode=config.list_from_store))
 
3691
        self.assertEquals(['start', 'middle', 'end'],
 
3692
                           self.conf.get('list', expand=True))
 
3693
 
 
3694
    def test_pathologically_hidden_list(self):
 
3695
        self.conf.store._load_from_string('''
 
3696
foo=bin
 
3697
bar=go
 
3698
start={foo
 
3699
middle=},{
 
3700
end=bar}
 
3701
hidden={start}{middle}{end}
 
3702
''')
 
3703
        # What matters is what the registration says, the conversion happens
 
3704
        # only after all expansions have been performed
 
3705
        self.registry.register(
 
3706
            config.Option('hidden', from_unicode=config.list_from_store))
 
3707
        self.assertEquals(['bin', 'go'],
 
3708
                          self.conf.get('hidden', expand=True))
 
3709
 
 
3710
 
 
3711
class TestStackCrossSectionsExpand(tests.TestCaseWithTransport):
 
3712
 
 
3713
    def setUp(self):
 
3714
        super(TestStackCrossSectionsExpand, self).setUp()
 
3715
 
 
3716
    def get_config(self, location, string):
 
3717
        if string is None:
 
3718
            string = ''
 
3719
        # Since we don't save the config we won't strictly require to inherit
 
3720
        # from TestCaseInTempDir, but an error occurs so quickly...
 
3721
        c = config.LocationStack(location)
 
3722
        c.store._load_from_string(string)
 
3723
        return c
 
3724
 
 
3725
    def test_dont_cross_unrelated_section(self):
 
3726
        c = self.get_config('/another/branch/path','''
 
3727
[/one/branch/path]
 
3728
foo = hello
 
3729
bar = {foo}/2
 
3730
 
 
3731
[/another/branch/path]
 
3732
bar = {foo}/2
 
3733
''')
 
3734
        self.assertRaises(errors.ExpandingUnknownOption,
 
3735
                          c.get, 'bar', expand=True)
 
3736
 
 
3737
    def test_cross_related_sections(self):
 
3738
        c = self.get_config('/project/branch/path','''
 
3739
[/project]
 
3740
foo = qu
 
3741
 
 
3742
[/project/branch/path]
 
3743
bar = {foo}ux
 
3744
''')
 
3745
        self.assertEquals('quux', c.get('bar', expand=True))
 
3746
 
 
3747
 
 
3748
class TestStackCrossStoresExpand(tests.TestCaseWithTransport):
 
3749
 
 
3750
    def test_cross_global_locations(self):
 
3751
        l_store = config.LocationStore()
 
3752
        l_store._load_from_string('''
 
3753
[/branch]
 
3754
lfoo = loc-foo
 
3755
lbar = {gbar}
 
3756
''')
 
3757
        l_store.save()
 
3758
        g_store = config.GlobalStore()
 
3759
        g_store._load_from_string('''
 
3760
[DEFAULT]
 
3761
gfoo = {lfoo}
 
3762
gbar = glob-bar
 
3763
''')
 
3764
        g_store.save()
 
3765
        stack = config.LocationStack('/branch')
 
3766
        self.assertEquals('glob-bar', stack.get('lbar', expand=True))
 
3767
        self.assertEquals('loc-foo', stack.get('gfoo', expand=True))
 
3768
 
 
3769
 
 
3770
class TestStackExpandSectionLocals(tests.TestCaseWithTransport):
 
3771
 
 
3772
    def test_expand_locals_empty(self):
 
3773
        l_store = config.LocationStore()
 
3774
        l_store._load_from_string('''
 
3775
[/home/user/project]
 
3776
base = {basename}
 
3777
rel = {relpath}
 
3778
''')
 
3779
        l_store.save()
 
3780
        stack = config.LocationStack('/home/user/project/')
 
3781
        self.assertEquals('', stack.get('base', expand=True))
 
3782
        self.assertEquals('', stack.get('rel', expand=True))
 
3783
 
 
3784
    def test_expand_basename_locally(self):
 
3785
        l_store = config.LocationStore()
 
3786
        l_store._load_from_string('''
 
3787
[/home/user/project]
 
3788
bfoo = {basename}
 
3789
''')
 
3790
        l_store.save()
 
3791
        stack = config.LocationStack('/home/user/project/branch')
 
3792
        self.assertEquals('branch', stack.get('bfoo', expand=True))
 
3793
 
 
3794
    def test_expand_basename_locally_longer_path(self):
 
3795
        l_store = config.LocationStore()
 
3796
        l_store._load_from_string('''
 
3797
[/home/user]
 
3798
bfoo = {basename}
 
3799
''')
 
3800
        l_store.save()
 
3801
        stack = config.LocationStack('/home/user/project/dir/branch')
 
3802
        self.assertEquals('branch', stack.get('bfoo', expand=True))
 
3803
 
 
3804
    def test_expand_relpath_locally(self):
 
3805
        l_store = config.LocationStore()
 
3806
        l_store._load_from_string('''
 
3807
[/home/user/project]
 
3808
lfoo = loc-foo/{relpath}
 
3809
''')
 
3810
        l_store.save()
 
3811
        stack = config.LocationStack('/home/user/project/branch')
 
3812
        self.assertEquals('loc-foo/branch', stack.get('lfoo', expand=True))
 
3813
 
 
3814
    def test_expand_relpath_unknonw_in_global(self):
 
3815
        g_store = config.GlobalStore()
 
3816
        g_store._load_from_string('''
 
3817
[DEFAULT]
 
3818
gfoo = {relpath}
 
3819
''')
 
3820
        g_store.save()
 
3821
        stack = config.LocationStack('/home/user/project/branch')
 
3822
        self.assertRaises(errors.ExpandingUnknownOption,
 
3823
                          stack.get, 'gfoo', expand=True)
 
3824
 
 
3825
    def test_expand_local_option_locally(self):
 
3826
        l_store = config.LocationStore()
 
3827
        l_store._load_from_string('''
 
3828
[/home/user/project]
 
3829
lfoo = loc-foo/{relpath}
 
3830
lbar = {gbar}
 
3831
''')
 
3832
        l_store.save()
 
3833
        g_store = config.GlobalStore()
 
3834
        g_store._load_from_string('''
 
3835
[DEFAULT]
 
3836
gfoo = {lfoo}
 
3837
gbar = glob-bar
 
3838
''')
 
3839
        g_store.save()
 
3840
        stack = config.LocationStack('/home/user/project/branch')
 
3841
        self.assertEquals('glob-bar', stack.get('lbar', expand=True))
 
3842
        self.assertEquals('loc-foo/branch', stack.get('gfoo', expand=True))
 
3843
 
 
3844
    def test_locals_dont_leak(self):
 
3845
        """Make sure we chose the right local in presence of several sections.
 
3846
        """
 
3847
        l_store = config.LocationStore()
 
3848
        l_store._load_from_string('''
 
3849
[/home/user]
 
3850
lfoo = loc-foo/{relpath}
 
3851
[/home/user/project]
 
3852
lfoo = loc-foo/{relpath}
 
3853
''')
 
3854
        l_store.save()
 
3855
        stack = config.LocationStack('/home/user/project/branch')
 
3856
        self.assertEquals('loc-foo/branch', stack.get('lfoo', expand=True))
 
3857
        stack = config.LocationStack('/home/user/bar/baz')
 
3858
        self.assertEquals('loc-foo/bar/baz', stack.get('lfoo', expand=True))
 
3859
 
2933
3860
 
2934
3861
 
2935
3862
class TestStackSet(TestStackWithTransport):
2936
3863
 
2937
3864
    def test_simple_set(self):
2938
3865
        conf = self.get_stack(self)
2939
 
        conf.store._load_from_string('foo=bar')
2940
 
        self.assertEquals('bar', conf.get('foo'))
 
3866
        self.assertEquals(None, conf.get('foo'))
2941
3867
        conf.set('foo', 'baz')
2942
3868
        # Did we get it back ?
2943
3869
        self.assertEquals('baz', conf.get('foo'))
2963
3889
 
2964
3890
    def test_remove_existing(self):
2965
3891
        conf = self.get_stack(self)
2966
 
        conf.store._load_from_string('foo=bar')
 
3892
        conf.set('foo', 'bar')
2967
3893
        self.assertEquals('bar', conf.get('foo'))
2968
3894
        conf.remove('foo')
2969
3895
        # Did we get it back ?
2980
3906
        config.ConfigHooks.install_named_hook('remove', hook, None)
2981
3907
        self.assertLength(0, calls)
2982
3908
        conf = self.get_stack(self)
2983
 
        conf.store._load_from_string('foo=bar')
 
3909
        conf.set('foo', 'bar')
2984
3910
        conf.remove('foo')
2985
3911
        self.assertLength(1, calls)
2986
3912
        self.assertEquals((conf, 'foo'), calls[0])
3161
4087
        conf = config.AuthenticationConfig(_file=StringIO(
3162
4088
                'foo = bar\xff'))
3163
4089
        self.assertRaises(errors.ConfigContentError, conf._get_config)
3164
 
        
 
4090
 
3165
4091
    def test_missing_auth_section_header(self):
3166
4092
        conf = config.AuthenticationConfig(_file=StringIO('foo = bar'))
3167
4093
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
3648
4574
 
3649
4575
    def test_auto_user_id(self):
3650
4576
        """Automatic inference of user name.
3651
 
        
 
4577
 
3652
4578
        This is a bit hard to test in an isolated way, because it depends on
3653
4579
        system functions that go direct to /etc or perhaps somewhere else.
3654
4580
        But it's reasonable to say that on Unix, with an /etc/mailname, we ought
3664
4590
        else:
3665
4591
            self.assertEquals((None, None), (realname, address))
3666
4592
 
 
4593
 
 
4594
class EmailOptionTests(tests.TestCase):
 
4595
 
 
4596
    def test_default_email_uses_BZR_EMAIL(self):
 
4597
        # BZR_EMAIL takes precedence over EMAIL
 
4598
        self.overrideEnv('BZR_EMAIL', 'jelmer@samba.org')
 
4599
        self.overrideEnv('EMAIL', 'jelmer@apache.org')
 
4600
        self.assertEquals('jelmer@samba.org', config.default_email())
 
4601
 
 
4602
    def test_default_email_uses_EMAIL(self):
 
4603
        self.overrideEnv('BZR_EMAIL', None)
 
4604
        self.overrideEnv('EMAIL', 'jelmer@apache.org')
 
4605
        self.assertEquals('jelmer@apache.org', config.default_email())
 
4606
 
 
4607
    def test_BZR_EMAIL_overrides(self):
 
4608
        self.overrideEnv('BZR_EMAIL', 'jelmer@apache.org')
 
4609
        self.assertEquals('jelmer@apache.org',
 
4610
            config.email_from_store('jelmer@debian.org'))
 
4611
        self.overrideEnv('BZR_EMAIL', None)
 
4612
        self.overrideEnv('EMAIL', 'jelmer@samba.org')
 
4613
        self.assertEquals('jelmer@debian.org',
 
4614
            config.email_from_store('jelmer@debian.org'))