Changeset 98576 in vbox
- Timestamp:
- Feb 15, 2023 1:48:41 AM (2 years ago)
- svn:sync-xref-src-repo-rev:
- 155862
- Location:
- trunk
- Files:
-
- 5 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/GuestHost/HGCMMock.h
r98574 r98576 1 /* $Id$ */2 1 /** @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. 5 3 * 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. 10 10 */ 11 11 … … 47 47 #endif 48 48 49 #i nclude <iprt/types.h>49 #ifdef IN_RING3 50 50 51 #include <iprt/asm.h>52 #include <iprt/assert.h>53 51 #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>63 52 #include <VBox/VBoxGuestLib.h> 64 53 #include <VBox/hgcmsvc.h> 65 54 66 67 /*********************************************************************************************************************************68 * Definitions. *69 *********************************************************************************************************************************/70 71 #if defined(IN_RING3) /* Only R3 parts implemented so far. */72 73 RT_C_DECLS_BEGIN74 75 DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad(VBOXHGCMSVCFNTABLE *ptable);76 77 RT_C_DECLS_END78 79 # define VBGLR3DECL(type) DECL_HIDDEN_NOTHROW(type) VBOXCALL80 55 81 56 /** Simple call handle structure for the guest call completion callback. */ … … 194 169 } TSTHGCMMOCKSVC; 195 170 196 /** Static HGCM service to mock. */197 static TSTHGCMMOCKSVC g_tstHgcmSvc;198 171 199 200 /*********************************************************************************************************************************201 * Prototypes. *202 *********************************************************************************************************************************/203 172 PTSTHGCMMOCKSVC TstHgcmMockSvcInst(void); 204 173 PTSTHGCMMOCKCLIENT TstHgcmMockSvcWaitForConnectEx(PTSTHGCMMOCKSVC pSvc, RTMSINTERVAL msTimeout); … … 211 180 int TstHgcmMockSvcHostCall(PTSTHGCMMOCKSVC pSvc, void *pvService, int32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 212 181 182 RT_C_DECLS_BEGIN 183 DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad(VBOXHGCMSVCFNTABLE *pTable); 184 RT_C_DECLS_END 185 186 # undef VBGLR3DECL 187 # define VBGLR3DECL(type) DECL_HIDDEN_NOTHROW(type) VBOXCALL 213 188 VBGLR3DECL(int) VbglR3HGCMConnect(const char *pszServiceName, HGCMCLIENTID *pidClient); 214 189 VBGLR3DECL(int) VbglR3HGCMDisconnect(HGCMCLIENTID idClient); … … 217 192 218 193 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 a364 * 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 code673 * @param pszServiceName Name of the host service.674 * @param pidClient Where to put the client ID on success. The client ID675 * 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 than718 * what the parameter count indicates because of719 * 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 812 194 #endif /* IN_RING3 */ 813 195 -
trunk/include/VBox/GuestHost/HGCMMockUtils.h
r98103 r98576 1 /* $Id */2 1 /** @file 3 * HGCMMockUtils.h:Utility functions for the HGCM Mocking framework.2 * TstHGCMMockUtils.h - Utility functions for the HGCM Mocking framework. 4 3 * 5 4 * The utility functions are optional to the actual HGCM Mocking framework and … … 66 65 #endif 67 66 68 #include <iprt/err.h>69 #include <iprt/semaphore.h>70 #include <iprt/thread.h>71 #include <iprt/types.h>72 73 74 67 #include <VBox/GuestHost/HGCMMock.h> 75 #include <VBox/VBoxGuestLib.h>76 77 78 #if defined(IN_RING3) /* Only R3 parts implemented so far. */79 68 80 69 /** Pointer to a HGCM Mock utils context. */ … … 143 132 144 133 145 /*********************************************************************************************************************************146 * Prototypes. *147 *********************************************************************************************************************************/148 134 /** @name Context handling. 149 135 * @{ */ … … 171 157 172 158 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 427 159 #endif /* !VBOX_INCLUDED_GuestHost_HGCMMockUtils_h */ 428 160 -
trunk/src/VBox/HostServices/GuestControl/testcase/Makefile.kmk
r98533 r98576 46 46 tstGuestControlMockHGCM_SOURCES = \ 47 47 ../VBoxGuestControlSvc.cpp \ 48 ../../testcase/TstHgcmMock.cpp \ 48 49 $(PATH_ROOT)/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp \ 49 50 $(PATH_ROOT)/src/VBox/HostServices/common/message.cpp \ -
trunk/src/VBox/HostServices/SharedClipboard/testcase/Makefile.kmk
r98415 r98576 43 43 tstClipboardMockHGCM_DEFS = VBOX_WITH_HGCM VBOX_WITH_SHARED_CLIPBOARD 44 44 tstClipboardMockHGCM_SOURCES = \ 45 tstClipboardMockHGCM.cpp \ 45 46 ../VBoxSharedClipboardSvc.cpp \ 47 ../../testcase/TstHgcmMock.cpp \ 48 ../../testcase/TstHgcmMockUtils.cpp \ 46 49 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp \ 47 50 $(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 50 52 tstClipboardMockHGCM_LIBS = $(LIB_RUNTIME) 51 53 -
trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardMockHGCM.cpp
r98575 r98576 26 26 */ 27 27 28 29 /********************************************************************************************************************************* 30 * Header Files * 31 *********************************************************************************************************************************/ 28 32 #include "../VBoxSharedClipboardSvc-internal.h" 29 33 -
trunk/src/VBox/HostServices/testcase/TstHGCMMock.cpp
r98574 r98576 1 1 /* $Id$ */ 2 2 /** @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. 10 11 */ 11 12 … … 29 30 * along with this program; if not, see <https://www.gnu.org/licenses>. 30 31 * 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> 50 40 51 41 #include <iprt/asm.h> … … 66 56 67 57 /********************************************************************************************************************************* 68 * Definitions.*58 * Global Variables * 69 59 *********************************************************************************************************************************/ 70 71 #if defined(IN_RING3) /* Only R3 parts implemented so far. */72 73 RT_C_DECLS_BEGIN74 75 DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad(VBOXHGCMSVCFNTABLE *ptable);76 77 RT_C_DECLS_END78 79 # define VBGLR3DECL(type) DECL_HIDDEN_NOTHROW(type) VBOXCALL80 81 /** Simple call handle structure for the guest call completion callback. */82 typedef struct VBOXHGCMCALLHANDLE_TYPEDEF83 {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 TSTHGCMMOCKFNTYPE92 {93 TSTHGCMMOCKFNTYPE_NONE = 0,94 TSTHGCMMOCKFNTYPE_CONNECT,95 TSTHGCMMOCKFNTYPE_DISCONNECT,96 TSTHGCMMOCKFNTYPE_CALL,97 TSTHGCMMOCKFNTYPE_HOST_CALL98 } 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 TSTHGCMMOCKCLIENT107 {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 asynchronous120 * 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 TSTHGCMMOCKFN132 {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 union142 {143 struct144 {145 int32_t iFunc;146 uint32_t cParms;147 PVBOXHGCMSVCPARM pParms;148 VBOXHGCMCALLHANDLE hCall;149 } Call;150 struct151 {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 TSTHGCMMOCKSVC165 {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 message179 * 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 196 60 /** Static HGCM service to mock. */ 197 61 static TSTHGCMMOCKSVC g_tstHgcmSvc; … … 199 63 200 64 /********************************************************************************************************************************* 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 * 221 66 *********************************************************************************************************************************/ 222 67 … … 269 114 } 270 115 271 /* @copydoc VBOXHGCMSVCFNTABLE::pfnConnect */116 /** @copydoc VBOXHGCMSVCFNTABLE::pfnConnect */ 272 117 static DECLCALLBACK(int) tstHgcmMockSvcConnect(PTSTHGCMMOCKSVC pSvc, void *pvService, uint32_t *pidClient) 273 118 { … … 304 149 } 305 150 306 /* @copydoc VBOXHGCMSVCFNTABLE::pfnDisconnect */151 /** @copydoc VBOXHGCMSVCFNTABLE::pfnDisconnect */ 307 152 static DECLCALLBACK(int) tstHgcmMockSvcDisconnect(PTSTHGCMMOCKSVC pSvc, void *pvService, uint32_t idClient) 308 153 { … … 329 174 } 330 175 331 /* @copydoc VBOXHGCMSVCFNTABLE::pfnCall */176 /** @copydoc VBOXHGCMSVCFNTABLE::pfnCall */ 332 177 static DECLCALLBACK(int) tstHgcmMockSvcCall(PTSTHGCMMOCKSVC pSvc, void *pvService, VBOXHGCMCALLHANDLE callHandle, uint32_t idClient, void *pvClient, 333 178 int32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) … … 367 212 } 368 213 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. */ 371 216 int TstHgcmMockSvcHostCall(PTSTHGCMMOCKSVC pSvc, void *pvService, int32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 372 217 { … … 527 372 } 528 373 RTListNodeRemove(&pFn->Node); 529 RTMemFree(pFn); 374 RTMemFree(pFn); /* Note! caller frees the parameters? Or at least it uses them again. */ 530 375 } 531 376 } … … 537 382 538 383 /********************************************************************************************************************************* 539 * Public functions*384 * Public functions * 540 385 *********************************************************************************************************************************/ 541 386 … … 655 500 rc = rcThread; 656 501 if (RT_SUCCESS(rc)) 657 {658 502 pSvc->hThread = NIL_RTTHREAD; 659 }660 503 661 504 return rc; … … 810 653 } 811 654 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$ */ 2 2 /** @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. 29 4 */ 30 5 … … 48 23 * along with this program; if not, see <https://www.gnu.org/licenses>. 49 24 * 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> 67 33 68 34 #include <iprt/err.h> … … 72 38 73 39 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 * 147 42 *********************************************************************************************************************************/ 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 ********************************************************************************************************************************/176 43 /** 177 44 * Initializes a HGCM Mock utils context. … … 189 56 190 57 /********************************************************************************************************************************* 191 * Tasks*192 58 * Tasks * 59 *********************************************************************************************************************************/ 193 60 /** 194 61 * Returns the current task of a HGCM Mock utils context. … … 423 290 } 424 291 425 #endif /* IN_RING3 */426 427 #endif /* !VBOX_INCLUDED_GuestHost_HGCMMockUtils_h */428
Note:
See TracChangeset
for help on using the changeset viewer.