~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_config.py

  • Committer: Martin Packman
  • Date: 2012-01-05 10:44:12 UTC
  • mfrom: (6424 +trunk)
  • mto: This revision was merged to the branch mainline in revision 6427.
  • Revision ID: martin.packman@canonical.com-20120105104412-z03fi9m43h946fvs
Merge bzr.dev to resolve conflicts

Show diffs side-by-side

added added

removed removed

Lines of Context:
144
144
config.test_stack_builder_registry.register('branch', build_branch_stack)
145
145
 
146
146
 
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)
157
157
 
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
537
537
 
538
538
    def test_log_format_default(self):
539
539
        my_config = config.Config()
540
 
        self.assertEqual('long', my_config.log_format())
 
540
        self.assertEqual('long',
 
541
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
542
                                              my_config.log_format))
541
543
 
542
544
    def test_acceptable_keys_default(self):
543
545
        my_config = config.Config()
1069
1071
si_g = 5g,
1070
1072
si_gb = 5gB,
1071
1073
""")
1072
 
        get_si = conf.get_user_option_as_int_from_SI
 
1074
        def get_si(s, default=None):
 
1075
            return self.applyDeprecated(
 
1076
                deprecated_in((2, 5, 0)),
 
1077
                conf.get_user_option_as_int_from_SI, s, default)
1073
1078
        self.assertEqual(100, get_si('plain'))
1074
1079
        self.assertEqual(5000, get_si('si_k'))
1075
1080
        self.assertEqual(5000, get_si('si_kb'))
1080
1085
        self.assertEqual(None, get_si('non-exist'))
1081
1086
        self.assertEqual(42, get_si('non-exist-with-default',  42))
1082
1087
 
 
1088
 
1083
1089
class TestSupressWarning(TestIniConfig):
1084
1090
 
1085
1091
    def make_warnings_config(self, s):
1317
1323
 
1318
1324
    def test_configured_logformat(self):
1319
1325
        my_config = self._get_sample_config()
1320
 
        self.assertEqual("short", my_config.log_format())
 
1326
        self.assertEqual("short",
 
1327
                         self.applyDeprecated(deprecated_in((2, 5, 0)),
 
1328
                                              my_config.log_format))
1321
1329
 
1322
1330
    def test_configured_acceptable_keys(self):
1323
1331
        my_config = self._get_sample_config()
2358
2366
class TestOptionConverterMixin(object):
2359
2367
 
2360
2368
    def assertConverted(self, expected, opt, value):
2361
 
        self.assertEquals(expected, opt.convert_from_unicode(value))
2362
 
 
2363
 
    def assertWarns(self, opt, value):
2364
 
        warnings = []
2365
 
        def warning(*args):
2366
 
            warnings.append(args[0] % args[1:])
2367
 
        self.overrideAttr(trace, 'warning', warning)
2368
 
        self.assertEquals(None, opt.convert_from_unicode(value))
2369
 
        self.assertLength(1, warnings)
2370
 
        self.assertEquals(
2371
 
            'Value "%s" is not valid for "%s"' % (value, opt.name),
2372
 
            warnings[0])
2373
 
 
2374
 
    def assertErrors(self, opt, value):
2375
 
        self.assertRaises(errors.ConfigOptionValueError,
2376
 
                          opt.convert_from_unicode, value)
2377
 
 
2378
 
    def assertConvertInvalid(self, opt, invalid_value):
2379
 
        opt.invalid = None
2380
 
        self.assertEquals(None, opt.convert_from_unicode(invalid_value))
2381
 
        opt.invalid = 'warning'
2382
 
        self.assertWarns(opt, invalid_value)
2383
 
        opt.invalid = 'error'
2384
 
        self.assertErrors(opt, invalid_value)
2385
 
 
2386
 
 
2387
 
class TestOptionWithBooleanConverter(tests.TestCase, TestOptionConverterMixin):
2388
 
 
2389
 
    def get_option(self):
2390
 
        return config.Option('foo', help='A boolean.',
2391
 
                             from_unicode=config.bool_from_store)
2392
 
 
2393
 
    def test_convert_invalid(self):
2394
 
        opt = self.get_option()
2395
 
        # A string that is not recognized as a boolean
2396
 
        self.assertConvertInvalid(opt, u'invalid-boolean')
2397
 
        # A list of strings is never recognized as a boolean
2398
 
        self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
2399
 
 
2400
 
    def test_convert_valid(self):
2401
 
        opt = self.get_option()
2402
 
        self.assertConverted(True, opt, u'True')
2403
 
        self.assertConverted(True, opt, u'1')
2404
 
        self.assertConverted(False, opt, u'False')
2405
 
 
2406
 
 
2407
 
class TestOptionWithIntegerConverter(tests.TestCase, TestOptionConverterMixin):
2408
 
 
2409
 
    def get_option(self):
2410
 
        return config.Option('foo', help='An integer.',
2411
 
                             from_unicode=config.int_from_store)
2412
 
 
2413
 
    def test_convert_invalid(self):
2414
 
        opt = self.get_option()
2415
 
        # A string that is not recognized as an integer
2416
 
        self.assertConvertInvalid(opt, u'forty-two')
2417
 
        # A list of strings is never recognized as an integer
2418
 
        self.assertConvertInvalid(opt, [u'a', u'list'])
2419
 
 
2420
 
    def test_convert_valid(self):
2421
 
        opt = self.get_option()
2422
 
        self.assertConverted(16, opt, u'16')
2423
 
 
2424
 
 
2425
 
class TestOptionWithListConverter(tests.TestCase, TestOptionConverterMixin):
2426
 
 
2427
 
    def get_option(self):
2428
 
        return config.Option('foo', help='A list.',
2429
 
                             from_unicode=config.list_from_store)
2430
 
 
2431
 
    def test_convert_invalid(self):
2432
 
        # No string is invalid as all forms can be converted to a list
2433
 
        pass
2434
 
 
2435
 
    def test_convert_valid(self):
2436
 
        opt = self.get_option()
2437
 
        # An empty string is an empty list
2438
 
        self.assertConverted([], opt, '') # Using a bare str() just in case
2439
 
        self.assertConverted([], opt, u'')
2440
 
        # A boolean
2441
 
        self.assertConverted([u'True'], opt, u'True')
2442
 
        # An integer
2443
 
        self.assertConverted([u'42'], opt, u'42')
2444
 
        # A single string
2445
 
        self.assertConverted([u'bar'], opt, u'bar')
2446
 
        # A list remains a list (configObj will turn a string containing commas
2447
 
        # into a list, but that's not what we're testing here)
2448
 
        self.assertConverted([u'foo', u'1', u'True'],
2449
 
                             opt, [u'foo', u'1', u'True'])
2450
 
 
2451
 
 
2452
 
class TestOptionConverterMixin(object):
2453
 
 
2454
 
    def assertConverted(self, expected, opt, value):
2455
 
        self.assertEquals(expected, opt.convert_from_unicode(value))
2456
 
 
2457
 
    def assertWarns(self, opt, value):
2458
 
        warnings = []
2459
 
        def warning(*args):
2460
 
            warnings.append(args[0] % args[1:])
2461
 
        self.overrideAttr(trace, 'warning', warning)
2462
 
        self.assertEquals(None, opt.convert_from_unicode(value))
2463
 
        self.assertLength(1, warnings)
2464
 
        self.assertEquals(
2465
 
            'Value "%s" is not valid for "%s"' % (value, opt.name),
2466
 
            warnings[0])
2467
 
 
2468
 
    def assertErrors(self, opt, value):
2469
 
        self.assertRaises(errors.ConfigOptionValueError,
2470
 
                          opt.convert_from_unicode, value)
2471
 
 
2472
 
    def assertConvertInvalid(self, opt, invalid_value):
2473
 
        opt.invalid = None
2474
 
        self.assertEquals(None, opt.convert_from_unicode(invalid_value))
2475
 
        opt.invalid = 'warning'
2476
 
        self.assertWarns(opt, invalid_value)
2477
 
        opt.invalid = 'error'
2478
 
        self.assertErrors(opt, invalid_value)
2479
 
 
2480
 
 
2481
 
class TestOptionWithBooleanConverter(tests.TestCase, TestOptionConverterMixin):
2482
 
 
2483
 
    def get_option(self):
2484
 
        return config.Option('foo', help='A boolean.',
2485
 
                             from_unicode=config.bool_from_store)
2486
 
 
2487
 
    def test_convert_invalid(self):
2488
 
        opt = self.get_option()
2489
 
        # A string that is not recognized as a boolean
2490
 
        self.assertConvertInvalid(opt, u'invalid-boolean')
2491
 
        # A list of strings is never recognized as a boolean
2492
 
        self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
2493
 
 
2494
 
    def test_convert_valid(self):
2495
 
        opt = self.get_option()
2496
 
        self.assertConverted(True, opt, u'True')
2497
 
        self.assertConverted(True, opt, u'1')
2498
 
        self.assertConverted(False, opt, u'False')
2499
 
 
2500
 
 
2501
 
class TestOptionWithIntegerConverter(tests.TestCase, TestOptionConverterMixin):
2502
 
 
2503
 
    def get_option(self):
2504
 
        return config.Option('foo', help='An integer.',
2505
 
                             from_unicode=config.int_from_store)
2506
 
 
2507
 
    def test_convert_invalid(self):
2508
 
        opt = self.get_option()
2509
 
        # A string that is not recognized as an integer
2510
 
        self.assertConvertInvalid(opt, u'forty-two')
2511
 
        # A list of strings is never recognized as an integer
2512
 
        self.assertConvertInvalid(opt, [u'a', u'list'])
2513
 
 
2514
 
    def test_convert_valid(self):
2515
 
        opt = self.get_option()
2516
 
        self.assertConverted(16, opt, u'16')
2517
 
 
2518
 
 
2519
 
class TestOptionWithListConverter(tests.TestCase, TestOptionConverterMixin):
2520
 
 
2521
 
    def get_option(self):
2522
 
        return config.Option('foo', help='A list.',
2523
 
                             from_unicode=config.list_from_store)
 
2369
        self.assertEquals(expected, opt.convert_from_unicode(None, value))
 
2370
 
 
2371
    def assertWarns(self, opt, value):
 
2372
        warnings = []
 
2373
        def warning(*args):
 
2374
            warnings.append(args[0] % args[1:])
 
2375
        self.overrideAttr(trace, 'warning', warning)
 
2376
        self.assertEquals(None, opt.convert_from_unicode(None, value))
 
2377
        self.assertLength(1, warnings)
 
2378
        self.assertEquals(
 
2379
            'Value "%s" is not valid for "%s"' % (value, opt.name),
 
2380
            warnings[0])
 
2381
 
 
2382
    def assertErrors(self, opt, value):
 
2383
        self.assertRaises(errors.ConfigOptionValueError,
 
2384
                          opt.convert_from_unicode, None, value)
 
2385
 
 
2386
    def assertConvertInvalid(self, opt, invalid_value):
 
2387
        opt.invalid = None
 
2388
        self.assertEquals(None, opt.convert_from_unicode(None, invalid_value))
 
2389
        opt.invalid = 'warning'
 
2390
        self.assertWarns(opt, invalid_value)
 
2391
        opt.invalid = 'error'
 
2392
        self.assertErrors(opt, invalid_value)
 
2393
 
 
2394
 
 
2395
class TestOptionWithBooleanConverter(tests.TestCase, TestOptionConverterMixin):
 
2396
 
 
2397
    def get_option(self):
 
2398
        return config.Option('foo', help='A boolean.',
 
2399
                             from_unicode=config.bool_from_store)
 
2400
 
 
2401
    def test_convert_invalid(self):
 
2402
        opt = self.get_option()
 
2403
        # A string that is not recognized as a boolean
 
2404
        self.assertConvertInvalid(opt, u'invalid-boolean')
 
2405
        # A list of strings is never recognized as a boolean
 
2406
        self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
 
2407
 
 
2408
    def test_convert_valid(self):
 
2409
        opt = self.get_option()
 
2410
        self.assertConverted(True, opt, u'True')
 
2411
        self.assertConverted(True, opt, u'1')
 
2412
        self.assertConverted(False, opt, u'False')
 
2413
 
 
2414
 
 
2415
class TestOptionWithIntegerConverter(tests.TestCase, TestOptionConverterMixin):
 
2416
 
 
2417
    def get_option(self):
 
2418
        return config.Option('foo', help='An integer.',
 
2419
                             from_unicode=config.int_from_store)
 
2420
 
 
2421
    def test_convert_invalid(self):
 
2422
        opt = self.get_option()
 
2423
        # A string that is not recognized as an integer
 
2424
        self.assertConvertInvalid(opt, u'forty-two')
 
2425
        # A list of strings is never recognized as an integer
 
2426
        self.assertConvertInvalid(opt, [u'a', u'list'])
 
2427
 
 
2428
    def test_convert_valid(self):
 
2429
        opt = self.get_option()
 
2430
        self.assertConverted(16, opt, u'16')
 
2431
 
 
2432
 
 
2433
class TestOptionWithSIUnitConverter(tests.TestCase, TestOptionConverterMixin):
 
2434
 
 
2435
    def get_option(self):
 
2436
        return config.Option('foo', help='An integer in SI units.',
 
2437
                             from_unicode=config.int_SI_from_store)
 
2438
 
 
2439
    def test_convert_invalid(self):
 
2440
        opt = self.get_option()
 
2441
        self.assertConvertInvalid(opt, u'not-a-unit')
 
2442
        self.assertConvertInvalid(opt, u'Gb') # Forgot the int
 
2443
        self.assertConvertInvalid(opt, u'1b') # Forgot the unit
 
2444
        self.assertConvertInvalid(opt, u'1GG')
 
2445
        self.assertConvertInvalid(opt, u'1Mbb')
 
2446
        self.assertConvertInvalid(opt, u'1MM')
 
2447
 
 
2448
    def test_convert_valid(self):
 
2449
        opt = self.get_option()
 
2450
        self.assertConverted(int(5e3), opt, u'5kb')
 
2451
        self.assertConverted(int(5e6), opt, u'5M')
 
2452
        self.assertConverted(int(5e6), opt, u'5MB')
 
2453
        self.assertConverted(int(5e9), opt, u'5g')
 
2454
        self.assertConverted(int(5e9), opt, u'5gB')
 
2455
        self.assertConverted(100, opt, u'100')
 
2456
 
 
2457
 
 
2458
class TestListOption(tests.TestCase, TestOptionConverterMixin):
 
2459
 
 
2460
    def get_option(self):
 
2461
        return config.ListOption('foo', help='A list.')
2524
2462
 
2525
2463
    def test_convert_invalid(self):
2526
2464
        opt = self.get_option()
2676
2614
    def setUp(self):
2677
2615
        super(TestCommandLineStore, self).setUp()
2678
2616
        self.store = config.CommandLineStore()
 
2617
        self.overrideAttr(config, 'option_registry', config.OptionRegistry())
2679
2618
 
2680
2619
    def get_section(self):
2681
2620
        """Get the unique section for the command line overrides."""
2696
2635
        self.assertEqual('b', section.get('a'))
2697
2636
 
2698
2637
    def test_list_override(self):
 
2638
        opt = config.ListOption('l')
 
2639
        config.option_registry.register(opt)
2699
2640
        self.store._from_cmdline(['l=1,2,3'])
2700
2641
        val = self.get_section().get('l')
2701
2642
        self.assertEqual('1,2,3', val)
2702
2643
        # Reminder: lists should be registered as such explicitely, otherwise
2703
2644
        # the conversion needs to be done afterwards.
2704
 
        self.assertEqual(['1', '2', '3'], config.list_from_store(val))
 
2645
        self.assertEqual(['1', '2', '3'],
 
2646
                         opt.convert_from_unicode(self.store, val))
2705
2647
 
2706
2648
    def test_multiple_overrides(self):
2707
2649
        self.store._from_cmdline(['a=b', 'x=y'])
2713
2655
        self.assertRaises(errors.BzrCommandError,
2714
2656
                          self.store._from_cmdline, ['a=b', 'c'])
2715
2657
 
 
2658
class TestStoreMinimalAPI(tests.TestCaseWithTransport):
 
2659
 
 
2660
    scenarios = [(key, {'get_store': builder}) for key, builder
 
2661
                 in config.test_store_builder_registry.iteritems()] + [
 
2662
        ('cmdline', {'get_store': lambda test: config.CommandLineStore()})]
 
2663
 
 
2664
    def test_id(self):
 
2665
        store = self.get_store(self)
 
2666
        if type(store) == config.TransportIniFileStore:
 
2667
            raise tests.TestNotApplicable(
 
2668
                "%s is not a concrete Store implementation"
 
2669
                " so it doesn't need an id" % (store.__class__.__name__,))
 
2670
        self.assertIsNot(None, store.id)
 
2671
 
2716
2672
 
2717
2673
class TestStore(tests.TestCaseWithTransport):
2718
2674
 
2761
2717
        self.assertRaises(AssertionError, store._load_from_string, 'bar=baz')
2762
2718
 
2763
2719
 
 
2720
class TestStoreQuoting(TestStore):
 
2721
 
 
2722
    scenarios = [(key, {'get_store': builder}) for key, builder
 
2723
                 in config.test_store_builder_registry.iteritems()]
 
2724
 
 
2725
    def setUp(self):
 
2726
        super(TestStoreQuoting, self).setUp()
 
2727
        self.store = self.get_store(self)
 
2728
        # We need a loaded store but any content will do
 
2729
        self.store._load_from_string('')
 
2730
 
 
2731
    def assertIdempotent(self, s):
 
2732
        """Assert that quoting an unquoted string is a no-op and vice-versa.
 
