2387
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)
2466
def test_convert_invalid(self):
2467
opt = self.get_option()
2468
# We don't even try to convert a list into a list, we only expect
2470
self.assertConvertInvalid(opt, [1])
2471
# No string is invalid as all forms can be converted to a list
2473
def test_convert_valid(self):
2474
opt = self.get_option()
2475
# An empty string is an empty list
2476
self.assertConverted([], opt, '') # Using a bare str() just in case
2477
self.assertConverted([], opt, u'')
2479
self.assertConverted([u'True'], opt, u'True')
2481
self.assertConverted([u'42'], opt, u'42')
2483
self.assertConverted([u'bar'], opt, u'bar')
2390
2486
class TestOptionRegistry(tests.TestCase):
2392
2488
def setUp(self):
3272
3397
self.conf.store._load_from_string('foo=m,o,r,e')
3273
3398
self.assertEquals(['m', 'o', 'r', 'e'], self.conf.get('foo'))
3400
def test_get_with_list_converter_embedded_spaces_many_items(self):
3401
self.register_list_option('foo', None)
3402
self.conf.store._load_from_string('foo=" bar", "baz "')
3403
self.assertEquals([' bar', 'baz '], self.conf.get('foo'))
3405
def test_get_with_list_converter_stripped_spaces_many_items(self):
3406
self.register_list_option('foo', None)
3407
self.conf.store._load_from_string('foo= bar , baz ')
3408
self.assertEquals(['bar', 'baz'], self.conf.get('foo'))
3411
class TestStackExpandOptions(tests.TestCaseWithTransport):
3414
super(TestStackExpandOptions, self).setUp()
3415
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3416
self.registry = config.option_registry
3417
self.conf = build_branch_stack(self)
3419
def assertExpansion(self, expected, string, env=None):
3420
self.assertEquals(expected, self.conf.expand_options(string, env))
3422
def test_no_expansion(self):
3423
self.assertExpansion('foo', 'foo')
3425
def test_expand_default_value(self):
3426
self.conf.store._load_from_string('bar=baz')
3427
self.registry.register(config.Option('foo', default=u'{bar}'))
3428
self.assertEquals('baz', self.conf.get('foo', expand=True))
3430
def test_expand_default_from_env(self):
3431
self.conf.store._load_from_string('bar=baz')
3432
self.registry.register(config.Option('foo', default_from_env=['FOO']))
3433
self.overrideEnv('FOO', '{bar}')
3434
self.assertEquals('baz', self.conf.get('foo', expand=True))
3436
def test_expand_default_on_failed_conversion(self):
3437
self.conf.store._load_from_string('baz=bogus\nbar=42\nfoo={baz}')
3438
self.registry.register(
3439
config.Option('foo', default=u'{bar}',
3440
from_unicode=config.int_from_store))
3441
self.assertEquals(42, self.conf.get('foo', expand=True))
3443
def test_env_adding_options(self):
3444
self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3446
def test_env_overriding_options(self):
3447
self.conf.store._load_from_string('foo=baz')
3448
self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3450
def test_simple_ref(self):
3451
self.conf.store._load_from_string('foo=xxx')
3452
self.assertExpansion('xxx', '{foo}')
3454
def test_unknown_ref(self):
3455
self.assertRaises(errors.ExpandingUnknownOption,
3456
self.conf.expand_options, '{foo}')
3458
def test_indirect_ref(self):
3459
self.conf.store._load_from_string('''
3463
self.assertExpansion('xxx', '{bar}')
3465
def test_embedded_ref(self):
3466
self.conf.store._load_from_string('''
3470
self.assertExpansion('xxx', '{{bar}}')
3472
def test_simple_loop(self):
3473
self.conf.store._load_from_string('foo={foo}')
3474
self.assertRaises(errors.OptionExpansionLoop,
3475
self.conf.expand_options, '{foo}')
3477
def test_indirect_loop(self):
3478
self.conf.store._load_from_string('''
3482
e = self.assertRaises(errors.OptionExpansionLoop,
3483
self.conf.expand_options, '{foo}')
3484
self.assertEquals('foo->bar->baz', e.refs)
3485
self.assertEquals('{foo}', e.string)
3487
def test_list(self):
3488
self.conf.store._load_from_string('''
3492
list={foo},{bar},{baz}
3494
self.registry.register(
3495
config.Option('list', from_unicode=config.list_from_store))
3496
self.assertEquals(['start', 'middle', 'end'],
3497
self.conf.get('list', expand=True))
3499
def test_cascading_list(self):
3500
self.conf.store._load_from_string('''
3506
self.registry.register(
3507
config.Option('list', from_unicode=config.list_from_store))
3508
self.assertEquals(['start', 'middle', 'end'],
3509
self.conf.get('list', expand=True))
3511
def test_pathologically_hidden_list(self):
3512
self.conf.store._load_from_string('''
3518
hidden={start}{middle}{end}
3520
# What matters is what the registration says, the conversion happens
3521
# only after all expansions have been performed
3522
self.registry.register(
3523
config.Option('hidden', from_unicode=config.list_from_store))
3524
self.assertEquals(['bin', 'go'],
3525
self.conf.get('hidden', expand=True))
3528
class TestStackCrossSectionsExpand(tests.TestCaseWithTransport):
3531
super(TestStackCrossSectionsExpand, self).setUp()
3533
def get_config(self, location, string):
3536
# Since we don't save the config we won't strictly require to inherit
3537
# from TestCaseInTempDir, but an error occurs so quickly...
3538
c = config.LocationStack(location)
3539
c.store._load_from_string(string)
3542
def test_dont_cross_unrelated_section(self):
3543
c = self.get_config('/another/branch/path','''
3548
[/another/branch/path]
3551
self.assertRaises(errors.ExpandingUnknownOption,
3552
c.get, 'bar', expand=True)
3554
def test_cross_related_sections(self):
3555
c = self.get_config('/project/branch/path','''
3559
[/project/branch/path]
3562
self.assertEquals('quux', c.get('bar', expand=True))
3276
3565
class TestStackSet(TestStackWithTransport):