"""
$URL: svn+ssh://svn.mems-exchange.org/repos/trunk/dulcinea/lib/param/test/utest_types.py $
$Id: utest_types.py 28105 2006-03-30 16:24:19Z dbinger $
"""
from dulcinea.common import CommonTest
from dulcinea.material import get_material_db
from dulcinea.param import get_parameter_db
from dulcinea.param.errors import ParamTypeError
from dulcinea.param.parameter_type import ParameterType
from dulcinea.physical_unit import get_standard_unit
from dulcinea.physical_value import PhysicalValue
from dulcinea.range_value import RangeValue
from sancho.utest import raises

class ParameterTypeTest (CommonTest):

    def _pre (self):
        CommonTest._pre(self)
        if get_parameter_db() is None:
            return
        self.plib = get_parameter_db()
        self.mdb = get_material_db()

    def check_int_type (self):
        if get_parameter_db() is None:
            return
        parameter_type1 = self.plib.get_parameter_type(ParameterType.ATOMIC,
                                                       ParameterType.INT)

        assert parameter_type1.is_atomic()
        assert parameter_type1.is_int()
        assert not parameter_type1.is_string()
        assert not parameter_type1.is_physical_value()
        assert not parameter_type1.is_material()
        assert not parameter_type1.is_list()
        assert not parameter_type1.is_table()
        assert not parameter_type1.is_boolean()

        parameter_type2 = self.plib.get_parameter_type(ParameterType.ATOMIC,
                                                       ParameterType.STRING)
        assert parameter_type2 is not parameter_type1
        parameter_type2 = self.plib.get_parameter_type(ParameterType.ATOMIC,
                                                       ParameterType.INT)
        assert parameter_type2 is parameter_type1

        parameter_type1.check_value(None)
        parameter_type1.check_value(10)
        parameter_type1.check_value(RangeValue(10, 20))
        raises(ParamTypeError, parameter_type1.check_value, [10, 20])
        raises(ParamTypeError, parameter_type1.check_value, 'hello')
        raises(ParamTypeError, parameter_type1.check_value, ['hello', 'bye'])
        raises(AssertionError,
            self.plib.get_parameter_type,
            ParameterType.ATOMIC, ParameterType.INT, key_type=1)

    def check_string_type (self):
        if get_parameter_db() is None:
            return
        parameter_type1 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.STRING)

        assert parameter_type1.is_atomic()
        assert not parameter_type1.is_int()
        assert parameter_type1.is_string()
        assert not parameter_type1.is_physical_value()
        assert not parameter_type1.is_material()
        assert not parameter_type1.is_list()
        assert not parameter_type1.is_table()
        assert not parameter_type1.is_boolean()

        parameter_type2 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.INT)
        assert parameter_type2 is not parameter_type1
        parameter_type2 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.STRING)
        assert parameter_type2 is parameter_type1

        parameter_type1.check_value(None)
        parameter_type1.check_value('hello')
        raises(ParamTypeError, parameter_type1.check_value, ['hello', 'bye'])
        raises(ParamTypeError, parameter_type1.check_value, 10)
        raises(ParamTypeError, parameter_type1.check_value, RangeValue(10, 20))
        raises(ParamTypeError, parameter_type1.check_value, [10, 20])

    def check_boolean_type (self):
        if get_parameter_db() is None:
            return
        parameter_type1 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.BOOLEAN)

        assert parameter_type1.is_atomic()
        assert not parameter_type1.is_int()
        assert not parameter_type1.is_string()
        assert not parameter_type1.is_physical_value()
        assert not parameter_type1.is_material()
        assert not parameter_type1.is_list()
        assert not parameter_type1.is_table()
        assert parameter_type1.is_boolean()

        parameter_type2 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.INT)
        assert parameter_type2 is not parameter_type1
        parameter_type2 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.BOOLEAN)
        assert parameter_type2 is parameter_type1

        parameter_type1.check_value(True)
        parameter_type1.check_value(False)
        parameter_type1.check_value(0)
        parameter_type1.check_value(1)
        parameter_type1.check_value(None)
        raises(ParamTypeError, parameter_type1.check_value, '')
        raises(ParamTypeError, parameter_type1.check_value, [True])
        assert parameter_type1.format_value(True) == 'yes'
        assert parameter_type1.format_value(0) == 'no'

    def check_physical_value_type (self):
        if get_parameter_db() is None:
            return
        parameter_type1 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.PHYSICAL_VALUE)

        assert parameter_type1.is_atomic()
        assert not parameter_type1.is_int()
        assert not parameter_type1.is_string()
        assert parameter_type1.is_physical_value()
        assert not parameter_type1.is_material()
        assert not parameter_type1.is_list()
        assert not parameter_type1.is_table()
        assert not parameter_type1.is_boolean()

        parameter_type2 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.PHYSICAL_VALUE)
        assert parameter_type2 is parameter_type1

        inch = get_standard_unit('inch')
        parameter_type2 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.PHYSICAL_VALUE,
            element_sub_type=inch)
        assert parameter_type2 is not parameter_type1

        parameter_type1.check_value(None)
        parameter_type1.check_value(PhysicalValue(10))
        parameter_type1.check_value(PhysicalValue(RangeValue(10, 20)))
        parameter_type2.check_value(PhysicalValue(10, 'inch'))
        parameter_type2.check_value(PhysicalValue(RangeValue(10, 20), 'inch'))
        parameter_type2.check_value(PhysicalValue(10, 'm'))
        parameter_type2.check_value(PhysicalValue(RangeValue(10, 20), 'm'))
        raises(ParamTypeError, parameter_type1.check_value, 
            PhysicalValue(10, 'inch'))
        raises(ParamTypeError, parameter_type2.check_value, PhysicalValue(10))
        raises(ParamTypeError, parameter_type2.check_value, 
            PhysicalValue(10, 's'))
        raises(ParamTypeError, parameter_type1.check_value, [PhysicalValue(10)])
        raises(ParamTypeError, parameter_type2.check_value,
            [PhysicalValue(10, 'inch')])
        raises(ParamTypeError,
            parameter_type1.check_value, 10)
        raises(ParamTypeError,
            parameter_type1.check_value, RangeValue(10, 20))
        raises(ParamTypeError,
            parameter_type1.check_value, [10, 20])
        raises(ParamTypeError,
            parameter_type1.check_value, 'hello')
        raises(ParamTypeError,
            parameter_type1.check_value, ['hello', 'bye'])
        raises(AssertionError,
            self.plib.get_parameter_type,
            ParameterType.ATOMIC, ParameterType.PHYSICAL_VALUE,
            element_sub_type=1)
        raises(AssertionError,
            self.plib.get_parameter_type,
            ParameterType.ATOMIC, ParameterType.PHYSICAL_VALUE, key_type=1)
        raises(AssertionError,
            self.plib.get_parameter_type,
            ParameterType.ATOMIC, ParameterType.PHYSICAL_VALUE, key_sub_type=1)

    def check_material_type (self):
        if get_parameter_db() is None:
            return
        parameter_type1 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.MATERIAL)

        assert parameter_type1.is_atomic()
        assert not parameter_type1.is_int()
        assert not parameter_type1.is_string()
        assert not parameter_type1.is_physical_value()
        assert parameter_type1.is_material()
        assert not parameter_type1.is_list()
        assert not parameter_type1.is_table()
        assert not parameter_type1.is_boolean()

        parameter_type2 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.MATERIAL)
        assert parameter_type2 is parameter_type1

        silicone = self.mdb.get_material('silicone')
        gold = self.mdb.get_material('gold')
        inch = get_standard_unit('inch')

        parameter_type2 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.MATERIAL)
        assert parameter_type2 is parameter_type1

        parameter_type1.check_value(None)
        parameter_type1.check_value(silicone)
        parameter_type1.check_value(gold)
        raises(ParamTypeError,
            parameter_type1.check_value, [gold])
        raises(ParamTypeError,
            parameter_type1.check_value, 'hello')
        raises(ParamTypeError,
            parameter_type1.check_value, ['hello', 'bye'])
        parameter_type2.check_value(silicone)


    def check_list_type (self):
        if get_parameter_db() is None:
            return
        parameter_type1 = self.plib.get_parameter_type(
            ParameterType.LIST, ParameterType.INT)
        assert not parameter_type1.is_atomic()
        assert parameter_type1.is_int()
        assert not parameter_type1.is_string()
        assert not parameter_type1.is_physical_value()
        assert not parameter_type1.is_material()
        assert parameter_type1.is_list()
        assert not parameter_type1.is_table()
        assert not parameter_type1.is_boolean()

        parameter_type2 = self.plib.get_parameter_type(
            ParameterType.LIST, ParameterType.INT)
        assert parameter_type2 is parameter_type1
        parameter_type2 = self.plib.get_parameter_type(
            ParameterType.LIST, ParameterType.STRING)
        assert parameter_type2 is not parameter_type1
        parameter_type3 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.STRING)
        assert parameter_type3 is parameter_type2.element_type

        assert not parameter_type2.is_int()
        assert parameter_type2.is_string()

        parameter_type1.check_value(None)
        parameter_type1.check_value([10])
        parameter_type1.check_value([10, 20])
        parameter_type1.check_value([RangeValue(10, 20)])
        parameter_type1.check_value([10, 20, RangeValue(10, 20)])
        raises(ParamTypeError,
            parameter_type1.check_value, 10)
        raises(ParamTypeError,
            parameter_type1.check_value, RangeValue(10, 20))
        raises(ParamTypeError,
            parameter_type1.check_value, 'hello')

    def check_table_type (self):
        if get_parameter_db() is None:
            return
        parameter_type1 = self.plib.get_parameter_type(
            ParameterType.TABLE, ParameterType.PHYSICAL_VALUE,
            key_type=ParameterType.MATERIAL)

        assert not parameter_type1.is_atomic()
        assert not parameter_type1.is_int()
        assert not parameter_type1.is_string()
        assert parameter_type1.is_physical_value()
        assert not parameter_type1.is_material()
        assert not parameter_type1.is_list()
        assert parameter_type1.is_table()
        assert not parameter_type1.is_boolean()

        assert not parameter_type1.is_key_int()
        assert not parameter_type1.is_key_string()
        assert not parameter_type1.is_key_physical_value()
        assert parameter_type1.is_key_material()

        silicone = self.mdb.get_material('silicone')
        gold = self.mdb.get_material('gold')
        inch = get_standard_unit('inch')

        parameter_type2 = self.plib.get_parameter_type(
            ParameterType.TABLE, ParameterType.PHYSICAL_VALUE,
            key_type=ParameterType.MATERIAL)
        assert parameter_type2 is parameter_type1
        parameter_type2 = self.plib.get_parameter_type(
            ParameterType.TABLE, ParameterType.PHYSICAL_VALUE,
            key_type=ParameterType.MATERIAL)
        assert parameter_type2 is parameter_type1
        parameter_type3 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.PHYSICAL_VALUE)
        assert parameter_type3 is parameter_type1.element_type
        assert parameter_type3 is parameter_type2.element_type
        parameter_type3 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.MATERIAL)
        assert parameter_type3 is parameter_type1.key_type
        assert parameter_type3 is parameter_type2.key_type
        parameter_type3 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.MATERIAL)
        assert parameter_type3 is parameter_type1.key_type
        assert parameter_type3 is parameter_type2.key_type
        parameter_type3 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.PHYSICAL_VALUE)
        assert parameter_type3 is parameter_type1.element_type
        parameter_type3 = self.plib.get_parameter_type(
            ParameterType.ATOMIC, ParameterType.MATERIAL)
        assert parameter_type3 is parameter_type1.key_type

        parameter_type1.check_value(None)
        parameter_type1.check_value(
            {gold:PhysicalValue(10),
             silicone:PhysicalValue(RangeValue(10, 20))})

        raises(ParamTypeError,
            parameter_type1.check_value, 10)
        raises(ParamTypeError,
            parameter_type1.check_value, [10])
        raises(ParamTypeError,
            parameter_type1.check_value, RangeValue(10, 20))
        raises(ParamTypeError,
            parameter_type1.check_value, 'hello')
        raises(ParamTypeError,
            parameter_type1.check_value, PhysicalValue(10))
        raises(ParamTypeError,
            parameter_type1.check_value, [PhysicalValue(10)])
        raises(ParamTypeError,
            parameter_type1.check_value, [gold])
        raises(AssertionError,
            self.plib.get_parameter_type,
            ParameterType.TABLE, ParameterType.INT)

if __name__ == "__main__":
    ParameterTypeTest()
