fix tests

Change-Id: I53e9143121a6d01dbd1733f6fcd71fe1a9a9e3e3
Reviewed-on: https://forge.frm2.tum.de/review/16260
Tested-by: JenkinsCodeReview <bjoern_pedersen@frm2.tum.de>
Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
This commit is contained in:
Enrico Faulhaber 2017-09-18 12:00:29 +02:00
parent ee5f749aad
commit 0c63522eab
2 changed files with 106 additions and 118 deletions

View File

@ -23,7 +23,6 @@
from .errors import ProgrammingError from .errors import ProgrammingError
from collections import OrderedDict
# Only export these classes for 'from secop.datatypes import *' # Only export these classes for 'from secop.datatypes import *'
__all__ = [ __all__ = [
@ -44,16 +43,16 @@ class DataType(object):
def validate(self, value): def validate(self, value):
"""validate a external representation and return an internal one""" """validate a external representation and return an internal one"""
raise NotImplemented raise NotImplementedError
def export(self, value): def export(self, value):
"""returns a python object fit for external serialisation or logging""" """returns a python object fit for external serialisation or logging"""
raise NotImplemented raise NotImplementedError
def from_string(self, text): def from_string(self, text):
"""interprets a given string and returns a validated (internal) value""" """interprets a given string and returns a validated (internal) value"""
# to evaluate values from configfiles, etc... # to evaluate values from configfiles, etc...
raise NotImplemented raise NotImplementedError
# goodie: if called, validate # goodie: if called, validate
def __call__(self, value): def __call__(self, value):
@ -63,15 +62,15 @@ class DataType(object):
class FloatRange(DataType): class FloatRange(DataType):
"""Restricted float type""" """Restricted float type"""
def __init__(self, min=None, max=None): def __init__(self, minval=None, maxval=None):
self.min = None if min is None else float(min) self.min = None if minval is None else float(minval)
self.max = None if max is None else float(max) self.max = None if maxval is None else float(maxval)
# note: as we may compare to Inf all comparisons would be false # note: as we may compare to Inf all comparisons would be false
if (self.min or float('-inf')) <= (self.max or float('+inf')): if (self.min or float('-inf')) <= (self.max or float('+inf')):
if min is None and max is None: if minval is None and maxval is None:
self.as_json = ['double'] self.as_json = ['double']
else: else:
self.as_json = ['double', min, max] self.as_json = ['double', minval, maxval]
else: else:
raise ValueError('Max must be larger then min!') raise ValueError('Max must be larger then min!')
@ -113,9 +112,9 @@ class FloatRange(DataType):
class IntRange(DataType): class IntRange(DataType):
"""Restricted int type""" """Restricted int type"""
def __init__(self, min=None, max=None): def __init__(self, minval=None, maxval=None):
self.min = int(min) if min is not None else min self.min = int(minval) if minval is not None else minval
self.max = int(max) if max is not None else max self.max = int(maxval) if maxval is not None else maxval
if self.min is not None and self.max is not None and self.min > self.max: if self.min is not None and self.max is not None and self.min > self.max:
raise ValueError('Max must be larger then min!') raise ValueError('Max must be larger then min!')
if self.min is None and self.max is None: if self.min is None and self.max is None:
@ -210,29 +209,28 @@ class EnumType(DataType):
class BLOBType(DataType): class BLOBType(DataType):
minsize = None
maxsize = None
def __init__(self, maxsize=None, minsize=0):
def __init__(self, minsize=0, maxsize=None): if maxsize is None:
# if only one arg is given it is maxsize! raise ValueError('BLOBType needs a maximum number of Bytes count!')
if maxsize is None and minsize: minsize, maxsize = min(minsize, maxsize), max(minsize, maxsize)
maxsize = minsize
minsize = 0
self.minsize = minsize self.minsize = minsize
self.maxsize = maxsize self.maxsize = maxsize
if minsize < 0:
raise ValueError('sizes must be bigger than or equal to 0!')
if minsize: if minsize:
self.as_json = ['blob', maxsize, minsize] self.as_json = ['blob', maxsize, minsize]
elif maxsize:
self.as_json = ['blob', maxsize]
else: else:
self.as_json = ['blob'] self.as_json = ['blob', maxsize]
if minsize is not None and maxsize is not None and minsize > maxsize:
raise ValueError('maxsize must be bigger than minsize!')
def __repr__(self): def __repr__(self):
if self.maxsize:
return 'BLOB(%s, %s)' % (str(self.minsize), str(self.maxsize))
if self.minsize: if self.minsize:
return 'BLOB(%d)' % self.minsize return 'BLOB(%s, %s)' % (
return 'BLOB()' str(self.minsize) if self.minsize else 'unspecified',
str(self.maxsize) if self.maxsize else 'unspecified')
return 'BLOB(%s)' % (str(self.minsize) if self.minsize else 'unspecified')
def validate(self, value): def validate(self, value):
"""return the validated (internal) value or raise""" """return the validated (internal) value or raise"""
@ -259,29 +257,28 @@ class BLOBType(DataType):
class StringType(DataType): class StringType(DataType):
as_json = ['string'] as_json = ['string']
minsize = None
maxsize = None
def __init__(self, minsize=0, maxsize=None): def __init__(self, maxsize=None, minsize=0):
# if only one arg is given it is maxsize! if maxsize is None:
if maxsize is None and minsize: raise ValueError('StringType needs a maximum bytes count!')
maxsize = minsize minsize, maxsize = min(minsize, maxsize), max(minsize, maxsize)
minsize = 0
self.as_json = ['string', maxsize] if minsize < 0:
elif maxsize or minsize: raise ValueError('sizes must be >= 0')
if minsize:
self.as_json = ['string', maxsize, minsize] self.as_json = ['string', maxsize, minsize]
else: else:
self.as_json = ['string'] self.as_json = ['string', maxsize]
self.minsize = minsize self.minsize = minsize
self.maxsize = maxsize self.maxsize = maxsize
if minsize is not None and maxsize is not None and minsize > maxsize:
raise ValueError('maxsize must be bigger than minsize!')
def __repr__(self): def __repr__(self):
if self.maxsize:
return 'StringType(%s, %s)' % (
str(self.minsize), str(self.maxsize))
if self.minsize: if self.minsize:
return 'StringType(%d)' % str(self.minsize) return 'StringType(%s, %s)' % (
return 'StringType()' str(self.minsize) or 'unspecified', str(self.maxsize) or 'unspecified')
return 'StringType(%d)' % str(self.maxsize)
def validate(self, value): def validate(self, value):
"""return the validated (internal) value or raise""" """return the validated (internal) value or raise"""
@ -339,36 +336,32 @@ class BoolType(DataType):
class ArrayOf(DataType): class ArrayOf(DataType):
minsize = None
def __init__(self, subtype, minsize=0, maxsize=None): maxsize = None
def __init__(self, subtype, maxsize=None, minsize=0):
self.subtype = subtype
if not isinstance(subtype, DataType): if not isinstance(subtype, DataType):
raise ValueError( raise ValueError(
'ArrayOf only works with DataType objs as first argument!') 'ArrayOf only works with DataType objs as first argument!')
if maxsize is None:
raise ValueError('ArrayOf needs a maximum size')
minsize, maxsize = min(minsize, maxsize), max(minsize, maxsize)
if minsize < 0:
raise ValueError('sizes must be > 0')
if maxsize < 1:
raise ValueError('Maximum size must be >= 1!')
# if only one arg is given, it is maxsize! # if only one arg is given, it is maxsize!
if minsize and not maxsize: if minsize:
maxsize = minsize
minsize = 0
self.as_json = ['array', subtype.as_json, maxsize]
elif maxsize:
self.as_json = ['array', subtype.as_json, maxsize, minsize] self.as_json = ['array', subtype.as_json, maxsize, minsize]
else: else:
self.as_json = ['array', subtype.as_json] self.as_json = ['array', subtype.as_json, maxsize]
self.minsize = minsize or 0 self.minsize = minsize
self.maxsize = maxsize self.maxsize = maxsize
self.subtype = subtype
if self.maxsize is not None and self.minsize > maxsize:
raise ValueError('minsize must be less than or equal to maxsize!')
if self.minsize < 0:
raise ValueError('Minimum size must be >= 0!')
if self.maxsize is not None and self.maxsize < 1:
raise ValueError('Maximum size must be >= 1!')
if self.maxsize is not None and self.minsize > self.maxsize:
raise ValueError('Maximum size must be >= Minimum size')
def __repr__(self): def __repr__(self):
return 'ArrayOf(%s, %s, %s)' % ( return 'ArrayOf(%s, %s, %s)' % (
repr(self.subtype), self.minsize, self.maxsize) repr(self.subtype), self.minsize or 'unspecified', self.maxsize or 'unspecified')
def validate(self, value): def validate(self, value):
"""validate a external representation to an internal one""" """validate a external representation to an internal one"""
@ -391,7 +384,8 @@ class ArrayOf(DataType):
return [self.subtype.export(elem) for elem in value] return [self.subtype.export(elem) for elem in value]
def from_string(self, text): def from_string(self, text):
value = eval(text) # XXX: !!! # XXX: parse differntly than using eval!
value = eval(text) # pylint: disable=W0123
return self.validate(value) return self.validate(value)
@ -429,7 +423,8 @@ class TupleOf(DataType):
return [sub.export(elem) for sub, elem in zip(self.subtypes, value)] return [sub.export(elem) for sub, elem in zip(self.subtypes, value)]
def from_string(self, text): def from_string(self, text):
value = eval(text) # XXX: !!! # XXX: parse differntly than using eval!
value = eval(text) # pylint: disable=W0123
return self.validate(tuple(value)) return self.validate(tuple(value))
@ -476,7 +471,8 @@ class StructOf(DataType):
for k, v in value.items()) for k, v in value.items())
def from_string(self, text): def from_string(self, text):
value = eval(text) # XXX: !!! # XXX: parse differntly than using eval!
value = eval(text) # pylint: disable=W0123
return self.validate(dict(value)) return self.validate(dict(value))
@ -484,8 +480,8 @@ class StructOf(DataType):
class Command(DataType): class Command(DataType):
IS_COMMAND = True IS_COMMAND = True
def __init__(self, argtypes=[], resulttype=None): def __init__(self, argtypes=tuple(), resulttype=None):
for arg in argsin: for arg in argtypes:
if not isinstance(arg, DataType): if not isinstance(arg, DataType):
raise ValueError('Command: Argument types must be DataTypes!') raise ValueError('Command: Argument types must be DataTypes!')
if resulttype is not None: if resulttype is not None:
@ -537,15 +533,12 @@ class Command(DataType):
# XXX: derive from above classes automagically! # XXX: derive from above classes automagically!
DATATYPES = dict( DATATYPES = dict(
bool=lambda: BoolType(), bool=BoolType,
int=lambda _min=None, _max=None: IntRange(_min, _max), int=lambda _min=None, _max=None: IntRange(_min, _max),
double=lambda _min=None, _max=None: FloatRange(_min, _max), double=lambda _min=None, _max=None: FloatRange(_min, _max),
blob=lambda _max=None, _min=None: BLOBType( blob=lambda _max=None, _min=0: BLOBType(_max, _min),
_min, _max) if _min else BLOBType(_max), string=lambda _max=None, _min=0: StringType(_max, _min),
string=lambda _max=None, _min=None: StringType( array=lambda subtype, _max=None, _min=0: ArrayOf(get_datatype(subtype), _max, _min),
_min, _max) if _min else StringType(_max),
array=lambda subtype, _max=None, _min=None: ArrayOf(
get_datatype(subtype), _min, _max) if _min else ArrayOf(getdatatype(subtype), _min),
tuple=lambda subtypes: TupleOf(*map(get_datatype, subtypes)), tuple=lambda subtypes: TupleOf(*map(get_datatype, subtypes)),
enum=lambda kwds: EnumType(**kwds), enum=lambda kwds: EnumType(**kwds),
struct=lambda named_subtypes: StructOf( struct=lambda named_subtypes: StructOf(
@ -567,12 +560,6 @@ def get_datatype(json):
if json is None: if json is None:
return json return json
if not isinstance(json, list): if not isinstance(json, list):
import mlzlog
if mlzlog.log is None:
mlzlog.initLogging('xxxxxxxxx')
mlzlog.getLogger('datatypes').warning(
"WARNING: invalid datatype specified! trying fallback mechanism. ymmv!")
return get_datatype([json])
raise ValueError( raise ValueError(
'Can not interpret datatype %r, it should be a list!', json) 'Can not interpret datatype %r, it should be a list!', json)
if len(json) < 1: if len(json) < 1:
@ -588,6 +575,6 @@ def get_datatype(json):
args = json[1:] args = json[1:]
try: try:
return DATATYPES[base](*args) return DATATYPES[base](*args)
except (TypeError, AttributeError) as exc: except (TypeError, AttributeError):
raise ValueError('Invalid datatype descriptor in %r', json) raise ValueError('Invalid datatype descriptor in %r', json)
raise ValueError('can not convert %r to datatype', json) raise ValueError('can not convert %r to datatype', json)

View File

@ -21,11 +21,12 @@
# ***************************************************************************** # *****************************************************************************
"""test data types.""" """test data types."""
import sys
sys.path.insert(0, sys.path[0] + '/..')
# no fixtures needed # no fixtures needed
import pytest import pytest
import sys
sys.path.insert(0, sys.path[0] + '/..')
from secop.datatypes import DataType, FloatRange, IntRange, \ from secop.datatypes import DataType, FloatRange, IntRange, \
EnumType, BLOBType, StringType, BoolType, ArrayOf, TupleOf, StructOf, \ EnumType, BLOBType, StringType, BoolType, ArrayOf, TupleOf, StructOf, \
@ -36,10 +37,10 @@ def test_DataType():
dt = DataType() dt = DataType()
assert dt.as_json == ['undefined'] assert dt.as_json == ['undefined']
with pytest.raises(TypeError): with pytest.raises(NotImplementedError):
dt = DataType() dt = DataType()
dt.validate('') dt.validate('')
dt.export() dt.export('')
def test_FloatRange(): def test_FloatRange():
@ -119,8 +120,8 @@ def test_EnumType():
def test_BLOBType(): def test_BLOBType():
# test constructor catching illegal arguments # test constructor catching illegal arguments
with pytest.raises(ValueError):
dt = BLOBType() dt = BLOBType()
assert dt.as_json == ['blob']
dt = BLOBType(10) dt = BLOBType(10)
assert dt.as_json == ['blob', 10] assert dt.as_json == ['blob', 10]
@ -144,8 +145,8 @@ def test_BLOBType():
def test_StringType(): def test_StringType():
# test constructor catching illegal arguments # test constructor catching illegal arguments
with pytest.raises(ValueError):
dt = StringType() dt = StringType()
assert dt.as_json == ['string']
dt = StringType(12) dt = StringType(12)
assert dt.as_json == ['string', 12] assert dt.as_json == ['string', 12]
@ -179,21 +180,21 @@ def test_BoolType():
with pytest.raises(ValueError): with pytest.raises(ValueError):
dt.validate('av') dt.validate('av')
assert dt.validate('true') == True assert dt.validate('true') is True
assert dt.validate('off') == False assert dt.validate('off') is False
assert dt.validate(1) == True assert dt.validate(1) is True
assert dt.export('false') == False assert dt.export('false') is False
assert dt.export(0) == False assert dt.export(0) is False
assert dt.export('on') == True assert dt.export('on') is True
def test_ArrayOf(): def test_ArrayOf():
# test constructor catching illegal arguments # test constructor catching illegal arguments
with pytest.raises(ValueError): with pytest.raises(ValueError):
ArrayOf(int) ArrayOf(int)
dt = ArrayOf(IntRange(-10, 10)) with pytest.raises(ValueError):
assert dt.as_json == ['array', ['int', -10, 10]] ArrayOf(IntRange(-10,10))
dt = ArrayOf(IntRange(-10, 10), 5) dt = ArrayOf(IntRange(-10, 10), 5)
assert dt.as_json == ['array', ['int', -10, 10], 5] assert dt.as_json == ['array', ['int', -10, 10], 5]
@ -230,12 +231,12 @@ def test_TupleOf():
def test_StructOf(): def test_StructOf():
# test constructor catching illegal arguments # test constructor catching illegal arguments
with pytest.raises(TypeError): with pytest.raises(TypeError):
StructOf(IntRange) StructOf(IntRange) # pylint: disable=E1121
with pytest.raises(ProgrammingError): with pytest.raises(ProgrammingError):
StructOf(IntRange=1) StructOf(IntRange=1)
dt = StructOf(a_string=StringType(), an_int=IntRange(0, 999)) dt = StructOf(a_string=StringType(55), an_int=IntRange(0, 999))
assert dt.as_json == ['struct', {'a_string': ['string'], assert dt.as_json == ['struct', {'a_string': ['string', 55],
'an_int': ['int', 0, 999], 'an_int': ['int', 0, 999],
}] }]
@ -295,18 +296,18 @@ def test_get_datatype():
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(['enum', [1, 2, 3]]) get_datatype(['enum', [1, 2, 3]])
assert isinstance(get_datatype(['blob']), BLOBType)
assert isinstance(get_datatype(['blob', 1]), BLOBType) assert isinstance(get_datatype(['blob', 1]), BLOBType)
assert isinstance(get_datatype(['blob', 1, 10]), BLOBType) assert isinstance(get_datatype(['blob', 10, 1]), BLOBType)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(['blob', 10, -10]) get_datatype(['blob', 10, -10])
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(['blob', 10, -10, 1]) get_datatype(['blob', 10, -10, 1])
assert isinstance(get_datatype(['string']), StringType) with pytest.raises(ValueError):
get_datatype(['string'])
assert isinstance(get_datatype(['string', 1]), StringType) assert isinstance(get_datatype(['string', 1]), StringType)
assert isinstance(get_datatype(['string', 1, 10]), StringType) assert isinstance(get_datatype(['string', 10, 1]), StringType)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(['string', 10, -10]) get_datatype(['string', 10, -10])
@ -319,15 +320,15 @@ def test_get_datatype():
get_datatype(['array', 1]) get_datatype(['array', 1])
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(['array', [1], 2, 3]) get_datatype(['array', [1], 2, 3])
assert isinstance(get_datatype(['array', ['blob']]), ArrayOf) assert isinstance(get_datatype(['array', ['blob', 1], 1]), ArrayOf)
assert isinstance(get_datatype(['array', ['blob']]).subtype, BLOBType) assert isinstance(get_datatype(['array', ['blob', 1], 1]).subtype, BLOBType)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(['array', ['blob'], -10]) get_datatype(['array', ['blob', 1], -10])
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(['array', ['blob'], -10, 10]) get_datatype(['array', ['blob', 1], 10, -10])
assert isinstance(get_datatype(['array', ['blob'], 1, 10]), ArrayOf) assert isinstance(get_datatype(['array', ['blob', 1], 10, 1]), ArrayOf)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(['tuple']) get_datatype(['tuple'])
@ -335,16 +336,16 @@ def test_get_datatype():
get_datatype(['tuple', 1]) get_datatype(['tuple', 1])
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(['tuple', [1], 2, 3]) get_datatype(['tuple', [1], 2, 3])
assert isinstance(get_datatype(['tuple', [['blob']]]), TupleOf) assert isinstance(get_datatype(['tuple', [['blob', 1]]]), TupleOf)
assert isinstance(get_datatype( assert isinstance(get_datatype(
['tuple', [['blob']]]).subtypes[0], BLOBType) ['tuple', [['blob', 1]]]).subtypes[0], BLOBType)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(['tuple', [['blob']], -10]) get_datatype(['tuple', [['blob', 1]], -10])
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(['tuple', [['blob']], -10, 10]) get_datatype(['tuple', [['blob', 1]], 10, -10])
assert isinstance(get_datatype(['tuple', [['blob'], ['int']]]), TupleOf) assert isinstance(get_datatype(['tuple', [['blob', 1], ['int']]]), TupleOf)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(['struct']) get_datatype(['struct'])
@ -352,14 +353,14 @@ def test_get_datatype():
get_datatype(['struct', 1]) get_datatype(['struct', 1])
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(['struct', [1], 2, 3]) get_datatype(['struct', [1], 2, 3])
assert isinstance(get_datatype(['struct', {'blob': ['blob']}]), StructOf) assert isinstance(get_datatype(['struct', {'blob': ['blob', 1]}]), StructOf)
assert isinstance(get_datatype( assert isinstance(get_datatype(
['struct', {'blob': ['blob']}]).named_subtypes['blob'], BLOBType) ['struct', {'blob': ['blob', 1]}]).named_subtypes['blob'], BLOBType)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(['struct', [['blob']], -10]) get_datatype(['struct', [['blob', 1]], -10])
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(['struct', [['blob']], -10, 10]) get_datatype(['struct', [['blob', 1]], 10, -10])
assert isinstance(get_datatype( assert isinstance(get_datatype(
['struct', {'blob': ['blob'], 'int':['int']}]), StructOf) ['struct', {'blob': ['blob', 1], 'int':['int']}]), StructOf)