VirtualBox

source: vbox/trunk/src/VBox/HostServices/GuestControl/testcase/tstGuestControlSvc.cpp@ 100595

Last change on this file since 100595 was 99775, checked in by vboxsync, 19 months ago

*: Mark functions as static if not used outside of a given compilation unit. Enables the compiler to optimize inlining, reduces the symbol tables, exposes unused functions and in some rare cases exposes mismtaches between function declarations and definitions, but most importantly reduces the number of parfait reports for the extern-function-no-forward-declaration category. This should not result in any functional changes, bugref:3409

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.0 KB
Line 
1/* $Id: tstGuestControlSvc.cpp 99775 2023-05-12 12:21:58Z vboxsync $ */
2/** @file
3 * Testcase for the guest control service.
4 */
5
6/*
7 * Copyright (C) 2011-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <VBox/HostServices/GuestControlSvc.h>
33#include <iprt/initterm.h>
34#include <iprt/stream.h>
35#include <iprt/test.h>
36
37
38/*********************************************************************************************************************************
39* Global Variables *
40*********************************************************************************************************************************/
41static RTTEST g_hTest = NIL_RTTEST;
42
43using namespace guestControl;
44
45extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad(VBOXHGCMSVCFNTABLE *pTable);
46
47/** Simple call handle structure for the guest call completion callback */
48struct VBOXHGCMCALLHANDLE_TYPEDEF
49{
50 /** Where to store the result code. */
51 int32_t rc;
52};
53
54/** Call completion callback for guest calls. */
55static DECLCALLBACK(int) callComplete(VBOXHGCMCALLHANDLE callHandle, int32_t rc)
56{
57 callHandle->rc = rc;
58 return VINF_SUCCESS;
59}
60
61/**
62 * Initialise the HGCM service table as much as we need to start the
63 * service.
64 *
65 * @return IPRT status code.
66 * @param pTable the table to initialise
67 */
68static int initTable(VBOXHGCMSVCFNTABLE *pTable, VBOXHGCMSVCHELPERS *pHelpers)
69{
70 pTable->cbSize = sizeof (VBOXHGCMSVCFNTABLE);
71 pTable->u32Version = VBOX_HGCM_SVC_VERSION;
72 pHelpers->pfnCallComplete = callComplete;
73 pTable->pHelpers = pHelpers;
74
75 return VINF_SUCCESS;
76}
77
78typedef struct CMDHOST
79{
80 /** The HGCM command to execute. */
81 int cmd;
82 /** Number of parameters. */
83 int num_parms;
84 /** The actual parameters. */
85 const PVBOXHGCMSVCPARM parms;
86 /** Flag indicating whether we need a connected client for this command. */
87 bool fNeedsClient;
88 /** The desired return value from the host. */
89 int rc;
90} CMDHOST, *PCMDHOST;
91
92typedef struct CMDCLIENT
93{
94 /** The client's ID. */
95 int client_id;
96 /** The HGCM command to execute. */
97 int cmd;
98 /** Number of parameters. */
99 int num_parms;
100 /** The actual parameters. */
101 const PVBOXHGCMSVCPARM parms;
102 /** The desired return value from the host. */
103 int rc;
104} CMDCLIENT, *PCMDCLIENT;
105
106/**
107 * Tests the HOST_EXEC_CMD function.
108 * @returns iprt status value to indicate whether the test went as expected.
109 * @note prints its own diagnostic information to stdout.
110 */
111static int testHostCmd(const VBOXHGCMSVCFNTABLE *pTable, const PCMDHOST pCmd, uint32_t uNumTests)
112{
113 int rc = VINF_SUCCESS;
114 if (!RT_VALID_PTR(pTable->pfnHostCall))
115 {
116 RTTestPrintf(g_hTest, RTTESTLVL_FAILURE, "Invalid pfnHostCall() pointer\n");
117 rc = VERR_INVALID_POINTER;
118 }
119 if (RT_SUCCESS(rc))
120 {
121 for (unsigned i = 0; (i < uNumTests) && RT_SUCCESS(rc); i++)
122 {
123 RTTestPrintf(g_hTest, RTTESTLVL_INFO, "Testing #%u (cmd: %d, num_parms: %d, parms: 0x%p\n",
124 i, pCmd[i].cmd, pCmd[i].num_parms, pCmd[i].parms);
125
126 if (pCmd[i].fNeedsClient)
127 {
128 int client_rc = pTable->pfnConnect(pTable->pvService, 1000 /* Client ID */, NULL /* pvClient */, 0, false);
129 if (RT_FAILURE(client_rc))
130 rc = client_rc;
131 }
132
133 if (RT_SUCCESS(rc))
134 {
135 int host_rc = pTable->pfnHostCall(pTable->pvService,
136 pCmd[i].cmd,
137 pCmd[i].num_parms,
138 pCmd[i].parms);
139 if (host_rc != pCmd[i].rc)
140 {
141 RTTestPrintf(g_hTest, RTTESTLVL_FAILURE, "Host call test #%u returned with rc=%Rrc instead of rc=%Rrc\n",
142 i, host_rc, pCmd[i].rc);
143 rc = host_rc;
144 if (RT_SUCCESS(rc))
145 rc = VERR_INVALID_PARAMETER;
146 }
147
148 if (pCmd[i].fNeedsClient)
149 {
150 int client_rc = pTable->pfnDisconnect(pTable->pvService, 1000 /* Client ID */, NULL /* pvClient */);
151 if (RT_SUCCESS(rc))
152 rc = client_rc;
153 }
154 }
155 }
156 }
157 return rc;
158}
159
160static int testHost(const VBOXHGCMSVCFNTABLE *pTable)
161{
162 RTTestSub(g_hTest, "Testing host commands ...");
163
164 VBOXHGCMSVCPARM aParms[1];
165 HGCMSvcSetU32(&aParms[0], 1000 /* Context ID */);
166
167 CMDHOST aCmdHostAll[] =
168 {
169#if 0
170 /** No client connected. */
171 { 1024 /* Not existing command */, 0, 0, false, VERR_NOT_FOUND },
172 { -1 /* Invalid command */, 0, 0, false, VERR_NOT_FOUND },
173 { HOST_CANCEL_PENDING_WAITS, 1024, 0, false, VERR_NOT_FOUND },
174 { HOST_CANCEL_PENDING_WAITS, 0, &aParms[0], false, VERR_NOT_FOUND },
175
176 /** No client connected, valid command. */
177 { HOST_CANCEL_PENDING_WAITS, 0, 0, false, VERR_NOT_FOUND },
178
179 /** Client connected, no parameters given. */
180 { HOST_EXEC_SET_INPUT, 0 /* No parameters given */, 0, true, VERR_INVALID_PARAMETER },
181 { 1024 /* Not existing command */, 0 /* No parameters given */, 0, true, VERR_INVALID_PARAMETER },
182 { -1 /* Invalid command */, 0 /* No parameters given */, 0, true, VERR_INVALID_PARAMETER },
183
184 /** Client connected, valid parameters given. */
185 { HOST_CANCEL_PENDING_WAITS, 0, 0, true, VINF_SUCCESS },
186 { HOST_CANCEL_PENDING_WAITS, 1024, &aParms[0], true, VINF_SUCCESS },
187 { HOST_CANCEL_PENDING_WAITS, 0, &aParms[0], true, VINF_SUCCESS},
188#endif
189
190 /** Client connected, invalid parameters given. */
191 { HOST_MSG_EXEC_CMD, 1024, 0, true, VERR_INVALID_POINTER },
192 { HOST_MSG_EXEC_CMD, 1, 0, true, VERR_INVALID_POINTER },
193 { HOST_MSG_EXEC_CMD, -1, 0, true, VERR_INVALID_POINTER },
194
195 /** Client connected, parameters given. */
196 { HOST_MSG_CANCEL_PENDING_WAITS, 1, &aParms[0], true, VINF_SUCCESS },
197 { HOST_MSG_EXEC_CMD, 1, &aParms[0], true, VINF_SUCCESS },
198 { HOST_MSG_EXEC_SET_INPUT, 1, &aParms[0], true, VINF_SUCCESS },
199 { HOST_MSG_EXEC_GET_OUTPUT, 1, &aParms[0], true, VINF_SUCCESS },
200
201 /** Client connected, unknown command + valid parameters given. */
202 { -1, 1, &aParms[0], true, VINF_SUCCESS }
203 };
204
205 int rc = testHostCmd(pTable, &aCmdHostAll[0], RT_ELEMENTS(aCmdHostAll));
206 RTTestSubDone(g_hTest);
207 return rc;
208}
209
210static int testClient(const VBOXHGCMSVCFNTABLE *pTable)
211{
212 RTTestSub(g_hTest, "Testing client commands ...");
213
214 int rc = pTable->pfnConnect(pTable->pvService, 1 /* Client ID */, NULL /* pvClient */, 0, false);
215 if (RT_SUCCESS(rc))
216 {
217 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
218
219 /* No commands from host yet. */
220 VBOXHGCMSVCPARM aParmsGuest[8];
221 HGCMSvcSetU32(&aParmsGuest[0], 0 /* Msg type */);
222 HGCMSvcSetU32(&aParmsGuest[1], 0 /* Parameters */);
223 pTable->pfnCall(pTable->pvService, &callHandle, 1 /* Client ID */, NULL /* pvClient */,
224 GUEST_MSG_WAIT, 2, &aParmsGuest[0], 0);
225 RTTEST_CHECK_RC_RET(g_hTest, callHandle.rc, VINF_SUCCESS, callHandle.rc);
226
227 /* Host: Add a dummy command. */
228 VBOXHGCMSVCPARM aParmsHost[8];
229 HGCMSvcSetU32(&aParmsHost[0], 1000 /* Context ID */);
230 HGCMSvcSetStr(&aParmsHost[1], "foo.bar");
231 HGCMSvcSetStr(&aParmsHost[2], "baz");
232
233 rc = pTable->pfnHostCall(pTable->pvService, HOST_MSG_EXEC_CMD, 3, &aParmsHost[0]);
234 RTTEST_CHECK_RC_RET(g_hTest, rc, VINF_SUCCESS, rc);
235
236 /* Client: Disconnect again. */
237 int rc2 = pTable->pfnDisconnect(pTable->pvService, 1000 /* Client ID */, NULL /* pvClient */);
238 if (RT_SUCCESS(rc))
239 rc = rc2;
240 }
241
242 RTTestSubDone(g_hTest);
243 return rc;
244}
245
246/*
247 * Set environment variable "IPRT_TEST_MAX_LEVEL=all" to get more debug output!
248 */
249int main()
250{
251 RTEXITCODE rcExit = RTTestInitAndCreate("tstGuestControlSvc", &g_hTest);
252 if (rcExit != RTEXITCODE_SUCCESS)
253 return rcExit;
254 RTTestBanner(g_hTest);
255
256 /* Some host info. */
257 RTTestIPrintf(RTTESTLVL_ALWAYS, "sizeof(void*)=%d\n", sizeof(void*));
258
259 /* Do the tests. */
260 VBOXHGCMSVCFNTABLE svcTable;
261 VBOXHGCMSVCHELPERS svcHelpers;
262 RTTEST_CHECK_RC_RET(g_hTest, initTable(&svcTable, &svcHelpers), VINF_SUCCESS, 1);
263
264 do
265 {
266 RTTESTI_CHECK_RC_BREAK(VBoxHGCMSvcLoad(&svcTable), VINF_SUCCESS);
267
268 RTTESTI_CHECK_RC_BREAK(testHost(&svcTable), VINF_SUCCESS);
269
270 RTTESTI_CHECK_RC_BREAK(svcTable.pfnUnload(svcTable.pvService), VINF_SUCCESS);
271
272 RTTESTI_CHECK_RC_BREAK(VBoxHGCMSvcLoad(&svcTable), VINF_SUCCESS);
273
274 RTTESTI_CHECK_RC_BREAK(testClient(&svcTable), VINF_SUCCESS);
275
276 RTTESTI_CHECK_RC_BREAK(svcTable.pfnUnload(svcTable.pvService), VINF_SUCCESS);
277
278 } while (0);
279
280 return RTTestSummaryAndDestroy(g_hTest);
281}
282
Note: See TracBrowser for help on using the repository browser.

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