1 /*
2 * Copyright (c) 2023 Prevas A/S
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8
9 #include <zephyr/drivers/rtc.h>
10 #include <zephyr/drivers/rtc/rtc_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
16 /**
17 * @addtogroup t_rtc_driver
18 * @{
19 * @defgroup t_rtc_api test_rtc_shell
20 * @}
21 */
22
23 DEFINE_FFF_GLOBALS;
24
25 #define FAKE_RTC_NAME DEVICE_DT_NAME(DT_NODELABEL(fake_rtc))
26
27 /* Helper to mock time */
28 struct time_mock_val {
29 int ret_val;
30 struct rtc_time rtc;
31 };
32 static struct time_mock_val get_time_mock;
33 static struct time_mock_val set_time_mock;
34
rtc_fake_get_time_mock(const struct device * dev,struct rtc_time * rtc)35 static int rtc_fake_get_time_mock(const struct device *dev, struct rtc_time *rtc)
36 {
37 ARG_UNUSED(dev);
38
39 *rtc = get_time_mock.rtc;
40 return get_time_mock.ret_val;
41 }
42
rtc_fake_set_time_mock(const struct device * dev,const struct rtc_time * rtc)43 static int rtc_fake_set_time_mock(const struct device *dev, const struct rtc_time *rtc)
44 {
45 ARG_UNUSED(dev);
46
47 set_time_mock.rtc = *rtc;
48 return set_time_mock.ret_val;
49 }
50
configure_set_time_mock(int ret_val)51 static void configure_set_time_mock(int ret_val)
52 {
53 set_time_mock.ret_val = ret_val;
54
55 rtc_fake_set_time_fake.custom_fake = rtc_fake_set_time_mock;
56 }
57
configure_get_time_mock(int ret_val)58 static void configure_get_time_mock(int ret_val)
59 {
60 get_time_mock.ret_val = ret_val;
61 get_time_mock.rtc.tm_year = 2023 - 1900; /* rtc_time year offset */
62 get_time_mock.rtc.tm_mon = 12 - 1; /* rtc_time month offset */
63 get_time_mock.rtc.tm_mday = 24;
64 get_time_mock.rtc.tm_hour = 12;
65 get_time_mock.rtc.tm_min = 34;
66 get_time_mock.rtc.tm_sec = 56;
67
68 rtc_fake_get_time_fake.custom_fake = rtc_fake_get_time_mock;
69 }
70
assert_set_time(int year,int mon,int mday,int hour,int min,int sec)71 static void assert_set_time(int year, int mon, int mday, int hour, int min, int sec)
72 {
73 const struct rtc_time *rtctime;
74
75 zassert_equal(rtc_fake_set_time_fake.call_count, 1, "set_time not called");
76
77 rtctime = &set_time_mock.rtc;
78
79 zassert_equal(year, rtctime->tm_year + 1900, "Year mismatch");
80 zassert_equal(mon, rtctime->tm_mon + 1, "Month mismatch");
81 zassert_equal(mday, rtctime->tm_mday, "Day mismatch");
82 zassert_equal(hour, rtctime->tm_hour, "Hour mismatch");
83 zassert_equal(min, rtctime->tm_min, "Minute mismatch");
84 zassert_equal(sec, rtctime->tm_sec, "Second mismatch");
85 }
86
ZTEST(rtc_shell,test_rtc_get_ok)87 ZTEST(rtc_shell, test_rtc_get_ok)
88 {
89 const struct shell *sh = shell_backend_dummy_get_ptr();
90 int err;
91
92 configure_get_time_mock(0);
93
94 err = shell_execute_cmd(sh, "rtc get " FAKE_RTC_NAME);
95 zassert_ok(err, "failed to execute shell command (err %d)", err);
96 zassert_equal(rtc_fake_get_time_fake.call_count, 1, "get_time not called");
97 }
98
ZTEST(rtc_shell,test_rtc_get_not_initialized)99 ZTEST(rtc_shell, test_rtc_get_not_initialized)
100 {
101 const struct shell *sh = shell_backend_dummy_get_ptr();
102 int err;
103
104 configure_get_time_mock(-ENODATA);
105
106 err = shell_execute_cmd(sh, "rtc get " FAKE_RTC_NAME);
107 zassert_ok(err, "shell command (err %d)", err);
108 zassert_equal(rtc_fake_get_time_fake.call_count, 1, "get_time not called");
109 }
110
ZTEST(rtc_shell,test_rtc_get_error)111 ZTEST(rtc_shell, test_rtc_get_error)
112 {
113 const struct shell *sh = shell_backend_dummy_get_ptr();
114 int err;
115
116 configure_get_time_mock(-1);
117
118 err = shell_execute_cmd(sh, "rtc get " FAKE_RTC_NAME);
119 zassert_true(err != 0, "shell command (err %d)", err);
120 zassert_equal(rtc_fake_get_time_fake.call_count, 1, "get_time not called");
121 }
122
ZTEST(rtc_shell,test_rtc_set_date)123 ZTEST(rtc_shell, test_rtc_set_date)
124 {
125 const struct shell *sh = shell_backend_dummy_get_ptr();
126 int err;
127
128 rtc_fake_set_time_fake.return_val = 0;
129
130 configure_get_time_mock(0);
131 configure_set_time_mock(0);
132
133 err = shell_execute_cmd(sh, "rtc set " FAKE_RTC_NAME " 2022-05-17");
134 zassert_ok(err, "failed to execute shell command (err %d)", err);
135 zassert_equal(rtc_fake_get_time_fake.call_count, 1, "get_time not called");
136
137 assert_set_time(2022, 5, 17, get_time_mock.rtc.tm_hour, get_time_mock.rtc.tm_min,
138 get_time_mock.rtc.tm_sec);
139 }
140
ZTEST(rtc_shell,test_rtc_set_time)141 ZTEST(rtc_shell, test_rtc_set_time)
142 {
143 const struct shell *sh = shell_backend_dummy_get_ptr();
144 int err;
145
146 configure_get_time_mock(0);
147 configure_set_time_mock(0);
148
149 err = shell_execute_cmd(sh, "rtc set " FAKE_RTC_NAME " 23:45:16");
150 zassert_ok(err, "failed to execute shell command (err %d)", err);
151 zassert_equal(rtc_fake_get_time_fake.call_count, 1, "get_time not called");
152
153 assert_set_time(2023, 12, 24, 23, 45, 16);
154 }
155
ZTEST(rtc_shell,test_rtc_set_full)156 ZTEST(rtc_shell, test_rtc_set_full)
157 {
158 const struct shell *sh = shell_backend_dummy_get_ptr();
159 int err;
160
161 configure_get_time_mock(0);
162 configure_set_time_mock(0);
163
164 err = shell_execute_cmd(sh, "rtc set " FAKE_RTC_NAME " 2022-05-17T23:45:16");
165 zassert_ok(err, "failed to execute shell command (err %d)", err);
166 zassert_equal(rtc_fake_get_time_fake.call_count, 1, "get_time not called");
167
168 assert_set_time(2022, 5, 17, 23, 45, 16);
169 }
170
ZTEST(rtc_shell,test_rtc_set_error)171 ZTEST(rtc_shell, test_rtc_set_error)
172 {
173 const struct shell *sh = shell_backend_dummy_get_ptr();
174 int err;
175
176 configure_get_time_mock(0);
177 configure_set_time_mock(-EINVAL);
178
179 err = shell_execute_cmd(sh, "rtc set " FAKE_RTC_NAME " 2022:05:17T23:45:16");
180 zassert_true(err != 0, "failed to execute shell command (err %d)", err);
181 zassert_equal(rtc_fake_get_time_fake.call_count, 1, "get_time not called");
182 zassert_equal(rtc_fake_set_time_fake.call_count, 0, "set_time called");
183 }
184
rtc_shell_setup(void)185 static void *rtc_shell_setup(void)
186 {
187 const struct shell *sh = shell_backend_dummy_get_ptr();
188
189 /* Wait for the initialization of the shell dummy backend. */
190 WAIT_FOR(shell_ready(sh), 20000, k_msleep(1));
191 zassert_true(shell_ready(sh), "timed out waiting for dummy shell backend");
192
193 return NULL;
194 }
195
196 ZTEST_SUITE(rtc_shell, NULL, rtc_shell_setup, NULL, NULL, NULL);
197