3#include <winpr/print.h>
4#include <winpr/image.h>
5#include <winpr/clipboard.h>
6#include <winpr/stream.h>
9#define test_log(fmt, ...) test_log_fn(__FILE__, __func__, __LINE__, (fmt), ##__VA_ARGS__)
10static void test_log_fn(
const char* file,
const char* func,
size_t line,
const char* fmt, ...)
17 winpr_vasprintf(&fstr, &fslen, fmt, ap);
18 (void)fprintf(stderr,
"[%" PRIu32
":%s]: %s\n", line, func, fstr);
23#define test_ClipboardSetData(clipboard, formatId, data, size) \
24 test_ClipboardSetDataFn(__FILE__, __func__, __LINE__, (clipboard), (formatId), (data), (size))
25static BOOL test_ClipboardSetDataFn(
const char* file,
const char* func,
size_t line,
26 wClipboard* clipboard, UINT32 formatId,
const void* data,
29 const BOOL rc = ClipboardSetData(clipboard, formatId, data, size);
32 test_log_fn(file, func, line,
"ClipboardSetData %s[0x%04" PRIx32
"][%" PRIu32
"] failed",
33 ClipboardGetFormatName(clipboard, formatId), formatId, size);
38#define test_ClipboardGetData(clipboard, formatId, size) \
39 test_ClipboardGetDataFn(__FILE__, __func__, __LINE__, (clipboard), (formatId), (size))
40static void* test_ClipboardGetDataFn(
const char* file,
const char* func,
size_t line,
41 wClipboard* clipboard, UINT32 formatId, UINT32* pSize)
43 void* rc = ClipboardGetData(clipboard, formatId, pSize);
46 test_log_fn(file, func, line,
"ClipboardGetData %s[0x%04" PRIx32
"] failed",
47 ClipboardGetFormatName(clipboard, formatId), formatId);
53static BOOL test_dib_to_bmp(
const BYTE* dib,
size_t dibSize,
size_t expectedOffset)
57 wClipboard* clipboard = ClipboardCreate();
60 test_log(
"ClipboardCreate failed");
64 const UINT32 bmpId = ClipboardRegisterFormat(clipboard,
"image/bmp");
67 test_log(
"bmpId == 0");
70 if (dibSize > UINT32_MAX)
72 test_log(
"dibSize %" PRIuz
" > UINT32_MAX failed");
75 if (!test_ClipboardSetData(clipboard, CF_DIB, dib, (UINT32)dibSize))
79 BYTE* bmp = test_ClipboardGetData(clipboard, bmpId, &bmpSize);
84 wImage* image = winpr_image_new();
87 test_log(
"winpr_image_new failed");
90 rc = (winpr_image_read_buffer(image, bmp, bmpSize) > 0);
92 test_log(
"winpr_image_read_buffer failed");
93 winpr_image_free(image, TRUE);
98 ClipboardDestroy(clipboard);
102static void write_dib_info_header(
wStream* s, UINT32 size, UINT16 bpp, UINT32 compression)
106 Stream_Write_UINT32(s, size);
107 Stream_Write_INT32(s, 1);
108 Stream_Write_INT32(s, 1);
109 Stream_Write_UINT16(s, 1);
110 Stream_Write_UINT16(s, bpp);
111 Stream_Write_UINT32(s, compression);
112 Stream_Write_UINT32(s, 4);
117static BOOL test_dib_offsets(
void)
120 wStream sbuffer = WINPR_C_ARRAY_INIT;
121 wStream* s = Stream_StaticInit(&sbuffer, v4,
sizeof(v4));
124 write_dib_info_header(s,
sizeof(
BITMAPV4HEADER), 32, BI_BITFIELDS);
126 Stream_Write_UINT32(s, 0x00FF0000);
127 Stream_Write_UINT32(s, 0x0000FF00);
128 Stream_Write_UINT32(s, 0x000000FF);
129 Stream_Write_UINT32(s, 0xFF000000);
131 Stream_Write_UINT32(s, 0xFF123456);
135 BYTE bitfields[
sizeof(
BITMAPINFOHEADER) + 3 *
sizeof(DWORD) + 4] = WINPR_C_ARRAY_INIT;
136 s = Stream_StaticInit(&sbuffer, bitfields,
sizeof(bitfields));
140 Stream_Write_UINT32(s, 0x00FF0000);
141 Stream_Write_UINT32(s, 0x0000FF00);
142 Stream_Write_UINT32(s, 0x000000FF);
143 Stream_Write_UINT32(s, 0xFF123456);
144 if (!test_dib_to_bmp(bitfields,
sizeof(bitfields),
150 s = Stream_StaticInit(&sbuffer, paletted,
sizeof(paletted));
154 Stream_Zero(s, 256 *
sizeof(
RGBQUAD));
155 Stream_Write_UINT32(s, 0);
156 return test_dib_to_bmp(paletted,
sizeof(paletted),
162static BOOL test_text_leading_newline(
void)
164 const char* tests[][2] = { {
"\nfoo",
"\r\nfoo" }, {
"\n",
"\r\n" } };
167 wClipboard* clipboard = ClipboardCreate();
170 test_log(
"ClipboardCreate failed");
174 const UINT32 textId = ClipboardRegisterFormat(clipboard,
"text/plain");
175 for (
size_t x = 0; x < ARRAYSIZE(tests); x++)
178 if (!test_ClipboardSetData(clipboard, textId, tests[x][0], (UINT32)strlen(tests[x][0])))
182 WCHAR* wstr = test_ClipboardGetData(clipboard, CF_UNICODETEXT, &size);
183 char* str = ConvertWCharNToUtf8Alloc(wstr, size /
sizeof(WCHAR),
nullptr);
184 const BOOL match = str && (strcmp(str, tests[x][1]) == 0);
189 test_log(
"text/plain to CF_UNICODETEXT failed for case %" PRIuz
"", x);
196 ClipboardDestroy(clipboard);
201static BOOL test_text_conversion(
void)
203 wClipboard* clipboard = ClipboardCreate();
217 const test_case_t tests[] = {
218 { ClipboardRegisterFormat(clipboard,
"text/plain"),
219 ClipboardRegisterFormat(clipboard,
"text/plain;charset=utf-8"),
"a\nb\rc\\u1234\\u055e",
220 17,
"a\nb\ncሴ՞", 10 },
221 { ClipboardRegisterFormat(clipboard,
"text/plain;charset=utf-8"),
222 ClipboardRegisterFormat(clipboard,
"text/plain"),
"a\r\nb\nc՞՞", 10,
223 "a\r\nb\nc\\u055e\\u055e", 18 },
224 { ClipboardRegisterFormat(clipboard,
"text/plain"), CF_UNICODETEXT,
"a\nb\rc\\u1234\\u055e",
225 17,
"\x61\x00\x0d\x00\x0a\x00\x62\x00\x0d\x0\x0a\x00\x63\x00\x34\x12\x5e\x05\x00\x00\x00",
227 { CF_UNICODETEXT, ClipboardRegisterFormat(clipboard,
"text/plain"),
228 "\x61\x00\x0d\x00\x0a\x00\x62\x00\x0d\x0\x0a\x00\x63\x00\x34\x12\x5e\x05\x00\x00\x00", 18,
229 "a\nb\nc\\u1234\\u055e", 17 },
230 { ClipboardRegisterFormat(clipboard,
"text/plain"), CF_TEXT,
"a\nb\rc\\u1234\\u055e", 17,
231 "a\nb\nc\\u1234\\u055e", 17 },
232 { CF_TEXT, ClipboardRegisterFormat(clipboard,
"text/plain"),
"a\nb\nc\\u1234\\u055e", 17,
233 "a\nb\nc\\u1234\\u055e", 17 },
234 { ClipboardRegisterFormat(clipboard,
"text/plain"), CF_OEMTEXT,
"a\nb\rc\\u1234\\u055e", 17,
235 "a\nb\nc\\u1234\\u055e", 17 },
236 { CF_OEMTEXT, ClipboardRegisterFormat(clipboard,
"text/plain"),
"a\nb\rc\\u1234\\u055e", 17,
237 "a\nb\nc\\u1234\\u055e", 17 }
242 for (
size_t x = 0; x < ARRAYSIZE(tests); x++)
244 const test_case_t* cur = &tests[x];
247 if (!test_ClipboardSetData(clipboard, cur->srcFormat, cur->src, cur->srcLen))
251 BYTE* data = test_ClipboardGetData(clipboard, cur->dstFormat, &dstSize);
252 if (dstSize != cur->expectLen)
254 winpr_znfree(data, dstSize);
261 winpr_znfree(data, dstSize);
264 const int rc = memcmp(cur->expect, data, cur->expectLen);
265 winpr_znfree(data, dstSize);
270 winpr_znfree(data, dstSize);
275 ClipboardDestroy(clipboard);
279int TestClipboardFormats(
int argc,
char* argv[])
283 UINT32* pFormatIds =
nullptr;
284 const char* formatName =
nullptr;
285 UINT32 utf8StringFormatId = 0;
290 if (!test_text_leading_newline())
293 if (!test_text_conversion())
296 wClipboard* clipboard = ClipboardCreate();
300 const char* mime_types[] = {
"text/plain",
"text/plain;charset=utf-8",
301 "text/html",
"image/bmp",
302 "image/png",
"image/webp",
304 for (
size_t x = 0; x < ARRAYSIZE(mime_types); x++)
306 const char* mime = mime_types[x];
307 UINT32
id = ClipboardRegisterFormat(clipboard, mime);
308 test_log(
"ClipboardRegisterFormat(%s) -> 0x%08" PRIx32
"", mime,
id);
313 utf8StringFormatId = ClipboardRegisterFormat(clipboard,
"UTF8_STRING");
314 pFormatIds =
nullptr;
315 count = ClipboardGetRegisteredFormatIds(clipboard, &pFormatIds);
317 for (UINT32 index = 0; index < count; index++)
319 UINT32 formatId = pFormatIds[index];
320 formatName = ClipboardGetFormatName(clipboard, formatId);
321 test_log(
"Format: 0x%08" PRIX32
" %s", formatId, formatName);
330 const char pSrcData[] =
"this is a test string";
331 char* pDstData =
nullptr;
333 SrcSize = (UINT32)(strnlen(pSrcData, ARRAYSIZE(pSrcData)) + 1);
334 const BOOL bSuccess =
335 test_ClipboardSetData(clipboard, utf8StringFormatId, pSrcData, SrcSize);
340 pDstData = (
char*)test_ClipboardGetData(clipboard, utf8StringFormatId, &DstSize);
347 char* pSrcData =
nullptr;
348 WCHAR* pDstData =
nullptr;
350 pDstData = (WCHAR*)test_ClipboardGetData(clipboard, CF_UNICODETEXT, &DstSize);
351 pSrcData = ConvertWCharNToUtf8Alloc(pDstData, DstSize /
sizeof(WCHAR),
nullptr);
357 pFormatIds =
nullptr;
358 count = ClipboardGetFormatIds(clipboard, &pFormatIds);
360 for (UINT32 index = 0; index < count; index++)
362 UINT32 formatId = pFormatIds[index];
363 formatName = ClipboardGetFormatName(clipboard, formatId);
364 test_log(
"Format: 0x%08" PRIX32
" %s", formatId, formatName);
369 const char* name = TEST_CLIP_BMP;
370 BOOL bSuccess = FALSE;
371 UINT32 idBmp = ClipboardRegisterFormat(clipboard,
"image/bmp");
373 wImage* img = winpr_image_new();
377 if (winpr_image_read(img, name) <= 0)
379 winpr_image_free(img, TRUE);
384 void* data = winpr_image_write_buffer(img, WINPR_IMAGE_BITMAP, &bmpsize);
385 bSuccess = test_ClipboardSetData(clipboard, idBmp, data, bmpsize);
388 winpr_image_free(img, TRUE);
396 void* pDstData = test_ClipboardGetData(clipboard,
id, &DstSize);
399 bSuccess = test_ClipboardSetData(clipboard,
id, pDstData, DstSize);
405 const uint32_t
id = ClipboardGetFormatId(clipboard,
"HTML Format");
407 void* pDstData = test_ClipboardGetData(clipboard,
id, &DstSize);
411 FILE* fp = fopen(
"test.html",
"w");
414 (void)fwrite(pDstData, 1, DstSize, fp);
421 UINT32
id = ClipboardRegisterFormat(clipboard,
"image/bmp");
424 void* pDstData = test_ClipboardGetData(clipboard,
id, &DstSize);
428 if (DstSize != bmpsize)
432#if defined(WINPR_UTILS_IMAGE_PNG)
434 UINT32
id = ClipboardRegisterFormat(clipboard,
"image/png");
437 void* pDstData = test_ClipboardGetData(clipboard,
id, &DstSize);
443 const char* name = TEST_CLIP_PNG;
444 BOOL bSuccess = FALSE;
445 UINT32 idBmp = ClipboardRegisterFormat(clipboard,
"image/png");
447 wImage* img = winpr_image_new();
451 if (winpr_image_read(img, name) <= 0)
453 winpr_image_free(img, TRUE);
458 void* data = winpr_image_write_buffer(img, WINPR_IMAGE_PNG, &bmpsize);
459 bSuccess = test_ClipboardSetData(clipboard, idBmp, data, bmpsize);
462 winpr_image_free(img, TRUE);
470 void* pDstData = test_ClipboardGetData(clipboard,
id, &DstSize);
473 bSuccess = test_ClipboardSetData(clipboard,
id, pDstData, DstSize);
480#if defined(WINPR_UTILS_IMAGE_WEBP)
482 UINT32
id = ClipboardRegisterFormat(clipboard,
"image/webp");
485 void* pDstData = test_ClipboardGetData(clipboard,
id, &DstSize);
492#if defined(WINPR_UTILS_IMAGE_JPEG)
494 UINT32
id = ClipboardRegisterFormat(clipboard,
"image/jpeg");
497 void* pDstData = test_ClipboardGetData(clipboard,
id, &DstSize);
505 if (!test_dib_offsets())
512 ClipboardDestroy(clipboard);