我设计的工厂测试工具是CS结构的,在设备端会有一个Server,再PC端会有一个Client,两者进行交互完成测试。
通讯方式选择:
1.Stocket:优点是不基于ADB,可以自己定义接口,相对稳定,在Android2.3以前似乎多数的测试工具都是使用这个方式,需要在设备端跑起来一个S程序,等待接收命令。
2.ADB:优点方便,直接移植过来Android的ADBD的程序即可,加一些传输的信息的D-CODE以及P-CODE即可,在Android2.3以后ADB逐渐稳定,我觉得使用这种方式更加方便。
PC端:窗口设计需要简明,简单,按钮大,方便工厂测试工人的操作;与工厂产线的接口需要开放,扩展性好。(推荐使用VC开发)
设备端:设计需要扩展性强,稳定,(使用C开发)
我主要做的设备端,就说说设备端的设计吧:
先确定你需要测试的模块,在确定你需要测试模块的相关功能,这样把每个模块分开,可以尽量的模块之间的干扰。
main.h
-
#define CMD(cmd) extern int cmd##_main(char**, int, char*);
-
#include<DefineCommand.h>
-
#undef CMD
-
-
typedef int (*mode_main_func)(char** argv, int argc, char* send_buff);
-
-
typedef struct _MODE
-
{
-
char* name;
-
mode_main_func main_func;
-
} MODE;
-
-
MODE g_ModeTable[] = {
-
#define CMD(cmd) { #cmd, cmd##_main },
-
#include<DefineCommand.h>
-
#undef CMD
-
};
DefineCommand
.h
-
CMD(bt)
-
CMD(wifi)
-
CMD(nfc)
-
CMD(fm)
-
CMD(audio)
-
CMD(headset)
-
CMD(mic)
-
CMD(speaker)
-
CMD(camera)
-
CMD(gps)
-
CMD(touch)
-
CMD(rtc)
-
CMD(vibrator)
-
CMD(imei)
-
CMD(battery)
-
CMD(charging)
-
CMD(g_sensors)
-
CMD(p_sensors)
-
CMD(l_sensors)
-
CMD(led)
-
CMD(lcd)
-
CMD(keypad)
-
CMD(modem)
-
CMD(sd)
-
CMD(hdmi)
-
CMD(small_camera)
-
CMD(lcd_back_light)
-
CMD(camera_flash)
main.c
-
MODE* getMode(char* mode);
-
-
int main(int argc, char **argv)
-
{
-
int ret = 0;
-
MODE* tMode = NULL;
-
char* mode_name = (char *)malloc(MODE_SIZE); //模块名称
-
char* func_name = (char *)malloc(FUNC_SIZE); //模块测试功能名称
-
char* send_buff = (char *)malloc(MAXBUFF);
-
int func_val = -1, func_argc= 0;
-
-
if (argc < ARGC_NUM) {
-
//TCMD_LOGE(mode_name, func_name, COMMAND_ARGC_ERROR);
-
return COMMAND_ARGC_ERROR;
-
}
-
-
stpcpy(mode_name, argv[1]);
-
stpcpy(func_name, argv[2]);
-
func_argc = argc - 3;
-
-
tMode = getMode(mode_name);
-
-
if (tMode) {
-
-
func_val = tMode->main_func(argv, func_argc, send_buff);
-
-
switch (func_val)
-
{
-
case COMMAND_UNDEFINE_FUNC:
-
//TCMD_LOGE(mode_name, func_name, COMMAND_UNDEFINE_FUNC);
-
ret = COMMAND_UNDEFINE_FUNC;
-
break;
-
case COMMAND_ARGC_ERROR:
-
//TCMD_LOGE(mode_name, func_name, COMMAND_ARGC_ERROR);
-
ret = COMMAND_ARGC_ERROR;
-
break;
-
case COMMAND_EXEC_FAILE:
-
//TCMD_LOGE(mode_name, func_name, COMMAND_EXEC_FAILE);
-
ret = COMMAND_EXEC_FAILE;
-
case COMMAND_EXEC_SUCCESSFUL:
-
//TCMD_LOGI(mode_name, func_name, "Successful.\n");
-
ret = COMMAND_EXEC_SUCCESSFUL;
-
break;
-
default:
-
//TCMD_LOGE(mode_name, func_name, COMMAND_UNKNOWN_ERROR);
-
ret = COMMAND_UNKNOWN_ERROR;
-
break;
-
}
-
-
} else {
-
//TCMD_LOGE(mode_name, func_name,COMMAND_UNDEFINE_MODE);
-
ret = COMMAND_UNDEFINE_MODE;
-
}
-
-
return ret;
-
}
-
MODE* getMode(char* name)
-
{
-
MODE* tMode = NULL;
-
int i = 0;
-
int mode_num = sizeof(g_ModeTable) / sizeof(MODE);
-
-
for (; i < mode_num; ++i) {
-
if(!strcmp(name, g_ModeTable[i].name)) {
-
tMode = &g_ModeTable[i];
-
TCMD_LOGD("Mode_table.name = %s", tMode->name);
-
break;
-
}
-
-
}
-
return tMode == NULL ? NULL : tMode;
-
}
然后就进入到各个模块的的main中执行了,例子battery.c
-
int battery_main(char** argv, int argc, char* send_buff)
-
{
-
int ret = 0;
-
char* func_name = (char *)malloc(FUNC_SIZE);
-
-
stpcpy(func_name, argv[2]);
-
-
if(!strcmp(func_name, "--info"))
-
ret = battery_read_info(argv, argc, send_buff);
-
else
-
ret = COMMAND_UNDEFINE_FUNC;
-
-
return ret;
-
}
分两种的测试方式,一种是直接操作kernel提供的sys测试节点,比如Touch Sensor Battery Rtc都可以这样搞,但是像Audio Camera BT/WIFI/GPS Modem这样的大型模块就不太好这样测试了,需要调用相关的测试模块,这样就需要进程之间的通信,我使用的recovery中recovery与updater之间的方式,pipefd。
举例子,测试modem的时候:
-
int modem_read_imsi(char** argv, int argc, char* send_buff)
-
{
-
int ret = 1;
-
const char* binary = MODEM_ADAPTER;
-
-
TCMD_LOGI(argv[1], argv[2], "Test to start...\n");
-
-
if ( argc != MODEM_READ_IMSI_ARGC)
-
ret = COMMAND_ARGC_ERROR;
-
else {
-
int pipefd[2];
-
pipe(pipefd);
-
-
const char** args = (const char**)malloc(sizeof(char*) * 4);
-
args[0] = binary;
-
args[1] = IMSI;
-
char* temp = (char*)malloc(10);
-
sprintf(temp, "%d", pipefd[1]);
-
args[2] = temp;
-
args[3] = NULL;
-
-
ret = exec_binary(binary, args, pipefd[0], pipefd[1], send_buff);
-
}
-
return ret;
-
}
-
int modem_main(char** argv, int argc, char* send_buff)
-
{
-
int ret = 0;
-
char* func_name = (char *)malloc(FUNC_SIZE);
-
-
stpcpy(func_name, argv[2]);
-
-
if(!strcmp(func_name, "--imei"))
-
ret = modem_read_imei(argv, argc, send_buff);
-
else if(!strcmp(func_name, "--ue_version"))
-
ret = modem_read_uversion(argv, argc, send_buff);
-
else if(!strcmp(func_name, "--imsi"))
-
ret = modem_read_imsi(argv, argc, send_buff);
-
else if(!strcmp(func_name, "--echo"))
-
ret = modem_get_status(argv, argc, send_buff);
-
else
-
ret = COMMAND_UNDEFINE_FUNC;
-
-
return ret;
-
}
-
int exec_binary(const char* binary, const char** cmd, int fb_p, int fb_c, char* send_buff)
-
{
-
pid_t pid = fork();
-
-
if (pid == 0) {
-
close(fb_p);
-
execv(binary, (char* const*)cmd);
-
_exit(-1);
-
}
-
close(fb_c);
-
-
FILE* from_child = fdopen(fb_p, "r");
-
int size = fread(send_buff, 1, MAXBUFF, from_child);
-
if ( size <= 0)
-
return COMMAND_EXEC_FAILE;
-
-
int status;
-
waitpid(pid, &status, 0);
-
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
-
return COMMAND_EXEC_FAILE;
-
-
return COMMAND_EXEC_SUCCESSFUL;
-
}
这样设计的好处就是如果测试相关模块出现问题,不用修改测试工具,直接更新模块的binary即可。
这就是我设计的工厂测试工具,设计与开发大概不到2星期,相关模块的集成在一个月做完,但是由于公司项目黄了,没有用到,但是我还是从中学习到了好多知识,感谢指导我思路的老宋,大牛!
阅读(3522) | 评论(2) | 转发(0) |