Init Commit: Moved bproto to seperate repo

This commit is contained in:
AlexanderHD27
2025-04-14 14:43:03 +02:00
commit 45bfc724fc
125 changed files with 10822 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
import sys
import pytest
from typing import Any
sys.path.append('src/')
from protocol_components.dtypes import BprotoFieldBaseType
from parser.parser import create_ast_parser, bproto_ErrorListener
from parser.ast_visitor import BprotoASTVisitor
@pytest.mark.parametrize("source_text,expected_output", [
("uint64\n", (BprotoFieldBaseType.UINT64, 1, None)),
("float32\n", (BprotoFieldBaseType.FLOAT32, 1, None)),
("float32[8]\n", (BprotoFieldBaseType.FLOAT32, 8, None)),
])
def test_ast_field_dtype_defintion(
source_text: str,
expected_output: tuple[BprotoFieldBaseType, int, Any]):
err_listner = bproto_ErrorListener()
parser = create_ast_parser(source_text, err_listner)
ast = parser.dtype()
vinterp = BprotoASTVisitor()
assert len(err_listner.syntax_error_list) == 0
res = vinterp.visit(ast)
assert isinstance(res, tuple)
assert len(res) == 3
# Correct dtype
assert res[0] == expected_output[0].value
# Correct array size
assert res[1] == expected_output[1]
# Correct refrerence; Should normally be None be Non
assert res[2] == expected_output[2]

View File

@@ -0,0 +1,23 @@
import sys
sys.path.append('src/')
from parser.parser import create_ast_parser, bproto_ErrorListener
from parser.ast_visitor import BprotoASTVisitor
def test_ast_tag_line():
source = "protocol HCP version 25\n"
err_listner = bproto_ErrorListener()
parser = create_ast_parser(source, err_listner)
ast = parser.protocol_header()
vinterp = BprotoASTVisitor()
assert len(err_listner.syntax_error_list) == 0
res = vinterp.visit(ast)
assert isinstance(res, tuple)
assert len(res) == 2
name, version = res
assert name == "HCP"
assert version == 25

View File

@@ -0,0 +1,26 @@
import sys
from compiler import BprotoCompiler
sys.path.append('src/')
from errors import BprotoCompilerError
from backend.rendering.cBackend import CBackendRenderer
from backend.fsOutput import BackendFileSystemOutput
def test_compiler_c_smoke_test():
# Load Refernces
with open("test/test_protocol.bproto") as f:
source_text = f.read()
# Comile Stuff
compiler = BprotoCompiler([
CBackendRenderer(".")
], "template")
try:
output: BackendFileSystemOutput = compiler.compile(source_text, ".")
except BprotoCompilerError:
assert False, "This should run througth"
output.saveToDisk("test/backend_output/c")
output.toString()

View File

@@ -0,0 +1,59 @@
import sys
import pytest
from compiler import BprotoCompiler
sys.path.append('src/')
from errors import BprotoCompilerError
from backend.rendering.pythonBackend import PythonBackendRenderer
from backend.fsOutput import BackendFileSystemOutput
@pytest.mark.skip()
def test_compiler_python_against_ref():
# Load Refernces
with open("test/test_protocol.bproto") as f:
source_text = f.read()
# Comile Stuff
compiler = BprotoCompiler([
PythonBackendRenderer(".")
], "template")
try:
output: BackendFileSystemOutput = compiler.compile(source_text, ".")
except BprotoCompilerError:
assert False, "This should run througth"
output.saveToDisk("test/backend_output/python")
string_output = output.toString()
with open("test/reference/python/HCP_protocol_enum.py") as f:
assert f.read() == string_output.get("HCP_protocol_enum.py")
with open("test/reference/python/HCP_protocol_bitfield.py") as f:
assert f.read() == string_output.get("HCP_protocol_bitfield.py")
with open("test/reference/python/HCP_protocol_message_ids.py") as f:
assert f.read() == string_output.get("HCP_protocol_message_ids.py")
with open("test/reference/python/HCP_protocol_packets.py") as f:
assert f.read() == string_output.get("HCP_protocol_packets.py")
def test_compiler_python_smoke_test():
# Load Refernces
with open("test/test_protocol.bproto") as f:
source_text = f.read()
# Comile Stuff
compiler = BprotoCompiler([
PythonBackendRenderer(".")
], "template")
try:
output: BackendFileSystemOutput = compiler.compile(source_text, ".")
except BprotoCompilerError:
assert False, "This should run througth"
output.saveToDisk("test/backend_output/python")
output.toString()

View File

@@ -0,0 +1,32 @@
import sys
from compiler import BprotoCompiler
sys.path.append('src/')
from errors import BprotoCompilerError
from backend.rendering.txtBackend import TxtBackendRenderer
from backend.fsOutput import BackendFileSystemOutput
def test_compiler_txt_against_ref():
with open("test/test_protocol.bproto") as f:
source_text = f.read()
# Comile Stuff
compiler = BprotoCompiler([
TxtBackendRenderer(".")
], "template")
try:
output: BackendFileSystemOutput = compiler.compile(source_text, ".")
except BprotoCompilerError:
assert False, "This should run througth"
string_output = output.toString()
output.saveToDisk("test/backend_output/txt")
# Load Refernces
with open("test/reference/txt/protocolSummary.txt") as f:
expected_output = f.read()
assert isinstance(string_output.get("protocolSummary.txt"), str)
assert string_output.get("protocolSummary.txt") == expected_output

