VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTPath.cpp@ 45389

Last change on this file since 45389 was 45389, checked in by vboxsync, 12 years ago

IPRT: A Study in Paths - Chapter 1: The cross platform parser.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 32.4 KB
Line 
1/* $Id: tstRTPath.cpp 45389 2013-04-07 16:11:30Z vboxsync $ */
2/** @file
3 * IPRT Testcase - Test various path functions.
4 */
5
6/*
7 * Copyright (C) 2006-2011 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#include <iprt/path.h>
31
32#include <iprt/err.h>
33#include <iprt/initterm.h>
34#include <iprt/param.h>
35#include <iprt/process.h>
36#include <iprt/stream.h>
37#include <iprt/string.h>
38#include <iprt/test.h>
39
40
41static void testParser(RTTEST hTest)
42{
43 RTTestSub(hTest, "RTPathParse");
44
45 static struct
46 {
47 uint16_t cComps;
48 uint16_t cchPath;
49 uint16_t offSuffix;
50 const char *pszPath;
51 uint16_t fProps;
52 uint32_t fFlags;
53 } const s_aTests[] =
54 {
55 { 2, 13, 9, "C:/Config.sys", RTPATH_PROP_VOLUME | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX, RTPATHPARSE_FLAGS_STYLE_DOS },
56 { 2, 13, 10, "C://Config.sys", RTPATH_PROP_VOLUME | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX | RTPATH_PROP_EXTRA_SLASHES, RTPATHPARSE_FLAGS_STYLE_DOS },
57 { 2, 12, 8, "C:Config.sys", RTPATH_PROP_VOLUME | RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX, RTPATHPARSE_FLAGS_STYLE_DOS },
58 { 1, 10, 6, "Config.sys", RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX, RTPATHPARSE_FLAGS_STYLE_DOS },
59 { 1, 4, 4, "//./", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE, RTPATHPARSE_FLAGS_STYLE_DOS },
60 { 2, 5, 5, "//./f", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATHPARSE_FLAGS_STYLE_DOS },
61 { 2, 5, 6, "//.//f", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_EXTRA_SLASHES, RTPATHPARSE_FLAGS_STYLE_DOS },
62 { 3, 7, 7, "//././f", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_DOT_REFS, RTPATHPARSE_FLAGS_STYLE_DOS },
63 { 3, 8, 8, "//.././f", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_DOT_REFS, RTPATHPARSE_FLAGS_STYLE_DOS },
64 { 3, 9, 9, "//../../f", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME | RTPATH_PROP_DOTDOT_REFS, RTPATHPARSE_FLAGS_STYLE_DOS },
65 { 1, 1, 1, "/", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE, RTPATHPARSE_FLAGS_STYLE_UNIX },
66 { 2, 4, 4, "/bin", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATHPARSE_FLAGS_STYLE_UNIX },
67 { 2, 4, 5, "/bin/", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_DIR_SLASH, RTPATHPARSE_FLAGS_STYLE_UNIX },
68 { 3, 7, 7, "/bin/ls", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATHPARSE_FLAGS_STYLE_UNIX },
69 { 3, 12, 7, "/etc/rc.conf", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX, RTPATHPARSE_FLAGS_STYLE_UNIX },
70 { 1, 1, 2, "//", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_EXTRA_SLASHES, RTPATHPARSE_FLAGS_STYLE_UNIX },
71 { 1, 1, 3, "///", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_EXTRA_SLASHES, RTPATHPARSE_FLAGS_STYLE_UNIX },
72 { 3, 6, 7, "/.//bin", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_EXTRA_SLASHES | RTPATH_PROP_DOT_REFS | RTPATH_PROP_FILENAME, RTPATHPARSE_FLAGS_STYLE_UNIX },
73 { 1, 3, 3, "bin", RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME, RTPATHPARSE_FLAGS_STYLE_UNIX },
74 { 1, 3, 4, "bin/", RTPATH_PROP_RELATIVE | RTPATH_PROP_DIR_SLASH, RTPATHPARSE_FLAGS_STYLE_UNIX },
75 { 1, 3, 7, "bin////", RTPATH_PROP_RELATIVE | RTPATH_PROP_DIR_SLASH | RTPATH_PROP_EXTRA_SLASHES, RTPATHPARSE_FLAGS_STYLE_UNIX },
76 { 3, 10, 10, "bin/../usr", RTPATH_PROP_RELATIVE | RTPATH_PROP_DOTDOT_REFS | RTPATH_PROP_FILENAME, RTPATHPARSE_FLAGS_STYLE_UNIX },
77 { 4, 11, 11, "/bin/../usr", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_RELATIVE | RTPATH_PROP_DOTDOT_REFS | RTPATH_PROP_FILENAME, RTPATHPARSE_FLAGS_STYLE_UNIX },
78 { 4, 8, 8, "/a/.../u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATHPARSE_FLAGS_STYLE_UNIX },
79 { 4, 8, 8, "/a/.b./u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATHPARSE_FLAGS_STYLE_UNIX },
80 { 4, 8, 8, "/a/..c/u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATHPARSE_FLAGS_STYLE_UNIX },
81 { 4, 8, 8, "/a/d../u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATHPARSE_FLAGS_STYLE_UNIX },
82 { 4, 8, 8, "/a/.e/.u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATHPARSE_FLAGS_STYLE_UNIX },
83 { 4, 8, 8, "/a/.f/.u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATHPARSE_FLAGS_STYLE_UNIX },
84 { 4, 8, 8, "/a/.g/u.", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATHPARSE_FLAGS_STYLE_UNIX },
85 { 3, 9, 10, "/a/h/u.ext", RTPATH_PROP_EXTRA_SLASHES | RTPATH_PROP_RELATIVE, RTPATHPARSE_FLAGS_STYLE_UNIX | RTPATHPARSE_FLAGS_MIDDLE },
86 { 3, 9, 9, "a/h/u.ext", RTPATH_PROP_RELATIVE, RTPATHPARSE_FLAGS_STYLE_UNIX | RTPATHPARSE_FLAGS_MIDDLE },
87 { 3, 9, 10, "a/h/u.ext/", RTPATH_PROP_EXTRA_SLASHES | RTPATH_PROP_RELATIVE, RTPATHPARSE_FLAGS_STYLE_UNIX | RTPATHPARSE_FLAGS_MIDDLE },
88 };
89
90 union
91 {
92 RTPATHPARSED Parsed;
93 uint8_t ab[4096];
94 } u;
95
96 for (uint32_t i = 0; i < RT_ELEMENTS(s_aTests); i++)
97 {
98 int rc = RTPathParse(s_aTests[i].pszPath, &u.Parsed, sizeof(u), s_aTests[i].fFlags);
99 if ( rc != VINF_SUCCESS
100 || s_aTests[i].cComps != u.Parsed.cComps
101 || s_aTests[i].fProps != u.Parsed.fProps
102 || s_aTests[i].offSuffix != u.Parsed.offSuffix
103 || s_aTests[i].cchPath != u.Parsed.cchPath)
104 {
105 RTTestFailed(hTest, "i=%d rc=%Rrc %s", i, rc, s_aTests[i].pszPath);
106 RTTestFailureDetails(hTest,
107 " cComps %u, got %u\n"
108 " fProps %#x, got %#x, xor=>%#x\n"
109 " offSuffix %u, got %u\n"
110 " cchPath %u, got %u\n"
111 ,
112 s_aTests[i].cComps, u.Parsed.cComps,
113 s_aTests[i].fProps, u.Parsed.fProps, s_aTests[i].fProps ^ u.Parsed.fProps,
114 s_aTests[i].offSuffix, u.Parsed.offSuffix,
115 s_aTests[i].cchPath, u.Parsed.cchPath);
116 }
117 }
118}
119
120
121int main()
122{
123 char szPath[RTPATH_MAX];
124
125 /*
126 * Init RT+Test.
127 */
128 RTTEST hTest;
129 int rc = RTTestInitAndCreate("tstRTPath", &hTest);
130 if (rc)
131 return rc;
132 RTTestBanner(hTest);
133
134 /*
135 * RTPathExecDir, RTPathUserHome and RTProcGetExecutablePath.
136 */
137 RTTestSub(hTest, "RTPathExecDir");
138 RTTESTI_CHECK_RC(rc = RTPathExecDir(szPath, sizeof(szPath)), VINF_SUCCESS);
139 if (RT_SUCCESS(rc))
140 RTTestIPrintf(RTTESTLVL_INFO, "ExecDir={%s}\n", szPath);
141
142 RTTestSub(hTest, "RTProcGetExecutablePath");
143 if (RTProcGetExecutablePath(szPath, sizeof(szPath)) == szPath)
144 RTTestIPrintf(RTTESTLVL_INFO, "ExecutableName={%s}\n", szPath);
145 else
146 RTTestIFailed("RTProcGetExecutablePath -> NULL");
147
148 RTTestSub(hTest, "RTPathUserHome");
149 RTTESTI_CHECK_RC(rc = RTPathUserHome(szPath, sizeof(szPath)), VINF_SUCCESS);
150 if (RT_SUCCESS(rc))
151 RTTestIPrintf(RTTESTLVL_INFO, "UserHome={%s}\n", szPath);
152
153 RTTestSub(hTest, "RTPathUserDocuments");
154 RTTESTI_CHECK_RC(rc = RTPathUserDocuments(szPath, sizeof(szPath)), VINF_SUCCESS);
155 if (RT_SUCCESS(rc))
156 RTTestIPrintf(RTTESTLVL_INFO, "UserDocuments={%s}\n", szPath);
157
158 RTTestSub(hTest, "RTPathTemp");
159 RTTESTI_CHECK_RC(rc = RTPathTemp(szPath, sizeof(szPath)), VINF_SUCCESS);
160 if (RT_SUCCESS(rc))
161 RTTestIPrintf(RTTESTLVL_INFO, "PathTemp={%s}\n", szPath);
162 size_t cch = strlen(szPath);
163 RTTESTI_CHECK_RC(RTPathTemp(szPath, cch), VERR_BUFFER_OVERFLOW);
164 RTTESTI_CHECK_RC(RTPathTemp(szPath, cch+1), VINF_SUCCESS);
165 RTTESTI_CHECK_RC(RTPathTemp(szPath, cch+2), VINF_SUCCESS);
166
167
168 /*
169 * RTPathAbsEx
170 */
171 RTTestSub(hTest, "RTPathAbsEx");
172 static const struct
173 {
174 const char *pcszInputBase;
175 const char *pcszInputPath;
176 int rc;
177 const char *pcszOutput;
178 }
179 s_aRTPathAbsExTests[] =
180 {
181#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
182 { NULL, "", VERR_INVALID_PARAMETER, NULL },
183 { NULL, ".", VINF_SUCCESS, "%p" },
184 { NULL, "\\", VINF_SUCCESS, "%d\\" },
185 { NULL, "\\..", VINF_SUCCESS, "%d\\" },
186 { NULL, "/absolute/..", VINF_SUCCESS, "%d\\" },
187 { NULL, "/absolute\\\\../..", VINF_SUCCESS, "%d\\" },
188 { NULL, "/absolute//../path\\", VINF_SUCCESS, "%d\\path" },
189 { NULL, "/absolute/../../path", VINF_SUCCESS, "%d\\path" },
190 { NULL, "relative/../dir\\.\\.\\.\\file.txt", VINF_SUCCESS, "%p\\dir\\file.txt" },
191 { NULL, "\\data\\", VINF_SUCCESS, "%d\\data" },
192 { "relative_base/dir\\", "\\from_root", VINF_SUCCESS, "%d\\from_root" },
193 { "relative_base/dir/", "relative_also", VINF_SUCCESS, "%p\\relative_base\\dir\\relative_also" },
194#else
195 { NULL, "", VERR_INVALID_PARAMETER, NULL },
196 { NULL, ".", VINF_SUCCESS, "%p" },
197 { NULL, "/", VINF_SUCCESS, "/" },
198 { NULL, "/..", VINF_SUCCESS, "/" },
199 { NULL, "/absolute/..", VINF_SUCCESS, "/" },
200 { NULL, "/absolute\\\\../..", VINF_SUCCESS, "/" },
201 { NULL, "/absolute//../path/", VINF_SUCCESS, "/path" },
202 { NULL, "/absolute/../../path", VINF_SUCCESS, "/path" },
203 { NULL, "relative/../dir/./././file.txt", VINF_SUCCESS, "%p/dir/file.txt" },
204 { NULL, "relative/../dir\\.\\.\\.\\file.txt", VINF_SUCCESS, "%p/dir\\.\\.\\.\\file.txt" }, /* linux-specific */
205 { NULL, "/data/", VINF_SUCCESS, "/data" },
206 { "relative_base/dir/", "/from_root", VINF_SUCCESS, "/from_root" },
207 { "relative_base/dir/", "relative_also", VINF_SUCCESS, "%p/relative_base/dir/relative_also" },
208#endif
209#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
210 { NULL, "C:\\", VINF_SUCCESS, "C:\\" },
211 { "C:\\", "..", VINF_SUCCESS, "C:\\" },
212 { "C:\\temp", "..", VINF_SUCCESS, "C:\\" },
213 { "C:\\VirtualBox/Machines", "..\\VirtualBox.xml", VINF_SUCCESS, "C:\\VirtualBox\\VirtualBox.xml" },
214 { "C:\\MustDie", "\\from_root/dir/..", VINF_SUCCESS, "C:\\from_root" },
215 { "C:\\temp", "D:\\data", VINF_SUCCESS, "D:\\data" },
216 { NULL, "\\\\server\\..\\share", VINF_SUCCESS, "\\\\server\\..\\share" /* kind of strange */ },
217 { NULL, "\\\\server/", VINF_SUCCESS, "\\\\server" },
218 { NULL, "\\\\", VINF_SUCCESS, "\\\\" },
219 { NULL, "\\\\\\something", VINF_SUCCESS, "\\\\\\something" /* kind of strange */ },
220 { "\\\\server\\share_as_base", "/from_root", VINF_SUCCESS, "\\\\server\\from_root" },
221 { "\\\\just_server", "/from_root", VINF_SUCCESS, "\\\\just_server\\from_root" },
222 { "\\\\server\\share_as_base", "relative\\data", VINF_SUCCESS, "\\\\server\\share_as_base\\relative\\data" },
223 { "base", "\\\\?\\UNC\\relative/edwef/..", VINF_SUCCESS, "\\\\?\\UNC\\relative" },
224 { "\\\\?\\UNC\\base", "/from_root", VERR_INVALID_NAME, NULL },
225#else
226 { "/temp", "..", VINF_SUCCESS, "/" },
227 { "/VirtualBox/Machines", "../VirtualBox.xml", VINF_SUCCESS, "/VirtualBox/VirtualBox.xml" },
228 { "/MustDie", "/from_root/dir/..", VINF_SUCCESS, "/from_root" },
229 { "\\temp", "\\data", VINF_SUCCESS, "%p/\\temp/\\data" },
230#endif
231 };
232
233 for (unsigned i = 0; i < RT_ELEMENTS(s_aRTPathAbsExTests); ++ i)
234 {
235 rc = RTPathAbsEx(s_aRTPathAbsExTests[i].pcszInputBase,
236 s_aRTPathAbsExTests[i].pcszInputPath,
237 szPath, sizeof(szPath));
238 if (rc != s_aRTPathAbsExTests[i].rc)
239 {
240 RTTestIFailed("unexpected result code!\n"
241 " input base: '%s'\n"
242 " input path: '%s'\n"
243 " output: '%s'\n"
244 " rc: %Rrc\n"
245 " expected rc: %Rrc",
246 s_aRTPathAbsExTests[i].pcszInputBase,
247 s_aRTPathAbsExTests[i].pcszInputPath,
248 szPath, rc,
249 s_aRTPathAbsExTests[i].rc);
250 continue;
251 }
252
253 char szTmp[RTPATH_MAX];
254 char *pszExpected = NULL;
255 if (s_aRTPathAbsExTests[i].pcszOutput != NULL)
256 {
257 if (s_aRTPathAbsExTests[i].pcszOutput[0] == '%')
258 {
259 RTTESTI_CHECK_RC(rc = RTPathGetCurrent(szTmp, sizeof(szTmp)), VINF_SUCCESS);
260 if (RT_FAILURE(rc))
261 break;
262
263 pszExpected = szTmp;
264
265 if (s_aRTPathAbsExTests[i].pcszOutput[1] == 'p')
266 {
267 cch = strlen(szTmp);
268 if (cch + strlen(s_aRTPathAbsExTests[i].pcszOutput) - 2 <= sizeof(szTmp))
269 strcpy(szTmp + cch, s_aRTPathAbsExTests[i].pcszOutput + 2);
270 }
271#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
272 else if (s_aRTPathAbsExTests[i].pcszOutput[1] == 'd')
273 {
274 if (2 + strlen(s_aRTPathAbsExTests[i].pcszOutput) - 2 <= sizeof(szTmp))
275 strcpy(szTmp + 2, s_aRTPathAbsExTests[i].pcszOutput + 2);
276 }
277#endif
278 }
279 else
280 {
281 strcpy(szTmp, s_aRTPathAbsExTests[i].pcszOutput);
282 pszExpected = szTmp;
283 }
284
285 if (strcmp(szPath, pszExpected))
286 {
287 RTTestIFailed("Unexpected result\n"
288 " input base: '%s'\n"
289 " input path: '%s'\n"
290 " output: '%s'\n"
291 " expected: '%s'",
292 s_aRTPathAbsExTests[i].pcszInputBase,
293 s_aRTPathAbsExTests[i].pcszInputPath,
294 szPath,
295 s_aRTPathAbsExTests[i].pcszOutput);
296 }
297 }
298 }
299
300 /*
301 * RTPathStripFilename
302 */
303 RTTestSub(hTest, "RTPathStripFilename");
304 static const char *s_apszStripFilenameTests[] =
305 {
306 "/usr/include///", "/usr/include//",
307 "/usr/include/", "/usr/include",
308 "/usr/include", "/usr",
309 "/usr", "/",
310 "usr", ".",
311#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
312 "c:/windows", "c:/",
313 "c:/", "c:/",
314 "D:", "D:",
315 "C:\\OS2\\DLLS", "C:\\OS2",
316#endif
317 };
318 for (unsigned i = 0; i < RT_ELEMENTS(s_apszStripFilenameTests); i += 2)
319 {
320 const char *pszInput = s_apszStripFilenameTests[i];
321 const char *pszExpect = s_apszStripFilenameTests[i + 1];
322 strcpy(szPath, pszInput);
323 RTPathStripFilename(szPath);
324 if (strcmp(szPath, pszExpect))
325 {
326 RTTestIFailed("Unexpected result\n"
327 " input: '%s'\n"
328 " output: '%s'\n"
329 "expected: '%s'",
330 pszInput, szPath, pszExpect);
331 }
332 }
333
334 /*
335 * RTPathAppend.
336 */
337 RTTestSub(hTest, "RTPathAppend");
338 static const char *s_apszAppendTests[] =
339 {
340 /* base append result */
341 "/", "", "/",
342 "", "/", "/",
343 "/", "/", "/",
344 "/x", "", "/x",
345 "/x", "/", "/x/",
346 "/", "x", "/x",
347 "dir", "file", "dir/file",
348 "dir", "/file", "dir/file",
349 "dir", "//file", "dir/file",
350 "dir", "///file", "dir/file",
351 "dir/", "/file", "dir/file",
352 "dir/", "//file", "dir/file",
353 "dir/", "///file", "dir/file",
354 "dir//", "file", "dir/file",
355 "dir//", "/file", "dir/file",
356 "dir//", "//file", "dir/file",
357 "dir///", "///file", "dir/file",
358 "/bin/testcase", "foo.r0", "/bin/testcase/foo.r0",
359#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
360 "/", "\\", "/",
361 "\\", "/", "\\",
362 "\\\\srv\\shr", "dir//", "\\\\srv\\shr/dir//",
363 "\\\\srv\\shr", "dir//file", "\\\\srv\\shr/dir//file",
364 "\\\\srv\\shr", "//dir//", "\\\\srv\\shr/dir//",
365 "\\\\srv\\shr", "/\\dir//", "\\\\srv\\shr\\dir//",
366 "\\\\", "not-srv/not-shr/file", "\\not-srv/not-shr/file",
367 "C:", "autoexec.bat", "C:autoexec.bat",
368 "C:", "/autoexec.bat", "C:/autoexec.bat",
369 "C:", "\\autoexec.bat", "C:\\autoexec.bat",
370 "C:\\", "/autoexec.bat", "C:\\autoexec.bat",
371 "C:\\\\", "autoexec.bat", "C:\\autoexec.bat",
372 "E:\\bin\\testcase", "foo.r0", "E:\\bin\\testcase/foo.r0",
373#endif
374 };
375 for (unsigned i = 0; i < RT_ELEMENTS(s_apszAppendTests); i += 3)
376 {
377 const char *pszInput = s_apszAppendTests[i];
378 const char *pszAppend = s_apszAppendTests[i + 1];
379 const char *pszExpect = s_apszAppendTests[i + 2];
380 strcpy(szPath, pszInput);
381 RTTESTI_CHECK_RC(rc = RTPathAppend(szPath, sizeof(szPath), pszAppend), VINF_SUCCESS);
382 if (RT_FAILURE(rc))
383 continue;
384 if (strcmp(szPath, pszExpect))
385 {
386 RTTestIFailed("Unexpected result\n"
387 " input: '%s'\n"
388 " append: '%s'\n"
389 " output: '%s'\n"
390 "expected: '%s'",
391 pszInput, pszAppend, szPath, pszExpect);
392 }
393 else
394 {
395 size_t const cchResult = strlen(szPath);
396
397 strcpy(szPath, pszInput);
398 RTTESTI_CHECK_RC(rc = RTPathAppend(szPath, cchResult + 2, pszAppend), VINF_SUCCESS);
399 RTTESTI_CHECK(RT_FAILURE(rc) || !strcmp(szPath, pszExpect));
400
401 strcpy(szPath, pszInput);
402 RTTESTI_CHECK_RC(rc = RTPathAppend(szPath, cchResult + 1, pszAppend), VINF_SUCCESS);
403 RTTESTI_CHECK(RT_FAILURE(rc) || !strcmp(szPath, pszExpect));
404
405 if (strlen(pszInput) < cchResult)
406 {
407 strcpy(szPath, pszInput);
408 RTTESTI_CHECK_RC(RTPathAppend(szPath, cchResult, pszAppend), VERR_BUFFER_OVERFLOW);
409 }
410 }
411 }
412
413 /*
414 * RTPathJoin - reuse the append tests.
415 */
416 RTTestSub(hTest, "RTPathJoin");
417 for (unsigned i = 0; i < RT_ELEMENTS(s_apszAppendTests); i += 3)
418 {
419 const char *pszInput = s_apszAppendTests[i];
420 const char *pszAppend = s_apszAppendTests[i + 1];
421 const char *pszExpect = s_apszAppendTests[i + 2];
422
423 memset(szPath, 'a', sizeof(szPath)); szPath[sizeof(szPath) - 1] = '\0';
424
425 RTTESTI_CHECK_RC(rc = RTPathJoin(szPath, sizeof(szPath), pszInput, pszAppend), VINF_SUCCESS);
426 if (RT_FAILURE(rc))
427 continue;
428 if (strcmp(szPath, pszExpect))
429 {
430 RTTestIFailed("Unexpected result\n"
431 " input: '%s'\n"
432 " append: '%s'\n"
433 " output: '%s'\n"
434 "expected: '%s'",
435 pszInput, pszAppend, szPath, pszExpect);
436 }
437 else
438 {
439 size_t const cchResult = strlen(szPath);
440
441 memset(szPath, 'a', sizeof(szPath)); szPath[sizeof(szPath) - 1] = '\0';
442 RTTESTI_CHECK_RC(rc = RTPathJoin(szPath, cchResult + 2, pszInput, pszAppend), VINF_SUCCESS);
443 RTTESTI_CHECK(RT_FAILURE(rc) || !strcmp(szPath, pszExpect));
444
445 memset(szPath, 'a', sizeof(szPath)); szPath[sizeof(szPath) - 1] = '\0';
446 RTTESTI_CHECK_RC(rc = RTPathJoin(szPath, cchResult + 1, pszInput, pszAppend), VINF_SUCCESS);
447 RTTESTI_CHECK(RT_FAILURE(rc) || !strcmp(szPath, pszExpect));
448
449 RTTESTI_CHECK_RC(rc = RTPathJoin(szPath, cchResult, pszInput, pszAppend), VERR_BUFFER_OVERFLOW);
450 }
451 }
452
453 /*
454 * RTPathJoinA - reuse the append tests.
455 */
456 RTTestSub(hTest, "RTPathJoinA");
457 for (unsigned i = 0; i < RT_ELEMENTS(s_apszAppendTests); i += 3)
458 {
459 const char *pszInput = s_apszAppendTests[i];
460 const char *pszAppend = s_apszAppendTests[i + 1];
461 const char *pszExpect = s_apszAppendTests[i + 2];
462
463 char *pszPathDst;
464 RTTESTI_CHECK(pszPathDst = RTPathJoinA(pszInput, pszAppend));
465 if (!pszPathDst)
466 continue;
467 if (strcmp(pszPathDst, pszExpect))
468 {
469 RTTestIFailed("Unexpected result\n"
470 " input: '%s'\n"
471 " append: '%s'\n"
472 " output: '%s'\n"
473 "expected: '%s'",
474 pszInput, pszAppend, pszPathDst, pszExpect);
475 }
476 RTStrFree(pszPathDst);
477 }
478
479 /*
480 * RTPathStripTrailingSlash
481 */
482 static const char *s_apszStripTrailingSlash[] =
483 {
484 /* input result */
485 "/", "/",
486 "//", "/",
487 "////////////////////", "/",
488 "/tmp", "/tmp",
489 "/tmp////////////////", "/tmp",
490 "tmp", "tmp",
491 "tmp////////////////", "tmp",
492 "./", ".",
493#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
494 "////////////////////", "/",
495 "D:", "D:",
496 "D:/", "D:/",
497 "D:\\", "D:\\",
498 "D:\\/\\", "D:\\",
499 "D:/\\/\\", "D:/",
500 "C:/Temp", "D:/Temp",
501 "C:/Temp/", "D:/Temp/",
502 "C:/Temp\\/", "D:/Temp",
503#endif
504 };
505 for (unsigned i = 0; i < RT_ELEMENTS(s_apszStripTrailingSlash); i += 2)
506 {
507 const char *pszInput = s_apszStripTrailingSlash[i];
508 const char *pszExpect = s_apszStripTrailingSlash[i + 1];
509
510 strcpy(szPath, pszInput);
511 cch = RTPathStripTrailingSlash(szPath);
512 if (strcmp(szPath, pszExpect))
513 RTTestIFailed("Unexpected result\n"
514 " input: '%s'\n"
515 " output: '%s'\n"
516 "expected: '%s'",
517 pszInput, szPath, pszExpect);
518 else
519 RTTESTI_CHECK(cch == strlen(szPath));
520 }
521
522 /*
523 * RTPathCountComponents
524 */
525 RTTestSub(hTest, "RTPathCountComponents");
526 RTTESTI_CHECK(RTPathCountComponents("") == 0);
527 RTTESTI_CHECK(RTPathCountComponents("/") == 1);
528 RTTESTI_CHECK(RTPathCountComponents("//") == 1);
529 RTTESTI_CHECK(RTPathCountComponents("//////////////") == 1);
530 RTTESTI_CHECK(RTPathCountComponents("//////////////bin") == 2);
531 RTTESTI_CHECK(RTPathCountComponents("//////////////bin/") == 2);
532 RTTESTI_CHECK(RTPathCountComponents("//////////////bin/////") == 2);
533 RTTESTI_CHECK(RTPathCountComponents("..") == 1);
534 RTTESTI_CHECK(RTPathCountComponents("../") == 1);
535 RTTESTI_CHECK(RTPathCountComponents("../..") == 2);
536 RTTESTI_CHECK(RTPathCountComponents("../../") == 2);
537#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
538 RTTESTI_CHECK(RTPathCountComponents("d:") == 1);
539 RTTESTI_CHECK(RTPathCountComponents("d:/") == 1);
540 RTTESTI_CHECK(RTPathCountComponents("d:/\\") == 1);
541 RTTESTI_CHECK(RTPathCountComponents("d:\\") == 1);
542 RTTESTI_CHECK(RTPathCountComponents("c:\\config.sys") == 2);
543 RTTESTI_CHECK(RTPathCountComponents("c:\\windows") == 2);
544 RTTESTI_CHECK(RTPathCountComponents("c:\\windows\\") == 2);
545 RTTESTI_CHECK(RTPathCountComponents("c:\\windows\\system32") == 3);
546 RTTESTI_CHECK(RTPathCountComponents("//./C$") == 1);
547 RTTESTI_CHECK(RTPathCountComponents("\\\\.\\C$") == 1);
548 RTTESTI_CHECK(RTPathCountComponents("/\\.\\C$") == 1);
549 RTTESTI_CHECK(RTPathCountComponents("//myserver") == 1);
550 RTTESTI_CHECK(RTPathCountComponents("//myserver/") == 1);
551 RTTESTI_CHECK(RTPathCountComponents("//myserver/share") == 1);
552 RTTESTI_CHECK(RTPathCountComponents("//myserver/share/") == 1);
553 RTTESTI_CHECK(RTPathCountComponents("//myserver/share\\") == 1);
554 RTTESTI_CHECK(RTPathCountComponents("//myserver/share\\x") == 2);
555 RTTESTI_CHECK(RTPathCountComponents("//myserver/share\\x\\y") == 3);
556 RTTESTI_CHECK(RTPathCountComponents("//myserver/share\\x\\y\\") == 3);
557#endif
558
559 /*
560 * RTPathCopyComponents
561 */
562 struct
563 {
564 const char *pszSrc;
565 size_t cComponents;
566 const char *pszResult;
567 } s_aCopyComponents[] =
568 {
569 { "", 0, "" },
570 { "", 5, "" },
571 { "/", 0, "" },
572 { "/", 1, "/" },
573 { "/", 2, "/" },
574 { "/usr/bin/sed", 0, "" },
575 { "/usr/bin/sed", 1, "/" },
576 { "/usr/bin/sed", 2, "/usr/" },
577 { "/usr/bin/sed", 3, "/usr/bin/" },
578 { "/usr/bin/sed", 4, "/usr/bin/sed" },
579 { "/usr/bin/sed", 5, "/usr/bin/sed" },
580 { "/usr/bin/sed", 6, "/usr/bin/sed" },
581 { "/usr///bin/sed", 2, "/usr///" },
582 };
583 for (unsigned i = 0; i < RT_ELEMENTS(s_aCopyComponents); i++)
584 {
585 const char *pszInput = s_aCopyComponents[i].pszSrc;
586 size_t cComponents = s_aCopyComponents[i].cComponents;
587 const char *pszResult = s_aCopyComponents[i].pszResult;
588
589 memset(szPath, 'a', sizeof(szPath));
590 rc = RTPathCopyComponents(szPath, sizeof(szPath), pszInput, cComponents);
591 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
592 if (RT_SUCCESS(rc) && strcmp(szPath, pszResult))
593 RTTestIFailed("Unexpected result\n"
594 " input: '%s' cComponents=%u\n"
595 " output: '%s'\n"
596 "expected: '%s'",
597 pszInput, cComponents, szPath, pszResult);
598 else if (RT_SUCCESS(rc))
599 {
600 RTTESTI_CHECK_RC(RTPathCopyComponents(szPath, strlen(pszResult) + 1, pszInput, cComponents), VINF_SUCCESS);
601 RTTESTI_CHECK_RC(RTPathCopyComponents(szPath, strlen(pszResult), pszInput, cComponents), VERR_BUFFER_OVERFLOW);
602 }
603 }
604
605
606 /*
607 * RTPathStripExt
608 */
609 RTTestSub(hTest, "RTPathStripExt");
610 struct
611 {
612 const char *pszSrc;
613 const char *pszResult;
614 } s_aStripExt[] =
615 {
616 { "filename.ext", "filename" },
617 { "filename.ext1.ext2.ext3", "filename.ext1.ext2" },
618 { "filename..ext", "filename." },
619 { "filename.ext.", "filename.ext" }, /** @todo This is a bit weird/wrong, but not half as weird as the way Windows+OS/2 deals with a trailing dots. */
620 };
621 for (unsigned i = 0; i < RT_ELEMENTS(s_aStripExt); i++)
622 {
623 const char *pszInput = s_aStripExt[i].pszSrc;
624 const char *pszResult = s_aStripExt[i].pszResult;
625
626 strcpy(szPath, pszInput);
627 RTPathStripExt(szPath);
628 if (strcmp(szPath, pszResult))
629 RTTestIFailed("Unexpected result\n"
630 " input: '%s'\n"
631 " output: '%s'\n"
632 "expected: '%s'",
633 pszInput, szPath, pszResult);
634 }
635
636 /*
637 * RTPathCalcRelative
638 */
639 RTTestSub(hTest, "RTPathCalcRelative");
640 struct
641 {
642 const char *pszFrom;
643 const char *pszTo;
644 int rc;
645 const char *pszExpected;
646 } s_aRelPath[] =
647 {
648 { "/home/test.ext", "/home/test2.ext", VINF_SUCCESS, "test2.ext"},
649 { "/dir/test.ext", "/dir/dir2/test2.ext", VINF_SUCCESS, "dir2/test2.ext"},
650 { "/dir/dir2/test.ext", "/dir/test2.ext", VINF_SUCCESS, "../test2.ext"},
651 { "/dir/dir2/test.ext", "/dir/dir3/test2.ext", VINF_SUCCESS, "../dir3/test2.ext"},
652#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
653 { "\\\\server\\share\\test.ext", "\\\\server\\share2\\test2.ext", VERR_NOT_SUPPORTED, ""},
654 { "c:\\dir\\test.ext", "f:\\dir\\test.ext", VERR_NOT_SUPPORTED, ""}
655#endif
656 };
657 for (unsigned i = 0; i < RT_ELEMENTS(s_aRelPath); i++)
658 {
659 const char *pszFrom = s_aRelPath[i].pszFrom;
660 const char *pszTo = s_aRelPath[i].pszTo;
661
662 rc = RTPathCalcRelative(szPath, sizeof(szPath), pszFrom, pszTo);
663 if (rc != s_aRelPath[i].rc)
664 RTTestIFailed("Unexpected return code\n"
665 " got: %Rrc\n"
666 "expected: %Rrc",
667 rc, s_aRelPath[i].rc);
668 else if ( RT_SUCCESS(rc)
669 && strcmp(szPath, s_aRelPath[i].pszExpected))
670 RTTestIFailed("Unexpected result\n"
671 " from: '%s'\n"
672 " to: '%s'\n"
673 " output: '%s'\n"
674 "expected: '%s'",
675 pszFrom, pszTo, szPath, s_aRelPath[i].pszExpected);
676 }
677
678 testParser(hTest);
679
680 /*
681 * Summary.
682 */
683 return RTTestSummaryAndDestroy(hTest);
684}
685
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette