Compare commits

...

8 Commits

Author SHA1 Message Date
Ken Van Hoeylandt
b6edd39539 Fixes 2026-02-09 00:29:36 +01:00
Ken Van Hoeylandt
96c68db0de Add timeout to test execution 2026-02-09 00:27:21 +01:00
Ken Van Hoeylandt
603a8f478e Fix 2026-02-09 00:26:23 +01:00
Ken Van Hoeylandt
165051ad85 Fix for tests 2026-02-09 00:10:29 +01:00
Ken Van Hoeylandt
dcc1f9bcf1 Fix for path 2026-02-09 00:08:17 +01:00
Ken Van Hoeylandt
cc7d6d7674 Add DevicetreeCompiler tests 2026-02-09 00:06:15 +01:00
Ken Van Hoeylandt
26b4ea360e Fix 2026-02-08 23:39:06 +01:00
Ken Van Hoeylandt
1a81b4a81a Fix 2026-02-08 23:32:10 +01:00
8 changed files with 169 additions and 9 deletions

View File

@ -6,7 +6,7 @@ on:
pull_request: pull_request:
types: [ opened, synchronize, reopened ] types: [ opened, synchronize, reopened ]
jobs: jobs:
run: TactilityTests:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: "Checkout repo" - name: "Checkout repo"
@ -27,3 +27,17 @@ jobs:
run: build/Tests/Tactility/TactilityTests run: build/Tests/Tactility/TactilityTests
- name: "Run TactilityKernel Tests" - name: "Run TactilityKernel Tests"
run: build/Tests/TactilityKernel/TactilityKernelTests run: build/Tests/TactilityKernel/TactilityKernelTests
DevicetreeTests:
runs-on: ubuntu-latest
steps:
- name: "Checkout repo"
uses: actions/checkout@v2
with:
submodules: recursive
- name: "Install Python Dependencies"
shell: bash
run: pip install lark==1.3.1 pyyaml==6.0.3
- name: "Run Devicetree Tests"
shell: bash
working-directory: Buildscripts/DevicetreeCompiler/tests
run: python test_integration.py

View File

@ -63,12 +63,18 @@ def property_to_string(property: DeviceProperty, devices: list[Device]) -> str:
type = property.type type = property.type
if type == "value" or type == "int": if type == "value" or type == "int":
return property.value return property.value
elif type == "boolean": elif type == "boolean" or type == "bool":
return "true" return "true"
elif type == "text": elif type == "text":
return f"\"{property.value}\"" return f"\"{property.value}\""
elif type == "values": elif type == "values":
return "{ " + ",".join(property.value) + " }" value_list = list()
for item in property.value:
if isinstance(item, PropertyValue):
value_list.append(property_to_string(DeviceProperty(name="", type=item.type, value=item.value), devices))
else:
value_list.append(str(item))
return "{ " + ",".join(value_list) + " }"
elif type == "phandle": elif type == "phandle":
return find_phandle(devices, property.value) return find_phandle(devices, property.value)
else: else:
@ -101,17 +107,17 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], de
for index, binding_property in enumerate(binding_properties): for index, binding_property in enumerate(binding_properties):
device_property = find_device_property(device, binding_property.name) device_property = find_device_property(device, binding_property.name)
if device_property is None: if device_property is None:
if binding_property.type == "bool": if binding_property.default is not None:
result[index] = "false"
elif binding_property.required:
raise DevicetreeException(f"device {device.node_name} doesn't have property '{binding_property.name}'")
elif binding_property.default is not None:
temp_prop = DeviceProperty( temp_prop = DeviceProperty(
name=binding_property.name, name=binding_property.name,
type=binding_property.type, type=binding_property.type,
value=binding_property.default value=binding_property.default
) )
result[index] = property_to_string(temp_prop, devices) result[index] = property_to_string(temp_prop, devices)
elif binding_property.required:
raise DevicetreeException(f"device {device.node_name} doesn't have property '{binding_property.name}'")
elif binding_property.type == "bool":
result[index] = "false"
else: else:
raise DevicetreeException(f"Device {device.node_name} doesn't have property '{binding_property.name}' and no default value is set") raise DevicetreeException(f"Device {device.node_name} doesn't have property '{binding_property.name}' and no default value is set")
else: else:

View File

@ -0,0 +1,14 @@
description: Test device binding
compatible: "test,device"
properties:
reg:
type: int
required: true
status:
type: string
boolean-prop:
type: boolean
int-prop:
type: int
string-prop:
type: string