2733
 
 
2734
        What matters here is that option values, as they appear in a store, can
 
2735
        be safely round-tripped out of the store and back.
 
2736
 
 
2737
        :param s: A string, quoted if required.
 
2738
        """
 
2739
        self.assertEquals(s, self.store.quote(self.store.unquote(s)))
 
2740
        self.assertEquals(s, self.store.unquote(self.store.quote(s)))
 
2741
 
 
2742
    def test_empty_string(self):
 
2743
        if isinstance(self.store, config.IniFileStore):
 
2744
            # configobj._quote doesn't handle empty values
 
2745
            self.assertRaises(AssertionError,
 
2746
                              self.assertIdempotent, '')
 
2747
        else:
 
2748
            self.assertIdempotent('')
 
2749
        # But quoted empty strings are ok
 
2750
        self.assertIdempotent('""')
 
2751
 
 
2752
    def test_embedded_spaces(self):
 
2753
        self.assertIdempotent('" a b c "')
 
2754
 
 
2755
    def test_embedded_commas(self):
 
2756
        self.assertIdempotent('" a , b c "')
 
2757
 
 
2758
    def test_simple_comma(self):
 
2759
        if isinstance(self.store, config.IniFileStore):
 
2760
            # configobj requires that lists are special-cased
 
2761
           self.assertRaises(AssertionError,
 
2762
                             self.assertIdempotent, ',')
 
2763
        else:
 
2764
            self.assertIdempotent(',')
 
2765
        # When a single comma is required, quoting is also required
 
2766
        self.assertIdempotent('","')
 
2767
 
 
2768
    def test_list(self):
 
2769
        if isinstance(self.store, config.IniFileStore):
 
2770
            # configobj requires that lists are special-cased
 
2771
            self.assertRaises(AssertionError,
 
2772
                              self.assertIdempotent, 'a,b')
 
2773
        else:
 
2774
            self.assertIdempotent('a,b')
 
2775
 
 
2776
 
 
2777
class TestDictFromStore(tests.TestCase):
 
2778
 
 
2779
    def test_unquote_not_string(self):
 
2780
        conf = config.MemoryStack('x=2\n[a_section]\na=1\n')
 
2781
        value = conf.get('a_section')
 
2782
        # Urgh, despite 'conf' asking for the no-name section, we get the
 
2783
        # content of another section as a dict o_O
 
2784
        self.assertEquals({'a': '1'}, value)
 
2785
        unquoted = conf.store.unquote(value)
 
2786
        # Which cannot be unquoted but shouldn't crash either (the use cases
 
2787
        # are getting the value or displaying it. In the later case, '%s' will
 
2788
        # do).
 
2789
        self.assertEquals({'a': '1'}, unquoted)
 
2790
        self.assertEquals("{u'a': u'1'}", '%s' % (unquoted,))
 
2791
 
 
2792
 
2764
2793
class TestIniFileStoreContent(tests.TestCaseWithTransport):
2765
2794
    """Simulate loading a config store with content of various encodings.
