MeshX 0.4
This repository provides an implementation for Bluetooth Low Energy (BLE) Mesh network nodes. The project allows you to create BLE mesh nodes that can communicate with each other, enabling the development of smart home solutions or other IoT-based applications.
Loading...
Searching...
No Matches
gpio_unit_test.c File Reference

Unit tests for MeshX GPIO subsystem. More...

Data Structures

struct  gpio_test_state_t
 Test state for tracking GPIO operations. More...

Functions

meshx_err_t meshx_gpio_test_set_pin_count (uint8_t count)
meshx_err_t meshx_gpio_test_set_pin_mode (uint8_t logical_pin, uint8_t mode)
static void init_test_state (void)
static void mock_interrupt_callback (uint8_t logical_pin, void *user_data)
static meshx_err_t test_gpio_init (void)
static meshx_err_t test_gpio_deinit (void)
static meshx_err_t test_gpio_reinit (void)
static meshx_err_t test_set_level_valid (void)
static meshx_err_t test_set_level_invalid (void)
static meshx_err_t test_set_level_all_modes (void)
static meshx_err_t test_get_level_valid (void)
static meshx_err_t test_get_level_invalid (void)
static meshx_err_t test_toggle_valid (void)
static meshx_err_t test_toggle_invalid_mode (void)
static meshx_err_t test_interrupt_register (void)
static meshx_err_t test_interrupt_register_invalid (void)
static meshx_err_t test_interrupt_enable_disable (void)
static meshx_err_t test_all_interrupt_types (void)
static meshx_err_t test_execute_function_set_level (void)
static meshx_err_t test_execute_function_toggle (void)
static meshx_err_t test_execute_function_pwm_duty (void)
static meshx_err_t test_execute_function_pwm_frequency (void)
static meshx_err_t test_execute_function_multi_args (void)
static meshx_err_t test_hosted_mode_set_get (void)
static meshx_err_t test_hosted_mode_operations (void)
static meshx_err_t test_error_recovery_after_invalid_input (void)
static meshx_err_t test_error_recovery_after_mode_mismatch (void)
static meshx_err_t run_gpio_unit_tests (void)
 Run all GPIO unit tests.
static meshx_err_t gpio_unit_test_handler (int cmd_id, int argc, char **argv)
 GPIO unit test command handler.
meshx_err_t register_gpio_unit_tests (void)
 Register GPIO unit tests with unit test framework.

Variables

static gpio_test_state_t test_state

Detailed Description

Unit tests for MeshX GPIO subsystem.

This file implements comprehensive unit tests for the MeshX GPIO subsystem, validating all API functions with valid and invalid inputs, error conditions, recovery strategies, and function-based API operations.

Validates: Requirements 10.1-10.4

Requirements coverage:

  • 10.1: Unit tests validate all GPIO API functions with valid and invalid inputs
  • 10.2: Unit tests test each GPIO mode (input, output, open-drain, etc.)
  • 10.3: Unit tests test interrupt registration, triggering, and handling
  • 10.4: Unit tests test PWM frequency, duty cycle, and start/stop operations
Author
MeshX Team
Date
2024

Function Documentation

◆ gpio_unit_test_handler()

meshx_err_t gpio_unit_test_handler ( int cmd_id,
int argc,
char ** argv )
static

GPIO unit test command handler.

969{
970 (void)argc;
971 (void)argv;
972
973 MESHX_LOGD(MODULE_ID_COMMON, "GPIO Unit Test Handler - Command ID: %d", cmd_id);
974
975 switch (cmd_id) {
976 case 0: return run_gpio_unit_tests();
977 case 1: init_test_state(); return test_gpio_init();
978 case 2: init_test_state(); return test_gpio_deinit();
979 case 3: init_test_state(); return test_gpio_reinit();
980 case 4: init_test_state(); return test_set_level_valid();
981 case 5: init_test_state(); return test_set_level_invalid();
982 case 6: init_test_state(); return test_set_level_all_modes();
983 case 7: init_test_state(); return test_get_level_valid();
984 case 8: init_test_state(); return test_get_level_invalid();
985 case 9: init_test_state(); return test_toggle_valid();
986 case 10: init_test_state(); return test_toggle_invalid_mode();
987 case 11: init_test_state(); return test_interrupt_register();
990 case 14: init_test_state(); return test_all_interrupt_types();
996 case 20: init_test_state(); return test_hosted_mode_set_get();
997 case 21: init_test_state(); return test_hosted_mode_operations();
1000 default:
1001 MESHX_LOGE(MODULE_ID_COMMON, "Unknown GPIO unit test command: %d", cmd_id);
1002 return MESHX_INVALID_ARG;
1003 }
1004}
static meshx_err_t test_execute_function_set_level(void)
Definition gpio_unit_test.c:587
static meshx_err_t run_gpio_unit_tests(void)
Run all GPIO unit tests.
Definition gpio_unit_test.c:875
static meshx_err_t test_gpio_reinit(void)
Definition gpio_unit_test.c:131
static meshx_err_t test_interrupt_register(void)
Definition gpio_unit_test.c:451
static meshx_err_t test_set_level_invalid(void)
Definition gpio_unit_test.c:197
static meshx_err_t test_hosted_mode_operations(void)
Definition gpio_unit_test.c:770
static meshx_err_t test_get_level_invalid(void)
Definition gpio_unit_test.c:361
static meshx_err_t test_all_interrupt_types(void)
Definition gpio_unit_test.c:547
static meshx_err_t test_execute_function_multi_args(void)
Definition gpio_unit_test.c:698
static meshx_err_t test_execute_function_pwm_frequency(void)
Definition gpio_unit_test.c:671
static meshx_err_t test_toggle_invalid_mode(void)
Definition gpio_unit_test.c:422
static meshx_err_t test_gpio_init(void)
Definition gpio_unit_test.c:76
static meshx_err_t test_interrupt_enable_disable(void)
Definition gpio_unit_test.c:511
static meshx_err_t test_execute_function_pwm_duty(void)
Definition gpio_unit_test.c:643
static meshx_err_t test_toggle_valid(void)
Definition gpio_unit_test.c:389
static meshx_err_t test_get_level_valid(void)
Definition gpio_unit_test.c:319
static meshx_err_t test_error_recovery_after_invalid_input(void)
Definition gpio_unit_test.c:806
static meshx_err_t test_set_level_valid(void)
Definition gpio_unit_test.c:156
static meshx_err_t test_execute_function_toggle(void)
Definition gpio_unit_test.c:615
static meshx_err_t test_gpio_deinit(void)
Definition gpio_unit_test.c:104
static meshx_err_t test_hosted_mode_set_get(void)
Definition gpio_unit_test.c:728
static meshx_err_t test_error_recovery_after_mode_mismatch(void)
Definition gpio_unit_test.c:835
static meshx_err_t test_interrupt_register_invalid(void)
Definition gpio_unit_test.c:480
static meshx_err_t test_set_level_all_modes(void)
Definition gpio_unit_test.c:265
static void init_test_state(void)
Definition gpio_unit_test.c:58
@ MESHX_INVALID_ARG
Definition meshx_err.h:46
#define MESHX_LOGE(module_id, format,...)
Definition meshx_log.h:114
#define MESHX_LOGD(module_id, format,...)
Definition meshx_log.h:132
@ MODULE_ID_COMMON
Definition module_id.h:36

