1 /*
2  * Copyright (c) 2020-2022 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 "hdf_message_test.h"
10 #include "message/message_types.h"
11 #include "message/message_router.h"
12 #include "message/sidecar.h"
13 #include "hdf_log.h"
14 #include "hdf_sbuf.h"
15 #include "osal_time.h"
16 
17 const uint32_t SEND_MESSAGE_COUNT = 40000;
18 const uint32_t SYNC_MESSAGE_TIMEOUT = 2;
19 const uint32_t ASYNC_MESSAGE_TIMEOUT = 8;
20 #define COMMON_SEM_TIMEOUT 300
21 
22 enum ServiceList {
23     SERVICE_ID_A = 10,
24     SERVICE_ID_B
25 };
26 
27 const uint8_t CUSTOM_DISPATCHER_ID = 1;
28 const uint8_t SINGLE_NODE_TEST_CUSTOM_DISPATCHER_PRIORITYLEVEL = 4;
29 const uint32_t SINGLE_NODE_TEST_CUSTOM_DISPATCHER_QUEUESIZE = 10000;
30 
31 const uint16_t SMALL_LOAD_WAIT_TIME = 500;
32 
33 
34 #define CMD_LIST_MAX_SIZE 32
35 uint8_t g_cmdList[CMD_LIST_MAX_SIZE];
36 uint8_t g_cmdListCount = 0;
37 
FuncNoLoad(const RequestContext * context,struct HdfSBuf * reqData,struct HdfSBuf * rspData)38 static ErrorCode FuncNoLoad(const RequestContext *context, struct HdfSBuf *reqData, struct HdfSBuf *rspData)
39 {
40     (void)reqData;
41     (void)rspData;
42     (void)context;
43     return ME_SUCCESS;
44 }
45 
FuncSmallLoad(const RequestContext * context,struct HdfSBuf * reqData,struct HdfSBuf * rspData)46 static ErrorCode FuncSmallLoad(const RequestContext *context, struct HdfSBuf *reqData, struct HdfSBuf *rspData)
47 {
48     if (context == NULL) {
49         HDF_LOGE("%s:FuncSmallLoad context NULL!", __func__);
50         return HDF_FAILURE;
51     }
52     (void)reqData;
53     (void)rspData;
54     HDF_LOGI("Handle message %d\n", context->commandId);
55 
56     OsalMSleep(SMALL_LOAD_WAIT_TIME);
57     if (g_cmdListCount >= CMD_LIST_MAX_SIZE) {
58         HDF_LOGE("%s:Too much cmd!", __func__);
59         return HDF_FAILURE;
60     }
61     g_cmdList[g_cmdListCount++] = context->commandId;
62     HDF_LOGI("Finish handle message %d\n", context->commandId);
63     return ME_SUCCESS;
64 }
65 
66 static struct MessageDef g_testServiceACmds[] = {
67     DUEMessage(0, FuncNoLoad, 1)
68 };
69 
70 ServiceDefine(TestServiceA, SERVICE_ID_A, g_testServiceACmds);
71 
72 static struct MessageDef g_testServiceBCmds[] = {
73     DUEMessage(0, FuncNoLoad, 2), // commandId = 0
74     DUEMessage(1, FuncSmallLoad, 0),
75     DUEMessage(2, FuncSmallLoad, 1),
76     DUEMessage(3, FuncSmallLoad, 2),
77     DUEMessage(4, FuncSmallLoad, 3),
78 };
79 
80 ServiceDefine(TestServiceB, SERVICE_ID_B, g_testServiceBCmds);
81 
82 Service *g_serviceA = NULL;
83 Service *g_serviceB = NULL;
84 bool g_dispatcherInited = false;
85 
StartEnv(void)86 static int32_t StartEnv(void)
87 {
88     int32_t errCode;
89     if (!g_dispatcherInited) {
90         DispatcherConfig config = {
91             .dispatcherId = CUSTOM_DISPATCHER_ID,
92             .priorityLevelCount = SINGLE_NODE_TEST_CUSTOM_DISPATCHER_PRIORITYLEVEL,
93             .queueSize = SINGLE_NODE_TEST_CUSTOM_DISPATCHER_QUEUESIZE
94         };
95         MSG_RETURN_IF_FUNCTION_FAILED(errCode, AddDispatcher(&config));
96         g_dispatcherInited = true;
97     }
98     if (g_serviceA == NULL) {
99         ServiceCfg cfgA = {
100             .dispatcherId = DEFAULT_DISPATCHER_ID
101         };
102         g_serviceA = CreateService(TestServiceA, &cfgA);
103         MSG_RETURN_IF(g_serviceA == NULL);
104     }
105 
106     if (g_serviceB == NULL) {
107         ServiceCfg cfgB = {
108             .dispatcherId = CUSTOM_DISPATCHER_ID
109         };
110         g_serviceB = CreateService(TestServiceB, &cfgB);
111         MSG_RETURN_IF(g_serviceB == NULL);
112     }
113     return HDF_SUCCESS;
114 }
115 
StopEnv(void)116 static int32_t StopEnv(void)
117 {
118     if (g_serviceA != NULL) {
119         if (g_serviceA->Destroy != NULL) {
120             g_serviceA->Destroy(g_serviceA);
121         }
122         g_serviceA = NULL;
123     }
124 
125     if (g_serviceB != NULL) {
126         if (g_serviceB->Destroy != NULL) {
127             g_serviceB->Destroy(g_serviceB);
128         }
129         g_serviceB = NULL;
130     }
131     return HDF_SUCCESS;
132 }
133 
134 // Repeated register
MessageSingleNodeTest001(void)135 int32_t MessageSingleNodeTest001(void)
136 {
137     ErrorCode errCode = HDF_SUCCESS;
138     ErrorCode errShutdown = HDF_SUCCESS;
139     Service *service = NULL;
140 
141     do {
142         ServiceCfg cfgB = {
143             .dispatcherId = CUSTOM_DISPATCHER_ID
144         };
145 
146         MSG_RETURN_IF_FUNCTION_FAILED(errCode, StartEnv());
147 
148         service = CreateService(TestServiceB, &cfgB);
149         MSG_BREAK_IF(errCode, service != NULL);
150     } while (false);
151 
152     MSG_RETURN_IF_FUNCTION_FAILED(errShutdown, StopEnv());
153     if (service != NULL) {
154         if (service->Destroy != NULL) {
155             service->Destroy(service);
156         }
157         service = NULL;
158     }
159     return errCode;
160 }
161 
162 // Sync message test
MessageSingleNodeTest002(void)163 int32_t MessageSingleNodeTest002(void)
164 {
165     ErrorCode errCode = HDF_SUCCESS;
166     ErrorCode errShutdown = HDF_SUCCESS;
167     struct HdfSBuf *rspData = NULL;
168 
169     do {
170         MSG_BREAK_IF_FUNCTION_FAILED(errCode, StartEnv());
171 
172         MSG_BREAK_IF(errCode, g_serviceA == NULL);
173 
174         rspData = HdfSbufObtainDefaultSize();
175 
176         MSG_BREAK_IF_FUNCTION_FAILED(errCode, g_serviceA->SendSyncMessage(g_serviceA, SERVICE_ID_B, 0, NULL, rspData));
177     } while (false);
178 
179     if (rspData != NULL) {
180         HdfSbufRecycle(rspData);
181         rspData = NULL;
182     }
183 
184     MSG_RETURN_IF_FUNCTION_FAILED(errShutdown, StopEnv());
185 
186     return errCode;
187 }
188 
189 
190 // Sync Perf test
MessageSingleNodeTest003(void)191 int32_t MessageSingleNodeTest003(void)
192 {
193     ErrorCode errCode = HDF_SUCCESS;
194     ErrorCode errShutdown = HDF_SUCCESS;
195     uint32_t i;
196     struct HdfSBuf *rspData = NULL;
197     struct HdfSBuf *sendData = NULL;
198     do {
199         OsalTimespec startTime;
200         OsalTimespec endTime;
201         OsalTimespec diffTime;
202         MSG_BREAK_IF_FUNCTION_FAILED(errCode, StartEnv());
203         MSG_BREAK_IF(errCode, g_serviceA == NULL);
204         rspData = HdfSbufObtainDefaultSize();
205         sendData = HdfSbufObtainDefaultSize();
206 
207         MSG_BREAK_IF_FUNCTION_FAILED(errCode, OsalGetTime(&startTime));
208         for (i = 0; i < SEND_MESSAGE_COUNT; i++) {
209             MSG_BREAK_IF_FUNCTION_FAILED(errCode,
210                 g_serviceA->SendSyncMessage(g_serviceA, SERVICE_ID_B, 0, sendData, rspData));
211         }
212         MSG_BREAK_IF_FUNCTION_FAILED(errCode, OsalGetTime(&endTime));
213 
214         MSG_BREAK_IF_FUNCTION_FAILED(errCode, OsalDiffTime(&startTime, &endTime, &diffTime));
215 
216         HDF_LOGI("Process time %llu \n", diffTime.sec);
217         MSG_BREAK_IF(errCode, diffTime.sec > SYNC_MESSAGE_TIMEOUT);
218     } while (false);
219 
220     if (rspData != NULL) {
221         HdfSbufRecycle(rspData);
222         rspData = NULL;
223     }
224 
225     if (sendData != NULL) {
226         HdfSbufRecycle(sendData);
227         sendData = NULL;
228     }
229 
230     MSG_RETURN_IF_FUNCTION_FAILED(errShutdown, StopEnv());
231 
232     return errCode;
233 }
234 
235 OSAL_DECLARE_SEMAPHORE(g_callBackSem);
236 
SendMessageTestCallBack(const RequestContext * context,struct HdfSBuf * reqData,struct HdfSBuf * rspData,ErrorCode rspCode)237 static void SendMessageTestCallBack(const RequestContext *context, struct HdfSBuf *reqData, struct HdfSBuf *rspData,
238     ErrorCode rspCode)
239 {
240     if (context == NULL) {
241         HDF_LOGE("%s:SendMessageTestCallBack context NULL!", __func__);
242         return;
243     }
244     (void)reqData;
245     (void)rspData;
246     (void)rspCode;
247     OsalSemPost(&g_callBackSem);
248     HDF_LOGI("Receive response for CMD %d.\n", context->commandId);
249 }
250 
MessageSingleNodeTest004(void)251 int32_t MessageSingleNodeTest004(void)
252 {
253     ErrorCode errCode = HDF_SUCCESS;
254     ErrorCode errShutdown = HDF_SUCCESS;
255 
256     do {
257         MSG_BREAK_IF_FUNCTION_FAILED(errCode, StartEnv());
258         MSG_BREAK_IF(errCode, g_serviceA == NULL);
259 
260         MSG_BREAK_IF_FUNCTION_FAILED(errCode, OsalSemInit(&g_callBackSem, 0));
261 
262         MSG_BREAK_IF_FUNCTION_FAILED(errCode,
263             g_serviceA->SendAsyncMessage(g_serviceA, SERVICE_ID_B, 0, NULL, SendMessageTestCallBack));
264 
265         MSG_BREAK_IF_FUNCTION_FAILED(errCode, OsalSemWait(&g_callBackSem, COMMON_SEM_TIMEOUT));
266     } while (false);
267     errShutdown = OsalSemDestroy(&g_callBackSem);
268     errShutdown = errShutdown | StopEnv();
269     if (errShutdown != HDF_SUCCESS) {
270         HDF_LOGE("%s:Destroy message semaphore failed! errShutdown=%d", __func__, errShutdown);
271     }
272 
273     return errCode;
274 }
275 
SendMessagePerfTestCallBack(const RequestContext * context,struct HdfSBuf * reqData,struct HdfSBuf * rspData,ErrorCode rspCode)276 static void SendMessagePerfTestCallBack(const RequestContext *context, struct HdfSBuf *reqData, struct HdfSBuf *rspData,
277     ErrorCode rspCode)
278 {
279     (void)context;
280     (void)reqData;
281     (void)rspData;
282     (void)rspCode;
283 
284     ErrorCode errCode = OsalSemPost(&g_callBackSem);
285     if (HDF_SUCCESS != errCode) {
286         HDF_LOGE("%s:Post sem failed!ret=%d", __func__, errCode);
287     }
288 }
289 
290 const uint32_t PERF_TEST_COUNT = 10000;
291 
MessageSingleNodeTest005(void)292 int32_t MessageSingleNodeTest005(void)
293 {
294     ErrorCode errCode = HDF_SUCCESS;
295     ErrorCode errShutdown = HDF_SUCCESS;
296     uint32_t i;
297 
298     do {
299         OsalTimespec startTime;
300         OsalTimespec endTime;
301         OsalTimespec diffTime;
302         MSG_BREAK_IF_FUNCTION_FAILED(errCode, StartEnv());
303         MSG_BREAK_IF(errCode, g_serviceA == NULL);
304 
305         MSG_BREAK_IF_FUNCTION_FAILED(errCode, OsalSemInit(&g_callBackSem, 0));
306 
307         MSG_BREAK_IF_FUNCTION_FAILED(errCode, OsalGetTime(&startTime));
308 
309         for (i = 0; i < PERF_TEST_COUNT; i++) {
310             MSG_BREAK_IF_FUNCTION_FAILED(errCode,
311                 g_serviceA->SendAsyncMessage(g_serviceA, SERVICE_ID_B, 0, NULL, SendMessagePerfTestCallBack));
312         }
313 
314         for (i = 0; i < PERF_TEST_COUNT; i++) {
315             MSG_BREAK_IF_FUNCTION_FAILED(errCode, OsalSemWait(&g_callBackSem, COMMON_SEM_TIMEOUT));
316         }
317 
318         MSG_BREAK_IF_FUNCTION_FAILED(errCode, OsalGetTime(&endTime));
319 
320         MSG_BREAK_IF_FUNCTION_FAILED(errCode, OsalDiffTime(&startTime, &endTime, &diffTime));
321 
322         HDF_LOGW("Process time %llu \n", diffTime.sec);
323         MSG_BREAK_IF(errCode, diffTime.sec > ASYNC_MESSAGE_TIMEOUT);
324     } while (false);
325     errShutdown = OsalSemDestroy(&g_callBackSem);
326     errShutdown = errShutdown | StopEnv();
327     if (errShutdown != HDF_SUCCESS) {
328         HDF_LOGE("%s:Destroy message semaphore failed! errShutdown=%d", __func__, errShutdown);
329     }
330 
331     return errCode;
332 }
333