/* Build: LDFLAGS += -lsocket_db */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "outlog.h" #include "fileops.h" #include "interact.h" #define BASE_JSON_PATH OUTLOG_PATH"/dragonmat" #define WAIT_TILL_CONNECTED BASE_JSON_PATH"/wait_till_connected" #define EXIT_WHEN_END BASE_JSON_PATH"/exit_when_end" #define EXIT_CALL BASE_JSON_PATH"/exit_call" #define EXIT_WHEN_END_CONTROL "/tmp/exit_dragonmat" // This file is used by DragonMAT to show list. #define TESTCASES_LIST_INI "/tmp/tinatest.ini" #define TIMEOUT 60000 #define MSGSND 123 #define MSGRCV 124 volatile int connected; int msgsnd_id=0; int msgrcv_id=0; int picsnd = 0; typedef struct{ long msgtype; char msgtext[2048]; }msgstru; /* * abstract out the send command public part * and it will be called by dragonmat_* interface * which need to send msg. */ static int dragonmat_snd_common(msgstru *msgs) { if (msgsnd_id == 0) { msgsnd_id = msgget(MSGSND, IPC_EXCL); if (msgsnd_id < 0) { ERROR("msgget failed! - %s\n", strerror(errno)); return -1; } } if (msgsnd(msgsnd_id, msgs, sizeof(msgstru), 0) < 0) { ERROR("msgsnd failed! - %s\n", strerror(errno)); return -1; } return 0; } /* * abstract out the revice command public part * and it will be called by dragonmat_* interface * which need to revice msg. */ static int dragonmat_rcv_common(msgstru *msgs) { if (msgrcv_id == 0) { msgrcv_id = msgget(MSGRCV, IPC_EXCL); if (msgrcv_id < 0) { ERROR("msgget failed! - %s\n", strerror(errno)); return -1; } } if (msgrcv(msgrcv_id, msgs, sizeof(msgstru), msgs->msgtype, 0) < 0) { ERROR("msgrcv failed! - %s\n", strerror(errno)); return -1; } return 0; } /* * integrated send & revice command */ static int dragonmat_reply(msgstru *msgs) { if ((dragonmat_snd_common(msgs)) < 0) { ERROR("dragonmat_reply: snd failed! - %s\n", strerror(errno)); return -1; } if ((dragonmat_rcv_common(msgs)) < 0) { ERROR("dragonmat_reply: rcv failed! - %s\n", strerror(errno)); return -1; } return 0; } int dragonmat_before_all(struct list_head *TASK_LIST) { FILE *fp = fopen(TESTCASES_LIST_INI, "w"); if (fp == NULL) { ERROR("Create %s failed - %s\n", TESTCASES_LIST_INI, strerror(errno)); return -1; } struct task *task = NULL; char *key = NULL; list_for_each_entry(task, TASK_LIST, lnode) { key = strrchr(task->keypath, '/') + 1; DEBUG(BASE, "dragonmat: add testcase %s\n", key); fprintf(fp, "[%s]\n", key); fprintf(fp, "display_name = %s\n", key); fprintf(fp, "activated = 1\n\n"); } fclose(fp); return 0; } int dragonmat_before_one(struct task *task) { msgstru msgs; memset(&msgs, 0, sizeof(msgstru)); if (connected == FALSE) return 0; char *key = strrchr(task->keypath, '/') + 1; DEBUG(BASE, "%s start\n", key); msgs.msgtype = (long)sendStartCase_fix(key, msgs.msgtext); if (dragonmat_reply(&msgs) < 0) { ERROR("%s: reply failed! - %s\n", __func__, strerror(errno)); return -1; } sleep(1); return 0; } int dragonmat_after_one_end(struct task *task) { msgstru msgs; memset(&msgs, 0, sizeof(msgstru)); char *key = strrchr(task->keypath, '/') + 1; int result = 0; if (connected == FALSE) return 0; for (int num = 0; num < task->run_times; num++) { if (task->result[num] != 0) { result = task->result[num]; break; } } DEBUG(BASE, "%s end with %d\n", key, result); msgs.msgtype = (long)sendResult_fix(key, "", result == 0 ? PASS : FAILED, msgs.msgtext); if (dragonmat_reply(&msgs) < 0) { ERROR("%s: reply failed! - %s\n", __func__, strerror(errno)); return -1; } sleep(1); return 0; } int dragonmat_after_all_call(int result) { char *exit_call = NULL; int pid, len, ret = 0, status = 0; char *buf = NULL; exit_call = mjson_fetch_string(EXIT_CALL); if (exit_call) { len = strlen(exit_call) + 10; buf = malloc(len); if (!buf) return -1; snprintf(buf, len, "%s %s", exit_call, result == 0 ? "pass" : "failed"); if ((pid = fork()) < 0) { ret = -1; goto out; } else if (pid == 0) { //child execl("/bin/sh", "/bin/sh", "-c", buf, NULL); _exit(-127); } else { //father waitpid(pid, &status, 0); ret = WEXITSTATUS(status); } } out: free(buf); return ret; } int dragonmat_after_all_exit(void) { int exit = mjson_fetch_boolean(EXIT_WHEN_END); if (exit < 0) exit = FALSE; DEBUG(DATA, "outlog_dragonmat: exit_when_end : %d\n", exit_when_end); if (exit == FALSE) { DEBUG(BASE, "Don't exit tt\n"); remove(EXIT_WHEN_END_CONTROL); if (mkfifo(EXIT_WHEN_END_CONTROL, 0666) < 0) { ERROR("mkfifo %s failed - %s\n", EXIT_WHEN_END_CONTROL, strerror(errno)); return -1; } int fd = open(EXIT_WHEN_END_CONTROL, O_RDONLY); if (fd < 0) { ERROR("open %s failed - %s\n", EXIT_WHEN_END_CONTROL, strerror(errno)); return -1; } char control = 0; while (1) { if (read(fd, &control, 1) != 1) { ERROR("read %s failed - %s\n", EXIT_WHEN_END_CONTROL, strerror(errno)); close(fd); return -1; } if (control == '1') { close(fd); DEBUG(BASE, "Exit outlog-dragonmat now\n"); return 0; } } } return 0; } int dragonmat_after_all(struct list_head *TASK_LIST) { int num; msgstru msgs; memset(&msgs, 0, sizeof(msgstru)); int result = 0, ret = 0; struct task *task = NULL; if (connected == FALSE) return 0; list_for_each_entry(task, TASK_LIST, lnode) { for (num = 0; num < task->run_times; num++) { if (task->result[num] != 0) { result = task->result[num]; break; } } if (result != 0) break; } msgs.msgtype = (long)sendTestEnd_fix(result == 0 ? PASS : FAILED, "null", msgs.msgtext); if (dragonmat_reply(&msgs) < 0) { ERROR("%s: reply failed! - %s\n", __func__, strerror(errno)); ret = -1; goto out; } dragonmat_after_all_call(result); dragonmat_after_all_exit(); out: remove(EXIT_WHEN_END_CONTROL); return ret; } void *wait_connected(void *arg) { if (waitSocketConnect() < 0) pthread_exit("wait Socket Connect failed"); connected = TRUE; pthread_exit("dragonmat connected"); } int dragonmat_init(void) { connected = FALSE; if (init_entry() < 0) { ERROR("init entry of socket_db failed\n"); return -1; } int wait_till_connected = mjson_fetch_boolean(WAIT_TILL_CONNECTED); if (wait_till_connected < 0) wait_till_connected = 0; DEBUG(DATA, "outlog_dragonmat: wait_till_connected : %d\n", wait_till_connected); pthread_t tid; if (pthread_create(&tid, NULL, wait_connected, NULL) != 0) { ERROR("create pthread to wait connected failed\n"); return -1; } char *ret; if (wait_till_connected == TRUE && connected != TRUE) { DEBUG(BASE, "waiting dragonmat connected\n"); pthread_join(tid, (void **)&ret); if (connected == TRUE) DEBUG(BASE, "%s\n", ret); else ERROR("%s\n", ret); } else { pthread_detach(tid); } return 0; } /* assignment to struct fileInfo with filepath */ static struct fileInfo dragonmat_fileinit(const char *file_dir, const char *file_base) { struct fileInfo file; strcpy(file.filename, file_base); strcpy(file.filedir, file_dir); file.size = 0; file.compress = 0; file.checksum = 0; return file; } static int dragonmat_filesnd(const char *filepath, const char *testcase, const char *tips, msgstru *msgs) { int ret = -1; struct fileInfo file; cutpath cp = cut_path(filepath); const int len_pathdir_0 = strlen(cp.dir) + 1; const int len_pathbase = strlen(cp.base); char *path = (char *)malloc(sizeof(char) * 256); memset(path, '\0', sizeof(char) * 256); strncpy(path, cp.dir, len_pathdir_0); DIR *dp; struct dirent *dirp; if ((dp = opendir(cp.dir)) == NULL) { ERROR("open dir: %s failed! - %s\n", cp.dir, strerror(errno)); goto err; } while ((dirp = readdir(dp)) != NULL) { if(strncmp(cp.base, dirp->d_name, len_pathbase) != 0) continue; file = dragonmat_fileinit(path, dirp->d_name); msgs->msgtype = (long)uploadFileRequest_fix(&file, testcase, tips, msgs->msgtext); if (dragonmat_reply(msgs) < 0) { ERROR("dragonmat_filesnd: upload file failed! - %s\n", strerror(errno)); goto err; } if (picsnd == 1) { // msgs->msgtype = (long)sendShowResRequest_fix(&file, "image", testcase, tips, msgs->msgtext); memset(msgs->msgtext, 0, 2048); msgs->msgtype = (long)sendCMDselect_fix(cp.base, tips, dirp->d_name, TIMEOUT, msgs->msgtext); if (dragonmat_reply(msgs) < 0){ ERROR("dragonmat_filesnd: show image failed! - %s\n", strerror(errno)); goto err; } ret = getReturn_fix(msgs->msgtext) == 1 ? 0 : 1; } } if (ret < 0) ret = 0; err: closedir(dp); free(cp.dir); free(path); return ret; } /* * FIXME: dragonmat_ask interface are not complete. * It will be achieve until libsocket_db add function * that get user input string on dragonmat */ static int dragonmat_ask(const char *testcase, const char *tips, char *reply, int len) { int ret = -1; msgstru msgs; memset(&msgs, 0, sizeof(msgstru)); cutpath cp = cut_path(testcase); msgs.msgtype = (long)sendEdit_fix(cp.base, tips, reply, cp.base, TIMEOUT, msgs.msgtext); if (dragonmat_reply(&msgs) < 0) { ERROR("dragonmat_ask: reply failed! - %s\n", strerror(errno)); goto err; } ret = getValue_fix(msgs.msgtext, "editvalue", reply, &len) == 1 ? 0 : -1; err: free(cp.dir); return ret; } /* * send select CMD to user, people will choose (Yes/No) * on dragonmat. * @testcase: testcase name * @tips: tips message to user * * return: 1(Yes) / 0(No) */ static int dragonmat_istrue(const char *testcase, const char *tips) { int ret = -1; cutpath cp = cut_path(testcase); msgstru msgs; memset(&msgs, 0, sizeof(msgstru)); /* msgstru *msgs = (msgstru *)malloc(sizeof(msgstru)); if (NULL == msgs) { ERROR("dragonmat_istrue: malloc failed! - %s\n", strerror(errno)); goto err; } */ msgs.msgtype = (long)sendCMDselect_fix(cp.base, tips, "", TIMEOUT, msgs.msgtext); if (dragonmat_reply(&msgs) < 0) { ERROR("dragonmat_istrue: reply failed! - %s\n", strerror(errno)); goto err; } ret = getReturn_fix(msgs.msgtext) == 1 ? true : false; err: // free(msgs); free(cp.dir); return ret; } /* * send tips message to user. * @testcase: testcase name * @tips: tips message to user * * return: -1(failed) / 0(success) */ static int dragonmat_tips(const char *testcase, const char *tips) { int ret = -1; cutpath cp = cut_path(testcase); msgstru msgs; memset(&msgs, 0, sizeof(msgstru)); /* msgstru *msgs = (msgstru *)malloc(sizeof(msgstru)); if (NULL == msgs) { ERROR("dragonmat_tips: malloc failed! - %s\n", strerror(errno)); goto err; } */ msgs.msgtype = (long)sendTip_fix(cp.base, tips, msgs.msgtext); if (dragonmat_reply(&msgs) < 0) { ERROR("dragonmat_ttips: reply failed! - %s\n", strerror(errno)); goto err; } ret = 0; err: // free(msgs); free(cp.dir); return ret; } /* * upload file from device to PC and the file will * be stored in dragonmat_xxx/result_dir/0/ directory. * @testcase: testcase name * @filepath: the file directory on device * @tips: tips message to user * * return: -1(failed) / 0(success) */ static int dragonmat_upfile(const char *testcase, const char *filepath, const char *tips) { int ret = -1; cutpath cp = cut_path(testcase); msgstru msgs; memset(&msgs, 0, sizeof(msgstru)); /* msgstru *msgs = (msgstru *)malloc(sizeof(msgstru)); if (NULL == msgs) { ERROR("dragonmat_tips: malloc failed! - %s\n", strerror(errno)); goto err; } */ if ((dragonmat_filesnd(filepath, cp.base, tips, &msgs)) < 0) { ERROR("dragonmat_upfile: filesnd failed! - %s\n", strerror(errno)); goto err; } ret = 0; err: // free(msgs); free(cp.dir); return ret; } /* * 1. upload image from device to PC * 2. show image * 3. ask people * @testcase: testcase name * @filepath: the image directory on device * @tips: tips message to user * * return: 1(Yes) / 0(No) */ static int dragonmat_showimg(const char *testcase, const char *filepath, const char *tips) { int ret = -1; picsnd = 1; cutpath cp = cut_path(testcase); msgstru msgs; memset(&msgs, 0, sizeof(msgstru)); /* msgstru *msgs = (msgstru *)malloc(sizeof(msgstru)); if (NULL == msgs) { ERROR("dragonmat_tips: malloc failed! - %s\n", strerror(errno)); goto err; } */ /* get specify format filepath */ if ((ret = dragonmat_filesnd(filepath, cp.base, tips, &msgs)) < 0){ ERROR("dragonmat_showimg: filesnd failed! - %s\n", strerror(errno)); goto err; } err: // free(msgs); picsnd = 0; free(cp.dir); return ret; } void module_init(void) { if (dragonmat_init() < 0) return; outlog_register_ex( dragonmat_before_all, dragonmat_before_one, NULL, NULL, dragonmat_after_one_end, dragonmat_after_all); interact_register( dragonmat_ask, dragonmat_tips, dragonmat_istrue, dragonmat_upfile, dragonmat_showimg); }