◆ init_test_state()

void init_test_state ( void )
static
59{
60 memset(&test_state, 0, sizeof(test_state));
61 for (int i = 0; i < 256; i++) {
62 test_state.pin_modes[i] = MESHX_GPIO_MODE_MAX;
63 }
64}
static gpio_test_state_t test_state
Definition gpio_property_test.c:57
@ MESHX_GPIO_MODE_MAX
Definition meshx_gpio.h:35

◆ meshx_gpio_test_set_pin_count()

meshx_err_t meshx_gpio_test_set_pin_count ( uint8_t count)
extern
73{
74 if (count <= 128) {
75 gpio_runtime.pin_count = count;
76 return MESHX_SUCCESS;
77 }
78 return MESHX_FAIL;
79}
@ MESHX_FAIL
Definition meshx_err.h:45
static meshx_gpio_runtime_t gpio_runtime
Definition meshx_gpio.c:38
**This function is called by the parent element when a state change request *is received It validates the request and returns a result to the element not the model layer **return * MESHX_SUCCESS
Definition meshx_model_level.cpp:385

◆ meshx_gpio_test_set_pin_mode()

meshx_err_t meshx_gpio_test_set_pin_mode ( uint8_t logical_pin,
uint8_t mode )
extern
83{
84 if (logical_pin < 128 && gpio_runtime.pin_configs != NULL) {
85 gpio_runtime.pin_configs[logical_pin].mode = mode;
86 return MESHX_SUCCESS;
87 }
88 return MESHX_FAIL;
89}

◆ mock_interrupt_callback()

void mock_interrupt_callback ( uint8_t logical_pin,
void * user_data )
static
67{
68 (void)user_data;
69 test_state.interrupt_counts[logical_pin]++;
70}

◆ register_gpio_unit_tests()

meshx_err_t register_gpio_unit_tests ( void )

Register GPIO unit tests with unit test framework.

Returns
meshx_err_t Registration result
1010{
1011 MESHX_LOGD(MODULE_ID_GPIO_UNIT_TEST, "Registering GPIO unit tests");
1012 /* Register under both IDs for compatibility with documentation (16) and internal organization (17) */
1015}
static meshx_err_t gpio_unit_test_handler(int cmd_id, int argc, char **argv)
GPIO unit test command handler.
Definition gpio_unit_test.c:968
@ MODULE_ID_COMPONENT_MESHX_GPIO
Definition module_id.h:44
@ MODULE_ID_GPIO_UNIT_TEST
Definition module_id.h:45
meshx_err_t register_unit_test(module_id_t module_id, module_callback_t callback)
Register a unit test for a specific module.
Definition unit_test.c:137

◆ run_gpio_unit_tests()

meshx_err_t run_gpio_unit_tests ( void )
static

Run all GPIO unit tests.

876{
877 MESHX_LOGD(MODULE_ID_COMMON, "Starting GPIO Unit Tests");
878 MESHX_LOGD(MODULE_ID_COMMON, "Validates: Requirements 10.1-10.4");
879
881
882 meshx_err_t result;
883
884 /* Initialization tests */
885 result = test_gpio_init();
886 if (result != MESHX_SUCCESS) return result;
887
888 result = test_gpio_deinit();
889 if (result != MESHX_SUCCESS) return result;
890
891 result = test_gpio_reinit();
892 if (result != MESHX_SUCCESS) return result;
893
894 /* Set level tests */
895 result = test_set_level_valid();
896 if (result != MESHX_SUCCESS) return result;
897
898 result = test_set_level_invalid();
899 if (result != MESHX_SUCCESS) return result;
900
901 result = test_set_level_all_modes();
902 if (result != MESHX_SUCCESS) return result;
903
904 /* Get level tests */
905 result = test_get_level_valid();
906 if (result != MESHX_SUCCESS) return result;
907
908 result = test_get_level_invalid();
909 if (result != MESHX_SUCCESS) return result;
910
911 /* Toggle tests */
912 result = test_toggle_valid();
913 if (result != MESHX_SUCCESS) return result;
914
915 result = test_toggle_invalid_mode();
916 if (result != MESHX_SUCCESS) return result;
917
918 /* Interrupt tests */
919 result = test_interrupt_register();
920 if (result != MESHX_SUCCESS) return result;
921
923 if (result != MESHX_SUCCESS) return result;
924
926 if (result != MESHX_SUCCESS) return result;
927
928 result = test_all_interrupt_types();
929 if (result != MESHX_SUCCESS) return result;
930
931 /* Function-based API tests */
933 if (result != MESHX_SUCCESS) return result;
934
936 if (result != MESHX_SUCCESS) return result;
937
939 if (result != MESHX_SUCCESS) return result;
940
942 if (result != MESHX_SUCCESS) return result;
943
945 if (result != MESHX_SUCCESS) return result;
946
947 /* Hosted mode tests */
948 result = test_hosted_mode_set_get();
949 if (result != MESHX_SUCCESS) return result;
950
952 if (result != MESHX_SUCCESS) return result;
953
954 /* Error recovery tests */
956 if (result != MESHX_SUCCESS) return result;
957
959 if (result != MESHX_SUCCESS) return result;
960
961 MESHX_LOGI(MODULE_ID_COMMON, "All GPIO Unit Tests PASSED");
962 return MESHX_SUCCESS;
963}
meshx_err_t
MeshX Error Codes.
Definition meshx_err.h:43
#define MESHX_LOGI(module_id, format,...)
Definition meshx_log.h:126