View File

@@ -0,0 +1,168 @@
import sys
import os
import pytest
import shutil
from jinja2 import Environment, FileSystemLoader, select_autoescape
sys.path.append('src/')
from backend.fsOutput import BackendFSOutFile, BackendFSOutStaticConent, BackendFSOutFolder, BackendFSOutputJinjaFile
TEST_FOLDER = "/tmp/protocolGenerator_test_data"
@pytest.fixture
def filesystem_folder():
yield TEST_FOLDER
shutil.rmtree(TEST_FOLDER)
print("Cleanup done")
def test_fsOutput_saveToDisk(filesystem_folder: str):
jinja_env = Environment(
loader=FileSystemLoader("test/data/templates/"),
autoescape=select_autoescape()
)
# Setup
root_folder = BackendFSOutFolder("root", [
BackendFSOutFile("file1", "some content"),
BackendFSOutFile("file2", "some other content"),
BackendFSOutFolder("subfolder", [
BackendFSOutFile("file3", "some more content #2"),
BackendFSOutFile("file4", "even more content"),
]),
BackendFSOutStaticConent("test/data/static_folder/static_content2.txt", "static_content2.txt"),
BackendFSOutStaticConent("test/data/static_content1.txt", "static_content1.txt"),
BackendFSOutputJinjaFile(jinja_env, "template.jinja2", "template.txt", {"name": "World"})
])
root_folder.saveToDisk(filesystem_folder)
# Test Structure
assert os.path.isdir(filesystem_folder)
assert os.path.isfile(filesystem_folder + "/root/file1")
assert os.path.isfile(filesystem_folder + "/root/file2")
assert os.path.isdir(filesystem_folder + "/root/subfolder")
assert os.path.isfile(filesystem_folder + "/root/subfolder/file3")
assert os.path.isfile(filesystem_folder + "/root/subfolder/file4")
assert os.path.isfile(filesystem_folder + "/root/static_content1.txt")
assert os.path.isfile(filesystem_folder + "/root/static_content2.txt")
assert os.path.isfile(filesystem_folder + "/root/template.txt")
# Test Content
with open(filesystem_folder + "/root/file1", "r") as f:
assert f.read() == "some content"
with open(filesystem_folder + "/root/file2", "r") as f:
assert f.read() == "some other content"
with open(filesystem_folder + "/root/subfolder/file3", "r") as f:
assert f.read() == "some more content #2"
with open(filesystem_folder + "/root/subfolder/file4", "r") as f:
assert f.read() == "even more content"
with open(filesystem_folder + "/root/static_content1.txt", "r") as f:
assert f.read() == "test1"
with open(filesystem_folder + "/root/static_content2.txt", "r") as f:
assert f.read() == "test2"
with open(filesystem_folder + "/root/template.txt", "r") as f:
assert f.read() == "Hello World!"
def test_fsOutput_treeString():
jinja_env = Environment(
loader=FileSystemLoader("test/data/templates/"),
autoescape=select_autoescape()
)
root_folder = BackendFSOutFolder("root", [
BackendFSOutFile("file1", "some content"),
BackendFSOutFile("file2", "some other content"),
BackendFSOutFolder("subfolder", [
BackendFSOutFile("file3", "some more content #2"),
BackendFSOutFile("file4", "even more content"),
BackendFSOutputJinjaFile(jinja_env, "template.jinja", "generate", {"name": "Jinja2"})
]),
BackendFSOutStaticConent("test/data/static_folder", "data"),
BackendFSOutputJinjaFile(jinja_env, "template.jinja", None, {"name": "World"})
])
string = root_folder.assemble_file_tree_string()
assert string == """└── root
├── [file1]
├── [file2]
├── subfolder
│ ├── [file3]
│ ├── [file4]
│ └── Template [generate]
├── Static [data]
└── Template [template]
"""
def test_fsOutput_toString():
jinja_env = Environment(
loader=FileSystemLoader("test/data/templates/"),
autoescape=select_autoescape()
)
root_folder = BackendFSOutFolder("root", [
BackendFSOutFile("file1", "some content"),
BackendFSOutFile("file2", "some other content"),
BackendFSOutFolder("subfolder", [
BackendFSOutFile("file3", "some more content #2"),
BackendFSOutFile("file4", "even more content"),
BackendFSOutputJinjaFile(jinja_env, "template.jinja2", "generate", {"name": "Jinja2"})
]),
BackendFSOutStaticConent("test/data/static_folder", "data/static_folder"),
BackendFSOutStaticConent("test/data/static_content1.txt", "data"),
BackendFSOutputJinjaFile(jinja_env, "template.jinja2", None, {"name": "World"})
])
res = root_folder.toString()
assert res == {
"root/file1": "some content",
"root/file2": "some other content",
"root/subfolder/file3": "some more content #2",
"root/subfolder/file4": "even more content",
"root/subfolder/generate": "Hello Jinja2!",
"root/data/static_content1.txt": "test1",
"root/data/static_folder/static_content2.txt": "test2",
"root/template": "Hello World!"
}
def test_fsOutput_pathnormalization(filesystem_folder: str):
root_folder = BackendFSOutFolder(".", [
BackendFSOutFolder(".", [
BackendFSOutFile("file2", "some other content"),
]),
BackendFSOutFile("file1", "some content"),
])
# Check if this works for toString
res = root_folder.toString()
assert res == {
"file2": "some other content",
"file1": "some content"
}
# Check if this works for saveToDisk
root_folder.saveToDisk(filesystem_folder)
assert os.path.isfile(filesystem_folder + "/file1")
assert os.path.isfile(filesystem_folder + "/file2")
with open(filesystem_folder + "/file1", "r") as f:
assert f.read() == "some content"
with open(filesystem_folder + "/file2", "r") as f:
assert f.read() == "some other content"

