Milestone 5: deliver embedded RDP sessions and lifecycle hardening

This commit is contained in:
Keith Smith
2026-03-03 18:59:26 -07:00
parent 230a401386
commit 36006bd4aa
2941 changed files with 724359 additions and 77 deletions

View File

@@ -0,0 +1,55 @@
set(MODULE_NAME "TestWinPRUtils")
set(MODULE_PREFIX "TEST_WINPR_UTILS")
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
set(${MODULE_PREFIX}_TESTS
TestIni.c
TestVersion.c
TestImage.c
TestBacktrace.c
TestQueue.c
TestPrint.c
TestPubSub.c
TestStream.c
TestBitStream.c
TestArrayList.c
TestLinkedList.c
TestListDictionary.c
TestCmdLine.c
TestASN1.c
TestWLog.c
TestWLogCallback.c
TestHashTable.c
TestBufferPool.c
TestStreamPool.c
TestMessageQueue.c
TestMessagePipe.c
)
if(WITH_LODEPNG)
list(APPEND ${MODULES_PREFIX}_TESTS TestImage.c)
endif()
create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS})
add_compile_definitions(TEST_SOURCE_PATH="${CMAKE_CURRENT_SOURCE_DIR}")
add_compile_definitions(TEST_BINARY_PATH="${CMAKE_CURRENT_BINARY_DIR}")
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
target_link_libraries(${MODULE_NAME} winpr)
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
foreach(test ${${MODULE_PREFIX}_TESTS})
get_filename_component(TestName ${test} NAME_WE)
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
endforeach()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")
add_executable(img-cnv img-cnv.c)
target_link_libraries(img-cnv winpr)

View File

@@ -0,0 +1,347 @@
#include <winpr/asn1.h>
#include <winpr/print.h>
static const BYTE boolContent[] = { 0x01, 0x01, 0xFF };
static const BYTE badBoolContent[] = { 0x01, 0x04, 0xFF };
static const BYTE integerContent[] = { 0x02, 0x01, 0x02 };
static const BYTE badIntegerContent[] = { 0x02, 0x04, 0x02 };
static const BYTE positiveIntegerContent[] = { 0x02, 0x02, 0x00, 0xff };
static const BYTE negativeIntegerContent[] = { 0x02, 0x01, 0xff };
static const BYTE seqContent[] = { 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1B, 0x44,
0x69, 0x67, 0x69, 0x74, 0x61, 0x6C, 0x20, 0x53, 0x69, 0x67,
0x6E, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75,
0x73, 0x74, 0x20, 0x43, 0x6F, 0x2E, 0x31 };
static const BYTE contextualInteger[] = { 0xA0, 0x03, 0x02, 0x01, 0x02 };
static const BYTE oidContent[] = { 0x06, 0x03, 0x55, 0x04, 0x0A };
static const BYTE badOidContent[] = { 0x06, 0x89, 0x55, 0x04, 0x0A };
static const BYTE oidValue[] = { 0x55, 0x04, 0x0A };
static const BYTE ia5stringContent[] = { 0x16, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F,
0x63, 0x70, 0x73, 0x2E, 0x72, 0x6F, 0x6F, 0x74, 0x2D,
0x78, 0x31, 0x2E, 0x6C, 0x65, 0x74, 0x73, 0x65, 0x6E,
0x63, 0x72, 0x79, 0x70, 0x74, 0x2E, 0x6F, 0x72, 0x67 };
static const BYTE utctimeContent[] = { 0x17, 0x0D, 0x32, 0x31, 0x30, 0x33, 0x31, 0x37,
0x31, 0x36, 0x34, 0x30, 0x34, 0x36, 0x5A };
int TestASN1Read(int argc, char* argv[])
{
WinPrAsn1Decoder decoder = WinPrAsn1Decoder_init();
WinPrAsn1Decoder seqDecoder = WinPrAsn1Decoder_init();
wStream staticS = WINPR_C_ARRAY_INIT;
WinPrAsn1_BOOL boolV = 0;
WinPrAsn1_INTEGER integerV = 0;
WinPrAsn1_OID oidV = WINPR_C_ARRAY_INIT;
WinPrAsn1_IA5STRING ia5stringV = nullptr;
WinPrAsn1_UTCTIME utctimeV = WINPR_C_ARRAY_INIT;
WinPrAsn1_tag tag = 0;
size_t len = 0;
BOOL error = 0;
/* ============== Test INTEGERs ================ */
Stream_StaticConstInit(&staticS, integerContent, sizeof(integerContent));
WinPrAsn1Decoder_Init(&decoder, WINPR_ASN1_DER, &staticS);
if (!WinPrAsn1DecReadInteger(&decoder, &integerV))
return -1;
Stream_StaticConstInit(&staticS, positiveIntegerContent, sizeof(positiveIntegerContent));
WinPrAsn1Decoder_Init(&decoder, WINPR_ASN1_DER, &staticS);
if (!WinPrAsn1DecReadInteger(&decoder, &integerV) && integerV != 0xff)
return -1;
Stream_StaticConstInit(&staticS, negativeIntegerContent, sizeof(negativeIntegerContent));
WinPrAsn1Decoder_Init(&decoder, WINPR_ASN1_DER, &staticS);
if (!WinPrAsn1DecReadInteger(&decoder, &integerV) && integerV != -1)
return -1;
Stream_StaticConstInit(&staticS, badIntegerContent, sizeof(badIntegerContent));
WinPrAsn1Decoder_Init(&decoder, WINPR_ASN1_DER, &staticS);
if (WinPrAsn1DecReadInteger(&decoder, &integerV))
return -1;
/* ================ Test BOOL ================*/
Stream_StaticConstInit(&staticS, boolContent, sizeof(boolContent));
WinPrAsn1Decoder_Init(&decoder, WINPR_ASN1_DER, &staticS);
if (!WinPrAsn1DecReadBoolean(&decoder, &boolV))
return -10;
Stream_StaticConstInit(&staticS, badBoolContent, sizeof(badBoolContent));
WinPrAsn1Decoder_Init(&decoder, WINPR_ASN1_DER, &staticS);
if (WinPrAsn1DecReadBoolean(&decoder, &boolV))
return -11;
/* ================ Test OID ================*/
Stream_StaticConstInit(&staticS, oidContent, sizeof(oidContent));
WinPrAsn1Decoder_Init(&decoder, WINPR_ASN1_DER, &staticS);
if (!WinPrAsn1DecReadOID(&decoder, &oidV, TRUE) || oidV.len != 3 ||
(memcmp(oidV.data, oidValue, oidV.len) != 0))
return -15;
WinPrAsn1FreeOID(&oidV);
Stream_StaticConstInit(&staticS, badOidContent, sizeof(badOidContent));
WinPrAsn1Decoder_Init(&decoder, WINPR_ASN1_DER, &staticS);
if (WinPrAsn1DecReadOID(&decoder, &oidV, TRUE))
return -15;
WinPrAsn1FreeOID(&oidV);
Stream_StaticConstInit(&staticS, ia5stringContent, sizeof(ia5stringContent));
WinPrAsn1Decoder_Init(&decoder, WINPR_ASN1_DER, &staticS);
if (!WinPrAsn1DecReadIA5String(&decoder, &ia5stringV) ||
(strcmp(ia5stringV, "http://cps.root-x1.letsencrypt.org") != 0))
return -16;
free(ia5stringV);
/* ================ Test utc time ================*/
Stream_StaticConstInit(&staticS, utctimeContent, sizeof(utctimeContent));
WinPrAsn1Decoder_Init(&decoder, WINPR_ASN1_DER, &staticS);
if (!WinPrAsn1DecReadUtcTime(&decoder, &utctimeV) || utctimeV.year != 2021 ||
utctimeV.month != 3 || utctimeV.day != 17 || utctimeV.minute != 40 || utctimeV.tz != 'Z')
return -17;
/* ================ Test sequence ================*/
Stream_StaticConstInit(&staticS, seqContent, sizeof(seqContent));
WinPrAsn1Decoder_Init(&decoder, WINPR_ASN1_DER, &staticS);
if (!WinPrAsn1DecReadSequence(&decoder, &seqDecoder))
return -20;
Stream_StaticConstInit(&staticS, seqContent, sizeof(seqContent));
WinPrAsn1Decoder_Init(&decoder, WINPR_ASN1_DER, &staticS);
if (!WinPrAsn1DecReadTagLenValue(&decoder, &tag, &len, &seqDecoder))
return -21;
if (tag != ER_TAG_SEQUENCE)
return -22;
if (!WinPrAsn1DecPeekTag(&seqDecoder, &tag) || tag != ER_TAG_OBJECT_IDENTIFIER)
return -23;
/* ================ Test contextual ================*/
Stream_StaticConstInit(&staticS, contextualInteger, sizeof(contextualInteger));
WinPrAsn1Decoder_Init(&decoder, WINPR_ASN1_DER, &staticS);
error = TRUE;
if (!WinPrAsn1DecReadContextualInteger(&decoder, 0, &error, &integerV) || error)
return -25;
/* test reading a contextual integer that is not there (index 1).
* that should not touch the decoder read head and we shall be able to extract contextual tag 0
* after that
*/
WinPrAsn1Decoder_Init(&decoder, WINPR_ASN1_DER, &staticS);
error = FALSE;
if (WinPrAsn1DecReadContextualInteger(&decoder, 1, &error, &integerV) || error)
return -26;
error = FALSE;
if (!WinPrAsn1DecReadContextualInteger(&decoder, 0, &error, &integerV) || error)
return -27;
return 0;
}
static BYTE oid1_val[] = { 1 };
static const WinPrAsn1_OID oid1 = { sizeof(oid1_val), oid1_val };
static BYTE oid2_val[] = { 2, 2 };
static WinPrAsn1_OID oid2 = { sizeof(oid2_val), oid2_val };
static BYTE oid3_val[] = { 3, 3, 3 };
static WinPrAsn1_OID oid3 = { sizeof(oid3_val), oid3_val };
static BYTE oid4_val[] = { 4, 4, 4, 4 };
static WinPrAsn1_OID oid4 = { sizeof(oid4_val), oid4_val };
int TestASN1Write(int argc, char* argv[])
{
wStream* s = nullptr;
size_t expectedOuputSz = 0;
int retCode = 100;
WinPrAsn1_UTCTIME utcTime;
WinPrAsn1_IA5STRING ia5string = nullptr;
WinPrAsn1Encoder* enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
if (!enc)
goto out;
/* Let's encode something like:
* APP(3)
* SEQ2
* OID1
* OID2
* SEQ3
* OID3
* OID4
*
* [5] integer(200)
* [6] SEQ (empty)
* [7] UTC time (2016-03-17 16:40:41 UTC)
* [8] IA5String(test)
* [9] OctetString
* SEQ(empty)
*
*/
/* APP(3) */
retCode = 101;
if (!WinPrAsn1EncAppContainer(enc, 3))
goto out;
/* SEQ2 */
retCode = 102;
if (!WinPrAsn1EncSeqContainer(enc))
goto out;
retCode = 103;
if (WinPrAsn1EncOID(enc, &oid1) != 3)
goto out;
retCode = 104;
if (WinPrAsn1EncOID(enc, &oid2) != 4)
goto out;
retCode = 105;
if (WinPrAsn1EncEndContainer(enc) != 9)
goto out;
/* SEQ3 */
retCode = 110;
if (!WinPrAsn1EncSeqContainer(enc))
goto out;
retCode = 111;
if (WinPrAsn1EncOID(enc, &oid3) != 5)
goto out;
retCode = 112;
if (WinPrAsn1EncOID(enc, &oid4) != 6)
goto out;
retCode = 113;
if (WinPrAsn1EncEndContainer(enc) != 13)
goto out;
/* [5] integer(200) */
retCode = 114;
if (WinPrAsn1EncContextualInteger(enc, 5, 200) != 6)
goto out;
/* [6] SEQ (empty) */
retCode = 115;
if (!WinPrAsn1EncContextualSeqContainer(enc, 6))
goto out;
retCode = 116;
if (WinPrAsn1EncEndContainer(enc) != 4)
goto out;
/* [7] UTC time (2016-03-17 16:40:41 UTC) */
retCode = 117;
utcTime.year = 2016;
utcTime.month = 3;
utcTime.day = 17;
utcTime.hour = 16;
utcTime.minute = 40;
utcTime.second = 41;
utcTime.tz = 'Z';
if (WinPrAsn1EncContextualUtcTime(enc, 7, &utcTime) != 17)
goto out;
/* [8] IA5String(test) */
retCode = 118;
ia5string = "test";
if (!WinPrAsn1EncContextualContainer(enc, 8))
goto out;
retCode = 119;
if (WinPrAsn1EncIA5String(enc, ia5string) != 6)
goto out;
retCode = 120;
if (WinPrAsn1EncEndContainer(enc) != 8)
goto out;
/* [9] OctetString
* SEQ(empty)
*/
retCode = 121;
if (!WinPrAsn1EncContextualOctetStringContainer(enc, 9))
goto out;
retCode = 122;
if (!WinPrAsn1EncSeqContainer(enc))
goto out;
retCode = 123;
if (WinPrAsn1EncEndContainer(enc) != 2)
goto out;
retCode = 124;
if (WinPrAsn1EncEndContainer(enc) != 6)
goto out;
/* close APP */
expectedOuputSz = 24 + 6 + 4 + 17 + 8 + 6;
retCode = 200;
if (WinPrAsn1EncEndContainer(enc) != expectedOuputSz)
goto out;
/* let's output the result */
retCode = 201;
s = Stream_New(nullptr, 1024);
if (!s)
goto out;
retCode = 202;
if (!WinPrAsn1EncToStream(enc, s) || Stream_GetPosition(s) != expectedOuputSz)
goto out;
/* winpr_HexDump("", WLOG_ERROR, Stream_Buffer(s), Stream_GetPosition(s));*/
/*
* let's perform a mini-performance test, where we encode an ASN1 message with a big depth,
* so that we trigger reallocation routines in the encoder. We're gonna encode something like
* SEQ1
* SEQ2
* SEQ3
* ...
* SEQ1000
* INTEGER(2)
*
* As static chunks and containers are 50, a depth of 1000 should be enough
*
*/
WinPrAsn1Encoder_Reset(enc);
retCode = 203;
for (size_t i = 0; i < 1000; i++)
{
if (!WinPrAsn1EncSeqContainer(enc))
goto out;
}
retCode = 204;
if (WinPrAsn1EncInteger(enc, 2) != 3)
goto out;
retCode = 205;
for (size_t i = 0; i < 1000; i++)
{
if (!WinPrAsn1EncEndContainer(enc))
goto out;
}
retCode = 0;
out:
if (s)
Stream_Free(s, TRUE);
WinPrAsn1Encoder_Free(&enc);
return retCode;
}
int TestASN1(int argc, char* argv[])
{
int ret = TestASN1Read(argc, argv);
if (ret)
return ret;
return TestASN1Write(argc, argv);
}

View File