◆ test_all_interrupt_types()

meshx_err_t test_all_interrupt_types ( void )
static
548{
549 MESHX_LOGD(MODULE_ID_COMMON, "Test: all interrupt types");
550
551 if (!test_state.gpio_initialized) {
552 meshx_err_t result = meshx_gpio_init();
553 if (result != MESHX_SUCCESS) return result;
554 test_state.gpio_initialized = true;
555 }
557
558 const meshx_gpio_intr_type_t types[] = {
564 };
565
566 for (size_t i = 0; i < 5; i++) {
567 uint8_t pin = 70 + i;
568 test_state.pin_modes[pin] = MESHX_GPIO_MODE_INPUT;
569 test_state.pin_initialized[pin] = true;
570
571 meshx_err_t result = meshx_gpio_register_intr(pin, types[i], mock_interrupt_callback, NULL);
572 if (result != MESHX_SUCCESS) {
573 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: type %d failed: %d", types[i], result);
574 return MESHX_FAIL;
575 }
577 }
578
579 MESHX_LOGI(MODULE_ID_COMMON, "PASS: all interrupt types");
580 return MESHX_SUCCESS;
581}
static void mock_interrupt_callback(uint8_t logical_pin, void *user_data)
Mock interrupt callback for testing.
Definition gpio_integration_test.c:101
meshx_err_t meshx_gpio_test_set_pin_count(uint8_t count)
Definition meshx_gpio.c:72
meshx_err_t meshx_gpio_unregister_intr(uint8_t logical_pin)
Unregister GPIO interrupt handler.
Definition meshx_gpio.c:557
meshx_err_t meshx_gpio_init(void)
Initialize GPIO subsystem.
Definition meshx_gpio.c:95
@ MESHX_GPIO_MODE_INPUT
Definition meshx_gpio.h:29
meshx_err_t meshx_gpio_register_intr(uint8_t logical_pin, meshx_gpio_intr_type_t intr_type, meshx_gpio_intr_cb_t callback, void *user_data)
Register GPIO interrupt handler.
Definition meshx_gpio.c:488
meshx_gpio_intr_type_t
GPIO Interrupt Trigger Types.
Definition meshx_gpio_types.h:28
@ MESHX_GPIO_INTR_POSITIVE_EDGE
Definition meshx_gpio_types.h:30
@ MESHX_GPIO_INTR_NEGATIVE_EDGE
Definition meshx_gpio_types.h:31
@ MESHX_GPIO_INTR_ANY_EDGE
Definition meshx_gpio_types.h:32
@ MESHX_GPIO_INTR_LOW_LEVEL
Definition meshx_gpio_types.h:33
@ MESHX_GPIO_INTR_HIGH_LEVEL
Definition meshx_gpio_types.h:34

◆ test_error_recovery_after_invalid_input()

meshx_err_t test_error_recovery_after_invalid_input ( void )
static
807{
808 MESHX_LOGD(MODULE_ID_COMMON, "Test: error recovery after invalid input");
809
810 if (!test_state.gpio_initialized) {
811 meshx_err_t result = meshx_gpio_init();
812 if (result != MESHX_SUCCESS) return result;
813 test_state.gpio_initialized = true;
814 }
816
817 uint8_t pin = 100;
818 test_state.pin_modes[pin] = MESHX_GPIO_MODE_OUTPUT;
819 test_state.pin_initialized[pin] = true;
820
821 /* Send invalid input */
822 meshx_gpio_set_level(pin, 255);
823
824 /* Verify subsequent valid operation works */
825 meshx_err_t result = meshx_gpio_set_level(pin, 0);
826 if (result != MESHX_SUCCESS) {
827 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: Recovery failed: %p", result);
828 return MESHX_FAIL;
829 }
830
831 MESHX_LOGI(MODULE_ID_COMMON, "PASS: error recovery after invalid input");
832 return MESHX_SUCCESS;
833}
meshx_err_t meshx_gpio_set_level(uint8_t logical_pin, uint8_t level)
Set GPIO pin level.
Definition meshx_gpio.c:322
@ MESHX_GPIO_MODE_OUTPUT
Definition meshx_gpio.h:30

◆ test_error_recovery_after_mode_mismatch()

