From 7425bf0362ff2efdc38d1edf049173663e15dfb8 Mon Sep 17 00:00:00 2001 From: Stuart Dilts Date: Mon, 19 Jan 2026 15:25:23 -0700 Subject: [PATCH 1/2] Add actual python unit tests Move the integration tests into `/integrated` so we can use the works-by-convention pythyon `unittest` framework. --- .github/workflows/python-app.yml | 7 +++++-- {test => integrated}/framework.py | 0 {test => integrated}/inputs/builtin_pointers.h | 0 {test => integrated}/inputs/capitalization.h | 0 {test => integrated}/inputs/constant_array_in_struct.h | 0 {test => integrated}/inputs/forward_declaration.h | 0 {test => integrated}/inputs/function_pointer.h | 0 {test => integrated}/inputs/header_guard.h | 0 {test => integrated}/inputs/header_guard_path.h | 0 {test => integrated}/inputs/macro_constant.h | 0 {test => integrated}/inputs/macro_constant_invalid.h | 0 {test => integrated}/inputs/nested_anonymous_records.h | 0 {test => integrated}/inputs/nested_struct.h | 0 {test => integrated}/inputs/simple_struct.h | 0 {test => integrated}/inputs/standard_types.h | 0 {test => integrated}/inputs/typedef.h | 0 {test => integrated}/outputs/builtin-pointers.lisp | 0 {test => integrated}/outputs/capitalization.lisp | 0 {test => integrated}/outputs/constant-array-in-struct.lisp | 0 {test => integrated}/outputs/forward_declaration.lisp | 0 {test => integrated}/outputs/function-pointer.lisp | 0 {test => integrated}/outputs/header-guard-path.lisp | 0 {test => integrated}/outputs/header-guard.lisp | 0 {test => integrated}/outputs/macro-constant-invalid.lisp | 0 {test => integrated}/outputs/macro-constant.lisp | 0 {test => integrated}/outputs/nested-anonymous-records.lisp | 0 {test => integrated}/outputs/nested-struct.lisp | 0 {test => integrated}/outputs/simple-struct.lisp | 0 {test => integrated}/outputs/standard_types.lisp | 0 {test => integrated}/outputs/typedef.lisp | 0 {test => integrated}/run_tests.py | 0 test/__init__.py | 2 ++ 32 files changed, 7 insertions(+), 2 deletions(-) rename {test => integrated}/framework.py (100%) rename {test => integrated}/inputs/builtin_pointers.h (100%) rename {test => integrated}/inputs/capitalization.h (100%) rename {test => integrated}/inputs/constant_array_in_struct.h (100%) rename {test => integrated}/inputs/forward_declaration.h (100%) rename {test => integrated}/inputs/function_pointer.h (100%) rename {test => integrated}/inputs/header_guard.h (100%) rename {test => integrated}/inputs/header_guard_path.h (100%) rename {test => integrated}/inputs/macro_constant.h (100%) rename {test => integrated}/inputs/macro_constant_invalid.h (100%) rename {test => integrated}/inputs/nested_anonymous_records.h (100%) rename {test => integrated}/inputs/nested_struct.h (100%) rename {test => integrated}/inputs/simple_struct.h (100%) rename {test => integrated}/inputs/standard_types.h (100%) rename {test => integrated}/inputs/typedef.h (100%) rename {test => integrated}/outputs/builtin-pointers.lisp (100%) rename {test => integrated}/outputs/capitalization.lisp (100%) rename {test => integrated}/outputs/constant-array-in-struct.lisp (100%) rename {test => integrated}/outputs/forward_declaration.lisp (100%) rename {test => integrated}/outputs/function-pointer.lisp (100%) rename {test => integrated}/outputs/header-guard-path.lisp (100%) rename {test => integrated}/outputs/header-guard.lisp (100%) rename {test => integrated}/outputs/macro-constant-invalid.lisp (100%) rename {test => integrated}/outputs/macro-constant.lisp (100%) rename {test => integrated}/outputs/nested-anonymous-records.lisp (100%) rename {test => integrated}/outputs/nested-struct.lisp (100%) rename {test => integrated}/outputs/simple-struct.lisp (100%) rename {test => integrated}/outputs/standard_types.lisp (100%) rename {test => integrated}/outputs/typedef.lisp (100%) rename {test => integrated}/run_tests.py (100%) create mode 100644 test/__init__.py diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 6bfff01..61d9a4b 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -24,9 +24,12 @@ jobs: run: | pip install . pip uninstall -y clang - - name: Run Tests + - name: Run Unit Tests run: | - python test/run_tests.py + python -m unittest + - name: Run Integration tests + run: | + python integrated/run_tests.py lint: runs-on: ubuntu-latest steps: diff --git a/test/framework.py b/integrated/framework.py similarity index 100% rename from test/framework.py rename to integrated/framework.py diff --git a/test/inputs/builtin_pointers.h b/integrated/inputs/builtin_pointers.h similarity index 100% rename from test/inputs/builtin_pointers.h rename to integrated/inputs/builtin_pointers.h diff --git a/test/inputs/capitalization.h b/integrated/inputs/capitalization.h similarity index 100% rename from test/inputs/capitalization.h rename to integrated/inputs/capitalization.h diff --git a/test/inputs/constant_array_in_struct.h b/integrated/inputs/constant_array_in_struct.h similarity index 100% rename from test/inputs/constant_array_in_struct.h rename to integrated/inputs/constant_array_in_struct.h diff --git a/test/inputs/forward_declaration.h b/integrated/inputs/forward_declaration.h similarity index 100% rename from test/inputs/forward_declaration.h rename to integrated/inputs/forward_declaration.h diff --git a/test/inputs/function_pointer.h b/integrated/inputs/function_pointer.h similarity index 100% rename from test/inputs/function_pointer.h rename to integrated/inputs/function_pointer.h diff --git a/test/inputs/header_guard.h b/integrated/inputs/header_guard.h similarity index 100% rename from test/inputs/header_guard.h rename to integrated/inputs/header_guard.h diff --git a/test/inputs/header_guard_path.h b/integrated/inputs/header_guard_path.h similarity index 100% rename from test/inputs/header_guard_path.h rename to integrated/inputs/header_guard_path.h diff --git a/test/inputs/macro_constant.h b/integrated/inputs/macro_constant.h similarity index 100% rename from test/inputs/macro_constant.h rename to integrated/inputs/macro_constant.h diff --git a/test/inputs/macro_constant_invalid.h b/integrated/inputs/macro_constant_invalid.h similarity index 100% rename from test/inputs/macro_constant_invalid.h rename to integrated/inputs/macro_constant_invalid.h diff --git a/test/inputs/nested_anonymous_records.h b/integrated/inputs/nested_anonymous_records.h similarity index 100% rename from test/inputs/nested_anonymous_records.h rename to integrated/inputs/nested_anonymous_records.h diff --git a/test/inputs/nested_struct.h b/integrated/inputs/nested_struct.h similarity index 100% rename from test/inputs/nested_struct.h rename to integrated/inputs/nested_struct.h diff --git a/test/inputs/simple_struct.h b/integrated/inputs/simple_struct.h similarity index 100% rename from test/inputs/simple_struct.h rename to integrated/inputs/simple_struct.h diff --git a/test/inputs/standard_types.h b/integrated/inputs/standard_types.h similarity index 100% rename from test/inputs/standard_types.h rename to integrated/inputs/standard_types.h diff --git a/test/inputs/typedef.h b/integrated/inputs/typedef.h similarity index 100% rename from test/inputs/typedef.h rename to integrated/inputs/typedef.h diff --git a/test/outputs/builtin-pointers.lisp b/integrated/outputs/builtin-pointers.lisp similarity index 100% rename from test/outputs/builtin-pointers.lisp rename to integrated/outputs/builtin-pointers.lisp diff --git a/test/outputs/capitalization.lisp b/integrated/outputs/capitalization.lisp similarity index 100% rename from test/outputs/capitalization.lisp rename to integrated/outputs/capitalization.lisp diff --git a/test/outputs/constant-array-in-struct.lisp b/integrated/outputs/constant-array-in-struct.lisp similarity index 100% rename from test/outputs/constant-array-in-struct.lisp rename to integrated/outputs/constant-array-in-struct.lisp diff --git a/test/outputs/forward_declaration.lisp b/integrated/outputs/forward_declaration.lisp similarity index 100% rename from test/outputs/forward_declaration.lisp rename to integrated/outputs/forward_declaration.lisp diff --git a/test/outputs/function-pointer.lisp b/integrated/outputs/function-pointer.lisp similarity index 100% rename from test/outputs/function-pointer.lisp rename to integrated/outputs/function-pointer.lisp diff --git a/test/outputs/header-guard-path.lisp b/integrated/outputs/header-guard-path.lisp similarity index 100% rename from test/outputs/header-guard-path.lisp rename to integrated/outputs/header-guard-path.lisp diff --git a/test/outputs/header-guard.lisp b/integrated/outputs/header-guard.lisp similarity index 100% rename from test/outputs/header-guard.lisp rename to integrated/outputs/header-guard.lisp diff --git a/test/outputs/macro-constant-invalid.lisp b/integrated/outputs/macro-constant-invalid.lisp similarity index 100% rename from test/outputs/macro-constant-invalid.lisp rename to integrated/outputs/macro-constant-invalid.lisp diff --git a/test/outputs/macro-constant.lisp b/integrated/outputs/macro-constant.lisp similarity index 100% rename from test/outputs/macro-constant.lisp rename to integrated/outputs/macro-constant.lisp diff --git a/test/outputs/nested-anonymous-records.lisp b/integrated/outputs/nested-anonymous-records.lisp similarity index 100% rename from test/outputs/nested-anonymous-records.lisp rename to integrated/outputs/nested-anonymous-records.lisp diff --git a/test/outputs/nested-struct.lisp b/integrated/outputs/nested-struct.lisp similarity index 100% rename from test/outputs/nested-struct.lisp rename to integrated/outputs/nested-struct.lisp diff --git a/test/outputs/simple-struct.lisp b/integrated/outputs/simple-struct.lisp similarity index 100% rename from test/outputs/simple-struct.lisp rename to integrated/outputs/simple-struct.lisp diff --git a/test/outputs/standard_types.lisp b/integrated/outputs/standard_types.lisp similarity index 100% rename from test/outputs/standard_types.lisp rename to integrated/outputs/standard_types.lisp diff --git a/test/outputs/typedef.lisp b/integrated/outputs/typedef.lisp similarity index 100% rename from test/outputs/typedef.lisp rename to integrated/outputs/typedef.lisp diff --git a/test/run_tests.py b/integrated/run_tests.py similarity index 100% rename from test/run_tests.py rename to integrated/run_tests.py diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..b381dba --- /dev/null +++ b/test/__init__.py @@ -0,0 +1,2 @@ +""" Unit Test Suite for cl-bindgen +""" From b4000d5b93aa4f95339a1493d30a10e8574d98cb Mon Sep 17 00:00:00 2001 From: Stuart Dilts Date: Mon, 19 Jan 2026 15:29:39 -0700 Subject: [PATCH 2/2] Correctly handle underscores in names Makes strings like `GRAVITY_TOP_RIGHT` be converted correctly --- cl_bindgen/mangler.py | 5 ++++- test/test_CamelCaseConverter.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 test/test_CamelCaseConverter.py diff --git a/cl_bindgen/mangler.py b/cl_bindgen/mangler.py index 48a79c6..1ae977f 100644 --- a/cl_bindgen/mangler.py +++ b/cl_bindgen/mangler.py @@ -108,12 +108,15 @@ def __init__(self): def can_mangle(self, string): return len(string) > 0 + def _should_add_dash(self, cur_char, prev): + return cur_char.isupper() and not prev.isupper() and prev.isalnum() + def mangle(self, string): builder = io.StringIO() builder.write(string[0].lower()) for i in range(1, len(string)): cur_char = string[i] - if cur_char.isupper() and not string[i-1].isupper(): + if self._should_add_dash(cur_char, string[i-1]): builder.write('-') builder.write(cur_char.lower()) return builder.getvalue() diff --git a/test/test_CamelCaseConverter.py b/test/test_CamelCaseConverter.py new file mode 100644 index 0000000..7632452 --- /dev/null +++ b/test/test_CamelCaseConverter.py @@ -0,0 +1,30 @@ +import unittest + +from cl_bindgen.mangler import CamelCaseConverter + +class CamelCaseConverterTest(unittest.TestCase): + mangler = CamelCaseConverter() + + def test_title_case_converts(self): + result = self.mangler.mangle('TestTitleCase') + self.assertEqual('test-title-case', result) + + def test_converts_camelcase(self): + result = self.mangler.mangle('camelCase') + self.assertEqual('camel-case', result) + + def test_converts_all_lowercase(self): + result = self.mangler.mangle('camels') + self.assertEqual('camels', result) + + def test_converts_consective_at_end(self): + result = self.mangler.mangle('ThingDNE') + self.assertEqual('thing-dne', result) + + def test_converts_consective_at_begining(self): + result = self.mangler.mangle('IString') + self.assertEqual('istring', result) + + def test_converts_snakecase_names(self): + result = self.mangler.mangle('GRAVITY_TOP_RIGHT') + self.assertEqual('gravity_top_right', result)