View File

@@ -0,0 +1,49 @@
import sys
sys.path.append('src/')
from nameHandling.base import ComponentName, NameStyleBproto
def test_component_name():
assert ComponentName(["test"]) != 1234
assert ComponentName(["test"]) == ComponentName(["test"])
assert ComponentName(["test"]) != ComponentName(["test", "test"])
assert hash(ComponentName(["test"])) == hash(ComponentName(["test"]))
assert hash(ComponentName(["test"])) != hash(ComponentName(["test", "test"]))
assert repr(ComponentName(["test"])) == "ComponentName(Test)"
assert repr(ComponentName(["test", "test"])) == "ComponentName(Test-Test)"
def test_ComponentNameStyleBproto():
assert NameStyleBproto.fromStr("test") == ComponentName(["test"])
assert NameStyleBproto.fromStr("ThisIsATest") == ComponentName(["this", "is", "a", "test"])
assert NameStyleBproto.fromStr("thisIsATest") == ComponentName(["this", "is", "a", "test"])
assert NameStyleBproto.fromStr("this-is-a-test") == ComponentName(["this", "is", "a", "test"])
assert NameStyleBproto.fromStr("this-Is-A-test") == ComponentName(["this", "is", "a", "test"])
assert NameStyleBproto.fromStr("this_is_a_test") == ComponentName(["this", "is", "a", "test"])
assert NameStyleBproto.fromStr("this_Is_a_Test") == ComponentName(["this", "is", "a", "test"])
assert NameStyleBproto.fromStr("this-Is_ATest") == ComponentName(["this", "is", "a", "test"])
assert NameStyleBproto.fromStr("ThisIs-A_test") == ComponentName(["this", "is", "a", "test"])
def test_ComponentNameStyleBproto_context_enum():
assert NameStyleBproto.fromStr("test", "enum") == ComponentName(["test"])
assert NameStyleBproto.fromStr("ThisIsATest", "enum") == ComponentName(["thisisatest"])
assert NameStyleBproto.fromStr("TESTTEST", "enum") == ComponentName(["testtest"])
assert NameStyleBproto.fromStr("TEST_TEST", "enum") == ComponentName(["test", "test"])
def test_ComponentNameStyleBproto_comparison():
c = NameStyleBproto.fromStr("ThisIsATest")
assert c == "this-is-a-test"
assert c == "this_is_a_test"
assert c == "thisIsATest"
assert c == "ThisIsATest"
assert c == "This_Is_A_Test"
def test_ComponentNameStyleBproto_from_Component():
c = ComponentName(["this", "is", "a", "test"])
c2 = NameStyleBproto.fromStr(c)
assert c == c2

View File

@@ -0,0 +1,40 @@
import sys
sys.path.append('src/')
from nameHandling.brand_applier import BrandApplier
from protocol_components.message import Message
from nameHandling.base import ComponentName
def test_name_applier():
protocolNameApplier = BrandApplier("brand")
name = ComponentName(["test"])
name = protocolNameApplier.apply(name)
assert name == ComponentName(["brand", "test"])
name = ComponentName(["test", "test"])
name = protocolNameApplier.apply(name)
assert name == ComponentName(["brand", "test", "test"])
msg = Message(ComponentName(["this", "is", "a", "test"]), 0)
msg: Message = protocolNameApplier.apply(msg)
assert msg.name == ComponentName(["brand", "this", "is", "a", "test"])
protocolNameApplier = BrandApplier(ComponentName(["happy", "brand"]))
msg = Message(ComponentName(["this", "is", "a", "test"]), 0)
msg: Message = protocolNameApplier.apply(msg)
assert msg.name == ComponentName(["happy", "brand", "this", "is", "a", "test"])
try:
protocolNameApplier.apply(None)
assert False
except Exception as e:
assert isinstance(e, TypeError)
try:
protocolNameApplier = BrandApplier(None)
assert False
except Exception as e:
assert isinstance(e, TypeError)

View File