2766
2795
 
2972
3001
        self.assertEquals((store,), calls[0])
2973
3002
 
2974
3003
 
 
3004
class TestQuotingIniFileStore(tests.TestCaseWithTransport):
 
3005
 
 
3006
    def get_store(self):
 
3007
        return config.TransportIniFileStore(self.get_transport(), 'foo.conf')
 
3008
 
 
3009
    def test_get_quoted_string(self):
 
3010
        store = self.get_store()
 
3011
        store._load_from_string('foo= " abc "')
 
3012
        stack = config.Stack([store.get_sections])
 
3013
        self.assertEquals(' abc ', stack.get('foo'))
 
3014
 
 
3015
    def test_set_quoted_string(self):
 
3016
        store = self.get_store()
 
3017
        stack = config.Stack([store.get_sections], store)
 
3018
        stack.set('foo', ' a b c ')
 
3019
        store.save()
 
3020
        self.assertFileEqual('foo = " a b c "' + os.linesep, 'foo.conf')
 
3021
 
 
3022
 
2975
3023
class TestTransportIniFileStore(TestStore):
2976
3024
 
2977
3025
    def test_loading_unknown_file_fails(self):
3321
3369
        self.assertLength(0, sections)
3322
3370
 
3323
3371
 
3324
 
class TestStackGet(tests.TestCase):
3325
 
 
3326
 
    # FIXME: This should be parametrized for all known Stack or dedicated
