1493
1512
self.get_branch_config('http://www.example.com',
1494
1513
global_config=sample_ignore_signatures)
1495
1514
self.assertEqual(config.CHECK_ALWAYS,
1496
self.my_config.signature_checking())
1515
self.applyDeprecated(deprecated_in((2, 5, 0)),
1516
self.my_config.signature_checking))
1497
1517
self.assertEqual(config.SIGN_NEVER,
1498
self.my_config.signing_policy())
1518
self.applyDeprecated(deprecated_in((2, 5, 0)),
1519
self.my_config.signing_policy))
1500
1521
def test_signatures_never(self):
1501
1522
self.get_branch_config('/a/c')
1502
1523
self.assertEqual(config.CHECK_NEVER,
1503
self.my_config.signature_checking())
1524
self.applyDeprecated(deprecated_in((2, 5, 0)),
1525
self.my_config.signature_checking))
1505
1527
def test_signatures_when_available(self):
1506
1528
self.get_branch_config('/a/', global_config=sample_ignore_signatures)
1507
1529
self.assertEqual(config.CHECK_IF_POSSIBLE,
1508
self.my_config.signature_checking())
1530
self.applyDeprecated(deprecated_in((2, 5, 0)),
1531
self.my_config.signature_checking))
1510
1533
def test_signatures_always(self):
1511
1534
self.get_branch_config('/b')
1512
1535
self.assertEqual(config.CHECK_ALWAYS,
1513
self.my_config.signature_checking())
1536
self.applyDeprecated(deprecated_in((2, 5, 0)),
1537
self.my_config.signature_checking))
1515
1539
def test_gpg_signing_command(self):
1516
1540
self.get_branch_config('/b')
1517
self.assertEqual("gnome-gpg", self.my_config.gpg_signing_command())
1541
self.assertEqual("gnome-gpg",
1542
self.applyDeprecated(deprecated_in((2, 5, 0)),
1543
self.my_config.gpg_signing_command))
1519
1545
def test_gpg_signing_command_missing(self):
1520
1546
self.get_branch_config('/a')
1521
self.assertEqual("false", self.my_config.gpg_signing_command())
1547
self.assertEqual("false",
1548
self.applyDeprecated(deprecated_in((2, 5, 0)),
1549
self.my_config.gpg_signing_command))
1551
def test_gpg_signing_key(self):
1552
self.get_branch_config('/b')
1553
self.assertEqual("DD4D5088", self.applyDeprecated(deprecated_in((2, 5, 0)),
1554
self.my_config.gpg_signing_key))
1556
def test_gpg_signing_key_default(self):
1557
self.get_branch_config('/a')
1558
self.assertEqual("erik@bagfors.nu",
1559
self.applyDeprecated(deprecated_in((2, 5, 0)),
1560
self.my_config.gpg_signing_key))
1523
1562
def test_get_user_option_global(self):
1524
1563
self.get_branch_config('/a')
2199
2226
opt = config.Option('foo', default='bar')
2200
2227
self.assertEquals('bar', opt.get_default())
2229
def test_callable_default_value(self):
2230
def bar_as_unicode():
2232
opt = config.Option('foo', default=bar_as_unicode)
2233
self.assertEquals('bar', opt.get_default())
2235
def test_default_value_from_env(self):
2236
opt = config.Option('foo', default='bar', default_from_env=['FOO'])
2237
self.overrideEnv('FOO', 'quux')
2238
# Env variable provides a default taking over the option one
2239
self.assertEquals('quux', opt.get_default())
2241
def test_first_default_value_from_env_wins(self):
2242
opt = config.Option('foo', default='bar',
2243
default_from_env=['NO_VALUE', 'FOO', 'BAZ'])
2244
self.overrideEnv('FOO', 'foo')
2245
self.overrideEnv('BAZ', 'baz')
2246
# The first env var set wins
2247
self.assertEquals('foo', opt.get_default())
2249
def test_not_supported_list_default_value(self):
2250
self.assertRaises(AssertionError, config.Option, 'foo', default=[1])
2252
def test_not_supported_object_default_value(self):
2253
self.assertRaises(AssertionError, config.Option, 'foo',
2256
def test_not_supported_callable_default_value_not_unicode(self):
2257
def bar_not_unicode():
2259
opt = config.Option('foo', default=bar_not_unicode)
2260
self.assertRaises(AssertionError, opt.get_default)
2262
def test_get_help_topic(self):
2263
opt = config.Option('foo')
2264
self.assertEquals('foo', opt.get_help_topic())
2267
class TestOptionConverterMixin(object):
2269
def assertConverted(self, expected, opt, value):
2270
self.assertEquals(expected, opt.convert_from_unicode(None, value))
2272
def assertWarns(self, opt, value):
2275
warnings.append(args[0] % args[1:])
2276
self.overrideAttr(trace, 'warning', warning)
2277
self.assertEquals(None, opt.convert_from_unicode(None, value))
2278
self.assertLength(1, warnings)
2280
'Value "%s" is not valid for "%s"' % (value, opt.name),
2283
def assertErrors(self, opt, value):
2284
self.assertRaises(errors.ConfigOptionValueError,
2285
opt.convert_from_unicode, None, value)
2287
def assertConvertInvalid(self, opt, invalid_value):
2289
self.assertEquals(None, opt.convert_from_unicode(None, invalid_value))
2290
opt.invalid = 'warning'
2291
self.assertWarns(opt, invalid_value)
2292
opt.invalid = 'error'
2293
self.assertErrors(opt, invalid_value)
2296
class TestOptionWithBooleanConverter(tests.TestCase, TestOptionConverterMixin):
2298
def get_option(self):
2299
return config.Option('foo', help='A boolean.',
2300
from_unicode=config.bool_from_store)
2302
def test_convert_invalid(self):
2303
opt = self.get_option()
2304
# A string that is not recognized as a boolean
2305
self.assertConvertInvalid(opt, u'invalid-boolean')
2306
# A list of strings is never recognized as a boolean
2307
self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
2309
def test_convert_valid(self):
2310
opt = self.get_option()
2311
self.assertConverted(True, opt, u'True')
2312
self.assertConverted(True, opt, u'1')
2313
self.assertConverted(False, opt, u'False')
2316
class TestOptionWithIntegerConverter(tests.TestCase, TestOptionConverterMixin):
2318
def get_option(self):
2319
return config.Option('foo', help='An integer.',
2320
from_unicode=config.int_from_store)
2322
def test_convert_invalid(self):
2323
opt = self.get_option()
2324
# A string that is not recognized as an integer
2325
self.assertConvertInvalid(opt, u'forty-two')
2326
# A list of strings is never recognized as an integer
2327
self.assertConvertInvalid(opt, [u'a', u'list'])
2329
def test_convert_valid(self):
2330
opt = self.get_option()
2331
self.assertConverted(16, opt, u'16')
2334
class TestOptionWithSIUnitConverter(tests.TestCase, TestOptionConverterMixin):
2336
def get_option(self):
2337
return config.Option('foo', help='An integer in SI units.',
2338
from_unicode=config.int_SI_from_store)
2340
def test_convert_invalid(self):
2341
opt = self.get_option()
2342
self.assertConvertInvalid(opt, u'not-a-unit')
2343
self.assertConvertInvalid(opt, u'Gb') # Forgot the int
2344
self.assertConvertInvalid(opt, u'1b') # Forgot the unit
2345
self.assertConvertInvalid(opt, u'1GG')
2346
self.assertConvertInvalid(opt, u'1Mbb')
2347
self.assertConvertInvalid(opt, u'1MM')
2349
def test_convert_valid(self):
2350
opt = self.get_option()
2351
self.assertConverted(int(5e3), opt, u'5kb')
2352
self.assertConverted(int(5e6), opt, u'5M')
2353
self.assertConverted(int(5e6), opt, u'5MB')
2354
self.assertConverted(int(5e9), opt, u'5g')
2355
self.assertConverted(int(5e9), opt, u'5gB')
2356
self.assertConverted(100, opt, u'100')
2359
class TestListOption(tests.TestCase, TestOptionConverterMixin):
2361
def get_option(self):
2362
return config.ListOption('foo', help='A list.')
2364
def test_convert_invalid(self):
2365
opt = self.get_option()
2366
# We don't even try to convert a list into a list, we only expect
2368
self.assertConvertInvalid(opt, [1])
2369
# No string is invalid as all forms can be converted to a list
2371
def test_convert_valid(self):
2372
opt = self.get_option()
2373
# An empty string is an empty list
2374
self.assertConverted([], opt, '') # Using a bare str() just in case
2375
self.assertConverted([], opt, u'')
2377
self.assertConverted([u'True'], opt, u'True')
2379
self.assertConverted([u'42'], opt, u'42')
2381
self.assertConverted([u'bar'], opt, u'bar')
2384
class TestRegistryOption(tests.TestCase, TestOptionConverterMixin):
2386
def get_option(self, registry):
2387
return config.RegistryOption('foo', registry,
2388
help='A registry option.')
2390
def test_convert_invalid(self):
2391
registry = _mod_registry.Registry()
2392
opt = self.get_option(registry)
2393
self.assertConvertInvalid(opt, [1])
2394
self.assertConvertInvalid(opt, u"notregistered")
2396
def test_convert_valid(self):
2397
registry = _mod_registry.Registry()
2398
registry.register("someval", 1234)
2399
opt = self.get_option(registry)
2400
# Using a bare str() just in case
2401
self.assertConverted(1234, opt, "someval")
2402
self.assertConverted(1234, opt, u'someval')
2403
self.assertConverted(None, opt, None)
2405
def test_help(self):
2406
registry = _mod_registry.Registry()
2407
registry.register("someval", 1234, help="some option")
2408
registry.register("dunno", 1234, help="some other option")
2409
opt = self.get_option(registry)
2411
'A registry option.\n'
2413
'The following values are supported:\n'
2414
' dunno - some other option\n'
2415
' someval - some option\n',
2418
def test_get_help_text(self):
2419
registry = _mod_registry.Registry()
2420
registry.register("someval", 1234, help="some option")
2421
registry.register("dunno", 1234, help="some other option")
2422
opt = self.get_option(registry)
2424
'A registry option.\n'
2426
'The following values are supported:\n'
2427
' dunno - some other option\n'
2428
' someval - some option\n',
2429
opt.get_help_text())
2203
2432
class TestOptionRegistry(tests.TestCase):
2205
2434
def setUp(self):
2206
2435
super(TestOptionRegistry, self).setUp()
2207
2436
# Always start with an empty registry
2208
self.overrideAttr(config, 'option_registry', registry.Registry())
2437
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
2209
2438
self.registry = config.option_registry
2211
2440
def test_register(self):
2212
2441
opt = config.Option('foo')
2213
self.registry.register('foo', opt)
2442
self.registry.register(opt)
2214
2443
self.assertIs(opt, self.registry.get('foo'))
2216
lazy_option = config.Option('lazy_foo')
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'))
2223
2445
def test_registered_help(self):
2224
opt = config.Option('foo')
2225
self.registry.register('foo', opt, help='A simple option')
2446
opt = config.Option('foo', help='A simple option')
2447
self.registry.register(opt)
2226
2448
self.assertEquals('A simple option', self.registry.get_help('foo'))
2450
lazy_option = config.Option('lazy_foo', help='Lazy help')
2452
def test_register_lazy(self):
2453
self.registry.register_lazy('lazy_foo', self.__module__,
2454
'TestOptionRegistry.lazy_option')
2455
self.assertIs(self.lazy_option, self.registry.get('lazy_foo'))
2457
def test_registered_lazy_help(self):
2458
self.registry.register_lazy('lazy_foo', self.__module__,
2459
'TestOptionRegistry.lazy_option')
2460
self.assertEquals('Lazy help', self.registry.get_help('lazy_foo'))
2229
2463
class TestRegisteredOptions(tests.TestCase):
2230
2464
"""All registered options should verify some constraints."""
2321
2557
self.assertEquals(config._NewlyCreatedOption, section.orig['foo'])
2560
class TestCommandLineStore(tests.TestCase):
2563
super(TestCommandLineStore, self).setUp()
2564
self.store = config.CommandLineStore()
2565
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
2567
def get_section(self):
2568
"""Get the unique section for the command line overrides."""
2569
sections = list(self.store.get_sections())
2570
self.assertLength(1, sections)
2571
store, section = sections[0]
2572
self.assertEquals(self.store, store)
2575
def test_no_override(self):
2576
self.store._from_cmdline([])
2577
section = self.get_section()
2578
self.assertLength(0, list(section.iter_option_names()))
2580
def test_simple_override(self):
2581
self.store._from_cmdline(['a=b'])
2582
section = self.get_section()
2583
self.assertEqual('b', section.get('a'))
2585
def test_list_override(self):
2586
opt = config.ListOption('l')
2587
config.option_registry.register(opt)
2588
self.store._from_cmdline(['l=1,2,3'])
2589
val = self.get_section().get('l')
2590
self.assertEqual('1,2,3', val)
2591
# Reminder: lists should be registered as such explicitely, otherwise
2592
# the conversion needs to be done afterwards.
2593
self.assertEqual(['1', '2', '3'],
2594
opt.convert_from_unicode(self.store, val))
2596
def test_multiple_overrides(self):
2597
self.store._from_cmdline(['a=b', 'x=y'])
2598
section = self.get_section()
2599
self.assertEquals('b', section.get('a'))
2600
self.assertEquals('y', section.get('x'))
2602
def test_wrong_syntax(self):
2603
self.assertRaises(errors.BzrCommandError,
2604
self.store._from_cmdline, ['a=b', 'c'])
2606
class TestStoreMinimalAPI(tests.TestCaseWithTransport):
2608
scenarios = [(key, {'get_store': builder}) for key, builder
2609
in config.test_store_builder_registry.iteritems()] + [
2610
('cmdline', {'get_store': lambda test: config.CommandLineStore()})]
2613
store = self.get_store(self)
2614
if type(store) == config.TransportIniFileStore:
2615
raise tests.TestNotApplicable(
2616
"%s is not a concrete Store implementation"
2617
" so it doesn't need an id" % (store.__class__.__name__,))
2618
self.assertIsNot(None, store.id)
2324
2621
class TestStore(tests.TestCaseWithTransport):
2326
def assertSectionContent(self, expected, section):
2623
def assertSectionContent(self, expected, (store, section)):
2327
2624
"""Assert that some options have the proper values in a section."""
2328
2625
expected_name, expected_options = expected
2329
2626
self.assertEquals(expected_name, section.id)
2371
2665
self.assertRaises(AssertionError, store._load_from_string, 'bar=baz')
2668
class TestStoreQuoting(TestStore):
2670
scenarios = [(key, {'get_store': builder}) for key, builder
2671
in config.test_store_builder_registry.iteritems()]
2674
super(TestStoreQuoting, self).setUp()
2675
self.store = self.get_store(self)
2676
# We need a loaded store but any content will do
2677
self.store._load_from_string('')
2679
def assertIdempotent(self, s):
2680
"""Assert that quoting an unquoted string is a no-op and vice-versa.
2682
What matters here is that option values, as they appear in a store, can
2683
be safely round-tripped out of the store and back.
2685
:param s: A string, quoted if required.
2687
self.assertEquals(s, self.store.quote(self.store.unquote(s)))
2688
self.assertEquals(s, self.store.unquote(self.store.quote(s)))
2690
def test_empty_string(self):
2691
if isinstance(self.store, config.IniFileStore):
2692
# configobj._quote doesn't handle empty values
2693
self.assertRaises(AssertionError,
2694
self.assertIdempotent, '')
2696
self.assertIdempotent('')
2697
# But quoted empty strings are ok
2698
self.assertIdempotent('""')
2700
def test_embedded_spaces(self):
2701
self.assertIdempotent('" a b c "')
2703
def test_embedded_commas(self):
2704
self.assertIdempotent('" a , b c "')
2706
def test_simple_comma(self):
2707
if isinstance(self.store, config.IniFileStore):
2708
# configobj requires that lists are special-cased
2709
self.assertRaises(AssertionError,
2710
self.assertIdempotent, ',')
2712
self.assertIdempotent(',')
2713
# When a single comma is required, quoting is also required
2714
self.assertIdempotent('","')
2716
def test_list(self):
2717
if isinstance(self.store, config.IniFileStore):
2718
# configobj requires that lists are special-cased
2719
self.assertRaises(AssertionError,
2720
self.assertIdempotent, 'a,b')
2722
self.assertIdempotent('a,b')
2725
class TestDictFromStore(tests.TestCase):
2727
def test_unquote_not_string(self):
2728
conf = config.MemoryStack('x=2\n[a_section]\na=1\n')
2729
value = conf.get('a_section')
2730
# Urgh, despite 'conf' asking for the no-name section, we get the
2731
# content of another section as a dict o_O
2732
self.assertEquals({'a': '1'}, value)
2733
unquoted = conf.store.unquote(value)
2734
# Which cannot be unquoted but shouldn't crash either (the use cases
2735
# are getting the value or displaying it. In the later case, '%s' will
2737
self.assertEquals({'a': '1'}, unquoted)
2738
self.assertEquals("{u'a': u'1'}", '%s' % (unquoted,))
2374
2741
class TestIniFileStoreContent(tests.TestCaseWithTransport):
2375
"""Simulate loading a config store without content of various encodings.
2742
"""Simulate loading a config store with content of various encodings.
2377
2744
All files produced by bzr are in utf8 content.
2556
2981
config.ConfigHooks.install_named_hook('save', hook, None)
2557
2982
self.assertLength(0, calls)
2558
2983
store = self.get_store(self)
2984
# FIXME: There should be a better way than relying on the test
2985
# parametrization to identify branch.conf -- vila 2011-0526
2986
if self.store_id in ('branch', 'remote_branch'):
2987
# branch stores requires write locked branches
2988
self.addCleanup(store.branch.lock_write().unlock)
2559
2989
section = store.get_mutable_section('baz')
2560
2990
section.set('foo', 'bar')
2562
2992
self.assertLength(1, calls)
2563
2993
self.assertEquals((store,), calls[0])
2566
class TestIniFileStore(TestStore):
2995
def test_set_mark_dirty(self):
2996
stack = config.MemoryStack('')
2997
self.assertLength(0, stack.store.dirty_sections)
2998
stack.set('foo', 'baz')
2999
self.assertLength(1, stack.store.dirty_sections)
3000
self.assertTrue(stack.store._need_saving())
3002
def test_remove_mark_dirty(self):
3003
stack = config.MemoryStack('foo=bar')
3004
self.assertLength(0, stack.store.dirty_sections)
3006
self.assertLength(1, stack.store.dirty_sections)
3007
self.assertTrue(stack.store._need_saving())
3010
class TestStoreSaveChanges(tests.TestCaseWithTransport):
3011
"""Tests that config changes are kept in memory and saved on-demand."""
3014
super(TestStoreSaveChanges, self).setUp()
3015
self.transport = self.get_transport()
3016
# Most of the tests involve two stores pointing to the same persistent
3017
# storage to observe the effects of concurrent changes
3018
self.st1 = config.TransportIniFileStore(self.transport, 'foo.conf')
3019
self.st2 = config.TransportIniFileStore(self.transport, 'foo.conf')
3022
self.warnings.append(args[0] % args[1:])
3023
self.overrideAttr(trace, 'warning', warning)
3025
def has_store(self, store):
3026
store_basename = urlutils.relative_url(self.transport.external_url(),
3027
store.external_url())
3028
return self.transport.has(store_basename)
3030
def get_stack(self, store):
3031
# Any stack will do as long as it uses the right store, just a single
3032
# no-name section is enough
3033
return config.Stack([store.get_sections], store)
3035
def test_no_changes_no_save(self):
3036
s = self.get_stack(self.st1)
3037
s.store.save_changes()
3038
self.assertEquals(False, self.has_store(self.st1))
3040
def test_unrelated_concurrent_update(self):
3041
s1 = self.get_stack(self.st1)
3042
s2 = self.get_stack(self.st2)
3043
s1.set('foo', 'bar')
3044
s2.set('baz', 'quux')
3046
# Changes don't propagate magically
3047
self.assertEquals(None, s1.get('baz'))
3048
s2.store.save_changes()
3049
self.assertEquals('quux', s2.get('baz'))
3050
# Changes are acquired when saving
3051
self.assertEquals('bar', s2.get('foo'))
3052
# Since there is no overlap, no warnings are emitted
3053
self.assertLength(0, self.warnings)
3055
def test_concurrent_update_modified(self):
3056
s1 = self.get_stack(self.st1)
3057
s2 = self.get_stack(self.st2)
3058
s1.set('foo', 'bar')
3059
s2.set('foo', 'baz')
3062
s2.store.save_changes()
3063
self.assertEquals('baz', s2.get('foo'))
3064
# But the user get a warning
3065
self.assertLength(1, self.warnings)
3066
warning = self.warnings[0]
3067
self.assertStartsWith(warning, 'Option foo in section None')
3068
self.assertEndsWith(warning, 'was changed from <CREATED> to bar.'
3069
' The baz value will be saved.')
3071
def test_concurrent_deletion(self):
3072
self.st1._load_from_string('foo=bar')
3074
s1 = self.get_stack(self.st1)
3075
s2 = self.get_stack(self.st2)
3078
s1.store.save_changes()
3080
self.assertLength(0, self.warnings)
3081
s2.store.save_changes()
3083
self.assertLength(1, self.warnings)
3084
warning = self.warnings[0]
3085
self.assertStartsWith(warning, 'Option foo in section None')
3086
self.assertEndsWith(warning, 'was changed from bar to <CREATED>.'
3087
' The <DELETED> value will be saved.')
3090
class TestQuotingIniFileStore(tests.TestCaseWithTransport):
3092
def get_store(self):
3093
return config.TransportIniFileStore(self.get_transport(), 'foo.conf')
3095
def test_get_quoted_string(self):
3096
store = self.get_store()
3097
store._load_from_string('foo= " abc "')
3098
stack = config.Stack([store.get_sections])
3099
self.assertEquals(' abc ', stack.get('foo'))
3101
def test_set_quoted_string(self):
3102
store = self.get_store()
3103
stack = config.Stack([store.get_sections], store)
3104
stack.set('foo', ' a b c ')
3106
self.assertFileEqual('foo = " a b c "' + os.linesep, 'foo.conf')
3109
class TestTransportIniFileStore(TestStore):
2568
3111
def test_loading_unknown_file_fails(self):
2569
store = config.IniFileStore(self.get_transport(), 'I-do-not-exist')
3112
store = config.TransportIniFileStore(self.get_transport(),
2570
3114
self.assertRaises(errors.NoSuchFile, store.load)
2572
3116
def test_invalid_content(self):
2573
store = config.IniFileStore(self.get_transport(), 'foo.conf', )
3117
store = config.TransportIniFileStore(self.get_transport(), 'foo.conf')
2574
3118
self.assertEquals(False, store.is_loaded())
2575
3119
exc = self.assertRaises(
2576
3120
errors.ParseConfigError, store._load_from_string,
2846
3418
matcher = config.LocationMatcher(store, expected_url)
2847
3419
self.assertEquals(expected_location, matcher.location)
2850
class TestStackGet(tests.TestCase):
2852
# FIXME: This should be parametrized for all known Stack or dedicated
2853
# paramerized tests created to avoid bloating -- vila 2011-03-31
2855
def test_single_config_get(self):
2856
conf = dict(foo='bar')
2857
conf_stack = config.Stack([conf])
2858
self.assertEquals('bar', conf_stack.get('foo'))
3421
def test_branch_name_colo(self):
3422
store = self.get_store(self)
3423
store._load_from_string(dedent("""\
3425
push_location=my{branchname}
3427
matcher = config.LocationMatcher(store, 'file:///,branch=example%3c')
3428
self.assertEqual('example<', matcher.branch_name)
3429
((_, section),) = matcher.get_sections()
3430
self.assertEqual('example<', section.locals['branchname'])
3432
def test_branch_name_basename(self):
3433
store = self.get_store(self)
3434
store._load_from_string(dedent("""\
3436
push_location=my{branchname}
3438
matcher = config.LocationMatcher(store, 'file:///parent/example%3c')
3439
self.assertEqual('example<', matcher.branch_name)
3440
((_, section),) = matcher.get_sections()
3441
self.assertEqual('example<', section.locals['branchname'])
3444
class TestStartingPathMatcher(TestStore):
3447
super(TestStartingPathMatcher, self).setUp()
3448
# Any simple store is good enough
3449
self.store = config.IniFileStore()
3451
def assertSectionIDs(self, expected, location, content):
3452
self.store._load_from_string(content)
3453
matcher = config.StartingPathMatcher(self.store, location)
3454
sections = list(matcher.get_sections())
3455
self.assertLength(len(expected), sections)
3456
self.assertEqual(expected, [section.id for _, section in sections])
3459
def test_empty(self):
3460
self.assertSectionIDs([], self.get_url(), '')
3462
def test_url_vs_local_paths(self):
3463
# The matcher location is an url and the section names are local paths
3464
sections = self.assertSectionIDs(['/foo/bar', '/foo'],
3465
'file:///foo/bar/baz', '''\
3470
def test_local_path_vs_url(self):
3471
# The matcher location is a local path and the section names are urls
3472
sections = self.assertSectionIDs(['file:///foo/bar', 'file:///foo'],
3473
'/foo/bar/baz', '''\
3479
def test_no_name_section_included_when_present(self):
3480
# Note that other tests will cover the case where the no-name section
3481
# is empty and as such, not included.
3482
sections = self.assertSectionIDs(['/foo/bar', '/foo', None],
3483
'/foo/bar/baz', '''\
3484
option = defined so the no-name section exists
3488
self.assertEquals(['baz', 'bar/baz', '/foo/bar/baz'],
3489
[s.locals['relpath'] for _, s in sections])
3491
def test_order_reversed(self):
3492
self.assertSectionIDs(['/foo/bar', '/foo'], '/foo/bar/baz', '''\
3497
def test_unrelated_section_excluded(self):
3498
self.assertSectionIDs(['/foo/bar', '/foo'], '/foo/bar/baz', '''\
3504
def test_glob_included(self):
3505
sections = self.assertSectionIDs(['/foo/*/baz', '/foo/b*', '/foo'],
3506
'/foo/bar/baz', '''\
3512
# Note that 'baz' as a relpath for /foo/b* is not fully correct, but
3513
# nothing really is... as far using {relpath} to append it to something
3514
# else, this seems good enough though.
3515
self.assertEquals(['', 'baz', 'bar/baz'],
3516
[s.locals['relpath'] for _, s in sections])
3518
def test_respect_order(self):
3519
self.assertSectionIDs(['/foo', '/foo/b*', '/foo/*/baz'],
3520
'/foo/bar/baz', '''\
3528
class TestNameMatcher(TestStore):
3531
super(TestNameMatcher, self).setUp()
3532
self.matcher = config.NameMatcher
3533
# Any simple store is good enough
3534
self.get_store = config.test_store_builder_registry.get('configobj')
3536
def get_matching_sections(self, name):
3537
store = self.get_store(self)
3538
store._load_from_string('''
3546
matcher = self.matcher(store, name)
3547
return list(matcher.get_sections())
3549
def test_matching(self):
3550
sections = self.get_matching_sections('foo')
3551
self.assertLength(1, sections)
3552
self.assertSectionContent(('foo', {'option': 'foo'}), sections[0])
3554
def test_not_matching(self):
3555
sections = self.get_matching_sections('baz')
3556
self.assertLength(0, sections)
3559
class TestBaseStackGet(tests.TestCase):
3562
super(TestBaseStackGet, self).setUp()
3563
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3565
def test_get_first_definition(self):
3566
store1 = config.IniFileStore()
3567
store1._load_from_string('foo=bar')
3568
store2 = config.IniFileStore()
3569
store2._load_from_string('foo=baz')
3570
conf = config.Stack([store1.get_sections, store2.get_sections])
3571
self.assertEquals('bar', conf.get('foo'))
2860
3573
def test_get_with_registered_default_value(self):
2861
conf_stack = config.Stack([dict()])
2862
opt = config.Option('foo', default='bar')
2863
self.overrideAttr(config, 'option_registry', registry.Registry())
2864
config.option_registry.register('foo', opt)
3574
config.option_registry.register(config.Option('foo', default='bar'))
3575
conf_stack = config.Stack([])
2865
3576
self.assertEquals('bar', conf_stack.get('foo'))
2867
3578
def test_get_without_registered_default_value(self):
2868
conf_stack = config.Stack([dict()])
2869
opt = config.Option('foo')
2870
self.overrideAttr(config, 'option_registry', registry.Registry())
2871
config.option_registry.register('foo', opt)
3579
config.option_registry.register(config.Option('foo'))
3580
conf_stack = config.Stack([])
2872
3581
self.assertEquals(None, conf_stack.get('foo'))
2874
3583
def test_get_without_default_value_for_not_registered(self):
2875
conf_stack = config.Stack([dict()])
2876
opt = config.Option('foo')
2877
self.overrideAttr(config, 'option_registry', registry.Registry())
3584
conf_stack = config.Stack([])
2878
3585
self.assertEquals(None, conf_stack.get('foo'))
2880
def test_get_first_definition(self):
2881
conf1 = dict(foo='bar')
2882
conf2 = dict(foo='baz')
2883
conf_stack = config.Stack([conf1, conf2])
2884
self.assertEquals('bar', conf_stack.get('foo'))
2886
def test_get_embedded_definition(self):
2887
conf1 = dict(yy='12')
2888
conf2 = config.Stack([dict(xx='42'), dict(foo='baz')])
2889
conf_stack = config.Stack([conf1, conf2])
2890
self.assertEquals('baz', conf_stack.get('foo'))
2892
3587
def test_get_for_empty_section_callable(self):
2893
3588
conf_stack = config.Stack([lambda : []])
2894
3589
self.assertEquals(None, conf_stack.get('foo'))
2896
3591
def test_get_for_broken_callable(self):
2897
3592
# Trying to use and invalid callable raises an exception on first use
2898
conf_stack = config.Stack([lambda : object()])
3593
conf_stack = config.Stack([object])
2899
3594
self.assertRaises(TypeError, conf_stack.get, 'foo')
3597
class TestStackWithSimpleStore(tests.TestCase):
3600
super(TestStackWithSimpleStore, self).setUp()
3601
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3602
self.registry = config.option_registry
3604
def get_conf(self, content=None):
3605
return config.MemoryStack(content)
3607
def test_override_value_from_env(self):
3608
self.overrideEnv('FOO', None)
3609
self.registry.register(
3610
config.Option('foo', default='bar', override_from_env=['FOO']))
3611
self.overrideEnv('FOO', 'quux')
3612
# Env variable provides a default taking over the option one
3613
conf = self.get_conf('foo=store')
3614
self.assertEquals('quux', conf.get('foo'))
3616
def test_first_override_value_from_env_wins(self):
3617
self.overrideEnv('NO_VALUE', None)
3618
self.overrideEnv('FOO', None)
3619
self.overrideEnv('BAZ', None)
3620
self.registry.register(
3621
config.Option('foo', default='bar',
3622
override_from_env=['NO_VALUE', 'FOO', 'BAZ']))
3623
self.overrideEnv('FOO', 'foo')
3624
self.overrideEnv('BAZ', 'baz')
3625
# The first env var set wins
3626
conf = self.get_conf('foo=store')
3627
self.assertEquals('foo', conf.get('foo'))
3630
class TestMemoryStack(tests.TestCase):
3633
conf = config.MemoryStack('foo=bar')
3634
self.assertEquals('bar', conf.get('foo'))
3637
conf = config.MemoryStack('foo=bar')
3638
conf.set('foo', 'baz')
3639
self.assertEquals('baz', conf.get('foo'))
3641
def test_no_content(self):
3642
conf = config.MemoryStack()
3643
# No content means no loading
3644
self.assertFalse(conf.store.is_loaded())
3645
self.assertRaises(NotImplementedError, conf.get, 'foo')
3646
# But a content can still be provided
3647
conf.store._load_from_string('foo=bar')
3648
self.assertEquals('bar', conf.get('foo'))
3651
class TestStackIterSections(tests.TestCase):
3653
def test_empty_stack(self):
3654
conf = config.Stack([])
3655
sections = list(conf.iter_sections())
3656
self.assertLength(0, sections)
3658
def test_empty_store(self):
3659
store = config.IniFileStore()
3660
store._load_from_string('')
3661
conf = config.Stack([store.get_sections])
3662
sections = list(conf.iter_sections())
3663
self.assertLength(0, sections)
3665
def test_simple_store(self):
3666
store = config.IniFileStore()
3667
store._load_from_string('foo=bar')
3668
conf = config.Stack([store.get_sections])
3669
tuples = list(conf.iter_sections())
3670
self.assertLength(1, tuples)
3671
(found_store, found_section) = tuples[0]
3672
self.assertIs(store, found_store)
3674
def test_two_stores(self):
3675
store1 = config.IniFileStore()
3676
store1._load_from_string('foo=bar')
3677
store2 = config.IniFileStore()
3678
store2._load_from_string('bar=qux')
3679
conf = config.Stack([store1.get_sections, store2.get_sections])
3680
tuples = list(conf.iter_sections())
3681
self.assertLength(2, tuples)
3682
self.assertIs(store1, tuples[0][0])
3683
self.assertIs(store2, tuples[1][0])
2902
3686
class TestStackWithTransport(tests.TestCaseWithTransport):
2904
3688
scenarios = [(key, {'get_stack': builder}) for key, builder
2915
3699
class TestStackGet(TestStackWithTransport):
3702
super(TestStackGet, self).setUp()
3703
self.conf = self.get_stack(self)
2917
3705
def test_get_for_empty_stack(self):
2918
conf = self.get_stack(self)
2919
self.assertEquals(None, conf.get('foo'))
3706
self.assertEquals(None, self.conf.get('foo'))
2921
3708
def test_get_hook(self):
2922
conf = self.get_stack(self)
2923
conf.store._load_from_string('foo=bar')
3709
self.conf.set('foo', 'bar')
2925
3711
def hook(*args):
2926
3712
calls.append(args)
2927
3713
config.ConfigHooks.install_named_hook('get', hook, None)
2928
3714
self.assertLength(0, calls)
2929
value = conf.get('foo')
3715
value = self.conf.get('foo')
2930
3716
self.assertEquals('bar', value)
2931
3717
self.assertLength(1, calls)
2932
self.assertEquals((conf, 'foo', 'bar'), calls[0])
3718
self.assertEquals((self.conf, 'foo', 'bar'), calls[0])
3721
class TestStackGetWithConverter(tests.TestCase):
3724
super(TestStackGetWithConverter, self).setUp()
3725
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3726
self.registry = config.option_registry
3728
def get_conf(self, content=None):
3729
return config.MemoryStack(content)
3731
def register_bool_option(self, name, default=None, default_from_env=None):
3732
b = config.Option(name, help='A boolean.',
3733
default=default, default_from_env=default_from_env,
3734
from_unicode=config.bool_from_store)
3735
self.registry.register(b)
3737
def test_get_default_bool_None(self):
3738
self.register_bool_option('foo')
3739
conf = self.get_conf('')
3740
self.assertEquals(None, conf.get('foo'))
3742
def test_get_default_bool_True(self):
3743
self.register_bool_option('foo', u'True')
3744
conf = self.get_conf('')
3745
self.assertEquals(True, conf.get('foo'))
3747
def test_get_default_bool_False(self):
3748
self.register_bool_option('foo', False)
3749
conf = self.get_conf('')
3750
self.assertEquals(False, conf.get('foo'))
3752
def test_get_default_bool_False_as_string(self):
3753
self.register_bool_option('foo', u'False')
3754
conf = self.get_conf('')
3755
self.assertEquals(False, conf.get('foo'))
3757
def test_get_default_bool_from_env_converted(self):
3758
self.register_bool_option('foo', u'True', default_from_env=['FOO'])
3759
self.overrideEnv('FOO', 'False')
3760
conf = self.get_conf('')
3761
self.assertEquals(False, conf.get('foo'))
3763
def test_get_default_bool_when_conversion_fails(self):
3764
self.register_bool_option('foo', default='True')
3765
conf = self.get_conf('foo=invalid boolean')
3766
self.assertEquals(True, conf.get('foo'))
3768
def register_integer_option(self, name,
3769
default=None, default_from_env=None):
3770
i = config.Option(name, help='An integer.',
3771
default=default, default_from_env=default_from_env,
3772
from_unicode=config.int_from_store)
3773
self.registry.register(i)
3775
def test_get_default_integer_None(self):
3776
self.register_integer_option('foo')
3777
conf = self.get_conf('')
3778
self.assertEquals(None, conf.get('foo'))
3780
def test_get_default_integer(self):
3781
self.register_integer_option('foo', 42)
3782
conf = self.get_conf('')
3783
self.assertEquals(42, conf.get('foo'))
3785
def test_get_default_integer_as_string(self):
3786
self.register_integer_option('foo', u'42')
3787
conf = self.get_conf('')
3788
self.assertEquals(42, conf.get('foo'))
3790
def test_get_default_integer_from_env(self):
3791
self.register_integer_option('foo', default_from_env=['FOO'])
3792
self.overrideEnv('FOO', '18')
3793
conf = self.get_conf('')
3794
self.assertEquals(18, conf.get('foo'))
3796
def test_get_default_integer_when_conversion_fails(self):
3797
self.register_integer_option('foo', default='12')
3798
conf = self.get_conf('foo=invalid integer')
3799
self.assertEquals(12, conf.get('foo'))
3801
def register_list_option(self, name, default=None, default_from_env=None):
3802
l = config.ListOption(name, help='A list.', default=default,
3803
default_from_env=default_from_env)
3804
self.registry.register(l)
3806
def test_get_default_list_None(self):
3807
self.register_list_option('foo')
3808
conf = self.get_conf('')
3809
self.assertEquals(None, conf.get('foo'))
3811
def test_get_default_list_empty(self):
3812
self.register_list_option('foo', '')
3813
conf = self.get_conf('')
3814
self.assertEquals([], conf.get('foo'))
3816
def test_get_default_list_from_env(self):
3817
self.register_list_option('foo', default_from_env=['FOO'])
3818
self.overrideEnv('FOO', '')
3819
conf = self.get_conf('')
3820
self.assertEquals([], conf.get('foo'))
3822
def test_get_with_list_converter_no_item(self):
3823
self.register_list_option('foo', None)
3824
conf = self.get_conf('foo=,')
3825
self.assertEquals([], conf.get('foo'))
3827
def test_get_with_list_converter_many_items(self):
3828
self.register_list_option('foo', None)
3829
conf = self.get_conf('foo=m,o,r,e')
3830
self.assertEquals(['m', 'o', 'r', 'e'], conf.get('foo'))
3832
def test_get_with_list_converter_embedded_spaces_many_items(self):
3833
self.register_list_option('foo', None)
3834
conf = self.get_conf('foo=" bar", "baz "')
3835
self.assertEquals([' bar', 'baz '], conf.get('foo'))
3837
def test_get_with_list_converter_stripped_spaces_many_items(self):
3838
self.register_list_option('foo', None)
3839
conf = self.get_conf('foo= bar , baz ')
3840
self.assertEquals(['bar', 'baz'], conf.get('foo'))
3843
class TestIterOptionRefs(tests.TestCase):
3844
"""iter_option_refs is a bit unusual, document some cases."""
3846
def assertRefs(self, expected, string):
3847
self.assertEquals(expected, list(config.iter_option_refs(string)))
3849
def test_empty(self):
3850
self.assertRefs([(False, '')], '')
3852
def test_no_refs(self):
3853
self.assertRefs([(False, 'foo bar')], 'foo bar')
3855
def test_single_ref(self):
3856
self.assertRefs([(False, ''), (True, '{foo}'), (False, '')], '{foo}')
3858
def test_broken_ref(self):
3859
self.assertRefs([(False, '{foo')], '{foo')
3861
def test_embedded_ref(self):
3862
self.assertRefs([(False, '{'), (True, '{foo}'), (False, '}')],
3865
def test_two_refs(self):
3866
self.assertRefs([(False, ''), (True, '{foo}'),
3867
(False, ''), (True, '{bar}'),
3871
def test_newline_in_refs_are_not_matched(self):
3872
self.assertRefs([(False, '{\nxx}{xx\n}{{\n}}')], '{\nxx}{xx\n}{{\n}}')
3875
class TestStackExpandOptions(tests.TestCaseWithTransport):
3878
super(TestStackExpandOptions, self).setUp()
3879
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3880
self.registry = config.option_registry
3881
store = config.TransportIniFileStore(self.get_transport(), 'foo.conf')
3882
self.conf = config.Stack([store.get_sections], store)
3884
def assertExpansion(self, expected, string, env=None):
3885
self.assertEquals(expected, self.conf.expand_options(string, env))
3887
def test_no_expansion(self):
3888
self.assertExpansion('foo', 'foo')
3890
def test_expand_default_value(self):
3891
self.conf.store._load_from_string('bar=baz')
3892
self.registry.register(config.Option('foo', default=u'{bar}'))
3893
self.assertEquals('baz', self.conf.get('foo', expand=True))
3895
def test_expand_default_from_env(self):
3896
self.conf.store._load_from_string('bar=baz')
3897
self.registry.register(config.Option('foo', default_from_env=['FOO']))
3898
self.overrideEnv('FOO', '{bar}')
3899
self.assertEquals('baz', self.conf.get('foo', expand=True))
3901
def test_expand_default_on_failed_conversion(self):
3902
self.conf.store._load_from_string('baz=bogus\nbar=42\nfoo={baz}')
3903
self.registry.register(
3904
config.Option('foo', default=u'{bar}',
3905
from_unicode=config.int_from_store))
3906
self.assertEquals(42, self.conf.get('foo', expand=True))
3908
def test_env_adding_options(self):
3909
self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3911
def test_env_overriding_options(self):
3912
self.conf.store._load_from_string('foo=baz')
3913
self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3915
def test_simple_ref(self):
3916
self.conf.store._load_from_string('foo=xxx')
3917
self.assertExpansion('xxx', '{foo}')
3919
def test_unknown_ref(self):
3920
self.assertRaises(errors.ExpandingUnknownOption,
3921
self.conf.expand_options, '{foo}')
3923
def test_indirect_ref(self):
3924
self.conf.store._load_from_string('''
3928
self.assertExpansion('xxx', '{bar}')
3930
def test_embedded_ref(self):
3931
self.conf.store._load_from_string('''
3935
self.assertExpansion('xxx', '{{bar}}')
3937
def test_simple_loop(self):
3938
self.conf.store._load_from_string('foo={foo}')
3939
self.assertRaises(errors.OptionExpansionLoop,
3940
self.conf.expand_options, '{foo}')
3942
def test_indirect_loop(self):
3943
self.conf.store._load_from_string('''
3947
e = self.assertRaises(errors.OptionExpansionLoop,
3948
self.conf.expand_options, '{foo}')
3949
self.assertEquals('foo->bar->baz', e.refs)
3950
self.assertEquals('{foo}', e.string)
3952
def test_list(self):
3953
self.conf.store._load_from_string('''
3957
list={foo},{bar},{baz}
3959
self.registry.register(
3960
config.ListOption('list'))
3961
self.assertEquals(['start', 'middle', 'end'],
3962
self.conf.get('list', expand=True))
3964
def test_cascading_list(self):
3965
self.conf.store._load_from_string('''
3971
self.registry.register(config.ListOption('list'))
3972
# Register an intermediate option as a list to ensure no conversion
3973
# happen while expanding. Conversion should only occur for the original
3974
# option ('list' here).
3975
self.registry.register(config.ListOption('baz'))
3976
self.assertEquals(['start', 'middle', 'end'],
3977
self.conf.get('list', expand=True))
3979
def test_pathologically_hidden_list(self):
3980
self.conf.store._load_from_string('''
3986
hidden={start}{middle}{end}
3988
# What matters is what the registration says, the conversion happens
3989
# only after all expansions have been performed
3990
self.registry.register(config.ListOption('hidden'))
3991
self.assertEquals(['bin', 'go'],
3992
self.conf.get('hidden', expand=True))
3995
class TestStackCrossSectionsExpand(tests.TestCaseWithTransport):
3998
super(TestStackCrossSectionsExpand, self).setUp()
4000
def get_config(self, location, string):
4003
# Since we don't save the config we won't strictly require to inherit
4004
# from TestCaseInTempDir, but an error occurs so quickly...
4005
c = config.LocationStack(location)
4006
c.store._load_from_string(string)
4009
def test_dont_cross_unrelated_section(self):
4010
c = self.get_config('/another/branch/path','''
4015
[/another/branch/path]
4018
self.assertRaises(errors.ExpandingUnknownOption,
4019
c.get, 'bar', expand=True)
4021
def test_cross_related_sections(self):
4022
c = self.get_config('/project/branch/path','''
4026
[/project/branch/path]
4029
self.assertEquals('quux', c.get('bar', expand=True))
4032
class TestStackCrossStoresExpand(tests.TestCaseWithTransport):
4034
def test_cross_global_locations(self):
4035
l_store = config.LocationStore()
4036
l_store._load_from_string('''
4042
g_store = config.GlobalStore()
4043
g_store._load_from_string('''
4049
stack = config.LocationStack('/branch')
4050
self.assertEquals('glob-bar', stack.get('lbar', expand=True))
4051
self.assertEquals('loc-foo', stack.get('gfoo', expand=True))
4054
class TestStackExpandSectionLocals(tests.TestCaseWithTransport):
4056
def test_expand_locals_empty(self):
4057
l_store = config.LocationStore()
4058
l_store._load_from_string('''
4059
[/home/user/project]
4064
stack = config.LocationStack('/home/user/project/')
4065
self.assertEquals('', stack.get('base', expand=True))
4066
self.assertEquals('', stack.get('rel', expand=True))
4068
def test_expand_basename_locally(self):
4069
l_store = config.LocationStore()
4070
l_store._load_from_string('''
4071
[/home/user/project]
4075
stack = config.LocationStack('/home/user/project/branch')
4076
self.assertEquals('branch', stack.get('bfoo', expand=True))
4078
def test_expand_basename_locally_longer_path(self):
4079
l_store = config.LocationStore()
4080
l_store._load_from_string('''
4085
stack = config.LocationStack('/home/user/project/dir/branch')
4086
self.assertEquals('branch', stack.get('bfoo', expand=True))
4088
def test_expand_relpath_locally(self):
4089
l_store = config.LocationStore()
4090
l_store._load_from_string('''
4091
[/home/user/project]
4092
lfoo = loc-foo/{relpath}
4095
stack = config.LocationStack('/home/user/project/branch')
4096
self.assertEquals('loc-foo/branch', stack.get('lfoo', expand=True))
4098
def test_expand_relpath_unknonw_in_global(self):
4099
g_store = config.GlobalStore()
4100
g_store._load_from_string('''
4105
stack = config.LocationStack('/home/user/project/branch')
4106
self.assertRaises(errors.ExpandingUnknownOption,
4107
stack.get, 'gfoo', expand=True)
4109
def test_expand_local_option_locally(self):
4110
l_store = config.LocationStore()
4111
l_store._load_from_string('''
4112
[/home/user/project]
4113
lfoo = loc-foo/{relpath}
4117
g_store = config.GlobalStore()
4118
g_store._load_from_string('''
4124
stack = config.LocationStack('/home/user/project/branch')
4125
self.assertEquals('glob-bar', stack.get('lbar', expand=True))
4126
self.assertEquals('loc-foo/branch', stack.get('gfoo', expand=True))
4128
def test_locals_dont_leak(self):
4129
"""Make sure we chose the right local in presence of several sections.
4131
l_store = config.LocationStore()
4132
l_store._load_from_string('''
4134
lfoo = loc-foo/{relpath}
4135
[/home/user/project]
4136
lfoo = loc-foo/{relpath}
4139
stack = config.LocationStack('/home/user/project/branch')
4140
self.assertEquals('loc-foo/branch', stack.get('lfoo', expand=True))
4141
stack = config.LocationStack('/home/user/bar/baz')
4142
self.assertEquals('loc-foo/bar/baz', stack.get('lfoo', expand=True))
2935
4146
class TestStackSet(TestStackWithTransport):
2937
4148
def test_simple_set(self):
2938
4149
conf = self.get_stack(self)
2939
conf.store._load_from_string('foo=bar')
2940
self.assertEquals('bar', conf.get('foo'))
4150
self.assertEquals(None, conf.get('foo'))
2941
4151
conf.set('foo', 'baz')
2942
4152
# Did we get it back ?
2943
4153
self.assertEquals('baz', conf.get('foo'))
3665
4893
self.assertEquals((None, None), (realname, address))
4896
class TestDefaultMailDomain(tests.TestCaseInTempDir):
4897
"""Test retrieving default domain from mailname file"""
4899
def test_default_mail_domain_simple(self):
4900
f = file('simple', 'w')
4902
f.write("domainname.com\n")
4905
r = config._get_default_mail_domain('simple')
4906
self.assertEquals('domainname.com', r)
4908
def test_default_mail_domain_no_eol(self):
4909
f = file('no_eol', 'w')
4911
f.write("domainname.com")
4914
r = config._get_default_mail_domain('no_eol')
4915
self.assertEquals('domainname.com', r)
4917
def test_default_mail_domain_multiple_lines(self):
4918
f = file('multiple_lines', 'w')
4920
f.write("domainname.com\nsome other text\n")
4923
r = config._get_default_mail_domain('multiple_lines')
4924
self.assertEquals('domainname.com', r)
4927
class EmailOptionTests(tests.TestCase):
4929
def test_default_email_uses_BZR_EMAIL(self):
4930
conf = config.MemoryStack('email=jelmer@debian.org')
4931
# BZR_EMAIL takes precedence over EMAIL
4932
self.overrideEnv('BZR_EMAIL', 'jelmer@samba.org')
4933
self.overrideEnv('EMAIL', 'jelmer@apache.org')
4934
self.assertEquals('jelmer@samba.org', conf.get('email'))
4936
def test_default_email_uses_EMAIL(self):
4937
conf = config.MemoryStack('')
4938
self.overrideEnv('BZR_EMAIL', None)
4939
self.overrideEnv('EMAIL', 'jelmer@apache.org')
4940
self.assertEquals('jelmer@apache.org', conf.get('email'))
4942
def test_BZR_EMAIL_overrides(self):
4943
conf = config.MemoryStack('email=jelmer@debian.org')
4944
self.overrideEnv('BZR_EMAIL', 'jelmer@apache.org')
4945
self.assertEquals('jelmer@apache.org', conf.get('email'))
4946
self.overrideEnv('BZR_EMAIL', None)
4947
self.overrideEnv('EMAIL', 'jelmer@samba.org')
4948
self.assertEquals('jelmer@debian.org', conf.get('email'))
4951
class MailClientOptionTests(tests.TestCase):
4953
def test_default(self):
4954
conf = config.MemoryStack('')
4955
client = conf.get('mail_client')
4956
self.assertIs(client, mail_client.DefaultMail)
4958
def test_evolution(self):
4959
conf = config.MemoryStack('mail_client=evolution')
4960
client = conf.get('mail_client')
4961
self.assertIs(client, mail_client.Evolution)
4963
def test_kmail(self):
4964
conf = config.MemoryStack('mail_client=kmail')
4965
client = conf.get('mail_client')
4966
self.assertIs(client, mail_client.KMail)
4968
def test_mutt(self):
4969
conf = config.MemoryStack('mail_client=mutt')
4970
client = conf.get('mail_client')
4971
self.assertIs(client, mail_client.Mutt)
4973
def test_thunderbird(self):
4974
conf = config.MemoryStack('mail_client=thunderbird')
4975
client = conf.get('mail_client')
4976
self.assertIs(client, mail_client.Thunderbird)
4978
def test_explicit_default(self):
4979
conf = config.MemoryStack('mail_client=default')
4980
client = conf.get('mail_client')
4981
self.assertIs(client, mail_client.DefaultMail)
4983
def test_editor(self):
4984
conf = config.MemoryStack('mail_client=editor')
4985
client = conf.get('mail_client')
4986
self.assertIs(client, mail_client.Editor)
4988
def test_mapi(self):
4989
conf = config.MemoryStack('mail_client=mapi')
4990
client = conf.get('mail_client')
4991
self.assertIs(client, mail_client.MAPIClient)
4993
def test_xdg_email(self):
4994
conf = config.MemoryStack('mail_client=xdg-email')
4995
client = conf.get('mail_client')
4996
self.assertIs(client, mail_client.XDGEmail)
4998
def test_unknown(self):
4999
conf = config.MemoryStack('mail_client=firebird')
5000
self.assertRaises(errors.ConfigOptionValueError, conf.get,