@@ -0,0 +1,73 @@
import sys
sys.path.append('src/')
from nameHandling.base import ComponentName
from protocol_components.protocolFactory import FactoryProtocolDefition
from protocol_components.enumeration import FactoryEnumeration, Enumeration
from protocol_components.bitfields import FactoryBitfield, Bitfield
from protocol_components.dtypes import BprotoFieldBaseType
from protocol_components.field import FactoryField
from protocol_components.message import FactoryMessage, Message
from nameHandling.style.cNameStyle import NameStyleC
def test_style_c_fromStr():
try:
NameStyleC.fromStr("")
assert False
except Exception as e:
assert isinstance(e, NotImplementedError)
def test_style_c_toStr_enum():
assert NameStyleC.toStr(ComponentName(["my", "custom", "Values"]), "enum_name") == "MyCustomValues"
assert NameStyleC.toStr(ComponentName(["my", "custom", "enum", "value"]), "enum_item") == "MY_CUSTOM_ENUM_VALUE"
assert NameStyleC.toStr(ComponentName(["my", "custom", "class"]), "struct_name") == "MyCustomClass"
assert NameStyleC.toStr(ComponentName(["my", "custom", "class", "member"]), "struct_member") == "myCustomClassMember"
assert NameStyleC.toStr(ComponentName(["my", "custom", "class"]), "bitfield_name") == "MyCustomClass"
assert NameStyleC.toStr(ComponentName(["my", "custom", "class", "member"]), "bitfield_member") == "myCustomClassMember"
def test_style_c_preprocessor():
protocol_factory = FactoryProtocolDefition()
enum_factory = FactoryEnumeration()
enum_factory.add_value("first-Value", 1)
enum_factory.add_value("second-Important-Value", 2)
protocol_factory.add_enum(enum_factory.assemble("mode"))
bitfield_factory = FactoryBitfield()
bitfield_factory.add_bit("FirstBit", 0)
bitfield_factory.add_bit("SecondBit", 1)
protocol_factory.add_bitfield(bitfield_factory.assemble("bitfield1"))
message_factory = FactoryMessage()
message_factory.add_field(FactoryField().assemble("x", 1, BprotoFieldBaseType.FLOAT32, 2, None))
message_factory.add_field(FactoryField().assemble("y", 2, BprotoFieldBaseType.FLOAT32, 2, None))
protocol_factory.add_message(message_factory.assemble("cordUpdate", 1))
protocol = protocol_factory.assemble("ABCP", 5)
protocol = NameStyleC.preprocess(protocol)
enum: Enumeration = list(protocol.enums.values())[0]
bitfield: Bitfield = list(protocol.bitfields.values())[0]
message: Message = list(protocol.messages.values())[0]
assert isinstance(enum, Enumeration)
assert isinstance(bitfield, Bitfield)
assert isinstance(message, Message)
assert NameStyleC.toStr(enum.name, "enum_name") == "Abcp_enum_Mode"
assert NameStyleC.toStr(bitfield.name, "bitfield_name") == "Abcp_bitfield_Bitfield1"
assert NameStyleC.toStr(message.name, "struct_name") == "Abcp_message_CordUpdate"
assert enum.values == {
ComponentName(["abcp", "_enum_", "mode", "value", "first", "value"]): 1,
ComponentName(["abcp", "_enum_", "mode", "value", "second", "important", "value"]): 2
}
assert bitfield.bits == {
ComponentName(["first", "bit"]): 0,
ComponentName(["second", "bit"]): 1
}

View File

@@ -0,0 +1,59 @@
import sys
sys.path.append('src/')
from nameHandling.base import ComponentName
from protocol_components.protocolFactory import FactoryProtocolDefition
from protocol_components.enumeration import FactoryEnumeration, Enumeration
from protocol_components.bitfields import FactoryBitfield, Bitfield
from protocol_components.dtypes import BprotoFieldBaseType
from protocol_components.field import FactoryField
from protocol_components.message import FactoryMessage, Message
from nameHandling.style.pythonNameStyle import NameStylePython
def test_style_python_fromStr():
try:
NameStylePython.fromStr("")
assert False
except Exception as e:
assert isinstance(e, NotImplementedError)
def test_style_python_toStr_enum():
assert NameStylePython.toStr(ComponentName(["my", "custom", "enum"]), "enum_name") == "MyCustomEnum"
assert NameStylePython.toStr(ComponentName(["my", "custom", "enum", "value"]), "enum_item") == "MY_CUSTOM_ENUM_VALUE"
assert NameStylePython.toStr(ComponentName(["my", "custom", "class"]), "class_name") == "MyCustomClass"
assert NameStylePython.toStr(ComponentName(["my", "custom", "class", "member"]), "class_member") == "my_custom_class_member"
def test_style_python_preprocessor():
protocol_factory = FactoryProtocolDefition()
enum_factory = FactoryEnumeration()
enum_factory.add_value("first-Value", 1)
enum_factory.add_value("second-Important-Value", 2)
protocol_factory.add_enum(enum_factory.assemble("mode"))
bitfield_factory = FactoryBitfield()
bitfield_factory.add_bit("FirstBit", 0)
bitfield_factory.add_bit("SecondBit", 1)
protocol_factory.add_bitfield(bitfield_factory.assemble("bitfield1"))
message_factory = FactoryMessage()
message_factory.add_field(FactoryField().assemble("x", 1, BprotoFieldBaseType.FLOAT32, 2, None))
message_factory.add_field(FactoryField().assemble("y", 2, BprotoFieldBaseType.FLOAT32, 2, None))
protocol_factory.add_message(message_factory.assemble("cordUpdate", 1))
protocol = protocol_factory.assemble("HCPT", 5)
protocol = NameStylePython.preprocess(protocol)
enum: Enumeration = list(protocol.enums.values())[0]
bitfield: Bitfield = list(protocol.bitfields.values())[0]
message: Message = list(protocol.messages.values())[0]
assert isinstance(enum, Enumeration)
assert isinstance(bitfield, Bitfield)
assert NameStylePython.toStr(enum.name, "enum_name") == "HcptEnumMode"
assert NameStylePython.toStr(bitfield.name, "class_name") == "HcptBitfieldBitfield1"
assert NameStylePython.toStr(message.name, "class_name") == "HcptMessageCordUpdate"

View File

