add new option's type: PortOption
authorEmmanuel Garette <egarette@cadoles.com>
Thu, 11 Jul 2013 21:05:33 +0000 (23:05 +0200)
committerEmmanuel Garette <egarette@cadoles.com>
Thu, 11 Jul 2013 21:05:33 +0000 (23:05 +0200)
test/test_config_ip.py
tiramisu/option.py

index 7512384..e889c92 100644 (file)
@@ -1,10 +1,8 @@
 import autopath
 from py.test import raises
-
-from tiramisu.setting import owners
 from tiramisu.config import Config
 from tiramisu.option import IPOption, NetworkOption, NetmaskOption, \
-    OptionDescription
+    PortOption, OptionDescription
 
 
 def test_ip():
@@ -16,12 +14,19 @@ def test_ip():
     c.a = '192.168.1.0'
     c.a = '88.88.88.88'
     c.a = '0.0.0.0'
-    assert(ValueError, "c.a = '255.255.255.0'")
+    raises(ValueError, "c.a = '255.255.255.0'")
     c.b = '192.168.1.1'
     c.b = '192.168.1.0'
-    assert(ValueError, "c.b = '88.88.88.88'")
+    raises(ValueError, "c.b = '88.88.88.88'")
     c.b = '0.0.0.0'
-    assert(ValueError, "c.b = '255.255.255.0'")
+    raises(ValueError, "c.b = '255.255.255.0'")
+
+
+def test_ip_default():
+    a = IPOption('a', '', '88.88.88.88')
+    od = OptionDescription('od', '', [a])
+    c = Config(od)
+    c.a == '88.88.88.88'
 
 
 def test_network():
@@ -32,14 +37,156 @@ def test_network():
     c.a = '192.168.1.0'
     c.a = '88.88.88.88'
     c.a = '0.0.0.0'
-    assert(ValueError, "c.a = '255.255.255.0'")
+    raises(ValueError, "c.a = '255.255.255.0'")
+
 
 def test_netmask():
     a = NetmaskOption('a', '')
     od = OptionDescription('od', '', [a])
     c = Config(od)
-    assert(ValueError, "c.a = '192.168.1.1'")
-    assert(ValueError, "c.a = '192.168.1.0'")
-    assert(ValueError, "c.a = '88.88.88.88'")
+    raises(ValueError, "c.a = '192.168.1.1'")
+    raises(ValueError, "c.a = '192.168.1.0'")
+    raises(ValueError, "c.a = '88.88.88.88'")
     c.a = '0.0.0.0'
     c.a = '255.255.255.0'
+
+
+def test_port():
+    a = PortOption('a', '')
+    b = PortOption('b', '', allow_zero=True)
+    c = PortOption('c', '', allow_zero=True, allow_registred=False)
+    d = PortOption('d', '', allow_zero=True, allow_wellknown=False, allow_registred=False)
+    e = PortOption('e', '', allow_zero=True, allow_private=True)
+    f = PortOption('f', '', allow_private=True)
+    od = OptionDescription('od', '', [a, b, c, d, e, f])
+    c = Config(od)
+    raises(ValueError, "c.a = 0")
+    c.a = 1
+    c.a = 1023
+    c.a = 1024
+    c.a = 49151
+    raises(ValueError, "c.a = 49152")
+    raises(ValueError, "c.a = 65535")
+    raises(ValueError, "c.a = 65536")
+
+    c.b = 0
+    c.b = 1
+    c.b = 1023
+    c.b = 1024
+    c.b = 49151
+    raises(ValueError, "c.b = 49152")
+    raises(ValueError, "c.b = 65535")
+    raises(ValueError, "c.b = 65536")
+
+    c.c = 0
+    c.c = 1
+    c.c = 1023
+    raises(ValueError, "c.c = 1024")
+    raises(ValueError, "c.c = 49151")
+    raises(ValueError, "c.c = 49152")
+    raises(ValueError, "c.c = 65535")
+    raises(ValueError, "c.c = 65536")
+
+    c.d = 0
+    raises(ValueError, "c.d = 1")
+    raises(ValueError, "c.d = 1023")
+    raises(ValueError, "c.d = 1024")
+    raises(ValueError, "c.d = 49151")
+    raises(ValueError, "c.d = 49152")
+    raises(ValueError, "c.d = 65535")
+    raises(ValueError, "c.d = 65536")
+
+    c.e = 0
+    c.e = 1
+    c.e = 1023
+    c.e = 1024
+    c.e = 49151
+    c.e = 49152
+    c.e = 65535
+
+    raises(ValueError, "c.f = 0")
+    c.f = 1
+    c.f = 1023
+    c.f = 1024
+    c.f = 49151
+    c.f = 49152
+    c.f = 65535
+    raises(ValueError, "c.f = 65536")
+
+
+def test_port_range():
+    a = PortOption('a', '', allow_range=True)
+    b = PortOption('b', '', allow_range=True, allow_zero=True)
+    c = PortOption('c', '', allow_range=True, allow_zero=True, allow_registred=False)
+    d = PortOption('d', '', allow_range=True, allow_zero=True, allow_wellknown=False, allow_registred=False)
+    e = PortOption('e', '', allow_range=True, allow_zero=True, allow_private=True)
+    f = PortOption('f', '', allow_range=True, allow_private=True)
+    od = OptionDescription('od', '', [a, b, c, d, e, f])
+    c = Config(od)
+    raises(ValueError, "c.a = 0")
+    c.a = 1
+    c.a = 1023
+    c.a = 1024
+    c.a = 49151
+    raises(ValueError, "c.a = 49152")
+    raises(ValueError, "c.a = 65535")
+    raises(ValueError, "c.a = 65536")
+    c.a = '1:49151'
+    raises(ValueError, "c.a = '0:49151'")
+    raises(ValueError, "c.a = '1:49152'")
+
+    c.b = 0
+    c.b = 1
+    c.b = 1023
+    c.b = 1024
+    c.b = 49151
+    raises(ValueError, "c.b = 49152")
+    raises(ValueError, "c.b = 65535")
+    raises(ValueError, "c.b = 65536")
+    c.b = '0:49151'
+    raises(ValueError, "c.b = '0:49152'")
+
+    c.c = 0
+    c.c = 1
+    c.c = 1023
+    raises(ValueError, "c.c = 1024")
+    raises(ValueError, "c.c = 49151")
+    raises(ValueError, "c.c = 49152")
+    raises(ValueError, "c.c = 65535")
+    raises(ValueError, "c.c = 65536")
+    c.c = '0:1023'
+    raises(ValueError, "c.c = '0:1024'")
+
+    c.d = 0
+    raises(ValueError, "c.d = 1")
+    raises(ValueError, "c.d = 1023")
+    raises(ValueError, "c.d = 1024")
+    raises(ValueError, "c.d = 49151")
+    raises(ValueError, "c.d = 49152")
+    raises(ValueError, "c.d = 65535")
+    raises(ValueError, "c.d = 65536")
+    raises(ValueError, "c.d = '0:0'")
+    raises(ValueError, "c.d = '0:1'")
+
+    c.e = 0
+    c.e = 1
+    c.e = 1023
+    c.e = 1024
+    c.e = 49151
+    c.e = 49152
+    c.e = 65535
+    c.e = '0:65535'
+    raises(ValueError, "c.e = '0:65536'")
+
+    raises(ValueError, "c.f = 0")
+    c.f = 1
+    c.f = 1023
+    c.f = 1024
+    c.f = 49151
+    c.f = 49152
+    c.f = 65535
+    raises(ValueError, "c.f = 65536")
+    c.f = '1:65535'
+    c.f = '3:4'
+    raises(ValueError, "c.f = '0:65535'")
+    raises(ValueError, "c.f = '4:3'")
index e645a31..5c8bbda 100644 (file)
@@ -277,8 +277,8 @@ class Option(BaseInformation):
             if value is not None and ((self._validator is not None and
                                        not val_validator()) or
                                       not self._validate(value)):
