VirtualBox

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

最後變更 在這個檔案從100204是 100204,由 vboxsync 提交於 21 月 前

Shared Clipboard: Unified root list entry code to also use the generic list entry code, a lot of updates for the cross OS transfer handling code, more updates for HTTP server transfer handling.

This also changed the handling of how that transfers are being initiated, as we needed to have this for X11: Before, transfers were initiated as soon as on side announced the URI list format -- now we postpone initiating the transfer until the receiving side requests the data as URI list.

bugref:9437

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

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