statable 3.5.2__tar.gz → 3.5.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {statable-3.5.2 → statable-3.5.3}/PKG-INFO +1 -1
- {statable-3.5.2 → statable-3.5.3}/codegen/__init__.py +1 -1
- {statable-3.5.2 → statable-3.5.3}/pyproject.toml +1 -1
- {statable-3.5.2 → statable-3.5.3}/statable/__init__.py +1 -1
- {statable-3.5.2 → statable-3.5.3}/statable.egg-info/PKG-INFO +1 -1
- {statable-3.5.2 → statable-3.5.3}/statable.egg-info/SOURCES.txt +1 -0
- statable-3.5.3/tests/test_v3_5_3_eclipse_installer_deep.py +337 -0
- {statable-3.5.2 → statable-3.5.3}/README.md +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/c_code_generator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/code_merger.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/code_templates.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/config.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/enum_generator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/event_queue_generator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/interrupt_generator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/naming_convention.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/osal_generator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/role_function_generator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/sample_data.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/state_actions_generator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/struct_generator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/timer_generator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/transition_generator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/type_mapper.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/__init__.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/change_actions.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/change_applier.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/clipboard_manager.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/data/__init__.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/data/action_definitions.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/data/keywords.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/data/prompt_templates.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/data/validation_rules.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/items/__init__.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/items/base_validator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/items/cell_validator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/items/custom_type_validator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/items/event_validator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/items/flag_validator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/items/interrupt_validator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/items/queue_validator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/items/role_function_validator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/items/state_validator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/items/timer_validator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/items/transition_validator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/items/variable_validator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/logger.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/models.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/prompt_generator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/response_parser.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/response_validator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/validation_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/validate/validator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/codegen/variable_generator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/setup.cfg +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable/__main__.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable/cli.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable/global_defs.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable/mermaid_gen.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable/model.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable/output_utils.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable/parser.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable/sample_data.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable/shared/__init__.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable/shared/condition_library.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable/shared/literal_library.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable/shared/role_function_library.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable/smoke.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable/state_machine.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable/xml_io.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable.egg-info/dependency_links.txt +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable.egg-info/entry_points.txt +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable.egg-info/requires.txt +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable.egg-info/top_level.txt +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/__init__.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/action_edit_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/code_generation_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/code_generation_settings_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/common_widgets.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/condition_builder_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/condition_edit_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/condition_template_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/config.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/dialogs.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/event_definition_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/event_delivery_settings_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/event_queue_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/fs_cleanup.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/global_defs.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/global_defs_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/i18n/__init__.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/interrupt_handler_edit_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/layer_settings_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/libcntrl/__init__.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/libcntrl/condition_library.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/libcntrl/literal_library.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/libcntrl/literal_management_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/libcntrl/role_function_edit_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/libcntrl/role_function_library.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/literal_definition_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/logger.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/main_window.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/matrix_table.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/new_project_templates.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/new_project_wizard.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/output_warning.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/preference_keys.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/preferences.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/role_function_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/sample_data.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/state_actions_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/symbol_picker.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/traceball.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/__init__.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/actions_tab.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/code_widget.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/coverage_analyzer.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/draft.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/edit_dialogs.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/overview_tab.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/palette_widget.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/relations_edit_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/relations_tab.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/system_global_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/transition_actions_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/transitions_tab.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/validation_dialog.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/statable_gui/widgets.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_ci_registration.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_readme_consistency.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_2_p1.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_2_p12_10.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_2_p12_2.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_2_p12_5.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_2_p12_6.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_2_p12_7.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_2_p12_8.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_2_p12_9.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_2_p2.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_2_p3.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_2_p4a.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_2_p4b.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_3_p1.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_4_p1_merge.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_5_p1.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_5_p10.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_5_p11.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_5_p2.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_5_p3.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_5_p4.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_5_p5.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_5_p6.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_5_p8.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_5_p9.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_6_p1.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_6_p2.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_6_p3.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_7_p3.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_7_p4.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_7_p5_validation.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_8_p1_ai_prompt.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_8_p2_response_parser.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_8_p3_response_validator.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v2_8_p4_gui_integration.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v3_0_g1_shared.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v3_0_s1_packaging.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v3_0_s2_public_api.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v3_0_s3_cli.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v3_0_s4_docs.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v3_2_s1_wizard.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v3_2_s2_signals.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v3_4_0_signal_safety.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v3_4_0_state_actions.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v3_5_1_eclipse_installer.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v3_5_gui_output_clean.py +0 -0
- {statable-3.5.2 → statable-3.5.3}/tests/test_v3_5_s1_smoke.py +0 -0
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "statable"
|
|
9
|
-
version = "3.5.
|
|
9
|
+
version = "3.5.3"
|
|
10
10
|
description = "MISRA C:2012-aware state machine design and C code generation for embedded systems"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
requires-python = ">=3.10"
|
|
@@ -170,5 +170,6 @@ tests/test_v3_2_s2_signals.py
|
|
|
170
170
|
tests/test_v3_4_0_signal_safety.py
|
|
171
171
|
tests/test_v3_4_0_state_actions.py
|
|
172
172
|
tests/test_v3_5_1_eclipse_installer.py
|
|
173
|
+
tests/test_v3_5_3_eclipse_installer_deep.py
|
|
173
174
|
tests/test_v3_5_gui_output_clean.py
|
|
174
175
|
tests/test_v3_5_s1_smoke.py
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
# tests/test_v3_5_3_eclipse_installer_deep.py
|
|
2
|
+
"""
|
|
3
|
+
StaTable v3.5.3 Eclipse Installer deep test suite (L1+L2)
|
|
4
|
+
|
|
5
|
+
L1: Template integrity
|
|
6
|
+
- No BOM, LF-only
|
|
7
|
+
- Placeholder syntax @@KEY@@
|
|
8
|
+
- Valid XML for .project / .cproject
|
|
9
|
+
- Makefile tab chars
|
|
10
|
+
- Required templates present
|
|
11
|
+
- linker.ld / startup.s / syscalls.c / main_demo.c content
|
|
12
|
+
|
|
13
|
+
L2: core.install edge cases
|
|
14
|
+
- Custom generated_subdir
|
|
15
|
+
- with_* flags all off
|
|
16
|
+
- Idempotency
|
|
17
|
+
- overwrite_generated=False
|
|
18
|
+
- Empty output_dir
|
|
19
|
+
- Deep nested structure
|
|
20
|
+
- Unicode filename
|
|
21
|
+
- Same filename in different subdirs
|
|
22
|
+
- with_samples=True
|
|
23
|
+
- Missing project_root error
|
|
24
|
+
"""
|
|
25
|
+
import os
|
|
26
|
+
import re
|
|
27
|
+
import stat
|
|
28
|
+
import sys
|
|
29
|
+
import tempfile
|
|
30
|
+
import xml.etree.ElementTree as ET
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
|
|
33
|
+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
34
|
+
|
|
35
|
+
_total = 0
|
|
36
|
+
_passed = 0
|
|
37
|
+
_failed = 0
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def check(label, condition):
|
|
41
|
+
global _total, _passed, _failed
|
|
42
|
+
_total += 1
|
|
43
|
+
if condition:
|
|
44
|
+
_passed += 1
|
|
45
|
+
print(f" [PASS] {label}")
|
|
46
|
+
else:
|
|
47
|
+
_failed += 1
|
|
48
|
+
print(f" [FAIL] {label}")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def section(title):
|
|
52
|
+
print()
|
|
53
|
+
print(f"[{title}]")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
57
|
+
EI = ROOT / "eclipse_installer"
|
|
58
|
+
TPL = EI / "templates"
|
|
59
|
+
|
|
60
|
+
# ======================================================================
|
|
61
|
+
# L1: Template integrity
|
|
62
|
+
# ======================================================================
|
|
63
|
+
section("L1 template integrity")
|
|
64
|
+
|
|
65
|
+
# 1-1: No BOM
|
|
66
|
+
for f in TPL.rglob("*"):
|
|
67
|
+
if f.is_file():
|
|
68
|
+
data = f.read_bytes()
|
|
69
|
+
check(f"no BOM: {f.relative_to(TPL)}",
|
|
70
|
+
not data.startswith(b"\xef\xbb\xbf"))
|
|
71
|
+
|
|
72
|
+
# 1-2: LF-only
|
|
73
|
+
for f in TPL.rglob("*"):
|
|
74
|
+
if f.is_file():
|
|
75
|
+
data = f.read_bytes()
|
|
76
|
+
check(f"LF-only: {f.relative_to(TPL)}", b"\r\n" not in data)
|
|
77
|
+
|
|
78
|
+
# 1-3: Placeholder syntax @@KEY@@ (meta + actual)
|
|
79
|
+
_placeholder_re = re.compile(r"(?<!@)@([A-Z_]+)@(?!@)")
|
|
80
|
+
check("placeholder regex detects single-@ (meta)",
|
|
81
|
+
bool(_placeholder_re.search("X @FOO@ Y")))
|
|
82
|
+
check("placeholder regex allows @@ (meta)",
|
|
83
|
+
not _placeholder_re.search("X @@FOO@@ Y"))
|
|
84
|
+
|
|
85
|
+
for f in TPL.rglob("*"):
|
|
86
|
+
if not f.is_file():
|
|
87
|
+
continue
|
|
88
|
+
try:
|
|
89
|
+
t = f.read_text(encoding="utf-8")
|
|
90
|
+
except UnicodeDecodeError:
|
|
91
|
+
continue
|
|
92
|
+
bad = _placeholder_re.findall(t)
|
|
93
|
+
check(f"placeholder syntax: {f.relative_to(TPL)}", not bad)
|
|
94
|
+
|
|
95
|
+
# 1-4: Valid XML
|
|
96
|
+
for name in ("project.tmpl", "cproject.tmpl"):
|
|
97
|
+
p = TPL / name
|
|
98
|
+
try:
|
|
99
|
+
ET.fromstring(p.read_text(encoding="utf-8"))
|
|
100
|
+
check(f"valid XML: {name}", True)
|
|
101
|
+
except ET.ParseError as e:
|
|
102
|
+
check(f"valid XML: {name} ({e})", False)
|
|
103
|
+
|
|
104
|
+
# 1-5: Makefile tab bytes
|
|
105
|
+
mk_bytes = (TPL / "Makefile.tmpl").read_bytes()
|
|
106
|
+
check("Makefile.tmpl has >= 5 tab bytes", mk_bytes.count(9) >= 5)
|
|
107
|
+
mk_text = (TPL / "Makefile.tmpl").read_text(encoding="utf-8")
|
|
108
|
+
tab_lines = sum(1 for l in mk_text.split("\n") if l.startswith("\t"))
|
|
109
|
+
check("Makefile.tmpl has >= 5 tab-prefixed lines", tab_lines >= 5)
|
|
110
|
+
|
|
111
|
+
# 1-6: Required templates present
|
|
112
|
+
required = [
|
|
113
|
+
"startup_stm32f405.s", "linker_stm32f405.ld", "syscalls.c",
|
|
114
|
+
"main_demo.c", "Makefile.tmpl", "project.tmpl", "cproject.tmpl",
|
|
115
|
+
"settings/org.eclipse.core.resources.prefs",
|
|
116
|
+
"settings/language.settings.xml",
|
|
117
|
+
]
|
|
118
|
+
for rel in required:
|
|
119
|
+
check(f"template present: {rel}", (TPL / rel).is_file())
|
|
120
|
+
|
|
121
|
+
# 1-7: linker.ld content
|
|
122
|
+
ld_text = (TPL / "linker_stm32f405.ld").read_text(encoding="utf-8")
|
|
123
|
+
check("linker.ld ENTRY(Reset_Handler)",
|
|
124
|
+
"ENTRY(Reset_Handler)" in ld_text)
|
|
125
|
+
check("linker.ld FLASH 0x08000000",
|
|
126
|
+
"ORIGIN = 0x08000000" in ld_text)
|
|
127
|
+
check("linker.ld RAM 0x20000000",
|
|
128
|
+
"ORIGIN = 0x20000000" in ld_text)
|
|
129
|
+
|
|
130
|
+
# 1-8: startup.s content
|
|
131
|
+
st_text = (TPL / "startup_stm32f405.s").read_text(encoding="utf-8")
|
|
132
|
+
check("startup.s Reset_Handler", "Reset_Handler:" in st_text)
|
|
133
|
+
check("startup.s g_pfnVectors", "g_pfnVectors:" in st_text)
|
|
134
|
+
|
|
135
|
+
# 1-9: syscalls.c newlib stubs
|
|
136
|
+
sc_text = (TPL / "syscalls.c").read_text(encoding="utf-8")
|
|
137
|
+
for stub in ("_write", "_read", "_sbrk", "_close", "_fstat", "_exit"):
|
|
138
|
+
check(f"syscalls.c has {stub}", stub in sc_text)
|
|
139
|
+
|
|
140
|
+
# 1-10: main_demo.c weak hooks
|
|
141
|
+
md_text = (TPL / "main_demo.c").read_text(encoding="utf-8")
|
|
142
|
+
check("main_demo.c app_init weak",
|
|
143
|
+
"__attribute__((weak)) void app_init" in md_text)
|
|
144
|
+
check("main_demo.c app_step weak",
|
|
145
|
+
"__attribute__((weak)) void app_step" in md_text)
|
|
146
|
+
|
|
147
|
+
# ======================================================================
|
|
148
|
+
# L2: core.install edge cases
|
|
149
|
+
# ======================================================================
|
|
150
|
+
section("L2 core.install edge cases")
|
|
151
|
+
|
|
152
|
+
from eclipse_installer.core import InstallOptions, install
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _mkfile(root, rel, content="x"):
|
|
156
|
+
full = os.path.join(root, rel)
|
|
157
|
+
parent = os.path.dirname(full)
|
|
158
|
+
if parent:
|
|
159
|
+
os.makedirs(parent, exist_ok=True)
|
|
160
|
+
with open(full, "w", encoding="utf-8") as f:
|
|
161
|
+
f.write(content)
|
|
162
|
+
return os.path.abspath(full)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
# 2-1: Custom generated_subdir
|
|
166
|
+
with tempfile.TemporaryDirectory() as out_td, \
|
|
167
|
+
tempfile.TemporaryDirectory() as proj_td:
|
|
168
|
+
_mkfile(out_td, "a.c", "// a")
|
|
169
|
+
opts = InstallOptions(
|
|
170
|
+
project_root=Path(proj_td),
|
|
171
|
+
output_dir=Path(out_td),
|
|
172
|
+
generated_subdir="my/custom/dir",
|
|
173
|
+
)
|
|
174
|
+
res = install(opts)
|
|
175
|
+
check("2-1 custom subdir: no errors", not res.errors)
|
|
176
|
+
check("2-1 custom subdir: file placed",
|
|
177
|
+
(Path(proj_td) / "my" / "custom" / "dir" / "a.c").is_file())
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
# 2-2: All with_* off -> only generated C
|
|
181
|
+
with tempfile.TemporaryDirectory() as out_td, \
|
|
182
|
+
tempfile.TemporaryDirectory() as proj_td:
|
|
183
|
+
_mkfile(out_td, "x.c", "// x")
|
|
184
|
+
opts = InstallOptions(
|
|
185
|
+
project_root=Path(proj_td),
|
|
186
|
+
output_dir=Path(out_td),
|
|
187
|
+
with_startup=False, with_linker=False, with_syscalls=False,
|
|
188
|
+
with_main=False, with_makefile=False, with_eclipse_project=False,
|
|
189
|
+
)
|
|
190
|
+
res = install(opts)
|
|
191
|
+
check("2-2 all off: no errors", not res.errors)
|
|
192
|
+
check("2-2 all off: no main.c",
|
|
193
|
+
not (Path(proj_td) / "main.c").exists())
|
|
194
|
+
check("2-2 all off: no .project",
|
|
195
|
+
not (Path(proj_td) / ".project").exists())
|
|
196
|
+
check("2-2 all off: generated C copied",
|
|
197
|
+
(Path(proj_td) / "src" / "statable_generated" / "x.c").is_file())
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
# 2-3: Idempotency
|
|
201
|
+
with tempfile.TemporaryDirectory() as out_td, \
|
|
202
|
+
tempfile.TemporaryDirectory() as proj_td:
|
|
203
|
+
_mkfile(out_td, "x.c", "// x")
|
|
204
|
+
opts = InstallOptions(
|
|
205
|
+
project_root=Path(proj_td),
|
|
206
|
+
output_dir=Path(out_td),
|
|
207
|
+
)
|
|
208
|
+
res1 = install(opts)
|
|
209
|
+
res2 = install(opts)
|
|
210
|
+
check("2-3 idempotent: 1st no errors", not res1.errors)
|
|
211
|
+
check("2-3 idempotent: 2nd no errors", not res2.errors)
|
|
212
|
+
# 1st install: everything fresh (installed = all)
|
|
213
|
+
# 2nd install: generated C overwritten (installed), scaffolding
|
|
214
|
+
# skipped (overwrite_scaffolding=False default)
|
|
215
|
+
check("2-3 idempotent: 2nd has fewer installed",
|
|
216
|
+
len(res2.installed) < len(res1.installed))
|
|
217
|
+
check("2-3 idempotent: 2nd skipped scaffolding (>= 1)",
|
|
218
|
+
len(res2.skipped) >= 1)
|
|
219
|
+
check("2-3 idempotent: 2nd installed + skipped == 1st installed",
|
|
220
|
+
len(res2.installed) + len(res2.skipped) == len(res1.installed))
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
# 2-4: overwrite_generated=False preserves generated C
|
|
224
|
+
with tempfile.TemporaryDirectory() as out_td, \
|
|
225
|
+
tempfile.TemporaryDirectory() as proj_td:
|
|
226
|
+
_mkfile(out_td, "x.c", "// original")
|
|
227
|
+
opts = InstallOptions(
|
|
228
|
+
project_root=Path(proj_td),
|
|
229
|
+
output_dir=Path(out_td),
|
|
230
|
+
overwrite_generated=False,
|
|
231
|
+
)
|
|
232
|
+
install(opts)
|
|
233
|
+
target = Path(proj_td) / "src" / "statable_generated" / "x.c"
|
|
234
|
+
target.write_text("// user modified", encoding="utf-8")
|
|
235
|
+
res2 = install(opts)
|
|
236
|
+
check("2-4 overwrite=False: user file preserved",
|
|
237
|
+
target.read_text(encoding="utf-8") == "// user modified")
|
|
238
|
+
check("2-4 overwrite=False: skipped reported",
|
|
239
|
+
len(res2.skipped) >= 1)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
# 2-5: Empty output_dir
|
|
243
|
+
with tempfile.TemporaryDirectory() as out_td, \
|
|
244
|
+
tempfile.TemporaryDirectory() as proj_td:
|
|
245
|
+
opts = InstallOptions(
|
|
246
|
+
project_root=Path(proj_td),
|
|
247
|
+
output_dir=Path(out_td),
|
|
248
|
+
)
|
|
249
|
+
res = install(opts)
|
|
250
|
+
check("2-5 empty output: no errors", not res.errors)
|
|
251
|
+
src_dir = Path(proj_td) / "src"
|
|
252
|
+
gen_c = list(src_dir.rglob("*.c")) if src_dir.exists() else []
|
|
253
|
+
check("2-5 empty output: 0 generated C", not gen_c)
|
|
254
|
+
|
|
255
|
+
# 2-6: Deeply nested structure preserved
|
|
256
|
+
with tempfile.TemporaryDirectory() as out_td, \
|
|
257
|
+
tempfile.TemporaryDirectory() as proj_td:
|
|
258
|
+
_mkfile(out_td, "a/b/c/d/e/deep.c", "// deep")
|
|
259
|
+
opts = InstallOptions(
|
|
260
|
+
project_root=Path(proj_td),
|
|
261
|
+
output_dir=Path(out_td),
|
|
262
|
+
)
|
|
263
|
+
install(opts)
|
|
264
|
+
check("2-6 deep nested preserved",
|
|
265
|
+
(Path(proj_td) / "src" / "statable_generated"
|
|
266
|
+
/ "a" / "b" / "c" / "d" / "e" / "deep.c").is_file())
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
# 2-7: Unicode filename
|
|
270
|
+
with tempfile.TemporaryDirectory() as out_td, \
|
|
271
|
+
tempfile.TemporaryDirectory() as proj_td:
|
|
272
|
+
_mkfile(out_td, "\u65e5\u672c\u8a9e.c", "// unicode")
|
|
273
|
+
opts = InstallOptions(
|
|
274
|
+
project_root=Path(proj_td),
|
|
275
|
+
output_dir=Path(out_td),
|
|
276
|
+
)
|
|
277
|
+
res = install(opts)
|
|
278
|
+
check("2-7 unicode: no errors", not res.errors)
|
|
279
|
+
check("2-7 unicode: filename preserved",
|
|
280
|
+
(Path(proj_td) / "src" / "statable_generated"
|
|
281
|
+
/ "\u65e5\u672c\u8a9e.c").is_file())
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
# 2-8: Same filename in different subdirs
|
|
285
|
+
with tempfile.TemporaryDirectory() as out_td, \
|
|
286
|
+
tempfile.TemporaryDirectory() as proj_td:
|
|
287
|
+
_mkfile(out_td, "a/x.c", "// a")
|
|
288
|
+
_mkfile(out_td, "b/x.c", "// b")
|
|
289
|
+
opts = InstallOptions(
|
|
290
|
+
project_root=Path(proj_td),
|
|
291
|
+
output_dir=Path(out_td),
|
|
292
|
+
)
|
|
293
|
+
res = install(opts)
|
|
294
|
+
check("2-8 dup name: no errors", not res.errors)
|
|
295
|
+
a = (Path(proj_td) / "src" / "statable_generated" / "a" / "x.c")
|
|
296
|
+
b = (Path(proj_td) / "src" / "statable_generated" / "b" / "x.c")
|
|
297
|
+
check("2-8 dup name: a/x.c exists", a.is_file())
|
|
298
|
+
check("2-8 dup name: b/x.c exists", b.is_file())
|
|
299
|
+
check("2-8 dup name: content distinct",
|
|
300
|
+
a.read_text(encoding="utf-8") == "// a"
|
|
301
|
+
and b.read_text(encoding="utf-8") == "// b")
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
# 2-9: with_samples=True copies XML
|
|
305
|
+
with tempfile.TemporaryDirectory() as out_td, \
|
|
306
|
+
tempfile.TemporaryDirectory() as proj_td:
|
|
307
|
+
_mkfile(out_td, "x.c", "// x")
|
|
308
|
+
_mkfile(out_td, "sample.xml", "<xml/>")
|
|
309
|
+
opts = InstallOptions(
|
|
310
|
+
project_root=Path(proj_td),
|
|
311
|
+
output_dir=Path(out_td),
|
|
312
|
+
with_samples=True,
|
|
313
|
+
)
|
|
314
|
+
res = install(opts)
|
|
315
|
+
check("2-9 samples: no errors", not res.errors)
|
|
316
|
+
check("2-9 samples: xml copied",
|
|
317
|
+
(Path(proj_td) / "samples" / "sample.xml").is_file())
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
# 2-10: Missing project_root -> error
|
|
321
|
+
with tempfile.TemporaryDirectory() as td:
|
|
322
|
+
res = install(InstallOptions(
|
|
323
|
+
project_root=Path(td) / "no_such",
|
|
324
|
+
output_dir=Path(td),
|
|
325
|
+
))
|
|
326
|
+
check("2-10 missing project_root: error", len(res.errors) >= 1)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
# ======================================================================
|
|
330
|
+
# Summary
|
|
331
|
+
# ======================================================================
|
|
332
|
+
print()
|
|
333
|
+
print("=" * 70)
|
|
334
|
+
print(f" TOTAL: {_total} PASSED: {_passed} FAILED: {_failed}")
|
|
335
|
+
print("=" * 70)
|
|
336
|
+
|
|
337
|
+
sys.exit(0 if _failed == 0 else 1)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/coverage_analyzer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/relations_edit_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/system_global_dialog.py
RENAMED
|
File without changes
|
{statable-3.5.2 → statable-3.5.3}/statable_gui/transition_editor_direct/transition_actions_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|