@@ -0,0 +1,84 @@
#include <winpr/crt.h>
#include <winpr/tchar.h>
#include <winpr/collections.h>
int TestArrayList(int argc, char* argv[])
{
int res = -1;
SSIZE_T rc = 0;
size_t val = 0;
const size_t elemsToInsert = 10;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
wArrayList* arrayList = ArrayList_New(TRUE);
if (!arrayList)
return -1;
for (size_t index = 0; index < elemsToInsert; index++)
{
if (!ArrayList_Append(arrayList, (void*)index))
goto fail;
}
size_t count = ArrayList_Count(arrayList);
printf("ArrayList count: %" PRIuz "\n", count);
SSIZE_T index = ArrayList_IndexOf(arrayList, (void*)(size_t)6, -1, -1);
printf("ArrayList index: %" PRIdz "\n", index);
if (index != 6)
goto fail;
ArrayList_Insert(arrayList, 5, (void*)(size_t)100);
index = ArrayList_IndexOf(arrayList, (void*)(size_t)6, -1, -1);
printf("ArrayList index: %" PRIdz "\n", index);
if (index != 7)
goto fail;
ArrayList_Remove(arrayList, (void*)(size_t)100);
rc = ArrayList_IndexOf(arrayList, (void*)(size_t)6, -1, -1);
printf("ArrayList index: %" PRIdz "\n", rc);
if (rc != 6)
goto fail;
for (size_t index = 0; index < elemsToInsert; index++)
{
val = (size_t)ArrayList_GetItem(arrayList, 0);
if (!ArrayList_RemoveAt(arrayList, 0))
goto fail;
if (val != index)
{
printf("ArrayList: shifted %" PRIdz " entries, expected value %" PRIdz ", got %" PRIdz
"\n",
index, index, val);
goto fail;
}
}
rc = ArrayList_IndexOf(arrayList, (void*)elemsToInsert, -1, -1);
printf("ArrayList index: %" PRIdz "\n", rc);
if (rc != -1)
goto fail;
count = ArrayList_Count(arrayList);
printf("ArrayList count: %" PRIuz "\n", count);
if (count != 0)
goto fail;
ArrayList_Clear(arrayList);
res = 0;
fail:
ArrayList_Free(arrayList);
return res;
}

View File

@@ -0,0 +1,34 @@
#include <stdio.h>
#include <winpr/debug.h>
int TestBacktrace(int argc, char* argv[])
{
int rc = -1;
size_t used = 0;
char** msg = nullptr;
void* stack = winpr_backtrace(20);
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
if (!stack)
{
(void)fprintf(stderr, "winpr_backtrace failed!\n");
return -1;
}
msg = winpr_backtrace_symbols(stack, &used);
if (msg)
{
for (size_t x = 0; x < used; x++)
printf("%" PRIuz ": %s\n", x, msg[x]);
rc = 0;
}
winpr_backtrace_symbols_fd(stack, fileno(stdout));
winpr_backtrace_free(stack);
free((void*)msg);
return rc;
}

View File

@@ -0,0 +1,86 @@
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/stream.h>
#include <winpr/bitstream.h>
static void BitStrGen(void)
{
char str[64] = WINPR_C_ARRAY_INIT;
for (DWORD i = 0; i < 256;)
{
printf("\t");
for (DWORD j = 0; j < 4; j++)
{
if (0)
{
/* Least Significant Bit First */
str[0] = (i & (1 << 7)) ? '1' : '0';
str[1] = (i & (1 << 6)) ? '1' : '0';
str[2] = (i & (1 << 5)) ? '1' : '0';
str[3] = (i & (1 << 4)) ? '1' : '0';
str[4] = (i & (1 << 3)) ? '1' : '0';
str[5] = (i & (1 << 2)) ? '1' : '0';
str[6] = (i & (1 << 1)) ? '1' : '0';
str[7] = (i & (1 << 0)) ? '1' : '0';
str[8] = '\0';
}
else
{
/* Most Significant Bit First */
str[7] = (i & (1 << 7)) ? '1' : '0';
str[6] = (i & (1 << 6)) ? '1' : '0';
str[5] = (i & (1 << 5)) ? '1' : '0';
str[4] = (i & (1 << 4)) ? '1' : '0';
str[3] = (i & (1 << 3)) ? '1' : '0';
str[2] = (i & (1 << 2)) ? '1' : '0';
str[1] = (i & (1 << 1)) ? '1' : '0';
str[0] = (i & (1 << 0)) ? '1' : '0';
str[8] = '\0';
}
printf("\"%s\",%s", str, j == 3 ? "" : " ");
i++;
}
printf("\n");
}
}
int TestBitStream(int argc, char* argv[])
{
wBitStream* bs = nullptr;
BYTE buffer[1024] = WINPR_C_ARRAY_INIT;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
bs = BitStream_New();
if (!bs)
return 1;
BitStream_Attach(bs, buffer, sizeof(buffer));
BitStream_Write_Bits(bs, 0xAF, 8); /* 11110101 */
BitStream_Write_Bits(bs, 0xF, 4); /* 1111 */
BitStream_Write_Bits(bs, 0xA, 4); /* 0101 */
BitStream_Flush(bs);
BitDump(__func__, WLOG_INFO, buffer, bs->position, BITDUMP_MSB_FIRST);
BitStream_Write_Bits(bs, 3, 2); /* 11 */
BitStream_Write_Bits(bs, 0, 3); /* 000 */
BitStream_Write_Bits(bs, 0x2D, 6); /* 101101 */
BitStream_Write_Bits(bs, 0x19, 5); /* 11001 */
// BitStream_Flush(bs); /* flush should be done automatically here (32 bits written) */
BitDump(__func__, WLOG_INFO, buffer, bs->position, BITDUMP_MSB_FIRST);
BitStream_Write_Bits(bs, 3, 2); /* 11 */
BitStream_Flush(bs);
BitDump(__func__, WLOG_INFO, buffer, bs->position, BITDUMP_MSB_FIRST);
BitStream_Write_Bits(bs, 00, 2); /* 00 */
BitStream_Write_Bits(bs, 0xF, 4); /* 1111 */
BitStream_Write_Bits(bs, 0, 20);
BitStream_Write_Bits(bs, 0xAFF, 12); /* 111111110101 */
BitStream_Flush(bs);
BitDump(__func__, WLOG_INFO, buffer, bs->position, BITDUMP_MSB_FIRST);
BitStream_Free(bs);
return 0;
}

View File

@@ -0,0 +1,68 @@
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <winpr/collections.h>
int TestBufferPool(int argc, char* argv[])
{
DWORD PoolSize = 0;
SSIZE_T BufferSize = 0;
wBufferPool* pool = nullptr;
BYTE* Buffers[10] = WINPR_C_ARRAY_INIT;
int DefaultSize = 1234;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
pool = BufferPool_New(TRUE, -1, 16);
if (!pool)
return -1;
Buffers[0] = BufferPool_Take(pool, DefaultSize);
Buffers[1] = BufferPool_Take(pool, DefaultSize);
Buffers[2] = BufferPool_Take(pool, 2048);
if (!Buffers[0] || !Buffers[1] || !Buffers[2])
return -1;
BufferSize = BufferPool_GetBufferSize(pool, Buffers[0]);
if (BufferSize != DefaultSize)
{
printf("BufferPool_GetBufferSize failure: Actual: %" PRIdz " Expected: %" PRIu32 "\n",
BufferSize, DefaultSize);
return -1;
}
BufferSize = BufferPool_GetBufferSize(pool, Buffers[1]);
if (BufferSize != DefaultSize)
{
printf("BufferPool_GetBufferSize failure: Actual: %" PRIdz " Expected: %" PRIu32 "\n",
BufferSize, DefaultSize);
return -1;
}
BufferSize = BufferPool_GetBufferSize(pool, Buffers[2]);
if (BufferSize != 2048)
{
printf("BufferPool_GetBufferSize failure: Actual: %" PRIdz " Expected: 2048\n", BufferSize);
return -1;
}
BufferPool_Return(pool, Buffers[1]);
PoolSize = BufferPool_GetPoolSize(pool);
if (PoolSize != 2)
{
printf("BufferPool_GetPoolSize failure: Actual: %" PRIu32 " Expected: 2\n", PoolSize);
return -1;
}
BufferPool_Clear(pool);
BufferPool_Free(pool);
return 0;
}

View File

@@ -0,0 +1,379 @@
#include <errno.h>
#include <winpr/crt.h>
#include <winpr/assert.h>
#include <winpr/tchar.h>
#include <winpr/cmdline.h>
#include <winpr/strlst.h>
static const char* testArgv[] = { "mstsc.exe",
"+z",
"/w:1024",
"/h:768",
"/bpp:32",
"/admin",
"/multimon",
"+fonts",
"-wallpaper",
"/v:localhost:3389",
"/valuelist:value1,value2",
"/valuelist-empty:",
nullptr };
static const char testListAppName[] = "test app name";
static const char* testListArgs[] = {
"g:some.gateway.server,u:some\\\"user,p:some\\\"password,d:some\\\"domain,type:auto",
"a,b,c,d",
"a:,\"b:xxx, yyy\",c",
"a:,,,b",
"a:,\",b",
"\"a,b,c,d d d,fff\"",
"",
nullptr,
"'a,b,\",c'",
"\"a,b,',c\"",
"', a, ', b,c'",
"\"a,b,\",c\"",
};
static const char* testListArgs1[] = { testListAppName, "a", "b", "c", "d" };
static const char* testListArgs2[] = { testListAppName, "a:", "b:xxx, yyy", "c" };
// static const char* testListArgs3[] = {};
// static const char* testListArgs4[] = {};
static const char* testListArgs5[] = { testListAppName, "a", "b", "c", "d d d", "fff" };
static const char* testListArgs6[] = { testListAppName };
static const char* testListArgs7[] = { testListAppName };
static const char* testListArgs8[] = { testListAppName, "a", "b", "\"", "c" };
static const char* testListArgs9[] = { testListAppName, "a", "b", "'", "c" };
// static const char* testListArgs10[] = {};
// static const char* testListArgs11[] = {};
static const char* testListArgs12[] = { testListAppName, "g:some.gateway.server",
"u:some\\\"user", "p:some\\\"password",
"d:some\\\"domain", "type:auto" };
static const char** testListArgsResult[] = {
testListArgs12,
testListArgs1,
testListArgs2,
nullptr /* testListArgs3 */,
nullptr /* testListArgs4 */,
testListArgs5,
testListArgs6,
testListArgs7,
testListArgs8,
testListArgs9,
nullptr /* testListArgs10 */,
nullptr /* testListArgs11 */
};
static const size_t testListArgsCount[] = {
ARRAYSIZE(testListArgs12), ARRAYSIZE(testListArgs1),
ARRAYSIZE(testListArgs2), 0 /* ARRAYSIZE(testListArgs3) */,
0 /* ARRAYSIZE(testListArgs4) */, ARRAYSIZE(testListArgs5),
ARRAYSIZE(testListArgs6), ARRAYSIZE(testListArgs7),
ARRAYSIZE(testListArgs8), ARRAYSIZE(testListArgs9),
0 /* ARRAYSIZE(testListArgs10) */, 0 /* ARRAYSIZE(testListArgs11) */
};
static BOOL checkResult(size_t index, char** actual, size_t actualCount)
{
const char** result = testListArgsResult[index];
const size_t resultCount = testListArgsCount[index];
if (resultCount != actualCount)
return FALSE;
if (actualCount == 0)
{
return (actual == nullptr);
}
else
{
if (!actual)
return FALSE;
for (size_t x = 0; x < actualCount; x++)
{
const char* a = result[x];
const char* b = actual[x];
if (strcmp(a, b) != 0)
return FALSE;
}
}
return TRUE;
}
static BOOL TestCommandLineParseCommaSeparatedValuesEx(void)
{
WINPR_ASSERT(ARRAYSIZE(testListArgs) == ARRAYSIZE(testListArgsResult));
WINPR_ASSERT(ARRAYSIZE(testListArgs) == ARRAYSIZE(testListArgsCount));
for (size_t x = 0; x < ARRAYSIZE(testListArgs); x++)
{
union
{
char* p;
char** pp;
const char** ppc;
} ptr;
const char* list = testListArgs[x];
size_t count = 42;
ptr.pp = CommandLineParseCommaSeparatedValuesEx(testListAppName, list, &count);
BOOL valid = checkResult(x, ptr.pp, count);
free(ptr.p);
if (!valid)
return FALSE;
}
return TRUE;
}
int TestCmdLine(int argc, char* argv[])
{
int status = 0;
int ret = -1;
DWORD flags = 0;
long width = 0;
long height = 0;
const COMMAND_LINE_ARGUMENT_A* arg = nullptr;
int testArgc = 0;
char** command_line = nullptr;
COMMAND_LINE_ARGUMENT_A args[] = {
{ "v", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr,
"destination server" },
{ "port", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr,
"server port" },
{ "w", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr, "width" },
{ "h", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr, "height" },
{ "f", COMMAND_LINE_VALUE_FLAG, nullptr, nullptr, nullptr, -1, nullptr, "fullscreen" },
{ "bpp", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr,
"session bpp (color depth)" },
{ "admin", COMMAND_LINE_VALUE_FLAG, nullptr, nullptr, nullptr, -1, "console",
"admin (or console) session" },
{ "multimon", COMMAND_LINE_VALUE_FLAG, nullptr, nullptr, nullptr, -1, nullptr,
"multi-monitor" },
{ "a", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, "addin", "addin" },
{ "u", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr, "username" },
{ "p", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr, "password" },
{ "d", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr, "domain" },
{ "z", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueFalse, nullptr, -1, nullptr,
"compression" },
{ "audio", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr,
"audio output mode" },
{ "mic", COMMAND_LINE_VALUE_FLAG, nullptr, nullptr, nullptr, -1, nullptr,
"audio input (microphone)" },
{ "fonts", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueFalse, nullptr, -1, nullptr,
"smooth fonts (cleartype)" },
{ "aero", COMMAND_LINE_VALUE_BOOL, nullptr, nullptr, BoolValueFalse, -1, nullptr,
"desktop composition" },
{ "window-drag", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueFalse, nullptr, -1, nullptr,
"full window drag" },
{ "menu-anims", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueFalse, nullptr, -1, nullptr,
"menu animations" },
{ "themes", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
"themes" },
{ "wallpaper", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
"wallpaper" },
{ "codec", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr, "codec" },
{ "nego", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
"protocol security negotiation" },
{ "sec", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr,
"force specific protocol security" },
#if defined(WITH_FREERDP_DEPRECATED)
{ "sec-rdp", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
"rdp protocol security" },
{ "sec-tls", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
"tls protocol security" },
{ "sec-nla", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueTrue, nullptr, -1, nullptr,
"nla protocol security" },
{ "sec-ext", COMMAND_LINE_VALUE_BOOL, nullptr, BoolValueFalse, nullptr, -1, nullptr,
"nla extended protocol security" },
{ "cert-name", COMMAND_LINE_VALUE_REQUIRED, nullptr, nullptr, nullptr, -1, nullptr,
"certificate name" },
{ "cert-ignore", COMMAND_LINE_VALUE_FLAG, nullptr, nullptr, nullptr, -1, nullptr,
"ignore certificate" },
#endif
{ "valuelist", COMMAND_LINE_VALUE_REQUIRED, "<val1>,<val2>", nullptr, nullptr, -1, nullptr,
"List of comma separated values." },
{ "valuelist-empty", COMMAND_LINE_VALUE_REQUIRED, "<val1>,<val2>", nullptr, nullptr, -1,
nullptr,
"List of comma separated values. Used to test correct behavior if an empty list was "
"passed." },
{ "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, nullptr, nullptr,
nullptr, -1, nullptr, "print version" },
{ "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, nullptr, nullptr, nullptr, -1,
"?", "print help" },
{ nullptr, 0, nullptr, nullptr, nullptr, -1, nullptr, nullptr }
};
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
flags = COMMAND_LINE_SIGIL_SLASH | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_SIGIL_PLUS_MINUS;
testArgc = string_list_length(testArgv);
command_line = string_list_copy(testArgv);
if (!command_line)
{
printf("Argument duplication failed (not enough memory?)\n");
return ret;
}
status =
CommandLineParseArgumentsA(testArgc, command_line, args, flags, nullptr, nullptr, nullptr);
if (status != 0)
{
printf("CommandLineParseArgumentsA failure: %d\n", status);
goto out;
}
arg = CommandLineFindArgumentA(args, "w");
if (strcmp("1024", arg->Value) != 0)
{
printf("CommandLineFindArgumentA: unexpected %s value %s\n", arg->Name, arg->Value);
goto out;
}
arg = CommandLineFindArgumentA(args, "h");
if (strcmp("768", arg->Value) != 0)
{
printf("CommandLineFindArgumentA: unexpected %s value %s\n", arg->Name, arg->Value);
goto out;
}
arg = CommandLineFindArgumentA(args, "f");
if (arg->Value)
{
printf("CommandLineFindArgumentA: unexpected %s value\n", arg->Name);
goto out;
}
arg = CommandLineFindArgumentA(args, "admin");
if (!arg->Value)
{
printf("CommandLineFindArgumentA: unexpected %s value\n", arg->Name);
goto out;
}
arg = CommandLineFindArgumentA(args, "multimon");
if (!arg->Value)
{
printf("CommandLineFindArgumentA: unexpected %s value\n", arg->Name);
goto out;
}
arg = CommandLineFindArgumentA(args, "v");
if (strcmp("localhost:3389", arg->Value) != 0)
{
printf("CommandLineFindArgumentA: unexpected %s value %s\n", arg->Name, arg->Value);
goto out;
}
arg = CommandLineFindArgumentA(args, "fonts");
if (!arg->Value)
{
printf("CommandLineFindArgumentA: unexpected %s value\n", arg->Name);
goto out;
}
arg = CommandLineFindArgumentA(args, "wallpaper");
if (arg->Value)
{
printf("CommandLineFindArgumentA: unexpected %s value\n", arg->Name);
goto out;
}
arg = CommandLineFindArgumentA(args, "help");
if (arg->Value)
{
printf("CommandLineFindArgumentA: unexpected %s value\n", arg->Name);
goto out;
}
arg = args;
errno = 0;
do
{
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
continue;
printf("Argument: %s\n", arg->Name);
CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "v")
{
}
CommandLineSwitchCase(arg, "w")
{
width = strtol(arg->Value, nullptr, 0);
if (errno != 0)
goto out;
}
CommandLineSwitchCase(arg, "h")
{
height = strtol(arg->Value, nullptr, 0);
if (errno != 0)
goto out;
}
CommandLineSwitchCase(arg, "valuelist")
{
size_t count = 0;
char** p = CommandLineParseCommaSeparatedValuesEx(arg->Name, arg->Value, &count);
free((void*)p);
if (!p || count != 3)
{
printf("CommandLineParseCommaSeparatedValuesEx: invalid p or count (%" PRIuz
"!=3)\n",
count);
goto out;
}
}
CommandLineSwitchCase(arg, "valuelist-empty")
{
size_t count = 0;
char** p = CommandLineParseCommaSeparatedValuesEx(arg->Name, arg->Value, &count);
free((void*)p);
if (!p || count != 1)
{
printf("CommandLineParseCommaSeparatedValuesEx: invalid p or count (%" PRIuz
"!=1)\n",
count);
goto out;
}
}
CommandLineSwitchDefault(arg)
{
}
CommandLineSwitchEnd(arg)
} while ((arg = CommandLineFindNextArgumentA(arg)) != nullptr);
if ((width != 1024) || (height != 768))
{
printf("Unexpected width and height: Actual: (%ldx%ld), Expected: (1024x768)\n", width,
height);
goto out;
}
ret = 0;
out:
string_list_free(command_line);
if (!TestCommandLineParseCommaSeparatedValuesEx())
return -1;
return ret;
}