3327
 
    # paramerized tests created to avoid bloating -- vila 2011-03-31
3328
 
 
3329
 
    def overrideOptionRegistry(self):
 
3372
class TestBaseStackGet(tests.TestCase):
 
3373
 
 
3374
    def setUp(self):
 
3375
        super(TestBaseStackGet, self).setUp()
3330
3376
        self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3331
3377
 
3332
 
    def test_single_config_get(self):
3333
 
        conf = dict(foo='bar')
3334
 
        conf_stack = config.Stack([conf])
3335
 
        self.assertEquals('bar', conf_stack.get('foo'))
 
3378
    def test_get_first_definition(self):
 
3379
        store1 = config.IniFileStore()
 
3380
        store1._load_from_string('foo=bar')
 
3381
        store2 = config.IniFileStore()
 
3382
        store2._load_from_string('foo=baz')
 
3383
        conf = config.Stack([store1.get_sections, store2.get_sections])
 
3384
        self.assertEquals('bar', conf.get('foo'))
3336
3385
 
3337
3386
    def test_get_with_registered_default_value(self):
3338
 
        conf_stack = config.Stack([dict()])
3339
 
        opt = config.Option('foo', default='bar')
3340
 
        self.overrideOptionRegistry()
3341
 
        config.option_registry.register('foo', opt)
 
