Init Commit: Moved bproto to seperate repo
This commit is contained in:
228
test/compiler/test_emums.py
Normal file
228
test/compiler/test_emums.py
Normal file
@@ -0,0 +1,228 @@
|
||||
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)
|
||||
Reference in New Issue
Block a user