View File

@@ -0,0 +1,446 @@
#include <winpr/crt.h>
#include <winpr/tchar.h>
#include <winpr/collections.h>
static char* key1 = "key1";
static char* key2 = "key2";
static char* key3 = "key3";
static char* val1 = "val1";
static char* val2 = "val2";
static char* val3 = "val3";
static int test_hash_table_pointer(void)
{
int rc = -1;
size_t count = 0;
char* value = nullptr;
wHashTable* table = nullptr;
table = HashTable_New(TRUE);
if (!table)
return -1;
if (!HashTable_Insert(table, key1, val1))
goto fail;
if (!HashTable_Insert(table, key2, val2))
goto fail;
if (!HashTable_Insert(table, key3, val3))
goto fail;
count = HashTable_Count(table);
if (count != 3)
{
printf("HashTable_Count: Expected : 3, Actual: %" PRIuz "\n", count);
goto fail;
}
if (!HashTable_Remove(table, key2))
goto fail;
count = HashTable_Count(table);
if (count != 2)
{
printf("HashTable_Count: Expected : 2, Actual: %" PRIuz "\n", count);
goto fail;
}
if (!HashTable_Remove(table, key3))
goto fail;
count = HashTable_Count(table);
if (count != 1)
{
printf("HashTable_Count: Expected : 1, Actual: %" PRIuz "\n", count);
goto fail;
}
if (!HashTable_Remove(table, key1))
goto fail;
count = HashTable_Count(table);
if (count != 0)
{
printf("HashTable_Count: Expected : 0, Actual: %" PRIuz "\n", count);
goto fail;
}
if (!HashTable_Insert(table, key1, val1))
goto fail;
if (!HashTable_Insert(table, key2, val2))
goto fail;
if (!HashTable_Insert(table, key3, val3))
goto fail;
count = HashTable_Count(table);
if (count != 3)
{
printf("HashTable_Count: Expected : 3, Actual: %" PRIuz "\n", count);
goto fail;
}
value = (char*)HashTable_GetItemValue(table, key1);
if (strcmp(value, val1) != 0)
{
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val1, value);
goto fail;
}
value = (char*)HashTable_GetItemValue(table, key2);
if (strcmp(value, val2) != 0)
{
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val2, value);
goto fail;
}
value = (char*)HashTable_GetItemValue(table, key3);
if (strcmp(value, val3) != 0)
{
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val3, value);
goto fail;
}
if (!HashTable_SetItemValue(table, key2, "apple"))
goto fail;
value = (char*)HashTable_GetItemValue(table, key2);
if (strcmp(value, "apple") != 0)
{
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", "apple", value);
goto fail;
}
if (!HashTable_Contains(table, key2))
{
printf("HashTable_Contains: Expected : TRUE, Actual: FALSE\n");
goto fail;
}
if (!HashTable_Remove(table, key2))
{
printf("HashTable_Remove: Expected : TRUE, Actual: FALSE\n");
goto fail;
}
if (HashTable_Remove(table, key2))
{
printf("HashTable_Remove: Expected : FALSE, Actual: TRUE\n");
goto fail;
}
HashTable_Clear(table);
count = HashTable_Count(table);
if (count != 0)
{
printf("HashTable_Count: Expected : 0, Actual: %" PRIuz "\n", count);
goto fail;
}
rc = 1;
fail:
HashTable_Free(table);
return rc;
}
static int test_hash_table_string(void)
{
int rc = -1;
size_t count = 0;
char* value = nullptr;
wHashTable* table = HashTable_New(TRUE);
if (!table)
return -1;
if (!HashTable_SetupForStringData(table, TRUE))
goto fail;
if (!HashTable_Insert(table, key1, val1))
goto fail;
if (!HashTable_Insert(table, key2, val2))
goto fail;
if (!HashTable_Insert(table, key3, val3))
goto fail;
count = HashTable_Count(table);
if (count != 3)
{
printf("HashTable_Count: Expected : 3, Actual: %" PRIuz "\n", count);
goto fail;
}
if (!HashTable_Remove(table, key2))
goto fail;
count = HashTable_Count(table);
if (count != 2)
{
printf("HashTable_Count: Expected : 3, Actual: %" PRIuz "\n", count);
goto fail;
}
if (!HashTable_Remove(table, key3))
goto fail;
count = HashTable_Count(table);
if (count != 1)
{
printf("HashTable_Count: Expected : 1, Actual: %" PRIuz "\n", count);
goto fail;
}
if (!HashTable_Remove(table, key1))
goto fail;
count = HashTable_Count(table);
if (count != 0)
{
printf("HashTable_Count: Expected : 0, Actual: %" PRIuz "\n", count);
goto fail;
}
if (!HashTable_Insert(table, key1, val1))
goto fail;
if (!HashTable_Insert(table, key2, val2))
goto fail;
if (!HashTable_Insert(table, key3, val3))
goto fail;
count = HashTable_Count(table);
if (count != 3)
{
printf("HashTable_Count: Expected : 3, Actual: %" PRIuz "\n", count);
goto fail;
}
value = (char*)HashTable_GetItemValue(table, key1);
if (strcmp(value, val1) != 0)
{
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val1, value);
goto fail;
}
value = (char*)HashTable_GetItemValue(table, key2);
if (strcmp(value, val2) != 0)
{
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val2, value);
goto fail;
}
value = (char*)HashTable_GetItemValue(table, key3);
if (strcmp(value, val3) != 0)
{
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val3, value);
goto fail;
}
if (!HashTable_SetItemValue(table, key2, "apple"))
goto fail;
value = (char*)HashTable_GetItemValue(table, key2);
if (strcmp(value, "apple") != 0)
{
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", "apple", value);
goto fail;
}
if (!HashTable_Contains(table, key2))
{
printf("HashTable_Contains: Expected : TRUE, Actual: FALSE\n");
goto fail;
}
if (!HashTable_Remove(table, key2))
{
printf("HashTable_Remove: Expected : TRUE, Actual: FALSE\n");
goto fail;
}
if (HashTable_Remove(table, key2))
{
printf("HashTable_Remove: Expected : FALSE, Actual: TRUE\n");
goto fail;
}
HashTable_Clear(table);
count = HashTable_Count(table);
if (count != 0)
{
printf("HashTable_Count: Expected : 0, Actual: %" PRIuz "\n", count);
goto fail;
}
rc = 1;
fail:
HashTable_Free(table);
return rc;
}
typedef struct
{
wHashTable* table;
size_t strlenCounter;
size_t foreachCalls;
BOOL test3error;
} ForeachData;
static BOOL foreachFn1(const void* key, void* value, void* arg)
{
ForeachData* d = (ForeachData*)arg;
WINPR_UNUSED(key);
d->strlenCounter += strlen((const char*)value);
return TRUE;
}
static BOOL foreachFn2(const void* key, void* value, void* arg)
{
ForeachData* d = (ForeachData*)arg;
WINPR_UNUSED(key);
WINPR_UNUSED(value);
d->foreachCalls++;
return (d->foreachCalls != 2);
}
static BOOL foreachFn3(const void* key, void* value, void* arg)
{
const char* keyStr = (const char*)key;
ForeachData* d = (ForeachData*)arg;
ForeachData d2;
WINPR_UNUSED(value);
WINPR_ASSERT(keyStr);
if (strcmp(keyStr, "key1") == 0)
{
/* when we pass on key1, let's remove key2 and check that the value is not
* visible anymore (even if has just been marked for removal)*/
HashTable_Remove(d->table, "key2");
if (HashTable_Contains(d->table, "key2"))
{
d->test3error = TRUE;
return FALSE;
}
if (HashTable_ContainsValue(d->table, "value2"))
{
d->test3error = TRUE;
return FALSE;
}
/* number of elements of the table shall be correct too */
if (HashTable_Count(d->table) != 2)
{
d->test3error = TRUE;
return FALSE;
}
/* we try recursive HashTable_Foreach */
d2.table = d->table;
d2.strlenCounter = 0;
if (!HashTable_Foreach(d->table, foreachFn1, &d2))
{
d->test3error = TRUE;
return FALSE;
}
if (d2.strlenCounter != 8)
{
d->test3error = TRUE;
return FALSE;
}
}
return TRUE;
}
static int test_hash_foreach(void)
{
ForeachData foreachData;
wHashTable* table = nullptr;
int retCode = 0;
foreachData.table = table = HashTable_New(TRUE);
if (!table)
return -1;
if (!HashTable_SetupForStringData(table, TRUE))
goto out;
if (HashTable_Insert(table, key1, val1) < 0 || HashTable_Insert(table, key2, val2) < 0 ||
HashTable_Insert(table, key3, val3) < 0)
{
retCode = -2;
goto out;
}
/* let's try a first trivial foreach */
foreachData.strlenCounter = 0;
if (!HashTable_Foreach(table, foreachFn1, &foreachData))
{
retCode = -10;
goto out;
}
if (foreachData.strlenCounter != 12)
{
retCode = -11;
goto out;
}
/* interrupted foreach */
foreachData.foreachCalls = 0;
if (HashTable_Foreach(table, foreachFn2, &foreachData))
{
retCode = -20;
goto out;
}
if (foreachData.foreachCalls != 2)
{
retCode = -21;
goto out;
}
/* let's try a foreach() call that will remove a value from the table in the callback */
foreachData.test3error = FALSE;
if (!HashTable_Foreach(table, foreachFn3, &foreachData))
{
retCode = -30;
goto out;
}
if (foreachData.test3error)
{
retCode = -31;
goto out;
}
out:
HashTable_Free(table);
return retCode;
}
int TestHashTable(int argc, char* argv[])
{
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
if (test_hash_table_pointer() < 0)
return 1;
if (test_hash_table_string() < 0)
return 2;
if (test_hash_foreach() < 0)
return 3;
return 0;
}

View File

