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 config TESTING_MONKEY_STACKSIZE
int "Stack size" int "Stack size"
default 16384 default 4096
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
config TESTING_MONKEY_REC_DIR_PATH config TESTING_MONKEY_REC_DIR_PATH
string "Recorder directory path" string "Recorder directory path"
default "/data/monkey" 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 endif

View File

@ -37,12 +37,17 @@
* Pre-processor Definitions * 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) \ #define MONKEY_DEV_CREATE_MATCH(monkey, type_mask, type) \
do { \ do { \
if (((type_mask) & MONKEY_DEV_TYPE_##type) == MONKEY_DEV_TYPE_##type) \ if (((type_mask) & MONKEY_DEV_TYPE_##type) == MONKEY_DEV_TYPE_##type) \
{ \ { \
FAR struct monkey_dev_s *dev; \ 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); \ MONKEY_DEV_TYPE_##type); \
if (!dev) \ if (!dev) \
{ \ { \
@ -126,11 +131,10 @@ void monkey_config_default_init(FAR struct monkey_config_s *config)
{ {
MONKEY_ASSERT_NULL(config); MONKEY_ASSERT_NULL(config);
memset(config, 0, sizeof(struct monkey_config_s)); memset(config, 0, sizeof(struct monkey_config_s));
config->screen.type = MONKEY_SCREEN_TYPE_RECT; config->screen.hor_res = 480;
config->screen.hor_res = CONFIG_TESTING_MONKEY_SCREEN_HOR_RES; config->screen.ver_res = 480;
config->screen.ver_res = CONFIG_TESTING_MONKEY_SCREEN_VER_RES; config->period.min = 100;
config->period.min = CONFIG_TESTING_MONKEY_PERIOD_MIN_DEFAULT; config->period.max = 500;
config->period.max = CONFIG_TESTING_MONKEY_PERIOD_MAX_DEFAULT;
} }
/**************************************************************************** /****************************************************************************

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 * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_TESTING_MONKEY_LOG_ENABLE
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
****************************************************************************/ ****************************************************************************/
static enum monkey_log_level_type_e g_log_level = static enum monkey_log_level_type_e g_log_level = MONKEY_LOG_LEVEL_NOTICE;
CONFIG_TESTING_MONKEY_LOG_LEVEL_DEFAULT;
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
@ -56,7 +53,7 @@ void monkey_log_printf(enum monkey_log_level_type_e level,
struct va_format vaf; struct va_format vaf;
va_list ap; 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 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) 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); MONKEY_LOG_WARN("error level: %d", level);
return; return;
@ -96,5 +93,3 @@ enum monkey_log_level_type_e monkey_log_get_level(void)
{ {
return g_log_level; return g_log_level;
} }
#endif /* CONFIG_TESTING_MONKEY_LOG_ENABLE */

View File

@ -31,33 +31,26 @@
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_TESTING_MONKEY_LOG_ENABLE #define MONKEY_LOG_INFO(format, ...) \
# define MONKEY_LOG_INFO(format, ...) \ monkey_log_printf(MONKEY_LOG_LEVEL_INFO, \
monkey_log_printf(MONKEY_LOG_LEVEL_INFO, \ __func__, \
__func__, \ format, \
format, \ ##__VA_ARGS__)
##__VA_ARGS__) #define MONKEY_LOG_NOTICE(format, ...) \
# define MONKEY_LOG_NOTICE(format, ...) \ monkey_log_printf(MONKEY_LOG_LEVEL_NOTICE, \
monkey_log_printf(MONKEY_LOG_LEVEL_NOTICE, \ __func__, \
__func__, \ format, \
format, \ ##__VA_ARGS__)
##__VA_ARGS__) #define MONKEY_LOG_WARN(format, ...) \
# define MONKEY_LOG_WARN(format, ...) \ monkey_log_printf(MONKEY_LOG_LEVEL_WARN, \
monkey_log_printf(MONKEY_LOG_LEVEL_WARN, \ __func__, \
__func__, \ format, \
format, \ ##__VA_ARGS__)
##__VA_ARGS__) #define MONKEY_LOG_ERROR(format, ...) \
# define MONKEY_LOG_ERROR(format, ...) \ monkey_log_printf(MONKEY_LOG_LEVEL_ERROR, \
monkey_log_printf(MONKEY_LOG_LEVEL_ERROR, \ __func__, \
__func__, \ format, \
format, \ ##__VA_ARGS__)
##__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 */
#ifdef __cplusplus #ifdef __cplusplus
#define EXTERN extern "C" #define EXTERN extern "C"
@ -67,8 +60,6 @@ extern "C"
#define EXTERN extern #define EXTERN extern
#endif #endif
#ifdef CONFIG_TESTING_MONKEY_LOG_ENABLE
/**************************************************************************** /****************************************************************************
* Public Types * Public Types
****************************************************************************/ ****************************************************************************/
@ -79,7 +70,7 @@ enum monkey_log_level_type_e
MONKEY_LOG_LEVEL_NOTICE, MONKEY_LOG_LEVEL_NOTICE,
MONKEY_LOG_LEVEL_WARN, MONKEY_LOG_LEVEL_WARN,
MONKEY_LOG_LEVEL_ERROR, 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); enum monkey_log_level_type_e monkey_log_get_level(void);
#endif /* CONFIG_TESTING_MONKEY_LOG_ENABLE */
#undef EXTERN #undef EXTERN
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -23,7 +23,10 @@
****************************************************************************/ ****************************************************************************/
#include <nuttx/config.h> #include <nuttx/config.h>
#include <nuttx/video/fb.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <inttypes.h> #include <inttypes.h>
#include <signal.h> #include <signal.h>
#include <stdint.h> #include <stdint.h>
@ -31,7 +34,10 @@
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <sys/ioctl.h>
#include "monkey.h" #include "monkey.h"
#include "monkey_utils.h"
#include "monkey_log.h"
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
@ -39,17 +45,78 @@
#define MONKEY_PREFIX "monkey" #define MONKEY_PREFIX "monkey"
#define CONSTRAIN(x, low, high) \
((x) < (low) ? (low) : ((x) > (high) ? (high) : (x)))
#define OPTARG_TO_VALUE(value, type, base) \ #define OPTARG_TO_VALUE(value, type, base) \
do \ do \
{ \ { \
FAR char *ptr; \ FAR char *ptr; \
(value) = (type)strtoul(optarg, &ptr, (base)); \ (value) = (type)strtoul(optarg, &ptr, (base)); \
if (*ptr != '\0') \ if (*ptr != '\0') \
{ \ { \
printf(MONKEY_PREFIX "Parameter error: -%c %s\n", ch, optarg); \ MONKEY_LOG_ERROR("Parameter error: -%c %s", ch, optarg); \
show_usage(argv[0], EXIT_FAILURE); \ show_usage(argv[0], EXIT_FAILURE); \
} \ } \
} while (0) } 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 * Private Type Declarations
@ -63,6 +130,9 @@ struct monkey_param_s
int ver_res; int ver_res;
int period_min; int period_min;
int period_max; 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 enum monkey_wait_res_e
@ -84,9 +154,22 @@ enum monkey_wait_res_e
static void show_usage(FAR const char *progname, int exitcode) static void show_usage(FAR const char *progname, int exitcode)
{ {
printf("\nUsage: %s" 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); progname);
printf("\nWhere:\n"); printf("\nWhere:\n");
printf(" -t <hex-value> Device type mask: uinput = 0x%02X;" printf(" -t <hex-value> Device type mask: uinput = 0x%02X;"
" touch = 0x%02X; button = 0x%02X.\n", " touch = 0x%02X; button = 0x%02X.\n",
MONKEY_UINPUT_TYPE_MASK, 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"); "<decimal-value min>-<decimal-value max>\n");
printf(" -s <string> Screen resolution: " printf(" -s <string> Screen resolution: "
"<decimal-value hor_res>x<decimal-value ver_res>\n"); "<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); 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 * Name: monkey_init
****************************************************************************/ ****************************************************************************/
@ -110,6 +249,7 @@ static FAR struct monkey_s *monkey_init(
{ {
FAR struct monkey_s *monkey; FAR struct monkey_s *monkey;
struct monkey_config_s config; struct monkey_config_s config;
int i;
if (!param->dev_type_mask) if (!param->dev_type_mask)
{ {
@ -124,24 +264,34 @@ static FAR struct monkey_s *monkey_init(
} }
monkey_config_default_init(&config); 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.hor_res = param->hor_res;
config.screen.ver_res = param->ver_res; config.screen.ver_res = param->ver_res;
config.period.min = param->period_min; config.period.min = param->period_min;
config.period.max = param->period_max; 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_set_config(monkey, &config);
monkey_log_set_level(param->log_level);
printf(MONKEY_PREFIX ": Screen: %dx%d %s\n", MONKEY_LOG_NOTICE("Screen: %dx%d",
config.screen.hor_res, config.screen.hor_res,
config.screen.ver_res, config.screen.ver_res);
(config.screen.type == MONKEY_SCREEN_TYPE_ROUND) MONKEY_LOG_NOTICE("Period: %" PRIu32 " ~ %" PRIu32 "ms",
? "ROUND" : "RECT"); 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", for (i = 0; i < MONKEY_EVENT_LAST; i++)
config.period.min, {
config.period.max); 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)) if (MONKEY_IS_UINPUT_TYPE(param->dev_type_mask))
{ {
@ -181,6 +331,42 @@ failed:
return NULL; 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 * Name: parse_commandline
****************************************************************************/ ****************************************************************************/
@ -189,22 +375,39 @@ static void parse_commandline(int argc, FAR char **argv,
FAR struct monkey_param_s *param) FAR struct monkey_param_s *param)
{ {
int ch; int ch;
int hor_res = -1; int longindex = 0;
int ver_res = -1; FAR const char *optstring = "t:f:p:s:b:l:";
int period_min = -1; const struct option longopts[] =
int period_max = -1; {
int converted; {"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)); memset(param, 0, sizeof(struct monkey_param_s));
param->hor_res = CONFIG_TESTING_MONKEY_SCREEN_HOR_RES; monkey_get_screen_resolution(&param->hor_res, &param->ver_res);
param->ver_res = CONFIG_TESTING_MONKEY_SCREEN_VER_RES; param->period_min = MONKEY_PERIOD_MIN_DEFAULT;
param->period_min = CONFIG_TESTING_MONKEY_PERIOD_MIN_DEFAULT; param->period_max = MONKEY_PERIOD_MAX_DEFAULT;
param->period_max = CONFIG_TESTING_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) switch (ch)
{ {
case 0:
parse_long_commandline(argc, argv, ch,
longopts, longindex, param);
break;
case 't': case 't':
OPTARG_TO_VALUE(param->dev_type_mask, int, 16); OPTARG_TO_VALUE(param->dev_type_mask, int, 16);
break; break;
@ -214,36 +417,26 @@ static void parse_commandline(int argc, FAR char **argv,
break; break;
case 'p': case 'p':
converted = sscanf(optarg, "%d-%d", &period_min, &period_max); OPTARG_TO_RANGE(param->period_min, param->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);
}
break; break;
case 's': case 's':
converted = sscanf(optarg, "%dx%d", &hor_res, &ver_res); OPTARG_TO_RANGE(param->hor_res, param->ver_res, "x");
if (converted == 2 && hor_res > 0 && ver_res > 0) break;
{
param->hor_res = hor_res; case 'b':
param->ver_res = ver_res; OPTARG_TO_VALUE(param->btn_bit, uint8_t, 10);
} param->btn_bit = CONSTRAIN(param->btn_bit, 0, 31);
else break;
{
printf(MONKEY_PREFIX ": Error screen resolution: %s\n", case 'l':
optarg); OPTARG_TO_VALUE(param->log_level, uint8_t, 10);
show_usage(argv[0], EXIT_FAILURE); param->log_level = CONSTRAIN(param->log_level, 0,
} MONKEY_LOG_LEVEL_LAST - 1);
break; break;
case '?': case '?':
printf(MONKEY_PREFIX ": Unknown option: %c\n", optopt); MONKEY_LOG_WARN("Unknown option: %c", optopt);
show_usage(argv[0], EXIT_FAILURE); show_usage(argv[0], EXIT_FAILURE);
break; break;
} }
@ -302,7 +495,7 @@ static enum monkey_wait_res_e monkey_wait(uint32_t ms)
} }
else else
{ {
printf(MONKEY_PREFIX ": Unknow error: %d\n", errcode); MONKEY_LOG_ERROR("Unknow error: %d", errcode);
} }
} }
else if (ret == SIGTSTP) 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: * Description:
* *
@ -363,13 +556,13 @@ int main(int argc, FAR char *argv[])
} }
else if (res == MONKEY_WAIT_RES_PAUSE) else if (res == MONKEY_WAIT_RES_PAUSE)
{ {
printf(MONKEY_PREFIX ": pause\n"); MONKEY_LOG_NOTICE("pause");
if (monkey_pause() < 0) if (monkey_pause() < 0)
{ {
break; break;
} }
printf(MONKEY_PREFIX ": continue...\n"); MONKEY_LOG_NOTICE("continue...");
} }
else else
{ {

View File

@ -26,11 +26,11 @@
#include <inttypes.h> #include <inttypes.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include "monkey.h" #include "monkey.h"
#include "monkey_assert.h" #include "monkey_assert.h"
#include "monkey_log.h"
#include "monkey_dev.h" #include "monkey_dev.h"
#include "monkey_event.h"
#include "monkey_log.h"
#include "monkey_recorder.h" #include "monkey_recorder.h"
#include "monkey_utils.h" #include "monkey_utils.h"
@ -38,15 +38,6 @@
* Private Functions * 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 * 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) static bool monkey_update_uinput_ramdom(FAR struct monkey_s *monkey)
{ {
int i; int i;
bool retval = false;
for (i = 0; i < monkey->dev_num; i++) for (i = 0; i < monkey->dev_num; i++)
{ {
struct monkey_dev_state_s state;
FAR struct monkey_dev_s *dev = monkey->devs[i]; 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; break;
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);
} }
} }
return true; return retval;
} }
/**************************************************************************** /****************************************************************************

View File

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

View File

@ -153,6 +153,45 @@ bool monkey_dir_check(FAR const char *dir_path)
return retval; 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 * 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; 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); 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 * 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); 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 #undef EXTERN
#ifdef __cplusplus #ifdef __cplusplus
} }