1/* 2 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/* @test 25 * @summary Unit test for java.net.URL (Based on the URI tests that is authored by Mark Reinhold) 26 * @bug 4496251 27 */ 28 29import java.io.ByteArrayInputStream; 30import java.io.ByteArrayOutputStream; 31import java.io.IOException; 32import java.io.ObjectInputStream; 33import java.io.ObjectOutputStream; 34import java.io.PrintStream; 35import java.net.URL; 36import java.net.MalformedURLException; 37 38 39public class Test { 40 41 static PrintStream out = System.out; 42 static int testCount = 0; 43 44 // Properties that we check 45 static final int PARSEFAIL = 1 << 0; 46 static final int PROTOCOL = 1 << 1; 47 static final int USERINFO = 1 << 2; 48 static final int HOST = 1 << 3; 49 static final int PORT = 1 << 4; 50 static final int PATH = 1 << 5; 51 static final int QUERY = 1 << 6; 52 static final int REF = 1 << 7; 53 54 String input; 55 URL url = null; 56 URL originalURL; 57 URL base = null; // Base for resolution/relativization 58 String op = null; // Op performed if url != originalURL 59 int checked = 0; // Mask for checked properties 60 int failed = 0; // Mask for failed properties 61 Exception exc = null; 62 63 private Test(String s) { 64 testCount++; 65 input = s; 66 try { 67 url = new URL(s); 68 } catch (MalformedURLException x) { 69 exc = x; 70 } 71 originalURL = url; 72 } 73 74 static Test test(String s) { 75 return new Test(s); 76 } 77 78 private Test(String s, boolean xxx) { 79 testCount++; 80 try { 81 url = new URL(s); 82 } catch (Exception x) { 83 exc = x; 84 } 85 if (url != null) 86 input = url.toString(); 87 originalURL = url; 88 } 89 90 static Test test(URL base, String spec) { 91 return new Test(base, spec); 92 } 93 private Test(URL base, String spec) { 94 testCount++; 95 try { 96 url = new URL(base, spec); 97 } catch (Exception x) { 98 exc = x; 99 } 100 if (url != null) 101 input = url.toString(); 102 originalURL = url; 103 } 104 105 static Test test(String protocol, String host, int port, String file) { 106 return new Test(protocol, host, port, file); 107 } 108 private Test(String protocol, String host, int port, String file) { 109 testCount++; 110 try { 111 url = new URL(protocol, host, port, file); 112 } catch (Exception x) { 113 exc = x; 114 } 115 if (url != null) 116 input = url.toString(); 117 originalURL = url; 118 } 119 120 boolean parsed() { 121 return url != null; 122 } 123 124 boolean resolved() { 125 return base != null; 126 } 127 128 URL url() { 129 return url; 130 } 131 132 // Operations on Test instances 133 // 134 // These are short so as to make test cases compact. 135 // 136 // s Scheme 137 // u User info 138 // h Host 139 // n port Number 140 // p Path 141 // q Query 142 // f Fragment 143 // 144 // rslv Resolve against given base 145 // rtvz Relativize 146 // psa Parse server Authority 147 // norm Normalize 148 // 149 // x Check that parse failed as expected 150 // z End -- ensure that unchecked components are null 151 152 private boolean check1(int prop) { 153 checked |= prop; 154 if (!parsed()) { 155 failed |= prop; 156 return false; 157 } 158 return true; 159 } 160 161 private void check2(String s, String ans, int prop) { 162 if (s == null && ans == null) 163 return; 164 if ((s == null) || !s.equals(ans)) 165 failed |= prop; 166 } 167 168 Test s(String s) { 169 if (check1(PROTOCOL)) check2(url.getProtocol(), s, PROTOCOL); 170 return this; 171 } 172 173 Test u(String s) { 174 if (check1(USERINFO)) check2(url.getUserInfo(), s, USERINFO); 175 return this; 176 } 177 178 Test h(String s) { 179 if (check1(HOST)) check2(url.getHost(), s, HOST); 180 return this; 181 } 182 183 Test n(int n) { 184 checked |= PORT; 185 if (!parsed() || (url.getPort() != n)) 186 failed |= PORT; 187 return this; 188 } 189 190 Test p(String s) { 191 if (check1(PATH)) check2(url.getPath(), s, PATH); 192 return this; 193 } 194 195 Test q(String s) { 196 if (check1(QUERY)) check2(url.getQuery(), s, QUERY); 197 return this; 198 } 199 200 Test f(String s) { 201 if (check1(REF)) check2(url.getRef(), s, REF); 202 return this; 203 } 204 205 Test x() { 206 checked |= PARSEFAIL; 207 if (parsed()) 208 failed |= PARSEFAIL; 209 return this; 210 } 211 212 private void checkEmpty(String s, int prop) { 213 if (((checked & prop) == 0) && (s != null)) 214 failed |= prop; 215 } 216 217 // Check that unchecked component properties are not defined, 218 // and report any failures 219 Test z() { 220 if (!parsed()) { 221 report(); 222 return this; 223 } 224 checkEmpty(url.getProtocol(), PROTOCOL); 225 checkEmpty(url.getUserInfo(), USERINFO); 226 checkEmpty(url.getHost(), HOST); 227 if (((checked & PORT) == 0) && (url.getPort() != -1)) failed |= PORT; 228 checkEmpty(url.getPath(), PATH); 229 checkEmpty(url.getQuery(), QUERY); 230 checkEmpty(url.getRef(), REF); 231 report(); 232 return this; 233 } 234 235 236 // Summarization and reporting 237 238 static void header(String s) { 239 out.println(); 240 out.println(); 241 out.println("-- " + s + " --"); 242 } 243 244 static void show(String prefix, MalformedURLException x) { 245 out.println(prefix + ": " + x.getMessage()); 246 } 247 248 private void summarize() { 249 out.println(); 250 StringBuffer sb = new StringBuffer(); 251 if (input.length() == 0) 252 sb.append("\"\""); 253 else 254 sb.append(input); 255 if (base != null) { 256 sb.append(" "); 257 sb.append(base); 258 } 259 if (!parsed()) { 260 String s = (((checked & PARSEFAIL) != 0) 261 ? "Correct exception" : "UNEXPECTED EXCEPTION"); 262 if (exc instanceof MalformedURLException) 263 show(s, (MalformedURLException)exc); 264 else { 265 out.println(sb.toString()); 266 out.print(s + ": "); 267 exc.printStackTrace(out); 268 } 269 } else { 270 if (url != originalURL) { 271 sb.append(" "); 272 sb.append(op); 273 sb.append(" --> "); 274 sb.append(url); 275 } 276 out.println(sb.toString()); 277 } 278 } 279 280 static void show(String n, String v) { 281 out.println(" " + n + " = ".substring(n.length()) + v); 282 } 283 284 public static void show(URL u) { 285 show("scheme", u.getProtocol()); 286 show("authority", u.getAuthority()); 287 show("userInfo", u.getUserInfo()); 288 show("host", u.getHost()); 289 show("port", "" + u.getPort()); 290 show("path", u.getPath()); 291 show("query", u.getQuery()); 292 show("ref", u.getRef()); 293 } 294 295 private void report() { 296 summarize(); 297 if (failed == 0) return; 298 StringBuffer sb = new StringBuffer(); 299 sb.append("FAIL:"); 300 if ((failed & PARSEFAIL) != 0) sb.append(" parsefail"); 301 if ((failed & PROTOCOL) != 0) sb.append(" scheme"); 302 if ((failed & USERINFO) != 0) sb.append(" userinfo"); 303 if ((failed & HOST) != 0) sb.append(" host"); 304 if ((failed & PORT) != 0) sb.append(" port"); 305 if ((failed & PATH) != 0) sb.append(" path"); 306 if ((failed & QUERY) != 0) sb.append(" query"); 307 if ((failed & REF) != 0) sb.append(" fragment"); 308 out.println(sb.toString()); 309 if (url != null) show(url); 310 throw new RuntimeException("Test failed"); 311 } 312 313 private static boolean hasFtp() { 314 try { 315 return new java.net.URL("ftp://") != null; 316 } catch (java.net.MalformedURLException x) { 317 System.out.println("FTP not supported by this runtime."); 318 return false; 319 } 320 } 321 322 // -- Tests -- 323 324 static void rfc2396() { 325 326 327 header("RFC2396: Basic examples"); 328 329 if (hasFtp()) 330 test("ftp://ftp.is.co.za/rfc/rfc1808.txt") 331 .s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z(); 332 333 test("http://www.math.uio.no/faq/compression-faq/part1.html") 334 .s("http").h("www.math.uio.no").p("/faq/compression-faq/part1.html").z(); 335 336 test("http://www.w3.org/Addressing/") 337 .s("http").h("www.w3.org").p("/Addressing/").z(); 338 339 if (hasFtp()) 340 test("ftp://ds.internic.net/rfc/") 341 .s("ftp").h("ds.internic.net").p("/rfc/").z(); 342 343 test("http://www.ics.uci.edu/pub/ietf/url/historical.html#WARNING") 344 .s("http").h("www.ics.uci.edu").p("/pub/ietf/url/historical.html") 345 .f("WARNING").z(); 346 347 test("http://www.ics.uci.edu/pub/ietf/url/#Related") 348 .s("http").h("www.ics.uci.edu").p("/pub/ietf/url/") 349 .f("Related").z(); 350 351 test("file:/home/someone/dir1/dir2/file").s("file").h("").p("/home/someone/dir1/dir2/file").z(); 352 353 header("RFC2396: Normal relative-URL examples (appendix C)"); 354 355 URL base = (test("http://a/b/c/d;p?q") 356 .s("http").h("a").p("/b/c/d;p").q("q").z().url()); 357 358 // g:h g:h 359 // test(base, "http:h").s("g").p("h").z(); 360 361 // g http://a/b/c/g 362 test(base, "g").s("http").h("a").p("/b/c/g").z(); 363 364 // ./g http://a/b/c/g 365 test(base, "./g").s("http").h("a").p("/b/c/g").z(); 366 367 // g/ http://a/b/c/g/ 368 test(base, "g/").s("http").h("a").p("/b/c/g/").z(); 369 370 // /g http://a/g 371 test(base, "/g").s("http").h("a").p("/g").z(); 372 373 // //g http://g 374 test(base,"//g").s("http").h("g").p("").z(); 375 376 // ?y http://a/b/c/?y 377 test(base, "?y").s("http").h("a").p("/b/c/").q("y").z(); 378 379 // g?y http://a/b/c/g?y 380 test(base, "g?y").s("http").h("a").p("/b/c/g").q("y").z(); 381 382 // #s (current document)#s 383 // DEVIATION: Lone fragment parses as relative URL with empty path, 384 // and resolves without removing the last segment of the base path. 385 // test(base,"#s").s("http").h("a").p("/b/c/d;p").f("s").z(); 386 test(base,"#s").s("http").h("a").p("/b/c/d;p").q("q").f("s").z(); 387 388 // g#s http://a/b/c/g#s 389 test(base, "g#s").s("http").h("a").p("/b/c/g").f("s").z(); 390 391 // g?y#s http://a/b/c/g?y#s 392 test(base,"g?y#s").s("http").h("a").p("/b/c/g").q("y").f("s").z(); 393 394 // ;x http://a/b/c/;x 395 test(base,";x").s("http").h("a").p("/b/c/;x").z(); 396 397 // g;x http://a/b/c/g;x 398 test(base,"g;x").s("http").h("a").p("/b/c/g;x").z(); 399 400 // g;x?y#s http://a/b/c/g;x?y#s 401 test(base,"g;x?y#s").s("http").h("a").p("/b/c/g;x").q("y").f("s").z(); 402 403 // . http://a/b/c/ 404 test(base,".").s("http").h("a").p("/b/c/").z(); 405 406 // ./ http://a/b/c/ 407 test(base,"./").s("http").h("a").p("/b/c/").z(); 408 409 // .. http://a/b/ 410 test(base,"..").s("http").h("a").p("/b/").z(); 411 412 // ../ http://a/b/ 413 test(base,"../").s("http").h("a").p("/b/").z(); 414 415 // ../g http://a/b/g 416 test(base,"../g").s("http").h("a").p("/b/g").z(); 417 418 // ../.. http://a/ 419 test(base,"../..").s("http").h("a").p("/").z(); 420 421 // ../../ http://a/ 422 test(base,"../../").s("http").h("a").p("/").z(); 423 424 // ../../g http://a/g 425 test(base,"../../g").s("http").h("a").p("/g").z(); 426 427 428 // http://u@s1/p1 http://s2/p2 429 test(test("http://u:p@s1/p1").url(),"http://s2/p2") 430 .s("http").h("s2").u(null).p("/p2").z(); 431 432 header("RFC2396: Abnormal relative-URL examples (appendix C)"); 433 434 // ../../../g = http://a/../g 435 test(base,"../../../g").s("http").h("a").p("/../g").z(); 436 437 // ../../../../g = http://a/../../g 438 test(base, "../../../../g").s("http").h("a").p("/../../g").z(); 439 440 441 // /./g = http://a/./g 442 test(base,"/./g").s("http").h("a").p("/./g").z(); 443 444 // /../g = http://a/../g 445 test(base,"/../g").s("http").h("a").p("/../g").z(); 446 447 // g. = http://a/b/c/g. 448 test(base,"g.").s("http").h("a").p("/b/c/g.").z(); 449 450 // .g = http://a/b/c/.g 451 test(base,".g").s("http").h("a").p("/b/c/.g").z(); 452 453 // g.. = http://a/b/c/g.. 454 test(base,"g..").s("http").h("a").p("/b/c/g..").z(); 455 456 // ..g = http://a/b/c/..g 457 test(base,"..g").s("http").h("a").p("/b/c/..g").z(); 458 459 // ./../g = http://a/b/g 460 test(base,"./../g").s("http").h("a").p("/b/g").z(); 461 462 // ./g/. = http://a/b/c/g/ 463 test(base,"./g/.").s("http").h("a").p("/b/c/g/").z(); 464 465 // g/./h = http://a/b/c/g/h 466 test(base,"g/./h").s("http").h("a").p("/b/c/g/h").z(); 467 468 // g/../h = http://a/b/c/h 469 test(base,"g/../h").s("http").h("a").p("/b/c/h").z(); 470 471 // g;x=1/./y = http://a/b/c/g;x=1/y 472 test(base,"g;x=1/./y").s("http").h("a").p("/b/c/g;x=1/y").z(); 473 474 // g;x=1/../y = http://a/b/c/y 475 test(base,"g;x=1/../y").s("http").h("a").p("/b/c/y").z(); 476 477 // g?y/./x = http://a/b/c/g?y/./x 478 test(base,"g?y/./x").s("http").h("a").p("/b/c/g").q("y/./x").z(); 479 480 // g?y/../x = http://a/b/c/g?y/../x 481 test(base,"g?y/../x").s("http").h("a").p("/b/c/g").q("y/../x").z(); 482 483 // g#s/./x = http://a/b/c/g#s/./x 484 test(base,"g#s/./x").s("http").h("a").p("/b/c/g").f("s/./x").z(); 485 486 // g#s/../x = http://a/b/c/g#s/../x 487 test(base,"g#s/../x").s("http").h("a").p("/b/c/g").f("s/../x").z(); 488 489 // http:g = http:g 490 // test(base,"http:g").s("http").p("g").z(); 491 492 } 493 494 495 static void ip() { 496 497 header("IP addresses"); 498 499 test("http://1.2.3.4:5") 500 .s("http").h("1.2.3.4").n(5).p("").z(); 501 502 // From RFC2732 503 504 test("http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html") 505 .s("http").h("[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]") 506 .n(80).p("/index.html").z(); 507 508 test("http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210%12]:80/index.html") 509 .s("http").h("[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210%12]") 510 .n(80).p("/index.html").z(); 511 512 test("http://[1080:0:0:0:8:800:200C:417A]/index.html") 513 .s("http").h("[1080:0:0:0:8:800:200C:417A]").p("/index.html").z(); 514 515 test("http://[1080:0:0:0:8:800:200C:417A%1]/index.html") 516 .s("http").h("[1080:0:0:0:8:800:200C:417A%1]").p("/index.html").z(); 517 518 test("http://[3ffe:2a00:100:7031::1]") 519 .s("http").h("[3ffe:2a00:100:7031::1]").p("").z(); 520 521 test("http://[1080::8:800:200C:417A]/foo") 522 .s("http").h("[1080::8:800:200C:417A]").p("/foo").z(); 523 524 test("http://[::192.9.5.5]/ipng") 525 .s("http").h("[::192.9.5.5]").p("/ipng").z(); 526 527 test("http://[::192.9.5.5%interface]/ipng") 528 .s("http").h("[::192.9.5.5%interface]").p("/ipng").z(); 529 530 test("http://[::FFFF:129.144.52.38]:80/index.html") 531 .s("http").h("[::FFFF:129.144.52.38]").n(80).p("/index.html").z(); 532 533 test("http://[2010:836B:4179::836B:4179]") 534 .s("http").h("[2010:836B:4179::836B:4179]").p("").z(); 535 536 // From RFC2373 537 538 test("http://[FF01::101]") 539 .s("http").h("[FF01::101]").p("").z(); 540 541 test("http://[::1]") 542 .s("http").h("[::1]").p("").z(); 543 544 test("http://[::]") 545 .s("http").h("[::]").p("").z(); 546 547 test("http://[::%hme0]") 548 .s("http").h("[::%hme0]").p("").z(); 549 550 test("http://[0:0:0:0:0:0:13.1.68.3]") 551 .s("http").h("[0:0:0:0:0:0:13.1.68.3]").p("").z(); 552 553 test("http://[0:0:0:0:0:FFFF:129.144.52.38]") 554 .s("http").h("[0:0:0:0:0:FFFF:129.144.52.38]").p("").z(); 555 556 test("http://[0:0:0:0:0:FFFF:129.144.52.38%33]") 557 .s("http").h("[0:0:0:0:0:FFFF:129.144.52.38%33]").p("").z(); 558 559 test("http://[::13.1.68.3]") 560 .s("http").h("[::13.1.68.3]").p("").z(); 561 562 test("http://[::13.1.68.3]:") 563 .s("http").h("[::13.1.68.3]").p("").z(); 564 // Error cases 565 566 test("http://[ff01:234/foo").x().z(); 567 test("http://[ff01:234:zzz]/foo").x().z(); 568 test("http://[foo]").x().z(); 569 test("http://[]").x().z(); 570 test("http://[129.33.44.55]").x().z(); 571 test("http://[ff:ee:dd::cc:bb::aa:9:8]").x().z(); 572 test("http://[1:2:3:4:5:6:7:8%]").x().z(); 573 test("http://[1:2:3:4:5:6:7:8%!/]").x().z(); 574 test("http://[1:2:3:4:5:6:7:8:9]").x().z(); 575 test("http://[::1.2.3.300]").x().z(); 576 test("http://[1.2.3.4:5]").x().z(); 577 578 // Optional IPv6 brackets in constructors 579 test("http", "1:2:3:4:5:6:7:8", -1, "") 580 .s("http").h("[1:2:3:4:5:6:7:8]").p("").z(); 581 test("http", "1:2:3:4:5:6:7:8%hme0", -1, "") 582 .s("http").h("[1:2:3:4:5:6:7:8%hme0]").p("").z(); 583 test("http", "[1:2:3:4:5:6:7:8]", -1, "") 584 .s("http").h("[1:2:3:4:5:6:7:8]").p("").z(); 585 586 } 587 588 static void serial() throws IOException, MalformedURLException { 589 590 header("Serialization"); 591 592 ByteArrayOutputStream bo = new ByteArrayOutputStream(); 593 ObjectOutputStream oo = new ObjectOutputStream(bo); 594 URL u = new URL("http://java.sun.com/jdk/1.4?release#beta"); 595 oo.writeObject(u); 596 oo.close(); 597 598 ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray()); 599 ObjectInputStream oi = new ObjectInputStream(bi); 600 try { 601 Object o = oi.readObject(); 602 u.equals(o); 603 } catch (ClassNotFoundException x) { 604 x.printStackTrace(); 605 throw new RuntimeException(x.toString()); 606 } 607 608 } 609 610 static void tests() throws IOException, MalformedURLException { 611 rfc2396(); 612 ip(); 613 serial(); 614 } 615 616 617 // -- Command-line invocation -- 618 619 static void usage() { 620 out.println("Usage:"); 621 out.println(" java Test -- Runs all tests in this file"); 622 out.println(" java Test <url> -- Parses url, shows components"); 623 out.println(" java Test <base> <url> -- Parses url and base, then resolves"); 624 out.println(" url against base"); 625 } 626 627 public static void main(String[] args) throws Exception { 628 switch (args.length) { 629 630 case 0: 631 tests(); 632 out.println(); 633 out.println("Test cases: " + testCount); 634 break; 635 636 case 1: 637 if (args[0].equals("-help")) { 638 usage(); 639 break; 640 } 641 // clargs(null, args[0]); 642 break; 643 644 case 2: 645 // clargs(args[0], args[1]); 646 break; 647 648 default: 649 usage(); 650 break; 651 652 } 653 } 654 655} 656