You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2016/08/27 19:48:55 UTC

[07/14] incubator-juneau git commit: Clean up test and test resource class names.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/PathsTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/PathsTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/PathsTest.java
new file mode 100755
index 0000000..9a01e93
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/PathsTest.java
@@ -0,0 +1,1368 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.juneau.server;
+
+import static org.junit.Assert.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.client.*;
+import org.apache.juneau.json.*;
+import org.junit.*;
+
+public class PathsTest {
+
+	private static String URL = "/testPaths";
+
+	//====================================================================================================
+	// Basic tests
+	//====================================================================================================
+	@Test
+	public void testBasic() throws Exception {
+		RestClient client = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+		ObjectMap r;
+		String url;
+
+		// [/test/testPaths]
+		//	{
+		//		pathInfo:null,
+		//		pathInfoUndecoded:null,
+		//		pathInfoParts:[],
+		//		pathRemainder:null,
+		//		pathRemainderUndecoded:null,
+		//		requestURI:'/jazz/juneau/test/testPaths',
+		//		requestParentURI:'/jazz/juneau/test',
+		//		requestURL:'https://localhost:9443/jazz/juneau/test/testPaths',
+		//		servletPath:'/juneau/test/testPaths',
+		//		relativeServletURI:'/jazz/juneau/test/testPaths',
+		//		pathRemainder2:null
+		//	}
+		url = URL;
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertNull(r.getString("pathInfo"));
+		assertNull(r.getString("pathInfoUndecoded"));
+		assertEquals("[]", r.getObjectList("pathInfoParts").toString());
+		assertNull(r.getString("pathRemainder"));
+		assertNull(r.getString("pathRemainderUndecoded"));
+		assertNull(r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths"));
+		assertTrue(r.getString("requestParentURI").endsWith("/"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(1, (int)r.getInt("method"));
+
+
+		// [/test/testPaths/]
+		//		{
+		//			pathInfo: '/',
+		//			pathInfoUndecoded: '/',
+		//			pathInfoParts: [
+		//			],
+		//			pathRemainder: '',
+		//			pathRemainderUndecoded: '',
+		//			requestURI: '/jazz/juneau/test/testPaths/',
+		//			requestParentURI: '/jazz/juneau/test',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/',
+		//			servletPath: '/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: ''
+		//		}
+		url = URL + '/';
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/", r.getString("pathInfo"));
+		assertEquals("/", r.getString("pathInfoUndecoded"));
+		assertEquals("[]", r.getObjectList("pathInfoParts").toString());
+		assertEquals("", r.getString("pathRemainder"));
+		assertEquals("", r.getString("pathRemainderUndecoded"));
+		assertEquals("", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/"));
+		assertTrue(r.getString("requestParentURI").endsWith("/"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(1, (int)r.getInt("method"));
+
+		// [/test/testPaths//]
+		//		{
+		//			pathInfo: '//',
+		//			pathInfoParts: [''],
+		//			pathRemainder: '/',
+		//			requestURI: '/jazz/juneau/test/testPaths//',
+		//			requestParentURI: '/jazz/juneau/test',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths//',
+		//			servletPath: '/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: '/'
+		//		}
+		url = URL + "//";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("//", r.getString("pathInfo"));
+		assertEquals("['']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("/", r.getString("pathRemainder"));
+		assertEquals("/", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths//"));
+		assertTrue(r.getString("requestParentURI").endsWith("/"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths//"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(1, (int)r.getInt("method"));
+
+		// [/test/testPaths///]
+		//		{
+		//			pathInfo: '///',
+		//			pathInfoParts: ['',''],
+		//			pathRemainder: '//',
+		//			requestURI: '/jazz/juneau/test/testPaths///',
+		//			requestParentURI: '/jazz/juneau/test',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths///',
+		//			servletPath: '/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: '//'
+		//		}
+		url = URL + "///";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("///", r.getString("pathInfo"));
+		assertEquals("['','']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("//", r.getString("pathRemainder"));
+		assertEquals("//", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths///"));
+		assertTrue(r.getString("requestParentURI").endsWith("/"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths///"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(1, (int)r.getInt("method"));
+
+		// [/test/testPaths/foo/bar]
+		//		{
+		//			pathInfo: '/foo/bar',
+		//			pathInfoParts: [
+		//				'foo',
+		//				'bar'
+		//			],
+		//			pathRemainder: 'foo/bar',
+		//			requestURI: '/jazz/juneau/test/testPaths/foo/bar',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/foo',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/foo/bar',
+		//			servletPath: '/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: 'foo/bar'
+		//		}
+		url = URL + "/foo/bar";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/foo/bar", r.getString("pathInfo"));
+		assertEquals("['foo','bar']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("foo/bar", r.getString("pathRemainder"));
+		assertEquals("foo/bar", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/foo/bar"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/foo"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/foo/bar"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(1, (int)r.getInt("method"));
+
+		// [/test/testPaths/foo/bar/]
+		//		{
+		//			pathInfo: '/foo/bar/',
+		//			pathInfoParts: [
+		//				'foo',
+		//				'bar'
+		//			],
+		//			pathRemainder: 'foo/bar/',
+		//			requestURI: '/jazz/juneau/test/testPaths/foo/bar/',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/foo',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/foo/bar/',
+		//			servletPath: '/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: 'foo/bar/'
+		//		}
+		url = URL + "/foo/bar/";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/foo/bar/", r.getString("pathInfo"));
+		assertEquals("['foo','bar']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("foo/bar/", r.getString("pathRemainder"));
+		assertEquals("foo/bar/", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/foo/bar/"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/foo"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/foo/bar/"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(1, (int)r.getInt("method"));
+
+		// [/test/testPaths//foo//bar//]
+		//		{
+		//			pathInfo: '//foo//bar//',
+		//			pathInfoParts: [
+		//				'',
+		//				'foo',
+		//				'',
+		//				'bar',
+		//				''
+		//			],
+		//			pathRemainder: '/foo//bar//',
+		//			requestURI: '/jazz/juneau/test/testPaths//foo//bar//',
+		//			requestParentURI: '/jazz/juneau/test/testPaths//foo',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths//foo//bar//',
+		//			servletPath: '/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: '/foo//bar//'
+		//		}
+		url = URL + "//foo//bar//";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("//foo//bar//", r.getString("pathInfo"));
+		assertEquals("['','foo','','bar','']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("/foo//bar//", r.getString("pathRemainder"));
+		assertEquals("/foo//bar//", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths//foo//bar//"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths//foo/"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths//foo//bar//"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(1, (int)r.getInt("method"));
+
+		// [/test/testPaths/foo%2Fbar]
+		//		{
+		//			pathInfo: '/foo//bar',
+		//			pathInfoUndecoded: '/foo%2F%2Fbar',
+		//			pathInfoParts: [
+		//				'foo//bar'
+		//			],
+		//			pathRemainder: 'foo//bar',
+		//			pathRemainderUndecoded: 'foo%2F%2Fbar',
+		//			requestURI: '/jazz/juneau/test/testPaths/foo%2F%2Fbar',
+		//			requestParentURI: '/jazz/juneau/test/testPaths',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/foo%2F%2Fbar',
+		//			servletPath: '/juneau/test/testPaths',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: 'foo//bar',
+		//			method: 1
+		//		}
+		url = URL + "/foo%2F%2Fbar";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/foo//bar", r.getString("pathInfo"));
+		assertEquals("/foo%2F%2Fbar", r.getString("pathInfoUndecoded"));
+		assertEquals("['foo//bar']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("foo//bar", r.getString("pathRemainder"));
+		assertEquals("foo%2F%2Fbar", r.getString("pathRemainderUndecoded"));
+		assertEquals("foo//bar", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/foo%2F%2Fbar"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/foo%2F%2Fbar"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(1, (int)r.getInt("method"));
+
+		// [/test/testPaths//foo%2Fbar//]
+		//		{
+		//			pathInfo: '//foo//bar//',
+		//			pathInfoUndecoded: '//foo%2F%2Fbar//',
+		//			pathInfoParts: [
+		//				'',
+		//				'foo//bar',
+		//				''
+		//			],
+		//			pathRemainder: '/foo//bar//',
+		//			pathRemainderUndecoded: '/foo%2F%2Fbar//',
+		//			requestURI: '/jazz/juneau/test/testPaths//foo%2F%2Fbar//',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths//foo%2F%2Fbar//',
+		//			servletPath: '/juneau/test/testPaths',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: '/foo//bar//',
+		//			method: 1
+		//		}
+		url = URL + "//foo%2F%2Fbar//";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("//foo//bar//", r.getString("pathInfo"));
+		assertEquals("//foo%2F%2Fbar//", r.getString("pathInfoUndecoded"));
+		assertEquals("['','foo//bar','']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("/foo//bar//", r.getString("pathRemainder"));
+		assertEquals("/foo%2F%2Fbar//", r.getString("pathRemainderUndecoded"));
+		assertEquals("/foo//bar//", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths//foo%2F%2Fbar//"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths//foo%2F%2Fbar//"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(1, (int)r.getInt("method"));
+
+		// [/test/testPaths/test2]
+		//		{
+		//			pathInfo: '/test2',
+		//			pathInfoParts: [
+		//				'test2'
+		//			],
+		//			pathRemainder: null,
+		//			requestURI: '/jazz/juneau/test/testPaths/test2',
+		//			requestParentURI: '/jazz/juneau/test/testPaths',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/test2',
+		//			servletPath: '/juneau/test/testPaths',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: null,
+		//			method: 2
+		//		}
+		url = URL + "/test2";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2", r.getString("pathInfo"));
+		assertEquals("['test2']", r.getObjectList("pathInfoParts").toString());
+		assertNull(r.getString("pathRemainder"));
+		assertNull(r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/test2"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/test2"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(2, (int)r.getInt("method"));
+
+
+		// [/test/testPaths/test2/]
+		//		{
+		//			pathInfo: '/test2/',
+		//			pathInfoParts: [
+		//				'test2'
+		//			],
+		//			pathRemainder: '',
+		//			requestURI: '/jazz/juneau/test/testPaths/test2/',
+		//			requestParentURI: '/jazz/juneau/test/testPaths',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/test2/',
+		//			servletPath: '/juneau/test/testPaths',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: '',
+		//			method: 2
+		//		}
+		url = URL + "/test2/";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2/", r.getString("pathInfo"));
+		assertEquals("['test2']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("", r.getString("pathRemainder"));
+		assertEquals("", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/test2/"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/test2/"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(2, (int)r.getInt("method"));
+
+		// [/test/testPaths/test2//]
+		//		{
+		//			pathInfo: '/test2//',
+		//			pathInfoParts: [
+		//				'test2',
+		//				''
+		//			],
+		//			pathRemainder: '/',
+		//			requestURI: '/jazz/juneau/test/testPaths/test2//',
+		//			requestParentURI: '/jazz/juneau/test/testPaths',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/test2//',
+		//			servletPath: '/juneau/test/testPaths',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: '/',
+		//			method: 2
+		//		}
+		url = URL + "/test2//";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2//", r.getString("pathInfo"));
+		assertEquals("['test2','']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("/", r.getString("pathRemainder"));
+		assertEquals("/", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/test2//"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/test2//"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(2, (int)r.getInt("method"));
+
+		// [/test/testPaths/test2///]
+		//		{
+		//			pathInfo: '/test2///',
+		//			pathInfoParts: [
+		//				'test2',
+		//				'',
+		//				''
+		//			],
+		//			pathRemainder: '//',
+		//			requestURI: '/jazz/juneau/test/testPaths/test2///',
+		//			requestParentURI: '/jazz/juneau/test/testPaths',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/test2///',
+		//			servletPath: '/juneau/test/testPaths',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: '//',
+		//			method: 2
+		//		}
+		url = URL + "/test2///";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2///", r.getString("pathInfo"));
+		assertEquals("['test2','','']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("//", r.getString("pathRemainder"));
+		assertEquals("//", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/test2///"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/test2///"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(2, (int)r.getInt("method"));
+
+		// [/test/testPaths/test2/foo/bar]
+		//		{
+		//			pathInfo: '/test2/foo/bar',
+		//			pathInfoParts: [
+		//				'test2',
+		//				'foo',
+		//				'bar'
+		//			],
+		//			pathRemainder: 'foo/bar',
+		//			requestURI: '/jazz/juneau/test/testPaths/test2/foo/bar',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/test2/foo',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/test2/foo/bar',
+		//			servletPath: '/juneau/test/testPaths',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: 'foo/bar',
+		//			method: 2
+		//		}
+		url = URL + "/test2/foo/bar";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2/foo/bar", r.getString("pathInfo"));
+		assertEquals("['test2','foo','bar']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("foo/bar", r.getString("pathRemainder"));
+		assertEquals("foo/bar", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/test2/foo/bar"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/test2/foo"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/test2/foo/bar"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(2, (int)r.getInt("method"));
+
+		// [/test/testPaths/test2/foo/bar/]
+		//		{
+		//			pathInfo: '/test2/foo/bar/',
+		//			pathInfoParts: [
+		//				'test2',
+		//				'foo',
+		//				'bar'
+		//			],
+		//			pathRemainder: 'foo/bar/',
+		//			requestURI: '/jazz/juneau/test/testPaths/test2/foo/bar/',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/test2/foo',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/test2/foo/bar/',
+		//			servletPath: '/juneau/test/testPaths',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: 'foo/bar/',
+		//			method: 2
+		//		}
+		url = URL + "/test2/foo/bar/";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2/foo/bar/", r.getString("pathInfo"));
+		assertEquals("['test2','foo','bar']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("foo/bar/", r.getString("pathRemainder"));
+		assertEquals("foo/bar/", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/test2/foo/bar/"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/test2/foo"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/test2/foo/bar/"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(2, (int)r.getInt("method"));
+
+		// [/test/testPaths/test2//foo//bar//]
+		//		{
+		//			pathInfo: '/test2//foo//bar//',
+		//			pathInfoParts: [
+		//				'test2',
+		//				'',
+		//				'foo',
+		//				'',
+		//				'bar',
+		//				''
+		//			],
+		//			pathRemainder: '/foo//bar//',
+		//			requestURI: '/jazz/juneau/test/testPaths/test2//foo//bar//',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/test2//foo/',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/test2//foo//bar//',
+		//			servletPath: '/juneau/test/testPaths',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: '/foo//bar//',
+		//			method: 2
+		//		}
+		url = URL + "/test2//foo//bar//";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2//foo//bar//", r.getString("pathInfo"));
+		assertEquals("['test2','','foo','','bar','']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("/foo//bar//", r.getString("pathRemainder"));
+		assertEquals("/foo//bar//", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/test2//foo//bar//"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/test2//foo/"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/test2//foo//bar//"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(2, (int)r.getInt("method"));
+
+		// [/test/testPaths/test2/foo%2Fbar]
+		//		{
+		//			pathInfo: '/test2/foo//bar',
+		//			pathInfoUndecoded: '/test2/foo%2F%2Fbar',
+		//			pathInfoParts: [
+		//				'test2',
+		//				'foo//bar'
+		//			],
+		//			pathRemainder: 'foo//bar',
+		//			pathRemainderUndecoded: 'foo%2F%2Fbar',
+		//			requestURI: '/jazz/juneau/test/testPaths/test2/foo%2F%2Fbar',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/test2',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/test2/foo%2F%2Fbar',
+		//			servletPath: '/juneau/test/testPaths',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: 'foo//bar',
+		//			method: 2
+		//		}
+		url = URL + "/test2/foo%2F%2Fbar";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2/foo//bar", r.getString("pathInfo"));
+		assertEquals("/test2/foo%2F%2Fbar", r.getString("pathInfoUndecoded"));
+		assertEquals("['test2','foo//bar']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("foo//bar", r.getString("pathRemainder"));
+		assertEquals("foo%2F%2Fbar", r.getString("pathRemainderUndecoded"));
+		assertEquals("foo//bar", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/test2/foo%2F%2Fbar"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/test2"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/test2/foo%2F%2Fbar"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(2, (int)r.getInt("method"));
+
+		// [/test/testPaths/test2//foo%2Fbar//]
+		//		{
+		//			pathInfo: '/test2//foo//bar//',
+		//			pathInfoUndecoded: '/test2//foo%2F%2Fbar//',
+		//			pathInfoParts: [
+		//				'test2',
+		//				'',
+		//				'foo//bar',
+		//				''
+		//			],
+		//			pathRemainder: '/foo//bar//',
+		//			pathRemainderUndecoded: '/foo%2F%2Fbar//',
+		//			requestURI: '/jazz/juneau/test/testPaths/test2//foo%2F%2Fbar//',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/test2/',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/test2//foo%2F%2Fbar//',
+		//			servletPath: '/juneau/test/testPaths',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths',
+		//			pathRemainder2: '/foo//bar//',
+		//			method: 2
+		//		}
+		url = URL + "/test2//foo%2F%2Fbar//";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2//foo//bar//", r.getString("pathInfo"));
+		assertEquals("/test2//foo%2F%2Fbar//", r.getString("pathInfoUndecoded"));
+		assertEquals("['test2','','foo//bar','']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("/foo//bar//", r.getString("pathRemainder"));
+		assertEquals("/foo%2F%2Fbar//", r.getString("pathRemainderUndecoded"));
+		assertEquals("/foo//bar//", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/test2//foo%2F%2Fbar//"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/test2/"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/test2//foo%2F%2Fbar//"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(2, (int)r.getInt("method"));
+
+		// [/test/testPaths/a]
+		//		{
+		//			pathInfo: null,
+		//			pathInfoParts: [
+		//			],
+		//			pathRemainder: null,
+		//			requestURI: '/jazz/juneau/test/testPaths/a',
+		//			requestParentURI: '/jazz/juneau/test/testPaths',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: null,
+		//			method: 3
+		//		}
+		url = URL + "/a";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertNull(r.getString("pathInfo"));
+		assertEquals("[]", r.getObjectList("pathInfoParts").toString());
+		assertNull(r.getString("pathRemainder"));
+		assertNull(r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(3, (int)r.getInt("method"));
+
+		// [/test/testPaths/a/]
+		//		{
+		//			pathInfo: '/',
+		//			pathInfoParts: [
+		//			],
+		//			pathRemainder: '',
+		//			requestURI: '/jazz/juneau/test/testPaths/a/',
+		//			requestParentURI: '/jazz/juneau/test/testPaths',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a/',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: '',
+		//			method: 3
+		//		}
+		url = URL + "/a/";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/", r.getString("pathInfo"));
+		assertEquals("[]", r.getObjectList("pathInfoParts").toString());
+		assertEquals("", r.getString("pathRemainder"));
+		assertEquals("", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(3, (int)r.getInt("method"));
+
+		// [/test/testPaths/a//]
+		//		{
+		//			pathInfo: '//',
+		//			pathInfoParts: [
+		//				''
+		//			],
+		//			pathRemainder: '/',
+		//			requestURI: '/jazz/juneau/test/testPaths/a//',
+		//			requestParentURI: '/jazz/juneau/test/testPaths',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a//',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: '/',
+		//			method: 3
+		//		}
+		url = URL + "/a//";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("//", r.getString("pathInfo"));
+		assertEquals("['']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("/", r.getString("pathRemainder"));
+		assertEquals("/", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a//"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a//"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(3, (int)r.getInt("method"));
+
+		// [/test/testPaths/a///]
+		//		{
+		//			pathInfo: '///',
+		//			pathInfoParts: [
+		//				'',
+		//				''
+		//			],
+		//			pathRemainder: '//',
+		//			requestURI: '/jazz/juneau/test/testPaths/a///',
+		//			requestParentURI: '/jazz/juneau/test/testPaths',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a///',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: '//',
+		//			method: 3
+		//		}
+		url = URL + "/a///";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("///", r.getString("pathInfo"));
+		assertEquals("['','']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("//", r.getString("pathRemainder"));
+		assertEquals("//", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a///"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a///"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(3, (int)r.getInt("method"));
+
+		// [/test/testPaths/a/foo/bar]
+		//		{
+		//			pathInfo: '/foo/bar',
+		//			pathInfoParts: [
+		//				'foo',
+		//				'bar'
+		//			],
+		//			pathRemainder: 'foo/bar',
+		//			requestURI: '/jazz/juneau/test/testPaths/a/foo/bar',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/a/foo',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a/foo/bar',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: 'foo/bar',
+		//			method: 3
+		//		}
+		url = URL + "/a/foo/bar";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/foo/bar", r.getString("pathInfo"));
+		assertEquals("['foo','bar']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("foo/bar", r.getString("pathRemainder"));
+		assertEquals("foo/bar", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/foo/bar"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a/foo"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/foo/bar"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(3, (int)r.getInt("method"));
+
+		// [/test/testPaths/a/foo/bar/]
+		//		{
+		//			pathInfo: '/foo/bar/',
+		//			pathInfoParts: [
+		//				'foo',
+		//				'bar'
+		//			],
+		//			pathRemainder: 'foo/bar/',
+		//			requestURI: '/jazz/juneau/test/testPaths/a/foo/bar/',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/a/foo',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a/foo/bar/',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: 'foo/bar/',
+		//			method: 3
+		//		}
+		url = URL + "/a/foo/bar/";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/foo/bar/", r.getString("pathInfo"));
+		assertEquals("['foo','bar']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("foo/bar/", r.getString("pathRemainder"));
+		assertEquals("foo/bar/", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/foo/bar/"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a/foo"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/foo/bar/"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(3, (int)r.getInt("method"));
+
+		// [/test/testPaths/a//foo//bar//]
+		//		{
+		//			pathInfo: '//foo//bar//',
+		//			pathInfoParts: [
+		//				'',
+		//				'foo',
+		//				'',
+		//				'bar',
+		//				''
+		//			],
+		//			pathRemainder: '/foo//bar//',
+		//			requestURI: '/jazz/juneau/test/testPaths/a//foo//bar//',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/a//foo/',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a//foo//bar//',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: '/foo//bar//',
+		//			method: 3
+		//		}
+		url = URL + "/a//foo//bar//";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("//foo//bar//", r.getString("pathInfo"));
+		assertEquals("['','foo','','bar','']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("/foo//bar//", r.getString("pathRemainder"));
+		assertEquals("/foo//bar//", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a//foo//bar//"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a//foo/"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a//foo//bar//"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(3, (int)r.getInt("method"));
+
+		// [/test/testPaths/a/foo%2Fbar]
+		//		{
+		//			pathInfo: '/foo//bar',
+		//			pathInfoUndecoded: '/foo%2F%2Fbar',
+		//			pathInfoParts: [
+		//				'foo//bar'
+		//			],
+		//			pathRemainder: 'foo//bar',
+		//			pathRemainderUndecoded: 'foo%2F%2Fbar',
+		//			requestURI: '/jazz/juneau/test/testPaths/a/foo%2F%2Fbar',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/a',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a/foo%2F%2Fbar',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: 'foo//bar',
+		//			method: 3
+		//		}
+		url = URL + "/a/foo%2F%2Fbar";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/foo//bar", r.getString("pathInfo"));
+		assertEquals("/foo%2F%2Fbar", r.getString("pathInfoUndecoded"));
+		assertEquals("['foo//bar']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("foo//bar", r.getString("pathRemainder"));
+		assertEquals("foo%2F%2Fbar", r.getString("pathRemainderUndecoded"));
+		assertEquals("foo//bar", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/foo%2F%2Fbar"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/foo%2F%2Fbar"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(3, (int)r.getInt("method"));
+
+		// [/test/testPaths/a//foo%2Fbar//]
+		//		{
+		//			pathInfo: '//foo//bar//',
+		//			pathInfoUndecoded: '//foo%2F%2Fbar//',
+		//			pathInfoParts: [
+		//				'',
+		//				'foo//bar',
+		//				''
+		//			],
+		//			pathRemainder: '/foo//bar//',
+		//			pathRemainderUndecoded: '/foo%2F%2Fbar//',
+		//			requestURI: '/jazz/juneau/test/testPaths/a//foo%2F%2Fbar//',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/a/',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a//foo%2F%2Fbar//',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: '/foo//bar//',
+		//			method: 3
+		//		}
+		url = URL + "/a//foo%2F%2Fbar//";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("//foo//bar//", r.getString("pathInfo"));
+		assertEquals("//foo%2F%2Fbar//", r.getString("pathInfoUndecoded"));
+		assertEquals("['','foo//bar','']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("/foo//bar//", r.getString("pathRemainder"));
+		assertEquals("/foo%2F%2Fbar//", r.getString("pathRemainderUndecoded"));
+		assertEquals("/foo//bar//", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a//foo%2F%2Fbar//"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a/"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a//foo%2F%2Fbar//"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(3, (int)r.getInt("method"));
+
+
+		// [/test/testPaths/a/test2]
+		//		{
+		//			pathInfo: '/test2',
+		//			pathInfoParts: [
+		//				'test2'
+		//			],
+		//			pathRemainder: null,
+		//			requestURI: '/jazz/juneau/test/testPaths/a/test2',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/a',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a/test2',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: null,
+		//			method: 4
+		//		}
+		url = URL + "/a/test2";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2", r.getString("pathInfo"));
+		assertEquals("['test2']", r.getObjectList("pathInfoParts").toString());
+		assertNull(r.getString("pathRemainder"));
+		assertNull(r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/test2"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/test2"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(4, (int)r.getInt("method"));
+
+		// [/test/testPaths/a/test2/]
+		//		{
+		//			pathInfo: '/test2/',
+		//			pathInfoParts: [
+		//				'test2'
+		//			],
+		//			pathRemainder: '',
+		//			requestURI: '/jazz/juneau/test/testPaths/a/test2/',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/a',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a/test2/',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: '',
+		//			method: 4
+		//		}
+		url = URL + "/a/test2/";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2/", r.getString("pathInfo"));
+		assertEquals("['test2']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("", r.getString("pathRemainder"));
+		assertEquals("", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/test2/"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/test2/"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(4, (int)r.getInt("method"));
+
+		// [/test/testPaths/a/test2//]
+		//		{
+		//			pathInfo: '/test2//',
+		//			pathInfoParts: [
+		//				'test2',
+		//				''
+		//			],
+		//			pathRemainder: '/',
+		//			requestURI: '/jazz/juneau/test/testPaths/a/test2//',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/a',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a/test2//',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: '/',
+		//			method: 4
+		//		}
+		url = URL + "/a/test2//";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2//", r.getString("pathInfo"));
+		assertEquals("['test2','']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("/", r.getString("pathRemainder"));
+		assertEquals("/", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/test2//"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/test2//"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(4, (int)r.getInt("method"));
+
+		// [/test/testPaths/a/test2///]
+		//		{
+		//			pathInfo: '/test2///',
+		//			pathInfoParts: [
+		//				'test2',
+		//				'',
+		//				''
+		//			],
+		//			pathRemainder: '//',
+		//			requestURI: '/jazz/juneau/test/testPaths/a/test2///',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/a',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a/test2///',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: '//',
+		//			method: 4
+		//		}
+		url = URL + "/a/test2///";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2///", r.getString("pathInfo"));
+		assertEquals("['test2','','']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("//", r.getString("pathRemainder"));
+		assertEquals("//", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/test2///"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/test2///"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(4, (int)r.getInt("method"));
+
+		// [/test/testPaths/a/test2/foo/bar]
+		//		{
+		//			pathInfo: '/test2/foo/bar',
+		//			pathInfoParts: [
+		//				'test2',
+		//				'foo',
+		//				'bar'
+		//			],
+		//			pathRemainder: 'foo/bar',
+		//			requestURI: '/jazz/juneau/test/testPaths/a/test2/foo/bar',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/a/test2/foo',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a/test2/foo/bar',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: 'foo/bar',
+		//			method: 4
+		//		}
+		url = URL + "/a/test2/foo/bar";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2/foo/bar", r.getString("pathInfo"));
+		assertEquals("['test2','foo','bar']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("foo/bar", r.getString("pathRemainder"));
+		assertEquals("foo/bar", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/test2/foo/bar"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a/test2/foo"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/test2/foo/bar"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(4, (int)r.getInt("method"));
+
+		// [/test/testPaths/a/test2/foo/bar/]
+		//		{
+		//			pathInfo: '/test2/foo/bar/',
+		//			pathInfoParts: [
+		//				'test2',
+		//				'foo',
+		//				'bar'
+		//			],
+		//			pathRemainder: 'foo/bar/',
+		//			requestURI: '/jazz/juneau/test/testPaths/a/test2/foo/bar/',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/a/test2/foo',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a/test2/foo/bar/',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: 'foo/bar/',
+		//			method: 4
+		//		}
+		url = URL + "/a/test2/foo/bar/";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2/foo/bar/", r.getString("pathInfo"));
+		assertEquals("['test2','foo','bar']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("foo/bar/", r.getString("pathRemainder"));
+		assertEquals("foo/bar/", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/test2/foo/bar/"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a/test2/foo"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/test2/foo/bar/"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(4, (int)r.getInt("method"));
+
+		// [/test/testPaths/a/test2//foo//bar//]
+		//		{
+		//			pathInfo: '/test2//foo//bar//',
+		//			pathInfoParts: [
+		//				'test2',
+		//				'',
+		//				'foo',
+		//				'',
+		//				'bar',
+		//				''
+		//			],
+		//			pathRemainder: '/foo//bar//',
+		//			requestURI: '/jazz/juneau/test/testPaths/a/test2//foo//bar//',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/a/test2//foo/',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a/test2//foo//bar//',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: '/foo//bar//',
+		//			method: 4
+		//		}
+		url = URL + "/a/test2//foo//bar//";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2//foo//bar//", r.getString("pathInfo"));
+		assertEquals("['test2','','foo','','bar','']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("/foo//bar//", r.getString("pathRemainder"));
+		assertEquals("/foo//bar//", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/test2//foo//bar//"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a/test2//foo/"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/test2//foo//bar//"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(4, (int)r.getInt("method"));
+
+		// [/test/testPaths/a/test2/foo%2Fbar]
+		//		{
+		//			pathInfo: '/test2/foo//bar',
+		//			pathInfoUndecoded: '/test2/foo%2F%2Fbar',
+		//			pathInfoParts: [
+		//				'test2',
+		//				'foo//bar'
+		//			],
+		//			pathRemainder: 'foo//bar',
+		//			pathRemainderUndecoded: 'foo%2F%2Fbar',
+		//			requestURI: '/jazz/juneau/test/testPaths/a/test2/foo%2F%2Fbar',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/a/test2',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a/test2/foo%2F%2Fbar',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: 'foo//bar',
+		//			method: 4
+		//		}
+		url = URL + "/a/test2/foo%2F%2Fbar";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2/foo//bar", r.getString("pathInfo"));
+		assertEquals("/test2/foo%2F%2Fbar", r.getString("pathInfoUndecoded"));
+		assertEquals("['test2','foo//bar']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("foo//bar", r.getString("pathRemainder"));
+		assertEquals("foo%2F%2Fbar", r.getString("pathRemainderUndecoded"));
+		assertEquals("foo//bar", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/test2/foo%2F%2Fbar"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a/test2"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/test2/foo%2F%2Fbar"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(4, (int)r.getInt("method"));
+
+		// [/test/testPaths/a/test2//foo%2Fbar//]
+		//		{
+		//			pathInfo: '/test2//foo//bar//',
+		//			pathInfoUndecoded: '/test2//foo%2F%2Fbar//',
+		//			pathInfoParts: [
+		//				'test2',
+		//				'',
+		//				'foo//bar',
+		//				''
+		//			],
+		//			pathRemainder: '/foo//bar//',
+		//			pathRemainderUndecoded: '/foo%2F%2Fbar//',
+		//			requestURI: '/jazz/juneau/test/testPaths/a/test2//foo%2F%2Fbar//',
+		//			requestParentURI: '/jazz/juneau/test/testPaths/a/test2/',
+		//			requestURL: 'https://localhost:9443/jazz/juneau/test/testPaths/a/test2//foo%2F%2Fbar//',
+		//			servletPath: '/juneau/test/testPaths/a',
+		//			servletURI: 'https://localhost:9443/jazz/juneau/test/testPaths/a',
+		//			servletParentURI: 'https://localhost:9443/jazz/juneau/test/testPaths',
+		//			relativeServletURI: '/jazz/juneau/test/testPaths/a',
+		//			pathRemainder2: '/foo//bar//',
+		//			method: 4
+		//		}
+		url = URL + "/a/test2//foo%2F%2Fbar//";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2//foo//bar//", r.getString("pathInfo"));
+		assertEquals("/test2//foo%2F%2Fbar//", r.getString("pathInfoUndecoded"));
+		assertEquals("['test2','','foo//bar','']", r.getObjectList("pathInfoParts").toString());
+		assertEquals("/foo//bar//", r.getString("pathRemainder"));
+		assertEquals("/foo%2F%2Fbar//", r.getString("pathRemainderUndecoded"));
+		assertEquals("/foo//bar//", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/test2//foo%2F%2Fbar//"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a/test2/"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/test2//foo%2F%2Fbar//"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(4, (int)r.getInt("method"));
+
+		//--------------------------------------------------------------------------------
+		// Spaces
+		//--------------------------------------------------------------------------------
+		url = URL + "/%20";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/ ", r.getString("pathInfo"));
+		assertEquals("/%20", r.getString("pathInfoUndecoded"));
+		assertEquals("[' ']", r.getObjectList("pathInfoParts").toString());
+		assertEquals(" ", r.getString("pathRemainder"));
+		assertEquals("%20", r.getString("pathRemainderUndecoded"));
+		assertEquals(" ", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/%20"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/%20"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(1, (int)r.getInt("method"));
+
+		url = URL + "/test2/%20";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2/ ", r.getString("pathInfo"));
+		assertEquals("/test2/%20", r.getString("pathInfoUndecoded"));
+		assertEquals("['test2',' ']", r.getObjectList("pathInfoParts").toString());
+		assertEquals(" ", r.getString("pathRemainder"));
+		assertEquals("%20", r.getString("pathRemainderUndecoded"));
+		assertEquals(" ", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/test2/%20"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/test2"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/test2/%20"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(2, (int)r.getInt("method"));
+
+		url = URL + "/a/%20";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/ ", r.getString("pathInfo"));
+		assertEquals("/%20", r.getString("pathInfoUndecoded"));
+		assertEquals("[' ']", r.getObjectList("pathInfoParts").toString());
+		assertEquals(" ", r.getString("pathRemainder"));
+		assertEquals("%20", r.getString("pathRemainderUndecoded"));
+		assertEquals(" ", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/%20"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/%20"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(3, (int)r.getInt("method"));
+
+		url = URL + "/a/test2/%20";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2/ ", r.getString("pathInfo"));
+		assertEquals("/test2/%20", r.getString("pathInfoUndecoded"));
+		assertEquals("['test2',' ']", r.getObjectList("pathInfoParts").toString());
+		assertEquals(" ", r.getString("pathRemainder"));
+		assertEquals("%20", r.getString("pathRemainderUndecoded"));
+		assertEquals(" ", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/test2/%20"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a/test2"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/test2/%20"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(4, (int)r.getInt("method"));
+
+		url = URL + "/+";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/ ", r.getString("pathInfo"));
+		assertEquals("/+", r.getString("pathInfoUndecoded"));
+		assertEquals("[' ']", r.getObjectList("pathInfoParts").toString());
+		assertEquals(" ", r.getString("pathRemainder"));
+		assertEquals("+", r.getString("pathRemainderUndecoded"));
+		assertEquals(" ", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/+"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/+"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(1, (int)r.getInt("method"));
+
+		url = URL + "/test2/+";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2/ ", r.getString("pathInfo"));
+		assertEquals("/test2/+", r.getString("pathInfoUndecoded"));
+		assertEquals("['test2',' ']", r.getObjectList("pathInfoParts").toString());
+		assertEquals(" ", r.getString("pathRemainder"));
+		assertEquals("+", r.getString("pathRemainderUndecoded"));
+		assertEquals(" ", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/test2/+"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/test2"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/test2/+"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths"));
+		assertEquals(2, (int)r.getInt("method"));
+
+		url = URL + "/a/+";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/ ", r.getString("pathInfo"));
+		assertEquals("/+", r.getString("pathInfoUndecoded"));
+		assertEquals("[' ']", r.getObjectList("pathInfoParts").toString());
+		assertEquals(" ", r.getString("pathRemainder"));
+		assertEquals("+", r.getString("pathRemainderUndecoded"));
+		assertEquals(" ", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/+"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/+"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(3, (int)r.getInt("method"));
+
+		url = URL + "/a/test2/+";
+		r = client.doGet(url).getResponse(ObjectMap.class);
+		assertEquals("/test2/ ", r.getString("pathInfo"));
+		assertEquals("/test2/+", r.getString("pathInfoUndecoded"));
+		assertEquals("['test2',' ']", r.getObjectList("pathInfoParts").toString());
+		assertEquals(" ", r.getString("pathRemainder"));
+		assertEquals("+", r.getString("pathRemainderUndecoded"));
+		assertEquals(" ", r.getString("pathRemainder2"));
+		assertTrue(r.getString("requestURI").endsWith("/testPaths/a/test2/+"));
+		assertTrue(r.getString("requestParentURI").endsWith("/testPaths/a/test2"));
+		assertTrue(r.getString("requestURL").endsWith("/testPaths/a/test2/+"));
+		assertTrue(r.getString("servletPath").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletURI").endsWith("/testPaths/a"));
+		assertTrue(r.getString("servletParentURI").endsWith("/testPaths"));
+		assertTrue(r.getString("relativeServletURI").endsWith("/testPaths/a"));
+		assertEquals(4, (int)r.getInt("method"));
+
+		client.closeQuietly();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/PropertiesTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/PropertiesTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/PropertiesTest.java
new file mode 100755
index 0000000..388367c
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/PropertiesTest.java
@@ -0,0 +1,48 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.juneau.server;
+
+import static org.junit.Assert.*;
+
+import org.apache.juneau.client.*;
+import org.apache.juneau.json.*;
+import org.junit.*;
+
+public class PropertiesTest {
+
+	private static String URL = "/testProperties";
+
+	//====================================================================================================
+	// Properties defined on method.
+	//====================================================================================================
+	@Test
+	public void testPropertiesDefinedOnMethod() throws Exception {
+		RestClient client = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+		String r = client.doGet(URL + "/testPropertiesDefinedOnMethod").getResponseAsString();
+		assertTrue(r.matches("A1=a1,A2=c,B1=b1,B2=c,C=c,R1a=.*/testProperties/testPropertiesDefinedOnMethod,R1b=.*/testProperties,R2=bar,R3=baz,R4=a1,R5=c,R6=c"));
+
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Make sure attributes/parameters/headers are available through ctx.getProperties().
+	//====================================================================================================
+	@Test
+	public void testProperties() throws Exception {
+		RestClient client = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+		String r = client.doGet(URL + "/testProperties/a1?P=p1").setHeader("H", "h1").getResponseAsString();
+		assertEquals("A=a1,P=p1,H=h1", r);
+
+		client.closeQuietly();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/RestClientTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/RestClientTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/RestClientTest.java
new file mode 100755
index 0000000..d801033
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/RestClientTest.java
@@ -0,0 +1,199 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.juneau.server;
+
+import static org.apache.juneau.server.TestUtils.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+import java.util.regex.*;
+
+import org.apache.http.entity.*;
+import org.apache.juneau.client.*;
+import org.apache.juneau.json.*;
+import org.junit.*;
+
+public class RestClientTest {
+
+	private static String URL = "/testRestClient";
+
+	//====================================================================================================
+	// successPattern()
+	//====================================================================================================
+	@Test
+	public void testSuccessPattern() throws Exception {
+		RestClient c = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+		String r;
+		int rc;
+
+		r = c.doPost(URL, new StringEntity("xxxSUCCESSxxx")).successPattern("SUCCESS").getResponseAsString();
+		assertEquals("xxxSUCCESSxxx", r);
+		rc = c.doPost(URL, new StringEntity("xxxSUCCESSxxx")).successPattern("SUCCESS").run();
+		assertEquals(200, rc);
+
+		try {
+			r = c.doPost(URL, new StringEntity("xxxFAILURExxx")).successPattern("SUCCESS").getResponseAsString();
+			fail();
+		} catch (RestCallException e) {
+			assertEquals("Success pattern not detected.", e.getLocalizedMessage());
+		}
+
+		c.closeQuietly();
+	}
+
+	//====================================================================================================
+	// failurePattern()
+	//====================================================================================================
+	@Test
+	public void testFailurePattern() throws Exception {
+		RestClient c = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+		String r;
+		int rc;
+
+		r = c.doPost(URL, new StringEntity("xxxSUCCESSxxx")).failurePattern("FAILURE").getResponseAsString();
+		assertEquals("xxxSUCCESSxxx", r);
+		rc = c.doPost(URL, new StringEntity("xxxSUCCESSxxx")).failurePattern("FAILURE").run();
+		assertEquals(200, rc);
+
+		try {
+			r = c.doPost(URL, new StringEntity("xxxFAILURExxx")).failurePattern("FAILURE").getResponseAsString();
+			fail();
+		} catch (RestCallException e) {
+			assertEquals("Failure pattern detected.", e.getLocalizedMessage());
+		}
+
+		try {
+			r = c.doPost(URL, new StringEntity("xxxERRORxxx")).failurePattern("FAILURE|ERROR").getResponseAsString();
+			fail();
+		} catch (RestCallException e) {
+			assertEquals("Failure pattern detected.", e.getLocalizedMessage());
+		}
+
+		c.closeQuietly();
+	}
+
+	//====================================================================================================
+	// captureResponse()/getCapturedResponse()
+	//====================================================================================================
+	@Test
+	public void testCaptureResponse() throws Exception {
+		RestClient c = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+		RestCall rc = c.doPost(URL, new StringEntity("xxx")).captureResponse();
+
+		try {
+			rc.getCapturedResponse();
+			fail();
+		} catch (IllegalStateException e) {
+			assertEquals("This method cannot be called until the response has been consumed.", e.getLocalizedMessage());
+		}
+		rc.run();
+		assertEquals("xxx", rc.getCapturedResponse());
+		assertEquals("xxx", rc.getCapturedResponse());
+
+		rc = c.doPost(URL, new StringEntity("xxx")).captureResponse();
+		assertEquals("xxx", rc.getResponseAsString());
+		assertEquals("xxx", rc.getCapturedResponse());
+		assertEquals("xxx", rc.getCapturedResponse());
+
+		try {
+			rc.getResponseAsString();
+			fail();
+		} catch (IllegalStateException e) {
+			assertEquals("Method cannot be called.  Response has already been consumed.", e.getLocalizedMessage());
+		}
+
+		c.closeQuietly();
+	}
+
+	//====================================================================================================
+	// addResponsePattern()
+	//====================================================================================================
+	@Test
+	public void testAddResponsePattern() throws Exception {
+		RestClient c = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+		String r;
+
+		final List<String> l = new ArrayList<String>();
+		ResponsePattern p = new ResponsePattern("x=(\\d+),y=(\\S+)") {
+			@Override
+			public void onMatch(RestCall restCall, Matcher m) throws RestCallException {
+				l.add(m.group(1)+'/'+m.group(2));
+			}
+			@Override
+			public void onNoMatch(RestCall restCall) throws RestCallException {
+				throw new RestCallException("Pattern not found!");
+			}
+		};
+
+		r = c.doPost(URL, new StringEntity("x=1,y=2")).addResponsePattern(p).getResponseAsString();
+		assertEquals("x=1,y=2", r);
+		assertObjectEquals("['1/2']", l);
+
+		l.clear();
+
+		r = c.doPost(URL, new StringEntity("x=1,y=2\nx=3,y=4")).addResponsePattern(p).getResponseAsString();
+		assertEquals("x=1,y=2\nx=3,y=4", r);
+		assertObjectEquals("['1/2','3/4']", l);
+
+		try {
+			c.doPost(URL, new StringEntity("x=1")).addResponsePattern(p).run();
+			fail();
+		} catch (RestCallException e) {
+			assertEquals("Pattern not found!", e.getLocalizedMessage());
+			assertEquals(0, e.getResponseCode());
+		}
+
+		// Two patterns!
+		ResponsePattern p1 = new ResponsePattern("x=(\\d+)") {
+			@Override
+			public void onMatch(RestCall restCall, Matcher m) throws RestCallException {
+				l.add("x="+m.group(1));
+			}
+			@Override
+			public void onNoMatch(RestCall restCall) throws RestCallException {
+				throw new RestCallException("Pattern x not found!");
+			}
+		};
+		ResponsePattern p2 = new ResponsePattern("y=(\\S+)") {
+			@Override
+			public void onMatch(RestCall restCall, Matcher m) throws RestCallException {
+				l.add("y="+m.group(1));
+			}
+			@Override
+			public void onNoMatch(RestCall restCall) throws RestCallException {
+				throw new RestCallException("Pattern y not found!");
+			}
+		};
+
+		l.clear();
+		r = c.doPost(URL, new StringEntity("x=1,y=2\nx=3,y=4")).addResponsePattern(p1).addResponsePattern(p2).getResponseAsString();
+		assertEquals("x=1,y=2\nx=3,y=4", r);
+		assertObjectEquals("['x=1','x=3','y=2','y=4']", l);
+
+		try {
+			c.doPost(URL, new StringEntity("x=1\nx=3")).addResponsePattern(p1).addResponsePattern(p2).getResponseAsString();
+		} catch (RestCallException e) {
+			assertEquals("Pattern y not found!", e.getLocalizedMessage());
+			assertEquals(0, e.getResponseCode());
+		}
+
+		try {
+			c.doPost(URL, new StringEntity("y=1\ny=3")).addResponsePattern(p1).addResponsePattern(p2).getResponseAsString();
+		} catch (RestCallException e) {
+			assertEquals("Pattern x not found!", e.getLocalizedMessage());
+			assertEquals(0, e.getResponseCode());
+		}
+
+		c.closeQuietly();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/SerializersTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/SerializersTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/SerializersTest.java
new file mode 100755
index 0000000..95ecf68
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/SerializersTest.java
@@ -0,0 +1,152 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.juneau.server;
+
+import static javax.servlet.http.HttpServletResponse.*;
+import static org.apache.juneau.server.TestUtils.*;
+import static org.junit.Assert.*;
+
+import org.apache.juneau.client.*;
+import org.apache.juneau.json.*;
+import org.junit.*;
+
+public class SerializersTest {
+
+	private static String URL = "/testSerializers";
+	private static boolean debug = false;
+	private static RestClient client;
+
+	@BeforeClass
+	public static void beforeClass() {
+		client = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+	}
+
+	@AfterClass
+	public static void afterClass() {
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Serializer defined on class.
+	//====================================================================================================
+	@Test
+	public void testSerializerOnClass() throws Exception {
+		String url = URL + "/testSerializerOnClass";
+
+		client.setAccept("text/a");
+		String r = client.doGet(url).getResponseAsString();
+		assertEquals("text/a - test1", r);
+
+		try {
+			client.setAccept("text/b");
+			client.doGet(url + "?noTrace=true").getResponseAsString();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
+				"Unsupported media-type in request header 'Accept': 'text/b'",
+				"Supported media-types: [text/a, ");
+		}
+
+		client.setAccept("text/json");
+		r = client.doGet(url).getResponseAsString();
+		assertEquals("\"test1\"", r);
+	}
+
+	//====================================================================================================
+	// Serializer defined on method.
+	//====================================================================================================
+	@Test
+	public void testSerializerOnMethod() throws Exception {
+		String url = URL + "/testSerializerOnMethod";
+
+		try {
+			client.setAccept("text/a");
+			client.doGet(url + "?noTrace=true").getResponseAsString();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
+				"Unsupported media-type in request header 'Accept': 'text/a'",
+				"Supported media-types: [text/b]"
+			);
+		}
+
+		try {
+			client.setAccept("text/json");
+			client.doGet(url + "?noTrace=true").getResponseAsString();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
+				"Unsupported media-type in request header 'Accept': 'text/json'",
+				"Supported media-types: [text/b]"
+			);
+		}
+	}
+
+	//====================================================================================================
+	// Serializer overridden on method.
+	//====================================================================================================
+	@Test
+	public void testSerializerOverriddenOnMethod() throws Exception {
+		String url = URL + "/testSerializerOverriddenOnMethod";
+
+		client.setAccept("text/a");
+		String r = client.doGet(url).getResponseAsString();
+		assertEquals("text/c - test3", r);
+
+		client.setAccept("text/b");
+		r = client.doGet(url).getResponseAsString();
+		assertEquals("text/b - test3", r);
+
+		client.setAccept("text/json");
+		r = client.doGet(url).getResponseAsString();
+		assertEquals("\"test3\"", r);
+	}
+
+	//====================================================================================================
+	// Serializer with different Accept than Content-Type.
+	//====================================================================================================
+	@Test
+	public void testSerializerWithDifferentMediaTypes() throws Exception {
+		String url = URL + "/testSerializerWithDifferentMediaTypes";
+
+		client.setAccept("text/a");
+		String r = client.doGet(url).getResponseAsString();
+		assertEquals("text/d - test4", r);
+
+		client.setAccept("text/d");
+		r = client.doGet(url).getResponseAsString();
+		assertEquals("text/d - test4", r);
+
+		client.setAccept("text/json");
+		r = client.doGet(url).getResponseAsString();
+		assertEquals("\"test4\"", r);
+	}
+
+	//====================================================================================================
+	// Check for valid 406 error response.
+	//====================================================================================================
+	@Test
+	public void test406() throws Exception {
+		String url = URL + "/test406";
+
+		try {
+			client.setAccept("text/bad");
+			client.doGet(url + "?noTrace=true").getResponseAsString();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
+				"Unsupported media-type in request header 'Accept': 'text/bad'",
+				"Supported media-types: [text/a");
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/StaticFilesTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/StaticFilesTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/StaticFilesTest.java
new file mode 100755
index 0000000..8ec05ae
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/StaticFilesTest.java
@@ -0,0 +1,56 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.juneau.server;
+
+import static org.junit.Assert.*;
+
+import org.apache.juneau.client.*;
+import org.apache.juneau.plaintext.*;
+import org.junit.*;
+
+public class StaticFilesTest {
+
+	private static String URL = "/testStaticFiles";
+
+	//====================================================================================================
+	// Tests the @RestResource(staticFiles) annotation.
+	//====================================================================================================
+	@Test
+	public void testXdocs() throws Exception {
+		RestClient client = new TestRestClient(PlainTextSerializer.class, PlainTextParser.class);
+		String r;
+		String url = URL + "/xdocs";
+
+		r = client.doGet(url + "/test.txt").getResponseAsString();
+		assertEquals("OK-1", r);
+		r = client.doGet(url + "/xdocs/test.txt").getResponseAsString();
+		assertEquals("OK-2", r);
+
+		// For security reasons, paths containing ".." should always return 404.
+		try {
+			client.doGet(url + "/xdocs/../test.txt?noTrace=true").connect();
+			fail("404 exception expected");
+		} catch (RestCallException e) {
+			assertEquals(404, e.getResponseCode());
+		}
+
+		try {
+			client.doGet(url + "/xdocs/%2E%2E/test.txt?noTrace=true").connect();
+			fail("404 exception expected");
+		} catch (RestCallException e) {
+			assertEquals(404, e.getResponseCode());
+		}
+
+		client.closeQuietly();
+	}
+}