diff options
Diffstat (limited to 'src/VBox/Runtime/testcase/tstRTUri.cpp')
-rw-r--r-- | src/VBox/Runtime/testcase/tstRTUri.cpp | 900 |
1 files changed, 900 insertions, 0 deletions
diff --git a/src/VBox/Runtime/testcase/tstRTUri.cpp b/src/VBox/Runtime/testcase/tstRTUri.cpp new file mode 100644 index 00000000..5e6e3632 --- /dev/null +++ b/src/VBox/Runtime/testcase/tstRTUri.cpp @@ -0,0 +1,900 @@ +/* $Id: tstRTUri.cpp $ */ +/** @file + * IPRT Testcase - URI parsing and creation. + */ + +/* + * Copyright (C) 2011-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <iprt/uri.h> + +#include <iprt/string.h> +#include <iprt/err.h> +#include <iprt/mem.h> +#include <iprt/path.h> +#include <iprt/test.h> + +#if 0 && defined(RT_OS_WINDOWS) /* Enable for windows API reference results. */ +# define TSTRTURI_WITH_WINDOWS_REFERENCE_RESULTS +# include <iprt/win/shlwapi.h> +# include <iprt/stream.h> +#endif + + +/********************************************************************************************************************************* +* Test data * +*********************************************************************************************************************************/ + +static struct +{ + const char *pszUri; + const char *pszScheme; + const char *pszAuthority; + const char *pszPath; + const char *pszQuery; + const char *pszFragment; + + const char *pszUsername; + const char *pszPassword; + const char *pszHost; + uint32_t uPort; + + const char *pszCreated; +} g_aTests[] = +{ + { /* #0 */ + "foo://tt:yt@example.com:8042/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there?name=%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60ferret#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60", + /*.pszScheme =*/ "foo", + /*.pszAuthority =*/ "tt:yt@example.com:8042", + /*.pszPath =*/ "/over/ <>#%\"{}|^[]`/there", + /*.pszQuery =*/ "name= <>#%\"{}|^[]`ferret", + /*.pszFragment =*/ "nose <>#%\"{}|^[]`", + /*.pszUsername =*/ "tt", + /*.pszPassword =*/ "yt", + /*.pszHost =*/ "example.com", + /*.uPort =*/ 8042, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #1 */ + "foo://tt:yt@example.com:8042/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there?name=%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60ferret", + /*.pszScheme =*/ "foo", + /*.pszAuthority =*/ "tt:yt@example.com:8042", + /*.pszPath =*/ "/over/ <>#%\"{}|^[]`/there", + /*.pszQuery =*/ "name= <>#%\"{}|^[]`ferret", + /*.pszFragment =*/ NULL, + /*.pszUsername =*/ "tt", + /*.pszPassword =*/ "yt", + /*.pszHost =*/ "example.com", + /*.uPort =*/ 8042, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #2 */ + "foo://tt:yt@example.com:8042/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there", + /*.pszScheme =*/ "foo", + /*.pszAuthority =*/ "tt:yt@example.com:8042", + /*.pszPath =*/ "/over/ <>#%\"{}|^[]`/there", + /*.pszQuery =*/ NULL, + /*.pszFragment =*/ NULL, + /*.pszUsername =*/ "tt", + /*.pszPassword =*/ "yt", + /*.pszHost =*/ "example.com", + /*.uPort =*/ 8042, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #3 */ + "foo:tt@example.com", + /*.pszScheme =*/ "foo", + /*.pszAuthority =*/ NULL, + /*.pszPath =*/ "tt@example.com", + /*.pszQuery =*/ NULL, + /*.pszFragment =*/ NULL, + /*.pszUsername =*/ NULL, + /*.pszPassword =*/ NULL, + /*.pszHost =*/ NULL, + /*.uPort =*/ UINT32_MAX, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #4 */ + "foo:/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there?name=%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60ferret#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60", + /*.pszScheme =*/ "foo", + /*.pszAuthority =*/ NULL, + /*.pszPath =*/ "/over/ <>#%\"{}|^[]`/there", + /*.pszQuery =*/ "name= <>#%\"{}|^[]`ferret", + /*.pszFragment =*/ "nose <>#%\"{}|^[]`", + /*.pszUsername =*/ NULL, + /*.pszPassword =*/ NULL, + /*.pszHost =*/ NULL, + /*.uPort =*/ UINT32_MAX, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #5 */ + "foo:/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60", + /*.pszScheme =*/ "foo", + /*.pszAuthority =*/ NULL, + /*.pszPath =*/ "/over/ <>#%\"{}|^[]`/there", + /*.pszQuery =*/ NULL, + /*.pszFragment =*/ "nose <>#%\"{}|^[]`", + /*.pszUsername =*/ NULL, + /*.pszPassword =*/ NULL, + /*.pszHost =*/ NULL, + /*.uPort =*/ UINT32_MAX, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #6 */ + "urn:example:animal:ferret:nose", + /*.pszScheme =*/ "urn", + /*.pszAuthority =*/ NULL, + /*.pszPath =*/ "example:animal:ferret:nose", + /*.pszQuery =*/ NULL, + /*.pszFragment =*/ NULL, + /*.pszUsername =*/ NULL, + /*.pszPassword =*/ NULL, + /*.pszHost =*/ NULL, + /*.uPort =*/ UINT32_MAX, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #7 */ + "foo:?name=%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60ferret#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60", + /*.pszScheme =*/ "foo", + /*.pszAuthority =*/ NULL, + /*.pszPath =*/ NULL, + /*.pszQuery =*/ "name= <>#%\"{}|^[]`ferret", + /*.pszFragment =*/ "nose <>#%\"{}|^[]`", + /*.pszUsername =*/ NULL, + /*.pszPassword =*/ NULL, + /*.pszHost =*/ NULL, + /*.uPort =*/ UINT32_MAX, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #8 */ + "foo:#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60", + /*.pszScheme =*/ "foo", + /*.pszAuthority =*/ NULL, + /*.pszPath =*/ NULL, + /*.pszQuery =*/ NULL, + /*.pszFragment =*/ "nose <>#%\"{}|^[]`", + /*.pszUsername =*/ NULL, + /*.pszPassword =*/ NULL, + /*.pszHost =*/ NULL, + /*.uPort =*/ UINT32_MAX, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #9 */ + "foo://tt:yt@example.com:8042/?name=%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60ferret#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60", + /*.pszScheme =*/ "foo", + /*.pszAuthority =*/ "tt:yt@example.com:8042", + /*.pszPath =*/ "/", + /*.pszQuery =*/ "name= <>#%\"{}|^[]`ferret", + /*.pszFragment =*/ "nose <>#%\"{}|^[]`", + /*.pszUsername =*/ "tt", + /*.pszPassword =*/ "yt", + /*.pszHost =*/ "example.com", + /*.uPort =*/ 8042, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #10 */ + "foo://tt:yt@example.com:8042/", + /*.pszScheme =*/ "foo", + /*.pszAuthority =*/ "tt:yt@example.com:8042", + /*.pszPath =*/ "/", + /*.pszQuery =*/ NULL, + /*.pszFragment =*/ NULL, + /*.pszUsername =*/ "tt", + /*.pszPassword =*/ "yt", + /*.pszHost =*/ "example.com", + /*.uPort =*/ 8042, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #11 */ + "foo://tt:yt@example.com:8042?name=%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60ferret#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60", + /*.pszScheme =*/ "foo", + /*.pszAuthority =*/ "tt:yt@example.com:8042", + /*.pszPath =*/ NULL, + /*.pszQuery =*/ "name= <>#%\"{}|^[]`ferret", + /*.pszFragment =*/ "nose <>#%\"{}|^[]`", + /*.pszUsername =*/ "tt", + /*.pszPassword =*/ "yt", + /*.pszHost =*/ "example.com", + /*.uPort =*/ 8042, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #12 */ + "foo://tt:yt@example.com:8042#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60", + /*.pszScheme =*/ "foo", + /*.pszAuthority =*/ "tt:yt@example.com:8042", + /*.pszPath =*/ NULL, + /*.pszQuery =*/ NULL, + /*.pszFragment =*/ "nose <>#%\"{}|^[]`", + /*.pszUsername =*/ "tt", + /*.pszPassword =*/ "yt", + /*.pszHost =*/ "example.com", + /*.uPort =*/ 8042, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #13 */ + "foo://tt:yt@example.com:8042", + /*.pszScheme =*/ "foo", + /*.pszAuthority =*/ "tt:yt@example.com:8042", + /*.pszPath =*/ NULL, + /*.pszQuery =*/ NULL, + /*.pszFragment =*/ NULL, + /*.pszUsername =*/ "tt", + /*.pszPassword =*/ "yt", + /*.pszHost =*/ "example.com", + /*.uPort =*/ 8042, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #14 */ + "file:///dir/dir/file", + /*.pszScheme =*/ "file", + /*.pszAuthority =*/ "", + /*.pszPath =*/ "/dir/dir/file", + /*.pszQuery =*/ NULL, + /*.pszFragment =*/ NULL, + /*.pszUsername =*/ NULL, + /*.pszPassword =*/ NULL, + /*.pszHost =*/ NULL, + /*.uPort =*/ UINT32_MAX, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #15 */ + "foo:///", + /*.pszScheme =*/ "foo", + /*.pszAuthority =*/ "", + /*.pszPath =*/ "/", + /*.pszQuery =*/ NULL, + /*.pszFragment =*/ NULL, + /*.pszUsername =*/ NULL, + /*.pszPassword =*/ NULL, + /*.pszHost =*/ NULL, + /*.uPort =*/ UINT32_MAX, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #16 */ + "foo://", + /*.pszScheme =*/ "foo", + /*.pszAuthority =*/ "", + /*.pszPath =*/ NULL, + /*.pszQuery =*/ NULL, + /*.pszFragment =*/ NULL, + /*.pszUsername =*/ NULL, + /*.pszPassword =*/ NULL, + /*.pszHost =*/ NULL, + /*.uPort =*/ UINT32_MAX, + /*.pszCreated =*/ NULL /* same as pszUri*/, + }, + { /* #17 - UTF-8 escape sequences. */ + "http://example.com/%ce%b3%ce%bb%cf%83%ce%b1%20%e0%a4%95\xe0\xa4\x95", + /*.pszScheme =*/ "http", + /*.pszAuthority =*/ "example.com", + /*.pszPath =*/ "/\xce\xb3\xce\xbb\xcf\x83\xce\xb1 \xe0\xa4\x95\xe0\xa4\x95", + /*.pszQuery =*/ NULL, + /*.pszFragment =*/ NULL, + /*.pszUsername =*/ NULL, + /*.pszPassword =*/ NULL, + /*.pszHost =*/ "example.com", + /*.uPort =*/ UINT32_MAX, + /*.pszCreated =*/ "http://example.com/\xce\xb3\xce\xbb\xcf\x83\xce\xb1%20\xe0\xa4\x95\xe0\xa4\x95", + }, +}; + + +static struct URIFILETEST +{ + const char *pszPath; + uint32_t fPathPathStyle; + const char *pszUri; + uint32_t fUriPathStyle; + const char *pszCreatedPath; + const char *pszCreatedUri; +} g_aCreateFileURIs[] = +{ + { /* #0: */ + /* .pszPath =*/ "C:\\over\\ <>#%\"{}|^[]`\\there", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:///C:%5Cover/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%5Cthere", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "C:\\over\\ <>#%\"{}|^[]`\\there", + /* .pszCreatedUri =*/ "file:///C:/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there", + /* PathCreateFromUrl = "C:\\over\\ <>#%\"{}|^[]`\\there" - same */ + /* UrlCreateFromPath = "file:///C:/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there" - same */ + }, + { /* #1: */ + /* .pszPath =*/ "/over/ <>#%\"{}|^[]`/there", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszUri =*/ "file:///over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszCreatedPath =*/ "/over/ <>#%\"{}|^[]`/there", + /* .pszCreatedUri =*/ "file:///over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there", + /* PathCreateFromUrl = "\\over\\ <>#%\"{}|^[]`\\there" - differs */ + /* UrlCreateFromPath = "file:///over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there" - same */ + }, + { /* #2: */ + /* .pszPath =*/ NULL, + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszUri =*/ "file://", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszCreatedPath =*/ NULL, + /* .pszCreatedUri =*/ NULL, + /* PathCreateFromUrl = "" - differs */ + /* UrlCreateFromPath => 0x80070057 (E_INVALIDARG) */ + }, + { /* #3: */ + /* .pszPath =*/ NULL, + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file://", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ NULL, + /* .pszCreatedUri =*/ NULL, + /* PathCreateFromUrl = "" - differs */ + /* UrlCreateFromPath => 0x80070057 (E_INVALIDARG) */ + }, + { /* #4: */ + /* .pszPath =*/ "/", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszUri =*/ "file:///", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszCreatedPath =*/ "/", + /* .pszCreatedUri =*/ "file:///", + /* PathCreateFromUrl = "" - differs */ + /* UrlCreateFromPath = "file:///" - same */ + }, + { /* #5: */ + /* .pszPath =*/ "\\", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:///", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "\\", + /* .pszCreatedUri =*/ "file:///", + /* PathCreateFromUrl = "" - differs */ + /* UrlCreateFromPath = "file:///" - same */ + }, + { /* #6: */ + /* .pszPath =*/ "/foo/bar", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszUri =*/ "file:///foo/bar", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszCreatedPath =*/ "/foo/bar", + /* .pszCreatedUri =*/ "file:///foo/bar", + /* PathCreateFromUrl = "\\foo\\bar" - differs */ + /* UrlCreateFromPath = "file:///foo/bar" - same */ + }, + { /* #7: */ + /* .pszPath =*/ "\\foo\\bar", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:///foo%5Cbar", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "\\foo\\bar", + /* .pszCreatedUri =*/ "file:///foo/bar", + /* PathCreateFromUrl = "\\foo\\bar" - same */ + /* UrlCreateFromPath = "file:///foo/bar" - same */ + }, + { /* #8: */ + /* .pszPath =*/ "C:/over/ <>#%\"{}|^[]`/there", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszUri =*/ "file:///C:/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszCreatedPath =*/ "C:/over/ <>#%\"{}|^[]`/there", + /* .pszCreatedUri =*/ "file:///C:/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there", + /* PathCreateFromUrl = "C:\\over\\ <>#%\"{}|^[]`\\there" - differs */ + /* UrlCreateFromPath = "file:///C:/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there" - same */ + }, + { /* #9: */ + /* .pszPath =*/ "\\over\\ <>#%\"{}|^[]`\\there", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:///over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "\\over\\ <>#%\"{}|^[]`\\there", + /* .pszCreatedUri =*/ "file:///over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there", + /* PathCreateFromUrl = "\\over\\ <>#%\"{}|^[]`\\there" - same */ + /* UrlCreateFromPath = "file:///over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there" - same */ + }, + { /* #10: */ + /* .pszPath =*/ "/usr/bin/grep", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszUri =*/ "file:///usr/bin/grep", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszCreatedPath =*/ "/usr/bin/grep", + /* .pszCreatedUri =*/ "file:///usr/bin/grep", + /* PathCreateFromUrl = "\\usr\\bin\\grep" - differs */ + /* UrlCreateFromPath = "file:///usr/bin/grep" - same */ + }, + { /* #11: */ + /* .pszPath =*/ "\\usr\\bin\\grep", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:///usr/bin/grep", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "\\usr\\bin\\grep", + /* .pszCreatedUri =*/ "file:///usr/bin/grep", + /* PathCreateFromUrl = "\\usr\\bin\\grep" - same */ + /* UrlCreateFromPath = "file:///usr/bin/grep" - same */ + }, + { /* #12: */ + /* .pszPath =*/ "/somerootsubdir/isos/files.lst", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszUri =*/ "file:///somerootsubdir/isos/files.lst", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszCreatedPath =*/ "/somerootsubdir/isos/files.lst", + /* .pszCreatedUri =*/ "file:///somerootsubdir/isos/files.lst", + /* PathCreateFromUrl = "\\somerootsubdir\\isos\\files.lst" - differs */ + /* UrlCreateFromPath = "file:///somerootsubdir/isos/files.lst" - same */ + }, + { /* #13: */ + /* .pszPath =*/ "\\not-a-cifsserver\\isos\\files.lst", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:///not-a-cifsserver/isos/files.lst", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "\\not-a-cifsserver\\isos\\files.lst", + /* .pszCreatedUri =*/ "file:///not-a-cifsserver/isos/files.lst", + /* PathCreateFromUrl = "\\not-a-cifsserver\\isos\\files.lst" - same */ + /* UrlCreateFromPath = "file:///not-a-cifsserver/isos/files.lst" - same */ + }, + { /* #14: */ + /* .pszPath =*/ "/rootsubdir/isos/files.lst", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszUri =*/ "file:///rootsubdir/isos/files.lst", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_UNIX, + /* .pszCreatedPath =*/ "/rootsubdir/isos/files.lst", + /* .pszCreatedUri =*/ "file:///rootsubdir/isos/files.lst", + /* PathCreateFromUrl = "\\rootsubdir\\isos\\files.lst" - differs */ + /* UrlCreateFromPath = "file:///rootsubdir/isos/files.lst" - same */ + }, + { /* #15: */ + /* .pszPath =*/ "\\not-a-cifsserver-either\\isos\\files.lst", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:///not-a-cifsserver-either/isos/files.lst", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "\\not-a-cifsserver-either\\isos\\files.lst", + /* .pszCreatedUri =*/ "file:///not-a-cifsserver-either/isos/files.lst", + /* PathCreateFromUrl = "\\not-a-cifsserver-either\\isos\\files.lst" - same */ + /* UrlCreateFromPath = "file:///not-a-cifsserver-either/isos/files.lst" - same */ + }, + { /* #16: */ + /* .pszPath =*/ "\\\\cifsserver\\isos\\files.lst", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:////cifsserver/isos/files.lst", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "\\\\cifsserver\\isos\\files.lst", + /* .pszCreatedUri =*/ "file://cifsserver/isos/files.lst", + /* PathCreateFromUrl = "\\\\cifsserver\\isos\\files.lst" - same */ + /* UrlCreateFromPath = "file://cifsserver/isos/files.lst" - same */ + }, + { /* #17: */ + /* .pszPath =*/ "c:boot.ini", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file://localhost/c:boot.ini", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "c:boot.ini", + /* .pszCreatedUri =*/ "file:///c:boot.ini", + /* PathCreateFromUrl = "c:boot.ini" - same */ + /* UrlCreateFromPath = "file:///c:boot.ini" - same */ + }, + { /* #18: */ + /* .pszPath =*/ "c:boot.ini", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:///c|boot.ini", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "c:boot.ini", + /* .pszCreatedUri =*/ "file:///c:boot.ini", + /* PathCreateFromUrl = "c:boot.ini" - same */ + /* UrlCreateFromPath = "file:///c:boot.ini" - same */ + }, + { /* #19: */ + /* .pszPath =*/ "c:\\legacy-no-slash.ini", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:c:\\legacy-no-slash%2Eini", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "c:\\legacy-no-slash.ini", + /* .pszCreatedUri =*/ "file:///c:/legacy-no-slash.ini", + /* PathCreateFromUrl = "c:\\legacy-no-slash.ini" - same */ + /* UrlCreateFromPath = "file:///c:/legacy-no-slash.ini" - same */ + }, + { /* #20: */ + /* .pszPath =*/ "c:\\legacy-no-slash.ini", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:c|\\legacy-no-slash%2Eini", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "c:\\legacy-no-slash.ini", + /* .pszCreatedUri =*/ "file:///c:/legacy-no-slash.ini", + /* PathCreateFromUrl = "c:\\legacy-no-slash.ini" - same */ + /* UrlCreateFromPath = "file:///c:/legacy-no-slash.ini" - same */ + }, + { /* #21: */ + /* .pszPath =*/ "c:\\legacy-single-slash.ini", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:/c:\\legacy-single-slash%2Eini", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "c:\\legacy-single-slash.ini", + /* .pszCreatedUri =*/ "file:///c:/legacy-single-slash.ini", + /* PathCreateFromUrl = "c:\\legacy-single-slash.ini" - same */ + /* UrlCreateFromPath = "file:///c:/legacy-single-slash.ini" - same */ + }, + { /* #22: */ + /* .pszPath =*/ "c:\\legacy-single-slash.ini", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:/c:\\legacy-single-slash%2Eini", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "c:\\legacy-single-slash.ini", + /* .pszCreatedUri =*/ "file:///c:/legacy-single-slash.ini", + /* PathCreateFromUrl = "c:\\legacy-single-slash.ini" - same */ + /* UrlCreateFromPath = "file:///c:/legacy-single-slash.ini" - same */ + }, + { /* #23: */ + /* .pszPath =*/ "\\legacy-single-slash.ini", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:/legacy-single-slash%2Eini", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "\\legacy-single-slash.ini", + /* .pszCreatedUri =*/ "file:///legacy-single-slash.ini", + /* PathCreateFromUrl = "\\legacy-single-slash.ini" - same */ + /* UrlCreateFromPath = "file:///legacy-single-slash.ini" - same */ + }, + { /* #24: */ + /* .pszPath =*/ "C:\\legacy-double-slash%2E.ini", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file://C:\\legacy-double-slash%2E.ini", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "C:\\legacy-double-slash%2E.ini", + /* .pszCreatedUri =*/ "file:///C:/legacy-double-slash%252E.ini", + /* PathCreateFromUrl = "C:\\legacy-double-slash%2E.ini" - same */ + /* UrlCreateFromPath = "file:///C:/legacy-double-slash.ini" - same */ + }, + { /* #25: */ + /* .pszPath =*/ "C:\\legacy-double-slash%2E.ini", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file://C|/legacy-double-slash%2E.ini", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "C:\\legacy-double-slash%2E.ini", + /* .pszCreatedUri =*/ "file:///C:/legacy-double-slash%252E.ini", + /* PathCreateFromUrl = "C:\\legacy-double-slash%2E.ini" - same */ + /* UrlCreateFromPath = "file:///C:/legacy-double-slash%252E.ini" - same */ + }, + { /* #26: */ + /* .pszPath =*/ "C:\\legacy-4-slashes%2E.ini", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:////C|/legacy-4-slashes%2E.ini", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "C:\\legacy-4-slashes%2E.ini", + /* .pszCreatedUri =*/ "file:///C:/legacy-4-slashes%252E.ini", + /* PathCreateFromUrl = "C:\\legacy-4-slashes%2E.ini" - same */ + /* UrlCreateFromPath = "file:///C:/legacy-4-slashes%252E.ini" - same */ + }, + { /* #27: */ + /* .pszPath =*/ "C:\\legacy-4-slashes%2E.ini", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:////C:/legacy-4-slashes%2E.ini", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "C:\\legacy-4-slashes%2E.ini", + /* .pszCreatedUri =*/ "file:///C:/legacy-4-slashes%252E.ini", + /* PathCreateFromUrl = "C:\\legacy-4-slashes%2E.ini" - same */ + /* UrlCreateFromPath = "file:///C:/legacy-4-slashes%252E.ini" - same */ + }, + { /* #28: */ + /* .pszPath =*/ "\\\\cifsserver\\share\\legacy-4-slashes%2E.ini", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file:////cifsserver/share/legacy-4-slashes%2E.ini", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "\\\\cifsserver\\share\\legacy-4-slashes%2E.ini", + /* .pszCreatedUri =*/ "file://cifsserver/share/legacy-4-slashes%252E.ini", + /* PathCreateFromUrl = "\\\\cifsserver\\share\\legacy-4-slashes%2E.ini" - same */ + /* UrlCreateFromPath = "file://cifsserver/share/legacy-4-slashes%252E.ini" - same */ + }, + { /* #29: */ + /* .pszPath =*/ "\\\\cifsserver\\share\\legacy-5-slashes.ini", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file://///cifsserver/share/legacy-5-slashes%2Eini", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "\\\\cifsserver\\share\\legacy-5-slashes.ini", + /* .pszCreatedUri =*/ "file://cifsserver/share/legacy-5-slashes.ini", + /* PathCreateFromUrl = "\\\\cifsserver\\share\\legacy-5-slashes.ini" - same */ + /* UrlCreateFromPath = "file://cifsserver/share/legacy-5-slashes.ini" - same */ + }, + { /* #30: */ + /* .pszPath =*/ "\\\\C|\\share\\legacy-5-slashes.ini", + /* .fPathPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszUri =*/ "file://///C|/share/legacy-5-slashes%2Eini", + /* .fUriPathStyle =*/ RTPATH_STR_F_STYLE_DOS, + /* .pszCreatedPath =*/ "\\\\C|\\share\\legacy-5-slashes.ini", + /* .pszCreatedUri =*/ "file://C%7C/share/legacy-5-slashes.ini", + /* PathCreateFromUrl = "\\\\C|\\share\\legacy-5-slashes.ini" - same */ + /* UrlCreateFromPath = "file:///C%7C/share/legacy-5-slashes.ini" - differs */ + }, +}; + +#ifdef TSTRTURI_WITH_WINDOWS_REFERENCE_RESULTS + +static void tstPrintCString(const char *pszString) +{ + if (pszString) + { + char ch; + RTPrintf("\""); + while ((ch = *pszString++) != '\0') + { + if (ch >= 0x20 && ch < 0x7f) + switch (ch) + { + default: + RTPrintf("%c", ch); + break; + case '\\': + case '"': + RTPrintf("\\%c", ch); + break; + } + else + RTPrintf("\\x%02X", ch); /* good enough */ + } + RTPrintf("\""); + } + else + RTPrintf("NULL"); +} + +static const char *tstNamePathStyle(uint32_t fPathStyle) +{ + switch (fPathStyle) + { + case RTPATH_STR_F_STYLE_DOS: return "RTPATH_STR_F_STYLE_DOS"; + case RTPATH_STR_F_STYLE_UNIX: return "RTPATH_STR_F_STYLE_UNIX"; + case RTPATH_STR_F_STYLE_HOST: return "RTPATH_STR_F_STYLE_HOST"; + default: AssertFailedReturn("Invalid"); + } +} + +static void tstWindowsReferenceResults(void) +{ + /* + * Feed the g_aCreateFileURIs values as input to the Windows + * PathCreateFromUrl and URlCreateFromPath APIs and print the results. + * + * We reproduce the entire source file content of g_aCreateFileURIs here. + */ + for (size_t i = 0; i < RT_ELEMENTS(g_aCreateFileURIs); ++i) + { + RTPrintf(" { /* #%u: */\n", i); + RTPrintf(" /* .pszPath =*/ "); + tstPrintCString(g_aCreateFileURIs[i].pszPath); + RTPrintf(",\n"); + RTPrintf(" /* .fPathPathStyle =*/ %s,\n", tstNamePathStyle(g_aCreateFileURIs[i].fPathPathStyle)); + RTPrintf(" /* .pszUri =*/ "); + tstPrintCString(g_aCreateFileURIs[i].pszUri); + RTPrintf(",\n"); + RTPrintf(" /* .fUriPathStyle =*/ %s,\n", tstNamePathStyle(g_aCreateFileURIs[i].fUriPathStyle)); + RTPrintf(" /* .pszCreatedPath =*/ "); + tstPrintCString(g_aCreateFileURIs[i].pszCreatedPath); + RTPrintf(",\n"); + RTPrintf(" /* .pszCreatedUri =*/ "); + tstPrintCString(g_aCreateFileURIs[i].pszCreatedUri); + RTPrintf(",\n"); + + /* + * PathCreateFromUrl + */ + PRTUTF16 pwszInput = NULL; + if (g_aCreateFileURIs[i].pszUri) + RTTESTI_CHECK_RC_OK_RETV(RTStrToUtf16(g_aCreateFileURIs[i].pszUri, &pwszInput)); + WCHAR wszResult[_1K]; + DWORD cwcResult = RT_ELEMENTS(wszResult); + RT_ZERO(wszResult); + HRESULT hrc = PathCreateFromUrlW(pwszInput, wszResult, &cwcResult, 0 /*dwFlags*/); + RTUtf16Free(pwszInput); + + if (SUCCEEDED(hrc)) + { + char *pszResult; + RTTESTI_CHECK_RC_OK_RETV(RTUtf16ToUtf8(wszResult, &pszResult)); + RTPrintf(" /* PathCreateFromUrl = "); + tstPrintCString(pszResult); + if ( g_aCreateFileURIs[i].pszCreatedPath + && strcmp(pszResult, g_aCreateFileURIs[i].pszCreatedPath) == 0) + RTPrintf(" - same */\n"); + else + RTPrintf(" - differs */\n"); + RTStrFree(pszResult); + } + else + RTPrintf(" /* PathCreateFromUrl => %#x (%Rhrc) */\n", hrc, hrc); + + /* + * UrlCreateFromPath + UrlEscape + */ + pwszInput = NULL; + if (g_aCreateFileURIs[i].pszPath) + RTTESTI_CHECK_RC_OK_RETV(RTStrToUtf16(g_aCreateFileURIs[i].pszPath, &pwszInput)); + RT_ZERO(wszResult); + cwcResult = RT_ELEMENTS(wszResult); + hrc = UrlCreateFromPathW(pwszInput, wszResult, &cwcResult, 0 /*dwFlags*/); + RTUtf16Free(pwszInput); + + if (SUCCEEDED(hrc)) + { + WCHAR wszResult2[_1K]; + DWORD cwcResult2 = RT_ELEMENTS(wszResult2); + hrc = UrlEscapeW(wszResult, wszResult2, &cwcResult2, URL_DONT_ESCAPE_EXTRA_INFO | URL_ESCAPE_AS_UTF8 ); + if (SUCCEEDED(hrc)) + { + char *pszResult; + RTTESTI_CHECK_RC_OK_RETV(RTUtf16ToUtf8(wszResult2, &pszResult)); + RTPrintf(" /* UrlCreateFromPath = "); + tstPrintCString(pszResult); + if ( g_aCreateFileURIs[i].pszCreatedUri + && strcmp(pszResult, g_aCreateFileURIs[i].pszCreatedUri) == 0) + RTPrintf(" - same */\n"); + else + RTPrintf(" - differs */\n"); + RTStrFree(pszResult); + } + else + RTPrintf(" /* UrlEscapeW => %#x (%Rhrc) */\n", hrc, hrc); + } + else + RTPrintf(" /* UrlCreateFromPath => %#x (%Rhrc) */\n", hrc, hrc); + RTPrintf(" },\n"); + } +} + +#endif /* TSTRTURI_WITH_WINDOWS_REFERENCE_RESULTS */ + + +static void tstRTUriFilePathEx(void) +{ + RTTestISub("RTUriFilePathEx"); + for (size_t i = 0; i < RT_ELEMENTS(g_aCreateFileURIs); ++i) + { + uint32_t const fPathStyle = g_aCreateFileURIs[i].fUriPathStyle; + const char * const pszUri = g_aCreateFileURIs[i].pszUri; + char *pszPath = (char *)&pszPath; + int rc = RTUriFilePathEx(pszUri, fPathStyle, &pszPath, 0, NULL); + if (RT_SUCCESS(rc)) + { + if (g_aCreateFileURIs[i].pszCreatedPath) + { + if (strcmp(pszPath, g_aCreateFileURIs[i].pszCreatedPath) == 0) + { + /** @todo check out the other variations of the API. */ + } + else + RTTestIFailed("#%u: '%s'/%#x => '%s', expected '%s'", + i, pszUri, fPathStyle, pszPath, g_aCreateFileURIs[i].pszCreatedPath); + } + else + RTTestIFailed("#%u: bad testcase; pszCreatedPath is NULL\n", i); + RTStrFree(pszPath); + } + else if (rc != VERR_PATH_ZERO_LENGTH || RTStrCmp(pszUri, "file://") != 0) + RTTestIFailed("#%u: '%s'/%#x => %Rrc", i, pszUri, fPathStyle, rc); + } +} + + +static void tstRTUriFileCreateEx(void) +{ + RTTestISub("RTUriFileCreateEx"); + for (size_t i = 0; i < RT_ELEMENTS(g_aCreateFileURIs); ++i) + { + uint32_t const fPathStyle = g_aCreateFileURIs[i].fPathPathStyle; + const char * const pszPath = g_aCreateFileURIs[i].pszPath; + char *pszUri = (char *)&pszUri; + int rc = RTUriFileCreateEx(pszPath, fPathStyle, &pszUri, 0, NULL); + if (RT_SUCCESS(rc)) + { + if (g_aCreateFileURIs[i].pszCreatedUri) + { + if (strcmp(pszUri, g_aCreateFileURIs[i].pszCreatedUri) == 0) + { + /** @todo check out the other variations of the API. */ + } + else + RTTestIFailed("#%u: '%s'/%#x => '%s', expected '%s'", + i, pszPath, fPathStyle, pszUri, g_aCreateFileURIs[i].pszCreatedUri); + } + else + RTTestIFailed("#%u: bad testcase; pszCreatedUri is NULL\n", i); + RTStrFree(pszUri); + } + else if (rc != VERR_INVALID_POINTER || pszPath != NULL) + RTTestIFailed("#%u: '%s'/%#x => %Rrc", i, pszPath, fPathStyle, rc); + } +} + + +int main() +{ + RTTEST hTest; + int rc = RTTestInitAndCreate("tstRTUri", &hTest); + if (rc) + return rc; + RTTestBanner(hTest); + +#define CHECK_STR_API(a_Call, a_pszExpected) \ + do { \ + char *pszTmp = a_Call; \ + if (a_pszExpected) \ + { \ + if (!pszTmp) \ + RTTestIFailed("#%u: %s returns NULL, expected '%s'", i, #a_Call, a_pszExpected); \ + else if (strcmp(pszTmp, a_pszExpected)) \ + RTTestIFailed("#%u: %s returns '%s', expected '%s'", i, #a_Call, pszTmp, a_pszExpected); \ + } \ + else if (pszTmp) \ + RTTestIFailed("#%u: %s returns '%s', expected NULL", i, #a_Call, pszTmp); \ + RTStrFree(pszTmp); \ + } while (0) + + RTTestISub("RTUriParse & RTUriParsed*"); + for (uint32_t i = 0; i < RT_ELEMENTS(g_aTests); i++) + { + RTURIPARSED Parsed; + RTTESTI_CHECK_RC(rc = RTUriParse(g_aTests[i].pszUri, &Parsed), VINF_SUCCESS); + if (RT_SUCCESS(rc)) + { + CHECK_STR_API(RTUriParsedScheme(g_aTests[i].pszUri, &Parsed), g_aTests[i].pszScheme); + CHECK_STR_API(RTUriParsedAuthority(g_aTests[i].pszUri, &Parsed), g_aTests[i].pszAuthority); + CHECK_STR_API(RTUriParsedAuthorityUsername(g_aTests[i].pszUri, &Parsed), g_aTests[i].pszUsername); + CHECK_STR_API(RTUriParsedAuthorityPassword(g_aTests[i].pszUri, &Parsed), g_aTests[i].pszPassword); + CHECK_STR_API(RTUriParsedAuthorityHost(g_aTests[i].pszUri, &Parsed), g_aTests[i].pszHost); + CHECK_STR_API(RTUriParsedPath(g_aTests[i].pszUri, &Parsed), g_aTests[i].pszPath); + CHECK_STR_API(RTUriParsedQuery(g_aTests[i].pszUri, &Parsed), g_aTests[i].pszQuery); + CHECK_STR_API(RTUriParsedFragment(g_aTests[i].pszUri, &Parsed), g_aTests[i].pszFragment); + uint32_t uPort = RTUriParsedAuthorityPort(g_aTests[i].pszUri, &Parsed); + if (uPort != g_aTests[i].uPort) + RTTestIFailed("#%u: RTUriParsedAuthorityPort returns %#x, expected %#x", i, uPort, g_aTests[i].uPort); + } + } + + /* Creation */ + RTTestISub("RTUriCreate"); + for (uint32_t i = 0; i < RT_ELEMENTS(g_aTests); i++) + CHECK_STR_API(RTUriCreate(g_aTests[i].pszScheme, g_aTests[i].pszAuthority, g_aTests[i].pszPath, + g_aTests[i].pszQuery, g_aTests[i].pszFragment), + g_aTests[i].pszCreated ? g_aTests[i].pszCreated : g_aTests[i].pszUri); + +#ifdef TSTRTURI_WITH_WINDOWS_REFERENCE_RESULTS + tstWindowsReferenceResults(); +#endif + + bool fSavedMayPanic = RTAssertSetMayPanic(false); + bool fSavedQuiet = RTAssertSetQuiet(true); + + tstRTUriFilePathEx(); + tstRTUriFileCreateEx(); + + RTAssertSetMayPanic(fSavedMayPanic); + RTAssertSetQuiet(fSavedQuiet); + + return RTTestSummaryAndDestroy(hTest); +} + |