VirtualBox

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

Last change on this file since 76794 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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