meshx_err_t test_error_recovery_after_mode_mismatch ( void )
static
836{
837 MESHX_LOGD(MODULE_ID_COMMON, "Test: error recovery after mode mismatch");
838
839 if (!test_state.gpio_initialized) {
840 meshx_err_t result = meshx_gpio_init();
841 if (result != MESHX_SUCCESS) return result;
842 test_state.gpio_initialized = true;
843 }
845
846 uint8_t input_pin = 101;
847 uint8_t output_pin = 102;
848
849 test_state.pin_modes[input_pin] = MESHX_GPIO_MODE_INPUT;
850 test_state.pin_initialized[input_pin] = true;
851 test_state.pin_modes[output_pin] = MESHX_GPIO_MODE_OUTPUT;
852 test_state.pin_initialized[output_pin] = true;
853
854 /* Try invalid operation on input pin */
855 meshx_gpio_set_level(input_pin, 1);
856
857 /* Verify subsequent valid operation on correct pin works */
858 meshx_err_t result = meshx_gpio_set_level(output_pin, 1);
859 if (result != MESHX_SUCCESS) {
860 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: Recovery failed: %p", result);
861 return MESHX_FAIL;
862 }
863
864 MESHX_LOGI(MODULE_ID_COMMON, "PASS: error recovery after mode mismatch");
865 return MESHX_SUCCESS;
866}

◆ test_execute_function_multi_args()

meshx_err_t test_execute_function_multi_args ( void )
static
699{
700 MESHX_LOGD(MODULE_ID_COMMON, "Test: execute_function multiple arguments");
701
702 if (!test_state.gpio_initialized) {
703 meshx_err_t result = meshx_gpio_init();
704 if (result != MESHX_SUCCESS) return result;
705 test_state.gpio_initialized = true;
706 }
708
709 uint8_t pin = 84;
710 test_state.pin_modes[pin] = MESHX_GPIO_MODE_PWM_OUTPUT;
711 test_state.pin_initialized[pin] = true;
712
713 /* Test with multiple arguments */
714 uint32_t args[4] = {1000, 50, 10, 0}; /* frequency, duty, resolution, channel */
716
717 /* CUSTOM function may or may not be supported - just verify it doesn't crash */
718 (void)result;
719
720 MESHX_LOGI(MODULE_ID_COMMON, "PASS: execute_function multiple arguments");
721 return MESHX_SUCCESS;
722}
meshx_err_t meshx_gpio_execute_function(uint8_t logical_pin, meshx_io_function_t function, const uint32_t *args, uint8_t arg_count)
Execute IO function on GPIO pin.
Definition meshx_gpio.c:616
@ MESHX_GPIO_MODE_PWM_OUTPUT
Definition meshx_gpio.h:34
@ MESHX_IO_FUNCTION_CUSTOM
Definition meshx_gpio.h:70

◆ test_execute_function_pwm_duty()

meshx_err_t test_execute_function_pwm_duty ( void )
static
644{
645 MESHX_LOGD(MODULE_ID_COMMON, "Test: execute_function SET_PWM_DUTY");
646
647 if (!test_state.gpio_initialized) {
648 meshx_err_t result = meshx_gpio_init();
649 if (result != MESHX_SUCCESS) return result;
650 test_state.gpio_initialized = true;
651 }
653
654 uint8_t pin = 82;
655 test_state.pin_modes[pin] = MESHX_GPIO_MODE_PWM_OUTPUT;
656 test_state.pin_initialized[pin] = true;
658
659 uint32_t args[1] = {50}; /* 50% duty cycle */
661
662 if (result != MESHX_SUCCESS) {
663 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: SET_PWM_DUTY: %p", result);
664 return MESHX_FAIL;
665 }
666
667 MESHX_LOGI(MODULE_ID_COMMON, "PASS: execute_function SET_PWM_DUTY");
668 return MESHX_SUCCESS;
669}
meshx_err_t meshx_gpio_test_set_pin_mode(uint8_t logical_pin, uint8_t mode)
Definition meshx_gpio.c:82
@ MESHX_IO_FUNCTION_SET_PWM_DUTY
Definition meshx_gpio.h:67

◆ test_execute_function_pwm_frequency()

meshx_err_t test_execute_function_pwm_frequency ( void )
static
672{
673 MESHX_LOGD(MODULE_ID_COMMON, "Test: execute_function SET_PWM_FREQUENCY");
674
675 if (!test_state.gpio_initialized) {
676 meshx_err_t result = meshx_gpio_init();
677 if (result != MESHX_SUCCESS) return result;
678 test_state.gpio_initialized = true;
679 }
681
682 uint8_t pin = 83;
683 test_state.pin_modes[pin] = MESHX_GPIO_MODE_PWM_OUTPUT;
684 test_state.pin_initialized[pin] = true;
685
686 uint32_t args[1] = {1000}; /* 1kHz */
688
689 if (result != MESHX_SUCCESS) {
690 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: SET_PWM_FREQUENCY: %p", result);
691 return MESHX_FAIL;
692 }
693
694 MESHX_LOGI(MODULE_ID_COMMON, "PASS: execute_function SET_PWM_FREQUENCY");
695 return MESHX_SUCCESS;
696}
@ MESHX_IO_FUNCTION_SET_PWM_FREQUENCY
Definition meshx_gpio.h:68

◆ test_execute_function_set_level()

meshx_err_t test_execute_function_set_level ( void )
static
588{
589 MESHX_LOGD(MODULE_ID_COMMON, "Test: execute_function SET_LEVEL");
590
591 if (!test_state.gpio_initialized) {
592 meshx_err_t result = meshx_gpio_init();
593 if (result != MESHX_SUCCESS) return result;
594 test_state.gpio_initialized = true;
595 }
597
598 uint8_t pin = 80;
599 test_state.pin_modes[pin] = MESHX_GPIO_MODE_OUTPUT;
600 test_state.pin_initialized[pin] = true;
602
603 uint32_t args[1] = {1};
605
606 if (result != MESHX_SUCCESS) {
607 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: SET_LEVEL: %p", result);
608 return MESHX_FAIL;
609 }
610
611 MESHX_LOGI(MODULE_ID_COMMON, "PASS: execute_function SET_LEVEL");
612 return MESHX_SUCCESS;
613}
@ MESHX_IO_FUNCTION_SET_LEVEL
Definition meshx_gpio.h:64

