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_NAME DEVICE_DT_NAME(DT_NODELABEL(fake_stepper))
18 
19 /* Global variables */
20 static const struct device *const fake_stepper_dev = DEVICE_DT_GET(DT_NODELABEL(fake_stepper));
21 
22 DEFINE_FFF_GLOBALS;
23 
24 #define ASSERT_STEPPER_FUNC_CALLED(stepper_fake_func, retval)                                      \
25 	zassert_ok(retval, "failed to execute shell command (err %d)", retval);                    \
26 	zassert_equal(stepper_fake_func.call_count, 1,                                             \
27 		      STRINGIFY(stepper_fake_func) " function not called");                        \
28 	zassert_equal(stepper_fake_func.arg0_val, fake_stepper_dev, "wrong device pointer")
29 
stepper_shell_setup(void)30 static void *stepper_shell_setup(void)
31 {
32 	const struct shell *sh = shell_backend_dummy_get_ptr();
33 
34 	/* Wait for the initialization of the shell dummy backend. */
35 	WAIT_FOR(shell_ready(sh), 20000, k_msleep(1));
36 	zassert_true(shell_ready(sh), "timed out waiting for dummy shell backend");
37 
38 	return NULL;
39 }
40 
41 ZTEST_SUITE(stepper_shell, NULL, stepper_shell_setup, NULL, NULL, NULL);
42 
ZTEST(stepper_shell,test_stepper_enable)43 ZTEST(stepper_shell, test_stepper_enable)
44 {
45 	const struct shell *sh = shell_backend_dummy_get_ptr();
46 	int err = shell_execute_cmd(sh, "stepper enable " FAKE_STEPPER_NAME " on");
47 
48 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_enable_fake, err);
49 	zassert_equal(fake_stepper_enable_fake.arg1_val, true, "wrong enable value");
50 
51 	RESET_FAKE(fake_stepper_enable);
52 
53 	err = shell_execute_cmd(sh, "stepper enable " FAKE_STEPPER_NAME " off");
54 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_enable_fake, err);
55 	zassert_equal(fake_stepper_enable_fake.arg1_val, false, "wrong enable value");
56 }
57 
ZTEST(stepper_shell,test_stepper_move_by)58 ZTEST(stepper_shell, test_stepper_move_by)
59 {
60 	const struct shell *sh = shell_backend_dummy_get_ptr();
61 	int err = shell_execute_cmd(sh, "stepper move_by " FAKE_STEPPER_NAME " 1000");
62 
63 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_move_by_fake, err);
64 	zassert_equal(fake_stepper_move_by_fake.arg1_val, 1000, "wrong microsteps value");
65 }
66 
ZTEST(stepper_shell,test_stepper_set_microstep_interval)67 ZTEST(stepper_shell, test_stepper_set_microstep_interval)
68 {
69 	const struct shell *sh = shell_backend_dummy_get_ptr();
70 	int err = shell_execute_cmd(sh, "stepper set_microstep_interval " FAKE_STEPPER_NAME " 200");
71 
72 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_set_microstep_interval_fake, err);
73 	zassert_equal(fake_stepper_set_microstep_interval_fake.arg1_val, 200,
74 		      "wrong step_interval value");
75 }
76 
ZTEST(stepper_shell,test_stepper_set_micro_step_res)77 ZTEST(stepper_shell, test_stepper_set_micro_step_res)
78 {
79 	const struct shell *sh = shell_backend_dummy_get_ptr();
80 	int err = shell_execute_cmd(sh, "stepper set_micro_step_res " FAKE_STEPPER_NAME " 64");
81 
82 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_set_micro_step_res_fake, err);
83 	zassert_equal(fake_stepper_set_micro_step_res_fake.arg1_val, 64,
84 		      "wrong micro steps resolution value");
85 }
86 
ZTEST(stepper_shell,test_stepper_set_micro_step_res_invalid_value)87 ZTEST(stepper_shell, test_stepper_set_micro_step_res_invalid_value)
88 {
89 	const struct shell *sh = shell_backend_dummy_get_ptr();
90 	int err = shell_execute_cmd(sh, "stepper set_micro_step_res " FAKE_STEPPER_NAME " 111");
91 
92 	zassert_not_equal(err, 0, " executed set_micro_step_res with invalid micro steps value");
93 }
94 
ZTEST(stepper_shell,test_stepper_get_micro_step_res)95 ZTEST(stepper_shell, test_stepper_get_micro_step_res)
96 {
97 	const struct shell *sh = shell_backend_dummy_get_ptr();
98 	int err = shell_execute_cmd(sh, "stepper get_micro_step_res " FAKE_STEPPER_NAME);
99 
100 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_get_micro_step_res_fake, err);
101 }
102 
ZTEST(stepper_shell,test_stepper_set_reference_position)103 ZTEST(stepper_shell, test_stepper_set_reference_position)
104 {
105 	const struct shell *sh = shell_backend_dummy_get_ptr();
106 	int err = shell_execute_cmd(sh, "stepper set_reference_position " FAKE_STEPPER_NAME " 100");
107 
108 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_set_reference_position_fake, err);
109 	zassert_equal(fake_stepper_set_reference_position_fake.arg1_val, 100,
110 		      "wrong actual position value");
111 }
112 
ZTEST(stepper_shell,test_stepper_get_actual_position)113 ZTEST(stepper_shell, test_stepper_get_actual_position)
114 {
115 	const struct shell *sh = shell_backend_dummy_get_ptr();
116 	int err = shell_execute_cmd(sh, "stepper get_actual_position " FAKE_STEPPER_NAME);
117 
118 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_get_actual_position_fake, err);
119 }
120 
ZTEST(stepper_shell,test_stepper_move_to)121 ZTEST(stepper_shell, test_stepper_move_to)
122 {
123 	const struct shell *sh = shell_backend_dummy_get_ptr();
124 	int err = shell_execute_cmd(sh, "stepper move_to " FAKE_STEPPER_NAME " 200");
125 
126 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_move_to_fake, err);
127 	zassert_equal(fake_stepper_move_to_fake.arg1_val, 200, "wrong target position value");
128 }
129 
ZTEST(stepper_shell,test_stepper_run)130 ZTEST(stepper_shell, test_stepper_run)
131 {
132 	const struct shell *sh = shell_backend_dummy_get_ptr();
133 	int err = shell_execute_cmd(sh, "stepper run " FAKE_STEPPER_NAME " positive");
134 
135 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_run_fake, err);
136 	zassert_equal(fake_stepper_run_fake.arg1_val, STEPPER_DIRECTION_POSITIVE,
137 		      "wrong direction value");
138 }
139 
ZTEST(stepper_shell,test_stepper_run_invalid_direction)140 ZTEST(stepper_shell, test_stepper_run_invalid_direction)
141 {
142 	const struct shell *sh = shell_backend_dummy_get_ptr();
143 	int err = shell_execute_cmd(sh, "stepper run " FAKE_STEPPER_NAME " foo");
144 
145 	zassert_not_equal(err, 0, " executed run with invalid direction value");
146 }
147 
ZTEST(stepper_shell,test_stepper_stop)148 ZTEST(stepper_shell, test_stepper_stop)
149 {
150 	const struct shell *sh = shell_backend_dummy_get_ptr();
151 	int err = shell_execute_cmd(sh, "stepper stop " FAKE_STEPPER_NAME);
152 
153 	ASSERT_STEPPER_FUNC_CALLED(fake_stepper_stop_fake, err);
154 	zassert_equal(err, 0, "stepper stop could not be executed");
155 }
156 
ZTEST(stepper_shell,test_stepper_info)157 ZTEST(stepper_shell, test_stepper_info)
158 {
159 	const struct shell *sh = shell_backend_dummy_get_ptr();
160 	int err = shell_execute_cmd(sh, "stepper info " FAKE_STEPPER_NAME);
161 
162 	zassert_ok(err, "failed to execute shell command (err %d)", err);
163 
164 	zassert_equal(fake_stepper_is_moving_fake.call_count, 1, "is_moving function not called");
165 	zassert_equal(fake_stepper_get_actual_position_fake.call_count, 1,
166 		      "get_actual_position function not called");
167 	zassert_equal(fake_stepper_get_micro_step_res_fake.call_count, 1,
168 		      "get_micro_step_res function not called");
169 }
170