VirtualBox

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

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

tstSharedFolderService.cpp: Need to catch RTFileWriteAt and RTFileReadAt too now. bugref:9172

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 54.2 KB
Line 
1/* $Id: tstSharedFolderService.cpp 77276 2019-02-12 13:44:35Z 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 testRTFileReadAt(RTFILE hFile, uint64_t offFile, void *pvBuf, size_t cbToRead, size_t *pcbRead)
417{
418 RT_NOREF1(hFile);
419 RT_NOREF(offFile);
420 /* RTPrintf("%s : File=%p, cbToRead=%llu\n", __PRETTY_FUNCTION__, File,
421 LLUIFY(cbToRead)); */
422 bufferFromPath(pvBuf, cbToRead, testRTFileReadData);
423 if (pcbRead)
424 *pcbRead = RT_MIN(cbToRead, strlen(testRTFileReadData) + 1);
425 testRTFileReadData = 0;
426 return VINF_SUCCESS;
427}
428
429extern int testRTFileSeek(RTFILE hFile, int64_t offSeek, unsigned uMethod, uint64_t *poffActual)
430{
431 RT_NOREF3(hFile, offSeek, uMethod);
432 /* RTPrintf("%s : hFile=%p, offSeek=%llu, uMethod=%u\n", __PRETTY_FUNCTION__,
433 hFile, LLUIFY(offSeek), uMethod); */
434 if (poffActual)
435 *poffActual = 0;
436 return VINF_SUCCESS;
437}
438
439static uint64_t testRTFileSetFMode;
440
441extern int testRTFileSetMode(RTFILE File, RTFMODE fMode)
442{
443 RT_NOREF1(File);
444 /* RTPrintf("%s: fMode=%llu\n", __PRETTY_FUNCTION__, LLUIFY(fMode)); */
445 testRTFileSetFMode = fMode;
446 return VINF_SUCCESS;
447}
448
449static RTFILE g_testRTFileSetSizeFile;
450static RTFOFF testRTFileSetSizeSize;
451
452extern int testRTFileSetSize(RTFILE File, uint64_t cbSize)
453{
454 /* RTPrintf("%s: File=%llu, cbSize=%llu\n", __PRETTY_FUNCTION__, LLUIFY(File),
455 LLUIFY(cbSize)); */
456 g_testRTFileSetSizeFile = File;
457 testRTFileSetSizeSize = (RTFOFF) cbSize; /* Why was this signed before? */
458 return VINF_SUCCESS;
459}
460
461static RTTIMESPEC testRTFileSetTimesATime;
462
463extern int testRTFileSetTimes(RTFILE File, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
464 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
465{
466 RT_NOREF4(File, pModificationTime, pChangeTime, pBirthTime);
467 /* RTPrintf("%s: pFile=%p, *pAccessTime=%lli, *pModificationTime=%lli, *pChangeTime=%lli, *pBirthTime=%lli\n",
468 __PRETTY_FUNCTION__,
469 pAccessTime ? (long long)RTTimeSpecGetNano(pAccessTime) : -1,
470 pModificationTime
471 ? (long long)RTTimeSpecGetNano(pModificationTime) : -1,
472 pChangeTime ? (long long)RTTimeSpecGetNano(pChangeTime) : -1,
473 pBirthTime ? (long long)RTTimeSpecGetNano(pBirthTime) : -1); */
474 if (pAccessTime)
475 testRTFileSetTimesATime = *pAccessTime;
476 else
477 RT_ZERO(testRTFileSetTimesATime);
478 return VINF_SUCCESS;
479}
480
481static RTFILE g_testRTFileUnlockFile;
482static int64_t testRTFileUnlockOffset;
483static uint64_t testRTFileUnlockSize;
484
485extern int testRTFileUnlock(RTFILE File, int64_t offLock, uint64_t cbLock)
486{
487 /* RTPrintf("%s: hFile=%p, ofLock=%lli, cbLock=%llu\n", __PRETTY_FUNCTION__,
488 File, (long long) offLock, LLUIFY(cbLock)); */
489 g_testRTFileUnlockFile = File;
490 testRTFileUnlockOffset = offLock;
491 testRTFileUnlockSize = cbLock;
492 return VINF_SUCCESS;
493}
494
495static char testRTFileWriteData[256];
496
497extern int testRTFileWrite(RTFILE File, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
498{
499 RT_NOREF2(File, cbToWrite);
500 /* RTPrintf("%s: File=%p, pvBuf=%.*s, cbToWrite=%llu\n", __PRETTY_FUNCTION__,
501 File, cbToWrite, (const char *)pvBuf, LLUIFY(cbToWrite)); */
502 ARRAY_FROM_PATH(testRTFileWriteData, (const char *)pvBuf);
503 if (pcbWritten)
504 *pcbWritten = strlen(testRTFileWriteData) + 1;
505 return VINF_SUCCESS;
506}
507
508extern int testRTFileWriteAt(RTFILE File, uint64_t offFile, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
509{
510 RT_NOREF3(File, cbToWrite, offFile);
511 /* RTPrintf("%s: File=%p, pvBuf=%.*s, cbToWrite=%llu\n", __PRETTY_FUNCTION__,
512 File, cbToWrite, (const char *)pvBuf, LLUIFY(cbToWrite)); */
513 ARRAY_FROM_PATH(testRTFileWriteData, (const char *)pvBuf);
514 if (pcbWritten)
515 *pcbWritten = strlen(testRTFileWriteData) + 1;
516 return VINF_SUCCESS;
517}
518
519extern int testRTFsQueryProperties(const char *pszFsPath, PRTFSPROPERTIES pProperties)
520{
521 RT_NOREF1(pszFsPath);
522 /* RTPrintf("%s, pszFsPath=%s\n", __PRETTY_FUNCTION__, pszFsPath);
523 RT_ZERO(*pProperties); */
524 pProperties->cbMaxComponent = 256;
525 pProperties->fCaseSensitive = true;
526 return VINF_SUCCESS;
527}
528
529extern int testRTFsQuerySerial(const char *pszFsPath, uint32_t *pu32Serial)
530{
531 RT_NOREF2(pszFsPath, pu32Serial);
532 RTPrintf("%s\n", __PRETTY_FUNCTION__);
533 return 0;
534}
535extern int testRTFsQuerySizes(const char *pszFsPath, PRTFOFF pcbTotal, RTFOFF *pcbFree, uint32_t *pcbBlock, uint32_t *pcbSector)
536{
537 RT_NOREF5(pszFsPath, pcbTotal, pcbFree, pcbBlock, pcbSector);
538 RTPrintf("%s\n", __PRETTY_FUNCTION__);
539 return 0;
540}
541
542extern int testRTPathQueryInfoEx(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
543{
544 RT_NOREF2(enmAdditionalAttribs, fFlags);
545 /* RTPrintf("%s: pszPath=%s, enmAdditionalAttribs=0x%x, fFlags=0x%x\n",
546 __PRETTY_FUNCTION__, pszPath, (unsigned) enmAdditionalAttribs,
547 (unsigned) fFlags); */
548 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszPath, "/\\")))
549 return VERR_FILE_NOT_FOUND;
550 RT_ZERO(*pObjInfo);
551 return VINF_SUCCESS;
552}
553
554extern int testRTSymlinkDelete(const char *pszSymlink, uint32_t fDelete)
555{
556 RT_NOREF2(pszSymlink, fDelete);
557 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszSymlink, "/\\")))
558 return VERR_FILE_NOT_FOUND;
559 RTPrintf("%s\n", __PRETTY_FUNCTION__);
560 return 0;
561}
562
563extern int testRTSymlinkRead(const char *pszSymlink, char *pszTarget, size_t cbTarget, uint32_t fRead)
564{
565 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszSymlink, "/\\")))
566 return VERR_FILE_NOT_FOUND;
567 RT_NOREF4(pszSymlink, pszTarget, cbTarget, fRead);
568 RTPrintf("%s\n", __PRETTY_FUNCTION__);
569 return 0;
570}
571
572
573/*********************************************************************************************************************************
574* Tests *
575*********************************************************************************************************************************/
576
577/* Sub-tests for testMappingsQuery(). */
578void testMappingsQuerySimple(RTTEST hTest) { RT_NOREF1(hTest); }
579void testMappingsQueryTooFewBuffers(RTTEST hTest) { RT_NOREF1(hTest); }
580void testMappingsQueryAutoMount(RTTEST hTest) { RT_NOREF1(hTest); }
581void testMappingsQueryArrayWrongSize(RTTEST hTest) { RT_NOREF1(hTest); }
582
583/* Sub-tests for testMappingsQueryName(). */
584void testMappingsQueryNameValid(RTTEST hTest) { RT_NOREF1(hTest); }
585void testMappingsQueryNameInvalid(RTTEST hTest) { RT_NOREF1(hTest); }
586void testMappingsQueryNameBadBuffer(RTTEST hTest) { RT_NOREF1(hTest); }
587
588/* Sub-tests for testMapFolder(). */
589void testMapFolderValid(RTTEST hTest) { RT_NOREF1(hTest); }
590void testMapFolderInvalid(RTTEST hTest) { RT_NOREF1(hTest); }
591void testMapFolderTwice(RTTEST hTest) { RT_NOREF1(hTest); }
592void testMapFolderDelimiter(RTTEST hTest) { RT_NOREF1(hTest); }
593void testMapFolderCaseSensitive(RTTEST hTest) { RT_NOREF1(hTest); }
594void testMapFolderCaseInsensitive(RTTEST hTest) { RT_NOREF1(hTest); }
595void testMapFolderBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
596
597/* Sub-tests for testUnmapFolder(). */
598void testUnmapFolderValid(RTTEST hTest) { RT_NOREF1(hTest); }
599void testUnmapFolderInvalid(RTTEST hTest) { RT_NOREF1(hTest); }
600void testUnmapFolderBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
601
602/* Sub-tests for testCreate(). */
603void testCreateBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
604
605/* Sub-tests for testClose(). */
606void testCloseBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
607
608/* Sub-tests for testRead(). */
609void testReadBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
610
611/* Sub-tests for testWrite(). */
612void testWriteBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
613
614/* Sub-tests for testLock(). */
615void testLockBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
616
617/* Sub-tests for testFlush(). */
618void testFlushBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
619
620/* Sub-tests for testDirList(). */
621void testDirListBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
622
623/* Sub-tests for testReadLink(). */
624void testReadLinkBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
625
626/* Sub-tests for testFSInfo(). */
627void testFSInfoBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
628
629/* Sub-tests for testRemove(). */
630void testRemoveBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
631
632/* Sub-tests for testRename(). */
633void testRenameBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
634
635/* Sub-tests for testSymlink(). */
636void testSymlinkBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
637
638/* Sub-tests for testMappingsAdd(). */
639void testMappingsAddBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
640
641/* Sub-tests for testMappingsRemove(). */
642void testMappingsRemoveBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
643
644union TESTSHFLSTRING
645{
646 SHFLSTRING string;
647 char acData[256];
648};
649
650static void fillTestShflString(union TESTSHFLSTRING *pDest,
651 const char *pcszSource)
652{
653 const size_t cchSource = strlen(pcszSource);
654 AssertRelease( cchSource * 2 + 2
655 < sizeof(*pDest) - RT_UOFFSETOF(SHFLSTRING, String));
656 pDest->string.u16Length = (uint16_t)(cchSource * sizeof(RTUTF16));
657 pDest->string.u16Size = pDest->string.u16Length + sizeof(RTUTF16);
658 /* Copy pcszSource ASCIIZ, including the trailing 0, to the UTF16 pDest->string.String.ucs2. */
659 for (unsigned i = 0; i <= cchSource; ++i)
660 pDest->string.String.ucs2[i] = (uint16_t)pcszSource[i];
661}
662
663static SHFLROOT initWithWritableMapping(RTTEST hTest,
664 VBOXHGCMSVCFNTABLE *psvcTable,
665 VBOXHGCMSVCHELPERS *psvcHelpers,
666 const char *pcszFolderName,
667 const char *pcszMapping,
668 bool fCaseSensitive = true)
669{
670 VBOXHGCMSVCPARM aParms[RT_MAX(SHFL_CPARMS_ADD_MAPPING,
671 SHFL_CPARMS_MAP_FOLDER)];
672 union TESTSHFLSTRING FolderName;
673 union TESTSHFLSTRING Mapping;
674 union TESTSHFLSTRING AutoMountPoint;
675 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
676 int rc;
677
678 initTable(psvcTable, psvcHelpers);
679 AssertReleaseRC(VBoxHGCMSvcLoad(psvcTable));
680 AssertRelease( psvcTable->pvService
681 = RTTestGuardedAllocTail(hTest, psvcTable->cbClient));
682 RT_BZERO(psvcTable->pvService, psvcTable->cbClient);
683 fillTestShflString(&FolderName, pcszFolderName);
684 fillTestShflString(&Mapping, pcszMapping);
685 fillTestShflString(&AutoMountPoint, "");
686 HGCMSvcSetPv(&aParms[0], &FolderName, RT_UOFFSETOF(SHFLSTRING, String)
687 + FolderName.string.u16Size);
688 HGCMSvcSetPv(&aParms[1], &Mapping, RT_UOFFSETOF(SHFLSTRING, String)
689 + Mapping.string.u16Size);
690 HGCMSvcSetU32(&aParms[2], 1);
691 HGCMSvcSetPv(&aParms[3], &AutoMountPoint, SHFLSTRING_HEADER_SIZE + AutoMountPoint.string.u16Size);
692 rc = psvcTable->pfnHostCall(psvcTable->pvService, SHFL_FN_ADD_MAPPING,
693 SHFL_CPARMS_ADD_MAPPING, aParms);
694 AssertReleaseRC(rc);
695 HGCMSvcSetPv(&aParms[0], &Mapping, RT_UOFFSETOF(SHFLSTRING, String)
696 + Mapping.string.u16Size);
697 HGCMSvcSetU32(&aParms[1], 0); /* root */
698 HGCMSvcSetU32(&aParms[2], '/'); /* delimiter */
699 HGCMSvcSetU32(&aParms[3], fCaseSensitive);
700 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
701 psvcTable->pvService, SHFL_FN_MAP_FOLDER,
702 SHFL_CPARMS_MAP_FOLDER, aParms, 0);
703 AssertReleaseRC(callHandle.rc);
704 return aParms[1].u.uint32;
705}
706
707/** @todo Mappings should be automatically removed by unloading the service,
708 * but unloading is currently a no-op! */
709static void unmapAndRemoveMapping(RTTEST hTest, VBOXHGCMSVCFNTABLE *psvcTable,
710 SHFLROOT root, const char *pcszFolderName)
711{
712 RT_NOREF1(hTest);
713 VBOXHGCMSVCPARM aParms[RT_MAX(SHFL_CPARMS_UNMAP_FOLDER,
714 SHFL_CPARMS_REMOVE_MAPPING)];
715 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
716 union TESTSHFLSTRING FolderName;
717 int rc;
718
719 HGCMSvcSetU32(&aParms[0], root);
720 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
721 psvcTable->pvService, SHFL_FN_UNMAP_FOLDER,
722 SHFL_CPARMS_UNMAP_FOLDER, aParms, 0);
723 AssertReleaseRC(callHandle.rc);
724 fillTestShflString(&FolderName, pcszFolderName);
725 HGCMSvcSetPv(&aParms[0], &FolderName, RT_UOFFSETOF(SHFLSTRING, String)
726 + FolderName.string.u16Size);
727 rc = psvcTable->pfnHostCall(psvcTable->pvService, SHFL_FN_REMOVE_MAPPING,
728 SHFL_CPARMS_REMOVE_MAPPING, aParms);
729 AssertReleaseRC(rc);
730}
731
732static int createFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT Root,
733 const char *pcszFilename, uint32_t fCreateFlags,
734 SHFLHANDLE *pHandle, SHFLCREATERESULT *pResult)
735{
736 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_CREATE];
737 union TESTSHFLSTRING Path;
738 SHFLCREATEPARMS CreateParms;
739 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
740
741 fillTestShflString(&Path, pcszFilename);
742 RT_ZERO(CreateParms);
743 CreateParms.CreateFlags = fCreateFlags;
744 HGCMSvcSetU32(&aParms[0], Root);
745 HGCMSvcSetPv(&aParms[1], &Path, RT_UOFFSETOF(SHFLSTRING, String)
746 + Path.string.u16Size);
747 HGCMSvcSetPv(&aParms[2], &CreateParms, sizeof(CreateParms));
748 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
749 psvcTable->pvService, SHFL_FN_CREATE,
750 RT_ELEMENTS(aParms), aParms, 0);
751 if (RT_FAILURE(callHandle.rc))
752 return callHandle.rc;
753 if (pHandle)
754 *pHandle = CreateParms.Handle;
755 if (pResult)
756 *pResult = CreateParms.Result;
757 return VINF_SUCCESS;
758}
759
760static int readFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT Root,
761 SHFLHANDLE hFile, uint64_t offSeek, uint32_t cbRead,
762 uint32_t *pcbRead, void *pvBuf, uint32_t cbBuf)
763{
764 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_READ];
765 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
766
767 HGCMSvcSetU32(&aParms[0], Root);
768 HGCMSvcSetU64(&aParms[1], (uint64_t) hFile);
769 HGCMSvcSetU64(&aParms[2], offSeek);
770 HGCMSvcSetU32(&aParms[3], cbRead);
771 HGCMSvcSetPv(&aParms[4], pvBuf, cbBuf);
772 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
773 psvcTable->pvService, SHFL_FN_READ,
774 RT_ELEMENTS(aParms), aParms, 0);
775 if (pcbRead)
776 *pcbRead = aParms[3].u.uint32;
777 return callHandle.rc;
778}
779
780static int writeFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT Root,
781 SHFLHANDLE hFile, uint64_t offSeek, uint32_t cbWrite,
782 uint32_t *pcbWritten, const void *pvBuf, uint32_t cbBuf)
783{
784 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_WRITE];
785 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
786
787 HGCMSvcSetU32(&aParms[0], Root);
788 HGCMSvcSetU64(&aParms[1], (uint64_t) hFile);
789 HGCMSvcSetU64(&aParms[2], offSeek);
790 HGCMSvcSetU32(&aParms[3], cbWrite);
791 HGCMSvcSetPv(&aParms[4], (void *)pvBuf, cbBuf);
792 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
793 psvcTable->pvService, SHFL_FN_WRITE,
794 RT_ELEMENTS(aParms), aParms, 0);
795 if (pcbWritten)
796 *pcbWritten = aParms[3].u.uint32;
797 return callHandle.rc;
798}
799
800static int flushFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT root,
801 SHFLHANDLE handle)
802{
803 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_FLUSH];
804 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
805
806 HGCMSvcSetU32(&aParms[0], root);
807 HGCMSvcSetU64(&aParms[1], handle);
808 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
809 psvcTable->pvService, SHFL_FN_FLUSH,
810 SHFL_CPARMS_FLUSH, aParms, 0);
811 return callHandle.rc;
812}
813
814static int listDir(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT root,
815 SHFLHANDLE handle, uint32_t fFlags,
816 const char *pcszPath, void *pvBuf, uint32_t cbBuf,
817 uint32_t resumePoint, uint32_t *pcFiles)
818{
819 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_LIST];
820 union TESTSHFLSTRING Path;
821 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
822
823 HGCMSvcSetU32(&aParms[0], root);
824 HGCMSvcSetU64(&aParms[1], handle);
825 HGCMSvcSetU32(&aParms[2], fFlags);
826 HGCMSvcSetU32(&aParms[3], cbBuf);
827 if (pcszPath)
828 {
829 fillTestShflString(&Path, pcszPath);
830 HGCMSvcSetPv(&aParms[4], &Path, RT_UOFFSETOF(SHFLSTRING, String)
831 + Path.string.u16Size);
832 }
833 else
834 HGCMSvcSetPv(&aParms[4], NULL, 0);
835 HGCMSvcSetPv(&aParms[5], pvBuf, cbBuf);
836 HGCMSvcSetU32(&aParms[6], resumePoint);
837 HGCMSvcSetU32(&aParms[7], 0);
838 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
839 psvcTable->pvService, SHFL_FN_LIST,
840 RT_ELEMENTS(aParms), aParms, 0);
841 if (pcFiles)
842 *pcFiles = aParms[7].u.uint32;
843 return callHandle.rc;
844}
845
846static int sfInformation(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT root,
847 SHFLHANDLE handle, uint32_t fFlags, uint32_t cb,
848 SHFLFSOBJINFO *pInfo)
849{
850 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_INFORMATION];
851 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
852
853 HGCMSvcSetU32(&aParms[0], root);
854 HGCMSvcSetU64(&aParms[1], handle);
855 HGCMSvcSetU32(&aParms[2], fFlags);
856 HGCMSvcSetU32(&aParms[3], cb);
857 HGCMSvcSetPv(&aParms[4], pInfo, cb);
858 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
859 psvcTable->pvService, SHFL_FN_INFORMATION,
860 RT_ELEMENTS(aParms), aParms, 0);
861 return callHandle.rc;
862}
863
864static int lockFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT root,
865 SHFLHANDLE handle, int64_t offLock, uint64_t cbLock,
866 uint32_t fFlags)
867{
868 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_LOCK];
869 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
870
871 HGCMSvcSetU32(&aParms[0], root);
872 HGCMSvcSetU64(&aParms[1], handle);
873 HGCMSvcSetU64(&aParms[2], offLock);
874 HGCMSvcSetU64(&aParms[3], cbLock);
875 HGCMSvcSetU32(&aParms[4], fFlags);
876 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
877 psvcTable->pvService, SHFL_FN_LOCK,
878 RT_ELEMENTS(aParms), aParms, 0);
879 return callHandle.rc;
880}
881
882void testCreateFileSimple(RTTEST hTest)
883{
884 VBOXHGCMSVCFNTABLE svcTable;
885 VBOXHGCMSVCHELPERS svcHelpers;
886 SHFLROOT Root;
887 const RTFILE hFile = (RTFILE) 0x10000;
888 SHFLCREATERESULT Result;
889 int rc;
890
891 RTTestSub(hTest, "Create file simple");
892 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
893 "/test/mapping", "testname");
894 testRTFileOpenpFile = hFile;
895 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ, NULL,
896 &Result);
897 RTTEST_CHECK_RC_OK(hTest, rc);
898 RTTEST_CHECK_MSG(hTest,
899 !strcmp(&testRTFileOpenName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0],
900 "/test/mapping/test/file"),
901 (hTest, "pszFilename=%s\n", &testRTFileOpenName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0]));
902 RTTEST_CHECK_MSG(hTest, testRTFileOpenFlags == 0x181,
903 (hTest, "fOpen=%llu\n", LLUIFY(testRTFileOpenFlags)));
904 RTTEST_CHECK_MSG(hTest, Result == SHFL_FILE_CREATED,
905 (hTest, "Result=%d\n", (int) Result));
906 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
907 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
908 AssertReleaseRC(svcTable.pfnUnload(NULL));
909 RTTestGuardedFree(hTest, svcTable.pvService);
910 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hFile,
911 (hTest, "File=%u\n", (uintptr_t)g_testRTFileCloseFile));
912}
913
914void testCreateFileSimpleCaseInsensitive(RTTEST hTest)
915{
916 VBOXHGCMSVCFNTABLE svcTable;
917 VBOXHGCMSVCHELPERS svcHelpers;
918 SHFLROOT Root;
919 const RTFILE hFile = (RTFILE) 0x10000;
920 SHFLCREATERESULT Result;
921 int rc;
922
923 g_fFailIfNotLowercase = true;
924
925 RTTestSub(hTest, "Create file case insensitive");
926 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
927 "/test/mapping", "testname", false /*fCaseSensitive*/);
928 testRTFileOpenpFile = hFile;
929 rc = createFile(&svcTable, Root, "/TesT/FilE", SHFL_CF_ACCESS_READ, NULL,
930 &Result);
931 RTTEST_CHECK_RC_OK(hTest, rc);
932
933 RTTEST_CHECK_MSG(hTest,
934 !strcmp(&testRTFileOpenName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0],
935 "/test/mapping/test/file"),
936 (hTest, "pszFilename=%s\n", &testRTFileOpenName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0]));
937 RTTEST_CHECK_MSG(hTest, testRTFileOpenFlags == 0x181,
938 (hTest, "fOpen=%llu\n", LLUIFY(testRTFileOpenFlags)));
939 RTTEST_CHECK_MSG(hTest, Result == SHFL_FILE_CREATED,
940 (hTest, "Result=%d\n", (int) Result));
941 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
942 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
943 AssertReleaseRC(svcTable.pfnUnload(NULL));
944 RTTestGuardedFree(hTest, svcTable.pvService);
945 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hFile,
946 (hTest, "File=%u\n", (uintptr_t)g_testRTFileCloseFile));
947
948 g_fFailIfNotLowercase = false;
949}
950
951void testCreateDirSimple(RTTEST hTest)
952{
953 VBOXHGCMSVCFNTABLE svcTable;
954 VBOXHGCMSVCHELPERS svcHelpers;
955 SHFLROOT Root;
956 RTDIR hDir = (RTDIR)&g_aTestDirHandles[g_iNextDirHandle++ % RT_ELEMENTS(g_aTestDirHandles)];
957 SHFLCREATERESULT Result;
958 int rc;
959
960 RTTestSub(hTest, "Create directory simple");
961 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
962 "/test/mapping", "testname");
963 testRTDirOpen_hDir = hDir;
964 rc = createFile(&svcTable, Root, "test/dir",
965 SHFL_CF_DIRECTORY | SHFL_CF_ACCESS_READ, NULL, &Result);
966 RTTEST_CHECK_RC_OK(hTest, rc);
967 RTTEST_CHECK_MSG(hTest,
968 !strcmp(&testRTDirCreatePath[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0],
969 "/test/mapping/test/dir"),
970 (hTest, "pszPath=%s\n", &testRTDirCreatePath[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0]));
971 RTTEST_CHECK_MSG(hTest,
972 !strcmp(&testRTDirOpenName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0],
973 "/test/mapping/test/dir"),
974 (hTest, "pszFilename=%s\n", &testRTDirOpenName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0]));
975 RTTEST_CHECK_MSG(hTest, Result == SHFL_FILE_CREATED,
976 (hTest, "Result=%d\n", (int) Result));
977 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
978 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
979 AssertReleaseRC(svcTable.pfnUnload(NULL));
980 RTTestGuardedFree(hTest, svcTable.pvService);
981 RTTEST_CHECK_MSG(hTest, g_testRTDirClose_hDir == hDir, (hTest, "hDir=%p\n", g_testRTDirClose_hDir));
982}
983
984void testReadFileSimple(RTTEST hTest)
985{
986 VBOXHGCMSVCFNTABLE svcTable;
987 VBOXHGCMSVCHELPERS svcHelpers;
988 SHFLROOT Root;
989 const RTFILE hFile = (RTFILE) 0x10000;
990 SHFLHANDLE Handle;
991 const char *pcszReadData = "Data to read";
992 char achBuf[sizeof(pcszReadData) + 10];
993 uint32_t cbRead;
994 int rc;
995
996 RTTestSub(hTest, "Read file simple");
997 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
998 "/test/mapping", "testname");
999 testRTFileOpenpFile = hFile;
1000 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1001 &Handle, NULL);
1002 RTTEST_CHECK_RC_OK(hTest, rc);
1003 testRTFileReadData = pcszReadData;
1004 memset(achBuf, 'f', sizeof(achBuf));
1005 rc = readFile(&svcTable, Root, Handle, 0, (uint32_t)strlen(pcszReadData) + 1,
1006 &cbRead, achBuf, (uint32_t)sizeof(achBuf));
1007 RTTEST_CHECK_RC_OK(hTest, rc);
1008 RTTEST_CHECK_MSG(hTest,
1009 !strncmp(achBuf, pcszReadData, sizeof(achBuf)),
1010 (hTest, "pvBuf=%.*s Handle=%#RX64\n", sizeof(achBuf), achBuf, Handle));
1011 RTTEST_CHECK_MSG(hTest, cbRead == strlen(pcszReadData) + 1,
1012 (hTest, "cbRead=%llu\n", LLUIFY(cbRead)));
1013 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1014 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hFile, (hTest, "File=%u\n", g_testRTFileCloseFile));
1015 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1016 AssertReleaseRC(svcTable.pfnUnload(NULL));
1017 RTTestGuardedFree(hTest, svcTable.pvService);
1018}
1019
1020void testWriteFileSimple(RTTEST hTest)
1021{
1022 VBOXHGCMSVCFNTABLE svcTable;
1023 VBOXHGCMSVCHELPERS svcHelpers;
1024 SHFLROOT Root;
1025 const RTFILE hFile = (RTFILE) 0x10000;
1026 SHFLHANDLE Handle;
1027 const char *pcszWrittenData = "Data to write";
1028 uint32_t cbToWrite = (uint32_t)strlen(pcszWrittenData) + 1;
1029 uint32_t cbWritten;
1030 int rc;
1031
1032 RTTestSub(hTest, "Write file simple");
1033 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1034 "/test/mapping", "testname");
1035 testRTFileOpenpFile = hFile;
1036 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1037 &Handle, NULL);
1038 RTTEST_CHECK_RC_OK(hTest, rc);
1039 rc = writeFile(&svcTable, Root, Handle, 0, cbToWrite, &cbWritten,
1040 pcszWrittenData, cbToWrite);
1041 RTTEST_CHECK_RC_OK(hTest, rc);
1042 RTTEST_CHECK_MSG(hTest,
1043 !strcmp(testRTFileWriteData, pcszWrittenData),
1044 (hTest, "pvBuf=%s\n", testRTFileWriteData));
1045 RTTEST_CHECK_MSG(hTest, cbWritten == cbToWrite,
1046 (hTest, "cbWritten=%llu\n", LLUIFY(cbWritten)));
1047 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1048 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hFile, (hTest, "File=%u\n", g_testRTFileCloseFile));
1049 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1050 AssertReleaseRC(svcTable.pfnUnload(NULL));
1051 RTTestGuardedFree(hTest, svcTable.pvService);
1052}
1053
1054void testFlushFileSimple(RTTEST hTest)
1055{
1056 VBOXHGCMSVCFNTABLE svcTable;
1057 VBOXHGCMSVCHELPERS svcHelpers;
1058 SHFLROOT Root;
1059 const RTFILE hFile = (RTFILE) 0x10000;
1060 SHFLHANDLE Handle;
1061 int rc;
1062
1063 RTTestSub(hTest, "Flush file simple");
1064 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1065 "/test/mapping", "testname");
1066 testRTFileOpenpFile = hFile;
1067 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1068 &Handle, NULL);
1069 RTTEST_CHECK_RC_OK(hTest, rc);
1070 rc = flushFile(&svcTable, Root, Handle);
1071 RTTEST_CHECK_RC_OK(hTest, rc);
1072 RTTEST_CHECK_MSG(hTest, g_testRTFileFlushFile == hFile, (hTest, "File=%u\n", g_testRTFileFlushFile));
1073 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1074 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1075 AssertReleaseRC(svcTable.pfnUnload(NULL));
1076 RTTestGuardedFree(hTest, svcTable.pvService);
1077 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hFile, (hTest, "File=%u\n", g_testRTFileCloseFile));
1078}
1079
1080void testDirListEmpty(RTTEST hTest)
1081{
1082 VBOXHGCMSVCFNTABLE svcTable;
1083 VBOXHGCMSVCHELPERS svcHelpers;
1084 SHFLROOT Root;
1085 RTDIR hDir = (RTDIR)&g_aTestDirHandles[g_iNextDirHandle++ % RT_ELEMENTS(g_aTestDirHandles)];
1086 SHFLHANDLE Handle;
1087 union
1088 {
1089 SHFLDIRINFO DirInfo;
1090 uint8_t abBuffer[sizeof(SHFLDIRINFO) + 2 * sizeof(RTUTF16)];
1091 } Buf;
1092 uint32_t cFiles;
1093 int rc;
1094
1095 RTTestSub(hTest, "List empty directory");
1096 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1097 "/test/mapping", "testname");
1098 testRTDirOpen_hDir = hDir;
1099 rc = createFile(&svcTable, Root, "test/dir",
1100 SHFL_CF_DIRECTORY | SHFL_CF_ACCESS_READ, &Handle, NULL);
1101 RTTEST_CHECK_RC_OK(hTest, rc);
1102 rc = listDir(&svcTable, Root, Handle, 0, NULL, &Buf.DirInfo, sizeof(Buf), 0, &cFiles);
1103 RTTEST_CHECK_RC(hTest, rc, VERR_NO_MORE_FILES);
1104 RTTEST_CHECK_MSG(hTest, g_testRTDirReadEx_hDir == hDir, (hTest, "Dir=%p\n", g_testRTDirReadEx_hDir));
1105 RTTEST_CHECK_MSG(hTest, cFiles == 0,
1106 (hTest, "cFiles=%llu\n", LLUIFY(cFiles)));
1107 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1108 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1109 AssertReleaseRC(svcTable.pfnUnload(NULL));
1110 RTTestGuardedFree(hTest, svcTable.pvService);
1111 RTTEST_CHECK_MSG(hTest, g_testRTDirClose_hDir == hDir, (hTest, "hDir=%p\n", g_testRTDirClose_hDir));
1112}
1113
1114void testFSInfoQuerySetFMode(RTTEST hTest)
1115{
1116 VBOXHGCMSVCFNTABLE svcTable;
1117 VBOXHGCMSVCHELPERS svcHelpers;
1118 SHFLROOT Root;
1119 const RTFILE hFile = (RTFILE) 0x10000;
1120 const uint32_t fMode = 0660;
1121 SHFLFSOBJINFO Info;
1122 int rc;
1123
1124 RTTestSub(hTest, "Query and set file size");
1125 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1126 "/test/mapping", "testname");
1127 SHFLHANDLE Handle = SHFL_HANDLE_NIL;
1128 testRTFileOpenpFile = hFile;
1129 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1130 &Handle, NULL);
1131 RTTEST_CHECK_RC_OK_RETV(hTest, rc);
1132
1133 RT_ZERO(Info);
1134 testRTFileQueryInfoFMode = fMode;
1135 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_FILE, sizeof(Info),
1136 &Info);
1137 RTTEST_CHECK_RC_OK(hTest, rc);
1138 RTTEST_CHECK_MSG(hTest, g_testRTFileQueryInfoFile == hFile, (hTest, "File=%u\n", g_testRTFileQueryInfoFile));
1139 RTTEST_CHECK_MSG(hTest, Info.Attr.fMode == fMode,
1140 (hTest, "cbObject=%llu\n", LLUIFY(Info.cbObject)));
1141 RT_ZERO(Info);
1142 Info.Attr.fMode = fMode;
1143 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_SET | SHFL_INFO_FILE,
1144 sizeof(Info), &Info);
1145 RTTEST_CHECK_RC_OK(hTest, rc);
1146 RTTEST_CHECK_MSG(hTest, testRTFileSetFMode == fMode,
1147 (hTest, "Size=%llu\n", LLUIFY(testRTFileSetFMode)));
1148 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1149 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1150 AssertReleaseRC(svcTable.pfnUnload(NULL));
1151 RTTestGuardedFree(hTest, svcTable.pvService);
1152 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hFile, (hTest, "File=%u\n", g_testRTFileCloseFile));
1153}
1154
1155void testFSInfoQuerySetDirATime(RTTEST hTest)
1156{
1157 VBOXHGCMSVCFNTABLE svcTable;
1158 VBOXHGCMSVCHELPERS svcHelpers;
1159 SHFLROOT Root;
1160 const RTDIR hDir = (RTDIR)&g_aTestDirHandles[g_iNextDirHandle++ % RT_ELEMENTS(g_aTestDirHandles)];
1161 const int64_t ccAtimeNano = 100000;
1162 SHFLFSOBJINFO Info;
1163 SHFLHANDLE Handle;
1164 int rc;
1165
1166 RTTestSub(hTest, "Query and set directory atime");
1167 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1168 "/test/mapping", "testname");
1169 testRTDirOpen_hDir = hDir;
1170 rc = createFile(&svcTable, Root, "test/dir",
1171 SHFL_CF_DIRECTORY | SHFL_CF_ACCESS_READ, &Handle, NULL);
1172 RTTEST_CHECK_RC_OK(hTest, rc);
1173 RT_ZERO(Info);
1174 RTTimeSpecSetNano(&testRTDirQueryInfoATime, ccAtimeNano);
1175 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_FILE, sizeof(Info),
1176 &Info);
1177 RTTEST_CHECK_RC_OK(hTest, rc);
1178 RTTEST_CHECK_MSG(hTest, g_testRTDirQueryInfo_hDir == hDir, (hTest, "Dir=%p\n", g_testRTDirQueryInfo_hDir));
1179 RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&Info.AccessTime) == ccAtimeNano,
1180 (hTest, "ATime=%llu\n",
1181 LLUIFY(RTTimeSpecGetNano(&Info.AccessTime))));
1182 RT_ZERO(Info);
1183 RTTimeSpecSetNano(&Info.AccessTime, ccAtimeNano);
1184 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_SET | SHFL_INFO_FILE,
1185 sizeof(Info), &Info);
1186 RTTEST_CHECK_RC_OK(hTest, rc);
1187 RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&testRTDirSetTimesATime)
1188 == ccAtimeNano,
1189 (hTest, "ATime=%llu\n",
1190 LLUIFY(RTTimeSpecGetNano(&testRTDirSetTimesATime))));
1191 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1192 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1193 AssertReleaseRC(svcTable.pfnUnload(NULL));
1194 RTTestGuardedFree(hTest, svcTable.pvService);
1195 RTTEST_CHECK_MSG(hTest, g_testRTDirClose_hDir == hDir, (hTest, "hDir=%p\n", g_testRTDirClose_hDir));
1196}
1197
1198void testFSInfoQuerySetFileATime(RTTEST hTest)
1199{
1200 VBOXHGCMSVCFNTABLE svcTable;
1201 VBOXHGCMSVCHELPERS svcHelpers;
1202 SHFLROOT Root;
1203 const RTFILE hFile = (RTFILE) 0x10000;
1204 const int64_t ccAtimeNano = 100000;
1205 SHFLFSOBJINFO Info;
1206 SHFLHANDLE Handle;
1207 int rc;
1208
1209 RTTestSub(hTest, "Query and set file atime");
1210 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1211 "/test/mapping", "testname");
1212 testRTFileOpenpFile = hFile;
1213 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1214 &Handle, NULL);
1215 RTTEST_CHECK_RC_OK(hTest, rc);
1216 RT_ZERO(Info);
1217 RTTimeSpecSetNano(&testRTFileQueryInfoATime, ccAtimeNano);
1218 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_FILE, sizeof(Info),
1219 &Info);
1220 RTTEST_CHECK_RC_OK(hTest, rc);
1221 RTTEST_CHECK_MSG(hTest, g_testRTFileQueryInfoFile == hFile, (hTest, "File=%u\n", g_testRTFileQueryInfoFile));
1222 RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&Info.AccessTime) == ccAtimeNano,
1223 (hTest, "ATime=%llu\n",
1224 LLUIFY(RTTimeSpecGetNano(&Info.AccessTime))));
1225 RT_ZERO(Info);
1226 RTTimeSpecSetNano(&Info.AccessTime, ccAtimeNano);
1227 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_SET | SHFL_INFO_FILE,
1228 sizeof(Info), &Info);
1229 RTTEST_CHECK_RC_OK(hTest, rc);
1230 RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&testRTFileSetTimesATime)
1231 == ccAtimeNano,
1232 (hTest, "ATime=%llu\n",
1233 LLUIFY(RTTimeSpecGetNano(&testRTFileSetTimesATime))));
1234 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1235 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1236 AssertReleaseRC(svcTable.pfnUnload(NULL));
1237 RTTestGuardedFree(hTest, svcTable.pvService);
1238 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hFile, (hTest, "File=%u\n", g_testRTFileCloseFile));
1239}
1240
1241void testFSInfoQuerySetEndOfFile(RTTEST hTest)
1242{
1243 VBOXHGCMSVCFNTABLE svcTable;
1244 VBOXHGCMSVCHELPERS svcHelpers;
1245 SHFLROOT Root;
1246 const RTFILE hFile = (RTFILE) 0x10000;
1247 const RTFOFF cbNew = 50000;
1248 SHFLFSOBJINFO Info;
1249 SHFLHANDLE Handle;
1250 int rc;
1251
1252 RTTestSub(hTest, "Set end of file position");
1253 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1254 "/test/mapping", "testname");
1255 testRTFileOpenpFile = hFile;
1256 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1257 &Handle, NULL);
1258 RTTEST_CHECK_RC_OK(hTest, rc);
1259 RT_ZERO(Info);
1260 Info.cbObject = cbNew;
1261 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_SET | SHFL_INFO_SIZE,
1262 sizeof(Info), &Info);
1263 RTTEST_CHECK_RC_OK(hTest, rc);
1264 RTTEST_CHECK_MSG(hTest, g_testRTFileSetSizeFile == hFile, (hTest, "File=%u\n", g_testRTFileSetSizeFile));
1265 RTTEST_CHECK_MSG(hTest, testRTFileSetSizeSize == cbNew,
1266 (hTest, "Size=%llu\n", LLUIFY(testRTFileSetSizeSize)));
1267 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1268 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1269 AssertReleaseRC(svcTable.pfnUnload(NULL));
1270 RTTestGuardedFree(hTest, svcTable.pvService);
1271 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hFile, (hTest, "File=%u\n", g_testRTFileCloseFile));
1272}
1273
1274void testLockFileSimple(RTTEST hTest)
1275{
1276 VBOXHGCMSVCFNTABLE svcTable;
1277 VBOXHGCMSVCHELPERS svcHelpers;
1278 SHFLROOT Root;
1279 const RTFILE hFile = (RTFILE) 0x10000;
1280 const int64_t offLock = 50000;
1281 const uint64_t cbLock = 4000;
1282 SHFLHANDLE Handle;
1283 int rc;
1284
1285 RTTestSub(hTest, "Simple file lock and unlock");
1286 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1287 "/test/mapping", "testname");
1288 testRTFileOpenpFile = hFile;
1289 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1290 &Handle, NULL);
1291 RTTEST_CHECK_RC_OK(hTest, rc);
1292 rc = lockFile(&svcTable, Root, Handle, offLock, cbLock, SHFL_LOCK_SHARED);
1293 RTTEST_CHECK_RC_OK(hTest, rc);
1294#ifdef RT_OS_WINDOWS /* Locking is a no-op elsewhere. */
1295 RTTEST_CHECK_MSG(hTest, g_testRTFileLockFile == hFile, (hTest, "File=%u\n", g_testRTFileLockFile));
1296 RTTEST_CHECK_MSG(hTest, testRTFileLockfLock == 0,
1297 (hTest, "fLock=%u\n", testRTFileLockfLock));
1298 RTTEST_CHECK_MSG(hTest, testRTFileLockOffset == offLock,
1299 (hTest, "Offs=%llu\n", (long long) testRTFileLockOffset));
1300 RTTEST_CHECK_MSG(hTest, testRTFileLockSize == cbLock,
1301 (hTest, "Size=%llu\n", LLUIFY(testRTFileLockSize)));
1302#endif
1303 rc = lockFile(&svcTable, Root, Handle, offLock, cbLock, SHFL_LOCK_CANCEL);
1304 RTTEST_CHECK_RC_OK(hTest, rc);
1305#ifdef RT_OS_WINDOWS
1306 RTTEST_CHECK_MSG(hTest, g_testRTFileUnlockFile == hFile, (hTest, "File=%u\n", g_testRTFileUnlockFile));
1307 RTTEST_CHECK_MSG(hTest, testRTFileUnlockOffset == offLock,
1308 (hTest, "Offs=%llu\n",
1309 (long long) testRTFileUnlockOffset));
1310 RTTEST_CHECK_MSG(hTest, testRTFileUnlockSize == cbLock,
1311 (hTest, "Size=%llu\n", LLUIFY(testRTFileUnlockSize)));
1312#endif
1313 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1314 AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService));
1315 AssertReleaseRC(svcTable.pfnUnload(NULL));
1316 RTTestGuardedFree(hTest, svcTable.pvService);
1317 RTTEST_CHECK_MSG(hTest, g_testRTFileCloseFile == hFile, (hTest, "File=%u\n", g_testRTFileCloseFile));
1318}
1319
1320
1321/*********************************************************************************************************************************
1322* Main code *
1323*********************************************************************************************************************************/
1324
1325static void testAPI(RTTEST hTest)
1326{
1327 testMappingsQuery(hTest);
1328 testMappingsQueryName(hTest);
1329 testMapFolder(hTest);
1330 testUnmapFolder(hTest);
1331 testCreate(hTest);
1332 testClose(hTest);
1333 testRead(hTest);
1334 testWrite(hTest);
1335 testLock(hTest);
1336 testFlush(hTest);
1337 testDirList(hTest);
1338 testReadLink(hTest);
1339 testFSInfo(hTest);
1340 testRemove(hTest);
1341 testRename(hTest);
1342 testSymlink(hTest);
1343 testMappingsAdd(hTest);
1344 testMappingsRemove(hTest);
1345 /* testSetStatusLed(hTest); */
1346}
1347
1348int main(int argc, char **argv)
1349{
1350 RT_NOREF1(argc);
1351 RTEXITCODE rcExit = RTTestInitAndCreate(RTPathFilename(argv[0]), &g_hTest);
1352 if (rcExit != RTEXITCODE_SUCCESS)
1353 return rcExit;
1354 RTTestBanner(g_hTest);
1355 testAPI(g_hTest);
1356 return RTTestSummaryAndDestroy(g_hTest);
1357}
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