3387
        config.option_registry.register(config.Option('foo', default='bar'))
 
3388
        conf_stack = config.Stack([])
3342
3389
        self.assertEquals('bar', conf_stack.get('foo'))
3343
3390
 
3344
3391
    def test_get_without_registered_default_value(self):
3345
 
        conf_stack = config.Stack([dict()])
3346
 
        opt = config.Option('foo')
3347
 
        self.overrideOptionRegistry()
3348
 
        config.option_registry.register('foo', opt)
 
3392
        config.option_registry.register(config.Option('foo'))
 
3393
        conf_stack = config.Stack([])
3349
3394
        self.assertEquals(None, conf_stack.get('foo'))
3350
3395
 
3351
3396
    def test_get_without_default_value_for_not_registered(self):
3352
 
        conf_stack = config.Stack([dict()])
3353
 
        opt = config.Option('foo')
3354
 
        self.overrideOptionRegistry()
 
3397
        conf_stack = config.Stack([])
3355
3398
        self.assertEquals(None, conf_stack.get('foo'))
3356
3399
 
3357
 
    def test_get_first_definition(self):
3358
 
        conf1 = dict(foo='bar')
3359
 
        conf2 = dict(foo='baz')
3360
 
        conf_stack = config.Stack([conf1, conf2])
3361
 
        self.assertEquals('bar', conf_stack.get('foo'))
3362
 
 
3363
 
    def test_get_embedded_definition(self):
