Skip to content
This repository has been archived by the owner on Feb 9, 2018. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Validate cli --tries value
  • Loading branch information
bacher09 committed Feb 8, 2014
1 parent 99285a9 commit 2d0d43d
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 3 deletions.
32 changes: 29 additions & 3 deletions dynsupdate/client.py
Expand Up @@ -72,7 +72,7 @@ def simple_ip_fetch(url, extract_fun=lambda x: x.strip(), timeout=5):
# Limit response size
data = resp.read(MAX_RESPONSE_DATA)
except (URLError, socket.error) as e:
logger.warn('couldn\'t fetch url "{0}" with timeout {1:d}'
logger.warn('couldn\'t fetch url "{0}" with timeout {1:.4g}'
.format(url, timeout))
return None
else:
Expand Down Expand Up @@ -468,6 +468,30 @@ def parse(input_str):
return parse


def integer_range(min=None, max=None):

def validate_int(value):
try:
res = int(value)
except ValueError:
raise argparse.ArgumentTypeError('Invalid integer "%s"' % value)
else:
if min is not None and res < min:
raise argparse.ArgumentTypeError(
'Value "{val}" is smaller than "{min}"'
.format(val=res, min=min)
)
elif max is not None and res > max:
raise argparse.ArgumentTypeError(
'Value "{val}" is bigger than "{max}"'
.format(val=res, max=min)
)

return res

return validate_int


class Program(object):

COMMANDS = {
Expand Down Expand Up @@ -558,14 +582,16 @@ def ip_fun(cls, tries=5, timeout=5, types=None, services=None):

@classmethod
def ip_arguments(cls, parser):
tries_type = integer_range(min=1)
types_type = comma_separated_list(SimpleIpGetter.SERVICE_TYPES)
services_type = comma_separated_list(SimpleIpGetter.SERVICE_NAMES)
parser.add_argument('-n', '--tries', dest="tries", type=int, default=5)
parser.add_argument('-n', '--tries', dest="tries", type=tries_type,
default=5)
parser.add_argument('-t', '--types', dest="types", type=types_type,
default=None)
parser.add_argument('--services', dest="services", type=services_type,
default=None)
parser.add_argument('--timeout', dest="timeout", type=int, default=5)
parser.add_argument('--timeout', dest="timeout", type=float, default=5)

@classmethod
def build_parser(cls):
Expand Down
32 changes: 32 additions & 0 deletions tests/test_cli_iterface.py
Expand Up @@ -15,6 +15,10 @@
"""


class ExitException(Exception):
pass


class CliParseTest(TestCase):

def test_comma_separated_list(self):
Expand All @@ -27,6 +31,13 @@ def test_comma_separated_list(self):
self.assertRaises(argparse.ArgumentTypeError, my_types, "http,bad")
# TODO: Maybe tests arguments in uppercase to

def test_validate_int(self):
positive_int = client.integer_range(min=0)
self.assertRaises(argparse.ArgumentTypeError, positive_int, "bad")
self.assertRaises(argparse.ArgumentTypeError, positive_int, "-2")
self.assertRaises(argparse.ArgumentTypeError, positive_int, "-1")
self.assertEqual(positive_int("0"), 0)


class CliIterfaceTest(TestCase):

Expand All @@ -50,6 +61,17 @@ def patch_urlopen(self):
self.addCleanup(urlopen_patch.stop)

def patch_argparse(self):
self.arg_exit_mock = mock.Mock(spec=[])
self.arg_error_mock = mock.Mock(spec=[])
self.arg_exit_mock.side_effect = ExitException
self.arg_error_mock.side_effect = ExitException
argparse_patch = mock.patch.multiple(
'argparse.ArgumentParser',
exit=self.arg_exit_mock,
error=self.arg_error_mock
)
argparse_patch.start()
self.addCleanup(argparse_patch.stop)

filetype_patch = mock.patch('argparse.FileType')
self.filetype_mock = filetype_patch.start()
Expand Down Expand Up @@ -122,6 +144,16 @@ def test_interface_checkip(self):
ret_value = self.stdout_mock.getvalue()
self.assertIn('127.0.0.1', ret_value)

def test_interface_checkip_bad_num(self):
self.urlopen_mock.side_effect = mock.mock_open(read_data="127.0.0.1\n")
self.assertEqual(argparse.ArgumentParser.exit, self.arg_exit_mock)
prog = client.Program()
with self.assertRaises(ExitException):
prog.run("checkip -n -2".split(), log=False)

with self.assertRaises(ExitException):
prog.run("checkip -n 0".split(), log=False)

def test_interface_update(self):
response_mock = mock.mock_open(read_data="127.0.0.6\n")
self.urlopen_mock.side_effect = response_mock
Expand Down

0 comments on commit 2d0d43d

Please sign in to comment.