~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_config.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2011-09-02 08:34:51 UTC
  • mfrom: (6082.5.10 expand-in-stack)
  • Revision ID: pqm@pqm.ubuntu.com-20110902083451-ucpbb8ydrk5upxwv
(vila) Start supporting option expansion in config stacks. (Vincent Ladeuil)

Show diffs side-by-side

added added

removed removed

Lines of Context:
835
835
        self.assertEquals(['{foo', '}', '{', 'bar}'],
836
836
                          conf.get_user_option('hidden', expand=True))
837
837
 
 
838
 
838
839
class TestLocationConfigOptionExpansion(tests.TestCaseInTempDir):
839
840
 
840
841
    def get_config(self, location, string=None):
2387
2388
                             opt, [u'foo', u'1', u'True'])
2388
2389
 
2389
2390
 
 
2391
class TestOptionConverterMixin(object):
 
2392
 
 
2393
    def assertConverted(self, expected, opt, value):
 
2394
        self.assertEquals(expected, opt.convert_from_unicode(value))
 
2395
 
 
2396
    def assertWarns(self, opt, value):
 
2397
        warnings = []
 
2398
        def warning(*args):
 
2399
            warnings.append(args[0] % args[1:])
 
2400
        self.overrideAttr(trace, 'warning', warning)
 
2401
        self.assertEquals(None, opt.convert_from_unicode(value))
 
2402
        self.assertLength(1, warnings)
 
2403
        self.assertEquals(
 
2404
            'Value "%s" is not valid for "%s"' % (value, opt.name),
 
2405
            warnings[0])
 
2406
 
 
2407
    def assertErrors(self, opt, value):
 
2408
        self.assertRaises(errors.ConfigOptionValueError,
 
2409
                          opt.convert_from_unicode, value)
 
2410
 
 
2411
    def assertConvertInvalid(self, opt, invalid_value):
 
2412
        opt.invalid = None
 
2413
        self.assertEquals(None, opt.convert_from_unicode(invalid_value))
 
2414
        opt.invalid = 'warning'
 
2415
        self.assertWarns(opt, invalid_value)
 
2416
        opt.invalid = 'error'
 
2417
        self.assertErrors(opt, invalid_value)
 
2418
 
 
2419
 
 
2420
class TestOptionWithBooleanConverter(tests.TestCase, TestOptionConverterMixin):
 
2421
 
 
2422
    def get_option(self):
 
2423
        return config.Option('foo', help='A boolean.',
 
2424
                             from_unicode=config.bool_from_store)
 
2425
 
 
2426
    def test_convert_invalid(self):
 
2427
        opt = self.get_option()
 
2428
        # A string that is not recognized as a boolean
 
2429
        self.assertConvertInvalid(opt, u'invalid-boolean')
 
2430
        # A list of strings is never recognized as a boolean
 
2431
        self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
 
2432
 
 
2433
    def test_convert_valid(self):
 
2434
        opt = self.get_option()
 
2435
        self.assertConverted(True, opt, u'True')
 
2436
        self.assertConverted(True, opt, u'1')
 
2437
        self.assertConverted(False, opt, u'False')
 
2438
 
 
2439
 
 
2440
class TestOptionWithIntegerConverter(tests.TestCase, TestOptionConverterMixin):
 
2441
 
 
2442
    def get_option(self):
 
2443
        return config.Option('foo', help='An integer.',
 
2444
                             from_unicode=config.int_from_store)
 
2445
 
 
2446
    def test_convert_invalid(self):
 
2447
        opt = self.get_option()
 
2448
        # A string that is not recognized as an integer
 
2449
        self.assertConvertInvalid(opt, u'forty-two')
 
2450
        # A list of strings is never recognized as an integer
 
2451
        self.assertConvertInvalid(opt, [u'a', u'list'])
 
2452
 
 
2453
    def test_convert_valid(self):
 
2454
        opt = self.get_option()
 
2455
        self.assertConverted(16, opt, u'16')
 
2456
 
 
2457
 
 
2458
class TestOptionWithListConverter(tests.TestCase, TestOptionConverterMixin):
 