3364
 
        conf1 = dict(yy='12')
3365
 
        conf2 = config.Stack([dict(xx='42'), dict(foo='baz')])
3366
 
        conf_stack = config.Stack([conf1, conf2])
3367
 
        self.assertEquals('baz', conf_stack.get('foo'))
3368
 
 
3369
3400
    def test_get_for_empty_section_callable(self):
3370
3401
        conf_stack = config.Stack([lambda : []])
3371
3402
        self.assertEquals(None, conf_stack.get('foo'))
3372
3403
 
3373
3404
    def test_get_for_broken_callable(self):
3374
3405
        # Trying to use and invalid callable raises an exception on first use
3375
 
        conf_stack = config.Stack([lambda : object()])
 
3406
        conf_stack = config.Stack([object])
3376
3407
        self.assertRaises(TypeError, conf_stack.get, 'foo')
3377
3408
 
3378
3409
 
 
3410
class TestStackWithSimpleStore(tests.TestCase):
 
3411
 
 
3412
    def setUp(self):
 
3413
        super(TestStackWithSimpleStore, self).setUp()
 
3414
        self.overrideAttr(config, 'option_registry', config.OptionRegistry())
 
3415
        self.registry = config.option_registry
 
3416
 
 
3417
    def get_conf(self, content=None):
 
3418
        return config.MemoryStack(content)
 
3419
 
 
3420
    def test_override_value_from_env(self):
 
3421
        self.registry.register(
 
3422
            config.Option('foo', default='bar', override_from_env=['FOO']))
 
3423
        self.overrideEnv('FOO', 'quux')
 
3424
        # Env variable provides a default taking over the option one
 
3425
        conf = self.get_conf('foo=store')
 
3426
        self.assertEquals('quux', conf.get('foo'))
 
3427
 
 
3428
    def test_first_override_value_from_env_wins(self):
 
3429
        self.registry.register(
 
3430
            config.Option('foo', default='bar',
 
3431
                          override_from_env=['NO_VALUE', 'FOO', 'BAZ']))
 
3432
        self.overrideEnv('FOO', 'foo')
 
3433
        self.overrideEnv('BAZ', 'baz')
 
3434
        # The first env var set wins
 
3435
        conf = self.get_conf('foo=store')
 
3436
        self.assertEquals('foo', conf.get('foo'))
 
3437
 
 
3438
 
 
3439
class TestMemoryStack(tests.TestCase):
 
3440
 
 
3441
    def test_get(self):
 
3442
        conf = config.MemoryStack('foo=bar')
 
3443
        self.assertEquals('bar', conf.get('foo'))
 
3444
 
 
3445
    def test_set(self):
 
3446
        conf = config.MemoryStack('foo=bar')
 
3447
        conf.set('foo', 'baz')
 
3448
        self.assertEquals('baz', conf.get('foo'))
 
3449
 
 
3450
    def test_no_content(self):
 
3451
        conf = config.MemoryStack()
 
3452
        # No content means no loading
 
3453
        self.assertFalse(conf.store.is_loaded())
 
3454
        self.assertRaises(NotImplementedError, conf.get, 'foo')
 
3455
        # But a content can still be provided
 
3456
        conf.store._load_from_string('foo=bar')
 
3457
        self.assertEquals('bar', conf.get('foo'))
 
3458
 
 
3459
 
3379
3460
class TestStackWithTransport(tests.TestCaseWithTransport):
3380
3461
 
