From b31741df37ca45a1eabf733f8e5709d03b544170 Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Wed, 21 Aug 2024 19:11:42 -0600 Subject: [PATCH 01/20] Update `Parameter_Manager` component for testing --- src/assembly/linux/1 | 508 ++++++++++++ .../linux/linux_example.assembly.yaml | 11 +- ...onent-parameter_manager-implementation.adb | 233 +++--- ...onent-parameter_manager-implementation.ads | 61 +- .../doc/parameter_manager.pdf | Bin 245444 -> 287321 bytes .../doc/parameter_manager.tex | 25 + .../packed_parameter_table.record.yaml | 11 + .../packed_validation.record.yaml | 17 + .../packed_validation_header.record.yaml | 10 + .../parameter_manager.commands.yaml | 9 +- .../parameter_manager.component.yaml | 26 +- .../parameter_manager.data_products.yaml | 6 + .../parameter_manager.events.yaml | 16 +- .../parameter_manager.requirements.yaml | 3 +- ...parameter_manager_table_header.record.yaml | 23 + .../parameter_manager_types.ads | 13 + ...arameter_manager-implementation-tester.adb | 127 ++- ...arameter_manager-implementation-tester.ads | 71 +- src/components/parameter_manager/test/env.py | 8 - .../test/parameter_manager.tests.yaml | 12 +- ...parameter_manager_tests-implementation.adb | 729 ++++++++++++------ ...parameter_manager_tests-implementation.ads | 19 +- .../parameter_manager/types/.all_path | 0 ...cked_parameter_table_copy_type.record.yaml | 7 - .../types/parameter_manager_enums.enums.yaml | 12 - 25 files changed, 1486 insertions(+), 471 deletions(-) create mode 100644 src/assembly/linux/1 create mode 100644 src/components/parameter_manager/packed_parameter_table.record.yaml create mode 100644 src/components/parameter_manager/packed_validation.record.yaml create mode 100644 src/components/parameter_manager/packed_validation_header.record.yaml create mode 100644 src/components/parameter_manager/parameter_manager.data_products.yaml create mode 100644 src/components/parameter_manager/parameter_manager_table_header.record.yaml create mode 100644 src/components/parameter_manager/parameter_manager_types.ads delete mode 100644 src/components/parameter_manager/types/.all_path delete mode 100644 src/components/parameter_manager/types/packed_parameter_table_copy_type.record.yaml delete mode 100644 src/components/parameter_manager/types/parameter_manager_enums.enums.yaml diff --git a/src/assembly/linux/1 b/src/assembly/linux/1 new file mode 100644 index 0000000..82593e5 --- /dev/null +++ b/src/assembly/linux/1 @@ -0,0 +1,508 @@ +redo what  +redo all +redo clean +redo clean_all +redo clear_cache +redo templates +redo publish +redo targets +redo prove +redo analyze +redo style +redo pretty +redo test_all +redo coverage_all +redo style_all +redo build/bin/Linux/linux_example_command_sequencer_details_packet_type_type_ranges.elf +redo build/bin/Linux/linux_example_command_sequencer_summary_packet_type_type_ranges.elf +redo build/bin/Linux/linux_example_cpu_monitor_packet_type_type_ranges.elf +redo build/bin/Linux/linux_example_fault_responses_packed_id_type_type_ranges.elf +redo build/bin/Linux/linux_example_fault_responses_status_record_type_ranges.elf +redo build/bin/Linux/linux_example_parameter_table_record_type_ranges.elf +redo build/bin/Linux/linux_example_queue_monitor_packet_type_type_ranges.elf +redo build/bin/Linux/linux_example_stack_monitor_packet_type_type_ranges.elf +redo build/bin/Linux/linux_example_task_watchdog_list_state_record_type_ranges.elf +redo build/bin/Linux/linux_example_task_watchdog_list_watchdog_action_cmd_type_ranges.elf +redo build/bin/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd_type_ranges.elf +redo build/cosmos/plugin/linux_example_ccsds_cosmos_commands.txt +redo build/cosmos/plugin/linux_example_ccsds_cosmos_telemetry.txt +redo build/dot/linux_example.dot +redo build/eps/linux_example.eps +redo build/html/linux_example_arrayed_connections.html +redo build/html/linux_example_command_sequencer_details_packet_type.html +redo build/html/linux_example_command_sequencer_summary_packet_type.html +redo build/html/linux_example_commands.html +redo build/html/linux_example_components.html +redo build/html/linux_example_connections.html +redo build/html/linux_example_cpu_monitor_packet_type.html +redo build/html/linux_example_data_dependencies.html +redo build/html/linux_example_data_products.html +redo build/html/linux_example_events.html +redo build/html/linux_example_fault_responses_enums.html +redo build/html/linux_example_fault_responses_packed_id_type.html +redo build/html/linux_example_fault_responses_status_record.html +redo build/html/linux_example_faults.html +redo build/html/linux_example_interrupts.html +redo build/html/linux_example_packets.html +redo build/html/linux_example_parameter_table_record.html +redo build/html/linux_example_parameters.html +redo build/html/linux_example_priorities.html +redo build/html/linux_example_product_packets.html +redo build/html/linux_example_queue_monitor_packet_type.html +redo build/html/linux_example_queues.html +redo build/html/linux_example_seq.html +redo build/html/linux_example_stack_monitor_packet_type.html +redo build/html/linux_example_task_watchdog_list_state_record.html +redo build/html/linux_example_task_watchdog_list_watchdog_action_cmd.html +redo build/html/linux_example_task_watchdog_list_watchdog_limit_cmd.html +redo build/hydra/Config/linux_example.xml +redo build/hydra/Config/linux_example_ccsds_commands.xml +redo build/hydra/Config/linux_example_ccsds_packets.xml +redo build/hydra/Pages/linux_example_cpu_monitor.xml +redo build/hydra/Pages/linux_example_parameter_table.xml +redo build/hydra/Pages/linux_example_queue_monitor.xml +redo build/hydra/Pages/linux_example_stack_monitor.xml +redo build/hydra/Scripts/linux_example_packet_pages.prc +redo build/m/Linux_Example_Command_Sequencer_Details_Packet_Type.m +redo build/m/Linux_Example_Command_Sequencer_Summary_Packet_Type.m +redo build/m/Linux_Example_Cpu_Monitor_Packet_Type.m +redo build/m/Linux_Example_Fault_Responses_Enums +redo build/m/Linux_Example_Fault_Responses_Packed_Id_Type.m +redo build/m/Linux_Example_Fault_Responses_Status_Record.m +redo build/m/Linux_Example_Parameter_Table_Record.m +redo build/m/Linux_Example_Queue_Monitor_Packet_Type.m +redo build/m/Linux_Example_Stack_Monitor_Packet_Type.m +redo build/m/Linux_Example_Task_Watchdog_List_State_Record.m +redo build/m/Linux_Example_Task_Watchdog_List_Watchdog_Action_Cmd.m +redo build/m/Linux_Example_Task_Watchdog_List_Watchdog_Limit_Cmd.m +redo build/m/linux_example_events.m +redo build/metric/Linux/linux_example.adb.txt +redo build/metric/Linux/linux_example.ads.txt +redo build/metric/Linux/linux_example_command_sequencer_details_packet_type-assertion.adb.txt +redo build/metric/Linux/linux_example_command_sequencer_details_packet_type-assertion.ads.txt +redo build/metric/Linux/linux_example_command_sequencer_details_packet_type-c.ads.txt +redo build/metric/Linux/linux_example_command_sequencer_details_packet_type-representation.adb.txt +redo build/metric/Linux/linux_example_command_sequencer_details_packet_type-representation.ads.txt +redo build/metric/Linux/linux_example_command_sequencer_details_packet_type-validation.adb.txt +redo build/metric/Linux/linux_example_command_sequencer_details_packet_type-validation.ads.txt +redo build/metric/Linux/linux_example_command_sequencer_details_packet_type.adb.txt +redo build/metric/Linux/linux_example_command_sequencer_details_packet_type.ads.txt +redo build/metric/Linux/linux_example_command_sequencer_details_packet_type_type_ranges.adb.txt +redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type-assertion.adb.txt +redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type-assertion.ads.txt +redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type-c.ads.txt +redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type-representation.adb.txt +redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type-representation.ads.txt +redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type-validation.adb.txt +redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type-validation.ads.txt +redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type.adb.txt +redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type.ads.txt +redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type_type_ranges.adb.txt +redo build/metric/Linux/linux_example_commands.ads.txt +redo build/metric/Linux/linux_example_cpu_monitor_packet_type-assertion.adb.txt +redo build/metric/Linux/linux_example_cpu_monitor_packet_type-assertion.ads.txt +redo build/metric/Linux/linux_example_cpu_monitor_packet_type-c.ads.txt +redo build/metric/Linux/linux_example_cpu_monitor_packet_type-representation.adb.txt +redo build/metric/Linux/linux_example_cpu_monitor_packet_type-representation.ads.txt +redo build/metric/Linux/linux_example_cpu_monitor_packet_type-validation.adb.txt +redo build/metric/Linux/linux_example_cpu_monitor_packet_type-validation.ads.txt +redo build/metric/Linux/linux_example_cpu_monitor_packet_type.adb.txt +redo build/metric/Linux/linux_example_cpu_monitor_packet_type.ads.txt +redo build/metric/Linux/linux_example_cpu_monitor_packet_type_type_ranges.adb.txt +redo build/metric/Linux/linux_example_data_dependencies.ads.txt +redo build/metric/Linux/linux_example_data_products.ads.txt +redo build/metric/Linux/linux_example_event_to_text.adb.txt +redo build/metric/Linux/linux_example_event_to_text.ads.txt +redo build/metric/Linux/linux_example_events.ads.txt +redo build/metric/Linux/linux_example_fault_responses.ads.txt +redo build/metric/Linux/linux_example_fault_responses_enums-assertion.ads.txt +redo build/metric/Linux/linux_example_fault_responses_enums-representation.adb.txt +redo build/metric/Linux/linux_example_fault_responses_enums-representation.ads.txt +redo build/metric/Linux/linux_example_fault_responses_enums.ads.txt +redo build/metric/Linux/linux_example_fault_responses_packed_id_type-assertion.adb.txt +redo build/metric/Linux/linux_example_fault_responses_packed_id_type-assertion.ads.txt +redo build/metric/Linux/linux_example_fault_responses_packed_id_type-c.ads.txt +redo build/metric/Linux/linux_example_fault_responses_packed_id_type-representation.adb.txt +redo build/metric/Linux/linux_example_fault_responses_packed_id_type-representation.ads.txt +redo build/metric/Linux/linux_example_fault_responses_packed_id_type-validation.adb.txt +redo build/metric/Linux/linux_example_fault_responses_packed_id_type-validation.ads.txt +redo build/metric/Linux/linux_example_fault_responses_packed_id_type.adb.txt +redo build/metric/Linux/linux_example_fault_responses_packed_id_type.ads.txt +redo build/metric/Linux/linux_example_fault_responses_packed_id_type_type_ranges.adb.txt +redo build/metric/Linux/linux_example_fault_responses_status_record-assertion.adb.txt +redo build/metric/Linux/linux_example_fault_responses_status_record-assertion.ads.txt +redo build/metric/Linux/linux_example_fault_responses_status_record-c.ads.txt +redo build/metric/Linux/linux_example_fault_responses_status_record-representation.adb.txt +redo build/metric/Linux/linux_example_fault_responses_status_record-representation.ads.txt +redo build/metric/Linux/linux_example_fault_responses_status_record-validation.adb.txt +redo build/metric/Linux/linux_example_fault_responses_status_record-validation.ads.txt +redo build/metric/Linux/linux_example_fault_responses_status_record.adb.txt +redo build/metric/Linux/linux_example_fault_responses_status_record.ads.txt +redo build/metric/Linux/linux_example_fault_responses_status_record_type_ranges.adb.txt +redo build/metric/Linux/linux_example_faults.ads.txt +redo build/metric/Linux/linux_example_packets.ads.txt +redo build/metric/Linux/linux_example_parameter_table.ads.txt +redo build/metric/Linux/linux_example_parameter_table_record-assertion.adb.txt +redo build/metric/Linux/linux_example_parameter_table_record-assertion.ads.txt +redo build/metric/Linux/linux_example_parameter_table_record-c.ads.txt +redo build/metric/Linux/linux_example_parameter_table_record-representation.adb.txt +redo build/metric/Linux/linux_example_parameter_table_record-representation.ads.txt +redo build/metric/Linux/linux_example_parameter_table_record-validation.adb.txt +redo build/metric/Linux/linux_example_parameter_table_record-validation.ads.txt +redo build/metric/Linux/linux_example_parameter_table_record.adb.txt +redo build/metric/Linux/linux_example_parameter_table_record.ads.txt +redo build/metric/Linux/linux_example_parameter_table_record_type_ranges.adb.txt +redo build/metric/Linux/linux_example_parameters.ads.txt +redo build/metric/Linux/linux_example_product_packets.ads.txt +redo build/metric/Linux/linux_example_queue_monitor_packet_type-assertion.adb.txt +redo build/metric/Linux/linux_example_queue_monitor_packet_type-assertion.ads.txt +redo build/metric/Linux/linux_example_queue_monitor_packet_type-c.ads.txt +redo build/metric/Linux/linux_example_queue_monitor_packet_type-representation.adb.txt +redo build/metric/Linux/linux_example_queue_monitor_packet_type-representation.ads.txt +redo build/metric/Linux/linux_example_queue_monitor_packet_type-validation.adb.txt +redo build/metric/Linux/linux_example_queue_monitor_packet_type-validation.ads.txt +redo build/metric/Linux/linux_example_queue_monitor_packet_type.adb.txt +redo build/metric/Linux/linux_example_queue_monitor_packet_type.ads.txt +redo build/metric/Linux/linux_example_queue_monitor_packet_type_type_ranges.adb.txt +redo build/metric/Linux/linux_example_stack_monitor_packet_type-assertion.adb.txt +redo build/metric/Linux/linux_example_stack_monitor_packet_type-assertion.ads.txt +redo build/metric/Linux/linux_example_stack_monitor_packet_type-c.ads.txt +redo build/metric/Linux/linux_example_stack_monitor_packet_type-representation.adb.txt +redo build/metric/Linux/linux_example_stack_monitor_packet_type-representation.ads.txt +redo build/metric/Linux/linux_example_stack_monitor_packet_type-validation.adb.txt +redo build/metric/Linux/linux_example_stack_monitor_packet_type-validation.ads.txt +redo build/metric/Linux/linux_example_stack_monitor_packet_type.adb.txt +redo build/metric/Linux/linux_example_stack_monitor_packet_type.ads.txt +redo build/metric/Linux/linux_example_stack_monitor_packet_type_type_ranges.adb.txt +redo build/metric/Linux/linux_example_task_watchdog_list.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_state_record-assertion.adb.txt +redo build/metric/Linux/linux_example_task_watchdog_list_state_record-assertion.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_state_record-c.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_state_record-representation.adb.txt +redo build/metric/Linux/linux_example_task_watchdog_list_state_record-representation.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_state_record-validation.adb.txt +redo build/metric/Linux/linux_example_task_watchdog_list_state_record-validation.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_state_record.adb.txt +redo build/metric/Linux/linux_example_task_watchdog_list_state_record.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_state_record_type_ranges.adb.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-assertion.adb.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-assertion.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-c.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-representation.adb.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-representation.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-validation.adb.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-validation.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd.adb.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd_type_ranges.adb.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-assertion.adb.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-assertion.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-c.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-representation.adb.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-representation.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-validation.adb.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-validation.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd.adb.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd.ads.txt +redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd_type_ranges.adb.txt +redo build/metric/Linux/memory_map.ads.txt +redo build/metric/Linux/memory_map.o.txt +redo build/metric/Linux/start_up.adb.txt +redo build/metric/Linux/start_up.ads.txt +redo build/metric/Linux/start_up.o.txt +redo build/obj/Linux/linux_example.o +redo build/obj/Linux/linux_example_command_sequencer_details_packet_type-assertion.o +redo build/obj/Linux/linux_example_command_sequencer_details_packet_type-c.o +redo build/obj/Linux/linux_example_command_sequencer_details_packet_type-representation.o +redo build/obj/Linux/linux_example_command_sequencer_details_packet_type-validation.o +redo build/obj/Linux/linux_example_command_sequencer_details_packet_type.o +redo build/obj/Linux/linux_example_command_sequencer_details_packet_type_type_ranges.o +redo build/obj/Linux/linux_example_command_sequencer_summary_packet_type-assertion.o +redo build/obj/Linux/linux_example_command_sequencer_summary_packet_type-c.o +redo build/obj/Linux/linux_example_command_sequencer_summary_packet_type-representation.o +redo build/obj/Linux/linux_example_command_sequencer_summary_packet_type-validation.o +redo build/obj/Linux/linux_example_command_sequencer_summary_packet_type.o +redo build/obj/Linux/linux_example_command_sequencer_summary_packet_type_type_ranges.o +redo build/obj/Linux/linux_example_commands.o +redo build/obj/Linux/linux_example_cpu_monitor_packet_type-assertion.o +redo build/obj/Linux/linux_example_cpu_monitor_packet_type-c.o +redo build/obj/Linux/linux_example_cpu_monitor_packet_type-representation.o +redo build/obj/Linux/linux_example_cpu_monitor_packet_type-validation.o +redo build/obj/Linux/linux_example_cpu_monitor_packet_type.o +redo build/obj/Linux/linux_example_cpu_monitor_packet_type_type_ranges.o +redo build/obj/Linux/linux_example_data_dependencies.o +redo build/obj/Linux/linux_example_data_products.o +redo build/obj/Linux/linux_example_event_to_text.o +redo build/obj/Linux/linux_example_events.o +redo build/obj/Linux/linux_example_fault_responses.o +redo build/obj/Linux/linux_example_fault_responses_enums-assertion.o +redo build/obj/Linux/linux_example_fault_responses_enums-representation.o +redo build/obj/Linux/linux_example_fault_responses_enums.o +redo build/obj/Linux/linux_example_fault_responses_packed_id_type-assertion.o +redo build/obj/Linux/linux_example_fault_responses_packed_id_type-c.o +redo build/obj/Linux/linux_example_fault_responses_packed_id_type-representation.o +redo build/obj/Linux/linux_example_fault_responses_packed_id_type-validation.o +redo build/obj/Linux/linux_example_fault_responses_packed_id_type.o +redo build/obj/Linux/linux_example_fault_responses_packed_id_type_type_ranges.o +redo build/obj/Linux/linux_example_fault_responses_status_record-assertion.o +redo build/obj/Linux/linux_example_fault_responses_status_record-c.o +redo build/obj/Linux/linux_example_fault_responses_status_record-representation.o +redo build/obj/Linux/linux_example_fault_responses_status_record-validation.o +redo build/obj/Linux/linux_example_fault_responses_status_record.o +redo build/obj/Linux/linux_example_fault_responses_status_record_type_ranges.o +redo build/obj/Linux/linux_example_faults.o +redo build/obj/Linux/linux_example_packets.o +redo build/obj/Linux/linux_example_parameter_table.o +redo build/obj/Linux/linux_example_parameter_table_record-assertion.o +redo build/obj/Linux/linux_example_parameter_table_record-c.o +redo build/obj/Linux/linux_example_parameter_table_record-representation.o +redo build/obj/Linux/linux_example_parameter_table_record-validation.o +redo build/obj/Linux/linux_example_parameter_table_record.o +redo build/obj/Linux/linux_example_parameter_table_record_type_ranges.o +redo build/obj/Linux/linux_example_parameters.o +redo build/obj/Linux/linux_example_product_packets.o +redo build/obj/Linux/linux_example_queue_monitor_packet_type-assertion.o +redo build/obj/Linux/linux_example_queue_monitor_packet_type-c.o +redo build/obj/Linux/linux_example_queue_monitor_packet_type-representation.o +redo build/obj/Linux/linux_example_queue_monitor_packet_type-validation.o +redo build/obj/Linux/linux_example_queue_monitor_packet_type.o +redo build/obj/Linux/linux_example_queue_monitor_packet_type_type_ranges.o +redo build/obj/Linux/linux_example_stack_monitor_packet_type-assertion.o +redo build/obj/Linux/linux_example_stack_monitor_packet_type-c.o +redo build/obj/Linux/linux_example_stack_monitor_packet_type-representation.o +redo build/obj/Linux/linux_example_stack_monitor_packet_type-validation.o +redo build/obj/Linux/linux_example_stack_monitor_packet_type.o +redo build/obj/Linux/linux_example_stack_monitor_packet_type_type_ranges.o +redo build/obj/Linux/linux_example_task_watchdog_list.o +redo build/obj/Linux/linux_example_task_watchdog_list_state_record-assertion.o +redo build/obj/Linux/linux_example_task_watchdog_list_state_record-c.o +redo build/obj/Linux/linux_example_task_watchdog_list_state_record-representation.o +redo build/obj/Linux/linux_example_task_watchdog_list_state_record-validation.o +redo build/obj/Linux/linux_example_task_watchdog_list_state_record.o +redo build/obj/Linux/linux_example_task_watchdog_list_state_record_type_ranges.o +redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-assertion.o +redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-c.o +redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-representation.o +redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-validation.o +redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_action_cmd.o +redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_action_cmd_type_ranges.o +redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-assertion.o +redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-c.o +redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-representation.o +redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-validation.o +redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd.o +redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd_type_ranges.o +redo build/obj/Linux/memory_map.o +redo build/obj/Linux/start_up.o +redo build/pdf/linux_example_command_sequencer_details_packet_type.pdf +redo build/pdf/linux_example_command_sequencer_summary_packet_type.pdf +redo build/pdf/linux_example_cpu_monitor_packet_type.pdf +redo build/pdf/linux_example_fault_responses_enums.pdf +redo build/pdf/linux_example_fault_responses_packed_id_type.pdf +redo build/pdf/linux_example_fault_responses_status_record.pdf +redo build/pdf/linux_example_parameter_table_record.pdf +redo build/pdf/linux_example_queue_monitor_packet_type.pdf +redo build/pdf/linux_example_stack_monitor_packet_type.pdf +redo build/pdf/linux_example_task_watchdog_list_state_record.pdf +redo build/pdf/linux_example_task_watchdog_list_watchdog_action_cmd.pdf +redo build/pdf/linux_example_task_watchdog_list_watchdog_limit_cmd.pdf +redo build/png/linux_example.png +redo build/py/linux_example_command_sequencer_details_packet_type.py +redo build/py/linux_example_command_sequencer_summary_packet_type.py +redo build/py/linux_example_cpu_monitor_packet_type.py +redo build/py/linux_example_events.py +redo build/py/linux_example_fault_responses_enums.py +redo build/py/linux_example_fault_responses_packed_id_type.py +redo build/py/linux_example_fault_responses_status_record.py +redo build/py/linux_example_parameter_table_record.py +redo build/py/linux_example_queue_monitor_packet_type.py +redo build/py/linux_example_stack_monitor_packet_type.py +redo build/py/linux_example_task_watchdog_list_state_record.py +redo build/py/linux_example_task_watchdog_list_watchdog_action_cmd.py +redo build/py/linux_example_task_watchdog_list_watchdog_limit_cmd.py +redo build/src/linux_example.adb +redo build/src/linux_example.ads +redo build/src/linux_example_command_sequencer_details_packet_type-assertion.adb +redo build/src/linux_example_command_sequencer_details_packet_type-assertion.ads +redo build/src/linux_example_command_sequencer_details_packet_type-c.ads +redo build/src/linux_example_command_sequencer_details_packet_type-representation.adb +redo build/src/linux_example_command_sequencer_details_packet_type-representation.ads +redo build/src/linux_example_command_sequencer_details_packet_type-validation.adb +redo build/src/linux_example_command_sequencer_details_packet_type-validation.ads +redo build/src/linux_example_command_sequencer_details_packet_type.adb +redo build/src/linux_example_command_sequencer_details_packet_type.ads +redo build/src/linux_example_command_sequencer_details_packet_type_type_ranges.adb +redo build/src/linux_example_command_sequencer_summary_packet_type-assertion.adb +redo build/src/linux_example_command_sequencer_summary_packet_type-assertion.ads +redo build/src/linux_example_command_sequencer_summary_packet_type-c.ads +redo build/src/linux_example_command_sequencer_summary_packet_type-representation.adb +redo build/src/linux_example_command_sequencer_summary_packet_type-representation.ads +redo build/src/linux_example_command_sequencer_summary_packet_type-validation.adb +redo build/src/linux_example_command_sequencer_summary_packet_type-validation.ads +redo build/src/linux_example_command_sequencer_summary_packet_type.adb +redo build/src/linux_example_command_sequencer_summary_packet_type.ads +redo build/src/linux_example_command_sequencer_summary_packet_type_type_ranges.adb +redo build/src/linux_example_commands.ads +redo build/src/linux_example_cpu_monitor_packet_type-assertion.adb +redo build/src/linux_example_cpu_monitor_packet_type-assertion.ads +redo build/src/linux_example_cpu_monitor_packet_type-c.ads +redo build/src/linux_example_cpu_monitor_packet_type-representation.adb +redo build/src/linux_example_cpu_monitor_packet_type-representation.ads +redo build/src/linux_example_cpu_monitor_packet_type-validation.adb +redo build/src/linux_example_cpu_monitor_packet_type-validation.ads +redo build/src/linux_example_cpu_monitor_packet_type.adb +redo build/src/linux_example_cpu_monitor_packet_type.ads +redo build/src/linux_example_cpu_monitor_packet_type_type_ranges.adb +redo build/src/linux_example_data_dependencies.ads +redo build/src/linux_example_data_products.ads +redo build/src/linux_example_event_to_text.adb +redo build/src/linux_example_event_to_text.ads +redo build/src/linux_example_events.ads +redo build/src/linux_example_fault_responses.ads +redo build/src/linux_example_fault_responses_enums-assertion.ads +redo build/src/linux_example_fault_responses_enums-representation.adb +redo build/src/linux_example_fault_responses_enums-representation.ads +redo build/src/linux_example_fault_responses_enums.ads +redo build/src/linux_example_fault_responses_packed_id_type-assertion.adb +redo build/src/linux_example_fault_responses_packed_id_type-assertion.ads +redo build/src/linux_example_fault_responses_packed_id_type-c.ads +redo build/src/linux_example_fault_responses_packed_id_type-representation.adb +redo build/src/linux_example_fault_responses_packed_id_type-representation.ads +redo build/src/linux_example_fault_responses_packed_id_type-validation.adb +redo build/src/linux_example_fault_responses_packed_id_type-validation.ads +redo build/src/linux_example_fault_responses_packed_id_type.adb +redo build/src/linux_example_fault_responses_packed_id_type.ads +redo build/src/linux_example_fault_responses_packed_id_type_type_ranges.adb +redo build/src/linux_example_fault_responses_status_record-assertion.adb +redo build/src/linux_example_fault_responses_status_record-assertion.ads +redo build/src/linux_example_fault_responses_status_record-c.ads +redo build/src/linux_example_fault_responses_status_record-representation.adb +redo build/src/linux_example_fault_responses_status_record-representation.ads +redo build/src/linux_example_fault_responses_status_record-validation.adb +redo build/src/linux_example_fault_responses_status_record-validation.ads +redo build/src/linux_example_fault_responses_status_record.adb +redo build/src/linux_example_fault_responses_status_record.ads +redo build/src/linux_example_fault_responses_status_record_type_ranges.adb +redo build/src/linux_example_faults.ads +redo build/src/linux_example_packets.ads +redo build/src/linux_example_parameter_table.ads +redo build/src/linux_example_parameter_table_record-assertion.adb +redo build/src/linux_example_parameter_table_record-assertion.ads +redo build/src/linux_example_parameter_table_record-c.ads +redo build/src/linux_example_parameter_table_record-representation.adb +redo build/src/linux_example_parameter_table_record-representation.ads +redo build/src/linux_example_parameter_table_record-validation.adb +redo build/src/linux_example_parameter_table_record-validation.ads +redo build/src/linux_example_parameter_table_record.adb +redo build/src/linux_example_parameter_table_record.ads +redo build/src/linux_example_parameter_table_record_type_ranges.adb +redo build/src/linux_example_parameters.ads +redo build/src/linux_example_product_packets.ads +redo build/src/linux_example_queue_monitor_packet_type-assertion.adb +redo build/src/linux_example_queue_monitor_packet_type-assertion.ads +redo build/src/linux_example_queue_monitor_packet_type-c.ads +redo build/src/linux_example_queue_monitor_packet_type-representation.adb +redo build/src/linux_example_queue_monitor_packet_type-representation.ads +redo build/src/linux_example_queue_monitor_packet_type-validation.adb +redo build/src/linux_example_queue_monitor_packet_type-validation.ads +redo build/src/linux_example_queue_monitor_packet_type.adb +redo build/src/linux_example_queue_monitor_packet_type.ads +redo build/src/linux_example_queue_monitor_packet_type_type_ranges.adb +redo build/src/linux_example_stack_monitor_packet_type-assertion.adb +redo build/src/linux_example_stack_monitor_packet_type-assertion.ads +redo build/src/linux_example_stack_monitor_packet_type-c.ads +redo build/src/linux_example_stack_monitor_packet_type-representation.adb +redo build/src/linux_example_stack_monitor_packet_type-representation.ads +redo build/src/linux_example_stack_monitor_packet_type-validation.adb +redo build/src/linux_example_stack_monitor_packet_type-validation.ads +redo build/src/linux_example_stack_monitor_packet_type.adb +redo build/src/linux_example_stack_monitor_packet_type.ads +redo build/src/linux_example_stack_monitor_packet_type_type_ranges.adb +redo build/src/linux_example_task_watchdog_list.ads +redo build/src/linux_example_task_watchdog_list_state_record-assertion.adb +redo build/src/linux_example_task_watchdog_list_state_record-assertion.ads +redo build/src/linux_example_task_watchdog_list_state_record-c.ads +redo build/src/linux_example_task_watchdog_list_state_record-representation.adb +redo build/src/linux_example_task_watchdog_list_state_record-representation.ads +redo build/src/linux_example_task_watchdog_list_state_record-validation.adb +redo build/src/linux_example_task_watchdog_list_state_record-validation.ads +redo build/src/linux_example_task_watchdog_list_state_record.adb +redo build/src/linux_example_task_watchdog_list_state_record.ads +redo build/src/linux_example_task_watchdog_list_state_record_type_ranges.adb +redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd-assertion.adb +redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd-assertion.ads +redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd-c.ads +redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd-representation.adb +redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd-representation.ads +redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd-validation.adb +redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd-validation.ads +redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd.adb +redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd.ads +redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd_type_ranges.adb +redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd-assertion.adb +redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd-assertion.ads +redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd-c.ads +redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd-representation.adb +redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd-representation.ads +redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd-validation.adb +redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd-validation.ads +redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd.adb +redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd.ads +redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd_type_ranges.adb +redo build/svg/linux_example.svg +redo build/tex/linux_example_command_sequencer_details_packet_type.tex +redo build/tex/linux_example_command_sequencer_summary_packet_type.tex +redo build/tex/linux_example_cpu_monitor_packet_type.tex +redo build/tex/linux_example_fault_responses_enums.tex +redo build/tex/linux_example_fault_responses_packed_id_type.tex +redo build/tex/linux_example_fault_responses_status_record.tex +redo build/tex/linux_example_parameter_table_record.tex +redo build/tex/linux_example_queue_monitor_packet_type.tex +redo build/tex/linux_example_stack_monitor_packet_type.tex +redo build/tex/linux_example_task_watchdog_list_state_record.tex +redo build/tex/linux_example_task_watchdog_list_watchdog_action_cmd.tex +redo build/tex/linux_example_task_watchdog_list_watchdog_limit_cmd.tex +redo build/txt/linux_example_seq_cmd_tlm.txt +redo build/yaml/linux_example_command_sequencer_details_packet_type.record.yaml +redo build/yaml/linux_example_command_sequencer_summary_packet_type.record.yaml +redo build/yaml/linux_example_cpu_monitor_packet_type.record.yaml +redo build/yaml/linux_example_fault_responses_enums.enums.yaml +redo build/yaml/linux_example_fault_responses_packed_id_type.record.yaml +redo build/yaml/linux_example_fault_responses_status_record.record.yaml +redo build/yaml/linux_example_parameter_table_record.record.yaml +redo build/yaml/linux_example_queue_monitor_packet_type.record.yaml +redo build/yaml/linux_example_stack_monitor_packet_type.record.yaml +redo build/yaml/linux_example_task_watchdog_list_state_record.record.yaml +redo build/yaml/linux_example_task_watchdog_list_watchdog_action_cmd.record.yaml +redo build/yaml/linux_example_task_watchdog_list_watchdog_limit_cmd.record.yaml +redo doc/build/pdf/linux_example_commands.pdf +redo doc/build/pdf/linux_example_components.pdf +redo doc/build/pdf/linux_example_connections.pdf +redo doc/build/pdf/linux_example_data_dependencies.pdf +redo doc/build/pdf/linux_example_data_products.pdf +redo doc/build/pdf/linux_example_description.pdf +redo doc/build/pdf/linux_example_enums.pdf +redo doc/build/pdf/linux_example_events.pdf +redo doc/build/pdf/linux_example_faults.pdf +redo doc/build/pdf/linux_example_packets.pdf +redo doc/build/pdf/linux_example_parameters.pdf +redo doc/build/pdf/linux_example_priorities.pdf +redo doc/build/pdf/linux_example_stats.pdf +redo doc/build/pdf/linux_example_types.pdf +redo doc/build/pdf/linux_example_views.pdf +redo doc/build/template/linux_example.tex +redo doc/build/tex/linux_example_commands.tex +redo doc/build/tex/linux_example_components.tex +redo doc/build/tex/linux_example_connections.tex +redo doc/build/tex/linux_example_data_dependencies.tex +redo doc/build/tex/linux_example_data_products.tex +redo doc/build/tex/linux_example_description.tex +redo doc/build/tex/linux_example_enums.tex +redo doc/build/tex/linux_example_events.tex +redo doc/build/tex/linux_example_faults.tex +redo doc/build/tex/linux_example_packets.tex +redo doc/build/tex/linux_example_parameters.tex +redo doc/build/tex/linux_example_priorities.tex +redo doc/build/tex/linux_example_stats.tex +redo doc/build/tex/linux_example_types.tex +redo doc/build/tex/linux_example_views.tex diff --git a/src/assembly/linux/linux_example.assembly.yaml b/src/assembly/linux/linux_example.assembly.yaml index d48cfe2..bc23fd9 100644 --- a/src/assembly/linux/linux_example.assembly.yaml +++ b/src/assembly/linux/linux_example.assembly.yaml @@ -183,7 +183,6 @@ components: set_id_bases: - "Command_Id_Base => 5200" init: - - "Parameter_Table_Length => Linux_Example_Parameter_Table.Parameter_Table_Size_In_Bytes" - "Ticks_Until_Timeout => 3" ######################################## # Telemetry system: @@ -1070,9 +1069,17 @@ connections: to_component: Parameters_Instance to_connector: Parameters_Memory_Region_T_Recv_Async - from_component: Parameter_Manager_Instance - from_connector: Default_Parameters_Memory_Region_Send + from_connector: Primary_Parameters_Memory_Region_Send to_component: Parameter_Store_Instance to_connector: Parameters_Memory_Region_T_Recv_Async + - from_component: Parameter_Manager_Instance + from_connector: Redundant_Parameters_Memory_Region_Send + to_component: Parameter_Store_Instance + to_connector: Parameters_Memory_Region_T_Recv_Async + - from_component: Parameter_Manager_Instance + from_connector: Data_Product_T_Send + to_component: Product_Database_Instance + to_connector: Data_Product_T_Recv_Sync - from_component: Parameter_Store_Instance from_connector: Parameters_Memory_Region_Release_T_Send to_component: Parameter_Manager_Instance diff --git a/src/components/parameter_manager/component-parameter_manager-implementation.adb b/src/components/parameter_manager/component-parameter_manager-implementation.adb index 691c879..b471bc5 100644 --- a/src/components/parameter_manager/component-parameter_manager-implementation.adb +++ b/src/components/parameter_manager/component-parameter_manager-implementation.adb @@ -2,10 +2,7 @@ -- Parameter_Manager Component Implementation Body -------------------------------------------------------------------------------- -with Crc_16; with Parameter_Enums; -with Parameter_Manager_Enums; -with Packet_Types; package body Component.Parameter_Manager.Implementation is @@ -15,28 +12,25 @@ package body Component.Parameter_Manager.Implementation is -- Initialization parameters for the Parameter Manager. -- -- Init Parameters: - -- parameter_Table_Length : Natural - The size of the parameter table in bytes. This must be known to the component so it can construct correct sized memory regions for the downstream components. - -- ticks_Until_Timeout : Natural - The component will wait until it has received at least this many ticks before reporting a timeout error while waiting for a parameter update/fetch response from either the active or default parameter components. For example, if the component is attached to a 10Hz rate group and this value is set to 7, then the component will wait between 700 and 800 ms before declaring a timeout error from an unresponsive downstream component. + -- Ticks_Until_Timeout : Natural - The component will wait until it has received + -- at least this many ticks before reporting a timeout error while waiting for a + -- parameter update/fetch response from either the working or default parameter + -- components. For example, if the component is attached to a 10Hz rate group and + -- this value is set to 7, then the component will wait between 700 and 800 ms + -- before declaring a timeout error from an unresponsive downstream component. -- - overriding procedure Init (Self : in out Instance; Parameter_Table_Length : in Natural; Ticks_Until_Timeout : in Natural) is + overriding procedure Init (Self : in out Instance; Ticks_Until_Timeout : in Natural) is begin - -- Just save off the init parameters so we can use them later. - -- The implementation of this component assumes that the parameter table length fits cleanly in a maximum sized packet. - pragma Assert (Self.Parameter_Table_Length + Crc_16.Crc_16_Type'Length <= Packet_Types.Packet_Buffer_Type'Length, "The parameter table must not be larger than the maximum size packet!"); - Self.Parameter_Table_Length := Parameter_Table_Length; -- Save the ticks until timeout. Self.Sync_Object.Set_Timeout_Limit (Ticks_Until_Timeout); - - -- Allocate our temporary storage region. See more details in the .ads for why this is needed. - Self.Parameter_Bytes := new Basic_Types.Byte_Array (0 .. Self.Parameter_Table_Length - 1); - -- Create a memory region that points to this buffer: - Self.Parameter_Bytes_Region := (Address => Self.Parameter_Bytes.all'Address, Length => Self.Parameter_Bytes.all'Length); end Init; --------------------------------------- -- Invokee connector primitives: --------------------------------------- - -- The component should be attached to a periodic tick that is used to timeout waiting for a parameter update/fetch response. See the ticks_Until_Timeout initialization parameter. + -- The component should be attached to a periodic tick that is used to timeout + -- waiting for a parameter update/fetch response. See the ticks_Until_Timeout + -- initialization parameter. overriding procedure Timeout_Tick_Recv_Sync (Self : in out Instance; Arg : in Tick.T) is Ignore : Tick.T renames Arg; begin @@ -56,7 +50,9 @@ package body Component.Parameter_Manager.Implementation is Self.Command_Response_T_Send_If_Connected ((Source_Id => Arg.Header.Source_Id, Registration_Id => Self.Command_Reg_Id, Command_Id => Arg.Header.Id, Status => Stat)); end Command_T_Recv_Async; - -- Parameter update/fetch responses are returned synchronously on this connector. The component waits internally for this response, or times out if the response is not received in time. + -- Parameter update/fetch responses are returned synchronously on this connector. + -- The component waits internally for this response, or times out if the response + -- is not received in time. overriding procedure Parameters_Memory_Region_Release_T_Recv_Sync (Self : in out Instance; Arg : in Parameters_Memory_Region_Release.T) is begin -- First set the protected response with the response from the component. @@ -99,6 +95,7 @@ package body Component.Parameter_Manager.Implementation is -- that all copy commands must perform. function Wait_For_Response (Self : in out Instance) return Boolean is Wait_Timed_Out : Boolean; + use Parameter_Enums; begin -- OK wait for the response. Self.Sync_Object.Wait (Wait_Timed_Out); @@ -127,8 +124,9 @@ package body Component.Parameter_Manager.Implementation is return True; end Wait_For_Response; - -- Helper which sends a memory region request (set/get) to the default store. - function Copy_To_From_Default (Self : in out Instance; Request : in Parameters_Memory_Region.T) return Boolean is + -- Helper function which updates work parameter table data. + function Update_Working_Table (Self : in out Instance; Arg : in Parameters_Memory_Region.T) return Command_Execution_Status.E is + use Command_Execution_Status; begin -- First, clear the state of the synchronization -- object. This prevents us from just "falling through" the @@ -138,19 +136,20 @@ package body Component.Parameter_Manager.Implementation is -- fresh. Self.Sync_Object.Reset; - -- Send the request to the default component. - Self.Default_Parameters_Memory_Region_Send (Request); + -- Send the request to the working component. + Self.Working_Parameters_Memory_Region_Send_If_Connected (Arg); -- OK now we wait for and check the response. if not Self.Wait_For_Response then - return False; + return Failure; end if; - return True; - end Copy_To_From_Default; + return Success; + end Update_Working_Table; - -- Helper which sends a memory region request (set/get) to the default store. - function Copy_To_From_Working (Self : in out Instance; Request : in Parameters_Memory_Region.T) return Boolean is + -- Helper function which updates default parameter table data. + function Update_Primary_Table (Self : in out Instance; Arg : in Parameters_Memory_Region.T) return Command_Execution_Status.E is + use Command_Execution_Status; begin -- First, clear the state of the synchronization -- object. This prevents us from just "falling through" the @@ -160,96 +159,140 @@ package body Component.Parameter_Manager.Implementation is -- fresh. Self.Sync_Object.Reset; - -- Send the request to the default component. - Self.Working_Parameters_Memory_Region_Send (Request); + -- Send the request to the primary component. + Self.Primary_Parameters_Memory_Region_Send_If_Connected (Arg); -- OK now we wait for and check the response. if not Self.Wait_For_Response then - return False; - end if; - - return True; - end Copy_To_From_Working; - - -- Helper function which copies parameter table data from default to working. - function Copy_Default_To_Working (Self : in out Instance) return Command_Execution_Status.E is - use Command_Execution_Status; - use Parameter_Enums.Parameter_Table_Operation_Type; - begin - -- Send a get request to default: - if not Self.Copy_To_From_Default ((Region => Self.Parameter_Bytes_Region, Operation => Get)) then - return Failure; - end if; - - -- - -- Ok, now we have valid parameter data from the source component. Time to send - -- it to the destination. - -- - - -- Send a set request to working: - if not Self.Copy_To_From_Working ((Region => Self.Parameter_Bytes_Region, Operation => Set)) then return Failure; end if; return Success; - end Copy_Default_To_Working; + end Update_Primary_Table; - -- Helper function which copies parameter table data from working to default. - function Copy_Working_To_Default (Self : in out Instance) return Command_Execution_Status.E is + ----------------------------------------------- + -- Command handler primitives: + ----------------------------------------------- + -- Description: + -- These are the commands for the Parameter Manager component. + -- Send received parameter table to default and working regions. + overriding function Update_Parameter_Table (Self : in out Instance; Arg : in Packed_Parameter_Table.T) return Command_Execution_Status.E is use Command_Execution_Status; - use Parameter_Enums.Parameter_Table_Operation_Type; + -- The parameter table header includes the Table_Buffer_Length + -- before the CRC table, so the region must be taken from the + -- CRC table address instead of from the beginning. The region + -- length must be the Table_Buffer_Length size in bytes plus + -- the size in bytes of the CRC table and the version. + Parameter_Table_Region : constant Parameters_Memory_Region.T := ( + Region => ( + Address => Arg.Header.Crc_Table'Address, + Length => Arg.Header.Table_Buffer_Length + Parameter_Manager_Table_Header.Crc_Table_Size_In_Bytes + Parameter_Manager_Table_Header.Version_Size_In_Bytes + ), + Operation => (Parameter_Enums.Parameter_Table_Operation_Type.Set) + ); begin - -- Send a get request to default: - if not Self.Copy_To_From_Working ((Region => Self.Parameter_Bytes_Region, Operation => Get)) then + -- Info event: + Self.Event_T_Send_If_Connected (Self.Events.Starting_Parameter_Table_Copy (Self.Sys_Time_T_Get, Arg.Header)); + + if Self.Update_Working_Table (Parameter_Table_Region) /= Success + then + -- Info event: + Self.Event_T_Send_If_Connected (Self.Events.Working_Table_Update_Failure ( + Timestamp => Self.Sys_Time_T_Get, + Param => ( + Last_Validation_Header => Arg.Header, + Last_Validation_Status => Self.Response.Get_Var.Status + ) + )); return Failure; end if; - - -- - -- Ok, now we have valid parameter data from the source component. Time to send - -- it to the destination. - -- - - -- Send a set request to working: - if not Self.Copy_To_From_Default ((Region => Self.Parameter_Bytes_Region, Operation => Set)) then + if Self.Update_Primary_Table (Parameter_Table_Region) /= Success + then + -- Info event: + Self.Event_T_Send_If_Connected (Self.Events.Primary_Table_Update_Failure ( + Timestamp => Self.Sys_Time_T_Get, + Param => ( + Last_Validation_Header => Arg.Header, + Last_Validation_Status => Self.Response.Get_Var.Status + ) + )); return Failure; end if; - + -- Info event: + Self.Event_T_Send_If_Connected (Self.Events.Finished_Parameter_Table_Copy (Self.Sys_Time_T_Get, Arg.Header)); return Success; - end Copy_Working_To_Default; + end Update_Parameter_Table; - ----------------------------------------------- - -- Command handler primitives: - ----------------------------------------------- - -- Description: - -- These are the commands for the Parameter Store component. - -- Copy parameter table from source to destination based on the enumeration provided. - overriding function Copy_Parameter_Table (Self : in out Instance; Arg : in Packed_Parameter_Table_Copy_Type.T) return Command_Execution_Status.E is + -- Validate a received parameter table. + overriding function Validate_Parameter_Table (Self : in out Instance; Arg : in Packed_Parameter_Table.T) return Command_Execution_Status.E is use Command_Execution_Status; - use Parameter_Manager_Enums.Parameter_Table_Copy_Type; - To_Return : Command_Execution_Status.E; + -- The parameter table header includes the Table_Buffer_Length + -- before the CRC table, so the region must be taken from the + -- CRC table address instead of from the beginning. The region + -- length must be the Table_Buffer_Length size in bytes plus + -- the size in bytes of the CRC table and the version. + Parameter_Table_Region : constant Parameters_Memory_Region.T := ( + Region => ( + Address => Arg.Header.Crc_Table'Address, + Length => Arg.Header.Table_Buffer_Length + Parameter_Manager_Table_Header.Crc_Table_Size_In_Bytes + Parameter_Manager_Table_Header.Version_Size_In_Bytes + ), + Operation => (Parameter_Enums.Parameter_Table_Operation_Type.Validate) + ); begin - -- Info event: - Self.Event_T_Send_If_Connected (Self.Events.Starting_Parameter_Table_Copy (Self.Sys_Time_T_Get, Arg)); - - -- Determine the copy source and destination and perform copy: - case Arg.Copy_Type is - when Default_To_Working => - To_Return := Self.Copy_Default_To_Working; - when Working_To_Default => - To_Return := Self.Copy_Working_To_Default; - end case; + -- Validate argument table parameters: - -- Check the return status: - if To_Return /= Success then - -- An error event will have already been sent. - return To_Return; - end if; + -- First, clear the state of the synchronization + -- object. This prevents us from just "falling through" the + -- wait call below if some errant response was sent through + -- to us while we were not listening. + -- This also resets the timeout counter, so we start + -- fresh. + Self.Sync_Object.Reset; - -- Info event: - Self.Event_T_Send_If_Connected (Self.Events.Finished_Parameter_Table_Copy (Self.Sys_Time_T_Get, Arg)); + -- Send the request to the working component. + Self.Working_Parameters_Memory_Region_Send_If_Connected (Parameter_Table_Region); - return Success; - end Copy_Parameter_Table; + declare + -- Update the response: + Response : constant Boolean := Self.Wait_For_Response; + -- Update the timestamp: + Time : constant Sys_Time.T := Self.Sys_Time_T_Get; + -- Update the validation status: + Validation_Status : constant Parameter_Enums.Parameter_Table_Update_Status.E := Self.Response.Get_Var.Status; + begin + -- Send out the validation as a data product: + Self.Data_Product_T_Send_If_Connected (Self.Data_Products.Validation_Status ( + Timestamp => Time, + Item => ( + Last_Validation_Version => Arg.Header.Version, + Crc_Table => Arg.Header.Crc_Table, + Last_Validation_Status => Validation_Status + ) + )); + case Response is + when False => + -- Throw event: + Self.Event_T_Send_If_Connected (Self.Events.Table_Validation_Failure ( + Timestamp => Time, + Param => ( + Last_Validation_Header => Arg.Header, + Last_Validation_Status => Validation_Status + ) + )); + return Failure; + when True => + -- Throw event: + Self.Event_T_Send_If_Connected (Self.Events.Table_Validation_Success ( + Timestamp => Time, + Param => ( + Last_Validation_Header => Arg.Header, + Last_Validation_Status => Validation_Status + ) + )); + return Success; + end case; + end; + end Validate_Parameter_Table; -- Invalid command handler. This procedure is called when a command's arguments are found to be invalid: overriding procedure Invalid_Command (Self : in out Instance; Cmd : in Command.T; Errant_Field_Number : in Unsigned_32; Errant_Field : in Basic_Types.Poly_Type) is diff --git a/src/components/parameter_manager/component-parameter_manager-implementation.ads b/src/components/parameter_manager/component-parameter_manager-implementation.ads index 9965082..248c766 100644 --- a/src/components/parameter_manager/component-parameter_manager-implementation.ads +++ b/src/components/parameter_manager/component-parameter_manager-implementation.ads @@ -5,12 +5,16 @@ -- Includes: with Tick; with Command; +with Configuration; +with Parameter_Manager_Types; +with Parameter_Manager_Table_Header; with Parameters_Memory_Region_Release; with Protected_Variables; with Task_Synchronization; -with Memory_Region; --- This component is responsible for managing the working, scratch, and default parameter tables. Its sole responsibility is to respond to commands to copy parameter tables from one region to another or to dump the scratch region. +-- This component is responsible for managing a working and default parameter +-- table. Its sole responsibility is to respond to commands to copy parameter +-- tables from one region to another. package Component.Parameter_Manager.Implementation is -- The component class instance record: @@ -22,10 +26,14 @@ package Component.Parameter_Manager.Implementation is -- Initialization parameters for the Parameter Manager. -- -- Init Parameters: - -- parameter_Table_Length : Natural - The size of the parameter table in bytes. This must be known to the component so it can construct correct sized memory regions for the downstream components. - -- ticks_Until_Timeout : Natural - The component will wait until it has received at least this many ticks before reporting a timeout error while waiting for a parameter update/fetch response from either the active or default parameter components. For example, if the component is attached to a 10Hz rate group and this value is set to 7, then the component will wait between 700 and 800 ms before declaring a timeout error from an unresponsive downstream component. + -- Ticks_Until_Timeout : Natural - The component will wait until it has received + -- at least this many ticks before reporting a timeout error while waiting for a + -- parameter update/fetch response from either the working or default parameter + -- components. For example, if the component is attached to a 10Hz rate group and + -- this value is set to 7, then the component will wait between 700 and 800 ms + -- before declaring a timeout error from an unresponsive downstream component. -- - overriding procedure Init (Self : in out Instance; Parameter_Table_Length : in Natural; Ticks_Until_Timeout : in Natural); + overriding procedure Init (Self : in out Instance; Ticks_Until_Timeout : in Natural); private @@ -40,18 +48,6 @@ private Response : Protected_Parameters_Memory_Region_Release.Variable; -- Variables used for task synchronization and timeouts: Sync_Object : Task_Synchronization.Wait_Release_Timeout_Counter_Object; - -- Other configuration: - Parameter_Table_Length : Natural := 0; - -- Temporary storage to allow safe copying between Default and Working. - -- We declare this here, instead of as a temporary variable within a function - -- because if a timeout error occurs, we have no guarantee that the downstream - -- component is not reading/writing from this data. If it is declared here, then - -- at least only this data can be corrupted, and not the stack, which would be - -- a much worse situation. The assembly should be designed that timeout errors - -- never occur in order to fully prevent this issue. - Parameter_Bytes : Basic_Types.Byte_Array_Access; - -- Create a memory region that points to this buffer: - Parameter_Bytes_Region : Memory_Region.T; end record; --------------------------------------- @@ -69,13 +65,17 @@ private --------------------------------------- -- Invokee connector primitives: --------------------------------------- - -- The component should be attached to a periodic tick that is used to timeout waiting for a parameter update/fetch response. See the ticks_Until_Timeout initialization parameter. + -- The component should be attached to a periodic tick that is used to timeout + -- waiting for a parameter update/fetch response. See the ticks_Until_Timeout + -- initialization parameter. overriding procedure Timeout_Tick_Recv_Sync (Self : in out Instance; Arg : in Tick.T); -- The command receive connector. overriding procedure Command_T_Recv_Async (Self : in out Instance; Arg : in Command.T); -- This procedure is called when a Command_T_Recv_Async message is dropped due to a full queue. overriding procedure Command_T_Recv_Async_Dropped (Self : in out Instance; Arg : in Command.T); - -- Parameter update/fetch responses are returned synchronously on this connector. The component waits internally for this response, or times out if the response is not received in time. + -- Parameter update/fetch responses are returned synchronously on this connector. + -- The component waits internally for this response, or times out if the response + -- is not received in time. overriding procedure Parameters_Memory_Region_Release_T_Recv_Sync (Self : in out Instance; Arg : in Parameters_Memory_Region_Release.T); --------------------------------------- @@ -85,8 +85,12 @@ private overriding procedure Command_Response_T_Send_Dropped (Self : in out Instance; Arg : in Command_Response.T) is null; -- This procedure is called when a Working_Parameters_Memory_Region_Send message is dropped due to a full queue. overriding procedure Working_Parameters_Memory_Region_Send_Dropped (Self : in out Instance; Arg : in Parameters_Memory_Region.T) is null; - -- This procedure is called when a Default_Parameters_Memory_Region_Send message is dropped due to a full queue. - overriding procedure Default_Parameters_Memory_Region_Send_Dropped (Self : in out Instance; Arg : in Parameters_Memory_Region.T) is null; + -- This procedure is called when a Primary_Parameters_Memory_Region_Send message is dropped due to a full queue. + overriding procedure Primary_Parameters_Memory_Region_Send_Dropped (Self : in out Instance; Arg : in Parameters_Memory_Region.T) is null; + -- This procedure is called when a Redundant_Parameters_Memory_Region_Send message is dropped due to a full queue. + overriding procedure Redundant_Parameters_Memory_Region_Send_Dropped (Self : in out Instance; Arg : in Parameters_Memory_Region.T) is null; + -- This procedure is called when a Data_Product_T_Send message is dropped due to a full queue. + overriding procedure Data_Product_T_Send_Dropped (Self : in out Instance; Arg : in Data_Product.T) is null; -- This procedure is called when a Event_T_Send message is dropped due to a full queue. overriding procedure Event_T_Send_Dropped (Self : in out Instance; Arg : in Event.T) is null; @@ -94,11 +98,20 @@ private -- Command handler primitives: ----------------------------------------------- -- Description: - -- These are the commands for the Parameter Store component. - -- Copy parameter table from source to destination based on the enumeration provided. - overriding function Copy_Parameter_Table (Self : in out Instance; Arg : in Packed_Parameter_Table_Copy_Type.T) return Command_Execution_Status.E; + -- These are the commands for the Parameter Manager component. + -- Send received parameter table to default and working regions. + overriding function Update_Parameter_Table (Self : in out Instance; Arg : in Packed_Parameter_Table.T) return Command_Execution_Status.E; + -- Validate a received parameter table. + overriding function Validate_Parameter_Table (Self : in out Instance; Arg : in Packed_Parameter_Table.T) return Command_Execution_Status.E; -- Invalid command handler. This procedure is called when a command's arguments are found to be invalid: overriding procedure Invalid_Command (Self : in out Instance; Cmd : in Command.T; Errant_Field_Number : in Unsigned_32; Errant_Field : in Basic_Types.Poly_Type); + -- Compile time checks to make sure parameter manager types do not serialize longer than the size of the command buffer minus the parameter table header: + pragma Warnings (Off, "condition can only be True if invalid values present"); + pragma Compile_Time_Error ( + Configuration.Command_Buffer_Size - Parameter_Manager_Table_Header.Size_In_Bytes /= Parameter_Manager_Types.Parameter_Manager_Buffer_Type'Length, + "Parameter_Manager_Buffer_Length_Type has a maximum size in bytes unequal to the Command_Buffer_Size minus the Parameter_Manager_Table_Header size." + ); + pragma Warnings (On, "condition can only be True if invalid values present"); end Component.Parameter_Manager.Implementation; diff --git a/src/components/parameter_manager/doc/parameter_manager.pdf b/src/components/parameter_manager/doc/parameter_manager.pdf index dd88ca524d725912d99b70d406c03890cbbf3325..49eeb769d501ab6ff468456e77db185d66ca74d4 100644 GIT binary patch delta 162712 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%0Dcih{)NLsT;tO&mHf6cwBxO>FU^I8 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%0D^)Z8FsyTqT(Ug&C@_{|F4*m>1@-Ac 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�oxG!> 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 100); Self.Working_Parameters_Memory_Region_Recv_Sync_History.Init (Depth => 100); - Self.Default_Parameters_Memory_Region_Recv_Sync_History.Init (Depth => 100); + Self.Primary_Parameters_Memory_Region_Recv_Sync_History.Init (Depth => 100); + Self.Redundant_Parameters_Memory_Region_Recv_Sync_History.Init (Depth => 100); + Self.Data_Product_T_Recv_Sync_History.Init (Depth => 100); Self.Event_T_Recv_Sync_History.Init (Depth => 100); Self.Sys_Time_T_Return_History.Init (Depth => 100); -- Event histories: @@ -28,7 +30,13 @@ package body Component.Parameter_Manager.Implementation.Tester is Self.Invalid_Command_Received_History.Init (Depth => 100); Self.Parameter_Table_Copy_Timeout_History.Init (Depth => 100); Self.Parameter_Table_Copy_Failure_History.Init (Depth => 100); + Self.Working_Table_Update_Failure_History.Init (Depth => 100); + Self.Primary_Table_Update_Failure_History.Init (Depth => 100); Self.Command_Dropped_History.Init (Depth => 100); + Self.Table_Validation_Failure_History.Init (Depth => 100); + Self.Table_Validation_Success_History.Init (Depth => 100); + -- Data product histories: + Self.Validation_Status_History.Init (Depth => 100); end Init_Base; procedure Final_Base (Self : in out Instance) is @@ -37,7 +45,9 @@ package body Component.Parameter_Manager.Implementation.Tester is -- Connector histories: Self.Command_Response_T_Recv_Sync_History.Destroy; Self.Working_Parameters_Memory_Region_Recv_Sync_History.Destroy; - Self.Default_Parameters_Memory_Region_Recv_Sync_History.Destroy; + Self.Primary_Parameters_Memory_Region_Recv_Sync_History.Destroy; + Self.Redundant_Parameters_Memory_Region_Recv_Sync_History.Destroy; + Self.Data_Product_T_Recv_Sync_History.Destroy; Self.Event_T_Recv_Sync_History.Destroy; Self.Sys_Time_T_Return_History.Destroy; -- Event histories: @@ -46,7 +56,13 @@ package body Component.Parameter_Manager.Implementation.Tester is Self.Invalid_Command_Received_History.Destroy; Self.Parameter_Table_Copy_Timeout_History.Destroy; Self.Parameter_Table_Copy_Failure_History.Destroy; + Self.Working_Table_Update_Failure_History.Destroy; + Self.Primary_Table_Update_Failure_History.Destroy; Self.Command_Dropped_History.Destroy; + Self.Table_Validation_Failure_History.Destroy; + Self.Table_Validation_Success_History.Destroy; + -- Data product histories: + Self.Validation_Status_History.Destroy; -- Destroy component heap: Self.Component_Instance.Final_Base; @@ -59,7 +75,9 @@ package body Component.Parameter_Manager.Implementation.Tester is begin Self.Component_Instance.Attach_Command_Response_T_Send (To_Component => Self'Unchecked_Access, Hook => Self.Command_Response_T_Recv_Sync_Access); Self.Component_Instance.Attach_Working_Parameters_Memory_Region_Send (To_Component => Self'Unchecked_Access, Hook => Self.Working_Parameters_Memory_Region_Recv_Sync_Access); - Self.Component_Instance.Attach_Default_Parameters_Memory_Region_Send (To_Component => Self'Unchecked_Access, Hook => Self.Default_Parameters_Memory_Region_Recv_Sync_Access); + Self.Component_Instance.Attach_Primary_Parameters_Memory_Region_Send (To_Component => Self'Unchecked_Access, Hook => Self.Primary_Parameters_Memory_Region_Recv_Sync_Access); + Self.Component_Instance.Attach_Redundant_Parameters_Memory_Region_Send (To_Component => Self'Unchecked_Access, Hook => Self.Redundant_Parameters_Memory_Region_Recv_Sync_Access); + Self.Component_Instance.Attach_Data_Product_T_Send (To_Component => Self'Unchecked_Access, Hook => Self.Data_Product_T_Recv_Sync_Access); Self.Component_Instance.Attach_Event_T_Send (To_Component => Self'Unchecked_Access, Hook => Self.Event_T_Recv_Sync_Access); Self.Component_Instance.Attach_Sys_Time_T_Get (To_Component => Self'Unchecked_Access, Hook => Self.Sys_Time_T_Return_Access); Self.Attach_Timeout_Tick_Send (To_Component => Self.Component_Instance'Unchecked_Access, Hook => Self.Component_Instance.Timeout_Tick_Recv_Sync_Access); @@ -79,39 +97,33 @@ package body Component.Parameter_Manager.Implementation.Tester is -- Requests to update/fetch the working parameters are made on this connector. overriding procedure Working_Parameters_Memory_Region_Recv_Sync (Self : in out Instance; Arg : in Parameters_Memory_Region.T) is - use Parameter_Enums.Parameter_Table_Operation_Type; - begin - -- If it is a get then fill in the data: - if Arg.Operation = Get then - declare - subtype Safe_Byte_Array_Type is Basic_Types.Byte_Array (0 .. Arg.Region.Length - 1); - Safe_Byte_Array : Safe_Byte_Array_Type with Import, Convention => Ada, Address => Arg.Region.Address; - begin - Safe_Byte_Array := Self.Working; - end; - end if; - + begin -- Push the argument onto the test history for looking at later: Self.Working_Parameters_Memory_Region_Recv_Sync_History.Push (Arg); end Working_Parameters_Memory_Region_Recv_Sync; -- Requests to update/fetch the default parameters are made on this connector. - overriding procedure Default_Parameters_Memory_Region_Recv_Sync (Self : in out Instance; Arg : in Parameters_Memory_Region.T) is - use Parameter_Enums.Parameter_Table_Operation_Type; - begin - -- If it is a get then fill in the data: - if Arg.Operation = Get then - declare - subtype Safe_Byte_Array_Type is Basic_Types.Byte_Array (0 .. Arg.Region.Length - 1); - Safe_Byte_Array : Safe_Byte_Array_Type with Import, Convention => Ada, Address => Arg.Region.Address; - begin - Safe_Byte_Array := Self.Default; - end; - end if; + overriding procedure Primary_Parameters_Memory_Region_Recv_Sync (Self : in out Instance; Arg : in Parameters_Memory_Region.T) is + begin + -- Push the argument onto the test history for looking at later: + Self.Primary_Parameters_Memory_Region_Recv_Sync_History.Push (Arg); + end Primary_Parameters_Memory_Region_Recv_Sync; + -- Requests to update/fetch the default parameters are made on this connector. + overriding procedure Redundant_Parameters_Memory_Region_Recv_Sync (Self : in out Instance; Arg : in Parameters_Memory_Region.T) is + begin -- Push the argument onto the test history for looking at later: - Self.Default_Parameters_Memory_Region_Recv_Sync_History.Push (Arg); - end Default_Parameters_Memory_Region_Recv_Sync; + Self.Redundant_Parameters_Memory_Region_Recv_Sync_History.Push (Arg); + end Redundant_Parameters_Memory_Region_Recv_Sync; + + -- The destination for fetched data products to be sent to. + overriding procedure Data_Product_T_Recv_Sync (Self : in out Instance; Arg : in Data_Product.T) is + begin + -- Push the argument onto the test history for looking at later: + Self.Data_Product_T_Recv_Sync_History.Push (Arg); + -- Dispatch the data product to the correct handler: + Self.Dispatch_Data_Product (Arg); + end Data_Product_T_Recv_Sync; -- The event send connector overriding procedure Event_T_Recv_Sync (Self : in out Instance; Arg : in Event.T) is @@ -153,14 +165,14 @@ package body Component.Parameter_Manager.Implementation.Tester is -- Description: -- Events for the Parameter Manager component. -- Starting parameter table copy from source to destination. - overriding procedure Starting_Parameter_Table_Copy (Self : in out Instance; Arg : in Packed_Parameter_Table_Copy_Type.T) is + overriding procedure Starting_Parameter_Table_Copy (Self : in out Instance; Arg : in Parameter_Manager_Table_Header.T) is begin -- Push the argument onto the test history for looking at later: Self.Starting_Parameter_Table_Copy_History.Push (Arg); end Starting_Parameter_Table_Copy; -- Finished parameter table copy from source to destination, without errors. - overriding procedure Finished_Parameter_Table_Copy (Self : in out Instance; Arg : in Packed_Parameter_Table_Copy_Type.T) is + overriding procedure Finished_Parameter_Table_Copy (Self : in out Instance; Arg : in Parameter_Manager_Table_Header.T) is begin -- Push the argument onto the test history for looking at later: Self.Finished_Parameter_Table_Copy_History.Push (Arg); @@ -173,7 +185,8 @@ package body Component.Parameter_Manager.Implementation.Tester is Self.Invalid_Command_Received_History.Push (Arg); end Invalid_Command_Received; - -- A timeout occurred while waiting for a parameter table copy operation to complete. + -- A timeout occurred while waiting for a parameter table copy operation to + -- complete. overriding procedure Parameter_Table_Copy_Timeout (Self : in out Instance) is Arg : constant Natural := 0; begin @@ -188,6 +201,20 @@ package body Component.Parameter_Manager.Implementation.Tester is Self.Parameter_Table_Copy_Failure_History.Push (Arg); end Parameter_Table_Copy_Failure; + -- A parameter table copy to the working table failed. + overriding procedure Working_Table_Update_Failure (Self : in out Instance; Arg : in Packed_Validation_Header.T) is + begin + -- Push the argument onto the test history for looking at later: + Self.Working_Table_Update_Failure_History.Push (Arg); + end Working_Table_Update_Failure; + + -- A parameter table copy to the primary table failed. + overriding procedure Primary_Table_Update_Failure (Self : in out Instance; Arg : in Packed_Validation_Header.T) is + begin + -- Push the argument onto the test history for looking at later: + Self.Primary_Table_Update_Failure_History.Push (Arg); + end Primary_Table_Update_Failure; + -- A command was dropped due to a full queue. overriding procedure Command_Dropped (Self : in out Instance; Arg : in Command_Header.T) is begin @@ -195,6 +222,32 @@ package body Component.Parameter_Manager.Implementation.Tester is Self.Command_Dropped_History.Push (Arg); end Command_Dropped; + -- A parameter table validation failed. + overriding procedure Table_Validation_Failure (Self : in out Instance; Arg : in Packed_Validation_Header.T) is + begin + -- Push the argument onto the test history for looking at later: + Self.Table_Validation_Failure_History.Push (Arg); + end Table_Validation_Failure; + + -- A parameter table validation was successful. + overriding procedure Table_Validation_Success (Self : in out Instance; Arg : in Packed_Validation_Header.T) is + begin + -- Push the argument onto the test history for looking at later: + Self.Table_Validation_Success_History.Push (Arg); + end Table_Validation_Success; + + ----------------------------------------------- + -- Data product handler primitive: + ----------------------------------------------- + -- Description: + -- Data products for the Parameter Manager component + -- The validation status with timestamp and last table ID/version. + overriding procedure Validation_Status (Self : in out Instance; Arg : in Packed_Validation.T) is + begin + -- Push the argument onto the test history for looking at later: + Self.Validation_Status_History.Push (Arg); + end Validation_Status; + ----------------------------------------------- -- Special primitives for activating component -- queues: @@ -218,12 +271,4 @@ package body Component.Parameter_Manager.Implementation.Tester is return Num_Dispatched; end Dispatch_N; - ----------------------------------------------- - -- Custom white-box testing functions: - ----------------------------------------------- - function Get_Parameter_Bytes_Region (Self : in out Instance) return Memory_Region.T is - begin - return Self.Component_Instance.Parameter_Bytes_Region; - end Get_Parameter_Bytes_Region; - end Component.Parameter_Manager.Implementation.Tester; diff --git a/src/components/parameter_manager/test/component-parameter_manager-implementation-tester.ads b/src/components/parameter_manager/test/component-parameter_manager-implementation-tester.ads index 2189381..6e3444f 100644 --- a/src/components/parameter_manager/test/component-parameter_manager-implementation-tester.ads +++ b/src/components/parameter_manager/test/component-parameter_manager-implementation-tester.ads @@ -7,32 +7,47 @@ with Component.Parameter_Manager_Reciprocal; with Printable_History; with Command_Response.Representation; with Parameters_Memory_Region.Representation; +with Data_Product.Representation; with Event.Representation; with Sys_Time.Representation; +with Data_Product; +with Packed_Validation.Representation; +with Packed_Validation_Header.Representation; with Event; -with Packed_Parameter_Table_Copy_Type.Representation; +with Parameter_Manager_Table_Header.Representation; with Invalid_Command_Info.Representation; with Parameters_Memory_Region_Release.Representation; with Command_Header.Representation; --- This component is responsible for managing a working and default parameter table. Its sole responsibility is to respond to commands to copy parameter tables from one region to another. +-- This component is responsible for managing a working and default parameter +-- table. Its sole responsibility is to respond to commands to copy parameter +-- tables from one region to another. package Component.Parameter_Manager.Implementation.Tester is use Component.Parameter_Manager_Reciprocal; -- Invoker connector history packages: package Command_Response_T_Recv_Sync_History_Package is new Printable_History (Command_Response.T, Command_Response.Representation.Image); package Working_Parameters_Memory_Region_Recv_Sync_History_Package is new Printable_History (Parameters_Memory_Region.T, Parameters_Memory_Region.Representation.Image); - package Default_Parameters_Memory_Region_Recv_Sync_History_Package is new Printable_History (Parameters_Memory_Region.T, Parameters_Memory_Region.Representation.Image); + package Primary_Parameters_Memory_Region_Recv_Sync_History_Package is new Printable_History (Parameters_Memory_Region.T, Parameters_Memory_Region.Representation.Image); + package Redundant_Parameters_Memory_Region_Recv_Sync_History_Package is new Printable_History (Parameters_Memory_Region.T, Parameters_Memory_Region.Representation.Image); + package Data_Product_T_Recv_Sync_History_Package is new Printable_History (Data_Product.T, Data_Product.Representation.Image); package Event_T_Recv_Sync_History_Package is new Printable_History (Event.T, Event.Representation.Image); package Sys_Time_T_Return_History_Package is new Printable_History (Sys_Time.T, Sys_Time.Representation.Image); -- Event history packages: - package Starting_Parameter_Table_Copy_History_Package is new Printable_History (Packed_Parameter_Table_Copy_Type.T, Packed_Parameter_Table_Copy_Type.Representation.Image); - package Finished_Parameter_Table_Copy_History_Package is new Printable_History (Packed_Parameter_Table_Copy_Type.T, Packed_Parameter_Table_Copy_Type.Representation.Image); + package Starting_Parameter_Table_Copy_History_Package is new Printable_History (Parameter_Manager_Table_Header.T, Parameter_Manager_Table_Header.Representation.Image); + package Finished_Parameter_Table_Copy_History_Package is new Printable_History (Parameter_Manager_Table_Header.T, Parameter_Manager_Table_Header.Representation.Image); package Invalid_Command_Received_History_Package is new Printable_History (Invalid_Command_Info.T, Invalid_Command_Info.Representation.Image); package Parameter_Table_Copy_Timeout_History_Package is new Printable_History (Natural, Natural'Image); package Parameter_Table_Copy_Failure_History_Package is new Printable_History (Parameters_Memory_Region_Release.T, Parameters_Memory_Region_Release.Representation.Image); + package Working_Table_Update_Failure_History_Package is new Printable_History (Packed_Validation_Header.T, Packed_Validation_Header.Representation.Image); + package Primary_Table_Update_Failure_History_Package is new Printable_History (Packed_Validation_Header.T, Packed_Validation_Header.Representation.Image); package Command_Dropped_History_Package is new Printable_History (Command_Header.T, Command_Header.Representation.Image); + package Table_Validation_Failure_History_Package is new Printable_History (Packed_Validation_Header.T, Packed_Validation_Header.Representation.Image); + package Table_Validation_Success_History_Package is new Printable_History (Packed_Validation_Header.T, Packed_Validation_Header.Representation.Image); + + -- Data product history packages: + package Validation_Status_History_Package is new Printable_History (Packed_Validation.T, Packed_Validation.Representation.Image); -- Component class instance: type Instance is new Component.Parameter_Manager_Reciprocal.Base_Instance with record @@ -41,7 +56,9 @@ package Component.Parameter_Manager.Implementation.Tester is -- Connector histories: Command_Response_T_Recv_Sync_History : Command_Response_T_Recv_Sync_History_Package.Instance; Working_Parameters_Memory_Region_Recv_Sync_History : Working_Parameters_Memory_Region_Recv_Sync_History_Package.Instance; - Default_Parameters_Memory_Region_Recv_Sync_History : Default_Parameters_Memory_Region_Recv_Sync_History_Package.Instance; + Primary_Parameters_Memory_Region_Recv_Sync_History : Primary_Parameters_Memory_Region_Recv_Sync_History_Package.Instance; + Redundant_Parameters_Memory_Region_Recv_Sync_History : Redundant_Parameters_Memory_Region_Recv_Sync_History_Package.Instance; + Data_Product_T_Recv_Sync_History : Data_Product_T_Recv_Sync_History_Package.Instance; Event_T_Recv_Sync_History : Event_T_Recv_Sync_History_Package.Instance; Sys_Time_T_Return_History : Sys_Time_T_Return_History_Package.Instance; -- Event histories: @@ -50,13 +67,16 @@ package Component.Parameter_Manager.Implementation.Tester is Invalid_Command_Received_History : Invalid_Command_Received_History_Package.Instance; Parameter_Table_Copy_Timeout_History : Parameter_Table_Copy_Timeout_History_Package.Instance; Parameter_Table_Copy_Failure_History : Parameter_Table_Copy_Failure_History_Package.Instance; + Working_Table_Update_Failure_History : Working_Table_Update_Failure_History_Package.Instance; + Primary_Table_Update_Failure_History : Primary_Table_Update_Failure_History_Package.Instance; Command_Dropped_History : Command_Dropped_History_Package.Instance; + Table_Validation_Failure_History : Table_Validation_Failure_History_Package.Instance; + Table_Validation_Success_History : Table_Validation_Success_History_Package.Instance; + -- Data product histories: + Validation_Status_History : Validation_Status_History_Package.Instance; -- Booleans to control assertion if message is dropped on async queue: Expect_Command_T_Send_Dropped : Boolean := False; Command_T_Send_Dropped_Count : Natural := 0; - -- Memory regions for simulation: - Default : Basic_Types.Byte_Array (0 .. 99) := [others => 14]; - Working : Basic_Types.Byte_Array (0 .. 99) := [others => 14]; end record; type Instance_Access is access all Instance; @@ -79,7 +99,11 @@ package Component.Parameter_Manager.Implementation.Tester is -- Requests to update/fetch the working parameters are made on this connector. overriding procedure Working_Parameters_Memory_Region_Recv_Sync (Self : in out Instance; Arg : in Parameters_Memory_Region.T); -- Requests to update/fetch the default parameters are made on this connector. - overriding procedure Default_Parameters_Memory_Region_Recv_Sync (Self : in out Instance; Arg : in Parameters_Memory_Region.T); + overriding procedure Primary_Parameters_Memory_Region_Recv_Sync (Self : in out Instance; Arg : in Parameters_Memory_Region.T); + -- Requests to update/fetch the default parameters are made on this connector. + overriding procedure Redundant_Parameters_Memory_Region_Recv_Sync (Self : in out Instance; Arg : in Parameters_Memory_Region.T); + -- The destination for fetched data products to be sent to. + overriding procedure Data_Product_T_Recv_Sync (Self : in out Instance; Arg : in Data_Product.T); -- The event send connector overriding procedure Event_T_Recv_Sync (Self : in out Instance; Arg : in Event.T); -- The system time is retrieved via this connector. @@ -97,17 +121,34 @@ package Component.Parameter_Manager.Implementation.Tester is -- Description: -- Events for the Parameter Manager component. -- Starting parameter table copy from source to destination. - overriding procedure Starting_Parameter_Table_Copy (Self : in out Instance; Arg : in Packed_Parameter_Table_Copy_Type.T); + overriding procedure Starting_Parameter_Table_Copy (Self : in out Instance; Arg : in Parameter_Manager_Table_Header.T); -- Finished parameter table copy from source to destination, without errors. - overriding procedure Finished_Parameter_Table_Copy (Self : in out Instance; Arg : in Packed_Parameter_Table_Copy_Type.T); + overriding procedure Finished_Parameter_Table_Copy (Self : in out Instance; Arg : in Parameter_Manager_Table_Header.T); -- A command was received with invalid parameters. overriding procedure Invalid_Command_Received (Self : in out Instance; Arg : in Invalid_Command_Info.T); - -- A timeout occurred while waiting for a parameter table copy operation to complete. + -- A timeout occurred while waiting for a parameter table copy operation to + -- complete. overriding procedure Parameter_Table_Copy_Timeout (Self : in out Instance); -- A parameter table copy failed. overriding procedure Parameter_Table_Copy_Failure (Self : in out Instance; Arg : in Parameters_Memory_Region_Release.T); + -- A parameter table copy to the working table failed. + overriding procedure Working_Table_Update_Failure (Self : in out Instance; Arg : in Packed_Validation_Header.T); + -- A parameter table copy to the primary table failed. + overriding procedure Primary_Table_Update_Failure (Self : in out Instance; Arg : in Packed_Validation_Header.T); -- A command was dropped due to a full queue. overriding procedure Command_Dropped (Self : in out Instance; Arg : in Command_Header.T); + -- A parameter table validation failed. + overriding procedure Table_Validation_Failure (Self : in out Instance; Arg : in Packed_Validation_Header.T); + -- A parameter table validation was successful. + overriding procedure Table_Validation_Success (Self : in out Instance; Arg : in Packed_Validation_Header.T); + + ----------------------------------------------- + -- Data product handler primitives: + ----------------------------------------------- + -- Description: + -- Data products for the Parameter Manager component + -- The validation status with timestamp and last table ID/version. + overriding procedure Validation_Status (Self : in out Instance; Arg : in Packed_Validation.T); ----------------------------------------------- -- Special primitives for activating component @@ -118,8 +159,4 @@ package Component.Parameter_Manager.Implementation.Tester is -- Tell the component to dispatch n items off of its queue: not overriding function Dispatch_N (Self : in out Instance; N : in Positive := 1) return Natural; - ----------------------------------------------- - -- Custom white-box testing functions: - ----------------------------------------------- - function Get_Parameter_Bytes_Region (Self : in out Instance) return Memory_Region.T; end Component.Parameter_Manager.Implementation.Tester; diff --git a/src/components/parameter_manager/test/env.py b/src/components/parameter_manager/test/env.py index ebe0450..8d5248e 100644 --- a/src/components/parameter_manager/test/env.py +++ b/src/components/parameter_manager/test/env.py @@ -1,9 +1 @@ from environments import test # noqa: F401 -import os.path - -this_dir = os.path.dirname(os.path.realpath(__file__)) -os.environ["EXTRA_BUILD_PATH"] = this_dir + os.pathsep \ - + os.path.realpath(os.path.join(this_dir, "test_component_1")) + os.pathsep \ - + os.path.realpath(os.path.join(this_dir, "test_component_2")) + os.pathsep \ - + os.path.realpath(os.path.join(this_dir, "..")) + os.pathsep \ - + os.path.realpath(os.path.join(this_dir, "test_assembly")) diff --git a/src/components/parameter_manager/test/parameter_manager.tests.yaml b/src/components/parameter_manager/test/parameter_manager.tests.yaml index e66aa02..fae5f1b 100644 --- a/src/components/parameter_manager/test/parameter_manager.tests.yaml +++ b/src/components/parameter_manager/test/parameter_manager.tests.yaml @@ -1,10 +1,14 @@ --- description: This is a unit test suite for the Parameter Manager component. tests: - - name: Test_Nominal_Copy_Default_To_Working - description: This unit test tests the nominal copy command from default to working. - - name: Test_Nominal_Copy_Working_To_Default - description: This unit test tests the nominal copy command from working to default. + - name: Test_Nominal_Validation + description: This unit test tests the nominal validation command. + - name: Test_Validation_Failure + description: This unit test tests the component's response to a failed validation. + - name: Test_Validation_Timeout + description: This unit test tests the component's response when the destination component does not respond to a validation command before a timeout occurs. + - name: Test_Nominal_Copy + description: This unit test tests the nominal copy command. - name: Test_Copy_Failure description: This unit test tests the component's response to a failed parameter table copy. - name: Test_Copy_Timeout diff --git a/src/components/parameter_manager/test/parameter_manager_tests-implementation.adb b/src/components/parameter_manager/test/parameter_manager_tests-implementation.adb index 0904e36..4173cb3 100644 --- a/src/components/parameter_manager/test/parameter_manager_tests-implementation.adb +++ b/src/components/parameter_manager/test/parameter_manager_tests-implementation.adb @@ -4,21 +4,25 @@ with Ada.Real_Time; with Basic_Assertions; use Basic_Assertions; -with Command_Response.Assertion; use Command_Response.Assertion; with Command_Enums; use Command_Enums.Command_Response_Status; +with Serializer_Types; use Serializer_Types; +with Smart_Assert; +with System; use System; with Command; +with Command_Header.Assertion; use Command_Header.Assertion; +with Command_Response.Assertion; use Command_Response.Assertion; +with Parameters_Memory_Region; with Interfaces; use Interfaces; -with Memory_Region; -with Parameters_Memory_Region.Assertion; use Parameters_Memory_Region.Assertion; -with Parameters_Memory_Region_Release.Assertion; use Parameters_Memory_Region_Release.Assertion; -with Parameter_Enums; -with Parameter_Manager_Enums; use Parameter_Manager_Enums.Parameter_Table_Copy_Type; +with Parameter_Enums; use Parameter_Enums.Parameter_Table_Update_Status; with Basic_Types; with Invalid_Command_Info.Assertion; use Invalid_Command_Info.Assertion; -with Command_Header.Assertion; use Command_Header.Assertion; -with Packed_Parameter_Table_Copy_Type.Assertion; use Packed_Parameter_Table_Copy_Type.Assertion; -use Parameter_Enums.Parameter_Table_Update_Status; -use Parameter_Enums.Parameter_Table_Operation_Type; +with Parameter_Manager_Types; +with Parameter_Manager_Commands; +with Packed_Parameter_Table; +with Parameter_Manager_Table_Header; +with Parameter_Manager_Table_Header.Assertion; use Parameter_Manager_Table_Header.Assertion; +with Packed_Validation_Header; +with Packed_Validation; use Packed_Validation; package body Parameter_Manager_Tests.Implementation is @@ -44,13 +48,13 @@ package body Parameter_Manager_Tests.Implementation is Task_Response2 := Parameter_Enums.Parameter_Table_Update_Status.Success; -- Allocate heap memory to component: - Self.Tester.Init_Base (Queue_Size => Self.Tester.Component_Instance.Get_Max_Queue_Element_Size * 3); + Self.Tester.Init_Base (Queue_Size => Self.Tester.Component_Instance.Get_Max_Queue_Element_Size * 10); -- Make necessary connections between tester and component: Self.Tester.Connect; -- Call component init here. - Self.Tester.Component_Instance.Init (Parameter_Table_Length => 100, Ticks_Until_Timeout => 3); + Self.Tester.Component_Instance.Init (Ticks_Until_Timeout => 3); -- Call the component set up method that the assembly would normally call. Self.Tester.Component_Instance.Set_Up; @@ -81,8 +85,8 @@ package body Parameter_Manager_Tests.Implementation is Task_Exit : Boolean_Access ); - Sim_Bytes : aliased Basic_Types.Byte_Array := [0 .. 99 => 12]; - Sim_Bytes_2 : aliased Basic_Types.Byte_Array := [0 .. 99 => 11]; + Sim_Bytes : aliased Basic_Types.Byte_Array := [0 .. 246 => 12]; + Sim_Bytes_2 : aliased Basic_Types.Byte_Array := [0 .. 246 => 11]; task body Simulator_Task is Ignore : Natural; @@ -130,360 +134,605 @@ package body Parameter_Manager_Tests.Implementation is ------------------------------------------------------------------------- -- Tests: ------------------------------------------------------------------------- - overriding procedure Test_Nominal_Copy_Default_To_Working (Self : in out Instance) is + + package Ser_Status_Assert is new Smart_Assert.Discrete (Serializer_Types.Serialization_Status, Serializer_Types.Serialization_Status'Image); + + package Validation_Status_Assert is new Smart_Assert.Discrete (Parameter_Enums.Parameter_Table_Update_Status.E, Parameter_Enums.Parameter_Table_Update_Status.E'Image); + + -- This unit test tests the nominal validation command. + overriding procedure Test_Nominal_Validation (Self : in out Instance) is + use Parameter_Manager_Table_Header; T : Component.Parameter_Manager.Implementation.Tester.Instance_Access renames Self.Tester; Task_Exit : aliased Boolean := False; Sim_Task : Simulator_Task (Self'Unchecked_Access, Task_Exit'Unchecked_Access); + Table : aliased constant Basic_Types.Byte_Array := [0 .. 246 => 10]; + Packed_Table : constant Packed_Parameter_Table.T := ( + Header => ( + Table_Buffer_Length => Table'Length, + Crc_Table => [0 .. 1 => 0], + Version => 0.0 + ), + Table_Buffer => Table + ); + Cmd : Command.T; + Assert_Header : Packed_Validation_Header.T; + Assert_Region_Length : constant Integer := Packed_Table.Header.Table_Buffer_Length + Parameter_Manager_Table_Header.Crc_Table_Size_In_Bytes + Parameter_Manager_Table_Header.Version_Size_In_Bytes; + Assert_Region : Parameters_Memory_Region.T; + Assert_Data_Product : Packed_Validation.T; begin - -- Send copy command: - T.Command_T_Send (T.Commands.Copy_Parameter_Table ((Copy_Type => Default_To_Working))); + -- Send validate table command: + Ser_Status_Assert.Eq (T.Commands.Validate_Parameter_Table (Packed_Table, Cmd), Success); + T.Command_T_Send (Cmd); -- Execute the command and tell the task to respond. - Task_Send_Response_Twice := True; + Task_Send_Response := True; Natural_Assert.Eq (T.Dispatch_All, 1); - -- Copy to working should have occurred now. Check data: - Natural_Assert.Eq (T.Default_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 1); - Parameters_Memory_Region_Assert.Eq ( - T.Default_Parameters_Memory_Region_Recv_Sync_History.Get (1), - (Region => T.Get_Parameter_Bytes_Region, Operation => Get) - ); + -- Table validation should have occurred now. + -- Assert working parameters connector: Natural_Assert.Eq (T.Working_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 1); - Parameters_Memory_Region_Assert.Eq ( - T.Working_Parameters_Memory_Region_Recv_Sync_History.Get (1), - (Region => T.Get_Parameter_Bytes_Region, Operation => Set) - ); - - -- Check region data: - declare - Region : constant Memory_Region.T := T.Get_Parameter_Bytes_Region; - subtype Safe_Byte_Array_Type is Basic_Types.Byte_Array (0 .. Region.Length - 1); - Safe_Byte_Array : Safe_Byte_Array_Type with Import, Convention => Ada, Address => Region.Address; - begin - Byte_Array_Assert.Eq (Safe_Byte_Array, T.Default); - end; - - -- Check events: - Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 2); - Natural_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get_Count, 1); - Packed_Parameter_Table_Copy_Type_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get (1), (Copy_Type => Default_To_Working)); - Natural_Assert.Eq (T.Finished_Parameter_Table_Copy_History.Get_Count, 1); - Packed_Parameter_Table_Copy_Type_Assert.Eq (T.Finished_Parameter_Table_Copy_History.Get (1), (Copy_Type => Default_To_Working)); + -- Assert connector table region length: + Assert_Region := T.Working_Parameters_Memory_Region_Recv_Sync_History.Get (1); + Natural_Assert.Eq (Assert_Region.Region.Length, Assert_Region_Length); + -- Assert working connector address is not null: + Address_Assert.Neq (Assert_Region.Region.Address, System.Null_Address); + -- Assert table validation success: + Natural_Assert.Eq (T.Table_Validation_Success_History.Get_Count, 1); + -- Assert validation header: + Assert_Header := T.Table_Validation_Success_History.Get (1); + Parameter_Manager_Table_Header_Assert.Eq (Assert_Header.Last_Validation_Header, Packed_Table.Header); + -- Assert last validation status: + Validation_Status_Assert.Eq (Assert_Header.Last_Validation_Status, Success); + -- Assert data product was produced: + Natural_Assert.Eq (T.Data_Product_T_Recv_Sync_History.Get_Count, 1); + Natural_Assert.Eq (T.Validation_Status_History.Get_Count, 1); + -- Assert data product contents: + Assert_Data_Product := T.Validation_Status_History.Get (1); + Validation_Status_Assert.Eq (Assert_Data_Product.Last_Validation_Status, Success); -- Check command response: Natural_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get_Count, 1); - Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (1), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Copy_Parameter_Table_Id, Status => Success)); + Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (1), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Validate_Parameter_Table_Id, Status => Success)); -- Kill our helper task. Task_Exit := True; - end Test_Nominal_Copy_Default_To_Working; + end Test_Nominal_Validation; - overriding procedure Test_Nominal_Copy_Working_To_Default (Self : in out Instance) is + -- This unit test tests the component's response to a failed validation. + overriding procedure Test_Validation_Failure (Self : in out Instance) is + use Parameter_Manager_Table_Header; T : Component.Parameter_Manager.Implementation.Tester.Instance_Access renames Self.Tester; Task_Exit : aliased Boolean := False; Sim_Task : Simulator_Task (Self'Unchecked_Access, Task_Exit'Unchecked_Access); + Table : aliased constant Basic_Types.Byte_Array := [0 .. 246 => 10]; + Packed_Table : constant Packed_Parameter_Table.T := ( + Header => ( + Table_Buffer_Length => Table'Length, + Crc_Table => [0 .. 1 => 0], + Version => 0.0 + ), + Table_Buffer => Table + ); + Cmd : Command.T; + Assert_Header : Packed_Validation_Header.T; + Assert_Region_Length : constant Integer := Packed_Table.Header.Table_Buffer_Length + Parameter_Manager_Table_Header.Crc_Table_Size_In_Bytes + Parameter_Manager_Table_Header.Version_Size_In_Bytes; + Assert_Region : Parameters_Memory_Region.T; + Assert_Data_Product : Packed_Validation.T; begin - -- Send copy command: - T.Command_T_Send (T.Commands.Copy_Parameter_Table ((Copy_Type => Working_To_Default))); + -- Set task response to something other than success: + Task_Response := Parameter_Enums.Parameter_Table_Update_Status.Parameter_Error; + -- Send validate table command: + Ser_Status_Assert.Eq (T.Commands.Validate_Parameter_Table (Packed_Table, Cmd), Success); + T.Command_T_Send (Cmd); -- Execute the command and tell the task to respond. - Task_Send_Response_Twice := True; + Task_Send_Response := True; Natural_Assert.Eq (T.Dispatch_All, 1); - -- Copy to working should have occurred now. Check data: + -- Table validation should have occurred now. + -- Assert working parameters connector: Natural_Assert.Eq (T.Working_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 1); - Parameters_Memory_Region_Assert.Eq ( - T.Working_Parameters_Memory_Region_Recv_Sync_History.Get (1), - (Region => T.Get_Parameter_Bytes_Region, Operation => Get) - ); - Natural_Assert.Eq (T.Default_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 1); - Parameters_Memory_Region_Assert.Eq ( - T.Default_Parameters_Memory_Region_Recv_Sync_History.Get (1), - (Region => T.Get_Parameter_Bytes_Region, Operation => Set) - ); - - -- Check region data: - declare - Region : constant Memory_Region.T := T.Get_Parameter_Bytes_Region; - subtype Safe_Byte_Array_Type is Basic_Types.Byte_Array (0 .. Region.Length - 1); - Safe_Byte_Array : Safe_Byte_Array_Type with Import, Convention => Ada, Address => Region.Address; - begin - Byte_Array_Assert.Eq (Safe_Byte_Array, T.Working); - end; - - -- Check events: - Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 2); - Natural_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get_Count, 1); - Packed_Parameter_Table_Copy_Type_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get (1), (Copy_Type => Working_To_Default)); - Natural_Assert.Eq (T.Finished_Parameter_Table_Copy_History.Get_Count, 1); - Packed_Parameter_Table_Copy_Type_Assert.Eq (T.Finished_Parameter_Table_Copy_History.Get (1), (Copy_Type => Working_To_Default)); + -- Assert connector table region length: + Assert_Region := T.Working_Parameters_Memory_Region_Recv_Sync_History.Get (1); + Natural_Assert.Eq (Assert_Region.Region.Length, Assert_Region_Length); + -- Assert working connector address is not null: + Address_Assert.Neq (Assert_Region.Region.Address, System.Null_Address); + -- Assert table validation failure: + Natural_Assert.Eq (T.Table_Validation_Failure_History.Get_Count, 1); + -- Assert validation header: + Assert_Header := T.Table_Validation_Failure_History.Get (1); + Parameter_Manager_Table_Header_Assert.Eq (Assert_Header.Last_Validation_Header, Packed_Table.Header); + -- Assert last validation status: + Validation_Status_Assert.Eq (Assert_Header.Last_Validation_Status, Parameter_Error); + -- Assert data product was produced: + Natural_Assert.Eq (T.Data_Product_T_Recv_Sync_History.Get_Count, 1); + Natural_Assert.Eq (T.Validation_Status_History.Get_Count, 1); + -- Assert data product contents: + Assert_Data_Product := T.Validation_Status_History.Get (1); + Validation_Status_Assert.Eq (Assert_Data_Product.Last_Validation_Status, Parameter_Error); -- Check command response: Natural_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get_Count, 1); - Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (1), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Copy_Parameter_Table_Id, Status => Success)); + Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (1), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Validate_Parameter_Table_Id, Status => Failure)); -- Kill our helper task. Task_Exit := True; - end Test_Nominal_Copy_Working_To_Default; + end Test_Validation_Failure; - overriding procedure Test_Copy_Failure (Self : in out Instance) is + -- This unit test tests the component's response when the destination component + -- does not respond to a validation command before a timeout occurs. + overriding procedure Test_Validation_Timeout (Self : in out Instance) is + use Parameter_Manager_Table_Header; T : Component.Parameter_Manager.Implementation.Tester.Instance_Access renames Self.Tester; Task_Exit : aliased Boolean := False; Sim_Task : Simulator_Task (Self'Unchecked_Access, Task_Exit'Unchecked_Access); + Table : aliased constant Basic_Types.Byte_Array := [0 .. 246 => 10]; + Packed_Table : constant Packed_Parameter_Table.T := ( + Header => ( + Table_Buffer_Length => Table'Length, + Crc_Table => [0 .. 1 => 0], + Version => 0.0 + ), + Table_Buffer => Table + ); + Cmd : Command.T; + Assert_Header : Packed_Validation_Header.T; + Assert_Region_Length : constant Integer := Packed_Table.Header.Table_Buffer_Length + Parameter_Manager_Table_Header.Crc_Table_Size_In_Bytes + Parameter_Manager_Table_Header.Version_Size_In_Bytes; + Assert_Region : Parameters_Memory_Region.T; + Assert_Data_Product : Packed_Validation.T; begin - -- Set task response to something other than success: - Task_Response := Parameter_Enums.Parameter_Table_Update_Status.Parameter_Error; - - -- Send copy command: - T.Command_T_Send (T.Commands.Copy_Parameter_Table ((Copy_Type => Working_To_Default))); + -- First, send a normal validate table command: + Ser_Status_Assert.Eq (T.Commands.Validate_Parameter_Table (Packed_Table, Cmd), Success); + T.Command_T_Send (Cmd); -- Execute the command and tell the task to respond. Task_Send_Response := True; Natural_Assert.Eq (T.Dispatch_All, 1); - -- Copy from working should have occurred now. Check data: + -- Table validation should have occurred now. + -- Assert working parameters connector: Natural_Assert.Eq (T.Working_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 1); - Parameters_Memory_Region_Assert.Eq ( - T.Working_Parameters_Memory_Region_Recv_Sync_History.Get (1), - (Region => T.Get_Parameter_Bytes_Region, Operation => Get) - ); - -- No copy to default: - Natural_Assert.Eq (T.Default_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 0); - - -- Check events: - Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 2); - Natural_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get_Count, 1); - Packed_Parameter_Table_Copy_Type_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get (1), (Copy_Type => Working_To_Default)); - Natural_Assert.Eq (T.Finished_Parameter_Table_Copy_History.Get_Count, 0); - Natural_Assert.Eq (T.Parameter_Table_Copy_Failure_History.Get_Count, 1); - Parameters_Memory_Region_Release_Assert.Eq (T.Parameter_Table_Copy_Failure_History.Get (1), ( - Region => (Address => Sim_Bytes'Address, Length => Sim_Bytes'Length), - Status => Parameter_Enums.Parameter_Table_Update_Status.Parameter_Error - )); + -- Assert connector table region length: + Assert_Region := T.Working_Parameters_Memory_Region_Recv_Sync_History.Get (1); + Natural_Assert.Eq (Assert_Region.Region.Length, Assert_Region_Length); + -- Assert working connector address is not null: + Address_Assert.Neq (Assert_Region.Region.Address, System.Null_Address); + -- Assert table validation success: + Natural_Assert.Eq (T.Table_Validation_Success_History.Get_Count, 1); + -- Assert validation header: + Assert_Header := T.Table_Validation_Success_History.Get (1); + Parameter_Manager_Table_Header_Assert.Eq (Assert_Header.Last_Validation_Header, Packed_Table.Header); + -- Assert last validation status: + Validation_Status_Assert.Eq (Assert_Header.Last_Validation_Status, Success); + -- Assert data product was produced: + Natural_Assert.Eq (T.Data_Product_T_Recv_Sync_History.Get_Count, 1); + Natural_Assert.Eq (T.Validation_Status_History.Get_Count, 1); + -- Assert data product contents: + Assert_Data_Product := T.Validation_Status_History.Get (1); + Validation_Status_Assert.Eq (Assert_Data_Product.Last_Validation_Status, Success); -- Check command response: Natural_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get_Count, 1); - Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (1), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Copy_Parameter_Table_Id, Status => Failure)); + Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (1), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Validate_Parameter_Table_Id, Status => Success)); - -- Set task response 2 to something other than success: - Task_Response := Parameter_Enums.Parameter_Table_Update_Status.Crc_Error; - Task_Response2 := Parameter_Enums.Parameter_Table_Update_Status.Success; - - -- Send copy command: - T.Command_T_Send (T.Commands.Copy_Parameter_Table ((Copy_Type => Working_To_Default))); + -- Test validate table timeout: + -- Send validate table command: + Ser_Status_Assert.Eq (T.Commands.Validate_Parameter_Table (Packed_Table, Cmd), Success); + T.Command_T_Send (Cmd); -- Execute the command and tell the task to respond. - Task_Send_Response_Twice := True; + Task_Send_Timeout := True; Natural_Assert.Eq (T.Dispatch_All, 1); - -- Copy from working should have occurred now. Check data: + -- Table validation timeout should have occurred now. + -- Assert working parameters connector: Natural_Assert.Eq (T.Working_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 2); - Parameters_Memory_Region_Assert.Eq ( - T.Working_Parameters_Memory_Region_Recv_Sync_History.Get (2), - (Region => T.Get_Parameter_Bytes_Region, Operation => Get) - ); - -- Copy to default: - Natural_Assert.Eq (T.Default_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 1); - Parameters_Memory_Region_Assert.Eq ( - T.Default_Parameters_Memory_Region_Recv_Sync_History.Get (1), - (Region => T.Get_Parameter_Bytes_Region, Operation => Set) - ); - - -- Check events: - Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 4); - Natural_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get_Count, 2); - Packed_Parameter_Table_Copy_Type_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get (2), (Copy_Type => Working_To_Default)); - Natural_Assert.Eq (T.Finished_Parameter_Table_Copy_History.Get_Count, 0); - Natural_Assert.Eq (T.Parameter_Table_Copy_Failure_History.Get_Count, 2); - Parameters_Memory_Region_Release_Assert.Eq (T.Parameter_Table_Copy_Failure_History.Get (2), ( - Region => (Address => Sim_Bytes'Address, Length => Sim_Bytes'Length), - Status => Parameter_Enums.Parameter_Table_Update_Status.Crc_Error - )); + -- Assert connector table region length: + Assert_Region := T.Working_Parameters_Memory_Region_Recv_Sync_History.Get (2); + Natural_Assert.Eq (Assert_Region.Region.Length, Assert_Region_Length); + -- Assert working connector address is not null: + Address_Assert.Neq (Assert_Region.Region.Address, System.Null_Address); + -- Assert table validation failure: + Natural_Assert.Eq (T.Table_Validation_Failure_History.Get_Count, 1); + -- Assert validation header: + Assert_Header := T.Table_Validation_Failure_History.Get (1); + Parameter_Manager_Table_Header_Assert.Eq (Assert_Header.Last_Validation_Header, Packed_Table.Header); + -- Assert last validation status: + Validation_Status_Assert.Eq (Assert_Header.Last_Validation_Status, Success); + -- Assert data product was produced: + Natural_Assert.Eq (T.Data_Product_T_Recv_Sync_History.Get_Count, 2); + Natural_Assert.Eq (T.Validation_Status_History.Get_Count, 2); + -- Assert data product contents: + Assert_Data_Product := T.Validation_Status_History.Get (2); + Validation_Status_Assert.Eq (Assert_Data_Product.Last_Validation_Status, Success); -- Check command response: Natural_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get_Count, 2); - Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (2), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Copy_Parameter_Table_Id, Status => Failure)); + Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (2), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Validate_Parameter_Table_Id, Status => Failure)); - -- Set task response 2 to something other than success: - Task_Response := Parameter_Enums.Parameter_Table_Update_Status.Crc_Error; - Task_Response2 := Parameter_Enums.Parameter_Table_Update_Status.Success; + -- Kill our helper task. + Task_Exit := True; + end Test_Validation_Timeout; - -- Send copy command: - T.Command_T_Send (T.Commands.Copy_Parameter_Table ((Copy_Type => Default_To_Working))); + -- This unit test tests the nominal update table command. + overriding procedure Test_Nominal_Copy (Self : in out Instance) is + T : Component.Parameter_Manager.Implementation.Tester.Instance_Access renames Self.Tester; + Task_Exit : aliased Boolean := False; + Sim_Task : Simulator_Task (Self'Unchecked_Access, Task_Exit'Unchecked_Access); + Table : aliased constant Basic_Types.Byte_Array := [0 .. 246 => 10]; + Packed_Table : constant Packed_Parameter_Table.T := ( + Header => ( + Table_Buffer_Length => Table'Length, + Crc_Table => [0 .. 1 => 0], + Version => 0.0 + ), + Table_Buffer => Table + ); + Cmd : Command.T; + Assert_Header : Parameter_Manager_Table_Header.T; + Assert_Region_Length : constant Integer := Packed_Table.Header.Table_Buffer_Length + Parameter_Manager_Table_Header.Crc_Table_Size_In_Bytes + Parameter_Manager_Table_Header.Version_Size_In_Bytes; + Assert_Region : Parameters_Memory_Region.T; + begin + -- Send update table command: + Ser_Status_Assert.Eq (T.Commands.Update_Parameter_Table (Packed_Table, Cmd), Success); + T.Command_T_Send (Cmd); -- Execute the command and tell the task to respond. Task_Send_Response_Twice := True; Natural_Assert.Eq (T.Dispatch_All, 1); - -- Copy from working should have occurred now. Check data: - Natural_Assert.Eq (T.Default_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 2); - Parameters_Memory_Region_Assert.Eq ( - T.Default_Parameters_Memory_Region_Recv_Sync_History.Get (2), - (Region => T.Get_Parameter_Bytes_Region, Operation => Get) - ); - -- Copy to default: - Natural_Assert.Eq (T.Working_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 3); - Parameters_Memory_Region_Assert.Eq ( - T.Working_Parameters_Memory_Region_Recv_Sync_History.Get (3), - (Region => T.Get_Parameter_Bytes_Region, Operation => Set) + -- Table update should have occurred now. + -- Assert working parameters connector: + Natural_Assert.Eq (T.Working_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 1); + -- Assert connector table region length: + Assert_Region := T.Working_Parameters_Memory_Region_Recv_Sync_History.Get (1); + Natural_Assert.Eq (Assert_Region.Region.Length, Assert_Region_Length); + -- Assert working connector address is not null: + Address_Assert.Neq (Assert_Region.Region.Address, System.Null_Address); + -- Assert primary parameters connector: + Natural_Assert.Eq (T.Primary_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 1); + -- Assert connector table region length: + Assert_Region := T.Primary_Parameters_Memory_Region_Recv_Sync_History.Get (1); + Natural_Assert.Eq (Assert_Region.Region.Length, Assert_Region_Length); + -- Assert primary connector address is not null: + Address_Assert.Neq (Assert_Region.Region.Address, System.Null_Address); + + -- Assert events: + Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 2); + -- Assert start copy header: + Natural_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get_Count, 1); + Assert_Header := T.Starting_Parameter_Table_Copy_History.Get (1); + -- Assert start copy header address is not null: + Address_Assert.Neq (Assert_Header.Crc_Table'Address, System.Null_Address); + -- Assert start copy header length: + Natural_Assert.Eq (Assert_Header.Table_Buffer_Length, Packed_Table.Header.Table_Buffer_Length); + -- Assert no failure events: + Natural_Assert.Eq (T.Working_Table_Update_Failure_History.Get_Count, 0); + Natural_Assert.Eq (T.Primary_Table_Update_Failure_History.Get_Count, 0); + -- Assert finished copy header: + Natural_Assert.Eq (T.Finished_Parameter_Table_Copy_History.Get_Count, 1); + Assert_Header := T.Finished_Parameter_Table_Copy_History.Get (1); + -- Assert finished copy header address is not null: + Address_Assert.Neq (Assert_Header.Crc_Table'Address, System.Null_Address); + -- Assert finished copy header length: + Natural_Assert.Eq (Assert_Header.Table_Buffer_Length, Packed_Table.Header.Table_Buffer_Length); + + -- Check command response: + Natural_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get_Count, 1); + Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (1), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Update_Parameter_Table_Id, Status => Success)); + + -- Kill our helper task. + Task_Exit := True; + end Test_Nominal_Copy; + + -- This unit test tests the component's response to a failed parameter table copy. + overriding procedure Test_Copy_Failure (Self : in out Instance) is + T : Component.Parameter_Manager.Implementation.Tester.Instance_Access renames Self.Tester; + Task_Exit : aliased Boolean := False; + Sim_Task : Simulator_Task (Self'Unchecked_Access, Task_Exit'Unchecked_Access); + Table : aliased constant Basic_Types.Byte_Array := [0 .. 246 => 10]; + Packed_Table : constant Packed_Parameter_Table.T := ( + Header => ( + Table_Buffer_Length => Table'Length, + Crc_Table => [0 .. 1 => 0], + Version => 0.0 + ), + Table_Buffer => Table ); + Cmd : Command.T; + Assert_Validation_Header : Packed_Validation_Header.T; + Assert_Header : Parameter_Manager_Table_Header.T; + Assert_Region_Length : constant Integer := Packed_Table.Header.Table_Buffer_Length + Parameter_Manager_Table_Header.Crc_Table_Size_In_Bytes + Parameter_Manager_Table_Header.Version_Size_In_Bytes; + Assert_Region : Parameters_Memory_Region.T; + begin + -- Set task response to something other than success: + Task_Response := Parameter_Enums.Parameter_Table_Update_Status.Parameter_Error; - -- Check events: - Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 6); - Natural_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get_Count, 3); - Packed_Parameter_Table_Copy_Type_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get (3), (Copy_Type => Default_To_Working)); + -- Send update table command: + Ser_Status_Assert.Eq (T.Commands.Update_Parameter_Table (Packed_Table, Cmd), Success); + T.Command_T_Send (Cmd); + + -- Execute the command and tell the task to respond. + Task_Send_Response := True; + Natural_Assert.Eq (T.Dispatch_All, 1); + + -- Working table update should have been attempted now. + -- Assert working parameters connector: + Natural_Assert.Eq (T.Working_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 1); + -- Assert connector table region length: + Assert_Region := T.Working_Parameters_Memory_Region_Recv_Sync_History.Get (1); + Natural_Assert.Eq (Assert_Region.Region.Length, Assert_Region_Length); + -- Assert working connector address is not null: + Address_Assert.Neq (Assert_Region.Region.Address, System.Null_Address); + -- Assert no primary primary connector after working parameter update failure: + Natural_Assert.Eq (T.Primary_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 0); + + -- Assert events: + Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 3); + -- Assert start copy header: + Natural_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get_Count, 1); + Assert_Header := T.Starting_Parameter_Table_Copy_History.Get (1); + -- Assert start copy header address is not null: + Address_Assert.Neq (Assert_Header.Crc_Table'Address, System.Null_Address); + -- Assert start copy header length: + Natural_Assert.Eq (Assert_Header.Table_Buffer_Length, Packed_Table.Header.Table_Buffer_Length); + -- Assert expected failure events: + Natural_Assert.Eq (T.Parameter_Table_Copy_Failure_History.Get_Count, 1); + Natural_Assert.Eq (T.Working_Table_Update_Failure_History.Get_Count, 1); + Natural_Assert.Eq (T.Primary_Table_Update_Failure_History.Get_Count, 0); Natural_Assert.Eq (T.Finished_Parameter_Table_Copy_History.Get_Count, 0); - Natural_Assert.Eq (T.Parameter_Table_Copy_Failure_History.Get_Count, 3); - Parameters_Memory_Region_Release_Assert.Eq (T.Parameter_Table_Copy_Failure_History.Get (3), ( - Region => (Address => Sim_Bytes'Address, Length => Sim_Bytes'Length), - Status => Parameter_Enums.Parameter_Table_Update_Status.Crc_Error - )); + Assert_Validation_Header := T.Working_Table_Update_Failure_History.Get (1); + -- Assert working copy failure header address is not null: + Address_Assert.Neq (Assert_Validation_Header.Last_Validation_Header.Crc_Table'Address, System.Null_Address); + -- Assert working copy failure header length: + Natural_Assert.Eq (Assert_Validation_Header.Last_Validation_Header.Table_Buffer_Length, Packed_Table.Header.Table_Buffer_Length); -- Check command response: - Natural_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get_Count, 3); - Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (3), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Copy_Parameter_Table_Id, Status => Failure)); + Natural_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get_Count, 1); + Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (1), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Update_Parameter_Table_Id, Status => Failure)); - -- Set task response 2 to something other than success: - Task_Response := Parameter_Enums.Parameter_Table_Update_Status.Length_Error; - Task_Response2 := Parameter_Enums.Parameter_Table_Update_Status.Success; + -- Set working table task response to something other than success: + Task_Response := Parameter_Enums.Parameter_Table_Update_Status.Parameter_Error; - -- Send copy command: - T.Command_T_Send (T.Commands.Copy_Parameter_Table ((Copy_Type => Default_To_Working))); + -- Send update table command: + Ser_Status_Assert.Eq (T.Commands.Update_Parameter_Table (Packed_Table, Cmd), Success); + T.Command_T_Send (Cmd); -- Execute the command and tell the task to respond. - Task_Send_Response := True; + Task_Send_Response_Twice := True; Natural_Assert.Eq (T.Dispatch_All, 1); - -- Copy from working should have occurred now. Check data: - Natural_Assert.Eq (T.Default_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 3); - Parameters_Memory_Region_Assert.Eq ( - T.Default_Parameters_Memory_Region_Recv_Sync_History.Get (3), - (Region => T.Get_Parameter_Bytes_Region, Operation => Get) - ); - -- Copy to default: - Natural_Assert.Eq (T.Working_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 3); - - -- Check events: - Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 8); - Natural_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get_Count, 4); - Packed_Parameter_Table_Copy_Type_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get (3), (Copy_Type => Default_To_Working)); + -- Primary table update should have been attempted now. + -- Assert working parameters connector: + Natural_Assert.Eq (T.Working_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 2); + -- Assert connector table region length: + Assert_Region := T.Working_Parameters_Memory_Region_Recv_Sync_History.Get (2); + Natural_Assert.Eq (Assert_Region.Region.Length, Assert_Region_Length); + -- Assert working connector address is not null: + Address_Assert.Neq (Assert_Region.Region.Address, System.Null_Address); + -- Assert primary parameters connector: + Natural_Assert.Eq (T.Primary_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 1); + -- Assert connector table region length: + Assert_Region := T.Primary_Parameters_Memory_Region_Recv_Sync_History.Get (1); + Natural_Assert.Eq (Assert_Region.Region.Length, Assert_Region_Length); + -- Assert primary connector address is not null: + Address_Assert.Neq (Assert_Region.Region.Address, System.Null_Address); + + -- Assert events: + Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 6); + -- Assert start copy header: + Natural_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get_Count, 2); + Assert_Header := T.Starting_Parameter_Table_Copy_History.Get (2); + -- Assert start copy header address is not null: + Address_Assert.Neq (Assert_Header.Crc_Table'Address, System.Null_Address); + -- Assert start copy header length: + Natural_Assert.Eq (Assert_Header.Table_Buffer_Length, Packed_Table.Header.Table_Buffer_Length); + -- Assert expected failure events: + Natural_Assert.Eq (T.Parameter_Table_Copy_Failure_History.Get_Count, 2); + Natural_Assert.Eq (T.Working_Table_Update_Failure_History.Get_Count, 1); + Natural_Assert.Eq (T.Primary_Table_Update_Failure_History.Get_Count, 1); Natural_Assert.Eq (T.Finished_Parameter_Table_Copy_History.Get_Count, 0); - Natural_Assert.Eq (T.Parameter_Table_Copy_Failure_History.Get_Count, 4); - Parameters_Memory_Region_Release_Assert.Eq (T.Parameter_Table_Copy_Failure_History.Get (4), ( - Region => (Address => Sim_Bytes'Address, Length => Sim_Bytes'Length), - Status => Parameter_Enums.Parameter_Table_Update_Status.Length_Error - )); + Assert_Validation_Header := T.Primary_Table_Update_Failure_History.Get (1); + -- Assert primary copy failure header address is not null: + Address_Assert.Neq (Assert_Validation_Header.Last_Validation_Header.Crc_Table'Address, System.Null_Address); + -- Assert primary copy failure header length: + Natural_Assert.Eq (Assert_Validation_Header.Last_Validation_Header.Table_Buffer_Length, Packed_Table.Header.Table_Buffer_Length); -- Check command response: - Natural_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get_Count, 4); - Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (4), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Copy_Parameter_Table_Id, Status => Failure)); + Natural_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get_Count, 2); + Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (2), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Update_Parameter_Table_Id, Status => Failure)); -- Kill our helper task. Task_Exit := True; end Test_Copy_Failure; + -- This unit test tests the component's response when the destination component + -- does not respond to a copy command before a timeout occurs. overriding procedure Test_Copy_Timeout (Self : in out Instance) is T : Component.Parameter_Manager.Implementation.Tester.Instance_Access renames Self.Tester; Task_Exit : aliased Boolean := False; Sim_Task : Simulator_Task (Self'Unchecked_Access, Task_Exit'Unchecked_Access); + Table : aliased constant Basic_Types.Byte_Array := [0 .. 246 => 10]; + Packed_Table : constant Packed_Parameter_Table.T := ( + Header => ( + Table_Buffer_Length => Table'Length, + Crc_Table => [0 .. 1 => 0], + Version => 0.0 + ), + Table_Buffer => Table + ); + Cmd : Command.T; + Assert_Validation_Header : Packed_Validation_Header.T; + Assert_Header : Parameter_Manager_Table_Header.T; + Assert_Region_Length : constant Integer := Packed_Table.Header.Table_Buffer_Length + Parameter_Manager_Table_Header.Crc_Table_Size_In_Bytes + Parameter_Manager_Table_Header.Version_Size_In_Bytes; + Assert_Region : Parameters_Memory_Region.T; begin - -- Send copy command: - T.Command_T_Send (T.Commands.Copy_Parameter_Table ((Copy_Type => Working_To_Default))); + -- Send update table command: + Ser_Status_Assert.Eq (T.Commands.Update_Parameter_Table (Packed_Table, Cmd), Success); + T.Command_T_Send (Cmd); -- Execute the command and tell the task to respond with timeout Task_Send_Timeout := True; Natural_Assert.Eq (T.Dispatch_All, 1); - -- Copy from working should have occurred now. Check data: + -- Table update should have been attempted now. + -- Assert working parameters connector: Natural_Assert.Eq (T.Working_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 1); - Parameters_Memory_Region_Assert.Eq ( - T.Working_Parameters_Memory_Region_Recv_Sync_History.Get (1), - (Region => T.Get_Parameter_Bytes_Region, Operation => Get) - ); - -- No copy to default: - Natural_Assert.Eq (T.Default_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 0); - - -- Check events: - Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 2); + -- Assert connector table region length: + Assert_Region := T.Working_Parameters_Memory_Region_Recv_Sync_History.Get (1); + Natural_Assert.Eq (Assert_Region.Region.Length, Assert_Region_Length); + -- Assert working connector address is not null: + Address_Assert.Neq (Assert_Region.Region.Address, System.Null_Address); + -- Assert no primary primary connector after working parameter update timeout: + Natural_Assert.Eq (T.Primary_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 0); + + -- Assert events: + Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 3); + -- Assert start copy header: Natural_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get_Count, 1); - Packed_Parameter_Table_Copy_Type_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get (1), (Copy_Type => Working_To_Default)); - Natural_Assert.Eq (T.Finished_Parameter_Table_Copy_History.Get_Count, 0); + Assert_Header := T.Starting_Parameter_Table_Copy_History.Get (1); + -- Assert start copy header address is not null: + Address_Assert.Neq (Assert_Header.Crc_Table'Address, System.Null_Address); + -- Assert start copy header length: + Natural_Assert.Eq (Assert_Header.Table_Buffer_Length, Packed_Table.Header.Table_Buffer_Length); + -- Assert expected failure events: Natural_Assert.Eq (T.Parameter_Table_Copy_Timeout_History.Get_Count, 1); - - -- Check command response: - Natural_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get_Count, 1); - Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (1), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Copy_Parameter_Table_Id, Status => Failure)); - - -- Send copy command: - T.Command_T_Send (T.Commands.Copy_Parameter_Table ((Copy_Type => Default_To_Working))); - - -- Execute the command and tell the task to respond with timeout - -- Wait a bit to make sure our simulator task is reset and ready to go - Sleep (50); - Task_Send_Timeout := True; - Natural_Assert.Eq (T.Dispatch_All, 1); - - -- Copy from working should have occurred now. Check data: - Natural_Assert.Eq (T.Working_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 1); - -- No copy to default: - Natural_Assert.Eq (T.Default_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 1); - Parameters_Memory_Region_Assert.Eq ( - T.Default_Parameters_Memory_Region_Recv_Sync_History.Get (1), - (Region => T.Get_Parameter_Bytes_Region, Operation => Get) - ); - - -- Check events: - Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 4); - Natural_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get_Count, 2); - Packed_Parameter_Table_Copy_Type_Assert.Eq (T.Starting_Parameter_Table_Copy_History.Get (2), (Copy_Type => Default_To_Working)); + Natural_Assert.Eq (T.Working_Table_Update_Failure_History.Get_Count, 1); + Natural_Assert.Eq (T.Primary_Table_Update_Failure_History.Get_Count, 0); Natural_Assert.Eq (T.Finished_Parameter_Table_Copy_History.Get_Count, 0); - Natural_Assert.Eq (T.Parameter_Table_Copy_Timeout_History.Get_Count, 2); + Assert_Validation_Header := T.Working_Table_Update_Failure_History.Get (1); + -- Assert working copy failure header address is not null: + Address_Assert.Neq (Assert_Validation_Header.Last_Validation_Header.Crc_Table'Address, System.Null_Address); + -- Assert working copy failure header length: + Natural_Assert.Eq (Assert_Validation_Header.Last_Validation_Header.Table_Buffer_Length, Packed_Table.Header.Table_Buffer_Length); -- Check command response: - Natural_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get_Count, 2); - Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (2), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Copy_Parameter_Table_Id, Status => Failure)); + Natural_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get_Count, 1); + Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (1), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Update_Parameter_Table_Id, Status => Failure)); -- Kill our helper task. Task_Exit := True; end Test_Copy_Timeout; + -- This unit test tests a command or memory region being dropped due to a full + -- queue. overriding procedure Test_Full_Queue (Self : in out Instance) is T : Component.Parameter_Manager.Implementation.Tester.Instance_Access renames Self.Tester; Cmd : Command.T; begin - -- Send 3 commands to fill up queue. + -- Send 10 commands to fill up queue. Cmd.Header.Arg_Buffer_Length := Cmd.Arg_Buffer'Length; - T.Command_T_Send (Cmd); - T.Command_T_Send (Cmd); - T.Command_T_Send (Cmd); + for Index in 0 .. 9 loop + T.Command_T_Send (Cmd); + end loop; + + -- Assert queue usage is at maximum: + Boolean_Assert.Eq (T.Component_Instance.Get_Queue_Current_Percent_Used = T.Component_Instance.Get_Queue_Maximum_Percent_Used, True); -- OK the next command should overflow the queue. T.Expect_Command_T_Send_Dropped := True; T.Command_T_Send (Cmd); + -- Assert nothing received over connectors: + Natural_Assert.Eq (T.Working_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 0); + Natural_Assert.Eq (T.Primary_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 0); + -- Make sure event thrown: Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 1); Natural_Assert.Eq (T.Command_Dropped_History.Get_Count, 1); Command_Header_Assert.Eq (T.Command_Dropped_History.Get (1), Cmd.Header); end Test_Full_Queue; + -- This unit test exercises that an invalid command throws the appropriate event. overriding procedure Test_Invalid_Command (Self : in out Instance) is T : Component.Parameter_Manager.Implementation.Tester.Instance_Access renames Self.Tester; - Cmd : Command.T := T.Commands.Copy_Parameter_Table ((Copy_Type => Working_To_Default)); + Task_Exit : aliased Boolean := False; + Sim_Task : Simulator_Task (Self'Unchecked_Access, Task_Exit'Unchecked_Access); + Table : aliased constant Basic_Types.Byte_Array := [0 .. 246 => 10]; + Packed_Table : constant Packed_Parameter_Table.T := ( + Header => ( + Table_Buffer_Length => Table'Length, + Crc_Table => [0 .. 1 => 0], + Version => 0.0 + ), + Table_Buffer => Table + ); + Cmd : Command.T; + Invalid_Table : Packed_Parameter_Table.T; begin - -- Make the command invalid by modifying its length. - Cmd.Header.Arg_Buffer_Length := 22; + -- Send update table command: + Ser_Status_Assert.Eq (T.Commands.Update_Parameter_Table (Packed_Table, Cmd), Success); + -- Make the command invalid by setting the packed table + -- header's table buffer length larger than the command + -- header argument buffer length: + Cmd.Arg_Buffer (1) := Table'Length + 1; + + -- Execute the command and tell the task to respond + Task_Send_Response_Twice := True; + T.Command_T_Send (Cmd); -- Send bad command and expect bad response: - T.Command_T_Send (Cmd); Natural_Assert.Eq (T.Dispatch_All, 1); Natural_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get_Count, 1); - Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (1), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Copy_Parameter_Table_Id, Status => Length_Error)); + Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (1), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Update_Parameter_Table_Id, Status => Length_Error)); + + -- Assert nothing sent over memory region connectors: + Natural_Assert.Eq (T.Working_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 0); + Natural_Assert.Eq (T.Primary_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 0); -- Make sure some events were thrown: Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 1); Natural_Assert.Eq (T.Invalid_Command_Received_History.Get_Count, 1); - Invalid_Command_Info_Assert.Eq (T.Invalid_Command_Received_History.Get (1), (Id => T.Commands.Get_Copy_Parameter_Table_Id, Errant_Field_Number => Interfaces.Unsigned_32'Last, Errant_Field => [0, 0, 0, 0, 0, 0, 0, 22])); + Invalid_Command_Info_Assert.Eq (T.Invalid_Command_Received_History.Get (1), (Id => T.Commands.Get_Update_Parameter_Table_Id, Errant_Field_Number => Interfaces.Unsigned_32'Last, Errant_Field => [0, 0, 0, 0, 0, 0, 0, 255])); + + -- Send update table command: + Ser_Status_Assert.Eq (T.Commands.Update_Parameter_Table (Packed_Table, Cmd), Success); + -- Make the command invalid by setting the command header + -- argument buffer length smaller than the packed table + -- header's table buffer length: + Cmd.Header.Arg_Buffer_Length := 1; + + -- Execute the command and tell the task to respond + Task_Send_Response_Twice := True; + T.Command_T_Send (Cmd); + + -- Send bad command and expect bad response: + Natural_Assert.Eq (T.Dispatch_All, 1); + Natural_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get_Count, 2); + Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (2), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Update_Parameter_Table_Id, Status => Length_Error)); + + -- Assert nothing sent over memory region connectors: + Natural_Assert.Eq (T.Working_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 0); + Natural_Assert.Eq (T.Primary_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 0); + + -- Make sure some events were thrown: + Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 2); + Natural_Assert.Eq (T.Invalid_Command_Received_History.Get_Count, 2); + Invalid_Command_Info_Assert.Eq (T.Invalid_Command_Received_History.Get (2), (Id => T.Commands.Get_Update_Parameter_Table_Id, Errant_Field_Number => Interfaces.Unsigned_32'Last, Errant_Field => [0, 0, 0, 0, 0, 0, 0, 1])); + + -- Send update table command: + -- Make the command invalid by setting the packed table + -- header's table buffer length out of range for the type: + Invalid_Table.Header.Table_Buffer_Length := Parameter_Manager_Types.Parameter_Manager_Buffer_Length_Type'Last; + Ser_Status_Assert.Eq (T.Commands.Update_Parameter_Table (Invalid_Table, Cmd), Success); + + -- Execute the command and tell the task to respond + Task_Send_Response_Twice := True; + T.Command_T_Send (Cmd); + + -- Send bad command and expect bad response: + Natural_Assert.Eq (T.Dispatch_All, 1); + Natural_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get_Count, 3); + Command_Response_Assert.Eq (T.Command_Response_T_Recv_Sync_History.Get (3), (Source_Id => 0, Registration_Id => 0, Command_Id => T.Commands.Get_Update_Parameter_Table_Id, Status => Validation_Error)); + + -- Assert nothing sent over memory region connectors: + Natural_Assert.Eq (T.Working_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 0); + Natural_Assert.Eq (T.Primary_Parameters_Memory_Region_Recv_Sync_History.Get_Count, 0); + + -- Make sure some events were thrown: + Natural_Assert.Eq (T.Event_T_Recv_Sync_History.Get_Count, 3); + Natural_Assert.Eq (T.Invalid_Command_Received_History.Get_Count, 3); + Invalid_Command_Info_Assert.Eq (T.Invalid_Command_Received_History.Get (3), (Id => T.Commands.Get_Update_Parameter_Table_Id, Errant_Field_Number => 3, Errant_Field => [0, 0, 0, 0, 247, 0, 0, 0])); end Test_Invalid_Command; end Parameter_Manager_Tests.Implementation; diff --git a/src/components/parameter_manager/test/parameter_manager_tests-implementation.ads b/src/components/parameter_manager/test/parameter_manager_tests-implementation.ads index e1b2607..527a41e 100644 --- a/src/components/parameter_manager/test/parameter_manager_tests-implementation.ads +++ b/src/components/parameter_manager/test/parameter_manager_tests-implementation.ads @@ -14,15 +14,22 @@ private overriding procedure Set_Up_Test (Self : in out Instance); overriding procedure Tear_Down_Test (Self : in out Instance); - -- This unit test tests the nominal copy command from default to working. - overriding procedure Test_Nominal_Copy_Default_To_Working (Self : in out Instance); - -- This unit test tests the nominal copy command from working to default. - overriding procedure Test_Nominal_Copy_Working_To_Default (Self : in out Instance); + -- This unit test tests the nominal validation command. + overriding procedure Test_Nominal_Validation (Self : in out Instance); + -- This unit test tests the component's response to a failed validation. + overriding procedure Test_Validation_Failure (Self : in out Instance); + -- This unit test tests the component's response when the destination component + -- does not respond to a validation command before a timeout occurs. + overriding procedure Test_Validation_Timeout (Self : in out Instance); + -- This unit test tests the nominal copy command. + overriding procedure Test_Nominal_Copy (Self : in out Instance); -- This unit test tests the component's response to a failed parameter table copy. overriding procedure Test_Copy_Failure (Self : in out Instance); - -- This unit test tests the component's response when the destination component does not respond to a copy command before a timeout occurs. + -- This unit test tests the component's response when the destination component + -- does not respond to a copy command before a timeout occurs. overriding procedure Test_Copy_Timeout (Self : in out Instance); - -- This unit test tests a command or memory region being dropped due to a full queue. + -- This unit test tests a command or memory region being dropped due to a full + -- queue. overriding procedure Test_Full_Queue (Self : in out Instance); -- This unit test exercises that an invalid command throws the appropriate event. overriding procedure Test_Invalid_Command (Self : in out Instance); diff --git a/src/components/parameter_manager/types/.all_path b/src/components/parameter_manager/types/.all_path deleted file mode 100644 index e69de29..0000000 diff --git a/src/components/parameter_manager/types/packed_parameter_table_copy_type.record.yaml b/src/components/parameter_manager/types/packed_parameter_table_copy_type.record.yaml deleted file mode 100644 index 3b89028..0000000 --- a/src/components/parameter_manager/types/packed_parameter_table_copy_type.record.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -description: Packed record which holds the Parameter Manager copy type. -fields: - - name: Copy_Type - description: This enumeration describes the source and destination of the Parameter Manager copy command. - type: Parameter_Manager_Enums.Parameter_Table_Copy_Type.E - format: E8 diff --git a/src/components/parameter_manager/types/parameter_manager_enums.enums.yaml b/src/components/parameter_manager/types/parameter_manager_enums.enums.yaml deleted file mode 100644 index f45bb82..0000000 --- a/src/components/parameter_manager/types/parameter_manager_enums.enums.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -description: These are enumerations defined for the Parameter Manager. -enums: - - name: Parameter_Table_Copy_Type - description: This enumeration describes the source and destination of the Parameter Manager copy command. - literals: - - name: Default_To_Working - value: 0 - description: Copy the parameter table from Default (NVRAM) to Working (RAM). - - name: Working_To_Default - value: 1 - description: Copy the parameter table from Working (RAM) to Default (NVRAM). From e6ff25d16a956ee5e71bac5183945965df8c664a Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Wed, 21 Aug 2024 19:12:27 -0600 Subject: [PATCH 02/20] Add COSMOS table validation test --- test/scripts/validate-param-sys.py | 72 ++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 test/scripts/validate-param-sys.py diff --git a/test/scripts/validate-param-sys.py b/test/scripts/validate-param-sys.py new file mode 100644 index 0000000..ffdd8e2 --- /dev/null +++ b/test/scripts/validate-param-sys.py @@ -0,0 +1,72 @@ +######################################################################## +# This script is designed to function with OpenC3 COSMOS's Script Runner +######################################################################## +from openc3.script import * + +# Clear counts and data products from prior tests: +cmd("Linux_Example Ccsds_Command_Depacketizer_Instance-Reset_Counts") +cmd("Linux_Example Command_Router_Instance-Reset_Data_Products") +wait(0.5) + +# Send Noop_Arg command expecting success: +cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 1") +# Get received Software_Status_Packet: +wait(0.5) +sw_Status = get_tlm_packet("Linux_Example Software_Status_Packet", type='FORMATTED') +# Check succesful command count is 2 and that the last success was Noop_Arg with last Value 1: +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == '2'") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == '3'") +print("Noop_Arg success OK") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == '1'") +print("Noop_Arg last Value OK") + +# Send Noop command expecting failure: +cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 868") +# Get received Software_Status_Packet: +wait(0.5) +sw_Status = get_tlm_packet("Linux_Example Software_Status_Packet", type='FORMATTED') +# Check last failed command count was 1 and that it was Noop_Arg with last Value 1: +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '1'") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '3'") +print("Noop_Arg failure OK") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == '868'") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") +print("Noop_Arg last Value failure OK") + +############################################################################# +# If this point was reached then begin testing parameter validation functions +############################################################################# + +# Send nominal Validate_Parameter_Table command expecting success: +cmd("Linux_Example Parameter_Manager_Instance-Validate_Parameter_Table with Header.Table_Buffer_Length 24, Header.Crc_Table 33845, Table_Buffer [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]") +# Get received Software_Status_Packet: +wait(0.5) +sw_Status = get_tlm_packet("Linux_Example Software_Status_Packet", type='FORMATTED') +# Check succesful command count is 3 and that it was Validate_Parameter_Table: +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == '3'") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == '5201'") +print("Validate_Parameter_Table success OK") + +# Send test Validate_Parameter_Table command with bad CRC expecting Table_Validation_Failure and Memory_Region_Crc_Invalid: +cmd("Linux_Example Parameter_Manager_Instance-Validate_Parameter_Table with Header.Table_Buffer_Length 24, Header.Crc_Table 0, Table_Buffer [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]") +# Get received Software_Status_Packet: +wait(0.5) +sw_Status = get_tlm_packet("Linux_Example Software_Status_Packet", type='FORMATTED') +# Check last failed command count was 2 and that the last success was Validate_Parameter_Table with Status FAILURE: +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '2'") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '5201'") +print("Validate_Parameter_Table failure OK") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") +print("Validate_Parameter_Table last Status FAILURE OK") + +# Send test Validate_Parameter_Table command with bad CRC and length expecting Memory_Region_Length_Mismatch: +cmd("Linux_Example Parameter_Manager_Instance-Validate_Parameter_Table with Header.Table_Buffer_Length 26, Header.Crc_Table 0, Table_Buffer []") +# Get received Software_Status_Packet: +wait(0.5) +sw_Status = get_tlm_packet("Linux_Example Software_Status_Packet", type='FORMATTED') +# Check last failed command count was 3 and that it was Validate_Parameter_Table with Status FAILURE: +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '3'") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '5201'") +print("Validate_Parameter_Table failure OK") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") +print("Validate_Parameter_Table last Status FAILURE OK") From b6fba06ef0184799a1a8ab16efc01c5cf97a831c Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Wed, 21 Aug 2024 18:40:49 -0600 Subject: [PATCH 03/20] Modify COSMOS table validation test to use a mock table --- test/scripts/validate-param-sys.py | 86 ++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 22 deletions(-) diff --git a/test/scripts/validate-param-sys.py b/test/scripts/validate-param-sys.py index ffdd8e2..3b7906e 100644 --- a/test/scripts/validate-param-sys.py +++ b/test/scripts/validate-param-sys.py @@ -2,17 +2,16 @@ # This script is designed to function with OpenC3 COSMOS's Script Runner ######################################################################## from openc3.script import * +import struct # Clear counts and data products from prior tests: cmd("Linux_Example Ccsds_Command_Depacketizer_Instance-Reset_Counts") cmd("Linux_Example Command_Router_Instance-Reset_Data_Products") -wait(0.5) +wait(1.0) # Send Noop_Arg command expecting success: cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 1") -# Get received Software_Status_Packet: -wait(0.5) -sw_Status = get_tlm_packet("Linux_Example Software_Status_Packet", type='FORMATTED') +wait(1.0) # Check succesful command count is 2 and that the last success was Noop_Arg with last Value 1: check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == '2'") check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == '3'") @@ -22,9 +21,7 @@ # Send Noop command expecting failure: cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 868") -# Get received Software_Status_Packet: -wait(0.5) -sw_Status = get_tlm_packet("Linux_Example Software_Status_Packet", type='FORMATTED') +wait(1.0) # Check last failed command count was 1 and that it was Noop_Arg with last Value 1: check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '1'") check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '3'") @@ -37,36 +34,81 @@ # If this point was reached then begin testing parameter validation functions ############################################################################# +# Build a parameter table using bytearrays: +#Osc_A_Freq +Test_Packed_Table = bytearray(struct.pack(">f", 0.30)) +#Osc_A_Amp +Test_Packed_Table += bytearray(struct.pack(">f", 5.00)) +#Osc_A_Off +Test_Packed_Table += bytearray(struct.pack(">f", 2.50)) +#Osc_B_Freq +Test_Packed_Table += bytearray(struct.pack(">f", 0.30)) +#Osc_B_Amp +Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) +#Osc_B_Off +Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) +#Version +Test_Packed_Table += bytearray(struct.pack(">f", 0.0)) +#Crc_Table +Test_Packed_Table += bytearray(struct.pack(">h", 0)) +#Buffer_Length +Test_Packed_Table += bytearray(struct.pack(">h", 55)) + # Send nominal Validate_Parameter_Table command expecting success: -cmd("Linux_Example Parameter_Manager_Instance-Validate_Parameter_Table with Header.Table_Buffer_Length 24, Header.Crc_Table 33845, Table_Buffer [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]") -# Get received Software_Status_Packet: -wait(0.5) -sw_Status = get_tlm_packet("Linux_Example Software_Status_Packet", type='FORMATTED') +cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { "Header.Table_Buffer_Length": 24, "Header.Crc_Table": 19692, "Table_Buffer": list(Test_Packed_Table) }) +wait(1.0) # Check succesful command count is 3 and that it was Validate_Parameter_Table: check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == '3'") check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == '5201'") print("Validate_Parameter_Table success OK") -# Send test Validate_Parameter_Table command with bad CRC expecting Table_Validation_Failure and Memory_Region_Crc_Invalid: -cmd("Linux_Example Parameter_Manager_Instance-Validate_Parameter_Table with Header.Table_Buffer_Length 24, Header.Crc_Table 0, Table_Buffer [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]") -# Get received Software_Status_Packet: -wait(0.5) -sw_Status = get_tlm_packet("Linux_Example Software_Status_Packet", type='FORMATTED') -# Check last failed command count was 2 and that the last success was Validate_Parameter_Table with Status FAILURE: +# Send test Validate_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Table_Validation_Failure, and Command_Execution_Failure: +cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { "Header.Table_Buffer_Length": 24, "Header.Crc_Table": 0, "Table_Buffer": list(Test_Packed_Table) }) +wait(1.0) +# Check last failed command count was 2 and that it was Validate_Parameter_Table with Status FAILURE: check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '2'") check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '5201'") print("Validate_Parameter_Table failure OK") check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") print("Validate_Parameter_Table last Status FAILURE OK") -# Send test Validate_Parameter_Table command with bad CRC and length expecting Memory_Region_Length_Mismatch: -cmd("Linux_Example Parameter_Manager_Instance-Validate_Parameter_Table with Header.Table_Buffer_Length 26, Header.Crc_Table 0, Table_Buffer []") -# Get received Software_Status_Packet: -wait(0.5) -sw_Status = get_tlm_packet("Linux_Example Software_Status_Packet", type='FORMATTED') +# Send test Validate_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Table_Validation_Failure, and Command_Execution_Failure: +cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { "Header.Table_Buffer_Length": 26, "Header.Crc_Table": 19692, "Table_Buffer": list(Test_Packed_Table) }) +wait(1.0) # Check last failed command count was 3 and that it was Validate_Parameter_Table with Status FAILURE: check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '3'") check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '5201'") print("Validate_Parameter_Table failure OK") check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") print("Validate_Parameter_Table last Status FAILURE OK") + +# Send test Validate_Parameter_Table command with nominal values, and Osc_A_Freq = 999.0 to trigger the user implemented Validate_Parameters function, +# expecting Parameter_Validation_Failed, Parameter_Table_Copy_Failure, Table_Validation_Failure, and Command_Execution_Failure +# Rebuild the parameter table using known invalid Osc_A_Freq value: +#Osc_A_Freq +Test_Packed_Table = bytearray(struct.pack(">f", 999.0)) +#Osc_A_Amp +Test_Packed_Table += bytearray(struct.pack(">f", 5.00)) +#Osc_A_Off +Test_Packed_Table += bytearray(struct.pack(">f", 2.50)) +#Osc_B_Freq +Test_Packed_Table += bytearray(struct.pack(">f", 0.30)) +#Osc_B_Amp +Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) +#Osc_B_Off +Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) +#Version +Test_Packed_Table += bytearray(struct.pack(">f", 0.0)) +#Crc_Table +Test_Packed_Table += bytearray(struct.pack(">h", 0)) +#Buffer_Length +Test_Packed_Table += bytearray(struct.pack(">h", 55)) + +cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { "Header.Table_Buffer_Length": 24, "Header.Crc_Table": 65043, "Table_Buffer": list(Test_Packed_Table) }) +wait(1.0) +# Check last failed command count was 3 and that it was Validate_Parameter_Table with Status FAILURE: +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '4'") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '5201'") +print("Validate_Parameter_Table failure OK") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") +print("Validate_Parameter_Table last Status FAILURE OK") From eea01f3ad1692bc7672309fc491cc640fba50f0d Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Wed, 21 Aug 2024 18:41:41 -0600 Subject: [PATCH 04/20] Include `Update_Parameter_Table` in COSMOS parameter system tests squash this --- test/scripts/update-param-sys.py | 97 ++++++++++++++++++++++++++++++ test/scripts/validate-param-sys.py | 74 ++++++++++++++--------- 2 files changed, 143 insertions(+), 28 deletions(-) create mode 100644 test/scripts/update-param-sys.py diff --git a/test/scripts/update-param-sys.py b/test/scripts/update-param-sys.py new file mode 100644 index 0000000..f399d40 --- /dev/null +++ b/test/scripts/update-param-sys.py @@ -0,0 +1,97 @@ +######################################################################## +# This script is designed to function with OpenC3 COSMOS's Script Runner +######################################################################## +from openc3.script import * +import struct + +# Clear counts and data products from prior tests: +cmd("Linux_Example Ccsds_Command_Depacketizer_Instance-Reset_Counts") +cmd("Linux_Example Command_Router_Instance-Reset_Data_Products") +wait(1.0) + +# Send Noop_Arg command expecting success: +cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 1") +wait(1.0) +# Check successful command count is 2 and that the last success was Noop_Arg with last Value 1: +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == '2'") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == '3'") +print("Noop_Arg success OK") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == '1'") +print("Noop_Arg last Value OK") + +# Send Noop command expecting failure: +cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 868") +wait(1.0) +# Check last failed command count was 1 and that it was Noop_Arg with last Value 1: +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '1'") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '3'") +print("Noop_Arg failure OK") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == '868'") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") +print("Noop_Arg last Value failure OK") + +######################################################################### +# If this point was reached then begin testing parameter update functions +######################################################################### + +# Build a parameter table using bytearrays: +# Osc_A_Freq +Test_Packed_Table = bytearray(struct.pack(">f", 0.30)) +# Osc_A_Amp +Test_Packed_Table += bytearray(struct.pack(">f", 5.00)) +# Osc_A_Off +Test_Packed_Table += bytearray(struct.pack(">f", 2.50)) +# Osc_B_Freq +Test_Packed_Table += bytearray(struct.pack(">f", 0.30)) +# Osc_B_Amp +Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) +# Osc_B_Off +Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) +# Version +Test_Packed_Table += bytearray(struct.pack(">f", 0.0)) +# Crc_Table +Test_Packed_Table += bytearray(struct.pack(">h", 0)) +# Buffer_Length +Test_Packed_Table += bytearray(struct.pack(">h", 55)) + +# Send nominal Update_Parameter_Table command expecting success: +cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { + "Header.Table_Buffer_Length": 24, + "Header.Crc_Table": 19692, + "Table_Buffer": list(Test_Packed_Table) + }) +wait(1.0) +# Check successful command count is 3 and that it was Update_Parameter_Table: +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == '3'") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == '5200'") +print("Update_Parameter_Table success OK") + +# Send test Update_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Parameter_Table_Copy_Failure, +# Working_Table_Update_Failure, and Command_Execution_Failure: +cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { + "Header.Table_Buffer_Length": 24, + "Header.Crc_Table": 0, + "Table_Buffer": list(Test_Packed_Table) + }) +wait(1.0) +# Check last failed command count was 2 and that it was Update_Parameter_Table with Status FAILURE: +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '2'") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '5200'") +print("Update_Parameter_Table failure OK") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") +print("Update_Parameter_Table last Status FAILURE OK") + +# Send test Update_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Parameter_Table_Copy_Failure, +# Working_Table_Update_Failure, and Command_Execution_Failure: +cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { + "Header.Table_Buffer_Length": 26, + "Header.Crc_Table": 19692, + "Table_Buffer": list(Test_Packed_Table) + }) +wait(1.0) +# Check last failed command count was 3 and that it was Update_Parameter_Table with Status FAILURE: +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '3'") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '5200'") +print("Update_Parameter_Table failure OK") +check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") +print("Update_Parameter_Table last Status FAILURE OK") diff --git a/test/scripts/validate-param-sys.py b/test/scripts/validate-param-sys.py index 3b7906e..9cffccb 100644 --- a/test/scripts/validate-param-sys.py +++ b/test/scripts/validate-param-sys.py @@ -12,7 +12,7 @@ # Send Noop_Arg command expecting success: cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 1") wait(1.0) -# Check succesful command count is 2 and that the last success was Noop_Arg with last Value 1: +# Check successful command count is 2 and that the last success was Noop_Arg with last Value 1: check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == '2'") check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == '3'") print("Noop_Arg success OK") @@ -35,35 +35,44 @@ ############################################################################# # Build a parameter table using bytearrays: -#Osc_A_Freq +# Osc_A_Freq Test_Packed_Table = bytearray(struct.pack(">f", 0.30)) -#Osc_A_Amp +# Osc_A_Amp Test_Packed_Table += bytearray(struct.pack(">f", 5.00)) -#Osc_A_Off +# Osc_A_Off Test_Packed_Table += bytearray(struct.pack(">f", 2.50)) -#Osc_B_Freq +# Osc_B_Freq Test_Packed_Table += bytearray(struct.pack(">f", 0.30)) -#Osc_B_Amp +# Osc_B_Amp Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) -#Osc_B_Off +# Osc_B_Off Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) -#Version +# Version Test_Packed_Table += bytearray(struct.pack(">f", 0.0)) -#Crc_Table +# Crc_Table Test_Packed_Table += bytearray(struct.pack(">h", 0)) -#Buffer_Length +# Buffer_Length Test_Packed_Table += bytearray(struct.pack(">h", 55)) # Send nominal Validate_Parameter_Table command expecting success: -cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { "Header.Table_Buffer_Length": 24, "Header.Crc_Table": 19692, "Table_Buffer": list(Test_Packed_Table) }) +cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { + "Header.Table_Buffer_Length": 24, + "Header.Crc_Table": 19692, + "Table_Buffer": list(Test_Packed_Table) + }) wait(1.0) -# Check succesful command count is 3 and that it was Validate_Parameter_Table: +# Check successful command count is 3 and that it was Validate_Parameter_Table: check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == '3'") check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == '5201'") print("Validate_Parameter_Table success OK") -# Send test Validate_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Table_Validation_Failure, and Command_Execution_Failure: -cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { "Header.Table_Buffer_Length": 24, "Header.Crc_Table": 0, "Table_Buffer": list(Test_Packed_Table) }) +# Send test Validate_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Table_Validation_Failure, and +# Command_Execution_Failure: +cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { + "Header.Table_Buffer_Length": 24, + "Header.Crc_Table": 0, + "Table_Buffer": list(Test_Packed_Table) + }) wait(1.0) # Check last failed command count was 2 and that it was Validate_Parameter_Table with Status FAILURE: check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '2'") @@ -72,8 +81,13 @@ check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") print("Validate_Parameter_Table last Status FAILURE OK") -# Send test Validate_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Table_Validation_Failure, and Command_Execution_Failure: -cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { "Header.Table_Buffer_Length": 26, "Header.Crc_Table": 19692, "Table_Buffer": list(Test_Packed_Table) }) +# Send test Validate_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Table_Validation_Failure, and +# Command_Execution_Failure: +cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { + "Header.Table_Buffer_Length": 26, + "Header.Crc_Table": 19692, + "Table_Buffer": list(Test_Packed_Table) + }) wait(1.0) # Check last failed command count was 3 and that it was Validate_Parameter_Table with Status FAILURE: check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '3'") @@ -82,29 +96,33 @@ check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") print("Validate_Parameter_Table last Status FAILURE OK") -# Send test Validate_Parameter_Table command with nominal values, and Osc_A_Freq = 999.0 to trigger the user implemented Validate_Parameters function, -# expecting Parameter_Validation_Failed, Parameter_Table_Copy_Failure, Table_Validation_Failure, and Command_Execution_Failure +# Send test Validate_Parameter_Table command with nominal values, and Osc_A_Freq = 999.0 to trigger the user implemented Validate_Parameters +# function, expecting Parameter_Validation_Failed, Parameter_Table_Copy_Failure, Table_Validation_Failure, and Command_Execution_Failure # Rebuild the parameter table using known invalid Osc_A_Freq value: -#Osc_A_Freq +# Osc_A_Freq Test_Packed_Table = bytearray(struct.pack(">f", 999.0)) -#Osc_A_Amp +# Osc_A_Amp Test_Packed_Table += bytearray(struct.pack(">f", 5.00)) -#Osc_A_Off +# Osc_A_Off Test_Packed_Table += bytearray(struct.pack(">f", 2.50)) -#Osc_B_Freq +# Osc_B_Freq Test_Packed_Table += bytearray(struct.pack(">f", 0.30)) -#Osc_B_Amp +# Osc_B_Amp Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) -#Osc_B_Off +# Osc_B_Off Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) -#Version +# Version Test_Packed_Table += bytearray(struct.pack(">f", 0.0)) -#Crc_Table +# Crc_Table Test_Packed_Table += bytearray(struct.pack(">h", 0)) -#Buffer_Length +# Buffer_Length Test_Packed_Table += bytearray(struct.pack(">h", 55)) -cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { "Header.Table_Buffer_Length": 24, "Header.Crc_Table": 65043, "Table_Buffer": list(Test_Packed_Table) }) +cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { + "Header.Table_Buffer_Length": 24, + "Header.Crc_Table": 65043, + "Table_Buffer": list(Test_Packed_Table) + }) wait(1.0) # Check last failed command count was 3 and that it was Validate_Parameter_Table with Status FAILURE: check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '4'") From 9b73651d0a7265a54769f16fb3f1d8bb6107d659 Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Mon, 26 Aug 2024 14:28:59 -0600 Subject: [PATCH 05/20] Switch testing from `check_formatted` to `wait_check` --- test/scripts/update-param-sys.py | 37 +++++++++++------------- test/scripts/validate-param-sys.py | 46 +++++++++++++----------------- 2 files changed, 36 insertions(+), 47 deletions(-) diff --git a/test/scripts/update-param-sys.py b/test/scripts/update-param-sys.py index f399d40..251f34d 100644 --- a/test/scripts/update-param-sys.py +++ b/test/scripts/update-param-sys.py @@ -5,29 +5,27 @@ import struct # Clear counts and data products from prior tests: +cmd("Linux_Example Fault_Correction_Instance-Reset_Data_Products") cmd("Linux_Example Ccsds_Command_Depacketizer_Instance-Reset_Counts") cmd("Linux_Example Command_Router_Instance-Reset_Data_Products") -wait(1.0) # Send Noop_Arg command expecting success: cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 1") -wait(1.0) # Check successful command count is 2 and that the last success was Noop_Arg with last Value 1: -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == '2'") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == '3'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 2", 3) +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 3", 3) print("Noop_Arg success OK") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == '1'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == 1", 3) print("Noop_Arg last Value OK") # Send Noop command expecting failure: cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 868") -wait(1.0) # Check last failed command count was 1 and that it was Noop_Arg with last Value 1: -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '1'") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '3'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 1", 3) +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 3", 3) print("Noop_Arg failure OK") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == '868'") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == 868", 3) +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) print("Noop_Arg last Value failure OK") ######################################################################### @@ -60,10 +58,9 @@ "Header.Crc_Table": 19692, "Table_Buffer": list(Test_Packed_Table) }) -wait(1.0) # Check successful command count is 3 and that it was Update_Parameter_Table: -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == '3'") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == '5200'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 3", 3) +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 5200", 3) print("Update_Parameter_Table success OK") # Send test Update_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Parameter_Table_Copy_Failure, @@ -73,12 +70,11 @@ "Header.Crc_Table": 0, "Table_Buffer": list(Test_Packed_Table) }) -wait(1.0) # Check last failed command count was 2 and that it was Update_Parameter_Table with Status FAILURE: -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '2'") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '5200'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 2", 3) +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5200", 3) print("Update_Parameter_Table failure OK") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) print("Update_Parameter_Table last Status FAILURE OK") # Send test Update_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Parameter_Table_Copy_Failure, @@ -88,10 +84,9 @@ "Header.Crc_Table": 19692, "Table_Buffer": list(Test_Packed_Table) }) -wait(1.0) # Check last failed command count was 3 and that it was Update_Parameter_Table with Status FAILURE: -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '3'") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '5200'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 3", 3) +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5200", 3) print("Update_Parameter_Table failure OK") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) print("Update_Parameter_Table last Status FAILURE OK") diff --git a/test/scripts/validate-param-sys.py b/test/scripts/validate-param-sys.py index 9cffccb..c3d1cd4 100644 --- a/test/scripts/validate-param-sys.py +++ b/test/scripts/validate-param-sys.py @@ -5,29 +5,27 @@ import struct # Clear counts and data products from prior tests: +cmd("Linux_Example Fault_Correction_Instance-Reset_Data_Products") cmd("Linux_Example Ccsds_Command_Depacketizer_Instance-Reset_Counts") cmd("Linux_Example Command_Router_Instance-Reset_Data_Products") -wait(1.0) # Send Noop_Arg command expecting success: cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 1") -wait(1.0) # Check successful command count is 2 and that the last success was Noop_Arg with last Value 1: -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == '2'") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == '3'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 2", 3) +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 3", 3) print("Noop_Arg success OK") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == '1'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == 1", 3) print("Noop_Arg last Value OK") # Send Noop command expecting failure: cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 868") -wait(1.0) # Check last failed command count was 1 and that it was Noop_Arg with last Value 1: -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '1'") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '3'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 1", 3) +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 3", 3) print("Noop_Arg failure OK") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == '868'") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == 868", 3) +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) print("Noop_Arg last Value failure OK") ############################################################################# @@ -60,10 +58,9 @@ "Header.Crc_Table": 19692, "Table_Buffer": list(Test_Packed_Table) }) -wait(1.0) # Check successful command count is 3 and that it was Validate_Parameter_Table: -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == '3'") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == '5201'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 3", 3) +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 5201", 3) print("Validate_Parameter_Table success OK") # Send test Validate_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Table_Validation_Failure, and @@ -73,12 +70,11 @@ "Header.Crc_Table": 0, "Table_Buffer": list(Test_Packed_Table) }) -wait(1.0) # Check last failed command count was 2 and that it was Validate_Parameter_Table with Status FAILURE: -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '2'") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '5201'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 2", 3) +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) print("Validate_Parameter_Table failure OK") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) print("Validate_Parameter_Table last Status FAILURE OK") # Send test Validate_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Table_Validation_Failure, and @@ -88,12 +84,11 @@ "Header.Crc_Table": 19692, "Table_Buffer": list(Test_Packed_Table) }) -wait(1.0) # Check last failed command count was 3 and that it was Validate_Parameter_Table with Status FAILURE: -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '3'") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '5201'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 3", 3) +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) print("Validate_Parameter_Table failure OK") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) print("Validate_Parameter_Table last Status FAILURE OK") # Send test Validate_Parameter_Table command with nominal values, and Osc_A_Freq = 999.0 to trigger the user implemented Validate_Parameters @@ -123,10 +118,9 @@ "Header.Crc_Table": 65043, "Table_Buffer": list(Test_Packed_Table) }) -wait(1.0) -# Check last failed command count was 3 and that it was Validate_Parameter_Table with Status FAILURE: -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == '4'") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == '5201'") +# Check last failed command count was 4 and that it was Validate_Parameter_Table with Status FAILURE: +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 4", 3) +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) print("Validate_Parameter_Table failure OK") -check_formatted("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") +wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) print("Validate_Parameter_Table last Status FAILURE OK") From 2b86ad426e8c0c7903519452764c5bdb6c5bc497 Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Fri, 30 Aug 2024 18:00:53 -0600 Subject: [PATCH 06/20] Import CRC function, calculate length --- test/scripts/crc_16.py | 74 +++++++++++ test/scripts/test_setup.py | 28 ++++ test/scripts/update-param-sys.py | 140 ++++++++------------ test/scripts/validate-param-sys.py | 204 +++++++++++++---------------- 4 files changed, 248 insertions(+), 198 deletions(-) create mode 100644 test/scripts/crc_16.py create mode 100644 test/scripts/test_setup.py diff --git a/test/scripts/crc_16.py b/test/scripts/crc_16.py new file mode 100644 index 0000000..9a04b73 --- /dev/null +++ b/test/scripts/crc_16.py @@ -0,0 +1,74 @@ +_low_crc = [ + 0x00, 0x21, 0x42, 0x63, 0x84, 0xa5, 0xc6, 0xe7, 0x08, 0x29, 0x4a, 0x6b, 0x8c, + 0xad, 0xce, 0xef, 0x31, 0x10, 0x73, 0x52, 0xb5, 0x94, 0xf7, 0xd6, 0x39, 0x18, + 0x7b, 0x5a, 0xbd, 0x9c, 0xff, 0xde, 0x62, 0x43, 0x20, 0x01, 0xe6, 0xc7, 0xa4, + 0x85, 0x6a, 0x4b, 0x28, 0x09, 0xee, 0xcf, 0xac, 0x8d, 0x53, 0x72, 0x11, 0x30, + 0xd7, 0xf6, 0x95, 0xb4, 0x5b, 0x7a, 0x19, 0x38, 0xdf, 0xfe, 0x9d, 0xbc, 0xc4, + 0xe5, 0x86, 0xa7, 0x40, 0x61, 0x02, 0x23, 0xcc, 0xed, 0x8e, 0xaf, 0x48, 0x69, + 0x0a, 0x2b, 0xf5, 0xd4, 0xb7, 0x96, 0x71, 0x50, 0x33, 0x12, 0xfd, 0xdc, 0xbf, + 0x9e, 0x79, 0x58, 0x3b, 0x1a, 0xa6, 0x87, 0xe4, 0xc5, 0x22, 0x03, 0x60, 0x41, + 0xae, 0x8f, 0xec, 0xcd, 0x2a, 0x0b, 0x68, 0x49, 0x97, 0xb6, 0xd5, 0xf4, 0x13, + 0x32, 0x51, 0x70, 0x9f, 0xbe, 0xdd, 0xfc, 0x1b, 0x3a, 0x59, 0x78, 0x88, 0xa9, + 0xca, 0xeb, 0x0c, 0x2d, 0x4e, 0x6f, 0x80, 0xa1, 0xc2, 0xe3, 0x04, 0x25, 0x46, + 0x67, 0xb9, 0x98, 0xfb, 0xda, 0x3d, 0x1c, 0x7f, 0x5e, 0xb1, 0x90, 0xf3, 0xd2, + 0x35, 0x14, 0x77, 0x56, 0xea, 0xcb, 0xa8, 0x89, 0x6e, 0x4f, 0x2c, 0x0d, 0xe2, + 0xc3, 0xa0, 0x81, 0x66, 0x47, 0x24, 0x05, 0xdb, 0xfa, 0x99, 0xb8, 0x5f, 0x7e, + 0x1d, 0x3c, 0xd3, 0xf2, 0x91, 0xb0, 0x57, 0x76, 0x15, 0x34, 0x4c, 0x6d, 0x0e, + 0x2f, 0xc8, 0xe9, 0x8a, 0xab, 0x44, 0x65, 0x06, 0x27, 0xc0, 0xe1, 0x82, 0xa3, + 0x7d, 0x5c, 0x3f, 0x1e, 0xf9, 0xd8, 0xbb, 0x9a, 0x75, 0x54, 0x37, 0x16, 0xf1, + 0xd0, 0xb3, 0x92, 0x2e, 0x0f, 0x6c, 0x4d, 0xaa, 0x8b, 0xe8, 0xc9, 0x26, 0x07, + 0x64, 0x45, 0xa2, 0x83, 0xe0, 0xc1, 0x1f, 0x3e, 0x5d, 0x7c, 0x9b, 0xba, 0xd9, + 0xf8, 0x17, 0x36, 0x55, 0x74, 0x93, 0xb2, 0xd1, 0xf0 +] + +_high_crc = [ + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x81, 0x91, 0xa1, 0xb1, 0xc1, + 0xd1, 0xe1, 0xf1, 0x12, 0x02, 0x32, 0x22, 0x52, 0x42, 0x72, 0x62, 0x93, 0x83, + 0xb3, 0xa3, 0xd3, 0xc3, 0xf3, 0xe3, 0x24, 0x34, 0x04, 0x14, 0x64, 0x74, 0x44, + 0x54, 0xa5, 0xb5, 0x85, 0x95, 0xe5, 0xf5, 0xc5, 0xd5, 0x36, 0x26, 0x16, 0x06, + 0x76, 0x66, 0x56, 0x46, 0xb7, 0xa7, 0x97, 0x87, 0xf7, 0xe7, 0xd7, 0xc7, 0x48, + 0x58, 0x68, 0x78, 0x08, 0x18, 0x28, 0x38, 0xc9, 0xd9, 0xe9, 0xf9, 0x89, 0x99, + 0xa9, 0xb9, 0x5a, 0x4a, 0x7a, 0x6a, 0x1a, 0x0a, 0x3a, 0x2a, 0xdb, 0xcb, 0xfb, + 0xeb, 0x9b, 0x8b, 0xbb, 0xab, 0x6c, 0x7c, 0x4c, 0x5c, 0x2c, 0x3c, 0x0c, 0x1c, + 0xed, 0xfd, 0xcd, 0xdd, 0xad, 0xbd, 0x8d, 0x9d, 0x7e, 0x6e, 0x5e, 0x4e, 0x3e, + 0x2e, 0x1e, 0x0e, 0xff, 0xef, 0xdf, 0xcf, 0xbf, 0xaf, 0x9f, 0x8f, 0x91, 0x81, + 0xb1, 0xa1, 0xd1, 0xc1, 0xf1, 0xe1, 0x10, 0x00, 0x30, 0x20, 0x50, 0x40, 0x70, + 0x60, 0x83, 0x93, 0xa3, 0xb3, 0xc3, 0xd3, 0xe3, 0xf3, 0x02, 0x12, 0x22, 0x32, + 0x42, 0x52, 0x62, 0x72, 0xb5, 0xa5, 0x95, 0x85, 0xf5, 0xe5, 0xd5, 0xc5, 0x34, + 0x24, 0x14, 0x04, 0x74, 0x64, 0x54, 0x44, 0xa7, 0xb7, 0x87, 0x97, 0xe7, 0xf7, + 0xc7, 0xd7, 0x26, 0x36, 0x06, 0x16, 0x66, 0x76, 0x46, 0x56, 0xd9, 0xc9, 0xf9, + 0xe9, 0x99, 0x89, 0xb9, 0xa9, 0x58, 0x48, 0x78, 0x68, 0x18, 0x08, 0x38, 0x28, + 0xcb, 0xdb, 0xeb, 0xfb, 0x8b, 0x9b, 0xab, 0xbb, 0x4a, 0x5a, 0x6a, 0x7a, 0x0a, + 0x1a, 0x2a, 0x3a, 0xfd, 0xed, 0xdd, 0xcd, 0xbd, 0xad, 0x9d, 0x8d, 0x7c, 0x6c, + 0x5c, 0x4c, 0x3c, 0x2c, 0x1c, 0x0c, 0xef, 0xff, 0xcf, 0xdf, 0xaf, 0xbf, 0x8f, + 0x9f, 0x6e, 0x7e, 0x4e, 0x5e, 0x2e, 0x3e, 0x0e, 0x1e +] + + +def crc_16(byte_array, seed=[0xFF, 0xFF]): + """ + + 16-bit CRC: + Uses CCITT CRC polynomial: X^16 + X^12 + X^5 + 1. + The accepted start value is 0xffff. + + """ + high_parity = seed[0] + low_parity = seed[1] + for byte in list(byte_array): + k = byte ^ high_parity + high_parity = low_parity ^ _high_crc[k] + low_parity = _low_crc[k] + return [high_parity, low_parity] + + +def checksum_16(byte_array, seed=[0x00, 0x00]): + """Simple 16-bit checksum.""" + assert ( + len(byte_array) % 2 == 0 + ), "Checksum 16 only works on even numbered byte arrays" + csum = seed[0] * 0x100 + seed[1] + for i in range(0, len(byte_array), 2): + csum += byte_array[i] * 0x100 + byte_array[i + 1] + csum %= 0x10000 + return [int(csum / 0x100), csum % 0x100] diff --git a/test/scripts/test_setup.py b/test/scripts/test_setup.py new file mode 100644 index 0000000..0b3a5f1 --- /dev/null +++ b/test/scripts/test_setup.py @@ -0,0 +1,28 @@ +from openc3.script import * + +def test_setup(): + # Clear counts and data products from prior tests: + cmd("Linux_Example Fault_Correction_Instance-Reset_Data_Products") + cmd("Linux_Example Ccsds_Command_Depacketizer_Instance-Reset_Counts") + cmd("Linux_Example Command_Router_Instance-Reset_Data_Products") + + # Send Noop_Arg command expecting success: + cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 1") + # Check successful command count is 2 and that the last success was Noop_Arg with last Value 1: + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 2", 3) + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 3", 3) + print("Noop_Arg success OK") + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == 1", 3) + print("Noop_Arg last Value OK") + + # Send Noop command expecting failure: + cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 868") + # Check last failed command count was 1 and that it was Noop_Arg with last Value 1: + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 1", 3) + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 3", 3) + print("Noop_Arg failure OK") + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == 868", 3) + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) + print("Noop_Arg last Value failure OK") + + return True diff --git a/test/scripts/update-param-sys.py b/test/scripts/update-param-sys.py index 251f34d..7f1b3c6 100644 --- a/test/scripts/update-param-sys.py +++ b/test/scripts/update-param-sys.py @@ -1,92 +1,66 @@ ######################################################################## # This script is designed to function with OpenC3 COSMOS's Script Runner ######################################################################## -from openc3.script import * -import struct +import struct, sys +sys.path.append('/plugins/DEFAULT/targets_modified') +import crc_16 +import test_setup -# Clear counts and data products from prior tests: -cmd("Linux_Example Fault_Correction_Instance-Reset_Data_Products") -cmd("Linux_Example Ccsds_Command_Depacketizer_Instance-Reset_Counts") -cmd("Linux_Example Command_Router_Instance-Reset_Data_Products") +if test_setup.test_setup(): -# Send Noop_Arg command expecting success: -cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 1") -# Check successful command count is 2 and that the last success was Noop_Arg with last Value 1: -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 2", 3) -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 3", 3) -print("Noop_Arg success OK") -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == 1", 3) -print("Noop_Arg last Value OK") + ######################################################################### + # If this point was reached then begin testing parameter update functions + ######################################################################### -# Send Noop command expecting failure: -cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 868") -# Check last failed command count was 1 and that it was Noop_Arg with last Value 1: -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 1", 3) -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 3", 3) -print("Noop_Arg failure OK") -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == 868", 3) -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) -print("Noop_Arg last Value failure OK") + # Build a parameter table using bytearrays: + # Osc_A_Freq + Test_Packed_Table = bytearray(struct.pack(">f", 0.30)) + # Osc_A_Amp + Test_Packed_Table += bytearray(struct.pack(">f", 5.00)) + # Osc_A_Off + Test_Packed_Table += bytearray(struct.pack(">f", 2.50)) + # Osc_B_Freq + Test_Packed_Table += bytearray(struct.pack(">f", 0.30)) + # Osc_B_Amp + Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) + # Osc_B_Off + Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) -######################################################################### -# If this point was reached then begin testing parameter update functions -######################################################################### + # Send nominal Update_Parameter_Table command expecting success: + cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { + "Header.Table_Buffer_Length": len(Test_Packed_Table), + "Header.Crc_Table": 19692, + "Table_Buffer": list(Test_Packed_Table) + }) + # Check successful command count is 3 and that it was Update_Parameter_Table: + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 3", 3) + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 5200", 3) + print("Update_Parameter_Table success OK") -# Build a parameter table using bytearrays: -# Osc_A_Freq -Test_Packed_Table = bytearray(struct.pack(">f", 0.30)) -# Osc_A_Amp -Test_Packed_Table += bytearray(struct.pack(">f", 5.00)) -# Osc_A_Off -Test_Packed_Table += bytearray(struct.pack(">f", 2.50)) -# Osc_B_Freq -Test_Packed_Table += bytearray(struct.pack(">f", 0.30)) -# Osc_B_Amp -Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) -# Osc_B_Off -Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) -# Version -Test_Packed_Table += bytearray(struct.pack(">f", 0.0)) -# Crc_Table -Test_Packed_Table += bytearray(struct.pack(">h", 0)) -# Buffer_Length -Test_Packed_Table += bytearray(struct.pack(">h", 55)) + # Send test Update_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Parameter_Table_Copy_Failure, + # Working_Table_Update_Failure, and Command_Execution_Failure: + cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { + "Header.Table_Buffer_Length": len(Test_Packed_Table), + "Header.Crc_Table": 0, + "Table_Buffer": list(Test_Packed_Table) + }) + # Check last failed command count was 2 and that it was Update_Parameter_Table with Status FAILURE: + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 2", 3) + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5200", 3) + print("Update_Parameter_Table failure OK") + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) + print("Update_Parameter_Table last Status FAILURE OK") -# Send nominal Update_Parameter_Table command expecting success: -cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { - "Header.Table_Buffer_Length": 24, - "Header.Crc_Table": 19692, - "Table_Buffer": list(Test_Packed_Table) - }) -# Check successful command count is 3 and that it was Update_Parameter_Table: -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 3", 3) -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 5200", 3) -print("Update_Parameter_Table success OK") - -# Send test Update_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Parameter_Table_Copy_Failure, -# Working_Table_Update_Failure, and Command_Execution_Failure: -cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { - "Header.Table_Buffer_Length": 24, - "Header.Crc_Table": 0, - "Table_Buffer": list(Test_Packed_Table) - }) -# Check last failed command count was 2 and that it was Update_Parameter_Table with Status FAILURE: -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 2", 3) -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5200", 3) -print("Update_Parameter_Table failure OK") -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) -print("Update_Parameter_Table last Status FAILURE OK") - -# Send test Update_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Parameter_Table_Copy_Failure, -# Working_Table_Update_Failure, and Command_Execution_Failure: -cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { - "Header.Table_Buffer_Length": 26, - "Header.Crc_Table": 19692, - "Table_Buffer": list(Test_Packed_Table) - }) -# Check last failed command count was 3 and that it was Update_Parameter_Table with Status FAILURE: -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 3", 3) -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5200", 3) -print("Update_Parameter_Table failure OK") -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) -print("Update_Parameter_Table last Status FAILURE OK") + # Send test Update_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Parameter_Table_Copy_Failure, + # Working_Table_Update_Failure, and Command_Execution_Failure: + cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { + "Header.Table_Buffer_Length": len(Test_Packed_Table) + 1, + "Header.Crc_Table": 19692, + "Table_Buffer": list(Test_Packed_Table) + }) + # Check last failed command count was 3 and that it was Update_Parameter_Table with Status FAILURE: + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 3", 3) + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5200", 3) + print("Update_Parameter_Table failure OK") + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) + print("Update_Parameter_Table last Status FAILURE OK") diff --git a/test/scripts/validate-param-sys.py b/test/scripts/validate-param-sys.py index c3d1cd4..847e790 100644 --- a/test/scripts/validate-param-sys.py +++ b/test/scripts/validate-param-sys.py @@ -1,126 +1,100 @@ ######################################################################## # This script is designed to function with OpenC3 COSMOS's Script Runner ######################################################################## -from openc3.script import * -import struct +import struct, sys +sys.path.append('/plugins/DEFAULT/targets_modified') +import crc_16 +import test_setup -# Clear counts and data products from prior tests: -cmd("Linux_Example Fault_Correction_Instance-Reset_Data_Products") -cmd("Linux_Example Ccsds_Command_Depacketizer_Instance-Reset_Counts") -cmd("Linux_Example Command_Router_Instance-Reset_Data_Products") +if test_setup.test_setup(): -# Send Noop_Arg command expecting success: -cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 1") -# Check successful command count is 2 and that the last success was Noop_Arg with last Value 1: -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 2", 3) -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 3", 3) -print("Noop_Arg success OK") -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == 1", 3) -print("Noop_Arg last Value OK") + ############################################################################# + # If this point was reached then begin testing parameter validation functions + ############################################################################# -# Send Noop command expecting failure: -cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 868") -# Check last failed command count was 1 and that it was Noop_Arg with last Value 1: -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 1", 3) -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 3", 3) -print("Noop_Arg failure OK") -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == 868", 3) -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) -print("Noop_Arg last Value failure OK") + # Build a parameter table using bytearrays: + # Osc_A_Freq + Test_Packed_Table = bytearray(struct.pack(">f", 0.30)) + # Osc_A_Amp + Test_Packed_Table += bytearray(struct.pack(">f", 5.00)) + # Osc_A_Off + Test_Packed_Table += bytearray(struct.pack(">f", 2.50)) + # Osc_B_Freq + Test_Packed_Table += bytearray(struct.pack(">f", 0.30)) + # Osc_B_Amp + Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) + # Osc_B_Off + Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) -############################################################################# -# If this point was reached then begin testing parameter validation functions -############################################################################# + # Send nominal Validate_Parameter_Table command expecting success: + cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { + "Header.Table_Buffer_Length": len(Test_Packed_Table), + "Header.Crc_Table": 19692, + "Table_Buffer": list(Test_Packed_Table) + }) + # Check successful command count is 3 and that it was Validate_Parameter_Table: + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 3", 3) + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 5201", 3) + print("Validate_Parameter_Table success OK") -# Build a parameter table using bytearrays: -# Osc_A_Freq -Test_Packed_Table = bytearray(struct.pack(">f", 0.30)) -# Osc_A_Amp -Test_Packed_Table += bytearray(struct.pack(">f", 5.00)) -# Osc_A_Off -Test_Packed_Table += bytearray(struct.pack(">f", 2.50)) -# Osc_B_Freq -Test_Packed_Table += bytearray(struct.pack(">f", 0.30)) -# Osc_B_Amp -Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) -# Osc_B_Off -Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) -# Version -Test_Packed_Table += bytearray(struct.pack(">f", 0.0)) -# Crc_Table -Test_Packed_Table += bytearray(struct.pack(">h", 0)) -# Buffer_Length -Test_Packed_Table += bytearray(struct.pack(">h", 55)) + # Send test Validate_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Table_Validation_Failure, and + # Command_Execution_Failure: + cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { + "Header.Table_Buffer_Length": len(Test_Packed_Table), + "Header.Crc_Table": 0, + "Table_Buffer": list(Test_Packed_Table) + }) + # Check last failed command count was 2 and that it was Validate_Parameter_Table with Status FAILURE: + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 2", 3) + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) + print("Validate_Parameter_Table failure OK") + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) + print("Validate_Parameter_Table last Status FAILURE OK") -# Send nominal Validate_Parameter_Table command expecting success: -cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": 24, - "Header.Crc_Table": 19692, - "Table_Buffer": list(Test_Packed_Table) - }) -# Check successful command count is 3 and that it was Validate_Parameter_Table: -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 3", 3) -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 5201", 3) -print("Validate_Parameter_Table success OK") + # Send test Validate_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Table_Validation_Failure, and + # Command_Execution_Failure: + cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { + "Header.Table_Buffer_Length": len(Test_Packed_Table) + 1, + "Header.Crc_Table": 19692, + "Table_Buffer": list(Test_Packed_Table) + }) + # Check last failed command count was 3 and that it was Validate_Parameter_Table with Status FAILURE: + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 3", 3) + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) + print("Validate_Parameter_Table failure OK") + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) + print("Validate_Parameter_Table last Status FAILURE OK") -# Send test Validate_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Table_Validation_Failure, and -# Command_Execution_Failure: -cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": 24, - "Header.Crc_Table": 0, - "Table_Buffer": list(Test_Packed_Table) - }) -# Check last failed command count was 2 and that it was Validate_Parameter_Table with Status FAILURE: -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 2", 3) -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) -print("Validate_Parameter_Table failure OK") -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) -print("Validate_Parameter_Table last Status FAILURE OK") + # Send test Validate_Parameter_Table command with nominal values, and Osc_A_Freq = 999.0 to trigger the user implemented Validate_Parameters + # function, expecting Parameter_Validation_Failed, Parameter_Table_Copy_Failure, Table_Validation_Failure, and Command_Execution_Failure + # Rebuild the parameter table using known invalid Osc_A_Freq value: + # Osc_A_Freq + Test_Packed_Table = bytearray(struct.pack(">f", 999.0)) + # Osc_A_Amp + Test_Packed_Table += bytearray(struct.pack(">f", 5.00)) + # Osc_A_Off + Test_Packed_Table += bytearray(struct.pack(">f", 2.50)) + # Osc_B_Freq + Test_Packed_Table += bytearray(struct.pack(">f", 0.30)) + # Osc_B_Amp + Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) + # Osc_B_Off + Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) + # Version + #Test_Packed_Table += bytearray(struct.pack(">f", 0.0)) + # Crc_Table + #Test_Packed_Table += bytearray(struct.pack(">h", 0)) + # Buffer_Length + #Test_Packed_Table += bytearray(struct.pack(">h", 55)) -# Send test Validate_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Table_Validation_Failure, and -# Command_Execution_Failure: -cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": 26, - "Header.Crc_Table": 19692, - "Table_Buffer": list(Test_Packed_Table) - }) -# Check last failed command count was 3 and that it was Validate_Parameter_Table with Status FAILURE: -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 3", 3) -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) -print("Validate_Parameter_Table failure OK") -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) -print("Validate_Parameter_Table last Status FAILURE OK") - -# Send test Validate_Parameter_Table command with nominal values, and Osc_A_Freq = 999.0 to trigger the user implemented Validate_Parameters -# function, expecting Parameter_Validation_Failed, Parameter_Table_Copy_Failure, Table_Validation_Failure, and Command_Execution_Failure -# Rebuild the parameter table using known invalid Osc_A_Freq value: -# Osc_A_Freq -Test_Packed_Table = bytearray(struct.pack(">f", 999.0)) -# Osc_A_Amp -Test_Packed_Table += bytearray(struct.pack(">f", 5.00)) -# Osc_A_Off -Test_Packed_Table += bytearray(struct.pack(">f", 2.50)) -# Osc_B_Freq -Test_Packed_Table += bytearray(struct.pack(">f", 0.30)) -# Osc_B_Amp -Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) -# Osc_B_Off -Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) -# Version -Test_Packed_Table += bytearray(struct.pack(">f", 0.0)) -# Crc_Table -Test_Packed_Table += bytearray(struct.pack(">h", 0)) -# Buffer_Length -Test_Packed_Table += bytearray(struct.pack(">h", 55)) - -cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": 24, - "Header.Crc_Table": 65043, - "Table_Buffer": list(Test_Packed_Table) - }) -# Check last failed command count was 4 and that it was Validate_Parameter_Table with Status FAILURE: -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 4", 3) -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) -print("Validate_Parameter_Table failure OK") -wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) -print("Validate_Parameter_Table last Status FAILURE OK") + cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { + "Header.Table_Buffer_Length": len(Test_Packed_Table), + "Header.Crc_Table": 65043, + "Table_Buffer": list(Test_Packed_Table) + }) + # Check last failed command count was 4 and that it was Validate_Parameter_Table with Status FAILURE: + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 4", 3) + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) + print("Validate_Parameter_Table failure OK") + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) + print("Validate_Parameter_Table last Status FAILURE OK") From 5c9b2bec8ccd97494a73f5a1bff78c58ae3f6330 Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Fri, 30 Aug 2024 21:57:55 -0600 Subject: [PATCH 07/20] Modify COSMOS install script to also copy test scripts --- gnd/cosmos/install_cosmos_plugin.sh | 7 +++++++ test/scripts/update-param-sys.py | 17 ++++++++++++++--- test/scripts/validate-param-sys.py | 20 ++++++++++++++++---- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/gnd/cosmos/install_cosmos_plugin.sh b/gnd/cosmos/install_cosmos_plugin.sh index 60d8c0d..cf90d42 100755 --- a/gnd/cosmos/install_cosmos_plugin.sh +++ b/gnd/cosmos/install_cosmos_plugin.sh @@ -26,6 +26,8 @@ adamant_assembly_name=${adamant_assembly_model%.assembly.yaml} adamant_assembly_name=${adamant_assembly_name##*/} adamant_assembly_dir=`dirname $adamant_assembly_model` cosmos_plugin_dir=`realpath $cosmos_plugin_dir` +adamant_script_dir=`realpath $adamant_assembly_dir/../../../test/scripts` +cosmos_script_dir=`realpath $cosmos_plugin_dir/../plugins/DEFAULT/targets_modified` # Get build directory: adamant_assembly_name_short=(${adamant_assembly_name//_/ }) @@ -53,5 +55,10 @@ do_copy() { do_copy "$adamant_assembly_cmdtlm_dir/${adamant_assembly_name}_ccsds_cosmos_commands.txt" $cosmos_plugin_dir/targets/$adamant_assembly_name_upper/cmd_tlm/cmd.txt do_copy "$adamant_assembly_cmdtlm_dir/${adamant_assembly_name}_ccsds_cosmos_telemetry.txt" $cosmos_plugin_dir/targets/$adamant_assembly_name_upper/cmd_tlm/tlm.txt do_copy "$adamant_assembly_plugin_dir/plugin.txt" $cosmos_plugin_dir/plugin.txt +do_copy "$adamant_script_dir/update-param-sys.py" $cosmos_script_dir/update-param-sys.py +do_copy "$adamant_script_dir/validate-param-sys.py" $cosmos_script_dir/validate-param-sys.py +do_copy "$adamant_script_dir/test_setup.py" $cosmos_script_dir/test_setup.py +do_copy "$adamant_script_dir/crc_16.py" $cosmos_script_dir/crc_16.py echo "Success." echo "Plugin files copied to $cosmos_plugin_dir." +echo "Script files copied to $cosmos_script_dir." diff --git a/test/scripts/update-param-sys.py b/test/scripts/update-param-sys.py index 7f1b3c6..19760b5 100644 --- a/test/scripts/update-param-sys.py +++ b/test/scripts/update-param-sys.py @@ -25,10 +25,21 @@ Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) # Osc_B_Off Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) + table_length = len(Test_Packed_Table) + # Version + #Test_Packed_Table += bytearray(struct.pack(">f", 0.0)) + # Crc_Table + #Test_Packed_Table += bytearray(struct.pack(">h", 0)) + # Buffer_Length + #Test_Packed_Table += bytearray(struct.pack(">h", 0)) + + #test_crc = crc_16.crc_16(Test_Packed_Table) + #int_crc = int.from_bytes(test_crc, 'big') + #print(int_crc) # Remove if CRC fully functional # Send nominal Update_Parameter_Table command expecting success: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { - "Header.Table_Buffer_Length": len(Test_Packed_Table), + "Header.Table_Buffer_Length": table_length, "Header.Crc_Table": 19692, "Table_Buffer": list(Test_Packed_Table) }) @@ -40,7 +51,7 @@ # Send test Update_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Parameter_Table_Copy_Failure, # Working_Table_Update_Failure, and Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { - "Header.Table_Buffer_Length": len(Test_Packed_Table), + "Header.Table_Buffer_Length": table_length, "Header.Crc_Table": 0, "Table_Buffer": list(Test_Packed_Table) }) @@ -54,7 +65,7 @@ # Send test Update_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Parameter_Table_Copy_Failure, # Working_Table_Update_Failure, and Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { - "Header.Table_Buffer_Length": len(Test_Packed_Table) + 1, + "Header.Table_Buffer_Length": table_length + 1, "Header.Crc_Table": 19692, "Table_Buffer": list(Test_Packed_Table) }) diff --git a/test/scripts/validate-param-sys.py b/test/scripts/validate-param-sys.py index 847e790..1bcff06 100644 --- a/test/scripts/validate-param-sys.py +++ b/test/scripts/validate-param-sys.py @@ -25,10 +25,21 @@ Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) # Osc_B_Off Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) + table_length = len(Test_Packed_Table) + # Version + #Test_Packed_Table += bytearray(struct.pack(">f", 0.0)) + # Crc_Table + #Test_Packed_Table += bytearray(struct.pack(">h", 0)) + # Buffer_Length + #Test_Packed_Table += bytearray(struct.pack(">h", 0)) + + #test_crc = crc_16.crc_16(Test_Packed_Table) + #int_crc = int.from_bytes(test_crc, 'big') + #print(int_crc) # Remove if CRC fully functional # Send nominal Validate_Parameter_Table command expecting success: cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": len(Test_Packed_Table), + "Header.Table_Buffer_Length": table_length, "Header.Crc_Table": 19692, "Table_Buffer": list(Test_Packed_Table) }) @@ -40,7 +51,7 @@ # Send test Validate_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Table_Validation_Failure, and # Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": len(Test_Packed_Table), + "Header.Table_Buffer_Length": table_length, "Header.Crc_Table": 0, "Table_Buffer": list(Test_Packed_Table) }) @@ -54,7 +65,7 @@ # Send test Validate_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Table_Validation_Failure, and # Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": len(Test_Packed_Table) + 1, + "Header.Table_Buffer_Length": table_length + 1, "Header.Crc_Table": 19692, "Table_Buffer": list(Test_Packed_Table) }) @@ -80,6 +91,7 @@ Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) # Osc_B_Off Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) + table_length = len(Test_Packed_Table) # Version #Test_Packed_Table += bytearray(struct.pack(">f", 0.0)) # Crc_Table @@ -88,7 +100,7 @@ #Test_Packed_Table += bytearray(struct.pack(">h", 55)) cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": len(Test_Packed_Table), + "Header.Table_Buffer_Length": table_length, "Header.Crc_Table": 65043, "Table_Buffer": list(Test_Packed_Table) }) From ed678d538ed1f581d1fdee91b6bcbc4d634ae632 Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Fri, 6 Sep 2024 15:55:31 -0600 Subject: [PATCH 08/20] Add validation_status to SW status packet --- .../linux/linux_example.product_packets.yaml | 1 + test/scripts/update-param-sys.py | 11 +----- test/scripts/validate-param-sys.py | 38 +++++++------------ 3 files changed, 16 insertions(+), 34 deletions(-) diff --git a/src/assembly/linux/linux_example.product_packets.yaml b/src/assembly/linux/linux_example.product_packets.yaml index e023e5e..c8dc28d 100644 --- a/src/assembly/linux/linux_example.product_packets.yaml +++ b/src/assembly/linux/linux_example.product_packets.yaml @@ -30,4 +30,5 @@ packets: - name: Cpu_Monitor_Instance.Packet_Period - name: Queue_Monitor_Instance.Packet_Period - name: Stack_Monitor_Instance.Packet_Period + - name: Parameter_Manager_Instance.Validation_Status period: "1" # create every tick diff --git a/test/scripts/update-param-sys.py b/test/scripts/update-param-sys.py index 19760b5..4d9a2e4 100644 --- a/test/scripts/update-param-sys.py +++ b/test/scripts/update-param-sys.py @@ -25,17 +25,8 @@ Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) # Osc_B_Off Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) + # Get table length: table_length = len(Test_Packed_Table) - # Version - #Test_Packed_Table += bytearray(struct.pack(">f", 0.0)) - # Crc_Table - #Test_Packed_Table += bytearray(struct.pack(">h", 0)) - # Buffer_Length - #Test_Packed_Table += bytearray(struct.pack(">h", 0)) - - #test_crc = crc_16.crc_16(Test_Packed_Table) - #int_crc = int.from_bytes(test_crc, 'big') - #print(int_crc) # Remove if CRC fully functional # Send nominal Update_Parameter_Table command expecting success: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { diff --git a/test/scripts/validate-param-sys.py b/test/scripts/validate-param-sys.py index 1bcff06..15647ef 100644 --- a/test/scripts/validate-param-sys.py +++ b/test/scripts/validate-param-sys.py @@ -25,17 +25,8 @@ Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) # Osc_B_Off Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) + # Get table length: table_length = len(Test_Packed_Table) - # Version - #Test_Packed_Table += bytearray(struct.pack(">f", 0.0)) - # Crc_Table - #Test_Packed_Table += bytearray(struct.pack(">h", 0)) - # Buffer_Length - #Test_Packed_Table += bytearray(struct.pack(">h", 0)) - - #test_crc = crc_16.crc_16(Test_Packed_Table) - #int_crc = int.from_bytes(test_crc, 'big') - #print(int_crc) # Remove if CRC fully functional # Send nominal Validate_Parameter_Table command expecting success: cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { @@ -43,10 +34,11 @@ "Header.Crc_Table": 19692, "Table_Buffer": list(Test_Packed_Table) }) - # Check successful command count is 3 and that it was Validate_Parameter_Table: + # Check successful command count is 3 and that it was Validate_Parameter_Table with Status SUCCESS: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 3", 3) wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 5201", 3) - print("Validate_Parameter_Table success OK") + wait_check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'SUCCESS'", 3) + print("Validate_Parameter_Table SUCCESS OK") # Send test Validate_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Table_Validation_Failure, and # Command_Execution_Failure: @@ -55,12 +47,13 @@ "Header.Crc_Table": 0, "Table_Buffer": list(Test_Packed_Table) }) - # Check last failed command count was 2 and that it was Validate_Parameter_Table with Status FAILURE: + # Check last failed command count was 2 and that it was Validate_Parameter_Table with Status CRC_ERROR: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 2", 3) wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) print("Validate_Parameter_Table failure OK") wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) - print("Validate_Parameter_Table last Status FAILURE OK") + wait_check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'CRC_ERROR'", 3) + print("Validate_Parameter_Table last Status CRC_ERROR OK") # Send test Validate_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Table_Validation_Failure, and # Command_Execution_Failure: @@ -69,12 +62,13 @@ "Header.Crc_Table": 19692, "Table_Buffer": list(Test_Packed_Table) }) - # Check last failed command count was 3 and that it was Validate_Parameter_Table with Status FAILURE: + # Check last failed command count was 3 and that it was Validate_Parameter_Table with Status LENGTH_ERROR: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 3", 3) wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) print("Validate_Parameter_Table failure OK") wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) - print("Validate_Parameter_Table last Status FAILURE OK") + wait_check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'LENGTH_ERROR'", 3) + print("Validate_Parameter_Table last Status LENGTH_ERROR OK") # Send test Validate_Parameter_Table command with nominal values, and Osc_A_Freq = 999.0 to trigger the user implemented Validate_Parameters # function, expecting Parameter_Validation_Failed, Parameter_Table_Copy_Failure, Table_Validation_Failure, and Command_Execution_Failure @@ -91,22 +85,18 @@ Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) # Osc_B_Off Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) + # Get table length: table_length = len(Test_Packed_Table) - # Version - #Test_Packed_Table += bytearray(struct.pack(">f", 0.0)) - # Crc_Table - #Test_Packed_Table += bytearray(struct.pack(">h", 0)) - # Buffer_Length - #Test_Packed_Table += bytearray(struct.pack(">h", 55)) cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { "Header.Table_Buffer_Length": table_length, "Header.Crc_Table": 65043, "Table_Buffer": list(Test_Packed_Table) }) - # Check last failed command count was 4 and that it was Validate_Parameter_Table with Status FAILURE: + # Check last failed command count was 4 and that it was Validate_Parameter_Table with Status PARAMETER_ERROR: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 4", 3) wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) print("Validate_Parameter_Table failure OK") wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) - print("Validate_Parameter_Table last Status FAILURE OK") + wait_check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'PARAMETER_ERROR'", 3) + print("Validate_Parameter_Table last Status PARAMETER_ERROR OK") From d64f19664493950371121499248a4f1dcd22501d Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Fri, 6 Sep 2024 16:46:57 -0600 Subject: [PATCH 09/20] Use `crc_16.py` to apply CRC in COSMOS scripts --- test/scripts/update-param-sys.py | 10 +++++++--- test/scripts/validate-param-sys.py | 31 +++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/test/scripts/update-param-sys.py b/test/scripts/update-param-sys.py index 4d9a2e4..30659ca 100644 --- a/test/scripts/update-param-sys.py +++ b/test/scripts/update-param-sys.py @@ -25,13 +25,17 @@ Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) # Osc_B_Off Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) - # Get table length: table_length = len(Test_Packed_Table) + # Append table to Version and get CRC + CRC_Packed_Table = bytearray(struct.pack(">f", 0.0)) + CRC_Packed_Table += Test_Packed_Table + Test_CRC = crc_16.crc_16(CRC_Packed_Table) + Int_CRC = int.from_bytes(Test_CRC, 'big') # Send nominal Update_Parameter_Table command expecting success: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { "Header.Table_Buffer_Length": table_length, - "Header.Crc_Table": 19692, + "Header.Crc_Table": Int_CRC, "Table_Buffer": list(Test_Packed_Table) }) # Check successful command count is 3 and that it was Update_Parameter_Table: @@ -57,7 +61,7 @@ # Working_Table_Update_Failure, and Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { "Header.Table_Buffer_Length": table_length + 1, - "Header.Crc_Table": 19692, + "Header.Crc_Table": Int_CRC, "Table_Buffer": list(Test_Packed_Table) }) # Check last failed command count was 3 and that it was Update_Parameter_Table with Status FAILURE: diff --git a/test/scripts/validate-param-sys.py b/test/scripts/validate-param-sys.py index 15647ef..a681846 100644 --- a/test/scripts/validate-param-sys.py +++ b/test/scripts/validate-param-sys.py @@ -26,12 +26,17 @@ # Osc_B_Off Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) # Get table length: - table_length = len(Test_Packed_Table) + Table_Length = len(Test_Packed_Table) + # Append table to Version and get CRC + CRC_Packed_Table = bytearray(struct.pack(">f", 0.0)) + CRC_Packed_Table += Test_Packed_Table + Test_CRC = crc_16.crc_16(CRC_Packed_Table) + Int_CRC = int.from_bytes(Test_CRC, 'big') # Send nominal Validate_Parameter_Table command expecting success: cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": table_length, - "Header.Crc_Table": 19692, + "Header.Table_Buffer_Length": Table_Length, + "Header.Crc_Table": Int_CRC, "Table_Buffer": list(Test_Packed_Table) }) # Check successful command count is 3 and that it was Validate_Parameter_Table with Status SUCCESS: @@ -43,7 +48,7 @@ # Send test Validate_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Table_Validation_Failure, and # Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": table_length, + "Header.Table_Buffer_Length": Table_Length, "Header.Crc_Table": 0, "Table_Buffer": list(Test_Packed_Table) }) @@ -58,8 +63,8 @@ # Send test Validate_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Table_Validation_Failure, and # Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": table_length + 1, - "Header.Crc_Table": 19692, + "Header.Table_Buffer_Length": Table_Length + 1, + "Header.Crc_Table": Int_CRC, "Table_Buffer": list(Test_Packed_Table) }) # Check last failed command count was 3 and that it was Validate_Parameter_Table with Status LENGTH_ERROR: @@ -86,11 +91,19 @@ # Osc_B_Off Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) # Get table length: - table_length = len(Test_Packed_Table) + Table_Length = len(Test_Packed_Table) + # Version + CRC_Packed_Table = bytearray(struct.pack(">f", 0.0)) + # Append rest of Test_Packed_Table + CRC_Packed_Table += Test_Packed_Table + + Test_CRC = crc_16.crc_16(CRC_Packed_Table) + Int_CRC = int.from_bytes(Test_CRC, 'big') + print(Int_CRC) # Remove if CRC fully functional cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": table_length, - "Header.Crc_Table": 65043, + "Header.Table_Buffer_Length": Table_Length, + "Header.Crc_Table": Int_CRC, "Table_Buffer": list(Test_Packed_Table) }) # Check last failed command count was 4 and that it was Validate_Parameter_Table with Status PARAMETER_ERROR: From fad3e091fcf57aee94a97e13e40e3a8d008b398c Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Fri, 6 Sep 2024 17:52:08 -0600 Subject: [PATCH 10/20] Check active parameters using `Dump_Parameters` command --- test/scripts/update-param-sys.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/scripts/update-param-sys.py b/test/scripts/update-param-sys.py index 30659ca..3c92f08 100644 --- a/test/scripts/update-param-sys.py +++ b/test/scripts/update-param-sys.py @@ -70,3 +70,21 @@ print("Update_Parameter_Table failure OK") wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) print("Update_Parameter_Table last Status FAILURE OK") + + # Send Dump_Parameters command and check against prepared parameter table: + cmd("Linux_Example", "Parameters_Instance-Dump_Parameters") + # Check successful command count is 4 and that it was Dump_Parameter_Store: + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 4", 3) + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 30", 3) + # Check CRC and parameter values: + wait_check("Linux_Example Active_Parameters Parameters_Instance.Active_Parameters.Crc_Calculated == 19692", 3) + wait_check("Linux_Example Active_Parameters Parameters_Instance.Active_Parameters.Oscillator_A_Frequency.Value == 0.30000001192092896", 3) + wait_check("Linux_Example Active_Parameters Parameters_Instance.Active_Parameters.Oscillator_A_Amplitude.Value == 5", 3) + wait_check("Linux_Example Active_Parameters Parameters_Instance.Active_Parameters.Oscillator_A_Offset.Value == 2.5", 3) + wait_check("Linux_Example Active_Parameters Parameters_Instance.Active_Parameters.Oscillator_B_Frequency.Value == 0.30000001192092896", 3) + wait_check("Linux_Example Active_Parameters Parameters_Instance.Active_Parameters.Oscillator_B_Amplitude.Value == -5.0", 3) + wait_check("Linux_Example Active_Parameters Parameters_Instance.Active_Parameters.Oscillator_B_Offset.Value == -2.5", 3) + print("Dump_Parameters values OK") + # Optionally check the hash returned by: + # Active_Parameters = get_tlm("Linux_Example Active_Parameters") + # print(Active_Parameters) From 44c954293916fa7d33ca0e7be6b9ae85019a21ba Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Fri, 6 Sep 2024 19:11:52 -0600 Subject: [PATCH 11/20] Implement checking Active_Parameters CRC and table buffer directly --- test/scripts/update-param-sys.py | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/test/scripts/update-param-sys.py b/test/scripts/update-param-sys.py index 3c92f08..8b11324 100644 --- a/test/scripts/update-param-sys.py +++ b/test/scripts/update-param-sys.py @@ -25,7 +25,7 @@ Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) # Osc_B_Off Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) - table_length = len(Test_Packed_Table) + Table_Length = len(Test_Packed_Table) # Append table to Version and get CRC CRC_Packed_Table = bytearray(struct.pack(">f", 0.0)) CRC_Packed_Table += Test_Packed_Table @@ -34,7 +34,7 @@ # Send nominal Update_Parameter_Table command expecting success: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { - "Header.Table_Buffer_Length": table_length, + "Header.Table_Buffer_Length": Table_Length, "Header.Crc_Table": Int_CRC, "Table_Buffer": list(Test_Packed_Table) }) @@ -46,7 +46,7 @@ # Send test Update_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Parameter_Table_Copy_Failure, # Working_Table_Update_Failure, and Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { - "Header.Table_Buffer_Length": table_length, + "Header.Table_Buffer_Length": Table_Length, "Header.Crc_Table": 0, "Table_Buffer": list(Test_Packed_Table) }) @@ -60,7 +60,7 @@ # Send test Update_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Parameter_Table_Copy_Failure, # Working_Table_Update_Failure, and Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { - "Header.Table_Buffer_Length": table_length + 1, + "Header.Table_Buffer_Length": Table_Length + 1, "Header.Crc_Table": Int_CRC, "Table_Buffer": list(Test_Packed_Table) }) @@ -76,15 +76,11 @@ # Check successful command count is 4 and that it was Dump_Parameter_Store: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 4", 3) wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 30", 3) - # Check CRC and parameter values: - wait_check("Linux_Example Active_Parameters Parameters_Instance.Active_Parameters.Crc_Calculated == 19692", 3) - wait_check("Linux_Example Active_Parameters Parameters_Instance.Active_Parameters.Oscillator_A_Frequency.Value == 0.30000001192092896", 3) - wait_check("Linux_Example Active_Parameters Parameters_Instance.Active_Parameters.Oscillator_A_Amplitude.Value == 5", 3) - wait_check("Linux_Example Active_Parameters Parameters_Instance.Active_Parameters.Oscillator_A_Offset.Value == 2.5", 3) - wait_check("Linux_Example Active_Parameters Parameters_Instance.Active_Parameters.Oscillator_B_Frequency.Value == 0.30000001192092896", 3) - wait_check("Linux_Example Active_Parameters Parameters_Instance.Active_Parameters.Oscillator_B_Amplitude.Value == -5.0", 3) - wait_check("Linux_Example Active_Parameters Parameters_Instance.Active_Parameters.Oscillator_B_Offset.Value == -2.5", 3) - print("Dump_Parameters values OK") - # Optionally check the hash returned by: - # Active_Parameters = get_tlm("Linux_Example Active_Parameters") - # print(Active_Parameters) + Active_Parameters_Buffer = get_tlm_buffer("Linux_Example Active_Parameters") + Buffer = Active_Parameters_Buffer['buffer'] + # Check CRC + if list(Buffer[-32:-30]) == Test_CRC: + print("Dump_Parameters CRC OK") + # Check Active_Parameters table buffer: + if Buffer[-30:-2] == CRC_Packed_Table: + print("Dump_Parameters values OK") From 4ed2995fc88064fbbfaf488d0f5328fb0c5c1f32 Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Tue, 10 Sep 2024 13:56:43 -0600 Subject: [PATCH 12/20] Add `clear_counts` to `test_setup.py` --- test/scripts/test_setup.py | 12 +++++++++--- test/scripts/update-param-sys.py | 16 ++++++++-------- test/scripts/validate-param-sys.py | 12 ++++++------ 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/test/scripts/test_setup.py b/test/scripts/test_setup.py index 0b3a5f1..ba1912d 100644 --- a/test/scripts/test_setup.py +++ b/test/scripts/test_setup.py @@ -1,15 +1,18 @@ from openc3.script import * -def test_setup(): +def clear_counts(): # Clear counts and data products from prior tests: cmd("Linux_Example Fault_Correction_Instance-Reset_Data_Products") - cmd("Linux_Example Ccsds_Command_Depacketizer_Instance-Reset_Counts") cmd("Linux_Example Command_Router_Instance-Reset_Data_Products") + cmd("Linux_Example Ccsds_Command_Depacketizer_Instance-Reset_Counts") + +def test_setup(): + clear_counts() # Send Noop_Arg command expecting success: cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 1") # Check successful command count is 2 and that the last success was Noop_Arg with last Value 1: - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 2", 3) + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 3", 3) wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 3", 3) print("Noop_Arg success OK") wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == 1", 3) @@ -25,4 +28,7 @@ def test_setup(): wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) print("Noop_Arg last Value failure OK") + # Clear counts and data products to finish the test setup: + clear_counts() + return True diff --git a/test/scripts/update-param-sys.py b/test/scripts/update-param-sys.py index 8b11324..6e68a10 100644 --- a/test/scripts/update-param-sys.py +++ b/test/scripts/update-param-sys.py @@ -25,7 +25,7 @@ Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) # Osc_B_Off Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) - Table_Length = len(Test_Packed_Table) + table_length = len(Test_Packed_Table) # Append table to Version and get CRC CRC_Packed_Table = bytearray(struct.pack(">f", 0.0)) CRC_Packed_Table += Test_Packed_Table @@ -34,7 +34,7 @@ # Send nominal Update_Parameter_Table command expecting success: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { - "Header.Table_Buffer_Length": Table_Length, + "Header.Table_Buffer_Length": table_length, "Header.Crc_Table": Int_CRC, "Table_Buffer": list(Test_Packed_Table) }) @@ -46,12 +46,12 @@ # Send test Update_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Parameter_Table_Copy_Failure, # Working_Table_Update_Failure, and Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { - "Header.Table_Buffer_Length": Table_Length, + "Header.Table_Buffer_Length": table_length, "Header.Crc_Table": 0, "Table_Buffer": list(Test_Packed_Table) }) - # Check last failed command count was 2 and that it was Update_Parameter_Table with Status FAILURE: - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 2", 3) + # Check last failed command count was 1 and that it was Update_Parameter_Table with Status FAILURE: + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 1", 3) wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5200", 3) print("Update_Parameter_Table failure OK") wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) @@ -60,12 +60,12 @@ # Send test Update_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Parameter_Table_Copy_Failure, # Working_Table_Update_Failure, and Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { - "Header.Table_Buffer_Length": Table_Length + 1, + "Header.Table_Buffer_Length": table_length + 1, "Header.Crc_Table": Int_CRC, "Table_Buffer": list(Test_Packed_Table) }) - # Check last failed command count was 3 and that it was Update_Parameter_Table with Status FAILURE: - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 3", 3) + # Check last failed command count was 2 and that it was Update_Parameter_Table with Status FAILURE: + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 2", 3) wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5200", 3) print("Update_Parameter_Table failure OK") wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) diff --git a/test/scripts/validate-param-sys.py b/test/scripts/validate-param-sys.py index a681846..42e6aed 100644 --- a/test/scripts/validate-param-sys.py +++ b/test/scripts/validate-param-sys.py @@ -52,8 +52,8 @@ "Header.Crc_Table": 0, "Table_Buffer": list(Test_Packed_Table) }) - # Check last failed command count was 2 and that it was Validate_Parameter_Table with Status CRC_ERROR: - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 2", 3) + # Check last failed command count was 1 and that it was Validate_Parameter_Table with Status CRC_ERROR: + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 1", 3) wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) print("Validate_Parameter_Table failure OK") wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) @@ -67,8 +67,8 @@ "Header.Crc_Table": Int_CRC, "Table_Buffer": list(Test_Packed_Table) }) - # Check last failed command count was 3 and that it was Validate_Parameter_Table with Status LENGTH_ERROR: - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 3", 3) + # Check last failed command count was 2 and that it was Validate_Parameter_Table with Status LENGTH_ERROR: + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 2", 3) wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) print("Validate_Parameter_Table failure OK") wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) @@ -106,8 +106,8 @@ "Header.Crc_Table": Int_CRC, "Table_Buffer": list(Test_Packed_Table) }) - # Check last failed command count was 4 and that it was Validate_Parameter_Table with Status PARAMETER_ERROR: - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 4", 3) + # Check last failed command count was 3 and that it was Validate_Parameter_Table with Status PARAMETER_ERROR: + wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 3", 3) wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) print("Validate_Parameter_Table failure OK") wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) From 69d2779f525bd4474479b3a8481c691e206fbcc1 Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Tue, 10 Sep 2024 14:01:34 -0600 Subject: [PATCH 13/20] Index from the beginning for CRC and table_buffer --- test/scripts/update-param-sys.py | 4 ++-- test/scripts/validate-param-sys.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/test/scripts/update-param-sys.py b/test/scripts/update-param-sys.py index 6e68a10..7baf92f 100644 --- a/test/scripts/update-param-sys.py +++ b/test/scripts/update-param-sys.py @@ -79,8 +79,8 @@ Active_Parameters_Buffer = get_tlm_buffer("Linux_Example Active_Parameters") Buffer = Active_Parameters_Buffer['buffer'] # Check CRC - if list(Buffer[-32:-30]) == Test_CRC: + if list(Buffer[16:18]) == Test_CRC: print("Dump_Parameters CRC OK") # Check Active_Parameters table buffer: - if Buffer[-30:-2] == CRC_Packed_Table: + if Buffer[18:46] == CRC_Packed_Table: print("Dump_Parameters values OK") diff --git a/test/scripts/validate-param-sys.py b/test/scripts/validate-param-sys.py index 42e6aed..5730026 100644 --- a/test/scripts/validate-param-sys.py +++ b/test/scripts/validate-param-sys.py @@ -99,7 +99,6 @@ Test_CRC = crc_16.crc_16(CRC_Packed_Table) Int_CRC = int.from_bytes(Test_CRC, 'big') - print(Int_CRC) # Remove if CRC fully functional cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { "Header.Table_Buffer_Length": Table_Length, From 296686e7e543cc3ea7d4c6e66e958d8bf5210164 Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Tue, 10 Sep 2024 14:16:39 -0600 Subject: [PATCH 14/20] Replace `wait_check` with `check` where appropriate --- test/scripts/test_setup.py | 13 +++++++------ test/scripts/update-param-sys.py | 12 ++++++------ test/scripts/validate-param-sys.py | 23 ++++++++++++----------- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/test/scripts/test_setup.py b/test/scripts/test_setup.py index ba1912d..13dc89b 100644 --- a/test/scripts/test_setup.py +++ b/test/scripts/test_setup.py @@ -8,24 +8,25 @@ def clear_counts(): def test_setup(): clear_counts() + wait(1) # Send Noop_Arg command expecting success: cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 1") - # Check successful command count is 2 and that the last success was Noop_Arg with last Value 1: + # Check successful command count is 3 and that the last success was Noop_Arg with last Value 1: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 3", 3) - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 3", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 3") print("Noop_Arg success OK") - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == 1", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == 1") print("Noop_Arg last Value OK") # Send Noop command expecting failure: cmd("Linux_Example Command_Router_Instance-Noop_Arg with Value 868") # Check last failed command count was 1 and that it was Noop_Arg with last Value 1: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 1", 3) - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 3", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 3") print("Noop_Arg failure OK") - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == 868", 3) - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Noop_Arg_Last_Value.Value == 868") + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") print("Noop_Arg last Value failure OK") # Clear counts and data products to finish the test setup: diff --git a/test/scripts/update-param-sys.py b/test/scripts/update-param-sys.py index 7baf92f..1e3971b 100644 --- a/test/scripts/update-param-sys.py +++ b/test/scripts/update-param-sys.py @@ -40,7 +40,7 @@ }) # Check successful command count is 3 and that it was Update_Parameter_Table: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 3", 3) - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 5200", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 5200") print("Update_Parameter_Table success OK") # Send test Update_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Parameter_Table_Copy_Failure, @@ -52,9 +52,9 @@ }) # Check last failed command count was 1 and that it was Update_Parameter_Table with Status FAILURE: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 1", 3) - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5200", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5200") print("Update_Parameter_Table failure OK") - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") print("Update_Parameter_Table last Status FAILURE OK") # Send test Update_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Parameter_Table_Copy_Failure, @@ -66,16 +66,16 @@ }) # Check last failed command count was 2 and that it was Update_Parameter_Table with Status FAILURE: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 2", 3) - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5200", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5200") print("Update_Parameter_Table failure OK") - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") print("Update_Parameter_Table last Status FAILURE OK") # Send Dump_Parameters command and check against prepared parameter table: cmd("Linux_Example", "Parameters_Instance-Dump_Parameters") # Check successful command count is 4 and that it was Dump_Parameter_Store: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 4", 3) - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 30", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 30") Active_Parameters_Buffer = get_tlm_buffer("Linux_Example Active_Parameters") Buffer = Active_Parameters_Buffer['buffer'] # Check CRC diff --git a/test/scripts/validate-param-sys.py b/test/scripts/validate-param-sys.py index 5730026..2697ab1 100644 --- a/test/scripts/validate-param-sys.py +++ b/test/scripts/validate-param-sys.py @@ -41,8 +41,8 @@ }) # Check successful command count is 3 and that it was Validate_Parameter_Table with Status SUCCESS: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 3", 3) - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 5201", 3) - wait_check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'SUCCESS'", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 5201") + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'SUCCESS'") print("Validate_Parameter_Table SUCCESS OK") # Send test Validate_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Table_Validation_Failure, and @@ -54,10 +54,10 @@ }) # Check last failed command count was 1 and that it was Validate_Parameter_Table with Status CRC_ERROR: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 1", 3) - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201") print("Validate_Parameter_Table failure OK") - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) - wait_check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'CRC_ERROR'", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'CRC_ERROR'") print("Validate_Parameter_Table last Status CRC_ERROR OK") # Send test Validate_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Table_Validation_Failure, and @@ -69,10 +69,10 @@ }) # Check last failed command count was 2 and that it was Validate_Parameter_Table with Status LENGTH_ERROR: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 2", 3) - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201") print("Validate_Parameter_Table failure OK") - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) - wait_check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'LENGTH_ERROR'", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'LENGTH_ERROR'") print("Validate_Parameter_Table last Status LENGTH_ERROR OK") # Send test Validate_Parameter_Table command with nominal values, and Osc_A_Freq = 999.0 to trigger the user implemented Validate_Parameters @@ -99,6 +99,7 @@ Test_CRC = crc_16.crc_16(CRC_Packed_Table) Int_CRC = int.from_bytes(Test_CRC, 'big') + print(Int_CRC) # Remove if CRC fully functional cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { "Header.Table_Buffer_Length": Table_Length, @@ -107,8 +108,8 @@ }) # Check last failed command count was 3 and that it was Validate_Parameter_Table with Status PARAMETER_ERROR: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 3", 3) - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201") print("Validate_Parameter_Table failure OK") - wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'", 3) - wait_check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'PARAMETER_ERROR'", 3) + check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'PARAMETER_ERROR'") print("Validate_Parameter_Table last Status PARAMETER_ERROR OK") From bb3107a79ce639db92401058fc2b4540cc7ad37f Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Tue, 10 Sep 2024 14:35:41 -0600 Subject: [PATCH 15/20] Add checks in validation test for CRC and version --- test/scripts/update-param-sys.py | 1 + test/scripts/validate-param-sys.py | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/test/scripts/update-param-sys.py b/test/scripts/update-param-sys.py index 1e3971b..884fe2b 100644 --- a/test/scripts/update-param-sys.py +++ b/test/scripts/update-param-sys.py @@ -25,6 +25,7 @@ Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) # Osc_B_Off Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) + # Get table length: table_length = len(Test_Packed_Table) # Append table to Version and get CRC CRC_Packed_Table = bytearray(struct.pack(">f", 0.0)) diff --git a/test/scripts/validate-param-sys.py b/test/scripts/validate-param-sys.py index 2697ab1..ec83e40 100644 --- a/test/scripts/validate-param-sys.py +++ b/test/scripts/validate-param-sys.py @@ -42,7 +42,10 @@ # Check successful command count is 3 and that it was Validate_Parameter_Table with Status SUCCESS: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 3", 3) check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 5201") + # Check Last_Validation_Version, Crc_Table, and Last_Validation_Status: check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'SUCCESS'") + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Version == 0.00") + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == " + str(Int_CRC)) print("Validate_Parameter_Table SUCCESS OK") # Send test Validate_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Table_Validation_Failure, and @@ -57,7 +60,10 @@ check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201") print("Validate_Parameter_Table failure OK") check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") + # Check Last_Validation_Version, Crc_Table, and Last_Validation_Status: check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'CRC_ERROR'") + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Version == 0.00") + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == 0") print("Validate_Parameter_Table last Status CRC_ERROR OK") # Send test Validate_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Table_Validation_Failure, and @@ -72,7 +78,10 @@ check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201") print("Validate_Parameter_Table failure OK") check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") + # Check Last_Validation_Version, Crc_Table, and Last_Validation_Status: check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'LENGTH_ERROR'") + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Version == 0.00") + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == " + str(Int_CRC)) print("Validate_Parameter_Table last Status LENGTH_ERROR OK") # Send test Validate_Parameter_Table command with nominal values, and Osc_A_Freq = 999.0 to trigger the user implemented Validate_Parameters @@ -92,14 +101,11 @@ Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) # Get table length: Table_Length = len(Test_Packed_Table) - # Version + # Append table to Version and get CRC CRC_Packed_Table = bytearray(struct.pack(">f", 0.0)) - # Append rest of Test_Packed_Table CRC_Packed_Table += Test_Packed_Table - Test_CRC = crc_16.crc_16(CRC_Packed_Table) Int_CRC = int.from_bytes(Test_CRC, 'big') - print(Int_CRC) # Remove if CRC fully functional cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { "Header.Table_Buffer_Length": Table_Length, @@ -111,5 +117,8 @@ check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.ID == 5201") print("Validate_Parameter_Table failure OK") check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Failed_Command.Status == 'FAILURE'") + # Check Last_Validation_Version, Crc_Table, and Last_Validation_Status: check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'PARAMETER_ERROR'") + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Version == 0.00") + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == " + str(Int_CRC)) print("Validate_Parameter_Table last Status PARAMETER_ERROR OK") From 8bc9f2db6bba36143c7866aaa371b33ed8c0494c Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Sat, 21 Sep 2024 09:38:59 -0600 Subject: [PATCH 16/20] Create table records using Adamant type definitions --- test/scripts/update-param-sys.py | 55 ++++++++--------- test/scripts/validate-param-sys.py | 96 +++++++++++++----------------- 2 files changed, 68 insertions(+), 83 deletions(-) diff --git a/test/scripts/update-param-sys.py b/test/scripts/update-param-sys.py index 884fe2b..7155480 100644 --- a/test/scripts/update-param-sys.py +++ b/test/scripts/update-param-sys.py @@ -5,6 +5,7 @@ sys.path.append('/plugins/DEFAULT/targets_modified') import crc_16 import test_setup +import linux_example_parameter_table_record as Table_Record if test_setup.test_setup(): @@ -12,32 +13,26 @@ # If this point was reached then begin testing parameter update functions ######################################################################### - # Build a parameter table using bytearrays: - # Osc_A_Freq - Test_Packed_Table = bytearray(struct.pack(">f", 0.30)) - # Osc_A_Amp - Test_Packed_Table += bytearray(struct.pack(">f", 5.00)) - # Osc_A_Off - Test_Packed_Table += bytearray(struct.pack(">f", 2.50)) - # Osc_B_Freq - Test_Packed_Table += bytearray(struct.pack(">f", 0.30)) - # Osc_B_Amp - Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) - # Osc_B_Off - Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) - # Get table length: - table_length = len(Test_Packed_Table) - # Append table to Version and get CRC - CRC_Packed_Table = bytearray(struct.pack(">f", 0.0)) - CRC_Packed_Table += Test_Packed_Table - Test_CRC = crc_16.crc_16(CRC_Packed_Table) - Int_CRC = int.from_bytes(Test_CRC, 'big') + # Build a parameter table using the Adamant packed record definitions: + record = Table_Record.Linux_Example_Parameter_Table_Record( + Crc_Calculated=0, + Header=Table_Record.Parameter_Table_Header(), + Oscillator_A_Frequency=Table_Record.Packed_F32(0.30), + Oscillator_A_Amplitude=Table_Record.Packed_F32(5.00), + Oscillator_A_Offset=Table_Record.Packed_F32(2.50), + Oscillator_B_Frequency=Table_Record.Packed_F32(0.30), + Oscillator_B_Amplitude=Table_Record.Packed_F32(-5.00), + Oscillator_B_Offset=Table_Record.Packed_F32(-2.50) + ) + record_byte_array = record._to_byte_array().tobytes() + record_len = len(record_byte_array[8:]) + record_crc = int.from_bytes(crc_16.crc_16(record_byte_array[4:]), 'big') # Send nominal Update_Parameter_Table command expecting success: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { - "Header.Table_Buffer_Length": table_length, - "Header.Crc_Table": Int_CRC, - "Table_Buffer": list(Test_Packed_Table) + "Header.Table_Buffer_Length": record_len, + "Header.Crc_Table": record_crc, + "Table_Buffer": list(record_byte_array[8:]) }) # Check successful command count is 3 and that it was Update_Parameter_Table: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 3", 3) @@ -47,9 +42,9 @@ # Send test Update_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Parameter_Table_Copy_Failure, # Working_Table_Update_Failure, and Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { - "Header.Table_Buffer_Length": table_length, + "Header.Table_Buffer_Length": record_len, "Header.Crc_Table": 0, - "Table_Buffer": list(Test_Packed_Table) + "Table_Buffer": list(record_byte_array[8:]) }) # Check last failed command count was 1 and that it was Update_Parameter_Table with Status FAILURE: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 1", 3) @@ -61,9 +56,9 @@ # Send test Update_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Parameter_Table_Copy_Failure, # Working_Table_Update_Failure, and Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { - "Header.Table_Buffer_Length": table_length + 1, - "Header.Crc_Table": Int_CRC, - "Table_Buffer": list(Test_Packed_Table) + "Header.Table_Buffer_Length": record_len + 1, + "Header.Crc_Table": record_crc, + "Table_Buffer": list(record_byte_array[8:]) }) # Check last failed command count was 2 and that it was Update_Parameter_Table with Status FAILURE: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 2", 3) @@ -80,8 +75,8 @@ Active_Parameters_Buffer = get_tlm_buffer("Linux_Example Active_Parameters") Buffer = Active_Parameters_Buffer['buffer'] # Check CRC - if list(Buffer[16:18]) == Test_CRC: + if list(Buffer[16:18]) == record_crc: print("Dump_Parameters CRC OK") # Check Active_Parameters table buffer: - if Buffer[18:46] == CRC_Packed_Table: + if Buffer[18:46] == list(record_byte_array[8:]): print("Dump_Parameters values OK") diff --git a/test/scripts/validate-param-sys.py b/test/scripts/validate-param-sys.py index ec83e40..3dc5713 100644 --- a/test/scripts/validate-param-sys.py +++ b/test/scripts/validate-param-sys.py @@ -5,6 +5,7 @@ sys.path.append('/plugins/DEFAULT/targets_modified') import crc_16 import test_setup +import linux_example_parameter_table_record as Table_Record if test_setup.test_setup(): @@ -12,32 +13,26 @@ # If this point was reached then begin testing parameter validation functions ############################################################################# - # Build a parameter table using bytearrays: - # Osc_A_Freq - Test_Packed_Table = bytearray(struct.pack(">f", 0.30)) - # Osc_A_Amp - Test_Packed_Table += bytearray(struct.pack(">f", 5.00)) - # Osc_A_Off - Test_Packed_Table += bytearray(struct.pack(">f", 2.50)) - # Osc_B_Freq - Test_Packed_Table += bytearray(struct.pack(">f", 0.30)) - # Osc_B_Amp - Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) - # Osc_B_Off - Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) - # Get table length: - Table_Length = len(Test_Packed_Table) - # Append table to Version and get CRC - CRC_Packed_Table = bytearray(struct.pack(">f", 0.0)) - CRC_Packed_Table += Test_Packed_Table - Test_CRC = crc_16.crc_16(CRC_Packed_Table) - Int_CRC = int.from_bytes(Test_CRC, 'big') + # Build a parameter table using the Adamant packed record definitions: + record = Table_Record.Linux_Example_Parameter_Table_Record( + Crc_Calculated=0, + Header=Table_Record.Parameter_Table_Header(), + Oscillator_A_Frequency=Table_Record.Packed_F32(0.30), + Oscillator_A_Amplitude=Table_Record.Packed_F32(5.00), + Oscillator_A_Offset=Table_Record.Packed_F32(2.50), + Oscillator_B_Frequency=Table_Record.Packed_F32(0.30), + Oscillator_B_Amplitude=Table_Record.Packed_F32(-5.00), + Oscillator_B_Offset=Table_Record.Packed_F32(-2.50) + ) + record_byte_array = record._to_byte_array().tobytes() + record_len = len(record_byte_array[8:]) + record_crc = int.from_bytes(crc_16.crc_16(record_byte_array[4:]), 'big') # Send nominal Validate_Parameter_Table command expecting success: cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": Table_Length, - "Header.Crc_Table": Int_CRC, - "Table_Buffer": list(Test_Packed_Table) + "Header.Table_Buffer_Length": record_len, + "Header.Crc_Table": record_crc, + "Table_Buffer": list(record_byte_array[8:]) }) # Check successful command count is 3 and that it was Validate_Parameter_Table with Status SUCCESS: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Success_Count.Value == 3", 3) @@ -45,15 +40,15 @@ # Check Last_Validation_Version, Crc_Table, and Last_Validation_Status: check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'SUCCESS'") check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Version == 0.00") - check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == " + str(Int_CRC)) + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == " + str(record_crc)) print("Validate_Parameter_Table SUCCESS OK") # Send test Validate_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Table_Validation_Failure, and # Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": Table_Length, + "Header.Table_Buffer_Length": record_len, "Header.Crc_Table": 0, - "Table_Buffer": list(Test_Packed_Table) + "Table_Buffer": list(record_byte_array[8:]) }) # Check last failed command count was 1 and that it was Validate_Parameter_Table with Status CRC_ERROR: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 1", 3) @@ -69,9 +64,9 @@ # Send test Validate_Parameter_Table command with bad length expecting Memory_Region_Length_Mismatch, Table_Validation_Failure, and # Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": Table_Length + 1, - "Header.Crc_Table": Int_CRC, - "Table_Buffer": list(Test_Packed_Table) + "Header.Table_Buffer_Length": record_len + 1, + "Header.Crc_Table": record_crc, + "Table_Buffer": list(record_byte_array[8:]) }) # Check last failed command count was 2 and that it was Validate_Parameter_Table with Status LENGTH_ERROR: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 2", 3) @@ -81,36 +76,31 @@ # Check Last_Validation_Version, Crc_Table, and Last_Validation_Status: check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'LENGTH_ERROR'") check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Version == 0.00") - check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == " + str(Int_CRC)) + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == " + str(record_crc)) print("Validate_Parameter_Table last Status LENGTH_ERROR OK") # Send test Validate_Parameter_Table command with nominal values, and Osc_A_Freq = 999.0 to trigger the user implemented Validate_Parameters # function, expecting Parameter_Validation_Failed, Parameter_Table_Copy_Failure, Table_Validation_Failure, and Command_Execution_Failure # Rebuild the parameter table using known invalid Osc_A_Freq value: - # Osc_A_Freq - Test_Packed_Table = bytearray(struct.pack(">f", 999.0)) - # Osc_A_Amp - Test_Packed_Table += bytearray(struct.pack(">f", 5.00)) - # Osc_A_Off - Test_Packed_Table += bytearray(struct.pack(">f", 2.50)) - # Osc_B_Freq - Test_Packed_Table += bytearray(struct.pack(">f", 0.30)) - # Osc_B_Amp - Test_Packed_Table += bytearray(struct.pack(">f", -5.00)) - # Osc_B_Off - Test_Packed_Table += bytearray(struct.pack(">f", -2.50)) - # Get table length: - Table_Length = len(Test_Packed_Table) - # Append table to Version and get CRC - CRC_Packed_Table = bytearray(struct.pack(">f", 0.0)) - CRC_Packed_Table += Test_Packed_Table - Test_CRC = crc_16.crc_16(CRC_Packed_Table) - Int_CRC = int.from_bytes(Test_CRC, 'big') + # Build a parameter table using the Adamant packed record definitions: + record = Table_Record.Linux_Example_Parameter_Table_Record( + Crc_Calculated=0, + Header=Table_Record.Parameter_Table_Header(), + Oscillator_A_Frequency=Table_Record.Packed_F32(999.0), + Oscillator_A_Amplitude=Table_Record.Packed_F32(5.00), + Oscillator_A_Offset=Table_Record.Packed_F32(2.50), + Oscillator_B_Frequency=Table_Record.Packed_F32(0.30), + Oscillator_B_Amplitude=Table_Record.Packed_F32(-5.00), + Oscillator_B_Offset=Table_Record.Packed_F32(-2.50) + ) + record_byte_array = record._to_byte_array().tobytes() + record_len = len(record_byte_array[8:]) + record_crc = int.from_bytes(crc_16.crc_16(record_byte_array[4:]), 'big') cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { - "Header.Table_Buffer_Length": Table_Length, - "Header.Crc_Table": Int_CRC, - "Table_Buffer": list(Test_Packed_Table) + "Header.Table_Buffer_Length": record_len, + "Header.Crc_Table": record_crc, + "Table_Buffer": list(record_byte_array[8:]) }) # Check last failed command count was 3 and that it was Validate_Parameter_Table with Status PARAMETER_ERROR: wait_check("Linux_Example Software_Status_Packet Command_Router_Instance.Command_Failure_Count.Value == 3", 3) @@ -120,5 +110,5 @@ # Check Last_Validation_Version, Crc_Table, and Last_Validation_Status: check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'PARAMETER_ERROR'") check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Version == 0.00") - check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == " + str(Int_CRC)) + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == " + str(record_crc)) print("Validate_Parameter_Table last Status PARAMETER_ERROR OK") From 42948d8cea797db68d31707beb117741cd022fcc Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Sat, 21 Sep 2024 16:15:15 -0600 Subject: [PATCH 17/20] Modify scripts to handle type dependencies for COSMOS test scripts --- gnd/cosmos/build_cosmos_plugin.sh | 8 ++++++++ gnd/cosmos/install_cosmos_plugin.sh | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/gnd/cosmos/build_cosmos_plugin.sh b/gnd/cosmos/build_cosmos_plugin.sh index 33fb411..88a4f6a 100755 --- a/gnd/cosmos/build_cosmos_plugin.sh +++ b/gnd/cosmos/build_cosmos_plugin.sh @@ -9,4 +9,12 @@ assembly_dir=$1 cd $assembly_dir plugin=`redo what 2>&1 | grep "cosmos" | awk '{ print $2 }'` echo $plugin | xargs redo-ifchange +record_type=`redo what 2>&1 | grep "parameter_table_record.py" | awk '{ print $2 }'` +echo $record_type | xargs redo-ifchange +cd '../../../../adamant/src/types/parameter' +record_type=`redo what 2>&1 | grep "parameter_table_header.py" | awk '{ print $2 }'` +echo $record_type | xargs redo-ifchange +cd '../packed_types' +record_type=`redo what 2>&1 | grep "packed_f32.py" | awk '{ print $2 }'` +echo $record_type | xargs redo-ifchange cd - >/dev/null diff --git a/gnd/cosmos/install_cosmos_plugin.sh b/gnd/cosmos/install_cosmos_plugin.sh index cf90d42..f9329f9 100755 --- a/gnd/cosmos/install_cosmos_plugin.sh +++ b/gnd/cosmos/install_cosmos_plugin.sh @@ -35,6 +35,7 @@ adamant_assembly_name_upper=$(tr [:lower:] [:upper:] <<< "$adamant_assembly_name adamant_assembly_cmdtlm_dir=`realpath $adamant_assembly_dir/build/cosmos/plugin` adamant_assembly_plugin_dir=`realpath $adamant_assembly_dir/main/cosmos/plugin` adamant_protocol_dir=`realpath $this_dir/../../../adamant/gnd/cosmos` +adamant_dir=`realpath $this_dir/../../../adamant` # Copy all protocol files (plugins compile with only needed protocols): echo "Copying over plugin files..." @@ -59,6 +60,11 @@ do_copy "$adamant_script_dir/update-param-sys.py" $cosmos_script_dir/update-para do_copy "$adamant_script_dir/validate-param-sys.py" $cosmos_script_dir/validate-param-sys.py do_copy "$adamant_script_dir/test_setup.py" $cosmos_script_dir/test_setup.py do_copy "$adamant_script_dir/crc_16.py" $cosmos_script_dir/crc_16.py +do_copy "$adamant_assembly_dir/build/py/${adamant_assembly_name}_parameter_table_record.py" $cosmos_script_dir/${adamant_assembly_name}_parameter_table_record.py +mkdir -p $cosmos_script_dir/base_classes +do_copy "$adamant_dir/src/types/parameter/build/py/parameter_table_header.py" $cosmos_script_dir/parameter_table_header.py +do_copy "$adamant_dir/src/types/packed_types/build/py/packed_f32.py" $cosmos_script_dir/packed_f32.py +do_copy "$adamant_dir/gnd/base_classes/packed_type_base.py" $cosmos_script_dir/base_classes/packed_type_base.py echo "Success." echo "Plugin files copied to $cosmos_plugin_dir." echo "Script files copied to $cosmos_script_dir." From 84d2ca97a379b45b6513649529bdee7312d4c31e Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Sat, 21 Sep 2024 16:18:46 -0600 Subject: [PATCH 18/20] Modify setup script to copy crc_16.py from Adamant --- gnd/cosmos/install_cosmos_plugin.sh | 2 +- test/scripts/crc_16.py | 74 ----------------------------- 2 files changed, 1 insertion(+), 75 deletions(-) delete mode 100644 test/scripts/crc_16.py diff --git a/gnd/cosmos/install_cosmos_plugin.sh b/gnd/cosmos/install_cosmos_plugin.sh index f9329f9..8021d52 100755 --- a/gnd/cosmos/install_cosmos_plugin.sh +++ b/gnd/cosmos/install_cosmos_plugin.sh @@ -59,12 +59,12 @@ do_copy "$adamant_assembly_plugin_dir/plugin.txt" $cosmos_plugin_dir/plugin.txt do_copy "$adamant_script_dir/update-param-sys.py" $cosmos_script_dir/update-param-sys.py do_copy "$adamant_script_dir/validate-param-sys.py" $cosmos_script_dir/validate-param-sys.py do_copy "$adamant_script_dir/test_setup.py" $cosmos_script_dir/test_setup.py -do_copy "$adamant_script_dir/crc_16.py" $cosmos_script_dir/crc_16.py do_copy "$adamant_assembly_dir/build/py/${adamant_assembly_name}_parameter_table_record.py" $cosmos_script_dir/${adamant_assembly_name}_parameter_table_record.py mkdir -p $cosmos_script_dir/base_classes do_copy "$adamant_dir/src/types/parameter/build/py/parameter_table_header.py" $cosmos_script_dir/parameter_table_header.py do_copy "$adamant_dir/src/types/packed_types/build/py/packed_f32.py" $cosmos_script_dir/packed_f32.py do_copy "$adamant_dir/gnd/base_classes/packed_type_base.py" $cosmos_script_dir/base_classes/packed_type_base.py +do_copy "$adamant_dir/gnd/util/crc_16.py" $cosmos_script_dir/crc_16.py echo "Success." echo "Plugin files copied to $cosmos_plugin_dir." echo "Script files copied to $cosmos_script_dir." diff --git a/test/scripts/crc_16.py b/test/scripts/crc_16.py deleted file mode 100644 index 9a04b73..0000000 --- a/test/scripts/crc_16.py +++ /dev/null @@ -1,74 +0,0 @@ -_low_crc = [ - 0x00, 0x21, 0x42, 0x63, 0x84, 0xa5, 0xc6, 0xe7, 0x08, 0x29, 0x4a, 0x6b, 0x8c, - 0xad, 0xce, 0xef, 0x31, 0x10, 0x73, 0x52, 0xb5, 0x94, 0xf7, 0xd6, 0x39, 0x18, - 0x7b, 0x5a, 0xbd, 0x9c, 0xff, 0xde, 0x62, 0x43, 0x20, 0x01, 0xe6, 0xc7, 0xa4, - 0x85, 0x6a, 0x4b, 0x28, 0x09, 0xee, 0xcf, 0xac, 0x8d, 0x53, 0x72, 0x11, 0x30, - 0xd7, 0xf6, 0x95, 0xb4, 0x5b, 0x7a, 0x19, 0x38, 0xdf, 0xfe, 0x9d, 0xbc, 0xc4, - 0xe5, 0x86, 0xa7, 0x40, 0x61, 0x02, 0x23, 0xcc, 0xed, 0x8e, 0xaf, 0x48, 0x69, - 0x0a, 0x2b, 0xf5, 0xd4, 0xb7, 0x96, 0x71, 0x50, 0x33, 0x12, 0xfd, 0xdc, 0xbf, - 0x9e, 0x79, 0x58, 0x3b, 0x1a, 0xa6, 0x87, 0xe4, 0xc5, 0x22, 0x03, 0x60, 0x41, - 0xae, 0x8f, 0xec, 0xcd, 0x2a, 0x0b, 0x68, 0x49, 0x97, 0xb6, 0xd5, 0xf4, 0x13, - 0x32, 0x51, 0x70, 0x9f, 0xbe, 0xdd, 0xfc, 0x1b, 0x3a, 0x59, 0x78, 0x88, 0xa9, - 0xca, 0xeb, 0x0c, 0x2d, 0x4e, 0x6f, 0x80, 0xa1, 0xc2, 0xe3, 0x04, 0x25, 0x46, - 0x67, 0xb9, 0x98, 0xfb, 0xda, 0x3d, 0x1c, 0x7f, 0x5e, 0xb1, 0x90, 0xf3, 0xd2, - 0x35, 0x14, 0x77, 0x56, 0xea, 0xcb, 0xa8, 0x89, 0x6e, 0x4f, 0x2c, 0x0d, 0xe2, - 0xc3, 0xa0, 0x81, 0x66, 0x47, 0x24, 0x05, 0xdb, 0xfa, 0x99, 0xb8, 0x5f, 0x7e, - 0x1d, 0x3c, 0xd3, 0xf2, 0x91, 0xb0, 0x57, 0x76, 0x15, 0x34, 0x4c, 0x6d, 0x0e, - 0x2f, 0xc8, 0xe9, 0x8a, 0xab, 0x44, 0x65, 0x06, 0x27, 0xc0, 0xe1, 0x82, 0xa3, - 0x7d, 0x5c, 0x3f, 0x1e, 0xf9, 0xd8, 0xbb, 0x9a, 0x75, 0x54, 0x37, 0x16, 0xf1, - 0xd0, 0xb3, 0x92, 0x2e, 0x0f, 0x6c, 0x4d, 0xaa, 0x8b, 0xe8, 0xc9, 0x26, 0x07, - 0x64, 0x45, 0xa2, 0x83, 0xe0, 0xc1, 0x1f, 0x3e, 0x5d, 0x7c, 0x9b, 0xba, 0xd9, - 0xf8, 0x17, 0x36, 0x55, 0x74, 0x93, 0xb2, 0xd1, 0xf0 -] - -_high_crc = [ - 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x81, 0x91, 0xa1, 0xb1, 0xc1, - 0xd1, 0xe1, 0xf1, 0x12, 0x02, 0x32, 0x22, 0x52, 0x42, 0x72, 0x62, 0x93, 0x83, - 0xb3, 0xa3, 0xd3, 0xc3, 0xf3, 0xe3, 0x24, 0x34, 0x04, 0x14, 0x64, 0x74, 0x44, - 0x54, 0xa5, 0xb5, 0x85, 0x95, 0xe5, 0xf5, 0xc5, 0xd5, 0x36, 0x26, 0x16, 0x06, - 0x76, 0x66, 0x56, 0x46, 0xb7, 0xa7, 0x97, 0x87, 0xf7, 0xe7, 0xd7, 0xc7, 0x48, - 0x58, 0x68, 0x78, 0x08, 0x18, 0x28, 0x38, 0xc9, 0xd9, 0xe9, 0xf9, 0x89, 0x99, - 0xa9, 0xb9, 0x5a, 0x4a, 0x7a, 0x6a, 0x1a, 0x0a, 0x3a, 0x2a, 0xdb, 0xcb, 0xfb, - 0xeb, 0x9b, 0x8b, 0xbb, 0xab, 0x6c, 0x7c, 0x4c, 0x5c, 0x2c, 0x3c, 0x0c, 0x1c, - 0xed, 0xfd, 0xcd, 0xdd, 0xad, 0xbd, 0x8d, 0x9d, 0x7e, 0x6e, 0x5e, 0x4e, 0x3e, - 0x2e, 0x1e, 0x0e, 0xff, 0xef, 0xdf, 0xcf, 0xbf, 0xaf, 0x9f, 0x8f, 0x91, 0x81, - 0xb1, 0xa1, 0xd1, 0xc1, 0xf1, 0xe1, 0x10, 0x00, 0x30, 0x20, 0x50, 0x40, 0x70, - 0x60, 0x83, 0x93, 0xa3, 0xb3, 0xc3, 0xd3, 0xe3, 0xf3, 0x02, 0x12, 0x22, 0x32, - 0x42, 0x52, 0x62, 0x72, 0xb5, 0xa5, 0x95, 0x85, 0xf5, 0xe5, 0xd5, 0xc5, 0x34, - 0x24, 0x14, 0x04, 0x74, 0x64, 0x54, 0x44, 0xa7, 0xb7, 0x87, 0x97, 0xe7, 0xf7, - 0xc7, 0xd7, 0x26, 0x36, 0x06, 0x16, 0x66, 0x76, 0x46, 0x56, 0xd9, 0xc9, 0xf9, - 0xe9, 0x99, 0x89, 0xb9, 0xa9, 0x58, 0x48, 0x78, 0x68, 0x18, 0x08, 0x38, 0x28, - 0xcb, 0xdb, 0xeb, 0xfb, 0x8b, 0x9b, 0xab, 0xbb, 0x4a, 0x5a, 0x6a, 0x7a, 0x0a, - 0x1a, 0x2a, 0x3a, 0xfd, 0xed, 0xdd, 0xcd, 0xbd, 0xad, 0x9d, 0x8d, 0x7c, 0x6c, - 0x5c, 0x4c, 0x3c, 0x2c, 0x1c, 0x0c, 0xef, 0xff, 0xcf, 0xdf, 0xaf, 0xbf, 0x8f, - 0x9f, 0x6e, 0x7e, 0x4e, 0x5e, 0x2e, 0x3e, 0x0e, 0x1e -] - - -def crc_16(byte_array, seed=[0xFF, 0xFF]): - """ - - 16-bit CRC: - Uses CCITT CRC polynomial: X^16 + X^12 + X^5 + 1. - The accepted start value is 0xffff. - - """ - high_parity = seed[0] - low_parity = seed[1] - for byte in list(byte_array): - k = byte ^ high_parity - high_parity = low_parity ^ _high_crc[k] - low_parity = _low_crc[k] - return [high_parity, low_parity] - - -def checksum_16(byte_array, seed=[0x00, 0x00]): - """Simple 16-bit checksum.""" - assert ( - len(byte_array) % 2 == 0 - ), "Checksum 16 only works on even numbered byte arrays" - csum = seed[0] * 0x100 + seed[1] - for i in range(0, len(byte_array), 2): - csum += byte_array[i] * 0x100 + byte_array[i + 1] - csum %= 0x10000 - return [int(csum / 0x100), csum % 0x100] From b97401539f9bb9c7c9d66a9de2c7618a5faf036f Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Sat, 21 Sep 2024 19:32:02 -0600 Subject: [PATCH 19/20] Modify `update-param-sys.py` to use Adamant defs when checking dumped parameter table --- test/scripts/update-param-sys.py | 27 +++++++++++++++------------ test/scripts/validate-param-sys.py | 18 ++++++++++-------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/test/scripts/update-param-sys.py b/test/scripts/update-param-sys.py index 7155480..29ce964 100644 --- a/test/scripts/update-param-sys.py +++ b/test/scripts/update-param-sys.py @@ -1,7 +1,7 @@ ######################################################################## # This script is designed to function with OpenC3 COSMOS's Script Runner ######################################################################## -import struct, sys +import struct, sys, bitstring sys.path.append('/plugins/DEFAULT/targets_modified') import crc_16 import test_setup @@ -17,21 +17,23 @@ record = Table_Record.Linux_Example_Parameter_Table_Record( Crc_Calculated=0, Header=Table_Record.Parameter_Table_Header(), - Oscillator_A_Frequency=Table_Record.Packed_F32(0.30), + Oscillator_A_Frequency=Table_Record.Packed_F32(0.25), Oscillator_A_Amplitude=Table_Record.Packed_F32(5.00), Oscillator_A_Offset=Table_Record.Packed_F32(2.50), - Oscillator_B_Frequency=Table_Record.Packed_F32(0.30), + Oscillator_B_Frequency=Table_Record.Packed_F32(0.25), Oscillator_B_Amplitude=Table_Record.Packed_F32(-5.00), Oscillator_B_Offset=Table_Record.Packed_F32(-2.50) ) record_byte_array = record._to_byte_array().tobytes() + record.Crc_Calculated = int.from_bytes(crc_16.crc_16(record_byte_array[4:])) + record.Header.Crc_Table = record.Crc_Calculated + record.Header.Version = 0.0 record_len = len(record_byte_array[8:]) - record_crc = int.from_bytes(crc_16.crc_16(record_byte_array[4:]), 'big') # Send nominal Update_Parameter_Table command expecting success: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { "Header.Table_Buffer_Length": record_len, - "Header.Crc_Table": record_crc, + "Header.Crc_Table": record.Crc_Calculated, "Table_Buffer": list(record_byte_array[8:]) }) # Check successful command count is 3 and that it was Update_Parameter_Table: @@ -57,7 +59,7 @@ # Working_Table_Update_Failure, and Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Update_Parameter_Table", { "Header.Table_Buffer_Length": record_len + 1, - "Header.Crc_Table": record_crc, + "Header.Crc_Table": record.Crc_Calculated, "Table_Buffer": list(record_byte_array[8:]) }) # Check last failed command count was 2 and that it was Update_Parameter_Table with Status FAILURE: @@ -74,9 +76,10 @@ check("Linux_Example Software_Status_Packet Command_Router_Instance.Last_Successful_Command.Id == 30") Active_Parameters_Buffer = get_tlm_buffer("Linux_Example Active_Parameters") Buffer = Active_Parameters_Buffer['buffer'] - # Check CRC - if list(Buffer[16:18]) == record_crc: - print("Dump_Parameters CRC OK") - # Check Active_Parameters table buffer: - if Buffer[18:46] == list(record_byte_array[8:]): - print("Dump_Parameters values OK") + # Check dumped record against the original sent record: + dump_record = Table_Record.Linux_Example_Parameter_Table_Record() + dump_record._from_byte_array(bitstring.ConstBitStream(Buffer[14:])) + print(record.to_tuple_string()) + print(dump_record.to_tuple_string()) + if dump_record == record: + print("Dump_Parameters match OK") diff --git a/test/scripts/validate-param-sys.py b/test/scripts/validate-param-sys.py index 3dc5713..63b2e3c 100644 --- a/test/scripts/validate-param-sys.py +++ b/test/scripts/validate-param-sys.py @@ -25,13 +25,14 @@ Oscillator_B_Offset=Table_Record.Packed_F32(-2.50) ) record_byte_array = record._to_byte_array().tobytes() + record.Crc_Calculated = int.from_bytes(crc_16.crc_16(record_byte_array[4:])) + record.Header.Crc_Table = record.Crc_Calculated record_len = len(record_byte_array[8:]) - record_crc = int.from_bytes(crc_16.crc_16(record_byte_array[4:]), 'big') # Send nominal Validate_Parameter_Table command expecting success: cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { "Header.Table_Buffer_Length": record_len, - "Header.Crc_Table": record_crc, + "Header.Crc_Table": record.Crc_Calculated, "Table_Buffer": list(record_byte_array[8:]) }) # Check successful command count is 3 and that it was Validate_Parameter_Table with Status SUCCESS: @@ -40,7 +41,7 @@ # Check Last_Validation_Version, Crc_Table, and Last_Validation_Status: check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'SUCCESS'") check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Version == 0.00") - check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == " + str(record_crc)) + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == " + str(record.Crc_Calculated)) print("Validate_Parameter_Table SUCCESS OK") # Send test Validate_Parameter_Table command with bad CRC expecting Memory_Region_Crc_Invalid, Table_Validation_Failure, and @@ -65,7 +66,7 @@ # Command_Execution_Failure: cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { "Header.Table_Buffer_Length": record_len + 1, - "Header.Crc_Table": record_crc, + "Header.Crc_Table": record.Crc_Calculated, "Table_Buffer": list(record_byte_array[8:]) }) # Check last failed command count was 2 and that it was Validate_Parameter_Table with Status LENGTH_ERROR: @@ -76,7 +77,7 @@ # Check Last_Validation_Version, Crc_Table, and Last_Validation_Status: check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'LENGTH_ERROR'") check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Version == 0.00") - check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == " + str(record_crc)) + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == " + str(record.Crc_Calculated)) print("Validate_Parameter_Table last Status LENGTH_ERROR OK") # Send test Validate_Parameter_Table command with nominal values, and Osc_A_Freq = 999.0 to trigger the user implemented Validate_Parameters @@ -94,12 +95,13 @@ Oscillator_B_Offset=Table_Record.Packed_F32(-2.50) ) record_byte_array = record._to_byte_array().tobytes() + record.Crc_Calculated = int.from_bytes(crc_16.crc_16(record_byte_array[4:])) + record.Header.Crc_Table = record.Crc_Calculated record_len = len(record_byte_array[8:]) - record_crc = int.from_bytes(crc_16.crc_16(record_byte_array[4:]), 'big') cmd("Linux_Example", "Parameter_Manager_Instance-Validate_Parameter_Table", { "Header.Table_Buffer_Length": record_len, - "Header.Crc_Table": record_crc, + "Header.Crc_Table": record.Crc_Calculated, "Table_Buffer": list(record_byte_array[8:]) }) # Check last failed command count was 3 and that it was Validate_Parameter_Table with Status PARAMETER_ERROR: @@ -110,5 +112,5 @@ # Check Last_Validation_Version, Crc_Table, and Last_Validation_Status: check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Status == 'PARAMETER_ERROR'") check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Last_Validation_Version == 0.00") - check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == " + str(record_crc)) + check("Linux_Example Software_Status_Packet Parameter_Manager_Instance.Validation_Status.Crc_Table == " + str(record.Crc_Calculated)) print("Validate_Parameter_Table last Status PARAMETER_ERROR OK") From 4bf8cbfcb5c441afbadcb74a6eb1686477592183 Mon Sep 17 00:00:00 2001 From: Jacob Seman <90524106+Jbsco@users.noreply.github.com> Date: Sat, 21 Sep 2024 19:53:45 -0600 Subject: [PATCH 20/20] Remove errant log --- src/assembly/linux/1 | 508 ------------------------------------------- 1 file changed, 508 deletions(-) delete mode 100644 src/assembly/linux/1 diff --git a/src/assembly/linux/1 b/src/assembly/linux/1 deleted file mode 100644 index 82593e5..0000000 --- a/src/assembly/linux/1 +++ /dev/null @@ -1,508 +0,0 @@ -redo what  -redo all -redo clean -redo clean_all -redo clear_cache -redo templates -redo publish -redo targets -redo prove -redo analyze -redo style -redo pretty -redo test_all -redo coverage_all -redo style_all -redo build/bin/Linux/linux_example_command_sequencer_details_packet_type_type_ranges.elf -redo build/bin/Linux/linux_example_command_sequencer_summary_packet_type_type_ranges.elf -redo build/bin/Linux/linux_example_cpu_monitor_packet_type_type_ranges.elf -redo build/bin/Linux/linux_example_fault_responses_packed_id_type_type_ranges.elf -redo build/bin/Linux/linux_example_fault_responses_status_record_type_ranges.elf -redo build/bin/Linux/linux_example_parameter_table_record_type_ranges.elf -redo build/bin/Linux/linux_example_queue_monitor_packet_type_type_ranges.elf -redo build/bin/Linux/linux_example_stack_monitor_packet_type_type_ranges.elf -redo build/bin/Linux/linux_example_task_watchdog_list_state_record_type_ranges.elf -redo build/bin/Linux/linux_example_task_watchdog_list_watchdog_action_cmd_type_ranges.elf -redo build/bin/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd_type_ranges.elf -redo build/cosmos/plugin/linux_example_ccsds_cosmos_commands.txt -redo build/cosmos/plugin/linux_example_ccsds_cosmos_telemetry.txt -redo build/dot/linux_example.dot -redo build/eps/linux_example.eps -redo build/html/linux_example_arrayed_connections.html -redo build/html/linux_example_command_sequencer_details_packet_type.html -redo build/html/linux_example_command_sequencer_summary_packet_type.html -redo build/html/linux_example_commands.html -redo build/html/linux_example_components.html -redo build/html/linux_example_connections.html -redo build/html/linux_example_cpu_monitor_packet_type.html -redo build/html/linux_example_data_dependencies.html -redo build/html/linux_example_data_products.html -redo build/html/linux_example_events.html -redo build/html/linux_example_fault_responses_enums.html -redo build/html/linux_example_fault_responses_packed_id_type.html -redo build/html/linux_example_fault_responses_status_record.html -redo build/html/linux_example_faults.html -redo build/html/linux_example_interrupts.html -redo build/html/linux_example_packets.html -redo build/html/linux_example_parameter_table_record.html -redo build/html/linux_example_parameters.html -redo build/html/linux_example_priorities.html -redo build/html/linux_example_product_packets.html -redo build/html/linux_example_queue_monitor_packet_type.html -redo build/html/linux_example_queues.html -redo build/html/linux_example_seq.html -redo build/html/linux_example_stack_monitor_packet_type.html -redo build/html/linux_example_task_watchdog_list_state_record.html -redo build/html/linux_example_task_watchdog_list_watchdog_action_cmd.html -redo build/html/linux_example_task_watchdog_list_watchdog_limit_cmd.html -redo build/hydra/Config/linux_example.xml -redo build/hydra/Config/linux_example_ccsds_commands.xml -redo build/hydra/Config/linux_example_ccsds_packets.xml -redo build/hydra/Pages/linux_example_cpu_monitor.xml -redo build/hydra/Pages/linux_example_parameter_table.xml -redo build/hydra/Pages/linux_example_queue_monitor.xml -redo build/hydra/Pages/linux_example_stack_monitor.xml -redo build/hydra/Scripts/linux_example_packet_pages.prc -redo build/m/Linux_Example_Command_Sequencer_Details_Packet_Type.m -redo build/m/Linux_Example_Command_Sequencer_Summary_Packet_Type.m -redo build/m/Linux_Example_Cpu_Monitor_Packet_Type.m -redo build/m/Linux_Example_Fault_Responses_Enums -redo build/m/Linux_Example_Fault_Responses_Packed_Id_Type.m -redo build/m/Linux_Example_Fault_Responses_Status_Record.m -redo build/m/Linux_Example_Parameter_Table_Record.m -redo build/m/Linux_Example_Queue_Monitor_Packet_Type.m -redo build/m/Linux_Example_Stack_Monitor_Packet_Type.m -redo build/m/Linux_Example_Task_Watchdog_List_State_Record.m -redo build/m/Linux_Example_Task_Watchdog_List_Watchdog_Action_Cmd.m -redo build/m/Linux_Example_Task_Watchdog_List_Watchdog_Limit_Cmd.m -redo build/m/linux_example_events.m -redo build/metric/Linux/linux_example.adb.txt -redo build/metric/Linux/linux_example.ads.txt -redo build/metric/Linux/linux_example_command_sequencer_details_packet_type-assertion.adb.txt -redo build/metric/Linux/linux_example_command_sequencer_details_packet_type-assertion.ads.txt -redo build/metric/Linux/linux_example_command_sequencer_details_packet_type-c.ads.txt -redo build/metric/Linux/linux_example_command_sequencer_details_packet_type-representation.adb.txt -redo build/metric/Linux/linux_example_command_sequencer_details_packet_type-representation.ads.txt -redo build/metric/Linux/linux_example_command_sequencer_details_packet_type-validation.adb.txt -redo build/metric/Linux/linux_example_command_sequencer_details_packet_type-validation.ads.txt -redo build/metric/Linux/linux_example_command_sequencer_details_packet_type.adb.txt -redo build/metric/Linux/linux_example_command_sequencer_details_packet_type.ads.txt -redo build/metric/Linux/linux_example_command_sequencer_details_packet_type_type_ranges.adb.txt -redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type-assertion.adb.txt -redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type-assertion.ads.txt -redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type-c.ads.txt -redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type-representation.adb.txt -redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type-representation.ads.txt -redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type-validation.adb.txt -redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type-validation.ads.txt -redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type.adb.txt -redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type.ads.txt -redo build/metric/Linux/linux_example_command_sequencer_summary_packet_type_type_ranges.adb.txt -redo build/metric/Linux/linux_example_commands.ads.txt -redo build/metric/Linux/linux_example_cpu_monitor_packet_type-assertion.adb.txt -redo build/metric/Linux/linux_example_cpu_monitor_packet_type-assertion.ads.txt -redo build/metric/Linux/linux_example_cpu_monitor_packet_type-c.ads.txt -redo build/metric/Linux/linux_example_cpu_monitor_packet_type-representation.adb.txt -redo build/metric/Linux/linux_example_cpu_monitor_packet_type-representation.ads.txt -redo build/metric/Linux/linux_example_cpu_monitor_packet_type-validation.adb.txt -redo build/metric/Linux/linux_example_cpu_monitor_packet_type-validation.ads.txt -redo build/metric/Linux/linux_example_cpu_monitor_packet_type.adb.txt -redo build/metric/Linux/linux_example_cpu_monitor_packet_type.ads.txt -redo build/metric/Linux/linux_example_cpu_monitor_packet_type_type_ranges.adb.txt -redo build/metric/Linux/linux_example_data_dependencies.ads.txt -redo build/metric/Linux/linux_example_data_products.ads.txt -redo build/metric/Linux/linux_example_event_to_text.adb.txt -redo build/metric/Linux/linux_example_event_to_text.ads.txt -redo build/metric/Linux/linux_example_events.ads.txt -redo build/metric/Linux/linux_example_fault_responses.ads.txt -redo build/metric/Linux/linux_example_fault_responses_enums-assertion.ads.txt -redo build/metric/Linux/linux_example_fault_responses_enums-representation.adb.txt -redo build/metric/Linux/linux_example_fault_responses_enums-representation.ads.txt -redo build/metric/Linux/linux_example_fault_responses_enums.ads.txt -redo build/metric/Linux/linux_example_fault_responses_packed_id_type-assertion.adb.txt -redo build/metric/Linux/linux_example_fault_responses_packed_id_type-assertion.ads.txt -redo build/metric/Linux/linux_example_fault_responses_packed_id_type-c.ads.txt -redo build/metric/Linux/linux_example_fault_responses_packed_id_type-representation.adb.txt -redo build/metric/Linux/linux_example_fault_responses_packed_id_type-representation.ads.txt -redo build/metric/Linux/linux_example_fault_responses_packed_id_type-validation.adb.txt -redo build/metric/Linux/linux_example_fault_responses_packed_id_type-validation.ads.txt -redo build/metric/Linux/linux_example_fault_responses_packed_id_type.adb.txt -redo build/metric/Linux/linux_example_fault_responses_packed_id_type.ads.txt -redo build/metric/Linux/linux_example_fault_responses_packed_id_type_type_ranges.adb.txt -redo build/metric/Linux/linux_example_fault_responses_status_record-assertion.adb.txt -redo build/metric/Linux/linux_example_fault_responses_status_record-assertion.ads.txt -redo build/metric/Linux/linux_example_fault_responses_status_record-c.ads.txt -redo build/metric/Linux/linux_example_fault_responses_status_record-representation.adb.txt -redo build/metric/Linux/linux_example_fault_responses_status_record-representation.ads.txt -redo build/metric/Linux/linux_example_fault_responses_status_record-validation.adb.txt -redo build/metric/Linux/linux_example_fault_responses_status_record-validation.ads.txt -redo build/metric/Linux/linux_example_fault_responses_status_record.adb.txt -redo build/metric/Linux/linux_example_fault_responses_status_record.ads.txt -redo build/metric/Linux/linux_example_fault_responses_status_record_type_ranges.adb.txt -redo build/metric/Linux/linux_example_faults.ads.txt -redo build/metric/Linux/linux_example_packets.ads.txt -redo build/metric/Linux/linux_example_parameter_table.ads.txt -redo build/metric/Linux/linux_example_parameter_table_record-assertion.adb.txt -redo build/metric/Linux/linux_example_parameter_table_record-assertion.ads.txt -redo build/metric/Linux/linux_example_parameter_table_record-c.ads.txt -redo build/metric/Linux/linux_example_parameter_table_record-representation.adb.txt -redo build/metric/Linux/linux_example_parameter_table_record-representation.ads.txt -redo build/metric/Linux/linux_example_parameter_table_record-validation.adb.txt -redo build/metric/Linux/linux_example_parameter_table_record-validation.ads.txt -redo build/metric/Linux/linux_example_parameter_table_record.adb.txt -redo build/metric/Linux/linux_example_parameter_table_record.ads.txt -redo build/metric/Linux/linux_example_parameter_table_record_type_ranges.adb.txt -redo build/metric/Linux/linux_example_parameters.ads.txt -redo build/metric/Linux/linux_example_product_packets.ads.txt -redo build/metric/Linux/linux_example_queue_monitor_packet_type-assertion.adb.txt -redo build/metric/Linux/linux_example_queue_monitor_packet_type-assertion.ads.txt -redo build/metric/Linux/linux_example_queue_monitor_packet_type-c.ads.txt -redo build/metric/Linux/linux_example_queue_monitor_packet_type-representation.adb.txt -redo build/metric/Linux/linux_example_queue_monitor_packet_type-representation.ads.txt -redo build/metric/Linux/linux_example_queue_monitor_packet_type-validation.adb.txt -redo build/metric/Linux/linux_example_queue_monitor_packet_type-validation.ads.txt -redo build/metric/Linux/linux_example_queue_monitor_packet_type.adb.txt -redo build/metric/Linux/linux_example_queue_monitor_packet_type.ads.txt -redo build/metric/Linux/linux_example_queue_monitor_packet_type_type_ranges.adb.txt -redo build/metric/Linux/linux_example_stack_monitor_packet_type-assertion.adb.txt -redo build/metric/Linux/linux_example_stack_monitor_packet_type-assertion.ads.txt -redo build/metric/Linux/linux_example_stack_monitor_packet_type-c.ads.txt -redo build/metric/Linux/linux_example_stack_monitor_packet_type-representation.adb.txt -redo build/metric/Linux/linux_example_stack_monitor_packet_type-representation.ads.txt -redo build/metric/Linux/linux_example_stack_monitor_packet_type-validation.adb.txt -redo build/metric/Linux/linux_example_stack_monitor_packet_type-validation.ads.txt -redo build/metric/Linux/linux_example_stack_monitor_packet_type.adb.txt -redo build/metric/Linux/linux_example_stack_monitor_packet_type.ads.txt -redo build/metric/Linux/linux_example_stack_monitor_packet_type_type_ranges.adb.txt -redo build/metric/Linux/linux_example_task_watchdog_list.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_state_record-assertion.adb.txt -redo build/metric/Linux/linux_example_task_watchdog_list_state_record-assertion.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_state_record-c.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_state_record-representation.adb.txt -redo build/metric/Linux/linux_example_task_watchdog_list_state_record-representation.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_state_record-validation.adb.txt -redo build/metric/Linux/linux_example_task_watchdog_list_state_record-validation.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_state_record.adb.txt -redo build/metric/Linux/linux_example_task_watchdog_list_state_record.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_state_record_type_ranges.adb.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-assertion.adb.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-assertion.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-c.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-representation.adb.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-representation.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-validation.adb.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-validation.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd.adb.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_action_cmd_type_ranges.adb.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-assertion.adb.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-assertion.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-c.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-representation.adb.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-representation.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-validation.adb.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-validation.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd.adb.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd.ads.txt -redo build/metric/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd_type_ranges.adb.txt -redo build/metric/Linux/memory_map.ads.txt -redo build/metric/Linux/memory_map.o.txt -redo build/metric/Linux/start_up.adb.txt -redo build/metric/Linux/start_up.ads.txt -redo build/metric/Linux/start_up.o.txt -redo build/obj/Linux/linux_example.o -redo build/obj/Linux/linux_example_command_sequencer_details_packet_type-assertion.o -redo build/obj/Linux/linux_example_command_sequencer_details_packet_type-c.o -redo build/obj/Linux/linux_example_command_sequencer_details_packet_type-representation.o -redo build/obj/Linux/linux_example_command_sequencer_details_packet_type-validation.o -redo build/obj/Linux/linux_example_command_sequencer_details_packet_type.o -redo build/obj/Linux/linux_example_command_sequencer_details_packet_type_type_ranges.o -redo build/obj/Linux/linux_example_command_sequencer_summary_packet_type-assertion.o -redo build/obj/Linux/linux_example_command_sequencer_summary_packet_type-c.o -redo build/obj/Linux/linux_example_command_sequencer_summary_packet_type-representation.o -redo build/obj/Linux/linux_example_command_sequencer_summary_packet_type-validation.o -redo build/obj/Linux/linux_example_command_sequencer_summary_packet_type.o -redo build/obj/Linux/linux_example_command_sequencer_summary_packet_type_type_ranges.o -redo build/obj/Linux/linux_example_commands.o -redo build/obj/Linux/linux_example_cpu_monitor_packet_type-assertion.o -redo build/obj/Linux/linux_example_cpu_monitor_packet_type-c.o -redo build/obj/Linux/linux_example_cpu_monitor_packet_type-representation.o -redo build/obj/Linux/linux_example_cpu_monitor_packet_type-validation.o -redo build/obj/Linux/linux_example_cpu_monitor_packet_type.o -redo build/obj/Linux/linux_example_cpu_monitor_packet_type_type_ranges.o -redo build/obj/Linux/linux_example_data_dependencies.o -redo build/obj/Linux/linux_example_data_products.o -redo build/obj/Linux/linux_example_event_to_text.o -redo build/obj/Linux/linux_example_events.o -redo build/obj/Linux/linux_example_fault_responses.o -redo build/obj/Linux/linux_example_fault_responses_enums-assertion.o -redo build/obj/Linux/linux_example_fault_responses_enums-representation.o -redo build/obj/Linux/linux_example_fault_responses_enums.o -redo build/obj/Linux/linux_example_fault_responses_packed_id_type-assertion.o -redo build/obj/Linux/linux_example_fault_responses_packed_id_type-c.o -redo build/obj/Linux/linux_example_fault_responses_packed_id_type-representation.o -redo build/obj/Linux/linux_example_fault_responses_packed_id_type-validation.o -redo build/obj/Linux/linux_example_fault_responses_packed_id_type.o -redo build/obj/Linux/linux_example_fault_responses_packed_id_type_type_ranges.o -redo build/obj/Linux/linux_example_fault_responses_status_record-assertion.o -redo build/obj/Linux/linux_example_fault_responses_status_record-c.o -redo build/obj/Linux/linux_example_fault_responses_status_record-representation.o -redo build/obj/Linux/linux_example_fault_responses_status_record-validation.o -redo build/obj/Linux/linux_example_fault_responses_status_record.o -redo build/obj/Linux/linux_example_fault_responses_status_record_type_ranges.o -redo build/obj/Linux/linux_example_faults.o -redo build/obj/Linux/linux_example_packets.o -redo build/obj/Linux/linux_example_parameter_table.o -redo build/obj/Linux/linux_example_parameter_table_record-assertion.o -redo build/obj/Linux/linux_example_parameter_table_record-c.o -redo build/obj/Linux/linux_example_parameter_table_record-representation.o -redo build/obj/Linux/linux_example_parameter_table_record-validation.o -redo build/obj/Linux/linux_example_parameter_table_record.o -redo build/obj/Linux/linux_example_parameter_table_record_type_ranges.o -redo build/obj/Linux/linux_example_parameters.o -redo build/obj/Linux/linux_example_product_packets.o -redo build/obj/Linux/linux_example_queue_monitor_packet_type-assertion.o -redo build/obj/Linux/linux_example_queue_monitor_packet_type-c.o -redo build/obj/Linux/linux_example_queue_monitor_packet_type-representation.o -redo build/obj/Linux/linux_example_queue_monitor_packet_type-validation.o -redo build/obj/Linux/linux_example_queue_monitor_packet_type.o -redo build/obj/Linux/linux_example_queue_monitor_packet_type_type_ranges.o -redo build/obj/Linux/linux_example_stack_monitor_packet_type-assertion.o -redo build/obj/Linux/linux_example_stack_monitor_packet_type-c.o -redo build/obj/Linux/linux_example_stack_monitor_packet_type-representation.o -redo build/obj/Linux/linux_example_stack_monitor_packet_type-validation.o -redo build/obj/Linux/linux_example_stack_monitor_packet_type.o -redo build/obj/Linux/linux_example_stack_monitor_packet_type_type_ranges.o -redo build/obj/Linux/linux_example_task_watchdog_list.o -redo build/obj/Linux/linux_example_task_watchdog_list_state_record-assertion.o -redo build/obj/Linux/linux_example_task_watchdog_list_state_record-c.o -redo build/obj/Linux/linux_example_task_watchdog_list_state_record-representation.o -redo build/obj/Linux/linux_example_task_watchdog_list_state_record-validation.o -redo build/obj/Linux/linux_example_task_watchdog_list_state_record.o -redo build/obj/Linux/linux_example_task_watchdog_list_state_record_type_ranges.o -redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-assertion.o -redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-c.o -redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-representation.o -redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_action_cmd-validation.o -redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_action_cmd.o -redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_action_cmd_type_ranges.o -redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-assertion.o -redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-c.o -redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-representation.o -redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd-validation.o -redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd.o -redo build/obj/Linux/linux_example_task_watchdog_list_watchdog_limit_cmd_type_ranges.o -redo build/obj/Linux/memory_map.o -redo build/obj/Linux/start_up.o -redo build/pdf/linux_example_command_sequencer_details_packet_type.pdf -redo build/pdf/linux_example_command_sequencer_summary_packet_type.pdf -redo build/pdf/linux_example_cpu_monitor_packet_type.pdf -redo build/pdf/linux_example_fault_responses_enums.pdf -redo build/pdf/linux_example_fault_responses_packed_id_type.pdf -redo build/pdf/linux_example_fault_responses_status_record.pdf -redo build/pdf/linux_example_parameter_table_record.pdf -redo build/pdf/linux_example_queue_monitor_packet_type.pdf -redo build/pdf/linux_example_stack_monitor_packet_type.pdf -redo build/pdf/linux_example_task_watchdog_list_state_record.pdf -redo build/pdf/linux_example_task_watchdog_list_watchdog_action_cmd.pdf -redo build/pdf/linux_example_task_watchdog_list_watchdog_limit_cmd.pdf -redo build/png/linux_example.png -redo build/py/linux_example_command_sequencer_details_packet_type.py -redo build/py/linux_example_command_sequencer_summary_packet_type.py -redo build/py/linux_example_cpu_monitor_packet_type.py -redo build/py/linux_example_events.py -redo build/py/linux_example_fault_responses_enums.py -redo build/py/linux_example_fault_responses_packed_id_type.py -redo build/py/linux_example_fault_responses_status_record.py -redo build/py/linux_example_parameter_table_record.py -redo build/py/linux_example_queue_monitor_packet_type.py -redo build/py/linux_example_stack_monitor_packet_type.py -redo build/py/linux_example_task_watchdog_list_state_record.py -redo build/py/linux_example_task_watchdog_list_watchdog_action_cmd.py -redo build/py/linux_example_task_watchdog_list_watchdog_limit_cmd.py -redo build/src/linux_example.adb -redo build/src/linux_example.ads -redo build/src/linux_example_command_sequencer_details_packet_type-assertion.adb -redo build/src/linux_example_command_sequencer_details_packet_type-assertion.ads -redo build/src/linux_example_command_sequencer_details_packet_type-c.ads -redo build/src/linux_example_command_sequencer_details_packet_type-representation.adb -redo build/src/linux_example_command_sequencer_details_packet_type-representation.ads -redo build/src/linux_example_command_sequencer_details_packet_type-validation.adb -redo build/src/linux_example_command_sequencer_details_packet_type-validation.ads -redo build/src/linux_example_command_sequencer_details_packet_type.adb -redo build/src/linux_example_command_sequencer_details_packet_type.ads -redo build/src/linux_example_command_sequencer_details_packet_type_type_ranges.adb -redo build/src/linux_example_command_sequencer_summary_packet_type-assertion.adb -redo build/src/linux_example_command_sequencer_summary_packet_type-assertion.ads -redo build/src/linux_example_command_sequencer_summary_packet_type-c.ads -redo build/src/linux_example_command_sequencer_summary_packet_type-representation.adb -redo build/src/linux_example_command_sequencer_summary_packet_type-representation.ads -redo build/src/linux_example_command_sequencer_summary_packet_type-validation.adb -redo build/src/linux_example_command_sequencer_summary_packet_type-validation.ads -redo build/src/linux_example_command_sequencer_summary_packet_type.adb -redo build/src/linux_example_command_sequencer_summary_packet_type.ads -redo build/src/linux_example_command_sequencer_summary_packet_type_type_ranges.adb -redo build/src/linux_example_commands.ads -redo build/src/linux_example_cpu_monitor_packet_type-assertion.adb -redo build/src/linux_example_cpu_monitor_packet_type-assertion.ads -redo build/src/linux_example_cpu_monitor_packet_type-c.ads -redo build/src/linux_example_cpu_monitor_packet_type-representation.adb -redo build/src/linux_example_cpu_monitor_packet_type-representation.ads -redo build/src/linux_example_cpu_monitor_packet_type-validation.adb -redo build/src/linux_example_cpu_monitor_packet_type-validation.ads -redo build/src/linux_example_cpu_monitor_packet_type.adb -redo build/src/linux_example_cpu_monitor_packet_type.ads -redo build/src/linux_example_cpu_monitor_packet_type_type_ranges.adb -redo build/src/linux_example_data_dependencies.ads -redo build/src/linux_example_data_products.ads -redo build/src/linux_example_event_to_text.adb -redo build/src/linux_example_event_to_text.ads -redo build/src/linux_example_events.ads -redo build/src/linux_example_fault_responses.ads -redo build/src/linux_example_fault_responses_enums-assertion.ads -redo build/src/linux_example_fault_responses_enums-representation.adb -redo build/src/linux_example_fault_responses_enums-representation.ads -redo build/src/linux_example_fault_responses_enums.ads -redo build/src/linux_example_fault_responses_packed_id_type-assertion.adb -redo build/src/linux_example_fault_responses_packed_id_type-assertion.ads -redo build/src/linux_example_fault_responses_packed_id_type-c.ads -redo build/src/linux_example_fault_responses_packed_id_type-representation.adb -redo build/src/linux_example_fault_responses_packed_id_type-representation.ads -redo build/src/linux_example_fault_responses_packed_id_type-validation.adb -redo build/src/linux_example_fault_responses_packed_id_type-validation.ads -redo build/src/linux_example_fault_responses_packed_id_type.adb -redo build/src/linux_example_fault_responses_packed_id_type.ads -redo build/src/linux_example_fault_responses_packed_id_type_type_ranges.adb -redo build/src/linux_example_fault_responses_status_record-assertion.adb -redo build/src/linux_example_fault_responses_status_record-assertion.ads -redo build/src/linux_example_fault_responses_status_record-c.ads -redo build/src/linux_example_fault_responses_status_record-representation.adb -redo build/src/linux_example_fault_responses_status_record-representation.ads -redo build/src/linux_example_fault_responses_status_record-validation.adb -redo build/src/linux_example_fault_responses_status_record-validation.ads -redo build/src/linux_example_fault_responses_status_record.adb -redo build/src/linux_example_fault_responses_status_record.ads -redo build/src/linux_example_fault_responses_status_record_type_ranges.adb -redo build/src/linux_example_faults.ads -redo build/src/linux_example_packets.ads -redo build/src/linux_example_parameter_table.ads -redo build/src/linux_example_parameter_table_record-assertion.adb -redo build/src/linux_example_parameter_table_record-assertion.ads -redo build/src/linux_example_parameter_table_record-c.ads -redo build/src/linux_example_parameter_table_record-representation.adb -redo build/src/linux_example_parameter_table_record-representation.ads -redo build/src/linux_example_parameter_table_record-validation.adb -redo build/src/linux_example_parameter_table_record-validation.ads -redo build/src/linux_example_parameter_table_record.adb -redo build/src/linux_example_parameter_table_record.ads -redo build/src/linux_example_parameter_table_record_type_ranges.adb -redo build/src/linux_example_parameters.ads -redo build/src/linux_example_product_packets.ads -redo build/src/linux_example_queue_monitor_packet_type-assertion.adb -redo build/src/linux_example_queue_monitor_packet_type-assertion.ads -redo build/src/linux_example_queue_monitor_packet_type-c.ads -redo build/src/linux_example_queue_monitor_packet_type-representation.adb -redo build/src/linux_example_queue_monitor_packet_type-representation.ads -redo build/src/linux_example_queue_monitor_packet_type-validation.adb -redo build/src/linux_example_queue_monitor_packet_type-validation.ads -redo build/src/linux_example_queue_monitor_packet_type.adb -redo build/src/linux_example_queue_monitor_packet_type.ads -redo build/src/linux_example_queue_monitor_packet_type_type_ranges.adb -redo build/src/linux_example_stack_monitor_packet_type-assertion.adb -redo build/src/linux_example_stack_monitor_packet_type-assertion.ads -redo build/src/linux_example_stack_monitor_packet_type-c.ads -redo build/src/linux_example_stack_monitor_packet_type-representation.adb -redo build/src/linux_example_stack_monitor_packet_type-representation.ads -redo build/src/linux_example_stack_monitor_packet_type-validation.adb -redo build/src/linux_example_stack_monitor_packet_type-validation.ads -redo build/src/linux_example_stack_monitor_packet_type.adb -redo build/src/linux_example_stack_monitor_packet_type.ads -redo build/src/linux_example_stack_monitor_packet_type_type_ranges.adb -redo build/src/linux_example_task_watchdog_list.ads -redo build/src/linux_example_task_watchdog_list_state_record-assertion.adb -redo build/src/linux_example_task_watchdog_list_state_record-assertion.ads -redo build/src/linux_example_task_watchdog_list_state_record-c.ads -redo build/src/linux_example_task_watchdog_list_state_record-representation.adb -redo build/src/linux_example_task_watchdog_list_state_record-representation.ads -redo build/src/linux_example_task_watchdog_list_state_record-validation.adb -redo build/src/linux_example_task_watchdog_list_state_record-validation.ads -redo build/src/linux_example_task_watchdog_list_state_record.adb -redo build/src/linux_example_task_watchdog_list_state_record.ads -redo build/src/linux_example_task_watchdog_list_state_record_type_ranges.adb -redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd-assertion.adb -redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd-assertion.ads -redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd-c.ads -redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd-representation.adb -redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd-representation.ads -redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd-validation.adb -redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd-validation.ads -redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd.adb -redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd.ads -redo build/src/linux_example_task_watchdog_list_watchdog_action_cmd_type_ranges.adb -redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd-assertion.adb -redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd-assertion.ads -redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd-c.ads -redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd-representation.adb -redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd-representation.ads -redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd-validation.adb -redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd-validation.ads -redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd.adb -redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd.ads -redo build/src/linux_example_task_watchdog_list_watchdog_limit_cmd_type_ranges.adb -redo build/svg/linux_example.svg -redo build/tex/linux_example_command_sequencer_details_packet_type.tex -redo build/tex/linux_example_command_sequencer_summary_packet_type.tex -redo build/tex/linux_example_cpu_monitor_packet_type.tex -redo build/tex/linux_example_fault_responses_enums.tex -redo build/tex/linux_example_fault_responses_packed_id_type.tex -redo build/tex/linux_example_fault_responses_status_record.tex -redo build/tex/linux_example_parameter_table_record.tex -redo build/tex/linux_example_queue_monitor_packet_type.tex -redo build/tex/linux_example_stack_monitor_packet_type.tex -redo build/tex/linux_example_task_watchdog_list_state_record.tex -redo build/tex/linux_example_task_watchdog_list_watchdog_action_cmd.tex -redo build/tex/linux_example_task_watchdog_list_watchdog_limit_cmd.tex -redo build/txt/linux_example_seq_cmd_tlm.txt -redo build/yaml/linux_example_command_sequencer_details_packet_type.record.yaml -redo build/yaml/linux_example_command_sequencer_summary_packet_type.record.yaml -redo build/yaml/linux_example_cpu_monitor_packet_type.record.yaml -redo build/yaml/linux_example_fault_responses_enums.enums.yaml -redo build/yaml/linux_example_fault_responses_packed_id_type.record.yaml -redo build/yaml/linux_example_fault_responses_status_record.record.yaml -redo build/yaml/linux_example_parameter_table_record.record.yaml -redo build/yaml/linux_example_queue_monitor_packet_type.record.yaml -redo build/yaml/linux_example_stack_monitor_packet_type.record.yaml -redo build/yaml/linux_example_task_watchdog_list_state_record.record.yaml -redo build/yaml/linux_example_task_watchdog_list_watchdog_action_cmd.record.yaml -redo build/yaml/linux_example_task_watchdog_list_watchdog_limit_cmd.record.yaml -redo doc/build/pdf/linux_example_commands.pdf -redo doc/build/pdf/linux_example_components.pdf -redo doc/build/pdf/linux_example_connections.pdf -redo doc/build/pdf/linux_example_data_dependencies.pdf -redo doc/build/pdf/linux_example_data_products.pdf -redo doc/build/pdf/linux_example_description.pdf -redo doc/build/pdf/linux_example_enums.pdf -redo doc/build/pdf/linux_example_events.pdf -redo doc/build/pdf/linux_example_faults.pdf -redo doc/build/pdf/linux_example_packets.pdf -redo doc/build/pdf/linux_example_parameters.pdf -redo doc/build/pdf/linux_example_priorities.pdf -redo doc/build/pdf/linux_example_stats.pdf -redo doc/build/pdf/linux_example_types.pdf -redo doc/build/pdf/linux_example_views.pdf -redo doc/build/template/linux_example.tex -redo doc/build/tex/linux_example_commands.tex -redo doc/build/tex/linux_example_components.tex -redo doc/build/tex/linux_example_connections.tex -redo doc/build/tex/linux_example_data_dependencies.tex -redo doc/build/tex/linux_example_data_products.tex -redo doc/build/tex/linux_example_description.tex -redo doc/build/tex/linux_example_enums.tex -redo doc/build/tex/linux_example_events.tex -redo doc/build/tex/linux_example_faults.tex -redo doc/build/tex/linux_example_packets.tex -redo doc/build/tex/linux_example_parameters.tex -redo doc/build/tex/linux_example_priorities.tex -redo doc/build/tex/linux_example_stats.tex -redo doc/build/tex/linux_example_types.tex -redo doc/build/tex/linux_example_views.tex