-                raise ValueError(_("invalid value {0} for option {1}"
-                                   "").format(value, self._name))
+                raise ValueError(_("invalid value {0} for option {1} (type {2})"
+                                   "").format(value, self._name, self.__class__))
             if context is not None:
                 descr._valid_consistency(self, value, context, None)
         else:
@@ -478,6 +478,7 @@ class IPOption(Option):
                  requires=None, multi=False, callback=None,
                  callback_params=None, validator=None, validator_args=None,
                  properties=None, only_private=False):
+        self._only_private = only_private
         super(IPOption, self).__init__(name, doc, default=default,
                                        default_multi=default_multi,
                                        callback=callback,
@@ -487,7 +488,6 @@ class IPOption(Option):
                                        validator=validator,
                                        validator_args=validator_args,
                                        properties=properties)
-        self._only_private = only_private
 
     def _validate(self, value):
         try:
@@ -499,6 +499,76 @@ class IPOption(Option):
             return False
 
 
+class PortOption(Option):
+    """represents the choice of a port
+    The port numbers are divided into three ranges:
+    the well-known ports,
+    the registered ports,
+    and the dynamic or private ports.
+    You can actived this three range.
+    Port number 0 is reserved and can't be used.
+    see: http://en.wikipedia.org/wiki/Port_numbers
+    """
+    __slots__ = ('_opt_type', '_allow_range', '_allow_zero', '_min_value',
+                 '_max_value')
+    _opt_type = 'port'
+
+    def __init__(self, name, doc, default=None, default_multi=None,
+                 requires=None, multi=False, callback=None,
+                 callback_params=None, validator=None, validator_args=None,
+                 properties=None, allow_range=False, allow_zero=False,
+                 allow_wellknown=True, allow_registred=True,
+                 allow_private=False):
+        self._allow_range = allow_range
+        self._min_value = None
+        self._max_value = None
+        ports_min = [0, 1, 1024, 49152]
+        ports_max = [0, 1023, 49151, 65535]
+        is_finally = False
+        for index, allowed in enumerate([allow_zero, allow_wellknown, allow_registred, allow_private]):
+            if self._min_value is None:
+                if allowed:
+                    self._min_value = ports_min[index]
+            elif not allowed:
+                is_finally = True
+            elif allowed and is_finally:
+                raise ValueError(_('inconsistency in allowed range'))
+            if allowed:
+                self._max_value = ports_max[index]
+
+        if self._max_value is None:
+            raise ValueError(_('max value is empty'))
+
+        super(PortOption, self).__init__(name, doc, default=default,
+                                         default_multi=default_multi,
+                                         callback=callback,
+                                         callback_params=callback_params,
+                                         requires=requires,
+                                         multi=multi,
+                                         validator=validator,
+                                         validator_args=validator_args,
+                                         properties=properties)
+
+    def _validate(self, value):
+        try:
+            if self._allow_range and ":" in str(value):
+                value = str(value).split(':')
+                if len(value) != 2:
+                    return False
+                if not value[0] < value[1]:
+                    return False
+            else:
+                value = [value]
+
+            for val in value:
+                if not self._min_value <= int(val) <= self._max_value:
+                    return False
+
+            return True
+        except ValueError:
+            return False
+
+
 class NetworkOption(Option):
     "represents the choice of a network"
     __slots__ = ('_opt_type',)