VirtualBox

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

Last change on this file since 75737 was 75737, checked in by vboxsync, 6 years ago

HGCM: Replace C++-style inline members on VBOXHGCMSVCPARM with simple functions.
bugref:9172: Shared folder performance tuning
Changes in bugref:9172 caused a build regression on Ubuntu 18.10 due to the
use of RT_ZERO on a structure containing an embedded VBOXHGCMSVCPARM, as
VBOXHGCMSVCPARM had member functions and was therefore not a simple plain-
old-data structure. Rather than just doing the sensible thing and zeroing
it in a different way, I converted the inline member getters and setters to
standard inline C functions, including fixing callers. Actually I had planned
this for some time, as the member function use seemed a bit gratuitous in
hindsight.

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