@@ -0,0 +1,80 @@
import sys
sys.path.append('src/')
from nameHandling.base import ComponentName
from protocol_components.bitfields import FactoryBitfield, Bitfield
from errors import BprotoDuplicateNameError, BprotoDuplicateBitfieldPositionError, BprotoCompilerError
from nameHandling.base import NameStyleBproto
def test_bitfield_factory():
fatory = FactoryBitfield()
fatory.add_bit("BIT #1", 0)
fatory.add_bit("BIT #4", None)
fatory.add_bit("BIT #2", 1)
fatory.add_bit("BIT #5", 4)
fatory.add_bit("BIT #6", None)
fatory.add_bit("BIT #3", 2)
fatory.add_bit("BIT #7", 6)
bitfield: Bitfield = fatory.assemble("TestBitfield")
assert bitfield.name == "TestBitfield"
assert isinstance(bitfield.name, ComponentName)
assert isinstance(bitfield.get_name(), ComponentName)
assert isinstance(bitfield.get_identifier(), ComponentName)
assert bitfield.bits == {
NameStyleBproto.fromStr("BIT #1"): 0,
NameStyleBproto.fromStr("BIT #2"): 1,
NameStyleBproto.fromStr("BIT #3"): 2,
NameStyleBproto.fromStr("BIT #4"): 3,
NameStyleBproto.fromStr("BIT #5"): 4,
NameStyleBproto.fromStr("BIT #6"): 5,
NameStyleBproto.fromStr("BIT #7"): 6,
}
assert isinstance(list(bitfield.bits.keys())[0], ComponentName)
def test_bitfield_factory_failure_cases_duplicate_name():
factory = FactoryBitfield()
factory.add_bit("BIT #1", 0)
factory.add_bit("BIT #1", 1)
factory.add_bit("BIT #2", 2)
try:
factory.assemble("TestBitfield")
assert False
except BprotoCompilerError as e:
assert isinstance(e, BprotoDuplicateNameError)
def test_bitfield_factory_failure_cases_duplicate_position():
factory = FactoryBitfield()
factory.add_bit("BIT #1", 0)
factory.add_bit("BIT #2", 1)
factory.add_bit("BIT #3", 1)
try:
factory.assemble("TestBitfield")
assert False
except BprotoCompilerError as e:
assert isinstance(e, BprotoDuplicateBitfieldPositionError)
def test_bitfield_size_calculation():
bitfield = Bitfield("TestBitfield")
bitfield.length = 7
assert bitfield.get_size_bytes() == 1
bitfield.length = 0
assert bitfield.get_size_bytes() == 1
bitfield.length = 8
assert bitfield.get_size_bytes() == 1
bitfield.length = 9
assert bitfield.get_size_bytes() == 2

View File

@@ -0,0 +1,73 @@
from nameHandling.base import ComponentName, NameStyleBproto
from nameHandling.style.pythonNameStyle import NameStylePython
from protocol_components.enumeration import FactoryEnumeration
from copy import deepcopy
def test_deepcopy_component_name():
name = ComponentName(["This", "Is", "Some", "text"], NameStylePython, source_string="ThisIsSomeText")
new_name = deepcopy(name)
name.name_parts = ["Some", "Other", "Stuff"]
name.source_string = "SomeOtherStuff"
name.source_style = NameStyleBproto
# Verify Values did not change
assert name.name_parts != new_name.name_parts
assert name.source_string != new_name.source_string
assert name.source_style != new_name.source_style
def test_deepcopy_enum():
old_enum_factory = FactoryEnumeration()
old_enum_factory.add_value("Value1", 1)
old_enum_factory.add_value("Value2", 2)
old_enum_factory.add_value("Value3", 3)
old_enum = old_enum_factory.assemble("OldEnum")
new_enum = deepcopy(old_enum)
# Check ids
assert id(new_enum) != id(old_enum)
assert id(new_enum.name) != id(old_enum.name)
assert id(old_enum.values) != id(new_enum.values)
old_keys = list(old_enum.values.keys())
new_keys = list(new_enum.values.keys())
assert id(old_keys[0]) != id(new_keys[0])
assert id(old_keys[1]) != id(new_keys[1])
assert id(old_keys[2]) != id(new_keys[2])
def test_deepcopy_component_names_memo():
name1 = NameStyleBproto.fromStr("Value1")
name2 = NameStyleBproto.fromStr("Value2")
assert id(name1) != id(name2)
name1_copy = deepcopy(name1)
assert isinstance(name1_copy, ComponentName)
assert name1_copy == name1
assert id(name1_copy) != id(name1)
name1_copy2 = deepcopy(name1, {
id(name1): name1_copy,
id(name1_copy): name1_copy
})
name1_copy3 = deepcopy(name1_copy, {
id(name1): name1_copy,
id(name1_copy): name1_copy
})
assert isinstance(name1_copy2, ComponentName)
assert isinstance(name1_copy3, ComponentName)
assert id(name1_copy) == id(name1_copy2)
assert id(name1_copy2) != id(name1)
assert id(name1_copy) == id(name1_copy3)
assert id(name1_copy3) != id(name1)

228
test/compiler/test_emums.py Normal file
View 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)

View File