2459
 
 
2460
    def get_option(self):
 
2461
        return config.Option('foo', help='A list.',
 
2462
                             from_unicode=config.list_from_store)
 
2463
 
 
2464
    def test_convert_invalid(self):
 
2465
        # No string is invalid as all forms can be converted to a list
 
2466
        pass
 
2467
 
 
2468
    def test_convert_valid(self):
 
2469
        opt = self.get_option()
 
2470
        # An empty string is an empty list
 
2471
        self.assertConverted([], opt, '') # Using a bare str() just in case
 
2472
        self.assertConverted([], opt, u'')
 
2473
        # A boolean
 
2474
        self.assertConverted([u'True'], opt, u'True')
 
2475
        # An integer
 
2476
        self.assertConverted([u'42'], opt, u'42')
 
2477
        # A single string
 
2478
        self.assertConverted([u'bar'], opt, u'bar')
 
2479
        # A list remains a list (configObj will turn a string containing commas
 
2480
        # into a list, but that's not what we're testing here)
 
2481
        self.assertConverted([u'foo', u'1', u'True'],
 
2482
                             opt, [u'foo', u'1', u'True'])
 
2483
 
 
2484
 
2390
2485
class TestOptionRegistry(tests.TestCase):
2391
2486
 
2392
2487
    def setUp(self):
3273
3368
        self.assertEquals(['m', 'o', 'r', 'e'], self.conf.get('foo'))
3274
3369
 
3275
3370
 
 
3371
class TestStackExpandOptions(tests.TestCaseWithTransport):
 
3372
 
 
3373
    def setUp(self):
 
3374
        super(TestStackExpandOptions, self).setUp()
 
3375
        self.overrideAttr(config, 'option_registry', config.OptionRegistry())
 
3376
        self.registry = config.option_registry
 
3377
        self.conf = build_branch_stack(self)
 
3378
 
 
3379
    def assertExpansion(self, expected, string, env=None):
 
3380
        self.assertEquals(expected, self.conf.expand_options(string, env))
 
3381
 
 
3382
    def test_no_expansion(self):
 
3383
        self.assertExpansion('foo', 'foo')
 
3384
 
 
3385
    def test_expand_default_value(self):
 
3386
        self.conf.store._load_from_string('bar=baz')
 
3387
        self.registry.register(config.Option('foo', default=u'{bar}'))
 
3388
        self.assertEquals('baz', self.conf.get('foo', expand=True))
 
3389
 
 
3390
    def test_expand_default_from_env(self):
 
3391
        self.conf.store._load_from_string('bar=baz')
 
3392
        self.registry.register(config.Option('foo', default_from_env=['FOO']))
 
3393
        self.overrideEnv('FOO', '{bar}')
 
3394
        self.assertEquals('baz', self.conf.get('foo', expand=True))
 
3395
 
 
3396
    def test_expand_default_on_failed_conversion(self):
 
3397
        self.conf.store._load_from_string('baz=bogus\nbar=42\nfoo={baz}')
 
3398
        self.registry.register(
 
3399
            config.Option('foo', default=u'{bar}',
 
3400
                          from_unicode=config.int_from_store))
 
3401
        self.assertEquals(42, self.conf.get('foo', expand=True))
 
3402
 
 
3403
    def test_env_adding_options(self):
 
3404
        self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
 
3405
 
 
3406
    def test_env_overriding_options(self):
 
3407
        self.conf.store._load_from_string('foo=baz')
 
3408
        self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
 
3409
 
 
3410
    def test_simple_ref(self):
 
3411
        self.conf.store._load_from_string('foo=xxx')
 
3412
        self.assertExpansion('xxx', '{foo}')
 
3413
 
 
3414
    def test_unknown_ref(self):
 
3415
        self.assertRaises(errors.ExpandingUnknownOption,
 
3416
                          self.conf.expand_options, '{foo}')
 
3417
 
 
3418
    def test_indirect_ref(self):
 
3419
        self.conf.store._load_from_string('''
 
3420
foo=xxx
 
3421
bar={foo}
 
3422
''')
 