@@ -0,0 +1,232 @@
#include <stdio.h>
#include <winpr/string.h>
#include <winpr/assert.h>
#include <winpr/file.h>
#include <winpr/path.h>
#include <winpr/image.h>
static const char test_src_filename[] = TEST_SOURCE_PATH "/rgb";
static const char test_bin_filename[] = TEST_BINARY_PATH "/rgb";
static BOOL test_image_equal(const wImage* imageA, const wImage* imageB)
{
return winpr_image_equal(imageA, imageB,
WINPR_IMAGE_CMP_IGNORE_DEPTH | WINPR_IMAGE_CMP_IGNORE_ALPHA |
WINPR_IMAGE_CMP_FUZZY);
}
static BOOL test_equal_to(const wImage* bmp, const char* name, UINT32 format)
{
BOOL rc = FALSE;
wImage* cmp = winpr_image_new();
if (!cmp)
goto fail;
char path[MAX_PATH] = WINPR_C_ARRAY_INIT;
(void)_snprintf(path, sizeof(path), "%s.%s", name, winpr_image_format_extension(format));
const int cmpSize = winpr_image_read(cmp, path);
if (cmpSize <= 0)
{
(void)fprintf(stderr, "[%s] winpr_image_read failed for %s", __func__, path);
goto fail;
}
rc = test_image_equal(bmp, cmp);
if (!rc)
(void)fprintf(stderr, "[%s] winpr_image_eqal failed", __func__);
fail:
winpr_image_free(cmp, TRUE);
return rc;
}
static BOOL test_equal(void)
{
BOOL rc = FALSE;
wImage* bmp = winpr_image_new();
if (!bmp)
goto fail;
char path[MAX_PATH] = WINPR_C_ARRAY_INIT;
(void)_snprintf(path, sizeof(path), "%s.bmp", test_src_filename);
PathCchConvertStyleA(path, sizeof(path), PATH_STYLE_NATIVE);
const int bmpSize = winpr_image_read(bmp, path);
if (bmpSize <= 0)
{
(void)fprintf(stderr, "[%s] winpr_image_read failed for %s", __func__, path);
goto fail;
}
for (UINT32 x = 0; x < UINT8_MAX; x++)
{
if (!winpr_image_format_is_supported(x))
continue;
if (!test_equal_to(bmp, test_src_filename, x))
goto fail;
}
rc = TRUE;
fail:
winpr_image_free(bmp, TRUE);
return rc;
}
static BOOL test_read_write_compare(const char* tname, const char* tdst, UINT32 format)
{
BOOL rc = FALSE;
wImage* bmp1 = winpr_image_new();
wImage* bmp2 = winpr_image_new();
wImage* bmp3 = winpr_image_new();
if (!bmp1 || !bmp2 || !bmp3)
goto fail;
char spath[MAX_PATH] = WINPR_C_ARRAY_INIT;
char dpath[MAX_PATH] = WINPR_C_ARRAY_INIT;
char bpath1[MAX_PATH] = WINPR_C_ARRAY_INIT;
char bpath2[MAX_PATH] = WINPR_C_ARRAY_INIT;
(void)_snprintf(spath, sizeof(spath), "%s.%s", tname, winpr_image_format_extension(format));
(void)_snprintf(dpath, sizeof(dpath), "%s.%s", tdst, winpr_image_format_extension(format));
(void)_snprintf(bpath1, sizeof(bpath1), "%s.src.%s", dpath,
winpr_image_format_extension(WINPR_IMAGE_BITMAP));
(void)_snprintf(bpath2, sizeof(bpath2), "%s.bin.%s", dpath,
winpr_image_format_extension(WINPR_IMAGE_BITMAP));
PathCchConvertStyleA(spath, sizeof(spath), PATH_STYLE_NATIVE);
PathCchConvertStyleA(dpath, sizeof(dpath), PATH_STYLE_NATIVE);
PathCchConvertStyleA(bpath1, sizeof(bpath1), PATH_STYLE_NATIVE);
PathCchConvertStyleA(bpath2, sizeof(bpath2), PATH_STYLE_NATIVE);
const int bmpRSize = winpr_image_read(bmp1, spath);
if (bmpRSize <= 0)
{
(void)fprintf(stderr, "[%s] winpr_image_read failed for %s", __func__, spath);
goto fail;
}
const int bmpWSize = winpr_image_write(bmp1, dpath);
if (bmpWSize <= 0)
{
(void)fprintf(stderr, "[%s] winpr_image_write failed for %s", __func__, dpath);
goto fail;
}
const int bmp2RSize = winpr_image_read(bmp2, dpath);
if (bmp2RSize <= 0)
{
(void)fprintf(stderr, "[%s] winpr_image_read failed for %s", __func__, dpath);
goto fail;
}
const int bmpSrcWSize = winpr_image_write_ex(bmp1, WINPR_IMAGE_BITMAP, bpath1);
if (bmpSrcWSize <= 0)
{
(void)fprintf(stderr, "[%s] winpr_image_write_ex failed for %s", __func__, bpath1);
goto fail;
}
/* write a bitmap and read it back.
* this tests if we have the proper internal format */
const int bmpBinWSize = winpr_image_write_ex(bmp2, WINPR_IMAGE_BITMAP, bpath2);
if (bmpBinWSize <= 0)
{
(void)fprintf(stderr, "[%s] winpr_image_write_ex failed for %s", __func__, bpath2);
goto fail;
}
const int bmp3RSize = winpr_image_read(bmp3, bpath2);
if (bmp3RSize <= 0)
{
(void)fprintf(stderr, "[%s] winpr_image_read failed for %s", __func__, bpath2);
goto fail;
}
if (!winpr_image_equal(bmp1, bmp2,
WINPR_IMAGE_CMP_IGNORE_DEPTH | WINPR_IMAGE_CMP_IGNORE_ALPHA |
WINPR_IMAGE_CMP_FUZZY))
{
(void)fprintf(stderr, "[%s] winpr_image_eqal failed bmp1 bmp2", __func__);
goto fail;
}
rc = winpr_image_equal(bmp3, bmp2,
WINPR_IMAGE_CMP_IGNORE_DEPTH | WINPR_IMAGE_CMP_IGNORE_ALPHA |
WINPR_IMAGE_CMP_FUZZY);
if (!rc)
(void)fprintf(stderr, "[%s] winpr_image_eqal failed bmp3 bmp2", __func__);
fail:
winpr_image_free(bmp1, TRUE);
winpr_image_free(bmp2, TRUE);
winpr_image_free(bmp3, TRUE);
return rc;
}
static BOOL test_read_write(void)
{
BOOL rc = TRUE;
for (UINT32 x = 0; x < UINT8_MAX; x++)
{
if (!winpr_image_format_is_supported(x))
continue;
if (!test_read_write_compare(test_src_filename, test_bin_filename, x))
rc = FALSE;
}
return rc;
}
static BOOL test_load_file(const char* name)
{
BOOL rc = FALSE;
wImage* image = winpr_image_new();
if (!image || !name)
goto fail;
const int res = winpr_image_read(image, name);
rc = (res > 0);
fail:
winpr_image_free(image, TRUE);
return rc;
}
static BOOL test_load(void)
{
const char* names[] = {
"rgb.16a.bmp", "rgb.16a.nocolor.bmp", "rgb.16.bmp", "rgb.16.nocolor.bmp",
"rgb.16x.bmp", "rgb.16x.nocolor.bmp", "rgb.24.bmp", "rgb.24.nocolor.bmp",
"rgb.32.bmp", "rgb.32.nocolor.bmp", "rgb.32x.bmp", "rgb.32x.nocolor.bmp",
"rgb.bmp"
};
for (size_t x = 0; x < ARRAYSIZE(names); x++)
{
const char* name = names[x];
char* fname = GetCombinedPath(TEST_SOURCE_PATH, name);
const BOOL res = test_load_file(fname);
free(fname);
if (!res)
return FALSE;
}
return TRUE;
}
int TestImage(int argc, char* argv[])
{
int rc = 0;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
if (!test_equal())
rc -= 1;
if (!test_read_write())
rc -= 2;
if (!test_load())
rc -= 4;
return rc;
}

View File

@@ -0,0 +1,160 @@
#include <winpr/crt.h>
#include <winpr/ini.h>
static const char TEST_INI_01[] = "; This is a sample .ini config file\n"
"\n"
"[first_section]\n"
"one = 1\n"
"five = 5\n"
"animal = BIRD\n"
"\n"
"[second_section]\n"
"path = \"/usr/local/bin\"\n"
"URL = \"http://www.example.com/~username\"\n"
"\n";
static const char TEST_INI_02[] = "[FreeRDS]\n"
"prefix=\"/usr/local\"\n"
"bindir=\"bin\"\n"
"sbindir=\"sbin\"\n"
"libdir=\"lib\"\n"
"datarootdir=\"share\"\n"
"localstatedir=\"var\"\n"
"sysconfdir=\"etc\"\n"
"\n";
static const char TEST_INI_03[] = "[FreeRDS]\n"
"prefix=\"/usr/local\"\n"
"bindir=\"bin\"\n"
"# some illegal string\n"
"sbindir=\"sbin\"\n"
"libdir=\"lib\"\n"
"invalid key-value pair\n"
"datarootdir=\"share\"\n"
"localstatedir=\"var\"\n"
"sysconfdir=\"etc\"\n"
"\n";
int TestIni(int argc, char* argv[])
{
int rc = -1;
size_t nKeys = 0;
size_t nSections = 0;
UINT32 iValue = 0;
wIniFile* ini = nullptr;
const char* sValue = nullptr;
char** keyNames = nullptr;
char** sectionNames = nullptr;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
/* First Sample */
ini = IniFile_New();
if (!ini)
goto fail;
if (IniFile_ReadBuffer(ini, TEST_INI_01) < 0)
goto fail;
free((void*)sectionNames);
sectionNames = IniFile_GetSectionNames(ini, &nSections);
if (!sectionNames && (nSections > 0))
goto fail;
for (size_t i = 0; i < nSections; i++)
{
free((void*)keyNames);
keyNames = IniFile_GetSectionKeyNames(ini, sectionNames[i], &nKeys);
printf("[%s]\n", sectionNames[i]);
if (!keyNames && (nKeys > 0))
goto fail;
for (size_t j = 0; j < nKeys; j++)
{
sValue = IniFile_GetKeyValueString(ini, sectionNames[i], keyNames[j]);
printf("%s = %s\n", keyNames[j], sValue);
}
}
iValue = IniFile_GetKeyValueInt(ini, "first_section", "one");
if (iValue != 1)
{
printf("IniFile_GetKeyValueInt failure\n");
goto fail;
}
iValue = IniFile_GetKeyValueInt(ini, "first_section", "five");
if (iValue != 5)
{
printf("IniFile_GetKeyValueInt failure\n");
goto fail;
}
sValue = IniFile_GetKeyValueString(ini, "first_section", "animal");
if (strcmp(sValue, "BIRD") != 0)
{
printf("IniFile_GetKeyValueString failure\n");
goto fail;
}
sValue = IniFile_GetKeyValueString(ini, "second_section", "path");
if (strcmp(sValue, "/usr/local/bin") != 0)
{
printf("IniFile_GetKeyValueString failure\n");
goto fail;
}
sValue = IniFile_GetKeyValueString(ini, "second_section", "URL");
if (strcmp(sValue, "http://www.example.com/~username") != 0)
{
printf("IniFile_GetKeyValueString failure\n");
goto fail;
}
IniFile_Free(ini);
/* Second Sample */
ini = IniFile_New();
if (!ini)
goto fail;
if (IniFile_ReadBuffer(ini, TEST_INI_02) < 0)
goto fail;
free((void*)sectionNames);
sectionNames = IniFile_GetSectionNames(ini, &nSections);
if (!sectionNames && (nSections > 0))
goto fail;
for (size_t i = 0; i < nSections; i++)
{
free((void*)keyNames);
keyNames = IniFile_GetSectionKeyNames(ini, sectionNames[i], &nKeys);
printf("[%s]\n", sectionNames[i]);
if (!keyNames && (nKeys > 0))
goto fail;
for (size_t j = 0; j < nKeys; j++)
{
sValue = IniFile_GetKeyValueString(ini, sectionNames[i], keyNames[j]);
printf("%s = %s\n", keyNames[j], sValue);
}
}
IniFile_Free(ini);
/* Third sample - invalid input */
ini = IniFile_New();
if (IniFile_ReadBuffer(ini, TEST_INI_03) != -1)
goto fail;
rc = 0;
fail:
free((void*)keyNames);
free((void*)sectionNames);
IniFile_Free(ini);
return rc;
}

View File

@@ -0,0 +1,135 @@
#include <winpr/crt.h>
#include <winpr/tchar.h>
#include <winpr/collections.h>
int TestLinkedList(int argc, char* argv[])
{
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
wLinkedList* list = LinkedList_New();
if (!list)
return -1;
if (!LinkedList_AddFirst(list, (void*)(size_t)1))
return -1;
if (!LinkedList_AddLast(list, (void*)(size_t)2))
return -1;
if (!LinkedList_AddLast(list, (void*)(size_t)3))
return -1;
size_t count = LinkedList_Count(list);
if (count != 3)
{
printf("LinkedList_Count: expected 3, actual: %" PRIuz "\n", count);
return -1;
}
LinkedList_Enumerator_Reset(list);
while (LinkedList_Enumerator_MoveNext(list))
{
printf("\t%p\n", LinkedList_Enumerator_Current(list));
}
printf("\n");
printf("LinkedList First: %p Last: %p\n", LinkedList_First(list), LinkedList_Last(list));
LinkedList_RemoveFirst(list);
LinkedList_RemoveLast(list);
count = LinkedList_Count(list);
if (count != 1)
{
printf("LinkedList_Count: expected 1, actual: %" PRIuz "\n", count);
return -1;
}
LinkedList_Enumerator_Reset(list);
while (LinkedList_Enumerator_MoveNext(list))
{
printf("\t%p\n", LinkedList_Enumerator_Current(list));
}
printf("\n");
printf("LinkedList First: %p Last: %p\n", LinkedList_First(list), LinkedList_Last(list));
LinkedList_RemoveFirst(list);
LinkedList_RemoveLast(list);
count = LinkedList_Count(list);
if (count != 0)
{
printf("LinkedList_Count: expected 0, actual: %" PRIuz "\n", count);
return -1;
}
if (!LinkedList_AddFirst(list, (void*)(size_t)4))
return -1;
if (!LinkedList_AddLast(list, (void*)(size_t)5))
return -1;
if (!LinkedList_AddLast(list, (void*)(size_t)6))
return -1;
count = LinkedList_Count(list);
if (count != 3)
{
printf("LinkedList_Count: expected 3, actual: %" PRIuz "\n", count);
return -1;
}
LinkedList_Enumerator_Reset(list);
while (LinkedList_Enumerator_MoveNext(list))
{
printf("\t%p\n", LinkedList_Enumerator_Current(list));
}
printf("\n");
printf("LinkedList First: %p Last: %p\n", LinkedList_First(list), LinkedList_Last(list));
if (!LinkedList_Remove(list, (void*)(size_t)5))
return -1;
LinkedList_Enumerator_Reset(list);
while (LinkedList_Enumerator_MoveNext(list))
{
printf("\t%p\n", LinkedList_Enumerator_Current(list));
}
printf("\n");
printf("LinkedList First: %p Last: %p\n", LinkedList_First(list), LinkedList_Last(list));
LinkedList_Free(list);
/* Test enumerator robustness */
/* enumerator on an empty list */
list = LinkedList_New();
if (!list)
return -1;
LinkedList_Enumerator_Reset(list);
while (LinkedList_Enumerator_MoveNext(list))
{
printf("\terror: %p\n", LinkedList_Enumerator_Current(list));
}
printf("\n");
LinkedList_Free(list);
/* Use an enumerator without reset */
list = LinkedList_New();
if (!list)
return -1;
if (!LinkedList_AddFirst(list, (void*)(size_t)4))
return -1;
if (!LinkedList_AddLast(list, (void*)(size_t)5))
return -1;
if (!LinkedList_AddLast(list, (void*)(size_t)6))
return -1;
while (LinkedList_Enumerator_MoveNext(list))
{
printf("\t%p\n", LinkedList_Enumerator_Current(list));
}
printf("\n");
LinkedList_Free(list);
return 0;
}

View File

@@ -0,0 +1,178 @@
#include <winpr/crt.h>
#include <winpr/tchar.h>
#include <winpr/collections.h>
static char* key1 = "key1";
static char* key2 = "key2";
static char* key3 = "key3";
static char* val1 = "val1";
static char* val2 = "val2";
static char* val3 = "val3";
int TestListDictionary(int argc, char* argv[])
{
size_t count = 0;
char* value = nullptr;
wListDictionary* list = nullptr;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
list = ListDictionary_New(TRUE);
if (!list)
return -1;
if (!ListDictionary_Add(list, key1, val1) || !ListDictionary_Add(list, key2, val2) ||
!ListDictionary_Add(list, key3, val3))
return -1;
count = ListDictionary_Count(list);
if (count != 3)
{
printf("ListDictionary_Count: Expected : 3, Actual: %" PRIuz "\n", count);
return -1;
}
ListDictionary_Remove(list, key2);
count = ListDictionary_Count(list);
if (count != 2)
{
printf("ListDictionary_Count: Expected : 2, Actual: %" PRIuz "\n", count);
return -1;
}
ListDictionary_Remove(list, key3);
count = ListDictionary_Count(list);
if (count != 1)
{
printf("ListDictionary_Count: Expected : 1, Actual: %" PRIuz "\n", count);
return -1;
}
ListDictionary_Remove(list, key1);
count = ListDictionary_Count(list);
if (count != 0)
{
printf("ListDictionary_Count: Expected : 0, Actual: %" PRIuz "\n", count);
return -1;
}
if (!ListDictionary_Add(list, key1, val1) || !ListDictionary_Add(list, key2, val2) ||
!ListDictionary_Add(list, key3, val3))
return -1;
count = ListDictionary_Count(list);
if (count != 3)
{
printf("ListDictionary_Count: Expected : 3, Actual: %" PRIuz "\n", count);
return -1;
}
value = (char*)ListDictionary_GetItemValue(list, key1);
if (strcmp(value, val1) != 0)
{
printf("ListDictionary_GetItemValue: Expected : %" PRIuz ", Actual: %" PRIuz "\n",
(size_t)val1, (size_t)value);
return -1;
}
value = (char*)ListDictionary_GetItemValue(list, key2);
if (strcmp(value, val2) != 0)
{
printf("ListDictionary_GetItemValue: Expected : %" PRIuz ", Actual: %" PRIuz "\n",
(size_t)val2, (size_t)value);
return -1;
}
value = (char*)ListDictionary_GetItemValue(list, key3);
if (strcmp(value, val3) != 0)
{
printf("ListDictionary_GetItemValue: Expected : %" PRIuz ", Actual: %" PRIuz "\n",
(size_t)val3, (size_t)value);
return -1;
}
ListDictionary_SetItemValue(list, key2, "apple");
value = (char*)ListDictionary_GetItemValue(list, key2);
if (strcmp(value, "apple") != 0)
{
printf("ListDictionary_GetItemValue: Expected : %s, Actual: %s\n", "apple", value);
return -1;
}
if (!ListDictionary_Contains(list, key2))
{
printf("ListDictionary_Contains: Expected : TRUE, Actual: FALSE\n");
return -1;
}
if (!ListDictionary_Take(list, key2))
{
printf("ListDictionary_Remove: Expected : TRUE, Actual: FALSE\n");
return -1;
}
if (ListDictionary_Take(list, key2))
{
printf("ListDictionary_Remove: Expected : FALSE, Actual: TRUE\n");
return -1;
}
value = ListDictionary_Take_Head(list);
count = ListDictionary_Count(list);
if ((strncmp(value, val1, 4) != 0) || (count != 1))
{
printf("ListDictionary_Remove_Head: Expected : %s, Actual: %s Count: %" PRIuz "\n", val1,
value, count);
return -1;
}
value = ListDictionary_Take_Head(list);
count = ListDictionary_Count(list);
if ((strncmp(value, val3, 4) != 0) || (count != 0))
{
printf("ListDictionary_Remove_Head: Expected : %s, Actual: %s Count: %" PRIuz "\n", val3,
value, count);
return -1;
}
value = ListDictionary_Take_Head(list);
if (value)
{
printf("ListDictionary_Remove_Head: Expected : (null), Actual: %s\n", value);
return -1;
}
if (!ListDictionary_Add(list, key1, val1) || !ListDictionary_Add(list, key2, val2) ||
!ListDictionary_Add(list, key3, val3))
return -1;
ListDictionary_Clear(list);
count = ListDictionary_Count(list);
if (count != 0)
{
printf("ListDictionary_Count: Expected : 0, Actual: %" PRIuz "\n", count);
return -1;
}
ListDictionary_Free(list);
return 0;
}

