1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-14 06:42:58 +08:00

feat(tests): add freetype font stress tests (#5828)

This commit is contained in:
Benign X 2024-03-14 15:58:13 +08:00 committed by GitHub
parent d7f7447148
commit 4d8dd2f4e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 626 additions and 1 deletions

View File

@ -289,9 +289,19 @@ endif()
# disable test targets for build only tests
if (ENABLE_TESTS)
file( GLOB_RECURSE TEST_CASE_FILES src/test_cases/*.c )
file(GLOB_RECURSE TEST_CASE_FILES src/test_cases/*.c)
file(GLOB_RECURSE TEST_LIBS_FILES src/test_libs/*.c)
else()
set(TEST_CASE_FILES)
set(TEST_LIBS_FILES)
endif()
# build a test libs target
if (TEST_LIBS_FILES)
add_library(test_libs STATIC ${TEST_LIBS_FILES})
target_include_directories(test_libs PUBLIC ${TEST_INCLUDE_DIRS} "src/test_libs")
target_compile_options(test_libs PUBLIC ${LVGL_TESTFILE_COMPILE_OPTIONS})
list(APPEND TEST_LIBS test_libs)
endif()
foreach( test_case_fname ${TEST_CASE_FILES} )

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

View File

@ -0,0 +1,209 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
#if LV_USE_FREETYPE
#include "rnd_unicodes/lv_rnd_unicodes.h"
#if __WORDSIZE == 64
#define TEST_FREETYPE_ASSERT_EQUAL_SCREENSHOT(INDEX) \
lv_snprintf(buf, sizeof(buf), "libs/font_stress/snapshot_%0d.lp64.png", (INDEX));\
TEST_ASSERT_EQUAL_SCREENSHOT(buf)
#elif __WORDSIZE == 32
#define TEST_FREETYPE_ASSERT_EQUAL_SCREENSHOT(INDEX) \
lv_snprintf(buf, sizeof(buf), "libs/font_stress/snapshot_%0d.lp32.png", (INDEX));\
TEST_ASSERT_EQUAL_SCREENSHOT(buf)
#endif
/**********************
* TYPEDEFS
**********************/
typedef struct {
const char ** font_name_arr;
int font_cnt;
int label_cnt;
int loop_cnt;
} lvx_font_stress_config_t;
typedef struct {
lv_obj_t * par;
lv_obj_t ** label_arr;
lvx_font_stress_config_t config;
} stress_test_ctx_t;
/**********************
* STATIC PROTOTYPES
**********************/
static void update_cb(void);
/**********************
* STATIC VARIABLES
**********************/
static stress_test_ctx_t g_ctx = { 0 };
static const char * font_name_arr[] = {
"./src/test_files/fonts/noto/NotoSansSC-Regular.ttf",
"../src/libs/freetype/arial.ttf",
"../demos/multilang/assets/fonts/Montserrat-Bold.ttf",
"UNKNOWN_FONT_NAME"
};
static const uint16_t font_style[] = {
LV_FREETYPE_FONT_STYLE_NORMAL,
LV_FREETYPE_FONT_STYLE_ITALIC,
LV_FREETYPE_FONT_STYLE_BOLD,
};
/**********************
* MACROS
**********************/
#define RND_START_SEED 0x114514
#define CAPTURE_SKIP_FRAMES 17
#define MAX_FONT_SIZE 128
#define MAX_LABEL_CNT 32
#define MAX_LOOP_CNT 200
#define MAX_LABEL_CONTENT_LEN 16
/**********************
* GLOBAL FUNCTIONS
**********************/
/**********************
* STATIC FUNCTIONS
**********************/
static lv_obj_t * label_create(const char * font_name, lv_obj_t * par, int size, int x, int y)
{
uint32_t index = lv_rand(0, sizeof(font_style) / sizeof(uint16_t) - 1);
uint32_t r = lv_rand(0, 0xFF);
uint32_t g = lv_rand(0, 0xFF);
uint32_t b = lv_rand(0, 0xFF);
lv_opa_t opa = lv_rand(0, LV_OPA_COVER);
lv_color_t color = lv_color_make(r, g, b);
lv_font_t * font = lv_freetype_font_create(font_name, LV_FREETYPE_FONT_RENDER_MODE_BITMAP, size, font_style[index]);
if(!font) {
return NULL;
}
lv_obj_t * label = lv_label_create(par);
lv_obj_set_style_text_font(label, font, 0);
lv_obj_set_style_text_opa(label, opa, 0);
lv_obj_set_style_text_color(label, color, 0);
lv_obj_set_pos(label, x, y);
lv_obj_set_style_outline_color(label, color, 0);
lv_obj_set_style_outline_width(label, 1, 0);
uint8_t str[128];
lv_random_utf8_chars(str, sizeof(str), LV_RND_UNICODE_ALPHANUM_AND_CJK_TABLE, LV_RND_UNICODE_ALPHANUM_AND_CJK_TABLE_LEN,
MAX_LABEL_CONTENT_LEN);
lv_label_set_text(label, (char *)str);
return label;
}
static void label_delete(lv_obj_t * label)
{
const lv_font_t * font = lv_obj_get_style_text_font(label, 0);
LV_ASSERT_NULL(font);
lv_freetype_font_delete((lv_font_t *)font);
lv_obj_del(label);
}
static void label_delete_all(stress_test_ctx_t * ctx)
{
for(int i = 0; i < ctx->config.label_cnt; i++) {
lv_obj_t * label = ctx->label_arr[i];
if(label) {
label_delete(label);
ctx->label_arr[i] = NULL;
}
}
}
static void update_cb(void)
{
stress_test_ctx_t * ctx = &g_ctx;
uint32_t label_index = lv_rand(0, ctx->config.label_cnt - 1);
uint32_t font_index = lv_rand(0, ctx->config.font_cnt - 1);
uint32_t font_size = lv_rand(0, MAX_FONT_SIZE);
uint32_t label_x = lv_rand(0, LV_HOR_RES) - LV_HOR_RES / 2;
uint32_t label_y = lv_rand(0, LV_VER_RES);
lv_obj_t * label = ctx->label_arr[label_index];
if(label) {
label_delete(label);
ctx->label_arr[label_index] = NULL;
}
else {
const char * pathname = ctx->config.font_name_arr[font_index];
LV_ASSERT_NULL(pathname);
label = label_create(
pathname,
ctx->par,
(int)font_size,
(int)label_x,
(int)label_y);
ctx->label_arr[label_index] = label;
}
}
void setUp(void)
{
lv_freetype_init(0, 0, 0);
g_ctx.par = lv_scr_act();
g_ctx.config.loop_cnt = MAX_LOOP_CNT;
g_ctx.config.label_cnt = MAX_LABEL_CNT;
g_ctx.config.font_name_arr = font_name_arr;
g_ctx.config.font_cnt = sizeof(font_name_arr) / sizeof(font_name_arr[0]);
size_t arr_size = sizeof(lv_obj_t *) * g_ctx.config.label_cnt;
g_ctx.label_arr = lv_malloc(arr_size);
LV_ASSERT_MALLOC(g_ctx.label_arr);
lv_memzero(g_ctx.label_arr, arr_size);
lv_rand_set_seed(RND_START_SEED);
}
void tearDown(void)
{
label_delete_all(&g_ctx);
lv_freetype_uninit();
lv_free(g_ctx.label_arr);
}
void test_font_stress(void)
{
for(uint32_t i = 0; g_ctx.config.loop_cnt > 0; g_ctx.config.loop_cnt--) {
update_cb();
lv_refr_now(NULL);
if(g_ctx.config.loop_cnt % CAPTURE_SKIP_FRAMES == 0) {
char buf[64];
TEST_FREETYPE_ASSERT_EQUAL_SCREENSHOT(i);
i++;
}
}
}
#else
void setUp(void)
{
}
void tearDown(void)
{
}
void test_font_stress(void)
{
}
#endif
#endif

View File

@ -0,0 +1,65 @@
/**
* @file lv_rnd_unicodes.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_rnd_unicodes.h"
#include "rnd_unicodes/src/library.h"
#define UNICODE_MAX_VALUE 0x10FFFF
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
const uint32_t LV_RND_UNICODE_ALPHANUM_AND_CJK_TABLE[] = {
0x4e00, 0x9fa5, // CJK Unified Ideographs
'A', 'Z',
'a', 'z',
'0', '9',
};
const uint32_t LV_RND_UNICODE_ALPHANUM_AND_CJK_TABLE_LEN = sizeof(LV_RND_UNICODE_ALPHANUM_AND_CJK_TABLE) / sizeof(
unicode_t) / 2;
/**********************
* GLOBAL VARIABLES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
uint32_t RANDOM_CALL_PROCESS(void)
{
return lv_rand(0, UNICODE_MAX_VALUE);
}
int lv_random_utf8_chars(uint8_t * buf, int buf_len, const uint32_t * ranges, uint32_t range_num, int char_num)
{
return random_utf8_chars(buf, buf_len, ranges, range_num, char_num);
}
/**********************
* STATIC FUNCTIONS
**********************/

View File

@ -0,0 +1,56 @@
/**
* @file lv_rnd_unicodes.h
*
*/
#ifndef LV_RND_UNICODES_H
#define LV_RND_UNICODES_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lvgl.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
extern const uint32_t LV_RND_UNICODE_ALPHANUM_AND_CJK_TABLE[];
extern const uint32_t LV_RND_UNICODE_ALPHANUM_AND_CJK_TABLE_LEN;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Generate random UTF-8 characters in the given ranges.
* @param buf buffer to store the generated characters
* @param buf_len length of the buffer
* @param ranges array of ranges to choose from
* @param range_num number of ranges
* @param char_num number of characters to generate
* @return number of generated characters in bytes
*/
int lv_random_utf8_chars(uint8_t * buf, int buf_len, const uint32_t * ranges, uint32_t range_num, int char_num);
/*************************
* GLOBAL VARIABLES
*************************/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_RND_UNICODES_H*/

View File

@ -0,0 +1,5 @@
cmake-build-*
build/*
.idea
*.o
.DS_Store

View File

@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.10)
project(rnd_unicodes C)
set(CMAKE_C_STANDARD 11)
add_library(rnd_unicodes SHARED src/library.c)
add_executable(rnd_unicodes_test examples/main.c)
target_link_libraries(rnd_unicodes_test rnd_unicodes)

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Benign X
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,41 @@
# rnd_unicodes
## Description
This is a simple c lib that generates a random unicode string of a given length.
## Usage
```c
#include "library.h"
#include "stdio.h"
#include "stdlib.h"
#include "time.h"
#define BUF_LEN 1024
utf8_t chars[BUF_LEN];
// override the random function to use the system's random number generator
uint32_t RANDOM_CALL_PROCESS(void) {
return rand();
}
int main() {
srand(time(NULL));
int len = random_utf8_chars(chars, BUF_LEN, ALPHANUM_AND_CJK_TABLE, ALPHANUM_AND_CJK_TABLE_LEN, 256);
printf("LEN: %d\n%s\n", len, chars);
return 0;
}
```
```bash
LEN: 398
9Ky鰒9奷鱈39澂9R鴥8覗E祫f912QR梑dX啀凐覎liGPC俟j3S6V4ZBU8藉W舖旫iR8EFcHV8b尜橃o8Wsle121nb駆侓6璸9hQQ6Cy桪oc8姌f7X賣5孛0幬5Sb2埉w砏3XRSh钳D869b盓儊a95B菩62濆Z机郹9145UHaLT擎馇貤m臨v夛砃xPD7CWQq堾j稄3YmFw7Z欠P8PCcu7鶚68韾7KGgTN2P793L雙hy壒TGb螿虊C6m弩呚YBt0骇fAtn恔雸餙営n共1MeH嘿刑步焒簡RejV援21q77rT蛸4N橷4ZFa恲m詘焣悷b61瘥Z绢v
```
## License
MIT

View File

@ -0,0 +1,162 @@
/*
* MIT License
*
* Copyright (c) 2023 Benign X
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
#include "library.h"
__attribute__((weak)) uint32_t RANDOM_CALL_PROCESS(void)
{
/*Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs"*/
static uint32_t x = 0x114514;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
return x;
}
const uint32_t ALPHANUM_AND_CJK_TABLE[] = {
0x4e00, 0x9fa5, // CJK Unified Ideographs
'A', 'Z',
'a', 'z',
'0', '9',
};
const uint32_t ALPHANUM_AND_CJK_TABLE_LEN = sizeof(ALPHANUM_AND_CJK_TABLE) / sizeof(unicode_t) / 2;
const uint32_t ONLY_CJK_TABLE[] = {
0x4e00, 0x9fa5, // CJK Unified Ideographs
};
const uint32_t ONLY_CJK_TABLE_LEN = sizeof(ALPHANUM_AND_CJK_TABLE) / sizeof(unicode_t) / 2;
const uint32_t ALPHANUM_TABLE[] = {
'A', 'Z',
'a', 'z',
'0', '9',
};
const uint32_t ALPHANUM_TABLE_LEN = sizeof(ALPHANUM_TABLE) / sizeof(unicode_t) / 2;
static int unicode_to_utf8_bytes_len(unicode_t unicode)
{
if(unicode < 0x80) {
return 1;
}
else if(unicode < 0x800) {
return 2;
}
else if(unicode < 0x10000) {
return 3;
}
else if(unicode < 0x200000) {
return 4;
}
else if(unicode < 0x4000000) {
return 5;
}
else {
return 6;
}
}
static int unicode_to_uft8(utf8_t * buf, uint32_t buf_len, unicode_t unicode)
{
uint32_t unicode_len = unicode_to_utf8_bytes_len(unicode);
if(buf_len < unicode_len) {
return -1;
}
int buf_index = 0;
switch(unicode_len) {
case 1:
buf[buf_index++] = (uint8_t) unicode;
break;
case 2:
buf[buf_index++] = (uint8_t)(0xc0 | (unicode >> 6));
buf[buf_index++] = (uint8_t)(0x80 | (unicode & 0x3f));
break;
case 3:
buf[buf_index++] = (uint8_t)(0xe0 | (unicode >> 12));
buf[buf_index++] = (uint8_t)(0x80 | ((unicode >> 6) & 0x3f));
buf[buf_index++] = (uint8_t)(0x80 | (unicode & 0x3f));
break;
case 4:
buf[buf_index++] = (uint8_t)(0xf0 | (unicode >> 18));
buf[buf_index++] = (uint8_t)(0x80 | ((unicode >> 12) & 0x3f));
buf[buf_index++] = (uint8_t)(0x80 | ((unicode >> 6) & 0x3f));
buf[buf_index++] = (uint8_t)(0x80 | (unicode & 0x3f));
break;
case 5:
buf[buf_index++] = (uint8_t)(0xf8 | (unicode >> 24));
buf[buf_index++] = (uint8_t)(0x80 | ((unicode >> 18) & 0x3f));
buf[buf_index++] = (uint8_t)(0x80 | ((unicode >> 12) & 0x3f));
buf[buf_index++] = (uint8_t)(0x80 | ((unicode >> 6) & 0x3f));
buf[buf_index++] = (uint8_t)(0x80 | (unicode & 0x3f));
break;
case 6:
buf[buf_index++] = (uint8_t)(0xfc | (unicode >> 30));
buf[buf_index++] = (uint8_t)(0x80 | ((unicode >> 24) & 0x3f));
buf[buf_index++] = (uint8_t)(0x80 | ((unicode >> 18) & 0x3f));
buf[buf_index++] = (uint8_t)(0x80 | ((unicode >> 12) & 0x3f));
buf[buf_index++] = (uint8_t)(0x80 | ((unicode >> 6) & 0x3f));
buf[buf_index++] = (uint8_t)(0x80 | (unicode & 0x3f));
break;
default:
return -1;
}
return buf_index;
}
static int random_one_utf8_char(utf8_t * buf, int buf_len, unicode_t char_range_min, unicode_t char_range_max)
{
if(buf_len < 1) {
return -1;
}
uint32_t r = RANDOM_CALL_PROCESS() % (char_range_max - char_range_min + 1) + char_range_min;
return unicode_to_uft8(buf, buf_len, r);
}
int random_utf8_chars(utf8_t * buf, int buf_len, const unicode_t * ranges, uint32_t range_num, int char_num)
{
if(buf_len < char_num) {
return -1;
}
int buf_index = 0;
for(int i = 0; i < char_num && buf_index < buf_len; i++) {
int range_index = RANDOM_CALL_PROCESS() % range_num;
int ret = random_one_utf8_char(buf + buf_index,
buf_len - buf_index,
ranges[2 * range_index],
ranges[2 * range_index + 1]);
if(ret < 0) {
return -1;
}
buf_index += ret;
}
buf[buf_index] = '\0';
return buf_index;
}

View File

@ -0,0 +1,47 @@
/*
* MIT License
*
* Copyright (c) 2023 Benign X
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
#ifndef RND_UNICODES_LIBRARY_H
#define RND_UNICODES_LIBRARY_H
#include <stdint.h>
typedef uint32_t unicode_t;
typedef uint8_t utf8_t;
extern const uint32_t ALPHANUM_AND_CJK_TABLE[];
extern const uint32_t ALPHANUM_AND_CJK_TABLE_LEN;
extern const uint32_t ONLY_CJK_TABLE[];
extern const uint32_t ONLY_CJK_TABLE_LEN;
extern const uint32_t ALPHANUM_TABLE[];
extern const uint32_t ALPHANUM_TABLE_LEN;
uint32_t RANDOM_CALL_PROCESS(void);
int random_utf8_chars(utf8_t * buf, int buf_len, const unicode_t * ranges, uint32_t range_num, int char_num);
#endif //RND_UNICODES_LIBRARY_H