testing/monkey: refact monkey test

1. Simplify kconfig configuration items.
2. Use events to control the status of virtual devices and improve testing efficiency.
3. Add adaptive screen resolution support.

Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
pengyiqiang 2023-09-11 19:18:15 +08:00 committed by Xiang Xiao
parent 0c572e1675
commit 8cc06ac5cf
11 changed files with 658 additions and 234 deletions

View File

@ -17,70 +17,10 @@ config TESTING_MONKEY_PRIORITY
config TESTING_MONKEY_STACKSIZE
int "Stack size"
default 16384
config TESTING_MONKEY_LOG_ENABLE
bool "Enable log output"
default y
config TESTING_MONKEY_LOG_LEVEL_DEFAULT
int "Log level default"
range 0 3
default 1
depends on TESTING_MONKEY_LOG_ENABLE
---help---
0 - INFO
1 - NOTICE
2 - WARN
3 - ERROR
default 4096
config TESTING_MONKEY_REC_DIR_PATH
string "Recorder directory path"
default "/data/monkey"
config TESTING_MONKEY_PERIOD_MIN_DEFAULT
int "Default test period[ms] min"
default 10
config TESTING_MONKEY_PERIOD_MAX_DEFAULT
int "Default test period[ms] max"
default 100
config TESTING_MONKEY_SCREEN_HOR_RES
int "Screen horizontal resolution"
default 480
config TESTING_MONKEY_SCREEN_VER_RES
int "Screen vertical resolution"
default 480
config TESTING_MONKEY_SCREEN_IS_ROUND
bool "Round screen"
default n
config TESTING_MONKEY_BUTTON_NUM
int "Button test number"
range 0 32
default 1
config TESTING_MONKEY_BUTTON_CLICK_TIME
int "Button click hold time[ms]"
default 100
config TESTING_MONKEY_DEV_PATH_TOUCH
string "input device path - touch"
default "/dev/input0"
config TESTING_MONKEY_DEV_PATH_BUTTON
string "input device path - button"
default "/dev/buttons"
config TESTING_MONKEY_DEV_PATH_UTOUCH
string "uinput device path - utouch"
default "/dev/utouch"
config TESTING_MONKEY_DEV_PATH_UBUTTON
string "uinput device path - ubutton"
default "/dev/ubutton"
endif

View File