View File

@@ -0,0 +1,105 @@
#include <winpr/crt.h>
#include <winpr/thread.h>
#include <winpr/collections.h>
static DWORD WINAPI message_echo_pipe_client_thread(LPVOID arg)
{
int index = 0;
wMessagePipe* pipe = (wMessagePipe*)arg;
while (index < 100)
{
wMessage message = WINPR_C_ARRAY_INIT;
int count = -1;
if (!MessageQueue_Post(pipe->In, nullptr, 0, (void*)(size_t)index, nullptr))
break;
if (!MessageQueue_Wait(pipe->Out))
break;
if (!MessageQueue_Peek(pipe->Out, &message, TRUE))
break;
if (message.id == WMQ_QUIT)
break;
count = (int)(size_t)message.wParam;
if (count != index)
printf("Echo count mismatch: Actual: %d, Expected: %d\n", count, index);
index++;
}
MessageQueue_PostQuit(pipe->In, 0);
return 0;
}
static DWORD WINAPI message_echo_pipe_server_thread(LPVOID arg)
{
wMessage message = WINPR_C_ARRAY_INIT;
wMessagePipe* pipe = (wMessagePipe*)arg;
while (MessageQueue_Wait(pipe->In))
{
if (MessageQueue_Peek(pipe->In, &message, TRUE))
{
if (message.id == WMQ_QUIT)
break;
if (!MessageQueue_Dispatch(pipe->Out, &message))
break;
}
}
return 0;
}
int TestMessagePipe(int argc, char* argv[])
{
HANDLE ClientThread = nullptr;
HANDLE ServerThread = nullptr;
wMessagePipe* EchoPipe = nullptr;
int ret = 1;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
if (!(EchoPipe = MessagePipe_New()))
{
printf("failed to create message pipe\n");
goto out;
}
if (!(ClientThread = CreateThread(nullptr, 0, message_echo_pipe_client_thread, (void*)EchoPipe,
0, nullptr)))
{
printf("failed to create client thread\n");
goto out;
}
if (!(ServerThread = CreateThread(nullptr, 0, message_echo_pipe_server_thread, (void*)EchoPipe,
0, nullptr)))
{
printf("failed to create server thread\n");
goto out;
}
(void)WaitForSingleObject(ClientThread, INFINITE);
(void)WaitForSingleObject(ServerThread, INFINITE);
ret = 0;
out:
if (EchoPipe)
MessagePipe_Free(EchoPipe);
if (ClientThread)
(void)CloseHandle(ClientThread);
if (ServerThread)
(void)CloseHandle(ServerThread);
return ret;
}

View File

@@ -0,0 +1,192 @@
#include <winpr/crt.h>
#include <winpr/thread.h>
#include <winpr/collections.h>
static DWORD WINAPI message_queue_consumer_thread(LPVOID arg)
{
wMessage message = WINPR_C_ARRAY_INIT;
wMessageQueue* queue = (wMessageQueue*)arg;
while (MessageQueue_Wait(queue))
{
if (MessageQueue_Peek(queue, &message, TRUE))
{
if (message.id == WMQ_QUIT)
break;
printf("Message.Type: %" PRIu32 "\n", message.id);
}
}
return 0;
}
static bool wrap_test(bool (*fkt)(wMessageQueue* queue))
{
wMessageQueue* queue = MessageQueue_New(nullptr);
if (!queue)
return false;
WINPR_ASSERT(fkt);
const bool rc = fkt(queue);
MessageQueue_Free(queue);
return rc;
}
static bool check(const wMessage* message, size_t pos)
{
if (!message)
return false;
if (message->context != (void*)13)
return false;
if (message->id != pos)
return false;
if (message->wParam != (void*)23)
return false;
if (message->lParam != (void*)42)
return false;
if (message->Free != nullptr)
return false;
return true;
}
static bool append(wMessageQueue* queue, size_t pos)
{
const wMessage message = { .context = (void*)13,
.id = WINPR_ASSERTING_INT_CAST(DWORD, pos),
.wParam = (void*)23,
.lParam = (void*)42,
.Free = nullptr };
return MessageQueue_Dispatch(queue, &message);
}
static bool fill_capcity(wMessageQueue* queue, size_t* pos)
{
WINPR_ASSERT(pos);
size_t cpos = *pos;
const size_t capacity = MessageQueue_Capacity(queue);
while (MessageQueue_Size(queue) < capacity)
{
if (!append(queue, cpos++))
return false;
}
*pos = cpos;
return true;
}
static bool drain(wMessageQueue* queue, size_t expect)
{
wMessage message = WINPR_C_ARRAY_INIT;
if (MessageQueue_Get(queue, &message) < 0)
return false;
if (!check(&message, expect))
return false;
return true;
}
static bool drain_capcity(wMessageQueue* queue, size_t remain, size_t* pos)
{
WINPR_ASSERT(pos);
size_t cpos = *pos;
while (MessageQueue_Size(queue) > remain)
{
if (!drain(queue, cpos++))
return false;
}
*pos = cpos;
return true;
}
static bool test_growth_move(wMessageQueue* queue, bool big)
{
WINPR_ASSERT(queue);
const size_t cap = MessageQueue_Capacity(queue);
if (cap < 4)
return false;
size_t wpos = 0;
size_t rpos = 0;
if (!fill_capcity(queue, &wpos))
return false;
if (big)
{
if (!append(queue, wpos++))
return false;
}
if (!drain_capcity(queue, 3, &rpos))
return false;
if (!fill_capcity(queue, &wpos))
return false;
if (!append(queue, wpos++))
return false;
return drain_capcity(queue, 0, &rpos);
}
static bool test_growth_big_move(wMessageQueue* queue)
{
return test_growth_move(queue, true);
}
static bool test_growth_small_move(wMessageQueue* queue)
{
return test_growth_move(queue, false);
}
static bool test_operation_run(wMessageQueue* queue, HANDLE thread)
{
WINPR_ASSERT(queue);
WINPR_ASSERT(thread);
if (!MessageQueue_Post(queue, nullptr, 123, nullptr, nullptr))
return false;
if (!MessageQueue_Post(queue, nullptr, 456, nullptr, nullptr))
return false;
if (!MessageQueue_Post(queue, nullptr, 789, nullptr, nullptr))
return false;
if (!MessageQueue_PostQuit(queue, 0))
return false;
const DWORD status = WaitForSingleObject(thread, INFINITE);
return (status == WAIT_OBJECT_0);
}
static bool test_operation(wMessageQueue* queue)
{
WINPR_ASSERT(queue);
HANDLE thread = CreateThread(nullptr, 0, message_queue_consumer_thread, queue, 0, nullptr);
if (!thread)
{
printf("failed to create thread\n");
return false;
}
const bool rc = test_operation_run(queue, thread);
if (!CloseHandle(thread))
return false;
return rc;
}
int TestMessageQueue(WINPR_ATTR_UNUSED int argc, WINPR_ATTR_UNUSED char* argv[])
{
if (!wrap_test(test_growth_big_move))
return -1;
if (!wrap_test(test_growth_small_move))
return -2;
if (!wrap_test(test_operation))
return -3;
return 0;
}

View File