◆ test_execute_function_toggle()

meshx_err_t test_execute_function_toggle ( void )
static
616{
617 MESHX_LOGD(MODULE_ID_COMMON, "Test: execute_function TOGGLE");
618
619 if (!test_state.gpio_initialized) {
620 meshx_err_t result = meshx_gpio_init();
621 if (result != MESHX_SUCCESS) return result;
622 test_state.gpio_initialized = true;
623 }
625
626 uint8_t pin = 81;
627 test_state.pin_modes[pin] = MESHX_GPIO_MODE_OUTPUT;
628 test_state.pin_initialized[pin] = true;
630 meshx_gpio_set_level(pin, 0);
631
633
634 if (result != MESHX_SUCCESS) {
635 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: TOGGLE: %p", result);
636 return MESHX_FAIL;
637 }
638
639 MESHX_LOGI(MODULE_ID_COMMON, "PASS: execute_function TOGGLE");
640 return MESHX_SUCCESS;
641}
@ MESHX_IO_FUNCTION_TOGGLE
Definition meshx_gpio.h:66

◆ test_get_level_invalid()

meshx_err_t test_get_level_invalid ( void )
static
362{
363 MESHX_LOGD(MODULE_ID_COMMON, "Test: get_level invalid inputs");
364
365 if (!test_state.gpio_initialized) {
366 meshx_err_t result = meshx_gpio_init();
367 if (result != MESHX_SUCCESS) return result;
368 test_state.gpio_initialized = true;
369 }
370
371 uint8_t input_pin = 40;
372 test_state.pin_modes[input_pin] = MESHX_GPIO_MODE_INPUT;
373 test_state.pin_initialized[input_pin] = true;
374
375 meshx_err_t result = meshx_gpio_get_level(input_pin, NULL);
376 if (result != MESHX_INVALID_ARG) {
377 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: NULL ptr should return INVALID_ARG, got: %p", result);
378 return MESHX_FAIL;
379 }
380
381 MESHX_LOGI(MODULE_ID_COMMON, "PASS: get_level invalid inputs");
382 return MESHX_SUCCESS;
383}
meshx_err_t meshx_gpio_get_level(uint8_t logical_pin, uint8_t *level)
Get GPIO pin level.
Definition meshx_gpio.c:392

◆ test_get_level_valid()

meshx_err_t test_get_level_valid ( void )
static
320{
321 MESHX_LOGD(MODULE_ID_COMMON, "Test: get_level valid inputs");
322
323 if (!test_state.gpio_initialized) {
324 meshx_err_t result = meshx_gpio_init();
325 if (result != MESHX_SUCCESS) return result;
326 test_state.gpio_initialized = true;
327 }
328
329 const uint8_t pins[] = {30, 31, 32};
330 const meshx_gpio_mode_t modes[] = {
334 };
335
336 /* Set pin count for valid tests */
338
339 for (size_t i = 0; i < 3; i++) {
340 test_state.pin_modes[pins[i]] = modes[i];
341 test_state.pin_initialized[pins[i]] = true;
342 meshx_gpio_test_set_pin_mode(pins[i], modes[i]);
343
344 uint8_t level;
345 meshx_err_t result = meshx_gpio_get_level(pins[i], &level);
346
347 if (result != MESHX_SUCCESS) {
348 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: get_level pin %u: %p", pins[i], result);
349 return MESHX_FAIL;
350 }
351 if (level > 1) {
352 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: Invalid level %u", level);
353 return MESHX_FAIL;
354 }
355 }
356
357 MESHX_LOGI(MODULE_ID_COMMON, "PASS: get_level valid inputs");
358 return MESHX_SUCCESS;
359}
meshx_gpio_mode_t
GPIO Pin Modes.
Definition meshx_gpio.h:28
@ MESHX_GPIO_MODE_INPUT_OUTPUT
Definition meshx_gpio.h:31
@ MESHX_GPIO_MODE_OPEN_DRAIN_INPUT_OUTPUT
Definition meshx_gpio.h:33

◆ test_gpio_deinit()

meshx_err_t test_gpio_deinit ( void )
static
105{
106 MESHX_LOGD(MODULE_ID_COMMON, "Test: GPIO deinitialization");
107
108 if (!test_state.gpio_initialized) {
109 meshx_err_t result = meshx_gpio_init();
110 if (result != MESHX_SUCCESS) return result;
111 test_state.gpio_initialized = true;
112 }
113
115 if (result != MESHX_SUCCESS) {
116 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: GPIO deinit failed: %p", result);
117 return MESHX_FAIL;
118 }
119
120 test_state.gpio_initialized = false;
121
123 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: GPIO still marked initialized after deinit");
124 return MESHX_FAIL;
125 }
126
127 MESHX_LOGI(MODULE_ID_COMMON, "PASS: GPIO deinitialization");
128 return MESHX_SUCCESS;
129}
meshx_err_t meshx_gpio_deinit(void)
Deinitialize GPIO subsystem.
Definition meshx_gpio.c:189
bool meshx_gpio_is_initialized(void)
Check if GPIO subsystem is initialized.
Definition meshx_gpio.c:641

◆ test_gpio_init()

meshx_err_t test_gpio_init ( void )
static
77{
78 MESHX_LOGD(MODULE_ID_COMMON, "Test: GPIO initialization");
79
81 if (result != MESHX_SUCCESS) {
82 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: GPIO init failed: %p", result);
83 return MESHX_FAIL;
84 }
85
87 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: GPIO not marked as initialized");
88 return MESHX_FAIL;
89 }
90
91 test_state.gpio_initialized = true;
92
93 /* Test repeated init (should succeed) */
94 result = meshx_gpio_init();
95 if (result != MESHX_SUCCESS) {
96 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: Repeated init failed: %p", result);
97 return MESHX_FAIL;
98 }
99
100 MESHX_LOGI(MODULE_ID_COMMON, "PASS: GPIO initialization");
101 return MESHX_SUCCESS;
102}

