test/url: move test for empty port-specification
[vlc.git] / src / test / url.c
1 /*****************************************************************************
2  * url.c: Test for url encoding/decoding stuff
3  *****************************************************************************
4  * Copyright (C) 2006 Rémi Denis-Courmont
5  * $Id$
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation; either version 2.1 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
20  *****************************************************************************/
21
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #undef NDEBUG
27
28 #include <assert.h>
29 #include <errno.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32
33 #include <vlc_common.h>
34 #include <vlc_url.h>
35 #include <vlc_strings.h>
36
37 static int exitcode = 0;
38
39 typedef char * (*conv_t) (const char *);
40
41 static void test (conv_t f, const char *in, const char *out)
42 {
43     char *res;
44
45     if (out != NULL)
46        printf ("\"%s\" -> \"%s\" ?\n", in, out);
47     else
48        printf ("\"%s\" -> NULL ?\n", in);
49     res = f (in);
50     if (res == NULL)
51     {
52         if (out == NULL)
53             return; /* good: NULL -> NULL */
54         puts (" ERROR: got NULL");
55         exit (2);
56     }
57     if (out == NULL || strcmp (res, out))
58     {
59         printf (" ERROR: got \"%s\"\n", res);
60         exit (2);
61     }
62
63     free (res);
64 }
65
66 static inline void test_decode (const char *in, const char *out)
67 {
68     test (vlc_uri_decode_duplicate, in, out);
69 }
70
71 static inline void test_b64 (const char *in, const char *out)
72 {
73     test (vlc_b64_encode, in, out);
74 }
75
76 static char *make_URI_def (const char *in)
77 {
78     return vlc_path2uri (in, NULL);
79 }
80
81 static inline void test_path (const char *in, const char *out)
82 {
83     test (make_URI_def, in, out);
84 }
85
86 static inline void test_current_directory_path (const char *in, const char *cwd, const char *out)
87 {
88     char *expected_result;
89     int val = asprintf (&expected_result, "file://%s/%s", cwd, out);
90     assert (val != -1);
91
92     test (make_URI_def, in, expected_result);
93     free(expected_result);
94 }
95
96 static void test_url_parse(const char* in, const char* protocol, const char* user,
97                            const char* pass, const char* host, unsigned i_port,
98                            const char* path, const char* option )
99 {
100 #define CHECK( a, b ) \
101     if (a == NULL) \
102         assert(b == NULL); \
103     else \
104         assert(b != NULL && !strcmp((a), (b)))
105
106     vlc_url_t url;
107     int ret = vlc_UrlParse(&url, in);
108
109     CHECK( url.psz_protocol, protocol );
110     CHECK( url.psz_username, user );
111     CHECK( url.psz_password, pass );
112
113     if (ret != 0 && errno == ENOSYS)
114     {
115         assert(url.psz_host == NULL);
116         exitcode = 77;
117     }
118     else
119         CHECK(url.psz_host, host);
120
121     CHECK( url.psz_path, path );
122     assert( url.i_port == i_port );
123     CHECK( url.psz_option, option );
124
125     vlc_UrlClean( &url );
126
127 #undef CHECK
128 }
129
130 static void test_url_resolve(const char *base, const char *reference,
131                              const char *expected)
132 {
133     fprintf(stderr, "(%s) \"%s\" -> \"%s\" ?\n", base, reference, expected);
134
135     char *result = vlc_uri_resolve(base, reference);
136     assert(result != NULL);
137     if (strcmp(result, expected))
138     {
139         fprintf(stderr, " ERROR: got \"%s\"\n", result);
140         abort();
141     }
142     free(result);
143 }
144
145 static void test_rfc3986(const char *reference, const char *expected)
146 {
147     test_url_resolve("http://a/b/c/d;p?q", reference, expected);
148 }
149
150 static void test_fixup_noop(const char *expected)
151 {
152     fprintf(stderr, "\"%s\" -> \"%s\" ?\n", expected, expected);
153
154     char *result = vlc_uri_fixup(expected);
155     assert(result != NULL);
156     if (strcmp(result, expected))
157     {
158         fprintf(stderr, " ERROR: got \"%s\"\n", result);
159         abort();
160     }
161     free(result);
162 }
163
164 int main (void)
165 {
166     int val;
167
168     (void)setvbuf (stdout, NULL, _IONBF, 0);
169     test_decode ("this_should_not_be_modified_1234",
170                  "this_should_not_be_modified_1234");
171
172     test_decode ("This%20should%20be%20modified%201234!",
173                  "This should be modified 1234!");
174
175     test_decode ("%7E", "~");
176
177     /* tests with invalid input */
178     test_decode ("%", NULL);
179     test_decode ("%2", NULL);
180     test_decode ("%0000", "");
181
182     /* Non-ASCII tests */
183     test_decode ("T%C3%a9l%c3%A9vision %e2%82%Ac", "Télévision €");
184     test_decode ("T%E9l%E9vision", "T\xe9l\xe9vision");
185
186     /* Base 64 tests */
187     test_b64 ("", "");
188     test_b64 ("f", "Zg==");
189     test_b64 ("fo", "Zm8=");
190     test_b64 ("foo", "Zm9v");
191     test_b64 ("foob", "Zm9vYg==");
192     test_b64 ("fooba", "Zm9vYmE=");
193     test_b64 ("foobar", "Zm9vYmFy");
194
195     /* Path test */
196 #ifndef _WIN32
197     test_path ("/", "file:///");
198     test_path ("/home/john/", "file:///home/john/");
199     test_path ("/home/john//too///many//slashes",
200                "file:///home/john//too///many//slashes");
201     test_path ("/home/john/music.ogg", "file:///home/john/music.ogg");
202 #else
203     test_path ("C:\\", "file:///C:/");
204     test_path ("C:\\Users\\john\\", "file:///C:/Users/john/");
205     test_path ("C:\\Users\\john\\music.ogg",
206                "file:///C:/Users/john/music.ogg");
207     test_path ("\\\\server\\share\\dir\\file.ext",
208                "file://server/share/dir/file.ext");
209 #endif
210
211     /*int fd = open (".", O_RDONLY);
212     assert (fd != -1);*/
213     val = chdir ("/tmp");
214     assert (val != -1);
215
216     char buf[256];
217     char * tmpdir;
218     tmpdir = getcwd(buf, sizeof(buf)/sizeof(*buf));
219     assert (tmpdir);
220
221 #ifndef _WIN32 /* FIXME: deal with anti-slashes */
222     test_current_directory_path ("movie.ogg", tmpdir, "movie.ogg");
223     test_current_directory_path (".", tmpdir, ".");
224     test_current_directory_path ("", tmpdir, "");
225 #endif
226
227     /*val = fchdir (fd);
228     assert (val != -1);*/
229
230     /* URI to path tests */
231 #define test( a, b ) test (vlc_uri2path, a, b)
232     test ("mailto:john@example.com", NULL);
233     test ("http://www.example.com/file.html#ref", NULL);
234     test ("file://", NULL);
235 #ifndef _WIN32
236     test ("file:///", "/");
237     test ("file://localhost/home/john/music%2Eogg", "/home/john/music.ogg");
238     test ("file://localhost/home/john/text#ref", "/home/john/text");
239     test ("file://localhost/home/john/text?name=value", "/home/john/text");
240     test ("file://localhost/home/john/text?name=value#ref", "/home/john/text");
241     test ("file://?name=value", NULL);
242     test ("file:///?name=value", "/");
243     test ("fd://0foobar", NULL);
244     test ("fd://0#ref", "/dev/stdin");
245     test ("fd://1", "/dev/stdout");
246     test ("fd://12345", "/dev/fd/12345");
247 #else
248     test ("file:///C:", "C:");
249     test ("file:///C:/Users/john/music%2Eogg", "C:\\Users\\john\\music.ogg");
250     test ("file://server/share/dir/file%2Eext",
251           "\\\\server\\share\\dir\\file.ext");
252     test ("file:///C:/Users/john/text#ref", "C:\\Users\\john\\text");
253     test ("file:///C:/Users/john/text?name=value", "C:\\Users\\john\\text");
254     test ("file:///C:/Users/john/text?name=value#ref",
255           "C:\\Users\\john\\text");
256     test ("file://?name=value", NULL);
257     test ("file:///C:?name=value", "C:");
258     test ("fd://0foobar", NULL);
259     test ("fd://0#ref", "CON");
260     test ("fd://1", "CON");
261     test ("fd://12345", NULL);
262 #endif
263 #undef test
264
265     test_url_parse("http://example.com", "http", NULL, NULL, "example.com", 0,
266                    NULL, NULL);
267     test_url_parse("http://example.com/", "http", NULL, NULL, "example.com", 0,
268                    "/", NULL);
269     test_url_parse("http://[2001:db8::1]", "http", NULL, NULL, "2001:db8::1",
270                    0, NULL, NULL);
271     test_url_parse("http://example.com:", "http", NULL, NULL, "example.com", 0,
272                     NULL, NULL);
273     test_url_parse("protocol://john:doe@1.2.3.4:567", "protocol", "john", "doe", "1.2.3.4", 567, NULL, NULL);
274     test_url_parse("http://a.b/?opt=val", "http", NULL, NULL, "a.b", 0, "/", "opt=val");
275     test_url_parse("p://u:p@host:123/a/b/c?o=v", "p", "u", "p", "host", 123, "/a/b/c", "o=v");
276     test_url_parse("p://?o=v", "p", NULL, NULL, "", 0, NULL, "o=v");
277     test_url_parse("p://h?o=v", "p", NULL, NULL, "h", 0, NULL, "o=v");
278     test_url_parse("p://h:123?o=v", "p", NULL, NULL, "h", 123, NULL, "o=v");
279     test_url_parse("p://u:p@h:123?o=v", "p", "u", "p", "h", 123, NULL, "o=v");
280     test_url_parse("p://caf\xc3\xa9.example.com", "p", NULL, NULL,
281                    "xn--caf-dma.example.com", 0, NULL, NULL);
282     test_url_parse("p://caf%C3%A9.example.com", "p", NULL, NULL,
283                    "xn--caf-dma.example.com", 0, NULL, NULL);
284     test_url_parse("p://www.example.com/caf\xc3\xa9/", "p", NULL, NULL,
285                    "www.example.com", 0, "/caf%C3%A9/", NULL);
286     test_url_parse("p://h/white%20spaced", "p", NULL, NULL, "h", 0,
287                    "/white%20spaced", NULL);
288     /* Relative URIs */
289     test_url_parse("//example.com", NULL, NULL, NULL, "example.com", 0,
290                    NULL, NULL);
291     test_url_parse("/file", NULL, NULL, NULL, NULL, 0, "/file", NULL);
292     test_url_parse("?opt=val", NULL, NULL, NULL, NULL, 0, "", "opt=val");
293     test_url_parse("?o1=v1&o2=v2", NULL, NULL, NULL, NULL, 0, "",
294                    "o1=v1&o2=v2");
295     test_url_parse("/f?o=v", NULL, NULL, NULL, NULL, 0, "/f", "o=v");
296     test_url_parse("//example.com/file", NULL, NULL, NULL, "example.com", 0,
297                    "/file", NULL);
298     test_url_parse("//example.com?opt=val", NULL, NULL, NULL, "example.com", 0,
299                    NULL, "opt=val");
300     test_url_parse("//example.com/f?o=v", NULL, NULL, NULL, "example.com", 0,
301                    "/f", "o=v");
302     /* Invalid URIs */
303     test_url_parse("p://G a r b a g e", "p", NULL, NULL, NULL, 0, NULL, NULL);
304     test_url_parse("p://h/G a r b a g e", "p", NULL, NULL, "h", 0, NULL, NULL);
305     test_url_parse("http://example.com:123xyz", "http", NULL, NULL,
306                    "example.com", 123, NULL, NULL);
307
308     /* Reference test cases for reference URI resolution */
309     static const char *rfc3986_cases[] =
310     {
311         "g:h",           "g:h",
312         "g",             "http://a/b/c/g",
313         "./g",           "http://a/b/c/g",
314         "g/",            "http://a/b/c/g/",
315         "/g",            "http://a/g",
316         "//g",           "http://g",
317         "?y",            "http://a/b/c/d;p?y",
318         "g?y",           "http://a/b/c/g?y",
319         //"#s",            "http://a/b/c/d;p?q#s",
320         //"g#s",           "http://a/b/c/g#s",
321         //"g?y#s",         "http://a/b/c/g?y#s",
322         ";x",            "http://a/b/c/;x",
323         "g;x",           "http://a/b/c/g;x",
324         //"g;x?y#s",       "http://a/b/c/g;x?y#s",
325         "",              "http://a/b/c/d;p?q",
326         ".",             "http://a/b/c/",
327         "./",            "http://a/b/c/",
328         "..",            "http://a/b/",
329         "../",           "http://a/b/",
330         "../g",          "http://a/b/g",
331         "../..",         "http://a/",
332         "../../",        "http://a/",
333         "../../g",       "http://a/g",
334
335         "../../../g",    "http://a/g",
336         "../../../../g", "http://a/g",
337
338         "/./g",          "http://a/g",
339         "/../g",         "http://a/g",
340         "g.",            "http://a/b/c/g.",
341         ".g",            "http://a/b/c/.g",
342         "g..",           "http://a/b/c/g..",
343         "..g",           "http://a/b/c/..g",
344
345         "./../g",        "http://a/b/g",
346         "./g/.",         "http://a/b/c/g/",
347         "g/./h",         "http://a/b/c/g/h",
348         "g/../h",        "http://a/b/c/h",
349         "g;x=1/./y",     "http://a/b/c/g;x=1/y",
350         "g;x=1/../y",    "http://a/b/c/y",
351
352         "g?y/./x",       "http://a/b/c/g?y/./x",
353         "g?y/../x",      "http://a/b/c/g?y/../x",
354         //"g#s/./x",       "http://a/b/c/g#s/./x",
355         //"g#s/../x",      "http://a/b/c/g#s/../x",
356     };
357
358     for (size_t i = 0; i < ARRAY_SIZE(rfc3986_cases); i += 2)
359         test_rfc3986(rfc3986_cases[i], rfc3986_cases[i + 1]);
360
361     /* Check that fixup does not mangle valid URIs */
362     static const char *valid_uris[] =
363     {
364         "#href", "?opt=val",
365         ".", "..", "/", "../../dir/subdir/subsubdir/file.ext",
366         "//example.com?q=info",
367         "//192.0.2.1/index.html",
368         "//[2001:db8::1]/index.html",
369         "https://www.example.com:8443/?opt1=val1&opt2=val2",
370         "https://192.0.2.1:8443/#foobar",
371         "https://[2001:db8::1]:8443/file?opt=val#foobar",
372         "https://[v9.abcd:efgh]:8443/welcome?to=the#future",
373         "mailto:john@example.com",
374         "mailto:mailman@example.com?subject=help",
375         "mailto:mailman@example.com?body=subscribe%20news-flash",
376         "mailto:literal@[192.0.2.1],literal@[IPv6:2001:db8::1]",
377     };
378
379     for (size_t i = 0; i < ARRAY_SIZE(valid_uris); i++)
380         test_fixup_noop(valid_uris[i]);
381
382     return exitcode;
383 }