3381
3462
    scenarios = [(key, {'get_stack': builder}) for key, builder
3411
3492
        self.assertEquals((self.conf, 'foo', 'bar'), calls[0])
3412
3493
 
3413
3494
 
3414
 
class TestStackGetWithConverter(tests.TestCaseWithTransport):
 
3495
class TestStackGetWithConverter(tests.TestCase):
3415
3496
 
3416
3497
    def setUp(self):
3417
3498
        super(TestStackGetWithConverter, self).setUp()
3418
3499
        self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3419
3500
        self.registry = config.option_registry
3420
 
        # We just want a simple stack with a simple store so we can inject
3421
 
        # whatever content the tests need without caring about what section
3422
 
        # names are valid for a given store/stack.
3423
 
        store = config.TransportIniFileStore(self.get_transport(), 'foo.conf')
3424
 
        self.conf = config.Stack([store.get_sections], store)
 
3501
 
 
3502
    def get_conf(self, content=None):
 
3503
        return config.MemoryStack(content)
3425
3504
 
3426
3505
    def register_bool_option(self, name, default=None, default_from_env=None):
3427
3506
        b = config.Option(name, help='A boolean.',
3431
3510
 
3432
3511
    def test_get_default_bool_None(self):
3433
3512
        self.register_bool_option('foo')
3434
 
        self.assertEquals(None, self.conf.get('foo'))
 
3513
        conf = self.get_conf('')
 
3514
        self.assertEquals(None, conf.get('foo'))
3435
3515
 
3436
3516
    def test_get_default_bool_True(self):
3437
3517
        self.register_bool_option('foo', u'True')
3438
 
        self.assertEquals(True, self.conf.get('foo'))
 
3518
        conf = self.get_conf('')
 
3519
        self.assertEquals(True, conf.get('foo'))
3439
3520
 
3440
3521
    def test_get_default_bool_False(self):
3441
3522
        self.register_bool_option('foo', False)
3442
 
        self.assertEquals(False, self.conf.get('foo'))
 
3523
        conf = self.get_conf('')
 
3524
        self.assertEquals(False, conf.get('foo'))
3443
3525
 
3444
3526
    def test_get_default_bool_False_as_string(self):
3445
3527
        self.register_bool_option('foo', u'False')
3446
 
        self.assertEquals(False, self.conf.get('foo'))
 
3528
        conf = self.get_conf('')
 
3529
        self.assertEquals(False, conf.get('foo'))
3447
3530
 
3448
3531
    def test_get_default_bool_from_env_converted(self):
3449
3532
        self.register_bool_option('foo', u'True', default_from_env=['FOO'])
3450
3533
        self.overrideEnv('FOO', 'False')
3451
 
        self.assertEquals(False, self.conf.get('foo'))
 
3534
        conf = self.get_conf('')
 
3535
        self.assertEquals(False, conf.get('foo'))
3452
3536
 
3453
3537
    def test_get_default_bool_when_conversion_fails(self):
3454
3538
        self.register_bool_option('foo', default='True')
3455
 
        self.conf.store._load_from_string('foo=invalid boolean')
3456
 
        self.assertEquals(True, self.conf.get('foo'))
 
3539
        conf = self.get_conf('foo=invalid boolean')
 
3540
        self.assertEquals(True, conf.get('foo'))
3457
3541
 
3458
3542
    def register_integer_option(self, name,
3459
3543
                                default=None, default_from_env=None):
3464
3548
 
3465
3549
    def test_get_default_integer_None(self):
3466
3550
        self.register_integer_option('foo')
3467
 
        self.assertEquals(None, self.conf.get('foo'))
 
3551
        conf = self.get_conf('')
 
3552
        self.assertEquals(None, conf.get('foo'))
3468
3553
 
3469
3554
    def test_get_default_integer(self):
3470
3555
        self.register_integer_option('foo', 42)
3471
 
        self.assertEquals(42, self.conf.get('foo'))
 
3556
        conf = self.get_conf('')
 
3557
        self.assertEquals(42, conf.get('foo'))
3472
3558
 
3473
3559
    def test_get_default_integer_as_string(self):
3474
3560
        self.register_integer_option('foo', u'42')
3475
 
        self.assertEquals(42, self.conf.get('foo'))
 
3561
        conf = self.get_conf('')
 
3562
        self.assertEquals(42, conf.get('foo'))
3476
3563
 
3477
3564
    def test_get_default_integer_from_env(self):
3478
3565
        self.register_integer_option('foo', default_from_env=['FOO'])
3479
3566
        self.overrideEnv('FOO', '18')
3480
 
        self.assertEquals(18, self.conf.get('foo'))
 
3567
        conf = self.get_conf('')
 
3568
        self.assertEquals(18, conf.get('foo'))
3481
3569
 
3482
3570
    def test_get_default_integer_when_conversion_fails(self):
3483
3571
        self.register_integer_option('foo', default='12')
3484
 
        self.conf.store._load_from_string('foo=invalid integer')
3485
 
        self.assertEquals(12, self.conf.get('foo'))
 
3572
        conf = self.get_conf('foo=invalid integer')
 
3573
        self.assertEquals(12, conf.get('foo'))
3486
3574
 
3487
3575
    def register_list_option(self, name, default=None, default_from_env=None):
3488
 
        l = config.Option(name, help='A list.',
3489
 
                          default=default, default_from_env=default_from_env,
3490
 
                          from_unicode=config.list_from_store)
 
3576
        l = config.ListOption(name, help='A list.', default=default,
 
3577
                              default_from_env=default_from_env)
3491
3578
        self.registry.register(l)
3492
3579
 
3493
3580
    def test_get_default_list_None(self):
3494
3581
        self.register_list_option('foo')
3495
 
        self.assertEquals(None, self.conf.get('foo'))
 
3582
        conf = self.get_conf('')
 
3583
        self.assertEquals(None, conf.get('foo'))
3496
3584
 
3497
3585
    def test_get_default_list_empty(self):
3498
3586
        self.register_list_option('foo', '')
3499
 
        self.assertEquals([], self.conf.get('foo'))
 
3587
        conf = self.get_conf('')
 
3588
        self.assertEquals([], conf.get('foo'))
3500
3589
 
3501
3590
    def test_get_default_list_from_env(self):
3502
3591
        self.register_list_option('foo', default_from_env=['FOO'])
3503
3592
        self.overrideEnv('FOO', '')
3504
 
        self.assertEquals([], self.conf.get('foo'))
 
3593
        conf = self.get_conf('')
 
3594
        self.assertEquals([], conf.get('foo'))
3505
3595
 
3506
3596
    def test_get_with_list_converter_no_item(self):
3507
3597
        self.register_list_option('foo', None)
3508
 
        self.conf.store._load_from_string('foo=,')
3509
 
        self.assertEquals([], self.conf.get('foo'))
 
3598
        conf = self.get_conf('foo=,')
 
3599
        self.assertEquals([], conf.get('foo'))
3510
3600
 
3511
3601
    def test_get_with_list_converter_many_items(self):
3512
3602
        self.register_list_option('foo', None)
3513
 
        self.conf.store._load_from_string('foo=m,o,r,e')
3514
 
        self.assertEquals(['m', 'o', 'r', 'e'], self.conf.get('foo'))
 
3603
        conf = self.get_conf('foo=m,o,r,e')
 
3604
        self.assertEquals(['m', 'o', 'r', 'e'], conf.get('foo'))
3515
3605
 
3516
3606
    def test_get_with_list_converter_embedded_spaces_many_items(self):
3517
3607
        self.register_list_option('foo', None)
3518
 
        self.conf.store._load_from_string('foo=" bar", "baz "')
3519
 
        self.assertEquals([' bar', 'baz '], self.conf.get('foo'))
 
3608
        conf = self.get_conf('foo=" bar", "baz "')
 
3609
        self.assertEquals([' bar', 'baz '], conf.get('foo'))
3520
3610
 
3521
3611
    def test_get_with_list_converter_stripped_spaces_many_items(self):
3522
3612
        self.register_list_option('foo', None)
3523
 
        self.conf.store._load_from_string('foo= bar ,  baz ')
3524
 
        self.assertEquals(['bar', 'baz'], self.conf.get('foo'))
 
3613
        conf = self.get_conf('foo= bar ,  baz ')
 
3614
        self.assertEquals(['bar', 'baz'], conf.get('foo'))
3525
3615
 
3526
3616
 
3527
3617
class TestIterOptionRefs(tests.TestCase):
3640
3730
list={foo},{bar},{baz}
3641
3731
''')
3642
3732
        self.registry.register(
3643
 
            config.Option('list', from_unicode=config.list_from_store))
 
3733
            config.ListOption('list'))
3644
3734
        self.assertEquals(['start', 'middle', 'end'],
3645
3735
                           self.conf.get('list', expand=True))
3646
3736
 
3652
3742
list={foo}
3653
3743
''')
3654
3744
        self.registry.register(
3655
 
            config.Option('list', from_unicode=config.list_from_store))
 
3745
            config.ListOption('list'))
