1 /*
2  * Copyright (c) 2020-2023 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "watchdog_test.h"
10 #include "hdf_base.h"
11 #include "hdf_io_service_if.h"
12 #include "hdf_log.h"
13 #include "osal_mem.h"
14 #include "osal_time.h"
15 #include "securec.h"
16 #include "watchdog_if.h"
17 
18 #define HDF_LOG_TAG watchdog_test
19 static int32_t g_wdtState = 0;
20 
21 struct WatchdogTestEntry {
22     int cmd;
23     int32_t (*func)(struct WatchdogTester *tester);
24 };
25 
WatchdogTestGetTestConfig(struct WatchdogTestConfig * config)26 static int32_t WatchdogTestGetTestConfig(struct WatchdogTestConfig *config)
27 {
28     int32_t ret;
29     struct HdfSBuf *reply = NULL;
30     struct HdfIoService *service = NULL;
31     const void *buf = NULL;
32     uint32_t len;
33 
34     service = HdfIoServiceBind("WATCHDOG_TEST");
35     if ((service == NULL) || (service->dispatcher == NULL) || (service->dispatcher->Dispatch == NULL)) {
36         HDF_LOGE("WatchdogTestGetTestConfig: service null!");
37         return HDF_ERR_NOT_SUPPORT;
38     }
39 
40     reply = HdfSbufObtain(sizeof(*config) + sizeof(uint64_t));
41     if (reply == NULL) {
42         HDF_LOGE("WatchdogTestGetTestConfig: fail to obtain reply!");
43         HdfIoServiceRecycle(service);
44         return HDF_ERR_MALLOC_FAIL;
45     }
46 
47     ret = service->dispatcher->Dispatch(&service->object, 0, NULL, reply);
48     if (ret != HDF_SUCCESS) {
49         HDF_LOGE("WatchdogTestGetTestConfig: remote dispatch fail, ret: %d!", ret);
50         HdfIoServiceRecycle(service);
51         HdfSbufRecycle(reply);
52         return ret;
53     }
54 
55     if (!HdfSbufReadBuffer(reply, &buf, &len)) {
56         HDF_LOGE("WatchdogTestGetTestConfig: read buf fail!");
57         HdfIoServiceRecycle(service);
58         HdfSbufRecycle(reply);
59         return HDF_ERR_IO;
60     }
61 
62     if (len != sizeof(*config)) {
63         HDF_LOGE("WatchdogTestGetTestConfig: config size:%zu, read size:%u!", sizeof(*config), len);
64         HdfIoServiceRecycle(service);
65         HdfSbufRecycle(reply);
66         return HDF_ERR_IO;
67     }
68 
69     if (memcpy_s(config, sizeof(*config), buf, sizeof(*config)) != EOK) {
70         HDF_LOGE("WatchdogTestGetTestConfig: memcpy buf fail!");
71         HdfIoServiceRecycle(service);
72         HdfSbufRecycle(reply);
73         return HDF_ERR_IO;
74     }
75     HdfIoServiceRecycle(service);
76     HdfSbufRecycle(reply);
77     return HDF_SUCCESS;
78 }
79 
WatchdogTesterGet(void)80 static struct WatchdogTester *WatchdogTesterGet(void)
81 {
82     int32_t ret;
83     static struct WatchdogTester tester;
84 
85     ret = WatchdogTestGetTestConfig(&tester.config);
86     if (ret != HDF_SUCCESS) {
87         HDF_LOGE("WatchdogTesterGet: read config fail, ret: %d!", ret);
88         return NULL;
89     }
90 
91     ret = WatchdogOpen(tester.config.id, &tester.handle);
92     if (ret != HDF_SUCCESS) {
93         if (ret == HDF_ERR_DEVICE_BUSY) {
94             g_wdtState = ret;
95         }
96         HDF_LOGE("WatchdogTesterGet: open watchdog_%d fail, ret: %d!", tester.config.id, ret);
97         return NULL;
98     }
99 
100     return &tester;
101 }
102 
WatchdogTesterPut(struct WatchdogTester * tester)103 static void WatchdogTesterPut(struct WatchdogTester *tester)
104 {
105     if (tester == NULL) {
106         HDF_LOGE("WatchdogTesterPut: tester is null!");
107         return;
108     }
109     WatchdogClose(tester->handle);
110     tester->handle = NULL;
111 }
112 
TestCaseWatchdogSetGetTimeout(struct WatchdogTester * tester)113 static int32_t TestCaseWatchdogSetGetTimeout(struct WatchdogTester *tester)
114 {
115     int32_t ret;
116     uint32_t timeoutGet = 0;
117 
118     ret = WatchdogSetTimeout(tester->handle, tester->config.timeoutSet);
119     if (ret != HDF_SUCCESS) {
120         HDF_LOGE("TestCaseWatchdogSetGetTimeout: set timeout fail, ret: %d!", ret);
121         return ret;
122     }
123     ret = WatchdogGetTimeout(tester->handle, &timeoutGet);
124     if (ret != HDF_SUCCESS) {
125         HDF_LOGE("TestCaseWatchdogSetGetTimeout: get timeout fail, ret: %d!", ret);
126         return ret;
127     }
128     if (tester->config.timeoutSet != timeoutGet) {
129         HDF_LOGE("TestCaseWatchdogSetGetTimeout: set:%u, but get:%u!", tester->config.timeoutSet, timeoutGet);
130         return HDF_FAILURE;
131     }
132 
133     return HDF_SUCCESS;
134 }
135 
TestCaseWatchdogStartStop(struct WatchdogTester * tester)136 static int32_t TestCaseWatchdogStartStop(struct WatchdogTester *tester)
137 {
138     int32_t ret;
139     int32_t status;
140 
141     ret = WatchdogStart(tester->handle);
142     if (ret != HDF_SUCCESS) {
143         HDF_LOGE("TestCaseWatchdogStartStop: satrt fail, ret: %d!", ret);
144         return ret;
145     }
146     status = WATCHDOG_STOP;
147     ret = WatchdogGetStatus(tester->handle, &status);
148     if (ret != HDF_SUCCESS) {
149         HDF_LOGE("TestCaseWatchdogStartStop: get status fail, ret: %d!", ret);
150         return ret;
151     }
152     if (status != WATCHDOG_START) {
153         HDF_LOGE("TestCaseWatchdogStartStop: status is:%d after start!", status);
154         return HDF_FAILURE;
155     }
156 
157     ret = WatchdogStop(tester->handle);
158     if (ret != HDF_SUCCESS) {
159         HDF_LOGE("TestCaseWatchdogStartStop: stop fail, ret: %d!", ret);
160         return ret;
161     }
162     status = WATCHDOG_START;
163     ret = WatchdogGetStatus(tester->handle, &status);
164     if (status != WATCHDOG_STOP) {
165         HDF_LOGE("TestCaseWatchdogStartStop: status is:%d after stop!", status);
166         return HDF_FAILURE;
167     }
168 
169     return HDF_SUCCESS;
170 }
171 
TestCaseWatchdogFeed(struct WatchdogTester * tester)172 static int32_t TestCaseWatchdogFeed(struct WatchdogTester *tester)
173 {
174     int32_t ret;
175     uint32_t i;
176 
177     ret = WatchdogStart(tester->handle);
178     if (ret != HDF_SUCCESS) {
179         HDF_LOGE("TestCaseWatchdogFeed: satrt fail, ret: %d!", ret);
180         return ret;
181     }
182 
183     for (i = 0; i < tester->config.feedTime; i++) {
184         HDF_LOGE("TestCaseWatchdogFeed: feeding watchdog %d times... ", i);
185         ret = WatchdogFeed(tester->handle);
186         if (ret != HDF_SUCCESS) {
187             HDF_LOGE("TestCaseWatchdogFeed: feed dog fail, ret: %d!", ret);
188             return ret;
189         }
190         OsalSleep(1);
191     }
192 
193     ret = WatchdogStop(tester->handle);
194     if (ret != HDF_SUCCESS) {
195         HDF_LOGE("TestCaseWatchdogFeed: stop fail, ret: %d!", ret);
196         return ret;
197     }
198 
199     HDF_LOGD("TestCaseWatchdogFeed: no reset ... feeding test OK!!!");
200     return HDF_SUCCESS;
201 }
202 
TestCaseWatchdogBark(struct WatchdogTester * tester)203 static int32_t TestCaseWatchdogBark(struct WatchdogTester *tester)
204 {
205 #ifdef WATCHDOG_TEST_BARK_RESET
206     int32_t ret;
207     int32_t i;
208 
209     ret = WatchdogStart(tester->handle);
210     if (ret != HDF_SUCCESS) {
211         HDF_LOGE("TestCaseWatchdogBark: satrt fail, ret: %d!", ret);
212         return ret;
213     }
214 
215     for (i = 0; i < tester->config.feedTime; i++) {
216         HDF_LOGE("TestCaseWatchdogBark: watiting dog buck %d times... ", i);
217         OsalSleep(1);
218     }
219 
220     HDF_LOGE("TestCaseWatchdogBark: dog has't buck!!! ", i);
221     return HDF_FAILURE;
222 #else
223     (void)tester;
224     return HDF_SUCCESS;
225 #endif
226 }
227 
TestCaseWatchdogReliability(struct WatchdogTester * tester)228 static int32_t TestCaseWatchdogReliability(struct WatchdogTester *tester)
229 {
230     int32_t status;
231     uint32_t timeout;
232 
233     HDF_LOGD("TestCaseWatchdogReliability: test dfr for WatchdogGetStatus ...");
234     /* invalid device handle */
235     (void)WatchdogGetStatus(NULL, &status);
236     /* invalid status pointer */
237     (void)WatchdogGetStatus(tester->handle, NULL);
238 
239     HDF_LOGD("TestCaseWatchdogReliability: test dfr for WatchdogStart&Stop ...");
240     /* invalid device handle */
241     (void)WatchdogStart(NULL);
242     /* invalid device handle */
243     (void)WatchdogStop(NULL);
244 
245     HDF_LOGD("TestCaseWatchdogReliability: test dfr for WatchdogSet&GetTimeout ...");
246     /* invalid device handle */
247     (void)WatchdogSetTimeout(NULL, tester->config.timeoutSet);
248     /* invalid device handle */
249     (void)WatchdogGetTimeout(NULL, &timeout);
250     /* invalid timeout pointer */
251     (void)WatchdogGetTimeout(tester->handle, NULL);
252 
253     HDF_LOGD("TestCaseWatchdogReliability: test dfr for WatchdogFeed ...");
254     /* invalid device handle */
255     (void)WatchdogFeed(NULL);
256 
257     return HDF_SUCCESS;
258 }
259 
TestCaseWatchdogIfPerformanceTest(struct WatchdogTester * tester)260 static int32_t TestCaseWatchdogIfPerformanceTest(struct WatchdogTester *tester)
261 {
262 #ifdef __LITEOS__
263     // liteos the accuracy of the obtained time is too large and inaccurate.
264     if (tester == NULL) {
265         HDF_LOGE("TestCaseWatchdogIfPerformanceTest: tester is null!");
266         return HDF_FAILURE;
267     }
268     return HDF_SUCCESS;
269 #endif
270 
271     uint32_t timeoutGet = 0;
272     uint64_t startMs;
273     uint64_t endMs;
274     uint64_t useTime;    // ms
275 
276     if (tester == NULL) {
277         HDF_LOGE("TestCaseWatchdogIfPerformanceTest: tester is null!");
278         return HDF_FAILURE;
279     }
280 
281     startMs = OsalGetSysTimeMs();
282     WatchdogGetTimeout(tester->handle, &timeoutGet);
283     endMs = OsalGetSysTimeMs();
284 
285     useTime = endMs - startMs;
286     HDF_LOGI("TestCaseWatchdogIfPerformanceTest: ----->interface performance test:[start - end] < 1ms[%s]\r\n",
287         useTime < 1 ? "yes" : "no");
288     return HDF_SUCCESS;
289 }
290 
291 static struct WatchdogTestEntry g_entry[] = {
292     { WATCHDOG_TEST_SET_GET_TIMEOUT, TestCaseWatchdogSetGetTimeout},
293     { WATCHDOG_TEST_START_STOP, TestCaseWatchdogStartStop},
294     { WATCHDOG_TEST_FEED, TestCaseWatchdogFeed},
295     { WATCHDOG_TEST_RELIABILITY, TestCaseWatchdogReliability},
296     { WATCHDOG_TEST_BARK, TestCaseWatchdogBark},
297     { WATCHDOG_IF_PERFORMANCE_TEST, TestCaseWatchdogIfPerformanceTest},
298 };
299 
WatchdogTestExecute(int cmd)300 int32_t WatchdogTestExecute(int cmd)
301 {
302     uint32_t i;
303     int32_t ret = HDF_ERR_NOT_SUPPORT;
304     struct WatchdogTester *tester = NULL;
305 
306     tester = WatchdogTesterGet();
307     if (tester == NULL) {
308         if (g_wdtState == HDF_ERR_DEVICE_BUSY) {
309             HDF_LOGE("WatchdogTestExecute: device is busy!");
310             return HDF_SUCCESS;
311         }
312         HDF_LOGE("WatchdogTestExecute: get tester fail!");
313         return HDF_ERR_INVALID_OBJECT;
314     }
315 
316     if (cmd > WATCHDOG_TEST_MAX) {
317         HDF_LOGE("WatchdogTestExecute: invalid cmd:%d!", cmd);
318         ret = HDF_ERR_NOT_SUPPORT;
319         HDF_LOGI("[WatchdogTestExecute][======cmd:%d====ret:%d======]", cmd, ret);
320         WatchdogTesterPut(tester);
321         return ret;
322     }
323 
324     for (i = 0; i < sizeof(g_entry) / sizeof(g_entry[0]); i++) {
325         if (g_entry[i].cmd != cmd || g_entry[i].func == NULL) {
326             continue;
327         }
328         ret = g_entry[i].func(tester);
329         break;
330     }
331 
332     HDF_LOGI("[WatchdogTestExecute][======cmd:%d====ret:%d======]", cmd, ret);
333     WatchdogTesterPut(tester);
334     return ret;
335 }
336