1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 * License for the specific language governing permissions and limitations under 15 * the License. 16 */ 17 package org.apache.harmony.tests.java.net; 18 19 import junit.framework.TestCase; 20 21 import java.net.HttpCookie; 22 import java.text.DateFormat; 23 import java.text.SimpleDateFormat; 24 import java.util.Date; 25 import java.util.List; 26 import java.util.Locale; 27 import java.util.TimeZone; 28 29 public class HttpCookieTest extends TestCase { 30 private Locale locale; 31 32 /** 33 * java.net.HttpCookie(String, String). 34 * @since 1.6 35 */ 36 public void test_HttpCookie_LString_LString() { 37 assertNotNull(new HttpCookie("harmony_6", "test,sem")); 38 assertNotNull(new HttpCookie("harmony_6", null)); 39 assertNotNull(new HttpCookie("harmony ", null)); 40 assertEquals("harmony", new HttpCookie("harmony ", null).getName()); 41 42 constructHttpCookie("", null); 43 44 String value = "value"; 45 constructHttpCookie("", value); 46 47 constructHttpCookie("harmony,", value); 48 constructHttpCookie("harmony;", value); 49 constructHttpCookie("$harmony", value); 50 constructHttpCookie("n\tame", value); 51 constructHttpCookie("n\rame", value); 52 constructHttpCookie("n\r\name", value); 53 constructHttpCookie("Comment", value); 54 constructHttpCookie("CommentURL", value); 55 constructHttpCookie("Domain", value); 56 constructHttpCookie("Discard", value); 57 constructHttpCookie("Max-Age", value); 58 constructHttpCookie(" Path ", value); 59 constructHttpCookie("Port ", value); 60 constructHttpCookie("SeCure", value); 61 constructHttpCookie("VErsion", value); 62 constructHttpCookie("expires", value); 63 constructHttpCookie("na\u0085me", value); 64 constructHttpCookie("\u2028me", value); 65 constructHttpCookie("na\u2029me", value); 66 67 try { 68 new HttpCookie(null, value); 69 fail("Should throw NullPointerException"); 70 } catch (NullPointerException e) { 71 // expected 72 } 73 74 try { 75 new HttpCookie("\u007f", value); 76 fail("Should throw IllegalArgumentException"); 77 } catch (IllegalArgumentException e) { 78 // expected 79 } 80 81 HttpCookie cookie = new HttpCookie("harmony!", null); 82 assertEquals("harmony!", cookie.getName()); 83 84 cookie = new HttpCookie("harmon$y", null); 85 assertEquals("harmon$y", cookie.getName()); 86 87 } 88 89 private static void constructHttpCookie(String name, String value) { 90 try { 91 new HttpCookie(name, value); 92 fail("Should throw IllegalArgumentException"); 93 } catch (IllegalArgumentException e) { 94 // expected 95 } 96 } 97 98 /** 99 * java.net.HttpCookie#domainMatches(String, String). 100 * @since 1.6 101 */ 102 public void test_DomainMatches() { 103 104 /* 105 * Rule 1: A host isn't in a domain (RFC 2965 sec. 3.3.2) if: The value 106 * for the Domain attribute contains no embedded dots, and the value is 107 * not .local. 108 */ 109 boolean match = HttpCookie.domainMatches("hostname", "hostname"); 110 assertFalse(match); 111 112 match = HttpCookie.domainMatches(".com", "test.com"); 113 assertFalse(match); 114 115 match = HttpCookie.domainMatches(".com.", "test.com"); 116 assertFalse(match); 117 118 // During comparison, host name is transformed to effective host name 119 // first. 120 match = HttpCookie.domainMatches(".local", "hostname"); 121 assertTrue(match); 122 123 /* 124 * Rule 3: The request-host is a HDN (not IP address) and has the form 125 * HD, where D is the value of the Domain attribute, and H is a string 126 * that contains one or more dots. 127 */ 128 match = HttpCookie.domainMatches(".c.d", "a.b.c.d"); 129 assertTrue(match); 130 131 match = HttpCookie.domainMatches("c.d", "a.b.c.d"); 132 assertFalse(match); 133 134 match = HttpCookie.domainMatches(".foo.com", "y.x.foo.com"); 135 assertTrue(match); 136 137 match = HttpCookie.domainMatches(".foo.com", "x.foo.com"); 138 assertTrue(match); 139 140 match = HttpCookie.domainMatches(".local", "hostname.local"); 141 assertTrue(match); 142 143 match = HttpCookie.domainMatches(".ajax.com", "a.ajax.com"); 144 assertTrue(match); 145 146 match = HttpCookie.domainMatches(".ajax.com", "a.AJAX.com"); 147 assertTrue(match); 148 149 match = HttpCookie.domainMatches("...", "test..."); 150 assertFalse(match); 151 152 match = HttpCookie.domainMatches(".ajax.com", "b.a.AJAX.com"); 153 assertTrue(match); 154 155 match = HttpCookie.domainMatches(".a", "b.a"); 156 assertFalse(match); 157 158 // when either parameter is null 159 match = HttpCookie.domainMatches(".ajax.com", null); 160 assertFalse(match); 161 162 match = HttpCookie.domainMatches(null, null); 163 assertFalse(match); 164 165 match = HttpCookie.domainMatches(null, "b.a.AJAX.com"); 166 assertFalse(match); 167 168 // JDK-7023713 169 match = HttpCookie.domainMatches("hostname.local", "hostname"); 170 assertTrue(match); 171 } 172 173 /** 174 * java.net.HttpCookie#getVersion(), setVersion(int). 175 * @since 1.6 176 */ 177 public void test_Get_SetVersion() { 178 HttpCookie cookie = new HttpCookie("name", "value"); 179 assertEquals(1, cookie.getVersion()); 180 cookie.setVersion(0); 181 assertEquals(0, cookie.getVersion()); 182 cookie.setVersion(1); 183 assertEquals(1, cookie.getVersion()); 184 185 try { 186 cookie.setVersion(-1); 187 fail("should throw IllegalArgumentException"); 188 } catch (IllegalArgumentException e) { 189 // expected 190 } 191 192 try { 193 cookie.setVersion(2); 194 fail("should throw IllegalArgumentException"); 195 } catch (IllegalArgumentException e) { 196 // expected 197 } 198 } 199 200 /** 201 * java.net.HttpCookie#getValue(), setValue(String) 202 * @since 1.6 203 */ 204 public void test_Get_SetValue() { 205 HttpCookie cookie = new HttpCookie("name", "value"); 206 assertEquals("value", cookie.getValue()); 207 cookie.setValue("newValue"); 208 assertEquals("newValue", cookie.getValue()); 209 210 cookie.setValue(null); 211 assertNull(cookie.getValue()); 212 213 cookie.setValue("na\u64DEme"); 214 assertEquals("na\u64DEme", cookie.getValue()); 215 cookie.setVersion(0); 216 cookie.setValue("{(new value, 11)}"); 217 assertEquals("{(new value, 11)}", cookie.getValue()); 218 } 219 220 /** 221 * java.net.HttpCookie#getName() 222 * @since 1.6 223 */ 224 public void test_GetName() { 225 HttpCookie cookie = new HttpCookie("testName", "value"); 226 assertEquals("testName", cookie.getName()); 227 } 228 229 /** 230 * java.net.HttpCookie#getSecure(), setSecure(boolean) 231 * @since 1.6 232 */ 233 public void test_Get_SetSecure() { 234 HttpCookie cookie = new HttpCookie("testName", "value"); 235 assertFalse(cookie.getSecure()); 236 cookie.setVersion(0); 237 assertFalse(cookie.getSecure()); 238 239 cookie.setSecure(true); 240 assertTrue(cookie.getSecure()); 241 cookie.setSecure(false); 242 cookie.setVersion(1); 243 assertFalse(cookie.getSecure()); 244 } 245 246 /** 247 * java.net.HttpCookie#getPath(), setPath(String) 248 * @since 1.6 249 */ 250 public void test_Get_SetPath() { 251 HttpCookie cookie = new HttpCookie("name", "test new value"); 252 assertNull(cookie.getPath()); 253 254 cookie.setPath("{}() test,; 43!@"); 255 assertEquals("{}() test,; 43!@", cookie.getPath()); 256 257 cookie.setPath(" test"); 258 assertEquals(" test", cookie.getPath()); 259 260 cookie.setPath("\u63DF\u64DE"); 261 cookie.setDomain("test"); 262 assertEquals("\u63DF\u64DE", cookie.getPath()); 263 } 264 265 /** 266 * java.net.HttpCookie#getMaxAge(), setMaxAge(long) 267 * @since 1.6 268 */ 269 public void test_Get_SetMaxAge() { 270 HttpCookie cookie = new HttpCookie("name", "test new value"); 271 assertEquals(-1, cookie.getMaxAge()); 272 273 cookie.setMaxAge(Long.MAX_VALUE); 274 assertEquals(Long.MAX_VALUE, cookie.getMaxAge()); 275 276 cookie.setMaxAge(Long.MIN_VALUE); 277 cookie.setDiscard(false); 278 assertEquals(Long.MIN_VALUE, cookie.getMaxAge()); 279 } 280 281 /** 282 * java.net.HttpCookie#getDomain(), setDomain(String) 283 * @since 1.6 284 */ 285 public void test_Get_SetDomain() { 286 HttpCookie cookie = new HttpCookie("name", "test new value"); 287 assertNull(cookie.getDomain()); 288 289 cookie.setDomain("a.b.d.c.com."); 290 assertEquals("a.b.d.c.com.", cookie.getDomain()); 291 292 cookie.setDomain(" a.b.d.c.com. "); 293 assertEquals(" a.b.d.c.com. ", cookie.getDomain()); 294 295 cookie.setPath("temp/subTemp"); 296 cookie.setDomain("xy.foo.bar.de.edu"); 297 assertEquals("xy.foo.bar.de.edu", cookie.getDomain()); 298 } 299 300 /** 301 * java.net.HttpCookie#getPortlist(), setPortlist(String) 302 * @since 1.6 303 */ 304 public void test_Get_SetPortlist() { 305 HttpCookie cookie = new HttpCookie("cookieName", "cookieName value"); 306 assertNull(cookie.getPortlist()); 307 308 cookie.setPortlist("80,23,20"); 309 assertEquals("80,23,20", cookie.getPortlist()); 310 cookie.setPortlist("abcdefg1234567"); 311 cookie.setValue("cookie value again"); 312 assertEquals("abcdefg1234567", cookie.getPortlist()); 313 } 314 315 /** 316 * java.net.HttpCookie#getDiscard(), setDiscard(boolean) 317 * @since 1.6 318 */ 319 public void test_Get_SetDiscard() { 320 HttpCookie cookie = new HttpCookie("cookie'sName", 321 "cookie's Test value"); 322 assertFalse(cookie.getDiscard()); 323 324 cookie.setDiscard(true); 325 assertTrue(cookie.getDiscard()); 326 cookie.setDiscard(false); 327 cookie.setMaxAge(-1); 328 assertFalse(cookie.getDiscard()); 329 } 330 331 /** 332 * java.net.HttpCookie#getCommentURL(), setCommentURL(String) 333 * @since 1.6 334 */ 335 public void test_Get_SetCommentURL() { 336 HttpCookie cookie = new HttpCookie("cookie'\"sName", 337 "cookie's Test value"); 338 assertNull(cookie.getCommentURL()); 339 340 cookie.setCommentURL("http://www.test.com"); 341 assertEquals("http://www.test.com", cookie.getCommentURL()); 342 343 cookie.setCommentURL("schema://harmony.test.org"); 344 cookie.setComment("just a comment"); 345 assertEquals("schema://harmony.test.org", cookie.getCommentURL()); 346 } 347 348 /** 349 * java.net.HttpCookie#getComment(), setComment(String) 350 * @since 1.6 351 */ 352 public void test_Get_SetComment() { 353 HttpCookie cookie = new HttpCookie("cookie'\"sName?", 354 "cookie's Test??!@# value"); 355 assertNull(cookie.getComment()); 356 357 cookie.setComment(""); 358 assertEquals("", cookie.getComment()); 359 360 cookie.setComment("cookie''s @#$!&*()"); 361 cookie.setVersion(0); 362 assertEquals("cookie''s @#$!&*()", cookie.getComment()); 363 } 364 365 /** 366 * java.net.HttpCookie#hasExpired() 367 * @since 1.6 368 */ 369 public void test_HasExpired() { 370 HttpCookie cookie = new HttpCookie("cookie'\"sName123456", 371 "cookie's Test?()!@# value"); 372 assertFalse(cookie.hasExpired()); 373 374 cookie.setMaxAge(0); 375 assertTrue(cookie.hasExpired()); 376 377 cookie.setMaxAge(Long.MAX_VALUE); 378 cookie.setVersion(0); 379 assertFalse(cookie.hasExpired()); 380 381 cookie.setMaxAge(Long.MIN_VALUE); 382 cookie.setDiscard(false); 383 assertTrue(cookie.hasExpired()); 384 385 cookie.setDiscard(true); 386 cookie.setMaxAge(-1); 387 assertFalse(cookie.hasExpired()); 388 } 389 390 /** 391 * Regression test for http://b/25682357. 392 */ 393 public void test_HasExpiredBug25682357() throws Exception { 394 HttpCookie cookie1 = HttpCookie.parse("Set-Cookie:name=value;max-age=2;").get(0); 395 HttpCookie cookie2 = HttpCookie.parse("Set-Cookie:name=value;max-age=100;").get(0); 396 assertFalse(cookie1.hasExpired()); 397 assertFalse(cookie2.hasExpired()); 398 399 // Sleep for long enough to force expiry of the first cookie. 400 Thread.sleep(3000); 401 assertTrue(cookie1.hasExpired()); 402 assertFalse(cookie2.hasExpired()); 403 404 assertEquals(2, cookie1.getMaxAge()); 405 assertEquals(100, cookie2.getMaxAge()); 406 407 // Changing the max age should not reset the expiry status. 408 cookie1.setMaxAge(2); 409 assertTrue(cookie1.hasExpired()); 410 } 411 412 /** 413 * Regression test for http://b/25682357. 414 */ 415 public void test_HasExpiredBug25682357_2() throws Exception { 416 // The following tests do not pass on the RI: it may not handle "expires" at all. 417 DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US); 418 dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); 419 String pastExpiryDate = dateFormat.format(new Date(System.currentTimeMillis() - 100_000)); 420 String pastExpiryCookieHeader = 421 "Set-Cookie:name=value;expires=" + pastExpiryDate + ";"; 422 HttpCookie pastExpiryCookie = HttpCookie.parse(pastExpiryCookieHeader).get(0); 423 assertTrue(pastExpiryCookie.hasExpired()); 424 425 String futureExpiryDate = dateFormat.format(new Date(System.currentTimeMillis() + 100_000)); 426 String futureExpiryCookieHeader = 427 "Set-Cookie:name=value;expires=" + futureExpiryDate + ";"; 428 HttpCookie futureExpiryCookie = HttpCookie.parse(futureExpiryCookieHeader).get(0); 429 assertFalse(futureExpiryCookie.hasExpired()); 430 } 431 432 /** 433 * java.net.HttpCookie#equals() 434 * @since 1.6 435 */ 436 public void test_Equals() { 437 Object obj = new Object(); 438 HttpCookie cookie = new HttpCookie("test", "testValue"); 439 HttpCookie cookie2 = new HttpCookie("TesT", "TEstValue"); 440 441 assertFalse(cookie.equals(obj)); 442 assertFalse(cookie.equals(null)); 443 assertTrue(cookie2.equals(cookie)); 444 assertTrue(cookie.equals(cookie2)); 445 assertTrue(cookie.equals(cookie)); 446 447 cookie.setDomain(" test"); 448 cookie2.setDomain("test"); 449 assertFalse(cookie.equals(cookie2)); 450 cookie.setDomain("TEST"); 451 assertTrue(cookie.equals(cookie2)); 452 453 cookie.setPath("temp\\e"); 454 assertFalse(cookie.equals(cookie2)); 455 cookie2.setPath("temp\\E"); 456 assertFalse(cookie.equals(cookie2)); 457 458 cookie.setDiscard(true); 459 cookie.setMaxAge(-1234); 460 cookie2.setPath("temp\\e"); 461 assertTrue(cookie.equals(cookie2)); 462 } 463 464 /** 465 * java.net.HttpCookie#clone() 466 * @since 1.6 467 */ 468 public void test_Clone() { 469 HttpCookie cookie = new HttpCookie("test", "testValue"); 470 cookie.setMaxAge(33l); 471 cookie.setComment("test comment"); 472 HttpCookie cloneCookie = (HttpCookie) cookie.clone(); 473 assertNotSame(cloneCookie, cookie); 474 assertEquals("test", cloneCookie.getName()); 475 assertEquals(33l, cloneCookie.getMaxAge()); 476 assertEquals("test comment", cloneCookie.getComment()); 477 } 478 479 /** 480 * java.net.HttpCookie#toString() 481 * @since 1.6 482 */ 483 public void test_ToString() { 484 HttpCookie cookie = new HttpCookie("test", "testValue"); 485 cookie.setComment("ABCd"); 486 cookie.setCommentURL("\u63DF"); 487 cookie.setDomain(".B.com"); 488 cookie.setDiscard(true); 489 cookie.setMaxAge(Integer.MAX_VALUE); 490 cookie.setPath("temp/22RuTh"); 491 cookie.setPortlist("80.562Ab"); 492 cookie.setSecure(true); 493 cookie.setVersion(1); 494 495 assertEquals( 496 "test=\"testValue\";$Path=\"temp/22RuTh\";$Domain=\".b.com\";$Port=\"80.562Ab\"", 497 cookie.toString()); 498 499 cookie.setPath(null); 500 assertEquals( 501 "test=\"testValue\";$Domain=\".b.com\";$Port=\"80.562Ab\"", 502 cookie.toString()); 503 cookie.setComment(null); 504 assertEquals( 505 "test=\"testValue\";$Domain=\".b.com\";$Port=\"80.562Ab\"", 506 cookie.toString()); 507 cookie.setPortlist(null); 508 assertEquals("test=\"testValue\";$Domain=\".b.com\"", cookie.toString()); 509 cookie.setDomain(null); 510 assertEquals("test=\"testValue\"", cookie.toString()); 511 512 cookie.setVersion(0); 513 cookie.setPortlist("80,8000"); 514 assertEquals("test=testValue", cookie.toString()); 515 } 516 517 /** 518 * java.net.HttpCookie#hashCode() 519 * @since 1.6 520 */ 521 public void test_HashCode() { 522 HttpCookie cookie = new HttpCookie("nAmW_1", "value_1"); 523 assertEquals(-1052814577, cookie.hashCode()); 524 525 cookie.setDomain("a.b.c.de"); 526 assertEquals(1222695220, cookie.hashCode()); 527 528 cookie.setPath("3kmxiq;1"); 529 assertEquals(-675006347, cookie.hashCode()); 530 cookie.setPath("3KmxiQ;1"); 531 assertEquals(989616181, cookie.hashCode()); 532 533 cookie.setValue("Vw0,22_789"); 534 assertEquals(989616181, cookie.hashCode()); 535 cookie.setComment("comment"); 536 assertEquals(989616181, cookie.hashCode()); 537 538 cookie.setDomain(""); 539 assertEquals(-1285893616, cookie.hashCode()); 540 } 541 542 /** 543 * java.net.HttpCookie#parse(String) for exception cases 544 * @since 1.6 545 */ 546 public void test_Parse_exception() { 547 try { 548 HttpCookie.parse(null); 549 fail("Should throw NullPointerException"); 550 } catch (NullPointerException e) { 551 // expected 552 } 553 /* 554 * Please note that Netscape draft specification does not fully conform 555 * to the HTTP header format. Netscape draft does not specify whether 556 * multiple cookies may be sent in one header. Hence, comma character 557 * may be present in unquoted cookie value or unquoted parameter value. 558 * Refer to <a 559 * href="http://jakarta.apache.org/commons/httpclient/apidocs/org/apache/commons/httpclient/cookie/NetscapeDraftSpec.html#parse(java.lang.String,%20int,%20java.lang.String,%20boolean,%20java.lang.String)"> 560 * http://jakarta.apache.org/commons/httpclient/apidocs/org/apache/commons/httpclient/cookie/NetscapeDraftSpec.html#parse(java.lang.String,%20int,%20java.lang.String,%20boolean,%20java.lang.String) 561 * </a> 562 */ 563 // violates the cookie specification's syntax 564 checkInvalidCookie("invalid cookie name"); 565 checkInvalidCookie("Set-Cookie2:"); 566 checkInvalidCookie("name"); 567 checkInvalidCookie("$name="); 568 checkInvalidCookie("Set-Cookie2:$name="); 569 checkInvalidCookie("Set-Cookie:$"); 570 checkInvalidCookie("Set-Cookie"); 571 572 // cookie name contains llegal characters 573 checkInvalidCookie("Set-Cookie:n,ame="); 574 checkInvalidCookie("Set-Cookie2:n\name="); 575 checkInvalidCookie("Set-Cookie2:n,ame="); 576 checkInvalidCookie("Set-Cookie2:n\tame="); 577 checkInvalidCookie("Set-Cookie2:n\rame="); 578 checkInvalidCookie("Set-Cookie2:n\r\name="); 579 checkInvalidCookie("Set-Cookie2:na\u0085me="); 580 checkInvalidCookie("Set-Cookie2:na\u2028me="); 581 checkInvalidCookie("Set-Cookie2:na\u2029me="); 582 checkInvalidCookie("Set-Cookie2:="); 583 checkInvalidCookie("Set-Cookie2:name=tes,t"); 584 585 // 'CommentURL' is one of the tokens reserved, case-insensitive 586 checkInvalidCookie("Set-Cookie2:COmmentURL=\"lala\""); 587 588 // check value 589 checkInvalidCookie("Set-Cookie2:val,ue"); 590 checkInvalidCookie("Set-Cookie2:name=test;comMent=sent,ence"); 591 checkInvalidCookie("Set-Cookie2:name=test;comMentUrL=u,rl"); 592 checkInvalidCookie("Set-Cookie2:name=test;Discard=fa,lse"); 593 checkInvalidCookie("Set-Cookie2:name=test;Disc,ard"); 594 checkInvalidCookie("Set-Cookie2:name=test;Domain=u,rl"); 595 checkInvalidCookie("Set-Cookie2:name=test;Path=pa,th"); 596 checkInvalidCookie("Set-Cookie2:name=test;Secure=se,cure"); 597 checkInvalidCookie("Set-Cookie2:name=test;se,cure"); 598 checkInvalidCookie("Set-Cookie2:name=test;Max-Age=se,cure"); 599 checkInvalidCookie("Set-Cookie2:name=test;Max-Age="); 600 checkInvalidCookie("Set-Cookie2:name=test;Max-Age=max-age"); 601 checkInvalidCookie("Set-Cookie2:name=test;Max-Age=1000.0"); 602 } 603 604 /** 605 * java.net.HttpCookie#parse(String) for locales other than 606 * Locale.ENGLISH. 607 * @since 1.6 608 */ 609 public void test_Parse_locale() { 610 Locale.setDefault(Locale.FRENCH); 611 List<HttpCookie> list = HttpCookie 612 .parse("Set-Cookie:name=test;expires=Thu, 30-Oct-2008 19:14:07 GMT;"); 613 HttpCookie cookie = list.get(0); 614 assertTrue(cookie.hasExpired()); 615 616 Locale.setDefault(Locale.GERMAN); 617 list = HttpCookie 618 .parse("Set-Cookie:name=test;expires=Sun, 30-Oct-2005 19:14:07 GMT;"); 619 cookie = list.get(0); 620 assertTrue(cookie.hasExpired()); 621 622 Locale.setDefault(Locale.KOREA); 623 list = HttpCookie 624 .parse("Set-Cookie:name=test;max-age=1234;expires=Sun, 30-Oct-2005 19:14:07 GMT;"); 625 cookie = list.get(0); 626 assertEquals(0, cookie.getVersion()); 627 assertEquals(1234, cookie.getMaxAge()); 628 assertFalse(cookie.hasExpired()); 629 630 Locale.setDefault(Locale.TAIWAN); 631 list = HttpCookie 632 .parse("Set-Cookie:name=test;max-age=-12345;"); 633 cookie = list.get(0); 634 assertEquals(-12345, cookie.getMaxAge()); 635 assertTrue(cookie.hasExpired()); 636 637 // Locale does not affect version 1 cookie. 638 Locale.setDefault(Locale.ITALIAN); 639 list = HttpCookie.parse("Set-Cookie2:name=test;max-age=1000"); 640 cookie = list.get(0); 641 assertEquals(1000, cookie.getMaxAge()); 642 assertFalse(cookie.hasExpired()); 643 } 644 645 /** 646 * java.net.HttpCookie#parse(String) for normal cases 647 * @since 1.6 648 */ 649 public void test_Parse() { 650 List<HttpCookie> list = HttpCookie.parse("test=\"null\""); 651 HttpCookie cookie = list.get(0); 652 // when two '"' presents, the parser ignores it. 653 assertEquals("null", cookie.getValue()); 654 assertNull(cookie.getComment()); 655 assertNull(cookie.getCommentURL()); 656 assertFalse(cookie.getDiscard()); 657 assertNull(cookie.getDomain()); 658 assertEquals(-1, cookie.getMaxAge()); 659 assertNull(cookie.getPath()); 660 assertNull(cookie.getPortlist()); 661 assertFalse(cookie.getSecure()); 662 // default version is 0 663 assertEquals(0, cookie.getVersion()); 664 665 list = HttpCookie.parse("Set-cookie2:name=\"tes,t\""); 666 cookie = list.get(0); 667 // when two '"' presents, the parser ignores it. 668 assertEquals("tes,t", cookie.getValue()); 669 670 // If cookie header = Set-Cookie2, version = 1 671 list = HttpCookie 672 .parse("Set-cookie2:test=null\";;Port=abde,82;Path=/temp;;;Discard;commentURl=http://harmonytest.org;Max-age=-10;"); 673 cookie = list.get(0); 674 assertEquals("null\"", cookie.getValue()); 675 assertEquals(1, cookie.getVersion()); 676 assertEquals("/temp", cookie.getPath()); 677 assertTrue(cookie.getDiscard()); 678 assertEquals("http://harmonytest.org", cookie.getCommentURL()); 679 assertEquals(-10l, cookie.getMaxAge()); 680 assertTrue(cookie.hasExpired()); 681 assertEquals("abde,82", cookie.getPortlist()); 682 // Version 0 cookie 683 list = HttpCookie 684 .parse("Set-Cookie:name=tes,t;Comment=version1-cookie;Discard=false;commentURL=vers\nion1-cookie-url;Domain=x.y;"); 685 cookie = list.get(0); 686 assertEquals(0, cookie.getVersion()); 687 assertEquals("tes,t", cookie.getValue()); 688 assertEquals("name", cookie.getName()); 689 assertEquals("version1-cookie", cookie.getComment()); 690 assertEquals("vers\nion1-cookie-url", cookie.getCommentURL()); 691 assertEquals("x.y", cookie.getDomain()); 692 assertTrue(cookie.getDiscard()); 693 694 // Check value 695 checkValidValue("Set-Cookie:", "val,ue"); 696 checkValidValue("Set-Cookie:", "val\nue"); 697 checkValidValue("Set-Cookie:", "value=value"); 698 checkValidValue("Set-Cookie2:", "val\nue"); 699 checkValidValue("Set-Cookie2:", "val\u2029ue"); 700 checkValidValue("Set-Cookie2:", "value=value"); 701 702 // Check comment 703 // In RFC 2965 '=' is mandatory, but this is not the case in RI. 704 list = HttpCookie.parse("Set-Cookie:name=tes,t;Comment;"); 705 cookie = list.get(0); 706 assertNull(cookie.getComment()); 707 708 list = HttpCookie 709 .parse("Set-Cookie:name=tes,t;Comment=sentence;Comment=anotherSentence"); 710 cookie = list.get(0); 711 assertEquals("sentence", cookie.getComment()); 712 713 // Check CommentURL 714 list = HttpCookie 715 .parse("Set-Cookie:name=tes,t;Commenturl;commentuRL=(la,la)"); 716 cookie = list.get(0); 717 assertEquals("(la,la)", cookie.getCommentURL()); 718 719 // Check Domain 720 list = HttpCookie.parse("Set-Cookie:name=test;Domain=a_domain"); 721 cookie = list.get(0); 722 assertEquals("a_domain", cookie.getDomain()); 723 724 // Check Path 725 list = HttpCookie.parse("Set-Cookie:name=test;PaTh=pa$th"); 726 cookie = list.get(0); 727 assertEquals("pa$th", cookie.getPath()); 728 729 // Check Max-Age 730 list = HttpCookie.parse("Set-Cookie:name=test;Max-Age=1000"); 731 cookie = list.get(0); 732 assertEquals(1000, cookie.getMaxAge()); 733 734 list = HttpCookie.parse("Set-Cookie:name=test;Max-Age=-1000"); 735 cookie = list.get(0); 736 assertEquals(-1000, cookie.getMaxAge()); 737 738 // TODO: Uncomment when Long.parseLong() accepts numbers with a leading + 739 // list = HttpCookie.parse("Set-Cookie:name=test;max-age=+12345;"); 740 // cookie = list.get(0); 741 // assertEquals(12345, cookie.getMaxAge()); 742 743 list = HttpCookie.parse("Set-Cookie:name=test;max-age=0;"); 744 cookie = list.get(0); 745 assertEquals(0, cookie.getMaxAge()); 746 747 // Check portlist 748 list = HttpCookie.parse("Set-Cookie:name=tes,t;port"); 749 cookie = list.get(0); 750 assertEquals("", cookie.getPortlist()); 751 752 list = HttpCookie.parse("Set-Cookie:name=tes,t;port="); 753 cookie = list.get(0); 754 assertEquals("", cookie.getPortlist()); 755 756 list = HttpCookie.parse("Set-Cookie:name=tes,t;port=123 345"); 757 cookie = list.get(0); 758 assertEquals("123 345", cookie.getPortlist()); 759 760 list = HttpCookie.parse("Set-Cookie:name=tes,t;port=123,345"); 761 cookie = list.get(0); 762 assertEquals("123,345", cookie.getPortlist()); 763 764 // Check Secure 765 list = HttpCookie.parse("Set-Cookie:name=test;secure"); 766 cookie = list.get(0); 767 assertTrue(cookie.getSecure()); 768 769 list = HttpCookie.parse("Set-Cookie:name=test;secure=fa"); 770 cookie = list.get(0); 771 assertTrue(cookie.getSecure()); 772 assertFalse(cookie.hasExpired()); 773 774 list = HttpCookie.parse("Set-Cookie2:name=test;secure=false"); 775 cookie = list.get(0); 776 assertTrue(cookie.getSecure()); 777 778 // Check expire 779 list = HttpCookie.parse("Set-Cookie:name=test;expires=2006-10-23"); 780 cookie = list.get(0); 781 assertEquals(0, cookie.getMaxAge()); 782 assertTrue(cookie.hasExpired()); 783 784 // Also recognize invalid date 785 list = HttpCookie 786 .parse("Set-Cookie:name=test;expires=Sun, 29-Feb-1999 19:14:07 GMT"); 787 cookie = list.get(0); 788 assertTrue(cookie.getMaxAge() < 0); 789 assertTrue(cookie.hasExpired()); 790 791 // Parse multiple cookies 792 list = HttpCookie 793 .parse("Set-Cookie2:name=test;,Set-Cookie2:name2=test2;comment=c234;"); 794 cookie = list.get(0); 795 assertEquals("name", cookie.getName()); 796 assertEquals(1, cookie.getVersion()); 797 assertEquals("test", cookie.getValue()); 798 cookie = list.get(1); 799 assertEquals(1, cookie.getVersion()); 800 // From the second cookie, the "set-cookie2" header does not take effect 801 assertEquals("Set-Cookie2:name2", cookie.getName()); 802 assertEquals("c234", cookie.getComment()); 803 804 list = HttpCookie.parse("Set-Cookie2:name=test,name2=test2"); 805 assertEquals(1, list.get(0).getVersion()); 806 assertEquals(1, list.get(1).getVersion()); 807 808 // Must begin with "set-cookie2" header 809 list = HttpCookie.parse("name=test,Set-Cookie2:name2=test2"); 810 cookie = list.get(0); 811 assertEquals(1, list.size()); 812 813 HttpCookie c = HttpCookie.parse( 814 "Set-cookie:NAME2=VALUE2;path=/t;domain=.b.c;version=1").get(0); 815 assertEquals(1, c.getVersion()); 816 817 c = HttpCookie.parse( 818 "Set-cookie2:NAME2=VALUE2;path=/t;domain=.b.c;version=0") 819 .get(0); 820 assertEquals(1, c.getVersion()); 821 822 list = HttpCookie.parse("Set-cookie:null=;Domain=null;Port=null"); 823 cookie = list.get(0); 824 825 assertNotNull(cookie.getValue()); 826 assertNotNull(cookie.getName()); 827 assertNotNull(cookie.getDomain()); 828 assertNotNull(cookie.getPortlist()); 829 830 try { 831 list = HttpCookie 832 .parse("Set-Cookie:a name=tes,t;Commenturl;commentuRL=(la,la);path=hello"); 833 fail("IllegalArgumentException expected"); 834 } catch (IllegalArgumentException expected) { 835 } 836 837 838 list = HttpCookie 839 .parse("Set-Cookie:name=tes,t;Commenturl;commentuRL=(la,la);commentuRL=hello"); 840 cookie = list.get(0); 841 assertEquals("(la,la)", cookie.getCommentURL()); 842 843 list = HttpCookie 844 .parse("Set-Cookie:name=tes,t;Commenturl;commentuRL=(la,la); path =hello"); 845 cookie = list.get(0); 846 assertEquals("(la,la)", cookie.getCommentURL()); 847 assertEquals("hello", cookie.getPath()); 848 849 try { 850 list = HttpCookie 851 .parse("a Set-Cookie:name=tes,t;Commenturl;commentuRL=(la,la);path=hello"); 852 fail("IllegalArgumentException expected"); 853 } catch (IllegalArgumentException expected) { 854 } 855 } 856 857 public void test_Parse_httpOnly() { 858 // Default is !httpOnly. 859 List<HttpCookie> list = HttpCookie.parse("Set-Cookie: SID=31d4d96e407aad42"); 860 HttpCookie cookie = list.get(0); 861 862 // Well formed, simple. 863 list = HttpCookie.parse("Set-Cookie: SID=31d4d96e407aad42; HttpOnly"); 864 cookie = list.get(0); 865 866 // Well formed, other attributes present. 867 list = HttpCookie.parse("Set-Cookie: SID=31d4d96e407aad42; Path=/; Secure; HttpOnly"); 868 cookie = list.get(0); 869 assertTrue(cookie.getSecure()); 870 assertEquals("/", cookie.getPath()); 871 872 // Mangled spacing, casing and attributes that have an (ignored) value. 873 list = HttpCookie.parse("Set-Cookie:SID=31d4d96e407aad42;Path=/;secure=false;httponly=false"); 874 cookie = list.get(0); 875 assertTrue(cookie.getSecure()); 876 assertEquals("/", cookie.getPath()); 877 } 878 879 /** 880 * java.net.HttpCookie#parse(String) for version conflict cases 881 * @since 1.6 882 */ 883 public void test_Parse_versionConflict() { 884 // If attribute expires presents, cookie will be recognized as version 885 // 0. No matter header is Set-cookie or Set-cookie2 886 List<HttpCookie> list = HttpCookie 887 .parse("Set-Cookie2:name=;expires=;discard"); 888 HttpCookie cookie = list.get(0); 889 assertEquals(0, cookie.getVersion()); 890 assertTrue(cookie.getDiscard()); 891 892 list = HttpCookie.parse("Set-Cookie: name=value;port=80"); 893 cookie = list.get(0); 894 assertEquals(0, cookie.getVersion()); 895 assertEquals("80", cookie.getPortlist()); 896 897 // In Set-Cookie header, max-age does not take effect when expires 898 // exists. 899 list = HttpCookie 900 .parse("Set-Cookie:name=test;expires=Tue, 27-Jan-1998 19:14:07 GMT;Max-Age=1000"); 901 cookie = list.get(0); 902 assertTrue(cookie.getMaxAge() < 0); 903 assertTrue(cookie.hasExpired()); 904 assertFalse(cookie.getDiscard()); 905 // Reverse sequence. max-age takes effect and decides the result of 906 // hasExpired() method. 907 list = HttpCookie 908 .parse("Set-Cookie:name=value;max-age=1000;expires=Tue, 17-Jan-1998 19:14:07 GMT;version=1"); 909 cookie = list.get(0); 910 assertEquals(0, cookie.getVersion()); 911 assertEquals(1000, cookie.getMaxAge()); 912 assertFalse(cookie.hasExpired()); 913 914 // expires decides the version. Not take Set-cookie header, version into 915 // consideration if expires exists. 916 list = HttpCookie 917 .parse("Set-Cookie2:name=value;max-age=1000;version=1;expires=Tue, 17-Jan-1998 19:07:14 GMT;"); 918 cookie = list.get(0); 919 assertEquals(0, cookie.getVersion()); 920 assertEquals(1000, cookie.getMaxAge()); 921 assertFalse(cookie.hasExpired()); 922 923 // expires does not cover other version 1 attributes. 924 list = HttpCookie 925 .parse("Set-Cookie2: name=value;expires=Sun, 27-Jan-2018 19:14:07 GMT;comment=mycomment;port=80,8080"); 926 cookie = list.get(0); 927 assertEquals(0, cookie.getVersion()); 928 assertEquals("80,8080", cookie.getPortlist()); 929 assertEquals("mycomment", cookie.getComment()); 930 931 // When expires does not exist, version takes effect. 932 list = HttpCookie.parse("Set-Cookie:name=test;Version=1"); 933 cookie = list.get(0); 934 assertEquals(1, cookie.getVersion()); 935 assertEquals(-1, cookie.getMaxAge()); 936 list = HttpCookie.parse("Set-Cookie:name=test;vERsion=0;Version=1;versioN=0;vErsIon=1"); 937 cookie = list.get(0); 938 assertEquals(1, cookie.getVersion()); 939 940 // When expires does not exist, max-age takes effect. 941 list = HttpCookie.parse("Set-Cookie:name=test;Max-Age=11"); 942 cookie = list.get(0); 943 assertEquals(1, cookie.getVersion()); 944 assertEquals(11, cookie.getMaxAge()); 945 // other version 1 attributes does not take effect 946 list = HttpCookie 947 .parse("Set-Cookie:name=test;comment=mycomment;commentURL=url;discard;domain=a.b.com;path=temp;port=79;secure"); 948 cookie = list.get(0); 949 assertEquals(0, cookie.getVersion()); 950 } 951 952 // http://b/31039416. Android N+ checks current time in hasExpired. 953 // Repeated invocations of cookie.hasExpired() may return different results 954 // due to time passage. 955 // This was not the case in earlier android versions, where hasExpired 956 // was testing the value of max-age/expires at the time of cookie creation. 957 public void test_hasExpired_checksTime() throws Exception { 958 List<HttpCookie> list = HttpCookie.parse("Set-Cookie:name=test;Max-Age=1"); 959 HttpCookie cookie = list.get(0); 960 assertFalse(cookie.hasExpired()); 961 Thread.sleep(2000); 962 assertTrue(cookie.hasExpired()); 963 } 964 965 /** 966 * java.net.HttpCookie#parse(String) on multiple threads 967 * Regression test for HARMONY-6307 968 * @since 1.6 969 */ 970 class ParseThread extends Thread { 971 public AssertionError error = null; 972 973 public void run() { 974 try { 975 for (int i = 0; i < 200; i++) { 976 List<HttpCookie> list = HttpCookie.parse("Set-cookie:PREF=test;path=/;domain=.b.c;"); 977 assertEquals(1, list.size()); 978 HttpCookie cookie = list.get(0); 979 assertEquals(0, cookie.getVersion()); 980 assertEquals(".b.c", cookie.getDomain()); 981 } 982 } catch (AssertionError e) { 983 error = e; 984 } 985 } 986 } 987 988 public void test_Parse_multipleThreads() throws InterruptedException { 989 ParseThread[] threads = new ParseThread[10]; 990 // create threads 991 for (int i = 0; i < threads.length; i++) { 992 threads[i] = new ParseThread(); 993 } 994 995 // start threads 996 for (ParseThread thread : threads) { 997 thread.start(); 998 } 999 1000 // wait for threads to finish 1001 for (ParseThread thread : threads) { 1002 thread.join(); 1003 } 1004 1005 for (ParseThread thread : threads) { 1006 if (thread.error != null) { 1007 fail("Assertion thrown in thread " + thread + ": " + thread.error); 1008 } 1009 } 1010 } 1011 1012 private void checkValidValue(String header, String value) { 1013 List<HttpCookie> list = HttpCookie 1014 .parse(header + "name=" + value + ";"); 1015 HttpCookie cookie = list.get(0); 1016 assertEquals(value, cookie.getValue()); 1017 } 1018 1019 private void checkInvalidCookie(String header) { 1020 try { 1021 HttpCookie.parse(header); 1022 fail("Should throw IllegalArgumentException"); 1023 } catch (IllegalArgumentException e) { 1024 // expected 1025 } 1026 } 1027 1028 @Override 1029 protected void setUp() throws Exception { 1030 super.setUp(); 1031 // version 0 cookie only takes effect on Locale.ENGLISH 1032 locale = Locale.getDefault(); 1033 Locale.setDefault(Locale.ENGLISH); 1034 } 1035 1036 @Override 1037 protected void tearDown() throws Exception { 1038 Locale.setDefault(locale); 1039 super.tearDown(); 1040 } 1041 1042 } 1043