3656
3746
        self.assertEquals(['start', 'middle', 'end'],
3657
3747
                           self.conf.get('list', expand=True))
3658
3748
 
3667
3757
''')
3668
3758
        # What matters is what the registration says, the conversion happens
3669
3759
        # only after all expansions have been performed
3670
 
        self.registry.register(
3671
 
            config.Option('hidden', from_unicode=config.list_from_store))
 
3760
        self.registry.register(config.ListOption('hidden'))
3672
3761
        self.assertEquals(['bin', 'go'],
3673
3762
                          self.conf.get('hidden', expand=True))
3674
3763
 
4559
4648
class EmailOptionTests(tests.TestCase):
4560
4649
 
4561
4650
    def test_default_email_uses_BZR_EMAIL(self):
 
4651
        conf = config.MemoryStack('email=jelmer@debian.org')
4562
4652
        # BZR_EMAIL takes precedence over EMAIL
4563
4653
        self.overrideEnv('BZR_EMAIL', 'jelmer@samba.org')
4564
4654
        self.overrideEnv('EMAIL', 'jelmer@apache.org')
4565
 
        self.assertEquals('jelmer@samba.org', config.default_email())
 
4655
        self.assertEquals('jelmer@samba.org', conf.get('email'))
4566
4656
 
4567
4657
    def test_default_email_uses_EMAIL(self):
 
4658
        conf = config.MemoryStack('')
4568
4659
        self.overrideEnv('BZR_EMAIL', None)
4569
4660
        self.overrideEnv('EMAIL', 'jelmer@apache.org')
4570
 
        self.assertEquals('jelmer@apache.org', config.default_email())
 
4661
        self.assertEquals('jelmer@apache.org', conf.get('email'))
4571
4662
 
4572
4663
    def test_BZR_EMAIL_overrides(self):
 
4664
        conf = config.MemoryStack('email=jelmer@debian.org')
4573
4665
        self.overrideEnv('BZR_EMAIL', 'jelmer@apache.org')
4574
 
        self.assertEquals('jelmer@apache.org',
4575
 
            config.email_from_store('jelmer@debian.org'))
 
4666
        self.assertEquals('jelmer@apache.org', conf.get('email'))
4576
4667
        self.overrideEnv('BZR_EMAIL', None)
4577
4668
        self.overrideEnv('EMAIL', 'jelmer@samba.org')
4578
 
        self.assertEquals('jelmer@debian.org',
4579
 
            config.email_from_store('jelmer@debian.org'))
 
4669
        self.assertEquals('jelmer@debian.org', conf.get('email'))