blob: 790a879ca398d30cd78548edcdcc4ecf0a1895da [file] [log] [blame]
xjb04a4022021-11-25 15:01:52 +08001/* MediaTek Inc. (C) 2016. All rights reserved.
2 *
3 * Copyright Statement:
4 * This software/firmware and related documentation ("MediaTek Software") are
5 * protected under relevant copyright laws. The information contained herein is
6 * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
7 * the prior written permission of MediaTek inc. and/or its licensors, any
8 * reproduction, modification, use or disclosure of MediaTek Software, and
9 * information contained herein, in whole or in part, shall be strictly
10 * prohibited.
11 */
12
13/*
14 * Description:
15 * Implement unit test cases
16 */
17
18#include "AudioParamParserPriv.h"
19
20typedef APP_STATUS(*TEST_FUN)(AppHandle *appHandle);
21
22typedef struct {
23 AppHandle *appHandle;
24 int times;
25 TEST_FUN fun;
26} ThreadParam;
27
28EXPORT APP_STATUS unitTest(AppHandle *appHandle) {
29 APP_STATUS res = APP_NO_ERROR;
30 APP_STATUS finalRes = APP_NO_ERROR;
31
32 printf("===APP internal unit test===\n");
33#if 0
34 res = testAppHandleInitUninit();
35 if (res == APP_ERROR) {
36 finalRes = APP_ERROR;
37 }
38 printf("testAppHandleInitUninit: %s\n", res ? "pass" : "fail");
39#endif
40 res = testReadWriteParam(appHandle);
41 if (res == APP_ERROR) {
42 finalRes = APP_ERROR;
43 }
44 printf("testReadWriteParam: %s\n", res ? "pass" : "fail");
45
46 res = testMemoryLeak(appHandle);
47 if (res == APP_ERROR) {
48 finalRes = APP_ERROR;
49 }
50 printf("testMemoryLeak: %s\n", res ? "pass" : "fail");
51
52 res = testAudioTypeLock(appHandle);
53 if (res == APP_ERROR) {
54 finalRes = APP_ERROR;
55 }
56 printf("testAudioTypeLock: %s\n", res ? "pass" : "fail");
57 printf("=============================\n");
58
59 return finalRes;
60}
61
62
63EXPORT void *commonThreadLoop(void *arg) {
64 ThreadParam threadParam = *(ThreadParam *)arg;
65 int i = 0 ;
66 for (i = 0; i < threadParam.times; i++) {
67 (*threadParam.fun)(threadParam.appHandle);
68 INFO_LOG("2nd thread round = %d\n", i);
69 }
70 return NULL;
71}
72
73EXPORT void testDebugLevel() {
74 appSetDebugLevel(ERR_LEVEL);
75 ERR_LOG("error - pass\n");
76 WARN_LOG("warn - ok\n");
77 INFO_LOG("info - ok\n");
78 DEBUG_LOG("debug - ok\n");
79
80 appSetDebugLevel(WARN_LEVEL);
81 ERR_LOG("error - fail\n");
82 WARN_LOG("warn - pass\n");
83 INFO_LOG("info - ok\n");
84 DEBUG_LOG("debug - ok\n");
85
86 appSetDebugLevel(INFO_LEVEL);
87 ERR_LOG("error - fail\n");
88 WARN_LOG("warn - fail\n");
89 INFO_LOG("info - pass\n");
90 DEBUG_LOG("debug - ok\n");
91
92 appSetDebugLevel(DEBUG_LEVEL);
93 ERR_LOG("error - fail\n");
94 WARN_LOG("warn - fail\n");
95 INFO_LOG("info - fail\n");
96 DEBUG_LOG("debug - pass\n");
97}
98
99EXPORT void testHashParamTree() {
100 ParamTree *item;
101 ParamTree *ParamTreeHash = NULL, *tmp = NULL; /* Used for hash */
102 const char *key;
103
104 item = (ParamTree *)malloc(sizeof(ParamTree));
105 item->categoryPath = "NB,Normal,,";
106 item->paramId = 1;
107 HASH_ADD_KEYPTR(hh, ParamTreeHash, item->categoryPath, strlen(item->categoryPath), item);
108
109 item = (ParamTree *)malloc(sizeof(ParamTree));
110 item->categoryPath = "WB,Normal,,";
111 item->paramId = 7;
112 HASH_ADD_KEYPTR(hh, ParamTreeHash, item->categoryPath, strlen(item->categoryPath), item);
113
114 item = (ParamTree *)malloc(sizeof(ParamTree));
115 item->categoryPath = "NB,Normal,0,GSM,";
116 item->paramId = 1;
117 HASH_ADD_KEYPTR(hh, ParamTreeHash, item->categoryPath, strlen(item->categoryPath), item);
118
119 item = (ParamTree *)malloc(sizeof(ParamTree));
120 item->categoryPath = "NB,HAC,0,GSM";
121 item->paramId = 0;
122 HASH_ADD_KEYPTR(hh, ParamTreeHash, item->categoryPath, strlen(item->categoryPath), item);
123
124 /* Find string */
125 key = "WB,,,";
126 HASH_FIND_STR(ParamTreeHash, key, item);
127 if (item) { printf("[%s] id is %d\n", key, item->paramId); }
128
129 /* Free hash table content */
130 HASH_ITER(hh, ParamTreeHash, item, tmp) {
131 HASH_DEL(ParamTreeHash, item);
132 free(item);
133 }
134}
135
136EXPORT void testHashParamUnit() {
137 ParamUnit *item;
138 ParamUnit *ParamUnitHash = NULL, *tmp = NULL; /* Used for hash */
139 int key;
140
141 item = (ParamUnit *)malloc(sizeof(ParamUnit));
142 item->paramId = 0;
143 item->paramHash = (Param *) 0x1;
144 HASH_ADD_INT(ParamUnitHash, paramId, item);
145
146 item = (ParamUnit *)malloc(sizeof(ParamUnit));
147 item->paramId = 1;
148 item->paramHash = (Param *)0x2;
149 HASH_ADD_INT(ParamUnitHash, paramId, item);
150 item = (ParamUnit *)malloc(sizeof(ParamUnit));
151
152 item->paramId = 7;
153 item->paramHash = (Param *)0x3;
154 HASH_ADD_INT(ParamUnitHash, paramId, item);
155
156 /* Find string */
157 key = 0;
158 HASH_FIND_INT(ParamUnitHash, &key, item);
159 if (item) { INFO_LOG("[%d] Param is %p\n", key, item->paramHash); }
160
161 key = 1;
162 HASH_FIND_INT(ParamUnitHash, &key, item);
163 if (item) { INFO_LOG("[%d] Param is %p\n", key, item->paramHash); }
164
165 key = 7;
166 HASH_FIND_INT(ParamUnitHash, &key, item);
167 if (item) { INFO_LOG("[%d] Param is %p\n", key, item->paramHash); }
168
169 /* Free hash table content */
170 HASH_ITER(hh, ParamUnitHash, item, tmp) {
171 HASH_DEL(ParamUnitHash, item);
172 free(item);
173 }
174}
175
176EXPORT void testHashParam() {
177 Param *item;
178 Param *paramHash = NULL, *tmp = NULL; /* Used for hash */
179 const char *key;
180
181 item = (Param *)malloc(sizeof(Param));
182 memset(item, 0, sizeof(Param));
183 item->name = "speech_mode_para";
184 item->data = "0x0011,0x2233,0x4455";
185 HASH_ADD_KEYPTR(hh, paramHash, item->name, strlen(item->name), item);
186
187 item = (Param *)malloc(sizeof(Param));
188 memset(item, 0, sizeof(Param));
189 item->name = "uint_param";
190 item->data = "4294967295";
191 HASH_ADD_KEYPTR(hh, paramHash, item->name, strlen(item->name), item);
192
193 item = (Param *)malloc(sizeof(Param));
194 memset(item, 0, sizeof(Param));
195 item->name = "float_param";
196 item->data = "0.1234567";
197 HASH_ADD_KEYPTR(hh, paramHash, item->name, strlen(item->name), item);
198
199 /* Find string */
200 key = "speech_mode_para";
201 HASH_FIND_STR(paramHash, key, item);
202 if (item) { INFO_LOG("[%s] value is %s\n", key, (char *)item->data); }
203
204 key = "uint_param";
205 HASH_FIND_STR(paramHash, key, item);
206 if (item) { INFO_LOG("[%s] value is %s\n", key, (char *)item->data); }
207
208 key = "float_param";
209 HASH_FIND_STR(paramHash, key, item);
210 if (item) { INFO_LOG("[%s] value is %s\n", key, (char *)item->data); }
211
212 /* Free hash table content */
213 HASH_ITER(hh, paramHash, item, tmp) {
214 HASH_DEL(paramHash, item);
215 free(item);
216 }
217}
218
219void testCb(AppHandle *appHandle, const char *audioTypeName) {
220 printf("XML file changed. (cus folder = %s, audioType = %s)\n", appHandle->xmlCusDir, audioTypeName);
221}
222
223EXPORT void notifyCbTest(AppHandle *appHandle) {
224 NotifyCb *cb;
225
226 appHandleRegXmlChangedCb(appHandle, testCb);
227
228 LL_FOREACH(appHandle->noficyCbList, cb) {
229 (*cb->cb)(appHandle, "OK");
230 }
231
232 appHandleUnregXmlChangedCb(appHandle, testCb);
233
234 LL_FOREACH(appHandle->noficyCbList, cb) {
235 (*cb->cb)(appHandle, "FAIL");
236 }
237}
238
239EXPORT void inotifyTest(const char *path) {
240
241#ifndef WIN32
242#define INOTIFY_BUF_SIZE 512
243 /* inotify test */
244 int wd;
245 ssize_t len;
246 char buf[INOTIFY_BUF_SIZE];
247 char *ptr;
248 const struct inotify_event *event;
249
250 int fd = inotify_init();
251 if (fd < 0) {
252 printf("inotify_init failed !!!");
253 exit(1);
254 }
255
256 printf("inotify path = %s\n", path);
257 wd = inotify_add_watch(fd, path, IN_CLOSE_WRITE);
258 if (wd < 0) {
259 printf("inotify_add_watch failed !!!");
260 exit(1);
261 }
262
263 while (1) {
264 len = read(fd, buf, sizeof(buf));
265 if (len < 0) {
266 perror("read");
267 exit(EXIT_FAILURE);
268 }
269
270 /* Loop over all events in the buffer */
271 for (ptr = buf; ptr < buf + len; ptr += sizeof(struct inotify_event) + event->len) {
272 event = (const struct inotify_event *) ptr;
273
274 /* Print event type */
275 if (event->mask & IN_OPEN) {
276 printf("IN_OPEN: ");
277 }
278 if (event->mask & IN_CLOSE_NOWRITE) {
279 printf("IN_CLOSE_NOWRITE: ");
280 }
281 if (event->mask & IN_CLOSE_WRITE) {
282 printf("IN_CLOSE_WRITE: ");
283 }
284 if (event->mask & IN_ACCESS) {
285 printf("IN_ACCESS: ");
286 }
287
288 /* Print the name of the file */
289
290 if (event->len) {
291 printf("%s", event->name);
292 }
293
294 /* Print type of filesystem object */
295
296 if (event->mask & IN_ISDIR) {
297 printf(" [directory]\n");
298 } else {
299 printf(" [file]\n");
300 }
301 }
302 }
303 inotify_rm_watch(fd, IN_CLOSE_NOWRITE);
304#endif
305}
306
307/***********************************
308 * Test Steps:
309 * 1. Create thread to read/write param
310 * 2. Check the lock is work well
311 * Crash/deadlock checking
312 **********************************/
313EXPORT APP_STATUS testAudioTypeLockFun(AppHandle *appHandle) {
314 /* Read param */
315 char *audioTypeName = "Speech";
316 char *categoryPath = "Band,NB,Profile,4_pole_Headset,VolIndex,3";
317 char *paramName = "speech_mode_para";
318 unsigned short shortArray1[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
319 unsigned short shortArray2[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
320 int arraySize = 7;
321 AudioType *audioType;
322 ParamUnit *paramUnit;
323 ParamInfo *paramInfo;
324 Param *param;
325
326 appHandle = appHandleGetInstance();
327
328 /* Query AudioType */
329 audioType = appHandleGetAudioTypeByName(appHandle, audioTypeName);
330 if (!audioType) {
331 ERR_LOG("audioType is NULL\n");
332 return APP_ERROR;
333 }
334
335 /* Read Lock */
336 audioTypeReadLock(audioType, __FUNCTION__);
337
338 /* Query the ParamUnit */
339 paramUnit = audioTypeGetParamUnit(audioType, categoryPath);
340 if (!paramUnit) {
341 ERR_LOG("paramUnit is NULL\n");
342 return APP_ERROR;
343 }
344
345 /* Query the param value */
346 param = paramUnitGetParamByName(paramUnit, paramName);
347 if (!param) {
348 ERR_LOG("Error: Cannot query param value!\n");
349 return APP_ERROR;
350 }
351
352 /* Read unlock */
353 audioTypeUnlock(audioType);
354
355 utilUsleep(1); // delay time make cpu scheduling to other thread
356
357 /* Write param */
358 paramInfo = audioTypeGetParamInfoByName(audioType, paramName);
359 if (audioTypeSetParamData(audioType, categoryPath, paramInfo, (void *)shortArray1, arraySize) == APP_ERROR) {
360 ERR_LOG("Cannot update the param data!!\n");
361 return APP_ERROR;
362 }
363
364 utilUsleep(1); // delay time make cpu scheduling to other thread
365
366 if (audioTypeSetParamData(audioType, categoryPath, paramInfo, (void *)shortArray2, arraySize) == APP_ERROR) {
367 ERR_LOG("Cannot update the param data!!\n");
368 return APP_ERROR;
369 }
370
371 utilUsleep(1); // delay time make cpu scheduling to other thread
372
373 /* Save XML */
374 audioTypeSaveAudioParamXml(audioType, XML_CUS_FOLDER_ON_DEVICE, 1);
375
376 utilUsleep(1); // delay time make cpu scheduling to other thread
377
378 /* Reload XML */
379 if (appHandleReloadAudioType(appHandle, audioType->name) == APP_ERROR) {
380 ERR_LOG("Cannot reload AudioType!\n (%s)", audioType->name);
381 return APP_ERROR;
382 }
383
384 return APP_NO_ERROR;
385}
386
387EXPORT APP_STATUS testAudioTypeLock(AppHandle *appHandle) {
388#ifndef WIN32
389 int i;
390 pthread_t appThread;
391 void *status;
392 ThreadParam threadParam;
393
394 threadParam.times = 50;
395 threadParam.appHandle = appHandle;
396 threadParam.fun = testAudioTypeLockFun;
397
398 if (pthread_create(&appThread, NULL, commonThreadLoop, &threadParam)) {
399 ERR_LOG("Create app thread fail!\n");
400 return APP_ERROR;
401 }
402
403 for (i = 0; i < threadParam.times; i++) {
404 (*threadParam.fun)(appHandle);
405 INFO_LOG("Main thread test round = %d\n", i);
406 }
407
408 /* Waiting 2nd thread join */
409 pthread_join(appThread, &status);
410#else
411 INFO_LOG("Not test this UT on windows\n");
412#endif
413 return APP_NO_ERROR;
414}
415
416EXPORT APP_STATUS testAppHandleInitUninit() {
417 int times = 10;
418 int i;
419 for (i = 0; i < times; i++) {
420 AppHandle testAppHandle;
421 appHandleInit(&testAppHandle);
422#ifdef WIN32
423 appHandleParseXml(&testAppHandle, XML_FOLDER_LIST_ON_TUNING_TOOL, XML_CUS_FOLDER_ON_TUNING_TOOL);
424#else
425 char **xmlDirFromProperty = appGetXmlDirFromProperty();
426 if (xmlDirFromProperty) {
427 appHandleParseXml(&testAppHandle, (const char**)xmlDirFromProperty, XML_CUS_FOLDER_ON_DEVICE);
428 } else {
429 appHandleParseXml(&testAppHandle, XML_FOLDER_LIST_ON_DEVICE, XML_CUS_FOLDER_ON_DEVICE);
430 }
431#endif
432 appHandleUninit(&testAppHandle);
433 }
434 return APP_NO_ERROR;
435}
436
437/***********************************
438 * Test Steps:
439 * 1. Reload audio type xml 100 times
440 * Memory leak / crash checking
441 **********************************/
442EXPORT APP_STATUS testMemoryLeak(AppHandle *appHandle) {
443 int i = 0;
444 for (i = 0; i < 100; i++) {
445 /* stress test query / release / create */
446 AudioType *audioType = appHandleGetAudioTypeByName(appHandle, "Speech");
447 audioType->allowReload = 1;
448 if (appHandleReloadAudioType(appHandle, "Speech") == APP_ERROR) {
449 return APP_ERROR;
450 }
451 }
452
453 printf("Checking memory status and press enter key to continue\n");
454 getchar();
455 return APP_NO_ERROR;
456}
457
458/***********************************
459 * Test Steps:
460 * 1. Read param array
461 * 2. Update param array one item with 32767
462 * 3. Repeat array size times
463 * 4. Check the result
464 **********************************/
465APP_STATUS testReadWriteParam(AppHandle *appHandle) {
466 size_t i, j;
467 ParamUnit *paramUnit;
468 ParamInfo *paramInfo;
469 Param *param;
470 unsigned short *shortArray;
471 size_t arraySize = 1; // The size will update by real array size latter
472
473 const char *audioTypeName = "Speech";
474 const char *paraName = "speech_mode_para";
475 const char *categoryPath = "Band,NB,Profile,Normal,VolIndex,2,Network,GSM";
476
477 AudioType *audioType = appHandleGetAudioTypeByName(appHandle, audioTypeName);
478
479 /* Test steps */
480 for (j = 0; j < arraySize; j++) {
481 paramUnit = audioTypeGetParamUnit(audioType, categoryPath);
482 if (!paramUnit) {
483 ERR_LOG("Cannot find paramUnit\n");
484 return APP_ERROR;
485 }
486
487 param = paramUnitGetParamByName(paramUnit, paraName);
488 if (!param) {
489 ERR_LOG("Cannot query param value!\n");
490 return APP_ERROR;
491 }
492
493 shortArray = (unsigned short *)param->data;
494 arraySize = param->arraySize;
495 /*for(i = 0; i < param->arraySize; i++)
496 {
497 printf("[%d]0x%x\n", i, ((unsigned short*)param->data)[i])
498 }*/
499
500 shortArray[j] = 32767;
501
502 /* You should cache follow object in somewhere without query again */
503 paramInfo = audioTypeGetParamInfoByName(audioType, paraName);
504
505 /* The sph_in_fir param is short array type */
506 if (audioTypeSetParamData(audioType, categoryPath, paramInfo, (void *)shortArray, param->arraySize) == APP_ERROR) {
507 return APP_ERROR;
508 }
509 }
510
511 /* Result check */
512 paramUnit = audioTypeGetParamUnit(audioType, categoryPath);
513 if (!paramUnit) {
514 ERR_LOG("Cannot find paramUnit\n");
515 return APP_ERROR;
516 }
517
518 param = paramUnitGetParamByName(paramUnit, paraName);
519 if (!param) {
520 ERR_LOG("Cannot query param value!\n");
521 return APP_ERROR;
522 }
523
524 shortArray = (unsigned short *)param->data;
525 for (i = 0; i < param->arraySize; i++) {
526 if (shortArray[i] != 32767) {
527 ERR_LOG("Verify short array["APP_SIZE_T_FT"] = %d != 32767\n", i, shortArray[i]);
528 return APP_ERROR;
529 }
530 }
531
532 return APP_NO_ERROR;
533}