|  | #include "AudioParamParserPriv.h" | 
|  |  | 
|  | typedef APP_STATUS(*TEST_FUN)(AppHandle *appHandle); | 
|  |  | 
|  | typedef struct | 
|  | { | 
|  | AppHandle *appHandle; | 
|  | int times; | 
|  | TEST_FUN fun; | 
|  | } ThreadParam; | 
|  |  | 
|  | EXPORT APP_STATUS unitTest(AppHandle *appHandle) | 
|  | { | 
|  | APP_STATUS res = APP_NO_ERROR; | 
|  | APP_STATUS finalRes = APP_NO_ERROR; | 
|  |  | 
|  | printf("===APP internal unit test===\n"); | 
|  | #if 0 | 
|  | res = testAppHandleInitUninit(); | 
|  | if (res == APP_ERROR) | 
|  | { | 
|  | finalRes = APP_ERROR; | 
|  | } | 
|  | printf("testAppHandleInitUninit: %s\n", res ? "pass" : "fail"); | 
|  | #endif | 
|  | res = testReadWriteParam(appHandle); | 
|  | if (res == APP_ERROR) | 
|  | { | 
|  | finalRes = APP_ERROR; | 
|  | } | 
|  | printf("testReadWriteParam: %s\n", res ? "pass" : "fail"); | 
|  |  | 
|  | res = testMemoryLeak(appHandle); | 
|  | if (res == APP_ERROR) | 
|  | { | 
|  | finalRes = APP_ERROR; | 
|  | } | 
|  | printf("testMemoryLeak: %s\n", res ? "pass" : "fail"); | 
|  |  | 
|  | res = testAudioTypeLock(appHandle); | 
|  | if (res == APP_ERROR) | 
|  | { | 
|  | finalRes = APP_ERROR; | 
|  | } | 
|  | printf("testAudioTypeLock: %s\n", res ? "pass" : "fail"); | 
|  | printf("=============================\n"); | 
|  |  | 
|  | return finalRes; | 
|  | } | 
|  |  | 
|  |  | 
|  | EXPORT void *commonThreadLoop(void *arg) | 
|  | { | 
|  | ThreadParam threadParam = *(ThreadParam *)arg; | 
|  | int i = 0 ; | 
|  | for (i = 0; i < threadParam.times; i++) | 
|  | { | 
|  | (*threadParam.fun)(threadParam.appHandle); | 
|  | INFO_LOG("2nd thread round = %d\n", i); | 
|  | } | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | EXPORT void testDebugLevel() | 
|  | { | 
|  | appSetDebugLevel(ERR_LEVEL); | 
|  | ERR_LOG("error - pass\n"); | 
|  | WARN_LOG("warn - ok\n"); | 
|  | INFO_LOG("info - ok\n"); | 
|  | DEBUG_LOG("debug - ok\n"); | 
|  |  | 
|  | appSetDebugLevel(WARN_LEVEL); | 
|  | ERR_LOG("error - fail\n"); | 
|  | WARN_LOG("warn - pass\n"); | 
|  | INFO_LOG("info - ok\n"); | 
|  | DEBUG_LOG("debug - ok\n"); | 
|  |  | 
|  | appSetDebugLevel(INFO_LEVEL); | 
|  | ERR_LOG("error - fail\n"); | 
|  | WARN_LOG("warn - fail\n"); | 
|  | INFO_LOG("info - pass\n"); | 
|  | DEBUG_LOG("debug - ok\n"); | 
|  |  | 
|  | appSetDebugLevel(DEBUG_LEVEL); | 
|  | ERR_LOG("error - fail\n"); | 
|  | WARN_LOG("warn - fail\n"); | 
|  | INFO_LOG("info - fail\n"); | 
|  | DEBUG_LOG("debug - pass\n"); | 
|  | } | 
|  |  | 
|  | EXPORT void testHashParamTree() | 
|  | { | 
|  | ParamTree *item; | 
|  | ParamTree *ParamTreeHash = NULL, *tmp = NULL; /* Used for hash */ | 
|  | const char *key; | 
|  |  | 
|  | item = (ParamTree *)malloc(sizeof(ParamTree)); | 
|  | item->categoryPath = "NB,Normal,,"; | 
|  | item->paramId = 1; | 
|  | HASH_ADD_KEYPTR(hh, ParamTreeHash, item->categoryPath, strlen(item->categoryPath), item); | 
|  |  | 
|  | item = (ParamTree *)malloc(sizeof(ParamTree)); | 
|  | item->categoryPath = "WB,Normal,,"; | 
|  | item->paramId = 7; | 
|  | HASH_ADD_KEYPTR(hh, ParamTreeHash, item->categoryPath, strlen(item->categoryPath), item); | 
|  |  | 
|  | item = (ParamTree *)malloc(sizeof(ParamTree)); | 
|  | item->categoryPath = "NB,Normal,0,GSM,"; | 
|  | item->paramId = 1; | 
|  | HASH_ADD_KEYPTR(hh, ParamTreeHash, item->categoryPath, strlen(item->categoryPath), item); | 
|  |  | 
|  | item = (ParamTree *)malloc(sizeof(ParamTree)); | 
|  | item->categoryPath = "NB,HAC,0,GSM"; | 
|  | item->paramId = 0; | 
|  | HASH_ADD_KEYPTR(hh, ParamTreeHash, item->categoryPath, strlen(item->categoryPath), item); | 
|  |  | 
|  | /* Find string */ | 
|  | key = "WB,,,"; | 
|  | HASH_FIND_STR(ParamTreeHash, key, item); | 
|  | if (item) { printf("[%s] id is %d\n", key, item->paramId); } | 
|  |  | 
|  | /* Free hash table content */ | 
|  | HASH_ITER(hh, ParamTreeHash, item, tmp) | 
|  | { | 
|  | HASH_DEL(ParamTreeHash, item); | 
|  | free(item); | 
|  | } | 
|  | } | 
|  |  | 
|  | EXPORT void testHashParamUnit() | 
|  | { | 
|  | ParamUnit *item; | 
|  | ParamUnit *ParamUnitHash = NULL, *tmp = NULL; /* Used for hash */ | 
|  | int key; | 
|  |  | 
|  | item = (ParamUnit *)malloc(sizeof(ParamUnit)); | 
|  | item->paramId = 0; | 
|  | item->paramHash = (Param *) 0x1; | 
|  | HASH_ADD_INT(ParamUnitHash, paramId, item); | 
|  |  | 
|  | item = (ParamUnit *)malloc(sizeof(ParamUnit)); | 
|  | item->paramId = 1; | 
|  | item->paramHash = (Param *)0x2; | 
|  | HASH_ADD_INT(ParamUnitHash, paramId, item); | 
|  | item = (ParamUnit *)malloc(sizeof(ParamUnit)); | 
|  |  | 
|  | item->paramId = 7; | 
|  | item->paramHash = (Param *)0x3; | 
|  | HASH_ADD_INT(ParamUnitHash, paramId, item); | 
|  |  | 
|  | /* Find string */ | 
|  | key = 0; | 
|  | HASH_FIND_INT(ParamUnitHash, &key, item); | 
|  | if (item) { INFO_LOG("[%d] Param is %p\n", key, item->paramHash); } | 
|  |  | 
|  | key = 1; | 
|  | HASH_FIND_INT(ParamUnitHash, &key, item); | 
|  | if (item) { INFO_LOG("[%d] Param is %p\n", key, item->paramHash); } | 
|  |  | 
|  | key = 7; | 
|  | HASH_FIND_INT(ParamUnitHash, &key, item); | 
|  | if (item) { INFO_LOG("[%d] Param is %p\n", key, item->paramHash); } | 
|  |  | 
|  | /* Free hash table content */ | 
|  | HASH_ITER(hh, ParamUnitHash, item, tmp) | 
|  | { | 
|  | HASH_DEL(ParamUnitHash, item); | 
|  | free(item); | 
|  | } | 
|  | } | 
|  |  | 
|  | EXPORT void testHashParam() | 
|  | { | 
|  | Param *item; | 
|  | Param *paramHash = NULL, *tmp = NULL; /* Used for hash */ | 
|  | const char *key; | 
|  |  | 
|  | item = (Param *)malloc(sizeof(Param)); | 
|  | memset(item, 0, sizeof(Param)); | 
|  | item->name = "speech_mode_para"; | 
|  | item->data = "0x0011,0x2233,0x4455"; | 
|  | HASH_ADD_KEYPTR(hh, paramHash, item->name, strlen(item->name), item); | 
|  |  | 
|  | item = (Param *)malloc(sizeof(Param)); | 
|  | memset(item, 0, sizeof(Param)); | 
|  | item->name = "uint_param"; | 
|  | item->data = "4294967295"; | 
|  | HASH_ADD_KEYPTR(hh, paramHash, item->name, strlen(item->name), item); | 
|  |  | 
|  | item = (Param *)malloc(sizeof(Param)); | 
|  | memset(item, 0, sizeof(Param)); | 
|  | item->name = "float_param"; | 
|  | item->data = "0.1234567"; | 
|  | HASH_ADD_KEYPTR(hh, paramHash, item->name, strlen(item->name), item); | 
|  |  | 
|  | /* Find string */ | 
|  | key = "speech_mode_para"; | 
|  | HASH_FIND_STR(paramHash, key, item); | 
|  | if (item) { INFO_LOG("[%s] value is %s\n", key, (char *)item->data); } | 
|  |  | 
|  | key = "uint_param"; | 
|  | HASH_FIND_STR(paramHash, key, item); | 
|  | if (item) { INFO_LOG("[%s] value is %s\n", key, (char *)item->data); } | 
|  |  | 
|  | key = "float_param"; | 
|  | HASH_FIND_STR(paramHash, key, item); | 
|  | if (item) { INFO_LOG("[%s] value is %s\n", key, (char *)item->data); } | 
|  |  | 
|  | /* Free hash table content */ | 
|  | HASH_ITER(hh, paramHash, item, tmp) | 
|  | { | 
|  | HASH_DEL(paramHash, item); | 
|  | free(item); | 
|  | } | 
|  | } | 
|  |  | 
|  | void testCb(AppHandle *appHandle, const char *audioTypeName) | 
|  | { | 
|  | printf("XML file changed. (cus folder = %s, audioType = %s)\n", appHandle->xmlCusDir, audioTypeName); | 
|  | } | 
|  |  | 
|  | EXPORT void notifyCbTest(AppHandle *appHandle) | 
|  | { | 
|  | NotifyCb *cb; | 
|  |  | 
|  | appHandleRegXmlChangedCb(appHandle, testCb); | 
|  |  | 
|  | LL_FOREACH(appHandle->noficyCbList, cb) | 
|  | { | 
|  | (*cb->cb)(appHandle, "OK"); | 
|  | } | 
|  |  | 
|  | appHandleUnregXmlChangedCb(appHandle, testCb); | 
|  |  | 
|  | LL_FOREACH(appHandle->noficyCbList, cb) | 
|  | { | 
|  | (*cb->cb)(appHandle, "FAIL"); | 
|  | } | 
|  | } | 
|  |  | 
|  | EXPORT void inotifyTest(const char *path) | 
|  | { | 
|  |  | 
|  | #ifndef WIN32 | 
|  | #define INOTIFY_BUF_SIZE 512 | 
|  | /* inotify test */ | 
|  | int wd; | 
|  | size_t len; | 
|  | char buf[INOTIFY_BUF_SIZE]; | 
|  | char *ptr; | 
|  | const struct inotify_event *event; | 
|  |  | 
|  | int fd = inotify_init(); | 
|  | if (fd < 0) | 
|  | { | 
|  | printf("inotify_init failed !!!"); | 
|  | exit(1); | 
|  | } | 
|  |  | 
|  | printf("inotify path = %s\n", path); | 
|  | wd = inotify_add_watch(fd, path, IN_CLOSE_WRITE); | 
|  | if (wd < 0) | 
|  | { | 
|  | printf("inotify_add_watch failed !!!"); | 
|  | exit(1); | 
|  | } | 
|  |  | 
|  | while (1) | 
|  | { | 
|  | len = read(fd, buf, sizeof(buf)); | 
|  | if (len < 0) | 
|  | { | 
|  | perror("read"); | 
|  | exit(EXIT_FAILURE); | 
|  | } | 
|  |  | 
|  | /* Loop over all events in the buffer */ | 
|  | for (ptr = buf; ptr < buf + len; ptr += sizeof(struct inotify_event) + event->len) | 
|  | { | 
|  | event = (const struct inotify_event *) ptr; | 
|  |  | 
|  | /* Print event type */ | 
|  | if (event->mask & IN_OPEN) | 
|  | { | 
|  | printf("IN_OPEN: "); | 
|  | } | 
|  | if (event->mask & IN_CLOSE_NOWRITE) | 
|  | { | 
|  | printf("IN_CLOSE_NOWRITE: "); | 
|  | } | 
|  | if (event->mask & IN_CLOSE_WRITE) | 
|  | { | 
|  | printf("IN_CLOSE_WRITE: "); | 
|  | } | 
|  | if (event->mask & IN_ACCESS) | 
|  | { | 
|  | printf("IN_ACCESS: "); | 
|  | } | 
|  |  | 
|  | /* Print the name of the file */ | 
|  |  | 
|  | if (event->len) | 
|  | { | 
|  | printf("%s", event->name); | 
|  | } | 
|  |  | 
|  | /* Print type of filesystem object */ | 
|  |  | 
|  | if (event->mask & IN_ISDIR) | 
|  | { | 
|  | printf(" [directory]\n"); | 
|  | } | 
|  | else | 
|  | { | 
|  | printf(" [file]\n"); | 
|  | } | 
|  | } | 
|  | } | 
|  | inotify_rm_watch(fd, IN_CLOSE_NOWRITE); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | /*********************************** | 
|  | * Test Steps: | 
|  | * 1. Create thread to read/write param | 
|  | * 2. Check the lock is work well | 
|  | * Crash/deadlock checking | 
|  | **********************************/ | 
|  | EXPORT APP_STATUS testAudioTypeLockFun(AppHandle *appHandle) | 
|  | { | 
|  | /* Read param */ | 
|  | char *audioTypeName = "Speech"; | 
|  | char *categoryPath = "Band,NB,Profile,4_pole_Headset,VolIndex,3"; | 
|  | char *paramName = "speech_mode_para"; | 
|  | unsigned short shortArray1[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}; | 
|  | unsigned short shortArray2[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; | 
|  | int arraySize = 7; | 
|  | AudioType *audioType; | 
|  | ParamUnit *paramUnit; | 
|  | ParamInfo *paramInfo; | 
|  | Param *param; | 
|  |  | 
|  | appHandle = appHandleGetInstance(); | 
|  |  | 
|  | /* Query AudioType */ | 
|  | audioType = appHandleGetAudioTypeByName(appHandle, audioTypeName); | 
|  | if (!audioType) | 
|  | { | 
|  | ERR_LOG("audioType is NULL\n"); | 
|  | return APP_ERROR; | 
|  | } | 
|  |  | 
|  | /* Read Lock */ | 
|  | audioTypeReadLock(audioType, __FUNCTION__); | 
|  |  | 
|  | /* Query the ParamUnit */ | 
|  | paramUnit = audioTypeGetParamUnit(audioType, categoryPath); | 
|  | if (!paramUnit) | 
|  | { | 
|  | ERR_LOG("paramUnit is NULL\n"); | 
|  | return APP_ERROR; | 
|  | } | 
|  |  | 
|  | /* Query the param value */ | 
|  | param = paramUnitGetParamByName(paramUnit, paramName); | 
|  | if (!param) | 
|  | { | 
|  | ERR_LOG("Error: Cannot query param value!\n"); | 
|  | return APP_ERROR; | 
|  | } | 
|  |  | 
|  | /* Read unlock */ | 
|  | audioTypeUnlock(audioType); | 
|  |  | 
|  | utilUsleep(1);  // delay time make cpu scheduling to other thread | 
|  |  | 
|  | /* Write param */ | 
|  | paramInfo = audioTypeGetParamInfoByName(audioType, paramName); | 
|  | if (audioTypeSetParamData(audioType, categoryPath, paramInfo, (void *)shortArray1, arraySize) == APP_ERROR) | 
|  | { | 
|  | ERR_LOG("Cannot update the param data!!\n"); | 
|  | return APP_ERROR; | 
|  | } | 
|  |  | 
|  | utilUsleep(1);  // delay time make cpu scheduling to other thread | 
|  |  | 
|  | if (audioTypeSetParamData(audioType, categoryPath, paramInfo, (void *)shortArray2, arraySize) == APP_ERROR) | 
|  | { | 
|  | ERR_LOG("Cannot update the param data!!\n"); | 
|  | return APP_ERROR; | 
|  | } | 
|  |  | 
|  | utilUsleep(1);  // delay time make cpu scheduling to other thread | 
|  |  | 
|  | /* Save XML */ | 
|  | audioTypeSaveAudioParamXml(audioType, XML_CUS_FOLDER_ON_DEVICE, 1); | 
|  |  | 
|  | utilUsleep(1);  // delay time make cpu scheduling to other thread | 
|  |  | 
|  | /* Reload XML */ | 
|  | appHandleReloadAudioType(appHandle, audioType->name); | 
|  |  | 
|  | return APP_NO_ERROR; | 
|  | } | 
|  |  | 
|  | EXPORT APP_STATUS testAudioTypeLock(AppHandle *appHandle) | 
|  | { | 
|  | #ifndef WIN32 | 
|  | int i; | 
|  | pthread_t appThread; | 
|  | void *status; | 
|  | ThreadParam threadParam; | 
|  |  | 
|  | threadParam.times = 50; | 
|  | threadParam.appHandle = appHandle; | 
|  | threadParam.fun = testAudioTypeLockFun; | 
|  |  | 
|  | if (pthread_create(&appThread, NULL, commonThreadLoop, &threadParam)) | 
|  | { | 
|  | ERR_LOG("Create app thread fail!\n"); | 
|  | return APP_ERROR; | 
|  | } | 
|  |  | 
|  | for (i = 0; i < threadParam.times; i++) | 
|  | { | 
|  | (*threadParam.fun)(appHandle); | 
|  | INFO_LOG("Main thread test round = %d\n", i); | 
|  | } | 
|  |  | 
|  | /* Waiting 2nd thread join */ | 
|  | pthread_join(appThread, &status); | 
|  | #else | 
|  | INFO_LOG("Not test this UT on windows\n"); | 
|  | #endif | 
|  | return APP_NO_ERROR; | 
|  | } | 
|  |  | 
|  | EXPORT APP_STATUS testAppHandleInitUninit() | 
|  | { | 
|  | int times = 10; | 
|  | int i; | 
|  | for (i = 0; i < times; i++) | 
|  | { | 
|  | AppHandle testAppHandle; | 
|  | appHandleInit(&testAppHandle); | 
|  | #ifdef WIN32 | 
|  | appHandleParseXml(&testAppHandle, XML_FOLDER_ON_TUNING_TOOL, XML_CUS_FOLDER_ON_TUNING_TOOL); | 
|  | #else | 
|  | appHandleParseXml(&testAppHandle, XML_FOLDER_ON_DEVICE, XML_CUS_FOLDER_ON_DEVICE); | 
|  | #endif | 
|  | appHandleUninit(&testAppHandle); | 
|  | } | 
|  | return APP_NO_ERROR; | 
|  | } | 
|  |  | 
|  | /*********************************** | 
|  | * Test Steps: | 
|  | * 1. Reload audio type xml 100 times | 
|  | * Memory leak / crash checking | 
|  | **********************************/ | 
|  | EXPORT APP_STATUS testMemoryLeak(AppHandle *appHandle) | 
|  | { | 
|  | int i = 0; | 
|  | for (i = 0; i < 100; i++) | 
|  | { | 
|  | /* stress test query / release / create */ | 
|  | AudioType *audioType = appHandleGetAudioTypeByName(appHandle, "Speech"); | 
|  | audioType->allowReload = 1; | 
|  | if (appHandleReloadAudioType(appHandle, "Speech") == APP_ERROR) | 
|  | { | 
|  | return APP_ERROR; | 
|  | } | 
|  | } | 
|  |  | 
|  | printf("Checking memory status and press enter key to continue\n"); | 
|  | getchar(); | 
|  | return APP_NO_ERROR; | 
|  | } | 
|  |  | 
|  | /*********************************** | 
|  | * Test Steps: | 
|  | * 1. Read param array | 
|  | * 2. Update param array one item with 32767 | 
|  | * 3. Repeat array size times | 
|  | * 4. Check the result | 
|  | **********************************/ | 
|  | APP_STATUS testReadWriteParam(AppHandle *appHandle) | 
|  | { | 
|  | size_t i, j; | 
|  | ParamUnit *paramUnit; | 
|  | ParamInfo *paramInfo; | 
|  | Param *param; | 
|  | unsigned short *shortArray; | 
|  | size_t arraySize = 1;  // The size will update by real array size latter | 
|  |  | 
|  | const char *audioTypeName = "Speech"; | 
|  | const char *paraName = "speech_mode_para"; | 
|  | const char *categoryPath = "Band,NB,Profile,Normal,VolIndex,2,Network,GSM"; | 
|  |  | 
|  | AudioType *audioType = appHandleGetAudioTypeByName(appHandle, audioTypeName); | 
|  |  | 
|  | /* Test steps */ | 
|  | for (j = 0; j < arraySize; j++) | 
|  | { | 
|  | paramUnit = audioTypeGetParamUnit(audioType, categoryPath); | 
|  | if (!paramUnit) | 
|  | { | 
|  | ERR_LOG("Cannot find paramUnit\n"); | 
|  | return APP_ERROR; | 
|  | } | 
|  |  | 
|  | param = paramUnitGetParamByName(paramUnit, paraName); | 
|  | if (!param) | 
|  | { | 
|  | ERR_LOG("Cannot query param value!\n"); | 
|  | return APP_ERROR; | 
|  | } | 
|  |  | 
|  | shortArray = (unsigned short *)param->data; | 
|  | arraySize = param->arraySize; | 
|  | /*for(i = 0; i < param->arraySize; i++) | 
|  | { | 
|  | printf("[%d]0x%x\n", i, ((unsigned short*)param->data)[i]) | 
|  | }*/ | 
|  |  | 
|  | shortArray[j] = 32767; | 
|  |  | 
|  | /* You should cache follow object in somewhere without query again */ | 
|  | paramInfo = audioTypeGetParamInfoByName(audioType, paraName); | 
|  |  | 
|  | /* The sph_in_fir param is short array type */ | 
|  | if (audioTypeSetParamData(audioType, categoryPath, paramInfo, (void *)shortArray, param->arraySize) == APP_ERROR) | 
|  | { | 
|  | return APP_ERROR; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Result check */ | 
|  | paramUnit = audioTypeGetParamUnit(audioType, categoryPath); | 
|  | if (!paramUnit) | 
|  | { | 
|  | ERR_LOG("Cannot find paramUnit\n"); | 
|  | return APP_ERROR; | 
|  | } | 
|  |  | 
|  | param = paramUnitGetParamByName(paramUnit, paraName); | 
|  | if (!param) | 
|  | { | 
|  | ERR_LOG("Cannot query param value!\n"); | 
|  | return APP_ERROR; | 
|  | } | 
|  |  | 
|  | shortArray = (unsigned short *)param->data; | 
|  | for (i = 0; i < param->arraySize; i++) | 
|  | { | 
|  | if (shortArray[i] != 32767) | 
|  | { | 
|  | ERR_LOG("Verify short array[%lu] = %d != 32767\n", i, shortArray[i]); | 
|  | return APP_ERROR; | 
|  | } | 
|  | } | 
|  |  | 
|  | return APP_NO_ERROR; | 
|  | } |