144
144
config.test_stack_builder_registry.register('branch', build_branch_stack)
147
def build_remote_branch_stack(test):
147
def build_branch_only_stack(test):
148
148
# There is only one permutation (but we won't be able to handle more with
149
149
# this design anyway)
150
150
(transport_class,
151
151
server_class) = transport_remote.get_test_permutations()[0]
152
152
build_backing_branch(test, 'branch', transport_class, server_class)
153
153
b = branch.Branch.open(test.get_url('branch'))
154
return config.RemoteBranchStack(b)
155
config.test_stack_builder_registry.register('remote_branch',
156
build_remote_branch_stack)
154
return config.BranchOnlyStack(b)
155
config.test_stack_builder_registry.register('branch_only',
156
build_branch_only_stack)
158
158
def build_remote_control_stack(test):
159
159
# There is only one permutation (but we won't be able to handle more with
2366
2366
class TestOptionConverterMixin(object):
2368
2368
def assertConverted(self, expected, opt, value):
2369
self.assertEquals(expected, opt.convert_from_unicode(value),
2370
'Expecting %s, got %s' % (expected, value,))
2369
self.assertEquals(expected, opt.convert_from_unicode(None, value))
2372
2371
def assertWarns(self, opt, value):
2374
2373
def warning(*args):
2375
2374
warnings.append(args[0] % args[1:])
2376
2375
self.overrideAttr(trace, 'warning', warning)
2377
self.assertEquals(None, opt.convert_from_unicode(value))
2376
self.assertEquals(None, opt.convert_from_unicode(None, value))
2378
2377
self.assertLength(1, warnings)
2379
2378
self.assertEquals(
2380
2379
'Value "%s" is not valid for "%s"' % (value, opt.name),
2457
2455
self.assertConverted(100, opt, u'100')
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)
2466
def test_convert_invalid(self):
2467
# No string is invalid as all forms can be converted to a list
2470
def test_convert_valid(self):
2471
opt = self.get_option()
2472
# An empty string is an empty list
2473
self.assertConverted([], opt, '') # Using a bare str() just in case
2474
self.assertConverted([], opt, u'')
2476
self.assertConverted([u'True'], opt, u'True')
2478
self.assertConverted([u'42'], opt, u'42')
2480
self.assertConverted([u'bar'], opt, u'bar')
2481
# A list remains a list (configObj will turn a string containing commas
2482
# into a list, but that's not what we're testing here)
2483
self.assertConverted([u'foo', u'1', u'True'],
2484
opt, [u'foo', u'1', u'True'])
2487
class TestOptionConverterMixin(object):
2489
def assertConverted(self, expected, opt, value):
2490
self.assertEquals(expected, opt.convert_from_unicode(value))
2492
def assertWarns(self, opt, value):
2495
warnings.append(args[0] % args[1:])
2496
self.overrideAttr(trace, 'warning', warning)
2497
self.assertEquals(None, opt.convert_from_unicode(value))
2498
self.assertLength(1, warnings)
2500
'Value "%s" is not valid for "%s"' % (value, opt.name),
2503
def assertErrors(self, opt, value):
2504
self.assertRaises(errors.ConfigOptionValueError,
2505
opt.convert_from_unicode, value)
2507
def assertConvertInvalid(self, opt, invalid_value):
2509
self.assertEquals(None, opt.convert_from_unicode(invalid_value))
2510
opt.invalid = 'warning'
2511
self.assertWarns(opt, invalid_value)
2512
opt.invalid = 'error'
2513
self.assertErrors(opt, invalid_value)
2516
class TestOptionWithBooleanConverter(tests.TestCase, TestOptionConverterMixin):
2518
def get_option(self):
2519
return config.Option('foo', help='A boolean.',
2520
from_unicode=config.bool_from_store)
2522
def test_convert_invalid(self):
2523
opt = self.get_option()
2524
# A string that is not recognized as a boolean
2525
self.assertConvertInvalid(opt, u'invalid-boolean')
2526
# A list of strings is never recognized as a boolean
2527
self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
2529
def test_convert_valid(self):
2530
opt = self.get_option()
2531
self.assertConverted(True, opt, u'True')
2532
self.assertConverted(True, opt, u'1')
2533
self.assertConverted(False, opt, u'False')
2536
class TestOptionWithIntegerConverter(tests.TestCase, TestOptionConverterMixin):
2538
def get_option(self):
2539
return config.Option('foo', help='An integer.',
2540
from_unicode=config.int_from_store)
2542
def test_convert_invalid(self):
2543
opt = self.get_option()
2544
# A string that is not recognized as an integer
2545
self.assertConvertInvalid(opt, u'forty-two')
2546
# A list of strings is never recognized as an integer
2547
self.assertConvertInvalid(opt, [u'a', u'list'])
2549
def test_convert_valid(self):
2550
opt = self.get_option()
2551
self.assertConverted(16, opt, u'16')
2554
class TestOptionWithListConverter(tests.TestCase, TestOptionConverterMixin):
2556
def get_option(self):
2557
return config.Option('foo', help='A list.',
2558
from_unicode=config.list_from_store)
2458
class TestListOption(tests.TestCase, TestOptionConverterMixin):
2460
def get_option(self):
2461
return config.ListOption('foo', help='A list.')
2560
2463
def test_convert_invalid(self):
2561
2464
opt = self.get_option()
2731
2635
self.assertEqual('b', section.get('a'))
2733
2637
def test_list_override(self):
2638
opt = config.ListOption('l')
2639
config.option_registry.register(opt)
2734
2640
self.store._from_cmdline(['l=1,2,3'])
2735
2641
val = self.get_section().get('l')
2736
2642
self.assertEqual('1,2,3', val)
2737
2643
# Reminder: lists should be registered as such explicitely, otherwise
2738
2644
# the conversion needs to be done afterwards.
2739
self.assertEqual(['1', '2', '3'], config.list_from_store(val))
2645
self.assertEqual(['1', '2', '3'],
2646
opt.convert_from_unicode(self.store, val))
2741
2648
def test_multiple_overrides(self):
2742
2649
self.store._from_cmdline(['a=b', 'x=y'])
2796
2703
self.assertRaises(AssertionError, store._load_from_string, 'bar=baz')
2706
class TestStoreQuoting(TestStore):
2708
scenarios = [(key, {'get_store': builder}) for key, builder
2709
in config.test_store_builder_registry.iteritems()]
2712
super(TestStoreQuoting, self).setUp()
2713
self.store = self.get_store(self)
2714
# We need a loaded store but any content will do
2715
self.store._load_from_string('')
2717
def assertIdempotent(self, s):
2718
"""Assert that quoting an unquoted string is a no-op and vice-versa.
2720
What matters here is that option values, as they appear in a store, can
2721
be safely round-tripped out of the store and back.
2723
:param s: A string, quoted if required.
2725
self.assertEquals(s, self.store.quote(self.store.unquote(s)))
2726
self.assertEquals(s, self.store.unquote(self.store.quote(s)))
2728
def test_empty_string(self):
2729
if isinstance(self.store, config.IniFileStore):
2730
# configobj._quote doesn't handle empty values
2731
self.assertRaises(AssertionError,
2732
self.assertIdempotent, '')
2734
self.assertIdempotent('')
2735
# But quoted empty strings are ok
2736
self.assertIdempotent('""')
2738
def test_embedded_spaces(self):
2739
self.assertIdempotent('" a b c "')
2741
def test_embedded_commas(self):
2742
self.assertIdempotent('" a , b c "')
2744
def test_simple_comma(self):
2745
if isinstance(self.store, config.IniFileStore):
2746
# configobj requires that lists are special-cased
2747
self.assertRaises(AssertionError,
2748
self.assertIdempotent, ',')
2750
self.assertIdempotent(',')
2751
# When a single comma is required, quoting is also required
2752
self.assertIdempotent('","')
2754
def test_list(self):
2755
if isinstance(self.store, config.IniFileStore):
2756
# configobj requires that lists are special-cased
2757
self.assertRaises(AssertionError,
2758
self.assertIdempotent, 'a,b')
2760
self.assertIdempotent('a,b')
2799
2763
class TestIniFileStoreContent(tests.TestCaseWithTransport):
2800
2764
"""Simulate loading a config store with content of various encodings.
3356
3339
self.assertLength(0, sections)
3359
class TestStackGet(tests.TestCase):
3361
# FIXME: This should be parametrized for all known Stack or dedicated
3362
# paramerized tests created to avoid bloating -- vila 2011-03-31
3364
def overrideOptionRegistry(self):
3342
class TestBaseStackGet(tests.TestCase):
3345
super(TestBaseStackGet, self).setUp()
3365
3346
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3367
def test_single_config_get(self):
3368
conf = dict(foo='bar')
3369
conf_stack = config.Stack([conf])
3370
self.assertEquals('bar', conf_stack.get('foo'))
3348
def test_get_first_definition(self):
3349
store1 = config.IniFileStore()
3350
store1._load_from_string('foo=bar')
3351
store2 = config.IniFileStore()
3352
store2._load_from_string('foo=baz')
3353
conf = config.Stack([store1.get_sections, store2.get_sections])
3354
self.assertEquals('bar', conf.get('foo'))
3372
3356
def test_get_with_registered_default_value(self):
3373
conf_stack = config.Stack([dict()])
3374
opt = config.Option('foo', default='bar')
3375
self.overrideOptionRegistry()
3376
config.option_registry.register('foo', opt)
3357
config.option_registry.register(config.Option('foo', default='bar'))
3358
conf_stack = config.Stack([])
3377
3359
self.assertEquals('bar', conf_stack.get('foo'))
3379
3361
def test_get_without_registered_default_value(self):
3380
conf_stack = config.Stack([dict()])
3381
opt = config.Option('foo')
3382
self.overrideOptionRegistry()
3383
config.option_registry.register('foo', opt)
3362
config.option_registry.register(config.Option('foo'))
3363
conf_stack = config.Stack([])
3384
3364
self.assertEquals(None, conf_stack.get('foo'))
3386
3366
def test_get_without_default_value_for_not_registered(self):
3387
conf_stack = config.Stack([dict()])
3388
opt = config.Option('foo')
3389
self.overrideOptionRegistry()
3367
conf_stack = config.Stack([])
3390
3368
self.assertEquals(None, conf_stack.get('foo'))
3392
def test_get_first_definition(self):
3393
conf1 = dict(foo='bar')
3394
conf2 = dict(foo='baz')
3395
conf_stack = config.Stack([conf1, conf2])
3396
self.assertEquals('bar', conf_stack.get('foo'))
3398
def test_get_embedded_definition(self):
3399
conf1 = dict(yy='12')
3400
conf2 = config.Stack([dict(xx='42'), dict(foo='baz')])
3401
conf_stack = config.Stack([conf1, conf2])
3402
self.assertEquals('baz', conf_stack.get('foo'))
3404
3370
def test_get_for_empty_section_callable(self):
3405
3371
conf_stack = config.Stack([lambda : []])
3406
3372
self.assertEquals(None, conf_stack.get('foo'))
3408
3374
def test_get_for_broken_callable(self):
3409
3375
# Trying to use and invalid callable raises an exception on first use
3410
conf_stack = config.Stack([lambda : object()])
3376
conf_stack = config.Stack([object])
3411
3377
self.assertRaises(TypeError, conf_stack.get, 'foo')
3380
class TestMemoryStack(tests.TestCase):
3383
conf = config.MemoryStack('foo=bar')
3384
self.assertEquals('bar', conf.get('foo'))
3387
conf = config.MemoryStack('foo=bar')
3388
conf.set('foo', 'baz')
3389
self.assertEquals('baz', conf.get('foo'))
3391
def test_no_content(self):
3392
conf = config.MemoryStack()
3393
# No content means no loading
3394
self.assertFalse(conf.store.is_loaded())
3395
self.assertRaises(NotImplementedError, conf.get, 'foo')
3396
# But a content can still be provided
3397
conf.store._load_from_string('foo=bar')
3398
self.assertEquals('bar', conf.get('foo'))
3414
3401
class TestStackWithTransport(tests.TestCaseWithTransport):
3416
3403
scenarios = [(key, {'get_stack': builder}) for key, builder
3446
3433
self.assertEquals((self.conf, 'foo', 'bar'), calls[0])
3449
class TestStackGetWithConverter(tests.TestCaseWithTransport):
3436
class TestStackGetWithConverter(tests.TestCase):
3451
3438
def setUp(self):
3452
3439
super(TestStackGetWithConverter, self).setUp()
3453
3440
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3454
3441
self.registry = config.option_registry
3455
# We just want a simple stack with a simple store so we can inject
3456
# whatever content the tests need without caring about what section
3457
# names are valid for a given store/stack.
3458
store = config.TransportIniFileStore(self.get_transport(), 'foo.conf')
3459
self.conf = config.Stack([store.get_sections], store)
3443
def get_conf(self, content=None):
3444
return config.MemoryStack(content)
3461
3446
def register_bool_option(self, name, default=None, default_from_env=None):
3462
3447
b = config.Option(name, help='A boolean.',
3467
3452
def test_get_default_bool_None(self):
3468
3453
self.register_bool_option('foo')
3469
self.assertEquals(None, self.conf.get('foo'))
3454
conf = self.get_conf('')
3455
self.assertEquals(None, conf.get('foo'))
3471
3457
def test_get_default_bool_True(self):
3472
3458
self.register_bool_option('foo', u'True')
3473
self.assertEquals(True, self.conf.get('foo'))
3459
conf = self.get_conf('')
3460
self.assertEquals(True, conf.get('foo'))
3475
3462
def test_get_default_bool_False(self):
3476
3463
self.register_bool_option('foo', False)
3477
self.assertEquals(False, self.conf.get('foo'))
3464
conf = self.get_conf('')
3465
self.assertEquals(False, conf.get('foo'))
3479
3467
def test_get_default_bool_False_as_string(self):
3480
3468
self.register_bool_option('foo', u'False')
3481
self.assertEquals(False, self.conf.get('foo'))
3469
conf = self.get_conf('')
3470
self.assertEquals(False, conf.get('foo'))
3483
3472
def test_get_default_bool_from_env_converted(self):
3484
3473
self.register_bool_option('foo', u'True', default_from_env=['FOO'])
3485
3474
self.overrideEnv('FOO', 'False')
3486
self.assertEquals(False, self.conf.get('foo'))
3475
conf = self.get_conf('')
3476
self.assertEquals(False, conf.get('foo'))
3488
3478
def test_get_default_bool_when_conversion_fails(self):
3489
3479
self.register_bool_option('foo', default='True')
3490
self.conf.store._load_from_string('foo=invalid boolean')
3491
self.assertEquals(True, self.conf.get('foo'))
3480
conf = self.get_conf('foo=invalid boolean')
3481
self.assertEquals(True, conf.get('foo'))
3493
3483
def register_integer_option(self, name,
3494
3484
default=None, default_from_env=None):
3500
3490
def test_get_default_integer_None(self):
3501
3491
self.register_integer_option('foo')
3502
self.assertEquals(None, self.conf.get('foo'))
3492
conf = self.get_conf('')
3493
self.assertEquals(None, conf.get('foo'))
3504
3495
def test_get_default_integer(self):
3505
3496
self.register_integer_option('foo', 42)
3506
self.assertEquals(42, self.conf.get('foo'))
3497
conf = self.get_conf('')
3498
self.assertEquals(42, conf.get('foo'))
3508
3500
def test_get_default_integer_as_string(self):
3509
3501
self.register_integer_option('foo', u'42')
3510
self.assertEquals(42, self.conf.get('foo'))
3502
conf = self.get_conf('')
3503
self.assertEquals(42, conf.get('foo'))
3512
3505
def test_get_default_integer_from_env(self):
3513
3506
self.register_integer_option('foo', default_from_env=['FOO'])
3514
3507
self.overrideEnv('FOO', '18')
3515
self.assertEquals(18, self.conf.get('foo'))
3508
conf = self.get_conf('')
3509
self.assertEquals(18, conf.get('foo'))
3517
3511
def test_get_default_integer_when_conversion_fails(self):
3518
3512
self.register_integer_option('foo', default='12')
3519
self.conf.store._load_from_string('foo=invalid integer')
3520
self.assertEquals(12, self.conf.get('foo'))
3513
conf = self.get_conf('foo=invalid integer')
3514
self.assertEquals(12, conf.get('foo'))
3522
3516
def register_list_option(self, name, default=None, default_from_env=None):
3523
l = config.Option(name, help='A list.',
3524
default=default, default_from_env=default_from_env,
3525
from_unicode=config.list_from_store)
3517
l = config.ListOption(name, help='A list.', default=default,
3518
default_from_env=default_from_env)
3526
3519
self.registry.register(l)
3528
3521
def test_get_default_list_None(self):
3529
3522
self.register_list_option('foo')
3530
self.assertEquals(None, self.conf.get('foo'))
3523
conf = self.get_conf('')
3524
self.assertEquals(None, conf.get('foo'))
3532
3526
def test_get_default_list_empty(self):
3533
3527
self.register_list_option('foo', '')
3534
self.assertEquals([], self.conf.get('foo'))
3528
conf = self.get_conf('')
3529
self.assertEquals([], conf.get('foo'))
3536
3531
def test_get_default_list_from_env(self):
3537
3532
self.register_list_option('foo', default_from_env=['FOO'])
3538
3533
self.overrideEnv('FOO', '')
3539
self.assertEquals([], self.conf.get('foo'))
3534
conf = self.get_conf('')
3535
self.assertEquals([], conf.get('foo'))
3541
3537
def test_get_with_list_converter_no_item(self):
3542
3538
self.register_list_option('foo', None)
3543
self.conf.store._load_from_string('foo=,')
3544
self.assertEquals([], self.conf.get('foo'))
3539
conf = self.get_conf('foo=,')
3540
self.assertEquals([], conf.get('foo'))
3546
3542
def test_get_with_list_converter_many_items(self):
3547
3543
self.register_list_option('foo', None)
3548
self.conf.store._load_from_string('foo=m,o,r,e')
3549
self.assertEquals(['m', 'o', 'r', 'e'], self.conf.get('foo'))
3544
conf = self.get_conf('foo=m,o,r,e')
3545
self.assertEquals(['m', 'o', 'r', 'e'], conf.get('foo'))
3551
3547
def test_get_with_list_converter_embedded_spaces_many_items(self):
3552
3548
self.register_list_option('foo', None)
3553
self.conf.store._load_from_string('foo=" bar", "baz "')
3554
self.assertEquals([' bar', 'baz '], self.conf.get('foo'))
3549
conf = self.get_conf('foo=" bar", "baz "')
3550
self.assertEquals([' bar', 'baz '], conf.get('foo'))
3556
3552
def test_get_with_list_converter_stripped_spaces_many_items(self):
3557
3553
self.register_list_option('foo', None)
3558
self.conf.store._load_from_string('foo= bar , baz ')
3559
self.assertEquals(['bar', 'baz'], self.conf.get('foo'))
3554
conf = self.get_conf('foo= bar , baz ')
3555
self.assertEquals(['bar', 'baz'], conf.get('foo'))
3562
3558
class TestIterOptionRefs(tests.TestCase):