You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

166 lines
9.4 KiB

# License: Apache 2.0. See LICENSE file in root directory.
# Copyright(c) 2024 Intel Corporation. All Rights Reserved.
#test:donotrun:!dds
import pyrealdds as dds
from rspy import log, test
# Test dds.option mechanism and logic
with test.closure( 'read-only options' ):
test.check( dds.option.from_json( ['1', 0, 'desc'] ).is_read_only() )
test.check_false( dds.option.from_json( ['1', 0, 0, 'desc'] ).is_read_only() ) # default value -> not read-only
test.check( dds.option.from_json(
['Asic Temperature',None,-40.0,125.0,0.0,0.0,'Current Asic Temperature (degree celsius)',['optional','read-only']] ).is_read_only() )
test.check_equal_lists( dds.option.from_json( # default==min==max, step==0 -> read-only!
['Stereo Baseline',50.20994567871094,50.20994567871094,50.20994567871094,0.0,50.20994567871094,'...',['read-only']] ).to_json(),
['Stereo Baseline',50.20994567871094,'...'] )
test.check_equal( # 1.1 => 1.10000002 as float, => 1.1000000000000001 as double
dds.option.from_json( ['a', 1.1, 'desc'] ).get_value(),
1.1 )
with test.closure( 'boolean' ):
test.check_equal( dds.option.from_json( ['b', True, 'bool'] ).value_type(), 'boolean' )
test.check_equal( dds.option.from_json( ['b', False, 'bool'] ).value_type(), 'boolean' )
test.check_equal( dds.option.from_json( ['b', 0, 'bool', ['boolean']] ).value_type(), 'boolean' )
test.check_equal( dds.option.from_json( ['b', 0, 'bool', ['boolean']] ).get_value(), False )
test.check_equal( dds.option.from_json( ['b', 1, 'bool', ['boolean']] ).get_value(), True )
test.check_equal_lists(
dds.option.from_json( ['b', 1, 'bool', ['boolean']] ).to_json(),
['b', True, 'bool'] )
test.check_throws( lambda:
dds.option.from_json( ['b', 1., 'bool', ['boolean']] ),
RuntimeError, 'not convertible to a boolean: 1.0' )
test.check_throws( lambda:
dds.option.from_json( ['b', 2, 'bool', ['boolean']] ),
RuntimeError, 'not convertible to a boolean: 2' )
test.check_equal( dds.option.from_json( ['b', False, True, 'bool'] ).value_type(), 'boolean' )
test.check_equal( dds.option.from_json( ['b', False, None, 'bool', ['optional']] ).value_type(), 'boolean' )
with test.closure( 'enum' ):
test.check_equal( dds.option.from_json( ['e1', 'a', ['a','b','c'], 'c', 'enum'] ).value_type(), 'enum' )
test.check_equal( dds.option.from_json( ['e1', 'a', ['a','a','c'], 'c', 'enum'] ).value_type(), 'enum' )
test.check_throws( lambda:
dds.option.from_json( ['e1', 'd', [], 'c', 'enum'] ),
RuntimeError, 'invalid enum value: "c"' )
test.check_throws( lambda:
dds.option.from_json( ['e1', 'a', None, 'c', 'enum'] ),
RuntimeError, 'enum option requires a choices array' )
test.check_throws( lambda:
dds.option.from_json( ['e1', 'd', ['a','b','c'], 'c', 'enum'] ),
RuntimeError, 'invalid enum value: "d"' )
test.check_throws( lambda:
dds.option.from_json( ['e1', 'a', ['a','b','c'], 'd', 'enum'] ),
RuntimeError, 'invalid enum value: "d"' )
test.check_throws( lambda:
dds.option.from_json( ['e1', 'a', [None,'b','c'], 'd', 'enum'] ),
RuntimeError, 'enum choices must be strings' )
test.check_throws( lambda:
dds.option.from_json( ['e1', 1, [1,2,3], 3, 'enum'] ),
RuntimeError, 'non-string enum values' )
test.check_throws( lambda:
dds.option.from_json( ['e1', None, ['a','b','c'], 'c', 'enum'] ),
RuntimeError, 'value is not optional' )
test.check_equal( dds.option.from_json( ['e1', None, ['a','b','c'], 'c', 'enum', ['optional']] ).value_type(), 'enum' )
test.check_equal_lists(
dds.option.from_json( ['e1', None, ['a','b','c'], 'c', 'enum', ['optional']] ).to_json(),
['e1', None, ['a','b','c'], 'c', 'enum', ['optional']] )
with test.closure( 'r/o options are still settable' ):
# NOTE: the DDS options do not enforce logic post initialization; they serve only to COMMUNICATE any state and limits
test.check_equal( dds.option.from_json( ['1', 0, 'desc'] ).value_type(), 'int' )
dds.option.from_json( ['1', 0, 'desc'] ).set_value( 20. ) # OK because 20.0 can be expressed as int
test.check_throws( lambda:
dds.option.from_json( ['1', 0, 'desc'] ).set_value( 20.5 ),
RuntimeError, 'not convertible to a signed integer: 20.5' )
with test.closure( 'optional (default) value' ):
test.check_false( dds.option.from_json( ['1', 0, 'desc'] ).is_optional() )
test.check( dds.option.from_json( ['Asic Temperature',None,-40.0,125.0,0.0,0.0,'Current Asic Temperature (degree celsius)',['optional','read-only']] ).is_optional() )
dds.option.from_json( ['4', 'string-value', None, 'desc', ['optional']] )
dds.option.from_json( ['5', None, 'default-string-value', 'desc', ['optional']] ) # string type is deduced
test.check_throws( lambda:
dds.option.from_json( ['a', None, 'desc', ['optional']] ),
RuntimeError, 'cannot deduce value type: ["a",null,"desc",["optional"]]' )
test.check_equal_lists(
dds.option.from_json( ['Integer Option', None, None, 'Something', ['optional', 'int']] ).to_json(),
['Integer Option', None, None, 'Something', ['optional', 'int']] )
with test.closure( 'mixed types' ):
test.check_equal( dds.option.from_json( ['i', 0, 'desc'] ).value_type(), 'int' )
test.check_equal( dds.option.from_json( ['f', 0, 'desc', ['float']] ).value_type(), 'float' )
test.check_equal( dds.option.from_json( ['1', 0., 0, 1, 1, 0, 'desc'] ).value_type(), 'float' )
test.check_equal( dds.option.from_json( ['2', 0, 0., 1, 1, 0, 'desc'] ).value_type(), 'float' )
test.check_equal( dds.option.from_json( ['3', 0, 0, 1., 1, 0, 'desc'] ).value_type(), 'float' )
test.check_equal( dds.option.from_json( ['4', 0, 0, 1, 1., 0, 'desc'] ).value_type(), 'float' )
test.check_equal( dds.option.from_json( ['5', 0, 0, 1, 1, 0., 'desc'] ).value_type(), 'float' )
test.check_equal( dds.option.from_json( ['-1', 0, -1, 4, 1, 0, 'desc'] ).value_type(), 'int' )
test.check_equal( # float, but forced to an int
dds.option.from_json( ['3f', 3, 1, 5, 1, 2., '', ['int']] ).value_type(), 'int' )
test.check_throws( lambda: # same, but with an actual float
dds.option.from_json( ['3f', 3, 1, 5, 1, 2.2, '', ['int']] ),
RuntimeError, 'not convertible to a signed integer: 2.2' )
dds.option.from_json( ['a', 9223372036854775807, 'desc'] ) # max int64
test.check_throws( lambda:
dds.option.from_json( ['a', 9223372036854775808, 'desc'] ), # uint64
RuntimeError, 'not convertible to a signed integer: 9223372036854775808' )
dds.option.from_json( ['a', -9223372036854775808, 'desc'] ) # min int64
# -9223372036854775809 cannot be converted to json
test.check_equal( dds.option.from_json( ['Brightness',0,-64,64,1,0,'UVC image brightness'] ).value_type(), 'int' )
with test.closure( 'range' ):
test.check_throws( lambda:
dds.option.from_json( ['3x', 0, 0, -1, 1, 0, ''] ),
RuntimeError, 'default value 0 > -1 maximum' )
test.check_throws( lambda:
dds.option.from_json( ['3x', 0, 2, 3, 1, 0, ''] ),
RuntimeError, 'default value 0 < 2 minimum' )
test.check_throws( lambda:
dds.option.from_json( ['3y', -1, -2, 2, 1, 3, 'bad default'] ),
RuntimeError, 'default value 3 > 2 maximum' )
dds.option.from_json( ['3', -1, -2, 2, 1, 0, ''] )
dds.option.from_json( ['Backlight Compensation', 0, 0, 1, 1, 0, 'Backlight custom description'] )
dds.option.from_json( ['Custom Option', 5., -10, 10, 1, -5., 'Description'] )
with test.closure( 'IP address' ):
dds.option.from_json( ['ip', None, 'desc', ['IPv4', 'optional']] )
test.check_throws( lambda:
dds.option.from_json( ['ip', '', 'desc', ['IPv4']] ),
RuntimeError, 'not an IP address: ""' )
dds.option.from_json( ['ip', '0.0.0.0', 'desc', ['IPv4']] )
dds.option.from_json( ['ip', '255.255.255.255', 'desc', ['IPv4']] )
test.check_throws( lambda:
dds.option.from_json( ['ip', '255.255.255.256', 'desc', ['IPv4']] ),
RuntimeError, 'not an IP address: "255.255.255.256"' )
test.check_throws( lambda:
dds.option.from_json( ['ip', '255.255.256.255', 'desc', ['IPv4']] ),
RuntimeError, 'not an IP address: "255.255.256.255"' )
test.check_throws( lambda:
dds.option.from_json( ['ip', '255.256.255.255', 'desc', ['IPv4']] ),
RuntimeError, 'not an IP address: "255.256.255.255"' )
test.check_throws( lambda:
dds.option.from_json( ['ip', '256.255.255.255', 'desc', ['IPv4']] ),
RuntimeError, 'not an IP address: "256.255.255.255"' )
test.check_throws( lambda:
dds.option.from_json( ['ip', '1.2.3.4a', 'desc', ['IPv4']] ),
RuntimeError, 'not an IP address: "1.2.3.4a"' )
test.check_throws( lambda:
dds.option.from_json( ['ip', '1.2.3.4.', 'desc', ['IPv4']] ),
RuntimeError, 'not an IP address: "1.2.3.4."' )
test.check_throws( lambda:
dds.option.from_json( ['ip', '1.2..4', 'desc', ['IPv4']] ),
RuntimeError, 'not an IP address: "1.2..4"' )
test.check_throws( lambda:
dds.option.from_json( ['ip', '1.2.3.', 'desc', ['IPv4']] ),
RuntimeError, 'not an IP address: "1.2.3."' )
test.check_throws( lambda:
dds.option.from_json( ['ip', '1.2.3', 'desc', ['IPv4']] ),
RuntimeError, 'not an IP address: "1.2.3"' )
#############################################################################################
test.print_results()