urlmon/tests: Added tests for IUri_GetPropertyDWORD.
[wine] / dlls / urlmon / tests / uri.c
1 /*
2  * UrlMon IUri tests
3  *
4  * Copyright 2010 Thomas Mullaly
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 /*
22  * IUri testing framework goals:
23  *  - Test invalid args
24  *      - invalid flags
25  *      - invalid args (IUri, uri string)
26  *  - Test parsing for components when no canonicalization occurs
27  *  - Test parsing for components when canonicalization occurs.
28  *  - More tests...
29  */
30
31 #include <wine/test.h>
32 #include <stdarg.h>
33 #include <stddef.h>
34
35 #define COBJMACROS
36
37 #include "windef.h"
38 #include "winbase.h"
39 #include "urlmon.h"
40 #include "shlwapi.h"
41
42 #define URI_STR_PROPERTY_COUNT Uri_PROPERTY_STRING_LAST+1
43 #define URI_DWORD_PROPERTY_COUNT (Uri_PROPERTY_DWORD_LAST - Uri_PROPERTY_DWORD_START)+1
44
45 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
46
47 static const WCHAR http_urlW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
48         '.','o','r','g','/',0};
49
50 typedef struct _uri_create_flag_test {
51     DWORD   flags;
52     HRESULT expected;
53 } uri_create_flag_test;
54
55 static const uri_create_flag_test invalid_flag_tests[] = {
56     /* Set of invalid flag combinations to test for. */
57     {Uri_CREATE_DECODE_EXTRA_INFO | Uri_CREATE_NO_DECODE_EXTRA_INFO, E_INVALIDARG},
58     {Uri_CREATE_CANONICALIZE | Uri_CREATE_NO_CANONICALIZE, E_INVALIDARG},
59     {Uri_CREATE_CRACK_UNKNOWN_SCHEMES | Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, E_INVALIDARG},
60     {Uri_CREATE_PRE_PROCESS_HTML_URI | Uri_CREATE_NO_PRE_PROCESS_HTML_URI, E_INVALIDARG},
61     {Uri_CREATE_IE_SETTINGS | Uri_CREATE_NO_IE_SETTINGS, E_INVALIDARG}
62 };
63
64 typedef struct _uri_str_property {
65     const char* value;
66     HRESULT     expected;
67     BOOL        todo;
68 } uri_str_property;
69
70 typedef struct _uri_dword_property {
71     DWORD   value;
72     HRESULT expected;
73     BOOL    todo;
74 } uri_dword_property;
75
76 typedef struct _uri_properties {
77     const char*         uri;
78     DWORD               create_flags;
79     HRESULT             create_expected;
80     BOOL                create_todo;
81
82     uri_str_property    str_props[URI_STR_PROPERTY_COUNT];
83     uri_dword_property  dword_props[URI_DWORD_PROPERTY_COUNT];
84 } uri_properties;
85
86 static const uri_properties uri_tests[] = {
87     {   "http://www.winehq.org/tests/../tests/../..", 0, S_OK, FALSE,
88         {
89             {"http://www.winehq.org/",S_OK,TRUE},                       /* ABSOLUTE_URI */
90             {"www.winehq.org",S_OK,TRUE},                               /* AUTHORITY */
91             {"http://www.winehq.org/",S_OK,TRUE},                       /* DISPLAY_URI */
92             {"winehq.org",S_OK,TRUE},                                   /* DOMAIN */
93             {"",S_FALSE,TRUE},                                          /* EXTENSION */
94             {"",S_FALSE,TRUE},                                          /* FRAGMENT */
95             {"www.winehq.org",S_OK,TRUE},                               /* HOST */
96             {"",S_FALSE,TRUE},                                          /* PASSWORD */
97             {"/",S_OK,TRUE},                                            /* PATH */
98             {"/",S_OK,TRUE},                                            /* PATH_AND_QUERY */
99             {"",S_FALSE,TRUE},                                          /* QUERY */
100             {"http://www.winehq.org/tests/../tests/../..",S_OK,TRUE},   /* RAW_URI */
101             {"http",S_OK,TRUE},                                         /* SCHEME_NAME */
102             {"",S_FALSE,TRUE},                                          /* USER_INFO */
103             {"",S_FALSE,TRUE}                                           /* USER_NAME */
104         },
105         {
106             {Uri_HOST_DNS,S_OK,TRUE},                                   /* HOST_TYPE */
107             {80,S_OK,TRUE},                                             /* PORT */
108             {URL_SCHEME_HTTP,S_OK,TRUE},                                /* SCHEME */
109             {URLZONE_INVALID,E_NOTIMPL,FALSE}                           /* ZONE */
110         }
111     },
112     {   "http://winehq.org/tests/.././tests", 0, S_OK, FALSE,
113         {
114             {"http://winehq.org/tests",S_OK,TRUE},
115             {"winehq.org",S_OK,TRUE},
116             {"http://winehq.org/tests",S_OK,TRUE},
117             {"winehq.org",S_OK,TRUE},
118             {"",S_FALSE,TRUE},
119             {"",S_FALSE,TRUE},
120             {"winehq.org",S_OK,TRUE},
121             {"",S_FALSE,TRUE},
122             {"/tests",S_OK,TRUE},
123             {"/tests",S_OK,TRUE},
124             {"",S_FALSE,TRUE},
125             {"http://winehq.org/tests/.././tests",S_OK,TRUE},
126             {"http",S_OK,TRUE},
127             {"",S_FALSE,TRUE},
128             {"",S_FALSE,TRUE}
129         },
130         {
131             {Uri_HOST_DNS,S_OK,TRUE},
132             {80,S_OK,TRUE},
133             {URL_SCHEME_HTTP,S_OK,TRUE},
134             {URLZONE_INVALID,E_NOTIMPL,FALSE}
135         }
136     },
137     {   "HtTp://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
138         {
139             {"http://www.winehq.org/?query=x&return=y",S_OK,TRUE},
140             {"www.winehq.org",S_OK,TRUE},
141             {"http://www.winehq.org/?query=x&return=y",S_OK,TRUE},
142             {"winehq.org",S_OK,TRUE},
143             {"",S_FALSE,TRUE},
144             {"",S_FALSE,TRUE},
145             {"www.winehq.org",S_OK,TRUE},
146             {"",S_FALSE,TRUE},
147             {"/",S_OK,TRUE},
148             {"/?query=x&return=y",S_OK,TRUE},
149             {"?query=x&return=y",S_OK,TRUE},
150             {"HtTp://www.winehq.org/tests/..?query=x&return=y",S_OK,TRUE},
151             {"http",S_OK,TRUE},
152             {"",S_FALSE,TRUE},
153             {"",S_FALSE,TRUE}
154         },
155         {
156             {Uri_HOST_DNS,S_OK,TRUE},
157             {80,S_OK,TRUE},
158             {URL_SCHEME_HTTP,S_OK,TRUE},
159             {URLZONE_INVALID,E_NOTIMPL,FALSE},
160         }
161     },
162     {   "hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters", 0, S_OK, FALSE,
163         {
164             {"http://usEr%3Ainfo@example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
165             {"usEr%3Ainfo@example.com",S_OK,TRUE},
166             {"http://example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
167             {"example.com",S_OK,TRUE},
168             {"",S_FALSE,TRUE},
169             {"",S_FALSE,TRUE},
170             {"example.com",S_OK,TRUE},
171             {"",S_FALSE,TRUE},
172             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
173             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
174             {"",S_FALSE,TRUE},
175             {"hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters",S_OK,TRUE},
176             {"http",S_OK,TRUE},
177             {"usEr%3Ainfo",S_OK,TRUE},
178             {"usEr%3Ainfo",S_OK,TRUE}
179         },
180         {
181             {Uri_HOST_DNS,S_OK,TRUE},
182             {80,S_OK,TRUE},
183             {URL_SCHEME_HTTP,S_OK,TRUE},
184             {URLZONE_INVALID,E_NOTIMPL,FALSE},
185         }
186     },
187     {   "ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt", 0, S_OK, FALSE,
188         {
189             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,TRUE},
190             {"winepass:wine@ftp.winehq.org:9999",S_OK,TRUE},
191             {"ftp://ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,TRUE},
192             {"winehq.org",S_OK,TRUE},
193             {".txt",S_OK,TRUE},
194             {"",S_FALSE,TRUE},
195             {"ftp.winehq.org",S_OK,TRUE},
196             {"wine",S_OK,TRUE},
197             {"/dir/foo%20bar.txt",S_OK,TRUE},
198             {"/dir/foo%20bar.txt",S_OK,TRUE},
199             {"",S_FALSE,TRUE},
200             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt",S_OK,TRUE},
201             {"ftp",S_OK,TRUE},
202             {"winepass:wine",S_OK,TRUE},
203             {"winepass",S_OK,TRUE}
204         },
205         {
206             {Uri_HOST_DNS,S_OK,TRUE},
207             {9999,S_OK,TRUE},
208             {URL_SCHEME_FTP,S_OK,TRUE},
209             {URLZONE_INVALID,E_NOTIMPL,FALSE}
210         }
211     },
212     {   "file://c:\\tests\\../tests/foo%20bar.mp3", 0, S_OK, FALSE,
213         {
214             {"file:///c:/tests/foo%2520bar.mp3",S_OK,TRUE},
215             {"",S_FALSE,TRUE},
216             {"file:///c:/tests/foo%2520bar.mp3",S_OK,TRUE},
217             {"",S_FALSE,TRUE},
218             {".mp3",S_OK,TRUE},
219             {"",S_FALSE,TRUE},
220             {"",S_FALSE,TRUE},
221             {"",S_FALSE,TRUE},
222             {"/c:/tests/foo%2520bar.mp3",S_OK,TRUE},
223             {"/c:/tests/foo%2520bar.mp3",S_OK,TRUE},
224             {"",S_FALSE,TRUE},
225             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,TRUE},
226             {"file",S_OK,TRUE},
227             {"",S_FALSE,TRUE},
228             {"",S_FALSE,TRUE}
229         },
230         {
231             {Uri_HOST_UNKNOWN,S_OK,TRUE},
232             {0,S_FALSE,TRUE},
233             {URL_SCHEME_FILE,S_OK,TRUE},
234             {URLZONE_INVALID,E_NOTIMPL,FALSE}
235         }
236     },
237     {   "FILE://localhost/test dir\\../tests/test%20file.README.txt", 0, S_OK, FALSE,
238         {
239             {"file:///tests/test%20file.README.txt",S_OK,TRUE},
240             {"",S_FALSE,TRUE},
241             {"file:///tests/test%20file.README.txt",S_OK,TRUE},
242             {"",S_FALSE,TRUE},
243             {".txt",S_OK,TRUE},
244             {"",S_FALSE,TRUE},
245             {"",S_FALSE,TRUE},
246             {"",S_FALSE,TRUE},
247             {"/tests/test%20file.README.txt",S_OK,TRUE},
248             {"/tests/test%20file.README.txt",S_OK,TRUE},
249             {"",S_FALSE,TRUE},
250             {"FILE://localhost/test dir\\../tests/test%20file.README.txt",S_OK,TRUE},
251             {"file",S_OK,TRUE},
252             {"",S_FALSE,TRUE},
253             {"",S_FALSE,TRUE}
254         },
255         {
256             {Uri_HOST_UNKNOWN,S_OK,TRUE},
257             {0,S_FALSE,TRUE},
258             {URL_SCHEME_FILE,S_OK,TRUE},
259             {URLZONE_INVALID,E_NOTIMPL,FALSE}
260         }
261     },
262     {   "urn:nothing:should:happen here", 0, S_OK, FALSE,
263         {
264             {"urn:nothing:should:happen here",S_OK,TRUE},
265             {"",S_FALSE,TRUE},
266             {"urn:nothing:should:happen here",S_OK,TRUE},
267             {"",S_FALSE,TRUE},
268             {"",S_FALSE,TRUE},
269             {"",S_FALSE,TRUE},
270             {"",S_FALSE,TRUE},
271             {"",S_FALSE,TRUE},
272             {"nothing:should:happen here",S_OK,TRUE},
273             {"nothing:should:happen here",S_OK,TRUE},
274             {"",S_FALSE,TRUE},
275             {"urn:nothing:should:happen here",S_OK,TRUE},
276             {"urn",S_OK,TRUE},
277             {"",S_FALSE,TRUE},
278             {"",S_FALSE,TRUE}
279         },
280         {
281             {Uri_HOST_UNKNOWN,S_OK,TRUE},
282             {0,S_FALSE,TRUE},
283             {URL_SCHEME_UNKNOWN,S_OK,TRUE},
284             {URLZONE_INVALID,E_NOTIMPL,FALSE}
285         }
286     }
287 };
288
289 static inline LPWSTR a2w(LPCSTR str) {
290     LPWSTR ret = NULL;
291
292     if(str) {
293         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
294         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
295         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
296     }
297
298     return ret;
299 }
300
301 static inline BOOL heap_free(void* mem) {
302     return HeapFree(GetProcessHeap(), 0, mem);
303 }
304
305 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
306     LPWSTR strAW = a2w(strA);
307     DWORD ret = lstrcmpW(strAW, strB);
308     heap_free(strAW);
309     return ret;
310 }
311
312 /*
313  * Simple tests to make sure the CreateUri function handles invalid flag combinations
314  * correctly.
315  */
316 static void test_CreateUri_InvalidFlags(void) {
317     DWORD i;
318
319     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
320         HRESULT hr;
321         IUri *uri = (void*) 0xdeadbeef;
322
323         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
324         todo_wine {
325             ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
326                     hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
327         }
328         todo_wine { ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri); }
329     }
330 }
331
332 static void test_CreateUri_InvalidArgs(void) {
333     HRESULT hr;
334     IUri *uri = (void*) 0xdeadbeef;
335
336     hr = pCreateUri(http_urlW, 0, 0, NULL);
337     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
338
339     hr = pCreateUri(NULL, 0, 0, &uri);
340     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
341     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
342 }
343
344 static void test_IUri_GetPropertyBSTR(void) {
345     DWORD i;
346
347     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
348         uri_properties test = uri_tests[i];
349         HRESULT hr;
350         IUri *uri = NULL;
351         LPWSTR uriW;
352
353         uriW = a2w(test.uri);
354         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
355         if(test.create_todo) {
356             todo_wine {
357                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
358                         hr, test.create_expected, i);
359             }
360         } else {
361             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
362                     hr, test.create_expected, i);
363         }
364
365         if(SUCCEEDED(hr)) {
366             DWORD j;
367
368             /* Checks all the string properties of the uri. */
369             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
370                 BSTR received = NULL;
371                 uri_str_property prop = test.str_props[j];
372
373                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
374                 if(prop.todo) {
375                     todo_wine {
376                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
377                                 hr, prop.expected, i, j);
378                     }
379                     todo_wine {
380                         ok(!strcmp_aw(prop.value, received), "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
381                                 prop.value, wine_dbgstr_w(received), i, j);
382                     }
383                 } else {
384                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
385                             hr, prop.expected, i, j);
386                     ok(!strcmp_aw(prop.value, received), "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
387                             prop.value, wine_dbgstr_w(received), i, j);
388                 }
389
390                 SysFreeString(received);
391             }
392         }
393
394         if(uri) IUri_Release(uri);
395
396         heap_free(uriW);
397     }
398 }
399
400 static void test_IUri_GetPropertyDWORD(void) {
401     IUri *uri = NULL;
402     HRESULT hr;
403     DWORD i;
404
405     hr = pCreateUri(http_urlW, 0, 0, &uri);
406     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
407     if(SUCCEEDED(hr)) {
408         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
409         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
410     }
411     if(uri) IUri_Release(uri);
412
413     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
414         uri_properties test = uri_tests[i];
415         LPWSTR uriW;
416         uri = NULL;
417
418         uriW = a2w(test.uri);
419         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
420         if(test.create_todo) {
421             todo_wine {
422                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
423                         hr, test.create_expected, i);
424             }
425         } else {
426             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
427                     hr, test.create_expected, i);
428         }
429
430         if(SUCCEEDED(hr)) {
431             DWORD j;
432
433             /* Checks all the DWORD properties of the uri. */
434             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
435                 DWORD received;
436                 uri_dword_property prop = test.dword_props[j];
437
438                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
439                 if(prop.todo) {
440                     todo_wine {
441                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
442                                 hr, prop.expected, i, j);
443                     }
444                     todo_wine {
445                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
446                                 prop.value, received, i, j);
447                     }
448                 } else {
449                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
450                             hr, prop.expected, i, j);
451                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
452                             prop.value, received, i, j);
453                 }
454             }
455         }
456
457         if(uri) IUri_Release(uri);
458
459         heap_free(uriW);
460     }
461 }
462
463 START_TEST(uri) {
464     HMODULE hurlmon;
465
466     hurlmon = GetModuleHandle("urlmon.dll");
467     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
468
469     if(!pCreateUri) {
470         win_skip("CreateUri is not present, skipping tests.\n");
471         return;
472     }
473
474     trace("test CreateUri invalid flags...\n");
475     test_CreateUri_InvalidFlags();
476
477     trace("test CreateUri invalid args...\n");
478     test_CreateUri_InvalidArgs();
479
480     trace("test IUri_GetPropertyBSTR...\n");
481     test_IUri_GetPropertyBSTR();
482
483     trace("test IUri_GetPropretyDWORD...\n");
484     test_IUri_GetPropertyDWORD();
485 }