◆ test_gpio_reinit()

meshx_err_t test_gpio_reinit ( void )
static
132{
133 MESHX_LOGD(MODULE_ID_COMMON, "Test: GPIO re-initialization");
134
135 meshx_err_t result = meshx_gpio_init();
136 if (result != MESHX_SUCCESS) return result;
137
138 result = meshx_gpio_deinit();
139 if (result != MESHX_SUCCESS) return result;
140
141 result = meshx_gpio_init();
142 if (result != MESHX_SUCCESS) {
143 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: Re-init failed: %p", result);
144 return MESHX_FAIL;
145 }
146
147 test_state.gpio_initialized = true;
148 MESHX_LOGI(MODULE_ID_COMMON, "PASS: GPIO re-initialization");
149 return MESHX_SUCCESS;
150}

◆ test_hosted_mode_operations()

meshx_err_t test_hosted_mode_operations ( void )
static
771{
772 MESHX_LOGD(MODULE_ID_COMMON, "Test: hosted mode operations");
773
774 if (!test_state.gpio_initialized) {
775 meshx_err_t result = meshx_gpio_init();
776 if (result != MESHX_SUCCESS) return result;
777 test_state.gpio_initialized = true;
778 }
780
781 /* Set to hosted mode */
783
784 uint8_t pin = 90;
785 test_state.pin_modes[pin] = MESHX_GPIO_MODE_OUTPUT;
786 test_state.pin_initialized[pin] = true;
787
788 /* Operations should work in hosted mode (via callback) */
789 meshx_err_t result = meshx_gpio_set_level(pin, 1);
790 if (result != MESHX_SUCCESS) {
791 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: set_level in hosted mode: %p", result);
792 return MESHX_FAIL;
793 }
794
795 /* Restore non-hosted mode */
797
798 MESHX_LOGI(MODULE_ID_COMMON, "PASS: hosted mode operations");
799 return MESHX_SUCCESS;
800}
meshx_err_t meshx_gpio_set_hosted_mode(meshx_gpio_hosted_mode_t mode)
Set hosted mode for GPIO subsystem.
Definition meshx_gpio.c:711
@ MESHX_GPIO_MODE_NON_HOSTED
Definition meshx_gpio_types.h:170
@ MESHX_GPIO_MODE_HOSTED
Definition meshx_gpio_types.h:171

◆ test_hosted_mode_set_get()

meshx_err_t test_hosted_mode_set_get ( void )
static
729{
730 MESHX_LOGD(MODULE_ID_COMMON, "Test: hosted mode set/get");
731
732 if (!test_state.gpio_initialized) {
733 meshx_err_t result = meshx_gpio_init();
734 if (result != MESHX_SUCCESS) return result;
735 test_state.gpio_initialized = true;
736 }
738
739 /* Default should be non-hosted */
741 if (mode != MESHX_GPIO_MODE_NON_HOSTED) {
742 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: Default mode should be NON_HOSTED");
743 return MESHX_FAIL;
744 }
745
746 /* Set to hosted mode */
748 if (result != MESHX_SUCCESS) {
749 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: Set hosted mode: %p", result);
750 return MESHX_FAIL;
751 }
752
754 if (mode != MESHX_GPIO_MODE_HOSTED) {
755 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: Mode should be HOSTED");
756 return MESHX_FAIL;
757 }
758
759 /* Set back to non-hosted */
761 if (result != MESHX_SUCCESS) {
762 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: Set non-hosted mode: %p", result);
763 return MESHX_FAIL;
764 }
765
766 MESHX_LOGI(MODULE_ID_COMMON, "PASS: hosted mode set/get");
767 return MESHX_SUCCESS;
768}
meshx_gpio_hosted_mode_t meshx_gpio_get_hosted_mode(void)
Get current hosted mode.
Definition meshx_gpio.c:786
meshx_gpio_hosted_mode_t
Hosted Mode State.
Definition meshx_gpio_types.h:169

◆ test_interrupt_enable_disable()

meshx_err_t test_interrupt_enable_disable ( void )
static
512{
513 MESHX_LOGD(MODULE_ID_COMMON, "Test: interrupt enable/disable");
514
515 if (!test_state.gpio_initialized) {
516 meshx_err_t result = meshx_gpio_init();
517 if (result != MESHX_SUCCESS) return result;
518 test_state.gpio_initialized = true;
519 }
521
522 uint8_t pin = 62;
523 test_state.pin_modes[pin] = MESHX_GPIO_MODE_INPUT;
524 test_state.pin_initialized[pin] = true;
525
528 if (result != MESHX_SUCCESS) return result;
529
530 result = meshx_gpio_intr_enable(pin, true);
531 if (result != MESHX_SUCCESS) {
532 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: enable: %p", result);
533 return MESHX_FAIL;
534 }
535
536 result = meshx_gpio_intr_enable(pin, false);
537 if (result != MESHX_SUCCESS) {
538 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: disable: %p", result);
539 return MESHX_FAIL;
540 }
541
543 MESHX_LOGI(MODULE_ID_COMMON, "PASS: interrupt enable/disable");
544 return MESHX_SUCCESS;
545}
meshx_err_t meshx_gpio_intr_enable(uint8_t logical_pin, bool enable)
Enable/disable GPIO interrupt.
Definition meshx_gpio.c:591

◆ test_interrupt_register()

