VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedFolders/testcase/tstSharedFolderService.cpp@ 66250

Last change on this file since 66250 was 66099, checked in by vboxsync, 8 years ago

SharedFolders: Some adjustments necessary for flexible array syntax in SHFLSTRING.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 51.1 KB
Line 
1/* $Id: tstSharedFolderService.cpp 66099 2017-03-14 19:06:16Z vboxsync $ */
2/** @file
3 * Testcase for the shared folder service vbsf API.
4 *
5 * Note that this is still very threadbare (there is an awful lot which should
6 * really be tested, but it already took too long to produce this much). The
7 * idea is that anyone who makes changes to the shared folders service and who
8 * cares about unit testing them should add tests to the skeleton framework to
9 * exercise the bits they change before and after changing them.
10 */
11
12/*
13 * Copyright (C) 2011-2016 Oracle Corporation
14 *
15 * This file is part of VirtualBox Open Source Edition (OSE), as
16 * available from http://www.virtualbox.org. This file is free software;
17 * you can redistribute it and/or modify it under the terms of the GNU
18 * General Public License (GPL) as published by the Free Software
19 * Foundation, in version 2 as it comes in the "COPYING" file of the
20 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
21 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
22 */
23
24
25/*********************************************************************************************************************************
26* Header Files *
27*********************************************************************************************************************************/
28
29#include "tstSharedFolderService.h"
30#include "vbsf.h"
31
32#include <iprt/fs.h>
33#include <iprt/dir.h>
34#include <iprt/file.h>
35#include <iprt/path.h>
36#include <iprt/symlink.h>
37#include <iprt/stream.h>
38#include <iprt/test.h>
39#include <iprt/string.h>
40#include <iprt/utf16.h>
41
42#include "teststubs.h"
43
44
45/*********************************************************************************************************************************
46* Global Variables *
47*********************************************************************************************************************************/
48static RTTEST g_hTest = NIL_RTTEST;
49
50
51/*********************************************************************************************************************************
52* Declarations *
53*********************************************************************************************************************************/
54extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable);
55
56
57/*********************************************************************************************************************************
58* Helpers *
59*********************************************************************************************************************************/
60
61/** Simple call handle structure for the guest call completion callback */
62struct VBOXHGCMCALLHANDLE_TYPEDEF
63{
64 /** Where to store the result code */
65 int32_t rc;
66};
67
68/** Call completion callback for guest calls. */
69static DECLCALLBACK(void) callComplete(VBOXHGCMCALLHANDLE callHandle, int32_t rc)
70{
71 callHandle->rc = rc;
72}
73
74/**
75 * Initialise the HGCM service table as much as we need to start the
76 * service
77 * @param pTable the table to initialise
78 */
79void initTable(VBOXHGCMSVCFNTABLE *pTable, VBOXHGCMSVCHELPERS *pHelpers)
80{
81 pTable->cbSize = sizeof (VBOXHGCMSVCFNTABLE);
82 pTable->u32Version = VBOX_HGCM_SVC_VERSION;
83 pHelpers->pfnCallComplete = callComplete;
84 pTable->pHelpers = pHelpers;
85}
86
87#define LLUIFY(a) ((unsigned long long)(a))
88
89static void bufferFromString(void *pvDest, size_t cb, const char *pcszSrc)
90{
91 char *pchDest = (char *)pvDest;
92
93 Assert((cb) > 0);
94 strncpy((pchDest), (pcszSrc), (cb) - 1);
95 (pchDest)[(cb) - 1] = 0;
96}
97
98static void bufferFromPath(void *pvDest, size_t cb, const char *pcszSrc)
99{
100 char *psz;
101
102 bufferFromString(pvDest, cb, pcszSrc);
103 for (psz = (char *)pvDest; psz && psz < (char *)pvDest + cb; ++psz)
104 if (*psz == '\\')
105 *psz = '/';
106}
107
108#define ARRAY_FROM_PATH(a, b) \
109 do { \
110 void *p=(a); NOREF(p); \
111 Assert((a) == p); /* Constant parameter */ \
112 Assert(sizeof((a)) > 0); \
113 bufferFromPath(a, sizeof(a), b); \
114 } while (0)
115
116
117/*********************************************************************************************************************************
118* Stub functions and data *
119*********************************************************************************************************************************/
120static bool g_fFailIfNotLowercase = false;
121
122static PRTDIR g_testRTDirClosepDir;
123
124extern int testRTDirClose(PRTDIR pDir)
125{
126 /* RTPrintf("%s: pDir=%p\n", __PRETTY_FUNCTION__, pDir); */
127 g_testRTDirClosepDir = pDir;
128 return VINF_SUCCESS;
129}
130
131static char testRTDirCreatePath[256];
132//static RTFMODE testRTDirCreateMode; - unused
133
134extern int testRTDirCreate(const char *pszPath, RTFMODE fMode, uint32_t fCreate)
135{
136 RT_NOREF2(fMode, fCreate);
137 /* RTPrintf("%s: pszPath=%s, fMode=0x%llx\n", __PRETTY_FUNCTION__, pszPath,
138 LLUIFY(fMode)); */
139 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszPath, "/\\")))
140 return VERR_FILE_NOT_FOUND;
141 ARRAY_FROM_PATH(testRTDirCreatePath, pszPath);
142 return 0;
143}
144
145static char testRTDirOpenName[256];
146static struct TESTDIRHANDLE
147{
148 int iEntry;
149 int iDir;
150} g_aTestDirHandles[4];
151static int g_iNextDirHandle = 0;
152static PRTDIR testRTDirOpenpDir;
153
154extern int testRTDirOpen(PRTDIR *ppDir, const char *pszPath)
155{
156 /* RTPrintf("%s: pszPath=%s\n", __PRETTY_FUNCTION__, pszPath); */
157 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszPath, "/\\")))
158 return VERR_FILE_NOT_FOUND;
159 ARRAY_FROM_PATH(testRTDirOpenName, pszPath);
160 *ppDir = testRTDirOpenpDir;
161 testRTDirOpenpDir = 0;
162 if (!*ppDir && g_fFailIfNotLowercase)
163 *ppDir = (PRTDIR)&g_aTestDirHandles[g_iNextDirHandle++ % RT_ELEMENTS(g_aTestDirHandles)];
164 if (*ppDir)
165 {
166 struct TESTDIRHANDLE *pRealDir = (struct TESTDIRHANDLE *)*ppDir;
167 pRealDir->iEntry = 0;
168 pRealDir->iDir = 0;
169 const char *pszSlash = pszPath - 1;
170 while ((pszSlash = strpbrk(pszSlash + 1, "\\/")) != NULL)
171 pRealDir->iDir += 1;
172 /*RTPrintf("opendir %s = %d \n", pszPath, pRealDir->iDir);*/
173 }
174 return VINF_SUCCESS;
175}
176
177/** @todo Do something useful with the last two arguments. */
178extern int testRTDirOpenFiltered(PRTDIR *ppDir, const char *pszPath, RTDIRFILTER, uint32_t)
179{
180 /* RTPrintf("%s: pszPath=%s\n", __PRETTY_FUNCTION__, pszPath); */
181 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszPath, "/\\")))
182 return VERR_FILE_NOT_FOUND;
183 ARRAY_FROM_PATH(testRTDirOpenName, pszPath);
184 *ppDir = testRTDirOpenpDir;
185 testRTDirOpenpDir = 0;
186 if (!*ppDir && g_fFailIfNotLowercase)
187 *ppDir = (PRTDIR)&g_aTestDirHandles[g_iNextDirHandle++ % RT_ELEMENTS(g_aTestDirHandles)];
188 if (*ppDir)
189 {
190 struct TESTDIRHANDLE *pRealDir = (struct TESTDIRHANDLE *)*ppDir;
191 pRealDir->iEntry = 0;
192 pRealDir->iDir = 0;
193 const char *pszSlash = pszPath - 1;
194 while ((pszSlash = strpbrk(pszSlash + 1, "\\/")) != NULL)
195 pRealDir->iDir += 1;
196 pRealDir->iDir -= 1;
197 /*RTPrintf("openfiltered %s = %d\n", pszPath, pRealDir->iDir);*/
198 }
199 return VINF_SUCCESS;
200}
201
202static PRTDIR g_testRTDirQueryInfoDir;
203static RTTIMESPEC testRTDirQueryInfoATime;
204
205extern int testRTDirQueryInfo(PRTDIR pDir, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs)
206{
207 RT_NOREF1(enmAdditionalAttribs);
208 /* RTPrintf("%s: pDir=%p, enmAdditionalAttribs=0x%llx\n", __PRETTY_FUNCTION__,
209 pDir, LLUIFY(enmAdditionalAttribs)); */
210 g_testRTDirQueryInfoDir = pDir;
211 RT_ZERO(*pObjInfo);
212 pObjInfo->AccessTime = testRTDirQueryInfoATime;
213 RT_ZERO(testRTDirQueryInfoATime);
214 return VINF_SUCCESS;
215}
216
217extern int testRTDirRemove(const char *pszPath)
218{
219 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszPath, "/\\")))
220 return VERR_FILE_NOT_FOUND;
221 RTPrintf("%s\n", __PRETTY_FUNCTION__);
222 return 0;
223}
224
225static PRTDIR g_testRTDirReadExDir;
226
227extern int testRTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry,
228 RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
229{
230 RT_NOREF4(pDirEntry, pcbDirEntry, enmAdditionalAttribs, fFlags);
231 /* RTPrintf("%s: pDir=%p, pcbDirEntry=%d, enmAdditionalAttribs=%llu, fFlags=0x%llx\n",
232 __PRETTY_FUNCTION__, pDir, pcbDirEntry ? (int) *pcbDirEntry : -1,
233 LLUIFY(enmAdditionalAttribs), LLUIFY(fFlags)); */
234 g_testRTDirReadExDir = pDir;
235 if (g_fFailIfNotLowercase && pDir)
236 {
237 struct TESTDIRHANDLE *pRealDir = (struct TESTDIRHANDLE *)pDir;
238 if (pRealDir->iDir == 2) /* /test/mapping/ */
239 {
240 if (pRealDir->iEntry == 0)
241 {
242 pRealDir->iEntry++;
243 RT_ZERO(*pDirEntry);
244 pDirEntry->Info.Attr.fMode = RTFS_TYPE_DIRECTORY | RTFS_DOS_DIRECTORY | RTFS_UNIX_IROTH | RTFS_UNIX_IXOTH;
245 pDirEntry->cbName = 4;
246 pDirEntry->cwcShortName = 4;
247 strcpy(pDirEntry->szName, "test");
248 RTUtf16CopyAscii(pDirEntry->wszShortName, RT_ELEMENTS(pDirEntry->wszShortName), "test");
249 /*RTPrintf("readdir: 'test'\n");*/
250 return VINF_SUCCESS;
251 }
252 }
253 else if (pRealDir->iDir == 3) /* /test/mapping/test/ */
254 {
255 if (pRealDir->iEntry == 0)
256 {
257 pRealDir->iEntry++;
258 RT_ZERO(*pDirEntry);
259 pDirEntry->Info.Attr.fMode = RTFS_TYPE_FILE | RTFS_DOS_NT_NORMAL | RTFS_UNIX_IROTH | RTFS_UNIX_IXOTH;
260 pDirEntry->cbName = 4;
261 pDirEntry->cwcShortName = 4;
262 strcpy(pDirEntry->szName, "file");
263 RTUtf16CopyAscii(pDirEntry->wszShortName, RT_ELEMENTS(pDirEntry->wszShortName), "file");
264 /*RTPrintf("readdir: 'file'\n");*/
265 return VINF_SUCCESS;
266 }
267 }
268 /*else RTPrintf("%s: iDir=%d\n", pRealDir->iDir);*/
269 }
270 return VERR_NO_MORE_FILES;
271}
272
273static RTTIMESPEC testRTDirSetTimesATime;
274
275extern int testRTDirSetTimes(PRTDIR pDir, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
276 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
277{
278 RT_NOREF4(pDir, pModificationTime, pChangeTime, pBirthTime);
279 /* RTPrintf("%s: pDir=%p, *pAccessTime=%lli, *pModificationTime=%lli, *pChangeTime=%lli, *pBirthTime=%lli\n",
280 __PRETTY_FUNCTION__, pDir,
281 pAccessTime ? (long long)RTTimeSpecGetNano(pAccessTime) : -1,
282 pModificationTime
283 ? (long long)RTTimeSpecGetNano(pModificationTime) : -1,
284 pChangeTime ? (long long)RTTimeSpecGetNano(pChangeTime) : -1,
285 pBirthTime ? (long long)RTTimeSpecGetNano(pBirthTime) : -1); */
286 if (pAccessTime)
287 testRTDirSetTimesATime = *pAccessTime;
288 else
289 RT_ZERO(testRTDirSetTimesATime);
290 return VINF_SUCCESS;
291}
292
293static RTFILE g_testRTFileCloseFile;
294
295extern int testRTFileClose(RTFILE File)
296{
297 /* RTPrintf("%s: File=%p\n", __PRETTY_FUNCTION__, File); */
298 g_testRTFileCloseFile = File;
299 return 0;
300}
301
302extern int testRTFileDelete(const char *pszFilename)
303{
304 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszFilename, "/\\")))
305 return VERR_FILE_NOT_FOUND;
306 RTPrintf("%s\n", __PRETTY_FUNCTION__);
307 return 0;
308}
309
310static RTFILE g_testRTFileFlushFile;
311
312extern int testRTFileFlush(RTFILE File)
313{
314 /* RTPrintf("%s: File=%p\n", __PRETTY_FUNCTION__, File); */
315 g_testRTFileFlushFile = File;
316 return VINF_SUCCESS;
317}
318
319static RTFILE g_testRTFileLockFile;
320static unsigned testRTFileLockfLock;
321static int64_t testRTFileLockOffset;
322static uint64_t testRTFileLockSize;
323
324extern int testRTFileLock(RTFILE hFile, unsigned fLock, int64_t offLock, uint64_t cbLock)
325{
326 /* RTPrintf("%s: hFile=%p, fLock=%u, offLock=%lli, cbLock=%llu\n",
327 __PRETTY_FUNCTION__, hFile, fLock, (long long) offLock,
328 LLUIFY(cbLock)); */
329 g_testRTFileLockFile = hFile;
330 testRTFileLockfLock = fLock;
331 testRTFileLockOffset = offLock;
332 testRTFileLockSize = cbLock;
333 return VINF_SUCCESS;
334}
335
336static char testRTFileOpenName[256];
337static uint64_t testRTFileOpenFlags;
338static RTFILE testRTFileOpenpFile;
339
340extern int testRTFileOpen(PRTFILE pFile, const char *pszFilename, uint64_t fOpen)
341{
342 /* RTPrintf("%s, pszFilename=%s, fOpen=0x%llx\n", __PRETTY_FUNCTION__,
343 pszFilename, LLUIFY(fOpen)); */
344 ARRAY_FROM_PATH(testRTFileOpenName, pszFilename);
345 testRTFileOpenFlags = fOpen;
346 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszFilename, "/\\")))
347 return VERR_FILE_NOT_FOUND;
348 *pFile = testRTFileOpenpFile;
349 testRTFileOpenpFile = 0;
350 return VINF_SUCCESS;
351}
352
353static RTFILE g_testRTFileQueryInfoFile;
354static RTTIMESPEC testRTFileQueryInfoATime;
355static uint32_t testRTFileQueryInfoFMode;
356
357extern int testRTFileQueryInfo(RTFILE hFile, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs)
358{
359 RT_NOREF1(enmAdditionalAttribs);
360 /* RTPrintf("%s, hFile=%p, enmAdditionalAttribs=0x%llx\n",
361 __PRETTY_FUNCTION__, hFile, LLUIFY(enmAdditionalAttribs)); */
362 g_testRTFileQueryInfoFile = hFile;
363 RT_ZERO(*pObjInfo);
364 pObjInfo->AccessTime = testRTFileQueryInfoATime;
365 RT_ZERO(testRTDirQueryInfoATime);
366 pObjInfo->Attr.fMode = testRTFileQueryInfoFMode;
367 testRTFileQueryInfoFMode = 0;
368 return VINF_SUCCESS;
369}
370
371static const char *testRTFileReadData;
372
373extern int testRTFileRead(RTFILE File, void *pvBuf, size_t cbToRead, size_t *pcbRead)
374{
375 RT_NOREF1(File);
376 /* RTPrintf("%s : File=%p, cbToRead=%llu\n", __PRETTY_FUNCTION__, File,
377 LLUIFY(cbToRead)); */
378 bufferFromPath(pvBuf, cbToRead, testRTFileReadData);
379 if (pcbRead)
380 *pcbRead = RT_MIN(cbToRead, strlen(testRTFileReadData) + 1);
381 testRTFileReadData = 0;
382 return VINF_SUCCESS;
383}
384
385extern int testRTFileSeek(RTFILE hFile, int64_t offSeek, unsigned uMethod, uint64_t *poffActual)
386{
387 RT_NOREF3(hFile, offSeek, uMethod);
388 /* RTPrintf("%s : hFile=%p, offSeek=%llu, uMethod=%u\n", __PRETTY_FUNCTION__,
389 hFile, LLUIFY(offSeek), uMethod); */
390 if (poffActual)
391 *poffActual = 0;
392 return VINF_SUCCESS;
393}
394
395static uint64_t testRTFileSetFMode;
396
397extern int testRTFileSetMode(RTFILE File, RTFMODE fMode)
398{
399 RT_NOREF1(File);
400 /* RTPrintf("%s: fMode=%llu\n", __PRETTY_FUNCTION__, LLUIFY(fMode)); */
401 testRTFileSetFMode = fMode;
402 return VINF_SUCCESS;
403}
404
405static RTFILE g_testRTFileSetSizeFile;
406static RTFOFF testRTFileSetSizeSize;
407
408extern int testRTFileSetSize(RTFILE File, uint64_t cbSize)
409{
410 /* RTPrintf("%s: File=%llu, cbSize=%llu\n", __PRETTY_FUNCTION__, LLUIFY(File),
411 LLUIFY(cbSize)); */
412 g_testRTFileSetSizeFile = File;
413 testRTFileSetSizeSize = (RTFOFF) cbSize; /* Why was this signed before? */
414 return VINF_SUCCESS;
415}
416
417static RTTIMESPEC testRTFileSetTimesATime;
418
419extern int testRTFileSetTimes(RTFILE File, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
420 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
421{
422 RT_NOREF4(File, pModificationTime, pChangeTime, pBirthTime);
423 /* RTPrintf("%s: pFile=%p, *pAccessTime=%lli, *pModificationTime=%lli, *pChangeTime=%lli, *pBirthTime=%lli\n",
424 __PRETTY_FUNCTION__,
425 pAccessTime ? (long long)RTTimeSpecGetNano(pAccessTime) : -1,
426 pModificationTime
427 ? (long long)RTTimeSpecGetNano(pModificationTime) : -1,
428 pChangeTime ? (long long)RTTimeSpecGetNano(pChangeTime) : -1,
429 pBirthTime ? (long long)RTTimeSpecGetNano(pBirthTime) : -1); */
430 if (pAccessTime)
431 testRTFileSetTimesATime = *pAccessTime;
432 else
433 RT_ZERO(testRTFileSetTimesATime);
434 return VINF_SUCCESS;
435}
436
437static RTFILE g_testRTFileUnlockFile;
438static int64_t testRTFileUnlockOffset;
439static uint64_t testRTFileUnlockSize;
440
441extern int testRTFileUnlock(RTFILE File, int64_t offLock, uint64_t cbLock)
442{
443 /* RTPrintf("%s: hFile=%p, ofLock=%lli, cbLock=%llu\n", __PRETTY_FUNCTION__,
444 File, (long long) offLock, LLUIFY(cbLock)); */
445 g_testRTFileUnlockFile = File;
446 testRTFileUnlockOffset = offLock;
447 testRTFileUnlockSize = cbLock;
448 return VINF_SUCCESS;
449}
450
451static char testRTFileWriteData[256];
452
453extern int testRTFileWrite(RTFILE File, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
454{
455 RT_NOREF2(File, cbToWrite);
456 /* RTPrintf("%s: File=%p, pvBuf=%.*s, cbToWrite=%llu\n", __PRETTY_FUNCTION__,
457 File, cbToWrite, (const char *)pvBuf, LLUIFY(cbToWrite)); */
458 ARRAY_FROM_PATH(testRTFileWriteData, (const char *)pvBuf);
459 if (pcbWritten)
460 *pcbWritten = strlen(testRTFileWriteData) + 1;
461 return VINF_SUCCESS;
462}
463
464extern int testRTFsQueryProperties(const char *pszFsPath, PRTFSPROPERTIES pProperties)
465{
466 RT_NOREF1(pszFsPath);
467 /* RTPrintf("%s, pszFsPath=%s\n", __PRETTY_FUNCTION__, pszFsPath);
468 RT_ZERO(*pProperties); */
469 pProperties->cbMaxComponent = 256;
470 pProperties->fCaseSensitive = true;
471 return VINF_SUCCESS;
472}
473
474extern int testRTFsQuerySerial(const char *pszFsPath, uint32_t *pu32Serial)
475{
476 RT_NOREF2(pszFsPath, pu32Serial);
477 RTPrintf("%s\n", __PRETTY_FUNCTION__);
478 return 0;
479}
480extern int testRTFsQuerySizes(const char *pszFsPath, PRTFOFF pcbTotal, RTFOFF *pcbFree, uint32_t *pcbBlock, uint32_t *pcbSector)
481{
482 RT_NOREF5(pszFsPath, pcbTotal, pcbFree, pcbBlock, pcbSector);
483 RTPrintf("%s\n", __PRETTY_FUNCTION__);
484 return 0;
485}
486
487extern int testRTPathQueryInfoEx(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
488{
489 RT_NOREF2(enmAdditionalAttribs, fFlags);
490 /* RTPrintf("%s: pszPath=%s, enmAdditionalAttribs=0x%x, fFlags=0x%x\n",
491 __PRETTY_FUNCTION__, pszPath, (unsigned) enmAdditionalAttribs,
492 (unsigned) fFlags); */
493 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszPath, "/\\")))
494 return VERR_FILE_NOT_FOUND;
495 RT_ZERO(*pObjInfo);
496 return VINF_SUCCESS;
497}
498
499extern int testRTSymlinkDelete(const char *pszSymlink, uint32_t fDelete)
500{
501 RT_NOREF2(pszSymlink, fDelete);
502 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszSymlink, "/\\")))
503 return VERR_FILE_NOT_FOUND;
504 RTPrintf("%s\n", __PRETTY_FUNCTION__);
505 return 0;
506}
507
508extern int testRTSymlinkRead(const char *pszSymlink, char *pszTarget, size_t cbTarget, uint32_t fRead)
509{
510 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszSymlink, "/\\")))
511 return VERR_FILE_NOT_FOUND;
512 RT_NOREF4(pszSymlink, pszTarget, cbTarget, fRead);
513 RTPrintf("%s\n", __PRETTY_FUNCTION__);
514 return 0;
515}
516
517
518/*********************************************************************************************************************************
519* Tests *
520*********************************************************************************************************************************/
521
522/* Sub-tests for testMappingsQuery(). */
523void testMappingsQuerySimple(RTTEST hTest) { RT_NOREF1(hTest); }
524void testMappingsQueryTooFewBuffers(RTTEST hTest) { RT_NOREF1(hTest); }
525void testMappingsQueryAutoMount(RTTEST hTest) { RT_NOREF1(hTest); }
526void testMappingsQueryArrayWrongSize(RTTEST hTest) { RT_NOREF1(hTest); }
527
528/* Sub-tests for testMappingsQueryName(). */
529void testMappingsQueryNameValid(RTTEST hTest) { RT_NOREF1(hTest); }
530void testMappingsQueryNameInvalid(RTTEST hTest) { RT_NOREF1(hTest); }
531void testMappingsQueryNameBadBuffer(RTTEST hTest) { RT_NOREF1(hTest); }
532
533/* Sub-tests for testMapFolder(). */
534void testMapFolderValid(RTTEST hTest) { RT_NOREF1(hTest); }
535void testMapFolderInvalid(RTTEST hTest) { RT_NOREF1(hTest); }
536void testMapFolderTwice(RTTEST hTest) { RT_NOREF1(hTest); }
537void testMapFolderDelimiter(RTTEST hTest) { RT_NOREF1(hTest); }
538void testMapFolderCaseSensitive(RTTEST hTest) { RT_NOREF1(hTest); }
539void testMapFolderCaseInsensitive(RTTEST hTest) { RT_NOREF1(hTest); }
540void testMapFolderBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
541
542/* Sub-tests for testUnmapFolder(). */
543void testUnmapFolderValid(RTTEST hTest) { RT_NOREF1(hTest); }
544void testUnmapFolderInvalid(RTTEST hTest) { RT_NOREF1(hTest); }
545void testUnmapFolderBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
546
547/* Sub-tests for testCreate(). */
548void testCreateBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
549
550/* Sub-tests for testClose(). */
551void testCloseBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
552
553/* Sub-tests for testRead(). */
554void testReadBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
555
556/* Sub-tests for testWrite(). */
557void testWriteBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
558
559/* Sub-tests for testLock(). */
560void testLockBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
561
562/* Sub-tests for testFlush(). */
563void testFlushBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
564
565/* Sub-tests for testDirList(). */
566void testDirListBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
567
568/* Sub-tests for testReadLink(). */
569void testReadLinkBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
570
571/* Sub-tests for testFSInfo(). */
572void testFSInfoBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
573
574/* Sub-tests for testRemove(). */
575void testRemoveBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
576
577/* Sub-tests for testRename(). */
578void testRenameBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
579
580/* Sub-tests for testSymlink(). */
581void testSymlinkBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
582
583/* Sub-tests for testMappingsAdd(). */
584void testMappingsAddBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
585
586/* Sub-tests for testMappingsRemove(). */
587void testMappingsRemoveBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
588
589union TESTSHFLSTRING
590{
591 SHFLSTRING string;
592 char acData[256];
593};
594
595static void fillTestShflString(union TESTSHFLSTRING *pDest,
596 const char *pcszSource)
597{
598 const size_t cchSource = strlen(pcszSource);
599 AssertRelease( cchSource * 2 + 2
600 < sizeof(*pDest) - RT_UOFFSETOF(SHFLSTRING, String));
601 pDest->string.u16Length = (uint16_t)(cchSource * sizeof(RTUTF16));
602 pDest->string.u16Size = pDest->string.u16Length + sizeof(RTUTF16);
603 /* Copy pcszSource ASCIIZ, including the trailing 0, to the UTF16 pDest->string.String.ucs2. */
604 for (unsigned i = 0; i <= cchSource; ++i)
605 pDest->string.String.ucs2[i] = (uint16_t)pcszSource[i];
606}
607
608static SHFLROOT initWithWritableMapping(RTTEST hTest,
609 VBOXHGCMSVCFNTABLE *psvcTable,
610 VBOXHGCMSVCHELPERS *psvcHelpers,
611 const char *pcszFolderName,
612 const char *pcszMapping,
613 bool fCaseSensitive = true)
614{
615 VBOXHGCMSVCPARM aParms[RT_MAX(SHFL_CPARMS_ADD_MAPPING,
616 SHFL_CPARMS_MAP_FOLDER)];
617 union TESTSHFLSTRING FolderName;
618 union TESTSHFLSTRING Mapping;
619 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
620 int rc;
621
622 initTable(psvcTable, psvcHelpers);
623 AssertReleaseRC(VBoxHGCMSvcLoad(psvcTable));
624 AssertRelease( psvcTable->pvService
625 = RTTestGuardedAllocTail(hTest, psvcTable->cbClient));
626 RT_BZERO(psvcTable->pvService, psvcTable->cbClient);
627 fillTestShflString(&FolderName, pcszFolderName);
628 fillTestShflString(&Mapping, pcszMapping);
629 aParms[0].setPointer(&FolderName, RT_UOFFSETOF(SHFLSTRING, String)
630 + FolderName.string.u16Size);
631 aParms[1].setPointer(&Mapping, RT_UOFFSETOF(SHFLSTRING, String)
632 + Mapping.string.u16Size);
633 aParms[2].setUInt32(1);
634 rc = psvcTable->pfnHostCall(psvcTable->pvService, SHFL_FN_ADD_MAPPING,
635 SHFL_CPARMS_ADD_MAPPING, aParms);
636 AssertReleaseRC(rc);
637 aParms[0].setPointer(&Mapping, RT_UOFFSETOF(SHFLSTRING, String)
638 + Mapping.string.u16Size);
639 aParms[1].setUInt32(0); /* root */
640 aParms[2].setUInt32('/'); /* delimiter */
641 aParms[3].setUInt32(fCaseSensitive);
642 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
643 psvcTable->pvService, SHFL_FN_MAP_FOLDER,
644 SHFL_CPARMS_MAP_FOLDER, aParms);
645 AssertReleaseRC(callHandle.rc);
646 return aParms[1].u.uint32;
647}
648
649/** @todo Mappings should be automatically removed by unloading the service,
650 * but unloading is currently a no-op! */
651static void unmapAndRemoveMapping(RTTEST hTest, VBOXHGCMSVCFNTABLE *psvcTable,
652 SHFLROOT root, const char *pcszFolderName)
653{
654 RT_NOREF1(hTest);
655 VBOXHGCMSVCPARM aParms[RT_MAX(SHFL_CPARMS_UNMAP_FOLDER,
656 SHFL_CPARMS_REMOVE_MAPPING)];
657 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
658 union TESTSHFLSTRING FolderName;
659 int rc;
660
661 aParms[0].setUInt32(root);
662 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
663 psvcTable->pvService, SHFL_FN_UNMAP_FOLDER,
664 SHFL_CPARMS_UNMAP_FOLDER, aParms);
665 AssertReleaseRC(callHandle.rc);
666 fillTestShflString(&FolderName, pcszFolderName);
667 aParms[0].setPointer(&FolderName, RT_UOFFSETOF(SHFLSTRING, String)
668 + FolderName.string.u16Size);
669 rc = psvcTable->pfnHostCall(psvcTable->pvService, SHFL_FN_REMOVE_MAPPING,
670 SHFL_CPARMS_REMOVE_MAPPING, aParms);
671 AssertReleaseRC(rc);
672}
673
674static int createFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT Root,
675 const char *pcszFilename, uint32_t fCreateFlags,
676 SHFLHANDLE *pHandle, SHFLCREATERESULT *pResult)
677{
678 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_CREATE];
679 union TESTSHFLSTRING Path;
680 SHFLCREATEPARMS CreateParms;
681 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
682
683 fillTestShflString(&Path, pcszFilename);
684 RT_ZERO(CreateParms);
685 CreateParms.CreateFlags = fCreateFlags;
686 aParms[0].setUInt32(Root);
687 aParms[1].setPointer(&Path, RT_UOFFSETOF(SHFLSTRING, String)
688 + Path.string.u16Size);
689 aParms[2].setPointer(&CreateParms, sizeof(CreateParms));
690 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
691 psvcTable->pvService, SHFL_FN_CREATE,
692 RT_ELEMENTS(aParms), aParms);
693 if (RT_FAILURE(callHandle.rc))
694 return callHandle.rc;
695 if (pHandle)
696 *pHandle = CreateParms.Handle;
697 if (pResult)
698 *pResult = CreateParms.Result;
699 return VINF_SUCCESS;
700}
701
702static int readFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT Root,
703 SHFLHANDLE hFile, uint64_t offSeek, uint32_t cbRead,
704 uint32_t *pcbRead, void *pvBuf, uint32_t cbBuf)
705{
706 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_READ];
707 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
708
709 aParms[0].setUInt32(Root);
710 aParms[1].setUInt64((uint64_t) hFile);
711 aParms[2].setUInt64(offSeek);
712 aParms[3].setUInt32(cbRead);
713 aParms[4].setPointer(pvBuf, cbBuf);
714 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
715 psvcTable->pvService, SHFL_FN_READ,
716 RT_ELEMENTS(aParms), aParms);
717 if (pcbRead)
718 *pcbRead = aParms[3].u.uint32;
719 return callHandle.rc;
720}
721
722static int writeFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT Root,
723 SHFLHANDLE hFile, uint64_t offSeek, uint32_t cbWrite,
724 uint32_t *pcbWritten, const void *pvBuf, uint32_t cbBuf)
725{
726 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_WRITE];
727 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
728
729 aParms[0].setUInt32(Root);
730 aParms[1].setUInt64((uint64_t) hFile);
731 aParms[2].setUInt64(offSeek);
732 aParms[3].setUInt32(cbWrite);
733 aParms[4].setPointer((void *)pvBuf, cbBuf);
734 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
735 psvcTable->pvService, SHFL_FN_WRITE,
736 RT_ELEMENTS(aParms), aParms);
737 if (pcbWritten)
738 *pcbWritten = aParms[3].u.uint32;
739 return callHandle.rc;
740}
741
742static int flushFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT root,
743 SHFLHANDLE handle)
744{
745 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_FLUSH];
746 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
747
748 aParms[0].setUInt32(root);
749 aParms[1].setUInt64(handle);
750 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
751 psvcTable->pvService, SHFL_FN_FLUSH,
752 SHFL_CPARMS_FLUSH, aParms);
753 return callHandle.rc;
754}
755
756static int listDir(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT root,
757 SHFLHANDLE handle, uint32_t fFlags,
758 const char *pcszPath, void *pvBuf, uint32_t cbBuf,
759 uint32_t resumePoint, uint32_t *pcFiles)
760{
761 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_LIST];
762 union TESTSHFLSTRING Path;
763 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
764
765 aParms[0].setUInt32(root);
766 aParms[1].setUInt64(handle);
767 aParms[2].setUInt32(fFlags);
768 aParms[3].setUInt32(cbBuf);
769 if (pcszPath)
770 {
771 fillTestShflString(&Path, pcszPath);
772 aParms[4].setPointer(&Path, RT_UOFFSETOF(SHFLSTRING, String)
773 + Path.string.u16Size);
774 }
775 else
776 aParms[4].setPointer(NULL, 0);
777 aParms[5].setPointer(pvBuf, cbBuf);
778 aParms[6].setUInt32(resumePoint);
779 aParms[7].setUInt32(0);
780 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
781 psvcTable->pvService, SHFL_FN_LIST,
782 RT_ELEMENTS(aParms), aParms);
783 if (pcFiles)
784 *pcFiles = aParms[7].u.uint32;
785 return callHandle.rc;
786}
787
788static int sfInformation(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT root,
789 SHFLHANDLE handle, uint32_t fFlags, uint32_t cb,
790 SHFLFSOBJINFO *pInfo)
791{
792 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_INFORMATION];
793 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
794
795 aParms[0].setUInt32(root);
796 aParms[1].setUInt64(handle);
797 aParms[2].setUInt32(fFlags);
798 aParms[3].setUInt32(cb);
799 aParms[4].setPointer(pInfo, cb);
800 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
801 psvcTable->pvService, SHFL_FN_INFORMATION,
802 RT_ELEMENTS(aParms), aParms);
803 return callHandle.rc;
804}
805
806static int lockFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT root,
807 SHFLHANDLE handle, int64_t offLock, uint64_t cbLock,
808 uint32_t fFlags)
809{
810 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_LOCK];
811 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
812
813 aParms[0].setUInt32(root);
814 aParms[1].setUInt64(handle);
815 aParms[2].setUInt64(offLock);
816 aParms[3].setUInt64(cbLock);
817 aParms[4].setUInt32(fFlags);
818 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
819 psvcTable->pvService, SHFL_FN_LOCK,
820 RT_ELEMENTS(aParms), aParms);
821 return callHandle.rc;
822}
823
824void testCreateFileSimple(RTTEST hTest)
825{
826 VBOXHGCMSVCFNTABLE svcTable;
827 VBOXHGCMSVCHELPERS svcHelpers;
828 SHFLROOT Root;
829 const RTFILE hcFile = (RTFILE) 0x10000;
830 SHFLCREATERESULT Result;
831 int rc;
832
833 RTTestSub(hTest, "Create file simple");
834 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
835 "/test/mapping", "testname");
836 testRTFileOpenpFile = hcFile;
837 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ, NULL,
838 &Result);
839 RTTEST_CHECK_RC_OK(hTest, rc);
840 RTTEST_CHECK_MSG(hTest,
841 !strcmp(&testRTFileOpenName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0],
842 "/test/mapping/test/file"),
843 (hTest, "pszFilename=%s\n", &testRTFileOpenName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0]));
844 RTTEST_CHECK_MSG(hTest, testRTFileOpenFlags == 0x181,
845 (hTest, "fOpen=%llu\n", LLUIFY(testRTFileOpenFlags)));
846 RTTEST_CHECK_MSG(hTest, Result == SHFL_FILE_CREATED,
847 (hTest, "Result=%d\n", (int) Result));
848 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
849 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
850 RTTestGuardedFree(hTest, svcTable.pvService);
851 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hcFile,
852 (hTest, "File=%u\n", (uintptr_t)g_testRTFileCloseFile));
853}
854
855void testCreateFileSimpleCaseInsensitive(RTTEST hTest)
856{
857 VBOXHGCMSVCFNTABLE svcTable;
858 VBOXHGCMSVCHELPERS svcHelpers;
859 SHFLROOT Root;
860 const RTFILE hcFile = (RTFILE) 0x10000;
861 SHFLCREATERESULT Result;
862 int rc;
863
864 g_fFailIfNotLowercase = true;
865
866 RTTestSub(hTest, "Create file case insensitive");
867 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
868 "/test/mapping", "testname", false /*fCaseSensitive*/);
869 testRTFileOpenpFile = hcFile;
870 rc = createFile(&svcTable, Root, "/TesT/FilE", SHFL_CF_ACCESS_READ, NULL,
871 &Result);
872 RTTEST_CHECK_RC_OK(hTest, rc);
873
874 RTTEST_CHECK_MSG(hTest,
875 !strcmp(&testRTFileOpenName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0],
876 "/test/mapping/test/file"),
877 (hTest, "pszFilename=%s\n", &testRTFileOpenName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0]));
878 RTTEST_CHECK_MSG(hTest, testRTFileOpenFlags == 0x181,
879 (hTest, "fOpen=%llu\n", LLUIFY(testRTFileOpenFlags)));
880 RTTEST_CHECK_MSG(hTest, Result == SHFL_FILE_CREATED,
881 (hTest, "Result=%d\n", (int) Result));
882 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
883 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
884 RTTestGuardedFree(hTest, svcTable.pvService);
885 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hcFile,
886 (hTest, "File=%u\n", (uintptr_t)g_testRTFileCloseFile));
887
888 g_fFailIfNotLowercase = false;
889}
890
891void testCreateDirSimple(RTTEST hTest)
892{
893 VBOXHGCMSVCFNTABLE svcTable;
894 VBOXHGCMSVCHELPERS svcHelpers;
895 SHFLROOT Root;
896 PRTDIR pDir = (PRTDIR)&g_aTestDirHandles[g_iNextDirHandle++ % RT_ELEMENTS(g_aTestDirHandles)];
897 SHFLCREATERESULT Result;
898 int rc;
899
900 RTTestSub(hTest, "Create directory simple");
901 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
902 "/test/mapping", "testname");
903 testRTDirOpenpDir = pDir;
904 rc = createFile(&svcTable, Root, "test/dir",
905 SHFL_CF_DIRECTORY | SHFL_CF_ACCESS_READ, NULL, &Result);
906 RTTEST_CHECK_RC_OK(hTest, rc);
907 RTTEST_CHECK_MSG(hTest,
908 !strcmp(&testRTDirCreatePath[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0],
909 "/test/mapping/test/dir"),
910 (hTest, "pszPath=%s\n", &testRTDirCreatePath[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0]));
911 RTTEST_CHECK_MSG(hTest,
912 !strcmp(&testRTDirOpenName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0],
913 "/test/mapping/test/dir"),
914 (hTest, "pszFilename=%s\n", &testRTDirOpenName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0]));
915 RTTEST_CHECK_MSG(hTest, Result == SHFL_FILE_CREATED,
916 (hTest, "Result=%d\n", (int) Result));
917 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
918 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
919 RTTestGuardedFree(hTest, svcTable.pvService);
920 RTTEST_CHECK_MSG(hTest, g_testRTDirClosepDir == pDir, (hTest, "pDir=%p\n", g_testRTDirClosepDir));
921}
922
923void testReadFileSimple(RTTEST hTest)
924{
925 VBOXHGCMSVCFNTABLE svcTable;
926 VBOXHGCMSVCHELPERS svcHelpers;
927 SHFLROOT Root;
928 const RTFILE hcFile = (RTFILE) 0x10000;
929 SHFLHANDLE Handle;
930 const char *pcszReadData = "Data to read";
931 char acBuf[sizeof(pcszReadData) + 10];
932 uint32_t cbRead;
933 int rc;
934
935 RTTestSub(hTest, "Read file simple");
936 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
937 "/test/mapping", "testname");
938 testRTFileOpenpFile = hcFile;
939 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
940 &Handle, NULL);
941 RTTEST_CHECK_RC_OK(hTest, rc);
942 testRTFileReadData = pcszReadData;
943 rc = readFile(&svcTable, Root, Handle, 0, (uint32_t)strlen(pcszReadData) + 1,
944 &cbRead, acBuf, (uint32_t)sizeof(acBuf));
945 RTTEST_CHECK_RC_OK(hTest, rc);
946 RTTEST_CHECK_MSG(hTest,
947 !strncmp(acBuf, pcszReadData, sizeof(acBuf)),
948 (hTest, "pvBuf=%.*s\n", sizeof(acBuf), acBuf));
949 RTTEST_CHECK_MSG(hTest, cbRead == strlen(pcszReadData) + 1,
950 (hTest, "cbRead=%llu\n", LLUIFY(cbRead)));
951 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
952 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hcFile, (hTest, "File=%u\n", g_testRTFileCloseFile));
953 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
954 RTTestGuardedFree(hTest, svcTable.pvService);
955}
956
957void testWriteFileSimple(RTTEST hTest)
958{
959 VBOXHGCMSVCFNTABLE svcTable;
960 VBOXHGCMSVCHELPERS svcHelpers;
961 SHFLROOT Root;
962 const RTFILE hcFile = (RTFILE) 0x10000;
963 SHFLHANDLE Handle;
964 const char *pcszWrittenData = "Data to write";
965 uint32_t cbToWrite = (uint32_t)strlen(pcszWrittenData) + 1;
966 uint32_t cbWritten;
967 int rc;
968
969 RTTestSub(hTest, "Write file simple");
970 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
971 "/test/mapping", "testname");
972 testRTFileOpenpFile = hcFile;
973 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
974 &Handle, NULL);
975 RTTEST_CHECK_RC_OK(hTest, rc);
976 rc = writeFile(&svcTable, Root, Handle, 0, cbToWrite, &cbWritten,
977 pcszWrittenData, cbToWrite);
978 RTTEST_CHECK_RC_OK(hTest, rc);
979 RTTEST_CHECK_MSG(hTest,
980 !strcmp(testRTFileWriteData, pcszWrittenData),
981 (hTest, "pvBuf=%s\n", testRTFileWriteData));
982 RTTEST_CHECK_MSG(hTest, cbWritten == cbToWrite,
983 (hTest, "cbWritten=%llu\n", LLUIFY(cbWritten)));
984 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
985 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hcFile, (hTest, "File=%u\n", g_testRTFileCloseFile));
986 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
987 RTTestGuardedFree(hTest, svcTable.pvService);
988}
989
990void testFlushFileSimple(RTTEST hTest)
991{
992 VBOXHGCMSVCFNTABLE svcTable;
993 VBOXHGCMSVCHELPERS svcHelpers;
994 SHFLROOT Root;
995 const RTFILE hcFile = (RTFILE) 0x10000;
996 SHFLHANDLE Handle;
997 int rc;
998
999 RTTestSub(hTest, "Flush file simple");
1000 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1001 "/test/mapping", "testname");
1002 testRTFileOpenpFile = hcFile;
1003 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1004 &Handle, NULL);
1005 RTTEST_CHECK_RC_OK(hTest, rc);
1006 rc = flushFile(&svcTable, Root, Handle);
1007 RTTEST_CHECK_RC_OK(hTest, rc);
1008 RTTEST_CHECK_MSG(hTest, g_testRTFileFlushFile == hcFile, (hTest, "File=%u\n", g_testRTFileFlushFile));
1009 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1010 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1011 RTTestGuardedFree(hTest, svcTable.pvService);
1012 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hcFile, (hTest, "File=%u\n", g_testRTFileCloseFile));
1013}
1014
1015void testDirListEmpty(RTTEST hTest)
1016{
1017 VBOXHGCMSVCFNTABLE svcTable;
1018 VBOXHGCMSVCHELPERS svcHelpers;
1019 SHFLROOT Root;
1020 PRTDIR pDir = (PRTDIR)&g_aTestDirHandles[g_iNextDirHandle++ % RT_ELEMENTS(g_aTestDirHandles)];
1021 SHFLHANDLE Handle;
1022 union
1023 {
1024 SHFLDIRINFO DirInfo;
1025 uint8_t abBuffer[sizeof(SHFLDIRINFO) + 2 * sizeof(RTUTF16)];
1026 } Buf;
1027 uint32_t cFiles;
1028 int rc;
1029
1030 RTTestSub(hTest, "List empty directory");
1031 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1032 "/test/mapping", "testname");
1033 testRTDirOpenpDir = pDir;
1034 rc = createFile(&svcTable, Root, "test/dir",
1035 SHFL_CF_DIRECTORY | SHFL_CF_ACCESS_READ, &Handle, NULL);
1036 RTTEST_CHECK_RC_OK(hTest, rc);
1037 rc = listDir(&svcTable, Root, Handle, 0, NULL, &Buf.DirInfo, sizeof(Buf), 0, &cFiles);
1038 RTTEST_CHECK_RC(hTest, rc, VERR_NO_MORE_FILES);
1039 RTTEST_CHECK_MSG(hTest, g_testRTDirReadExDir == pDir, (hTest, "Dir=%p\n", g_testRTDirReadExDir));
1040 RTTEST_CHECK_MSG(hTest, cFiles == 0,
1041 (hTest, "cFiles=%llu\n", LLUIFY(cFiles)));
1042 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1043 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1044 RTTestGuardedFree(hTest, svcTable.pvService);
1045 RTTEST_CHECK_MSG(hTest, g_testRTDirClosepDir == pDir, (hTest, "pDir=%p\n", g_testRTDirClosepDir));
1046}
1047
1048void testFSInfoQuerySetFMode(RTTEST hTest)
1049{
1050 VBOXHGCMSVCFNTABLE svcTable;
1051 VBOXHGCMSVCHELPERS svcHelpers;
1052 SHFLROOT Root;
1053 const RTFILE hcFile = (RTFILE) 0x10000;
1054 const uint32_t fMode = 0660;
1055 SHFLFSOBJINFO Info;
1056 int rc;
1057
1058 RTTestSub(hTest, "Query and set file size");
1059 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1060 "/test/mapping", "testname");
1061 SHFLHANDLE Handle = SHFL_HANDLE_NIL;
1062 testRTFileOpenpFile = hcFile;
1063 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1064 &Handle, NULL);
1065 RTTEST_CHECK_RC_OK_RETV(hTest, rc);
1066
1067 RT_ZERO(Info);
1068 testRTFileQueryInfoFMode = fMode;
1069 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_FILE, sizeof(Info),
1070 &Info);
1071 RTTEST_CHECK_RC_OK(hTest, rc);
1072 RTTEST_CHECK_MSG(hTest, g_testRTFileQueryInfoFile == hcFile, (hTest, "File=%u\n", g_testRTFileQueryInfoFile));
1073 RTTEST_CHECK_MSG(hTest, Info.Attr.fMode == fMode,
1074 (hTest, "cbObject=%llu\n", LLUIFY(Info.cbObject)));
1075 RT_ZERO(Info);
1076 Info.Attr.fMode = fMode;
1077 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_SET | SHFL_INFO_FILE,
1078 sizeof(Info), &Info);
1079 RTTEST_CHECK_RC_OK(hTest, rc);
1080 RTTEST_CHECK_MSG(hTest, testRTFileSetFMode == fMode,
1081 (hTest, "Size=%llu\n", LLUIFY(testRTFileSetFMode)));
1082 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1083 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1084 RTTestGuardedFree(hTest, svcTable.pvService);
1085 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hcFile, (hTest, "File=%u\n", g_testRTFileCloseFile));
1086}
1087
1088void testFSInfoQuerySetDirATime(RTTEST hTest)
1089{
1090 VBOXHGCMSVCFNTABLE svcTable;
1091 VBOXHGCMSVCHELPERS svcHelpers;
1092 SHFLROOT Root;
1093 const PRTDIR pDir = (PRTDIR)&g_aTestDirHandles[g_iNextDirHandle++ % RT_ELEMENTS(g_aTestDirHandles)];
1094 const int64_t ccAtimeNano = 100000;
1095 SHFLFSOBJINFO Info;
1096 SHFLHANDLE Handle;
1097 int rc;
1098
1099 RTTestSub(hTest, "Query and set directory atime");
1100 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1101 "/test/mapping", "testname");
1102 testRTDirOpenpDir = pDir;
1103 rc = createFile(&svcTable, Root, "test/dir",
1104 SHFL_CF_DIRECTORY | SHFL_CF_ACCESS_READ, &Handle, NULL);
1105 RTTEST_CHECK_RC_OK(hTest, rc);
1106 RT_ZERO(Info);
1107 RTTimeSpecSetNano(&testRTDirQueryInfoATime, ccAtimeNano);
1108 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_FILE, sizeof(Info),
1109 &Info);
1110 RTTEST_CHECK_RC_OK(hTest, rc);
1111 RTTEST_CHECK_MSG(hTest, g_testRTDirQueryInfoDir == pDir, (hTest, "Dir=%p\n", g_testRTDirQueryInfoDir));
1112 RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&Info.AccessTime) == ccAtimeNano,
1113 (hTest, "ATime=%llu\n",
1114 LLUIFY(RTTimeSpecGetNano(&Info.AccessTime))));
1115 RT_ZERO(Info);
1116 RTTimeSpecSetNano(&Info.AccessTime, ccAtimeNano);
1117 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_SET | SHFL_INFO_FILE,
1118 sizeof(Info), &Info);
1119 RTTEST_CHECK_RC_OK(hTest, rc);
1120 RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&testRTDirSetTimesATime)
1121 == ccAtimeNano,
1122 (hTest, "ATime=%llu\n",
1123 LLUIFY(RTTimeSpecGetNano(&testRTDirSetTimesATime))));
1124 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1125 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1126 RTTestGuardedFree(hTest, svcTable.pvService);
1127 RTTEST_CHECK_MSG(hTest, g_testRTDirClosepDir == pDir, (hTest, "pDir=%p\n", g_testRTDirClosepDir));
1128}
1129
1130void testFSInfoQuerySetFileATime(RTTEST hTest)
1131{
1132 VBOXHGCMSVCFNTABLE svcTable;
1133 VBOXHGCMSVCHELPERS svcHelpers;
1134 SHFLROOT Root;
1135 const RTFILE hcFile = (RTFILE) 0x10000;
1136 const int64_t ccAtimeNano = 100000;
1137 SHFLFSOBJINFO Info;
1138 SHFLHANDLE Handle;
1139 int rc;
1140
1141 RTTestSub(hTest, "Query and set file atime");
1142 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1143 "/test/mapping", "testname");
1144 testRTFileOpenpFile = hcFile;
1145 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1146 &Handle, NULL);
1147 RTTEST_CHECK_RC_OK(hTest, rc);
1148 RT_ZERO(Info);
1149 RTTimeSpecSetNano(&testRTFileQueryInfoATime, ccAtimeNano);
1150 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_FILE, sizeof(Info),
1151 &Info);
1152 RTTEST_CHECK_RC_OK(hTest, rc);
1153 RTTEST_CHECK_MSG(hTest, g_testRTFileQueryInfoFile == hcFile, (hTest, "File=%u\n", g_testRTFileQueryInfoFile));
1154 RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&Info.AccessTime) == ccAtimeNano,
1155 (hTest, "ATime=%llu\n",
1156 LLUIFY(RTTimeSpecGetNano(&Info.AccessTime))));
1157 RT_ZERO(Info);
1158 RTTimeSpecSetNano(&Info.AccessTime, ccAtimeNano);
1159 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_SET | SHFL_INFO_FILE,
1160 sizeof(Info), &Info);
1161 RTTEST_CHECK_RC_OK(hTest, rc);
1162 RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&testRTFileSetTimesATime)
1163 == ccAtimeNano,
1164 (hTest, "ATime=%llu\n",
1165 LLUIFY(RTTimeSpecGetNano(&testRTFileSetTimesATime))));
1166 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1167 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1168 RTTestGuardedFree(hTest, svcTable.pvService);
1169 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hcFile, (hTest, "File=%u\n", g_testRTFileCloseFile));
1170}
1171
1172void testFSInfoQuerySetEndOfFile(RTTEST hTest)
1173{
1174 VBOXHGCMSVCFNTABLE svcTable;
1175 VBOXHGCMSVCHELPERS svcHelpers;
1176 SHFLROOT Root;
1177 const RTFILE hcFile = (RTFILE) 0x10000;
1178 const RTFOFF cbNew = 50000;
1179 SHFLFSOBJINFO Info;
1180 SHFLHANDLE Handle;
1181 int rc;
1182
1183 RTTestSub(hTest, "Set end of file position");
1184 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1185 "/test/mapping", "testname");
1186 testRTFileOpenpFile = hcFile;
1187 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1188 &Handle, NULL);
1189 RTTEST_CHECK_RC_OK(hTest, rc);
1190 RT_ZERO(Info);
1191 Info.cbObject = cbNew;
1192 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_SET | SHFL_INFO_SIZE,
1193 sizeof(Info), &Info);
1194 RTTEST_CHECK_RC_OK(hTest, rc);
1195 RTTEST_CHECK_MSG(hTest, g_testRTFileSetSizeFile == hcFile, (hTest, "File=%u\n", g_testRTFileSetSizeFile));
1196 RTTEST_CHECK_MSG(hTest, testRTFileSetSizeSize == cbNew,
1197 (hTest, "Size=%llu\n", LLUIFY(testRTFileSetSizeSize)));
1198 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1199 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1200 RTTestGuardedFree(hTest, svcTable.pvService);
1201 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hcFile, (hTest, "File=%u\n", g_testRTFileCloseFile));
1202}
1203
1204void testLockFileSimple(RTTEST hTest)
1205{
1206 VBOXHGCMSVCFNTABLE svcTable;
1207 VBOXHGCMSVCHELPERS svcHelpers;
1208 SHFLROOT Root;
1209 const RTFILE hcFile = (RTFILE) 0x10000;
1210 const int64_t offLock = 50000;
1211 const uint64_t cbLock = 4000;
1212 SHFLHANDLE Handle;
1213 int rc;
1214
1215 RTTestSub(hTest, "Simple file lock and unlock");
1216 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1217 "/test/mapping", "testname");
1218 testRTFileOpenpFile = hcFile;
1219 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1220 &Handle, NULL);
1221 RTTEST_CHECK_RC_OK(hTest, rc);
1222 rc = lockFile(&svcTable, Root, Handle, offLock, cbLock, SHFL_LOCK_SHARED);
1223 RTTEST_CHECK_RC_OK(hTest, rc);
1224#ifdef RT_OS_WINDOWS /* Locking is a no-op elsewhere. */
1225 RTTEST_CHECK_MSG(hTest, g_testRTFileLockFile == hcFile, (hTest, "File=%u\n", g_testRTFileLockFile));
1226 RTTEST_CHECK_MSG(hTest, testRTFileLockfLock == 0,
1227 (hTest, "fLock=%u\n", testRTFileLockfLock));
1228 RTTEST_CHECK_MSG(hTest, testRTFileLockOffset == offLock,
1229 (hTest, "Offs=%llu\n", (long long) testRTFileLockOffset));
1230 RTTEST_CHECK_MSG(hTest, testRTFileLockSize == cbLock,
1231 (hTest, "Size=%llu\n", LLUIFY(testRTFileLockSize)));
1232#endif
1233 rc = lockFile(&svcTable, Root, Handle, offLock, cbLock, SHFL_LOCK_CANCEL);
1234 RTTEST_CHECK_RC_OK(hTest, rc);
1235#ifdef RT_OS_WINDOWS
1236 RTTEST_CHECK_MSG(hTest, g_testRTFileUnlockFile == hcFile, (hTest, "File=%u\n", g_testRTFileUnlockFile));
1237 RTTEST_CHECK_MSG(hTest, testRTFileUnlockOffset == offLock,
1238 (hTest, "Offs=%llu\n",
1239 (long long) testRTFileUnlockOffset));
1240 RTTEST_CHECK_MSG(hTest, testRTFileUnlockSize == cbLock,
1241 (hTest, "Size=%llu\n", LLUIFY(testRTFileUnlockSize)));
1242#endif
1243 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1244 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1245 RTTestGuardedFree(hTest, svcTable.pvService);
1246 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hcFile, (hTest, "File=%u\n", g_testRTFileCloseFile));
1247}
1248
1249
1250/*********************************************************************************************************************************
1251* Main code *
1252*********************************************************************************************************************************/
1253
1254static void testAPI(RTTEST hTest)
1255{
1256 testMappingsQuery(hTest);
1257 testMappingsQueryName(hTest);
1258 testMapFolder(hTest);
1259 testUnmapFolder(hTest);
1260 testCreate(hTest);
1261 testClose(hTest);
1262 testRead(hTest);
1263 testWrite(hTest);
1264 testLock(hTest);
1265 testFlush(hTest);
1266 testDirList(hTest);
1267 testReadLink(hTest);
1268 testFSInfo(hTest);
1269 testRemove(hTest);
1270 testRename(hTest);
1271 testSymlink(hTest);
1272 testMappingsAdd(hTest);
1273 testMappingsRemove(hTest);
1274 /* testSetStatusLed(hTest); */
1275}
1276
1277int main(int argc, char **argv)
1278{
1279 RT_NOREF1(argc);
1280 RTEXITCODE rcExit = RTTestInitAndCreate(RTPathFilename(argv[0]), &g_hTest);
1281 if (rcExit != RTEXITCODE_SUCCESS)
1282 return rcExit;
1283 RTTestBanner(g_hTest);
1284 testAPI(g_hTest);
1285 return RTTestSummaryAndDestroy(g_hTest);
1286}
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