Modified: jakarta/commons/proper/httpclient/branches/COOKIE_2_BRANCH/src/test/org/apache/commons/httpclient/cookie/TestCookieRFC2965Spec.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/branches/COOKIE_2_BRANCH/src/test/org/apache/commons/httpclient/cookie/TestCookieRFC2965Spec.java?rev=264149&r1=264148&r2=264149&view=diff ============================================================================== --- jakarta/commons/proper/httpclient/branches/COOKIE_2_BRANCH/src/test/org/apache/commons/httpclient/cookie/TestCookieRFC2965Spec.java (original) +++ jakarta/commons/proper/httpclient/branches/COOKIE_2_BRANCH/src/test/org/apache/commons/httpclient/cookie/TestCookieRFC2965Spec.java Mon Aug 29 07:28:21 2005 @@ -33,7 +33,9 @@ import org.apache.commons.httpclient.Cookie; import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.NameValuePair; + +import java.util.Date; +import java.util.Arrays; /** * Test cases for RFC2965 cookie spec @@ -42,7 +44,6 @@ */ public class TestCookieRFC2965Spec extends TestCookieBase { - // ------------------------------------------------------------ Constructor public TestCookieRFC2965Spec(String name) { @@ -55,482 +56,700 @@ return new TestSuite(TestCookieRFC2965Spec.class); } - public void testParseAttributeInvalidParams() throws Exception { + + // ------------------------------------------------------- Test Cookie Parsing + + /** + * Test <tt>parse</tt> with invalid params. + */ + public void testParseInvalidParams() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); - Cookie cookie = new Cookie(); - NameValuePair attribute = new NameValuePair("name", "value"); try { - cookiespec.parseAttribute(null, cookie); + // invalid header + cookiespec.parse("www.domain.com", 80, "/", false, (Header) null /* header */); fail("IllegalArgumentException must have been thrown"); - } catch (IllegalArgumentException expected) { - } + } catch (IllegalArgumentException expected) {} + + Header header = new Header("Set-Cookie2", "name=value;Version=1"); + try { + // invalid request host + cookiespec.parse(null /* host */, 80, "/", false, header); + fail("IllegalArgumentException must have been thrown"); + } catch (IllegalArgumentException expected) {} try { - cookiespec.parseAttribute(attribute, null); + // invalid request port + cookiespec.parse("www.domain.com", -32 /* port */, "/", false, header); fail("IllegalArgumentException must have been thrown"); - } catch (IllegalArgumentException expected) { - } + } catch (IllegalArgumentException expected) {} + try { + // invalid request path + cookiespec.parse("www.domain.com", 80, null /* path */, false, header); + fail("IllegalArgumentException must have been thrown"); + } catch (IllegalArgumentException expected) {} } - public void testParseAttributePath() throws Exception { + /** + * Test parsing cookie <tt>"Path"</tt> attribute. + */ + public void testParsePath() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); - Cookie cookie = new Cookie(); - try { - cookiespec.parseAttribute(new NameValuePair("path", null), cookie); - fail("MalformedCookieException must have been thrown"); - } catch (MalformedCookieException expected) { - } - try { - cookiespec.parseAttribute(new NameValuePair("path", " "), cookie); - fail("MalformedCookieException must have been thrown"); - } catch (MalformedCookieException expected) { - } - cookiespec.parseAttribute(new NameValuePair("path", "/"), cookie); - assertEquals(cookie.getPath(), "/"); - // this will be ignored since path is already specified for this cookie - cookiespec.parseAttribute(new NameValuePair("path", null), cookie); + // path cannot be null + Header header = new Header("Set-Cookie2", "name=value;Path=;Version=1"); + Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNull(parsed); + //path cannot be blank + header = new Header("Set-Cookie2", "name=value;Path=\" \";Version=1"); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNull(parsed); + + // valid path + header = new Header("Set-Cookie2", "name=value;Path=/;Version=1;Path="); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + // only the first occurence of path attribute is considered, others ignored + Cookie2 cookie = (Cookie2) parsed[0]; + assertEquals("/", cookie.getPath()); + assertTrue(cookie.isPathAttributeSpecified()); + + // Path is OPTIONAL, defaults to the request path + header = new Header("Set-Cookie2", "name=value;Version=1"); + parsed = cookiespec.parse("www.domain.com", 80, "/path" /* request path */, false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + cookie = (Cookie2) parsed[0]; + assertEquals("/path", cookie.getPath()); + assertFalse(cookie.isPathAttributeSpecified()); } - public void testParseAttributeDomain() throws Exception { + /** + * Test parsing cookie <tt>"Domain"</tt> attribute. + */ + public void testParseDomain() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); - Cookie cookie = new Cookie(); - try { - cookiespec.parseAttribute(new NameValuePair("domain", null), cookie); - fail("MalformedCookieException must have been thrown"); - } catch (MalformedCookieException expected) { - } - try { - cookiespec.parseAttribute(new NameValuePair("domain", " "), cookie); - fail("MalformedCookieException must have been thrown"); - } catch (MalformedCookieException expected) { - } - cookiespec.parseAttribute(new NameValuePair("domain", ".domain.com"), cookie); - assertEquals(cookie.getDomain(), ".domain.com"); - // this will be ignored since domain is already specified for this cookie - cookiespec.parseAttribute(new NameValuePair("domain", null), cookie); + // domain cannot be null + Header header = new Header("Set-Cookie2", "name=value;Domain=;Version=1"); + Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNull(parsed); + + // domain cannot be blank + header = new Header("Set-Cookie2", "name=value;Domain=\" \";Version=1"); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNull(parsed); - // puts a dot in front of domain if missing - cookie = new Cookie(); - cookiespec.parseAttribute(new NameValuePair("domain", "domain.com"), cookie); - assertEquals(cookie.getDomain(), ".domain.com"); + header = new Header("Set-Cookie2", "name=value;Domain=.domain.com;Version=1;Domain="); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + // only the first occurence of domain attribute is considered, others ignored + Cookie2 cookie = (Cookie2) parsed[0]; + assertEquals(".domain.com", cookie.getDomain()); + assertTrue(cookie.isDomainAttributeSpecified()); + + // should put a leading dot if there is no dot in front of domain + header = new Header("Set-Cookie2", "name=value;Domain=domain.com;Version=1"); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + cookie = (Cookie2) parsed[0]; + assertEquals(".domain.com", cookie.getDomain()); + + // Domain is OPTIONAL, defaults to the request host + header = new Header("Set-Cookie2", "name=value;Version=1"); + parsed = cookiespec.parse("www.domain.com" /* request host */, 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + cookie = (Cookie2) parsed[0]; + assertEquals("www.domain.com", cookie.getDomain()); + assertFalse(cookie.isDomainAttributeSpecified()); } - public void testParseAttributePort() throws Exception { + /** + * Test parsing cookie <tt>"Port"</tt> attribute. + */ + public void testParsePort() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); - - Cookie cookie = new Cookie(); - cookie.setPorts(new int[] {80}); //default to request port - cookiespec.parseAttribute(new NameValuePair("port", null), cookie); // null port defaults to request port - assertTrue(equalArray(cookie.getPorts(), new int[] {80})); + Header header = new Header("Set-Cookie2", "name=value;Port=;Version=1"); + Cookie[] parsed = cookiespec.parse("www.domain.com", 80 /* request port */, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + Cookie2 cookie = (Cookie2) parsed[0]; + assertEquals(new int[] {80}, cookie.getPorts()); + assertTrue(cookie.isPortAttributeSpecified() && cookie.isPortAttributeBlank()); - cookie = new Cookie(); - cookie.setPorts(new int[] {80}); //default to request port - cookiespec.parseAttribute(new NameValuePair("port", " "), cookie); // blank port defaults to request port - assertTrue(equalArray(cookie.getPorts(), new int[] {80})); - - try { - cookie = new Cookie(); - cookiespec.parseAttribute(new NameValuePair("port", "nonsense"), cookie); - // anything else not an 'int' must fail - fail("MalformedCookieException must have been thrown"); - } catch (MalformedCookieException expected) { - } - - cookie = new Cookie(); - cookiespec.parseAttribute(new NameValuePair("port", "80,8080"), cookie); - assertTrue(equalArray(cookie.getPorts(), new int[] {80,8080})); - // this will be ignored since port already specified for this cookie - cookiespec.parseAttribute(new NameValuePair("port", "nonsense"), cookie); + header = new Header("Set-Cookie2", "name=value;Port=\" \";Version=1"); + parsed = cookiespec.parse("www.domain.com", 80 /* request port */, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + cookie = (Cookie2) parsed[0]; + assertEquals(new int[] {80}, cookie.getPorts()); + assertTrue(cookie.isPortAttributeSpecified() && cookie.isPortAttributeBlank()); + + // invalid port + header = new Header("Set-Cookie2", "name=value;Port=nonsense;Version=1"); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNull(parsed); + + // all ports must be > 0 + header = new Header("Set-Cookie2", "name=value;Port=\"80,-800,8000\";Version=1"); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNull(parsed); + + // valid ports + header = new Header("Set-Cookie2", "name=value;Port=\"80,800,8000\";Version=1;Port=nonsense"); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + // only the first occurence of port attribute is considered, others ignored + cookie = (Cookie2) parsed[0]; + assertEquals(new int[] {80,800,8000}, cookie.getPorts()); + assertTrue(cookie.isPortAttributeSpecified()); + + // Port is OPTIONAL, cookie can be accepted from any port + header = new Header("Set-Cookie2", "name=value;Version=1"); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + cookie = (Cookie2) parsed[0]; + assertFalse(cookie.isPortAttributeSpecified()); } - public void testParseAttributeVersion() throws Exception { + /** + * test parsing cookie name/value. + */ + public void testParseNameValue() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); - Cookie cookie = new Cookie(); - try { - cookiespec.parseAttribute(new NameValuePair("version", null), cookie); - fail("MalformedCookieException must have been thrown"); - } catch (MalformedCookieException expected) { - } - - try { - cookiespec.parseAttribute(new NameValuePair("version", "nonsense"), cookie); - fail("MalformedCookieException must have been thrown"); - } catch (MalformedCookieException expected) { - } - cookiespec.parseAttribute(new NameValuePair("version", "1"), cookie); - assertEquals(cookie.getVersion(), 1); + Header header = new Header("Set-Cookie2", "name=value;Version=1;"); + Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + Cookie2 cookie = (Cookie2) parsed[0]; + assertEquals("name", cookie.getName()); + assertEquals("value", cookie.getValue()); } - public void testParseAttributeMaxage() throws Exception { + /** + * test parsing cookie <tt>"Version"</tt> attribute. + */ + public void testParseVersion() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); - Cookie cookie = new Cookie(); - try { - cookiespec.parseAttribute(new NameValuePair("max-age", null), cookie); - fail("MalformedCookieException must have been thrown"); - } catch (MalformedCookieException expected) { - } + // version cannot ne null + Header header = new Header("Set-Cookie2", "name=value;Version=;"); + Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNull(parsed); - try { - cookiespec.parseAttribute(new NameValuePair("max-age", "nonsense"), cookie); - fail("MalformedCookieException must have been thrown"); - } catch (MalformedCookieException expected) { - } - cookiespec.parseAttribute(new NameValuePair("max-age", "3600"), cookie); - assertNotNull(cookie.getExpiryDate()); + // version must be > 0 + header = new Header("Set-Cookie2", "name=value;Version=-1;"); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNull(parsed); + + // valid version + header = new Header("Set-Cookie2", "name=value;Version=1;"); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + Cookie2 cookie = (Cookie2) parsed[0]; + assertEquals(1, cookie.getVersion()); + assertTrue(cookie.isVersionAttributeSpecified()); } - public void testParseAttributeOthers() throws Exception { + /** + * test parsing cookie <tt>"Max-age"</tt> attribute. + */ + public void testParseMaxage() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); - Cookie cookie = new Cookie(); - // test comment - String comment = "test cookie"; - cookiespec.parseAttribute(new NameValuePair("comment", comment), cookie); - assertEquals(cookie.getComment(), comment); - // test comment URL - String commentURL = "www.sourceforge.com/cookiedesc"; - cookiespec.parseAttribute(new NameValuePair("commenturl", commentURL), cookie); - assertEquals(cookie.getCommentURL(), commentURL); - // test secure - cookiespec.parseAttribute(new NameValuePair("secure", null), cookie); - assertTrue(cookie.getSecure()); - // test discard - cookiespec.parseAttribute(new NameValuePair("discard", null), cookie); + // max-age cannot be null + Header header = new Header("Set-Cookie2", "name=value;Max-age=;Version=1"); + Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNull(parsed); + + // max-age must be > 0 + header = new Header("Set-Cookie2", "name=value;Max-age=-3600;Version=1;"); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNull(parsed); + + // valid max-age + header = new Header("Set-Cookie2", "name=value;Max-age=3600;Version=1;Max-age=nonsense"); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + // only the first occurence of max-age attribute is considered, others ignored + Cookie2 cookie = (Cookie2) parsed[0]; + assertFalse(cookie.isExpired()); + + // Max-age is OPTIONAL, defaults to session cookie + header = new Header("Set-Cookie2", "name=value;Version=1"); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + cookie = (Cookie2) parsed[0]; assertFalse(cookie.isPersistent()); } /** - * Test domain equals host + * test parsing <tt>"Discard"</tt> attribute. */ - public void testParseValidateDomainEqualsHost() throws Exception { - Header header = new Header("Set-Cookie2", - "cookie-name=cookie-value; domain=www.b.com; version=1"); + public void testParseDiscard() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); - Cookie[] parsed = cookieParse(cookiespec, "www.b.com", 80, "/", false, header); + Header header = new Header("Set-Cookie2", "name=value;Discard;Max-age=36000;Version=1"); + Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); assertNotNull(parsed); assertEquals(1, parsed.length); - assertEquals("www.b.com", parsed[0].getDomain()); + Cookie2 cookie = (Cookie2) parsed[0]; + // discard overrides max-age + assertFalse(cookie.isPersistent()); - // test backward compatibility with Set-Cookie header - header = new Header("Set-Cookie", - "cookie-name=cookie-value; domain=www.b.com; version=1"); - parsed = cookieParse(cookiespec, "www.b.com", 80, "/", false, header); + // Discard is OPTIONAL, default behavior is dictated by max-age + header = new Header("Set-Cookie2", "name=value;Version=1"); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); assertNotNull(parsed); assertEquals(1, parsed.length); - assertEquals("www.b.com", parsed[0].getDomain()); } /** - * Test Domain with no leading dot in domain name + * test parsing <tt>"Comment"</tt>, <tt>"CommentURL"</tt> and + * <tt>"Secure"</tt> attributes. */ - public void testParseValidateDomainLeadingDot() throws Exception { - // set-cookie2 header works without a leading dot - Header header = new Header("Set-Cookie2", - "cookie-name=cookie-value; domain=a.b.com; version=1"); + public void testParseOtherAttributes() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); - Cookie[] parsed = cookieParse(cookiespec, "www.a.b.com", 80, "/", false, header); + Header header = new Header("Set-Cookie2", "name=value;Comment=\"good cookie\";" + + "CommentURL=\"www.domain.com/goodcookie/\";Secure;Version=1"); + Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); assertNotNull(parsed); assertEquals(1, parsed.length); - assertEquals(".a.b.com", parsed[0].getDomain()); + Cookie2 cookie = (Cookie2) parsed[0]; + assertEquals("good cookie", cookie.getComment()); + assertEquals("www.domain.com/goodcookie/", cookie.getCommentURL()); + assertTrue(cookie.getSecure()); - // test backward compatibility; set-cookie header must fail - // without a leading dot in domain name - header = new Header("Set-Cookie", - "cookie-name=cookie-value; domain=a.b.com; version=1"); - try { - parsed = cookieParse(cookiespec, "www.a.b.com", 80, "/", false, header); - fail("MalformedCookieException should have been thrown"); - } catch (MalformedCookieException e) { - // expected - } + // Comment, CommentURL, Secure are OPTIONAL + header = new Header("Set-Cookie2", "name=value;Version=1"); + parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + cookie = (Cookie2) parsed[0]; + assertFalse(cookie.getSecure()); } /** - * Domain must have atleast least one embedded dot + * Test parsing header with 2 cookies (separated by comma) */ - public void testParseValidateDomainEmbeddedDot() throws Exception { - Header header = new Header("Set-Cookie2", - "cookie-name=cookie-value; domain=.com; version=1"); + public void testCookiesWithComma() throws Exception { + CookieSpec cookiespec = new RFC2965Spec(); + Header header = new Header("Set-Cookie2", "a=b,c"); + Cookie[] parsed = cookiespec.parse("www.domain.com", 80, "/", false, header); + assertNotNull(parsed); + assertEquals(2, parsed.length); + assertEquals("a", parsed[0].getName()); + assertEquals("b", parsed[0].getValue()); + assertEquals("c", parsed[1].getName()); + assertEquals(null, parsed[1].getValue()); + } + + // ------------------------------------------------------- Test Cookie Validation + /** + * Test <tt>Domain</tt> validation when domain is not specified + * in <tt>Set-Cookie2</tt> header. + */ + public void testValidateNoDomain() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); - try { - Cookie[] parsed = cookieParse(cookiespec, "b.com", 80, "/", false, header); - fail("MalformedCookieException should have been thrown"); - } catch (MalformedCookieException e) { - // expected - } - - // test backward compatibility with Set-Cookie header - header = new Header("Set-Cookie2", - "cookie-name=cookie-value; domain=.com; version=1"); - try { - Cookie[] parsed = cookieParse(cookiespec, "b.com", 80, "/", false, header); - fail("MalformedCookieException should have been thrown"); - } catch (MalformedCookieException e) { - // expected - } + Header header = new Header("Set-Cookie2", "name=value;Version=1"); + Cookie[] parsed = cookieParse(cookiespec, "www.domain.com" /* request host */, 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + Cookie2 cookie = (Cookie2) parsed[0]; + // cookie domain must string match request host + assertEquals("www.domain.com", cookie.getDomain()); } /** - * test .local domain + * Test <tt>Domain</tt> validation. Cookie domain attribute must have a + * leading dot. */ - public void testParseValidateDomainLocal() throws Exception { - Header header = new Header("Set-Cookie2", - "cookie-name=cookie-value; domain=.local; version=1"); + public void testValidateDomainLeadingDot() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); - Cookie[] parsed = cookieParse(cookiespec, "host", 80, "/", false, header); + Header header = new Header("Set-Cookie2", "name=value;Domain=domain.com;Version=1"); + Cookie[] parsed = cookieParse(cookiespec, "www.domain.com", 80, "/", false, header); assertNotNull(parsed); assertEquals(1, parsed.length); - assertEquals(".local", parsed[0].getDomain()); - //TODO: however simple host name like 'host' should not be accepted if domain name is not .local + Cookie2 cookie = (Cookie2) parsed[0]; + assertEquals(".domain.com", cookie.getDomain()); } /** - * effective host name minus domain must not contain any dots. + * Test <tt>Domain</tt> validation. Domain must have atleast one embedded dot. */ - public void testParseValidateDomainIllegal() throws Exception { - Header header = new Header("Set-Cookie2", - "cookie-name=cookie-value; domain=.c.com; version=1"); + public void testValidateDomainEmbeddedDot() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); + Header header = new Header("Set-Cookie2", "name=value; domain=.com; version=1"); try { - Cookie[] parsed = cookieParse(cookiespec, "a.b.c.com", 80, "/", false, header); + cookieParse(cookiespec, "b.com", 80, "/", false, header); fail("MalformedCookieException should have been thrown"); - } catch (MalformedCookieException e) { - // expected - } - - // test backward compatibility with Set-Cookie header - header = new Header("Set-Cookie", - "cookie-name=cookie-value; domain=.c.com; version=1"); + } catch (MalformedCookieException expected) {} + + header = new Header("Set-Cookie2", "name=value;Domain=domain.com;Version=1"); + Cookie[] parsed = cookieParse(cookiespec, "www.domain.com", 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + } + + /** + * Test local <tt>Domain</tt> validation. Simple host names + * (without any dots) are valid only when cookie domain is specified + * as ".local". + */ + public void testValidateDomainLocal() throws Exception { + CookieSpec cookiespec = new RFC2965Spec(); + // when domain is specified as .local, simple host names are valid + Header header = new Header("Set-Cookie2", "name=value; domain=.local; version=1"); + Cookie[] parsed = cookieParse(cookiespec, "simplehost" /* request host */, 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + Cookie2 cookie = (Cookie2) parsed[0]; + assertEquals(".local", cookie.getDomain()); + + // when domain is NOT specified as .local, simple host names are invalid + header = new Header("Set-Cookie2", "name=value; domain=domain.com; version=1"); try { - Cookie[] parsed = cookieParse(cookiespec, "a.b.c.com", 80, "/", false, header); + // since domain is not .local, this must fail + parsed = cookieParse(cookiespec, "simplehost" /* request host */, 80, "/", false, header); fail("MalformedCookieException should have been thrown"); - } catch (MalformedCookieException e) { - // expected - } + } catch (MalformedCookieException expected) {} } + /** - * test version. + * Test <tt>Domain</tt> validation. Effective host name + * must domain-match domain attribute. */ - public void testParseValidateVersion() throws Exception { - Header header = new Header("Set-Cookie2", "cookie-name=cookie-value"); + public void testValidateDomainEffectiveHost() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); + + // cookie domain does not domain-match request host + Header header = new Header("Set-Cookie2", "name=value; domain=.domain.com; version=1"); try { - Cookie[] parsed = cookieParse(cookiespec, "c.a.com", 80, "/", false, header); - // version attribute is REQUIRED + cookieParse(cookiespec, "www.domain.org" /* request host */, 80, "/", false, header); fail("MalformedCookieException should have been thrown"); - } catch (MalformedCookieException e) { - // expected - } + } catch (MalformedCookieException expected) {} + + // cookie domain domain-matches request host + header = new Header("Set-Cookie2", "name=value; domain=.domain.com; version=1"); + Cookie[] parsed = cookieParse(cookiespec, "www.domain.com" /* request host */, 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + } - // test backward compatibility with Set-Cookie header - header = new Header("Set-Cookie", "cookie-name=cookie-value"); + /** + * Test local <tt>Domain</tt> validation. + * Effective host name minus domain must not contain any dots. + */ + public void testValidateDomainIllegal() throws Exception { + CookieSpec cookiespec = new RFC2965Spec(); + Header header = new Header("Set-Cookie2", "name=value; domain=.domain.com; version=1"); try { - Cookie[] parsed = cookieParse(cookiespec, "c.a.com", 80, "/", false, header); - // version attribute is REQUIRED + cookieParse(cookiespec, "a.b.domain.com" /* request host */, 80, "/", false, header); fail("MalformedCookieException should have been thrown"); - } catch (MalformedCookieException e) { - // expected - } + } catch (MalformedCookieException expected) {} } /** - * test path. + * Test cookie <tt>Path</tt> validation. Cookie path attribute must path-match + * request path. */ - public void testParseValidatePath() throws Exception { - Header header = new Header("Set-Cookie2", - "cookie-name=cookie-value; domain=127.0.0.1; path=/path"); + public void testValidatePath() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); + Header header = new Header("Set-Cookie2", "name=value;path=/path;version=1"); try { - Cookie[] parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/", false, header); - fail("HttpException exception should have been thrown"); - } catch (MalformedCookieException e) { - // expected - } - Cookie[] parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/path/path1", false, header); - assertNotNull(parsed); - assertEquals(1, parsed.length); - assertEquals("/path", parsed[0].getDomain()); + cookieParse(cookiespec, "www.domain.com", 80, "/" /* request path */, false, header); + fail("MalformedCookieException exception should have been thrown"); + } catch (MalformedCookieException expected) {} - // test backward compatibility with Set-Cookie header - header = new Header("Set-Cookie", - "cookie-name=cookie-value; domain=127.0.0.1; path=/path"); + // path-matching is case-sensitive + header = new Header("Set-Cookie2", "name=value;path=/Path;version=1"); try { - parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/", false, header); - fail("HttpException exception should have been thrown"); - } catch (MalformedCookieException e) { - // expected - } - parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/path/path1", false, header); + cookieParse(cookiespec, "www.domain.com", 80, "/path" /* request path */, false, header); + fail("MalformedCookieException exception should have been thrown"); + } catch (MalformedCookieException expected) {} + + header = new Header("Set-Cookie2", "name=value;path=/path;version=1"); + Cookie[] parsed = cookieParse(cookiespec, "www.domain.com", + 80, "/path/path1" /* request path */, false, header); assertNotNull(parsed); assertEquals(1, parsed.length); - assertEquals("/path", parsed[0].getDomain()); + assertEquals("/path", parsed[0].getPath()); } /** - * Tests if cookie constructor rejects cookie name containing blanks. + * Test cookie name validation. */ - public void testCookieNameWithBlanks() throws Exception { - Header header = new Header("Set-Cookie2", "invalid name="); + public void testValidateCookieName() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); + // cookie name must not contain blanks + Header header = new Header("Set-Cookie2", "invalid name=value; version=1"); try { - Cookie[] parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/", false, header); + cookieParse(cookiespec, "127.0.0.1", 80, "/", false, header); fail("MalformedCookieException exception should have been thrown"); - } catch (MalformedCookieException e) { - // expected - } + } catch (MalformedCookieException expected) {} - // backward compatibility with set-cookie - header = new Header("Set-Cookie", "invalid name="); + // cookie name must not start with '$'. + header = new Header("Set-Cookie2", "$invalid_name=value; version=1"); try { - Cookie[] parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/", false, header); + cookieParse(cookiespec, "127.0.0.1", 80, "/", false, header); fail("MalformedCookieException exception should have been thrown"); - } catch (MalformedCookieException e) { - // expected - } + } catch (MalformedCookieException expected) {} + + // valid name + header = new Header("Set-Cookie2", "name=value; version=1"); + Cookie[] parsed = cookieParse(cookiespec, "www.domain.com", 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + Cookie2 cookie = (Cookie2) parsed[0]; + assertEquals("name", cookie.getName()); + assertEquals("value", cookie.getValue()); } + /** + * Test cookie <tt>Port</tt> validation. Request port must be in the + * port attribute list. + */ + public void testValidatePort() throws Exception { + Header header = new Header("Set-Cookie2", "name=value; Port=\"80,800\"; version=1"); + CookieSpec cookiespec = new RFC2965Spec(); + try { + cookieParse(cookiespec, "www.domain.com", 8000 /* request port */, "/", false, header); + fail("MalformedCookieException should have been thrown"); + } catch (MalformedCookieException e) {} + + // valid port list + Cookie[] parsed = cookieParse(cookiespec, "www.domain.com", 80 /* request port */, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + Cookie2 cookie = (Cookie2) parsed[0]; + assertEquals(new int[] {80, 800}, cookie.getPorts()); + } /** - * Tests if cookie constructor rejects cookie name starting with $. + * Test cookie <tt>Version</tt> validation. */ - public void testCookieNameStartingWithDollarSign() throws Exception { - Header header = new Header("Set-Cookie2", "$invalid_name="); + public void testValidateVersion() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); + // version attribute is REQUIRED + Header header = new Header("Set-Cookie2", "name=value"); try { - Cookie[] parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/", false, header); - fail("MalformedCookieException exception should have been thrown"); - } catch (MalformedCookieException e) { - // expected - } + cookieParse(cookiespec, "www.domain.com", 8000, "/", false, header); + fail("MalformedCookieException should have been thrown"); + } catch (MalformedCookieException e) {} - // backward compatibility with set-cookie - header = new Header("Set-Cookie", "$invalid_name="); + // version attribute must be 1 with Set-Cookie2 header + header = new Header("Set-Cookie2", "name=value; version=0"); try { - Cookie[] parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/", false, header); - fail("MalformedCookieException exception should have been thrown"); - } catch (MalformedCookieException e) { - // expected - } + cookieParse(cookiespec, "www.domain.com", 8000, "/", false, header); + fail("MalformedCookieException should have been thrown"); + } catch (MalformedCookieException e) {} } - //TODO: test for cookie matching - //TODO: test for cookie formatting + // ------------------------------------------------------- Test Cookie Matching + /** - * Tests if cookie values with embedded comma are handled correctly. + * test cookie <tt>Path</tt> matching. Cookie path attribute must path-match + * path of the request URI. */ - public void testCookieWithComma() throws Exception { - Header header = new Header("Set-Cookie", "a=b,c"); + public void testMatchPath() throws Exception { + Cookie2 cookie = new Cookie2(".domain.com", "name", + "value", "/path" /* path */, null, false, new int[] {80}); + CookieSpec cookiespec = new RFC2965Spec(); + assertFalse(cookiespec.match("www.domain.com", 80, "/" /* request path */, false, cookie)); + assertTrue(cookiespec.match("www.domain.com", 80, "/path/path1" /* request path */, false, cookie)); + } + /** + * test cookie <tt>Domain</tt> matching. + */ + public void testMatchDomain() throws Exception { + Cookie2 cookie = new Cookie2(".domain.com" /* domain */, "name", + "value", "/", null, false, new int[] {80}); CookieSpec cookiespec = new RFC2965Spec(); - Cookie[] cookies = cookiespec.parse("localhost", 80, "/", false, header); - assertEquals("number of cookies", 2, cookies.length); - assertEquals("a", cookies[0].getName()); - assertEquals("b", cookies[0].getValue()); - assertEquals("c", cookies[1].getName()); - assertEquals(null, cookies[1].getValue()); + // effective host name minus domain must not contain any dots + assertFalse(cookiespec.match("a.b.domain.com" /* request host */, 80, "/", false, cookie)); + // The effective host name MUST domain-match the Domain + // attribute of the cookie. + assertFalse(cookiespec.match("www.domain.org" /* request host */, 80, "/", false, cookie)); + assertTrue(cookiespec.match("www.domain.com" /* request host */, 80, "/", false, cookie)); } - public void testFormatInvalidCookies() throws Exception { + /** + * test cookie local <tt>Domain</tt> matching. + */ + public void testMatchDomainLocal() throws Exception { + Cookie2 cookie = new Cookie2(".local" /* domain */, "name", + "value", "/", null, false, new int[] {80}); CookieSpec cookiespec = new RFC2965Spec(); - try { - String s = cookiespec.formatCookie(null); - fail("IllegalArgumentException nust have been thrown"); - } catch (IllegalArgumentException expected) { - } + assertTrue(cookiespec.match("host" /* request host */, 80, "/", false, cookie)); + assertFalse(cookiespec.match("host.com" /* request host */, 80, "/", false, cookie)); } /** - * Tests RFC 2965 compiant cookie formatting. + * test cookie <tt>Port</tt> matching. */ - public void testRFC2965CookieFormatting() throws Exception { + public void testMatchPort() throws Exception { + // cookie can be sent to any port if port attribute not specified + Cookie2 cookie = new Cookie2(".domain.com", "name", + "value", "/", null, false, null /* ports */); CookieSpec cookiespec = new RFC2965Spec(); - Header header = new Header("Set-Cookie", - "name=\"value\"; version=\"1\"; path=\"/\"; domain=\".mydomain.com\""); - Cookie[] cookies = cookiespec.parse("myhost.mydomain.com", 80, "/", false, header ); - cookiespec.validate("myhost.mydomain.com", 80, "/", false, cookies[0]); - String s1 = cookiespec.formatCookie(cookies[0]); - assertEquals(s1, "$Version=\"1\"; name=\"value\"; $Domain=\".mydomain.com\"; $Path=\"/\""); - - header = new Header( "Set-Cookie", - "name=value; path=/; domain=.mydomain.com"); - cookies = cookiespec.parse("myhost.mydomain.com", 80, "/", false, header ); - cookiespec.validate("myhost.mydomain.com", 80, "/", false, cookies[0]); - String s2 = cookiespec.formatCookie(cookies[0]); - assertEquals(s2, "$Version=0; name=value; $Domain=.mydomain.com; $Path=/"); + cookie.setPortAttributeSpecified(false); + assertTrue(cookiespec.match("www.domain.com", 8080 /* request port */, "/", false, cookie)); + assertTrue(cookiespec.match("www.domain.com", 323 /* request port */, "/", false, cookie)); + + // otherwise, request port must be in cookie's port list + cookie = new Cookie2(".domain.com", "name", + "value", "/", null, false, new int[] {80, 8080} /* ports */); + cookie.setPortAttributeSpecified(true); + assertFalse(cookiespec.match("www.domain.com", 434 /* request port */, "/", false, cookie)); + assertTrue(cookiespec.match("www.domain.com", 8080 /* request port */, "/", false, cookie)); } - public void testRFC2965CookiesFormatting() throws Exception { + /** + * test cookie expiration. + */ + public void testCookieExpiration() throws Exception { + Date afterOneHour = new Date(System.currentTimeMillis() + 3600 * 1000L); + Cookie2 cookie = new Cookie2(".domain.com", "name", + "value", "/", afterOneHour /* expiry */, false, null); CookieSpec cookiespec = new RFC2965Spec(); - Header header = new Header("Set-Cookie", - "name1=value1; path=/; domain=.mydomain.com, " + - "name2=\"value2\"; version=\"1\"; path=\"/\"; domain=\".mydomain.com\""); - Cookie[] cookies = cookieParse(cookiespec, "myhost.mydomain.com", 80, "/", false, header); - assertNotNull(cookies); - assertEquals(2, cookies.length); - String s1 = cookiespec.formatCookies(cookies); - assertEquals(s1, - "$Version=0; name1=value1; $Domain=.mydomain.com; $Path=/; " + - "name2=value2; $Domain=.mydomain.com; $Path=/"); - - header = new Header("Set-Cookie", - "name1=value1; version=1; path=/; domain=.mydomain.com, " + - "name2=\"value2\"; version=\"1\"; path=\"/\"; domain=\".mydomain.com\""); - cookies = cookieParse(cookiespec, "myhost.mydomain.com", 80, "/", false, header); - assertNotNull(cookies); - assertEquals(2, cookies.length); - String s2 = cookiespec.formatCookies(cookies); - assertEquals(s2, - "$Version=\"1\"; name1=\"value1\"; $Domain=\".mydomain.com\"; $Path=\"/\"; " + - "name2=\"value2\"; $Domain=\".mydomain.com\"; $Path=\"/\""); + assertTrue(cookiespec.match("www.domain.com", 80, "/", false, cookie)); + + Date beforeOneHour = new Date(System.currentTimeMillis() - 3600 * 1000L); + cookie = new Cookie2(".domain.com", "name", + "value", "/", beforeOneHour /* expiry */, false, null); + assertFalse(cookiespec.match("www.domain.com", 80, "/", false, cookie)); + + // discard attributes overrides cookie age, makes it a session cookie. + cookie.setDiscard(true); + assertFalse(cookie.isPersistent()); + assertTrue(cookiespec.match("www.domain.com", 80, "/", false, cookie)); } /** - * Tests if null cookie values are handled correctly. + * test cookie <tt>Secure</tt> attribute. */ - public void testNullCookieValueFormatting() { - Cookie cookie = new Cookie(".whatever.com", "name", null, "/", null, false); - cookie.setDomainAttributeSpecified(true); - cookie.setPathAttributeSpecified(true); + public void testCookieSecure() throws Exception { + CookieSpec cookiespec = new RFC2965Spec(); + // secure cookie can only be sent over a secure connection + Cookie2 cookie = new Cookie2(".domain.com", "name", + "value", "/", null, true /* secure */, null); + assertFalse(cookiespec.match("www.domain.com", 80, "/", false /* request secure */, cookie)); + assertTrue(cookiespec.match("www.domain.com", 80, "/", true /* request secure */, cookie)); + } + // ------------------------------------------------------- Test Cookie Formatting + + public void testFormatInvalidCookie() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); - String s = cookiespec.formatCookie(cookie); - assertEquals("$Version=0; name=; $Domain=.whatever.com; $Path=/", s); + try { + cookiespec.formatCookie(null); + fail("IllegalArgumentException nust have been thrown"); + } catch (IllegalArgumentException expected) {} + } + /** + * Tests RFC 2965 compliant cookie formatting. + */ + public void testRFC2965CookieFormatting() throws Exception { + CookieSpec cookiespec = new RFC2965Spec(); + Cookie2 cookie = new Cookie2(".domain.com", "name", + "value", "/", null, false, new int[] {80,8080}); cookie.setVersion(1); - s = cookiespec.formatCookie(cookie); - assertEquals("$Version=\"1\"; name=\"\"; $Domain=\".whatever.com\"; $Path=\"/\"", s); - } + // domain, path, port specified + cookie.setDomainAttributeSpecified(true); + cookie.setPathAttributeSpecified(true); + cookie.setPortAttributeSpecified(true); + assertEquals("$Version=\"1\"; name=\"value\"; $Domain=\".domain.com\"; $Path=\"/\"; $Port=\"80,8080\"", + cookiespec.formatCookie(cookie)); - public void testCookieNullDomainNullPathFormatting() { - Cookie cookie = new Cookie(null, "name", null, "/", null, false); + // domain, path specified but port unspecified cookie.setDomainAttributeSpecified(true); cookie.setPathAttributeSpecified(true); + cookie.setPortAttributeSpecified(false); + assertEquals("$Version=\"1\"; name=\"value\"; $Domain=\".domain.com\"; $Path=\"/\"", + cookiespec.formatCookie(cookie)); + // path specified, port specified but blank, domain unspecified + cookie.setDomainAttributeSpecified(false); + cookie.setPathAttributeSpecified(true); + cookie.setPortAttributeSpecified(true); + cookie.setPortAttributeBlank(true); + assertEquals("$Version=\"1\"; name=\"value\"; $Path=\"/\"; $Port=\"\"", + cookiespec.formatCookie(cookie)); + } + + /** + * Tests RFC 2965 compliant cookies formatting. + */ + public void testRFC2965CookiesFormatting() throws Exception { CookieSpec cookiespec = new RFC2965Spec(); - String s = cookiespec.formatCookie(cookie); - assertEquals("$Version=0; name=; $Path=/", s); + Cookie2 cookie1 = new Cookie2(".domain.com", "name1", + "value1", "/", null, false, new int[] {80,8080}); + cookie1.setVersion(1); + // domain, path, port specified + cookie1.setDomainAttributeSpecified(true); + cookie1.setPathAttributeSpecified(true); + cookie1.setPortAttributeSpecified(true); + Cookie2 cookie2 = new Cookie2(".domain.com", "name2", + null, "/", null, false, null); + cookie2.setVersion(1); + // value null, domain, path, port specified + cookie2.setDomainAttributeSpecified(true); + cookie2.setPathAttributeSpecified(true); + cookie2.setPortAttributeSpecified(false); + Cookie[] cookies = new Cookie[] {cookie1, cookie2}; + assertEquals("$Version=\"1\"; name1=\"value1\"; $Domain=\".domain.com\"; $Path=\"/\"; $Port=\"80,8080\"; " + + "name2=\"\"; $Domain=\".domain.com\"; $Path=\"/\"", cookiespec.formatCookies(cookies)); + } + + // ------------------------------------------------------- Backward compatibility tests - cookie.setDomainAttributeSpecified(false); - cookie.setPathAttributeSpecified(false); - s = cookiespec.formatCookie(cookie); - assertEquals("$Version=0; name=", s); - } - - private boolean equalArray(int[] a1, int[] a2) { - if (a1 == null && a2 == null) - return true; - if (a1 == null || a2 == null) - return false; - if (a1.length != a2.length) - return false; - for (int i = 0; i < a1.length; i++) { - if (a1[i] != a2[i]) - return false; - } - return true; + /** + * Test backward compatibility with <tt>Set-Cookie</tt> header. + */ + public void testCompatibilityWithSetCookie() throws Exception { + CookieSpec cookiespec = new RFC2965Spec(); + Header header = new Header("Set-Cookie", "name=value; domain=.domain.com; version=1"); + Cookie[] parsed = cookieParse(cookiespec, "www.domain.com", 80, "/", false, header); + assertNotNull(parsed); + assertEquals(1, parsed.length); + assertEquals("name", parsed[0].getName()); + assertEquals("value", parsed[0].getValue()); + assertEquals(".domain.com", parsed[0].getDomain()); + assertEquals("/", parsed[0].getPath()); + } + + // ------------------------------------------------------- Helper Methods + + /** + * Asserts that two arrays are equal (deep equality). + * @param expected expected array + * @param actual actual array + */ + public static void assertEquals(int[] expected, int[] actual) { + if (Arrays.equals(expected, actual)) + return; + // TODO: uses 1.5 specifc methods + //failNotEquals(null, Arrays.toString(expected), Arrays.toString(actual)); + } + + static private void failNotEquals(String message, Object expected, Object actual) { + fail(format(message, expected, actual)); + } + + static private String format(String message, Object expected, Object actual) { + String formatted= ""; + if (message != null) + formatted = message+" "; + return formatted + "expected:<"+expected+"> but was:<"+actual+">"; } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]