1 /*
2  * Copyright (c) 2024 Fabian Blatz <fabianblatz@gmail.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 
9 #include <zephyr/drivers/stepper.h>
10 #include <zephyr/drivers/stepper/stepper_fake.h>
11 #include <zephyr/fff.h>
12 #include <zephyr/shell/shell.h>
13 #include <zephyr/shell/shell_dummy.h>
14 #include <zephyr/ztest.h>
15 #include <zephyr/sys/util.h>
16 
17 #define FAKE_STEPPER_CONTROLLER DEVICE_DT_NAME(DT_NODELABEL(fake_stepper_controller))
18 #define FAKE_STEPPER_DRIVER     DEVICE_DT_NAME(DT_NODELABEL(fake_stepper_driver))
19 
20 /* Global variables */
21 static const struct device *const fake_stepper_driver_dev =
22 	DEVICE_DT_GET(DT_NODELABEL(fake_stepper_driver));
23 static const struct device *const fake_stepper_controller_dev =
24 	DEVICE_DT_GET(DT_NODELABEL(fake_stepper_controller));
25 
26 DEFINE_FFF_GLOBALS;
27 
28 #define ASSERT_STEPPER_FUNC_CALLED(stepper_fake_func, stepper_fake_dev, retval)                    \
29 	zassert_ok(retval, "failed to execute shell command (err %d)", retval);                    \
30 	zassert_equal(stepper_fake_func.call_count, 1,                                             \
31 		      STRINGIFY(stepper_fake_func) " function not called");                        \
32 	zassert_equal(stepper_fake_func.arg0_val, stepper_fake_dev, "wrong device pointer")
33 
stepper_shell_setup(void)34 static void *stepper_shell_setup(void)
35 {
36 	const struct shell *sh = shell_backend_dummy_get_ptr();
37 
38 	/* Wait for the initialization of the shell dummy backend. */
39 	WAIT_FOR(shell_ready(sh), 20000, k_msleep(1));
40 	zassert_true(shell_ready(sh), "timed out waiting for dummy shell backend");
41 
42 	return NULL;
43 }
44 
45 ZTEST_SUITE(stepper_shell, NULL, stepper_shell_setup, NULL, NULL, NULL);
46 
ZTEST(stepper_shell,test_stepper_drv_enable)47 ZTEST(stepper_shell, test_stepper_drv_enable)
48 {
49 	const struct shell *sh = shell_backend_dummy_get_ptr();
50 	int err = shell_execute_cmd(sh, "stepper enable " FAKE_STEPPER_DRIVER);
51 
52 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_drv_enable_fake, fake_stepper_driver_dev, err);
53 	zassert_equal(err, 0, "stepper enable could not be executed");
54 }
55 
ZTEST(stepper_shell,test_stepper_drv_disable)56 ZTEST(stepper_shell, test_stepper_drv_disable)
57 {
58 	const struct shell *sh = shell_backend_dummy_get_ptr();
59 	int err = shell_execute_cmd(sh, "stepper disable " FAKE_STEPPER_DRIVER);
60 
61 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_drv_disable_fake, fake_stepper_driver_dev, err);
62 	zassert_equal(err, 0, "stepper disable could not be executed");
63 }
64 
ZTEST(stepper_shell,test_stepper_move_by)65 ZTEST(stepper_shell, test_stepper_move_by)
66 {
67 	const struct shell *sh = shell_backend_dummy_get_ptr();
68 	int err = shell_execute_cmd(sh, "stepper move_by " FAKE_STEPPER_CONTROLLER " 1000");
69 
70 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_move_by_fake, fake_stepper_controller_dev, err);
71 	zassert_equal(fake_stepper_move_by_fake.arg1_val, 1000, "wrong microsteps value");
72 }
73 
ZTEST(stepper_shell,test_stepper_set_microstep_interval)74 ZTEST(stepper_shell, test_stepper_set_microstep_interval)
75 {
76 	const struct shell *sh = shell_backend_dummy_get_ptr();
77 	int err = shell_execute_cmd(sh, "stepper set_microstep_interval " FAKE_STEPPER_CONTROLLER
78 					" 200");
79 
80 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_set_microstep_interval_fake,
81 				   fake_stepper_controller_dev, err);
82 	zassert_equal(fake_stepper_set_microstep_interval_fake.arg1_val, 200,
83 		      "wrong step_interval value");
84 }
85 
ZTEST(stepper_shell,test_stepper_drv_set_micro_step_res)86 ZTEST(stepper_shell, test_stepper_drv_set_micro_step_res)
87 {
88 	const struct shell *sh = shell_backend_dummy_get_ptr();
89 	int err = shell_execute_cmd(sh, "stepper set_micro_step_res " FAKE_STEPPER_DRIVER " 64");
90 
91 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_drv_set_micro_step_res_fake,
92 				   fake_stepper_driver_dev, err);
93 	zassert_equal(fake_stepper_drv_set_micro_step_res_fake.arg1_val, 64,
94 		      "wrong micro steps resolution value");
95 }
96 
ZTEST(stepper_shell,test_stepper_drv_set_micro_step_res_invalid_value)97 ZTEST(stepper_shell, test_stepper_drv_set_micro_step_res_invalid_value)
98 {
99 	const struct shell *sh = shell_backend_dummy_get_ptr();
100 	int err = shell_execute_cmd(sh, "stepper set_micro_step_res " FAKE_STEPPER_DRIVER " 111");
101 
102 	zassert_not_equal(err, 0, " executed set_micro_step_res with invalid micro steps value");
103 }
104 
ZTEST(stepper_shell,test_stepper_drv_get_micro_step_res)105 ZTEST(stepper_shell, test_stepper_drv_get_micro_step_res)
106 {
107 	const struct shell *sh = shell_backend_dummy_get_ptr();
108 	int err = shell_execute_cmd(sh, "stepper get_micro_step_res " FAKE_STEPPER_DRIVER);
109 
110 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_drv_get_micro_step_res_fake,
111 				   fake_stepper_driver_dev, err);
112 }
113 
ZTEST(stepper_shell,test_stepper_set_reference_position)114 ZTEST(stepper_shell, test_stepper_set_reference_position)
115 {
116 	const struct shell *sh = shell_backend_dummy_get_ptr();
117 	int err = shell_execute_cmd(sh, "stepper set_reference_position " FAKE_STEPPER_CONTROLLER
118 					" 100");
119 
120 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_set_reference_position_fake,
121 				   fake_stepper_controller_dev, err);
122 	zassert_equal(fake_stepper_set_reference_position_fake.arg1_val, 100,
123 		      "wrong actual position value");
124 }
125 
ZTEST(stepper_shell,test_stepper_get_actual_position)126 ZTEST(stepper_shell, test_stepper_get_actual_position)
127 {
128 	const struct shell *sh = shell_backend_dummy_get_ptr();
129 	int err = shell_execute_cmd(sh, "stepper get_actual_position " FAKE_STEPPER_CONTROLLER);
130 
131 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_get_actual_position_fake,
132 				   fake_stepper_controller_dev, err);
133 }
134 
ZTEST(stepper_shell,test_stepper_move_to)135 ZTEST(stepper_shell, test_stepper_move_to)
136 {
137 	const struct shell *sh = shell_backend_dummy_get_ptr();
138 	int err = shell_execute_cmd(sh, "stepper move_to " FAKE_STEPPER_CONTROLLER " 200");
139 
140 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_move_to_fake, fake_stepper_controller_dev, err);
141 	zassert_equal(fake_stepper_move_to_fake.arg1_val, 200, "wrong target position value");
142 }
143 
ZTEST(stepper_shell,test_stepper_run)144 ZTEST(stepper_shell, test_stepper_run)
145 {
146 	const struct shell *sh = shell_backend_dummy_get_ptr();
147 	int err = shell_execute_cmd(sh, "stepper run " FAKE_STEPPER_CONTROLLER " positive");
148 
149 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_run_fake, fake_stepper_controller_dev, err);
150 	zassert_equal(fake_stepper_run_fake.arg1_val, STEPPER_DIRECTION_POSITIVE,
151 		      "wrong direction value");
152 }
153 
ZTEST(stepper_shell,test_stepper_run_invalid_direction)154 ZTEST(stepper_shell, test_stepper_run_invalid_direction)
155 {
156 	const struct shell *sh = shell_backend_dummy_get_ptr();
157 	int err = shell_execute_cmd(sh, "stepper run " FAKE_STEPPER_CONTROLLER " foo");
158 
159 	zassert_not_equal(err, 0, " executed run with invalid direction value");
160 }
161 
ZTEST(stepper_shell,test_stepper_stop)162 ZTEST(stepper_shell, test_stepper_stop)
163 {
164 	const struct shell *sh = shell_backend_dummy_get_ptr();
165 	int err = shell_execute_cmd(sh, "stepper stop " FAKE_STEPPER_CONTROLLER);
166 
167 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_stop_fake, fake_stepper_controller_dev, err);
168 	zassert_equal(err, 0, "stepper stop could not be executed");
169 }
170 
ZTEST(stepper_shell,test_stepper_controller_info)171 ZTEST(stepper_shell, test_stepper_controller_info)
172 {
173 	const struct shell *sh = shell_backend_dummy_get_ptr();
174 	int err = shell_execute_cmd(sh, "stepper control_info " FAKE_STEPPER_CONTROLLER);
175 
176 	zassert_ok(err, "failed to execute shell command (err %d)", err);
177 
178 	zassert_equal(fake_stepper_is_moving_fake.call_count, 1, "is_moving function not called");
179 	zassert_equal(fake_stepper_get_actual_position_fake.call_count, 1,
180 		      "get_actual_position function not called");
181 }
182 
ZTEST(stepper_shell,test_stepper_info)183 ZTEST(stepper_shell, test_stepper_info)
184 {
185 	const struct shell *sh = shell_backend_dummy_get_ptr();
186 	int err = shell_execute_cmd(sh, "stepper info " FAKE_STEPPER_DRIVER);
187 
188 	zassert_ok(err, "failed to execute shell command (err %d)", err);
189 
190 	zassert_equal(fake_stepper_drv_get_micro_step_res_fake.call_count, 1,
191 		      "get_micro_step_res function not called");
192 }
193