229 lines
6.7 KiB
Python
229 lines
6.7 KiB
Python
import sys
|
|
sys.path.append('src/')
|
|
|
|
from protocol_components.dtypes import BprotoFieldBaseType
|
|
from protocol_components.enumeration import FactoryEnumeration, Enumeration
|
|
from errors import BprotoDuplicateNameError, BprotoDuplicateEnumValueError, BprotoCompilerError, BprotoEnumBitsizeTooLargeError
|
|
from nameHandling.base import NameStyleBproto, ComponentName
|
|
|
|
|
|
def test_enum_factory():
|
|
|
|
factory = FactoryEnumeration()
|
|
|
|
factory.add_value("X", 0)
|
|
factory.add_value("A", 1)
|
|
factory.add_value("C", 3)
|
|
factory.add_value("B", 2)
|
|
factory.add_value("D", None)
|
|
factory.add_value("E", 5)
|
|
factory.add_value("F", None)
|
|
|
|
enum = factory.assemble("TestEnum")
|
|
|
|
assert enum.name == "TestEnum"
|
|
assert enum.values == {
|
|
NameStyleBproto.fromStr("X"): 0,
|
|
NameStyleBproto.fromStr("A"): 1,
|
|
NameStyleBproto.fromStr("B"): 2,
|
|
NameStyleBproto.fromStr("C"): 3,
|
|
NameStyleBproto.fromStr("D"): 4,
|
|
NameStyleBproto.fromStr("E"): 5,
|
|
NameStyleBproto.fromStr("F"): 6
|
|
}
|
|
|
|
assert isinstance(enum.name, ComponentName)
|
|
assert isinstance(enum.get_name(), ComponentName)
|
|
assert isinstance(enum.get_identifier(), ComponentName)
|
|
assert isinstance(list(enum.values.keys())[0], ComponentName)
|
|
|
|
|
|
def test_enum_factory_failure_cases_dubplicate_value():
|
|
|
|
factory = FactoryEnumeration()
|
|
|
|
factory.add_value("X", 0)
|
|
factory.add_value("Y", 0)
|
|
factory.add_value("Z", 1)
|
|
|
|
try:
|
|
factory.assemble("TestEnum")
|
|
assert False
|
|
except BprotoCompilerError as e:
|
|
assert isinstance(e, BprotoDuplicateEnumValueError)
|
|
|
|
|
|
def test_enum_factory_failure_cases_duplicate_name():
|
|
factory = FactoryEnumeration()
|
|
|
|
factory.add_value("X", 0)
|
|
factory.add_value("Y", 1)
|
|
factory.add_value("Y", 2)
|
|
|
|
try:
|
|
factory.assemble("TestEnum")
|
|
assert False
|
|
except BprotoCompilerError as e:
|
|
assert isinstance(e, BprotoDuplicateNameError)
|
|
|
|
|
|
def test_enum_factory_failure_cases_duplicate_name_and_value():
|
|
factory = FactoryEnumeration()
|
|
|
|
factory.add_value("X", 0)
|
|
factory.add_value("X", 0)
|
|
|
|
try:
|
|
factory.assemble("TestEnum")
|
|
assert False
|
|
except BprotoCompilerError as e:
|
|
assert isinstance(e, BprotoDuplicateNameError) or isinstance(e, BprotoDuplicateEnumValueError)
|
|
|
|
|
|
def test_enum_sorted():
|
|
factory = FactoryEnumeration()
|
|
|
|
factory.add_value("X", 0)
|
|
factory.add_value("D", None)
|
|
factory.add_value("C", 3)
|
|
factory.add_value("E", 5)
|
|
factory.add_value("F", None)
|
|
factory.add_value("B", 2)
|
|
factory.add_value("A", 1)
|
|
|
|
enum = factory.assemble("TestEnum")
|
|
|
|
assert list(enum.values.values()) == list(range(7))
|
|
|
|
|
|
def test_enum_size_calc():
|
|
assert FactoryEnumeration.calculate_bitsize(list(range(17))) == 5
|
|
assert FactoryEnumeration.calculate_bitsize(list(range(16))) == 4
|
|
assert FactoryEnumeration.calculate_bitsize(list(range(9))) == 4
|
|
assert FactoryEnumeration.calculate_bitsize(list(range(8))) == 3
|
|
assert FactoryEnumeration.calculate_bitsize(list(range(7))) == 3
|
|
|
|
assert FactoryEnumeration.calculate_bitsize([1, 2, 31]) == 5
|
|
assert FactoryEnumeration.calculate_bitsize([1, 32, 2]) == 6
|
|
assert FactoryEnumeration.calculate_bitsize([127, 0, 2]) == 7
|
|
|
|
assert FactoryEnumeration.calculate_bitsize([]) == 1
|
|
|
|
|
|
def test_enum_auxiliary_data_typemap():
|
|
|
|
e = Enumeration("TestEnum", 8)
|
|
assert e.map_auxiliary_datatypes() == BprotoFieldBaseType.UINT8
|
|
|
|
e = Enumeration("TestEnum", 16)
|
|
assert e.map_auxiliary_datatypes() == BprotoFieldBaseType.UINT16
|
|
|
|
e = Enumeration("TestEnum", 24)
|
|
assert e.map_auxiliary_datatypes() == BprotoFieldBaseType.UINT32
|
|
|
|
e = Enumeration("TestEnum", 32)
|
|
assert e.map_auxiliary_datatypes() == BprotoFieldBaseType.UINT32
|
|
|
|
e = Enumeration("TestEnum", 64)
|
|
assert e.map_auxiliary_datatypes() == BprotoFieldBaseType.UINT64
|
|
|
|
e = Enumeration("TestEnum", 65)
|
|
try:
|
|
e.map_auxiliary_datatypes()
|
|
assert False
|
|
except Exception as err:
|
|
assert isinstance(err, BprotoEnumBitsizeTooLargeError)
|
|
|
|
|
|
def test_enum_size_calculation():
|
|
# Uint8
|
|
factory = FactoryEnumeration()
|
|
for i in range(3):
|
|
factory.add_value(f"#{i}", i)
|
|
e = factory.assemble("TestEnum")
|
|
assert e.get_size_bits() == 8
|
|
assert e.get_size_bytes() == 1
|
|
|
|
factory = FactoryEnumeration()
|
|
for i in range(2**8):
|
|
factory.add_value(f"#{i}", i)
|
|
e = factory.assemble("TestEnum")
|
|
assert e.get_size_bits() == 8
|
|
assert e.get_size_bytes() == 1
|
|
|
|
# Uint16
|
|
factory = FactoryEnumeration()
|
|
for i in range(2**8 + 1):
|
|
factory.add_value(f"#{i}", i)
|
|
e = factory.assemble("TestEnum")
|
|
assert e.get_size_bits() == 16
|
|
assert e.get_size_bytes() == 2
|
|
|
|
factory = FactoryEnumeration()
|
|
for i in range(2**16):
|
|
factory.add_value(f"#{i}", i)
|
|
e = factory.assemble("TestEnum")
|
|
assert e.get_size_bits() == 16
|
|
assert e.get_size_bytes() == 2
|
|
|
|
# Uint32
|
|
factory = FactoryEnumeration()
|
|
for i in range(17):
|
|
factory.add_value(f"#{i}", i)
|
|
factory.add_value(f"#{2**16}", 2**16)
|
|
# We start couinting from 0 -> 2**16 does not fit in 16 bits
|
|
|
|
e = factory.assemble("TestEnum")
|
|
assert e.get_size_bits() == 32
|
|
assert e.get_size_bytes() == 4
|
|
|
|
factory = FactoryEnumeration()
|
|
for i in range(17):
|
|
factory.add_value(f"#{i}", i)
|
|
factory.add_value(f"#{2**32 - 1}", 2**32 - 1)
|
|
# We start couinting from 0 2**32 - 1 does barely fit in 32 bits
|
|
|
|
e = factory.assemble("TestEnum")
|
|
assert e.get_size_bits() == 32
|
|
assert e.get_size_bytes() == 4
|
|
|
|
# Uint64
|
|
factory = FactoryEnumeration()
|
|
for i in range(17):
|
|
factory.add_value(f"#{i}", i)
|
|
factory.add_value(f"#{2**32}", 2**32)
|
|
# We start couinting from 0 -> 2**32 does not fit in 32 bits
|
|
|
|
e = factory.assemble("TestEnum")
|
|
assert e.get_size_bits() == 64
|
|
assert e.get_size_bytes() == 8
|
|
|
|
factory = FactoryEnumeration()
|
|
for i in range(17):
|
|
factory.add_value(f"#{i}", i)
|
|
factory.add_value(f"#{2**64 - 1}", 2**64 - 1)
|
|
# We start couinting from 0 2**64 - 1 does barely fit in 64 bits
|
|
|
|
e = factory.assemble("TestEnum")
|
|
assert e.get_size_bits() == 64
|
|
assert e.get_size_bytes() == 8
|
|
|
|
# Too large
|
|
factory = FactoryEnumeration()
|
|
for i in range(17):
|
|
factory.add_value(f"#{i}", i)
|
|
factory.add_value(f"#{2**64}", 2**64)
|
|
|
|
# This can cause rounding errors
|
|
# log2(2**64) ~ log2(2**64 - 1) ~ 64
|
|
# This is btw not a problem for 2**32
|
|
# stupid floating point errors
|
|
|
|
# We start couinting from 0 -> 2**64 does not fit in 64 bits
|
|
|
|
try:
|
|
e = factory.assemble("TestEnum")
|
|
assert False
|
|
except Exception as err:
|
|
assert isinstance(err, BprotoEnumBitsizeTooLargeError)
|