1/*
2Copyright (c) 2012, Broadcom Europe Ltd
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the copyright holder nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28#include <stdio.h>
29
30#include "containers/containers.h"
31#include "containers/core/containers_common.h"
32#include "containers/core/containers_logging.h"
33#include "containers/core/containers_uri.h"
34
35#define TEST_CHAR '.'
36#define TEST_STRING "test"
37#define TEST_NAME "name"
38#define TEST_VALUE "value"
39
40#define ARRAY_SIZE(X) (sizeof(X)/sizeof(*(X)))
41
42struct
43{
44 const char *before;
45 const char *after;
46} test_parse_uris[] = {
47 {"", NULL},
48 {"C:\\test\\filename", NULL},
49 {"/usr/local/nix/filename", NULL},
50 {"scheme-only:", NULL},
51 {"scheme:/and/path", NULL},
52 {"scheme:/and/path#with_fragment", NULL},
53 {"scheme:/and/path?query=true", NULL},
54 {"scheme:/and/path?multiple+queries=true&more=false", NULL},
55 {"scheme:/and/path?multiple+queries=true&more=false#and+a+fragment,+too", NULL},
56 {"scheme:C:\\Windows\\path", "scheme:C:%5CWindows%5Cpath"},
57 {"scheme:C:\\Windows\\path#with_fragment", "scheme:C:%5CWindows%5Cpath#with_fragment"},
58 {"scheme:C:\\Windows\\path?query=true", "scheme:C:%5CWindows%5Cpath?query=true"},
59 {"scheme:C:\\Windows\\path?query#and+fragment", "scheme:C:%5CWindows%5Cpath?query#and+fragment"},
60 {"scheme://just.host", NULL},
61 {"scheme://host/and/path", NULL},
62 {"scheme://host:port", NULL},
63 {"scheme://host:port/and/path", NULL},
64 {"scheme://127.0.0.1:port/and/path", NULL},
65 {"scheme://userinfo@host:port/and/path?query#fragment", NULL},
66 {"HTTP://www.EXAMPLE.com/", "http://www.example.com/"},
67 {"%48%54%54%50://%54%45%53%54/", "http://test/"},
68 {"scheme:esc%", "scheme:esc%25"},
69 {"scheme:esc%%", "scheme:esc%25%25"},
70 {"scheme:esc%%%", "scheme:esc"},
71 {"scheme:esc%1%", "scheme:esc%10"},
72 {"scheme:esc%%1", "scheme:esc%01"},
73 {"s+-.1234567890:", NULL},
74 {"scheme:///", NULL},
75 {"scheme://:just_port", NULL},
76 {"scheme://:port/and/path", NULL},
77 {"scheme://just_userinfo@", NULL},
78 {"scheme://userinfo@/and/path", NULL},
79 {"scheme://userinfo@:port/and/path", NULL},
80 {"%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f:", "%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F:"},
81 {"%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E%5F%60%7B%7C%7D%7E%7F:", "%20%21%22%23%24%25%26%27%28%29%2A+%2C-.%2F%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E_%60%7B%7C%7D~%7F:"},
82 {"scheme://%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E%5F%60%7B%7C%7D%7E%7F@", "scheme://%20!%22%23$%25&'()*+,-.%2F:;%3C=%3E%3F%40%5B%5C%5D%5E_%60%7B%7C%7D~%7F@"},
83 {"scheme://%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E%5F%60%7B%7C%7D%7E%7F", "scheme://%20!%22%23$%25&'()*+,-.%2F:;%3C=%3E%3F%40[%5C]%5E_%60%7B%7C%7D~%7F"},
84 {"scheme://:%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E%5F%60%7B%7C%7D%7E%7F", "scheme://:%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E_%60%7B%7C%7D~%7F"},
85 {"scheme:///%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E%5F%60%7B%7C%7D%7E%7F", "scheme:///%20!%22%23$%25&'()*+,-./:;%3C=%3E%3F@%5B%5C%5D%5E_%60%7B%7C%7D~%7F"},
86 {"scheme://?%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E%5F%60%7B%7C%7D%7E%7F", "scheme://?%20!%22%23$%25&'()*+,-./:;%3C=%3E?@%5B%5C%5D%5E_%60%7B%7C%7D~%7F"},
87 {"scheme://#%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E%5F%60%7B%7C%7D%7E%7F", "scheme://#%20!%22%23$%25&'()*+,-./:;%3C=%3E?@%5B%5C%5D%5E_%60%7B%7C%7D~%7F"},
88 {"scheme://[v6.1234:5678]/", NULL},
89 {"scheme://[::1]/", NULL},
90 {"scheme://[1234:5678:90ab:cdef:1234:5678:90ab:cdef]/", NULL},
91 {"scheme://[::1]:1/", NULL},
92 {"scheme://?", "scheme://"},
93 {"scheme://?#", "scheme://#"},
94 {"scheme://?q&&;&n=&=v&=&n=v", "scheme://?q&n=&n=v"},
95 {"ldap://[2001:db8::7]/c=GB?objectClass?one", NULL},
96 {"mailto:John.Doe@example.com", NULL},
97 {"news:comp.infosystems.www.servers.unix", NULL},
98 {"tel:+1-816-555-1212", NULL},
99 {"urn:oasis:names:specification:docbook:dtd:xml:4.1.2", NULL},
100};
101
102typedef struct build_uri_tag
103{
104 const char *expected_uri;
105 const char *scheme;
106 const char *userinfo;
107 const char *host;
108 const char *port;
109 const char *path;
110 const char *fragment;
111 const char **queries; /* Held as name then value. NULL values allowed. NULL name terminates list */
112} BUILD_URI_T;
113
114/* Test query lists */
115const char *no_queries[] = { NULL };
116const char *query_true[] = { "query", "true", NULL };
117const char *multiple_queries[] = { "multiple+queries", "true", "more", "false", NULL };
118const char *just_query[] = {"query", NULL, NULL};
119const char *complex_query[] = { "q", NULL, "n", "", "n", "v", NULL };
120const char *objectClass_one[] = { "objectClass?one", NULL, NULL };
121
122BUILD_URI_T test_build_uris[] = {
123 {"", NULL, NULL, NULL, NULL, NULL, NULL, no_queries },
124 {"C:\\test\\filename", NULL, NULL, NULL, NULL, "C:\\test\\filename", NULL, no_queries},
125 {"/usr/local/nix/filename", NULL, NULL, NULL, NULL, "/usr/local/nix/filename", NULL, no_queries},
126 {"scheme-only:", "scheme-only", NULL, NULL, NULL, NULL, NULL, no_queries},
127 {"scheme:/and/path", "scheme", NULL, NULL, NULL, "/and/path", NULL, no_queries},
128 {"scheme:/and/path#with_fragment", "scheme", NULL, NULL, NULL, "/and/path", "with_fragment", no_queries},
129 {"scheme:/and/path?query=true", "scheme", NULL, NULL, NULL, "/and/path", NULL, query_true},
130 {"scheme:/and/path?multiple+queries=true&more=false", "scheme", NULL, NULL, NULL, "/and/path", NULL, multiple_queries},
131 {"scheme:/and/path?multiple+queries=true&more=false#and+a+fragment,+too", "scheme", NULL, NULL, NULL, "/and/path", "and+a+fragment,+too", multiple_queries},
132 {"scheme://just.host", "scheme", NULL, "just.host", NULL, NULL, NULL, no_queries},
133 {"scheme://host/and/path", "scheme", NULL, "host", NULL, "/and/path", NULL, no_queries},
134 {"scheme://host:port", "scheme", NULL, "host", "port", NULL, NULL, no_queries},
135 {"scheme://host:port/and/path", "scheme", NULL, "host", "port", "/and/path", NULL, no_queries},
136 {"scheme://127.0.0.1:port/and/path", "scheme", NULL, "127.0.0.1", "port", "/and/path", NULL, no_queries},
137 {"scheme://userinfo@host:port/and/path?query#fragment", "scheme", "userinfo", "host", "port", "/and/path", "fragment", just_query},
138 {"scheme:///", "scheme", NULL, "", NULL, "/", NULL, no_queries },
139 {"scheme://:just_port", "scheme", NULL, "", "just_port", NULL, NULL, no_queries },
140 {"scheme://:port/and/path", "scheme", NULL, "", "port", "/and/path", NULL, no_queries },
141 {"scheme://just_userinfo@", "scheme", "just_userinfo", "", NULL, NULL, NULL, no_queries },
142 {"scheme://userinfo@/and/path", "scheme", "userinfo", "", NULL, "/and/path", NULL, no_queries },
143 {"scheme://userinfo@:port/and/path", "scheme", "userinfo", "", "port", "/and/path", NULL, no_queries },
144 {"scheme://", "scheme", NULL, "", NULL, NULL, NULL, no_queries },
145 {"scheme://#", "scheme", NULL, "", NULL, NULL, "", no_queries },
146 {"scheme://?q&n=&n=v", "scheme", NULL, "", NULL, NULL, NULL, complex_query},
147 {"ldap://[2001:db8::7]/c=GB?objectClass?one", "ldap", NULL, "[2001:db8::7]", NULL, "/c=GB", NULL, objectClass_one},
148 {"mailto:John.Doe@example.com", "mailto", NULL, NULL, NULL, "John.Doe@example.com", NULL, no_queries },
149 {"news:comp.infosystems.www.servers.unix", "news", NULL, NULL, NULL, "comp.infosystems.www.servers.unix", NULL, no_queries },
150 {"tel:+1-816-555-1212", "tel", NULL, NULL, NULL, "+1-816-555-1212", NULL, no_queries },
151 {"urn:oasis:names:specification:docbook:dtd:xml:4.1.2", "urn", NULL, NULL, NULL, "oasis:names:specification:docbook:dtd:xml:4.1.2", NULL, no_queries },
152};
153
154typedef struct merge_uri_tag
155{
156 const char *base;
157 const char *relative;
158 const char *merged;
159} MERGE_URI_T;
160
161MERGE_URI_T test_merge_uris[] = {
162 /* Normal examples */
163 { "http://a/b/c/d;p?q#f", "ftp:h", "ftp:h" },
164 { "http://a/b/c/d;p?q#f", "g", "http://a/b/c/g" },
165 { "http://a/b/c/d;p?q#f", "./g", "http://a/b/c/g" },
166 { "http://a/b/c/d;p?q#f", "g/", "http://a/b/c/g/" },
167 { "http://a/b/c/d;p?q#f", "/g", "http://a/g" },
168 { "http://a/b/c/d;p?q#f", "//g", "http://g" },
169 { "http://a/b/c/d;p?q#f", "?y", "http://a/b/c/d;p?y" },
170 { "http://a/b/c/d;p?q#f", "g?y", "http://a/b/c/g?y" },
171 { "http://a/b/c/d;p?q#f", "g?y/./x", "http://a/b/c/g?y/./x" },
172 { "http://a/b/c/d;p?q#f", "#s", "http://a/b/c/d;p?q#s" },
173 { "http://a/b/c/d;p?q#f", "g#s", "http://a/b/c/g#s" },
174 { "http://a/b/c/d;p?q#f", "g#s/./x", "http://a/b/c/g#s/./x" },
175 { "http://a/b/c/d;p?q#f", "g?y#s", "http://a/b/c/g?y#s" },
176 { "http://a/b/c/d;p?q#f", ";x", "http://a/b/c/d;x" },
177 { "http://a/b/c/d;p?q#f", "g;x", "http://a/b/c/g;x" },
178 { "http://a/b/c/d;p?q#f", "g;x?y#s", "http://a/b/c/g;x?y#s" },
179 { "http://a/b/c/d;p?q#f", ".", "http://a/b/c/" },
180 { "http://a/b/c/d;p?q#f", "./", "http://a/b/c/" },
181 { "http://a/b/c/d;p?q#f", "..", "http://a/b/" },
182 { "http://a/b/c/d;p?q#f", "../", "http://a/b/" },
183 { "http://a/b/c/d;p?q#f", "../g", "http://a/b/g" },
184 { "http://a/b/c/d;p?q#f", "../..", "http://a/" },
185 { "http://a/b/c/d;p?q#f", "../../", "http://a/" },
186 { "http://a/b/c/d;p?q#f", "../../g", "http://a/g" },
187 /* Normal examples, without base network info */
188 { "http:/b/c/d;p?q#f", "g", "http:/b/c/g" },
189 { "http:/b/c/d;p?q#f", "./g", "http:/b/c/g" },
190 { "http:/b/c/d;p?q#f", "g/", "http:/b/c/g/" },
191 { "http:/b/c/d;p?q#f", "/g", "http:/g" },
192 { "http:/b/c/d;p?q#f", "//g", "http://g" },
193 { "http:/b/c/d;p?q#f", "?y", "http:/b/c/d;p?y" },
194 { "http:/b/c/d;p?q#f", "g?y", "http:/b/c/g?y" },
195 { "http:/b/c/d;p?q#f", "g?y/./x", "http:/b/c/g?y/./x" },
196 { "http:/b/c/d;p?q#f", "#s", "http:/b/c/d;p?q#s" },
197 { "http:/b/c/d;p?q#f", "g#s", "http:/b/c/g#s" },
198 { "http:/b/c/d;p?q#f", "g#s/./x", "http:/b/c/g#s/./x" },
199 { "http:/b/c/d;p?q#f", "g?y#s", "http:/b/c/g?y#s" },
200 { "http:/b/c/d;p?q#f", ";x", "http:/b/c/d;x" },
201 { "http:/b/c/d;p?q#f", "g;x", "http:/b/c/g;x" },
202 { "http:/b/c/d;p?q#f", "g;x?y#s", "http:/b/c/g;x?y#s" },
203 { "http:/b/c/d;p?q#f", ".", "http:/b/c/" },
204 { "http:/b/c/d;p?q#f", "./", "http:/b/c/" },
205 { "http:/b/c/d;p?q#f", "..", "http:/b/" },
206 { "http:/b/c/d;p?q#f", "../", "http:/b/" },
207 { "http:/b/c/d;p?q#f", "../g", "http:/b/g" },
208 { "http:/b/c/d;p?q#f", "../..", "http:/" },
209 { "http:/b/c/d;p?q#f", "../../", "http:/" },
210 { "http:/b/c/d;p?q#f", "../../g", "http:/g" },
211 /* Normal examples, without base network info or path root */
212 { "http:b/c/d;p?q#f", "g", "http:b/c/g" },
213 { "http:b/c/d;p?q#f", "./g", "http:b/c/g" },
214 { "http:b/c/d;p?q#f", "g/", "http:b/c/g/" },
215 { "http:b/c/d;p?q#f", "/g", "http:/g" },
216 { "http:b/c/d;p?q#f", "//g", "http://g" },
217 { "http:b/c/d;p?q#f", "?y", "http:b/c/d;p?y" },
218 { "http:b/c/d;p?q#f", "g?y", "http:b/c/g?y" },
219 { "http:b/c/d;p?q#f", "g?y/./x", "http:b/c/g?y/./x" },
220 { "http:b/c/d;p?q#f", "#s", "http:b/c/d;p?q#s" },
221 { "http:b/c/d;p?q#f", "g#s", "http:b/c/g#s" },
222 { "http:b/c/d;p?q#f", "g#s/./x", "http:b/c/g#s/./x" },
223 { "http:b/c/d;p?q#f", "g?y#s", "http:b/c/g?y#s" },
224 { "http:b/c/d;p?q#f", ";x", "http:b/c/d;x" },
225 { "http:b/c/d;p?q#f", "g;x", "http:b/c/g;x" },
226 { "http:b/c/d;p?q#f", "g;x?y#s", "http:b/c/g;x?y#s" },
227 { "http:b/c/d;p?q#f", ".", "http:b/c/" },
228 { "http:b/c/d;p?q#f", "./", "http:b/c/" },
229 { "http:b/c/d;p?q#f", "..", "http:b/" },
230 { "http:b/c/d;p?q#f", "../", "http:b/" },
231 { "http:b/c/d;p?q#f", "../g", "http:b/g" },
232 { "http:b/c/d;p?q#f", "../..", "http:" },
233 { "http:b/c/d;p?q#f", "../../", "http:" },
234 { "http:b/c/d;p?q#f", "../../g", "http:g" },
235 /* Normal examples, without base path */
236 { "http://a?q#f", "g", "http://a/g" },
237 { "http://a?q#f", "./g", "http://a/g" },
238 { "http://a?q#f", "g/", "http://a/g/" },
239 { "http://a?q#f", "/g", "http://a/g" },
240 { "http://a?q#f", "//g", "http://g" },
241 { "http://a?q#f", "?y", "http://a?y" },
242 { "http://a?q#f", "g?y", "http://a/g?y" },
243 { "http://a?q#f", "g?y/./x", "http://a/g?y/./x" },
244 { "http://a?q#f", "#s", "http://a?q#s" },
245 { "http://a?q#f", "g#s", "http://a/g#s" },
246 { "http://a?q#f", "g#s/./x", "http://a/g#s/./x" },
247 { "http://a?q#f", "g?y#s", "http://a/g?y#s" },
248 { "http://a?q#f", ";x", "http://a/;x" },
249 { "http://a?q#f", "g;x", "http://a/g;x" },
250 { "http://a?q#f", "g;x?y#s", "http://a/g;x?y#s" },
251 { "http://a?q#f", ".", "http://a/" },
252 { "http://a?q#f", "./", "http://a/" },
253 /* Normal examples, without base network info or path */
254 { "http:?q#f", "g", "http:g" },
255 { "http:?q#f", "./g", "http:g" },
256 { "http:?q#f", "g/", "http:g/" },
257 { "http:?q#f", "/g", "http:/g" },
258 { "http:?q#f", "//g", "http://g" },
259 { "http:?q#f", "?y", "http:?y" },
260 { "http:?q#f", "g?y", "http:g?y" },
261 { "http:?q#f", "g?y/./x", "http:g?y/./x" },
262 { "http:?q#f", "#s", "http:?q#s" },
263 { "http:?q#f", "g#s", "http:g#s" },
264 { "http:?q#f", "g#s/./x", "http:g#s/./x" },
265 { "http:?q#f", "g?y#s", "http:g?y#s" },
266 { "http:?q#f", ";x", "http:;x" },
267 { "http:?q#f", "g;x", "http:g;x" },
268 { "http:?q#f", "g;x?y#s", "http:g;x?y#s" },
269 /* Abnormal (but valid) examples */
270 { "http://a/b/c/d;p?q#f", "../../../g", "http://a/../g" },
271 { "http://a/b/c/d;p?q#f", "../../../../g", "http://a/../../g" },
272 { "http://a/b/c/d;p?q#f", "/./g", "http://a/./g" },
273 { "http://a/b/c/d;p?q#f", "/../g", "http://a/../g" },
274 { "http://a/b/c/d;p?q#f", "g.", "http://a/b/c/g." },
275 { "http://a/b/c/d;p?q#f", ".g", "http://a/b/c/.g" },
276 { "http://a/b/c/d;p?q#f", "g..", "http://a/b/c/g.." },
277 { "http://a/b/c/d;p?q#f", "..g", "http://a/b/c/..g" },
278 { "http://a/b/c/d;p?q#f", "./../g", "http://a/b/g" },
279 { "http://a/b/c/d;p?q#f", "./g/.", "http://a/b/c/g/" },
280 { "http://a/b/c/d;p?q#f", "g/./h", "http://a/b/c/g/h" },
281 { "http://a/b/c/d;p?q#f", "g/../h", "http://a/b/c/h" },
282 { "http://a/b/c/d;p?q#f", "./g:h", "http://a/b/c/g:h" },
283 { "http://a/b/c/d;p?q#f", "g/..", "http://a/b/c/" },
284 /* Abnormal examples without base path */
285 { "http://a?q#f", "../g", "http://a/../g" },
286 { "http://a?q#f", "./../g", "http://a/../g" },
287 /* Abnormal examples without base network info or path */
288 { "http:?q#f", "../g", "http:../g" },
289 { "http:?q#f", "./../g", "http:../g" },
290 { "http:?q#f", ".", "http:" },
291 { "http:?q#f", "./", "http:" },
292};
293
294
295/** Dump a URI structure to the log.
296 *
297 * \param uri URI structure to be dumped. */
298static void dump_uri(VC_URI_PARTS_T *uri)
299{
300 const char *str;
301 uint32_t query_count, ii;
302
303 str = vc_uri_scheme(uri);
304 if (str)
305 LOG_DEBUG(NULL, "Scheme: <%s>", str);
306
307 str = vc_uri_userinfo(uri);
308 if (str)
309 LOG_DEBUG(NULL, "Userinfo: <%s>", str);
310
311 str = vc_uri_host(uri);
312 if (str)
313 LOG_DEBUG(NULL, "Host: <%s>", str);
314
315 str = vc_uri_port(uri);
316 if (str)
317 LOG_DEBUG(NULL, "Port: <%s>", str);
318
319 str = vc_uri_path(uri);
320 if (str)
321 LOG_DEBUG(NULL, "Path: <%s>", str);
322
323 query_count = vc_uri_num_queries(uri);
324 for (ii = 0; ii < query_count; ii++)
325 {
326 const char *value;
327
328 vc_uri_query(uri, ii, &str, &value);
329 if (str)
330 {
331 if (value)
332 LOG_DEBUG(NULL, "Query %d: <%s>=<%s>", ii, str, value);
333 else
334 LOG_DEBUG(NULL, "Query %d: <%s>", ii, str);
335 }
336 }
337
338 str = vc_uri_fragment(uri);
339 if (str)
340 LOG_DEBUG(NULL, "Fragment: <%s>", str);
341}
342
343static int check_uri(VC_URI_PARTS_T *uri, const char *expected)
344{
345 uint32_t built_len;
346 char *built;
347
348 built_len = vc_uri_build(uri, NULL, 0) + 1;
349 built = (char *)malloc(built_len);
350 if (!built)
351 {
352 LOG_ERROR(NULL, "*** Unexpected memory allocation failure: %d bytes", built_len);
353 return 1;
354 }
355
356 vc_uri_build(uri, built, built_len);
357
358 if (strcmp(built, expected) != 0)
359 {
360 LOG_ERROR(NULL, "*** Built URI <%s>\nexpected <%s>", built, expected);
361 free(built);
362 return 1;
363 }
364
365 free(built);
366
367 return 0;
368}
369
370static int check_null_uri_pointer(void)
371{
372 int error_count = 0;
373 char buffer[1];
374
375 /* Check NULL URI can be passed without failure to all routines */
376 vc_uri_release( NULL );
377 vc_uri_clear( NULL );
378 if (vc_uri_parse( NULL, NULL ))
379 error_count++;
380 if (vc_uri_parse( NULL, "" ))
381 error_count++;
382 if (vc_uri_build( NULL, NULL, 0 ) != 0)
383 error_count++;
384 buffer[0] = TEST_CHAR;
385 if (vc_uri_build( NULL, buffer, sizeof(buffer) ) != 0)
386 error_count++;
387 if (buffer[0] != TEST_CHAR)
388 error_count++;
389 if (vc_uri_scheme( NULL ))
390 error_count++;
391 if (vc_uri_userinfo( NULL ))
392 error_count++;
393 if (vc_uri_host( NULL ))
394 error_count++;
395 if (vc_uri_port( NULL ))
396 error_count++;
397 if (vc_uri_path( NULL ))
398 error_count++;
399 if (vc_uri_fragment( NULL ))
400 error_count++;
401 if (vc_uri_num_queries( NULL ) != 0)
402 error_count++;
403 vc_uri_query( NULL, 0, NULL, NULL );
404 if (vc_uri_set_scheme( NULL, NULL ))
405 error_count++;
406 if (vc_uri_set_userinfo( NULL, NULL ))
407 error_count++;
408 if (vc_uri_set_host( NULL, NULL ))
409 error_count++;
410 if (vc_uri_set_port( NULL, NULL ))
411 error_count++;
412 if (vc_uri_set_path( NULL, NULL ))
413 error_count++;
414 if (vc_uri_set_fragment( NULL, NULL ))
415 error_count++;
416 if (vc_uri_add_query( NULL, NULL, NULL ))
417 error_count++;
418
419 if (error_count)
420 LOG_ERROR(NULL, "NULL URI parameter testing failed");
421
422 return error_count;
423}
424
425static int check_parse_parameters(VC_URI_PARTS_T *uri)
426{
427 int error_count = 0;
428
429 if (vc_uri_parse( uri, NULL ))
430 {
431 LOG_ERROR(NULL, "Parsing NULL URI failed");
432 error_count++;
433 }
434
435 return error_count;
436}
437
438static int check_build_parameters(VC_URI_PARTS_T *uri)
439{
440 int error_count = 0;
441 char buffer[1];
442
443 vc_uri_set_path( uri, TEST_STRING );
444
445 if (vc_uri_build( uri, NULL, 0 ) != strlen(TEST_STRING))
446 {
447 LOG_ERROR(NULL, "Retrieving URI length failed");
448 error_count++;
449 }
450
451 buffer[0] = TEST_CHAR;
452 if (vc_uri_build( uri, buffer, 1 ) != strlen(TEST_STRING))
453 {
454 LOG_ERROR(NULL, "Building URI to small buffer failed");
455 error_count++;
456 }
457 if (buffer[0] != TEST_CHAR)
458 {
459 LOG_ERROR(NULL, "Building URI to small buffer modified buffer");
460 error_count++;
461 }
462
463 vc_uri_set_path( uri, NULL ); /* Reset uri */
464
465 return error_count;
466}
467
468static int check_get_defaults(VC_URI_PARTS_T *uri)
469{
470 int error_count = 0;
471 const char *name = NULL, *value = NULL;
472 char buffer[1];
473
474 if (vc_uri_scheme( uri ))
475 error_count++;
476 if (vc_uri_userinfo( uri ))
477 error_count++;
478 if (vc_uri_host( uri ))
479 error_count++;
480 if (vc_uri_port( uri ))
481 error_count++;
482 if (vc_uri_path( uri ))
483 error_count++;
484 if (vc_uri_fragment( uri ))
485 error_count++;
486 if (vc_uri_num_queries( uri ) != 0)
487 error_count++;
488
489 vc_uri_query( uri, 0, &name, &value );
490 if (name != NULL || value != NULL)
491 error_count++;
492
493 if (vc_uri_build(uri, NULL, 0) != 0)
494 error_count++;
495 buffer[0] = ~*TEST_STRING; /* Initialize with something */
496 vc_uri_build(uri, buffer, sizeof(buffer));
497 if (buffer[0] != '\0') /* Expect empty string */
498 error_count++;
499
500 if (error_count)
501 LOG_ERROR(NULL, "Getting default values gave unexpected values");
502
503 return error_count;
504}
505
506static int check_accessors(VC_URI_PARTS_T *uri)
507{
508 int error_count = 0;
509 const char *str;
510
511 if (vc_uri_set_scheme( uri, TEST_STRING ))
512 {
513 str = vc_uri_scheme(uri);
514 if (!str || strcmp(TEST_STRING, str))
515 error_count++;
516 if (!vc_uri_set_scheme( uri, NULL ))
517 error_count++;
518 if (vc_uri_scheme(uri))
519 error_count++;
520 } else
521 error_count++;
522
523 if (vc_uri_set_userinfo( uri, TEST_STRING ))
524 {
525 str = vc_uri_userinfo(uri);
526 if (!str || strcmp(TEST_STRING, str))
527 error_count++;
528 if (!vc_uri_set_userinfo( uri, NULL ))
529 error_count++;
530 if (vc_uri_userinfo(uri))
531 error_count++;
532 } else
533 error_count++;
534
535 if (vc_uri_set_host( uri, TEST_STRING ))
536 {
537 str = vc_uri_host(uri);
538 if (!str || strcmp(TEST_STRING, str))
539 error_count++;
540 if (!vc_uri_set_host( uri, NULL ))
541 error_count++;
542 if (vc_uri_host(uri))
543 error_count++;
544 } else
545 error_count++;
546
547 if (vc_uri_set_port( uri, TEST_STRING ))
548 {
549 str = vc_uri_port(uri);
550 if (!str || strcmp(TEST_STRING, str))
551 error_count++;
552 if (!vc_uri_set_port( uri, NULL ))
553 error_count++;
554 if (vc_uri_port(uri))
555 error_count++;
556 } else
557 error_count++;
558
559 if (vc_uri_set_path( uri, TEST_STRING ))
560 {
561 str = vc_uri_path(uri);
562 if (!str || strcmp(TEST_STRING, str))
563 error_count++;
564 if (!vc_uri_set_path( uri, NULL ))
565 error_count++;
566 if (vc_uri_path(uri))
567 error_count++;
568 } else
569 error_count++;
570
571 if (vc_uri_set_fragment( uri, TEST_STRING ))
572 {
573 str = vc_uri_fragment(uri);
574 if (!str || strcmp(TEST_STRING, str))
575 error_count++;
576 if (!vc_uri_set_fragment( uri, NULL ))
577 error_count++;
578 if (vc_uri_fragment(uri))
579 error_count++;
580 } else
581 error_count++;
582
583 if (vc_uri_add_query( uri, NULL, NULL ))
584 error_count++;
585 if (vc_uri_add_query( uri, NULL, TEST_VALUE ))
586 error_count++;
587 if (!vc_uri_add_query( uri, TEST_STRING, NULL ))
588 error_count++;
589 if (!vc_uri_add_query( uri, TEST_NAME, TEST_VALUE ))
590 error_count++;
591
592 if (vc_uri_num_queries(uri) == 2)
593 {
594 const char *name = NULL, *value = NULL;
595
596 vc_uri_query(uri, 0, &name, &value);
597 if (!name || strcmp(TEST_STRING, name))
598 error_count++;
599 if (value)
600 error_count++;
601
602 vc_uri_query(uri, 1, &name, &value);
603 if (!name || strcmp(TEST_NAME, name))
604 error_count++;
605 if (!value || strcmp(TEST_VALUE, value))
606 error_count++;
607 } else
608 error_count++;
609
610 if (error_count)
611 LOG_ERROR(NULL, "Accessors failed");
612
613 return error_count;
614}
615
616/** Test parameter validation
617 *
618 * \param uri Pre-created URI structure.
619 * \return 1 on error, 0 on success. */
620static int test_parameter_validation(VC_URI_PARTS_T *uri)
621{
622 int error_count = 0;
623
624 error_count += check_null_uri_pointer();
625 error_count += check_get_defaults(uri);
626 error_count += check_parse_parameters(uri);
627 error_count += check_build_parameters(uri);
628 error_count += check_accessors(uri);
629
630 return error_count;
631}
632
633/** Test parsing and rebuilding a URI.
634 *
635 * \param uri Pre-created URI structure.
636 * \param original The original URI string.
637 * \param expected The expected, re-built string, or NULL if original is expected.
638 * \return 1 on error, 0 on success. */
639static int test_parsing_uri(VC_URI_PARTS_T *uri, const char *original, const char *expected)
640{
641 bool parsed;
642
643 LOG_INFO(NULL, "URI: <%s>", original);
644
645 parsed = vc_uri_parse( uri, original );
646 if (!parsed)
647 {
648 LOG_ERROR(NULL, "*** Expected <%s> to parse, but it didn't", original);
649 return 1;
650 }
651
652 dump_uri(uri);
653
654 return check_uri(uri, expected ? expected : original);
655}
656
657/** Test building a URI from component parts.
658 *
659 * \param uri Pre-created URI structure.
660 * \param uri_data The data for building the URI and the expected output.
661 * \return 1 on error, 0 on success. */
662static int test_building_uri(VC_URI_PARTS_T *uri, BUILD_URI_T *uri_data)
663{
664 const char **p_str;
665 const char *name, *value;
666
667 LOG_INFO(NULL, "Building URI <%s>", uri_data->expected_uri);
668
669 vc_uri_clear(uri);
670
671 if (!vc_uri_set_scheme(uri, uri_data->scheme))
672 {
673 LOG_ERROR(NULL, "*** Failed to set scheme");
674 return 1;
675 }
676
677 if (!vc_uri_set_userinfo(uri, uri_data->userinfo))
678 {
679 LOG_ERROR(NULL, "*** Failed to set userinfo");
680 return 1;
681 }
682
683 if (!vc_uri_set_host(uri, uri_data->host))
684 {
685 LOG_ERROR(NULL, "*** Failed to set host");
686 return 1;
687 }
688
689 if (!vc_uri_set_port(uri, uri_data->port))
690 {
691 LOG_ERROR(NULL, "*** Failed to set port");
692 return 1;
693 }
694
695 if (!vc_uri_set_path(uri, uri_data->path))
696 {
697 LOG_ERROR(NULL, "*** Failed to set path");
698 return 1;
699 }
700
701 if (!vc_uri_set_fragment(uri, uri_data->fragment))
702 {
703 LOG_ERROR(NULL, "*** Failed to set fragment");
704 return 1;
705 }
706
707 p_str = uri_data->queries;
708 name = *p_str++;
709
710 while (name)
711 {
712 value = *p_str++;
713 if (!vc_uri_add_query(uri, name, value))
714 {
715 LOG_ERROR(NULL, "*** Failed to add query");
716 return 1;
717 }
718 name = *p_str++;
719 }
720
721 dump_uri(uri);
722
723 return check_uri(uri, uri_data->expected_uri);
724}
725
726/** Test merging a relative URI with a base URI.
727 *
728 * \param uri Pre-created URI structure.
729 * \param uri_data The nase and relative URIs and the expected output.
730 * \return 1 on error, 0 on success. */
731static int test_merging_uri(VC_URI_PARTS_T *uri, MERGE_URI_T *uri_data)
732{
733 VC_URI_PARTS_T *base_uri;
734
735 LOG_INFO(NULL, "Base <%s>, relative <%s>, expect <%s>", uri_data->base, uri_data->relative, uri_data->merged);
736
737 vc_uri_clear(uri);
738 base_uri = vc_uri_create();
739 if (!base_uri)
740 {
741 LOG_ERROR(NULL, "*** Failed to allocate base URI structure");
742 return 1;
743 }
744
745 if (!vc_uri_parse(base_uri, uri_data->base))
746 {
747 LOG_ERROR(NULL, "*** Failed to parse base URI structure");
748 return 1;
749 }
750 if (!vc_uri_parse(uri, uri_data->relative))
751 {
752 LOG_ERROR(NULL, "*** Failed to parse relative URI structure");
753 return 1;
754 }
755
756 if (!vc_uri_merge(base_uri, uri))
757 {
758 LOG_ERROR(NULL, "*** Failed to merge base and relative URIs");
759 return 1;
760 }
761
762 vc_uri_release(base_uri);
763
764 return check_uri(uri, uri_data->merged);
765}
766
767int main(int argc, char **argv)
768{
769 VC_URI_PARTS_T *uri;
770 int error_count = 0;
771 size_t ii;
772
773 uri = vc_uri_create();
774 if (!uri)
775 {
776 LOG_ERROR(NULL, "*** Failed to create URI structure.");
777 return 1;
778 }
779
780 LOG_INFO(NULL, "Test parameter validation");
781 error_count += test_parameter_validation(uri);
782
783 LOG_INFO(NULL, "Test parsing URIs:");
784 for (ii = 0; ii < ARRAY_SIZE(test_parse_uris); ii++)
785 {
786 error_count += test_parsing_uri(uri, test_parse_uris[ii].before, test_parse_uris[ii].after);
787 }
788
789 LOG_INFO(NULL, "Test building URIs:");
790 for (ii = 0; ii < ARRAY_SIZE(test_build_uris); ii++)
791 {
792 error_count += test_building_uri(uri, &test_build_uris[ii]);
793 }
794
795 LOG_INFO(NULL, "Test merging URIs:");
796 for (ii = 0; ii < ARRAY_SIZE(test_merge_uris); ii++)
797 {
798 error_count += test_merging_uri(uri, &test_merge_uris[ii]);
799 }
800
801 if (argc > 1)
802 {
803 LOG_INFO(NULL, "Test parsing URIs from command line:");
804
805 while (argc-- > 1)
806 {
807 /* Test URIs passed on the command line are expected to parse and to
808 * match themselves when rebuilt. */
809 error_count += test_parsing_uri(uri, argv[argc], NULL);
810 }
811 }
812
813 vc_uri_release(uri);
814
815 if (error_count)
816 LOG_ERROR(NULL, "*** %d errors reported", error_count);
817
818#ifdef _MSC_VER
819 LOG_INFO(NULL, "Press return to complete test.");
820 getchar();
821#endif
822
823 return error_count;
824}
825