/* * Copyright (c) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.api.client.http; import com.google.api.client.util.Key; import junit.framework.TestCase; import org.junit.Assert; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * Tests {@link GenericUrl}. * * @author Yaniv Inbar */ public class GenericUrlTest extends TestCase { public GenericUrlTest() { } public GenericUrlTest(String name) { super(name); } private static final String MINIMAL = "http://bar"; public void testBuild_minimal() { GenericUrl url = new GenericUrl(); url.setScheme("http"); url.setHost("bar"); assertEquals(MINIMAL, url.build()); } public void testParse_minimal() { GenericUrl url = new GenericUrl(MINIMAL); assertEquals("http", url.getScheme()); } private static final String NO_PATH = "http://bar?a=b"; public void testBuild_noPath() { GenericUrl url = new GenericUrl(); url.setScheme("http"); url.setHost("bar"); url.set("a", "b"); assertEquals(NO_PATH, url.build()); } public void testBuild_noUserInfo() { GenericUrl url = new GenericUrl(NO_PATH); assertNull(url.getUserInfo()); } public void testBuild_noScheme() { GenericUrl url = new GenericUrl(); try { url.build(); fail("expected " + NullPointerException.class); } catch (NullPointerException e) { // expected } } public void testBuild_noHost() { GenericUrl url = new GenericUrl(); try { url.setScheme("http"); url.build(); fail("expected " + NullPointerException.class); } catch (NullPointerException e) { // expected } } public void testParse_noPath() { GenericUrl url = new GenericUrl(NO_PATH); assertEquals("http", url.getScheme()); assertEquals("bar", url.getHost()); assertEquals("b", url.getFirst("a")); assertNull(url.getPathParts()); } private static final String SHORT_PATH = "http://bar/path?a=b"; private static final List<String> SHORT_PATH_PARTS = Arrays.asList("", "path"); public void testBuild_shortPath() { GenericUrl url = new GenericUrl(); url.setScheme("http"); url.setHost("bar"); url.setPathParts(SHORT_PATH_PARTS); url.set("a", "b"); assertEquals(SHORT_PATH, url.build()); } public void testParse_shortPath() { GenericUrl url = new GenericUrl(SHORT_PATH); assertEquals("http", url.getScheme()); assertEquals("bar", url.getHost()); assertEquals(SHORT_PATH_PARTS, url.getPathParts()); assertEquals("b", url.getFirst("a")); } private static final String LONG_PATH = "http://bar/path/to/resource?a=b"; private static final List<String> LONG_PATH_PARTS = Arrays.asList("", "path", "to", "resource"); public void testBuild_longPath() { GenericUrl url = new GenericUrl(); url.setScheme("http"); url.setHost("bar"); url.setPathParts(LONG_PATH_PARTS); url.set("a", "b"); assertEquals(LONG_PATH, url.build()); } public void testParse_longPath() { GenericUrl url = new GenericUrl(LONG_PATH); assertEquals("http", url.getScheme()); assertEquals("bar", url.getHost()); assertEquals(LONG_PATH_PARTS, url.getPathParts()); assertEquals("b", url.getFirst("a")); } public static class TestUrl extends GenericUrl { @Key String foo; public String hidden; public TestUrl() { } public TestUrl(String encodedUrl) { super(encodedUrl); } } private static final String FULL = "https://user:%3Cpa&$w%40rd%3E@www.google.com:223/m8/feeds/contacts/" + "someone=%23%25&%20%3F%3Co%3E%7B%7D@gmail.com/" + "full?" + "foo=bar&" + "alt=json&" + "max-results=3&" + "prettyprint=true&" + "q=Go%3D%23/%25%26%20?%3Co%3Egle#%3CD@WNL:ADING%3E"; private static final List<String> FULL_PARTS = Arrays.asList("", "m8", "feeds", "contacts", "someone=#%& ?<o>{}@gmail.com", "full"); private static final String USER_INFO = "user:<pa&$w@rd>"; private static final String FRAGMENT = "<D@WNL:ADING>"; public void testBuild_full() { TestUrl url = new TestUrl(); url.setScheme("https"); url.setHost("www.google.com"); url.setPort(223); url.setPathParts(FULL_PARTS); url.set("alt", "json") .set("max-results", 3).set("prettyprint", true).set("q", "Go=#/%& ?<o>gle"); url.foo = "bar"; url.hidden = "invisible"; url.setFragment(FRAGMENT); url.setUserInfo(USER_INFO); assertEquals(FULL, url.build()); } public void testParse_full() { TestUrl url = new TestUrl(FULL); subtestFull(url); assertNull(url.hidden); assertEquals("bar", url.get("foo")); assertEquals("bar", url.foo); } public void testConstructor_url() throws MalformedURLException { GenericUrl url = new GenericUrl(new URL(FULL)); subtestFull(url); } public void testConstructor_uri() throws URISyntaxException { GenericUrl url = new GenericUrl(new URI(FULL)); subtestFull(url); } public void testConstructor_string() { GenericUrl url = new GenericUrl(FULL); subtestFull(url); } public void testConstructor_schemeToLowerCase() throws URISyntaxException, MalformedURLException { GenericUrl url = new GenericUrl("HTTps://www.google.com:223"); assertEquals("https", url.getScheme()); url = new GenericUrl(new URI("HTTPS://www.google.com:223")); assertEquals("https", url.getScheme()); url = new GenericUrl(new URL("hTTPs://www.google.com:223")); assertEquals("https", url.getScheme()); } private void subtestFull(GenericUrl url) { assertEquals("https", url.getScheme()); assertEquals("www.google.com", url.getHost()); assertEquals(223, url.getPort()); assertEquals(FULL_PARTS, url.getPathParts()); assertEquals("json", url.getFirst("alt")); assertEquals("3", url.getFirst("max-results")); assertEquals("true", url.getFirst("prettyprint")); assertEquals("Go=#/%& ?<o>gle", url.getFirst("q")); assertEquals("bar", url.getFirst("foo")); assertEquals(FRAGMENT, url.getFragment()); assertEquals(USER_INFO, url.getUserInfo()); } public static class FieldTypesUrl extends GenericUrl { @Key Boolean B; @Key Double D; @Key Integer I; @Key boolean b; @Key double d; @Key int i; @Key String s; String hidden; FieldTypesUrl() { } FieldTypesUrl(String encodedUrl) { super(encodedUrl); } @Override public FieldTypesUrl set(String fieldName, Object value) { return (FieldTypesUrl) super.set(fieldName, value); } } private static final String FIELD_TYPES = "http://bar?B=true&D=-3.14&I=-3&b=true&d=-3.14&i=-3&s=a&a=b"; public void testBuild_fieldTypes() { FieldTypesUrl url = new FieldTypesUrl(); url.setScheme("http"); url.setHost("bar"); url.set("a", "b"); url.B = true; url.D = -3.14; url.I = -3; url.b = true; url.d = -3.14; url.i = -3; url.s = "a"; url.hidden = "notHere"; assertEquals(FIELD_TYPES, url.build()); } public void testParse_fieldTypes() { FieldTypesUrl url = new FieldTypesUrl(FIELD_TYPES); assertEquals("http", url.getScheme()); assertEquals("bar", url.getHost()); assertEquals("b", url.getFirst("a")); assertNull(url.hidden); assertEquals(true, url.b); assertEquals(Boolean.TRUE, url.B); assertEquals(-3.14d, url.d, 1e-5d); assertEquals(-3.14d, url.D.doubleValue(), 1e-5d); assertEquals(-3, url.i); assertEquals(-3, url.I.intValue()); assertEquals("a", url.s); } private static final String FRAGMENT1 = "http://bar/path/to/resource#fragme=%23/%25&%20?%3Co%3Ent"; public void testBuild_fragment1() { GenericUrl url = new GenericUrl(); url.setScheme("http"); url.setHost("bar"); url.setPathParts(LONG_PATH_PARTS); url.setFragment("fragme=#/%& ?<o>nt"); assertEquals(FRAGMENT1, url.build()); } public void testParse_fragment1() { GenericUrl url = new GenericUrl(FRAGMENT1); assertEquals("http", url.getScheme()); assertEquals("bar", url.getHost()); assertEquals(LONG_PATH_PARTS, url.getPathParts()); assertEquals("fragme=#/%& ?<o>nt", url.getFragment()); } private static final String FRAGMENT2 = "http://bar/path/to/resource?a=b#fragment"; public void testBuild_fragment2() { GenericUrl url = new GenericUrl(); url.setScheme("http"); url.setHost("bar"); url.setPathParts(LONG_PATH_PARTS); url.set("a", "b"); url.setFragment("fragment"); assertEquals(FRAGMENT2, url.build()); } public void testParse_fragment2() { GenericUrl url = new GenericUrl(FRAGMENT2); assertEquals("http", url.getScheme()); assertEquals("bar", url.getHost()); assertEquals(LONG_PATH_PARTS, url.getPathParts()); assertEquals("b", url.getFirst("a")); assertEquals("fragment", url.getFragment()); } public void testBuildAuthority_exception() { // Test without a scheme. GenericUrl url = new GenericUrl(); url.setHost("example.com"); try { url.buildAuthority(); Assert.fail("no exception was thrown"); } catch (NullPointerException expected) { } // Test without a host. url = new GenericUrl(); url.setScheme("https"); try { url.buildAuthority(); Assert.fail("no exception was thrown"); } catch (NullPointerException expected) { } } public void testBuildAuthority_simple() { GenericUrl url = new GenericUrl(); url.setScheme("http"); url.setHost("example.com"); assertEquals("http://example.com", url.buildAuthority()); } public void testBuildAuthority_withPort() { GenericUrl url = new GenericUrl(); url.setScheme("http"); url.setHost("example.com"); url.setPort(1234); assertEquals("http://example.com:1234", url.buildAuthority()); } public void testBuildAuthority_withUserInfo() { GenericUrl url = new GenericUrl(); url.setScheme("http"); url.setHost("www.example.com"); url.setUserInfo("first.last:pa@@"); assertEquals("http://first.last:pa%40%40@www.example.com", url.buildAuthority()); } public void testBuildRelativeUrl_empty() { GenericUrl url = new GenericUrl(); url.setScheme("foo"); url.setHost("bar"); url.setRawPath(""); assertEquals("", url.buildRelativeUrl()); } public void testBuildRelativeUrl_simple() { GenericUrl url = new GenericUrl(); url.setScheme("foo"); url.setHost("bar"); url.setRawPath("/example"); assertEquals("/example", url.buildRelativeUrl()); } public void testBuildRelativeUrl_simpleQuery() { GenericUrl url = new GenericUrl(); url.setScheme("foo"); url.setHost("bar"); url.setRawPath("/example"); url.put("key", "value"); assertEquals("/example?key=value", url.buildRelativeUrl()); } public void testBuildRelativeUrl_fragment() { GenericUrl url = new GenericUrl(); url.setScheme("foo"); url.setHost("bar"); url.setRawPath("/example"); url.setFragment("test"); assertEquals("/example#test", url.buildRelativeUrl()); } public void testBuildRelativeUrl_onlyQuery() { GenericUrl url = new GenericUrl(); url.setScheme("foo"); url.setHost("bar"); url.setRawPath(""); url.put("key", "value"); assertEquals("?key=value", url.buildRelativeUrl()); } private static final String BASE_URL = "http://google.com"; private static final String FULL_PATH = "/some/path/someone%2Fis%2F@gmail.com/test/?one=1&two=2"; public void testBuildRelativeUrl_full() { GenericUrl url = new GenericUrl(BASE_URL + FULL_PATH); assertEquals(FULL_PATH, url.buildRelativeUrl()); } private static final String PATH_WITH_SLASH = "http://www.google.com/m8/feeds/contacts/someone%2Fis%2F@gmail.com/full/"; private static final List<String> PATH_WITH_SLASH_PARTS = Arrays.asList("", "m8", "feeds", "contacts", "someone/is/@gmail.com", "full", ""); public void testBuild_pathWithSlash() { GenericUrl url = new GenericUrl(); url.setScheme("http"); url.setHost("www.google.com"); url.setPathParts(PATH_WITH_SLASH_PARTS); assertEquals(PATH_WITH_SLASH, url.build()); } public void testConstructorUnderscore() { String url = "http://url_with_underscore.google.com"; GenericUrl parsed = new GenericUrl(url); assertEquals("url_with_underscore.google.com", parsed.getHost()); } public void testParse_pathWithSlash() { GenericUrl url = new GenericUrl(PATH_WITH_SLASH); assertEquals("http", url.getScheme()); assertEquals("www.google.com", url.getHost()); assertEquals(PATH_WITH_SLASH_PARTS, url.getPathParts()); } public void testToPathParts() { subtestToPathParts(null, (String[]) null); subtestToPathParts(null, ""); subtestToPathParts("/", "", ""); subtestToPathParts("a", "a"); subtestToPathParts("/a", "", "a"); subtestToPathParts("/a/", "", "a", ""); subtestToPathParts("path/to/resource", "path", "to", "resource"); subtestToPathParts("/path/to/resource", "", "path", "to", "resource"); subtestToPathParts("/path/to/resource/", "", "path", "to", "resource", ""); subtestToPathParts("/Go%3D%23%2F%25%26%20?%3Co%3Egle/2nd", "", "Go=#/%& ?<o>gle", "2nd"); } private void subtestToPathParts(String encodedPath, String... expectedDecodedParts) { List<String> result = GenericUrl.toPathParts(encodedPath); if (encodedPath == null) { assertNull(result); } else { assertEquals(Arrays.asList(expectedDecodedParts), result); } } public void testAppendPath() { GenericUrl url = new GenericUrl("http://google.com"); assertNull(url.getPathParts()); url.appendRawPath(null); assertNull(url.getPathParts()); url.appendRawPath(""); assertNull(url.getPathParts()); url.appendRawPath("/"); assertEquals(Arrays.asList("", ""), url.getPathParts()); url.appendRawPath("/"); assertEquals(Arrays.asList("", "", ""), url.getPathParts()); url.appendRawPath("/a"); assertEquals(Arrays.asList("", "", "", "a"), url.getPathParts()); url.appendRawPath("b"); assertEquals(Arrays.asList("", "", "", "ab"), url.getPathParts()); url.appendRawPath("c/d"); assertEquals(Arrays.asList("", "", "", "abc", "d"), url.getPathParts()); url.appendRawPath("/e"); assertEquals(Arrays.asList("", "", "", "abc", "d", "e"), url.getPathParts()); url.appendRawPath("/"); assertEquals(Arrays.asList("", "", "", "abc", "d", "e", ""), url.getPathParts()); } private static final String PREFIX = "https://www.googleapis.com"; private static final String REPEATED_PARAM_PATH = "/latitude/v1/location"; private static final List<String> REPEATED_PARAM_PATH_PARTS = Arrays.asList("", "latitude", "v1", "location"); private static final String REPEATED_PARAM = PREFIX + REPEATED_PARAM_PATH + "?q=c&q=a&q=b&s=e"; public void testRepeatedParam_build() { GenericUrl url = new GenericUrl(); url.setScheme("https"); url.setHost("www.googleapis.com"); url.setPathParts(REPEATED_PARAM_PATH_PARTS); url.set("q", Arrays.asList("c", "a", "b")); url.set("s", "e"); assertEquals(REPEATED_PARAM, url.build()); } public void testRepeatedParam_parse() { GenericUrl url = new GenericUrl(REPEATED_PARAM); assertEquals("https", url.getScheme()); assertEquals("www.googleapis.com", url.getHost()); assertEquals(REPEATED_PARAM_PATH_PARTS, url.getPathParts()); assertEquals("c", url.getFirst("q")); assertEquals("e", url.getFirst("s")); assertEquals(Arrays.asList("e"), url.get("s")); Collection<?> q = (Collection<?>) url.get("q"); Iterator<?> i = q.iterator(); assertEquals("c", i.next()); assertEquals("a", i.next()); assertEquals("b", i.next()); assertFalse(i.hasNext()); assertEquals(Arrays.asList("c", "a", "b"), new ArrayList<Object>(url.getAll("q"))); } public void testBuild_noValue() { GenericUrl url = new GenericUrl(); url.setScheme("https"); url.setHost("www.googleapis.com"); url.setRawPath(REPEATED_PARAM_PATH); url.set("noval", ""); assertEquals(PREFIX + REPEATED_PARAM_PATH + "?noval", url.build()); } public void testClone() { GenericUrl url = new GenericUrl("http://www.google.com"); GenericUrl clone = url.clone(); assertEquals("http://www.google.com", clone.build()); } public void testToUrl_relative() { // relative redirect testRedirectUtility("http://www.google.com/test", "http://www.google.com", "/test"); testRedirectUtility("http://www.google.com/test", "http://www.google.com/foo/bar/", "/test"); testRedirectUtility("http://www.google.com/test", "http://www.google.com", "test"); testRedirectUtility("http://www.google.com/test", "http://www.google.com/foo", "test"); testRedirectUtility("http://www.google.com/foo/test", "http://www.google.com/foo/", "test"); testRedirectUtility("http://www.google.com/foo/test", "http://www.google.com/foo/bar", "test"); testRedirectUtility( "http://www.google.com/foo/test/", "http://www.google.com/foo/bar", "test/"); testRedirectUtility( "http://www.google.com/foo/test/sub", "http://www.google.com/foo/bar", "test/sub"); // absolute redirect testRedirectUtility( "https://example.com/test", "http://www.google.com/foo", "https://example.com/test"); testRedirectUtility( "https://example.com/test", "http://www.google.com", "https://example.com/test"); testRedirectUtility( "https://example.com/test", "http://www.google.com/", "https://example.com/test"); } private void testRedirectUtility(String expectedResult, String url, String relative) { GenericUrl gu = new GenericUrl(url); GenericUrl redirectedUrl = new GenericUrl(gu.toURL(relative)); assertEquals(expectedResult, redirectedUrl.toString()); } }