001: /*
002: * $Header: $
003: * $Revision: 480424 $
004: * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
005: * ====================================================================
006: *
007: * Licensed to the Apache Software Foundation (ASF) under one or more
008: * contributor license agreements. See the NOTICE file distributed with
009: * this work for additional information regarding copyright ownership.
010: * The ASF licenses this file to You under the Apache License, Version 2.0
011: * (the "License"); you may not use this file except in compliance with
012: * the License. You may obtain a copy of the License at
013: *
014: * http://www.apache.org/licenses/LICENSE-2.0
015: *
016: * Unless required by applicable law or agreed to in writing, software
017: * distributed under the License is distributed on an "AS IS" BASIS,
018: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
019: * See the License for the specific language governing permissions and
020: * limitations under the License.
021: * ====================================================================
022: *
023: * This software consists of voluntary contributions made by many
024: * individuals on behalf of the Apache Software Foundation. For more
025: * information on the Apache Software Foundation, please see
026: * <http://www.apache.org/>.
027: *
028: */
029:
030: package org.apache.commons.httpclient.cookie;
031:
032: import junit.framework.Test;
033: import junit.framework.TestSuite;
034:
035: import org.apache.commons.httpclient.Cookie;
036: import org.apache.commons.httpclient.Header;
037:
038: import java.util.Date;
039:
040: /**
041: * Test cases for RFC2965 cookie spec
042: *
043: * @author jain.samit@gmail.com (Samit Jain)
044: */
045: public class TestCookieRFC2965Spec extends TestCookieBase {
046:
047: // ------------------------------------------------------------ Constructor
048:
049: public TestCookieRFC2965Spec(String name) {
050: super (name);
051: }
052:
053: // ------------------------------------------------------- TestCase Methods
054:
055: public static Test suite() {
056: return new TestSuite(TestCookieRFC2965Spec.class);
057: }
058:
059: // ------------------------------------------------------- Test Cookie Parsing
060:
061: /**
062: * Test <tt>parse</tt> with invalid params.
063: */
064: public void testParseInvalidParams() throws Exception {
065: CookieSpec cookiespec = new RFC2965Spec();
066: try {
067: // invalid header
068: cookiespec.parse("www.domain.com", 80, "/", false,
069: (Header) null /* header */);
070: fail("IllegalArgumentException must have been thrown");
071: } catch (IllegalArgumentException expected) {
072: }
073:
074: Header header = new Header("Set-Cookie2",
075: "name=value;Version=1");
076: try {
077: // invalid request host
078: cookiespec.parse(null /* host */, 80, "/", false, header);
079: fail("IllegalArgumentException must have been thrown");
080: } catch (IllegalArgumentException expected) {
081: }
082: try {
083: // invalid request port
084: cookiespec.parse("www.domain.com", -32 /* port */, "/",
085: false, header);
086: fail("IllegalArgumentException must have been thrown");
087: } catch (IllegalArgumentException expected) {
088: }
089: try {
090: // invalid request path
091: cookiespec.parse("www.domain.com", 80, null /* path */,
092: false, header);
093: fail("IllegalArgumentException must have been thrown");
094: } catch (IllegalArgumentException expected) {
095: }
096: }
097:
098: /**
099: * Test parsing cookie <tt>"Path"</tt> attribute.
100: */
101: public void testParsePath() throws Exception {
102: CookieSpec cookiespec = new RFC2965Spec();
103: Header header = new Header("Set-Cookie2",
104: "name=value;Path=/;Version=1;Path=");
105: Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/",
106: false, header);
107: assertNotNull(parsed);
108: assertEquals(1, parsed.length);
109: // only the first occurence of path attribute is considered, others ignored
110: Cookie2 cookie = (Cookie2) parsed[0];
111: assertEquals("/", cookie.getPath());
112: assertTrue(cookie.isPathAttributeSpecified());
113: }
114:
115: public void testParsePathDefault() throws Exception {
116: CookieSpec cookiespec = new RFC2965Spec();
117: // Path is OPTIONAL, defaults to the request path
118: Header header = new Header("Set-Cookie2",
119: "name=value;Version=1");
120: Cookie[] parsed = cookiespec.parse("www.domain.com", 80,
121: "/path" /* request path */, false, header);
122: assertNotNull(parsed);
123: assertEquals(1, parsed.length);
124: Cookie2 cookie = (Cookie2) parsed[0];
125: assertEquals("/path", cookie.getPath());
126: assertFalse(cookie.isPathAttributeSpecified());
127: }
128:
129: public void testParseNullPath() throws Exception {
130: CookieSpec cookiespec = new RFC2965Spec();
131: Header header = new Header("Set-Cookie2",
132: "name=value;Path=;Version=1");
133: try {
134: cookiespec.parse("www.domain.com", 80, "/", false, header);
135: fail("MalformedCookieException should have been thrown");
136: } catch (MalformedCookieException ex) {
137: // expected
138: }
139: }
140:
141: public void testParseBlankPath() throws Exception {
142: CookieSpec cookiespec = new RFC2965Spec();
143: Header header = new Header("Set-Cookie2",
144: "name=value;Path=\" \";Version=1");
145: try {
146: cookiespec.parse("www.domain.com", 80, "/", false, header);
147: fail("MalformedCookieException should have been thrown");
148: } catch (MalformedCookieException ex) {
149: // expected
150: }
151: }
152:
153: /**
154: * Test parsing cookie <tt>"Domain"</tt> attribute.
155: */
156: public void testParseDomain() throws Exception {
157: CookieSpec cookiespec = new RFC2965Spec();
158: Header header = new Header("Set-Cookie2",
159: "name=value;Domain=.domain.com;Version=1;Domain=");
160: Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/",
161: false, header);
162: assertNotNull(parsed);
163: assertEquals(1, parsed.length);
164: // only the first occurence of domain attribute is considered, others ignored
165: Cookie2 cookie = (Cookie2) parsed[0];
166: assertEquals(".domain.com", cookie.getDomain());
167: assertTrue(cookie.isDomainAttributeSpecified());
168:
169: // should put a leading dot if there is no dot in front of domain
170: header = new Header("Set-Cookie2",
171: "name=value;Domain=domain.com;Version=1");
172: parsed = cookiespec.parse("www.domain.com", 80, "/", false,
173: header);
174: assertNotNull(parsed);
175: assertEquals(1, parsed.length);
176: cookie = (Cookie2) parsed[0];
177: assertEquals(".domain.com", cookie.getDomain());
178: }
179:
180: public void testParseDomainDefault() throws Exception {
181: CookieSpec cookiespec = new RFC2965Spec();
182: // Domain is OPTIONAL, defaults to the request host
183: Header header = new Header("Set-Cookie2",
184: "name=value;Version=1");
185: Cookie[] parsed = cookiespec.parse(
186: "www.domain.com" /* request host */, 80, "/", false,
187: header);
188: assertNotNull(parsed);
189: assertEquals(1, parsed.length);
190: Cookie2 cookie = (Cookie2) parsed[0];
191: assertEquals("www.domain.com", cookie.getDomain());
192: assertFalse(cookie.isDomainAttributeSpecified());
193: }
194:
195: public void testParseNullDomain() throws Exception {
196: CookieSpec cookiespec = new RFC2965Spec();
197: // domain cannot be null
198: Header header = new Header("Set-Cookie2",
199: "name=value;Domain=;Version=1");
200: try {
201: cookiespec.parse("www.domain.com", 80, "/", false, header);
202: fail("MalformedCookieException should have been thrown");
203: } catch (MalformedCookieException ex) {
204: // expected
205: }
206: }
207:
208: public void testParseBlankDomain() throws Exception {
209: CookieSpec cookiespec = new RFC2965Spec();
210: Header header = new Header("Set-Cookie2",
211: "name=value;Domain=\" \";Version=1");
212: try {
213: cookiespec.parse("www.domain.com", 80, "/", false, header);
214: fail("MalformedCookieException should have been thrown");
215: } catch (MalformedCookieException ex) {
216: // expected
217: }
218: }
219:
220: /**
221: * Test parsing cookie <tt>"Port"</tt> attribute.
222: */
223: public void testParsePort() throws Exception {
224: CookieSpec cookiespec = new RFC2965Spec();
225: Header header = new Header("Set-Cookie2",
226: "name=value;Port=\"80,800,8000\";Version=1;Port=nonsense");
227: Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/",
228: false, header);
229: assertNotNull(parsed);
230: assertEquals(1, parsed.length);
231: // only the first occurence of port attribute is considered, others ignored
232: Cookie2 cookie = (Cookie2) parsed[0];
233: int[] ports = cookie.getPorts();
234: assertNotNull(ports);
235: assertEquals(3, ports.length);
236: assertEquals(80, ports[0]);
237: assertEquals(800, ports[1]);
238: assertEquals(8000, ports[2]);
239: assertTrue(cookie.isPortAttributeSpecified());
240: }
241:
242: public void testParsePortDefault() throws Exception {
243: CookieSpec cookiespec = new RFC2965Spec();
244: // Port is OPTIONAL, cookie can be accepted from any port
245: Header header = new Header("Set-Cookie2",
246: "name=value;Version=1");
247: Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/",
248: false, header);
249: assertNotNull(parsed);
250: assertEquals(1, parsed.length);
251: Cookie2 cookie = (Cookie2) parsed[0];
252: assertFalse(cookie.isPortAttributeSpecified());
253: }
254:
255: public void testParseNullPort() throws Exception {
256: CookieSpec cookiespec = new RFC2965Spec();
257: // null port defaults to request port
258: Header header = new Header("Set-Cookie2",
259: "name=value;Port=;Version=1");
260: Cookie[] parsed = cookiespec.parse("www.domain.com",
261: 80 /* request port */, "/", false, header);
262: assertNotNull(parsed);
263: assertEquals(1, parsed.length);
264: Cookie2 cookie = (Cookie2) parsed[0];
265: int[] ports = cookie.getPorts();
266: assertNotNull(ports);
267: assertEquals(1, ports.length);
268: assertEquals(80, ports[0]);
269: assertTrue(cookie.isPortAttributeSpecified()
270: && cookie.isPortAttributeBlank());
271: }
272:
273: public void testParseBlankPort() throws Exception {
274: CookieSpec cookiespec = new RFC2965Spec();
275: // blank port defaults to request port
276: Header header = new Header("Set-Cookie2",
277: "name=value;Port=\" \";Version=1");
278: Cookie[] parsed = cookiespec.parse("www.domain.com",
279: 80 /* request port */, "/", false, header);
280: assertNotNull(parsed);
281: assertEquals(1, parsed.length);
282: Cookie2 cookie = (Cookie2) parsed[0];
283: int[] ports = cookie.getPorts();
284: assertNotNull(ports);
285: assertEquals(1, ports.length);
286: assertEquals(80, ports[0]);
287: assertTrue(cookie.isPortAttributeSpecified()
288: && cookie.isPortAttributeBlank());
289: }
290:
291: public void testParseInvalidPort() throws Exception {
292: CookieSpec cookiespec = new RFC2965Spec();
293: Header header = new Header("Set-Cookie2",
294: "name=value;Port=nonsense;Version=1");
295: try {
296: cookiespec.parse("www.domain.com", 80, "/", false, header);
297: fail("MalformedCookieException should have been thrown");
298: } catch (MalformedCookieException ex) {
299: // expected
300: }
301: }
302:
303: public void testParseNegativePort() throws Exception {
304: CookieSpec cookiespec = new RFC2965Spec();
305: Header header = new Header("Set-Cookie2",
306: "name=value;Port=\"80,-800,8000\";Version=1");
307: try {
308: cookiespec.parse("www.domain.com", 80, "/", false, header);
309: fail("MalformedCookieException should have been thrown");
310: } catch (MalformedCookieException ex) {
311: // expected
312: }
313: }
314:
315: /**
316: * test parsing cookie name/value.
317: */
318: public void testParseNameValue() throws Exception {
319: CookieSpec cookiespec = new RFC2965Spec();
320: Header header = new Header("Set-Cookie2",
321: "name=value;Version=1;");
322: Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/",
323: false, header);
324: assertNotNull(parsed);
325: assertEquals(1, parsed.length);
326: Cookie2 cookie = (Cookie2) parsed[0];
327: assertEquals("name", cookie.getName());
328: assertEquals("value", cookie.getValue());
329: }
330:
331: /**
332: * test parsing cookie <tt>"Version"</tt> attribute.
333: */
334: public void testParseVersion() throws Exception {
335: CookieSpec cookiespec = new RFC2965Spec();
336: Header header = new Header("Set-Cookie2",
337: "name=value;Version=1;");
338: Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/",
339: false, header);
340: assertNotNull(parsed);
341: assertEquals(1, parsed.length);
342: Cookie2 cookie = (Cookie2) parsed[0];
343: assertEquals(1, cookie.getVersion());
344: assertTrue(cookie.isVersionAttributeSpecified());
345: }
346:
347: public void testParseNullVersion() throws Exception {
348: CookieSpec cookiespec = new RFC2965Spec();
349: // version cannot ne null
350: Header header = new Header("Set-Cookie2",
351: "name=value;Version=;");
352: try {
353: cookiespec.parse("www.domain.com", 80, "/", false, header);
354: fail("MalformedCookieException should have been thrown");
355: } catch (MalformedCookieException ex) {
356: // expected
357: }
358: }
359:
360: public void testParseNegativeVersion() throws Exception {
361: CookieSpec cookiespec = new RFC2965Spec();
362: Header header = new Header("Set-Cookie2",
363: "name=value;Version=-1;");
364: try {
365: cookiespec.parse("www.domain.com", 80, "/", false, header);
366: fail("MalformedCookieException should have been thrown");
367: } catch (MalformedCookieException ex) {
368: // expected
369: }
370: }
371:
372: /**
373: * test parsing cookie <tt>"Max-age"</tt> attribute.
374: */
375: public void testParseMaxage() throws Exception {
376: CookieSpec cookiespec = new RFC2965Spec();
377: Header header = new Header("Set-Cookie2",
378: "name=value;Max-age=3600;Version=1;Max-age=nonsense");
379: Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/",
380: false, header);
381: assertNotNull(parsed);
382: assertEquals(1, parsed.length);
383: // only the first occurence of max-age attribute is considered, others ignored
384: Cookie2 cookie = (Cookie2) parsed[0];
385: assertFalse(cookie.isExpired());
386: }
387:
388: public void testParseMaxageDefault() throws Exception {
389: CookieSpec cookiespec = new RFC2965Spec();
390: // Max-age is OPTIONAL, defaults to session cookie
391: Header header = new Header("Set-Cookie2",
392: "name=value;Version=1");
393: Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/",
394: false, header);
395: assertNotNull(parsed);
396: assertEquals(1, parsed.length);
397: Cookie2 cookie = (Cookie2) parsed[0];
398: assertFalse(cookie.isPersistent());
399: }
400:
401: public void testParseNullMaxage() throws Exception {
402: CookieSpec cookiespec = new RFC2965Spec();
403: Header header = new Header("Set-Cookie2",
404: "name=value;Max-age=;Version=1");
405: try {
406: cookiespec.parse("www.domain.com", 80, "/", false, header);
407: fail("MalformedCookieException should have been thrown");
408: } catch (MalformedCookieException ex) {
409: // expected
410: }
411: }
412:
413: public void testParseNegativeMaxage() throws Exception {
414: CookieSpec cookiespec = new RFC2965Spec();
415: Header header = new Header("Set-Cookie2",
416: "name=value;Max-age=-3600;Version=1;");
417: try {
418: cookiespec.parse("www.domain.com", 80, "/", false, header);
419: fail("MalformedCookieException should have been thrown");
420: } catch (MalformedCookieException ex) {
421: // expected
422: }
423: }
424:
425: /**
426: * test parsing <tt>"Secure"</tt> attribute.
427: */
428: public void testParseSecure() throws Exception {
429: CookieSpec cookiespec = new RFC2965Spec();
430: Header header = new Header("Set-Cookie2",
431: "name=value;Secure;Version=1");
432: Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/",
433: false, header);
434: assertNotNull(parsed);
435: assertEquals(1, parsed.length);
436: Cookie2 cookie = (Cookie2) parsed[0];
437: assertTrue(cookie.getSecure());
438: }
439:
440: /**
441: * test parsing <tt>"Discard"</tt> attribute.
442: */
443: public void testParseDiscard() throws Exception {
444: CookieSpec cookiespec = new RFC2965Spec();
445: Header header = new Header("Set-Cookie2",
446: "name=value;Discard;Max-age=36000;Version=1");
447: Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/",
448: false, header);
449: assertNotNull(parsed);
450: assertEquals(1, parsed.length);
451: Cookie2 cookie = (Cookie2) parsed[0];
452: // discard overrides max-age
453: assertFalse(cookie.isPersistent());
454:
455: // Discard is OPTIONAL, default behavior is dictated by max-age
456: header = new Header("Set-Cookie2",
457: "name=value;Max-age=36000;Version=1");
458: parsed = cookiespec.parse("www.domain.com", 80, "/", false,
459: header);
460: assertNotNull(parsed);
461: assertEquals(1, parsed.length);
462: cookie = (Cookie2) parsed[0];
463: assertTrue(cookie.isPersistent());
464: }
465:
466: /**
467: * test parsing <tt>"Comment"</tt>, <tt>"CommentURL"</tt> and
468: * <tt>"Secure"</tt> attributes.
469: */
470: public void testParseOtherAttributes() throws Exception {
471: CookieSpec cookiespec = new RFC2965Spec();
472: Header header = new Header(
473: "Set-Cookie2",
474: "name=value;Comment=\"good cookie\";"
475: + "CommentURL=\"www.domain.com/goodcookie/\";Secure;Version=1");
476: Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/",
477: false, header);
478: assertNotNull(parsed);
479: assertEquals(1, parsed.length);
480: Cookie2 cookie = (Cookie2) parsed[0];
481: assertEquals("good cookie", cookie.getComment());
482: assertEquals("www.domain.com/goodcookie/", cookie
483: .getCommentURL());
484: assertTrue(cookie.getSecure());
485:
486: // Comment, CommentURL, Secure are OPTIONAL
487: header = new Header("Set-Cookie2", "name=value;Version=1");
488: parsed = cookiespec.parse("www.domain.com", 80, "/", false,
489: header);
490: assertNotNull(parsed);
491: assertEquals(1, parsed.length);
492: cookie = (Cookie2) parsed[0];
493: assertFalse(cookie.getSecure());
494: }
495:
496: /**
497: * Test parsing header with 2 cookies (separated by comma)
498: */
499: public void testCookiesWithComma() throws Exception {
500: CookieSpec cookiespec = new RFC2965Spec();
501: Header header = new Header("Set-Cookie2", "a=b,c");
502: Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/",
503: false, header);
504: assertNotNull(parsed);
505: assertEquals(2, parsed.length);
506: assertEquals("a", parsed[0].getName());
507: assertEquals("b", parsed[0].getValue());
508: assertEquals("c", parsed[1].getName());
509: assertEquals(null, parsed[1].getValue());
510: }
511:
512: // ------------------------------------------------------- Test Cookie Validation
513:
514: /**
515: * Test <tt>Domain</tt> validation when domain is not specified
516: * in <tt>Set-Cookie2</tt> header.
517: */
518: public void testValidateNoDomain() throws Exception {
519: CookieSpec cookiespec = new RFC2965Spec();
520: Header header = new Header("Set-Cookie2",
521: "name=value;Version=1");
522: Cookie[] parsed = cookieParse(cookiespec,
523: "www.domain.com" /* request host */, 80, "/", false,
524: header);
525: assertNotNull(parsed);
526: assertEquals(1, parsed.length);
527: Cookie2 cookie = (Cookie2) parsed[0];
528: // cookie domain must string match request host
529: assertEquals("www.domain.com", cookie.getDomain());
530: }
531:
532: /**
533: * Test <tt>Domain</tt> validation. Cookie domain attribute must have a
534: * leading dot.
535: */
536: public void testValidateDomainLeadingDot() throws Exception {
537: CookieSpec cookiespec = new RFC2965Spec();
538: Header header = new Header("Set-Cookie2",
539: "name=value;Domain=domain.com;Version=1");
540: Cookie[] parsed = cookieParse(cookiespec, "www.domain.com", 80,
541: "/", false, header);
542: assertNotNull(parsed);
543: assertEquals(1, parsed.length);
544: Cookie2 cookie = (Cookie2) parsed[0];
545: assertEquals(".domain.com", cookie.getDomain());
546: }
547:
548: /**
549: * Test <tt>Domain</tt> validation. Domain must have atleast one embedded dot.
550: */
551: public void testValidateDomainEmbeddedDot() throws Exception {
552: CookieSpec cookiespec = new RFC2965Spec();
553: Header header = new Header("Set-Cookie2",
554: "name=value; domain=.com; version=1");
555: try {
556: cookieParse(cookiespec, "b.com", 80, "/", false, header);
557: fail("MalformedCookieException should have been thrown");
558: } catch (MalformedCookieException expected) {
559: }
560:
561: header = new Header("Set-Cookie2",
562: "name=value;Domain=domain.com;Version=1");
563: Cookie[] parsed = cookieParse(cookiespec, "www.domain.com", 80,
564: "/", false, header);
565: assertNotNull(parsed);
566: assertEquals(1, parsed.length);
567: }
568:
569: /**
570: * Test local <tt>Domain</tt> validation. Simple host names
571: * (without any dots) are valid only when cookie domain is specified
572: * as ".local".
573: */
574: public void testValidateDomainLocal() throws Exception {
575: CookieSpec cookiespec = new RFC2965Spec();
576: // when domain is specified as .local, simple host names are valid
577: Header header = new Header("Set-Cookie2",
578: "name=value; domain=.local; version=1");
579: Cookie[] parsed = cookieParse(cookiespec,
580: "simplehost" /* request host */, 80, "/", false,
581: header);
582: assertNotNull(parsed);
583: assertEquals(1, parsed.length);
584: Cookie2 cookie = (Cookie2) parsed[0];
585: assertEquals(".local", cookie.getDomain());
586:
587: // when domain is NOT specified as .local, simple host names are invalid
588: header = new Header("Set-Cookie2",
589: "name=value; domain=domain.com; version=1");
590: try {
591: // since domain is not .local, this must fail
592: parsed = cookieParse(cookiespec,
593: "simplehost" /* request host */, 80, "/", false,
594: header);
595: fail("MalformedCookieException should have been thrown");
596: } catch (MalformedCookieException expected) {
597: }
598: }
599:
600: /**
601: * Test <tt>Domain</tt> validation. Effective host name
602: * must domain-match domain attribute.
603: */
604: public void testValidateDomainEffectiveHost() throws Exception {
605: CookieSpec cookiespec = new RFC2965Spec();
606:
607: // cookie domain does not domain-match request host
608: Header header = new Header("Set-Cookie2",
609: "name=value; domain=.domain.com; version=1");
610: try {
611: cookieParse(cookiespec,
612: "www.domain.org" /* request host */, 80, "/",
613: false, header);
614: fail("MalformedCookieException should have been thrown");
615: } catch (MalformedCookieException expected) {
616: }
617:
618: // cookie domain domain-matches request host
619: header = new Header("Set-Cookie2",
620: "name=value; domain=.domain.com; version=1");
621: Cookie[] parsed = cookieParse(cookiespec,
622: "www.domain.com" /* request host */, 80, "/", false,
623: header);
624: assertNotNull(parsed);
625: assertEquals(1, parsed.length);
626: }
627:
628: /**
629: * Test local <tt>Domain</tt> validation.
630: * Effective host name minus domain must not contain any dots.
631: */
632: public void testValidateDomainIllegal() throws Exception {
633: CookieSpec cookiespec = new RFC2965Spec();
634: Header header = new Header("Set-Cookie2",
635: "name=value; domain=.domain.com; version=1");
636: try {
637: cookieParse(cookiespec,
638: "a.b.domain.com" /* request host */, 80, "/",
639: false, header);
640: fail("MalformedCookieException should have been thrown");
641: } catch (MalformedCookieException expected) {
642: }
643: }
644:
645: /**
646: * Test cookie <tt>Path</tt> validation. Cookie path attribute must path-match
647: * request path.
648: */
649: public void testValidatePath() throws Exception {
650: CookieSpec cookiespec = new RFC2965Spec();
651: Header header = new Header("Set-Cookie2",
652: "name=value;path=/path;version=1");
653: try {
654: cookieParse(cookiespec, "www.domain.com", 80,
655: "/" /* request path */, false, header);
656: fail("MalformedCookieException exception should have been thrown");
657: } catch (MalformedCookieException expected) {
658: }
659:
660: // path-matching is case-sensitive
661: header = new Header("Set-Cookie2",
662: "name=value;path=/Path;version=1");
663: try {
664: cookieParse(cookiespec, "www.domain.com", 80,
665: "/path" /* request path */, false, header);
666: fail("MalformedCookieException exception should have been thrown");
667: } catch (MalformedCookieException expected) {
668: }
669:
670: header = new Header("Set-Cookie2",
671: "name=value;path=/path;version=1");
672: Cookie[] parsed = cookieParse(cookiespec, "www.domain.com", 80,
673: "/path/path1" /* request path */, false, header);
674: assertNotNull(parsed);
675: assertEquals(1, parsed.length);
676: assertEquals("/path", parsed[0].getPath());
677: }
678:
679: /**
680: * Test cookie name validation.
681: */
682: public void testValidateCookieName() throws Exception {
683: CookieSpec cookiespec = new RFC2965Spec();
684: // cookie name must not contain blanks
685: Header header = new Header("Set-Cookie2",
686: "invalid name=value; version=1");
687: try {
688: cookieParse(cookiespec, "127.0.0.1", 80, "/", false, header);
689: fail("MalformedCookieException exception should have been thrown");
690: } catch (MalformedCookieException expected) {
691: }
692:
693: // cookie name must not start with '$'.
694: header = new Header("Set-Cookie2",
695: "$invalid_name=value; version=1");
696: try {
697: cookieParse(cookiespec, "127.0.0.1", 80, "/", false, header);
698: fail("MalformedCookieException exception should have been thrown");
699: } catch (MalformedCookieException expected) {
700: }
701:
702: // valid name
703: header = new Header("Set-Cookie2", "name=value; version=1");
704: Cookie[] parsed = cookieParse(cookiespec, "www.domain.com", 80,
705: "/", false, header);
706: assertNotNull(parsed);
707: assertEquals(1, parsed.length);
708: Cookie2 cookie = (Cookie2) parsed[0];
709: assertEquals("name", cookie.getName());
710: assertEquals("value", cookie.getValue());
711: }
712:
713: /**
714: * Test cookie <tt>Port</tt> validation. Request port must be in the
715: * port attribute list.
716: */
717: public void testValidatePort() throws Exception {
718: Header header = new Header("Set-Cookie2",
719: "name=value; Port=\"80,800\"; version=1");
720: CookieSpec cookiespec = new RFC2965Spec();
721: try {
722: cookieParse(cookiespec, "www.domain.com",
723: 8000 /* request port */, "/", false, header);
724: fail("MalformedCookieException should have been thrown");
725: } catch (MalformedCookieException e) {
726: }
727:
728: // valid port list
729: Cookie[] parsed = cookieParse(cookiespec, "www.domain.com",
730: 80 /* request port */, "/", false, header);
731: assertNotNull(parsed);
732: assertEquals(1, parsed.length);
733: Cookie2 cookie = (Cookie2) parsed[0];
734: int[] ports = cookie.getPorts();
735: assertNotNull(ports);
736: assertEquals(2, ports.length);
737: assertEquals(80, ports[0]);
738: assertEquals(800, ports[1]);
739: }
740:
741: /**
742: * Test cookie <tt>Version</tt> validation.
743: */
744: public void testValidateVersion() throws Exception {
745: CookieSpec cookiespec = new RFC2965Spec();
746: // version attribute is REQUIRED
747: Header header = new Header("Set-Cookie2", "name=value");
748: try {
749: cookieParse(cookiespec, "www.domain.com", 8000, "/", false,
750: header);
751: fail("MalformedCookieException should have been thrown");
752: } catch (MalformedCookieException e) {
753: }
754: }
755:
756: // ------------------------------------------------------- Test Cookie Matching
757:
758: /**
759: * test cookie <tt>Path</tt> matching. Cookie path attribute must path-match
760: * path of the request URI.
761: */
762: public void testMatchPath() throws Exception {
763: Cookie2 cookie = new Cookie2(".domain.com", "name", "value",
764: "/path" /* path */, null, false, new int[] { 80 });
765: CookieSpec cookiespec = new RFC2965Spec();
766: assertFalse(cookiespec.match("www.domain.com", 80,
767: "/" /* request path */, false, cookie));
768: assertTrue(cookiespec.match("www.domain.com", 80,
769: "/path/path1" /* request path */, false, cookie));
770: }
771:
772: /**
773: * test cookie <tt>Domain</tt> matching.
774: */
775: public void testMatchDomain() throws Exception {
776: Cookie2 cookie = new Cookie2(".domain.com" /* domain */,
777: "name", "value", "/", null, false, new int[] { 80 });
778: CookieSpec cookiespec = new RFC2965Spec();
779: // effective host name minus domain must not contain any dots
780: assertFalse(cookiespec.match(
781: "a.b.domain.com" /* request host */, 80, "/", false,
782: cookie));
783: // The effective host name MUST domain-match the Domain
784: // attribute of the cookie.
785: assertFalse(cookiespec.match(
786: "www.domain.org" /* request host */, 80, "/", false,
787: cookie));
788: assertTrue(cookiespec.match(
789: "www.domain.com" /* request host */, 80, "/", false,
790: cookie));
791: }
792:
793: /**
794: * test cookie local <tt>Domain</tt> matching.
795: */
796: public void testMatchDomainLocal() throws Exception {
797: Cookie2 cookie = new Cookie2(".local" /* domain */, "name",
798: "value", "/", null, false, new int[] { 80 });
799: CookieSpec cookiespec = new RFC2965Spec();
800: assertTrue(cookiespec.match("host" /* request host */, 80,
801: "/", false, cookie));
802: assertFalse(cookiespec.match("host.com" /* request host */,
803: 80, "/", false, cookie));
804: }
805:
806: /**
807: * test cookie <tt>Port</tt> matching.
808: */
809: public void testMatchPort() throws Exception {
810: // cookie can be sent to any port if port attribute not specified
811: Cookie2 cookie = new Cookie2(".domain.com", "name", "value",
812: "/", null, false, null /* ports */);
813: CookieSpec cookiespec = new RFC2965Spec();
814: cookie.setPortAttributeSpecified(false);
815: assertTrue(cookiespec.match("www.domain.com",
816: 8080 /* request port */, "/", false, cookie));
817: assertTrue(cookiespec.match("www.domain.com",
818: 323 /* request port */, "/", false, cookie));
819:
820: // otherwise, request port must be in cookie's port list
821: cookie = new Cookie2(".domain.com", "name", "value", "/", null,
822: false, new int[] { 80, 8080 } /* ports */);
823: cookie.setPortAttributeSpecified(true);
824: assertFalse(cookiespec.match("www.domain.com",
825: 434 /* request port */, "/", false, cookie));
826: assertTrue(cookiespec.match("www.domain.com",
827: 8080 /* request port */, "/", false, cookie));
828: }
829:
830: /**
831: * test cookie expiration.
832: */
833: public void testCookieExpiration() throws Exception {
834: Date afterOneHour = new Date(
835: System.currentTimeMillis() + 3600 * 1000L);
836: Cookie2 cookie = new Cookie2(".domain.com", "name", "value",
837: "/", afterOneHour /* expiry */, false, null);
838: CookieSpec cookiespec = new RFC2965Spec();
839: assertTrue(cookiespec.match("www.domain.com", 80, "/", false,
840: cookie));
841:
842: Date beforeOneHour = new Date(
843: System.currentTimeMillis() - 3600 * 1000L);
844: cookie = new Cookie2(".domain.com", "name", "value", "/",
845: beforeOneHour /* expiry */, false, null);
846: assertFalse(cookiespec.match("www.domain.com", 80, "/", false,
847: cookie));
848:
849: // discard attributes overrides cookie age, makes it a session cookie.
850: cookie.setDiscard(true);
851: assertFalse(cookie.isPersistent());
852: assertTrue(cookiespec.match("www.domain.com", 80, "/", false,
853: cookie));
854: }
855:
856: /**
857: * test cookie <tt>Secure</tt> attribute.
858: */
859: public void testCookieSecure() throws Exception {
860: CookieSpec cookiespec = new RFC2965Spec();
861: // secure cookie can only be sent over a secure connection
862: Cookie2 cookie = new Cookie2(".domain.com", "name", "value",
863: "/", null, true /* secure */, null);
864: assertFalse(cookiespec.match("www.domain.com", 80, "/",
865: false /* request secure */, cookie));
866: assertTrue(cookiespec.match("www.domain.com", 80, "/",
867: true /* request secure */, cookie));
868: }
869:
870: // ------------------------------------------------------- Test Cookie Formatting
871:
872: public void testFormatInvalidCookie() throws Exception {
873: CookieSpec cookiespec = new RFC2965Spec();
874: try {
875: cookiespec.formatCookie(null);
876: fail("IllegalArgumentException nust have been thrown");
877: } catch (IllegalArgumentException expected) {
878: }
879: }
880:
881: /**
882: * Tests RFC 2965 compliant cookie formatting.
883: */
884: public void testRFC2965CookieFormatting() throws Exception {
885: CookieSpec cookiespec = new RFC2965Spec();
886: Cookie2 cookie1 = new Cookie2(".domain.com", "name1", "value",
887: "/", null, false, new int[] { 80, 8080 });
888: cookie1.setVersion(1);
889: // domain, path, port specified
890: cookie1.setDomainAttributeSpecified(true);
891: cookie1.setPathAttributeSpecified(true);
892: cookie1.setPortAttributeSpecified(true);
893: assertEquals(
894: "$Version=\"1\"; name1=\"value\"; $Domain=\".domain.com\"; $Path=\"/\"; $Port=\"80,8080\"",
895: cookiespec.formatCookie(cookie1));
896:
897: Cookie2 cookie2 = new Cookie2(".domain.com", "name2", "value",
898: "/a/", null, false, new int[] { 80, 8080 });
899: cookie2.setVersion(2);
900: // domain, path specified but port unspecified
901: cookie2.setDomainAttributeSpecified(true);
902: cookie2.setPathAttributeSpecified(true);
903: cookie2.setPortAttributeSpecified(false);
904: assertEquals(
905: "$Version=\"2\"; name2=\"value\"; $Domain=\".domain.com\"; $Path=\"/a/\"",
906: cookiespec.formatCookie(cookie2));
907:
908: Cookie2 cookie3 = new Cookie2(".domain.com", "name3", "value",
909: "/a/b/", null, false, new int[] { 80, 8080 });
910: cookie3.setVersion(1);
911: // path specified, port specified but blank, domain unspecified
912: cookie3.setDomainAttributeSpecified(false);
913: cookie3.setPathAttributeSpecified(true);
914: cookie3.setPortAttributeSpecified(true);
915: cookie3.setPortAttributeBlank(true);
916: assertEquals(
917: "$Version=\"1\"; name3=\"value\"; $Path=\"/a/b/\"; $Port=\"\"",
918: cookiespec.formatCookie(cookie3));
919:
920: assertEquals(
921: "$Version=\"2\"; "
922: + "name3=\"value\"; $Path=\"/a/b/\"; $Port=\"\"; "
923: + "name2=\"value\"; $Domain=\".domain.com\"; $Path=\"/a/\"; "
924: + "name1=\"value\"; $Domain=\".domain.com\"; $Path=\"/\"; $Port=\"80,8080\"",
925: cookiespec.formatCookies(new Cookie[] { cookie3,
926: cookie2, cookie1 }));
927: }
928:
929: /**
930: * Tests RFC 2965 compliant cookies formatting.
931: */
932: public void testRFC2965CookiesFormatting() throws Exception {
933: CookieSpec cookiespec = new RFC2965Spec();
934: Cookie2 cookie1 = new Cookie2(".domain.com", "name1", "value1",
935: "/", null, false, new int[] { 80, 8080 });
936: cookie1.setVersion(1);
937: // domain, path, port specified
938: cookie1.setDomainAttributeSpecified(true);
939: cookie1.setPathAttributeSpecified(true);
940: cookie1.setPortAttributeSpecified(true);
941: Cookie2 cookie2 = new Cookie2(".domain.com", "name2", null,
942: "/", null, false, null);
943: cookie2.setVersion(1);
944: // value null, domain, path, port specified
945: cookie2.setDomainAttributeSpecified(true);
946: cookie2.setPathAttributeSpecified(true);
947: cookie2.setPortAttributeSpecified(false);
948: Cookie[] cookies = new Cookie[] { cookie1, cookie2 };
949: assertEquals(
950: "$Version=\"1\"; name1=\"value1\"; $Domain=\".domain.com\"; $Path=\"/\"; $Port=\"80,8080\"; "
951: + "name2=\"\"; $Domain=\".domain.com\"; $Path=\"/\"",
952: cookiespec.formatCookies(cookies));
953: }
954:
955: // ------------------------------------------------------- Backward compatibility tests
956:
957: /**
958: * Test backward compatibility with <tt>Set-Cookie</tt> header.
959: */
960: public void testCompatibilityWithSetCookie() throws Exception {
961: CookieSpec cookiespec = new RFC2965Spec();
962: Header header = new Header("Set-Cookie",
963: "name=value; domain=.domain.com; version=1");
964: Cookie[] parsed = cookieParse(cookiespec, "www.domain.com", 80,
965: "/", false, header);
966: assertNotNull(parsed);
967: assertEquals(1, parsed.length);
968: assertEquals("name", parsed[0].getName());
969: assertEquals("value", parsed[0].getValue());
970: assertEquals(".domain.com", parsed[0].getDomain());
971: assertEquals("/", parsed[0].getPath());
972: }
973:
974: }
|