@@ -0,0 +1,402 @@
#include <math.h>
#include <winpr/crt.h>
#include <winpr/tchar.h>
#include <winpr/print.h>
/**
* C Programming/C Reference/stdio.h/printf:
* http://en.wikibooks.org/wiki/C_Programming/C_Reference/stdio.h/printf
*
* C Programming/Procedures and functions/printf:
* http://en.wikibooks.org/wiki/C_Programming/Procedures_and_functions/printf
*
* C Tutorial printf, Format Specifiers, Format Conversions and Formatted Output:
* http://www.codingunit.com/printf-format-specifiers-format-conversions-and-formatted-output
*/
#define _printf printf // NOLINT(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
static BOOL test_bin_tohex_string(void)
{
BOOL rc = FALSE;
{
const BYTE binbuffer[33] = WINPR_C_ARRAY_INIT;
const char empty[33] = WINPR_C_ARRAY_INIT;
char strbuffer[33] = WINPR_C_ARRAY_INIT;
size_t len = winpr_BinToHexStringBuffer(nullptr, sizeof(binbuffer), strbuffer,
sizeof(strbuffer), TRUE);
if (len != 0)
goto fail;
if (memcmp(strbuffer, empty, sizeof(strbuffer)) != 0)
goto fail;
len = winpr_BinToHexStringBuffer(binbuffer, 0, strbuffer, sizeof(strbuffer), TRUE);
if (len != 0)
goto fail;
if (memcmp(strbuffer, empty, sizeof(strbuffer)) != 0)
goto fail;
len = winpr_BinToHexStringBuffer(binbuffer, sizeof(binbuffer), nullptr, sizeof(strbuffer),
TRUE);
if (len != 0)
goto fail;
if (memcmp(strbuffer, empty, sizeof(strbuffer)) != 0)
goto fail;
len = winpr_BinToHexStringBuffer(binbuffer, sizeof(binbuffer), strbuffer, 0, TRUE);
if (len != 0)
goto fail;
if (memcmp(strbuffer, empty, sizeof(strbuffer)) != 0)
goto fail;
len = winpr_BinToHexStringBuffer(binbuffer, 0, strbuffer, 0, TRUE);
if (len != 0)
goto fail;
if (memcmp(strbuffer, empty, sizeof(strbuffer)) != 0)
goto fail;
len = winpr_BinToHexStringBuffer(binbuffer, sizeof(binbuffer), nullptr, 0, TRUE);
if (len != 0)
goto fail;
if (memcmp(strbuffer, empty, sizeof(strbuffer)) != 0)
goto fail;
len = winpr_BinToHexStringBuffer(nullptr, sizeof(binbuffer), strbuffer, 0, TRUE);
if (len != 0)
goto fail;
if (memcmp(strbuffer, empty, sizeof(strbuffer)) != 0)
goto fail;
len = winpr_BinToHexStringBuffer(binbuffer, 0, nullptr, 0, TRUE);
if (len != 0)
goto fail;
if (memcmp(strbuffer, empty, sizeof(strbuffer)) != 0)
goto fail;
len = winpr_BinToHexStringBuffer(nullptr, 0, nullptr, 0, TRUE);
if (len != 0)
goto fail;
if (memcmp(strbuffer, empty, sizeof(strbuffer)) != 0)
goto fail;
len = winpr_BinToHexStringBuffer(binbuffer, 0, nullptr, 0, FALSE);
if (len != 0)
goto fail;
if (memcmp(strbuffer, empty, sizeof(strbuffer)) != 0)
goto fail;
}
{
const BYTE binbuffer1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 };
const char strbuffer1[] = "0102030405060708090A0B0C0D0E0F1011";
const char strbuffer1_space[] = "01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11";
char buffer[1024] = WINPR_C_ARRAY_INIT;
size_t len = winpr_BinToHexStringBuffer(binbuffer1, sizeof(binbuffer1), buffer,
sizeof(buffer), FALSE);
if (len != strnlen(strbuffer1, sizeof(strbuffer1)))
goto fail;
if (memcmp(strbuffer1, buffer, sizeof(strbuffer1)) != 0)
goto fail;
len = winpr_BinToHexStringBuffer(binbuffer1, sizeof(binbuffer1), buffer, sizeof(buffer),
TRUE);
if (len != strnlen(strbuffer1_space, sizeof(strbuffer1_space)))
goto fail;
if (memcmp(strbuffer1_space, buffer, sizeof(strbuffer1_space)) != 0)
goto fail;
}
{
const BYTE binbuffer1[] = { 0xF1, 0xe2, 0xD3, 0xc4, 0xB5, 0xA6, 0x97, 0x88, 0x79,
0x6A, 0x5b, 0x4C, 0x3d, 0x2E, 0x1f, 0x00, 0xfF };
const char strbuffer1[] = "F1E2D3C4B5A69788796A5B4C3D2E1F00FF";
const char strbuffer1_space[] = "F1 E2 D3 C4 B5 A6 97 88 79 6A 5B 4C 3D 2E 1F 00 FF";
char buffer[1024] = WINPR_C_ARRAY_INIT;
size_t len = winpr_BinToHexStringBuffer(binbuffer1, sizeof(binbuffer1), buffer,
sizeof(buffer), FALSE);
if (len != strnlen(strbuffer1, sizeof(strbuffer1)))
goto fail;
if (memcmp(strbuffer1, buffer, sizeof(strbuffer1)) != 0)
goto fail;
len = winpr_BinToHexStringBuffer(binbuffer1, sizeof(binbuffer1), buffer, sizeof(buffer),
TRUE);
if (len != strnlen(strbuffer1_space, sizeof(strbuffer1_space)))
goto fail;
if (memcmp(strbuffer1_space, buffer, sizeof(strbuffer1_space)) != 0)
goto fail;
}
{
}
rc = TRUE;
fail:
return rc;
}
static BOOL test_bin_tohex_string_alloc(void)
{
BOOL rc = FALSE;
char* str = nullptr;
{
const BYTE binbuffer[33] = WINPR_C_ARRAY_INIT;
str = winpr_BinToHexString(nullptr, sizeof(binbuffer), TRUE);
if (str)
goto fail;
str = winpr_BinToHexString(binbuffer, 0, TRUE);
if (str)
goto fail;
str = winpr_BinToHexString(binbuffer, 0, FALSE);
if (str)
goto fail;
str = winpr_BinToHexString(nullptr, sizeof(binbuffer), FALSE);
if (str)
goto fail;
}
{
const BYTE binbuffer1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 };
const char strbuffer1[] = "0102030405060708090A0B0C0D0E0F1011";
const char strbuffer1_space[] = "01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11";
str = winpr_BinToHexString(binbuffer1, sizeof(binbuffer1), FALSE);
if (!str)
goto fail;
if (memcmp(strbuffer1, str, sizeof(strbuffer1)) != 0)
goto fail;
free(str);
str = winpr_BinToHexString(binbuffer1, sizeof(binbuffer1), TRUE);
if (!str)
goto fail;
if (memcmp(strbuffer1_space, str, sizeof(strbuffer1_space)) != 0)
goto fail;
free(str);
str = nullptr;
}
{
const BYTE binbuffer1[] = { 0xF1, 0xe2, 0xD3, 0xc4, 0xB5, 0xA6, 0x97, 0x88, 0x79,
0x6A, 0x5b, 0x4C, 0x3d, 0x2E, 0x1f, 0x00, 0xfF };
const char strbuffer1[] = "F1E2D3C4B5A69788796A5B4C3D2E1F00FF";
const char strbuffer1_space[] = "F1 E2 D3 C4 B5 A6 97 88 79 6A 5B 4C 3D 2E 1F 00 FF";
str = winpr_BinToHexString(binbuffer1, sizeof(binbuffer1), FALSE);
if (!str)
goto fail;
if (memcmp(strbuffer1, str, sizeof(strbuffer1)) != 0)
goto fail;
free(str);
str = winpr_BinToHexString(binbuffer1, sizeof(binbuffer1), TRUE);
if (!str)
goto fail;
if (memcmp(strbuffer1_space, str, sizeof(strbuffer1_space)) != 0)
goto fail;
free(str);
str = nullptr;
}
rc = TRUE;
fail:
free(str);
return rc;
}
static BOOL test_hex_string_to_bin(void)
{
BOOL rc = FALSE;
{
const char stringbuffer[] = "123456789ABCDEFabcdef";
const BYTE empty[1024] = WINPR_C_ARRAY_INIT;
BYTE buffer[1024] = WINPR_C_ARRAY_INIT;
size_t len = winpr_HexStringToBinBuffer(nullptr, 0, nullptr, 0);
if (len != 0)
goto fail;
if (memcmp(buffer, empty, sizeof(buffer)) != 0)
goto fail;
len = winpr_HexStringToBinBuffer(nullptr, sizeof(stringbuffer), buffer, sizeof(buffer));
if (len != 0)
goto fail;
if (memcmp(buffer, empty, sizeof(buffer)) != 0)
goto fail;
len = winpr_HexStringToBinBuffer(stringbuffer, 0, buffer, sizeof(buffer));
if (len != 0)
goto fail;
if (memcmp(buffer, empty, sizeof(buffer)) != 0)
goto fail;
len =
winpr_HexStringToBinBuffer(stringbuffer, sizeof(stringbuffer), nullptr, sizeof(buffer));
if (len != 0)
goto fail;
if (memcmp(buffer, empty, sizeof(buffer)) != 0)
goto fail;
len = winpr_HexStringToBinBuffer(stringbuffer, sizeof(stringbuffer), buffer, 0);
if (len != 0)
goto fail;
if (memcmp(buffer, empty, sizeof(buffer)) != 0)
goto fail;
}
{
const char stringbuffer[] = "123456789ABCDEF1abcdef";
const BYTE expected[] = {
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf1, 0xab, 0xcd, 0xef
};
BYTE buffer[32] = WINPR_C_ARRAY_INIT;
size_t len =
winpr_HexStringToBinBuffer(stringbuffer, sizeof(stringbuffer), buffer, sizeof(buffer));
if (len != sizeof(expected))
goto fail;
if (memcmp(buffer, expected, sizeof(expected)) != 0)
goto fail;
len = winpr_HexStringToBinBuffer(stringbuffer, sizeof(stringbuffer), buffer,
sizeof(expected) / 2);
if (len != sizeof(expected) / 2)
goto fail;
if (memcmp(buffer, expected, sizeof(expected) / 2) != 0)
goto fail;
}
{
const char stringbuffer[] = "12 34 56 78 9A BC DE F1 ab cd ef";
const BYTE expected[] = {
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf1, 0xab, 0xcd, 0xef
};
BYTE buffer[1024] = WINPR_C_ARRAY_INIT;
size_t len =
winpr_HexStringToBinBuffer(stringbuffer, sizeof(stringbuffer), buffer, sizeof(buffer));
if (len != sizeof(expected))
goto fail;
if (memcmp(buffer, expected, sizeof(expected)) != 0)
goto fail;
len = winpr_HexStringToBinBuffer(stringbuffer, sizeof(stringbuffer), buffer,
sizeof(expected) / 2);
if (len != sizeof(expected) / 2)
goto fail;
if (memcmp(buffer, expected, sizeof(expected) / 2) != 0)
goto fail;
}
{
const char stringbuffer[] = "123456789ABCDEF1abcdef9";
const BYTE expected[] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
0xde, 0xf1, 0xab, 0xcd, 0xef, 0x09 };
BYTE buffer[1024] = WINPR_C_ARRAY_INIT;
size_t len =
winpr_HexStringToBinBuffer(stringbuffer, sizeof(stringbuffer), buffer, sizeof(buffer));
if (len != sizeof(expected))
goto fail;
if (memcmp(buffer, expected, sizeof(expected)) != 0)
goto fail;
len = winpr_HexStringToBinBuffer(stringbuffer, sizeof(stringbuffer), buffer,
sizeof(expected) / 2);
if (len != sizeof(expected) / 2)
goto fail;
if (memcmp(buffer, expected, sizeof(expected) / 2) != 0)
goto fail;
}
{
const char stringbuffer[] = "12 34 56 78 9A BC DE F1 ab cd ef 9";
const BYTE expected[] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
0xde, 0xf1, 0xab, 0xcd, 0xef, 0x09 };
BYTE buffer[1024] = WINPR_C_ARRAY_INIT;
size_t len =
winpr_HexStringToBinBuffer(stringbuffer, sizeof(stringbuffer), buffer, sizeof(buffer));
if (len != sizeof(expected))
goto fail;
if (memcmp(buffer, expected, sizeof(expected)) != 0)
goto fail;
len = winpr_HexStringToBinBuffer(stringbuffer, sizeof(stringbuffer), buffer,
sizeof(expected) / 2);
if (len != sizeof(expected) / 2)
goto fail;
if (memcmp(buffer, expected, sizeof(expected) / 2) != 0)
goto fail;
}
rc = TRUE;
fail:
return rc;
}
int TestPrint(int argc, char* argv[])
{
int a = 0;
int b = 0;
float c = NAN;
float d = NAN;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
/**
* 7
* 7
* 007
* 5.10
*/
a = 15;
b = a / 2;
_printf("%d\n", b);
_printf("%3d\n", b);
_printf("%03d\n", b);
c = 15.3f;
d = c / 3.0f;
_printf("%3.2f\n", d);
/**
* 0 -17.778
* 20 -6.667
* 40 04.444
* 60 15.556
* 80 26.667
* 100 37.778
* 120 48.889
* 140 60.000
* 160 71.111
* 180 82.222
* 200 93.333
* 220 104.444
* 240 115.556
* 260 126.667
* 280 137.778
* 300 148.889
*/
for (int a = 0; a <= 300; a = a + 20)
_printf("%3d %06.3f\n", a, (5.0 / 9.0) * (a - 32));
/**
* The color: blue
* First number: 12345
* Second number: 0025
* Third number: 1234
* Float number: 3.14
* Hexadecimal: ff
* Octal: 377
* Unsigned value: 150
* Just print the percentage sign %
*/
_printf("The color: %s\n", "blue");
_printf("First number: %d\n", 12345);
_printf("Second number: %04d\n", 25);
_printf("Third number: %i\n", 1234);
_printf("Float number: %3.2f\n", 3.14159);
_printf("Hexadecimal: %x/%X\n", 255, 255);
_printf("Octal: %o\n", 255);
_printf("Unsigned value: %u\n", 150);
_printf("Just print the percentage sign %%\n");
/**
* :Hello, world!:
* : Hello, world!:
* :Hello, wor:
* :Hello, world!:
* :Hello, world! :
* :Hello, world!:
* : Hello, wor:
* :Hello, wor :
*/
_printf(":%s:\n", "Hello, world!");
_printf(":%15s:\n", "Hello, world!");
_printf(":%.10s:\n", "Hello, world!");
_printf(":%-10s:\n", "Hello, world!");
_printf(":%-15s:\n", "Hello, world!");
_printf(":%.15s:\n", "Hello, world!");
_printf(":%15.10s:\n", "Hello, world!");
_printf(":%-15.10s:\n", "Hello, world!");
if (!test_bin_tohex_string())
return -1;
if (!test_bin_tohex_string_alloc())
return -1;
if (!test_hex_string_to_bin())
return -1;
return 0;
}

View File

@@ -0,0 +1,75 @@
#include <winpr/crt.h>
#include <winpr/thread.h>
#include <winpr/collections.h>
DEFINE_EVENT_BEGIN(MouseMotion)
int x;
int y;
DEFINE_EVENT_END(MouseMotion)
DEFINE_EVENT_BEGIN(MouseButton)
int x;
int y;
int flags;
int button;
DEFINE_EVENT_END(MouseButton)
static void MouseMotionEventHandler(void* context, const MouseMotionEventArgs* e)
{
printf("MouseMotionEvent: x: %d y: %d\n", e->x, e->y);
}
static void MouseButtonEventHandler(void* context, const MouseButtonEventArgs* e)
{
printf("MouseButtonEvent: x: %d y: %d flags: %d button: %d\n", e->x, e->y, e->flags, e->button);
}
static wEventType Node_Events[] = { DEFINE_EVENT_ENTRY(MouseMotion),
DEFINE_EVENT_ENTRY(MouseButton) };
#define NODE_EVENT_COUNT (sizeof(Node_Events) / sizeof(wEventType))
int TestPubSub(int argc, char* argv[])
{
wPubSub* node = nullptr;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
node = PubSub_New(TRUE);
if (!node)
return -1;
PubSub_AddEventTypes(node, Node_Events, NODE_EVENT_COUNT);
if (PubSub_SubscribeMouseMotion(node, MouseMotionEventHandler) < 0)
return -1;
if (PubSub_SubscribeMouseButton(node, MouseButtonEventHandler) < 0)
return -1;
/* Call Event Handler */
{
MouseMotionEventArgs e;
e.x = 64;
e.y = 128;
PubSub_OnMouseMotion(node, nullptr, &e);
}
{
MouseButtonEventArgs e;
e.x = 23;
e.y = 56;
e.flags = 7;
e.button = 1;
PubSub_OnMouseButton(node, nullptr, &e);
}
PubSub_Free(node);
return 0;
}

View File

@@ -0,0 +1,225 @@
#include <winpr/crt.h>
#include <winpr/tchar.h>
#include <winpr/collections.h>
static bool wrap_test(bool (*fkt)(wQueue* queue))
{
wQueue* queue = Queue_New(TRUE, -1, -1);
if (!queue)
return false;
WINPR_ASSERT(fkt);
const bool rc = fkt(queue);
Queue_Free(queue);
return rc;
}
static bool check(const void* ptr, size_t pos)
{
if (!ptr)
return false;
if (ptr != (void*)(pos + 23))
return false;
return true;
}
static bool append(wQueue* queue, size_t pos)
{
void* ptr = (void*)(pos + 23);
return Queue_Enqueue(queue, ptr);
}
static bool fill_capcity(wQueue* queue, size_t* pos)
{
WINPR_ASSERT(pos);
size_t cpos = *pos;
const size_t capacity = Queue_Capacity(queue);
while (Queue_Count(queue) < capacity)
{
if (!append(queue, cpos++))
return false;
}
*pos = cpos;
return true;
}
static bool drain(wQueue* queue, size_t expect)
{
void* ptr = Queue_Dequeue(queue);
return check(ptr, expect);
}
static bool drain_capcity(wQueue* queue, size_t remain, size_t* pos)
{
WINPR_ASSERT(pos);
size_t cpos = *pos;
while (Queue_Count(queue) > remain)
{
if (!drain(queue, cpos++))
return false;
}
*pos = cpos;
return true;
}
static bool test_growth_move(wQueue* queue, bool big)
{
WINPR_ASSERT(queue);
const size_t cap = Queue_Capacity(queue);
if (cap < 4)
return false;
size_t wpos = 0;
size_t rpos = 0;
if (!fill_capcity(queue, &wpos))
return false;
/* Ensure the (base) capacity is larger than the allocation step
* so a full copy of tail will not be possible */
if (big)
{
if (!append(queue, wpos++))
return false;
}
if (!drain_capcity(queue, 3, &rpos))
return false;
if (!fill_capcity(queue, &wpos))
return false;
if (!append(queue, wpos++))
return false;
return drain_capcity(queue, 0, &rpos);
}
static bool test_growth_big_move(wQueue* queue)
{
return test_growth_move(queue, true);
}
static bool test_growth_small_move(wQueue* queue)
{
return test_growth_move(queue, false);
}
static bool check_size(wQueue* queue, size_t expected)
{
WINPR_ASSERT(queue);
const size_t count = Queue_Count(queue);
printf("queue count: %" PRIuz "\n", count);
return (count == expected);
}
static bool enqueue(wQueue* queue, size_t val)
{
WINPR_ASSERT(queue);
void* ptr = (void*)(23 + val);
return Queue_Enqueue(queue, ptr);
}
static bool dequeue(wQueue* queue, size_t expected)
{
WINPR_ASSERT(queue);
const void* pexpect = (void*)(23 + expected);
void* ptr = Queue_Dequeue(queue);
return (pexpect == ptr);
}
static bool legacy_test(wQueue* queue)
{
WINPR_ASSERT(queue);
for (size_t index = 1; index <= 10; index++)
{
if (!enqueue(queue, index))
return false;
}
if (!check_size(queue, 10))
return false;
for (size_t index = 1; index <= 10; index++)
{
if (!dequeue(queue, index))
return false;
}
if (!check_size(queue, 0))
return false;
if (!enqueue(queue, 1))
return false;
if (!enqueue(queue, 2))
return false;
if (!enqueue(queue, 3))
return false;
if (!check_size(queue, 3))
return false;
if (!dequeue(queue, 1))
return false;
if (!dequeue(queue, 2))
return false;
if (!check_size(queue, 1))
return false;
if (!enqueue(queue, 4))
return false;
if (!enqueue(queue, 5))
return false;
if (!enqueue(queue, 6))
return false;
if (!check_size(queue, 4))
return false;
if (!dequeue(queue, 3))
return false;
if (!dequeue(queue, 4))
return false;
if (!dequeue(queue, 5))
return false;
if (!dequeue(queue, 6))
return false;
if (!check_size(queue, 0))
return false;
Queue_Clear(queue);
if (!check_size(queue, 0))
return false;
for (size_t x = 0; x < 32; x++)
{
void* ptr = (void*)(23 + x);
if (!Queue_Enqueue(queue, ptr))
return false;
}
if (!check_size(queue, 32))
return false;
Queue_Clear(queue);
return check_size(queue, 0);
}
int TestQueue(WINPR_ATTR_UNUSED int argc, WINPR_ATTR_UNUSED char* argv[])
{
if (!wrap_test(test_growth_big_move))
return -1;
if (!wrap_test(test_growth_small_move))
return -2;
if (!wrap_test(legacy_test))
return -3;
return 0;
}

View File