@@ -0,0 +1,98 @@
import sys
sys.path.append('src/')
from protocol_components.dtypes import BprotoFieldBaseType, BprotoArrayPolicyViolationError, BprotoUnknownDataTypeError
from protocol_components.field import Field, FactoryField, FieldBitfield, FieldBitfieldRef
from protocol_components.bitfields import Bitfield
from nameHandling.base import ComponentName
def test_field_object():
field = Field("field1", 3, BprotoFieldBaseType.UINT64, 4)
assert field.name == "field1"
assert field.pos == 3
assert field.type == BprotoFieldBaseType.UINT64
assert field.array_size == 4
assert field.get_identifier() == "field1"
assert field.get_name() == "field1"
assert field.get_type_name() == "field"
assert field.get_size_bytes() == 8 * 4
assert field.get_size_bits() == 64 * 4
def test_field_factory():
factory = FactoryField()
field: Field = factory.assemble("field1", 3, BprotoFieldBaseType.UINT64.value, 4, None)
assert isinstance(field, Field)
assert field.name == "field1"
assert field.pos == 3
assert field.type == BprotoFieldBaseType.UINT64
assert field.array_size == 4
assert isinstance(field.name, ComponentName)
assert isinstance(field.get_identifier(), ComponentName)
assert isinstance(field.get_name(), ComponentName)
assert isinstance(field.get_type_name(), str)
def test_field_factory_errors_invalid_datatype():
factory = FactoryField()
try:
factory.assemble(
"field1", 3, "junkDataType", 4, None
)
assert False
except BprotoUnknownDataTypeError:
assert True
except Exception as e:
assert False, f"Unexpected exception: {e}"
def test_field_factory_errors_invalid_array_policy():
factory = FactoryField()
try:
factory.assemble(
"field1", 1, BprotoFieldBaseType.BITFIELD, 4, None
)
assert False
except BprotoArrayPolicyViolationError:
assert True
except Exception as e:
assert False, f"Unexpected exception: {e}"
def test_field_factory_bitfield():
factory = FactoryField()
field: FieldBitfield = factory.assemble(
"field1", 3, BprotoFieldBaseType.BITFIELD, 1,
Bitfield("test")
)
assert isinstance(field, FieldBitfield)
assert field.name == "field1"
assert field.pos == 3
assert field.type == BprotoFieldBaseType.BITFIELD
assert field.array_size == 1
assert isinstance(field.bitfield, Bitfield)
assert field.bitfield.get_name() == "test"
def test_field_factory_bitfield_ref():
factory = FactoryField()
field: FieldBitfield = factory.assemble(
"field1", 3, BprotoFieldBaseType.BITFIELD, 1,
"test"
)
assert isinstance(field, FieldBitfieldRef)
assert field.name == "field1"
assert field.pos == 3
assert field.type == BprotoFieldBaseType.BITFIELD
assert field.array_size == 1
assert field.ref == "test"

View File

@@ -0,0 +1,71 @@
import sys
sys.path.append('src/')
from nameHandling.base import ComponentName, NameStyleBproto
from protocol_components.message import FactoryMessage, Message
from protocol_components.field import FactoryField
from errors import BprotoDuplicateNameError, BprotoMessageIDAlreadyUsed
def test_message_factory():
factory = FactoryMessage()
field1 = FactoryField().assemble("field1", 0, "uint64", 4, None)
field2 = FactoryField().assemble("field2", 1, "uint64", 4, None)
field3 = FactoryField().assemble("field3", 2, "uint64", 4, None)
field4 = FactoryField().assemble("field4", 3, "uint64", 4, None)
factory.add_field(field3)
factory.add_field(field2)
factory.add_field(field4)
factory.add_field(field1)
message: Message = factory.assemble("TestMessage", 42)
assert message.name == "TestMessage"
assert isinstance(message.name, ComponentName)
assert isinstance(message.get_name(), ComponentName)
assert message.message_index_number == 42
assert message.get_identifier() == 42
assert message.fields == {
NameStyleBproto.fromStr("field1"): field1,
NameStyleBproto.fromStr("field2"): field2,
NameStyleBproto.fromStr("field3"): field3,
NameStyleBproto.fromStr("field4"): field4
}
assert isinstance(list(message.fields.keys())[0], ComponentName)
assert message.get_size_bytes() == 8 * 4 * 4
assert message.get_size_bits() == 64 * 4 * 4
def test_message_factory_error_duplicate_name():
field1 = FactoryField().assemble("field1", 0, "uint64", 4, None)
field2 = FactoryField().assemble("field1", 1, "uint64", 4, None)
factory = FactoryMessage()
factory.add_field(field1)
factory.add_field(field2)
try:
factory.assemble("TestMessage", 42)
assert False
except Exception as e:
assert isinstance(e, BprotoDuplicateNameError)
def test_message_factory_error_duplicate_index():
field1 = FactoryField().assemble("field1", 0, "uint64", 4, None)
field2 = FactoryField().assemble("field2", 0, "uint64", 4, None)
factory = FactoryMessage()
factory.add_field(field1)
factory.add_field(field2)
try:
factory.assemble("TestMessage", 42)
assert False
except Exception as e:
assert isinstance(e, BprotoMessageIDAlreadyUsed)

View File

