VirtualBox

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

Last change on this file since 58171 was 58171, checked in by vboxsync, 9 years ago

doxygen: fixes.

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