urlmon/tests: Added tests for IUri_GetPropertyBSTR.
[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
41 #define URI_STR_PROPERTY_COUNT Uri_PROPERTY_STRING_LAST+1
42
43 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
44
45 static const WCHAR http_urlW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
46         '.','o','r','g','/',0};
47
48 typedef struct _uri_create_flag_test {
49     DWORD   flags;
50     HRESULT expected;
51 } uri_create_flag_test;
52
53 static const uri_create_flag_test invalid_flag_tests[] = {
54     /* Set of invalid flag combinations to test for. */
55     {Uri_CREATE_DECODE_EXTRA_INFO | Uri_CREATE_NO_DECODE_EXTRA_INFO, E_INVALIDARG},
56     {Uri_CREATE_CANONICALIZE | Uri_CREATE_NO_CANONICALIZE, E_INVALIDARG},
57     {Uri_CREATE_CRACK_UNKNOWN_SCHEMES | Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, E_INVALIDARG},
58     {Uri_CREATE_PRE_PROCESS_HTML_URI | Uri_CREATE_NO_PRE_PROCESS_HTML_URI, E_INVALIDARG},
59     {Uri_CREATE_IE_SETTINGS | Uri_CREATE_NO_IE_SETTINGS, E_INVALIDARG}
60 };
61
62 typedef struct _uri_str_property {
63     const char* value;
64     HRESULT     expected;
65     BOOL        todo;
66 } uri_str_property;
67
68 typedef struct _uri_properties {
69     const char*         uri;
70     DWORD               create_flags;
71     HRESULT             create_expected;
72     BOOL                create_todo;
73
74     uri_str_property    str_props[URI_STR_PROPERTY_COUNT];
75 } uri_properties;
76
77 static const uri_properties uri_tests[] = {
78     {   "http://www.winehq.org/tests/../tests/../..", 0, S_OK, FALSE,
79         {
80             {"http://www.winehq.org/",S_OK,TRUE},                       /* ABSOLUTE_URI */
81             {"www.winehq.org",S_OK,TRUE},                               /* AUTHORITY */
82             {"http://www.winehq.org/",S_OK,TRUE},                       /* DISPLAY_URI */
83             {"winehq.org",S_OK,TRUE},                                   /* DOMAIN */
84             {"",S_FALSE,TRUE},                                          /* EXTENSION */
85             {"",S_FALSE,TRUE},                                          /* FRAGMENT */
86             {"www.winehq.org",S_OK,TRUE},                               /* HOST */
87             {"",S_FALSE,TRUE},                                          /* PASSWORD */
88             {"/",S_OK,TRUE},                                            /* PATH */
89             {"/",S_OK,TRUE},                                            /* PATH_AND_QUERY */
90             {"",S_FALSE,TRUE},                                          /* QUERY */
91             {"http://www.winehq.org/tests/../tests/../..",S_OK,TRUE},   /* RAW_URI */
92             {"http",S_OK,TRUE},                                         /* SCHEME_NAME */
93             {"",S_FALSE,TRUE},                                          /* USER_INFO */
94             {"",S_FALSE,TRUE}                                           /* USER_NAME */
95         }
96     },
97     {   "http://winehq.org/tests/.././tests", 0, S_OK, FALSE,
98         {
99             {"http://winehq.org/tests",S_OK,TRUE},
100             {"winehq.org",S_OK,TRUE},
101             {"http://winehq.org/tests",S_OK,TRUE},
102             {"winehq.org",S_OK,TRUE},
103             {"",S_FALSE,TRUE},
104             {"",S_FALSE,TRUE},
105             {"winehq.org",S_OK,TRUE},
106             {"",S_FALSE,TRUE},
107             {"/tests",S_OK,TRUE},
108             {"/tests",S_OK,TRUE},
109             {"",S_FALSE,TRUE},
110             {"http://winehq.org/tests/.././tests",S_OK,TRUE},
111             {"http",S_OK,TRUE},
112             {"",S_FALSE,TRUE},
113             {"",S_FALSE,TRUE}
114         }
115     },
116     {   "HtTp://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
117         {
118             {"http://www.winehq.org/?query=x&return=y",S_OK,TRUE},
119             {"www.winehq.org",S_OK,TRUE},
120             {"http://www.winehq.org/?query=x&return=y",S_OK,TRUE},
121             {"winehq.org",S_OK,TRUE},
122             {"",S_FALSE,TRUE},
123             {"",S_FALSE,TRUE},
124             {"www.winehq.org",S_OK,TRUE},
125             {"",S_FALSE,TRUE},
126             {"/",S_OK,TRUE},
127             {"/?query=x&return=y",S_OK,TRUE},
128             {"?query=x&return=y",S_OK,TRUE},
129             {"HtTp://www.winehq.org/tests/..?query=x&return=y",S_OK,TRUE},
130             {"http",S_OK,TRUE},
131             {"",S_FALSE,TRUE},
132             {"",S_FALSE,TRUE}
133         }
134     },
135     {   "hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters", 0, S_OK, FALSE,
136         {
137             {"http://usEr%3Ainfo@example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
138             {"usEr%3Ainfo@example.com",S_OK,TRUE},
139             {"http://example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
140             {"example.com",S_OK,TRUE},
141             {"",S_FALSE,TRUE},
142             {"",S_FALSE,TRUE},
143             {"example.com",S_OK,TRUE},
144             {"",S_FALSE,TRUE},
145             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
146             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
147             {"",S_FALSE,TRUE},
148             {"hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters",S_OK,TRUE},
149             {"http",S_OK,TRUE},
150             {"usEr%3Ainfo",S_OK,TRUE},
151             {"usEr%3Ainfo",S_OK,TRUE}
152         }
153     },
154     {   "ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt", 0, S_OK, FALSE,
155         {
156             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,TRUE},
157             {"winepass:wine@ftp.winehq.org:9999",S_OK,TRUE},
158             {"ftp://ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,TRUE},
159             {"winehq.org",S_OK,TRUE},
160             {".txt",S_OK,TRUE},
161             {"",S_FALSE,TRUE},
162             {"ftp.winehq.org",S_OK,TRUE},
163             {"wine",S_OK,TRUE},
164             {"/dir/foo%20bar.txt",S_OK,TRUE},
165             {"/dir/foo%20bar.txt",S_OK,TRUE},
166             {"",S_FALSE,TRUE},
167             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt",S_OK,TRUE},
168             {"ftp",S_OK,TRUE},
169             {"winepass:wine",S_OK,TRUE},
170             {"winepass",S_OK,TRUE}
171         }
172     },
173     {   "file://c:\\tests\\../tests/foo%20bar.mp3", 0, S_OK, FALSE,
174         {
175             {"file:///c:/tests/foo%2520bar.mp3",S_OK,TRUE},
176             {"",S_FALSE,TRUE},
177             {"file:///c:/tests/foo%2520bar.mp3",S_OK,TRUE},
178             {"",S_FALSE,TRUE},
179             {".mp3",S_OK,TRUE},
180             {"",S_FALSE,TRUE},
181             {"",S_FALSE,TRUE},
182             {"",S_FALSE,TRUE},
183             {"/c:/tests/foo%2520bar.mp3",S_OK,TRUE},
184             {"/c:/tests/foo%2520bar.mp3",S_OK,TRUE},
185             {"",S_FALSE,TRUE},
186             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,TRUE},
187             {"file",S_OK,TRUE},
188             {"",S_FALSE,TRUE},
189             {"",S_FALSE,TRUE}
190         }
191     },
192     {   "FILE://localhost/test dir\\../tests/test%20file.README.txt", 0, S_OK, FALSE,
193         {
194             {"file:///tests/test%20file.README.txt",S_OK,TRUE},
195             {"",S_FALSE,TRUE},
196             {"file:///tests/test%20file.README.txt",S_OK,TRUE},
197             {"",S_FALSE,TRUE},
198             {".txt",S_OK,TRUE},
199             {"",S_FALSE,TRUE},
200             {"",S_FALSE,TRUE},
201             {"",S_FALSE,TRUE},
202             {"/tests/test%20file.README.txt",S_OK,TRUE},
203             {"/tests/test%20file.README.txt",S_OK,TRUE},
204             {"",S_FALSE,TRUE},
205             {"FILE://localhost/test dir\\../tests/test%20file.README.txt",S_OK,TRUE},
206             {"file",S_OK,TRUE},
207             {"",S_FALSE,TRUE},
208             {"",S_FALSE,TRUE}
209         }
210     },
211     {   "urn:nothing:should:happen here", 0, S_OK, FALSE,
212         {
213             {"urn:nothing:should:happen here",S_OK,TRUE},
214             {"",S_FALSE,TRUE},
215             {"urn:nothing:should:happen here",S_OK,TRUE},
216             {"",S_FALSE,TRUE},
217             {"",S_FALSE,TRUE},
218             {"",S_FALSE,TRUE},
219             {"",S_FALSE,TRUE},
220             {"",S_FALSE,TRUE},
221             {"nothing:should:happen here",S_OK,TRUE},
222             {"nothing:should:happen here",S_OK,TRUE},
223             {"",S_FALSE,TRUE},
224             {"urn:nothing:should:happen here",S_OK,TRUE},
225             {"urn",S_OK,TRUE},
226             {"",S_FALSE,TRUE},
227             {"",S_FALSE,TRUE}
228         }
229     }
230 };
231
232 static inline LPWSTR a2w(LPCSTR str) {
233     LPWSTR ret = NULL;
234
235     if(str) {
236         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
237         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
238         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
239     }
240
241     return ret;
242 }
243
244 static inline BOOL heap_free(void* mem) {
245     return HeapFree(GetProcessHeap(), 0, mem);
246 }
247
248 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
249     LPWSTR strAW = a2w(strA);
250     DWORD ret = lstrcmpW(strAW, strB);
251     heap_free(strAW);
252     return ret;
253 }
254
255 /*
256  * Simple tests to make sure the CreateUri function handles invalid flag combinations
257  * correctly.
258  */
259 static void test_CreateUri_InvalidFlags(void) {
260     DWORD i;
261
262     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
263         HRESULT hr;
264         IUri *uri = (void*) 0xdeadbeef;
265
266         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
267         todo_wine {
268             ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
269                     hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
270         }
271         todo_wine { ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri); }
272     }
273 }
274
275 static void test_CreateUri_InvalidArgs(void) {
276     HRESULT hr;
277     IUri *uri = (void*) 0xdeadbeef;
278
279     hr = pCreateUri(http_urlW, 0, 0, NULL);
280     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
281
282     hr = pCreateUri(NULL, 0, 0, &uri);
283     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
284     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
285 }
286
287 static void test_IUri_GetPropertyBSTR(void) {
288     DWORD i;
289
290     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
291         uri_properties test = uri_tests[i];
292         HRESULT hr;
293         IUri *uri = NULL;
294         LPWSTR uriW;
295
296         uriW = a2w(test.uri);
297         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
298         if(test.create_todo) {
299             todo_wine {
300                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
301                         hr, test.create_expected, i);
302             }
303         } else {
304             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
305                     hr, test.create_expected, i);
306         }
307
308         if(SUCCEEDED(hr)) {
309             DWORD j;
310
311             /* Checks all the string properties of the uri. */
312             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
313                 BSTR received = NULL;
314                 uri_str_property prop = test.str_props[j];
315
316                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
317                 if(prop.todo) {
318                     todo_wine {
319                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
320                                 hr, prop.expected, i, j);
321                     }
322                     todo_wine {
323                         ok(!strcmp_aw(prop.value, received), "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
324                                 prop.value, wine_dbgstr_w(received), i, j);
325                     }
326                 } else {
327                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
328                             hr, prop.expected, i, j);
329                     ok(!strcmp_aw(prop.value, received), "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
330                             prop.value, wine_dbgstr_w(received), i, j);
331                 }
332
333                 SysFreeString(received);
334             }
335         }
336
337         if(uri) IUri_Release(uri);
338
339         heap_free(uriW);
340     }
341 }
342
343 START_TEST(uri) {
344     HMODULE hurlmon;
345
346     hurlmon = GetModuleHandle("urlmon.dll");
347     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
348
349     if(!pCreateUri) {
350         win_skip("CreateUri is not present, skipping tests.\n");
351         return;
352     }
353
354     trace("test CreateUri invalid flags...\n");
355     test_CreateUri_InvalidFlags();
356
357     trace("test CreateUri invalid args...\n");
358     test_CreateUri_InvalidArgs();
359
360     trace("test IUri_GetPropertyBSTR...\n");
361     test_IUri_GetPropertyBSTR();
362 }