VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardServiceHost.cpp@ 85672

Last change on this file since 85672 was 84142, checked in by vboxsync, 5 years ago

Shared Clipboard/HostService: Renaming to match terminology (*SvcImpl* -> *Backend*).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.2 KB
Line 
1/* $Id: tstClipboardServiceHost.cpp 84142 2020-05-05 07:13:00Z vboxsync $ */
2/** @file
3 * Shared Clipboard host service test case.
4 */
5
6/*
7 * Copyright (C) 2011-2020 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#include "../VBoxSharedClipboardSvc-internal.h"
19
20#include <VBox/HostServices/VBoxClipboardSvc.h>
21
22#include <iprt/assert.h>
23#include <iprt/string.h>
24#include <iprt/test.h>
25
26extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable);
27
28static SHCLCLIENT g_Client;
29static VBOXHGCMSVCHELPERS g_Helpers = { NULL };
30
31/** Simple call handle structure for the guest call completion callback */
32struct VBOXHGCMCALLHANDLE_TYPEDEF
33{
34 /** Where to store the result code */
35 int32_t rc;
36};
37
38/** Call completion callback for guest calls. */
39static DECLCALLBACK(int) callComplete(VBOXHGCMCALLHANDLE callHandle, int32_t rc)
40{
41 callHandle->rc = rc;
42 return VINF_SUCCESS;
43}
44
45static int setupTable(VBOXHGCMSVCFNTABLE *pTable)
46{
47 pTable->cbSize = sizeof(*pTable);
48 pTable->u32Version = VBOX_HGCM_SVC_VERSION;
49 g_Helpers.pfnCallComplete = callComplete;
50 pTable->pHelpers = &g_Helpers;
51 return VBoxHGCMSvcLoad(pTable);
52}
53
54static void testSetMode(void)
55{
56 struct VBOXHGCMSVCPARM parms[2];
57 VBOXHGCMSVCFNTABLE table;
58 uint32_t u32Mode;
59 int rc;
60
61 RTTestISub("Testing VBOX_SHCL_HOST_FN_SET_MODE");
62 rc = setupTable(&table);
63 RTTESTI_CHECK_MSG_RETV(RT_SUCCESS(rc), ("rc=%Rrc\n", rc));
64
65 /* Reset global variable which doesn't reset itself. */
66 HGCMSvcSetU32(&parms[0], VBOX_SHCL_MODE_OFF);
67 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_MODE, 1, parms);
68 RTTESTI_CHECK_RC_OK(rc);
69 u32Mode = ShClSvcGetMode();
70 RTTESTI_CHECK_MSG(u32Mode == VBOX_SHCL_MODE_OFF, ("u32Mode=%u\n", (unsigned) u32Mode));
71
72 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_MODE, 0, parms);
73 RTTESTI_CHECK_RC(rc, VERR_INVALID_PARAMETER);
74
75 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_MODE, 2, parms);
76 RTTESTI_CHECK_RC(rc, VERR_INVALID_PARAMETER);
77
78 HGCMSvcSetU64(&parms[0], 99);
79 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_MODE, 1, parms);
80 RTTESTI_CHECK_RC(rc, VERR_INVALID_PARAMETER);
81
82 HGCMSvcSetU32(&parms[0], VBOX_SHCL_MODE_HOST_TO_GUEST);
83 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_MODE, 1, parms);
84 RTTESTI_CHECK_RC_OK(rc);
85 u32Mode = ShClSvcGetMode();
86 RTTESTI_CHECK_MSG(u32Mode == VBOX_SHCL_MODE_HOST_TO_GUEST, ("u32Mode=%u\n", (unsigned) u32Mode));
87
88 HGCMSvcSetU32(&parms[0], 99);
89 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_MODE, 1, parms);
90 RTTESTI_CHECK_RC(rc, VERR_NOT_SUPPORTED);
91
92 u32Mode = ShClSvcGetMode();
93 RTTESTI_CHECK_MSG(u32Mode == VBOX_SHCL_MODE_OFF, ("u32Mode=%u\n", (unsigned) u32Mode));
94 table.pfnUnload(NULL);
95}
96
97#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
98static void testSetTransferMode(void)
99{
100 struct VBOXHGCMSVCPARM parms[2];
101 VBOXHGCMSVCFNTABLE table;
102
103 RTTestISub("Testing VBOX_SHCL_HOST_FN_SET_TRANSFER_MODE");
104 int rc = setupTable(&table);
105 RTTESTI_CHECK_MSG_RETV(RT_SUCCESS(rc), ("rc=%Rrc\n", rc));
106
107 /* Invalid parameter. */
108 HGCMSvcSetU64(&parms[0], 99);
109 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_TRANSFER_MODE, 1, parms);
110 RTTESTI_CHECK_RC(rc, VERR_INVALID_PARAMETER);
111
112 /* Invalid mode. */
113 HGCMSvcSetU32(&parms[0], 99);
114 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_TRANSFER_MODE, 1, parms);
115 RTTESTI_CHECK_RC(rc, VERR_INVALID_FLAGS);
116
117 /* Enable transfers. */
118 HGCMSvcSetU32(&parms[0], VBOX_SHCL_TRANSFER_MODE_ENABLED);
119 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_TRANSFER_MODE, 1, parms);
120 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
121
122 /* Disable transfers again. */
123 HGCMSvcSetU32(&parms[0], VBOX_SHCL_TRANSFER_MODE_DISABLED);
124 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_TRANSFER_MODE, 1, parms);
125 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
126}
127#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
128
129/* Adds a host data read request message to the client's message queue. */
130static void testMsgAddReadData(PSHCLCLIENT pClient, SHCLFORMATS fFormats)
131{
132 int rc = ShClSvcDataReadRequest(pClient, fFormats, NULL /* pidEvent */);
133 RTTESTI_CHECK_RC_OK(rc);
134}
135
136/* Does testing of VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, needed for providing compatibility to older Guest Additions clients. */
137static void testGetHostMsgOld(void)
138{
139 struct VBOXHGCMSVCPARM parms[2];
140 VBOXHGCMSVCFNTABLE table;
141 VBOXHGCMCALLHANDLE_TYPEDEF call;
142 int rc;
143
144 RTTestISub("Setting up VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT test");
145 rc = setupTable(&table);
146 RTTESTI_CHECK_MSG_RETV(RT_SUCCESS(rc), ("rc=%Rrc\n", rc));
147 /* Unless we are bidirectional the host message requests will be dropped. */
148 HGCMSvcSetU32(&parms[0], VBOX_SHCL_MODE_BIDIRECTIONAL);
149 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_MODE, 1, parms);
150 RTTESTI_CHECK_RC_OK(rc);
151
152 rc = shClSvcClientInit(&g_Client, 1 /* clientId */);
153 RTTESTI_CHECK_RC_OK(rc);
154
155 RTTestISub("Testing one format, waiting guest call.");
156 HGCMSvcSetU32(&parms[0], 0);
157 HGCMSvcSetU32(&parms[1], 0);
158 call.rc = VERR_IPE_UNINITIALIZED_STATUS;
159 table.pfnConnect(NULL, 1 /* clientId */, &g_Client, 0, 0);
160 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
161 RTTESTI_CHECK_RC(call.rc, VERR_IPE_UNINITIALIZED_STATUS); /* This should get updated only when the guest call completes. */
162 testMsgAddReadData(&g_Client, VBOX_SHCL_FMT_UNICODETEXT);
163 RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
164 RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_UNICODETEXT);
165 RTTESTI_CHECK_RC_OK(call.rc);
166 call.rc = VERR_IPE_UNINITIALIZED_STATUS;
167 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
168 RTTESTI_CHECK_RC(call.rc, VERR_IPE_UNINITIALIZED_STATUS); /* This call should not complete yet. */
169 table.pfnDisconnect(NULL, 1 /* clientId */, &g_Client);
170
171 RTTestISub("Testing one format, no waiting guest calls.");
172 table.pfnConnect(NULL, 1 /* clientId */, &g_Client, 0, 0);
173 testMsgAddReadData(&g_Client, VBOX_SHCL_FMT_HTML);
174 HGCMSvcSetU32(&parms[0], 0);
175 HGCMSvcSetU32(&parms[1], 0);
176 call.rc = VERR_IPE_UNINITIALIZED_STATUS;
177 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
178 RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
179 RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_HTML);
180 RTTESTI_CHECK_RC_OK(call.rc);
181 call.rc = VERR_IPE_UNINITIALIZED_STATUS;
182 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
183 RTTESTI_CHECK_RC(call.rc, VERR_IPE_UNINITIALIZED_STATUS); /* This call should not complete yet. */
184 table.pfnDisconnect(NULL, 1 /* clientId */, &g_Client);
185
186 RTTestISub("Testing two formats, waiting guest call.");
187 table.pfnConnect(NULL, 1 /* clientId */, &g_Client, 0, 0);
188 HGCMSvcSetU32(&parms[0], 0);
189 HGCMSvcSetU32(&parms[1], 0);
190 call.rc = VERR_IPE_UNINITIALIZED_STATUS;
191 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
192 RTTESTI_CHECK_RC(call.rc, VERR_IPE_UNINITIALIZED_STATUS); /* This should get updated only when the guest call completes. */
193 testMsgAddReadData(&g_Client, VBOX_SHCL_FMT_UNICODETEXT | VBOX_SHCL_FMT_HTML);
194 RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
195 RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_UNICODETEXT);
196 RTTESTI_CHECK_RC_OK(call.rc);
197 call.rc = VERR_IPE_UNINITIALIZED_STATUS;
198 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
199 RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
200 RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_HTML);
201 RTTESTI_CHECK_RC_OK(call.rc);
202 call.rc = VERR_IPE_UNINITIALIZED_STATUS;
203 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
204 RTTESTI_CHECK_RC(call.rc, VERR_IPE_UNINITIALIZED_STATUS); /* This call should not complete yet. */
205 table.pfnDisconnect(NULL, 1 /* clientId */, &g_Client);
206
207 RTTestISub("Testing two formats, no waiting guest calls.");
208 table.pfnConnect(NULL, 1 /* clientId */, &g_Client, 0, 0);
209 testMsgAddReadData(&g_Client, VBOX_SHCL_FMT_UNICODETEXT | VBOX_SHCL_FMT_HTML);
210 HGCMSvcSetU32(&parms[0], 0);
211 HGCMSvcSetU32(&parms[1], 0);
212 call.rc = VERR_IPE_UNINITIALIZED_STATUS;
213 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
214 RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
215 RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_UNICODETEXT);
216 RTTESTI_CHECK_RC_OK(call.rc);
217 call.rc = VERR_IPE_UNINITIALIZED_STATUS;
218 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
219 RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
220 RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_HTML);
221 RTTESTI_CHECK_RC_OK(call.rc);
222 call.rc = VERR_IPE_UNINITIALIZED_STATUS;
223 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
224 RTTESTI_CHECK_RC(call.rc, VERR_IPE_UNINITIALIZED_STATUS); /* This call should not complete yet. */
225 table.pfnDisconnect(NULL, 1 /* clientId */, &g_Client);
226 table.pfnUnload(NULL);
227}
228
229static void testSetHeadless(void)
230{
231 struct VBOXHGCMSVCPARM parms[2];
232 VBOXHGCMSVCFNTABLE table;
233 bool fHeadless;
234 int rc;
235
236 RTTestISub("Testing HOST_FN_SET_HEADLESS");
237 rc = setupTable(&table);
238 RTTESTI_CHECK_MSG_RETV(RT_SUCCESS(rc), ("rc=%Rrc\n", rc));
239 /* Reset global variable which doesn't reset itself. */
240 HGCMSvcSetU32(&parms[0], false);
241 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_HEADLESS,
242 1, parms);
243 RTTESTI_CHECK_RC_OK(rc);
244 fHeadless = ShClSvcGetHeadless();
245 RTTESTI_CHECK_MSG(fHeadless == false, ("fHeadless=%RTbool\n", fHeadless));
246 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_HEADLESS,
247 0, parms);
248 RTTESTI_CHECK_RC(rc, VERR_INVALID_PARAMETER);
249 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_HEADLESS,
250 2, parms);
251 RTTESTI_CHECK_RC(rc, VERR_INVALID_PARAMETER);
252 HGCMSvcSetU64(&parms[0], 99);
253 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_HEADLESS,
254 1, parms);
255 RTTESTI_CHECK_RC(rc, VERR_INVALID_PARAMETER);
256 HGCMSvcSetU32(&parms[0], true);
257 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_HEADLESS,
258 1, parms);
259 RTTESTI_CHECK_RC_OK(rc);
260 fHeadless = ShClSvcGetHeadless();
261 RTTESTI_CHECK_MSG(fHeadless == true, ("fHeadless=%RTbool\n", fHeadless));
262 HGCMSvcSetU32(&parms[0], 99);
263 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_HEADLESS,
264 1, parms);
265 RTTESTI_CHECK_RC_OK(rc);
266 fHeadless = ShClSvcGetHeadless();
267 RTTESTI_CHECK_MSG(fHeadless == true, ("fHeadless=%RTbool\n", fHeadless));
268 table.pfnUnload(NULL);
269}
270
271static void testHostCall(void)
272{
273 testSetMode();
274#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
275 testSetTransferMode();
276#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
277 testSetHeadless();
278}
279
280int main(int argc, char *argv[])
281{
282 /*
283 * Init the runtime, test and say hello.
284 */
285 const char *pcszExecName;
286 NOREF(argc);
287 pcszExecName = strrchr(argv[0], '/');
288 pcszExecName = pcszExecName ? pcszExecName + 1 : argv[0];
289 RTTEST hTest;
290 RTEXITCODE rcExit = RTTestInitAndCreate(pcszExecName, &hTest);
291 if (rcExit != RTEXITCODE_SUCCESS)
292 return rcExit;
293 RTTestBanner(hTest);
294
295 /* Don't let assertions in the host service panic (core dump) the test cases. */
296 RTAssertSetMayPanic(false);
297
298 /*
299 * Run the tests.
300 */
301 testHostCall();
302 testGetHostMsgOld();
303
304 /*
305 * Summary
306 */
307 return RTTestSummaryAndDestroy(hTest);
308}
309
310int ShClBackendInit() { return VINF_SUCCESS; }
311void ShClBackendDestroy() { }
312int ShClBackendDisconnect(PSHCLCLIENT) { return VINF_SUCCESS; }
313int ShClBackendConnect(PSHCLCLIENT, bool) { return VINF_SUCCESS; }
314int ShClBackendFormatAnnounce(PSHCLCLIENT, SHCLFORMATS) { AssertFailed(); return VINF_SUCCESS; }
315int ShClBackendReadData(PSHCLCLIENT, PSHCLCLIENTCMDCTX, SHCLFORMAT, void *, uint32_t, unsigned int *) { AssertFailed(); return VERR_WRONG_ORDER; }
316int ShClBackendWriteData(PSHCLCLIENT, PSHCLCLIENTCMDCTX, SHCLFORMAT, void *, uint32_t) { AssertFailed(); return VINF_SUCCESS; }
317int ShClBackendSync(PSHCLCLIENT) { return VINF_SUCCESS; }
318
319#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
320int ShClBackendTransferCreate(PSHCLCLIENT, PSHCLTRANSFER) { return VINF_SUCCESS; }
321int ShClBackendTransferDestroy(PSHCLCLIENT, PSHCLTRANSFER) { return VINF_SUCCESS; }
322int ShClBackendTransferGetRoots(PSHCLCLIENT, PSHCLTRANSFER) { return VINF_SUCCESS; }
323#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
324
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