3423
        self.assertExpansion('xxx', '{bar}')
 
3424
 
 
3425
    def test_embedded_ref(self):
 
3426
        self.conf.store._load_from_string('''
 
3427
foo=xxx
 
3428
bar=foo
 
3429
''')
 
3430
        self.assertExpansion('xxx', '{{bar}}')
 
3431
 
 
3432
    def test_simple_loop(self):
 
3433
        self.conf.store._load_from_string('foo={foo}')
 
3434
        self.assertRaises(errors.OptionExpansionLoop,
 
3435
                          self.conf.expand_options, '{foo}')
 
3436
 
 
3437
    def test_indirect_loop(self):
 
3438
        self.conf.store._load_from_string('''
 
3439
foo={bar}
 
3440
bar={baz}
 
3441
baz={foo}''')
 
3442
        e = self.assertRaises(errors.OptionExpansionLoop,
 
3443
                              self.conf.expand_options, '{foo}')
 
3444
        self.assertEquals('foo->bar->baz', e.refs)
 
3445
        self.assertEquals('{foo}', e.string)
 
3446
 
 
3447
    def test_list(self):
 
3448
        self.conf.store._load_from_string('''
 
3449
foo=start
 
3450
bar=middle
 
3451
baz=end
 
3452
list={foo},{bar},{baz}
 
3453
''')
 
3454
        self.assertEquals(['start', 'middle', 'end'],
 
3455
                           self.conf.get('list', expand=True))
 
3456
 
 
3457
    def test_cascading_list(self):
 
3458
        self.conf.store._load_from_string('''
 
3459
foo=start,{bar}
 
3460
bar=middle,{baz}
 
3461
baz=end
 
3462
list={foo}
 
3463
''')
 
3464
        self.assertEquals(['start', 'middle', 'end'],
 
3465
                           self.conf.get('list', expand=True))
 
3466
 
 
3467
    def test_pathologically_hidden_list(self):
 
3468
        self.conf.store._load_from_string('''
 
3469
foo=bin
 
3470
bar=go
 
3471
start={foo
 
3472
middle=},{
 
3473
end=bar}
 
3474
hidden={start}{middle}{end}
 
3475
''')
 
3476
        # Nope, it's either a string or a list, and the list wins as soon as a
 
3477
        # ',' appears, so the string concatenation never occur.
 
3478
        self.assertEquals(['{foo', '}', '{', 'bar}'],
 
3479
                          self.conf.get('hidden', expand=True))
 
3480
 
 
3481
 
 
3482
class TestStackCrossSectionsExpand(tests.TestCaseWithTransport):
 
3483
 
 
3484
    def setUp(self):
 
3485
        super(TestStackCrossSectionsExpand, self).setUp()
 
3486
 
 
3487
    def get_config(self, location, string):
 
3488
        if string is None:
 
3489
            string = ''
 
3490
        # Since we don't save the config we won't strictly require to inherit
 
3491
        # from TestCaseInTempDir, but an error occurs so quickly...
 
3492
        c = config.LocationStack(location)
 
3493
        c.store._load_from_string(string)
 
3494
        return c
 
3495
 
 
3496
    def test_dont_cross_unrelated_section(self):
 
3497
        c = self.get_config('/another/branch/path','''
 
3498
[/one/branch/path]
 
3499
foo = hello
 
3500
bar = {foo}/2
 
3501
 
 
3502
[/another/branch/path]
 
3503
bar = {foo}/2
 
3504
''')
 
3505
        self.assertRaises(errors.ExpandingUnknownOption,
 
3506
                          c.get, 'bar', expand=True)
 
3507
 
 
3508
    def test_cross_related_sections(self):
 
3509
        c = self.get_config('/project/branch/path','''
 
3510
[/project]
 
3511
foo = qu
 
3512
 
 
3513
[/project/branch/path]
 
3514
bar = {foo}ux
 
3515
''')
 
3516
        self.assertEquals('quux', c.get('bar', expand=True))
 
3517
 
 
3518
 
3276
3519
class TestStackSet(TestStackWithTransport):
3277
3520
 
3278
3521
    def test_simple_set(self):