VirtualBox

Changeset 97272 in vbox for trunk/src/VBox/HostServices


Ignore:
Timestamp:
Oct 24, 2022 7:56:53 AM (2 years ago)
Author:
vboxsync
Message:

Shared Clipboard/testcase: More code for testing reading host clipboard data from the guest side (also wrt overflow handling) with the HGCM mocking framework. Enabled building the testcase on Linux by default.

Location:
trunk/src/VBox/HostServices/SharedClipboard/testcase
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedClipboard/testcase/Makefile.kmk

    r96407 r97272  
    3131if defined(VBOX_WITH_TESTCASES) && !defined(VBOX_ONLY_ADDITIONS) && !defined(VBOX_ONLY_SDK)
    3232
    33  if 0
    34         #
    35         # Testcase which mocks HGCM to also test the VbglR3-side of Shared Clipboard.
    36         #
    37         # Goal is to use and test as much guest side code as possible as a self-contained
    38         # binary on the host here.
    39         #
    40         # Note: No #ifdef TESTCASE hacks or similar allowed, has to run
    41         #       without #ifdef modifications to the core code!
    42         #
    43         PROGRAMS += tstClipboardMockHGCM
    44         tstClipboardMockHGCM_TEMPLATE = VBOXR3TSTEXE
    45         tstClipboardMockHGCM_DEFS     = VBOX_WITH_HGCM VBOX_WITH_SHARED_CLIPBOARD
    46         tstClipboardMockHGCM_SOURCES  = \
    47                 ../VBoxSharedClipboardSvc.cpp \
    48                 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp \
    49                 $(PATH_ROOT)/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp \
    50                 $(PATH_ROOT)/src/VBox/HostServices/common/message.cpp \
    51                 tstClipboardMockHGCM.cpp
    52         tstClipboardMockHGCM_LIBS     = $(LIB_RUNTIME)
     33#
     34# Testcase which mocks HGCM to also test the VbglR3-side of Shared Clipboard.
     35#
     36# Goal is to use and test as much guest side code as possible as a self-contained
     37# binary on the host here.
     38#
     39# Note: No #ifdef TESTCASE hacks or similar allowed, has to run
     40#       without #ifdef modifications to the core code!
     41#
     42PROGRAMS.linux += tstClipboardMockHGCM
     43tstClipboardMockHGCM_TEMPLATE = VBOXR3TSTEXE
     44tstClipboardMockHGCM_DEFS     = VBOX_WITH_HGCM VBOX_WITH_SHARED_CLIPBOARD
     45tstClipboardMockHGCM_SOURCES  = \
     46        ../VBoxSharedClipboardSvc.cpp \
     47        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp \
     48        $(PATH_ROOT)/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp \
     49        $(PATH_ROOT)/src/VBox/HostServices/common/message.cpp \
     50        tstClipboardMockHGCM.cpp
     51tstClipboardMockHGCM_LIBS     = $(LIB_RUNTIME)
    5352
    54         if1of ($(KBUILD_TARGET), linux)
    55         tstClipboardMockHGCM_SOURCES.linux  += \
    56                 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-x11.cpp \
    57                 ../VBoxSharedClipboardSvc-x11.cpp
    58         tstClipboardMockHGCM_LIBPATH = \
    59                 $(VBOX_LIBPATH_X11)
    60         tstClipboardMockHGCM_LIBS   += \
    61                 Xt \
    62                 X11
    63         endif
     53if1of ($(KBUILD_TARGET), linux)
     54 tstClipboardMockHGCM_SOURCES.linux  += \
     55        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-x11.cpp \
     56        ../VBoxSharedClipboardSvc-x11.cpp
     57 tstClipboardMockHGCM_LIBPATH = \
     58        $(VBOX_LIBPATH_X11)
     59 tstClipboardMockHGCM_LIBS   += \
     60        Xt \
     61        X11
     62endif
    6463
    65         tstClipboardMockHGCM_SOURCES.darwin += ../VBoxSharedClipboardSvc-darwin.cpp
    66         tstClipboardMockHGCM_SOURCES.win    += ../VBoxSharedClipboardSvc-win.cpp
     64tstClipboardMockHGCM_SOURCES.darwin += ../VBoxSharedClipboardSvc-darwin.cpp
     65tstClipboardMockHGCM_SOURCES.win    += ../VBoxSharedClipboardSvc-win.cpp
    6766
    68         tstClipboardMockHGCM_CLEAN           = $(tstClipboardMockHGCM_0_OUTDIR)/tstClipboardMockHGCM.run
     67tstClipboardMockHGCM_CLEAN           = $(tstClipboardMockHGCM_0_OUTDIR)/tstClipboardMockHGCM.run
    6968
    70         if defined(VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS)
    71          tstClipboardMockHGCM_DEFS    += VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    72          tstClipboardMockHGCM_SOURCES += \
    73                 ../VBoxSharedClipboardSvc-transfers.cpp \
    74          $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp
    75         endif
    76  endif
     69if defined(VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS)
     70 tstClipboardMockHGCM_DEFS    += VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     71 tstClipboardMockHGCM_SOURCES += \
     72        ../VBoxSharedClipboardSvc-transfers.cpp \
     73 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp
     74endif
     75
     76if 0 # Enable this if you want automatic runs after compilation.
     77 $$(tstClipboardMockHGCM_0_OUTDIR)/tstClipboardMockHGCM.run: $$(tstClipboardMockHGCM_1_STAGE_TARGET)
     78        export VBOX_LOG_DEST=nofile; $(tstClipboardMockHGCM_1_STAGE_TARGET) quiet
     79        $(QUIET)$(APPEND) -t "$@" "done"
     80 OTHERS += $(tstClipboardMockHGCM_0_OUTDIR)/tstClipboardMockHGCM.run
     81endif
    7782
    7883 #
  • trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardMockHGCM.cpp

    r96407 r97272  
    3535
    3636#include <VBox/GuestHost/HGCMMock.h>
     37#include <VBox/GuestHost/HGCMMockUtils.h>
    3738
    3839#include <iprt/assert.h>
     
    5051*********************************************************************************************************************************/
    5152static RTTEST     g_hTest;
    52 static SHCLCLIENT g_Client;
    5353
    5454
     
    5656*   Shared Clipboard testing                                                                                                     *
    5757*********************************************************************************************************************************/
    58 struct TESTDESC;
     58struct CLIPBOARDTESTDESC;
    5959/** Pointer to a test description. */
    60 typedef TESTDESC *PTESTDESC;
    61 
    62 struct TESTPARMS;
    63 /** Pointer to a test parameter structure. */
    64 typedef TESTPARMS *PTESTPARMS;
    65 
    66 struct TESTCTX;
     60typedef CLIPBOARDTESTDESC *PTESTDESC;
     61
     62struct CLIPBOARDTESTCTX;
    6763/** Pointer to a test context. */
    68 typedef TESTCTX *PTESTCTX;
     64typedef CLIPBOARDTESTCTX *PCLIPBOARDTESTCTX;
    6965
    7066/** Pointer a test descriptor. */
    71 typedef TESTDESC *PTESTDESC;
    72 
    73 typedef DECLCALLBACKTYPE(int, FNTESTSETUP,(PTESTPARMS pTstParms, void **ppvCtx));
    74 /** Pointer to an test setup callback. */
     67typedef CLIPBOARDTESTDESC *PTESTDESC;
     68
     69typedef DECLCALLBACKTYPE(int, FNTESTSETUP,(PCLIPBOARDTESTCTX pTstCtx, void **ppvCtx));
     70/** Pointer to a test setup callback. */
    7571typedef FNTESTSETUP *PFNTESTSETUP;
    7672
    77 typedef DECLCALLBACKTYPE(int, FNTESTEXEC,(PTESTPARMS pTstParms, void *pvCtx));
    78 /** Pointer to an test exec callback. */
     73typedef DECLCALLBACKTYPE(int, FNTESTEXEC,(PCLIPBOARDTESTCTX pTstCtx, void *pvCtx));
     74/** Pointer to a test exec callback. */
    7975typedef FNTESTEXEC *PFNTESTEXEC;
    8076
    81 typedef DECLCALLBACKTYPE(int, FNTESTGSTTHREAD,(PTESTCTX pCtx, void *pvCtx));
    82 /** Pointer to an test guest thread callback. */
    83 typedef FNTESTGSTTHREAD *PFNTESTGSTTHREAD;
    84 
    85 typedef DECLCALLBACKTYPE(int, FNTESTDESTROY,(PTESTPARMS pTstParms, void *pvCtx));
    86 /** Pointer to an test destroy callback. */
     77typedef DECLCALLBACKTYPE(int, FNTESTDESTROY,(PCLIPBOARDTESTCTX pTstCtx, void *pvCtx));
     78/** Pointer to a test destroy callback. */
    8779typedef FNTESTDESTROY *PFNTESTDESTROY;
    8880
    89 typedef struct TESTTASK
    90 {
    91     RTSEMEVENT  hEvent;
    92     int         rcCompleted;
    93     int         rcExpected;
     81
     82/**
     83 * Structure for keeping a clipboard test task.
     84 */
     85typedef struct CLIPBOARDTESTTASK
     86{
    9487    SHCLFORMATS enmFmtHst;
    9588    SHCLFORMATS enmFmtGst;
    96     /** For chunked reads / writes. */
     89    /** For testing chunked reads / writes. */
    9790    size_t      cbChunk;
     91    /** Data buffer to read / write for this task.
     92     *  Can be NULL if not needed. */
     93    void       *pvData;
     94    /** Size (in bytes) of \a pvData. */
    9895    size_t      cbData;
    99     void       *pvData;
    100 } TESTTASK;
    101 typedef TESTTASK *PTESTTASK;
     96    /** Number of bytes read / written from / to \a pvData. */
     97    size_t      cbProcessed;
     98} CLIPBOARDTESTTASK;
     99typedef CLIPBOARDTESTTASK *PCLIPBOARDTESTTASK;
    102100
    103101/**
    104  * Structure for keeping a test context.
     102 * Structure for keeping a clipboard test context.
    105103 */
    106 typedef struct TESTCTX
    107 {
    108     PTSTHGCMMOCKSVC      pSvc;
    109     /** Currently we only support one task at a time. */
    110     TESTTASK             Task;
    111     struct
    112     {
    113         RTTHREAD         hThread;
    114         VBGLR3SHCLCMDCTX CmdCtx;
    115         volatile bool    fShutdown;
    116         PFNTESTGSTTHREAD pfnThread;
    117     } Guest;
    118     struct
    119     {
    120         RTTHREAD         hThread;
    121         volatile bool    fShutdown;
    122     } Host;
    123 } TESTCTX;
    124 
    125 /** The one and only test context. */
    126 TESTCTX  g_TstCtx;
     104typedef struct CLIPBOARDTESTCTX
     105{
     106    /** The HGCM Mock utils context. */
     107    TSTHGCMUTILSCTX   HGCM;
     108    /** Clipboard-specific task data. */
     109    CLIPBOARDTESTTASK Task;
     110} CLIPBOARDTESTCTX;
     111
     112/** The one and only clipboard test context. One at a time. */
     113CLIPBOARDTESTCTX g_TstCtx;
    127114
    128115/**
    129  * Test parameters.
     116 * Structure for keeping a clipboard test description.
    130117 */
    131 typedef struct TESTPARMS
    132 {
    133     /** Pointer to test context to use. */
    134     PTESTCTX             pTstCtx;
    135 } TESTPARMS;
    136 
    137 typedef struct TESTDESC
     118typedef struct CLIPBOARDTESTDESC
    138119{
    139120    /** The setup callback. */
     
    143124    /** The destruction callback. */
    144125    PFNTESTDESTROY       pfnDestroy;
    145 } TESTDESC;
     126} CLIPBOARDTESTDESC;
    146127
    147128typedef struct SHCLCONTEXT
     
    150131
    151132
    152 #if 0
    153 static void tstBackendWriteData(HGCMCLIENTID idClient, SHCLFORMAT uFormat, void *pvData, size_t cbData)
    154 {
    155     ShClBackendSetClipboardData(&s_tstHgcmClient[idClient].Client, uFormat, pvData, cbData);
    156 }
    157 
    158 /** Adds a host data read request message to the client's message queue. */
    159 static int tstSvcMockRequestDataFromGuest(uint32_t idClient, SHCLFORMATS fFormats, PSHCLEVENT *ppEvent)
    160 {
    161     AssertPtrReturn(ppEvent, VERR_INVALID_POINTER);
    162 
    163     int rc = ShClSvcGuestDataRequest(&s_tstHgcmClient[idClient].Client, fFormats, ppEvent);
    164     RTTESTI_CHECK_RC_OK_RET(rc, rc);
    165 
    166     return rc;
    167 }
    168 #endif
    169 
    170 static int tstSetModeRc(PTSTHGCMMOCKSVC pSvc, uint32_t uMode, int rc)
     133static int tstSetModeRc(PTSTHGCMMOCKSVC pSvc, uint32_t uMode, int rcExpected)
    171134{
    172135    VBOXHGCMSVCPARM aParms[2];
    173136    HGCMSvcSetU32(&aParms[0], uMode);
    174137    int rc2 = TstHgcmMockSvcHostCall(pSvc, NULL, VBOX_SHCL_HOST_FN_SET_MODE, 1, aParms);
    175     RTTESTI_CHECK_MSG_RET(rc == rc2, ("Expected %Rrc, got %Rrc\n", rc, rc2), rc2);
    176     uint32_t const uModeRet = ShClSvcGetMode();
    177     RTTESTI_CHECK_MSG_RET(uMode == uModeRet, ("Expected mode %RU32, got %RU32\n", uMode, uModeRet), VERR_WRONG_TYPE);
     138    RTTESTI_CHECK_MSG_RET(rcExpected == rc2, ("Expected %Rrc, got %Rrc\n", rcExpected, rc2), rc2);
     139    if (RT_SUCCESS(rcExpected))
     140    {
     141        uint32_t const uModeRet = ShClSvcGetMode();
     142        RTTESTI_CHECK_MSG_RET(uMode == uModeRet, ("Expected mode %RU32, got %RU32\n", uMode, uModeRet), VERR_WRONG_TYPE);
     143    }
    178144    return rc2;
    179145}
    180146
    181 static int tstSetMode(PTSTHGCMMOCKSVC pSvc, uint32_t uMode)
     147static int tstClipboardSetMode(PTSTHGCMMOCKSVC pSvc, uint32_t uMode)
    182148{
    183149    return tstSetModeRc(pSvc, uMode, VINF_SUCCESS);
    184150}
    185151
    186 static bool tstGetMode(PTSTHGCMMOCKSVC pSvc, uint32_t uModeExpected)
     152static bool tstClipboardGetMode(PTSTHGCMMOCKSVC pSvc, uint32_t uModeExpected)
    187153{
    188154    RT_NOREF(pSvc);
     
    218184    RTTESTI_CHECK_RC(rc, VERR_INVALID_PARAMETER);
    219185
    220     tstSetMode(pSvc, VBOX_SHCL_MODE_HOST_TO_GUEST);
     186    tstClipboardSetMode(pSvc, VBOX_SHCL_MODE_HOST_TO_GUEST);
    221187    tstSetModeRc(pSvc, 99, VERR_NOT_SUPPORTED);
    222     tstGetMode(pSvc, VBOX_SHCL_MODE_OFF);
     188    tstClipboardGetMode(pSvc, VBOX_SHCL_MODE_OFF);
    223189}
    224190
     
    252218}
    253219#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
    254 
    255 /* Does testing of VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, needed for providing compatibility to older Guest Additions clients. */
    256 static void testHostGetMsgOld(void)
    257 {
    258     RTTestISub("Setting up VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT test");
    259 
    260     PTSTHGCMMOCKSVC pSvc = TstHgcmMockSvcInst();
    261 
    262     VBOXHGCMSVCPARM parms[2];
    263     RT_ZERO(parms);
    264 
    265     /* Unless we are bidirectional the host message requests will be dropped. */
    266     HGCMSvcSetU32(&parms[0], VBOX_SHCL_MODE_BIDIRECTIONAL);
    267     int rc = pSvc->fnTable.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_MODE, 1, parms);
    268     RTTESTI_CHECK_RC_OK(rc);
    269 
    270     RTTestISub("Testing one format, waiting guest u.Call.");
    271     RT_ZERO(g_Client);
    272     VBOXHGCMCALLHANDLE_TYPEDEF call;
    273     rc = VERR_IPE_UNINITIALIZED_STATUS;
    274     pSvc->fnTable.pfnConnect(NULL, 1 /* clientId */, &g_Client, 0, 0);
    275 
    276     HGCMSvcSetU32(&parms[0], 0);
    277     HGCMSvcSetU32(&parms[1], 0);
    278     pSvc->fnTable.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
    279     RTTESTI_CHECK_RC_OK(rc);
    280 
    281     //testMsgAddReadData(&g_Client, VBOX_SHCL_FMT_UNICODETEXT);
    282     RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
    283     RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_UNICODETEXT);
    284 #if 0
    285     RTTESTI_CHECK_RC_OK(u.Call.rc);
    286     u.Call.rc = VERR_IPE_UNINITIALIZED_STATUS;
    287     s_tstHgcmSrv.fnTable.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
    288     RTTESTI_CHECK_RC(u.Call.rc, VINF_SUCCESS);
    289     s_tstHgcmSrv.fnTable.pfnDisconnect(NULL, 1 /* clientId */, &g_Client);
    290 
    291     RTTestISub("Testing one format, no waiting guest calls.");
    292     RT_ZERO(g_Client);
    293     s_tstHgcmSrv.fnTable.pfnConnect(NULL, 1 /* clientId */, &g_Client, 0, 0);
    294     testMsgAddReadData(&g_Client, VBOX_SHCL_FMT_HTML);
    295     HGCMSvcSetU32(&parms[0], 0);
    296     HGCMSvcSetU32(&parms[1], 0);
    297     u.Call.rc = VERR_IPE_UNINITIALIZED_STATUS;
    298     s_tstHgcmSrv.fnTable.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
    299     RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
    300     RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_HTML);
    301     RTTESTI_CHECK_RC_OK(u.Call.rc);
    302     u.Call.rc = VERR_IPE_UNINITIALIZED_STATUS;
    303     s_tstHgcmSrv.fnTable.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
    304     RTTESTI_CHECK_RC(u.Call.rc, VINF_SUCCESS);
    305     s_tstHgcmSrv.fnTable.pfnDisconnect(NULL, 1 /* clientId */, &g_Client);
    306 
    307     RTTestISub("Testing two formats, waiting guest u.Call.");
    308     RT_ZERO(g_Client);
    309     s_tstHgcmSrv.fnTable.pfnConnect(NULL, 1 /* clientId */, &g_Client, 0, 0);
    310     HGCMSvcSetU32(&parms[0], 0);
    311     HGCMSvcSetU32(&parms[1], 0);
    312     u.Call.rc = VERR_IPE_UNINITIALIZED_STATUS;
    313     s_tstHgcmSrv.fnTable.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
    314     RTTESTI_CHECK_RC(u.Call.rc, VERR_IPE_UNINITIALIZED_STATUS);  /* This should get updated only when the guest call completes. */
    315     testMsgAddReadData(&g_Client, VBOX_SHCL_FMT_UNICODETEXT | VBOX_SHCL_FMT_HTML);
    316     RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
    317     RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_UNICODETEXT);
    318     RTTESTI_CHECK_RC_OK(u.Call.rc);
    319     u.Call.rc = VERR_IPE_UNINITIALIZED_STATUS;
    320     s_tstHgcmSrv.fnTable.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
    321     RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
    322     RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_HTML);
    323     RTTESTI_CHECK_RC_OK(u.Call.rc);
    324     u.Call.rc = VERR_IPE_UNINITIALIZED_STATUS;
    325     s_tstHgcmSrv.fnTable.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
    326     RTTESTI_CHECK_RC(u.Call.rc, VERR_IPE_UNINITIALIZED_STATUS);  /* This call should not complete yet. */
    327     s_tstHgcmSrv.fnTable.pfnDisconnect(NULL, 1 /* clientId */, &g_Client);
    328 
    329     RTTestISub("Testing two formats, no waiting guest calls.");
    330     RT_ZERO(g_Client);
    331     s_tstHgcmSrv.fnTable.pfnConnect(NULL, 1 /* clientId */, &g_Client, 0, 0);
    332     testMsgAddReadData(&g_Client, VBOX_SHCL_FMT_UNICODETEXT | VBOX_SHCL_FMT_HTML);
    333     HGCMSvcSetU32(&parms[0], 0);
    334     HGCMSvcSetU32(&parms[1], 0);
    335     u.Call.rc = VERR_IPE_UNINITIALIZED_STATUS;
    336     s_tstHgcmSrv.fnTable.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
    337     RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
    338     RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_UNICODETEXT);
    339     RTTESTI_CHECK_RC_OK(u.Call.rc);
    340     u.Call.rc = VERR_IPE_UNINITIALIZED_STATUS;
    341     s_tstHgcmSrv.fnTable.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
    342     RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
    343     RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_HTML);
    344     RTTESTI_CHECK_RC_OK(u.Call.rc);
    345     u.Call.rc = VERR_IPE_UNINITIALIZED_STATUS;
    346     s_tstHgcmSrv.fnTable.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
    347     RTTESTI_CHECK_RC(u.Call.rc, VERR_IPE_UNINITIALIZED_STATUS);  /* This call should not complete yet. */
    348 #endif
    349     pSvc->fnTable.pfnDisconnect(NULL, 1 /* clientId */, &g_Client);
    350 }
    351220
    352221static void testGuestSimple(void)
     
    400269     * Access allowed tests.
    401270     */
    402     tstSetMode(pSvc, VBOX_SHCL_MODE_BIDIRECTIONAL);
     271    tstClipboardSetMode(pSvc, VBOX_SHCL_MODE_BIDIRECTIONAL);
    403272
    404273    /* Try writing data without reporting formats before. */
     
    416285}
    417286
    418 static void testGuestWrite(void)
    419 {
    420     RTTestISub("Testing client (guest) API - Writing");
    421 }
    422 
    423 #if 0
    424 /**
    425  * Generate a random codepoint for simple UTF-16 encoding.
    426  */
     287static RTUTF16 tstGetRandUtf8(void)
     288{
     289    return RTRandU32Ex(0x20, 0x7A);
     290}
     291
     292static char *tstGenerateUtf8StringA(uint32_t uCch)
     293{
     294    char * pszRand = (char *)RTMemAlloc(uCch + 1);
     295    for (uint32_t i = 0; i < uCch; i++)
     296        pszRand[i] = tstGetRandUtf8();
     297    pszRand[uCch] = 0;
     298    return pszRand;
     299}
     300
     301#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
    427302static RTUTF16 tstGetRandUtf16(void)
    428303{
     
    443318    return pwszRand;
    444319}
    445 #endif
    446 
    447 #if 0
    448 static void testGuestRead(void)
    449 {
    450     RTTestISub("Testing client (guest) API - Reading");
    451 
    452     /* Preparations. */
    453     tstSetMode(VBOX_SHCL_MODE_BIDIRECTIONAL);
    454 
    455     VBGLR3SHCLCMDCTX Ctx;
    456     RTTESTI_CHECK_RC_OK(VbglR3ClipboardConnectEx(&Ctx, VBOX_SHCL_GF_0_CONTEXT_ID));
    457     RTThreadSleep(500); /** @todo BUGBUG -- Seems to be a startup race when querying the initial clipboard formats. */
    458 
    459     uint8_t abData[_4K]; uint32_t cbData; uint32_t cbRead;
    460 
    461     /* Issue a host request that we want to read clipboard data from the guest. */
    462     PSHCLEVENT pEvent;
    463     tstSvcMockRequestDataFromGuest(Ctx.idClient, VBOX_SHCL_FMT_UNICODETEXT, &pEvent);
    464 
    465     /* Write guest clipboard data to the host side. */
    466     RTTESTI_CHECK_RC_OK(VbglR3ClipboardReportFormats(Ctx.idClient, VBOX_SHCL_FMT_UNICODETEXT));
    467     cbData = RTRandU32Ex(1, sizeof(abData));
    468     PRTUTF16 pwszStr = tstGenerateUtf16String(cbData);
    469     RTTESTI_CHECK_RC_OK(VbglR3ClipboardWriteDataEx(&Ctx, VBOX_SHCL_FMT_UNICODETEXT, pwszStr, cbData));
    470     RTMemFree(pwszStr);
    471 
    472     PSHCLEVENTPAYLOAD pPayload;
    473     int rc = ShClEventWait(pEvent, RT_MS_30SEC, &pPayload);
    474     if (RT_SUCCESS(rc))
    475     {
    476 
    477     }
    478     ShClEventRelease(pEvent);
    479     pEvent = NULL;
    480 
    481 
    482     /* Read clipboard data from the host back to the guest side. */
    483     /* Note: Also could return VINF_BUFFER_OVERFLOW, so check for VINF_SUCCESS explicitly here. */
    484     RTTESTI_CHECK_RC(VbglR3ClipboardReadDataEx(&Ctx, VBOX_SHCL_FMT_UNICODETEXT,
    485                                                abData, sizeof(abData), &cbRead), VINF_SUCCESS);
    486     RTTESTI_CHECK(cbRead == cbData);
    487 
    488     RTPrintf("Data (%RU32): %ls\n", cbRead, (PCRTUTF16)abData);
    489 
    490     /* Tear down. */
    491     RTTESTI_CHECK_RC_OK(VbglR3ClipboardDisconnectEx(&Ctx));
    492 }
    493 #endif
    494 
    495 static DECLCALLBACK(int) tstGuestThread(RTTHREAD hThread, void *pvUser)
    496 {
    497     RT_NOREF(hThread);
    498     PTESTCTX pCtx = (PTESTCTX)pvUser;
    499     AssertPtr(pCtx);
    500 
    501     RTThreadUserSignal(hThread);
    502 
    503     if (pCtx->Guest.pfnThread)
    504         return pCtx->Guest.pfnThread(pCtx, NULL);
    505 
    506     return VINF_SUCCESS;
    507 }
    508 
    509 static DECLCALLBACK(int) tstHostThread(RTTHREAD hThread, void *pvUser)
    510 {
    511     RT_NOREF(hThread);
    512     PTESTCTX pCtx = (PTESTCTX)pvUser;
    513     AssertPtr(pCtx);
    514 
    515     int rc = VINF_SUCCESS;
    516 
    517     RTThreadUserSignal(hThread);
    518 
    519     for (;;)
    520     {
    521         RTThreadSleep(100);
    522 
    523         if (ASMAtomicReadBool(&pCtx->Host.fShutdown))
    524             break;
    525     }
    526 
    527     return rc;
    528 }
     320#endif /* RT_OS_WINDOWS) || RT_OS_OS2 */
    529321
    530322static void testSetHeadless(void)
     
    568360}
    569361
    570 static int tstGuestStart(PTESTCTX pTstCtx, PFNTESTGSTTHREAD pFnThread)
    571 {
    572     pTstCtx->Guest.pfnThread = pFnThread;
    573 
    574     int rc = RTThreadCreate(&pTstCtx->Guest.hThread, tstGuestThread, pTstCtx, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
    575                             "tstShClGst");
    576     if (RT_SUCCESS(rc))
    577         rc = RTThreadUserWait(pTstCtx->Guest.hThread, RT_MS_30SEC);
    578 
    579     return rc;
    580 }
    581 
    582 static int tstGuestStop(PTESTCTX pTstCtx)
    583 {
    584     ASMAtomicWriteBool(&pTstCtx->Guest.fShutdown, true);
    585 
    586     int rcThread;
    587     int rc = RTThreadWait(pTstCtx->Guest.hThread, RT_MS_30SEC, &rcThread);
    588     if (RT_SUCCESS(rc))
    589         rc = rcThread;
    590     if (RT_FAILURE(rc))
    591         RTTestFailed(g_hTest, "Shutting down guest thread failed with %Rrc\n", rc);
    592 
    593     pTstCtx->Guest.hThread = NIL_RTTHREAD;
    594 
    595     return rc;
    596 }
    597 
    598 static int tstHostStart(PTESTCTX pTstCtx)
    599 {
    600     int rc = RTThreadCreate(&pTstCtx->Host.hThread, tstHostThread, pTstCtx, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
    601                             "tstShClHst");
    602     if (RT_SUCCESS(rc))
    603         rc = RTThreadUserWait(pTstCtx->Host.hThread, RT_MS_30SEC);
    604 
    605     return rc;
    606 }
    607 
    608 static int tstHostStop(PTESTCTX pTstCtx)
    609 {
    610     ASMAtomicWriteBool(&pTstCtx->Host.fShutdown, true);
    611 
    612     int rcThread;
    613     int rc = RTThreadWait(pTstCtx->Host.hThread, RT_MS_30SEC, &rcThread);
    614     if (RT_SUCCESS(rc))
    615         rc = rcThread;
    616     if (RT_FAILURE(rc))
    617         RTTestFailed(g_hTest, "Shutting down host thread failed with %Rrc\n", rc);
    618 
    619     pTstCtx->Host.hThread = NIL_RTTHREAD;
    620 
    621     return rc;
    622 }
    623 
     362
     363/*********************************************************************************************************************************
     364 * Test: Guest reading from host                                                                                                 *
     365 ********************************************************************************************************************************/
    624366#if defined(RT_OS_LINUX)
    625 static DECLCALLBACK(int) tstShClUserMockReportFormatsCallback(PSHCLCONTEXT pCtx, uint32_t fFormats, void *pvUser)
     367/* Called from SHCLX11 thread. */
     368static DECLCALLBACK(int) tstTestReadFromHost_ReportFormatsCallback(PSHCLCONTEXT pCtx, uint32_t fFormats, void *pvUser)
    626369{
    627370    RT_NOREF(pCtx, fFormats, pvUser);
    628     RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstShClUserMockReportFormatsCallback: fFormats=%#x\n", fFormats);
     371
     372    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstTestReadFromHost_SvcReportFormatsCallback: fFormats=%#x\n", fFormats);
    629373    return VINF_SUCCESS;
    630374}
    631375
    632 /*
    633 static DECLCALLBACK(int) tstTestReadFromHost_RequestDataFromSourceCallback(PSHCLCONTEXT pCtx, SHCLFORMAT uFmt, void **ppv, uint32_t *pcb, void *pvUser)
    634 {
    635     RT_NOREF(pCtx, uFmt, ppv, pvUser);
    636 
    637     PTESTTASK pTask = &TaskRead;
    638 
    639     uint8_t *pvData = (uint8_t *)RTMemDup(pTask->pvData, pTask->cbData);
    640 
    641     *ppv = pvData;
    642     *pcb = pTask->cbData;
    643 
    644     return VINF_SUCCESS;
    645 }
    646 */
    647 
    648 #if 0
    649 static DECLCALLBACK(int) tstShClUserMockSendDataCallback(PSHCLCONTEXT pCtx, void *pv, uint32_t cb, void *pvUser)
    650 {
    651     RT_NOREF(pCtx, pv, cb, pvUser);
    652     RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "tstShClUserMockSendDataCallback\n");
    653 
    654     PTESTTASK pTask = &TaskRead;
    655 
    656     memcpy(pv, pTask->pvData, RT_MIN(pTask->cbData, cb));
    657 
    658     return VINF_SUCCESS;
    659 }
    660 #endif
    661 
    662 static DECLCALLBACK(int) tstShClUserMockOnGetDataCallback(PSHCLCONTEXT pCtx, SHCLFORMAT uFmt, void **ppv, size_t *pcb, void *pvUser)
     376/* Called by the backend, e.g. for X11 in the SHCLX11 thread. */
     377static DECLCALLBACK(int) tstTestReadFromHost_OnClipboardReadCallback(PSHCLCONTEXT pCtx,
     378                                                                     SHCLFORMAT uFmt, void **ppv, size_t *pcb, void *pvUser)
    663379{
    664380    RT_NOREF(pCtx, uFmt, pvUser);
    665381
    666     PTESTTASK pTask = &g_TstCtx.Task;
    667 
    668     uint8_t *pvData = pTask->cbData ? (uint8_t *)RTMemDup(pTask->pvData, pTask->cbData) : NULL;
    669     size_t   cbData = pTask->cbData;
     382    PCLIPBOARDTESTTASK pTask = (PCLIPBOARDTESTTASK)TstHGCMUtilsTaskGetCurrent(&g_TstCtx.HGCM)->pvUser;
     383
     384    void   *pvData = NULL;
     385    size_t  cbData = pTask->cbData - pTask->cbProcessed;
     386    if (cbData)
     387    {
     388        pvData = RTMemDup((uint8_t *)pTask->pvData + pTask->cbProcessed, cbData);
     389        AssertPtr(pvData);
     390    }
     391
     392    RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Host reporting back %RU32 bytes of data\n", cbData);
    670393
    671394    *ppv = pvData;
     
    685408typedef TSTUSERMOCK *PTSTUSERMOCK;
    686409
    687 static void tstShClUserMockInit(PTSTUSERMOCK pUsrMock, const char *pszName)
     410static void tstTestReadFromHost_MockInit(PTSTUSERMOCK pUsrMock, const char *pszName)
    688411{
    689412#if defined(RT_OS_LINUX)
    690413    SHCLCALLBACKS Callbacks;
    691414    RT_ZERO(Callbacks);
    692     Callbacks.pfnReportFormats   = tstShClUserMockReportFormatsCallback;
    693     Callbacks.pfnOnClipboardRead = tstShClUserMockOnGetDataCallback;
     415    Callbacks.pfnReportFormats   = tstTestReadFromHost_ReportFormatsCallback;
     416    Callbacks.pfnOnClipboardRead = tstTestReadFromHost_OnClipboardReadCallback;
    694417
    695418    pUsrMock->pCtx = (PSHCLCONTEXT)RTMemAllocZ(sizeof(SHCLCONTEXT));
     
    701424    RTThreadSleep(500);
    702425#else
    703     RT_NOREF(pUsrMock);
     426    RT_NOREF(pUsrMock, pszName);
    704427#endif /* RT_OS_LINUX */
    705428}
    706429
    707 static void tstShClUserMockDestroy(PTSTUSERMOCK pUsrMock)
     430static void tstTestReadFromHost_MockDestroy(PTSTUSERMOCK pUsrMock)
    708431{
    709432#if defined(RT_OS_LINUX)
     
    716439}
    717440
    718 static int tstTaskGuestRead(PTESTCTX pCtx, PTESTTASK pTask)
    719 {
    720     size_t   cbReadTotal = 0;
    721     size_t   cbToRead    = pTask->cbData;
    722 
     441static int tstTestReadFromHost_DoIt(PCLIPBOARDTESTCTX pCtx, PCLIPBOARDTESTTASK pTask)
     442{
     443    size_t   cbDst       = RT_MAX(_64K, pTask->cbData);
     444    uint8_t *pabDst      = (uint8_t *)RTMemAllocZ(cbDst);
     445    AssertPtrReturn(pabDst, VERR_NO_MEMORY);
     446
     447    AssertPtr(pTask->pvData);                /* Racing condition with host thread? */
     448    Assert(pTask->cbChunk);                  /* Buggy test? */
     449    Assert(pTask->cbChunk <= pTask->cbData); /* Ditto. */
     450
     451    size_t   cbToRead = pTask->cbData;
    723452    switch (pTask->enmFmtGst)
    724453    {
     
    731460    }
    732461
    733     size_t   cbDst       = _64K;
    734     uint8_t *pabDst      = (uint8_t *)RTMemAllocZ(cbDst);
    735     AssertPtrReturn(pabDst, VERR_NO_MEMORY);
    736 
    737     Assert(pTask->cbChunk);                  /* Buggy test? */
    738     Assert(pTask->cbChunk <= pTask->cbData); /* Ditto. */
    739 
    740     uint8_t *pabSrc = (uint8_t *)pTask->pvData;
    741 
    742     do
     462    PVBGLR3SHCLCMDCTX pCmdCtx = &pCtx->HGCM.Guest.CmdCtx;
     463
     464    /* Do random chunked reads. */
     465    uint32_t const cChunkedReads = RTRandU32Ex(1, 16);
     466    RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "%RU32 chunked reads\n", cChunkedReads);
     467    for (uint32_t i = 0; i < cChunkedReads; i++)
    743468    {
    744469        /* Note! VbglR3ClipboardReadData() currently does not support chunked reads!
    745470          *      It in turn returns VINF_BUFFER_OVERFLOW when the supplied buffer was too small. */
    746         uint32_t const cbChunk    = cbDst;
    747         uint32_t const cbExpected = cbToRead;
    748 
    749         uint32_t cbRead = 0;
    750         RTTEST_CHECK_RC(g_hTest, VbglR3ClipboardReadData(pCtx->Guest.CmdCtx.idClient,
    751                                                          pTask->enmFmtGst, pabDst, cbChunk, &cbRead), pTask->rcExpected);
    752         RTTEST_CHECK_MSG(g_hTest, cbRead == cbExpected, (g_hTest, "Read %RU32 bytes, expected %RU32\n", cbRead, cbExpected));
    753         RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Guest side received %RU32 bytes\n", cbRead);
    754         cbReadTotal += cbRead;
    755         Assert(cbReadTotal <= cbToRead);
    756 
    757     } while (cbReadTotal < cbToRead);
     471
     472        uint32_t cbChunk    = RTRandU32Ex(1, pTask->cbData / cChunkedReads);
     473        uint32_t cbRead     = 0;
     474        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Guest trying to read %RU32 bytes\n", cbChunk);
     475        int vrc2 = VbglR3ClipboardReadData(pCmdCtx->idClient, pTask->enmFmtGst, pabDst, cbChunk, &cbRead);
     476        if (   vrc2   == VINF_SUCCESS
     477            && cbRead == 0) /* No data there yet? */
     478        {
     479            RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "No data (yet) from host\n");
     480            RTThreadSleep(10);
     481            continue;
     482        }
     483        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Trying reading host clipboard data with a %RU32 buffer -> %Rrc (%RU32)\n", cbChunk, vrc2, cbRead);
     484        RTTEST_CHECK_MSG(g_hTest, vrc2 == VINF_BUFFER_OVERFLOW, (g_hTest, "Got %Rrc, expected VINF_BUFFER_OVERFLOW\n", vrc2));
     485    }
     486
     487    /* Last read: Read the data with a buffer big enough. This must succeed. */
     488    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Reading full data (%zu)\n", pTask->cbData);
     489    uint32_t cbRead = 0;
     490    int vrc2 = VbglR3ClipboardReadData(pCmdCtx->idClient, pTask->enmFmtGst, pabDst, cbDst, &cbRead);
     491    RTTEST_CHECK_MSG(g_hTest, vrc2 == VINF_SUCCESS, (g_hTest, "Got %Rrc, expected VINF_SUCCESS\n", vrc2));
     492    RTTEST_CHECK_MSG(g_hTest, cbRead == cbToRead, (g_hTest, "Read %RU32 bytes, expected %zu\n", cbRead, cbToRead));
    758493
    759494    if (pTask->enmFmtGst == VBOX_SHCL_FMT_UNICODETEXT)
     495        RTTEST_CHECK_MSG(g_hTest, RTUtf16ValidateEncoding((PRTUTF16)pabDst) == VINF_SUCCESS, (g_hTest, "Read data is not valid UTF-16\n"));
     496    if (cbRead == cbToRead)
    760497    {
    761         RTTEST_CHECK_RC_OK(g_hTest, RTUtf16ValidateEncoding((PRTUTF16)pabDst));
     498        PRTUTF16 pwszSrc;
     499        RTTEST_CHECK(g_hTest, RT_SUCCESS(RTStrToUtf16((const char *)pTask->pvData, &pwszSrc)));
     500        RTTEST_CHECK_MSG(g_hTest, memcmp(pwszSrc, pabDst, cbRead) == 0, (g_hTest, "Read data does not match host data\n"));
     501        RTUtf16Free(pwszSrc);
    762502    }
    763     else
    764         RTTEST_CHECK(g_hTest, memcmp(pabSrc, pabDst, RT_MIN(pTask->cbData, cbDst) == 0));
     503
     504    RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Read data from host:\n%.*Rhxd\n", cbRead, pabDst);
    765505
    766506    RTMemFree(pabDst);
     
    769509}
    770510
    771 static void tstTaskInit(PTESTTASK pTask)
    772 {
    773     RTSemEventCreate(&pTask->hEvent);
    774 }
    775 
    776 static void tstTaskDestroy(PTESTTASK pTask)
    777 {
    778     RTSemEventDestroy(pTask->hEvent);
    779 }
    780 
    781 static void tstTaskWait(PTESTTASK pTask, RTMSINTERVAL msTimeout)
    782 {
    783     RTTEST_CHECK_RC_OK(g_hTest, RTSemEventWait(pTask->hEvent, msTimeout));
    784     RTTEST_CHECK_RC(g_hTest, pTask->rcCompleted, pTask->rcExpected);
    785 }
    786 
    787 static void tstTaskSignal(PTESTTASK pTask, int rc)
    788 {
    789     pTask->rcCompleted = rc;
    790     RTTEST_CHECK_RC_OK(g_hTest, RTSemEventSignal(pTask->hEvent));
    791 }
    792 
    793 static DECLCALLBACK(int) tstTestReadFromHostThreadGuest(PTESTCTX pCtx, void *pvCtx)
    794 {
    795     RT_NOREF(pvCtx);
    796 
    797     RTThreadSleep(5000);
    798 RT_BREAKPOINT();
     511static DECLCALLBACK(int) tstTestReadFromHost_ThreadGuest(PTSTHGCMUTILSCTX pCtx, void *pvCtx)
     512{
     513    RTThreadSleep(1000); /* Fudge; wait until the host has prepared the data for the clipboard. */
    799514
    800515    RT_ZERO(pCtx->Guest.CmdCtx);
    801516    RTTEST_CHECK_RC_OK(g_hTest, VbglR3ClipboardConnectEx(&pCtx->Guest.CmdCtx, VBOX_SHCL_GF_0_CONTEXT_ID));
    802517
    803 #if 1
    804     PTESTTASK pTask = &pCtx->Task;
    805     tstTaskGuestRead(pCtx, pTask);
    806     tstTaskSignal(pTask, VINF_SUCCESS);
     518    RTThreadSleep(1000); /* Fudge; wait until the host has prepared the data for the clipboard. */
     519
     520    PCLIPBOARDTESTCTX  pTstCtx  = (PCLIPBOARDTESTCTX)pvCtx;
     521    AssertPtr(pTstCtx);
     522    PCLIPBOARDTESTTASK pTstTask = (PCLIPBOARDTESTTASK)pCtx->Task.pvUser;
     523    AssertPtr(pTstTask);
     524    tstTestReadFromHost_DoIt(pTstCtx, pTstTask);
     525
     526    /* Signal that the task ended. */
     527    TstHGCMUtilsTaskSignal(&pCtx->Task, VINF_SUCCESS);
     528
     529    RTTEST_CHECK_RC_OK(g_hTest, VbglR3ClipboardDisconnectEx(&pCtx->Guest.CmdCtx));
     530
     531    return VINF_SUCCESS;
     532}
     533
     534static DECLCALLBACK(int) tstTestReadFromHost_ClientConnectedCallback(PTSTHGCMUTILSCTX pCtx, PTSTHGCMMOCKCLIENT pClient,
     535                                                                     void *pvUser)
     536{
     537    RT_NOREF(pCtx, pClient);
     538
     539    PCLIPBOARDTESTCTX pTstCtx = (PCLIPBOARDTESTCTX)pvUser;
     540    AssertPtr(pTstCtx); RT_NOREF(pTstCtx);
     541
     542    RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Client %RU32 connected\n", pClient->idClient);
     543    return VINF_SUCCESS;
     544}
     545
     546static DECLCALLBACK(int) tstTestReadFromHostSetup(PCLIPBOARDTESTCTX pTstCtx, void **ppvCtx)
     547{
     548    RT_NOREF(ppvCtx);
     549
     550    /* Initialize the Shared Clipboard backend callbacks. */
     551    PSHCLBACKEND pBackend = ShClSvcGetBackend();
     552
     553    SHCLCALLBACKS ShClCallbacks;
     554    RT_ZERO(ShClCallbacks);
     555    ShClCallbacks.pfnReportFormats   = tstTestReadFromHost_ReportFormatsCallback;
     556    ShClCallbacks.pfnOnClipboardRead = tstTestReadFromHost_OnClipboardReadCallback;
     557    ShClBackendSetCallbacks(pBackend, &ShClCallbacks);
     558
     559    /* Set the right clipboard mode, so that the guest can read from the host. */
     560    tstClipboardSetMode(TstHgcmMockSvcInst(), VBOX_SHCL_MODE_BIDIRECTIONAL);
     561
     562    /* Start the host thread first, so that the guest thread can connect to it later. */
     563    TSTHGCMUTILSHOSTCALLBACKS HostCallbacks;
     564    RT_ZERO(HostCallbacks);
     565    HostCallbacks.pfnOnClientConnected = tstTestReadFromHost_ClientConnectedCallback;
     566    TstHGCMUtilsHostThreadStart(&pTstCtx->HGCM, &HostCallbacks, pTstCtx /* pvUser */);
     567
     568    PCLIPBOARDTESTTASK pTask  = &pTstCtx->Task;
     569    AssertPtr(pTask);
     570    pTask->enmFmtGst   = VBOX_SHCL_FMT_UNICODETEXT;
     571    pTask->enmFmtHst   = pTask->enmFmtGst;
     572    pTask->cbChunk     = RTRandU32Ex(1, 512);
     573    pTask->cbData      = RT_ALIGN_32(pTask->cbChunk * RTRandU32Ex(1, 16), 2);
     574    Assert(pTask->cbData % sizeof(RTUTF16) == 0);
     575#if !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2)
     576    pTask->pvData      = tstGenerateUtf8StringA(pTask->cbData);
     577    pTask->cbData++; /* Add terminating zero. */
     578#else
     579    pTask->pvData      = tstGenerateUtf16StringA(pTask->cbData / sizeof(RTUTF16));
     580    pTask->cbData     += sizeof(RTUTF16); /* Add terminating zero. */
    807581#endif
    808 
    809 #if 0
    810     for (;;)
    811     {
    812         PVBGLR3CLIPBOARDEVENT pEvent = (PVBGLR3CLIPBOARDEVENT)RTMemAllocZ(sizeof(VBGLR3CLIPBOARDEVENT));
    813         AssertPtrBreakStmt(pEvent, rc = VERR_NO_MEMORY);
    814 
    815         uint32_t idMsg  = 0;
    816         uint32_t cParms = 0;
    817         RTTEST_CHECK_RC_OK(g_hTest, VbglR3ClipboardMsgPeekWait(&pCtx->Guest.CmdCtx, &idMsg, &cParms, NULL /* pidRestoreCheck */));
    818         RTTEST_CHECK_RC_OK(g_hTest, VbglR3ClipboardEventGetNext(idMsg, cParms, &pCtx->Guest.CmdCtx, pEvent));
    819 
    820         if (pEvent)
    821         {
    822             VbglR3ClipboardEventFree(pEvent);
    823             pEvent = NULL;
    824         }
    825 
    826         if (ASMAtomicReadBool(&pCtx->Guest.fShutdown))
    827             break;
    828 
    829         RTThreadSleep(100);
    830     }
    831 #endif
    832 
    833     RTTEST_CHECK_RC_OK(g_hTest, VbglR3ClipboardDisconnectEx(&pCtx->Guest.CmdCtx));
    834 
     582    pTask->cbProcessed = 0;
     583
     584    RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Host data (%RU32):\n%.*Rhxd\n", pTask->cbData, pTask->cbData, pTask->pvData);
    835585    return VINF_SUCCESS;
    836586}
    837587
    838 static DECLCALLBACK(int) tstTestReadFromHostExec(PTESTPARMS pTstParms, void *pvCtx)
    839 {
    840     RT_NOREF(pvCtx, pTstParms);
    841 
    842     PTESTTASK pTask = &pTstParms->pTstCtx->Task;
    843 
    844     pTask->enmFmtGst = VBOX_SHCL_FMT_UNICODETEXT;
    845     pTask->enmFmtHst = pTask->enmFmtGst;
    846     pTask->pvData    = RTStrAPrintf2("foo!");
    847     pTask->cbData    = strlen((char *)pTask->pvData) + 1;
    848     pTask->cbChunk   = pTask->cbData;
    849 
    850     PTSTHGCMMOCKSVC    pSvc        = TstHgcmMockSvcInst();
    851     PTSTHGCMMOCKCLIENT pMockClient = TstHgcmMockSvcWaitForConnect(pSvc);
    852 
    853     AssertPtrReturn(pMockClient, VERR_INVALID_POINTER);
     588static DECLCALLBACK(int) tstTestReadFromHostExec(PCLIPBOARDTESTCTX pTstCtx, void *pvCtx)
     589{
     590    RT_NOREF(pvCtx);
     591
     592    TstHGCMUtilsGuestThreadStart(&pTstCtx->HGCM, tstTestReadFromHost_ThreadGuest, pTstCtx);
     593
     594    PTSTHGCMUTILSTASK pTask = (PTSTHGCMUTILSTASK)TstHGCMUtilsTaskGetCurrent(&pTstCtx->HGCM);
    854595
    855596    bool fUseMock = false;
    856597    TSTUSERMOCK UsrMock;
    857598    if (fUseMock)
    858         tstShClUserMockInit(&UsrMock, "tstX11Hst");
    859 
    860     RTThreadSleep(RT_MS_1SEC * 4);
    861 
    862 #if 1
    863     PSHCLBACKEND pBackend = ShClSvcGetBackend();
    864 
    865     ShClBackendReportFormats(pBackend, (PSHCLCLIENT)pMockClient->pvClient, pTask->enmFmtHst);
    866     tstTaskWait(pTask, RT_MS_30SEC);
    867 #endif
    868 
    869 RTThreadSleep(RT_MS_30SEC);
    870 
    871     //PSHCLCLIENT pClient = &pMockClient->Client;
    872 
    873 #if 1
    874     if (1)
    875     {
    876         //RTTEST_CHECK_RC_OK(g_hTest, ShClBackendMockSetData(pBackend, pTask->enmFmt, pwszStr, cbData));
    877         //RTMemFree(pwszStr);
    878     }
    879 #endif
     599        tstTestReadFromHost_MockInit(&UsrMock, "tstX11Hst");
     600
     601    /* Wait until the task has been finished. */
     602    TstHGCMUtilsTaskWait(pTask, RT_MS_30SEC);
    880603
    881604    if (fUseMock)
    882         tstShClUserMockDestroy(&UsrMock);
     605        tstTestReadFromHost_MockDestroy(&UsrMock);
    883606
    884607    return VINF_SUCCESS;
    885608}
    886609
    887 static DECLCALLBACK(int) tstTestReadFromHostSetup(PTESTPARMS pTstParms, void **ppvCtx)
    888 {
    889     RT_NOREF(ppvCtx);
    890 
    891     PTESTCTX pCtx = pTstParms->pTstCtx;
    892 
    893     tstHostStart(pCtx);
    894 
    895     PSHCLBACKEND pBackend = ShClSvcGetBackend();
    896 
    897     SHCLCALLBACKS Callbacks;
    898     RT_ZERO(Callbacks);
    899     Callbacks.pfnReportFormats = tstShClUserMockReportFormatsCallback;
    900     //Callbacks.pfnOnRequestDataFromSource = tstTestReadFromHost_RequestDataFromSourceCallback;
    901     Callbacks.pfnOnClipboardRead     = tstShClUserMockOnGetDataCallback;
    902     ShClBackendSetCallbacks(pBackend, &Callbacks);
    903 
    904     tstGuestStart(pCtx, tstTestReadFromHostThreadGuest);
    905 
    906     RTThreadSleep(1000);
    907 
    908     tstSetMode(pCtx->pSvc, VBOX_SHCL_MODE_BIDIRECTIONAL);
    909 
    910     return VINF_SUCCESS;
    911 }
    912 
    913 static DECLCALLBACK(int) tstTestReadFromHostDestroy(PTESTPARMS pTstParms, void *pvCtx)
     610static DECLCALLBACK(int) tstTestReadFromHostDestroy(PCLIPBOARDTESTCTX pTstCtx, void *pvCtx)
    914611{
    915612    RT_NOREF(pvCtx);
    916613
    917     int rc = VINF_SUCCESS;
    918 
    919     tstGuestStop(pTstParms->pTstCtx);
    920     tstHostStop(pTstParms->pTstCtx);
    921 
    922     return rc;
    923 }
     614    int vrc = TstHGCMUtilsGuestThreadStop(&pTstCtx->HGCM);
     615    AssertRC(vrc);
     616    vrc = TstHGCMUtilsHostThreadStop(&pTstCtx->HGCM);
     617    AssertRC(vrc);
     618
     619    return vrc;
     620}
     621
     622
     623/*********************************************************************************************************************************
     624 * Main                                                                                                                          *
     625 ********************************************************************************************************************************/
    924626
    925627/** Test definition table. */
    926 TESTDESC g_aTests[] =
    927 {
     628CLIPBOARDTESTDESC g_aTests[] =
     629{
     630    /* Tests guest reading clipboard data from the host.  */
    928631    { tstTestReadFromHostSetup,       tstTestReadFromHostExec,      tstTestReadFromHostDestroy }
    929632};
     
    931634unsigned g_cTests = RT_ELEMENTS(g_aTests);
    932635
    933 static int tstOne(PTSTHGCMMOCKSVC pSvc, PTESTDESC pTstDesc)
    934 {
    935     PTESTCTX pTstCtx = &g_TstCtx;
    936 
    937     TESTPARMS TstParms;
    938     RT_ZERO(TstParms);
    939 
    940     pTstCtx->pSvc    = pSvc;
    941     TstParms.pTstCtx = pTstCtx;
     636static int tstOne(PTESTDESC pTstDesc)
     637{
     638    PCLIPBOARDTESTCTX pTstCtx = &g_TstCtx;
    942639
    943640    void *pvCtx;
    944     int rc = pTstDesc->pfnSetup(&TstParms, &pvCtx);
     641    int rc = pTstDesc->pfnSetup(pTstCtx, &pvCtx);
    945642    if (RT_SUCCESS(rc))
    946643    {
    947         rc = pTstDesc->pfnExec(&TstParms, pvCtx);
    948 
    949         int rc2 = pTstDesc->pfnDestroy(&TstParms, pvCtx);
     644        rc = pTstDesc->pfnExec(pTstCtx, pvCtx);
     645
     646        int rc2 = pTstDesc->pfnDestroy(pTstCtx, pvCtx);
    950647        if (RT_SUCCESS(rc))
    951648            rc = rc2;
     
    969666    RTTestBanner(g_hTest);
    970667
     668#ifndef DEBUG_andy
    971669    /* Don't let assertions in the host service panic (core dump) the test cases. */
    972670    RTAssertSetMayPanic(false);
    973 
    974     PTSTHGCMMOCKSVC pSvc = TstHgcmMockSvcInst();
    975 
     671#endif
     672
     673    PTSTHGCMMOCKSVC const pSvc = TstHgcmMockSvcInst();
    976674    TstHgcmMockSvcCreate(pSvc, sizeof(SHCLCLIENT));
    977675    TstHgcmMockSvcStart(pSvc);
     
    980678     * Run the tests.
    981679     */
    982     if (1)
     680    if (0)
    983681    {
    984682        testGuestSimple();
    985         testGuestWrite();
    986683        testHostCall();
    987         testHostGetMsgOld();
    988684    }
    989685
    990686    RT_ZERO(g_TstCtx);
    991     tstTaskInit(&g_TstCtx.Task);
     687
     688    PTSTHGCMUTILSCTX pCtx = &g_TstCtx.HGCM;
     689    TstHGCMUtilsCtxInit(pCtx, pSvc);
     690
     691    PTSTHGCMUTILSTASK pTask = (PTSTHGCMUTILSTASK)TstHGCMUtilsTaskGetCurrent(pCtx);
     692    TstHGCMUtilsTaskInit(pTask);
     693    pTask->pvUser = &g_TstCtx.Task;
     694
    992695    for (unsigned i = 0; i < RT_ELEMENTS(g_aTests); i++)
    993         tstOne(pSvc, &g_aTests[i]);
    994     tstTaskDestroy(&g_TstCtx.Task);
     696        tstOne(&g_aTests[i]);
     697
     698    TstHGCMUtilsTaskDestroy(pTask);
    995699
    996700    TstHgcmMockSvcStop(pSvc);
     
    1002706    return RTTestSummaryAndDestroy(g_hTest);
    1003707}
     708
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette