Skip to content

Commit

Permalink
Merge 0d8a612 into 99eb0d4
Browse files Browse the repository at this point in the history
  • Loading branch information
Coffeemaker committed Jan 4, 2016
2 parents 99eb0d4 + 0d8a612 commit 5c37ce3
Show file tree
Hide file tree
Showing 2 changed files with 179 additions and 4 deletions.
150 changes: 150 additions & 0 deletions test/test_torconfig.py
Expand Up @@ -166,6 +166,47 @@ def test_boolean_parser(self):
self.assertTrue(conf.foo is False)
self.assertTrue(conf.bar is True)

def test_save_boolean(self):
self.protocol.answers.append('config/names=\nfoo Boolean\nbar Boolean')
self.protocol.answers.append({'foo': '0'})
self.protocol.answers.append({'bar': '1'})

conf = TorConfig(self.protocol)

# save some boolean value
conf.foo = True
conf.bar = False
conf.save()
self.assertEqual(set(self.protocol.sets),
set([('foo', 1), ('bar', 0)]))

def test_read_boolean_after_save(self):
self.protocol.answers.append('config/names=\nfoo Boolean\nbar Boolean')
self.protocol.answers.append({'foo': '0'})
self.protocol.answers.append({'bar': '1'})

conf = TorConfig(self.protocol)

# save some boolean value
conf.foo = True
conf.bar = False
conf.save()
self.assertTrue(conf.foo is True, msg="foo not True: %s" % conf.foo)
self.assertTrue(conf.bar is False, msg="bar not False: %s" % conf.bar)

def test_save_boolean_with_strange_values(self):
self.protocol.answers.append('config/names=\nfoo Boolean\nbar Boolean')
self.protocol.answers.append({'foo': '0'})
self.protocol.answers.append({'bar': '1'})

conf = TorConfig(self.protocol)
# save some non-boolean value
conf.foo = "Something True"
conf.bar = 0
conf.save()
self.assertEqual(set(self.protocol.sets),
set([('foo', 1), ('bar', 0)]))