@ -37,12 +37,17 @@
* Pre-processor Definitions
****************************************************************************/
#define MONKEY_DEV_PATH_TOUCH "/dev/input0"
#define MONKEY_DEV_PATH_BUTTON "/dev/buttons"
#define MONKEY_DEV_PATH_UTOUCH "/dev/utouch"
#define MONKEY_DEV_PATH_UBUTTON "/dev/ubutton"
#define MONKEY_DEV_CREATE_MATCH(monkey, type_mask, type) \
do { \
if (((type_mask) & MONKEY_DEV_TYPE_##type) == MONKEY_DEV_TYPE_##type) \
{ \
FAR struct monkey_dev_s *dev; \
dev = monkey_dev_create(CONFIG_TESTING_MONKEY_DEV_PATH_##type, \
dev = monkey_dev_create(MONKEY_DEV_PATH_##type, \
MONKEY_DEV_TYPE_##type); \
if (!dev) \
{ \
@ -126,11 +131,10 @@ void monkey_config_default_init(FAR struct monkey_config_s *config)
{
MONKEY_ASSERT_NULL(config);
memset(config, 0, sizeof(struct monkey_config_s));
config->screen.type = MONKEY_SCREEN_TYPE_RECT;
config->screen.hor_res = CONFIG_TESTING_MONKEY_SCREEN_HOR_RES;
config->screen.ver_res = CONFIG_TESTING_MONKEY_SCREEN_VER_RES;
config->period.min = CONFIG_TESTING_MONKEY_PERIOD_MIN_DEFAULT;
config->period.max = CONFIG_TESTING_MONKEY_PERIOD_MAX_DEFAULT;
config->screen.hor_res = 480;
config->screen.ver_res = 480;
config->period.min = 100;
config->period.max = 500;
}
/****************************************************************************

View File

@ -0,0 +1,193 @@
/****************************************************************************
* apps/testing/monkey/monkey_event.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <string.h>
#include <unistd.h>
#include "monkey_dev.h"
#include "monkey_event.h"
#include "monkey_log.h"
#include "monkey_utils.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: monkey_exec_darg
****************************************************************************/
static bool monkey_exec_darg(FAR struct monkey_dev_s *dev,
FAR struct monkey_dev_state_s *state,
FAR const struct monkey_event_param_s *param)
{
int t = 0;
uint32_t start;
state->data.touch.is_pressed = true;
start = monkey_tick_get();
while (t < param->duration)
{
t = monkey_tick_elaps(monkey_tick_get(), start);
state->data.touch.x = monkey_map(t, 0, param->duration,
param->x1, param->x2);
state->data.touch.y = monkey_map(t, 0, param->duration,
param->y1, param->y2);
monkey_dev_set_state(dev, state);
if (usleep(1000) < 0)
{
return false;
}
}
return true;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: monkey_event_gen
****************************************************************************/
void monkey_event_gen(FAR struct monkey_s *monkey,
FAR struct monkey_event_param_s *param)
{
int weight = 0;
int total = 0;
int i;
int rnd;
int duration_min;
int duration_max;
memset(param, 0, sizeof(struct monkey_event_param_s));
/* Calculate total weight */
for (i = 0; i < MONKEY_EVENT_LAST; i++)
{
total += monkey->config.event[i].weight;
}
rnd = monkey_random(0, total);
/* Select random events based on weight */
for (i = 0; i < MONKEY_EVENT_LAST; i++)
{
weight += monkey->config.event[i].weight;
if (rnd < weight)
{
param->event = i;
break;
}
}
duration_min = monkey->config.event[param->event].duration_min;
duration_max = monkey->config.event[param->event].duration_max;
param->duration = monkey_random(duration_min, duration_max);
param->x1 = monkey_random(0, monkey->config.screen.hor_res - 1);
param->y1 = monkey_random(0, monkey->config.screen.ver_res - 1);
param->x2 = monkey_random(0, monkey->config.screen.hor_res - 1);
param->y2 = monkey_random(0, monkey->config.screen.ver_res - 1);
MONKEY_LOG_INFO("event=%d(%s) duration=%d x1=%d y1=%d x2=%d y2=%d",
param->event,
monkey_event_type2name(param->event),
param->duration,
param->x1, param->y1,
param->x2, param->y2);
}
/****************************************************************************
* Name: monkey_event_exec
****************************************************************************/
bool monkey_event_exec(FAR struct monkey_s *monkey,
FAR struct monkey_dev_s *dev,
FAR const struct monkey_event_param_s *param)
{
bool retval = false;
struct monkey_dev_state_s state;
memset(&state, 0, sizeof(struct monkey_dev_state_s));
state.type = monkey_dev_get_type(dev);
MONKEY_LOG_INFO("dev=0x%x event=%d(%s) duration=%d"
" x1=%d y1=%d x2=%d y2=%d",
state.type,
param->event,
monkey_event_type2name(param->event),
param->duration,
param->x1, param->y1,
param->x2, param->y2);
if (state.type & MONKEY_DEV_TYPE_TOUCH)
{
state.data.touch.x = param->x1;
state.data.touch.y = param->y1;
state.data.touch.is_pressed = true;
monkey_dev_set_state(dev, &state);
if (param->event == MONKEY_EVENT_DRAG)
{
retval = monkey_exec_darg(dev, &state, param);
}
else
{
retval = usleep(param->duration * 1000) == 0;
}
if (!retval)
{
MONKEY_LOG_NOTICE("detect monkey killed");
}
state.data.touch.is_pressed = false;
monkey_dev_set_state(dev, &state);
}
else if (state.type & MONKEY_DEV_TYPE_BUTTON)
{
/* press button */
state.data.button.value = 1 << monkey->config.btn_bit;
monkey_dev_set_state(dev, &state);
retval = usleep(param->duration * 1000) == 0;
/* release button */
state.data.button.value = 0;
monkey_dev_set_state(dev, &state);
}
else
{
MONKEY_LOG_WARN("unsupport device type: %d", state.type);
}
return retval;
}

View File

@ -0,0 +1,77 @@
/****************************************************************************
* apps/testing/monkey/monkey_event.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __APPS_TESTING_MONKEY_EVENT_H
#define __APPS_TESTING_MONKEY_EVENT_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
#include "monkey_type.h"
/****************************************************************************
* Public Types
****************************************************************************/
struct monkey_event_param_s
{
enum monkey_event_e event;
int duration;
int x1;
int y1;
int x2;
int y2;
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Name: monkey_event_gen
****************************************************************************/
void monkey_event_gen(FAR struct monkey_s *monkey,
FAR struct monkey_event_param_s *param);
/****************************************************************************
* Name: monkey_event_exec
****************************************************************************/
bool monkey_event_exec(FAR struct monkey_s *monkey,
FAR struct monkey_dev_s *dev,
FAR const struct monkey_event_param_s *param);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __APPS_TESTING_MONKEY_EVENT_H */

View File

@ -31,14 +31,11 @@
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_TESTING_MONKEY_LOG_ENABLE
/****************************************************************************
* Private Data
****************************************************************************/
static enum monkey_log_level_type_e g_log_level =
CONFIG_TESTING_MONKEY_LOG_LEVEL_DEFAULT;
static enum monkey_log_level_type_e g_log_level = MONKEY_LOG_LEVEL_NOTICE;
/****************************************************************************
* Public Functions
@ -56,7 +53,7 @@ void monkey_log_printf(enum monkey_log_level_type_e level,
struct va_format vaf;
va_list ap;
static const int priority[_MONKEY_LOG_LEVEL_LAST] =
static const int priority[MONKEY_LOG_LEVEL_LAST] =
{
LOG_INFO, LOG_NOTICE, LOG_WARNING, LOG_ERR
};
@ -79,7 +76,7 @@ void monkey_log_printf(enum monkey_log_level_type_e level,
void monkey_log_set_level(enum monkey_log_level_type_e level)
{
if (level >= _MONKEY_LOG_LEVEL_LAST)
if (level >= MONKEY_LOG_LEVEL_LAST)
{
MONKEY_LOG_WARN("error level: %d", level);
return;
@ -96,5 +93,3 @@ enum monkey_log_level_type_e monkey_log_get_level(void)
{
return g_log_level;
}
#endif /* CONFIG_TESTING_MONKEY_LOG_ENABLE */

View File

@ -31,33 +31,26 @@
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_TESTING_MONKEY_LOG_ENABLE
# define MONKEY_LOG_INFO(format, ...) \
monkey_log_printf(MONKEY_LOG_LEVEL_INFO, \
__func__, \
format, \
##__VA_ARGS__)
# define MONKEY_LOG_NOTICE(format, ...) \
monkey_log_printf(MONKEY_LOG_LEVEL_NOTICE, \
__func__, \
format, \
##__VA_ARGS__)
# define MONKEY_LOG_WARN(format, ...) \
monkey_log_printf(MONKEY_LOG_LEVEL_WARN, \
__func__, \
format, \
##__VA_ARGS__)
# define MONKEY_LOG_ERROR(format, ...) \
monkey_log_printf(MONKEY_LOG_LEVEL_ERROR, \
__func__, \
format, \
##__VA_ARGS__)
#else
# define MONKEY_LOG_INFO(...)
# define MONKEY_LOG_NOTICE(...)
# define MONKEY_LOG_WARN(...)
# define MONKEY_LOG_ERROR(...)
#endif /* CONFIG_TESTING_MONKEY_LOG_ENABLE */
#define MONKEY_LOG_INFO(format, ...) \
monkey_log_printf(MONKEY_LOG_LEVEL_INFO, \
__func__, \
format, \
##__VA_ARGS__)
#define MONKEY_LOG_NOTICE(format, ...) \
monkey_log_printf(MONKEY_LOG_LEVEL_NOTICE, \
__func__, \
format, \
##__VA_ARGS__)
#define MONKEY_LOG_WARN(format, ...) \
monkey_log_printf(MONKEY_LOG_LEVEL_WARN, \
__func__, \
format, \
##__VA_ARGS__)
#define MONKEY_LOG_ERROR(format, ...) \
monkey_log_printf(MONKEY_LOG_LEVEL_ERROR, \
__func__, \
format, \
##__VA_ARGS__)
#ifdef __cplusplus
#define EXTERN extern "C"
@ -67,8 +60,6 @@ extern "C"
#define EXTERN extern
#endif
#ifdef CONFIG_TESTING_MONKEY_LOG_ENABLE
/****************************************************************************
* Public Types
****************************************************************************/
@ -79,7 +70,7 @@ enum monkey_log_level_type_e
MONKEY_LOG_LEVEL_NOTICE,
MONKEY_LOG_LEVEL_WARN,
MONKEY_LOG_LEVEL_ERROR,
_MONKEY_LOG_LEVEL_LAST
MONKEY_LOG_LEVEL_LAST
};
/****************************************************************************
@ -107,8 +98,6 @@ void monkey_log_set_level(enum monkey_log_level_type_e level);
enum monkey_log_level_type_e monkey_log_get_level(void);
#endif /* CONFIG_TESTING_MONKEY_LOG_ENABLE */
#undef EXTERN
#ifdef __cplusplus
}

View File

@ -23,7 +23,10 @@
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/video/fb.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <inttypes.h>
#include <signal.h>
#include <stdint.h>
@ -31,7 +34,10 @@
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/ioctl.h>
#include "monkey.h"
#include "monkey_utils.h"
#include "monkey_log.h"
/****************************************************************************
* Pre-processor Definitions
@ -39,17 +45,78 @@
#define MONKEY_PREFIX "monkey"
#define CONSTRAIN(x, low, high) \
((x) < (low) ? (low) : ((x) > (high) ? (high) : (x)))
#define OPTARG_TO_VALUE(value, type, base) \
do \
{ \
FAR char *ptr; \
(value) = (type)strtoul(optarg, &ptr, (base)); \
if (*ptr != '\0') \
{ \
printf(MONKEY_PREFIX "Parameter error: -%c %s\n", ch, optarg); \
show_usage(argv[0], EXIT_FAILURE); \
} \
} while (0)
{ \
FAR char *ptr; \
(value) = (type)strtoul(optarg, &ptr, (base)); \
if (*ptr != '\0') \
{ \
MONKEY_LOG_ERROR("Parameter error: -%c %s", ch, optarg); \
show_usage(argv[0], EXIT_FAILURE); \
} \
} while (0)
#define OPTARG_TO_RANGE(value_1, value_2, delimiter) \
do \
{ \
int converted; \
int v1; \
int v2; \
converted = sscanf(optarg, "%d" delimiter "%d", &v1, &v2); \
if (converted == 2 && v1 >= 0 && v2 >= 0) \
{ \
value_1 = v1; \
value_2 = v2; \
} \
else \
{ \
MONKEY_LOG_ERROR("Error range: %s", optarg); \
show_usage(argv[0], EXIT_FAILURE); \
} \
} while (0)
/* Default parameters */
#if defined(CONFIG_VIDEO_FB)
# define MONKEY_SCREEN_DEV "/dev/fb0"
# define MONKEY_SCREEN_GETVIDEOINFO FBIOGET_VIDEOINFO
#elif defined(CONFIG_LCD)
# define MONKEY_SCREEN_DEV "/dev/lcd0"
# define MONKEY_SCREEN_GETVIDEOINFO LCDDEVIO_GETVIDEOINFO
#endif
#define MONKEY_SCREEN_HOR_RES_DEFAULT 480
#define MONKEY_SCREEN_VER_RES_DEFAULT 480
#define MONKEY_PERIOD_MIN_DEFAULT 100
#define MONKEY_PERIOD_MAX_DEFAULT 500
#define MONKEY_BUTTON_BIT_DEFAULT 0
#define MONKEY_EVENT_CLICK_WEIGHT_DEFAULT 70
#define MONKEY_EVENT_LONG_PRESS_WEIGHT_DEFAULT 10
#define MONKEY_EVENT_DRAG_WEIGHT_DEFAULT 20
#define MONKEY_EVENT_CLICK_DURATION_MIN_DEFAULT 50
#define MONKEY_EVENT_CLICK_DURATION_MAX_DEFAULT 200
#define MONKEY_EVENT_LONG_PRESS_DURATION_MIN_DEFAULT 400
#define MONKEY_EVENT_LONG_PRESS_DURATION_MAX_DEFAULT 600
#define MONKEY_EVENT_DRAG_DURATION_MIN_DEFAULT 100
#define MONKEY_EVENT_DRAG_DURATION_MAX_DEFAULT 400
#define MONKEY_EVENT_PARAM_INIT(name) \
do \
{ \
param->event[MONKEY_EVENT_##name].weight = \
MONKEY_EVENT_##name##_WEIGHT_DEFAULT; \
param->event[MONKEY_EVENT_##name].duration_min = \
MONKEY_EVENT_##name##_DURATION_MIN_DEFAULT; \
param->event[MONKEY_EVENT_##name].duration_max = \
MONKEY_EVENT_##name##_DURATION_MAX_DEFAULT; \
} while (0)
/****************************************************************************
* Private Type Declarations
@ -63,6 +130,9 @@ struct monkey_param_s
int ver_res;
int period_min;
int period_max;
uint8_t btn_bit;
uint8_t log_level;
struct monkey_event_config_s event[MONKEY_EVENT_LAST];
};
enum monkey_wait_res_e
@ -84,9 +154,22 @@ enum monkey_wait_res_e
static void show_usage(FAR const char *progname, int exitcode)
{
printf("\nUsage: %s"
" -t <hex-value> -f <string> -p <string> -s <string>\n",
" -t <hex-value>"
" -f <string>"
" -p <string>"
" -s <string>"
" -b <decimal-value>"
" -l <decimal-value>\n"
" --weight-click <decimal-value>"
" --weight-longpress <decimal-value>"
" --weight-drag <decimal-value>\n"
" --duration-click <string>"
" --duration-longpress <string>"
" --duration-drag <string>\n",
progname);
printf("\nWhere:\n");
printf(" -t <hex-value> Device type mask: uinput = 0x%02X;"
" touch = 0x%02X; button = 0x%02X.\n",
MONKEY_UINPUT_TYPE_MASK,
@ -97,10 +180,66 @@ static void show_usage(FAR const char *progname, int exitcode)
"<decimal-value min>-<decimal-value max>\n");
printf(" -s <string> Screen resolution: "
"<decimal-value hor_res>x<decimal-value ver_res>\n");
printf(" -b <decimal-value> Button bit: 0 ~ 31\n");
printf(" -l <decimal-value> Log level: 0 ~ 3\n");
printf(" --weight-click <decimal-value> Click event weight.\n");
printf(" --weight-longpress <decimal-value> Long press event weight.\n");
printf(" --weight-drag <decimal-value> Drag event weight.\n");
printf(" --duration-click <string> Click duration(ms) range: "
"<decimal-value min>-<decimal-value max>.\n");
printf(" --duration-longpress <string> Long press duration(ms) range: "
"<decimal-value min>-<decimal-value max>.\n");
printf(" --duration-drag <string> Drag duration(ms) range: "
"<decimal-value min>-<decimal-value max>.\n");
exit(exitcode);
}
/****************************************************************************
* Name: monkey_get_screen_resolution
****************************************************************************/
static int monkey_get_screen_resolution(FAR int *hor_res, FAR int *ver_res)
{
#ifdef MONKEY_SCREEN_DEV
struct fb_videoinfo_s vinfo;
int fd;
int ret;
FAR const char *dev_path = MONKEY_SCREEN_DEV;
*hor_res = MONKEY_SCREEN_HOR_RES_DEFAULT;
*ver_res = MONKEY_SCREEN_VER_RES_DEFAULT;
fd = open(dev_path, 0);
if (fd < 0)
{
MONKEY_LOG_ERROR("screen dev %s open failed: %d", dev_path, errno);
return ERROR;
}
ret = ioctl(fd, MONKEY_SCREEN_GETVIDEOINFO,
(unsigned long)((uintptr_t)&vinfo));
if (ret < 0)
{
MONKEY_LOG_ERROR("get video info failed: %d", errno);
}
else
{
*hor_res = vinfo.xres;
*ver_res = vinfo.yres;
}
close(fd);
return ret;
#else
*hor_res = MONKEY_SCREEN_HOR_RES_DEFAULT;
*ver_res = MONKEY_SCREEN_VER_RES_DEFAULT;
return OK;
#endif /* MONKEY_SCREEN_DEV */
}
/****************************************************************************
* Name: monkey_init
****************************************************************************/
@ -110,6 +249,7 @@ static FAR struct monkey_s *monkey_init(
{
FAR struct monkey_s *monkey;
struct monkey_config_s config;
int i;
if (!param->dev_type_mask)
{
@ -124,24 +264,34 @@ static FAR struct monkey_s *monkey_init(
}
monkey_config_default_init(&config);
#ifdef CONFIG_TESTING_MONKEY_SCREEN_IS_ROUND
config.screen.type = MONKEY_SCREEN_TYPE_ROUND;
#endif
config.screen.hor_res = param->hor_res;
config.screen.ver_res = param->ver_res;
config.period.min = param->period_min;
config.period.max = param->period_max;
config.btn_bit = param->btn_bit;
memcpy(config.event, param->event, sizeof(config.event));
monkey_set_config(monkey, &config);
monkey_log_set_level(param->log_level);
printf(MONKEY_PREFIX ": Screen: %dx%d %s\n",
config.screen.hor_res,
config.screen.ver_res,
(config.screen.type == MONKEY_SCREEN_TYPE_ROUND)
? "ROUND" : "RECT");
MONKEY_LOG_NOTICE("Screen: %dx%d",
config.screen.hor_res,
config.screen.ver_res);
MONKEY_LOG_NOTICE("Period: %" PRIu32 " ~ %" PRIu32 "ms",
config.period.min,
config.period.max);
MONKEY_LOG_NOTICE("Button bit: %d", config.btn_bit);
MONKEY_LOG_NOTICE("Log level: %d", monkey_log_get_level());
printf(MONKEY_PREFIX ": Period: %" PRIu32 " ~ %" PRIu32 "ms\n",
config.period.min,
config.period.max);
for (i = 0; i < MONKEY_EVENT_LAST; i++)
{
MONKEY_LOG_NOTICE("Event %d(%s): weight=%d"
" duration %d ~ %dms",
i,
monkey_event_type2name(i),
config.event[i].weight,
config.event[i].duration_min,
config.event[i].duration_max);
}
if (MONKEY_IS_UINPUT_TYPE(param->dev_type_mask))
{
@ -181,6 +331,42 @@ failed:
return NULL;
}
/****************************************************************************
* Name: parse_long_commandline
****************************************************************************/
static void parse_long_commandline(int argc, FAR char **argv,
int ch,
FAR const struct option *longopts,
int longindex,
FAR struct monkey_param_s *param)
{
int event_index;
switch (longindex)
{
case 0:
case 1:
case 2:
event_index = longindex;
OPTARG_TO_VALUE(param->event[event_index].weight, uint8_t, 10);
break;
case 3:
case 4:
case 5:
event_index = longindex - 3;
OPTARG_TO_RANGE(param->event[event_index].duration_min,
param->event[event_index].duration_max,
"-");
break;
default:
MONKEY_LOG_WARN("Unknown longindex: %d", longindex);
show_usage(argv[0], EXIT_FAILURE);
break;
}
}
/****************************************************************************
* Name: parse_commandline
****************************************************************************/
@ -189,22 +375,39 @@ static void parse_commandline(int argc, FAR char **argv,
FAR struct monkey_param_s *param)
{
int ch;
int hor_res = -1;
int ver_res = -1;
int period_min = -1;
int period_max = -1;
int converted;
int longindex = 0;
FAR const char *optstring = "t:f:p:s:b:l:";
const struct option longopts[] =
{
{"weight-click", required_argument, NULL, 0 },
{"weight-longpress", required_argument, NULL, 0 },
{"weight-drag", required_argument, NULL, 0 },
{"duration-click", required_argument, NULL, 0 },
{"duration-longpress", required_argument, NULL, 0 },
{"duration-drag", required_argument, NULL, 0 },
{0, 0, NULL, 0 }
};
memset(param, 0, sizeof(struct monkey_param_s));
param->hor_res = CONFIG_TESTING_MONKEY_SCREEN_HOR_RES;
param->ver_res = CONFIG_TESTING_MONKEY_SCREEN_VER_RES;
param->period_min = CONFIG_TESTING_MONKEY_PERIOD_MIN_DEFAULT;
param->period_max = CONFIG_TESTING_MONKEY_PERIOD_MAX_DEFAULT;
monkey_get_screen_resolution(&param->hor_res, &param->ver_res);
param->period_min = MONKEY_PERIOD_MIN_DEFAULT;
param->period_max = MONKEY_PERIOD_MAX_DEFAULT;
param->btn_bit = MONKEY_BUTTON_BIT_DEFAULT;
param->log_level = MONKEY_LOG_LEVEL_NOTICE;
MONKEY_EVENT_PARAM_INIT(CLICK);
MONKEY_EVENT_PARAM_INIT(LONG_PRESS);
MONKEY_EVENT_PARAM_INIT(DRAG);
while ((ch = getopt(argc, argv, "t:f:p:s:")) != ERROR)
while ((ch = getopt_long(argc, argv,
optstring, longopts, &longindex)) != ERROR)
{
switch (ch)
{
case 0:
parse_long_commandline(argc, argv, ch,
longopts, longindex, param);
break;
case 't':
OPTARG_TO_VALUE(param->dev_type_mask, int, 16);
break;
@ -214,36 +417,26 @@ static void parse_commandline(int argc, FAR char **argv,
break;
case 'p':
converted = sscanf(optarg, "%d-%d", &period_min, &period_max);
if (converted == 2 && period_min >= 0 && period_max >= 0)
{
param->period_min = period_min;
param->period_max = period_max;
}
else
{
printf(MONKEY_PREFIX ": Error period range: %s\n", optarg);
show_usage(argv[0], EXIT_FAILURE);
}
OPTARG_TO_RANGE(param->period_min, param->period_max, "-");
break;
case 's':
converted = sscanf(optarg, "%dx%d", &hor_res, &ver_res);
if (converted == 2 && hor_res > 0 && ver_res > 0)
{
param->hor_res = hor_res;
param->ver_res = ver_res;
}
else
{
printf(MONKEY_PREFIX ": Error screen resolution: %s\n",
optarg);
show_usage(argv[0], EXIT_FAILURE);
}
OPTARG_TO_RANGE(param->hor_res, param->ver_res, "x");
break;
case 'b':
OPTARG_TO_VALUE(param->btn_bit, uint8_t, 10);
param->btn_bit = CONSTRAIN(param->btn_bit, 0, 31);
break;
case 'l':
OPTARG_TO_VALUE(param->log_level, uint8_t, 10);
param->log_level = CONSTRAIN(param->log_level, 0,
MONKEY_LOG_LEVEL_LAST - 1);
break;
case '?':
printf(MONKEY_PREFIX ": Unknown option: %c\n", optopt);
MONKEY_LOG_WARN("Unknown option: %c", optopt);
show_usage(argv[0], EXIT_FAILURE);
break;
}
@ -302,7 +495,7 @@ static enum monkey_wait_res_e monkey_wait(uint32_t ms)
}
else
{
printf(MONKEY_PREFIX ": Unknow error: %d\n", errcode);
MONKEY_LOG_ERROR("Unknow error: %d", errcode);
}
}
else if (ret == SIGTSTP)
@ -318,7 +511,7 @@ static enum monkey_wait_res_e monkey_wait(uint32_t ms)
****************************************************************************/
/****************************************************************************
* Name: main or monkey_main
* Name: monkey_main
*
* Description:
*
@ -363,13 +556,13 @@ int main(int argc, FAR char *argv[])
}
else if (res == MONKEY_WAIT_RES_PAUSE)
{
printf(MONKEY_PREFIX ": pause\n");
MONKEY_LOG_NOTICE("pause");
if (monkey_pause() < 0)
{
break;
}
printf(MONKEY_PREFIX ": continue...\n");
MONKEY_LOG_NOTICE("continue...");
}
else
{

View File

@ -26,11 +26,11 @@
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "monkey.h"
#include "monkey_assert.h"
#include "monkey_log.h"
#include "monkey_dev.h"
#include "monkey_event.h"
#include "monkey_log.h"
#include "monkey_recorder.h"
#include "monkey_utils.h"
@ -38,15 +38,6 @@
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: monkey_get_random_press
****************************************************************************/
static int monkey_get_random_press(int probability)
{
return monkey_random(0, 100) < probability ? 0 : 1;
}
/****************************************************************************
* Name: monkey_update_uinput_ramdom
****************************************************************************/
@ -54,64 +45,22 @@ static int monkey_get_random_press(int probability)
static bool monkey_update_uinput_ramdom(FAR struct monkey_s *monkey)
{
int i;
bool retval = false;
for (i = 0; i < monkey->dev_num; i++)
{
struct monkey_dev_state_s state;
FAR struct monkey_dev_s *dev = monkey->devs[i];
state.type = monkey_dev_get_type(dev);
struct monkey_event_param_s param;
monkey_event_gen(monkey, &param);
retval = monkey_event_exec(monkey, dev, &param);
if (state.type & MONKEY_DEV_TYPE_TOUCH)
if (!retval)
{
int x_max = monkey->config.screen.hor_res - 1;
int y_max = monkey->config.screen.ver_res - 1;
state.data.touch.x = monkey_random(0, x_max);
state.data.touch.y = monkey_random(0, y_max);
state.data.touch.is_pressed = monkey_get_random_press(50);
monkey_dev_set_state(dev, &state);
}
else if (state.type & MONKEY_DEV_TYPE_BUTTON)
{
const int btn_num = CONFIG_TESTING_MONKEY_BUTTON_NUM;
int usleep_ret;
int btn_bits;
if (!btn_num)
{
MONKEY_LOG_ERROR("Button test number is 0");
return false;
}
/* select a button to click */
btn_bits = monkey_random(0, btn_num - 1);
/* press button */
state.data.button.value = 1 << btn_bits;
monkey_dev_set_state(dev, &state);
usleep_ret = usleep(CONFIG_TESTING_MONKEY_BUTTON_CLICK_TIME
* 1000);
/* release button */
state.data.button.value = 0;
monkey_dev_set_state(dev, &state);
/* detect monkey killed */
if (usleep_ret < 0)
{
MONKEY_LOG_NOTICE("detect monkey killed");
return false;
}
}
else
{
MONKEY_LOG_WARN("unsupport device type: %d", state.type);
break;
}
}
return true;
return retval;
}
/****************************************************************************

View File

@ -44,12 +44,6 @@
struct monkey_dev_s;
struct monkey_recorder_s;
enum monkey_screen_type_e
{
MONKEY_SCREEN_TYPE_RECT,
MONKEY_SCREEN_TYPE_ROUND
};
enum monkey_mode_e
{
MONKEY_MODE_RANDOM,
@ -66,6 +60,14 @@ enum monkey_dev_type_e
MONKEY_DEV_TYPE_UBUTTON = MONKEY_UINPUT_TYPE_MASK | MONKEY_DEV_TYPE_BUTTON,
};
enum monkey_event_e
{
MONKEY_EVENT_CLICK,
MONKEY_EVENT_LONG_PRESS,
MONKEY_EVENT_DRAG,
MONKEY_EVENT_LAST
};
struct monkey_dev_state_s
{
enum monkey_dev_type_e type;
@ -85,11 +87,17 @@ struct monkey_dev_state_s
} data;
};
struct monkey_event_config_s
{
int weight;
int duration_min;
int duration_max;
};
struct monkey_config_s
{
struct
{
enum monkey_screen_type_e type;
int hor_res;
int ver_res;
} screen;
@ -99,6 +107,10 @@ struct monkey_config_s
uint32_t min;
uint32_t max;
} period;
uint8_t btn_bit;
struct monkey_event_config_s event[MONKEY_EVENT_LAST];
};
struct monkey_s

View File

@ -153,6 +153,45 @@ bool monkey_dir_check(FAR const char *dir_path)
return retval;
}
/****************************************************************************
* Name: monkey_map
****************************************************************************/
int monkey_map(int x, int min_in, int max_in, int min_out, int max_out)
{
if (max_in >= min_in && x >= max_in)
{
return max_out;
}
if (max_in >= min_in && x <= min_in)
{
return min_out;
}
if (max_in <= min_in && x <= max_in)
{
return max_out;
}
if (max_in <= min_in && x >= min_in)
{
return min_out;
}
/**
* The equation should be:
* ((x - min_in) * delta_out) / delta in) + min_out
* To avoid rounding error reorder the operations:
* (x - min_in) * (delta_out / delta_min) + min_out
*/
int delta_in = max_in - min_in;
int delta_out = max_out - min_out;
return ((x - min_in) * delta_out) / delta_in + min_out;
}
/****************************************************************************
* Name: monkey_dev_type2name
****************************************************************************/
@ -195,3 +234,24 @@ enum monkey_dev_type_e monkey_dev_name2type(FAR const char *name)
return MONKEY_DEV_TYPE_UNKNOW;
}
/****************************************************************************
* Name: monkey_event_type2name
****************************************************************************/
FAR const char *monkey_event_type2name(enum monkey_event_e event)
{
switch (event)
{
case MONKEY_EVENT_CLICK:
return "click";
case MONKEY_EVENT_LONG_PRESS:
return "long-press";
case MONKEY_EVENT_DRAG:
return "drag";
default:
break;
}
return "unknow";
}

View File

@ -74,6 +74,12 @@ void monkey_get_localtime_str(FAR char *str_buf, size_t buf_size);
bool monkey_dir_check(FAR const char *dir_path);
/****************************************************************************
* Name: monkey_map
****************************************************************************/
int monkey_map(int x, int min_in, int max_in, int min_out, int max_out);
/****************************************************************************
* Name: monkey_dev_type2name
****************************************************************************/
@ -86,6 +92,12 @@ FAR const char *monkey_dev_type2name(enum monkey_dev_type_e type);
enum monkey_dev_type_e monkey_dev_name2type(FAR const char *name);
/****************************************************************************
* Name: monkey_event_type2name
****************************************************************************/
FAR const char *monkey_event_type2name(enum monkey_event_e event);
#undef EXTERN
#ifdef __cplusplus
}