@@ -0,0 +1,181 @@
import sys
sys.path.append('src/')
from protocol_components.dtypes import BprotoFieldBaseType
from nameHandling.base import ComponentName, NameStyleBproto
from protocol_components.message import FactoryMessage
from protocol_components.enumeration import FactoryEnumeration, Enumeration
from protocol_components.bitfields import FactoryBitfield, Bitfield
from protocol_components.protocolFactory import FactoryProtocolDefition
from protocol_components.field import FactoryField, Field, FieldEnum, FieldBitfield, FieldEnumRef, FieldBitfieldRef
from errors import BprotoUnresolvedReferenceError, BprotoAlreadyDefinedError
from nameHandling.resolver import ProtocolReferenceResolver
def test_protocol_factory():
factory = FactoryProtocolDefition()
factory.add_message(FactoryMessage().assemble("Message1", 42))
factory.add_message(FactoryMessage().assemble("Message2", 43))
message_with_fields_factory = FactoryMessage()
message_with_fields_factory.add_field(FactoryField().assemble("field1", 0, "uint64", 1, None))
message_with_fields_factory.add_field(FactoryField().assemble("enum_ref", 1, BprotoFieldBaseType.ENUM, 1, "Enum1"))
message_with_fields_factory.add_field(FactoryField().assemble("bitfield_ref", 2, BprotoFieldBaseType.BITFIELD, 1, "Bitfield2"))
factory.add_message(
message_with_fields_factory.assemble("Message3", 44)
)
factory.add_enum(FactoryEnumeration().assemble("Enum1"))
factory.add_enum(FactoryEnumeration().assemble("Enum2"))
factory.add_enum(FactoryEnumeration().assemble("Enum3"))
factory.add_bitfield(FactoryBitfield().assemble("Bitfield1"))
factory.add_bitfield(FactoryBitfield().assemble("Bitfield2"))
factory.add_bitfield(FactoryBitfield().assemble("Bitfield3"))
protocol = factory.assemble("TESTPROTOCOL", 1)
assert protocol.name.name_parts == ["testprotocol"]
assert isinstance(protocol.name, ComponentName)
assert protocol.version == 1
assert protocol.messages == {
NameStyleBproto.fromStr("Message1"): factory.messages.get(NameStyleBproto.fromStr("Message1")),
NameStyleBproto.fromStr("Message2"): factory.messages.get(NameStyleBproto.fromStr("Message2")),
NameStyleBproto.fromStr("Message3"): factory.messages.get(NameStyleBproto.fromStr("Message3"))
}
assert protocol.enums == {
NameStyleBproto.fromStr("Enum1"): factory.enums.get(NameStyleBproto.fromStr("Enum1")),
NameStyleBproto.fromStr("Enum2"): factory.enums.get(NameStyleBproto.fromStr("Enum2")),
NameStyleBproto.fromStr("Enum3"): factory.enums.get(NameStyleBproto.fromStr("Enum3"))
}
assert protocol.bitfields == {
NameStyleBproto.fromStr("Bitfield1"): factory.bitfields.get(NameStyleBproto.fromStr("Bitfield1")),
NameStyleBproto.fromStr("Bitfield2"): factory.bitfields.get(NameStyleBproto.fromStr("Bitfield2")),
NameStyleBproto.fromStr("Bitfield3"): factory.bitfields.get(NameStyleBproto.fromStr("Bitfield3"))
}
# Check if references are resolved works
assert isinstance(protocol.messages.get(NameStyleBproto.fromStr("Message3")).fields.get(NameStyleBproto.fromStr("enum_ref")), FieldEnum)
assert isinstance(protocol.messages.get(NameStyleBproto.fromStr("Message3")).fields.get(NameStyleBproto.fromStr("bitfield_ref")), FieldBitfield)
def test_protocol_resolve_refernces():
enum1 = FactoryEnumeration().assemble("Enum1")
bitfield1 = FactoryBitfield().assemble("Bitfield1")
message1Factory = FactoryMessage()
message1Factory.add_field(FactoryField().assemble("field1", 0, "uint64", 1, None))
message1Factory.add_field(FactoryField().assemble("enum_field", 1, BprotoFieldBaseType.ENUM, 1, enum1))
message1Factory.add_field(FactoryField().assemble("enum_ref_field", 2, BprotoFieldBaseType.ENUM, 1, "Enum1"))
message1Factory.add_field(FactoryField().assemble("bitfield_field", 3, BprotoFieldBaseType.BITFIELD, 1, bitfield1))
message1Factory.add_field(FactoryField().assemble("bitfield_ref_field", 4, BprotoFieldBaseType.BITFIELD, 1, "Bitfield1"))
message1 = message1Factory.assemble("Message1", 42)
# Check if message is correctly assembled
assert isinstance(message1.fields.get(NameStyleBproto.fromStr("field1")), Field)
assert message1.fields.get(NameStyleBproto.fromStr("field1")).type == BprotoFieldBaseType.UINT64
assert message1.fields.get(NameStyleBproto.fromStr("field1")).array_size == 1
assert message1.fields.get(NameStyleBproto.fromStr("field1")).ref is None
assert isinstance(message1.fields.get(NameStyleBproto.fromStr("field1")).ref, type(None))
assert isinstance(message1.fields.get(NameStyleBproto.fromStr("enum_field")), FieldEnum)
assert message1.fields.get(NameStyleBproto.fromStr("enum_field")).type == BprotoFieldBaseType.ENUM
assert isinstance(message1.fields.get(NameStyleBproto.fromStr("enum_field")).enum, Enumeration)
assert message1.fields.get(NameStyleBproto.fromStr("enum_field")).enum == enum1
assert isinstance(message1.fields.get(NameStyleBproto.fromStr("enum_ref_field")), FieldEnumRef)
assert message1.fields.get(NameStyleBproto.fromStr("enum_ref_field")).type == BprotoFieldBaseType.ENUM
assert message1.fields.get(NameStyleBproto.fromStr("enum_ref_field")).ref == "Enum1"
assert isinstance(message1.fields.get(NameStyleBproto.fromStr("bitfield_field")), FieldBitfield)
assert message1.fields.get(NameStyleBproto.fromStr("bitfield_field")).type == BprotoFieldBaseType.BITFIELD
assert isinstance(message1.fields.get(NameStyleBproto.fromStr("bitfield_field")).bitfield, Bitfield)
assert message1.fields.get(NameStyleBproto.fromStr("bitfield_field")).bitfield == bitfield1
assert isinstance(message1.fields.get(NameStyleBproto.fromStr("bitfield_ref_field")), FieldBitfieldRef)
assert message1.fields.get(NameStyleBproto.fromStr("bitfield_ref_field")).type == BprotoFieldBaseType.BITFIELD
assert message1.fields.get(NameStyleBproto.fromStr("bitfield_ref_field")).ref == "Bitfield1"
factory = FactoryProtocolDefition()
factory.add_message(message1)
factory.add_enum(enum1)
factory.add_bitfield(bitfield1)
protocol = factory.assemble("TestProtocol", 1)
# Check if references are resolved works
resolver = ProtocolReferenceResolver(protocol)
resolver.resolve_refrence_protocol()
assert protocol.messages.get(NameStyleBproto.fromStr("Message1")).fields.get(NameStyleBproto.fromStr("enum_field")).type == BprotoFieldBaseType.ENUM
assert isinstance(protocol.messages.get(NameStyleBproto.fromStr("Message1")).fields.get(NameStyleBproto.fromStr("enum_field")), FieldEnum)
assert protocol.messages.get(NameStyleBproto.fromStr("Message1")).fields.get(NameStyleBproto.fromStr("enum_field")).enum == enum1
assert protocol.messages.get(NameStyleBproto.fromStr("Message1")).fields.get(NameStyleBproto.fromStr("enum_ref_field")).type == BprotoFieldBaseType.ENUM
assert isinstance(protocol.messages.get(NameStyleBproto.fromStr("Message1")).fields.get(NameStyleBproto.fromStr("enum_ref_field")), FieldEnum)
assert protocol.messages.get(NameStyleBproto.fromStr("Message1")).fields.get(NameStyleBproto.fromStr("enum_ref_field")).enum == enum1
assert protocol.messages.get(NameStyleBproto.fromStr("Message1")).fields.get(NameStyleBproto.fromStr("bitfield_field")).type == BprotoFieldBaseType.BITFIELD
assert isinstance(protocol.messages.get(NameStyleBproto.fromStr("Message1")).fields.get(NameStyleBproto.fromStr("bitfield_field")), FieldBitfield)
assert protocol.messages.get(NameStyleBproto.fromStr("Message1")).fields.get(NameStyleBproto.fromStr("bitfield_field")).bitfield == bitfield1
assert protocol.messages.get(NameStyleBproto.fromStr("Message1")).fields.get(NameStyleBproto.fromStr("bitfield_ref_field")).type == BprotoFieldBaseType.BITFIELD
assert isinstance(protocol.messages.get(NameStyleBproto.fromStr("Message1")).fields.get(NameStyleBproto.fromStr("bitfield_ref_field")), FieldBitfield)
assert protocol.messages.get(NameStyleBproto.fromStr("Message1")).fields.get(NameStyleBproto.fromStr("bitfield_ref_field")).bitfield == bitfield1
def test_protocol_resolve_refernces_unknown_refernces():
message1Factory = FactoryMessage()
message1Factory.add_field(FactoryField().assemble("field1", 0, "uint64", 1, None))
message1Factory.add_field(FactoryField().assemble("enum_ref_field", 1, BprotoFieldBaseType.ENUM, 1, "Enum1"))
message1Factory.add_field(FactoryField().assemble("bitfield_ref_field", 2, BprotoFieldBaseType.BITFIELD, 1, "Bitfield1",))
message1 = message1Factory.assemble("Message1", 42)
factory = FactoryProtocolDefition()
factory.add_message(message1)
try:
factory.assemble("TestProtocol", 1)
assert False
except Exception as e:
assert isinstance(e, BprotoUnresolvedReferenceError)
try:
factory.assemble("TestProtocol", 1)
assert False
except Exception as e:
assert isinstance(e, BprotoUnresolvedReferenceError)
def test_protocol_factory_already_define_error():
factory = FactoryProtocolDefition()
factory.add_message(FactoryMessage().assemble("Message1", 42))
try:
factory.add_message(FactoryMessage().assemble("Message1", 42))
factory.assemble("A", 1)
assert False
except Exception as e:
assert isinstance(e, BprotoAlreadyDefinedError)
factory = FactoryProtocolDefition()
factory.add_enum(FactoryEnumeration().assemble("Enum1"))
try:
factory.assemble("A", 1)
factory.add_enum(FactoryEnumeration().assemble("Enum1"))
assert False
except Exception as e:
assert isinstance(e, BprotoAlreadyDefinedError)
factory = FactoryProtocolDefition()
factory.add_bitfield(FactoryBitfield().assemble("Bitfield1"))
try:
factory.add_bitfield(FactoryBitfield().assemble("Bitfield1"))
factory.assemble("A", 1)
assert False
except Exception as e:
assert isinstance(e, BprotoAlreadyDefinedError)