blob: cebd47a7d6c8d685cc2d92c03ddb33587aa40ff6 [file] [log] [blame]
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import unicode_literals
import sys
import unittest
from mozfile.mozfile import NamedTemporaryFile
from mach.config import (
AbsolutePathType,
BooleanType,
ConfigProvider,
ConfigSettings,
IntegerType,
PathType,
PositiveIntegerType,
RelativePathType,
StringType,
)
from mozunit import main
if sys.version_info[0] == 3:
str_type = str
else:
str_type = basestring
CONFIG1 = r"""
[foo]
bar = bar_value
baz = /baz/foo.c
"""
CONFIG2 = r"""
[foo]
bar = value2
"""
class Provider1(ConfigProvider):
@classmethod
def _register_settings(cls):
cls.register_setting('foo', 'bar', StringType)
cls.register_setting('foo', 'baz', AbsolutePathType)
Provider1.register_settings()
class ProviderDuplicate(ConfigProvider):
@classmethod
def _register_settings(cls):
cls.register_setting('dupesect', 'foo', StringType)
cls.register_setting('dupesect', 'foo', StringType)
class TestConfigProvider(unittest.TestCase):
def test_construct(self):
s = Provider1.config_settings
self.assertEqual(len(s), 1)
self.assertIn('foo', s)
self.assertEqual(len(s['foo']), 2)
self.assertIn('bar', s['foo'])
self.assertIn('baz', s['foo'])
def test_duplicate_option(self):
with self.assertRaises(Exception):
ProviderDuplicate.register_settings()
class Provider2(ConfigProvider):
@classmethod
def _register_settings(cls):
cls.register_setting('a', 'string', StringType)
cls.register_setting('a', 'boolean', BooleanType)
cls.register_setting('a', 'pos_int', PositiveIntegerType)
cls.register_setting('a', 'int', IntegerType)
cls.register_setting('a', 'abs_path', AbsolutePathType)
cls.register_setting('a', 'rel_path', RelativePathType)
cls.register_setting('a', 'path', PathType)
Provider2.register_settings()
class TestConfigSettings(unittest.TestCase):
def test_empty(self):
s = ConfigSettings()
self.assertEqual(len(s), 0)
self.assertNotIn('foo', s)
def test_simple(self):
s = ConfigSettings()
s.register_provider(Provider1)
self.assertEqual(len(s), 1)
self.assertIn('foo', s)
foo = s['foo']
foo = s.foo
self.assertEqual(len(foo), 2)
self.assertIn('bar', foo)
self.assertIn('baz', foo)
foo['bar'] = 'value1'
self.assertEqual(foo['bar'], 'value1')
self.assertEqual(foo['bar'], 'value1')
def test_assignment_validation(self):
s = ConfigSettings()
s.register_provider(Provider2)
a = s.a
# Assigning an undeclared setting raises.
with self.assertRaises(KeyError):
a.undefined = True
with self.assertRaises(KeyError):
a['undefined'] = True
# Basic type validation.
a.string = 'foo'
a.string = 'foo'
with self.assertRaises(TypeError):
a.string = False
a.boolean = True
a.boolean = False
with self.assertRaises(TypeError):
a.boolean = 'foo'
a.pos_int = 5
a.pos_int = 0
with self.assertRaises(ValueError):
a.pos_int = -1
with self.assertRaises(TypeError):
a.pos_int = 'foo'
a.int = 5
a.int = 0
a.int = -5
with self.assertRaises(TypeError):
a.int = 1.24
with self.assertRaises(TypeError):
a.int = 'foo'
a.abs_path = '/home/gps'
with self.assertRaises(ValueError):
a.abs_path = 'home/gps'
a.rel_path = 'home/gps'
a.rel_path = './foo/bar'
a.rel_path = 'foo.c'
with self.assertRaises(ValueError):
a.rel_path = '/foo/bar'
a.path = '/home/gps'
a.path = 'foo.c'
a.path = 'foo/bar'
a.path = './foo'
def test_retrieval_type(self):
s = ConfigSettings()
s.register_provider(Provider2)
a = s.a
a.string = 'foo'
a.boolean = True
a.pos_int = 12
a.int = -4
a.abs_path = '/home/gps'
a.rel_path = 'foo.c'
a.path = './foo/bar'
self.assertIsInstance(a.string, str_type)
self.assertIsInstance(a.boolean, bool)
self.assertIsInstance(a.pos_int, int)
self.assertIsInstance(a.int, int)
self.assertIsInstance(a.abs_path, str_type)
self.assertIsInstance(a.rel_path, str_type)
self.assertIsInstance(a.path, str_type)
def test_file_reading_single(self):
temp = NamedTemporaryFile(mode='wt')
temp.write(CONFIG1)
temp.flush()
s = ConfigSettings()
s.register_provider(Provider1)
s.load_file(temp.name)
self.assertEqual(s.foo.bar, 'bar_value')
def test_file_reading_multiple(self):
"""Loading multiple files has proper overwrite behavior."""
temp1 = NamedTemporaryFile(mode='wt')
temp1.write(CONFIG1)
temp1.flush()
temp2 = NamedTemporaryFile(mode='wt')
temp2.write(CONFIG2)
temp2.flush()
s = ConfigSettings()
s.register_provider(Provider1)
s.load_files([temp1.name, temp2.name])
self.assertEqual(s.foo.bar, 'value2')
def test_file_reading_missing(self):
"""Missing files should silently be ignored."""
s = ConfigSettings()
s.load_file('/tmp/foo.ini')
def test_file_writing(self):
s = ConfigSettings()
s.register_provider(Provider2)
s.a.string = 'foo'
s.a.boolean = False
temp = NamedTemporaryFile('wt')
s.write(temp)
temp.flush()
s2 = ConfigSettings()
s2.register_provider(Provider2)
s2.load_file(temp.name)
self.assertEqual(s.a.string, s2.a.string)
self.assertEqual(s.a.boolean, s2.a.boolean)
def test_write_pot(self):
s = ConfigSettings()
s.register_provider(Provider1)
s.register_provider(Provider2)
# Just a basic sanity test.
temp = NamedTemporaryFile('wt')
s.write_pot(temp)
temp.flush()
if __name__ == '__main__':
main()