@@ -0,0 +1,859 @@
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/crypto.h>
#include <winpr/stream.h>
static BOOL TestStream_Verify(wStream* s, size_t mincap, size_t len, size_t pos)
{
if (Stream_Buffer(s) == nullptr)
{
printf("stream buffer is null\n");
return FALSE;
}
if (Stream_ConstPointer(s) == nullptr)
{
printf("stream pointer is null\n");
return FALSE;
}
if (Stream_PointerAs(s, BYTE) < Stream_Buffer(s))
{
printf("stream pointer (%p) or buffer (%p) is invalid\n", Stream_ConstPointer(s),
(void*)Stream_Buffer(s));
return FALSE;
}
if (Stream_Capacity(s) < mincap)
{
printf("stream capacity is %" PRIuz " but minimum expected value is %" PRIuz "\n",
Stream_Capacity(s), mincap);
return FALSE;
}
if (Stream_Length(s) != len)
{
printf("stream has unexpected length (%" PRIuz " instead of %" PRIuz ")\n",
Stream_Length(s), len);
return FALSE;
}
if (Stream_GetPosition(s) != pos)
{
printf("stream has unexpected position (%" PRIuz " instead of %" PRIuz ")\n",
Stream_GetPosition(s), pos);
return FALSE;
}
if (Stream_GetPosition(s) > Stream_Length(s))
{
printf("stream position (%" PRIuz ") exceeds length (%" PRIuz ")\n", Stream_GetPosition(s),
Stream_Length(s));
return FALSE;
}
if (Stream_GetPosition(s) > Stream_Capacity(s))
{
printf("stream position (%" PRIuz ") exceeds capacity (%" PRIuz ")\n",
Stream_GetPosition(s), Stream_Capacity(s));
return FALSE;
}
if (Stream_Length(s) > Stream_Capacity(s))
{
printf("stream length (%" PRIuz ") exceeds capacity (%" PRIuz ")\n", Stream_Length(s),
Stream_Capacity(s));
return FALSE;
}
if (Stream_GetRemainingLength(s) != len - pos)
{
printf("stream remaining length (%" PRIuz " instead of %" PRIuz ")\n",
Stream_GetRemainingLength(s), len - pos);
return FALSE;
}
return TRUE;
}
static BOOL TestStream_New(void)
{
/* Test creation of a 0-size stream with no buffer */
wStream* s = Stream_New(nullptr, 0);
if (s)
return FALSE;
Stream_Free(s, TRUE);
return TRUE;
}
static BOOL TestStream_Static(void)
{
BYTE buffer[20] = WINPR_C_ARRAY_INIT;
wStream staticStream = WINPR_C_ARRAY_INIT;
wStream* s = &staticStream;
UINT16 v = 0;
/* Test creation of a static stream */
Stream_StaticInit(s, buffer, sizeof(buffer));
Stream_Write_UINT16(s, 0xcab1);
Stream_ResetPosition(s);
Stream_Read_UINT16(s, v);
if (v != 0xcab1)
return FALSE;
Stream_ResetPosition(s);
Stream_Write_UINT16(s, 1);
if (!Stream_EnsureRemainingCapacity(s, 10)) /* we can ask for 10 bytes */
return FALSE;
/* 30 is bigger than the buffer, it will be reallocated on the heap */
if (!Stream_EnsureRemainingCapacity(s, 30) || !s->isOwner)
return FALSE;
Stream_Write_UINT16(s, 2);
Stream_ResetPosition(s);
Stream_Read_UINT16(s, v);
if (v != 1)
return FALSE;
Stream_Read_UINT16(s, v);
if (v != 2)
return FALSE;
// Intentional warning as the stream is not allocated.
// Still, Stream_Free should not release such memory, therefore this statement
// is required to test that.
WINPR_PRAGMA_DIAG_PUSH
WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
Stream_Free(s, TRUE);
WINPR_PRAGMA_DIAG_POP
return TRUE;
}
static BOOL TestStream_Create(size_t count, BOOL selfAlloc)
{
size_t len = 0;
size_t cap = 0;
wStream* s = nullptr;
void* buffer = nullptr;
for (size_t i = 0; i < count; i++)
{
len = cap = i + 1;
if (selfAlloc)
{
if (!(buffer = malloc(cap)))
{
printf("%s: failed to allocate buffer of size %" PRIuz "\n", __func__, cap);
goto fail;
}
}
if (!(s = Stream_New(selfAlloc ? buffer : nullptr, len)))
{
printf("%s: Stream_New failed for stream #%" PRIuz "\n", __func__, i);
goto fail;
}
if (!TestStream_Verify(s, cap, len, 0))
{
goto fail;
}
for (size_t pos = 0; pos < len; pos++)
{
Stream_SetPosition(s, pos);
Stream_SealLength(s);
if (!TestStream_Verify(s, cap, pos, pos))
{
goto fail;
}
}
if (selfAlloc)
{
memset(buffer, (BYTE)(i % 256), cap);
if (memcmp(buffer, Stream_Buffer(s), cap) != 0)
{
printf("%s: buffer memory corruption\n", __func__);
goto fail;
}
}
Stream_Free(s, buffer == nullptr);
free(buffer);
}
return TRUE;
fail:
free(buffer);
if (s)
{
Stream_Free(s, buffer == nullptr);
}
return FALSE;
}
static BOOL TestStream_Extent(UINT32 maxSize)
{
wStream* s = nullptr;
BOOL result = FALSE;
if (!(s = Stream_New(nullptr, 1)))
{
printf("%s: Stream_New failed\n", __func__);
return FALSE;
}
for (UINT32 i = 1; i < maxSize; i++)
{
if (i % 2)
{
if (!Stream_EnsureRemainingCapacity(s, i))
goto fail;
}
else
{
if (!Stream_EnsureCapacity(s, i))
goto fail;
}
Stream_SetPosition(s, i);
Stream_SealLength(s);
if (!TestStream_Verify(s, i, i, i))
{
printf("%s: failed to verify stream in iteration %" PRIu32 "\n", __func__, i);
goto fail;
}
}
result = TRUE;
fail:
if (s)
{
Stream_Free(s, TRUE);
}
return result;
}
#define Stream_Peek_UINT8_BE Stream_Peek_UINT8
#define Stream_Read_UINT8_BE Stream_Read_UINT8
#define Stream_Peek_Get_UINT8_BE Stream_Peek_Get_UINT8
#define Stream_Get_UINT8_BE Stream_Get_UINT8
#define Stream_Peek_INT8_BE Stream_Peek_INT8
#define Stream_Peek_Get_INT8_BE Stream_Peek_Get_INT8
#define Stream_Read_INT8_BE Stream_Read_INT8
#define Stream_Get_INT8_BE Stream_Get_INT8
#define TestStream_PeekAndRead(_s, _r, _t) \
do \
{ \
_t _a = 0; \
_t _b = 0; \
BYTE* _p = Stream_Buffer(_s); \
Stream_ResetPosition(_s); \
Stream_Peek_##_t(_s, _a); \
Stream_Read_##_t(_s, _b); \
if (_a != _b) \
{ \
printf("%s: test1 " #_t "_LE failed\n", __func__); \
(_r) = FALSE; \
} \
Stream_Rewind(_s, sizeof(_t)); \
const _t _d = Stream_Peek_Get_##_t(_s); \
const _t _c = Stream_Get_##_t(_s); \
if (_c != _d) \
{ \
printf("%s: test1 " #_t "_LE failed\n", __func__); \
(_r) = FALSE; \
} \
for (size_t _i = 0; _i < sizeof(_t); _i++) \
{ \
if (((_a >> (_i * 8)) & 0xFF) != _p[_i]) \
{ \
printf("%s: test2 " #_t "_LE failed\n", __func__); \
(_r) = FALSE; \
break; \
} \
} \
/* printf("a: 0x%016llX\n", a); */ \
Stream_ResetPosition(_s); \
Stream_Peek_##_t##_BE(_s, _a); \
Stream_Read_##_t##_BE(_s, _b); \
if (_a != _b) \
{ \
printf("%s: test1 " #_t "_BE failed\n", __func__); \
(_r) = FALSE; \
} \
Stream_Rewind(_s, sizeof(_t)); \
const _t _e = Stream_Peek_Get_##_t##_BE(_s); \
const _t _f = Stream_Get_##_t##_BE(_s); \
if (_e != _f) \
{ \
printf("%s: test1 " #_t "_BE failed\n", __func__); \
(_r) = FALSE; \
} \
for (size_t _i = 0; _i < sizeof(_t); _i++) \
{ \
if (((_a >> (_i * 8)) & 0xFF) != _p[sizeof(_t) - _i - 1]) \
{ \
printf("%s: test2 " #_t "_BE failed\n", __func__); \
(_r) = FALSE; \
break; \
} \
} \
/* printf("a: 0x%016llX\n", a); */ \
} while (0)
static BOOL TestStream_WriteAndRead(UINT64 value)
{
union
{
UINT8 u8;
UINT16 u16;
UINT32 u32;
UINT64 u64;
INT8 i8;
INT16 i16;
INT32 i32;
INT64 i64;
} val;
val.u64 = value;
wStream* s = Stream_New(nullptr, 1024);
if (!s)
return FALSE;
BOOL rc = FALSE;
{
Stream_Write_UINT8(s, val.u8);
Stream_Rewind_UINT8(s);
const UINT8 ru8 = Stream_Get_UINT8(s);
Stream_Rewind_UINT8(s);
if (val.u8 != ru8)
goto fail;
}
{
Stream_Write_UINT16(s, val.u16);
Stream_Rewind_UINT16(s);
const UINT16 ru = Stream_Get_UINT16(s);
Stream_Rewind_UINT16(s);
if (val.u16 != ru)
goto fail;
}
{
Stream_Write_UINT16_BE(s, val.u16);
Stream_Rewind_UINT16(s);
const UINT16 ru = Stream_Get_UINT16_BE(s);
Stream_Rewind_UINT16(s);
if (val.u16 != ru)
goto fail;
}
{
Stream_Write_UINT32(s, val.u32);
Stream_Rewind_UINT32(s);
const UINT32 ru = Stream_Get_UINT32(s);
Stream_Rewind_UINT32(s);
if (val.u32 != ru)
goto fail;
}
{
Stream_Write_UINT32_BE(s, val.u32);
Stream_Rewind_UINT32(s);
const UINT32 ru = Stream_Get_UINT32_BE(s);
Stream_Rewind_UINT32(s);
if (val.u32 != ru)
goto fail;
}
{
Stream_Write_UINT64(s, val.u64);
Stream_Rewind_UINT64(s);
const UINT64 ru = Stream_Get_UINT64(s);
Stream_Rewind_UINT64(s);
if (val.u64 != ru)
goto fail;
}
{
Stream_Write_UINT64_BE(s, val.u64);
Stream_Rewind_UINT64(s);
const UINT64 ru = Stream_Get_UINT64_BE(s);
Stream_Rewind_UINT64(s);
if (val.u64 != ru)
goto fail;
}
{
Stream_Write_INT8(s, val.i8);
Stream_Rewind(s, 1);
const INT8 ru8 = Stream_Get_INT8(s);
Stream_Rewind(s, 1);
if (val.i8 != ru8)
goto fail;
}
{
Stream_Write_INT16(s, val.i16);
Stream_Rewind(s, 2);
const INT16 ru = Stream_Get_INT16(s);
Stream_Rewind(s, 2);
if (val.i16 != ru)
goto fail;
}
{
Stream_Write_INT16_BE(s, val.i16);
Stream_Rewind(s, 2);
const INT16 ru = Stream_Get_INT16_BE(s);
Stream_Rewind(s, 2);
if (val.i16 != ru)
goto fail;
}
{
Stream_Write_INT32(s, val.i32);
Stream_Rewind(s, 4);
const INT32 ru = Stream_Get_INT32(s);
Stream_Rewind(s, 4);
if (val.i32 != ru)
goto fail;
}
{
Stream_Write_INT32_BE(s, val.i32);
Stream_Rewind(s, 4);
const INT32 ru = Stream_Get_INT32_BE(s);
Stream_Rewind(s, 4);
if (val.i32 != ru)
goto fail;
}
{
Stream_Write_INT64(s, val.i64);
Stream_Rewind(s, 8);
const INT64 ru = Stream_Get_INT64(s);
Stream_Rewind(s, 8);
if (val.i64 != ru)
goto fail;
}
{
Stream_Write_INT64_BE(s, val.i64);
Stream_Rewind(s, 8);
const INT64 ru = Stream_Get_INT64_BE(s);
Stream_Rewind(s, 8);
if (val.i64 != ru)
goto fail;
}
rc = TRUE;
fail:
Stream_Free(s, TRUE);
return rc;
}
static BOOL TestStream_Reading(void)
{
BYTE src[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
wStream* s = nullptr;
BOOL result = TRUE;
if (!(s = Stream_New(src, sizeof(src))))
{
printf("%s: Stream_New failed\n", __func__);
return FALSE;
}
TestStream_PeekAndRead(s, result, UINT8);
TestStream_PeekAndRead(s, result, INT8);
TestStream_PeekAndRead(s, result, UINT16);
TestStream_PeekAndRead(s, result, INT16);
TestStream_PeekAndRead(s, result, UINT32);
TestStream_PeekAndRead(s, result, INT32);
TestStream_PeekAndRead(s, result, UINT64);
TestStream_PeekAndRead(s, result, INT64);
Stream_Free(s, FALSE);
return result;
}
static BOOL TestStream_Write(void)
{
BOOL rc = FALSE;
UINT8 u8 = 0;
UINT16 u16 = 0;
UINT32 u32 = 0;
UINT64 u64 = 0;
const BYTE data[] = "someteststreamdata";
wStream* s = Stream_New(nullptr, 100);
if (!s)
goto out;
if (s->pointer != s->buffer)
goto out;
Stream_Write(s, data, sizeof(data));
if (memcmp(Stream_Buffer(s), data, sizeof(data)) == 0)
rc = TRUE;
if (s->pointer != s->buffer + sizeof(data))
goto out;
Stream_ResetPosition(s);
if (s->pointer != s->buffer)
goto out;
Stream_Write_UINT8(s, 42);
if (s->pointer != s->buffer + 1)
goto out;
Stream_ResetPosition(s);
if (s->pointer != s->buffer)
goto out;
Stream_Peek_UINT8(s, u8);
if (u8 != 42)
goto out;
Stream_Write_UINT16(s, 0x1234);
if (s->pointer != s->buffer + 2)
goto out;
Stream_ResetPosition(s);
if (s->pointer != s->buffer)
goto out;
Stream_Peek_UINT16(s, u16);
if (u16 != 0x1234)
goto out;
Stream_Write_UINT32(s, 0x12345678UL);
if (s->pointer != s->buffer + 4)
goto out;
Stream_ResetPosition(s);
if (s->pointer != s->buffer)
goto out;
Stream_Peek_UINT32(s, u32);
if (u32 != 0x12345678UL)
goto out;
Stream_Write_UINT64(s, 0x1234567890ABCDEFULL);
if (s->pointer != s->buffer + 8)
goto out;
Stream_ResetPosition(s);
if (s->pointer != s->buffer)
goto out;
Stream_Peek_UINT64(s, u64);
if (u64 != 0x1234567890ABCDEFULL)
goto out;
out:
Stream_Free(s, TRUE);
return rc;
}
static BOOL TestStream_Seek(void)
{
BOOL rc = FALSE;
wStream* s = Stream_New(nullptr, 100);
if (!s)
goto out;
if (s->pointer != s->buffer)
goto out;
Stream_Seek(s, 5);
if (s->pointer != s->buffer + 5)
goto out;
Stream_Seek_UINT8(s);
if (s->pointer != s->buffer + 6)
goto out;
Stream_Seek_UINT16(s);
if (s->pointer != s->buffer + 8)
goto out;
Stream_Seek_UINT32(s);
if (s->pointer != s->buffer + 12)
goto out;
Stream_Seek_UINT64(s);
if (s->pointer != s->buffer + 20)
goto out;
rc = TRUE;
out:
Stream_Free(s, TRUE);
return rc;
}
static BOOL TestStream_Rewind(void)
{
BOOL rc = FALSE;
wStream* s = Stream_New(nullptr, 100);
if (!s)
goto out;
if (s->pointer != s->buffer)
goto out;
Stream_Seek(s, 100);
if (s->pointer != s->buffer + 100)
goto out;
Stream_Rewind(s, 10);
if (s->pointer != s->buffer + 90)
goto out;
Stream_Rewind_UINT8(s);
if (s->pointer != s->buffer + 89)
goto out;
Stream_Rewind_UINT16(s);
if (s->pointer != s->buffer + 87)
goto out;
Stream_Rewind_UINT32(s);
if (s->pointer != s->buffer + 83)
goto out;
Stream_Rewind_UINT64(s);
if (s->pointer != s->buffer + 75)
goto out;
rc = TRUE;
out:
Stream_Free(s, TRUE);
return rc;
}
static BOOL TestStream_Zero(void)
{
BOOL rc = FALSE;
const BYTE data[] = "someteststreamdata";
wStream* s = Stream_New(nullptr, sizeof(data));
if (!s)
goto out;
Stream_Write(s, data, sizeof(data));
if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0)
goto out;
Stream_ResetPosition(s);
if (s->pointer != s->buffer)
goto out;
Stream_Zero(s, 5);
if (s->pointer != s->buffer + 5)
goto out;
if (memcmp(Stream_ConstPointer(s), data + 5, sizeof(data) - 5) != 0)
goto out;
Stream_ResetPosition(s);
if (s->pointer != s->buffer)
goto out;
for (UINT32 x = 0; x < 5; x++)
{
UINT8 val = 0;
Stream_Read_UINT8(s, val);
if (val != 0)
goto out;
}
rc = TRUE;
out:
Stream_Free(s, TRUE);
return rc;
}
static BOOL TestStream_Fill(void)
{
BOOL rc = FALSE;
const BYTE fill[7] = "XXXXXXX";
const BYTE data[] = "someteststreamdata";
wStream* s = Stream_New(nullptr, sizeof(data));
if (!s)
goto out;
Stream_Write(s, data, sizeof(data));
if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0)
goto out;
Stream_ResetPosition(s);
if (s->pointer != s->buffer)
goto out;
Stream_Fill(s, fill[0], sizeof(fill));
if (s->pointer != s->buffer + sizeof(fill))
goto out;
if (memcmp(Stream_ConstPointer(s), data + sizeof(fill), sizeof(data) - sizeof(fill)) != 0)
goto out;
Stream_ResetPosition(s);
if (s->pointer != s->buffer)
goto out;
if (memcmp(Stream_ConstPointer(s), fill, sizeof(fill)) != 0)
goto out;
rc = TRUE;
out:
Stream_Free(s, TRUE);
return rc;
}
static BOOL TestStream_Copy(void)
{
BOOL rc = FALSE;
const BYTE data[] = "someteststreamdata";
wStream* s = Stream_New(nullptr, sizeof(data));
wStream* d = Stream_New(nullptr, sizeof(data));
if (!s || !d)
goto out;
if (s->pointer != s->buffer)
goto out;
Stream_Write(s, data, sizeof(data));
if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0)
goto out;
if (s->pointer != s->buffer + sizeof(data))
goto out;
Stream_ResetPosition(s);
if (s->pointer != s->buffer)
goto out;
Stream_Copy(s, d, sizeof(data));
if (s->pointer != s->buffer + sizeof(data))
goto out;
if (d->pointer != d->buffer + sizeof(data))
goto out;
if (Stream_GetPosition(s) != Stream_GetPosition(d))
goto out;
if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0)
goto out;
if (memcmp(Stream_Buffer(d), data, sizeof(data)) != 0)
goto out;
rc = TRUE;
out:
Stream_Free(s, TRUE);
Stream_Free(d, TRUE);
return rc;
}
int TestStream(int argc, char* argv[])
{
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
if (!TestStream_Create(200, FALSE))
return 1;
if (!TestStream_Create(200, TRUE))
return 2;
if (!TestStream_Extent(4096))
return 3;
if (!TestStream_Reading())
return 4;
if (!TestStream_New())
return 5;
if (!TestStream_Write())
return 6;
if (!TestStream_Seek())
return 7;
if (!TestStream_Rewind())
return 8;
if (!TestStream_Zero())
return 9;
if (!TestStream_Fill())
return 10;
if (!TestStream_Copy())
return 11;
if (!TestStream_Static())
return 12;
if (!TestStream_WriteAndRead(0x1234567890abcdef))
return 13;
for (size_t x = 0; x < 10; x++)
{
UINT64 val = 0;
if (winpr_RAND(&val, sizeof(val)) < 0)
return -1;
if (!TestStream_WriteAndRead(val))
return 14;
}
return 0;
}

View File

@@ -0,0 +1,82 @@
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <winpr/collections.h>
#define BUFFER_SIZE 16384
int TestStreamPool(int argc, char* argv[])
{
wStream* s[5] = WINPR_C_ARRAY_INIT;
char buffer[8192] = WINPR_C_ARRAY_INIT;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
wStreamPool* pool = StreamPool_New(TRUE, BUFFER_SIZE);
s[0] = StreamPool_Take(pool, 0);
s[1] = StreamPool_Take(pool, 0);
s[2] = StreamPool_Take(pool, 0);
printf("%s\n", StreamPool_GetStatistics(pool, buffer, sizeof(buffer)));
Stream_Release(s[0]);
Stream_Release(s[1]);
Stream_Release(s[2]);
printf("%s\n", StreamPool_GetStatistics(pool, buffer, sizeof(buffer)));
s[3] = StreamPool_Take(pool, 0);
s[4] = StreamPool_Take(pool, 0);
printf("%s\n", StreamPool_GetStatistics(pool, buffer, sizeof(buffer)));
Stream_Release(s[3]);
Stream_Release(s[4]);
printf("%s\n", StreamPool_GetStatistics(pool, buffer, sizeof(buffer)));
s[2] = StreamPool_Take(pool, 0);
s[3] = StreamPool_Take(pool, 0);
s[4] = StreamPool_Take(pool, 0);
printf("%s\n", StreamPool_GetStatistics(pool, buffer, sizeof(buffer)));
Stream_AddRef(s[2]);
Stream_AddRef(s[3]);
Stream_AddRef(s[3]);
Stream_AddRef(s[4]);
Stream_AddRef(s[4]);
Stream_AddRef(s[4]);
Stream_Release(s[2]);
Stream_Release(s[2]);
Stream_Release(s[3]);
Stream_Release(s[3]);
Stream_Release(s[3]);
Stream_Release(s[4]);
Stream_Release(s[4]);
Stream_Release(s[4]);
Stream_Release(s[4]);
printf("%s\n", StreamPool_GetStatistics(pool, buffer, sizeof(buffer)));
s[2] = StreamPool_Take(pool, 0);
s[3] = StreamPool_Take(pool, 0);
s[4] = StreamPool_Take(pool, 0);
printf("%s\n", StreamPool_GetStatistics(pool, buffer, sizeof(buffer)));
Stream_Release(s[2]);
Stream_Release(s[3]);
Stream_Release(s[4]);
StreamPool_Free(pool);
return 0;
}

View File

@@ -0,0 +1,47 @@
#include <winpr/crt.h>
#include <winpr/version.h>
#include <winpr/winpr.h>
int TestVersion(int argc, char* argv[])
{
const char* version = nullptr;
const char* git = nullptr;
const char* build = nullptr;
int major = 0;
int minor = 0;
int revision = 0;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
winpr_get_version(&major, &minor, &revision);
if (major != WINPR_VERSION_MAJOR)
return -1;
if (minor != WINPR_VERSION_MINOR)
return -1;
if (revision != WINPR_VERSION_REVISION)
return -1;
version = winpr_get_version_string();
if (!version)
return -1;
git = winpr_get_build_revision();
if (!git)
return -1;
if (strncmp(git, WINPR_GIT_REVISION, sizeof(WINPR_GIT_REVISION)) != 0)
return -1;
build = winpr_get_build_config();
if (!build)
return -1;
return 0;
}

View File

@@ -0,0 +1,69 @@
#include <winpr/crt.h>
#include <winpr/tchar.h>
#include <winpr/path.h>
#include <winpr/file.h>
#include <winpr/wlog.h>
int TestWLog(int argc, char* argv[])
{
wLog* root = nullptr;
wLog* logA = nullptr;
wLog* logB = nullptr;
wLogLayout* layout = nullptr;
wLogAppender* appender = nullptr;
char* tmp_path = nullptr;
char* wlog_file = nullptr;
int result = 1;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
if (!(tmp_path = GetKnownPath(KNOWN_PATH_TEMP)))
{
(void)fprintf(stderr, "Failed to get temporary directory!\n");
goto out;
}
root = WLog_GetRoot();
WLog_SetLogAppenderType(root, WLOG_APPENDER_BINARY);
appender = WLog_GetLogAppender(root);
if (!WLog_ConfigureAppender(appender, "outputfilename", "test_w.log"))
goto out;
if (!WLog_ConfigureAppender(appender, "outputfilepath", tmp_path))
goto out;
layout = WLog_GetLogLayout(root);
WLog_Layout_SetPrefixFormat(root, layout, "[%lv:%mn] [%fl|%fn|%ln] - ");
WLog_OpenAppender(root);
logA = WLog_Get("com.test.ChannelA");
logB = WLog_Get("com.test.ChannelB");
WLog_SetLogLevel(logA, WLOG_INFO);
WLog_SetLogLevel(logB, WLOG_ERROR);
WLog_Print(logA, WLOG_INFO, "this is a test");
WLog_Print(logA, WLOG_WARN, "this is a %dnd %s", 2, "test");
WLog_Print(logA, WLOG_ERROR, "this is an error");
WLog_Print(logA, WLOG_TRACE, "this is a trace output");
WLog_Print(logB, WLOG_INFO, "just some info");
WLog_Print(logB, WLOG_WARN, "we're warning a %dnd %s", 2, "time");
WLog_Print(logB, WLOG_ERROR, "we've got an error");
WLog_Print(logB, WLOG_TRACE, "leaving a trace behind");
WLog_CloseAppender(root);
if ((wlog_file = GetCombinedPath(tmp_path, "test_w.log")))
winpr_DeleteFile(wlog_file);
result = 0;
out:
free(wlog_file);
free(tmp_path);
return result;
}

View File

@@ -0,0 +1,128 @@
#include <winpr/crt.h>
#include <winpr/tchar.h>
#include <winpr/path.h>
#include <winpr/wlog.h>
typedef struct
{
UINT32 level;
char* msg;
char* channel;
} test_t;
static const char* function = nullptr;
static const char* channels[] = { "com.test.channelA", "com.test.channelB" };
static const test_t messages[] = { { WLOG_INFO, "this is a test", "com.test.channelA" },
{ WLOG_INFO, "Just some info", "com.test.channelB" },
{ WLOG_WARN, "this is a %dnd %s", "com.test.channelA" },
{ WLOG_WARN, "we're warning a %dnd %s", "com.test.channelB" },
{ WLOG_ERROR, "this is an error", "com.test.channelA" },
{ WLOG_ERROR, "we've got an error", "com.test.channelB" },
{ WLOG_TRACE, "this is a trace output", "com.test.channelA" },
{ WLOG_TRACE, "leaving a trace behind", "com.test.channelB" } };
static BOOL success = TRUE;
static int pos = 0;
static BOOL check(const wLogMessage* msg)
{
BOOL rc = TRUE;
if (!msg)
rc = FALSE;
else if (strcmp(msg->FileName, __FILE__) != 0)
rc = FALSE;
else if (strcmp(msg->FunctionName, function) != 0)
rc = FALSE;
else if (strcmp(msg->PrefixString, messages[pos].channel) != 0)
rc = FALSE;
else if (msg->Level != messages[pos].level)
rc = FALSE;
else if (strcmp(msg->FormatString, messages[pos].msg) != 0)
rc = FALSE;
pos++;
if (!rc)
{
(void)fprintf(stderr, "Test failed!\n");
success = FALSE;
}
return rc;
}
static BOOL CallbackAppenderMessage(const wLogMessage* msg)
{
check(msg);
return TRUE;
}
static BOOL CallbackAppenderData(const wLogMessage* msg)
{
(void)fprintf(stdout, "%s\n", __func__);
return TRUE;
}
static BOOL CallbackAppenderImage(const wLogMessage* msg)
{
(void)fprintf(stdout, "%s\n", __func__);
return TRUE;
}
static BOOL CallbackAppenderPackage(const wLogMessage* msg)
{
(void)fprintf(stdout, "%s\n", __func__);
return TRUE;
}
int TestWLogCallback(int argc, char* argv[])
{
wLog* root = nullptr;
wLog* logA = nullptr;
wLog* logB = nullptr;
wLogLayout* layout = nullptr;
wLogAppender* appender = nullptr;
wLogCallbacks callbacks;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
function = __func__;
root = WLog_GetRoot();
WLog_SetLogAppenderType(root, WLOG_APPENDER_CALLBACK);
appender = WLog_GetLogAppender(root);
callbacks.data = CallbackAppenderData;
callbacks.image = CallbackAppenderImage;
callbacks.message = CallbackAppenderMessage;
callbacks.package = CallbackAppenderPackage;
if (!WLog_ConfigureAppender(appender, "callbacks", (void*)&callbacks))
return -1;
layout = WLog_GetLogLayout(root);
WLog_Layout_SetPrefixFormat(root, layout, "%mn");
WLog_OpenAppender(root);
logA = WLog_Get(channels[0]);
logB = WLog_Get(channels[1]);
WLog_SetLogLevel(logA, WLOG_TRACE);
WLog_SetLogLevel(logB, WLOG_TRACE);
WLog_Print(logA, messages[0].level, messages[0].msg);
WLog_Print(logB, messages[1].level, messages[1].msg);
WLog_Print(logA, messages[2].level, messages[2].msg, 2, "test");
WLog_Print(logB, messages[3].level, messages[3].msg, 2, "time");
WLog_Print(logA, messages[4].level, messages[4].msg);
WLog_Print(logB, messages[5].level, messages[5].msg);
WLog_Print(logA, messages[6].level, messages[6].msg);
WLog_Print(logB, messages[7].level, messages[7].msg);
WLog_CloseAppender(root);
return success ? 0 : -1;
}

View File

@@ -0,0 +1,105 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/image.h>
static const int formats[] = { WINPR_IMAGE_BITMAP, WINPR_IMAGE_PNG, WINPR_IMAGE_JPEG,
WINPR_IMAGE_WEBP };
static void usage(int argc, char* argv[])
{
const char* prg = "INVALID";
if (argc > 0)
prg = argv[0];
(void)fprintf(stdout, "%s <src> <dst>\n", prg);
(void)fprintf(stdout, "\tConvert image <src> to <dst>\n");
(void)fprintf(stdout, "\tSupported formats (for this build):\n");
for (size_t x = 0; x < ARRAYSIZE(formats); x++)
{
const int format = formats[x];
const char* ext = winpr_image_format_extension(format);
const char* mime = winpr_image_format_mime(format);
const BOOL supported = winpr_image_format_is_supported(format);
if (supported)
{
(void)fprintf(stdout, "\t\t%s [.%s]\n", mime, ext);
}
}
}
static int detect_format(const char* name)
{
const char* dot = strrchr(name, '.');
if (!dot)
{
(void)fprintf(stderr, "'%s' does not have a file extension\n", name);
return -1;
}
for (size_t x = 0; x < ARRAYSIZE(formats); x++)
{
const int format = formats[x];
const char* ext = winpr_image_format_extension(format);
const char* mime = winpr_image_format_mime(format);
const BOOL supported = winpr_image_format_is_supported(format);
if (strcmp(&dot[1], ext) == 0)
{
(void)fprintf(stdout, "'%s' is of format %s [supported:%s]\n", name, mime,
supported ? "true" : "false");
if (!supported)
return -2;
return format;
}
}
(void)fprintf(stderr, "'%s' is a unsupported format\n", name);
return -3;
}
int main(int argc, char* argv[])
{
int rc = -4;
if (argc != 3)
{
usage(argc, argv);
return -1;
}
const char* src = argv[1];
const char* dst = argv[2];
const int sfmt = detect_format(src);
const int dfmt = detect_format(dst);
if ((sfmt < 0) || (dfmt < 0))
{
usage(argc, argv);
return -2;
}
wImage* img = winpr_image_new();
if (!img)
{
return -3;
}
const int rrc = winpr_image_read(img, src);
if (rrc <= 0)
{
(void)fprintf(stderr, "Failed to read image '%s': %d\n", src, rrc);
goto fail;
}
const int wrc = winpr_image_write(img, dst);
if (wrc <= 0)
{
(void)fprintf(stderr, "Failed to write image '%s': %d\n", dst, wrc);
goto fail;
}
(void)fprintf(stdout, "Successfully converted '%s' to '%s'\n", src, dst);
rc = 0;
fail:
winpr_image_free(img, TRUE);
return rc;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB