VirtualBox

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

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

HGCM: Replace C++-style inline members on VBOXHGCMSVCPARM with simple functions.
bugref:9172: Shared folder performance tuning
Changes in bugref:9172 caused a build regression on Ubuntu 18.10 due to the
use of RT_ZERO on a structure containing an embedded VBOXHGCMSVCPARM, as
VBOXHGCMSVCPARM had member functions and was therefore not a simple plain-
old-data structure. Rather than just doing the sensible thing and zeroing
it in a different way, I converted the inline member getters and setters to
standard inline C functions, including fixing callers. Actually I had planned
this for some time, as the member function use seemed a bit gratuitous in
hindsight.

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