tstGuestControlSvc.cpp revision 462e60a19d02a99b2b1a5c08dff74bb0808d707c
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Testcase for the guest control service.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Copyright (C) 2011-2013 Oracle Corporation
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * available from http://www.virtualbox.org. This file is free software;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Header Files *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "../gctrl.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Global Variables *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
48d60b042893290a747d3abeda71a3085d9133fdvboxsyncusing namespace guestControl;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncextern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad(VBOXHGCMSVCFNTABLE *pTable);
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync/** Simple call handle structure for the guest call completion callback */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Where to store the result code. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** Call completion callback for guest calls. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic void callComplete(VBOXHGCMCALLHANDLE callHandle, int32_t rc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Initialise the HGCM service table as much as we need to start the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @return IPRT status.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pTable the table to initialise
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint initTable(VBOXHGCMSVCFNTABLE *pTable, VBOXHGCMSVCHELPERS *pHelpers)
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsynctypedef struct CMDHOST
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync /** The HGCM command to execute. */
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync /** Number of parameters. */
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync /** The actual parameters. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Flag indicating whether we need a connected client for this command. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The desired return value from the host. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsynctypedef struct CMDCLIENT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The client's ID. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The HGCM command to execute. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Number of parameters. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The actual parameters. */
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync /** The desired return value from the host. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Tests the HOST_EXEC_CMD function.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns iprt status value to indicate whether the test went as expected.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @note prints its own diagnostic information to stdout.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int testHostCmd(const VBOXHGCMSVCFNTABLE *pTable, const PCMDHOST pCmd, uint32_t uNumTests)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTTestPrintf(g_hTest, RTTESTLVL_FAILURE, "Invalid pfnHostCall() pointer\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (unsigned i = 0; (i < uNumTests) && RT_SUCCESS(rc); i++)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTTestPrintf(g_hTest, RTTESTLVL_INFO, "Testing #%u (cmd: %d, num_parms: %d, parms: 0x%p\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int client_rc = pTable->pfnConnect(pTable->pvService, 1000 /* Client ID */, NULL /* pvClient */);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int host_rc = pTable->pfnHostCall(pTable->pvService,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTTestPrintf(g_hTest, RTTESTLVL_FAILURE, "Host call test #%u returned with rc=%Rrc instead of rc=%Rrc\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int client_rc = pTable->pfnDisconnect(pTable->pvService, 1000 /* Client ID */, NULL /* pvClient */);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int testHost(const VBOXHGCMSVCFNTABLE *pTable)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** No client connected. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { 1024 /* Not existing command */, 0, 0, false, VERR_NOT_FOUND },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { -1 /* Invalid command */, 0, 0, false, VERR_NOT_FOUND },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { HOST_CANCEL_PENDING_WAITS, 1024, 0, false, VERR_NOT_FOUND },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { HOST_CANCEL_PENDING_WAITS, 0, &s_aParms[0], false, VERR_NOT_FOUND },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** No client connected, valid command. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { HOST_CANCEL_PENDING_WAITS, 0, 0, false, VERR_NOT_FOUND },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Client connected, no parameters given. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { HOST_EXEC_SET_INPUT, 0 /* No parameters given */, 0, true, VERR_INVALID_PARAMETER },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { 1024 /* Not existing command */, 0 /* No parameters given */, 0, true, VERR_INVALID_PARAMETER },
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync { -1 /* Invalid command */, 0 /* No parameters given */, 0, true, VERR_INVALID_PARAMETER },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Client connected, valid parameters given. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { HOST_CANCEL_PENDING_WAITS, 0, 0, true, VINF_SUCCESS },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { HOST_CANCEL_PENDING_WAITS, 1024, &s_aParms[0], true, VINF_SUCCESS },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { HOST_CANCEL_PENDING_WAITS, 0, &s_aParms[0], true, VINF_SUCCESS},
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Client connected, invalid parameters given. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { HOST_EXEC_CMD, 1024, 0, true, VERR_INVALID_POINTER },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { HOST_EXEC_CMD, 1, 0, true, VERR_INVALID_POINTER },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { HOST_EXEC_CMD, -1, 0, true, VERR_INVALID_POINTER },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Client connected, parameters given. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { HOST_CANCEL_PENDING_WAITS, 1, &s_aParms[0], true, VINF_SUCCESS },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { HOST_EXEC_CMD, 1, &s_aParms[0], true, VINF_SUCCESS },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { HOST_EXEC_SET_INPUT, 1, &s_aParms[0], true, VINF_SUCCESS },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { HOST_EXEC_GET_OUTPUT, 1, &s_aParms[0], true, VINF_SUCCESS },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Client connected, unknown command + valid parameters given. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = testHostCmd(pTable, &s_aCmdHostAll[0], RT_ELEMENTS(s_aCmdHostAll));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int testClient(const VBOXHGCMSVCFNTABLE *pTable)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = pTable->pfnConnect(pTable->pvService, 1 /* Client ID */, NULL /* pvClient */);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* No commands from host yet. */
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync pTable->pfnCall(pTable->pvService, &callHandle, 1 /* Client ID */, NULL /* pvClient */,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTTEST_CHECK_RC_RET(g_hTest, callHandle.rc, VINF_SUCCESS, callHandle.rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Host: Add a dummy command. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = pTable->pfnHostCall(pTable->pvService, HOST_EXEC_CMD, 3, &s_aParmsHost[0]);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTTEST_CHECK_RC_RET(g_hTest, rc, VINF_SUCCESS, rc);
38b70b2dcb1783801f7580cba797a0c8af4b5326vboxsync /* Client: Disconnect again. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc2 = pTable->pfnDisconnect(pTable->pvService, 1000 /* Client ID */, NULL /* pvClient */);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Set environment variable "IPRT_TEST_MAX_LEVEL=all" to get more debug output!
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTEXITCODE rcExit = RTTestInitAndCreate("tstGuestControlSvc", &g_hTest);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Some host info. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTTestIPrintf(RTTESTLVL_ALWAYS, "sizeof(void*)=%d\n", sizeof(void*));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Do the tests. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTTEST_CHECK_RC_RET(g_hTest, initTable(&svcTable, &svcHelpers), VINF_SUCCESS, 1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTTESTI_CHECK_RC_BREAK(VBoxHGCMSvcLoad(&svcTable), VINF_SUCCESS);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTTESTI_CHECK_RC_BREAK(testHost(&svcTable), VINF_SUCCESS);
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync RTTESTI_CHECK_RC_BREAK(svcTable.pfnUnload(svcTable.pvService), VINF_SUCCESS);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTTESTI_CHECK_RC_BREAK(VBoxHGCMSvcLoad(&svcTable), VINF_SUCCESS);
fa92c704624def98d3c4aca86d65182effb98e04vboxsync RTTESTI_CHECK_RC_BREAK(testClient(&svcTable), VINF_SUCCESS);
17c6e5e8177d068d1bc6af875d1610718efcfdb4vboxsync RTTESTI_CHECK_RC_BREAK(svcTable.pfnUnload(svcTable.pvService), VINF_SUCCESS);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } while (0);