501
489
def test_signatures_default(self):
502
490
my_config = config.Config()
503
self.assertFalse(my_config.signature_needed())
492
self.applyDeprecated(deprecated_in((2, 5, 0)),
493
my_config.signature_needed))
504
494
self.assertEqual(config.CHECK_IF_POSSIBLE,
505
my_config.signature_checking())
495
self.applyDeprecated(deprecated_in((2, 5, 0)),
496
my_config.signature_checking))
506
497
self.assertEqual(config.SIGN_WHEN_REQUIRED,
507
my_config.signing_policy())
498
self.applyDeprecated(deprecated_in((2, 5, 0)),
499
my_config.signing_policy))
509
501
def test_signatures_template_method(self):
510
502
my_config = InstrumentedConfig()
511
self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
503
self.assertEqual(config.CHECK_NEVER,
504
self.applyDeprecated(deprecated_in((2, 5, 0)),
505
my_config.signature_checking))
512
506
self.assertEqual(['_get_signature_checking'], my_config._calls)
514
508
def test_signatures_template_method_none(self):
515
509
my_config = InstrumentedConfig()
516
510
my_config._signatures = None
517
511
self.assertEqual(config.CHECK_IF_POSSIBLE,
518
my_config.signature_checking())
512
self.applyDeprecated(deprecated_in((2, 5, 0)),
513
my_config.signature_checking))
519
514
self.assertEqual(['_get_signature_checking'], my_config._calls)
521
516
def test_gpg_signing_command_default(self):
522
517
my_config = config.Config()
523
self.assertEqual('gpg', my_config.gpg_signing_command())
518
self.assertEqual('gpg',
519
self.applyDeprecated(deprecated_in((2, 5, 0)),
520
my_config.gpg_signing_command))
525
522
def test_get_user_option_default(self):
526
523
my_config = config.Config()
673
678
def test_saved_with_content(self):
674
679
content = 'foo = bar\n'
675
conf = config.IniBasedConfig.from_string(
676
content, file_name='./test.conf', save=True)
680
config.IniBasedConfig.from_string(content, file_name='./test.conf',
677
682
self.assertFileEqual(content, 'test.conf')
680
class TestIniConfigOptionExpansionDefaultValue(tests.TestCaseInTempDir):
681
"""What is the default value of expand for config options.
683
This is an opt-in beta feature used to evaluate whether or not option
684
references can appear in dangerous place raising exceptions, disapearing
685
(and as such corrupting data) or if it's safe to activate the option by
688
Note that these tests relies on config._expand_default_value being already
689
overwritten in the parent class setUp.
693
super(TestIniConfigOptionExpansionDefaultValue, self).setUp()
697
self.warnings.append(args[0] % args[1:])
698
self.overrideAttr(trace, 'warning', warning)
700
def get_config(self, expand):
701
c = config.GlobalConfig.from_string('bzr.config.expand=%s' % (expand,),
705
def assertExpandIs(self, expected):
706
actual = config._get_expand_default_value()
707
#self.config.get_user_option_as_bool('bzr.config.expand')
708
self.assertEquals(expected, actual)
710
def test_default_is_None(self):
711
self.assertEquals(None, config._expand_default_value)
713
def test_default_is_False_even_if_None(self):
714
self.config = self.get_config(None)
715
self.assertExpandIs(False)
717
def test_default_is_False_even_if_invalid(self):
718
self.config = self.get_config('<your choice>')
719
self.assertExpandIs(False)
721
# Huh ? My choice is False ? Thanks, always happy to hear that :D
722
# Wait, you've been warned !
723
self.assertLength(1, self.warnings)
725
'Value "<your choice>" is not a boolean for "bzr.config.expand"',
728
def test_default_is_True(self):
729
self.config = self.get_config(True)
730
self.assertExpandIs(True)
732
def test_default_is_False(self):
733
self.config = self.get_config(False)
734
self.assertExpandIs(False)
737
685
class TestIniConfigOptionExpansion(tests.TestCase):
738
686
"""Test option expansion from the IniConfig level.
1226
1187
my_config = config.GlobalConfig()
1227
1188
self.assertEqual(None, my_config._get_user_id())
1229
def test_configured_editor(self):
1230
my_config = config.GlobalConfig.from_string(sample_config_text)
1231
editor = self.applyDeprecated(
1232
deprecated_in((2, 4, 0)), my_config.get_editor)
1233
self.assertEqual('vim', editor)
1235
1190
def test_signatures_always(self):
1236
1191
my_config = config.GlobalConfig.from_string(sample_always_signatures)
1237
1192
self.assertEqual(config.CHECK_NEVER,
1238
my_config.signature_checking())
1193
self.applyDeprecated(deprecated_in((2, 5, 0)),
1194
my_config.signature_checking))
1239
1195
self.assertEqual(config.SIGN_ALWAYS,
1240
my_config.signing_policy())
1241
self.assertEqual(True, my_config.signature_needed())
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))
1243
1202
def test_signatures_if_possible(self):
1244
1203
my_config = config.GlobalConfig.from_string(sample_maybe_signatures)
1245
1204
self.assertEqual(config.CHECK_NEVER,
1246
my_config.signature_checking())
1205
self.applyDeprecated(deprecated_in((2, 5, 0)),
1206
my_config.signature_checking))
1247
1207
self.assertEqual(config.SIGN_WHEN_REQUIRED,
1248
my_config.signing_policy())
1249
self.assertEqual(False, my_config.signature_needed())
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))
1251
1213
def test_signatures_ignore(self):
1252
1214
my_config = config.GlobalConfig.from_string(sample_ignore_signatures)
1253
1215
self.assertEqual(config.CHECK_ALWAYS,
1254
my_config.signature_checking())
1216
self.applyDeprecated(deprecated_in((2, 5, 0)),
1217
my_config.signature_checking))
1255
1218
self.assertEqual(config.SIGN_NEVER,
1256
my_config.signing_policy())
1257
self.assertEqual(False, my_config.signature_needed())
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))
1259
1224
def _get_sample_config(self):
1260
1225
my_config = config.GlobalConfig.from_string(sample_config_text)
1538
1518
self.get_branch_config('http://www.example.com',
1539
1519
global_config=sample_ignore_signatures)
1540
1520
self.assertEqual(config.CHECK_ALWAYS,
1541
self.my_config.signature_checking())
1521
self.applyDeprecated(deprecated_in((2, 5, 0)),
1522
self.my_config.signature_checking))
1542
1523
self.assertEqual(config.SIGN_NEVER,
1543
self.my_config.signing_policy())
1524
self.applyDeprecated(deprecated_in((2, 5, 0)),
1525
self.my_config.signing_policy))
1545
1527
def test_signatures_never(self):
1546
1528
self.get_branch_config('/a/c')
1547
1529
self.assertEqual(config.CHECK_NEVER,
1548
self.my_config.signature_checking())
1530
self.applyDeprecated(deprecated_in((2, 5, 0)),
1531
self.my_config.signature_checking))
1550
1533
def test_signatures_when_available(self):
1551
1534
self.get_branch_config('/a/', global_config=sample_ignore_signatures)
1552
1535
self.assertEqual(config.CHECK_IF_POSSIBLE,
1553
self.my_config.signature_checking())
1536
self.applyDeprecated(deprecated_in((2, 5, 0)),
1537
self.my_config.signature_checking))
1555
1539
def test_signatures_always(self):
1556
1540
self.get_branch_config('/b')
1557
1541
self.assertEqual(config.CHECK_ALWAYS,
1558
self.my_config.signature_checking())
1542
self.applyDeprecated(deprecated_in((2, 5, 0)),
1543
self.my_config.signature_checking))
1560
1545
def test_gpg_signing_command(self):
1561
1546
self.get_branch_config('/b')
1562
self.assertEqual("gnome-gpg", self.my_config.gpg_signing_command())
1547
self.assertEqual("gnome-gpg",
1548
self.applyDeprecated(deprecated_in((2, 5, 0)),
1549
self.my_config.gpg_signing_command))
1564
1551
def test_gpg_signing_command_missing(self):
1565
1552
self.get_branch_config('/a')
1566
self.assertEqual("false", self.my_config.gpg_signing_command())
1553
self.assertEqual("false",
1554
self.applyDeprecated(deprecated_in((2, 5, 0)),
1555
self.my_config.gpg_signing_command))
1568
1557
def test_gpg_signing_key(self):
1569
1558
self.get_branch_config('/b')
1570
self.assertEqual("DD4D5088", self.my_config.gpg_signing_key())
1559
self.assertEqual("DD4D5088", self.applyDeprecated(deprecated_in((2, 5, 0)),
1560
self.my_config.gpg_signing_key))
1572
1562
def test_gpg_signing_key_default(self):
1573
1563
self.get_branch_config('/a')
1574
self.assertEqual("erik@bagfors.nu", self.my_config.gpg_signing_key())
1564
self.assertEqual("erik@bagfors.nu",
1565
self.applyDeprecated(deprecated_in((2, 5, 0)),
1566
self.my_config.gpg_signing_key))
1576
1568
def test_get_user_option_global(self):
1577
1569
self.get_branch_config('/a')
1790
1771
def test_signatures_forced(self):
1791
1772
my_config = self.get_branch_config(
1792
1773
global_config=sample_always_signatures)
1793
self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
1794
self.assertEqual(config.SIGN_ALWAYS, my_config.signing_policy())
1795
self.assertTrue(my_config.signature_needed())
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))
1797
1783
def test_signatures_forced_branch(self):
1798
1784
my_config = self.get_branch_config(
1799
1785
global_config=sample_ignore_signatures,
1800
1786
branch_data_config=sample_always_signatures)
1801
self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
1802
self.assertEqual(config.SIGN_ALWAYS, my_config.signing_policy())
1803
self.assertTrue(my_config.signature_needed())
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))
1805
1796
def test_gpg_signing_command(self):
1806
1797
my_config = self.get_branch_config(
1807
1798
global_config=sample_config_text,
1808
1799
# branch data cannot set gpg_signing_command
1809
1800
branch_data_config="gpg_signing_command=pgp")
1810
self.assertEqual('gnome-gpg', my_config.gpg_signing_command())
1801
self.assertEqual('gnome-gpg',
1802
self.applyDeprecated(deprecated_in((2, 5, 0)),
1803
my_config.gpg_signing_command))
1812
1805
def test_get_user_option_global(self):
1813
1806
my_config = self.get_branch_config(global_config=sample_config_text)
2265
2220
def test_save_hook_remote_bzrdir(self):
2266
2221
remote_branch = branch.Branch.open(self.get_url('tree'))
2267
2222
self.addCleanup(remote_branch.lock_write().unlock)
2268
remote_bzrdir = bzrdir.BzrDir.open(self.get_url('tree'))
2223
remote_bzrdir = controldir.ControlDir.open(self.get_url('tree'))
2269
2224
self.assertSaveHook(remote_bzrdir._get_config())
2227
class TestOptionNames(tests.TestCase):
2229
def is_valid(self, name):
2230
return config._option_ref_re.match('{%s}' % name) is not None
2232
def test_valid_names(self):
2233
self.assertTrue(self.is_valid('foo'))
2234
self.assertTrue(self.is_valid('foo.bar'))
2235
self.assertTrue(self.is_valid('f1'))
2236
self.assertTrue(self.is_valid('_'))
2237
self.assertTrue(self.is_valid('__bar__'))
2238
self.assertTrue(self.is_valid('a_'))
2239
self.assertTrue(self.is_valid('a1'))
2240
# Don't break bzr-svn for no good reason
2241
self.assertTrue(self.is_valid('guessed-layout'))
2243
def test_invalid_names(self):
2244
self.assertFalse(self.is_valid(' foo'))
2245
self.assertFalse(self.is_valid('foo '))
2246
self.assertFalse(self.is_valid('1'))
2247
self.assertFalse(self.is_valid('1,2'))
2248
self.assertFalse(self.is_valid('foo$'))
2249
self.assertFalse(self.is_valid('!foo'))
2250
self.assertFalse(self.is_valid('foo.'))
2251
self.assertFalse(self.is_valid('foo..bar'))
2252
self.assertFalse(self.is_valid('{}'))
2253
self.assertFalse(self.is_valid('{a}'))
2254
self.assertFalse(self.is_valid('a\n'))
2255
self.assertFalse(self.is_valid('-'))
2256
self.assertFalse(self.is_valid('-a'))
2257
self.assertFalse(self.is_valid('a-'))
2258
self.assertFalse(self.is_valid('a--a'))
2260
def assertSingleGroup(self, reference):
2261
# the regexp is used with split and as such should match the reference
2262
# *only*, if more groups needs to be defined, (?:...) should be used.
2263
m = config._option_ref_re.match('{a}')
2264
self.assertLength(1, m.groups())
2266
def test_valid_references(self):
2267
self.assertSingleGroup('{a}')
2268
self.assertSingleGroup('{{a}}')
2272
2271
class TestOption(tests.TestCase):
2274
2273
def test_default_value(self):
2275
2274
opt = config.Option('foo', default='bar')
2276
2275
self.assertEquals('bar', opt.get_default())
2277
def test_callable_default_value(self):
2278
def bar_as_unicode():
2280
opt = config.Option('foo', default=bar_as_unicode)
2281
self.assertEquals('bar', opt.get_default())
2278
2283
def test_default_value_from_env(self):
2279
2284
opt = config.Option('foo', default='bar', default_from_env=['FOO'])
2280
2285
self.overrideEnv('FOO', 'quux')
2296
2301
self.assertRaises(AssertionError, config.Option, 'foo',
2297
2302
default=object())
2300
class TestOptionConverterMixin(object):
2302
def assertConverted(self, expected, opt, value):
2303
self.assertEquals(expected, opt.convert_from_unicode(value))
2305
def assertWarns(self, opt, value):
2308
warnings.append(args[0] % args[1:])
2309
self.overrideAttr(trace, 'warning', warning)
2310
self.assertEquals(None, opt.convert_from_unicode(value))
2311
self.assertLength(1, warnings)
2313
'Value "%s" is not valid for "%s"' % (value, opt.name),
2316
def assertErrors(self, opt, value):
2317
self.assertRaises(errors.ConfigOptionValueError,
2318
opt.convert_from_unicode, value)
2320
def assertConvertInvalid(self, opt, invalid_value):
2322
self.assertEquals(None, opt.convert_from_unicode(invalid_value))
2323
opt.invalid = 'warning'
2324
self.assertWarns(opt, invalid_value)
2325
opt.invalid = 'error'
2326
self.assertErrors(opt, invalid_value)
2329
class TestOptionWithBooleanConverter(tests.TestCase, TestOptionConverterMixin):
2331
def get_option(self):
2332
return config.Option('foo', help='A boolean.',
2333
from_unicode=config.bool_from_store)
2335
def test_convert_invalid(self):
2336
opt = self.get_option()
2337
# A string that is not recognized as a boolean
2338
self.assertConvertInvalid(opt, u'invalid-boolean')
2339
# A list of strings is never recognized as a boolean
2340
self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
2342
def test_convert_valid(self):
2343
opt = self.get_option()
2344
self.assertConverted(True, opt, u'True')
2345
self.assertConverted(True, opt, u'1')
2346
self.assertConverted(False, opt, u'False')
2349
class TestOptionWithIntegerConverter(tests.TestCase, TestOptionConverterMixin):
2351
def get_option(self):
2352
return config.Option('foo', help='An integer.',
2353
from_unicode=config.int_from_store)
2355
def test_convert_invalid(self):
2356
opt = self.get_option()
2357
# A string that is not recognized as an integer
2358
self.assertConvertInvalid(opt, u'forty-two')
2359
# A list of strings is never recognized as an integer
2360
self.assertConvertInvalid(opt, [u'a', u'list'])
2362
def test_convert_valid(self):
2363
opt = self.get_option()
2364
self.assertConverted(16, opt, u'16')
2366
class TestOptionWithListConverter(tests.TestCase, TestOptionConverterMixin):
2368
def get_option(self):
2369
return config.Option('foo', help='A list.',
2370
from_unicode=config.list_from_store)
2372
def test_convert_invalid(self):
2373
# No string is invalid as all forms can be converted to a list
2376
def test_convert_valid(self):
2377
opt = self.get_option()
2378
# An empty string is an empty list
2379
self.assertConverted([], opt, '') # Using a bare str() just in case
2380
self.assertConverted([], opt, u'')
2382
self.assertConverted([u'True'], opt, u'True')
2384
self.assertConverted([u'42'], opt, u'42')
2386
self.assertConverted([u'bar'], opt, u'bar')
2387
# A list remains a list (configObj will turn a string containing commas
2388
# into a list, but that's not what we're testing here)
2389
self.assertConverted([u'foo', u'1', u'True'],
2390
opt, [u'foo', u'1', u'True'])
2393
class TestOptionConverterMixin(object):
2395
def assertConverted(self, expected, opt, value):
2396
self.assertEquals(expected, opt.convert_from_unicode(value))
2398
def assertWarns(self, opt, value):
2401
warnings.append(args[0] % args[1:])
2402
self.overrideAttr(trace, 'warning', warning)
2403
self.assertEquals(None, opt.convert_from_unicode(value))
2404
self.assertLength(1, warnings)
2406
'Value "%s" is not valid for "%s"' % (value, opt.name),
2409
def assertErrors(self, opt, value):
2410
self.assertRaises(errors.ConfigOptionValueError,
2411
opt.convert_from_unicode, value)
2413
def assertConvertInvalid(self, opt, invalid_value):
2415
self.assertEquals(None, opt.convert_from_unicode(invalid_value))
2416
opt.invalid = 'warning'
2417
self.assertWarns(opt, invalid_value)
2418
opt.invalid = 'error'
2419
self.assertErrors(opt, invalid_value)
2422
class TestOptionWithBooleanConverter(tests.TestCase, TestOptionConverterMixin):
2424
def get_option(self):
2425
return config.Option('foo', help='A boolean.',
2426
from_unicode=config.bool_from_store)
2428
def test_convert_invalid(self):
2429
opt = self.get_option()
2430
# A string that is not recognized as a boolean
2431
self.assertConvertInvalid(opt, u'invalid-boolean')
2432
# A list of strings is never recognized as a boolean
2433
self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
2435
def test_convert_valid(self):
2436
opt = self.get_option()
2437
self.assertConverted(True, opt, u'True')
2438
self.assertConverted(True, opt, u'1')
2439
self.assertConverted(False, opt, u'False')
2442
class TestOptionWithIntegerConverter(tests.TestCase, TestOptionConverterMixin):
2444
def get_option(self):
2445
return config.Option('foo', help='An integer.',
2446
from_unicode=config.int_from_store)
2448
def test_convert_invalid(self):
2449
opt = self.get_option()
2450
# A string that is not recognized as an integer
2451
self.assertConvertInvalid(opt, u'forty-two')
2452
# A list of strings is never recognized as an integer
2453
self.assertConvertInvalid(opt, [u'a', u'list'])
2455
def test_convert_valid(self):
2456
opt = self.get_option()
2457
self.assertConverted(16, opt, u'16')
2460
class TestOptionWithListConverter(tests.TestCase, TestOptionConverterMixin):
2462
def get_option(self):
2463
return config.Option('foo', help='A list.',
2464
from_unicode=config.list_from_store)
2304
def test_not_supported_callable_default_value_not_unicode(self):
2305
def bar_not_unicode():
2307
opt = config.Option('foo', default=bar_not_unicode)
2308
self.assertRaises(AssertionError, opt.get_default)
2310
def test_get_help_topic(self):
2311
opt = config.Option('foo')
2312
self.assertEquals('foo', opt.get_help_topic())
2315
class TestOptionConverter(tests.TestCase):
2317
def assertConverted(self, expected, opt, value):
2318
self.assertEquals(expected, opt.convert_from_unicode(None, value))
2320
def assertCallsWarning(self, opt, value):
2324
warnings.append(args[0] % args[1:])
2325
self.overrideAttr(trace, 'warning', warning)
2326
self.assertEquals(None, opt.convert_from_unicode(None, value))
2327
self.assertLength(1, warnings)
2329
'Value "%s" is not valid for "%s"' % (value, opt.name),
2332
def assertCallsError(self, opt, value):
2333
self.assertRaises(errors.ConfigOptionValueError,
2334
opt.convert_from_unicode, None, value)
2336
def assertConvertInvalid(self, opt, invalid_value):
2338
self.assertEquals(None, opt.convert_from_unicode(None, invalid_value))
2339
opt.invalid = 'warning'
2340
self.assertCallsWarning(opt, invalid_value)
2341
opt.invalid = 'error'
2342
self.assertCallsError(opt, invalid_value)
2345
class TestOptionWithBooleanConverter(TestOptionConverter):
2347
def get_option(self):
2348
return config.Option('foo', help='A boolean.',
2349
from_unicode=config.bool_from_store)
2351
def test_convert_invalid(self):
2352
opt = self.get_option()
2353
# A string that is not recognized as a boolean
2354
self.assertConvertInvalid(opt, u'invalid-boolean')
2355
# A list of strings is never recognized as a boolean
2356
self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
2358
def test_convert_valid(self):
2359
opt = self.get_option()
2360
self.assertConverted(True, opt, u'True')
2361
self.assertConverted(True, opt, u'1')
2362
self.assertConverted(False, opt, u'False')
2365
class TestOptionWithIntegerConverter(TestOptionConverter):
2367
def get_option(self):
2368
return config.Option('foo', help='An integer.',
2369
from_unicode=config.int_from_store)
2371
def test_convert_invalid(self):
2372
opt = self.get_option()
2373
# A string that is not recognized as an integer
2374
self.assertConvertInvalid(opt, u'forty-two')
2375
# A list of strings is never recognized as an integer
2376
self.assertConvertInvalid(opt, [u'a', u'list'])
2378
def test_convert_valid(self):
2379
opt = self.get_option()
2380
self.assertConverted(16, opt, u'16')
2383
class TestOptionWithSIUnitConverter(TestOptionConverter):
2385
def get_option(self):
2386
return config.Option('foo', help='An integer in SI units.',
2387
from_unicode=config.int_SI_from_store)
2389
def test_convert_invalid(self):
2390
opt = self.get_option()
2391
self.assertConvertInvalid(opt, u'not-a-unit')
2392
self.assertConvertInvalid(opt, u'Gb') # Forgot the value
2393
self.assertConvertInvalid(opt, u'1b') # Forgot the unit
2394
self.assertConvertInvalid(opt, u'1GG')
2395
self.assertConvertInvalid(opt, u'1Mbb')
2396
self.assertConvertInvalid(opt, u'1MM')
2398
def test_convert_valid(self):
2399
opt = self.get_option()
2400
self.assertConverted(int(5e3), opt, u'5kb')
2401
self.assertConverted(int(5e6), opt, u'5M')
2402
self.assertConverted(int(5e6), opt, u'5MB')
2403
self.assertConverted(int(5e9), opt, u'5g')
2404
self.assertConverted(int(5e9), opt, u'5gB')
2405
self.assertConverted(100, opt, u'100')
2408
class TestListOption(TestOptionConverter):
2410
def get_option(self):
2411
return config.ListOption('foo', help='A list.')
2466
2413
def test_convert_invalid(self):
2467
2414
opt = self.get_option()
2615
2625
self.assertEquals(config._NewlyCreatedOption, section.orig['foo'])
2618
class TestCommandLineSection(tests.TestCase):
2628
class TestCommandLineStore(tests.TestCase):
2620
2630
def setUp(self):
2621
super(TestCommandLineSection, self).setUp()
2622
self.section = config.CommandLineSection()
2631
super(TestCommandLineStore, self).setUp()
2632
self.store = config.CommandLineStore()
2633
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
2635
def get_section(self):
2636
"""Get the unique section for the command line overrides."""
2637
sections = list(self.store.get_sections())
2638
self.assertLength(1, sections)
2639
store, section = sections[0]
2640
self.assertEquals(self.store, store)
2624
2643
def test_no_override(self):
2625
self.section._from_cmdline([])
2626
# FIXME: we want some iterator over all options, failing that, we peek
2627
# under the cover -- vila 2011-09026
2628
self.assertLength(0, self.section.options)
2644
self.store._from_cmdline([])
2645
section = self.get_section()
2646
self.assertLength(0, list(section.iter_option_names()))
2630
2648
def test_simple_override(self):
2631
self.section._from_cmdline(['a=b'])
2632
self.assertEqual('b', self.section.get('a'))
2649
self.store._from_cmdline(['a=b'])
2650
section = self.get_section()
2651
self.assertEqual('b', section.get('a'))
2634
2653
def test_list_override(self):
2635
self.section._from_cmdline(['l=1,2,3'])
2636
val = self.section.get('l')
2654
opt = config.ListOption('l')
2655
config.option_registry.register(opt)
2656
self.store._from_cmdline(['l=1,2,3'])
2657
val = self.get_section().get('l')
2637
2658
self.assertEqual('1,2,3', val)
2638
# Reminder: lists should registered as such explicitely, otherwise the
2639
# conversion needs to be done afterwards.
2640
self.assertEqual(['1', '2', '3'], config.list_from_store(val))
2659
# Reminder: lists should be registered as such explicitely, otherwise
2660
# the conversion needs to be done afterwards.
2661
self.assertEqual(['1', '2', '3'],
2662
opt.convert_from_unicode(self.store, val))
2642
2664
def test_multiple_overrides(self):
2643
self.section._from_cmdline(['a=b', 'x=y'])
2644
self.assertEquals('b', self.section.get('a'))
2645
self.assertEquals('y', self.section.get('x'))
2665
self.store._from_cmdline(['a=b', 'x=y'])
2666
section = self.get_section()
2667
self.assertEquals('b', section.get('a'))
2668
self.assertEquals('y', section.get('x'))
2647
2670
def test_wrong_syntax(self):
2648
2671
self.assertRaises(errors.BzrCommandError,
2649
self.section._from_cmdline, ['a=b', 'c'])
2672
self.store._from_cmdline, ['a=b', 'c'])
2674
class TestStoreMinimalAPI(tests.TestCaseWithTransport):
2676
scenarios = [(key, {'get_store': builder}) for key, builder
2677
in config.test_store_builder_registry.iteritems()] + [
2678
('cmdline', {'get_store': lambda test: config.CommandLineStore()})]
2681
store = self.get_store(self)
2682
if type(store) == config.TransportIniFileStore:
2683
raise tests.TestNotApplicable(
2684
"%s is not a concrete Store implementation"
2685
" so it doesn't need an id" % (store.__class__.__name__,))
2686
self.assertIsNot(None, store.id)
2652
2689
class TestStore(tests.TestCaseWithTransport):
2654
def assertSectionContent(self, expected, section):
2691
def assertSectionContent(self, expected, (store, section)):
2655
2692
"""Assert that some options have the proper values in a section."""
2656
2693
expected_name, expected_options = expected
2657
2694
self.assertEquals(expected_name, section.id)
2696
2733
self.assertRaises(AssertionError, store._load_from_string, 'bar=baz')
2736
class TestStoreQuoting(TestStore):
2738
scenarios = [(key, {'get_store': builder}) for key, builder
2739
in config.test_store_builder_registry.iteritems()]
2742
super(TestStoreQuoting, self).setUp()
2743
self.store = self.get_store(self)
2744
# We need a loaded store but any content will do
2745
self.store._load_from_string('')
2747
def assertIdempotent(self, s):
2748
"""Assert that quoting an unquoted string is a no-op and vice-versa.
2750
What matters here is that option values, as they appear in a store, can
2751
be safely round-tripped out of the store and back.
2753
:param s: A string, quoted if required.
2755
self.assertEquals(s, self.store.quote(self.store.unquote(s)))
2756
self.assertEquals(s, self.store.unquote(self.store.quote(s)))
2758
def test_empty_string(self):
2759
if isinstance(self.store, config.IniFileStore):
2760
# configobj._quote doesn't handle empty values
2761
self.assertRaises(AssertionError,
2762
self.assertIdempotent, '')
2764
self.assertIdempotent('')
2765
# But quoted empty strings are ok
2766
self.assertIdempotent('""')
2768
def test_embedded_spaces(self):
2769
self.assertIdempotent('" a b c "')
2771
def test_embedded_commas(self):
2772
self.assertIdempotent('" a , b c "')
2774
def test_simple_comma(self):
2775
if isinstance(self.store, config.IniFileStore):
2776
# configobj requires that lists are special-cased
2777
self.assertRaises(AssertionError,
2778
self.assertIdempotent, ',')
2780
self.assertIdempotent(',')
2781
# When a single comma is required, quoting is also required
2782
self.assertIdempotent('","')
2784
def test_list(self):
2785
if isinstance(self.store, config.IniFileStore):
2786
# configobj requires that lists are special-cased
2787
self.assertRaises(AssertionError,
2788
self.assertIdempotent, 'a,b')
2790
self.assertIdempotent('a,b')
2793
class TestDictFromStore(tests.TestCase):
2795
def test_unquote_not_string(self):
2796
conf = config.MemoryStack('x=2\n[a_section]\na=1\n')
2797
value = conf.get('a_section')
2798
# Urgh, despite 'conf' asking for the no-name section, we get the
2799
# content of another section as a dict o_O
2800
self.assertEquals({'a': '1'}, value)
2801
unquoted = conf.store.unquote(value)
2802
# Which cannot be unquoted but shouldn't crash either (the use cases
2803
# are getting the value or displaying it. In the later case, '%s' will
2805
self.assertEquals({'a': '1'}, unquoted)
2806
self.assertEquals("{u'a': u'1'}", '%s' % (unquoted,))
2699
2809
class TestIniFileStoreContent(tests.TestCaseWithTransport):
2700
2810
"""Simulate loading a config store with content of various encodings.
2900
3049
config.ConfigHooks.install_named_hook('save', hook, None)
2901
3050
self.assertLength(0, calls)
2902
3051
store = self.get_store(self)
3052
# FIXME: There should be a better way than relying on the test
3053
# parametrization to identify branch.conf -- vila 2011-0526
3054
if self.store_id in ('branch', 'remote_branch'):
3055
# branch stores requires write locked branches
3056
self.addCleanup(store.branch.lock_write().unlock)
2903
3057
section = store.get_mutable_section('baz')
2904
3058
section.set('foo', 'bar')
2906
3060
self.assertLength(1, calls)
2907
3061
self.assertEquals((store,), calls[0])
2910
class TestIniFileStore(TestStore):
3063
def test_set_mark_dirty(self):
3064
stack = config.MemoryStack('')
3065
self.assertLength(0, stack.store.dirty_sections)
3066
stack.set('foo', 'baz')
3067
self.assertLength(1, stack.store.dirty_sections)
3068
self.assertTrue(stack.store._need_saving())
3070
def test_remove_mark_dirty(self):
3071
stack = config.MemoryStack('foo=bar')
3072
self.assertLength(0, stack.store.dirty_sections)
3074
self.assertLength(1, stack.store.dirty_sections)
3075
self.assertTrue(stack.store._need_saving())
3078
class TestStoreSaveChanges(tests.TestCaseWithTransport):
3079
"""Tests that config changes are kept in memory and saved on-demand."""
3082
super(TestStoreSaveChanges, self).setUp()
3083
self.transport = self.get_transport()
3084
# Most of the tests involve two stores pointing to the same persistent
3085
# storage to observe the effects of concurrent changes
3086
self.st1 = config.TransportIniFileStore(self.transport, 'foo.conf')
3087
self.st2 = config.TransportIniFileStore(self.transport, 'foo.conf')
3090
self.warnings.append(args[0] % args[1:])
3091
self.overrideAttr(trace, 'warning', warning)
3093
def has_store(self, store):
3094
store_basename = urlutils.relative_url(self.transport.external_url(),
3095
store.external_url())
3096
return self.transport.has(store_basename)
3098
def get_stack(self, store):
3099
# Any stack will do as long as it uses the right store, just a single
3100
# no-name section is enough
3101
return config.Stack([store.get_sections], store)
3103
def test_no_changes_no_save(self):
3104
s = self.get_stack(self.st1)
3105
s.store.save_changes()
3106
self.assertEquals(False, self.has_store(self.st1))
3108
def test_unrelated_concurrent_update(self):
3109
s1 = self.get_stack(self.st1)
3110
s2 = self.get_stack(self.st2)
3111
s1.set('foo', 'bar')
3112
s2.set('baz', 'quux')
3114
# Changes don't propagate magically
3115
self.assertEquals(None, s1.get('baz'))
3116
s2.store.save_changes()
3117
self.assertEquals('quux', s2.get('baz'))
3118
# Changes are acquired when saving
3119
self.assertEquals('bar', s2.get('foo'))
3120
# Since there is no overlap, no warnings are emitted
3121
self.assertLength(0, self.warnings)
3123
def test_concurrent_update_modified(self):
3124
s1 = self.get_stack(self.st1)
3125
s2 = self.get_stack(self.st2)
3126
s1.set('foo', 'bar')
3127
s2.set('foo', 'baz')
3130
s2.store.save_changes()
3131
self.assertEquals('baz', s2.get('foo'))
3132
# But the user get a warning
3133
self.assertLength(1, self.warnings)
3134
warning = self.warnings[0]
3135
self.assertStartsWith(warning, 'Option foo in section None')
3136
self.assertEndsWith(warning, 'was changed from <CREATED> to bar.'
3137
' The baz value will be saved.')
3139
def test_concurrent_deletion(self):
3140
self.st1._load_from_string('foo=bar')
3142
s1 = self.get_stack(self.st1)
3143
s2 = self.get_stack(self.st2)
3146
s1.store.save_changes()
3148
self.assertLength(0, self.warnings)
3149
s2.store.save_changes()
3151
self.assertLength(1, self.warnings)
3152
warning = self.warnings[0]
3153
self.assertStartsWith(warning, 'Option foo in section None')
3154
self.assertEndsWith(warning, 'was changed from bar to <CREATED>.'
3155
' The <DELETED> value will be saved.')
3158
class TestQuotingIniFileStore(tests.TestCaseWithTransport):
3160
def get_store(self):
3161
return config.TransportIniFileStore(self.get_transport(), 'foo.conf')
3163
def test_get_quoted_string(self):
3164
store = self.get_store()
3165
store._load_from_string('foo= " abc "')
3166
stack = config.Stack([store.get_sections])
3167
self.assertEquals(' abc ', stack.get('foo'))
3169
def test_set_quoted_string(self):
3170
store = self.get_store()
3171
stack = config.Stack([store.get_sections], store)
3172
stack.set('foo', ' a b c ')
3174
self.assertFileEqual('foo = " a b c "' + os.linesep, 'foo.conf')
3177
class TestTransportIniFileStore(TestStore):
2912
3179
def test_loading_unknown_file_fails(self):
2913
store = config.IniFileStore(self.get_transport(), 'I-do-not-exist')
3180
store = config.TransportIniFileStore(self.get_transport(),
2914
3182
self.assertRaises(errors.NoSuchFile, store.load)
2916
3184
def test_invalid_content(self):
2917
store = config.IniFileStore(self.get_transport(), 'foo.conf', )
3185
store = config.TransportIniFileStore(self.get_transport(), 'foo.conf')
2918
3186
self.assertEquals(False, store.is_loaded())
2919
3187
exc = self.assertRaises(
2920
3188
errors.ParseConfigError, store._load_from_string,
3223
3486
matcher = config.LocationMatcher(store, expected_url)
3224
3487
self.assertEquals(expected_location, matcher.location)
3489
def test_branch_name_colo(self):
3490
store = self.get_store(self)
3491
store._load_from_string(dedent("""\
3493
push_location=my{branchname}
3495
matcher = config.LocationMatcher(store, 'file:///,branch=example%3c')
3496
self.assertEqual('example<', matcher.branch_name)
3497
((_, section),) = matcher.get_sections()
3498
self.assertEqual('example<', section.locals['branchname'])
3500
def test_branch_name_basename(self):
3501
store = self.get_store(self)
3502
store._load_from_string(dedent("""\
3504
push_location=my{branchname}
3506
matcher = config.LocationMatcher(store, 'file:///parent/example%3c')
3507
self.assertEqual('example<', matcher.branch_name)
3508
((_, section),) = matcher.get_sections()
3509
self.assertEqual('example<', section.locals['branchname'])
3512
class TestStartingPathMatcher(TestStore):
3515
super(TestStartingPathMatcher, self).setUp()
3516
# Any simple store is good enough
3517
self.store = config.IniFileStore()
3519
def assertSectionIDs(self, expected, location, content):
3520
self.store._load_from_string(content)
3521
matcher = config.StartingPathMatcher(self.store, location)
3522
sections = list(matcher.get_sections())
3523
self.assertLength(len(expected), sections)
3524
self.assertEqual(expected, [section.id for _, section in sections])
3527
def test_empty(self):
3528
self.assertSectionIDs([], self.get_url(), '')
3530
def test_url_vs_local_paths(self):
3531
# The matcher location is an url and the section names are local paths
3532
self.assertSectionIDs(['/foo/bar', '/foo'],
3533
'file:///foo/bar/baz', '''\
3538
def test_local_path_vs_url(self):
3539
# The matcher location is a local path and the section names are urls
3540
self.assertSectionIDs(['file:///foo/bar', 'file:///foo'],
3541
'/foo/bar/baz', '''\
3547
def test_no_name_section_included_when_present(self):
3548
# Note that other tests will cover the case where the no-name section
3549
# is empty and as such, not included.
3550
sections = self.assertSectionIDs(['/foo/bar', '/foo', None],
3551
'/foo/bar/baz', '''\
3552
option = defined so the no-name section exists
3556
self.assertEquals(['baz', 'bar/baz', '/foo/bar/baz'],
3557
[s.locals['relpath'] for _, s in sections])
3559
def test_order_reversed(self):
3560
self.assertSectionIDs(['/foo/bar', '/foo'], '/foo/bar/baz', '''\
3565
def test_unrelated_section_excluded(self):
3566
self.assertSectionIDs(['/foo/bar', '/foo'], '/foo/bar/baz', '''\
3572
def test_glob_included(self):
3573
sections = self.assertSectionIDs(['/foo/*/baz', '/foo/b*', '/foo'],
3574
'/foo/bar/baz', '''\
3580
# Note that 'baz' as a relpath for /foo/b* is not fully correct, but
3581
# nothing really is... as far using {relpath} to append it to something
3582
# else, this seems good enough though.
3583
self.assertEquals(['', 'baz', 'bar/baz'],
3584
[s.locals['relpath'] for _, s in sections])
3586
def test_respect_order(self):
3587
self.assertSectionIDs(['/foo', '/foo/b*', '/foo/*/baz'],
3588
'/foo/bar/baz', '''\
3227
3596
class TestNameMatcher(TestStore):
3255
3624
self.assertLength(0, sections)
3258
class TestStackGet(tests.TestCase):
3260
# FIXME: This should be parametrized for all known Stack or dedicated
3261
# paramerized tests created to avoid bloating -- vila 2011-03-31
3263
def overrideOptionRegistry(self):
3627
class TestBaseStackGet(tests.TestCase):
3630
super(TestBaseStackGet, self).setUp()
3264
3631
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3266
def test_single_config_get(self):
3267
conf = dict(foo='bar')
3268
conf_stack = config.Stack([conf])
3269
self.assertEquals('bar', conf_stack.get('foo'))
3633
def test_get_first_definition(self):
3634
store1 = config.IniFileStore()
3635
store1._load_from_string('foo=bar')
3636
store2 = config.IniFileStore()
3637
store2._load_from_string('foo=baz')
3638
conf = config.Stack([store1.get_sections, store2.get_sections])
3639
self.assertEquals('bar', conf.get('foo'))
3271
3641
def test_get_with_registered_default_value(self):
3272
conf_stack = config.Stack([dict()])
3273
opt = config.Option('foo', default='bar')
3274
self.overrideOptionRegistry()
3275
config.option_registry.register('foo', opt)
3642
config.option_registry.register(config.Option('foo', default='bar'))
3643
conf_stack = config.Stack([])
3276
3644
self.assertEquals('bar', conf_stack.get('foo'))
3278
3646
def test_get_without_registered_default_value(self):
3279
conf_stack = config.Stack([dict()])
3280
opt = config.Option('foo')
3281
self.overrideOptionRegistry()
3282
config.option_registry.register('foo', opt)
3647
config.option_registry.register(config.Option('foo'))
3648
conf_stack = config.Stack([])
3283
3649
self.assertEquals(None, conf_stack.get('foo'))
3285
3651
def test_get_without_default_value_for_not_registered(self):
3286
conf_stack = config.Stack([dict()])
3287
opt = config.Option('foo')
3288
self.overrideOptionRegistry()
3652
conf_stack = config.Stack([])
3289
3653
self.assertEquals(None, conf_stack.get('foo'))
3291
def test_get_first_definition(self):
3292
conf1 = dict(foo='bar')
3293
conf2 = dict(foo='baz')
3294
conf_stack = config.Stack([conf1, conf2])
3295
self.assertEquals('bar', conf_stack.get('foo'))
3297
def test_get_embedded_definition(self):
3298
conf1 = dict(yy='12')
3299
conf2 = config.Stack([dict(xx='42'), dict(foo='baz')])
3300
conf_stack = config.Stack([conf1, conf2])
3301
self.assertEquals('baz', conf_stack.get('foo'))
3303
3655
def test_get_for_empty_section_callable(self):
3304
3656
conf_stack = config.Stack([lambda : []])
3305
3657
self.assertEquals(None, conf_stack.get('foo'))
3307
3659
def test_get_for_broken_callable(self):
3308
3660
# Trying to use and invalid callable raises an exception on first use
3309
conf_stack = config.Stack([lambda : object()])
3661
conf_stack = config.Stack([object])
3310
3662
self.assertRaises(TypeError, conf_stack.get, 'foo')
3665
class TestStackWithSimpleStore(tests.TestCase):
3668
super(TestStackWithSimpleStore, self).setUp()
3669
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3670
self.registry = config.option_registry
3672
def get_conf(self, content=None):
3673
return config.MemoryStack(content)
3675
def test_override_value_from_env(self):
3676
self.overrideEnv('FOO', None)
3677
self.registry.register(
3678
config.Option('foo', default='bar', override_from_env=['FOO']))
3679
self.overrideEnv('FOO', 'quux')
3680
# Env variable provides a default taking over the option one
3681
conf = self.get_conf('foo=store')
3682
self.assertEquals('quux', conf.get('foo'))
3684
def test_first_override_value_from_env_wins(self):
3685
self.overrideEnv('NO_VALUE', None)
3686
self.overrideEnv('FOO', None)
3687
self.overrideEnv('BAZ', None)
3688
self.registry.register(
3689
config.Option('foo', default='bar',
3690
override_from_env=['NO_VALUE', 'FOO', 'BAZ']))
3691
self.overrideEnv('FOO', 'foo')
3692
self.overrideEnv('BAZ', 'baz')
3693
# The first env var set wins
3694
conf = self.get_conf('foo=store')
3695
self.assertEquals('foo', conf.get('foo'))
3698
class TestMemoryStack(tests.TestCase):
3701
conf = config.MemoryStack('foo=bar')
3702
self.assertEquals('bar', conf.get('foo'))
3705
conf = config.MemoryStack('foo=bar')
3706
conf.set('foo', 'baz')
3707
self.assertEquals('baz', conf.get('foo'))
3709
def test_no_content(self):
3710
conf = config.MemoryStack()
3711
# No content means no loading
3712
self.assertFalse(conf.store.is_loaded())
3713
self.assertRaises(NotImplementedError, conf.get, 'foo')
3714
# But a content can still be provided
3715
conf.store._load_from_string('foo=bar')
3716
self.assertEquals('bar', conf.get('foo'))
3719
class TestStackIterSections(tests.TestCase):
3721
def test_empty_stack(self):
3722
conf = config.Stack([])
3723
sections = list(conf.iter_sections())
3724
self.assertLength(0, sections)
3726
def test_empty_store(self):
3727
store = config.IniFileStore()
3728
store._load_from_string('')
3729
conf = config.Stack([store.get_sections])
3730
sections = list(conf.iter_sections())
3731
self.assertLength(0, sections)
3733
def test_simple_store(self):
3734
store = config.IniFileStore()
3735
store._load_from_string('foo=bar')
3736
conf = config.Stack([store.get_sections])
3737
tuples = list(conf.iter_sections())
3738
self.assertLength(1, tuples)
3739
(found_store, found_section) = tuples[0]
3740
self.assertIs(store, found_store)
3742
def test_two_stores(self):
3743
store1 = config.IniFileStore()
3744
store1._load_from_string('foo=bar')
3745
store2 = config.IniFileStore()
3746
store2._load_from_string('bar=qux')
3747
conf = config.Stack([store1.get_sections, store2.get_sections])
3748
tuples = list(conf.iter_sections())
3749
self.assertLength(2, tuples)
3750
self.assertIs(store1, tuples[0][0])
3751
self.assertIs(store2, tuples[1][0])
3313
3754
class TestStackWithTransport(tests.TestCaseWithTransport):
3315
3756
scenarios = [(key, {'get_stack': builder}) for key, builder
3394
3843
def test_get_default_integer_None(self):
3395
3844
self.register_integer_option('foo')
3396
self.assertEquals(None, self.conf.get('foo'))
3845
conf = self.get_conf('')
3846
self.assertEquals(None, conf.get('foo'))
3398
3848
def test_get_default_integer(self):
3399
3849
self.register_integer_option('foo', 42)
3400
self.assertEquals(42, self.conf.get('foo'))
3850
conf = self.get_conf('')
3851
self.assertEquals(42, conf.get('foo'))
3402
3853
def test_get_default_integer_as_string(self):
3403
3854
self.register_integer_option('foo', u'42')
3404
self.assertEquals(42, self.conf.get('foo'))
3855
conf = self.get_conf('')
3856
self.assertEquals(42, conf.get('foo'))
3406
3858
def test_get_default_integer_from_env(self):
3407
3859
self.register_integer_option('foo', default_from_env=['FOO'])
3408
3860
self.overrideEnv('FOO', '18')
3409
self.assertEquals(18, self.conf.get('foo'))
3861
conf = self.get_conf('')
3862
self.assertEquals(18, conf.get('foo'))
3411
3864
def test_get_default_integer_when_conversion_fails(self):
3412
3865
self.register_integer_option('foo', default='12')
3413
self.conf.store._load_from_string('foo=invalid integer')
3414
self.assertEquals(12, self.conf.get('foo'))
3866
conf = self.get_conf('foo=invalid integer')
3867
self.assertEquals(12, conf.get('foo'))
3416
3869
def register_list_option(self, name, default=None, default_from_env=None):
3417
l = config.Option(name, help='A list.',
3418
default=default, default_from_env=default_from_env,
3419
from_unicode=config.list_from_store)
3870
l = config.ListOption(name, help='A list.', default=default,
3871
default_from_env=default_from_env)
3420
3872
self.registry.register(l)
3422
3874
def test_get_default_list_None(self):
3423
3875
self.register_list_option('foo')
3424
self.assertEquals(None, self.conf.get('foo'))
3876
conf = self.get_conf('')
3877
self.assertEquals(None, conf.get('foo'))
3426
3879
def test_get_default_list_empty(self):
3427
3880
self.register_list_option('foo', '')
3428
self.assertEquals([], self.conf.get('foo'))
3881
conf = self.get_conf('')
3882
self.assertEquals([], conf.get('foo'))
3430
3884
def test_get_default_list_from_env(self):
3431
3885
self.register_list_option('foo', default_from_env=['FOO'])
3432
3886
self.overrideEnv('FOO', '')
3433
self.assertEquals([], self.conf.get('foo'))
3887
conf = self.get_conf('')
3888
self.assertEquals([], conf.get('foo'))
3435
3890
def test_get_with_list_converter_no_item(self):
3436
3891
self.register_list_option('foo', None)
3437
self.conf.store._load_from_string('foo=,')
3438
self.assertEquals([], self.conf.get('foo'))
3892
conf = self.get_conf('foo=,')
3893
self.assertEquals([], conf.get('foo'))
3440
3895
def test_get_with_list_converter_many_items(self):
3441
3896
self.register_list_option('foo', None)
3442
self.conf.store._load_from_string('foo=m,o,r,e')
3443
self.assertEquals(['m', 'o', 'r', 'e'], self.conf.get('foo'))
3897
conf = self.get_conf('foo=m,o,r,e')
3898
self.assertEquals(['m', 'o', 'r', 'e'], conf.get('foo'))
3445
3900
def test_get_with_list_converter_embedded_spaces_many_items(self):
3446
3901
self.register_list_option('foo', None)
3447
self.conf.store._load_from_string('foo=" bar", "baz "')
3448
self.assertEquals([' bar', 'baz '], self.conf.get('foo'))
3902
conf = self.get_conf('foo=" bar", "baz "')
3903
self.assertEquals([' bar', 'baz '], conf.get('foo'))
3450
3905
def test_get_with_list_converter_stripped_spaces_many_items(self):
3451
3906
self.register_list_option('foo', None)
3452
self.conf.store._load_from_string('foo= bar , baz ')
3453
self.assertEquals(['bar', 'baz'], self.conf.get('foo'))
3907
conf = self.get_conf('foo= bar , baz ')
3908
self.assertEquals(['bar', 'baz'], conf.get('foo'))
3911
class TestIterOptionRefs(tests.TestCase):
3912
"""iter_option_refs is a bit unusual, document some cases."""
3914
def assertRefs(self, expected, string):
3915
self.assertEquals(expected, list(config.iter_option_refs(string)))
3917
def test_empty(self):
3918
self.assertRefs([(False, '')], '')
3920
def test_no_refs(self):
3921
self.assertRefs([(False, 'foo bar')], 'foo bar')
3923
def test_single_ref(self):
3924
self.assertRefs([(False, ''), (True, '{foo}'), (False, '')], '{foo}')
3926
def test_broken_ref(self):
3927
self.assertRefs([(False, '{foo')], '{foo')
3929
def test_embedded_ref(self):
3930
self.assertRefs([(False, '{'), (True, '{foo}'), (False, '}')],
3933
def test_two_refs(self):
3934
self.assertRefs([(False, ''), (True, '{foo}'),
3935
(False, ''), (True, '{bar}'),
3939
def test_newline_in_refs_are_not_matched(self):
3940
self.assertRefs([(False, '{\nxx}{xx\n}{{\n}}')], '{\nxx}{xx\n}{{\n}}')
3456
3943
class TestStackExpandOptions(tests.TestCaseWithTransport):
3607
4102
self.assertEquals('quux', c.get('bar', expand=True))
4105
class TestStackCrossStoresExpand(tests.TestCaseWithTransport):
4107
def test_cross_global_locations(self):
4108
l_store = config.LocationStore()
4109
l_store._load_from_string('''
4115
g_store = config.GlobalStore()
4116
g_store._load_from_string('''
4122
stack = config.LocationStack('/branch')
4123
self.assertEquals('glob-bar', stack.get('lbar', expand=True))
4124
self.assertEquals('loc-foo', stack.get('gfoo', expand=True))
4127
class TestStackExpandSectionLocals(tests.TestCaseWithTransport):
4129
def test_expand_locals_empty(self):
4130
l_store = config.LocationStore()
4131
l_store._load_from_string('''
4132
[/home/user/project]
4137
stack = config.LocationStack('/home/user/project/')
4138
self.assertEquals('', stack.get('base', expand=True))
4139
self.assertEquals('', stack.get('rel', expand=True))
4141
def test_expand_basename_locally(self):
4142
l_store = config.LocationStore()
4143
l_store._load_from_string('''
4144
[/home/user/project]
4148
stack = config.LocationStack('/home/user/project/branch')
4149
self.assertEquals('branch', stack.get('bfoo', expand=True))
4151
def test_expand_basename_locally_longer_path(self):
4152
l_store = config.LocationStore()
4153
l_store._load_from_string('''
4158
stack = config.LocationStack('/home/user/project/dir/branch')
4159
self.assertEquals('branch', stack.get('bfoo', expand=True))
4161
def test_expand_relpath_locally(self):
4162
l_store = config.LocationStore()
4163
l_store._load_from_string('''
4164
[/home/user/project]
4165
lfoo = loc-foo/{relpath}
4168
stack = config.LocationStack('/home/user/project/branch')
4169
self.assertEquals('loc-foo/branch', stack.get('lfoo', expand=True))
4171
def test_expand_relpath_unknonw_in_global(self):
4172
g_store = config.GlobalStore()
4173
g_store._load_from_string('''
4178
stack = config.LocationStack('/home/user/project/branch')
4179
self.assertRaises(errors.ExpandingUnknownOption,
4180
stack.get, 'gfoo', expand=True)
4182
def test_expand_local_option_locally(self):
4183
l_store = config.LocationStore()
4184
l_store._load_from_string('''
4185
[/home/user/project]
4186
lfoo = loc-foo/{relpath}
4190
g_store = config.GlobalStore()
4191
g_store._load_from_string('''
4197
stack = config.LocationStack('/home/user/project/branch')
4198
self.assertEquals('glob-bar', stack.get('lbar', expand=True))
4199
self.assertEquals('loc-foo/branch', stack.get('gfoo', expand=True))
4201
def test_locals_dont_leak(self):
4202
"""Make sure we chose the right local in presence of several sections.
4204
l_store = config.LocationStore()
4205
l_store._load_from_string('''
4207
lfoo = loc-foo/{relpath}
4208
[/home/user/project]
4209
lfoo = loc-foo/{relpath}
4212
stack = config.LocationStack('/home/user/project/branch')
4213
self.assertEquals('loc-foo/branch', stack.get('lfoo', expand=True))
4214
stack = config.LocationStack('/home/user/bar/baz')
4215
self.assertEquals('loc-foo/bar/baz', stack.get('lfoo', expand=True))
3610
4219
class TestStackSet(TestStackWithTransport):
3612
4221
def test_simple_set(self):
3613
4222
conf = self.get_stack(self)
3614
conf.store._load_from_string('foo=bar')
3615
self.assertEquals('bar', conf.get('foo'))
4223
self.assertEquals(None, conf.get('foo'))
3616
4224
conf.set('foo', 'baz')
3617
4225
# Did we get it back ?
3618
4226
self.assertEquals('baz', conf.get('foo'))
4340
4966
self.assertEquals((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.assertEquals('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.assertEquals('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.assertEquals('domainname.com', r)
5000
class EmailOptionTests(tests.TestCase):
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')
5006
self.overrideEnv('EMAIL', 'jelmer@apache.org')
5007
self.assertEquals('jelmer@samba.org', conf.get('email'))
5009
def test_default_email_uses_EMAIL(self):
5010
conf = config.MemoryStack('')
5011
self.overrideEnv('BZR_EMAIL', None)
5012
self.overrideEnv('EMAIL', 'jelmer@apache.org')
5013
self.assertEquals('jelmer@apache.org', conf.get('email'))
5015
def test_BZR_EMAIL_overrides(self):
5016
conf = config.MemoryStack('email=jelmer@debian.org')
5017
self.overrideEnv('BZR_EMAIL', 'jelmer@apache.org')
5018
self.assertEquals('jelmer@apache.org', conf.get('email'))
5019
self.overrideEnv('BZR_EMAIL', None)
5020
self.overrideEnv('EMAIL', 'jelmer@samba.org')
5021
self.assertEquals('jelmer@debian.org', conf.get('email'))
5024
class MailClientOptionTests(tests.TestCase):
5026
def test_default(self):
5027
conf = config.MemoryStack('')
5028
client = conf.get('mail_client')
5029
self.assertIs(client, mail_client.DefaultMail)
5031
def test_evolution(self):
5032
conf = config.MemoryStack('mail_client=evolution')
5033
client = conf.get('mail_client')
5034
self.assertIs(client, mail_client.Evolution)
5036
def test_kmail(self):
5037
conf = config.MemoryStack('mail_client=kmail')
5038
client = conf.get('mail_client')
5039
self.assertIs(client, mail_client.KMail)
5041
def test_mutt(self):
5042
conf = config.MemoryStack('mail_client=mutt')
5043
client = conf.get('mail_client')
5044
self.assertIs(client, mail_client.Mutt)
5046
def test_thunderbird(self):
5047
conf = config.MemoryStack('mail_client=thunderbird')
5048
client = conf.get('mail_client')
5049
self.assertIs(client, mail_client.Thunderbird)
5051
def test_explicit_default(self):
5052
conf = config.MemoryStack('mail_client=default')
5053
client = conf.get('mail_client')
5054
self.assertIs(client, mail_client.DefaultMail)
5056
def test_editor(self):
5057
conf = config.MemoryStack('mail_client=editor')
5058
client = conf.get('mail_client')
5059
self.assertIs(client, mail_client.Editor)
5061
def test_mapi(self):
5062
conf = config.MemoryStack('mail_client=mapi')
5063
client = conf.get('mail_client')
5064
self.assertIs(client, mail_client.MAPIClient)
5066
def test_xdg_email(self):
5067
conf = config.MemoryStack('mail_client=xdg-email')
5068
client = conf.get('mail_client')
5069
self.assertIs(client, mail_client.XDGEmail)
5071
def test_unknown(self):
5072
conf = config.MemoryStack('mail_client=firebird')
5073
self.assertRaises(errors.ConfigOptionValueError, conf.get,