meshx_err_t test_interrupt_register ( void )
static
452{
453 MESHX_LOGD(MODULE_ID_COMMON, "Test: interrupt register");
454
455 if (!test_state.gpio_initialized) {
456 meshx_err_t result = meshx_gpio_init();
457 if (result != MESHX_SUCCESS) return result;
458 test_state.gpio_initialized = true;
459 }
460
461 uint8_t pin = 60;
462 test_state.pin_modes[pin] = MESHX_GPIO_MODE_INPUT;
463 test_state.pin_initialized[pin] = true;
465
468 if (result != MESHX_SUCCESS) {
469 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: register_intr: %p", result);
470 return MESHX_FAIL;
471 }
472
473 test_state.interrupt_registered[pin] = true;
475
476 MESHX_LOGI(MODULE_ID_COMMON, "PASS: interrupt register");
477 return MESHX_SUCCESS;
478}

◆ test_interrupt_register_invalid()

meshx_err_t test_interrupt_register_invalid ( void )
static
481{
482 MESHX_LOGD(MODULE_ID_COMMON, "Test: interrupt register invalid");
483
484 if (!test_state.gpio_initialized) {
485 meshx_err_t result = meshx_gpio_init();
486 if (result != MESHX_SUCCESS) return result;
487 test_state.gpio_initialized = true;
488 }
490
491 uint8_t pin = 61;
492 test_state.pin_modes[pin] = MESHX_GPIO_MODE_INPUT;
493 test_state.pin_initialized[pin] = true;
494
496 if (result != MESHX_INVALID_ARG) {
497 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: NULL cb should fail, got: %p", result);
498 return MESHX_FAIL;
499 }
500
502 if (result != MESHX_ERR_GPIO_INTR_NOT_SUPPORTED) {
503 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: DISABLED type should fail, got: %p", result);
504 return MESHX_FAIL;
505 }
506
507 MESHX_LOGI(MODULE_ID_COMMON, "PASS: interrupt register invalid");
508 return MESHX_SUCCESS;
509}
@ MESHX_ERR_GPIO_INTR_NOT_SUPPORTED
Definition meshx_err.h:66
@ MESHX_GPIO_INTR_DISABLED
Definition meshx_gpio_types.h:29

◆ test_set_level_all_modes()

meshx_err_t test_set_level_all_modes ( void )
static
266{
267 MESHX_LOGD(MODULE_ID_COMMON, "Test: set_level all modes");
268
269 if (!test_state.gpio_initialized) {
270 meshx_err_t result = meshx_gpio_init();
271 if (result != MESHX_SUCCESS) return result;
272 test_state.gpio_initialized = true;
273 }
274
275 const struct {
277 const char* name;
278 bool should_succeed;
279 } tests[] = {
280 {MESHX_GPIO_MODE_INPUT, "INPUT", false},
281 {MESHX_GPIO_MODE_OUTPUT, "OUTPUT", true},
282 {MESHX_GPIO_MODE_INPUT_OUTPUT, "INPUT_OUTPUT", true},
283 {MESHX_GPIO_MODE_OPEN_DRAIN, "OPEN_DRAIN", true},
284 {MESHX_GPIO_MODE_OPEN_DRAIN_INPUT_OUTPUT, "OPEN_DRAIN_IO", true},
285 {MESHX_GPIO_MODE_PWM_OUTPUT, "PWM_OUTPUT", true},
286 };
287
288 /* Set pin count to accommodate pins up to 25 */
290
291 for (int i = 0; i < 6; i++) {
292 uint8_t pin = 4 + i;
293 test_state.pin_modes[pin] = tests[i].mode;
294 test_state.pin_initialized[pin] = true;
295
296 /* Set the actual mode in runtime config */
297 meshx_gpio_test_set_pin_mode(pin, tests[i].mode);
298
299 meshx_err_t result = meshx_gpio_set_level(pin, 1);
300
301 if (tests[i].should_succeed && result != MESHX_SUCCESS) {
302 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: set_level on %s should succeed, got: %d", tests[i].name, result);
303 return MESHX_FAIL;
304 }
305 if (!tests[i].should_succeed && result != MESHX_ERR_GPIO_INVALID_MODE) {
306 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: set_level on %s should fail, got: %d", tests[i].name, result);
307 return MESHX_FAIL;
308 }
309 }
310
311 MESHX_LOGI(MODULE_ID_COMMON, "PASS: set_level all modes");
312 return MESHX_SUCCESS;
313}
@ MESHX_ERR_GPIO_INVALID_MODE
Definition meshx_err.h:64
@ MESHX_GPIO_MODE_OPEN_DRAIN
Definition meshx_gpio.h:32

◆ test_set_level_invalid()

