1 /*
2  * Copyright (c) 2021-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 "platform_device_test.h"
10 #include "platform_assert.h"
11 #include "platform_manager.h"
12 
13 #define HDF_LOG_TAG platform_device_test
14 
15 #define PLAT_DEV_WAIT_TIMEOUT     10
16 
PlatformDeviceTestSetUpAll(void)17 void PlatformDeviceTestSetUpAll(void)
18 {
19 }
20 
PlatformDeviceTestTearDownAll(void)21 void PlatformDeviceTestTearDownAll(void)
22 {
23 }
24 
PlatformDeviceTestSetName(struct PlatformDevice * device)25 static int32_t PlatformDeviceTestSetName(struct PlatformDevice *device)
26 {
27     int32_t ret;
28 
29     PLAT_LOGD("PlatformDeviceTestSetName: enter!");
30     // should set name success
31     ret = PlatformDeviceSetName(device, "platform_device_name_%d", 1);
32     CHECK_EQ_RETURN(ret, HDF_SUCCESS, ret);
33     ret = strcmp(device->name, "platform_device_name_1");
34     CHECK_EQ_RETURN(ret, 0, HDF_FAILURE);
35 
36     // name should be null after clear
37     PlatformDeviceClearName(device);
38     CHECK_EQ_RETURN(device->name, NULL, HDF_FAILURE);
39 
40     // should set name success
41     ret = PlatformDeviceSetName(device, "platform_device_name");
42     CHECK_EQ_RETURN(ret, HDF_SUCCESS, ret);
43     ret = strcmp(device->name, "platform_device_name");
44     CHECK_EQ_RETURN(ret, 0, HDF_FAILURE);
45 
46     // clean the name after test
47     PlatformDeviceClearName(device);
48 
49     PLAT_LOGD("PlatformDeviceTestSetName: exit!");
50     return HDF_SUCCESS;
51 }
52 
PlatformDeviceTestGetDevice(struct PlatformDevice * device)53 static int32_t PlatformDeviceTestGetDevice(struct PlatformDevice *device)
54 {
55     int32_t ret;
56     int32_t refCntBeforeGet;
57     int32_t refCntAfterGet;
58     int32_t refCntAfterPut;
59 
60     PLAT_LOGD("PlatformDeviceTestGetDevice: enter!");
61     device->name = "platform_device_test_get";
62     refCntBeforeGet = PlatformDeviceRefCount(device);
63     ret = PlatformDeviceGet(device);
64     // should get device success
65     CHECK_EQ_RETURN(ret, HDF_SUCCESS, ret);
66 
67     refCntAfterGet = PlatformDeviceRefCount(device);
68     // ref count should increase by 1 after get
69     CHECK_EQ_RETURN(refCntAfterGet, refCntBeforeGet + 1, ret);
70 
71     ret = PlatformDeviceGet(device);
72     // should get device success again
73     CHECK_EQ_RETURN(ret, HDF_SUCCESS, ret);
74     refCntAfterGet = PlatformDeviceRefCount(device);
75     // ref count should increase by 2 after double get
76     CHECK_EQ_RETURN(refCntAfterGet, refCntBeforeGet + 2, ret);
77 
78     PlatformDevicePut(device);
79     refCntAfterPut = PlatformDeviceRefCount(device);
80     // ref count should decrease by 1 after put
81     CHECK_EQ_RETURN(refCntAfterPut, refCntBeforeGet + 1, ret);
82 
83     PlatformDevicePut(device);
84     refCntAfterPut = PlatformDeviceRefCount(device);
85     // ref count should decrease by 2 after put
86     CHECK_EQ_RETURN(refCntAfterPut, refCntBeforeGet, ret);
87 
88     PLAT_LOGD("PlatformDeviceTestGetDevice: exit!");
89     return HDF_SUCCESS;
90 }
91 
PlatformDeviceTestWaitEvent(struct PlatformDevice * device)92 static int32_t PlatformDeviceTestWaitEvent(struct PlatformDevice *device)
93 {
94     int32_t ret;
95     uint32_t eventA = 0x1;
96     uint32_t eventB = 0x4;
97     uint32_t mask = eventA | eventB;
98     uint32_t events;
99 
100     PLAT_LOGD("PlatformDeviceTestWaitEvent: enter!");
101     device->name = "platform_device_test_event";
102     // should not wait success before post
103     ret = PlatformDeviceWaitEvent(device, mask, PLAT_DEV_WAIT_TIMEOUT, &events);
104     CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
105 
106     // should post event success
107     ret = PlatformDevicePostEvent(device, eventA | eventB);
108     CHECK_EQ_RETURN(ret, HDF_SUCCESS, ret);
109 
110     // should wait success after post
111     ret = PlatformDeviceWaitEvent(device, mask, PLAT_DEV_WAIT_TIMEOUT, &events);
112     PLAT_LOGD("PlatformDeviceTestWaitEvent: events:%x!", events);
113     CHECK_EQ_RETURN(ret, HDF_SUCCESS, ret);
114     CHECK_EQ_RETURN(events, eventA | eventB, ret);
115 
116     PLAT_LOGD("PlatformDeviceTestWaitEvent: exit!");
117     return HDF_SUCCESS;
118 }
119 
PlatformDeviceTestAddDevice(struct PlatformDevice * device)120 static int32_t PlatformDeviceTestAddDevice(struct PlatformDevice *device)
121 {
122     int32_t ret;
123     struct PlatformManager *manager = NULL;
124     struct PlatformDevice *deviceGet = NULL;
125 
126     PLAT_LOGD("PlatformDeviceTestAddDevice: enter!");
127     device->name = "platform_device_test_add";
128     // should create manager success
129     ret = PlatformManagerCreate("platform_test_manager", &manager);
130     CHECK_EQ_RETURN(ret, HDF_SUCCESS, ret);
131 
132     device->number = 0x5A; // a random number just for testing
133     device->manager = manager;
134     // should add platform device success
135     ret = PlatformDeviceAdd(device);
136     CHECK_EQ_RETURN(ret, HDF_SUCCESS, ret);
137 
138     // should get the device added
139     deviceGet = PlatformManagerGetDeviceByNumber(manager, device->number);
140     CHECK_EQ_RETURN(deviceGet, device, ret);
141     PlatformDevicePut(deviceGet);
142 
143     PlatformDeviceDel(device);
144     // should not get the device after del
145     deviceGet = PlatformManagerGetDeviceByNumber(manager, device->number);
146     CHECK_EQ_RETURN(deviceGet, NULL, ret);
147 
148     PLAT_LOGD("PlatformDeviceTestAddDevice: exit!");
149     return HDF_SUCCESS;
150 }
151 
TestDispatch(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)152 static int32_t TestDispatch(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
153 {
154     (void)client;
155     (void)cmd;
156     (void)data;
157     (void)reply;
158     return HDF_SUCCESS;
159 }
160 
PlatformDeviceTestCreateService(struct PlatformDevice * device)161 static int32_t PlatformDeviceTestCreateService(struct PlatformDevice *device)
162 {
163     int32_t ret;
164 
165     PLAT_LOGD("PlatformDeviceTestCreateService: enter!");
166     device->name = "platform_device_test_create_service";
167     ret = PlatformDeviceCreateService(device, TestDispatch);
168     CHECK_EQ_RETURN(ret, HDF_SUCCESS, ret);
169 
170     CHECK_NE_RETURN(device->service, NULL, HDF_FAILURE);
171     CHECK_EQ_RETURN(device->service->Dispatch, TestDispatch, HDF_FAILURE);
172 
173     PlatformDeviceDestroyService(device);
174     CHECK_EQ_RETURN(device->service, NULL, HDF_FAILURE);
175 
176     PLAT_LOGD("PlatformDeviceTestCreateService: exit!");
177     return HDF_SUCCESS;
178 }
179 
PlatformDeviceTestBindDevice(struct PlatformDevice * device)180 static int32_t PlatformDeviceTestBindDevice(struct PlatformDevice *device)
181 {
182     int32_t ret;
183     struct HdfDeviceObject hdfDev;
184     struct IDeviceIoService service;
185     struct PlatformDevice *devFromHdf = NULL;
186 
187     PLAT_LOGD("PlatformDeviceTestBindDevice: enter!");
188     device->name = "platform_device_test_bind";
189     device->service = &service;
190     ret = PlatformDeviceBind(device, &hdfDev);
191     CHECK_EQ_RETURN(ret, HDF_SUCCESS, ret);
192     CHECK_EQ_RETURN(device->hdfDev, &hdfDev, HDF_FAILURE);
193     CHECK_EQ_RETURN(device->service, hdfDev.service, HDF_FAILURE);
194 
195     devFromHdf = PlatformDeviceFromHdfDev(&hdfDev);
196     CHECK_EQ_RETURN(device, devFromHdf, HDF_FAILURE);
197 
198     PlatformDeviceUnbind(device, &hdfDev);
199     CHECK_EQ_RETURN(device->hdfDev, NULL, ret);
200     CHECK_EQ_RETURN(hdfDev.service, NULL, ret);
201 
202     PLAT_LOGD("PlatformDeviceTestBindDevice: exit!");
203     return HDF_SUCCESS;
204 }
205 
PlatformDeviceTestReliability(struct PlatformDevice * device)206 static int32_t PlatformDeviceTestReliability(struct PlatformDevice *device)
207 {
208     int32_t ret;
209     uint32_t events;
210     struct HdfDeviceObject hdfDev;
211     struct PlatformDevice *devGet = NULL;
212 
213     PLAT_LOGD("PlatformDeviceTestReliability: enter!");
214     device->name = "platform_device_test_reliability";
215     ret = PlatformDeviceInit(NULL);
216     CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
217 
218     PlatformDeviceUninit(NULL);
219 
220     ret = PlatformDeviceSetName(NULL, "device_name");
221     CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
222 
223     ret = PlatformDeviceSetName(device, NULL);
224     CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
225     PlatformDeviceClearName(device);
226 
227     ret = PlatformDeviceGet(NULL);
228     CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
229     PlatformDevicePut(NULL);
230 
231     ret = PlatformDeviceRefCount(NULL);
232     CHECK_LT_RETURN(ret, 0, HDF_FAILURE);
233 
234     ret = PlatformDevicePostEvent(NULL, 0x1);
235     CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
236 
237     ret = PlatformDeviceWaitEvent(NULL, 0x1, 1, &events);
238     CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
239 
240     ret = PlatformDeviceAdd(NULL);
241     CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
242     PlatformDeviceDel(NULL);
243 
244     ret = PlatformDeviceCreateService(NULL, TestDispatch);
245     CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
246     PlatformDeviceDestroyService(NULL);
247 
248     ret = PlatformDeviceBind(device, NULL);
249     CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
250     ret = PlatformDeviceBind(NULL, &hdfDev);
251     CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
252     PlatformDeviceUnbind(device, NULL);
253     PlatformDeviceUnbind(NULL, NULL);
254 
255     devGet = PlatformDeviceFromHdfDev(NULL);
256     CHECK_NULL_RETURN(devGet, HDF_FAILURE);
257 
258     PLAT_LOGD("PlatformDeviceTestReliability: exit!");
259     return HDF_SUCCESS;
260 }
261 
262 struct PlatformDeviceTestEntry {
263     int cmd;
264     int32_t (*func)(struct PlatformDevice *device);
265     const char *name;
266 };
267 
268 static struct PlatformDeviceTestEntry g_entry[] = {
269     { PLAT_DEVICE_TEST_SET_NAME, PlatformDeviceTestSetName, "PlatformDeviceTestReliability" },
270     { PLAT_DEVICE_TEST_GET_DEVICE, PlatformDeviceTestGetDevice, "PlatformDeviceTestGetDevice" },
271     { PLAT_DEVICE_TEST_WAIT_EVENT, PlatformDeviceTestWaitEvent, "PlatformDeviceTestWaitEvent" },
272     { PLAT_DEVICE_TEST_ADD_DEVICE, PlatformDeviceTestAddDevice, "PlatformDeviceTestAddDevice" },
273     { PLAT_DEVICE_TEST_CREATE_SERVICE, PlatformDeviceTestCreateService, "PlatformDeviceTestCreateService" },
274     { PLAT_DEVICE_TEST_BIND_DEVICE, PlatformDeviceTestBindDevice, "PlatformDeviceTestBindDevice" },
275     { PLAT_DEVICE_TEST_RELIABILITY, PlatformDeviceTestReliability, "PlatformDeviceTestReliability" },
276 };
277 
PlatformDeviceTestExecute(int cmd)278 int PlatformDeviceTestExecute(int cmd)
279 {
280     uint32_t i;
281     int32_t ret = HDF_ERR_NOT_SUPPORT;
282     struct PlatformDevice device = {0};
283     struct PlatformDeviceTestEntry *entry = NULL;
284 
285     if (cmd > PLAT_DEVICE_TEST_CMD_MAX) {
286         PLAT_LOGE("PlatformDeviceTestExecute: invalid cmd:%d", cmd);
287         ret = HDF_ERR_NOT_SUPPORT;
288         PLAT_LOGE("[PlatformDeviceTestExecute][======cmd:%d====ret:%d======]", cmd, ret);
289         return ret;
290     }
291 
292     for (i = 0; i < (sizeof(g_entry) / sizeof(g_entry[0])); i++) {
293         if (g_entry[i].cmd != cmd || g_entry[i].func == NULL) {
294             continue;
295         }
296         entry = &g_entry[i];
297         break;
298     }
299 
300     if (entry == NULL) {
301         PLAT_LOGE("PlatformDeviceTestExecute: no entry matched, cmd = %d!", cmd);
302         return HDF_ERR_NOT_SUPPORT;
303     }
304 
305     if ((ret = PlatformDeviceInit(&device)) != HDF_SUCCESS) {
306         PLAT_LOGE("PlatformDeviceTestExecute: init failed, ret = %d!", ret);
307         return ret;
308     }
309 
310     ret = entry->func(&device);
311     PlatformDeviceUninit(&device);
312 
313     PLAT_LOGE("[PlatformDeviceTestExecute][======cmd:%d====ret:%d======]", cmd, ret);
314     return ret;
315 }
316 
PlatformDeviceTestExecuteAll(void)317 void PlatformDeviceTestExecuteAll(void)
318 {
319     int32_t i;
320     int32_t ret;
321     int32_t fails = 0;
322 
323     for (i = 0; i < PLAT_DEVICE_TEST_CMD_MAX; i++) {
324         ret = PlatformDeviceTestExecute(i);
325         fails += (ret != HDF_SUCCESS) ? 1 : 0;
326     }
327 
328     PLAT_LOGE("PlatformDeviceTestExecuteALL: **********PASS:%d  FAIL:%d************\n\n",
329         PLAT_DEVICE_TEST_CMD_MAX - fails, fails);
330 }
331