package test.codec.http2.model; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; import static org.junit.Assume.assumeNoException; import static org.junit.Assume.assumeNotNull; import java.net.URI; import java.net.URISyntaxException; import java.util.Arrays; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; import com.firefly.codec.http2.model.HttpURI; @RunWith(Parameterized.class) public class HttpURIParseTest { @Parameters(name = "{0}") public static List<String[]> data() { String[][] tests = { // Nothing but path { "path", null, null, "-1", "path", null, null, null }, { "path/path", null, null, "-1", "path/path", null, null, null }, { "%65ncoded/path", null, null, "-1", "%65ncoded/path", null, null, null }, // Basic path reference { "/path/to/context", null, null, "-1", "/path/to/context", null, null, null }, // Basic with encoded query { "http://example.com/path/to/context;param?query=%22value%22#fragment", "http", "example.com", "-1", "/path/to/context;param", "param", "query=%22value%22", "fragment" }, { "http://[::1]/path/to/context;param?query=%22value%22#fragment", "http", "[::1]", "-1", "/path/to/context;param", "param", "query=%22value%22", "fragment" }, // Basic with parameters and query { "http://example.com:8080/path/to/context;param?query=%22value%22#fragment", "http", "example.com", "8080", "/path/to/context;param", "param", "query=%22value%22", "fragment" }, { "http://[::1]:8080/path/to/context;param?query=%22value%22#fragment", "http", "[::1]", "8080", "/path/to/context;param", "param", "query=%22value%22", "fragment" }, // Path References { "/path/info", null, null, null, "/path/info", null, null, null }, { "/path/info#fragment", null, null, null, "/path/info", null, null, "fragment" }, { "/path/info?query", null, null, null, "/path/info", null, "query", null }, { "/path/info?query#fragment", null, null, null, "/path/info", null, "query", "fragment" }, { "/path/info;param", null, null, null, "/path/info;param", "param", null, null }, { "/path/info;param#fragment", null, null, null, "/path/info;param", "param", null, "fragment" }, { "/path/info;param?query", null, null, null, "/path/info;param", "param", "query", null }, { "/path/info;param?query#fragment", null, null, null, "/path/info;param", "param", "query", "fragment" }, // Protocol Less (aka scheme-less) URIs { "//host/path/info", null, "host", null, "/path/info", null, null, null }, { "//user@host/path/info", null, "host", null, "/path/info", null, null, null }, { "//user@host:8080/path/info", null, "host", "8080", "/path/info", null, null, null }, { "//host:8080/path/info", null, "host", "8080", "/path/info", null, null, null }, // Host Less { "http:/path/info", "http", null, null, "/path/info", null, null, null }, { "http:/path/info#fragment", "http", null, null, "/path/info", null, null, "fragment" }, { "http:/path/info?query", "http", null, null, "/path/info", null, "query", null }, { "http:/path/info?query#fragment", "http", null, null, "/path/info", null, "query", "fragment" }, { "http:/path/info;param", "http", null, null, "/path/info;param", "param", null, null }, { "http:/path/info;param#fragment", "http", null, null, "/path/info;param", "param", null, "fragment" }, { "http:/path/info;param?query", "http", null, null, "/path/info;param", "param", "query", null }, { "http:/path/info;param?query#fragment", "http", null, null, "/path/info;param", "param", "query", "fragment" }, // Everything and the kitchen sink { "http://user@host:8080/path/info;param?query#fragment", "http", "host", "8080", "/path/info;param", "param", "query", "fragment" }, { "xxxxx://user@host:8080/path/info;param?query#fragment", "xxxxx", "host", "8080", "/path/info;param", "param", "query", "fragment" }, // No host, parameter with no content { "http:///;?#", "http", null, null, "/;", "", "", "" }, // Path with query that has no value { "/path/info?a=?query", null, null, null, "/path/info", null, "a=?query", null }, // Path with query alt syntax { "/path/info?a=;query", null, null, null, "/path/info", null, "a=;query", null }, // URI with host character {"/@path/info",null,null,null,"/@path/info",null,null,null}, {"/user@path/info",null,null,null,"/user@path/info",null,null,null}, {"//user@host/info",null,"host",null,"/info",null,null,null}, {"//@host/info",null,"host",null,"/info",null,null,null}, {"@host/info",null,null,null,"@host/info",null,null,null}, // Scheme-less, with host and port (overlapping with path) { "//host:8080//", null, "host", "8080", "//", null, null, null }, // File reference { "file:///path/info", "file", null, null, "/path/info", null, null, null }, { "file:/path/info", "file", null, null, "/path/info", null, null, null }, // Bad URI (no scheme, no host, no path) { "//", null, null, null, null, null, null, null }, // Simple localhost references { "http://localhost/", "http", "localhost", null, "/", null, null, null }, { "http://localhost:8080/", "http", "localhost", "8080", "/", null, null, null }, { "http://localhost/?x=y", "http", "localhost", null, "/", null, "x=y", null }, // Simple path with parameter { "/;param", null, null, null, "/;param", "param", null, null }, { ";param", null, null, null, ";param", "param", null, null }, // Simple path with query { "/?x=y", null, null, null, "/", null, "x=y", null }, { "/?abc=test", null, null, null, "/", null, "abc=test", null }, // Simple path with fragment { "/#fragment", null, null, null, "/", null, null, "fragment" }, // Simple IPv4 host with port (default path) { "http://192.0.0.1:8080/", "http", "192.0.0.1", "8080", "/", null, null, null }, // Simple IPv6 host with port (default path) { "http://[2001:db8::1]:8080/", "http", "[2001:db8::1]", "8080", "/", null, null, null }, // IPv6 authenticated host with port (default path) { "http://user@[2001:db8::1]:8080/", "http", "[2001:db8::1]", "8080", "/", null, null, null }, // Simple IPv6 host no port (default path) { "http://[2001:db8::1]/", "http", "[2001:db8::1]", null, "/", null, null, null }, // Scheme-less IPv6, host with port (default path) { "//[2001:db8::1]:8080/", null, "[2001:db8::1]", "8080", "/", null, null, null }, // Interpreted as relative path of "*" (no // host/port/scheme/query/fragment) { "*", null, null, null, "*", null, null, null }, // Path detection Tests (seen from JSP/JSTL and <c:url> use { "http://host:8080/path/info?q1=v1&q2=v2", "http", "host", "8080", "/path/info", null, "q1=v1&q2=v2", null }, { "/path/info?q1=v1&q2=v2", null, null, null, "/path/info", null, "q1=v1&q2=v2", null }, { "/info?q1=v1&q2=v2", null, null, null, "/info", null, "q1=v1&q2=v2", null }, { "info?q1=v1&q2=v2", null, null, null, "info", null, "q1=v1&q2=v2", null }, { "info;q1=v1?q2=v2", null, null, null, "info;q1=v1", "q1=v1", "q2=v2", null }, // Path-less, query only (seen from JSP/JSTL and <c:url> use { "?q1=v1&q2=v2", null, null, null, "", null, "q1=v1&q2=v2", null } }; return Arrays.asList(tests); } @Parameter(0) public String input; @Parameter(1) public String scheme; @Parameter(2) public String host; @Parameter(3) public String port; @Parameter(4) public String path; @Parameter(5) public String param; @Parameter(6) public String query; @Parameter(7) public String fragment; @Test public void testParseString() throws Exception { HttpURI httpUri = new HttpURI(input); try { new URI(input); // URI is valid (per java.net.URI parsing) // Test case sanity check assertThat("[" + input + "] expected path (test case) cannot be null", path, notNullValue()); // Assert expectations assertThat("[" + input + "] .scheme", httpUri.getScheme(), is(scheme)); assertThat("[" + input + "] .host", httpUri.getHost(), is(host)); assertThat("[" + input + "] .port", httpUri.getPort(), is(port == null ? -1 : Integer.parseInt(port))); assertThat("[" + input + "] .path", httpUri.getPath(), is(path)); assertThat("[" + input + "] .param", httpUri.getParam(), is(param)); assertThat("[" + input + "] .query", httpUri.getQuery(), is(query)); assertThat("[" + input + "] .fragment", httpUri.getFragment(), is(fragment)); assertThat("[" + input + "] .toString", httpUri.toString(), is(input)); } catch (URISyntaxException e) { // Assert HttpURI values for invalid URI (such as "//") assertThat("[" + input + "] .scheme", httpUri.getScheme(), is(nullValue())); assertThat("[" + input + "] .host", httpUri.getHost(), is(nullValue())); assertThat("[" + input + "] .port", httpUri.getPort(), is(-1)); assertThat("[" + input + "] .path", httpUri.getPath(), is(nullValue())); assertThat("[" + input + "] .param", httpUri.getParam(), is(nullValue())); assertThat("[" + input + "] .query", httpUri.getQuery(), is(nullValue())); assertThat("[" + input + "] .fragment", httpUri.getFragment(), is(nullValue())); } } @Test public void testParseURI() throws Exception { URI javaUri = null; try { javaUri = new URI(input); assumeNotNull(javaUri); } catch (URISyntaxException e) { // Ignore, as URI is invalid anyway assumeNoException(e); } HttpURI httpUri = new HttpURI(javaUri); assertThat("[" + input + "] .scheme", httpUri.getScheme(), is(scheme)); assertThat("[" + input + "] .host", httpUri.getHost(), is(host)); assertThat("[" + input + "] .port", httpUri.getPort(), is(port == null ? -1 : Integer.parseInt(port))); assertThat("[" + input + "] .path", httpUri.getPath(), is(path)); assertThat("[" + input + "] .param", httpUri.getParam(), is(param)); assertThat("[" + input + "] .query", httpUri.getQuery(), is(query)); assertThat("[" + input + "] .fragment", httpUri.getFragment(), is(fragment)); assertThat("[" + input + "] .toString", httpUri.toString(), is(input)); } @Test public void testCompareToJavaNetURI() throws Exception { URI javaUri = null; try { javaUri = new URI(input); assumeNotNull(javaUri); } catch (URISyntaxException e) { // Ignore, as URI is invalid anyway assumeNoException(e); } HttpURI httpUri = new HttpURI(javaUri); assertThat("[" + input + "] .scheme", httpUri.getScheme(), is(javaUri.getScheme())); assertThat("[" + input + "] .host", httpUri.getHost(), is(javaUri.getHost())); assertThat("[" + input + "] .port", httpUri.getPort(), is(javaUri.getPort())); assertThat("[" + input + "] .path", httpUri.getPath(), is(javaUri.getRawPath())); // Not Relevant for java.net.URI -- assertThat("["+input+"] .param", // httpUri.getParam(), is(param)); assertThat("[" + input + "] .query", httpUri.getQuery(), is(javaUri.getRawQuery())); assertThat("[" + input + "] .fragment", httpUri.getFragment(), is(javaUri.getFragment())); assertThat("[" + input + "] .toString", httpUri.toString(), is(javaUri.toASCIIString())); } }