VirtualBox

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

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

Shared Clipboard: Renaming. bugref:9437

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.6 KB
Line 
1/* $Id: tstClipboardServiceHost.cpp 82846 2020-01-24 09:36:52Z vboxsync $ */
2/** @file
3 * Shared Clipboard host service test case.
4 */
5
6/*
7 * Copyright (C) 2011-2019 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, uint32_t fFormat)
131{
132 int rc = ShClSvcDataReadRequest(pClient, fFormat, 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_TRY_AGAIN;
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_TRY_AGAIN); /* 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_TRY_AGAIN;
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_TRY_AGAIN); /* This call should not complete yet. */
169
170 RTTestISub("Testing one format, no waiting guest calls.");
171 shClSvcClientReset(&g_Client);
172 testMsgAddReadData(&g_Client, VBOX_SHCL_FMT_HTML);
173 HGCMSvcSetU32(&parms[0], 0);
174 HGCMSvcSetU32(&parms[1], 0);
175 call.rc = VERR_TRY_AGAIN;
176 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
177 RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
178 RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_HTML);
179 RTTESTI_CHECK_RC_OK(call.rc);
180 call.rc = VERR_TRY_AGAIN;
181 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
182 RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN); /* This call should not complete yet. */
183
184 RTTestISub("Testing two formats, waiting guest call.");
185 shClSvcClientReset(&g_Client);
186 HGCMSvcSetU32(&parms[0], 0);
187 HGCMSvcSetU32(&parms[1], 0);
188 call.rc = VERR_TRY_AGAIN;
189 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
190 RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN); /* This should get updated only when the guest call completes. */
191 testMsgAddReadData(&g_Client, VBOX_SHCL_FMT_UNICODETEXT | VBOX_SHCL_FMT_HTML);
192 RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
193 RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_UNICODETEXT);
194 RTTESTI_CHECK_RC_OK(call.rc);
195 call.rc = VERR_TRY_AGAIN;
196 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
197 RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
198 RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_HTML);
199 RTTESTI_CHECK_RC_OK(call.rc);
200 call.rc = VERR_TRY_AGAIN;
201 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
202 RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN); /* This call should not complete yet. */
203
204 RTTestISub("Testing two formats, no waiting guest calls.");
205 shClSvcClientReset(&g_Client);
206 testMsgAddReadData(&g_Client, VBOX_SHCL_FMT_UNICODETEXT | VBOX_SHCL_FMT_HTML);
207 HGCMSvcSetU32(&parms[0], 0);
208 HGCMSvcSetU32(&parms[1], 0);
209 call.rc = VERR_TRY_AGAIN;
210 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
211 RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
212 RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_UNICODETEXT);
213 RTTESTI_CHECK_RC_OK(call.rc);
214 call.rc = VERR_TRY_AGAIN;
215 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
216 RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHCL_HOST_MSG_READ_DATA);
217 RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHCL_FMT_HTML);
218 RTTESTI_CHECK_RC_OK(call.rc);
219 call.rc = VERR_TRY_AGAIN;
220 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, 2, parms, 0);
221 RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN); /* This call should not complete yet. */
222 table.pfnDisconnect(NULL, 1 /* clientId */, &g_Client);
223 table.pfnUnload(NULL);
224}
225
226static void testSetHeadless(void)
227{
228 struct VBOXHGCMSVCPARM parms[2];
229 VBOXHGCMSVCFNTABLE table;
230 bool fHeadless;
231 int rc;
232
233 RTTestISub("Testing HOST_FN_SET_HEADLESS");
234 rc = setupTable(&table);
235 RTTESTI_CHECK_MSG_RETV(RT_SUCCESS(rc), ("rc=%Rrc\n", rc));
236 /* Reset global variable which doesn't reset itself. */
237 HGCMSvcSetU32(&parms[0], false);
238 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_HEADLESS,
239 1, parms);
240 RTTESTI_CHECK_RC_OK(rc);
241 fHeadless = ShClSvcGetHeadless();
242 RTTESTI_CHECK_MSG(fHeadless == false, ("fHeadless=%RTbool\n", fHeadless));
243 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_HEADLESS,
244 0, parms);
245 RTTESTI_CHECK_RC(rc, VERR_INVALID_PARAMETER);
246 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_HEADLESS,
247 2, parms);
248 RTTESTI_CHECK_RC(rc, VERR_INVALID_PARAMETER);
249 HGCMSvcSetU64(&parms[0], 99);
250 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_HEADLESS,
251 1, parms);
252 RTTESTI_CHECK_RC(rc, VERR_INVALID_PARAMETER);
253 HGCMSvcSetU32(&parms[0], true);
254 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_HEADLESS,
255 1, parms);
256 RTTESTI_CHECK_RC_OK(rc);
257 fHeadless = ShClSvcGetHeadless();
258 RTTESTI_CHECK_MSG(fHeadless == true, ("fHeadless=%RTbool\n", fHeadless));
259 HGCMSvcSetU32(&parms[0], 99);
260 rc = table.pfnHostCall(NULL, VBOX_SHCL_HOST_FN_SET_HEADLESS,
261 1, parms);
262 RTTESTI_CHECK_RC_OK(rc);
263 fHeadless = ShClSvcGetHeadless();
264 RTTESTI_CHECK_MSG(fHeadless == true, ("fHeadless=%RTbool\n", fHeadless));
265 table.pfnUnload(NULL);
266}
267
268static void testHostCall(void)
269{
270 testSetMode();
271#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
272 testSetTransferMode();
273#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
274 testSetHeadless();
275}
276
277int main(int argc, char *argv[])
278{
279 /*
280 * Init the runtime, test and say hello.
281 */
282 const char *pcszExecName;
283 NOREF(argc);
284 pcszExecName = strrchr(argv[0], '/');
285 pcszExecName = pcszExecName ? pcszExecName + 1 : argv[0];
286 RTTEST hTest;
287 RTEXITCODE rcExit = RTTestInitAndCreate(pcszExecName, &hTest);
288 if (rcExit != RTEXITCODE_SUCCESS)
289 return rcExit;
290 RTTestBanner(hTest);
291
292 /*
293 * Run the tests.
294 */
295 testHostCall();
296 testGetHostMsgOld();
297
298 /*
299 * Summary
300 */
301 return RTTestSummaryAndDestroy(hTest);
302}
303
304int ShClSvcImplInit() { return VINF_SUCCESS; }
305void ShClSvcImplDestroy() { }
306int ShClSvcImplDisconnect(PSHCLCLIENT) { return VINF_SUCCESS; }
307int ShClSvcImplConnect(PSHCLCLIENT, bool) { return VINF_SUCCESS; }
308int ShClSvcImplFormatAnnounce(PSHCLCLIENT, PSHCLCLIENTCMDCTX, PSHCLFORMATDATA) { AssertFailed(); return VINF_SUCCESS; }
309int ShClSvcImplReadData(PSHCLCLIENT, PSHCLCLIENTCMDCTX, PSHCLDATABLOCK, unsigned int *) { AssertFailed(); return VERR_WRONG_ORDER; }
310int ShClSvcImplWriteData(PSHCLCLIENT, PSHCLCLIENTCMDCTX, PSHCLDATABLOCK) { AssertFailed(); return VINF_SUCCESS; }
311int ShClSvcImplSync(PSHCLCLIENT) { return VINF_SUCCESS; }
312
313#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
314int ShClSvcImplTransferCreate(PSHCLCLIENT, PSHCLTRANSFER) { return VINF_SUCCESS; }
315int ShClSvcImplTransferDestroy(PSHCLCLIENT, PSHCLTRANSFER) { return VINF_SUCCESS; }
316int ShClSvcImplTransferGetRoots(PSHCLCLIENT, PSHCLTRANSFER) { return VINF_SUCCESS; }
317#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
318
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