def test_boolean_auto_parser(self):
self.protocol.answers.append(
'config/names=\nfoo Boolean+Auto\nbar Boolean+Auto\nbaz Boolean+Auto'
Expand All @@ -179,6 +220,48 @@ def test_boolean_auto_parser(self):
self.assertTrue(conf.bar is 1)
self.assertTrue(conf.baz is -1)

def test_save_boolean_auto(self):
self.protocol.answers.append(
'config/names=\nfoo Boolean+Auto\nbar Boolean+Auto\nbaz Boolean+Auto\nqux Boolean+Auto'
)
self.protocol.answers.append({'foo': '1'})
self.protocol.answers.append({'bar': '1'})
self.protocol.answers.append({'baz': '1'})
self.protocol.answers.append({'qux': '1'})

conf = TorConfig(self.protocol)
conf.foo = 1
conf.bar = 0
conf.baz = True
conf.qux = -1
conf.save()
self.assertEqual(set(self.protocol.sets),
set([('foo', 1),
('bar', 0),
('baz', 1),
('qux', 'auto')]))
self.assertTrue(conf.foo is 1)
self.assertTrue(conf.bar is 0)
self.assertTrue(conf.baz is 1)
self.assertTrue(conf.qux is -1)

def test_save_invalid_boolean_auto(self):
self.protocol.answers.append(
'config/names=\nfoo Boolean+Auto'
)
self.protocol.answers.append({'foo': '1'})

conf = TorConfig(self.protocol)
for value in ('auto', 'True', 'False', None):
try:
conf.foo = value
except (ValueError, TypeError):
pass
else:
self.fail("Invalid value '%s' allowed" % value)
conf.save()
self.assertEqual(self.protocol.sets, [])

def test_string_parser(self):
self.protocol.answers.append('config/names=\nfoo String')
self.protocol.answers.append({'foo': 'bar'})
Expand All @@ -191,6 +274,39 @@ def test_int_parser(self):
conf = TorConfig(self.protocol)
self.assertEqual(conf.foo, 123)

def test_int_validator(self):
self.protocol.answers.append('config/names=\nfoo Integer')
self.protocol.answers.append({'foo': '123'})
conf = TorConfig(self.protocol)

conf.foo = 2.33
conf.save()
self.assertEqual(conf.foo, 2)

conf.foo = '1'
conf.save()
self.assertEqual(conf.foo, 1)

conf.foo = '-100'
conf.save()
self.assertEqual(conf.foo, -100)

conf.foo = 0
conf.save()
self.assertEqual(conf.foo, 0)

conf.foo = '0'
conf.save()
self.assertEqual(conf.foo, 0)

for value in ('no', 'Not a value', None):
try:
conf.foo = value
except (ValueError, TypeError):
pass
else:
self.fail("No excpetion thrown")

def test_int_parser_error(self):
self.protocol.answers.append('config/names=\nfoo Integer')
self.protocol.answers.append({'foo': '123foo'})
Expand Down Expand Up @@ -603,6 +719,40 @@ def test_conf_changed(self):
self.assertEqual(config.Foo, 'bar')
self.assertEqual(config.Bar, DEFAULT_VALUE)

def test_conf_changed_parsed(self):
'''
Create a configuration which holds boolean types. These types
have to be parsed as booleans.
'''
protocol = FakeControlProtocol([])
protocol.answers.append('config/names=\nFoo Boolean\nBar Boolean')
protocol.answers.append({'Foo': '0'})
protocol.answers.append({'Bar': '1'})

config = TorConfig(protocol)
# Initial value is not tested here
protocol.events['CONF_CHANGED']('Foo=1\nBar=0')

msg = "Foo is not True: %r" % config.Foo
self.assertTrue(config.Foo is True, msg=msg)

msg = "Foo is not False: %r" % config.Bar
self.assertTrue(config.Bar is False, msg=msg)

def test_conf_changed_invalid_values(self):
protocol = FakeControlProtocol([])
protocol.answers.append('config/names=\nFoo Integer\nBar Integer')
protocol.answers.append({'Foo': '0'})
protocol.answers.append({'Bar': '1'})

config = TorConfig(protocol)
# Initial value is not tested here
try:
protocol.events['CONF_CHANGED']('Foo=INVALID\nBar=VALUES')
except (ValueError, TypeError):
pass
else:
self.fail("No excpetion thrown")

class CreateTorrcTests(unittest.TestCase):

Expand Down
33 changes: 29 additions & 4 deletions txtorcon/torconfig.py
Expand Up @@ -500,11 +500,17 @@ def validate(self, s, instance, name):


class Boolean(TorConfigType):
"Boolean values are stored as 0 or 1."
def parse(self, s):
if int(s):
return True
return False

def validate(self, s, instance, name):
if s:
return 1
return 0


class Boolean_Auto(TorConfigType):
"""
Expand All @@ -520,11 +526,24 @@ def parse(self, s):
return 1
return 0

def validate(self, s, instance, name):
# FIXME: Is 'auto' an allowed value? (currently not)
s = int(s)
if s < 0:
return 'auto'
elif s:
return 1
else:
return 0


class Integer(TorConfigType):
def parse(self, s):
return int(s)

def validate(self, s, instance, name):
return int(s)


class SignedInteger(Integer):
pass
Expand Down Expand Up @@ -805,8 +824,8 @@ def config_attributes(self):
if self.conf._supports['HiddenServiceDirGroupReadable'] \
and self.group_readable:
rtn.append(('HiddenServiceDirGroupReadable', str(1)))
for x in self.ports:
rtn.append(('HiddenServicePort', str(x)))
for port in self.ports:
rtn.append(('HiddenServicePort', str(port)))
if self.version:
rtn.append(('HiddenServiceVersion', str(self.version)))
for authline in self.authorize_client:
Expand Down Expand Up @@ -1249,7 +1268,10 @@ def _conf_changed(self, arg):
for (k, v) in conf.items():
# v will be txtorcon.DEFAULT_VALUE already from
# parse_keywords if it was unspecified
self.config[self._find_real_name(k)] = v
real_name = self._find_real_name(k)
if real_name in self.parsers:
v = self.parsers[real_name].parse(v)
self.config[real_name] = v

def bootstrap(self, arg=None):
'''
Expand Down Expand Up @@ -1329,7 +1351,10 @@ def save(self):

# FIXME in future we should wait for CONF_CHANGED and
# update then, right?
self.config[self._find_real_name(key)] = value
real_name = self._find_real_name(key)
if not isinstance(value, list) and real_name in self.parsers:
value = self.parsers[real_name].parse(value)
self.config[real_name] = value

# FIXME might want to re-think this, but currently there's no
# way to put things into a config and get them out again
Expand Down

0 comments on commit 5c37ce3

Please sign in to comment.