meshx_err_t test_set_level_invalid ( void )
static
198{
199 MESHX_LOGD(MODULE_ID_COMMON, "Test: set_level invalid inputs");
200
201 if (!test_state.gpio_initialized) {
202 meshx_err_t result = meshx_gpio_init();
203 if (result != MESHX_SUCCESS) return result;
204 test_state.gpio_initialized = true;
205 }
206 /* Ensure pin count is sufficient for valid pins first */
208
209 /* Test out of range pin */
210 uint8_t out_of_range_pin = 128;
211 meshx_err_t result = meshx_gpio_set_level(out_of_range_pin, 1);
212 if (result != MESHX_ERR_GPIO_INVALID_PIN) {
213 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: set_level(128) should return INVALID_PIN, got: %p", result);
214 return MESHX_FAIL;
215 }
216
217 /* Shrink count and test again */
219 out_of_range_pin = 10;
220 result = meshx_gpio_set_level(out_of_range_pin, 1);
221 if (result != MESHX_ERR_GPIO_INVALID_PIN) {
222 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: set_level(10) after shrink should return INVALID_PIN, got: %p", result);
223 return MESHX_FAIL;
224 }
225
226 /* Restore count for subsequent tests */
228
229 /* Test invalid level value */
230 uint8_t output_pin = 10;
231 test_state.pin_modes[output_pin] = MESHX_GPIO_MODE_OUTPUT;
232 test_state.pin_initialized[output_pin] = true;
233
234 result = meshx_gpio_set_level(output_pin, 2);
235 if (result != MESHX_ERR_GPIO_INVALID_LEVEL) {
236 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: set_level(2) should return INVALID_LEVEL, got: %p", result);
237 return MESHX_FAIL;
238 }
239
240 result = meshx_gpio_set_level(output_pin, 255);
241 if (result != MESHX_ERR_GPIO_INVALID_LEVEL) {
242 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: set_level(255) should return INVALID_LEVEL, got: %p", result);
243 return MESHX_FAIL;
244 }
245
246 /* Test on input pin */
247 uint8_t input_pin = 10; // Use a valid pin (within the 11 pins we set earlier)
249 test_state.pin_modes[input_pin] = MESHX_GPIO_MODE_INPUT;
250 test_state.pin_initialized[input_pin] = true;
251
252 result = meshx_gpio_set_level(input_pin, 1);
253 if (result != MESHX_ERR_GPIO_INVALID_MODE) {
254 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: set_level on input should return INVALID_MODE, got: %p", result);
255 return MESHX_FAIL;
256 }
257
258 // Restore pin count for subsequent tests
260
261 MESHX_LOGI(MODULE_ID_COMMON, "PASS: set_level invalid inputs");
262 return MESHX_SUCCESS;
263}
@ MESHX_ERR_GPIO_INVALID_PIN
Definition meshx_err.h:63
@ MESHX_ERR_GPIO_INVALID_LEVEL
Definition meshx_err.h:65

◆ test_set_level_valid()

meshx_err_t test_set_level_valid ( void )
static
157{
158 MESHX_LOGD(MODULE_ID_COMMON, "Test: set_level valid inputs");
159
160 if (!test_state.gpio_initialized) {
161 meshx_err_t result = meshx_gpio_init();
162 if (result != MESHX_SUCCESS) return result;
163 test_state.gpio_initialized = true;
164 }
165
166 /* Ensure pin count is sufficient for valid tests */
168
169 const uint8_t test_pins[] = {0, 1, 2, 3};
170 for (size_t i = 0; i < 4; i++) {
171 test_state.pin_modes[test_pins[i]] = MESHX_GPIO_MODE_OUTPUT;
172 test_state.pin_initialized[test_pins[i]] = true;
173 }
174
175 /* Test setting level 0 */
176 for (size_t i = 0; i < 4; i++) {
177 meshx_err_t result = meshx_gpio_set_level(test_pins[i], 0);
178 if (result != MESHX_SUCCESS) {
179 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: set_level(0) pin %u: %d", test_pins[i], result);
180 return MESHX_FAIL;
181 }
182 }
183
184 /* Test setting level 1 */
185 for (size_t i = 0; i < 4; i++) {
186 meshx_err_t result = meshx_gpio_set_level(test_pins[i], 1);
187 if (result != MESHX_SUCCESS) {
188 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: set_level(1) pin %u: %d", test_pins[i], result);
189 return MESHX_FAIL;
190 }
191 }
192
193 MESHX_LOGI(MODULE_ID_COMMON, "PASS: set_level valid inputs");
194 return MESHX_SUCCESS;
195}

◆ test_toggle_invalid_mode()

meshx_err_t test_toggle_invalid_mode ( void )
static
423{
424 MESHX_LOGD(MODULE_ID_COMMON, "Test: toggle invalid mode");
425
426 if (!test_state.gpio_initialized) {
427 meshx_err_t result = meshx_gpio_init();
428 if (result != MESHX_SUCCESS) return result;
429 test_state.gpio_initialized = true;
430 }
431
432 uint8_t pin = 51;
433 test_state.pin_modes[pin] = MESHX_GPIO_MODE_INPUT;
434 test_state.pin_initialized[pin] = true;
436
437 meshx_err_t result = meshx_gpio_toggle(pin);
438 if (result != MESHX_ERR_GPIO_INVALID_MODE) {
439 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: toggle on input should fail, got: %p", result);
440 return MESHX_FAIL;
441 }
442
443 MESHX_LOGI(MODULE_ID_COMMON, "PASS: toggle invalid mode");
444 return MESHX_SUCCESS;
445}
meshx_err_t meshx_gpio_toggle(uint8_t logical_pin)
Toggle GPIO pin level.
Definition meshx_gpio.c:453

◆ test_toggle_valid()

meshx_err_t test_toggle_valid ( void )
static
390{
391 MESHX_LOGD(MODULE_ID_COMMON, "Test: toggle valid");
392
393 if (!test_state.gpio_initialized) {
394 meshx_err_t result = meshx_gpio_init();
395 if (result != MESHX_SUCCESS) return result;
396 test_state.gpio_initialized = true;
397 }
398
399 uint8_t pin = 50;
400 test_state.pin_modes[pin] = MESHX_GPIO_MODE_OUTPUT;
401 test_state.pin_initialized[pin] = true;
403
404 meshx_gpio_set_level(pin, 0);
405
406 meshx_err_t result = meshx_gpio_toggle(pin);
407 if (result != MESHX_SUCCESS) {
408 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: toggle 1: %p", result);
409 return MESHX_FAIL;
410 }
411
412 result = meshx_gpio_toggle(pin);
413 if (result != MESHX_SUCCESS) {
414 MESHX_LOGE(MODULE_ID_COMMON, "FAIL: toggle 2: %p", result);
415 return MESHX_FAIL;
416 }
417
418 MESHX_LOGI(MODULE_ID_COMMON, "PASS: toggle valid");
419 return MESHX_SUCCESS;
420}

Variable Documentation

◆ test_state

gpio_test_state_t test_state
static