[codec,test] add new unit test TestFreeRDPCodecCursor

* Generate a series of cursor images from source dumps and compare these
  to a reference image
* Generation is automatic by picking up .c/.h files from
  libfreerdp/codec/test/cursor directory.
This commit is contained in:
akallabeth
2025-02-20 11:39:18 +01:00
parent 018ce108eb
commit 40dce19b0e
2 changed files with 115 additions and 1 deletions

View File

@@ -10,6 +10,7 @@ set(TESTS
TestFreeRDPCodecZGfx.c
TestFreeRDPCodecPlanar.c
TestFreeRDPCodecCopy.c
TestFreeRDPCodecCursor.c
TestFreeRDPCodecClear.c
TestFreeRDPCodecInterleaved.c
TestFreeRDPCodecProgressive.c
@@ -24,11 +25,45 @@ if(BUILD_TESTING_INTERNAL)
list(APPEND TESTS TestFreeRDPCodecMppc.c TestFreeRDPCodecNCrush.c TestFreeRDPCodecXCrush.c)
endif()
file(GLOB CURSOR_TESTCASES_C LIST_DIRECTORIES false RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "cursor/*.c")
file(GLOB CURSOR_TESTCASES_H LIST_DIRECTORIES false RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "cursor/*.h")
# Create a combined header for all testcases
set(TESTCASE_HEADER "${CMAKE_CURRENT_BINARY_DIR}/testcases.h")
write_file(${TESTCASE_HEADER} "#pragma once\n")
foreach(header ${CURSOR_TESTCASES_H})
write_file(${TESTCASE_HEADER} "#include <${header}>" APPEND)
endforeach()
write_file(${TESTCASE_HEADER} "\nstatic const gdiPalette* testcase_palette[] = {" APPEND)
foreach(header ${CURSOR_TESTCASES_H})
get_filename_component(NAME ${header} NAME_WE)
write_file(${TESTCASE_HEADER} "&${NAME}_palette," APPEND)
endforeach()
write_file(${TESTCASE_HEADER} "};\n" APPEND)
write_file(${TESTCASE_HEADER} "static const rdpPointer* testcase_pointer[] = {" APPEND)
foreach(header ${CURSOR_TESTCASES_H})
get_filename_component(NAME ${header} NAME_WE)
write_file(${TESTCASE_HEADER} "&${NAME}_pointer," APPEND)
endforeach()
write_file(${TESTCASE_HEADER} "};\n" APPEND)
write_file(${TESTCASE_HEADER} "static const uint8_t* testcase_image_bgra32[] = {" APPEND)
foreach(header ${CURSOR_TESTCASES_H})
get_filename_component(NAME ${header} NAME_WE)
write_file(${TESTCASE_HEADER} "${NAME}_image_bgra32," APPEND)
endforeach()
write_file(${TESTCASE_HEADER} "};" APPEND)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
create_test_sourcelist(SRCS ${DRIVER} ${TESTS})
add_compile_definitions(CMAKE_CURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
add_compile_definitions(CMAKE_CURRENT_BINARY_DIR="${CMAKE_CURRENT_BINARY_DIR}")
add_executable(${MODULE_NAME} ${SRCS})
add_executable(${MODULE_NAME} ${SRCS} ${CURSOR_TESTCASES_H} ${CURSOR_TESTCASES_C} ${TESTCASE_HEADER})
target_link_libraries(${MODULE_NAME} freerdp winpr)

View File

@@ -0,0 +1,79 @@
#include <stdint.h>
#include <winpr/path.h>
#include <winpr/image.h>
#include <freerdp/codec/color.h>
#include "testcases.h"
static BOOL run_testcase(size_t x, const gdiPalette* palette, const rdpPointer* pointer,
const uint8_t* ref)
{
WINPR_ASSERT(palette);
WINPR_ASSERT(pointer);
WINPR_ASSERT(ref);
WLog_INFO("test", "running cursor test case %" PRIuz, x);
BOOL rc = FALSE;
const uint32_t format = PIXEL_FORMAT_BGRA32;
const size_t width = pointer->width;
const size_t height = pointer->height;
const size_t xorBpp = pointer->xorBpp;
const size_t bpp = FreeRDPGetBytesPerPixel(format);
const size_t stride = width * bpp;
uint8_t* bmp = calloc(stride, height);
if (!bmp)
goto fail;
const BOOL result = freerdp_image_copy_from_pointer_data(
bmp, format, 0, 0, 0, width, height, pointer->xorMaskData, pointer->lengthXorMask,
pointer->andMaskData, pointer->lengthAndMask, xorBpp, palette);
if (!result)
goto fail;
rc = TRUE;
for (size_t y = 0; y < height; y++)
{
const uint8_t* linea = &bmp[y * stride];
const uint8_t* lineb = &ref[y * stride];
for (size_t x = 0; x < stride; x++)
{
const uint8_t a = linea[x];
const uint8_t b = lineb[x];
if (a != b)
{
printf("xxx: %" PRIuz "x%" PRIuz ": color %" PRIuz " diff 0x%02" PRIx8
"<-->0x%02" PRIx8 "\n",
x / 4, y, x % 4, a, b);
rc = FALSE;
}
}
}
fail:
free(bmp);
WLog_INFO("test", "cursor test case %" PRIuz ": %s", x, rc ? "success" : "failure");
return rc;
}
int TestFreeRDPCodecCursor(WINPR_ATTR_UNUSED int argc, WINPR_ATTR_UNUSED char* argv[])
{
const size_t palette_len = ARRAYSIZE(testcase_palette);
const size_t pointer_len = ARRAYSIZE(testcase_pointer);
const size_t bmp_len = ARRAYSIZE(testcase_image_bgra32);
WINPR_ASSERT(palette_len == pointer_len);
WINPR_ASSERT(palette_len == bmp_len);
int rc = 0;
for (size_t x = 0; x < palette_len; x++)
{
const rdpPalette* palette = testcase_palette[x];
const rdpPointer* pointer = testcase_pointer[x];
const uint8_t* bmp = testcase_image_bgra32[x];
if (!run_testcase(x, palette, pointer, bmp))
rc = -1;
}
return rc;
}