View File

@ -0,0 +1,5 @@
description: Test root binding
compatible: "test,root"
properties:
model:
type: string

View File

@ -0,0 +1,2 @@
dts: test.dts
bindings: bindings

View File

@ -0,0 +1,17 @@
/dts-v1/;
#include <test_include.h>
/ {
compatible = "test,root";
model = "Test Model";
test_device: test-device@0 {
compatible = "test,device";
reg = <0>;
status = "okay";
boolean-prop;
int-prop = <42>;
string-prop = "hello";
};
};

View File

@ -0,0 +1,102 @@
import os
import subprocess
import shutil
import sys
import tempfile
# Path to the compile.py script
# We assume this script is in Buildscripts/DevicetreeCompiler/tests/
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
PROJECT_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, ".."))
COMPILE_SCRIPT = os.path.join(PROJECT_ROOT, "compile.py")
TEST_DATA_DIR = os.path.join(SCRIPT_DIR, "data")
def run_compiler(config_path, output_path):
result = subprocess.run(
[sys.executable, COMPILE_SCRIPT, config_path, output_path],
capture_output=True,
text=True,
cwd=PROJECT_ROOT,
timeout=60
)
return result
def test_compile_success():
print("Running test_compile_success...")
with tempfile.TemporaryDirectory() as output_dir:
result = run_compiler(TEST_DATA_DIR, output_dir)
if result.returncode != 0:
print(f"FAILED: Compilation failed: {result.stderr}")
return False
if not os.path.exists(os.path.join(output_dir, "devicetree.c")):
print("FAILED: devicetree.c not generated")
return False
if not os.path.exists(os.path.join(output_dir, "devicetree.h")):
print("FAILED: devicetree.h not generated")
return False
print("PASSED")
return True
def test_compile_invalid_dts():
print("Running test_compile_invalid_dts...")
with tempfile.TemporaryDirectory() as tmp_dir:
bad_data_dir = os.path.join(tmp_dir, "bad_data")
os.makedirs(bad_data_dir)
output_dir = os.path.join(tmp_dir, "output")
os.makedirs(output_dir)
with open(os.path.join(bad_data_dir, "devicetree.yaml"), "w") as f:
f.write("dts: bad.dts\nbindings: bindings")
with open(os.path.join(bad_data_dir, "bad.dts"), "w") as f:
f.write("/dts-v1/;\n / { invalid syntax }")
os.makedirs(os.path.join(bad_data_dir, "bindings"))
result = run_compiler(bad_data_dir, output_dir)
if result.returncode == 0:
print("FAILED: Compilation should have failed but succeeded")
return False
print("PASSED")
return True
def test_compile_missing_config():
print("Running test_compile_missing_config...")
with tempfile.TemporaryDirectory() as output_dir:
result = run_compiler("/non/existent/path", output_dir)
if result.returncode == 0:
print("FAILED: Compilation should have failed for non-existent path")
return False
if "Directory not found" not in result.stdout:
print(f"FAILED: Expected 'Directory not found' error message, got: {result.stdout}")
return False
print("PASSED")
return True
if __name__ == "__main__":
tests = [
test_compile_success,
test_compile_invalid_dts,
test_compile_missing_config
]
failed = 0
for test in tests:
if not test():
failed += 1
if failed > 0:
print(f"\n{failed} tests failed")
sys.exit(1)
else:
print("\nAll tests passed")
sys.exit(0)

View File

@ -51,7 +51,7 @@ add_custom_target(AlwaysRun
add_custom_command( add_custom_command(
OUTPUT "${GENERATED_DIR}/devicetree.c" OUTPUT "${GENERATED_DIR}/devicetree.c"
"${GENERATED_DIR}/devicetree.h" "${GENERATED_DIR}/devicetree.h"
COMMAND pip install lark pyyaml COMMAND pip install lark==1.3.1 pyyaml==6.0.3
COMMAND python "${CMAKE_SOURCE_DIR}/Buildscripts/DevicetreeCompiler/compile.py" COMMAND python "${CMAKE_SOURCE_DIR}/Buildscripts/DevicetreeCompiler/compile.py"
"${DEVICETREE_LOCATION}" "${GENERATED_DIR}" "${DEVICETREE_LOCATION}" "${GENERATED_DIR}"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"