iPXE
uri_test.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 /** @file
00027  *
00028  * URI self-tests
00029  *
00030  */
00031 
00032 /* Forcibly enable assertions */
00033 #undef NDEBUG
00034 
00035 #include <string.h>
00036 #include <byteswap.h>
00037 #include <ipxe/uri.h>
00038 #include <ipxe/tcpip.h>
00039 #include <ipxe/params.h>
00040 #include <ipxe/test.h>
00041 
00042 /** A URI parsing/formatting test */
00043 struct uri_test {
00044         /** URI string */
00045         const char *string;
00046         /** URI */
00047         struct uri uri;
00048 };
00049 
00050 /** A URI port number test */
00051 struct uri_port_test {
00052         /** URI string */
00053         const char *string;
00054         /** Default port number */
00055         unsigned int default_port;
00056         /** Expected port number */
00057         unsigned int port;
00058 };
00059 
00060 /** A URI or path resolution test */
00061 struct uri_resolve_test {
00062         /** Base path or URI */
00063         const char *base;
00064         /** Relative path or URI */
00065         const char *relative;
00066         /** Expected resolved path or URI */
00067         const char *resolved;
00068 };
00069 
00070 /** A PXE URI test */
00071 struct uri_pxe_test {
00072         /** Server address */
00073         union {
00074                 struct sockaddr sa;
00075                 struct sockaddr_in sin;
00076                 struct sockaddr_in6 sin6;
00077                 struct sockaddr_tcpip st;
00078         } server;
00079         /** Filename */
00080         const char *filename;
00081         /** URI */
00082         struct uri uri;
00083         /** URI string (for display only; cannot be reparsed) */
00084         const char *string;
00085 };
00086 
00087 /** A current working URI test */
00088 struct uri_churi_test {
00089         /** Relative URI */
00090         const char *relative;
00091         /** Expected new working URI */
00092         const char *expected;
00093 };
00094 
00095 /** A form parameter URI test list */
00096 struct uri_params_test_list {
00097         /** Key */
00098         const char *key;
00099         /** Value */
00100         const char *value;
00101 };
00102 
00103 /** A form parameter URI test */
00104 struct uri_params_test {
00105         /** URI string */
00106         const char *string;
00107         /** URI */
00108         struct uri uri;
00109         /** Parameter list name */
00110         const char *name;
00111         /** Parameter list */
00112         struct uri_params_test_list *list;
00113 };
00114 
00115 /**
00116  * Compare two URI component strings
00117  *
00118  * @v first             First string, or NULL
00119  * @v second            Second string, or NULL
00120  * @v difference        Difference
00121  */
00122 static int uristrcmp ( const char *first, const char *second ) {
00123 
00124         /* Compare strings, allowing for either to be NULL */
00125         if ( first == second ) {
00126                 return 0;
00127         } else if ( ( first == NULL ) || ( second == NULL ) ) {
00128                 return -1;
00129         } else {
00130                 return strcmp ( first, second );
00131         }
00132 }
00133 
00134 /**
00135  * Report URI equality test result
00136  *
00137  * @v uri               URI
00138  * @v expected          Expected URI
00139  * @v file              Test code file
00140  * @v line              Test code line
00141  */
00142 static void uri_okx ( struct uri *uri, struct uri *expected, const char *file,
00143                       unsigned int line ) {
00144 
00145         okx ( uristrcmp ( uri->scheme, expected->scheme ) == 0, file, line );
00146         okx ( uristrcmp ( uri->opaque, expected->opaque ) == 0, file, line );
00147         okx ( uristrcmp ( uri->user, expected->user ) == 0, file, line );
00148         okx ( uristrcmp ( uri->password, expected->password ) == 0, file, line);
00149         okx ( uristrcmp ( uri->host, expected->host ) == 0, file, line );
00150         okx ( uristrcmp ( uri->port, expected->port ) == 0, file, line );
00151         okx ( uristrcmp ( uri->path, expected->path ) == 0, file, line );
00152         okx ( uristrcmp ( uri->query, expected->query ) == 0, file, line );
00153         okx ( uristrcmp ( uri->fragment, expected->fragment ) == 0, file, line);
00154         okx ( uri->params == expected->params, file, line );
00155 }
00156 #define uri_ok( uri, expected ) uri_okx ( uri, expected, __FILE__, __LINE__ )
00157 
00158 /**
00159  * Report URI parsing test result
00160  *
00161  * @v test              URI test
00162  * @v file              Test code file
00163  * @v line              Test code line
00164  */
00165 static void uri_parse_okx ( struct uri_test *test, const char *file,
00166                             unsigned int line ) {
00167         struct uri *uri;
00168 
00169         /* Parse URI */
00170         uri = parse_uri ( test->string );
00171         okx ( uri != NULL, file, line );
00172         if ( uri )
00173                 uri_okx ( uri, &test->uri, file, line );
00174         uri_put ( uri );
00175 }
00176 #define uri_parse_ok( test ) uri_parse_okx ( test, __FILE__, __LINE__ )
00177 
00178 /**
00179  * Report URI formatting test result
00180  *
00181  * @v test              URI test
00182  * @v file              Test code file
00183  * @v line              Test code line
00184  */
00185 static void uri_format_okx ( struct uri_test *test, const char *file,
00186                              unsigned int line ) {
00187         char buf[ strlen ( test->string ) + 1 /* NUL */ ];
00188         char *tmp;
00189         size_t len;
00190 
00191         /* Format into fixed-size buffer */
00192         len = format_uri ( &test->uri, buf, sizeof ( buf ) );
00193         okx ( len == ( sizeof ( buf ) - 1 /* NUL */ ), file, line );
00194         okx ( strcmp ( buf, test->string ) == 0, file, line );
00195 
00196         /* Format into temporarily allocated buffer */
00197         tmp = format_uri_alloc ( &test->uri );
00198         okx ( tmp != NULL, file, line );
00199         if ( tmp )
00200                 okx ( strcmp ( tmp, test->string ) == 0, file, line );
00201         free ( tmp );
00202 }
00203 #define uri_format_ok( test ) uri_format_okx ( test, __FILE__, __LINE__ )
00204 
00205 /**
00206  * Report URI duplication test result
00207  *
00208  * @v test              URI
00209  * @v file              Test code file
00210  * @v line              Test code line
00211  */
00212 static void uri_dup_okx ( struct uri *uri, const char *file,
00213                           unsigned int line ) {
00214         struct uri *dup;
00215 
00216         dup = uri_dup ( uri );
00217         okx ( dup != NULL, file, line );
00218         if ( dup )
00219                 uri_okx ( dup, uri, file, line );
00220         uri_put ( dup );
00221 }
00222 #define uri_dup_ok( test ) uri_dup_okx ( test, __FILE__, __LINE__ )
00223 
00224 /**
00225  * Report URI combined parsing and formatting test result
00226  *
00227  * @v test              URI test
00228  * @v file              Test code file
00229  * @v line              Test code line
00230  */
00231 static void uri_parse_format_dup_okx ( struct uri_test *test, const char *file,
00232                                        unsigned int line ) {
00233 
00234         uri_parse_okx ( test, file, line );
00235         uri_format_okx ( test, file, line );
00236         uri_dup_okx ( &test->uri, file, line );
00237 }
00238 #define uri_parse_format_dup_ok( test ) \
00239         uri_parse_format_dup_okx ( test, __FILE__, __LINE__ )
00240 
00241 /**
00242  * Report URI port number test result
00243  *
00244  * @v test              URI port number test
00245  * @v file              Test code file
00246  * @v line              Test code line
00247  */
00248 static void uri_port_okx ( struct uri_port_test *test, const char *file,
00249                            unsigned int line ) {
00250         struct uri *uri;
00251         unsigned int port;
00252 
00253         /* Parse URI */
00254         uri = parse_uri ( test->string );
00255         okx ( uri != NULL, file, line );
00256         if ( uri ) {
00257                 port = uri_port ( uri, test->default_port );
00258                 okx ( port == test->port, file, line );
00259         }
00260         uri_put ( uri );
00261 }
00262 #define uri_port_ok( test ) uri_port_okx ( test, __FILE__, __LINE__ )
00263 
00264 /**
00265  * Report URI resolution test result
00266  *
00267  * @v test              Path resolution test
00268  * @v file              Test code file
00269  * @v line              Test code line
00270  */
00271 static void uri_resolve_okx ( struct uri_resolve_test *test,
00272                               const char *file, unsigned int line ) {
00273         struct uri *base;
00274         struct uri *relative;
00275         struct uri *resolved = NULL;
00276         char *formatted;
00277 
00278         /* Parse URIs */
00279         base = parse_uri ( test->base );
00280         okx ( base != NULL, file, line );
00281         relative = parse_uri ( test->relative );
00282         okx ( relative != NULL, file, line );
00283 
00284         /* Resolve URI  */
00285         if ( base && relative ) {
00286                 resolved = resolve_uri ( base, relative );
00287                 okx ( resolved != NULL, file, line );
00288         }
00289 
00290         /* Format resolved URI */
00291         formatted = format_uri_alloc ( resolved );
00292         okx ( formatted != NULL, file, line );
00293 
00294         /* Check resolved URI */
00295         if ( formatted )
00296                 okx ( strcmp ( formatted, test->resolved ) == 0, file, line );
00297 
00298         free ( formatted );
00299         uri_put ( resolved );
00300         uri_put ( relative );
00301         uri_put ( base );
00302 }
00303 #define uri_resolve_ok( test ) uri_resolve_okx ( test, __FILE__, __LINE__ )
00304 
00305 /**
00306  * Report path resolution test result
00307  *
00308  * @v test              Path resolution test
00309  * @v file              Test code file
00310  * @v line              Test code line
00311  */
00312 static void uri_resolve_path_okx ( struct uri_resolve_test *test,
00313                                    const char *file, unsigned int line ) {
00314         char *resolved;
00315 
00316         /* Resolve paths using resolve_path() directly */
00317         resolved = resolve_path ( test->base, test->relative );
00318         okx ( resolved != NULL, file, line );
00319         if ( resolved )
00320                 okx ( strcmp ( resolved, test->resolved ) == 0, file, line );
00321         free ( resolved );
00322 
00323         /* Resolve paths as URIs (since all paths are valid URIs) */
00324         uri_resolve_okx ( test, file, line );
00325 }
00326 #define uri_resolve_path_ok( test ) \
00327         uri_resolve_path_okx ( test, __FILE__, __LINE__ )
00328 
00329 /**
00330  * Report URI PXE test result
00331  *
00332  * @v test              URI PXE test
00333  * @v file              Test code file
00334  * @v line              Test code line
00335  */
00336 static void uri_pxe_okx ( struct uri_pxe_test *test, const char *file,
00337                           unsigned int line ) {
00338         char buf[ strlen ( test->string ) + 1 /* NUL */ ];
00339         struct uri *uri;
00340         size_t len;
00341 
00342         /* Construct URI */
00343         uri = pxe_uri ( &test->server.sa, test->filename );
00344         okx ( uri != NULL, file, line );
00345         if ( uri ) {
00346                 uri_okx ( uri, &test->uri, file, line );
00347                 len = format_uri ( uri, buf, sizeof ( buf ) );
00348                 okx ( len == ( sizeof ( buf ) - 1 /* NUL */ ), file, line );
00349                 okx ( strcmp ( buf, test->string ) == 0, file, line );
00350         }
00351         uri_put ( uri );
00352 }
00353 #define uri_pxe_ok( test ) uri_pxe_okx ( test, __FILE__, __LINE__ )
00354 
00355 /**
00356  * Report current working URI test result
00357  *
00358  * @v tests             List of current working URI tests
00359  * @v file              Test code file
00360  * @v line              Test code line
00361  */
00362 static void uri_churi_okx ( struct uri_churi_test *test, const char *file,
00363                             unsigned int line ) {
00364         struct uri *old_cwuri;
00365         struct uri *uri;
00366         char *formatted;
00367 
00368         /* Preserve original current working URI */
00369         old_cwuri = uri_get ( cwuri );
00370 
00371         /* Perform sequence of current working URI changes */
00372         do {
00373                 /* Parse relative URI */
00374                 uri = parse_uri ( test->relative );
00375                 okx ( uri != NULL, file, line );
00376 
00377                 /* Move to this URI */
00378                 churi ( uri );
00379 
00380                 /* Format new current working URI */
00381                 formatted = format_uri_alloc ( cwuri );
00382                 okx ( formatted != NULL, file, line );
00383                 if ( formatted ) {
00384                         okx ( strcmp ( formatted, test->expected ) == 0,
00385                               file, line );
00386                 }
00387 
00388                 /* Free temporary storage */
00389                 free ( formatted );
00390                 uri_put ( uri );
00391 
00392                 /* Move to next current working URI test */
00393                 test++;
00394 
00395         } while ( test->relative != NULL );
00396 
00397         /* Restore original current working URI */
00398         churi ( old_cwuri );
00399         uri_put ( old_cwuri );
00400 }
00401 #define uri_churi_ok( test ) uri_churi_okx ( test, __FILE__, __LINE__ )
00402 
00403 /**
00404  * Report form parameter URI test list result
00405  *
00406  * @v test              Form parameter URI test
00407  * @v uri               URI
00408  * @v file              Test code file
00409  * @v line              Test code line
00410  */
00411 static void uri_params_list_okx ( struct uri_params_test *test,
00412                                   struct uri *uri, const char *file,
00413                                   unsigned int line ) {
00414         struct uri_params_test_list *list;
00415         struct parameter *param;
00416 
00417         /* Check URI */
00418         uri_okx ( uri, &test->uri, file, line );
00419 
00420         /* Check URI parameters */
00421         okx ( uri->params != NULL, file, line );
00422         if ( uri->params ) {
00423                 list = test->list;
00424                 for_each_param ( param, uri->params ) {
00425                         okx ( strcmp ( param->key, list->key ) == 0,
00426                               file, line );
00427                         okx ( strcmp ( param->value, list->value ) == 0,
00428                               file, line );
00429                         list++;
00430                 }
00431                 okx ( list->key == NULL, file, line );
00432         }
00433 }
00434 #define uri_params_list_ok( test ) \
00435         uri_params_list_okx ( test, __FILE__, __LINE__ )
00436 
00437 /**
00438  * Report form parameter URI test result
00439  *
00440  * @v test              Form parameter URI test
00441  * @v file              Test code file
00442  * @v line              Test code line
00443  */
00444 static void uri_params_okx ( struct uri_params_test *test, const char *file,
00445                              unsigned int line ) {
00446         struct uri_params_test_list *list;
00447         struct parameters *params;
00448         struct parameter *param;
00449         struct uri *uri;
00450         struct uri *dup;
00451 
00452         /* Create parameter list */
00453         params = create_parameters ( test->name );
00454         okx ( params != NULL, file, line );
00455         if ( params ) {
00456                 for ( list = test->list ; list->key ; list++ ) {
00457                         param = add_parameter ( params, list->key, list->value);
00458                         okx ( param != NULL, file, line );
00459                 }
00460         }
00461 
00462         /* Record parameter list as part of expected URI */
00463         test->uri.params = params;
00464 
00465         /* Parse URI */
00466         uri = parse_uri ( test->string );
00467         okx ( uri != NULL, file, line );
00468         if ( uri )
00469                 uri_params_list_okx ( test, uri, file, line );
00470 
00471         /* Duplicate URI */
00472         dup = uri_dup ( uri );
00473         okx ( dup != NULL, file, line );
00474         if ( dup )
00475                 uri_params_list_okx ( test, dup, file, line );
00476 
00477         /* Clear parameter list in expected URI */
00478         test->uri.params = NULL;
00479 
00480         uri_put ( uri );
00481         uri_put ( dup );
00482 }
00483 #define uri_params_ok( test ) uri_params_okx ( test, __FILE__, __LINE__ )
00484 
00485 /** Empty URI */
00486 static struct uri_test uri_empty = {
00487         .string = "",
00488 };
00489 
00490 /** Basic HTTP URI */
00491 static struct uri_test uri_boot_ipxe_org = {
00492         "http://boot.ipxe.org/demo/boot.php",
00493         { .scheme = "http", .host = "boot.ipxe.org", .path = "/demo/boot.php" }
00494 };
00495 
00496 /** Basic opaque URI */
00497 static struct uri_test uri_mailto = {
00498         "mailto:ipxe-devel@lists.ipxe.org",
00499         { .scheme = "mailto", .opaque = "ipxe-devel@lists.ipxe.org" }
00500 };
00501 
00502 /** Basic path-only URI */
00503 static struct uri_test uri_path = {
00504         "/var/lib/tftpboot/pxelinux.0",
00505         { .path = "/var/lib/tftpboot/pxelinux.0" },
00506 };
00507 
00508 /** Path-only URI with escaped characters */
00509 static struct uri_test uri_path_escaped = {
00510         "/hello%20world%3F",
00511         { .path = "/hello world?" },
00512 };
00513 
00514 /** HTTP URI with all the trimmings */
00515 static struct uri_test uri_http_all = {
00516         "http://anon:password@example.com:3001/~foo/cgi-bin/foo.pl?a=b&c=d#bit",
00517         {
00518                 .scheme = "http",
00519                 .user = "anon",
00520                 .password = "password",
00521                 .host = "example.com",
00522                 .port = "3001",
00523                 .path = "/~foo/cgi-bin/foo.pl",
00524                 .query = "a=b&c=d",
00525                 .fragment = "bit",
00526         },
00527 };
00528 
00529 /** HTTP URI with escaped characters */
00530 static struct uri_test uri_http_escaped = {
00531         "https://test.ipxe.org/wtf%3F%0A?kind%23of/uri%20is#this%3F",
00532         {
00533                 .scheme = "https",
00534                 .host = "test.ipxe.org",
00535                 .path = "/wtf?\n",
00536                 .query = "kind#of/uri is",
00537                 .fragment = "this?",
00538         },
00539 };
00540 
00541 /** HTTP URI with improperly escaped characters */
00542 static struct uri_test uri_http_escaped_improper = {
00543         /* We accept for parsing improperly escaped characters.
00544          * (Formatting the parsed URI would produce the properly
00545          * encoded form, and so would not exactly match the original
00546          * URI string.)
00547          */
00548         "https://test%2eipxe.org/wt%66%3f\n?kind%23of/uri is#this?",
00549         {
00550                 .scheme = "https",
00551                 .host = "test.ipxe.org",
00552                 .path = "/wtf?\n",
00553                 .query = "kind#of/uri is",
00554                 .fragment = "this?",
00555         },
00556 };
00557 
00558 /** IPv6 URI */
00559 static struct uri_test uri_ipv6 = {
00560         "http://[2001:ba8:0:1d4::6950:5845]/",
00561         {
00562                 .scheme = "http",
00563                 .host = "[2001:ba8:0:1d4::6950:5845]",
00564                 .path = "/",
00565         },
00566 };
00567 
00568 /** IPv6 URI with port */
00569 static struct uri_test uri_ipv6_port = {
00570         "http://[2001:ba8:0:1d4::6950:5845]:8001/boot",
00571         {
00572                 .scheme = "http",
00573                 .host = "[2001:ba8:0:1d4::6950:5845]",
00574                 .port = "8001",
00575                 .path = "/boot",
00576         },
00577 };
00578 
00579 /** IPv6 URI with link-local address */
00580 static struct uri_test uri_ipv6_local = {
00581         "http://[fe80::69ff:fe50:5845%25net0]/ipxe",
00582         {
00583                 .scheme = "http",
00584                 .host = "[fe80::69ff:fe50:5845%net0]",
00585                 .path = "/ipxe",
00586         },
00587 };
00588 
00589 /** IPv6 URI with link-local address not conforming to RFC 6874 */
00590 static struct uri_test uri_ipv6_local_non_conforming = {
00591         /* We accept for parsing a single "%" in "%net0" (rather than
00592          * the properly encoded form "%25net0").  (Formatting the
00593          * parsed URI would produce the properly encoded form, and so
00594          * would not exactly match the original URI string.)
00595          */
00596         "http://[fe80::69ff:fe50:5845%net0]/ipxe",
00597         {
00598                 .scheme = "http",
00599                 .host = "[fe80::69ff:fe50:5845%net0]",
00600                 .path = "/ipxe",
00601         },
00602 };
00603 
00604 /** iSCSI URI */
00605 static struct uri_test uri_iscsi = {
00606         "iscsi:10.253.253.1::::iqn.2010-04.org.ipxe:rabbit",
00607         {
00608                 .scheme = "iscsi",
00609                 .opaque = "10.253.253.1::::iqn.2010-04.org.ipxe:rabbit",
00610         },
00611 };
00612 
00613 /** File URI with relative (opaque) path */
00614 static struct uri_test uri_file_relative = {
00615         "file:boot/script.ipxe",
00616         {
00617                 .scheme = "file",
00618                 .opaque = "boot/script.ipxe",
00619         },
00620 };
00621 
00622 /** File URI with absolute path */
00623 static struct uri_test uri_file_absolute = {
00624         "file:/boot/script.ipxe",
00625         {
00626                 .scheme = "file",
00627                 .path = "/boot/script.ipxe",
00628         },
00629 };
00630 
00631 /** File URI with volume name */
00632 static struct uri_test uri_file_volume = {
00633         "file://hpilo/boot/script.ipxe",
00634         {
00635                 .scheme = "file",
00636                 .host = "hpilo",
00637                 .path = "/boot/script.ipxe",
00638         },
00639 };
00640 
00641 /** URI with port number */
00642 static struct uri_port_test uri_explicit_port = {
00643         "http://192.168.0.1:8080/boot.php",
00644         80,
00645         8080,
00646 };
00647 
00648 /** URI without port number */
00649 static struct uri_port_test uri_default_port = {
00650         "http://192.168.0.1/boot.php",
00651         80,
00652         80,
00653 };
00654 
00655 /** Simple path resolution test */
00656 static struct uri_resolve_test uri_simple_path = {
00657         "/etc/passwd",
00658         "group",
00659         "/etc/group",
00660 };
00661 
00662 /** Path resolution test with "." and ".." elements */
00663 static struct uri_resolve_test uri_relative_path = {
00664         "/var/lib/tftpboot/pxe/pxelinux.0",
00665         "./../ipxe/undionly.kpxe",
00666         "/var/lib/tftpboot/ipxe/undionly.kpxe",
00667 };
00668 
00669 /** Path resolution test terminating with directory */
00670 static struct uri_resolve_test uri_directory_path = {
00671         "/test/cgi-bin.pl/boot.ipxe",
00672         "..",
00673         "/test/",
00674 };
00675 
00676 /** Path resolution test with excessive ".." elements */
00677 static struct uri_resolve_test uri_excessive_path = {
00678         "/var/lib/tftpboot/ipxe.pxe",
00679         "../../../../../../../foo",
00680         "/foo",
00681 };
00682 
00683 /** Path resolution test with absolute path */
00684 static struct uri_resolve_test uri_absolute_path = {
00685         "/var/lib/tftpboot",
00686         "/etc/hostname",
00687         "/etc/hostname",
00688 };
00689 
00690 /** Relative URI resolution test */
00691 static struct uri_resolve_test uri_relative = {
00692         "http://boot.ipxe.org/demo/boot.php?vendor=10ec&device=8139",
00693         "initrd.img",
00694         "http://boot.ipxe.org/demo/initrd.img",
00695 };
00696 
00697 /** Absolute URI resolution test */
00698 static struct uri_resolve_test uri_absolute = {
00699         "http://boot.ipxe.org/demo/boot.php",
00700         "ftp://192.168.0.1/boot.ipxe",
00701         "ftp://192.168.0.1/boot.ipxe",
00702 };
00703 
00704 /** Absolute path URI resolution test */
00705 static struct uri_resolve_test uri_absolute_uri_path = {
00706         "http://boot.ipxe.org/demo/boot.php#test",
00707         "/demo/vmlinuz",
00708         "http://boot.ipxe.org/demo/vmlinuz",
00709 };
00710 
00711 /** Query URI resolution test */
00712 static struct uri_resolve_test uri_query = {
00713         "http://10.253.253.1/test.pl?mac=02-00-69-50-58-45",
00714         "?mac=00-1f-16-bc-fe-2f",
00715         "http://10.253.253.1/test.pl?mac=00-1f-16-bc-fe-2f",
00716 };
00717 
00718 /** Fragment URI resolution test */
00719 static struct uri_resolve_test uri_fragment = {
00720         "http://192.168.0.254/test#foo",
00721         "#bar",
00722         "http://192.168.0.254/test#bar",
00723 };
00724 
00725 /** PXE URI with absolute URI */
00726 static struct uri_pxe_test uri_pxe_absolute = {
00727         {
00728                 /* 192.168.0.3 */
00729                 .sin = {
00730                         .sin_family = AF_INET,
00731                         .sin_addr = { .s_addr = htonl ( 0xc0a80003 ) },
00732                 },
00733         },
00734         "http://not.a.tftp/uri",
00735         {
00736                 .scheme = "http",
00737                 .host = "not.a.tftp",
00738                 .path = "/uri",
00739         },
00740         "http://not.a.tftp/uri",
00741 };
00742 
00743 /** PXE URI with absolute path */
00744 static struct uri_pxe_test uri_pxe_absolute_path = {
00745         {
00746                 /* 192.168.0.2 */
00747                 .sin = {
00748                         .sin_family = AF_INET,
00749                         .sin_addr = { .s_addr = htonl ( 0xc0a80002 ) },
00750                 },
00751         },
00752         "/absolute/path",
00753         {
00754                 .scheme = "tftp",
00755                 .host = "192.168.0.2",
00756                 .path = "//absolute/path",
00757         },
00758         "tftp://192.168.0.2//absolute/path",
00759 };
00760 
00761 /** PXE URI with relative path */
00762 static struct uri_pxe_test uri_pxe_relative_path = {
00763         {
00764                 /* 192.168.0.3 */
00765                 .sin = {
00766                         .sin_family = AF_INET,
00767                         .sin_addr = { .s_addr = htonl ( 0xc0a80003 ) },
00768                 },
00769         },
00770         "relative/path",
00771         {
00772                 .scheme = "tftp",
00773                 .host = "192.168.0.3",
00774                 .path = "/relative/path",
00775         },
00776         "tftp://192.168.0.3/relative/path",
00777 };
00778 
00779 /** PXE URI with path containing special characters */
00780 static struct uri_pxe_test uri_pxe_icky = {
00781         {
00782                 /* 10.0.0.6 */
00783                 .sin = {
00784                         .sin_family = AF_INET,
00785                         .sin_addr = { .s_addr = htonl ( 0x0a000006 ) },
00786                 },
00787         },
00788         "C:\\tftpboot\\icky#path",
00789         {
00790                 .scheme = "tftp",
00791                 .host = "10.0.0.6",
00792                 .path = "/C:\\tftpboot\\icky#path",
00793         },
00794         "tftp://10.0.0.6/C%3A\\tftpboot\\icky%23path",
00795 };
00796 
00797 /** PXE URI with custom port */
00798 static struct uri_pxe_test uri_pxe_port = {
00799         {
00800                 /* 192.168.0.1:4069 */
00801                 .sin = {
00802                         .sin_family = AF_INET,
00803                         .sin_addr = { .s_addr = htonl ( 0xc0a80001 ) },
00804                         .sin_port = htons ( 4069 ),
00805                 },
00806         },
00807         "/another/path",
00808         {
00809                 .scheme = "tftp",
00810                 .host = "192.168.0.1",
00811                 .port = "4069",
00812                 .path = "//another/path",
00813         },
00814         "tftp://192.168.0.1:4069//another/path",
00815 };
00816 
00817 /** Current working URI test */
00818 static struct uri_churi_test uri_churi[] = {
00819         {
00820                 "http://boot.ipxe.org/demo/boot.php",
00821                 "http://boot.ipxe.org/demo/boot.php",
00822         },
00823         {
00824                 "?vendor=10ec&device=8139",
00825                 "http://boot.ipxe.org/demo/boot.php?vendor=10ec&device=8139",
00826         },
00827         {
00828                 "fedora/fedora.ipxe",
00829                 "http://boot.ipxe.org/demo/fedora/fedora.ipxe",
00830         },
00831         {
00832                 "vmlinuz",
00833                 "http://boot.ipxe.org/demo/fedora/vmlinuz",
00834         },
00835         {
00836                 "http://local/boot/initrd.img",
00837                 "http://local/boot/initrd.img",
00838         },
00839         {
00840                 "modules/8139too.ko",
00841                 "http://local/boot/modules/8139too.ko",
00842         },
00843         {
00844                 NULL,
00845                 NULL,
00846         }
00847 };
00848 
00849 /** Form parameter URI test list */
00850 static struct uri_params_test_list uri_params_list[] = {
00851         {
00852                 "vendor",
00853                 "10ec",
00854         },
00855         {
00856                 "device",
00857                 "8139",
00858         },
00859         {
00860                 "uuid",
00861                 "f59fac00-758f-498f-9fe5-87d790045d94",
00862         },
00863         {
00864                 NULL,
00865                 NULL,
00866         }
00867 };
00868 
00869 /** Form parameter URI test */
00870 static struct uri_params_test uri_params = {
00871         "http://boot.ipxe.org/demo/boot.php##params",
00872         {
00873                 .scheme = "http",
00874                 .host = "boot.ipxe.org",
00875                 .path = "/demo/boot.php",
00876         },
00877         NULL,
00878         uri_params_list,
00879 };
00880 
00881 /** Named form parameter URI test list */
00882 static struct uri_params_test_list uri_named_params_list[] = {
00883         {
00884                 "mac",
00885                 "00:1e:65:80:d3:b6",
00886         },
00887         {
00888                 "serial",
00889                 "LXTQ20Z1139322762F2000",
00890         },
00891         {
00892                 NULL,
00893                 NULL,
00894         }
00895 };
00896 
00897 /** Named form parameter URI test */
00898 static struct uri_params_test uri_named_params = {
00899         "http://192.168.100.4:3001/register##params=foo",
00900         {
00901                 .scheme = "http",
00902                 .host = "192.168.100.4",
00903                 .port = "3001",
00904                 .path = "/register",
00905         },
00906         "foo",
00907         uri_named_params_list,
00908 };
00909 
00910 /**
00911  * Perform URI self-test
00912  *
00913  */
00914 static void uri_test_exec ( void ) {
00915 
00916         /* URI parsing, formatting, and duplication tests */
00917         uri_parse_format_dup_ok ( &uri_empty );
00918         uri_parse_format_dup_ok ( &uri_boot_ipxe_org );
00919         uri_parse_format_dup_ok ( &uri_mailto );
00920         uri_parse_format_dup_ok ( &uri_path );
00921         uri_parse_format_dup_ok ( &uri_path_escaped );
00922         uri_parse_format_dup_ok ( &uri_http_all );
00923         uri_parse_format_dup_ok ( &uri_http_escaped );
00924         uri_parse_ok ( &uri_http_escaped_improper ); /* Parse only */
00925         uri_parse_format_dup_ok ( &uri_ipv6 );
00926         uri_parse_format_dup_ok ( &uri_ipv6_port );
00927         uri_parse_format_dup_ok ( &uri_ipv6_local );
00928         uri_parse_ok ( &uri_ipv6_local_non_conforming ); /* Parse only */
00929         uri_parse_format_dup_ok ( &uri_iscsi );
00930         uri_parse_format_dup_ok ( &uri_file_relative );
00931         uri_parse_format_dup_ok ( &uri_file_absolute );
00932         uri_parse_format_dup_ok ( &uri_file_volume );
00933 
00934         /** URI port number tests */
00935         uri_port_ok ( &uri_explicit_port );
00936         uri_port_ok ( &uri_default_port );
00937 
00938         /** Path resolution tests */
00939         uri_resolve_path_ok ( &uri_simple_path );
00940         uri_resolve_path_ok ( &uri_relative_path );
00941         uri_resolve_path_ok ( &uri_directory_path );
00942         uri_resolve_path_ok ( &uri_excessive_path );
00943         uri_resolve_path_ok ( &uri_absolute_path );
00944 
00945         /** URI resolution tests */
00946         uri_resolve_ok ( &uri_relative );
00947         uri_resolve_ok ( &uri_absolute );
00948         uri_resolve_ok ( &uri_absolute_uri_path );
00949         uri_resolve_ok ( &uri_query );
00950         uri_resolve_ok ( &uri_fragment );
00951 
00952         /* PXE URI construction tests */
00953         uri_pxe_ok ( &uri_pxe_absolute );
00954         uri_pxe_ok ( &uri_pxe_absolute_path );
00955         uri_pxe_ok ( &uri_pxe_relative_path );
00956         uri_pxe_ok ( &uri_pxe_icky );
00957         uri_pxe_ok ( &uri_pxe_port );
00958 
00959         /* Current working URI tests */
00960         uri_churi_ok ( uri_churi );
00961 
00962         /* Form parameter URI tests */
00963         uri_params_ok ( &uri_params );
00964         uri_params_ok ( &uri_named_params );
00965 }
00966 
00967 /** URI self-test */
00968 struct self_test uri_test __self_test = {
00969         .name = "uri",
00970         .exec = uri_test_exec,
00971 };