From 8cc06ac5cf729638dccf0fbef5beece3896c6222 Mon Sep 17 00:00:00 2001 From: pengyiqiang Date: Mon, 11 Sep 2023 19:18:15 +0800 Subject: [PATCH] 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 --- testing/monkey/Kconfig | 62 +------ testing/monkey/monkey.c | 16 +- testing/monkey/monkey_event.c | 193 +++++++++++++++++++++ testing/monkey/monkey_event.h | 77 +++++++++ testing/monkey/monkey_log.c | 11 +- testing/monkey/monkey_log.h | 53 +++--- testing/monkey/monkey_main.c | 311 +++++++++++++++++++++++++++------- testing/monkey/monkey_proc.c | 71 ++------ testing/monkey/monkey_type.h | 26 ++- testing/monkey/monkey_utils.c | 60 +++++++ testing/monkey/monkey_utils.h | 12 ++ 11 files changed, 658 insertions(+), 234 deletions(-) create mode 100644 testing/monkey/monkey_event.c create mode 100644 testing/monkey/monkey_event.h diff --git a/testing/monkey/Kconfig b/testing/monkey/Kconfig index 318b7cc4b..6add92a05 100644 --- a/testing/monkey/Kconfig +++ b/testing/monkey/Kconfig @@ -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 diff --git a/testing/monkey/monkey.c b/testing/monkey/monkey.c index e725c69ec..d01a216a6 100644 --- a/testing/monkey/monkey.c +++ b/testing/monkey/monkey.c @@ -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; } /**************************************************************************** diff --git a/testing/monkey/monkey_event.c b/testing/monkey/monkey_event.c new file mode 100644 index 000000000..c60d52a24 --- /dev/null +++ b/testing/monkey/monkey_event.c @@ -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 +#include +#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; +} diff --git a/testing/monkey/monkey_event.h b/testing/monkey/monkey_event.h new file mode 100644 index 000000000..2ee31ce59 --- /dev/null +++ b/testing/monkey/monkey_event.h @@ -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 +#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 */ diff --git a/testing/monkey/monkey_log.c b/testing/monkey/monkey_log.c index 01ae013bb..a964481d6 100644 --- a/testing/monkey/monkey_log.c +++ b/testing/monkey/monkey_log.c @@ -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 */ diff --git a/testing/monkey/monkey_log.h b/testing/monkey/monkey_log.h index dbe7cf6d5..931fb9cc2 100644 --- a/testing/monkey/monkey_log.h +++ b/testing/monkey/monkey_log.h @@ -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 } diff --git a/testing/monkey/monkey_main.c b/testing/monkey/monkey_main.c index 1004e2b5c..a40f918f4 100644 --- a/testing/monkey/monkey_main.c +++ b/testing/monkey/monkey_main.c @@ -23,7 +23,10 @@ ****************************************************************************/ #include +#include #include +#include +#include #include #include #include @@ -31,7 +34,10 @@ #include #include #include +#include #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 -f -p -s \n", + " -t " + " -f " + " -p " + " -s " + " -b " + " -l \n" + " --weight-click " + " --weight-longpress " + " --weight-drag \n" + " --duration-click " + " --duration-longpress " + " --duration-drag \n", progname); + printf("\nWhere:\n"); + printf(" -t 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) "-\n"); printf(" -s Screen resolution: " "x\n"); + printf(" -b Button bit: 0 ~ 31\n"); + printf(" -l Log level: 0 ~ 3\n"); + + printf(" --weight-click Click event weight.\n"); + printf(" --weight-longpress Long press event weight.\n"); + printf(" --weight-drag Drag event weight.\n"); + + printf(" --duration-click Click duration(ms) range: " + "-.\n"); + printf(" --duration-longpress Long press duration(ms) range: " + "-.\n"); + printf(" --duration-drag Drag duration(ms) range: " + "-.\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(¶m->hor_res, ¶m->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 { diff --git a/testing/monkey/monkey_proc.c b/testing/monkey/monkey_proc.c index d18fe5d9a..4574a6268 100644 --- a/testing/monkey/monkey_proc.c +++ b/testing/monkey/monkey_proc.c @@ -26,11 +26,11 @@ #include #include #include -#include #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, ¶m); + retval = monkey_event_exec(monkey, dev, ¶m); - 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; } /**************************************************************************** diff --git a/testing/monkey/monkey_type.h b/testing/monkey/monkey_type.h index 5708836cb..43a39f797 100644 --- a/testing/monkey/monkey_type.h +++ b/testing/monkey/monkey_type.h @@ -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 diff --git a/testing/monkey/monkey_utils.c b/testing/monkey/monkey_utils.c index d4b457def..21dae0296 100644 --- a/testing/monkey/monkey_utils.c +++ b/testing/monkey/monkey_utils.c @@ -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"; +} diff --git a/testing/monkey/monkey_utils.h b/testing/monkey/monkey_utils.h index 487665f21..342f87c90 100644 --- a/testing/monkey/monkey_utils.h +++ b/testing/monkey/monkey_utils.h @@ -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 }