VirtualBox

source: vbox/trunk/src/VBox/GuestHost/SharedClipboard/testcase/tstClipboardHttpServer.cpp@ 106901

Last change on this file since 106901 was 106061, checked in by vboxsync, 4 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.5 KB
Line 
1/* $Id: tstClipboardHttpServer.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * Shared Clipboard HTTP server test case.
4 */
5
6/*
7 * Copyright (C) 2023-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#include <iprt/assert.h>
29#include <iprt/dir.h>
30#include <iprt/file.h>
31#include <iprt/getopt.h>
32#include <iprt/http.h>
33#include <iprt/message.h>
34#include <iprt/path.h>
35#include <iprt/process.h>
36#include <iprt/rand.h>
37#include <iprt/stream.h>
38#include <iprt/string.h>
39#include <iprt/test.h>
40#include <iprt/utf16.h>
41
42#ifdef TESTCASE_WITH_X11
43#include <VBox/GuestHost/SharedClipboard-x11.h>
44#endif
45
46#include <VBox/GuestHost/SharedClipboard-transfers.h>
47
48
49/** The release logger. */
50static PRTLOGGER g_pRelLogger;
51/** The current logging verbosity level. */
52static unsigned g_uVerbosity = 0;
53/** Default maximum HTTP server runtime (in ms). */
54static RTMSINTERVAL g_msRuntime = RT_MS_5MIN;
55/** Shutdown indicator. */
56static bool g_fShutdown = false;
57/** Manual mode indicator; allows manual (i.e. interactive) testing w/ other HTTP clients or desktop environments. */
58static bool g_fManual = false;
59#ifdef TESTCASE_WITH_X11
60 /** Puts the URL on the X11 clipboard. Only works with manual mode. */
61 static bool g_fX11 = false;
62#endif
63
64/** Test files to handle + download.
65 * All files reside in a common temporary directory. */
66static struct
67{
68 /** File mode. Used for RTFS_TYPE_XXX only. */
69 RTFMODE fMode;
70 /** Local path to serve via HTTP server. */
71 const char *pszPath;
72 /** URL to use for downloading the file via RTHttp APIs. Has to be fully escaped. */
73 const char *pszUrl;
74 /** File allocation size.
75 * Specify UINT64_MAX for random size. */
76 uint64_t cbSize;
77 /** Expected test result. */
78 int rc;
79} g_aTests[] =
80{
81 /*
82 * Files.
83 */
84 RTFS_TYPE_FILE, "file1.txt", "file1.txt", _64K, VINF_SUCCESS,
85 /* Note: For RTHttpGetFile() the URL needs to be percent-encoded. */
86 RTFS_TYPE_FILE, "file2 with spaces.txt", "file2%20with%20spaces.txt", _64K, VINF_SUCCESS,
87 RTFS_TYPE_FILE, "bigfile.bin", "bigfile.bin", _512M, VINF_SUCCESS,
88 RTFS_TYPE_FILE, "zerobytes", "zerobytes", 0, VINF_SUCCESS,
89 RTFS_TYPE_FILE, "file\\with\\slashes", "file%5Cwith%5Cslashes", 42, VINF_SUCCESS,
90 /* Korean encoding. */
91 RTFS_TYPE_FILE, "VirtualBox가 크게 성공했습니다!", "VirtualBox%EA%B0%80%20%ED%81%AC%EA%B2%8C%20%EC%84%B1%EA%B3%B5%ED%96%88%EC%8A%B5%EB%8B%88%EB%8B%A4%21", 42, VINF_SUCCESS,
92 /*
93 * Other stuff (not supported).
94 */
95 RTFS_TYPE_DIRECTORY, "test-directory", "test-directory", 0, VERR_HTTP_NOT_SUPPORTED,
96 RTFS_TYPE_SYMLINK, "test-symlink", "test-symlink", 0, VERR_HTTP_NOT_SUPPORTED
97};
98
99
100static void tstCreateTransferSingle(RTTEST hTest, PSHCLTRANSFERCTX pTransferCtx, PSHCLHTTPSERVER pSrv,
101 const char *pszPath, PSHCLTXPROVIDER pProvider)
102{
103 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "tstCreateTransferSingle: pszPath=%s\n", pszPath);
104
105 PSHCLTRANSFER pTx;
106 RTTEST_CHECK_RC_OK(hTest, ShClTransferCreate(SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, NULL /* Callbacks */, &pTx));
107 RTTEST_CHECK_RC_OK(hTest, ShClTransferSetProvider(pTx, pProvider));
108 RTTEST_CHECK_RC_OK(hTest, ShClTransferRootsSetFromPath(pTx, pszPath));
109 RTTEST_CHECK_RC_OK(hTest, ShClTransferInit(pTx));
110 RTTEST_CHECK_RC_OK(hTest, ShClTransferCtxRegister(pTransferCtx, pTx, NULL));
111 RTTEST_CHECK_RC_OK(hTest, ShClTransferHttpServerRegisterTransfer(pSrv, pTx));
112}
113
114/**
115 * Run a manual (i.e. interacive) test.
116 *
117 * This will keep the HTTP server running, so that the file(s) can be downloaded manually.
118 */
119static void tstManual(RTTEST hTest, PSHCLTRANSFERCTX pTransferCtx, PSHCLHTTPSERVER pHttpSrv)
120{
121 char *pszUrls = NULL;
122
123 uint32_t const cTx = ShClTransferCtxGetTotalTransfers(pTransferCtx);
124 if (!cTx)
125 {
126 RTTestFailed(hTest, "Must specify at least one file to serve!\n");
127 return;
128 }
129
130 for (uint32_t i = 0; i < cTx; i++)
131 {
132 PSHCLTRANSFER pTx = ShClTransferCtxGetTransferByIndex(pTransferCtx, i);
133
134 uint16_t const uId = ShClTransferGetID(pTx);
135 char *pszUrl = ShClTransferHttpServerGetUrlA(pHttpSrv, uId, 0 /* Entry index */);
136 RTTEST_CHECK(hTest, pszUrl != NULL);
137 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "URL #%02RU32: %s\n", i, pszUrl);
138 RTStrAPrintf(&pszUrls, "%s", pszUrl);
139 if (i > 0)
140 RTStrAPrintf(&pszUrls, "\n");
141 RTStrFree(pszUrl);
142 }
143
144#ifdef TESTCASE_WITH_X11
145 SHCLX11CTX X11Ctx;
146 SHCLEVENTSOURCE EventSource;
147
148 if (g_fX11)
149 {
150 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Copied URLs to X11 clipboard\n");
151
152 SHCLCALLBACKS Callbacks;
153 RT_ZERO(Callbacks);
154 RTTEST_CHECK_RC_OK(hTest, ShClX11Init(&X11Ctx, &Callbacks, NULL /* pParent */, false /* fHeadless */));
155 RTTEST_CHECK_RC_OK(hTest, ShClX11ThreadStart(&X11Ctx, false /* fGrab */));
156 RTTEST_CHECK_RC_OK(hTest, ShClEventSourceCreate(&EventSource, 0));
157 RTTEST_CHECK_RC_OK(hTest, ShClX11WriteDataToX11(&X11Ctx, &EventSource, RT_MS_30SEC,
158 VBOX_SHCL_FMT_UNICODETEXT | VBOX_SHCL_FMT_URI_LIST,
159 pszUrls, RTStrNLen(pszUrls, RTSTR_MAX), NULL /* pcbWritten */));
160 }
161#endif
162
163 RTThreadSleep(g_msRuntime);
164
165#ifdef TESTCASE_WITH_X11
166 if (g_fX11)
167 {
168 RTTEST_CHECK_RC_OK(hTest, ShClEventSourceDestroy(&EventSource));
169 ShClX11ThreadStop(&X11Ctx);
170 ShClX11Destroy(&X11Ctx);
171 }
172#endif
173
174 RTStrFree(pszUrls);
175}
176
177static RTEXITCODE tstUsage(PRTSTREAM pStrm)
178{
179 RTStrmPrintf(pStrm, "Tests for the clipboard HTTP server.\n\n");
180
181 RTStrmPrintf(pStrm, "Usage: %s [options] [file 1] ... [file N]\n", RTProcShortName());
182 RTStrmPrintf(pStrm,
183 "\n"
184 "Options:\n"
185 " -h, -?, --help\n"
186 " Displays help.\n"
187 " -m, --manual\n"
188 " Enables manual (i.e. interactive) testing the HTTP server.\n"
189 " -p, --port\n"
190 " Sets the HTTP server port.\n"
191 " -v, --verbose\n"
192 " Increases verbosity.\n"
193#ifdef TESTCASE_WITH_X11
194 " -X, --x11\n"
195 " Copies the HTTP URLs to the X11 clipboard(s). Implies manual testing.\n"
196#endif
197 );
198
199 return RTEXITCODE_SUCCESS;
200}
201
202int main(int argc, char *argv[])
203{
204 /*
205 * Init the runtime, test and say hello.
206 */
207 RTTEST hTest;
208 RTEXITCODE rcExit = RTTestInitAndCreate("tstClipboardHttpServer", &hTest);
209 if (rcExit != RTEXITCODE_SUCCESS)
210 return rcExit;
211
212 /*
213 * Process options.
214 */
215 static const RTGETOPTDEF aOpts[] =
216 {
217 { "--help", 'h', RTGETOPT_REQ_NOTHING },
218 { "--manual", 'm', RTGETOPT_REQ_NOTHING },
219 { "--max-time", 't', RTGETOPT_REQ_UINT32 },
220 { "--port", 'p', RTGETOPT_REQ_UINT16 },
221 { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
222 { "--x11", 'X', RTGETOPT_REQ_NOTHING }
223 };
224
225 RTGETOPTSTATE GetState;
226 int rc = RTGetOptInit(&GetState, argc, argv, aOpts, RT_ELEMENTS(aOpts), 1 /*idxFirst*/, 0 /*fFlags - must not sort! */);
227 AssertRCReturn(rc, RTEXITCODE_INIT);
228
229 uint16_t uPort = 0;
230
231 int ch;
232 RTGETOPTUNION ValueUnion;
233 while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0)
234 {
235 switch (ch)
236 {
237 case 'h':
238 return tstUsage(g_pStdErr);
239
240 case 'p':
241 uPort = ValueUnion.u16;
242 break;
243
244 case 't':
245 g_msRuntime = ValueUnion.u32 * RT_MS_1SEC; /* Convert s to ms. */
246 break;
247
248 case 'm':
249 g_fManual = true;
250 break;
251
252 case 'v':
253 g_uVerbosity++;
254 break;
255
256#ifdef TESTCASE_WITH_X11
257 case 'X':
258 g_fX11 = true;
259 break;
260#endif
261 case VINF_GETOPT_NOT_OPTION:
262 continue;
263
264 default:
265 return RTGetOptPrintError(ch, &ValueUnion);
266 }
267 }
268
269 RTTestBanner(hTest);
270
271#ifdef TESTCASE_WITH_X11
272 /* Enable manual mode if X11 was selected. Pure convenience. */
273 if (g_fX11 && !g_fManual)
274 g_fManual = true;
275#endif
276
277 /*
278 * Configure release logging to go to stdout.
279 */
280 RTUINT fFlags = RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG;
281#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
282 fFlags |= RTLOGFLAGS_USECRLF;
283#endif
284 static const char * const s_apszLogGroups[] = VBOX_LOGGROUP_NAMES;
285 rc = RTLogCreate(&g_pRelLogger, fFlags, "all.e.l", "TST_CLIPBOARD_HTTPSERVER_RELEASE_LOG",
286 RT_ELEMENTS(s_apszLogGroups), s_apszLogGroups, RTLOGDEST_STDOUT, NULL /*"vkat-release.log"*/);
287 if (RT_SUCCESS(rc))
288 {
289 RTLogSetDefaultInstance(g_pRelLogger);
290 if (g_uVerbosity)
291 {
292 RTMsgInfo("Setting verbosity logging to level %u\n", g_uVerbosity);
293 switch (g_uVerbosity) /* Not very elegant, but has to do it for now. */
294 {
295 case 1:
296 rc = RTLogGroupSettings(g_pRelLogger, "shared_clipboard.e.l+http.e.l");
297 break;
298
299 case 2:
300 rc = RTLogGroupSettings(g_pRelLogger, "shared_clipboard.e.l.l2+http.e.l.l2");
301 break;
302
303 case 3:
304 rc = RTLogGroupSettings(g_pRelLogger, "shared_clipboard.e.l.l2.l3+http.e.l.l2.l3");
305 break;
306
307 case 4:
308 RT_FALL_THROUGH();
309 default:
310 rc = RTLogGroupSettings(g_pRelLogger, "shared_clipboard.e.l.l2.l3.l4.f+http.e.l.l2.l3.l4.f");
311 break;
312 }
313 if (RT_FAILURE(rc))
314 RTMsgError("Setting debug logging failed, rc=%Rrc\n", rc);
315 }
316 }
317 else
318 RTMsgWarning("Failed to create release logger: %Rrc", rc);
319
320 /*
321 * Create HTTP server.
322 */
323 SHCLHTTPSERVER HttpSrv;
324 ShClTransferHttpServerInit(&HttpSrv);
325 ShClTransferHttpServerStop(&HttpSrv); /* Try to stop a non-running server twice. */
326 ShClTransferHttpServerStop(&HttpSrv);
327 RTTEST_CHECK(hTest, ShClTransferHttpServerIsRunning(&HttpSrv) == false);
328 if (uPort)
329 rc = ShClTransferHttpServerStartEx(&HttpSrv, uPort);
330 else
331 rc = ShClTransferHttpServerStart(&HttpSrv, 32 /* cMaxAttempts */, &uPort);
332 RTTEST_CHECK_RC_OK(hTest, rc);
333 RTTEST_CHECK(hTest, ShClTransferHttpServerGetTransfer(&HttpSrv, 0) == false);
334 RTTEST_CHECK(hTest, ShClTransferHttpServerGetTransfer(&HttpSrv, 42) == false);
335
336 char *pszSrvAddr = ShClTransferHttpServerGetAddressA(&HttpSrv);
337 RTTEST_CHECK(hTest, pszSrvAddr != NULL);
338 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "HTTP server running: %s (for %RU32ms) ...\n", pszSrvAddr, g_msRuntime);
339 RTStrFree(pszSrvAddr);
340 pszSrvAddr = NULL;
341
342 SHCLTRANSFERCTX TxCtx;
343 RTTEST_CHECK_RC_OK(hTest, ShClTransferCtxInit(&TxCtx));
344
345 /* Query the local transfer provider. */
346 SHCLTXPROVIDER Provider;
347 RTTESTI_CHECK(ShClTransferProviderLocalQueryInterface(&Provider) != NULL);
348
349 /* Parse options again, but this time we only fetch all files we want to serve.
350 * Only can be done after we initialized the HTTP server above. */
351 RT_ZERO(GetState);
352 rc = RTGetOptInit(&GetState, argc, argv, aOpts, RT_ELEMENTS(aOpts), 1 /*idxFirst*/, 0 /*fFlags - must not sort! */);
353 AssertRCReturn(rc, RTEXITCODE_INIT);
354 while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0)
355 {
356 switch (ch)
357 {
358 case VINF_GETOPT_NOT_OPTION:
359 {
360 tstCreateTransferSingle(hTest, &TxCtx, &HttpSrv, ValueUnion.psz, &Provider);
361 break;
362 }
363
364 default:
365 continue;
366 }
367 }
368
369 char szTempDir[RTPATH_MAX];
370 RTTEST_CHECK_RC_OK(hTest, RTPathTemp(szTempDir, sizeof(szTempDir)));
371 RTTEST_CHECK_RC_OK(hTest, RTPathAppend(szTempDir, sizeof(szTempDir), "tstClipboardHttpServer-XXXXXX"));
372 RTTEST_CHECK_RC_OK(hTest, RTDirCreateTemp(szTempDir, 0700));
373
374 if (!g_fManual)
375 {
376 char szPath[RTPATH_MAX];
377 for (size_t i = 0; i < RT_ELEMENTS(g_aTests); i++)
378 {
379 RTTEST_CHECK (hTest, RTStrPrintf(szPath, sizeof(szPath), szTempDir));
380 RTTEST_CHECK_RC_OK(hTest, RTPathAppend(szPath, sizeof(szPath), g_aTests[i].pszPath));
381
382 size_t cbSize = g_aTests[i].cbSize == UINT64_MAX ? RTRandU32Ex(0, _256M) : g_aTests[i].cbSize;
383
384 switch (g_aTests[i].fMode & RTFS_TYPE_MASK)
385 {
386 case RTFS_TYPE_FILE:
387 {
388 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Random test file (%zu bytes): %s\n", cbSize, szPath);
389
390 RTFILE hFile;
391 rc = RTFileOpen(&hFile, szPath, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE);
392 if (RT_SUCCESS(rc))
393 {
394 uint8_t abBuf[_64K]; RTRandBytes(abBuf, sizeof(abBuf));
395
396 while (cbSize > 0)
397 {
398 size_t cbToWrite = sizeof(abBuf);
399 if (cbToWrite > cbSize)
400 cbToWrite = cbSize;
401 rc = RTFileWrite(hFile, abBuf, cbToWrite, NULL);
402 if (RT_FAILURE(rc))
403 {
404 RTTestIFailed("RTFileWrite(%#x) -> %Rrc\n", cbToWrite, rc);
405 break;
406 }
407 cbSize -= cbToWrite;
408 }
409
410 RTTESTI_CHECK_RC(RTFileClose(hFile), VINF_SUCCESS);
411 }
412 else
413 RTTestIFailed("RTFileOpen(%s) -> %Rrc\n", szPath, rc);
414 break;
415 }
416
417 case RTFS_TYPE_DIRECTORY:
418 RTTESTI_CHECK_RC_OK(RTDirCreate(szPath, 0755 /* fMode */, 0 /* fCreate */));
419 break;
420
421 case RTFS_TYPE_SYMLINK:
422 RTTESTI_CHECK_RC_OK(RTSymlinkCreate(szPath, szTempDir, RTSYMLINKTYPE_UNKNOWN, 0 /* fCreate */));
423 break;
424
425 default:
426 break;
427 }
428
429 if (RT_SUCCESS(rc))
430 tstCreateTransferSingle(hTest, &TxCtx, &HttpSrv, szPath, &Provider);
431 }
432 }
433
434 /* Don't bail out here to prevent cleaning up after ourselves on failure. */
435 if (RTTestErrorCount(hTest) == 0)
436 {
437 if (g_fManual)
438 {
439 tstManual(hTest, &TxCtx, &HttpSrv);
440 }
441 else /* Download all files to a temp file using our HTTP client. */
442 {
443 RTHTTP hClient;
444 rc = RTHttpCreate(&hClient);
445 if (RT_SUCCESS(rc))
446 {
447 /*
448 * Set it to not use any proxies for our testcase as it is not necessary and
449 * it will cause memory leaks on Linux where libproxy is used making the testcase fail
450 * for ASAN enabled builds.
451 */
452 RTTEST_CHECK_RC_OK(hTest, RTHttpSetProxy(hClient, NULL /*pszProxyUrl*/, 0 /*uPort*/,
453 NULL /*pszProxyUser*/, NULL /*pszProxyPwd*/));
454
455 char szURL[RTPATH_MAX];
456 for (size_t i = 0; i < RT_ELEMENTS(g_aTests); i++)
457 {
458 PSHCLTRANSFER pTx = ShClTransferCtxGetTransferByIndex(&TxCtx, i);
459 char *pszUrlBase = ShClTransferHttpServerGetUrlA(&HttpSrv, ShClTransferGetID(pTx), UINT64_MAX);
460 RTTEST_CHECK(hTest, RTStrPrintf2(szURL, sizeof(szURL), "%s/%s", pszUrlBase, g_aTests[i].pszUrl));
461 RTStrFree(pszUrlBase);
462
463 switch (g_aTests[i].fMode & RTFS_TYPE_MASK)
464 {
465 case RTFS_TYPE_FILE:
466 {
467 /* Download to destination file. */
468 char szDstFile[RTPATH_MAX];
469 RTTEST_CHECK_RC_OK(hTest, RTPathTemp(szDstFile, sizeof(szDstFile)));
470 RTTEST_CHECK_RC_OK(hTest, RTPathAppend(szDstFile, sizeof(szDstFile), "tstClipboardHttpServer-XXXXXX"));
471 RTTEST_CHECK_RC_OK(hTest, RTFileCreateTemp(szDstFile, 0600));
472 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Downloading file '%s' -> '%s'\n", szURL, szDstFile);
473 RTTEST_CHECK_RC_OK(hTest, RTHttpGetFile(hClient, szURL, szDstFile));
474
475 /* Compare files. */
476 char szSrcFile[RTPATH_MAX];
477 RTTEST_CHECK (hTest, RTStrPrintf(szSrcFile, sizeof(szSrcFile), szTempDir));
478 RTTEST_CHECK_RC_OK(hTest, RTPathAppend(szSrcFile, sizeof(szSrcFile), g_aTests[i].pszPath));
479 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Comparing files '%s' vs. '%s'\n", szSrcFile, szDstFile);
480 RTTEST_CHECK_RC_OK(hTest, RTFileCompare(szSrcFile, szDstFile));
481
482 RTTEST_CHECK_RC_OK(hTest, RTFileDelete(szDstFile));
483 break;
484 }
485
486 case RTFS_TYPE_DIRECTORY:
487 RT_FALL_THROUGH();
488 case RTFS_TYPE_SYMLINK:
489 {
490 char szDstFile[RTPATH_MAX];
491 RTTEST_CHECK_RC_OK(hTest, RTPathTemp(szDstFile, sizeof(szDstFile)));
492 RTTEST_CHECK_RC_OK(hTest, RTPathAppend(szDstFile, sizeof(szDstFile), "tstClipboardHttpServer-XXXXXX"));
493 RTTEST_CHECK_RC_OK(hTest, RTFileCreateTemp(szDstFile, 0600));
494 RTTEST_CHECK_RC (hTest, RTHttpGetFile(hClient, szURL, szDstFile), g_aTests[i].rc);
495 RTTEST_CHECK_RC_OK(hTest, RTFileDelete(szDstFile));
496 break;
497 }
498
499 default:
500 break;
501 }
502 }
503
504 RTTEST_CHECK_RC_OK(hTest, RTHttpDestroy(hClient));
505 }
506
507 /* This is supposed to run unattended, so shutdown automatically. */
508 ASMAtomicXchgBool(&g_fShutdown, true); /* Set shutdown indicator. */
509 }
510 }
511
512 RTTEST_CHECK_RC_OK(hTest, ShClTransferHttpServerDestroy(&HttpSrv));
513 ShClTransferCtxDestroy(&TxCtx);
514
515 /*
516 * Cleanup
517 */
518 char szPath[RTPATH_MAX];
519 for (size_t i = 0; i < RT_ELEMENTS(g_aTests); i++)
520 {
521 RTTEST_CHECK (hTest, RTStrPrintf(szPath, sizeof(szPath), szTempDir));
522 RTTEST_CHECK_RC_OK(hTest, RTPathAppend(szPath, sizeof(szPath), g_aTests[i].pszPath));
523
524 switch (g_aTests[i].fMode & RTFS_TYPE_MASK)
525 {
526 case RTFS_TYPE_FILE:
527 {
528 RTTEST_CHECK_RC_OK(hTest, RTFileDelete(szPath));
529 break;
530 }
531
532 case RTFS_TYPE_DIRECTORY:
533 {
534 RTTEST_CHECK_RC_OK(hTest, RTDirRemove(szPath)); /* ASSUMES empty dir. */
535 break;
536 }
537
538 case RTFS_TYPE_SYMLINK:
539 {
540 RTTEST_CHECK_RC_OK(hTest, RTSymlinkDelete(szPath, 0 /* fDelete */));
541 break;
542 }
543
544 default:
545 break;
546 }
547 }
548 RTTEST_CHECK_RC_OK(hTest, RTDirRemove(szTempDir));
549
550 /*
551 * Summary
552 */
553 return RTTestSummaryAndDestroy(hTest);
554}
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