VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardTransfers.cpp@ 100450

Last change on this file since 100450 was 100393, checked in by vboxsync, 17 months ago

Shared Clipboard: Made setting the transfer callbacks part of ShClTransferCreate(), otherwise the pfnOnCreated callback won't be called. ​​bugref:9437

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.5 KB
Line 
1/* $Id: tstClipboardTransfers.cpp 100393 2023-07-05 16:18:02Z vboxsync $ */
2/** @file
3 * Shared Clipboard transfers test case.
4 */
5
6/*
7 * Copyright (C) 2019-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.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/dir.h>
34#include <iprt/file.h>
35#include <iprt/path.h>
36#include <iprt/string.h>
37#include <iprt/test.h>
38
39
40static int testCreateTempDir(RTTEST hTest, const char *pszTestcase, char *pszTempDir, size_t cbTempDir)
41{
42 char szTempDir[RTPATH_MAX];
43 int rc = RTPathTemp(szTempDir, sizeof(szTempDir));
44 RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
45
46 rc = RTPathAppend(szTempDir, sizeof(szTempDir), "tstClipboardTransfers");
47 RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
48
49 rc = RTDirCreate(szTempDir, 0700, 0);
50 if (rc == VERR_ALREADY_EXISTS)
51 rc = VINF_SUCCESS;
52 RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
53
54 rc = RTPathAppend(szTempDir, sizeof(szTempDir), "XXXXX");
55 RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
56
57 rc = RTDirCreateTemp(szTempDir, 0700);
58 RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
59
60 rc = RTPathJoin(pszTempDir, cbTempDir, szTempDir, pszTestcase);
61 RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
62
63 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Created temporary directory: %s\n", pszTempDir);
64
65 return rc;
66}
67
68static int testRemoveTempDir(RTTEST hTest)
69{
70 char szTempDir[RTPATH_MAX];
71 int rc = RTPathTemp(szTempDir, sizeof(szTempDir));
72 RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
73
74 rc = RTPathAppend(szTempDir, sizeof(szTempDir), "tstClipboardTransfers");
75 RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
76
77 rc = RTDirRemoveRecursive(szTempDir, RTDIRRMREC_F_CONTENT_AND_DIR);
78 RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
79
80 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Removed temporary directory: %s\n", szTempDir);
81
82 return rc;
83}
84
85static int testCreateDir(RTTEST hTest, const char *pszPathToCreate)
86{
87 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Creating directory: %s\n", pszPathToCreate);
88
89 int rc = RTDirCreateFullPath(pszPathToCreate, 0700);
90 if (rc == VERR_ALREADY_EXISTS)
91 rc = VINF_SUCCESS;
92 RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
93
94 return rc;
95}
96
97static int testCreateFile(RTTEST hTest, const char *pszTempDir, const char *pszFileName, uint32_t fOpen, size_t cbSize,
98 char **ppszFilePathAbs)
99{
100 char szFilePath[RTPATH_MAX];
101
102 int rc = RTStrCopy(szFilePath, sizeof(szFilePath), pszTempDir);
103 RTTESTI_CHECK_RC_OK_RET(rc, rc);
104
105 rc = RTPathAppend(szFilePath, sizeof(szFilePath), pszFileName);
106 RTTESTI_CHECK_RC_OK_RET(rc, rc);
107
108 char *pszDirToCreate = RTStrDup(szFilePath);
109 RTTESTI_CHECK_RET(pszDirToCreate, VERR_NO_MEMORY);
110
111 RTPathStripFilename(pszDirToCreate);
112
113 rc = testCreateDir(hTest, pszDirToCreate);
114 RTTESTI_CHECK_RC_OK_RET(rc, rc);
115
116 RTStrFree(pszDirToCreate);
117 pszDirToCreate = NULL;
118
119 if (!fOpen)
120 fOpen = RTFILE_O_OPEN_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE;
121
122 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Creating file: %s\n", szFilePath);
123
124 RTFILE hFile;
125 rc = RTFileOpen(&hFile, szFilePath, fOpen);
126 if (RT_SUCCESS(rc))
127 {
128 if (cbSize)
129 {
130 /** @todo Fill in some random stuff. */
131 }
132
133 rc = RTFileClose(hFile);
134 RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
135 }
136
137 if (ppszFilePathAbs)
138 *ppszFilePathAbs = RTStrDup(szFilePath);
139
140 return rc;
141}
142
143typedef struct TESTTRANSFERROOTENTRY
144{
145 TESTTRANSFERROOTENTRY(const RTCString &a_strPath)
146 : strPath(a_strPath) { }
147
148 RTCString strPath;
149} TESTTRANSFERROOTENTRY;
150
151static int testAddRootEntry(RTTEST hTest, const char *pszTempDir,
152 const TESTTRANSFERROOTENTRY &rootEntry, char **ppszRoots)
153{
154 char *pszRoots = NULL;
155
156 const char *pszPath = rootEntry.strPath.c_str();
157
158 char *pszPathAbs;
159 int rc = testCreateFile(hTest, pszTempDir, pszPath, 0, 0, &pszPathAbs);
160 RTTESTI_CHECK_RC_OK_RET(rc, rc);
161
162 rc = RTStrAAppend(&pszRoots, pszPathAbs);
163 RTTESTI_CHECK_RC_OK(rc);
164
165 rc = RTStrAAppend(&pszRoots, "\r\n");
166 RTTESTI_CHECK_RC_OK(rc);
167
168 RTStrFree(pszPathAbs);
169
170 *ppszRoots = pszRoots;
171
172 return rc;
173}
174
175static int testAddRootEntries(RTTEST hTest, const char *pszTempDir,
176 RTCList<TESTTRANSFERROOTENTRY> &lstBase, RTCList<TESTTRANSFERROOTENTRY> lstToExtend,
177 char **ppszRoots)
178{
179 int rc = VINF_SUCCESS;
180
181 char *pszRoots = NULL;
182
183 for (size_t i = 0; i < lstBase.size(); ++i)
184 {
185 char *pszEntry = NULL;
186 rc = testAddRootEntry(hTest, pszTempDir, lstBase.at(i), &pszEntry);
187 RTTESTI_CHECK_RC_OK_BREAK(rc);
188 rc = RTStrAAppend(&pszRoots, pszEntry);
189 RTTESTI_CHECK_RC_OK_BREAK(rc);
190 RTStrFree(pszEntry);
191 }
192
193 for (size_t i = 0; i < lstToExtend.size(); ++i)
194 {
195 char *pszEntry = NULL;
196 rc = testAddRootEntry(hTest, pszTempDir, lstToExtend.at(i), &pszEntry);
197 RTTESTI_CHECK_RC_OK_BREAK(rc);
198 rc = RTStrAAppend(&pszRoots, pszEntry);
199 RTTESTI_CHECK_RC_OK_BREAK(rc);
200 RTStrFree(pszEntry);
201 }
202
203 if (RT_SUCCESS(rc))
204 *ppszRoots = pszRoots;
205
206 return rc;
207}
208
209static void testTransferRootsSetSingle(RTTEST hTest,
210 RTCList<TESTTRANSFERROOTENTRY> &lstBase, RTCList<TESTTRANSFERROOTENTRY> lstToExtend,
211 int rcExpected)
212{
213 PSHCLTRANSFER pTransfer;
214 int rc = ShClTransferCreate(SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, NULL /* Callbacks */, &pTransfer);
215 RTTESTI_CHECK_RC_OK(rc);
216
217 SHCLTXPROVIDER Provider;
218 RTTESTI_CHECK(ShClTransferProviderLocalQueryInterface(&Provider) != NULL);
219 RTTESTI_CHECK_RC_OK(ShClTransferSetProvider(pTransfer, &Provider));
220
221 char szTestTransferRootsSetDir[RTPATH_MAX];
222 rc = testCreateTempDir(hTest, "testTransferRootsSet", szTestTransferRootsSetDir, sizeof(szTestTransferRootsSetDir));
223 RTTESTI_CHECK_RC_OK_RETV(rc);
224
225 /* This is the file we're trying to access (but not supposed to). */
226 rc = testCreateFile(hTest, szTestTransferRootsSetDir, "must-not-access-this", 0, 0, NULL);
227 RTTESTI_CHECK_RC_OK(rc);
228
229 char *pszRoots;
230 rc = testAddRootEntries(hTest, szTestTransferRootsSetDir, lstBase, lstToExtend, &pszRoots);
231 RTTESTI_CHECK_RC_OK_RETV(rc);
232
233 rc = ShClTransferRootsInitFromStringList(pTransfer, pszRoots, strlen(pszRoots) + 1);
234 RTTESTI_CHECK_RC(rc, rcExpected);
235
236 RTStrFree(pszRoots);
237
238 rc = ShClTransferDestroy(pTransfer);
239 RTTESTI_CHECK_RC_OK(rc);
240}
241
242static void testTransferObjOpenSingle(RTTEST hTest,
243 RTCList<TESTTRANSFERROOTENTRY> &lstRoots, const char *pszObjPath, int rcExpected)
244{
245 RT_NOREF(hTest);
246
247 PSHCLTRANSFER pTransfer;
248 int rc = ShClTransferCreate(SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, NULL /* Callbacks */, &pTransfer);
249 RTTESTI_CHECK_RC_OK(rc);
250
251 SHCLTXPROVIDER Provider;
252 ShClTransferProviderLocalQueryInterface(&Provider);
253
254 rc = ShClTransferSetProvider(pTransfer, &Provider);
255 RTTESTI_CHECK_RC_OK(rc);
256
257 rc = ShClTransferInit(pTransfer);
258 RTTESTI_CHECK_RC_OK(rc);
259
260 char szTestTransferObjOpenDir[RTPATH_MAX];
261 rc = testCreateTempDir(hTest, "testTransferObjOpen", szTestTransferObjOpenDir, sizeof(szTestTransferObjOpenDir));
262 RTTESTI_CHECK_RC_OK_RETV(rc);
263
264 /* This is the file we're trying to access (but not supposed to). */
265 rc = testCreateFile(hTest, szTestTransferObjOpenDir, "file1.txt", 0, 0, NULL);
266 RTTESTI_CHECK_RC_OK(rc);
267
268 RTCList<TESTTRANSFERROOTENTRY> lstToExtendEmpty;
269
270 char *pszRoots;
271 rc = testAddRootEntries(hTest, szTestTransferObjOpenDir, lstRoots, lstToExtendEmpty, &pszRoots);
272 RTTESTI_CHECK_RC_OK_RETV(rc);
273
274 rc = ShClTransferRootsInitFromStringList(pTransfer, pszRoots, strlen(pszRoots) + 1);
275 RTTESTI_CHECK_RC_OK(rc);
276
277 RTStrFree(pszRoots);
278
279 SHCLOBJOPENCREATEPARMS openCreateParms;
280 rc = ShClTransferObjOpenParmsInit(&openCreateParms);
281 RTTESTI_CHECK_RC_OK(rc);
282
283 rc = RTStrCopy(openCreateParms.pszPath, openCreateParms.cbPath, pszObjPath);
284 RTTESTI_CHECK_RC_OK(rc);
285
286 SHCLOBJHANDLE hObj;
287 rc = ShClTransferObjOpen(pTransfer, &openCreateParms, &hObj);
288 RTTESTI_CHECK_RC(rc, rcExpected);
289 if (RT_SUCCESS(rc))
290 {
291 rc = ShClTransferObjClose(pTransfer, hObj);
292 RTTESTI_CHECK_RC_OK(rc);
293 }
294
295 rc = ShClTransferDestroy(pTransfer);
296 RTTESTI_CHECK_RC_OK(rc);
297}
298
299static void testTransferBasics(RTTEST hTest)
300{
301 RT_NOREF(hTest);
302
303 RTTestISub("Testing transfer basics");
304
305 SHCLEVENTSOURCE Source;
306 int rc = ShClEventSourceCreate(&Source, 0);
307 RTTESTI_CHECK_RC_OK(rc);
308 rc = ShClEventSourceDestroy(&Source);
309 RTTESTI_CHECK_RC_OK(rc);
310 PSHCLTRANSFER pTransfer;
311 rc = ShClTransferCreate(SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, NULL /* Callbacks */, &pTransfer);
312 RTTESTI_CHECK_RC_OK(rc);
313 rc = ShClTransferDestroy(pTransfer);
314 RTTESTI_CHECK_RC_OK(rc);
315 rc = ShClTransferDestroy(pTransfer); /* Second time, intentional. */
316 RTTESTI_CHECK_RC_OK(rc);
317
318 PSHCLLIST pList = ShClTransferListAlloc();
319 RTTESTI_CHECK(pList != NULL);
320 rc = ShClTransferCreate(SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, NULL /* Callbacks */, &pTransfer);
321 RTTESTI_CHECK_RC_OK(rc);
322 ShClTransferListFree(pList);
323 pList = NULL;
324 ShClTransferListFree(pList); /* Second time, intentional. */
325
326 SHCLLISTENTRY Entry;
327 RTTESTI_CHECK_RC_OK(ShClTransferListEntryInit(&Entry));
328 ShClTransferListEntryDestroy(&Entry);
329 ShClTransferListEntryDestroy(&Entry); /* Second time, intentional. */
330}
331
332static void testTransferRootsSet(RTTEST hTest)
333{
334 RTTestISub("Testing setting transfer roots");
335
336 /* Define the (valid) transfer root set. */
337 RTCList<TESTTRANSFERROOTENTRY> lstBase;
338 lstBase.append(TESTTRANSFERROOTENTRY("my-transfer-1/file1.txt"));
339 lstBase.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir1/file1.txt"));
340 lstBase.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir1/sub1/file1.txt"));
341 lstBase.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir2/file1.txt"));
342 lstBase.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir2/sub1/file1.txt"));
343
344 RTCList<TESTTRANSFERROOTENTRY> lstBreakout;
345 testTransferRootsSetSingle(hTest, lstBase, lstBreakout, VINF_SUCCESS);
346
347 lstBreakout.clear();
348 lstBase.append(TESTTRANSFERROOTENTRY("../must-not-access-this"));
349 testTransferRootsSetSingle(hTest, lstBase, lstBreakout, VERR_INVALID_PARAMETER);
350
351 lstBreakout.clear();
352 lstBase.append(TESTTRANSFERROOTENTRY("does-not-exist/file1.txt"));
353 testTransferRootsSetSingle(hTest, lstBase, lstBreakout, VERR_INVALID_PARAMETER);
354
355 lstBreakout.clear();
356 lstBase.append(TESTTRANSFERROOTENTRY("my-transfer-1/../must-not-access-this"));
357 testTransferRootsSetSingle(hTest, lstBase, lstBreakout, VERR_INVALID_PARAMETER);
358
359 lstBreakout.clear();
360 lstBase.append(TESTTRANSFERROOTENTRY("my-transfer-1/./../must-not-access-this"));
361 testTransferRootsSetSingle(hTest, lstBase, lstBreakout, VERR_INVALID_PARAMETER);
362
363 lstBreakout.clear();
364 lstBase.append(TESTTRANSFERROOTENTRY("../does-not-exist"));
365 testTransferRootsSetSingle(hTest, lstBase, lstBreakout, VERR_INVALID_PARAMETER);
366}
367
368static void testTransferObjOpen(RTTEST hTest)
369{
370 RTTestISub("Testing setting transfer object open");
371
372 /* Define the (valid) transfer root set. */
373 RTCList<TESTTRANSFERROOTENTRY> lstRoots;
374 lstRoots.append(TESTTRANSFERROOTENTRY("my-transfer-1/file1.txt"));
375 lstRoots.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir1/file1.txt"));
376 lstRoots.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir1/sub1/file1.txt"));
377 lstRoots.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir2/file1.txt"));
378 lstRoots.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir2/sub1/file1.txt"));
379
380 testTransferObjOpenSingle(hTest, lstRoots, "file1.txt", VINF_SUCCESS);
381 testTransferObjOpenSingle(hTest, lstRoots, "does-not-exist.txt", VERR_PATH_NOT_FOUND);
382 testTransferObjOpenSingle(hTest, lstRoots, "dir1/does-not-exist.txt", VERR_PATH_NOT_FOUND);
383 testTransferObjOpenSingle(hTest, lstRoots, "../must-not-access-this.txt", VERR_INVALID_PARAMETER);
384 testTransferObjOpenSingle(hTest, lstRoots, "dir1/../../must-not-access-this.txt", VERR_INVALID_PARAMETER);
385}
386
387int main(int argc, char *argv[])
388{
389 /*
390 * Init the runtime, test and say hello.
391 */
392 const char *pcszExecName;
393 NOREF(argc);
394 pcszExecName = strrchr(argv[0], '/');
395 pcszExecName = pcszExecName ? pcszExecName + 1 : argv[0];
396 RTTEST hTest;
397 RTEXITCODE rcExit = RTTestInitAndCreate(pcszExecName, &hTest);
398 if (rcExit != RTEXITCODE_SUCCESS)
399 return rcExit;
400 RTTestBanner(hTest);
401
402 testTransferBasics(hTest);
403 testTransferRootsSet(hTest);
404 testTransferObjOpen(hTest);
405
406 int rc = testRemoveTempDir(hTest);
407 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
408
409 /*
410 * Summary
411 */
412 return RTTestSummaryAndDestroy(hTest);
413}
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