These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / tests / uri_test.c
1 /*
2  * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 /** @file
27  *
28  * URI self-tests
29  *
30  */
31
32 /* Forcibly enable assertions */
33 #undef NDEBUG
34
35 #include <string.h>
36 #include <byteswap.h>
37 #include <ipxe/uri.h>
38 #include <ipxe/params.h>
39 #include <ipxe/test.h>
40
41 /** A URI parsing/formatting test */
42 struct uri_test {
43         /** URI string */
44         const char *string;
45         /** URI */
46         struct uri uri;
47 };
48
49 /** A URI port number test */
50 struct uri_port_test {
51         /** URI string */
52         const char *string;
53         /** Default port number */
54         unsigned int default_port;
55         /** Expected port number */
56         unsigned int port;
57 };
58
59 /** A URI or path resolution test */
60 struct uri_resolve_test {
61         /** Base path or URI */
62         const char *base;
63         /** Relative path or URI */
64         const char *relative;
65         /** Expected resolved path or URI */
66         const char *resolved;
67 };
68
69 /** A TFTP URI test */
70 struct uri_tftp_test {
71         /** Next-server address */
72         struct in_addr next_server;
73         /** Port number */
74         unsigned int port;
75         /** Filename */
76         const char *filename;
77         /** URI */
78         struct uri uri;
79         /** URI string (for display only; cannot be reparsed) */
80         const char *string;
81 };
82
83 /** A current working URI test */
84 struct uri_churi_test {
85         /** Relative URI */
86         const char *relative;
87         /** Expected new working URI */
88         const char *expected;
89 };
90
91 /** A form parameter URI test list */
92 struct uri_params_test_list {
93         /** Key */
94         const char *key;
95         /** Value */
96         const char *value;
97 };
98
99 /** A form parameter URI test */
100 struct uri_params_test {
101         /** URI string */
102         const char *string;
103         /** URI */
104         struct uri uri;
105         /** Parameter list name */
106         const char *name;
107         /** Parameter list */
108         struct uri_params_test_list *list;
109 };
110
111 /**
112  * Compare two URI component strings
113  *
114  * @v first             First string, or NULL
115  * @v second            Second string, or NULL
116  * @v difference        Difference
117  */
118 static int uristrcmp ( const char *first, const char *second ) {
119
120         /* Compare strings, allowing for either to be NULL */
121         if ( first == second ) {
122                 return 0;
123         } else if ( ( first == NULL ) || ( second == NULL ) ) {
124                 return -1;
125         } else {
126                 return strcmp ( first, second );
127         }
128 }
129
130 /**
131  * Report URI equality test result
132  *
133  * @v uri               URI
134  * @v expected          Expected URI
135  * @v file              Test code file
136  * @v line              Test code line
137  */
138 static void uri_okx ( struct uri *uri, struct uri *expected, const char *file,
139                       unsigned int line ) {
140
141         okx ( uristrcmp ( uri->scheme, expected->scheme ) == 0, file, line );
142         okx ( uristrcmp ( uri->opaque, expected->opaque ) == 0, file, line );
143         okx ( uristrcmp ( uri->user, expected->user ) == 0, file, line );
144         okx ( uristrcmp ( uri->password, expected->password ) == 0, file, line);
145         okx ( uristrcmp ( uri->host, expected->host ) == 0, file, line );
146         okx ( uristrcmp ( uri->port, expected->port ) == 0, file, line );
147         okx ( uristrcmp ( uri->path, expected->path ) == 0, file, line );
148         okx ( uristrcmp ( uri->query, expected->query ) == 0, file, line );
149         okx ( uristrcmp ( uri->fragment, expected->fragment ) == 0, file, line);
150         okx ( uri->params == expected->params, file, line );
151 }
152 #define uri_ok( uri, expected ) uri_okx ( uri, expected, __FILE__, __LINE__ )
153
154 /**
155  * Report URI parsing test result
156  *
157  * @v test              URI test
158  * @v file              Test code file
159  * @v line              Test code line
160  */
161 static void uri_parse_okx ( struct uri_test *test, const char *file,
162                             unsigned int line ) {
163         struct uri *uri;
164
165         /* Parse URI */
166         uri = parse_uri ( test->string );
167         okx ( uri != NULL, file, line );
168         if ( uri )
169                 uri_okx ( uri, &test->uri, file, line );
170         uri_put ( uri );
171 }
172 #define uri_parse_ok( test ) uri_parse_okx ( test, __FILE__, __LINE__ )
173
174 /**
175  * Report URI formatting test result
176  *
177  * @v test              URI test
178  * @v file              Test code file
179  * @v line              Test code line
180  */
181 static void uri_format_okx ( struct uri_test *test, const char *file,
182                              unsigned int line ) {
183         char buf[ strlen ( test->string ) + 1 /* NUL */ ];
184         char *tmp;
185         size_t len;
186
187         /* Format into fixed-size buffer */
188         len = format_uri ( &test->uri, buf, sizeof ( buf ) );
189         okx ( len == ( sizeof ( buf ) - 1 /* NUL */ ), file, line );
190         okx ( strcmp ( buf, test->string ) == 0, file, line );
191
192         /* Format into temporarily allocated buffer */
193         tmp = format_uri_alloc ( &test->uri );
194         okx ( tmp != NULL, file, line );
195         if ( tmp )
196                 okx ( strcmp ( tmp, test->string ) == 0, file, line );
197         free ( tmp );
198 }
199 #define uri_format_ok( test ) uri_format_okx ( test, __FILE__, __LINE__ )
200
201 /**
202  * Report URI duplication test result
203  *
204  * @v test              URI
205  * @v file              Test code file
206  * @v line              Test code line
207  */
208 static void uri_dup_okx ( struct uri *uri, const char *file,
209                           unsigned int line ) {
210         struct uri *dup;
211
212         dup = uri_dup ( uri );
213         okx ( dup != NULL, file, line );
214         if ( dup )
215                 uri_okx ( dup, uri, file, line );
216         uri_put ( dup );
217 }
218 #define uri_dup_ok( test ) uri_dup_okx ( test, __FILE__, __LINE__ )
219
220 /**
221  * Report URI combined parsing and formatting test result
222  *
223  * @v test              URI test
224  * @v file              Test code file
225  * @v line              Test code line
226  */
227 static void uri_parse_format_dup_okx ( struct uri_test *test, const char *file,
228                                        unsigned int line ) {
229
230         uri_parse_okx ( test, file, line );
231         uri_format_okx ( test, file, line );
232         uri_dup_okx ( &test->uri, file, line );
233 }
234 #define uri_parse_format_dup_ok( test ) \
235         uri_parse_format_dup_okx ( test, __FILE__, __LINE__ )
236
237 /**
238  * Report URI port number test result
239  *
240  * @v test              URI port number test
241  * @v file              Test code file
242  * @v line              Test code line
243  */
244 static void uri_port_okx ( struct uri_port_test *test, const char *file,
245                            unsigned int line ) {
246         struct uri *uri;
247         unsigned int port;
248
249         /* Parse URI */
250         uri = parse_uri ( test->string );
251         okx ( uri != NULL, file, line );
252         if ( uri ) {
253                 port = uri_port ( uri, test->default_port );
254                 okx ( port == test->port, file, line );
255         }
256         uri_put ( uri );
257 }
258 #define uri_port_ok( test ) uri_port_okx ( test, __FILE__, __LINE__ )
259
260 /**
261  * Report URI resolution test result
262  *
263  * @v test              Path resolution test
264  * @v file              Test code file
265  * @v line              Test code line
266  */
267 static void uri_resolve_okx ( struct uri_resolve_test *test,
268                               const char *file, unsigned int line ) {
269         struct uri *base;
270         struct uri *relative;
271         struct uri *resolved = NULL;
272         char *formatted;
273
274         /* Parse URIs */
275         base = parse_uri ( test->base );
276         okx ( base != NULL, file, line );
277         relative = parse_uri ( test->relative );
278         okx ( relative != NULL, file, line );
279
280         /* Resolve URI  */
281         if ( base && relative ) {
282                 resolved = resolve_uri ( base, relative );
283                 okx ( resolved != NULL, file, line );
284         }
285
286         /* Format resolved URI */
287         formatted = format_uri_alloc ( resolved );
288         okx ( formatted != NULL, file, line );
289
290         /* Check resolved URI */
291         if ( formatted )
292                 okx ( strcmp ( formatted, test->resolved ) == 0, file, line );
293
294         free ( formatted );
295         uri_put ( resolved );
296         uri_put ( relative );
297         uri_put ( base );
298 }
299 #define uri_resolve_ok( test ) uri_resolve_okx ( test, __FILE__, __LINE__ )
300
301 /**
302  * Report path resolution test result
303  *
304  * @v test              Path resolution test
305  * @v file              Test code file
306  * @v line              Test code line
307  */
308 static void uri_resolve_path_okx ( struct uri_resolve_test *test,
309                                    const char *file, unsigned int line ) {
310         char *resolved;
311
312         /* Resolve paths using resolve_path() directly */
313         resolved = resolve_path ( test->base, test->relative );
314         okx ( resolved != NULL, file, line );
315         if ( resolved )
316                 okx ( strcmp ( resolved, test->resolved ) == 0, file, line );
317         free ( resolved );
318
319         /* Resolve paths as URIs (since all paths are valid URIs) */
320         uri_resolve_okx ( test, file, line );
321 }
322 #define uri_resolve_path_ok( test ) \
323         uri_resolve_path_okx ( test, __FILE__, __LINE__ )
324
325 /**
326  * Report URI TFTP test result
327  *
328  * @v test              URI TFTP test
329  * @v file              Test code file
330  * @v line              Test code line
331  */
332 static void uri_tftp_okx ( struct uri_tftp_test *test, const char *file,
333                            unsigned int line ) {
334         char buf[ strlen ( test->string ) + 1 /* NUL */ ];
335         struct uri *uri;
336         size_t len;
337
338         /* Construct URI */
339         uri = tftp_uri ( test->next_server, test->port, test->filename );
340         okx ( uri != NULL, file, line );
341         if ( uri ) {
342                 uri_okx ( uri, &test->uri, file, line );
343                 len = format_uri ( uri, buf, sizeof ( buf ) );
344                 okx ( len == ( sizeof ( buf ) - 1 /* NUL */ ), file, line );
345                 okx ( strcmp ( buf, test->string ) == 0, file, line );
346         }
347         uri_put ( uri );
348 }
349 #define uri_tftp_ok( test ) uri_tftp_okx ( test, __FILE__, __LINE__ )
350
351 /**
352  * Report current working URI test result
353  *
354  * @v tests             List of current working URI tests
355  * @v file              Test code file
356  * @v line              Test code line
357  */
358 static void uri_churi_okx ( struct uri_churi_test *test, const char *file,
359                             unsigned int line ) {
360         struct uri *old_cwuri;
361         struct uri *uri;
362         char *formatted;
363
364         /* Preserve original current working URI */
365         old_cwuri = uri_get ( cwuri );
366
367         /* Perform sequence of current working URI changes */
368         do {
369                 /* Parse relative URI */
370                 uri = parse_uri ( test->relative );
371                 okx ( uri != NULL, file, line );
372
373                 /* Move to this URI */
374                 churi ( uri );
375
376                 /* Format new current working URI */
377                 formatted = format_uri_alloc ( cwuri );
378                 okx ( formatted != NULL, file, line );
379                 if ( formatted ) {
380                         okx ( strcmp ( formatted, test->expected ) == 0,
381                               file, line );
382                 }
383
384                 /* Free temporary storage */
385                 free ( formatted );
386                 uri_put ( uri );
387
388                 /* Move to next current working URI test */
389                 test++;
390
391         } while ( test->relative != NULL );
392
393         /* Restore original current working URI */
394         churi ( old_cwuri );
395         uri_put ( old_cwuri );
396 }
397 #define uri_churi_ok( test ) uri_churi_okx ( test, __FILE__, __LINE__ )
398
399 /**
400  * Report form parameter URI test list result
401  *
402  * @v test              Form parameter URI test
403  * @v uri               URI
404  * @v file              Test code file
405  * @v line              Test code line
406  */
407 static void uri_params_list_okx ( struct uri_params_test *test,
408                                   struct uri *uri, const char *file,
409                                   unsigned int line ) {
410         struct uri_params_test_list *list;
411         struct parameter *param;
412
413         /* Check URI */
414         uri_okx ( uri, &test->uri, file, line );
415
416         /* Check URI parameters */
417         okx ( uri->params != NULL, file, line );
418         if ( uri->params ) {
419                 list = test->list;
420                 for_each_param ( param, uri->params ) {
421                         okx ( strcmp ( param->key, list->key ) == 0,
422                               file, line );
423                         okx ( strcmp ( param->value, list->value ) == 0,
424                               file, line );
425                         list++;
426                 }
427                 okx ( list->key == NULL, file, line );
428         }
429 }
430 #define uri_params_list_ok( test ) \
431         uri_params_list_okx ( test, __FILE__, __LINE__ )
432
433 /**
434  * Report form parameter URI test result
435  *
436  * @v test              Form parameter URI test
437  * @v file              Test code file
438  * @v line              Test code line
439  */
440 static void uri_params_okx ( struct uri_params_test *test, const char *file,
441                              unsigned int line ) {
442         struct uri_params_test_list *list;
443         struct parameters *params;
444         struct parameter *param;
445         struct uri *uri;
446         struct uri *dup;
447
448         /* Create parameter list */
449         params = create_parameters ( test->name );
450         okx ( params != NULL, file, line );
451         if ( params ) {
452                 for ( list = test->list ; list->key ; list++ ) {
453                         param = add_parameter ( params, list->key, list->value);
454                         okx ( param != NULL, file, line );
455                 }
456         }
457
458         /* Record parameter list as part of expected URI */
459         test->uri.params = params;
460
461         /* Parse URI */
462         uri = parse_uri ( test->string );
463         okx ( uri != NULL, file, line );
464         if ( uri )
465                 uri_params_list_okx ( test, uri, file, line );
466
467         /* Duplicate URI */
468         dup = uri_dup ( uri );
469         okx ( dup != NULL, file, line );
470         if ( dup )
471                 uri_params_list_okx ( test, dup, file, line );
472
473         /* Clear parameter list in expected URI */
474         test->uri.params = NULL;
475
476         uri_put ( uri );
477         uri_put ( dup );
478 }
479 #define uri_params_ok( test ) uri_params_okx ( test, __FILE__, __LINE__ )
480
481 /** Empty URI */
482 static struct uri_test uri_empty = {
483         .string = "",
484 };
485
486 /** Basic HTTP URI */
487 static struct uri_test uri_boot_ipxe_org = {
488         "http://boot.ipxe.org/demo/boot.php",
489         { .scheme = "http", .host = "boot.ipxe.org", .path = "/demo/boot.php" }
490 };
491
492 /** Basic opaque URI */
493 static struct uri_test uri_mailto = {
494         "mailto:ipxe-devel@lists.ipxe.org",
495         { .scheme = "mailto", .opaque = "ipxe-devel@lists.ipxe.org" }
496 };
497
498 /** HTTP URI with all the trimmings */
499 static struct uri_test uri_http_all = {
500         "http://anon:password@example.com:3001/~foo/cgi-bin/foo.pl?a=b&c=d#bit",
501         {
502                 .scheme = "http",
503                 .user = "anon",
504                 .password = "password",
505                 .host = "example.com",
506                 .port = "3001",
507                 .path = "/~foo/cgi-bin/foo.pl",
508                 .query = "a=b&c=d",
509                 .fragment = "bit",
510         },
511 };
512
513 /** HTTP URI with escaped characters */
514 static struct uri_test uri_http_escaped = {
515         "https://test.ipxe.org/wtf%3F%0A?kind%23of/uri%20is#this%3F",
516         {
517                 .scheme = "https",
518                 .host = "test.ipxe.org",
519                 .path = "/wtf?\n",
520                 .query = "kind#of/uri is",
521                 .fragment = "this?",
522         },
523 };
524
525 /** HTTP URI with improperly escaped characters */
526 static struct uri_test uri_http_escaped_improper = {
527         /* We accept for parsing improperly escaped characters.
528          * (Formatting the parsed URI would produce the properly
529          * encoded form, and so would not exactly match the original
530          * URI string.)
531          */
532         "https://test%2eipxe.org/wt%66%3f\n?kind%23of/uri is#this?",
533         {
534                 .scheme = "https",
535                 .host = "test.ipxe.org",
536                 .path = "/wtf?\n",
537                 .query = "kind#of/uri is",
538                 .fragment = "this?",
539         },
540 };
541
542 /** IPv6 URI */
543 static struct uri_test uri_ipv6 = {
544         "http://[2001:ba8:0:1d4::6950:5845]/",
545         {
546                 .scheme = "http",
547                 .host = "[2001:ba8:0:1d4::6950:5845]",
548                 .path = "/",
549         },
550 };
551
552 /** IPv6 URI with port */
553 static struct uri_test uri_ipv6_port = {
554         "http://[2001:ba8:0:1d4::6950:5845]:8001/boot",
555         {
556                 .scheme = "http",
557                 .host = "[2001:ba8:0:1d4::6950:5845]",
558                 .port = "8001",
559                 .path = "/boot",
560         },
561 };
562
563 /** IPv6 URI with link-local address */
564 static struct uri_test uri_ipv6_local = {
565         "http://[fe80::69ff:fe50:5845%25net0]/ipxe",
566         {
567                 .scheme = "http",
568                 .host = "[fe80::69ff:fe50:5845%net0]",
569                 .path = "/ipxe",
570         },
571 };
572
573 /** IPv6 URI with link-local address not conforming to RFC 6874 */
574 static struct uri_test uri_ipv6_local_non_conforming = {
575         /* We accept for parsing a single "%" in "%net0" (rather than
576          * the properly encoded form "%25net0").  (Formatting the
577          * parsed URI would produce the properly encoded form, and so
578          * would not exactly match the original URI string.)
579          */
580         "http://[fe80::69ff:fe50:5845%net0]/ipxe",
581         {
582                 .scheme = "http",
583                 .host = "[fe80::69ff:fe50:5845%net0]",
584                 .path = "/ipxe",
585         },
586 };
587
588 /** iSCSI URI */
589 static struct uri_test uri_iscsi = {
590         "iscsi:10.253.253.1::::iqn.2010-04.org.ipxe:rabbit",
591         {
592                 .scheme = "iscsi",
593                 .opaque = "10.253.253.1::::iqn.2010-04.org.ipxe:rabbit",
594         },
595 };
596
597 /** URI with port number */
598 static struct uri_port_test uri_explicit_port = {
599         "http://192.168.0.1:8080/boot.php",
600         80,
601         8080,
602 };
603
604 /** URI without port number */
605 static struct uri_port_test uri_default_port = {
606         "http://192.168.0.1/boot.php",
607         80,
608         80,
609 };
610
611 /** Simple path resolution test */
612 static struct uri_resolve_test uri_simple_path = {
613         "/etc/passwd",
614         "group",
615         "/etc/group",
616 };
617
618 /** Path resolution test with "." and ".." elements */
619 static struct uri_resolve_test uri_relative_path = {
620         "/var/lib/tftpboot/pxe/pxelinux.0",
621         "./../ipxe/undionly.kpxe",
622         "/var/lib/tftpboot/ipxe/undionly.kpxe",
623 };
624
625 /** Path resolution test terminating with directory */
626 static struct uri_resolve_test uri_directory_path = {
627         "/test/cgi-bin.pl/boot.ipxe",
628         "..",
629         "/test/",
630 };
631
632 /** Path resolution test with excessive ".." elements */
633 static struct uri_resolve_test uri_excessive_path = {
634         "/var/lib/tftpboot/ipxe.pxe",
635         "../../../../../../../foo",
636         "/foo",
637 };
638
639 /** Path resolution test with absolute path */
640 static struct uri_resolve_test uri_absolute_path = {
641         "/var/lib/tftpboot",
642         "/etc/hostname",
643         "/etc/hostname",
644 };
645
646 /** Relative URI resolution test */
647 static struct uri_resolve_test uri_relative = {
648         "http://boot.ipxe.org/demo/boot.php?vendor=10ec&device=8139",
649         "initrd.img",
650         "http://boot.ipxe.org/demo/initrd.img",
651 };
652
653 /** Absolute URI resolution test */
654 static struct uri_resolve_test uri_absolute = {
655         "http://boot.ipxe.org/demo/boot.php",
656         "ftp://192.168.0.1/boot.ipxe",
657         "ftp://192.168.0.1/boot.ipxe",
658 };
659
660 /** Absolute path URI resolution test */
661 static struct uri_resolve_test uri_absolute_uri_path = {
662         "http://boot.ipxe.org/demo/boot.php#test",
663         "/demo/vmlinuz",
664         "http://boot.ipxe.org/demo/vmlinuz",
665 };
666
667 /** Query URI resolution test */
668 static struct uri_resolve_test uri_query = {
669         "http://10.253.253.1/test.pl?mac=02-00-69-50-58-45",
670         "?mac=00-1f-16-bc-fe-2f",
671         "http://10.253.253.1/test.pl?mac=00-1f-16-bc-fe-2f",
672 };
673
674 /** Fragment URI resolution test */
675 static struct uri_resolve_test uri_fragment = {
676         "http://192.168.0.254/test#foo",
677         "#bar",
678         "http://192.168.0.254/test#bar",
679 };
680
681 /** TFTP URI with absolute path */
682 static struct uri_tftp_test uri_tftp_absolute = {
683         { .s_addr = htonl ( 0xc0a80002 ) /* 192.168.0.2 */ }, 0,
684         "/absolute/path",
685         {
686                 .scheme = "tftp",
687                 .host = "192.168.0.2",
688                 .path = "/absolute/path",
689         },
690         "tftp://192.168.0.2/absolute/path",
691 };
692
693 /** TFTP URI with relative path */
694 static struct uri_tftp_test uri_tftp_relative = {
695         { .s_addr = htonl ( 0xc0a80003 ) /* 192.168.0.3 */ }, 0,
696         "relative/path",
697         {
698                 .scheme = "tftp",
699                 .host = "192.168.0.3",
700                 .path = "relative/path",
701         },
702         "tftp://192.168.0.3/relative/path",
703 };
704
705 /** TFTP URI with path containing special characters */
706 static struct uri_tftp_test uri_tftp_icky = {
707         { .s_addr = htonl ( 0x0a000006 ) /* 10.0.0.6 */ }, 0,
708         "C:\\tftpboot\\icky#path",
709         {
710                 .scheme = "tftp",
711                 .host = "10.0.0.6",
712                 .path = "C:\\tftpboot\\icky#path",
713         },
714         "tftp://10.0.0.6/C%3A\\tftpboot\\icky%23path",
715 };
716
717 /** TFTP URI with custom port */
718 static struct uri_tftp_test uri_tftp_port = {
719         { .s_addr = htonl ( 0xc0a80001 ) /* 192.168.0.1 */ }, 4069,
720         "/another/path",
721         {
722                 .scheme = "tftp",
723                 .host = "192.168.0.1",
724                 .port = "4069",
725                 .path = "/another/path",
726         },
727         "tftp://192.168.0.1:4069/another/path",
728 };
729
730 /** Current working URI test */
731 static struct uri_churi_test uri_churi[] = {
732         {
733                 "http://boot.ipxe.org/demo/boot.php",
734                 "http://boot.ipxe.org/demo/boot.php",
735         },
736         {
737                 "?vendor=10ec&device=8139",
738                 "http://boot.ipxe.org/demo/boot.php?vendor=10ec&device=8139",
739         },
740         {
741                 "fedora/fedora.ipxe",
742                 "http://boot.ipxe.org/demo/fedora/fedora.ipxe",
743         },
744         {
745                 "vmlinuz",
746                 "http://boot.ipxe.org/demo/fedora/vmlinuz",
747         },
748         {
749                 "http://local/boot/initrd.img",
750                 "http://local/boot/initrd.img",
751         },
752         {
753                 "modules/8139too.ko",
754                 "http://local/boot/modules/8139too.ko",
755         },
756         {
757                 NULL,
758                 NULL,
759         }
760 };
761
762 /** Form parameter URI test list */
763 static struct uri_params_test_list uri_params_list[] = {
764         {
765                 "vendor",
766                 "10ec",
767         },
768         {
769                 "device",
770                 "8139",
771         },
772         {
773                 "uuid",
774                 "f59fac00-758f-498f-9fe5-87d790045d94",
775         },
776         {
777                 NULL,
778                 NULL,
779         }
780 };
781
782 /** Form parameter URI test */
783 static struct uri_params_test uri_params = {
784         "http://boot.ipxe.org/demo/boot.php##params",
785         {
786                 .scheme = "http",
787                 .host = "boot.ipxe.org",
788                 .path = "/demo/boot.php",
789         },
790         NULL,
791         uri_params_list,
792 };
793
794 /** Named form parameter URI test list */
795 static struct uri_params_test_list uri_named_params_list[] = {
796         {
797                 "mac",
798                 "00:1e:65:80:d3:b6",
799         },
800         {
801                 "serial",
802                 "LXTQ20Z1139322762F2000",
803         },
804         {
805                 NULL,
806                 NULL,
807         }
808 };
809
810 /** Named form parameter URI test */
811 static struct uri_params_test uri_named_params = {
812         "http://192.168.100.4:3001/register##params=foo",
813         {
814                 .scheme = "http",
815                 .host = "192.168.100.4",
816                 .port = "3001",
817                 .path = "/register",
818         },
819         "foo",
820         uri_named_params_list,
821 };
822
823 /**
824  * Perform URI self-test
825  *
826  */
827 static void uri_test_exec ( void ) {
828
829         /* URI parsing, formatting, and duplication tests */
830         uri_parse_format_dup_ok ( &uri_empty );
831         uri_parse_format_dup_ok ( &uri_boot_ipxe_org );
832         uri_parse_format_dup_ok ( &uri_mailto );
833         uri_parse_format_dup_ok ( &uri_http_all );
834         uri_parse_format_dup_ok ( &uri_http_escaped );
835         uri_parse_ok ( &uri_http_escaped_improper ); /* Parse only */
836         uri_parse_format_dup_ok ( &uri_ipv6 );
837         uri_parse_format_dup_ok ( &uri_ipv6_port );
838         uri_parse_format_dup_ok ( &uri_ipv6_local );
839         uri_parse_ok ( &uri_ipv6_local_non_conforming ); /* Parse only */
840         uri_parse_format_dup_ok ( &uri_iscsi );
841
842         /** URI port number tests */
843         uri_port_ok ( &uri_explicit_port );
844         uri_port_ok ( &uri_default_port );
845
846         /** Path resolution tests */
847         uri_resolve_path_ok ( &uri_simple_path );
848         uri_resolve_path_ok ( &uri_relative_path );
849         uri_resolve_path_ok ( &uri_directory_path );
850         uri_resolve_path_ok ( &uri_excessive_path );
851         uri_resolve_path_ok ( &uri_absolute_path );
852
853         /** URI resolution tests */
854         uri_resolve_ok ( &uri_relative );
855         uri_resolve_ok ( &uri_absolute );
856         uri_resolve_ok ( &uri_absolute_uri_path );
857         uri_resolve_ok ( &uri_query );
858         uri_resolve_ok ( &uri_fragment );
859
860         /* TFTP URI construction tests */
861         uri_tftp_ok ( &uri_tftp_absolute );
862         uri_tftp_ok ( &uri_tftp_relative );
863         uri_tftp_ok ( &uri_tftp_icky );
864         uri_tftp_ok ( &uri_tftp_port );
865
866         /* Current working URI tests */
867         uri_churi_ok ( uri_churi );
868
869         /* Form parameter URI tests */
870         uri_params_ok ( &uri_params );
871         uri_params_ok ( &uri_named_params );
872 }
873
874 /** URI self-test */
875 struct self_test uri_test __self_test = {
876         .name = "uri",
877         .exec = uri_test_exec,
878 };