VirtualBox

Changeset 98576 in vbox


Ignore:
Timestamp:
Feb 15, 2023 1:48:41 AM (2 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
155862
Message:

HGCMMock*.h: Split out the code into .cpp files.

Location:
trunk
Files:
5 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/GuestHost/HGCMMock.h

    r98574 r98576  
    1 /* $Id$ */
    21/** @file
    3  * HGCMMock.h: Mocking framework for testing HGCM-based host services +
    4  *             Vbgl code on the host side.
     2 * TstHGCMMock.h - Mocking framework for testing HGCM-based host services.
    53 *
    6  *             Goal is to run host service + Vbgl code as unmodified as
    7  *             possible as part of testcases to gain test coverage which
    8  *             otherwise wouldn't possible for heavily user-centric features
    9  *             like Shared Clipboard or drag'n drop (DnD).
     4 * The goal is to run host service + Vbgl code as unmodified as possible as
     5 * part of testcases to gain test coverage which otherwise wouldn't possible
     6 * for heavily user-centric features like Shared Clipboard or drag'n drop (DnD).
     7 *
     8 * Currently, though, it's only the service that runs unmodified, the
     9 * testcases does custom Vbgl work.
    1010 */
    1111
     
    4747#endif
    4848
    49 #include <iprt/types.h>
     49#ifdef IN_RING3
    5050
    51 #include <iprt/asm.h>
    52 #include <iprt/assert.h>
    5351#include <iprt/list.h>
    54 #include <iprt/mem.h>
    55 #include <iprt/rand.h>
    56 #include <iprt/semaphore.h>
    57 #include <iprt/test.h>
    58 #include <iprt/time.h>
    59 #include <iprt/thread.h>
    60 #include <iprt/utf16.h>
    61 
    62 #include <VBox/err.h>
    6352#include <VBox/VBoxGuestLib.h>
    6453#include <VBox/hgcmsvc.h>
    6554
    66 
    67 /*********************************************************************************************************************************
    68 *  Definitions.                                                                                                                  *
    69 *********************************************************************************************************************************/
    70 
    71 #if defined(IN_RING3) /* Only R3 parts implemented so far. */
    72 
    73 RT_C_DECLS_BEGIN
    74 
    75 DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad(VBOXHGCMSVCFNTABLE *ptable);
    76 
    77 RT_C_DECLS_END
    78 
    79 # define VBGLR3DECL(type) DECL_HIDDEN_NOTHROW(type) VBOXCALL
    8055
    8156/** Simple call handle structure for the guest call completion callback. */
     
    194169} TSTHGCMMOCKSVC;
    195170
    196 /** Static HGCM service to mock. */
    197 static TSTHGCMMOCKSVC g_tstHgcmSvc;
    198171
    199 
    200 /*********************************************************************************************************************************
    201 *  Prototypes.                                                                                                                   *
    202 *********************************************************************************************************************************/
    203172PTSTHGCMMOCKSVC    TstHgcmMockSvcInst(void);
    204173PTSTHGCMMOCKCLIENT TstHgcmMockSvcWaitForConnectEx(PTSTHGCMMOCKSVC pSvc, RTMSINTERVAL msTimeout);
     
    211180int                TstHgcmMockSvcHostCall(PTSTHGCMMOCKSVC pSvc, void *pvService, int32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    212181
     182RT_C_DECLS_BEGIN
     183DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad(VBOXHGCMSVCFNTABLE *pTable);
     184RT_C_DECLS_END
     185
     186# undef VBGLR3DECL
     187# define VBGLR3DECL(type) DECL_HIDDEN_NOTHROW(type) VBOXCALL
    213188VBGLR3DECL(int)    VbglR3HGCMConnect(const char *pszServiceName, HGCMCLIENTID *pidClient);
    214189VBGLR3DECL(int)    VbglR3HGCMDisconnect(HGCMCLIENTID idClient);
     
    217192
    218193
    219 /*********************************************************************************************************************************
    220 *  Internal functions                                                                                                           *
    221 *********************************************************************************************************************************/
    222 
    223 /**
    224  * Initializes a HGCM mock client.
    225  *
    226  * @return VBox status code.
    227  * @param  pClient              Client instance to initialize.
    228  * @param  idClient             HGCM client ID to assign.
    229  * @param  cbClient             Size (in bytes) of service-specific (opaque) client data to allocate.
    230  */
    231 static int tstHgcmMockClientInit(PTSTHGCMMOCKCLIENT pClient, uint32_t idClient, size_t cbClient)
    232 {
    233     RT_BZERO(pClient, sizeof(TSTHGCMMOCKCLIENT));
    234 
    235     pClient->idClient = idClient;
    236     if (cbClient)
    237     {
    238         pClient->pvClient = RTMemAllocZ(cbClient);
    239         AssertPtrReturn(pClient->pvClient, VERR_NO_MEMORY);
    240         pClient->cbClient = cbClient;
    241     }
    242 
    243     return RTSemEventCreate(&pClient->hEvent);
    244 }
    245 
    246 /**
    247  * Destroys a HGCM mock client.
    248  *
    249  * @return VBox status code.
    250  * @param  pClient              Client instance to destroy.
    251  */
    252 static int tstHgcmMockClientDestroy(PTSTHGCMMOCKCLIENT pClient)
    253 {
    254     int rc = RTSemEventDestroy(pClient->hEvent);
    255     if (RT_SUCCESS(rc))
    256     {
    257         if (pClient->pvClient)
    258         {
    259             Assert(pClient->cbClient);
    260             RTMemFree(pClient->pvClient);
    261             pClient->pvClient = NULL;
    262             pClient->cbClient = 0;
    263         }
    264 
    265         pClient->hEvent = NIL_RTSEMEVENT;
    266     }
    267 
    268     return rc;
    269 }
    270 
    271 /* @copydoc VBOXHGCMSVCFNTABLE::pfnConnect */
    272 static DECLCALLBACK(int) tstHgcmMockSvcConnect(PTSTHGCMMOCKSVC pSvc, void *pvService, uint32_t *pidClient)
    273 {
    274     RT_NOREF(pvService);
    275 
    276     PTSTHGCMMOCKFN pFn = (PTSTHGCMMOCKFN)RTMemAllocZ(sizeof(TSTHGCMMOCKFN));
    277     AssertPtrReturn(pFn, VERR_NO_MEMORY);
    278 
    279     PTSTHGCMMOCKCLIENT pClient = &pSvc->aHgcmClient[pSvc->uNextClientId];
    280 
    281     int rc = tstHgcmMockClientInit(pClient, pSvc->uNextClientId, pSvc->fnTable.cbClient);
    282     if (RT_FAILURE(rc))
    283         return rc;
    284 
    285     pFn->enmType = TSTHGCMMOCKFNTYPE_CONNECT;
    286     pFn->pClient = pClient;
    287 
    288     RTListAppend(&pSvc->lstCall, &pFn->Node);
    289     pFn = NULL; /* Thread takes ownership now. */
    290 
    291     int rc2 = RTSemEventSignal(pSvc->hEventQueue);
    292     AssertRCReturn(rc2, rc2);
    293     rc2 = RTSemEventWait(pClient->hEvent, RT_MS_30SEC);
    294     AssertRCReturn(rc2, rc2);
    295 
    296     ASMAtomicIncU32(&pSvc->uNextClientId);
    297 
    298     rc2 = RTSemEventSignal(pSvc->hEventConnect);
    299     AssertRCReturn(rc2, rc2);
    300 
    301     *pidClient = pClient->idClient;
    302 
    303     return VINF_SUCCESS;
    304 }
    305 
    306 /* @copydoc VBOXHGCMSVCFNTABLE::pfnDisconnect */
    307 static DECLCALLBACK(int) tstHgcmMockSvcDisconnect(PTSTHGCMMOCKSVC pSvc, void *pvService, uint32_t idClient)
    308 {
    309     RT_NOREF(pvService);
    310 
    311     PTSTHGCMMOCKCLIENT pClient = &pSvc->aHgcmClient[idClient];
    312 
    313     PTSTHGCMMOCKFN pFn = (PTSTHGCMMOCKFN)RTMemAllocZ(sizeof(TSTHGCMMOCKFN));
    314     AssertPtrReturn(pFn, VERR_NO_MEMORY);
    315 
    316     pFn->enmType = TSTHGCMMOCKFNTYPE_DISCONNECT;
    317     pFn->pClient = pClient;
    318 
    319     RTListAppend(&pSvc->lstCall, &pFn->Node);
    320     pFn = NULL; /* Thread takes ownership now. */
    321 
    322     int rc2 = RTSemEventSignal(pSvc->hEventQueue);
    323     AssertRCReturn(rc2, rc2);
    324 
    325     rc2 = RTSemEventWait(pClient->hEvent, RT_MS_30SEC);
    326     AssertRCReturn(rc2, rc2);
    327 
    328     return tstHgcmMockClientDestroy(pClient);
    329 }
    330 
    331 /* @copydoc VBOXHGCMSVCFNTABLE::pfnCall */
    332 static DECLCALLBACK(int) tstHgcmMockSvcCall(PTSTHGCMMOCKSVC pSvc, void *pvService, VBOXHGCMCALLHANDLE callHandle, uint32_t idClient, void *pvClient,
    333                                             int32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    334 {
    335     RT_NOREF(pvService, pvClient);
    336 
    337     PTSTHGCMMOCKCLIENT pClient = &pSvc->aHgcmClient[idClient];
    338 
    339     PTSTHGCMMOCKFN pFn = (PTSTHGCMMOCKFN)RTMemAllocZ(sizeof(TSTHGCMMOCKFN));
    340     AssertPtrReturn(pFn, VERR_NO_MEMORY);
    341 
    342     const size_t cbParms = cParms * sizeof(VBOXHGCMSVCPARM);
    343 
    344     pFn->enmType         = TSTHGCMMOCKFNTYPE_CALL;
    345     pFn->pClient         = pClient;
    346 
    347     pFn->u.Call.hCall    = callHandle;
    348     pFn->u.Call.iFunc    = function;
    349     PVBOXHGCMSVCPARM const paParmsCopy = (PVBOXHGCMSVCPARM)RTMemDup(paParms, cbParms);
    350     pFn->u.Call.pParms   = paParmsCopy;
    351     AssertPtrReturn(pFn->u.Call.pParms, VERR_NO_MEMORY);
    352     pFn->u.Call.cParms   = cParms;
    353 
    354     RTListAppend(&pSvc->lstCall, &pFn->Node);
    355 
    356     int rc2 = RTSemEventSignal(pSvc->hEventQueue);
    357     AssertRCReturn(rc2, rc2);
    358 
    359     rc2 = RTSemEventWait(pClient->hEvent, RT_INDEFINITE_WAIT);
    360     AssertRCReturn(rc2, rc2);
    361 
    362     memcpy(paParms, paParmsCopy, cbParms);
    363     /** @todo  paParmsCopy is leaked, right? Doesn't appear to be a
    364      *         use-after-free here. (pFn is freeded though) */
    365 
    366     return VINF_SUCCESS; /** @todo Return host call rc */
    367 }
    368 
    369 /* @copydoc VBOXHGCMSVCFNTABLE::pfnHostCall */
    370 /** Note: Public for also being able to test host calls via testcases. */
    371 int TstHgcmMockSvcHostCall(PTSTHGCMMOCKSVC pSvc, void *pvService, int32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    372 {
    373     RT_NOREF(pvService);
    374     AssertReturn(pSvc->cHostCallers == 0, VERR_WRONG_ORDER); /* Only one host call at a time. */
    375 
    376     pSvc->cHostCallers++;
    377 
    378     PTSTHGCMMOCKFN pFn = (PTSTHGCMMOCKFN)RTMemAllocZ(sizeof(TSTHGCMMOCKFN));
    379     AssertPtrReturn(pFn, VERR_INVALID_POINTER);
    380 
    381     pFn->enmType           = TSTHGCMMOCKFNTYPE_HOST_CALL;
    382     pFn->u.HostCall.iFunc  = function;
    383     if (cParms)
    384     {
    385         pFn->u.HostCall.pParms = (PVBOXHGCMSVCPARM)RTMemDup(paParms, cParms * sizeof(VBOXHGCMSVCPARM));
    386         AssertPtrReturn(pFn->u.HostCall.pParms, VERR_NO_MEMORY);
    387         pFn->u.HostCall.cParms = cParms;
    388     }
    389 
    390     RTListAppend(&pSvc->lstCall, &pFn->Node);
    391     pFn = NULL; /* Thread takes ownership now. */
    392 
    393     int rc2 = RTSemEventSignal(pSvc->hEventQueue);
    394     AssertRC(rc2);
    395 
    396     rc2 = RTSemEventWait(pSvc->hEventHostCall, RT_INDEFINITE_WAIT);
    397     AssertRCReturn(rc2, rc2);
    398 
    399     Assert(pSvc->cHostCallers);
    400     pSvc->cHostCallers--;
    401 
    402     return pSvc->rcHostCall;
    403 }
    404 
    405 /**
    406  * Call completion callback for guest calls.
    407  *
    408  * @return VBox status code.
    409  * @param  callHandle           Call handle to complete.
    410  * @param  rc                   Return code to return to the caller.
    411  */
    412 static DECLCALLBACK(int) tstHgcmMockSvcCallComplete(VBOXHGCMCALLHANDLE callHandle, int32_t rc)
    413 {
    414     PTSTHGCMMOCKSVC pSvc = TstHgcmMockSvcInst();
    415 
    416     size_t i = 0;
    417     for (; RT_ELEMENTS(pSvc->aHgcmClient); i++)
    418     {
    419         PTSTHGCMMOCKCLIENT pClient = &pSvc->aHgcmClient[i];
    420         if (&pClient->hCall == callHandle) /* Slow, but works for now. */
    421         {
    422             if (rc == VINF_HGCM_ASYNC_EXECUTE)
    423             {
    424                 Assert(pClient->fAsyncExec == false);
    425             }
    426             else /* Complete call + notify client. */
    427             {
    428                 callHandle->rc = rc;
    429 
    430                 int rc2 = RTSemEventSignal(pClient->hEvent);
    431                 AssertRCReturn(rc2, rc2);
    432             }
    433 
    434             return VINF_SUCCESS;
    435         }
    436     }
    437 
    438     return VERR_NOT_FOUND;
    439 }
    440 
    441 /**
    442  * Main thread of HGCM mock service.
    443  *
    444  * @return VBox status code.
    445  * @param  hThread              Thread handle.
    446  * @param  pvUser               User-supplied data of type PTSTHGCMMOCKSVC.
    447  */
    448 static DECLCALLBACK(int) tstHgcmMockSvcThread(RTTHREAD hThread, void *pvUser)
    449 {
    450     RT_NOREF(hThread);
    451     PTSTHGCMMOCKSVC pSvc = (PTSTHGCMMOCKSVC)pvUser;
    452 
    453     pSvc->uNextClientId      = 0;
    454 
    455     pSvc->fnTable.cbSize     = sizeof(pSvc->fnTable);
    456     pSvc->fnTable.u32Version = VBOX_HGCM_SVC_VERSION;
    457 
    458     RT_ZERO(pSvc->fnHelpers);
    459     pSvc->fnHelpers.pfnCallComplete = tstHgcmMockSvcCallComplete;
    460     pSvc->fnTable.pHelpers          = &pSvc->fnHelpers;
    461 
    462     int rc = VBoxHGCMSvcLoad(&pSvc->fnTable);
    463     if (RT_SUCCESS(rc))
    464     {
    465         RTThreadUserSignal(hThread);
    466 
    467         for (;;)
    468         {
    469             rc = RTSemEventWait(pSvc->hEventQueue, 10 /* ms */);
    470             if (ASMAtomicReadBool(&pSvc->fShutdown))
    471             {
    472                 rc = VINF_SUCCESS;
    473                 break;
    474             }
    475             if (rc == VERR_TIMEOUT)
    476                 continue;
    477 
    478             PTSTHGCMMOCKFN pFn = RTListGetFirst(&pSvc->lstCall, TSTHGCMMOCKFN, Node);
    479             if (pFn)
    480             {
    481                 switch (pFn->enmType)
    482                 {
    483                     case TSTHGCMMOCKFNTYPE_CONNECT:
    484                     {
    485                         rc = pSvc->fnTable.pfnConnect(pSvc->fnTable.pvService,
    486                                                       pFn->pClient->idClient, pFn->pClient->pvClient,
    487                                                       VMMDEV_REQUESTOR_USR_NOT_GIVEN /* fRequestor */, false /* fRestoring */);
    488 
    489                         int rc2 = RTSemEventSignal(pFn->pClient->hEvent);
    490                         AssertRC(rc2);
    491                         break;
    492                     }
    493 
    494                     case TSTHGCMMOCKFNTYPE_DISCONNECT:
    495                     {
    496                         rc = pSvc->fnTable.pfnDisconnect(pSvc->fnTable.pvService,
    497                                                          pFn->pClient->idClient, pFn->pClient->pvClient);
    498 
    499                         int rc2 = RTSemEventSignal(pFn->pClient->hEvent);
    500                         AssertRC(rc2);
    501                         break;
    502                     }
    503 
    504                     case TSTHGCMMOCKFNTYPE_CALL:
    505                     {
    506                         pSvc->fnTable.pfnCall(pSvc->fnTable.pvService, pFn->u.Call.hCall, pFn->pClient->idClient,
    507                                               pFn->pClient->pvClient, pFn->u.Call.iFunc, pFn->u.Call.cParms,
    508                                               pFn->u.Call.pParms, RTTimeNanoTS());
    509 
    510                         /* Note: Call will be completed in the call completion callback. */
    511                         break;
    512                     }
    513 
    514                     case TSTHGCMMOCKFNTYPE_HOST_CALL:
    515                     {
    516                         pSvc->rcHostCall = pSvc->fnTable.pfnHostCall(pSvc->fnTable.pvService, pFn->u.HostCall.iFunc,
    517                                                                      pFn->u.HostCall.cParms, pFn->u.HostCall.pParms);
    518 
    519                         int rc2 = RTSemEventSignal(pSvc->hEventHostCall);
    520                         AssertRC(rc2);
    521                         break;
    522                     }
    523 
    524                     default:
    525                         AssertFailed();
    526                         break;
    527                 }
    528                 RTListNodeRemove(&pFn->Node);
    529                 RTMemFree(pFn);
    530             }
    531         }
    532     }
    533 
    534     return rc;
    535 }
    536 
    537 
    538 /*********************************************************************************************************************************
    539 *  Public functions                                                                                                           *
    540 *********************************************************************************************************************************/
    541 
    542 /**
    543  * Returns the pointer to the HGCM mock service instance.
    544  *
    545  * @return Pointer to HGCM mock service instance.
    546  */
    547 PTSTHGCMMOCKSVC TstHgcmMockSvcInst(void)
    548 {
    549     return &g_tstHgcmSvc;
    550 }
    551 
    552 /**
    553  * Waits for a HGCM mock client to connect, extended version.
    554  *
    555  * @return Pointer to connected client, or NULL if ran into timeout.
    556  * @param  pSvc                 HGCM mock service instance.
    557  * @param  msTimeout            Timeout (in ms) to wait for connection.
    558  */
    559 PTSTHGCMMOCKCLIENT TstHgcmMockSvcWaitForConnectEx(PTSTHGCMMOCKSVC pSvc, RTMSINTERVAL msTimeout)
    560 {
    561     int rc = RTSemEventWait(pSvc->hEventConnect, msTimeout);
    562     if (RT_SUCCESS(rc))
    563     {
    564         Assert(pSvc->uNextClientId);
    565         return &pSvc->aHgcmClient[pSvc->uNextClientId - 1];
    566     }
    567     return NULL;
    568 }
    569 
    570 /**
    571  * Waits for a HGCM mock client to connect.
    572  *
    573  * @return Pointer to connected client, or NULL if waiting for connection was aborted.
    574  * @param  pSvc                 HGCM mock service instance.
    575  */
    576 PTSTHGCMMOCKCLIENT TstHgcmMockSvcWaitForConnect(PTSTHGCMMOCKSVC pSvc)
    577 {
    578     return TstHgcmMockSvcWaitForConnectEx(pSvc, RT_MS_30SEC);
    579 }
    580 
    581 /**
    582  * Creates a HGCM mock service instance.
    583  *
    584  * @return VBox status code.
    585  * @param  pSvc                 HGCM mock service instance to create.
    586  */
    587 int TstHgcmMockSvcCreate(PTSTHGCMMOCKSVC pSvc)
    588 {
    589     RT_ZERO(pSvc->aHgcmClient);
    590     pSvc->fShutdown = false;
    591     int rc = RTSemEventCreate(&pSvc->hEventQueue);
    592     if (RT_SUCCESS(rc))
    593     {
    594         rc = RTSemEventCreate(&pSvc->hEventHostCall);
    595         if (RT_SUCCESS(rc))
    596         {
    597             rc = RTSemEventCreate(&pSvc->hEventConnect);
    598             if (RT_SUCCESS(rc))
    599             {
    600                 RTListInit(&pSvc->lstCall);
    601             }
    602         }
    603     }
    604 
    605     return rc;
    606 }
    607 
    608 /**
    609  * Destroys a HGCM mock service instance.
    610  *
    611  * @return VBox status code.
    612  * @param  pSvc                 HGCM mock service instance to destroy.
    613  */
    614 int TstHgcmMockSvcDestroy(PTSTHGCMMOCKSVC pSvc)
    615 {
    616     int rc = RTSemEventDestroy(pSvc->hEventQueue);
    617     if (RT_SUCCESS(rc))
    618     {
    619         rc = RTSemEventDestroy(pSvc->hEventHostCall);
    620         if (RT_SUCCESS(rc))
    621             RTSemEventDestroy(pSvc->hEventConnect);
    622     }
    623     return rc;
    624 }
    625 
    626 /**
    627  * Starts a HGCM mock service instance.
    628  *
    629  * @return VBox status code.
    630  * @param  pSvc                 HGCM mock service instance to start.
    631  */
    632 int TstHgcmMockSvcStart(PTSTHGCMMOCKSVC pSvc)
    633 {
    634     int rc = RTThreadCreate(&pSvc->hThread, tstHgcmMockSvcThread, pSvc, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
    635                             "MockSvc");
    636     if (RT_SUCCESS(rc))
    637         rc = RTThreadUserWait(pSvc->hThread, RT_MS_30SEC);
    638 
    639     return rc;
    640 }
    641 
    642 /**
    643  * Stops a HGCM mock service instance.
    644  *
    645  * @return VBox status code.
    646  * @param  pSvc                 HGCM mock service instance to stop.
    647  */
    648 int TstHgcmMockSvcStop(PTSTHGCMMOCKSVC pSvc)
    649 {
    650     ASMAtomicWriteBool(&pSvc->fShutdown, true);
    651 
    652     int rcThread;
    653     int rc = RTThreadWait(pSvc->hThread, RT_MS_30SEC, &rcThread);
    654     if (RT_SUCCESS(rc))
    655         rc = rcThread;
    656     if (RT_SUCCESS(rc))
    657     {
    658         pSvc->hThread = NIL_RTTHREAD;
    659     }
    660 
    661     return rc;
    662 }
    663 
    664 
    665 /*********************************************************************************************************************************
    666 *   VbglR3 stubs                                                                                                                 *
    667 *********************************************************************************************************************************/
    668 
    669 /**
    670  * Connects to an HGCM mock service.
    671  *
    672  * @returns VBox status code
    673  * @param   pszServiceName  Name of the host service.
    674  * @param   pidClient       Where to put the client ID on success. The client ID
    675  *                          must be passed to all the other calls to the service.
    676  */
    677 VBGLR3DECL(int) VbglR3HGCMConnect(const char *pszServiceName, HGCMCLIENTID *pidClient)
    678 {
    679     RT_NOREF(pszServiceName);
    680 
    681     PTSTHGCMMOCKSVC pSvc = TstHgcmMockSvcInst();
    682 
    683     return tstHgcmMockSvcConnect(pSvc, pSvc->fnTable.pvService, pidClient);
    684 }
    685 
    686 /**
    687  * Disconnect from an HGCM mock service.
    688  *
    689  * @returns VBox status code.
    690  * @param   idClient        The client id returned by VbglR3HGCMConnect().
    691  */
    692 VBGLR3DECL(int) VbglR3HGCMDisconnect(HGCMCLIENTID idClient)
    693 {
    694     PTSTHGCMMOCKSVC pSvc = TstHgcmMockSvcInst();
    695 
    696     return tstHgcmMockSvcDisconnect(pSvc, pSvc->fnTable.pvService, idClient);
    697 }
    698 
    699 /**
    700  * Query the session ID of the mocked VM.
    701  *
    702  * @returns IPRT status code.
    703  * @param   pu64IdSession       Session id (out).
    704  */
    705 VBGLR3DECL(int) VbglR3GetSessionId(uint64_t *pu64IdSession)
    706 {
    707     if (pu64IdSession)
    708         *pu64IdSession = 42;
    709     return VINF_SUCCESS;
    710 }
    711 
    712 /**
    713  * Makes a fully prepared HGCM call to an HGCM mock service.
    714  *
    715  * @returns VBox status code.
    716  * @param   pInfo           Fully prepared HGCM call info.
    717  * @param   cbInfo          Size of the info.  This may sometimes be larger than
    718  *                          what the parameter count indicates because of
    719  *                          parameter changes between versions and such.
    720  */
    721 VBGLR3DECL(int) VbglR3HGCMCall(PVBGLIOCHGCMCALL pInfo, size_t cbInfo)
    722 {
    723     RT_NOREF(cbInfo);
    724 
    725     AssertMsg(pInfo->Hdr.cbIn  == cbInfo, ("cbIn=%#x cbInfo=%#zx\n", pInfo->Hdr.cbIn, cbInfo));
    726     AssertMsg(pInfo->Hdr.cbOut == cbInfo, ("cbOut=%#x cbInfo=%#zx\n", pInfo->Hdr.cbOut, cbInfo));
    727     Assert(sizeof(*pInfo) + pInfo->cParms * sizeof(HGCMFunctionParameter) <= cbInfo);
    728 
    729     HGCMFunctionParameter *offSrcParms = VBGL_HGCM_GET_CALL_PARMS(pInfo);
    730     PVBOXHGCMSVCPARM       paDstParms  = (PVBOXHGCMSVCPARM)RTMemAlloc(pInfo->cParms * sizeof(VBOXHGCMSVCPARM));
    731 
    732     uint16_t i = 0;
    733     for (; i < pInfo->cParms; i++)
    734     {
    735         switch (offSrcParms->type)
    736         {
    737             case VMMDevHGCMParmType_32bit:
    738             {
    739                 paDstParms[i].type     = VBOX_HGCM_SVC_PARM_32BIT;
    740                 paDstParms[i].u.uint32 = offSrcParms->u.value32;
    741                 break;
    742             }
    743 
    744             case VMMDevHGCMParmType_64bit:
    745             {
    746                 paDstParms[i].type     = VBOX_HGCM_SVC_PARM_64BIT;
    747                 paDstParms[i].u.uint64 = offSrcParms->u.value64;
    748                 break;
    749             }
    750 
    751             case VMMDevHGCMParmType_LinAddr:
    752             {
    753                 paDstParms[i].type           = VBOX_HGCM_SVC_PARM_PTR;
    754                 paDstParms[i].u.pointer.addr = (void *)offSrcParms->u.LinAddr.uAddr;
    755                 paDstParms[i].u.pointer.size = offSrcParms->u.LinAddr.cb;
    756                 break;
    757             }
    758 
    759             default:
    760                 AssertFailed();
    761                 break;
    762         }
    763 
    764         offSrcParms++;
    765     }
    766 
    767     PTSTHGCMMOCKSVC const pSvc = TstHgcmMockSvcInst();
    768 
    769     int rc2 = tstHgcmMockSvcCall(pSvc, pSvc->fnTable.pvService, &pSvc->aHgcmClient[pInfo->u32ClientID].hCall,
    770                                  pInfo->u32ClientID, pSvc->aHgcmClient[pInfo->u32ClientID].pvClient,
    771                                  pInfo->u32Function, pInfo->cParms, paDstParms);
    772     if (RT_SUCCESS(rc2))
    773     {
    774         offSrcParms = VBGL_HGCM_GET_CALL_PARMS(pInfo);
    775 
    776         for (i = 0; i < pInfo->cParms; i++)
    777         {
    778             paDstParms[i].type = offSrcParms->type;
    779             switch (paDstParms[i].type)
    780             {
    781                 case VMMDevHGCMParmType_32bit:
    782                     offSrcParms->u.value32 = paDstParms[i].u.uint32;
    783                     break;
    784 
    785                 case VMMDevHGCMParmType_64bit:
    786                     offSrcParms->u.value64 = paDstParms[i].u.uint64;
    787                     break;
    788 
    789                 case VMMDevHGCMParmType_LinAddr:
    790                 {
    791                     offSrcParms->u.LinAddr.cb = paDstParms[i].u.pointer.size;
    792                     break;
    793                 }
    794 
    795                 default:
    796                     AssertFailed();
    797                     break;
    798             }
    799 
    800             offSrcParms++;
    801         }
    802     }
    803 
    804     RTMemFree(paDstParms);
    805 
    806     if (RT_SUCCESS(rc2))
    807         rc2 = pSvc->aHgcmClient[pInfo->u32ClientID].hCall.rc;
    808 
    809     return rc2;
    810 }
    811 
    812194#endif /* IN_RING3 */
    813195
  • trunk/include/VBox/GuestHost/HGCMMockUtils.h

    r98103 r98576  
    1 /* $Id */
    21/** @file
    3  * HGCMMockUtils.h: Utility functions for the HGCM Mocking framework.
     2 * TstHGCMMockUtils.h - Utility functions for the HGCM Mocking framework.
    43 *
    54 * The utility functions are optional to the actual HGCM Mocking framework and
     
    6665#endif
    6766
    68 #include <iprt/err.h>
    69 #include <iprt/semaphore.h>
    70 #include <iprt/thread.h>
    71 #include <iprt/types.h>
    72 
    73 
    7467#include <VBox/GuestHost/HGCMMock.h>
    75 #include <VBox/VBoxGuestLib.h>
    76 
    77 
    78 #if defined(IN_RING3) /* Only R3 parts implemented so far. */
    7968
    8069/** Pointer to a HGCM Mock utils context. */
     
    143132
    144133
    145 /*********************************************************************************************************************************
    146 *  Prototypes.                                                                                                                   *
    147 *********************************************************************************************************************************/
    148134/** @name Context handling.
    149135 * @{ */
     
    171157
    172158
    173 /*********************************************************************************************************************************
    174  * Context                                                                                                                       *
    175  ********************************************************************************************************************************/
    176 /**
    177  * Initializes a HGCM Mock utils context.
    178  *
    179  * @param   pCtx                Context to intiialize.
    180  * @param   pSvc                HGCM Mock service instance to use.
    181  */
    182 void TstHGCMUtilsCtxInit(PTSTHGCMUTILSCTX pCtx, PTSTHGCMMOCKSVC pSvc)
    183 {
    184     RT_BZERO(pCtx, sizeof(TSTHGCMUTILSCTX));
    185 
    186     pCtx->pSvc = pSvc;
    187 }
    188 
    189 
    190 /*********************************************************************************************************************************
    191  * Tasks                                                                                                                         *
    192  ********************************************************************************************************************************/
    193 /**
    194  * Returns the current task of a HGCM Mock utils context.
    195  *
    196  * @returns Current task of a HGCM Mock utils context. NULL if no current task found.
    197  * @param   pCtx                HGCM Mock utils context.
    198  */
    199 PTSTHGCMUTILSTASK TstHGCMUtilsTaskGetCurrent(PTSTHGCMUTILSCTX pCtx)
    200 {
    201     /* Currently we only support one task at a time. */
    202     return &pCtx->Task;
    203 }
    204 
    205 /**
    206  * Initializes a HGCM Mock utils task.
    207  *
    208  * @returns VBox status code.
    209  * @param   pTask               Task to initialize.
    210  */
    211 int TstHGCMUtilsTaskInit(PTSTHGCMUTILSTASK pTask)
    212 {
    213     pTask->pvUser = NULL;
    214     pTask->rcCompleted = pTask->rcExpected = VERR_IPE_UNINITIALIZED_STATUS;
    215     return RTSemEventCreate(&pTask->hEvent);
    216 }
    217 
    218 /**
    219  * Destroys a HGCM Mock utils task.
    220  *
    221  * @returns VBox status code.
    222  * @param   pTask               Task to destroy.
    223  */
    224 void TstHGCMUtilsTaskDestroy(PTSTHGCMUTILSTASK pTask)
    225 {
    226     RTSemEventDestroy(pTask->hEvent);
    227 }
    228 
    229 /**
    230  * Waits for a HGCM Mock utils task to complete.
    231  *
    232  * @returns VBox status code.
    233  * @param   pTask               Task to wait for.
    234  * @param   msTimeout           Timeout (in ms) to wait.
    235  */
    236 int TstHGCMUtilsTaskWait(PTSTHGCMUTILSTASK pTask, RTMSINTERVAL msTimeout)
    237 {
    238     return RTSemEventWait(pTask->hEvent, msTimeout);
    239 }
    240 
    241 /**
    242  * Returns if the HGCM Mock utils task has been completed successfully.
    243  *
    244  * @returns \c true if successful, \c false if not.
    245  * @param   pTask               Task to check.
    246  */
    247 bool TstHGCMUtilsTaskOk(PTSTHGCMUTILSTASK pTask)
    248 {
    249     return pTask->rcCompleted == pTask->rcExpected;
    250 }
    251 
    252 /**
    253  * Returns if the HGCM Mock utils task has been completed (failed or succeeded).
    254  *
    255  * @returns \c true if completed, \c false if (still) running.
    256  * @param   pTask               Task to check.
    257  */
    258 bool TstHGCMUtilsTaskCompleted(PTSTHGCMUTILSTASK pTask)
    259 {
    260     return pTask->rcCompleted != VERR_IPE_UNINITIALIZED_STATUS;
    261 }
    262 
    263 /**
    264  * Signals a HGCM Mock utils task to complete its operation.
    265  *
    266  * @param   pTask               Task to complete.
    267  * @param   rc                  Task result to set for completion.
    268  */
    269 void TstHGCMUtilsTaskSignal(PTSTHGCMUTILSTASK pTask, int rc)
    270 {
    271     AssertMsg(pTask->rcCompleted == VERR_IPE_UNINITIALIZED_STATUS, ("Task already completed\n"));
    272     pTask->rcCompleted = rc;
    273     int rc2 = RTSemEventSignal(pTask->hEvent);
    274     AssertRC(rc2);
    275 }
    276 
    277 
    278 /*********************************************************************************************************************************
    279  * Threading                                                                                                                     *
    280  ********************************************************************************************************************************/
    281 
    282 /**
    283  * Thread worker for the guest side thread.
    284  *
    285  * @returns VBox status code.
    286  * @param   hThread             Thread handle.
    287  * @param   pvUser              Pointer of type PTSTHGCMUTILSCTX.
    288  *
    289  * @note    Runs in the guest thread.
    290  */
    291 static DECLCALLBACK(int) tstHGCMUtilsGuestThread(RTTHREAD hThread, void *pvUser)
    292 {
    293     RT_NOREF(hThread);
    294     PTSTHGCMUTILSCTX pCtx = (PTSTHGCMUTILSCTX)pvUser;
    295     AssertPtr(pCtx);
    296 
    297     RTThreadUserSignal(hThread);
    298 
    299     if (pCtx->Guest.pfnThread)
    300         return pCtx->Guest.pfnThread(pCtx, pCtx->Guest.pvUser);
    301 
    302     return VINF_SUCCESS;
    303 }
    304 
    305 /**
    306  * Starts the guest side thread.
    307  *
    308  * @returns VBox status code.
    309  * @param   pCtx                HGCM Mock utils context to start guest thread for.
    310  * @param   pFnThread           Pointer to custom thread worker function to call within the guest side thread.
    311  * @param   pvUser              User-supplied pointer to guest thread context data. Optional and can be NULL.
    312  */
    313 int TstHGCMUtilsGuestThreadStart(PTSTHGCMUTILSCTX pCtx, PFNTSTHGCMUTILSTHREAD pFnThread, void *pvUser)
    314 {
    315     pCtx->Guest.pfnThread = pFnThread;
    316     pCtx->Guest.pvUser    = pvUser;
    317 
    318     int rc = RTThreadCreate(&pCtx->Guest.hThread, tstHGCMUtilsGuestThread, pCtx, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
    319                             "tstShClGst");
    320     if (RT_SUCCESS(rc))
    321         rc = RTThreadUserWait(pCtx->Guest.hThread, RT_MS_30SEC);
    322 
    323     return rc;
    324 }
    325 
    326 /**
    327  * Stops the guest side thread.
    328  *
    329  * @returns VBox status code.
    330  * @param   pCtx                HGCM Mock utils context to stop guest thread for.
    331  */
    332 int TstHGCMUtilsGuestThreadStop(PTSTHGCMUTILSCTX pCtx)
    333 {
    334     ASMAtomicWriteBool(&pCtx->Guest.fShutdown, true);
    335 
    336     int rcThread;
    337     int rc = RTThreadWait(pCtx->Guest.hThread, RT_MS_30SEC, &rcThread);
    338     if (RT_SUCCESS(rc))
    339         rc = rcThread;
    340     if (RT_SUCCESS(rc))
    341         pCtx->Guest.hThread = NIL_RTTHREAD;
    342 
    343     return rc;
    344 }
    345 
    346 /**
    347  * Thread worker function for the host side HGCM service.
    348  *
    349  * @returns VBox status code.
    350  * @param   hThread             Thread handle.
    351  * @param   pvUser              Pointer of type PTSTHGCMUTILSCTX.
    352  *
    353  * @note    Runs in the host service thread.
    354  */
    355 static DECLCALLBACK(int) tstHGCMUtilsHostThreadWorker(RTTHREAD hThread, void *pvUser)
    356 {
    357     RT_NOREF(hThread);
    358     PTSTHGCMUTILSCTX pCtx = (PTSTHGCMUTILSCTX)pvUser;
    359     AssertPtr(pCtx);
    360 
    361     int rc = VINF_SUCCESS;
    362 
    363     RTThreadUserSignal(hThread);
    364 
    365     PTSTHGCMMOCKSVC const pSvc = TstHgcmMockSvcInst();
    366 
    367     for (;;)
    368     {
    369         if (ASMAtomicReadBool(&pCtx->Host.fShutdown))
    370             break;
    371 
    372         /* Wait for a new (mock) HGCM client to connect. */
    373         PTSTHGCMMOCKCLIENT pMockClient = TstHgcmMockSvcWaitForConnectEx(pSvc, 100 /* ms */);
    374         if (pMockClient) /* Might be NULL when timed out. */
    375         {
    376             if (pCtx->Host.Callbacks.pfnOnClientConnected)
    377                 /* ignore rc */ pCtx->Host.Callbacks.pfnOnClientConnected(pCtx, pMockClient, pCtx->Host.pvUser);
    378         }
    379     }
    380 
    381     return rc;
    382 }
    383 
    384 /**
    385  * Starts the host side thread.
    386  *
    387  * @returns VBox status code.
    388  * @param   pCtx                HGCM Mock utils context to start host thread for.
    389  * @param   pCallbacks          Pointer to host callback table to use.
    390  * @param   pvUser              User-supplied pointer to reach into the host thread callbacks.
    391  */
    392 int TstHGCMUtilsHostThreadStart(PTSTHGCMUTILSCTX pCtx, PTSTHGCMUTILSHOSTCALLBACKS pCallbacks, void *pvUser)
    393 {
    394     memcpy(&pCtx->Host.Callbacks, pCallbacks, sizeof(TSTHGCMUTILSHOSTCALLBACKS));
    395     pCtx->Host.pvUser = pvUser;
    396 
    397     int rc = RTThreadCreate(&pCtx->Host.hThread, tstHGCMUtilsHostThreadWorker, pCtx, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
    398                             "tstShClHst");
    399     if (RT_SUCCESS(rc))
    400         rc = RTThreadUserWait(pCtx->Host.hThread, RT_MS_30SEC);
    401 
    402     return rc;
    403 }
    404 
    405 /**
    406  * Stops the host side thread.
    407  *
    408  * @returns VBox status code.
    409  * @param   pCtx                HGCM Mock utils context to stop host thread for.
    410  */
    411 int TstHGCMUtilsHostThreadStop(PTSTHGCMUTILSCTX pCtx)
    412 {
    413     ASMAtomicWriteBool(&pCtx->Host.fShutdown, true);
    414 
    415     int rcThread;
    416     int rc = RTThreadWait(pCtx->Host.hThread, RT_MS_30SEC, &rcThread);
    417     if (RT_SUCCESS(rc))
    418         rc = rcThread;
    419     if (RT_SUCCESS(rc))
    420         pCtx->Host.hThread = NIL_RTTHREAD;
    421 
    422     return rc;
    423 }
    424 
    425 #endif /* IN_RING3 */
    426 
    427159#endif /* !VBOX_INCLUDED_GuestHost_HGCMMockUtils_h */
    428160
  • trunk/src/VBox/HostServices/GuestControl/testcase/Makefile.kmk

    r98533 r98576  
    4646 tstGuestControlMockHGCM_SOURCES  = \
    4747        ../VBoxGuestControlSvc.cpp \
     48        ../../testcase/TstHgcmMock.cpp \
    4849        $(PATH_ROOT)/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp \
    4950        $(PATH_ROOT)/src/VBox/HostServices/common/message.cpp \
  • trunk/src/VBox/HostServices/SharedClipboard/testcase/Makefile.kmk

    r98415 r98576  
    4343 tstClipboardMockHGCM_DEFS    = VBOX_WITH_HGCM VBOX_WITH_SHARED_CLIPBOARD
    4444 tstClipboardMockHGCM_SOURCES = \
     45        tstClipboardMockHGCM.cpp \
    4546        ../VBoxSharedClipboardSvc.cpp \
     47        ../../testcase/TstHgcmMock.cpp \
     48        ../../testcase/TstHgcmMockUtils.cpp \
    4649        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp \
    4750        $(PATH_ROOT)/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp \
    48         $(PATH_ROOT)/src/VBox/HostServices/common/message.cpp \
    49         tstClipboardMockHGCM.cpp
     51        $(PATH_ROOT)/src/VBox/HostServices/common/message.cpp
    5052 tstClipboardMockHGCM_LIBS    = $(LIB_RUNTIME)
    5153
  • trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardMockHGCM.cpp

    r98575 r98576  
    2626 */
    2727
     28
     29/*********************************************************************************************************************************
     30*   Header Files                                                                                                                 *
     31*********************************************************************************************************************************/
    2832#include "../VBoxSharedClipboardSvc-internal.h"
    2933
  • trunk/src/VBox/HostServices/testcase/TstHGCMMock.cpp

    r98574 r98576  
    11/* $Id$ */
    22/** @file
    3  * HGCMMock.h: Mocking framework for testing HGCM-based host services +
    4  *             Vbgl code on the host side.
    5  *
    6  *             Goal is to run host service + Vbgl code as unmodified as
    7  *             possible as part of testcases to gain test coverage which
    8  *             otherwise wouldn't possible for heavily user-centric features
    9  *             like Shared Clipboard or drag'n drop (DnD).
     3 * TstHGCMMock.cpp - Mocking framework for testing HGCM-based host services.
     4 *
     5 * The goal is to run host service + Vbgl code as unmodified as possible as
     6 * part of testcases to gain test coverage which otherwise wouldn't possible
     7 * for heavily user-centric features like Shared Clipboard or drag'n drop (DnD).
     8 *
     9 * Currently, though, it's only the service that runs unmodified, the
     10 * testcases does custom Vbgl work.
    1011 */
    1112
     
    2930 * along with this program; if not, see <https://www.gnu.org/licenses>.
    3031 *
    31  * The contents of this file may alternatively be used under the terms
    32  * of the Common Development and Distribution License Version 1.0
    33  * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
    34  * in the VirtualBox distribution, in which case the provisions of the
    35  * CDDL are applicable instead of those of the GPL.
    36  *
    37  * You may elect to license modified versions of this file under the
    38  * terms and conditions of either the GPL or the CDDL or both.
    39  *
    40  * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
    41  */
    42 
    43 #ifndef VBOX_INCLUDED_GuestHost_HGCMMock_h
    44 #define VBOX_INCLUDED_GuestHost_HGCMMock_h
    45 #ifndef RT_WITHOUT_PRAGMA_ONCE
    46 # pragma once
    47 #endif
    48 
    49 #include <iprt/types.h>
     32 * SPDX-License-Identifier: GPL-3.0-only
     33 */
     34
     35
     36/*********************************************************************************************************************************
     37*   Header Files                                                                                                                 *
     38*********************************************************************************************************************************/
     39#include <VBox/GuestHost/HGCMMock.h>
    5040
    5141#include <iprt/asm.h>
     
    6656
    6757/*********************************************************************************************************************************
    68 Definitions.                                                                                                                  *
     58 Global Variables                                                                                                             *
    6959*********************************************************************************************************************************/
    70 
    71 #if defined(IN_RING3) /* Only R3 parts implemented so far. */
    72 
    73 RT_C_DECLS_BEGIN
    74 
    75 DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad(VBOXHGCMSVCFNTABLE *ptable);
    76 
    77 RT_C_DECLS_END
    78 
    79 # define VBGLR3DECL(type) DECL_HIDDEN_NOTHROW(type) VBOXCALL
    80 
    81 /** Simple call handle structure for the guest call completion callback. */
    82 typedef struct VBOXHGCMCALLHANDLE_TYPEDEF
    83 {
    84     /** Where to store the result code on call completion. */
    85     int32_t rc;
    86 } VBOXHGCMCALLHANDLE_TYPEDEF;
    87 
    88 /**
    89  * Enumeration for a HGCM mock function type.
    90  */
    91 typedef enum TSTHGCMMOCKFNTYPE
    92 {
    93     TSTHGCMMOCKFNTYPE_NONE = 0,
    94     TSTHGCMMOCKFNTYPE_CONNECT,
    95     TSTHGCMMOCKFNTYPE_DISCONNECT,
    96     TSTHGCMMOCKFNTYPE_CALL,
    97     TSTHGCMMOCKFNTYPE_HOST_CALL
    98 } TSTHGCMMOCKFNTYPE;
    99 
    100 /** Pointer to a mock HGCM service. */
    101 typedef struct TSTHGCMMOCKSVC *PTSTHGCMMOCKSVC;
    102 
    103 /**
    104  * Structure for mocking a server-side HGCM client.
    105  */
    106 typedef struct TSTHGCMMOCKCLIENT
    107 {
    108     /** Pointer to to mock service instance this client belongs to. */
    109     PTSTHGCMMOCKSVC            pSvc;
    110     /** Assigned HGCM client ID. */
    111     uint32_t                   idClient;
    112     /** Opaque pointer to service-specific client data.
    113      *  Can be NULL if not being used. */
    114     void                      *pvClient;
    115     /** Size (in bytes) of \a pvClient. */
    116     size_t                     cbClient;
    117     /** The client's current HGCM call handle. */
    118     VBOXHGCMCALLHANDLE_TYPEDEF hCall;
    119     /** Whether the current client call has an asynchronous
    120      *  call pending or not. */
    121     bool                       fAsyncExec;
    122     /** Event semaphore to signal call completion. */
    123     RTSEMEVENT                 hEvent;
    124 } TSTHGCMMOCKCLIENT;
    125 /** Pointer to a mock HGCM client. */
    126 typedef TSTHGCMMOCKCLIENT *PTSTHGCMMOCKCLIENT;
    127 
    128 /**
    129  * Structure for keeping HGCM mock function parameters.
    130  */
    131 typedef struct TSTHGCMMOCKFN
    132 {
    133     /** List node for storing this struct into a queue. */
    134     RTLISTNODE         Node;
    135     /** Function type. */
    136     TSTHGCMMOCKFNTYPE  enmType;
    137     /** Pointer to associated client. */
    138     PTSTHGCMMOCKCLIENT pClient;
    139     /** Union keeping function-specific parameters,
    140      *  depending on \a enmType. */
    141     union
    142     {
    143         struct
    144         {
    145             int32_t             iFunc;
    146             uint32_t            cParms;
    147             PVBOXHGCMSVCPARM    pParms;
    148             VBOXHGCMCALLHANDLE  hCall;
    149         } Call;
    150         struct
    151         {
    152             int32_t             iFunc;
    153             uint32_t            cParms;
    154             PVBOXHGCMSVCPARM    pParms;
    155         } HostCall;
    156     } u;
    157 } TSTHGCMMOCKFN;
    158 /** Pointer to a HGCM mock function parameters structure. */
    159 typedef TSTHGCMMOCKFN *PTSTHGCMMOCKFN;
    160 
    161 /**
    162  * Structure for keeping a HGCM mock service instance.
    163  */
    164 typedef struct TSTHGCMMOCKSVC
    165 {
    166     /** HGCM helper table to use. */
    167     VBOXHGCMSVCHELPERS fnHelpers;
    168     /** HGCM service function table to use. */
    169     VBOXHGCMSVCFNTABLE fnTable;
    170     /** Next HGCM client ID to assign.
    171      *  0 is considered as being invalid. */
    172     HGCMCLIENTID       uNextClientId;
    173     /** Array of connected HGCM mock clients.
    174      *  Currently limited to 4 clients maximum. */
    175     TSTHGCMMOCKCLIENT  aHgcmClient[4];
    176     /** Thread handle for the service's main loop. */
    177     RTTHREAD           hThread;
    178     /** Event semaphore for signalling a message
    179      *  queue change. */
    180     RTSEMEVENT         hEventQueue;
    181     /** Event semaphore for clients connecting to the server. */
    182     RTSEMEVENT         hEventConnect;
    183     /** Number of current host calls being served.
    184      *  Currently limited to one call at a time. */
    185     uint8_t            cHostCallers;
    186     /** Result code of last returned host call. */
    187     int                rcHostCall;
    188     /** Event semaphore for host calls. */
    189     RTSEMEVENT         hEventHostCall;
    190     /** List (queue) of function calls to process. */
    191     RTLISTANCHOR       lstCall;
    192     /** Shutdown indicator flag. */
    193     volatile bool      fShutdown;
    194 } TSTHGCMMOCKSVC;
    195 
    19660/** Static HGCM service to mock. */
    19761static TSTHGCMMOCKSVC g_tstHgcmSvc;
     
    19963
    20064/*********************************************************************************************************************************
    201 *  Prototypes.                                                                                                                   *
    202 *********************************************************************************************************************************/
    203 PTSTHGCMMOCKSVC    TstHgcmMockSvcInst(void);
    204 PTSTHGCMMOCKCLIENT TstHgcmMockSvcWaitForConnectEx(PTSTHGCMMOCKSVC pSvc, RTMSINTERVAL msTimeout);
    205 PTSTHGCMMOCKCLIENT TstHgcmMockSvcWaitForConnect(PTSTHGCMMOCKSVC pSvc);
    206 int                TstHgcmMockSvcCreate(PTSTHGCMMOCKSVC pSvc);
    207 int                TstHgcmMockSvcDestroy(PTSTHGCMMOCKSVC pSvc);
    208 int                TstHgcmMockSvcStart(PTSTHGCMMOCKSVC pSvc);
    209 int                TstHgcmMockSvcStop(PTSTHGCMMOCKSVC pSvc);
    210 
    211 int                TstHgcmMockSvcHostCall(PTSTHGCMMOCKSVC pSvc, void *pvService, int32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    212 
    213 VBGLR3DECL(int)    VbglR3HGCMConnect(const char *pszServiceName, HGCMCLIENTID *pidClient);
    214 VBGLR3DECL(int)    VbglR3HGCMDisconnect(HGCMCLIENTID idClient);
    215 VBGLR3DECL(int)    VbglR3GetSessionId(uint64_t *pu64IdSession);
    216 VBGLR3DECL(int)    VbglR3HGCMCall(PVBGLIOCHGCMCALL pInfo, size_t cbInfo);
    217 
    218 
    219 /*********************************************************************************************************************************
    220 *  Internal functions                                                                                                           *
     65*   Internal functions                                                                                                           *
    22166*********************************************************************************************************************************/
    22267
     
    269114}
    270115
    271 /* @copydoc VBOXHGCMSVCFNTABLE::pfnConnect */
     116/** @copydoc VBOXHGCMSVCFNTABLE::pfnConnect */
    272117static DECLCALLBACK(int) tstHgcmMockSvcConnect(PTSTHGCMMOCKSVC pSvc, void *pvService, uint32_t *pidClient)
    273118{
     
    304149}
    305150
    306 /* @copydoc VBOXHGCMSVCFNTABLE::pfnDisconnect */
     151/** @copydoc VBOXHGCMSVCFNTABLE::pfnDisconnect */
    307152static DECLCALLBACK(int) tstHgcmMockSvcDisconnect(PTSTHGCMMOCKSVC pSvc, void *pvService, uint32_t idClient)
    308153{
     
    329174}
    330175
    331 /* @copydoc VBOXHGCMSVCFNTABLE::pfnCall */
     176/** @copydoc VBOXHGCMSVCFNTABLE::pfnCall */
    332177static DECLCALLBACK(int) tstHgcmMockSvcCall(PTSTHGCMMOCKSVC pSvc, void *pvService, VBOXHGCMCALLHANDLE callHandle, uint32_t idClient, void *pvClient,
    333178                                            int32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     
    367212}
    368213
    369 /* @copydoc VBOXHGCMSVCFNTABLE::pfnHostCall */
    370 /** Note: Public for also being able to test host calls via testcases. */
     214/** @copydoc VBOXHGCMSVCFNTABLE::pfnHostCall
     215 * @note Public for also being able to test host calls via testcases. */
    371216int TstHgcmMockSvcHostCall(PTSTHGCMMOCKSVC pSvc, void *pvService, int32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    372217{
     
    527372                }
    528373                RTListNodeRemove(&pFn->Node);
    529                 RTMemFree(pFn);
     374                RTMemFree(pFn);  /* Note! caller frees the parameters? Or at least it uses them again. */
    530375            }
    531376        }
     
    537382
    538383/*********************************************************************************************************************************
    539 Public functions                                                                                                           *
     384 Public functions                                                                                                             *
    540385*********************************************************************************************************************************/
    541386
     
    655500        rc = rcThread;
    656501    if (RT_SUCCESS(rc))
    657     {
    658502        pSvc->hThread = NIL_RTTHREAD;
    659     }
    660503
    661504    return rc;
     
    810653}
    811654
    812 #endif /* IN_RING3 */
    813 
    814 #endif /* !VBOX_INCLUDED_GuestHost_HGCMMock_h */
  • trunk/src/VBox/HostServices/testcase/TstHGCMMockUtils.cpp

    r98569 r98576  
    1 /* $Id */
     1/* $Id$ */
    22/** @file
    3  * HGCMMockUtils.h: Utility functions for the HGCM Mocking framework.
    4  *
    5  * The utility functions are optional to the actual HGCM Mocking framework and
    6  * can support testcases which require a more advanced setup.
    7  *
    8  * With this one can setup host and guest side threads, which in turn can simulate
    9  * specific host (i.e. HGCM service) + guest (i.e. like in the Guest Addditions
    10  * via VbglR3) scenarios.
    11  *
    12  * Glossary:
    13  *
    14  * Host thread:
    15  *   - The host thread is used as part of the actual HGCM service being tested and
    16  *     provides callbacks (@see TSTHGCMUTILSHOSTCALLBACKS) for the unit test.
    17  * Guest thread:
    18  *    - The guest thread is used as part of the guest side and mimics
    19  *      VBoxClient / VBoxTray / VBoxService parts. (i.e. for VbglR3 calls).
    20  * Task:
    21  *    - A task is the simplest unit of test execution and used between the guest
    22  *      and host mocking threads.
    23  *
    24  ** @todo Add TstHGCMSimpleHost / TstHGCMSimpleGuest wrappers along those lines:
    25  *              Callback.pfnOnClientConnected = tstOnHostClientConnected()
    26  *              TstHGCMSimpleHostInitAndStart(&Callback)
    27  *              Callback.pfnOnConnected = tstOnGuestConnected()
    28  *              TstHGCMSimpleClientInitAndStart(&Callback)
     3 * TstHGCMMockUtils.cpp - Utility functions for the HGCM Mocking framework.
    294 */
    305
     
    4823 * along with this program; if not, see <https://www.gnu.org/licenses>.
    4924 *
    50  * The contents of this file may alternatively be used under the terms
    51  * of the Common Development and Distribution License Version 1.0
    52  * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
    53  * in the VirtualBox distribution, in which case the provisions of the
    54  * CDDL are applicable instead of those of the GPL.
    55  *
    56  * You may elect to license modified versions of this file under the
    57  * terms and conditions of either the GPL or the CDDL or both.
    58  *
    59  * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
    60  */
    61 
    62 #ifndef VBOX_INCLUDED_GuestHost_HGCMMockUtils_h
    63 #define VBOX_INCLUDED_GuestHost_HGCMMockUtils_h
    64 #ifndef RT_WITHOUT_PRAGMA_ONCE
    65 # pragma once
    66 #endif
     25 * SPDX-License-Identifier: GPL-3.0-only
     26 */
     27
     28
     29/*********************************************************************************************************************************
     30*   Header Files                                                                                                                 *
     31*********************************************************************************************************************************/
     32#include <VBox/GuestHost/HGCMMockUtils.h>
    6733
    6834#include <iprt/err.h>
     
    7238
    7339
    74 #include <VBox/GuestHost/HGCMMock.h>
    75 #include <VBox/VBoxGuestLib.h>
    76 
    77 
    78 #if defined(IN_RING3) /* Only R3 parts implemented so far. */
    79 
    80 /** Pointer to a HGCM Mock utils context. */
    81 typedef struct TSTHGCMUTILSCTX *PTSTHGCMUTILSCTX;
    82 
    83 /**
    84  * Structure for keeping a HGCM Mock utils host service callback table.
    85  */
    86 typedef struct TSTHGCMUTILSHOSTCALLBACKS
    87 {
    88     DECLCALLBACKMEMBER(int, pfnOnClientConnected,(PTSTHGCMUTILSCTX pCtx, PTSTHGCMMOCKCLIENT pClient, void *pvUser));
    89 } TSTHGCMUTILSHOSTCALLBACKS;
    90 /** Pointer to a HGCM Mock utils host callbacks table. */
    91 typedef TSTHGCMUTILSHOSTCALLBACKS *PTSTHGCMUTILSHOSTCALLBACKS;
    92 
    93 /**
    94  * Structure for keeping a generic HGCM Mock utils task.
    95  *
    96  * A task is a single test unit / entity.
    97  */
    98 typedef struct TSTHGCMUTILSTASK
    99 {
    100     /** Completion event. */
    101     RTSEMEVENT                    hEvent;
    102     /** Completion rc.
    103      *  Set to VERR_IPE_UNINITIALIZED_STATUS if not completed yet. */
    104     int                           rcCompleted;
    105     /** Expected completion rc. */
    106     int                           rcExpected;
    107     /** Pointer to opaque (testcase-specific) task parameters.
    108      *  Might be NULL if not needed / used. */
    109     void                         *pvUser;
    110 } TSTHGCMUTILSTASK;
    111 /** Pointer to a HGCM Mock utils task. */
    112 typedef TSTHGCMUTILSTASK *PTSTHGCMUTILSTASK;
    113 
    114 /** Callback function for HGCM Mock utils threads. */
    115 typedef DECLCALLBACKTYPE(int, FNTSTHGCMUTILSTHREAD,(PTSTHGCMUTILSCTX pCtx, void *pvUser));
    116 /** Pointer to a HGCM Mock utils guest thread callback. */
    117 typedef FNTSTHGCMUTILSTHREAD *PFNTSTHGCMUTILSTHREAD;
    118 
    119 /**
    120  * Structure for keeping a HGCM Mock utils context.
    121  */
    122 typedef struct TSTHGCMUTILSCTX
    123 {
    124     /** Pointer to the HGCM Mock service instance to use. */
    125     PTSTHGCMMOCKSVC               pSvc;
    126     /** Currently we only support one task at a time. */
    127     TSTHGCMUTILSTASK              Task;
    128     struct
    129     {
    130         RTTHREAD                  hThread;
    131         volatile bool             fShutdown;
    132         PFNTSTHGCMUTILSTHREAD     pfnThread;
    133         void                     *pvUser;
    134     } Guest;
    135     struct
    136     {
    137         RTTHREAD                  hThread;
    138         volatile bool             fShutdown;
    139         TSTHGCMUTILSHOSTCALLBACKS Callbacks;
    140         void                     *pvUser;
    141     } Host;
    142 } TSTHGCMUTILSCTX;
    143 
    144 
    145 /*********************************************************************************************************************************
    146 *  Prototypes.                                                                                                                   *
     40/*********************************************************************************************************************************
     41*   Context                                                                                                                      *
    14742*********************************************************************************************************************************/
    148 /** @name Context handling.
    149  * @{ */
    150 void TstHGCMUtilsCtxInit(PTSTHGCMUTILSCTX pCtx, PTSTHGCMMOCKSVC pSvc);
    151 /** @} */
    152 
    153 /** @name Task handling.
    154  * @{ */
    155 PTSTHGCMUTILSTASK TstHGCMUtilsTaskGetCurrent(PTSTHGCMUTILSCTX pCtx);
    156 int TstHGCMUtilsTaskInit(PTSTHGCMUTILSTASK pTask);
    157 void TstHGCMUtilsTaskDestroy(PTSTHGCMUTILSTASK pTask);
    158 int TstHGCMUtilsTaskWait(PTSTHGCMUTILSTASK pTask, RTMSINTERVAL msTimeout);
    159 bool TstHGCMUtilsTaskOk(PTSTHGCMUTILSTASK pTask);
    160 bool TstHGCMUtilsTaskCompleted(PTSTHGCMUTILSTASK pTask);
    161 void TstHGCMUtilsTaskSignal(PTSTHGCMUTILSTASK pTask, int rc);
    162 /** @} */
    163 
    164 /** @name Threading.
    165  * @{ */
    166 int TstHGCMUtilsGuestThreadStart(PTSTHGCMUTILSCTX pCtx, PFNTSTHGCMUTILSTHREAD pFnThread, void *pvUser);
    167 int TstHGCMUtilsGuestThreadStop(PTSTHGCMUTILSCTX pCtx);
    168 int TstHGCMUtilsHostThreadStart(PTSTHGCMUTILSCTX pCtx, PTSTHGCMUTILSHOSTCALLBACKS pCallbacks, void *pvUser);
    169 int TstHGCMUtilsHostThreadStop(PTSTHGCMUTILSCTX pCtx);
    170 /** @} */
    171 
    172 
    173 /*********************************************************************************************************************************
    174  * Context                                                                                                                       *
    175  ********************************************************************************************************************************/
    17643/**
    17744 * Initializes a HGCM Mock utils context.
     
    18956
    19057/*********************************************************************************************************************************
    191  * Tasks                                                                                                                         *
    192  ********************************************************************************************************************************/
     58*   Tasks                                                                                                                        *
     59*********************************************************************************************************************************/
    19360/**
    19461 * Returns the current task of a HGCM Mock utils context.
     
    423290}
    424291
    425 #endif /* IN_RING3 */
    426 
    427 #endif /* !VBOX_INCLUDED_GuestHost_HGCMMockUtils_h */
    428 
Note: See TracChangeset for help on using the changeset viewer.

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