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 2017/09/02 14:10:46 UTC

[24/51] [partial] incubator-juneau git commit: Add project hierarchies, part 1

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UrlEncodingSerializerTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UrlEncodingSerializerTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UrlEncodingSerializerTest.java
new file mode 100755
index 0000000..8f1ed5a
--- /dev/null
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UrlEncodingSerializerTest.java
@@ -0,0 +1,501 @@
+// ***************************************************************************************************************************
+// * 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.urlencoding;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.utils.*;
+import org.junit.*;
+
+@SuppressWarnings("javadoc")
+public class UrlEncodingSerializerTest {
+
+	static UrlEncodingSerializer s = UrlEncodingSerializer.DEFAULT;
+	static UrlEncodingSerializer sr = UrlEncodingSerializer.DEFAULT_READABLE;
+
+
+	//====================================================================================================
+	// Basic test
+	//====================================================================================================
+	@Test
+	public void testBasic() throws Exception {
+
+		Object t;
+
+		// Simple string
+		// Top level
+		t = "a";
+		assertEquals("_value=a", s.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{a:'a'}");
+		assertEquals("a=a", s.serialize(t));
+		assertEquals("a=a", sr.serialize(t));
+
+		// Simple map
+		// Top level
+		t = new ObjectMap("{a:'b',c:123,d:false,e:true,f:null}");
+		assertEquals("a=b&c=123&d=false&e=true&f=null", s.serialize(t));
+		assertEquals("a=b\n&c=123\n&d=false\n&e=true\n&f=null", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{a:{a:'b',c:123,d:false,e:true,f:null}}");
+		assertEquals("a=(a=b,c=123,d=false,e=true,f=null)", s.serialize(t));
+		assertEquals("a=(\n\ta=b,\n\tc=123,\n\td=false,\n\te=true,\n\tf=null\n)", sr.serialize(t));
+
+		// Simple map with primitives as literals
+		t = new ObjectMap("{a:'b',c:'123',d:'false',e:'true',f:'null'}");
+		assertEquals("a=b&c='123'&d='false'&e='true'&f='null'", s.serialize(t));
+		assertEquals("a=b\n&c='123'\n&d='false'\n&e='true'\n&f='null'", sr.serialize(t));
+
+		// null
+		// Note that serializeParams is always encoded.
+		// Top level
+		t = null;
+		assertEquals("_value=null", s.serialize(t));
+		assertEquals("_value=null", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{null:null}");
+		assertEquals("null=null", s.serialize(t));
+		assertEquals("null=null", sr.serialize(t));
+
+		// 3rd level
+		t = new ObjectMap("{null:{null:null}}");
+		assertEquals("null=(null=null)", s.serialize(t));
+		assertEquals("null=(\n\tnull=null\n)", sr.serialize(t));
+
+		// Empty array
+		// Top level
+		t = new String[0];
+		assertEquals("", s.serialize(t));
+		assertEquals("", sr.serialize(t));
+
+		// 2nd level in map
+		t = new ObjectMap("{x:[]}");
+		assertEquals("x=@()", s.serialize(t));
+		assertEquals("x=@()", sr.serialize(t));
+
+		// Empty 2 dimensional array
+		t = new String[1][0];
+		assertEquals("0=@()", s.serialize(t));
+		assertEquals("0=@()", sr.serialize(t));
+
+		// Array containing empty string
+		// Top level
+		t = new String[]{""};
+		assertEquals("0=''", s.serialize(t));
+		assertEquals("0=''", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{x:['']}");
+		assertEquals("x=@('')", s.serialize(t));
+		assertEquals("x=@(\n\t''\n)", sr.serialize(t));
+
+		// Array containing 3 empty strings
+		t = new String[]{"","",""};
+		assertEquals("0=''&1=''&2=''", s.serialize(t));
+		assertEquals("0=''\n&1=''\n&2=''", sr.serialize(t));
+
+		// String containing \u0000
+		// Top level
+		t = "\u0000";
+		assertEquals("_value=%00", s.serialize(t));
+		assertEquals("_value=%00", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{'\u0000':'\u0000'}");
+		assertEquals("%00=%00", s.serialize(t));
+		assertEquals("%00=%00", sr.serialize(t));
+
+		// Boolean
+		// Top level
+		t = false;
+		assertEquals("_value=false", s.serialize(t));
+		assertEquals("_value=false", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{x:false}");
+		assertEquals("x=false", s.serialize(t));
+		assertEquals("x=false", sr.serialize(t));
+
+		// Number
+		// Top level
+		t = 123;
+		assertEquals("_value=123", s.serialize(t));
+		assertEquals("_value=123", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{x:123}");
+		assertEquals("x=123", s.serialize(t));
+		assertEquals("x=123", sr.serialize(t));
+
+		// Unencoded chars
+		// Top level
+		t = "x;/?:@-_.!*'";
+		assertEquals("_value=x;/?:@-_.!*~'", s.serialize(t));
+		assertEquals("_value=x;/?:@-_.!*~'", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{x:'x;/?:@-_.!*\\''}");
+		assertEquals("x=x;/?:@-_.!*~'", s.serialize(t));
+		assertEquals("x=x;/?:@-_.!*~'", sr.serialize(t));
+
+		// Encoded chars
+		// Top level
+		t = "x{}|\\^[]`<>#%\"&+";
+		assertEquals("_value=x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B", s.serialize(t));
+		assertEquals("_value=x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{'x{}|\\\\^[]`<>#%\"&+':'x{}|\\\\^[]`<>#%\"&+'}");
+		assertEquals("x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B=x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B", s.serialize(t));
+		assertEquals("x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B=x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B", sr.serialize(t));
+
+		// Escaped chars
+		// Top level
+		t = "x$,()~";
+		assertEquals("_value='x$,()~~'", s.serialize(t));
+		assertEquals("_value='x$,()~~'", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{'x$,()~':'x$,()~'}");
+		assertEquals("'x$,()~~'='x$,()~~'", s.serialize(t));
+		assertEquals("'x$,()~~'='x$,()~~'", sr.serialize(t));
+
+		// 3rd level
+		t = new ObjectMap("{'x$,()~':{'x$,()~':'x$,()~'}}");
+		assertEquals("'x$,()~~'=('x$,()~~'='x$,()~~')", s.serialize(t));
+		assertEquals("'x$,()~~'=(\n\t'x$,()~~'='x$,()~~'\n)", sr.serialize(t));
+
+		// Equals sign
+		// Gets encoded at top level, and encoded+escaped at 2nd level.
+		// Top level
+		t = "x=";
+		assertEquals("_value='x='", s.serialize(t));
+		assertEquals("_value='x='", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{'x=':'x='}");
+		assertEquals("'x%3D'='x='", s.serialize(t));
+		assertEquals("'x%3D'='x='", sr.serialize(t));
+
+		// 3rd level
+		t = new ObjectMap("{'x=':{'x=':'x='}}");
+		assertEquals("'x%3D'=('x='='x=')", s.serialize(t));
+		assertEquals("'x%3D'=(\n\t'x='='x='\n)", sr.serialize(t));
+
+		// String starting with parenthesis
+		// Top level
+		t = "()";
+		assertEquals("_value='()'", s.serialize(t));
+		assertEquals("_value='()'", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{'()':'()'}");
+		assertEquals("'()'='()'", s.serialize(t));
+		assertEquals("'()'='()'", sr.serialize(t));
+
+		// String starting with $
+		// Top level
+		t = "$a";
+		assertEquals("_value=$a", s.serialize(t));
+		assertEquals("_value=$a", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{$a:'$a'}");
+		assertEquals("$a=$a", s.serialize(t));
+		assertEquals("$a=$a", sr.serialize(t));
+
+		// Blank string
+		// Top level
+		t = "";
+		assertEquals("_value=''", s.serialize(t));
+		assertEquals("_value=''", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{'':''}");
+		assertEquals("''=''", s.serialize(t));
+		assertEquals("''=''", sr.serialize(t));
+
+		// 3rd level
+		t = new ObjectMap("{'':{'':''}}");
+		assertEquals("''=(''='')", s.serialize(t));
+		assertEquals("''=(\n\t''=''\n)", sr.serialize(t));
+
+		// Newline character
+		// Top level
+		t = "\n";
+		assertEquals("_value='%0A'", s.serialize(t));
+		assertEquals("_value='%0A'", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{'\n':'\n'}");
+		assertEquals("'%0A'='%0A'", s.serialize(t));
+		assertEquals("'%0A'='%0A'", sr.serialize(t));
+
+		// 3rd level
+		t = new ObjectMap("{'\n':{'\n':'\n'}}");
+		assertEquals("'%0A'=('%0A'='%0A')", s.serialize(t));
+		assertEquals("'%0A'=(\n\t'%0A'='%0A'\n)", sr.serialize(t));
+	}
+
+	//====================================================================================================
+	// Unicode characters test
+	//====================================================================================================
+	@Test
+	public void testUnicodeChars() throws Exception {
+		Object t;
+
+		// 2-byte UTF-8 character
+		// Top level
+		t = "¢";
+		assertEquals("_value=%C2%A2", s.serialize(t));
+		assertEquals("_value=%C2%A2", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{'¢':'¢'}");
+		assertEquals("%C2%A2=%C2%A2", s.serialize(t));
+		assertEquals("%C2%A2=%C2%A2", sr.serialize(t));
+
+		// 3rd level
+		t = new ObjectMap("{'¢':{'¢':'¢'}}");
+		assertEquals("%C2%A2=(%C2%A2=%C2%A2)", s.serialize(t));
+		assertEquals("%C2%A2=(\n\t%C2%A2=%C2%A2\n)", sr.serialize(t));
+
+		// 3-byte UTF-8 character
+		// Top level
+		t = "€";
+		assertEquals("_value=%E2%82%AC", s.serialize(t));
+		assertEquals("_value=%E2%82%AC", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{'€':'€'}");
+		assertEquals("%E2%82%AC=%E2%82%AC", s.serialize(t));
+		assertEquals("%E2%82%AC=%E2%82%AC", sr.serialize(t));
+
+		// 3rd level
+		t = new ObjectMap("{'€':{'€':'€'}}");
+		assertEquals("%E2%82%AC=(%E2%82%AC=%E2%82%AC)", s.serialize(t));
+		assertEquals("%E2%82%AC=(\n\t%E2%82%AC=%E2%82%AC\n)", sr.serialize(t));
+
+		// 4-byte UTF-8 character
+		// Top level
+		t = "𤭢";
+		assertEquals("_value=%F0%A4%AD%A2", s.serialize(t));
+		assertEquals("_value=%F0%A4%AD%A2", sr.serialize(t));
+
+		// 2nd level
+		t = new ObjectMap("{'𤭢':'𤭢'}");
+		assertEquals("%F0%A4%AD%A2=%F0%A4%AD%A2", s.serialize(t));
+		assertEquals("%F0%A4%AD%A2=%F0%A4%AD%A2", sr.serialize(t));
+
+		// 3rd level
+		t = new ObjectMap("{'𤭢':{'𤭢':'𤭢'}}");
+		assertEquals("%F0%A4%AD%A2=(%F0%A4%AD%A2=%F0%A4%AD%A2)", s.serialize(t));
+		assertEquals("%F0%A4%AD%A2=(\n\t%F0%A4%AD%A2=%F0%A4%AD%A2\n)", sr.serialize(t));
+	}
+
+	//====================================================================================================
+	// Multi-part parameters on beans via URLENC_expandedParams
+	//====================================================================================================
+	@Test
+	public void testMultiPartParametersOnBeansViaProperty() throws Exception {
+		UrlEncodingSerializer s;
+		DTOs.B t = DTOs.B.create();
+		String r;
+
+		s = UrlEncodingSerializer.DEFAULT;
+		r = s.serialize(t);
+		String e = ""
+			+ "f01=@(a,b)"
+			+ "&f02=@(c,d)"
+			+ "&f03=@(1,2)"
+			+ "&f04=@(3,4)"
+			+ "&f05=@(@(e,f),@(g,h))"
+			+ "&f06=@(@(i,j),@(k,l))"
+			+ "&f07=@((a=a,b=1,c=true),(a=a,b=1,c=true))"
+			+ "&f08=@((a=a,b=1,c=true),(a=a,b=1,c=true))"
+			+ "&f09=@(@((a=a,b=1,c=true)),@((a=a,b=1,c=true)))"
+			+ "&f10=@(@((a=a,b=1,c=true)),@((a=a,b=1,c=true)))"
+			+ "&f11=@(a,b)"
+			+ "&f12=@(c,d)"
+			+ "&f13=@(1,2)"
+			+ "&f14=@(3,4)"
+			+ "&f15=@(@(e,f),@(g,h))"
+			+ "&f16=@(@(i,j),@(k,l))"
+			+ "&f17=@((a=a,b=1,c=true),(a=a,b=1,c=true))"
+			+ "&f18=@((a=a,b=1,c=true),(a=a,b=1,c=true))"
+			+ "&f19=@(@((a=a,b=1,c=true)),@((a=a,b=1,c=true)))"
+			+ "&f20=@(@((a=a,b=1,c=true)),@((a=a,b=1,c=true)))";
+		assertEquals(e, r);
+
+		s = new UrlEncodingSerializerBuilder().expandedParams(true).build();
+		r = s.serialize(t);
+		e = ""
+			+ "f01=a&f01=b"
+			+ "&f02=c&f02=d"
+			+ "&f03=1&f03=2"
+			+ "&f04=3&f04=4"
+			+ "&f05=@(e,f)&f05=@(g,h)"
+			+ "&f06=@(i,j)&f06=@(k,l)"
+			+ "&f07=(a=a,b=1,c=true)&f07=(a=a,b=1,c=true)"
+			+ "&f08=(a=a,b=1,c=true)&f08=(a=a,b=1,c=true)"
+			+ "&f09=@((a=a,b=1,c=true))&f09=@((a=a,b=1,c=true))"
+			+ "&f10=@((a=a,b=1,c=true))&f10=@((a=a,b=1,c=true))"
+			+ "&f11=a&f11=b"
+			+ "&f12=c&f12=d"
+			+ "&f13=1&f13=2"
+			+ "&f14=3&f14=4"
+			+ "&f15=@(e,f)&f15=@(g,h)"
+			+ "&f16=@(i,j)&f16=@(k,l)"
+			+ "&f17=(a=a,b=1,c=true)&f17=(a=a,b=1,c=true)"
+			+ "&f18=(a=a,b=1,c=true)&f18=(a=a,b=1,c=true)"
+			+ "&f19=@((a=a,b=1,c=true))&f19=@((a=a,b=1,c=true))"
+			+ "&f20=@((a=a,b=1,c=true))&f20=@((a=a,b=1,c=true))";
+		assertEquals(e, r);
+	}
+
+
+	//====================================================================================================
+	// Multi-part parameters on beans via @UrlEncoding.expandedParams on class
+	//====================================================================================================
+	@Test
+	public void testMultiPartParametersOnBeansViaAnnotationOnClass() throws Exception {
+		UrlEncodingSerializer s;
+		DTOs.C t = DTOs.C.create();
+		String r;
+
+		s = UrlEncodingSerializer.DEFAULT;
+		r = s.serialize(t);
+		String e = ""
+			+ "f01=a&f01=b"
+			+ "&f02=c&f02=d"
+			+ "&f03=1&f03=2"
+			+ "&f04=3&f04=4"
+			+ "&f05=@(e,f)&f05=@(g,h)"
+			+ "&f06=@(i,j)&f06=@(k,l)"
+			+ "&f07=(a=a,b=1,c=true)&f07=(a=a,b=1,c=true)"
+			+ "&f08=(a=a,b=1,c=true)&f08=(a=a,b=1,c=true)"
+			+ "&f09=@((a=a,b=1,c=true))&f09=@((a=a,b=1,c=true))"
+			+ "&f10=@((a=a,b=1,c=true))&f10=@((a=a,b=1,c=true))"
+			+ "&f11=a&f11=b"
+			+ "&f12=c&f12=d"
+			+ "&f13=1&f13=2"
+			+ "&f14=3&f14=4"
+			+ "&f15=@(e,f)&f15=@(g,h)"
+			+ "&f16=@(i,j)&f16=@(k,l)"
+			+ "&f17=(a=a,b=1,c=true)&f17=(a=a,b=1,c=true)"
+			+ "&f18=(a=a,b=1,c=true)&f18=(a=a,b=1,c=true)"
+			+ "&f19=@((a=a,b=1,c=true))&f19=@((a=a,b=1,c=true))"
+			+ "&f20=@((a=a,b=1,c=true))&f20=@((a=a,b=1,c=true))";
+		assertEquals(e, r);
+
+		s = new UrlEncodingSerializerBuilder().expandedParams(true).build();
+		r = s.serialize(t);
+		e = ""
+			+ "f01=a&f01=b"
+			+ "&f02=c&f02=d"
+			+ "&f03=1&f03=2"
+			+ "&f04=3&f04=4"
+			+ "&f05=@(e,f)&f05=@(g,h)"
+			+ "&f06=@(i,j)&f06=@(k,l)"
+			+ "&f07=(a=a,b=1,c=true)&f07=(a=a,b=1,c=true)"
+			+ "&f08=(a=a,b=1,c=true)&f08=(a=a,b=1,c=true)"
+			+ "&f09=@((a=a,b=1,c=true))&f09=@((a=a,b=1,c=true))"
+			+ "&f10=@((a=a,b=1,c=true))&f10=@((a=a,b=1,c=true))"
+			+ "&f11=a&f11=b"
+			+ "&f12=c&f12=d"
+			+ "&f13=1&f13=2"
+			+ "&f14=3&f14=4"
+			+ "&f15=@(e,f)&f15=@(g,h)"
+			+ "&f16=@(i,j)&f16=@(k,l)"
+			+ "&f17=(a=a,b=1,c=true)&f17=(a=a,b=1,c=true)"
+			+ "&f18=(a=a,b=1,c=true)&f18=(a=a,b=1,c=true)"
+			+ "&f19=@((a=a,b=1,c=true))&f19=@((a=a,b=1,c=true))"
+			+ "&f20=@((a=a,b=1,c=true))&f20=@((a=a,b=1,c=true))";
+		assertEquals(e, r);
+	}
+
+	@Test
+	public void testMultiPartParametersOnMapOfStringArrays() throws Exception {
+		UrlEncodingSerializer s;
+		String r;
+
+		Map<String,String[]> t = new LinkedHashMap<String,String[]>();
+		t.put("f1", new String[]{"bar"});
+		t.put("f2", new String[]{"bar","baz"});
+		t.put("f3", new String[]{});
+		s = UrlEncodingSerializer.DEFAULT_EXPANDED;
+		r = s.serialize(t);
+		String e = "f1=bar&f2=bar&f2=baz";
+		assertEquals(e, r);
+	}
+
+	@Test
+	public void testParseParameterObjectMap() throws Exception {
+		String in = "(name='foo bar')";
+
+		ObjectMap r =  UrlEncodingParser.DEFAULT.parse(PartType.QUERY, in, BeanContext.DEFAULT.createSession().getClassMeta(ObjectMap.class));
+
+		assertEquals("{name:'foo bar'}", JsonSerializer.DEFAULT_LAX.toString(r));
+	}
+
+	//====================================================================================================
+	// Test URLENC_paramFormat == PLAINTEXT.
+	//====================================================================================================
+	@Test
+	public void testPlainTextParams() throws Exception {
+		WriterSerializer s = UrlEncodingSerializer.DEFAULT.builder().plainTextParams().build();
+
+		assertEquals("_value=foo", s.serialize("foo"));
+		assertEquals("_value='foo'", s.serialize("'foo'"));
+		assertEquals("_value=(foo)", s.serialize("(foo)"));
+		assertEquals("_value=@(foo)", s.serialize("@(foo)"));
+
+		Map<String,Object> m = new AMap<String,Object>()
+			.append("foo", "foo")
+			.append("'foo'", "'foo'")
+			.append("(foo)", "(foo)")
+			.append("@(foo)", "@(foo)");
+		assertEquals("foo=foo&'foo'='foo'&(foo)=(foo)&@(foo)=@(foo)", s.serialize(m));
+
+		List<String> l = new AList<String>().appendAll("foo", "'foo'", "(foo)", "@(foo)");
+		assertEquals("0=foo&1='foo'&2=(foo)&3=@(foo)", s.serialize(l));
+
+		A a = new A();
+		assertEquals("'foo'='foo'&(foo)=(foo)&@(foo)=@(foo)&foo=foo", s.serialize(a));
+	}
+
+	@Bean(sort=true)
+	public static class A {
+
+		@BeanProperty(name="foo")
+		public String f1 = "foo";
+
+		@BeanProperty(name="'foo'")
+		public String f2 = "'foo'";
+
+		@BeanProperty(name="(foo)")
+		public String f3 = "(foo)";
+
+		@BeanProperty(name="@(foo)")
+		public String f4 = "@(foo)";
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ArgsTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ArgsTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ArgsTest.java
new file mode 100755
index 0000000..28fc6b2
--- /dev/null
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ArgsTest.java
@@ -0,0 +1,71 @@
+// ***************************************************************************************************************************
+// * 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.utils;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+@SuppressWarnings("javadoc")
+public class ArgsTest {
+
+	//====================================================================================================
+	// test - Basic tests
+	//====================================================================================================
+	@Test
+	public void test() throws Exception {
+		Args a;
+
+		// Empty args
+		a = new Args(new String[]{});
+		assertNull(a.getArg(0));
+		assertNull(a.getArg(1));
+		assertNull(a.getArg(-1));
+		assertNull(a.getArg("foo"));
+		assertEquals(0, a.getArgs("foo").size());
+		assertFalse(a.containsKey("foo"));
+
+		a = new Args(new String[]{"foo"});
+		assertEquals("foo", a.getArg(0));
+		assertNull(a.getArg(1));
+		assertNull(a.getArg(-1));
+		assertNull(a.getArg("foo"));
+		assertEquals(0, a.getArgs("foo").size());
+		assertFalse(a.containsKey("foo"));
+
+		a = new Args(new String[]{"foo", "bar bar"});
+		assertEquals("foo", a.getArg(0));
+		assertEquals("bar bar", a.getArg(1));
+		assertNull(a.getArg(-1));
+		assertNull(a.getArg("foo"));
+		assertEquals(0, a.getArgs("foo").size());
+		assertFalse(a.containsKey("foo"));
+
+		a = new Args(new String[]{"foo", "bar bar", "-foo"});
+		assertEquals("foo", a.getArg(0));
+		assertEquals("bar bar", a.getArg(1));
+		assertNull(a.getArg(-1));
+		assertNull(a.getArg("foo"));
+		assertEquals(0, a.getArgs("foo").size());
+		assertTrue(a.containsKey("foo"));
+
+		a = new Args(new String[]{"foo", "bar bar", "-foo", "bar bar"});
+		assertEquals("foo", a.getArg(0));
+		assertEquals("bar bar", a.getArg(1));
+		assertNull(a.getArg(-1));
+		assertEquals("bar bar", a.getArg("foo"));
+		assertEquals(1, a.getArgs("foo").size());
+		assertEquals("bar bar", a.getArgs("foo").get(0));
+		assertTrue(a.containsKey("foo"));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ArrayUtilsTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ArrayUtilsTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ArrayUtilsTest.java
new file mode 100755
index 0000000..249f8d3
--- /dev/null
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ArrayUtilsTest.java
@@ -0,0 +1,161 @@
+// ***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.apache.juneau.internal.ArrayUtils.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.junit.*;
+
+@SuppressWarnings("javadoc")
+public class ArrayUtilsTest {
+
+	//====================================================================================================
+	// iterator(T[])
+	//====================================================================================================
+	@Test
+	public void testArrayIterator() throws Exception {
+		assertObjectEquals("[1,2,3]", iterator(new Object[]{1,2,3}));
+		assertObjectEquals("[1,2,3]", iterator(new int[]{1,2,3}));
+		assertObjectEquals("[]", iterator(null));
+	}
+
+	//====================================================================================================
+	// append(T[], T...)
+	//====================================================================================================
+	@Test
+	public void testAppendArrayToArray() throws Exception {
+		String[] s = new String[0];
+
+		s = append(s, "a", "b");
+		assertObjectEquals("['a','b']", s);
+
+		s = append(s, "c");
+		assertObjectEquals("['a','b','c']", s);
+
+		s = append(s);
+		assertObjectEquals("['a','b','c']", s);
+
+		Object[] o = append((Object[])null);
+		assertObjectEquals("[]", o);
+
+		s = append((String[])null, "a", "b");
+		assertObjectEquals("['a','b']", s);
+	}
+
+	//====================================================================================================
+	// append(T[], Collection)
+	//====================================================================================================
+	@Test
+	public void testAppendCollectionToArray() throws Exception {
+		String[] s = new String[0];
+
+		s = append(s, Arrays.asList(new String[]{"a","b"}));
+		assertObjectEquals("['a','b']", s);
+
+		s = append(s, Arrays.asList(new String[]{"c"}));
+		assertObjectEquals("['a','b','c']", s);
+
+		s = append(s, Arrays.asList(new String[0]));
+		assertObjectEquals("['a','b','c']", s);
+
+		try {
+			append((Object[])null, Collections.emptyList());
+			fail();
+		} catch (IllegalArgumentException e) {}
+	}
+
+	//====================================================================================================
+	// reverse(T[] array)
+	//====================================================================================================
+	@Test
+	public void testReverse() throws Exception {
+		String[] s = new String[0];
+
+		s = new String[]{"a","b"};
+		assertObjectEquals("['b','a']", reverse(s));
+
+		try {
+			reverse((Object[])null);
+			fail();
+		} catch (IllegalArgumentException e) {}
+	}
+
+	//====================================================================================================
+	// asSet(T[])
+	//====================================================================================================
+	@Test
+	public void testAsSet() throws Exception {
+		String[] s = null;
+
+		try {
+			asSet(s);
+			fail();
+		} catch (IllegalArgumentException e) {}
+
+		s = new String[]{"a"};
+		Iterator<String> i = asSet(s).iterator();
+		assertEquals("a", i.next());
+
+		try {
+			i.remove();
+			fail();
+		} catch (UnsupportedOperationException e) {}
+
+		try {
+			i.next();
+			fail();
+		} catch (NoSuchElementException e) {}
+	}
+
+	//====================================================================================================
+	// iterator(T[])
+	//====================================================================================================
+	@Test
+	public void testIterator() throws Exception {
+		String[] s = null;
+
+		s = new String[]{"a"};
+		Iterator<Object> i = iterator(s);
+		assertEquals("a", i.next());
+
+		try {
+			i.remove();
+			fail();
+		} catch (UnsupportedOperationException e) {}
+
+		try {
+			i.next();
+			fail();
+		} catch (NoSuchElementException e) {}
+	}
+
+	//====================================================================================================
+	// combine(T[]...)
+	//====================================================================================================
+	@Test
+	public void testCombine() throws Exception {
+		String[] s1 = new String[]{"a"}, s2 = new String[]{"b"};
+
+		assertObjectEquals("['a','b']", combine(s1, s2));
+		assertObjectEquals("['a']", combine(s1));
+		assertObjectEquals("['b']", combine(s2));
+		assertObjectEquals("['a']", combine(s1,null));
+		assertObjectEquals("['b']", combine(null,s2));
+		assertNull(combine(null,null));
+		assertNull(combine());
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ByteArrayCacheTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ByteArrayCacheTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ByteArrayCacheTest.java
new file mode 100755
index 0000000..85c5ad1
--- /dev/null
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ByteArrayCacheTest.java
@@ -0,0 +1,61 @@
+// ***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.junit.Assert.*;
+
+import java.io.*;
+
+import org.apache.juneau.internal.*;
+import org.junit.*;
+
+@SuppressWarnings("javadoc")
+public class ByteArrayCacheTest {
+
+	//====================================================================================================
+	// testBasic
+	//====================================================================================================
+	@Test
+	public void testBasic() throws Exception {
+		ByteArrayCache bac = new ByteArrayCache();
+		byte[] b;
+
+		b = bac.cache(new byte[]{1,2,3});
+		assertObjectEquals("[1,2,3]", b);
+		assertEquals(1, bac.size());
+
+		b = bac.cache(new byte[]{1,2,3});
+		assertObjectEquals("[1,2,3]", b);
+		assertEquals(1, bac.size());
+
+		b = bac.cache(new byte[]{1,2,3,4});
+		assertObjectEquals("[1,2,3,4]", b);
+		b = bac.cache(new byte[]{1,2});
+		assertObjectEquals("[1,2]", b);
+		assertEquals(3, bac.size());
+
+		b = bac.cache(new byte[]{});
+		assertObjectEquals("[]", b);
+
+		b = bac.cache((byte[])null);
+		assertNull(b);
+
+		b = bac.cache((InputStream)null);
+		assertNull(b);
+
+		b = bac.cache(new ByteArrayInputStream(new byte[]{1,2,3}));
+		assertObjectEquals("[1,2,3]", b);
+		assertEquals(4, bac.size());
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ByteArrayInOutStreamTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ByteArrayInOutStreamTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ByteArrayInOutStreamTest.java
new file mode 100755
index 0000000..bd82240
--- /dev/null
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ByteArrayInOutStreamTest.java
@@ -0,0 +1,36 @@
+// ***************************************************************************************************************************
+// * 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.utils;
+
+import static org.junit.Assert.*;
+import static org.apache.juneau.internal.IOUtils.*;
+
+import java.io.*;
+
+import org.apache.juneau.internal.*;
+import org.junit.*;
+
+@SuppressWarnings("javadoc")
+public class ByteArrayInOutStreamTest {
+
+	//====================================================================================================
+	// testBasic
+	//====================================================================================================
+	@Test
+	public void testBasic() throws Exception {
+		InputStream is = new ByteArrayInputStream("foobar".getBytes(UTF8));
+		ByteArrayInOutStream baios = new ByteArrayInOutStream();
+		IOPipe.create(is, baios).run();
+		assertEquals("foobar", read(baios.getInputStream()));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/CharSetTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/CharSetTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/CharSetTest.java
new file mode 100755
index 0000000..71bfdb2
--- /dev/null
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/CharSetTest.java
@@ -0,0 +1,35 @@
+// ***************************************************************************************************************************
+// * 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.utils;
+
+import static org.junit.Assert.*;
+
+import org.apache.juneau.internal.*;
+import org.junit.*;
+
+@SuppressWarnings("javadoc")
+public class CharSetTest {
+
+	//====================================================================================================
+	// test - Basic tests
+	//====================================================================================================
+	@Test
+	public void test() throws Exception {
+		AsciiSet cs = new AsciiSet("abc\u1234");
+		assertTrue(cs.contains('a'));
+		assertFalse(cs.contains('d'));
+		assertFalse(cs.contains('\u1234'));
+		assertFalse(cs.contains((char)-1));
+		assertFalse(cs.contains((char)128));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ClassUtilsTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ClassUtilsTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ClassUtilsTest.java
new file mode 100755
index 0000000..dd268e2
--- /dev/null
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ClassUtilsTest.java
@@ -0,0 +1,321 @@
+// ***************************************************************************************************************************
+// * 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.utils;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+import static org.apache.juneau.internal.ClassUtils.*;
+import static org.junit.Assert.*;
+import static org.apache.juneau.TestUtils.*;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.internal.*;
+import org.junit.*;
+
+@SuppressWarnings("javadoc")
+public class ClassUtilsTest {
+
+	//====================================================================================================
+	// getReadableClassName(Class)
+	// getReadableClassName(String)
+	//====================================================================================================
+	@Test
+	public void testGetReadableClassName() throws Exception {
+		assertEquals("java.lang.Object", getReadableClassName(Object.class));
+		assertEquals("java.lang.Object[]", getReadableClassName(Object[].class));
+		assertEquals("java.lang.Object[][]", getReadableClassName(Object[][].class));
+
+		assertEquals("boolean", getReadableClassName(boolean.class));
+		assertEquals("boolean[]", getReadableClassName(boolean[].class));
+		assertEquals("boolean[][]", getReadableClassName(boolean[][].class));
+
+		assertEquals("byte", getReadableClassName(byte.class));
+		assertEquals("byte[]", getReadableClassName(byte[].class));
+		assertEquals("byte[][]", getReadableClassName(byte[][].class));
+
+		assertEquals("char", getReadableClassName(char.class));
+		assertEquals("char[]", getReadableClassName(char[].class));
+		assertEquals("char[][]", getReadableClassName(char[][].class));
+
+		assertEquals("double", getReadableClassName(double.class));
+		assertEquals("double[]", getReadableClassName(double[].class));
+		assertEquals("double[][]", getReadableClassName(double[][].class));
+
+		assertEquals("float", getReadableClassName(float.class));
+		assertEquals("float[]", getReadableClassName(float[].class));
+		assertEquals("float[][]", getReadableClassName(float[][].class));
+
+		assertEquals("int", getReadableClassName(int.class));
+		assertEquals("int[]", getReadableClassName(int[].class));
+		assertEquals("int[][]", getReadableClassName(int[][].class));
+
+		assertEquals("long", getReadableClassName(long.class));
+		assertEquals("long[]", getReadableClassName(long[].class));
+		assertEquals("long[][]", getReadableClassName(long[][].class));
+
+		assertEquals("short", getReadableClassName(short.class));
+		assertEquals("short[]", getReadableClassName(short[].class));
+		assertEquals("short[][]", getReadableClassName(short[][].class));
+
+		assertNull(getReadableClassName((Class<?>)null));
+		assertNull(getReadableClassName((String)null));
+	}
+
+	//====================================================================================================
+	// isParentClass(Class, Class)
+	//====================================================================================================
+	@Test
+	public void testIsParentClass() throws Exception {
+
+		// Strict
+		assertTrue(isParentClass(A.class, A1.class, true));
+		assertTrue(isParentClass(A1.class, A2.class, true));
+		assertTrue(isParentClass(Object.class, A2.class, true));
+		assertFalse(isParentClass(A.class, A.class, true));
+		assertFalse(isParentClass(A1.class, A1.class, true));
+		assertFalse(isParentClass(A2.class, A2.class, true));
+		assertFalse(isParentClass(A2.class, A1.class, true));
+		assertFalse(isParentClass(A1.class, A.class, true));
+		assertFalse(isParentClass(A2.class, Object.class, true));
+
+		// Not strict
+		assertTrue(isParentClass(A.class, A1.class, false));
+		assertTrue(isParentClass(A1.class, A2.class, false));
+		assertTrue(isParentClass(Object.class, A2.class, false));
+		assertTrue(isParentClass(A.class, A.class, false));
+		assertTrue(isParentClass(A1.class, A1.class, false));
+		assertTrue(isParentClass(A2.class, A2.class, false));
+		assertFalse(isParentClass(A2.class, A1.class, false));
+		assertFalse(isParentClass(A1.class, A.class, false));
+		assertFalse(isParentClass(A2.class, Object.class, false));
+	}
+
+	public interface A {}
+
+	public static class A1 implements A {}
+
+	public static class A2 extends A1 {}
+
+	//====================================================================================================
+	// getReadableClassNames(Object[])
+	//====================================================================================================
+	@Test
+	public void testGetReadableClassNames() throws Exception {
+		assertEquals("['java.lang.String','java.lang.Integer','java.lang.Boolean','null']", getReadableClassNames(new Object[]{"a",1,true,null}).toString());
+	}
+
+	public void getClassFromReadableName() throws Exception {
+		fail("Not implemented");
+	}
+
+	//====================================================================================================
+	// findPublicMethod
+	//====================================================================================================
+	@Test
+	public void testFindPublicMethod() {
+
+		assertNotNull(findPublicMethod(B.class, "m1", void.class));
+		assertNull(findPublicMethod(B.class, "m1", int.class));
+
+		assertNull(findPublicMethod(B.class, "m2", void.class));
+
+		assertNull(findPublicMethod(B.class, "m3", void.class));
+		assertNotNull(findPublicMethod(B.class, "m3", int.class));
+
+		assertNotNull(findPublicMethod(B.class, "m4", CharSequence.class));
+		assertNotNull(findPublicMethod(B.class, "m4", Object.class));
+		assertNull(findPublicMethod(B.class, "m4", String.class));
+
+		assertNotNull(findPublicMethod(B.class, "m5", void.class, int.class, CharSequence.class));
+		assertNotNull(findPublicMethod(B.class, "m5", void.class, int.class, String.class));
+		assertNull(findPublicMethod(B.class, "m5", void.class, int.class, Object.class));
+
+		assertNull(findPublicMethod(B.class, "m5", void.class, int.class));
+		assertNull(findPublicMethod(B.class, "m5", void.class, int.class, CharSequence.class, CharSequence.class));
+	}
+
+	public static class B {
+
+		public void m1() {};
+		protected void m2() {};
+		public int m3() { return 0; }
+		public CharSequence m4() { return ""; }
+
+		public void m5(int f1, CharSequence f2) {}
+	}
+
+
+	//====================================================================================================
+	// getMethodAnnotation
+	//====================================================================================================
+	@Test
+	public void getMethodAnnotations() throws Exception {
+		assertEquals("a1", getMethodAnnotation(TestAnnotation.class, CI3.class.getMethod("a1")).value());
+		assertEquals("a2b", getMethodAnnotation(TestAnnotation.class, CI3.class.getMethod("a2")).value());
+		assertEquals("a3", getMethodAnnotation(TestAnnotation.class, CI3.class.getMethod("a3", CharSequence.class)).value());
+		assertEquals("a4", getMethodAnnotation(TestAnnotation.class, CI3.class.getMethod("a4")).value());
+	}
+
+	public static interface CI1 {
+		@TestAnnotation("a1")
+		void a1();
+		@TestAnnotation("a2a")
+		void a2();
+		@TestAnnotation("a3")
+		void a3(CharSequence foo);
+
+		void a4();
+	}
+
+	public static class CI2 implements CI1 {
+		@Override
+		public void a1() {}
+		@Override
+		@TestAnnotation("a2b")
+		public void a2() {}
+		@Override
+		public void a3(CharSequence s) {}
+		@Override
+		public void a4() {}
+	}
+
+	public static class CI3 extends CI2 {
+		@Override
+		public void a1() {}
+		@Override public void a2() {}
+		@Override
+		@TestAnnotation("a4")
+		public void a4() {}
+	}
+
+	@Target(METHOD)
+	@Retention(RUNTIME)
+	public @interface TestAnnotation {
+		String value() default "";
+	}
+
+	//====================================================================================================
+	// getParentClassesParentFirst()
+	//====================================================================================================
+	@Test
+	public void getParentClassesParentFirst() throws Exception {
+		Set<String> s = new TreeSet<String>();
+		for (Iterator<Class<?>> i = ClassUtils.getParentClasses(CD.class, true, true); i.hasNext();) {
+			Class<?> c = i.next();
+			s.add(c.getSimpleName());
+		}
+		assertObjectEquals("['CA1','CA2','CA3','CB','CC','CD']", s);
+
+		s = new TreeSet<String>();
+		for (Iterator<Class<?>> i = ClassUtils.getParentClasses(CD.class, true, false); i.hasNext();) {
+			Class<?> c = i.next();
+			s.add(c.getSimpleName());
+		}
+		assertObjectEquals("['CB','CC','CD']", s);
+
+		s = new TreeSet<String>();
+		for (Iterator<Class<?>> i = ClassUtils.getParentClasses(CD.class, false, true); i.hasNext();) {
+			Class<?> c = i.next();
+			s.add(c.getSimpleName());
+		}
+		assertObjectEquals("['CA1','CA2','CA3','CB','CC','CD']", s);
+
+		s = new TreeSet<String>();
+		for (Iterator<Class<?>> i = ClassUtils.getParentClasses(CD.class, false, false); i.hasNext();) {
+			Class<?> c = i.next();
+			s.add(c.getSimpleName());
+		}
+		assertObjectEquals("['CB','CC','CD']", s);
+	}
+
+	static interface CA1 {}
+	static interface CA2 extends CA1 {}
+	static interface CA3 {}
+	static interface CA4 {}
+	static class CB implements CA1, CA2 {}
+	static class CC extends CB implements CA3 {}
+	static class CD extends CC {}
+
+	//====================================================================================================
+	// getAllMethodsParentFirst()
+	//====================================================================================================
+	@Test
+	public void getParentMethodsParentFirst() throws Exception {
+		Set<String> s = new TreeSet<String>();
+		for (Method m : ClassUtils.getAllMethods(DD.class, true))
+			if (! m.getName().startsWith("$"))
+				s.add(m.getDeclaringClass().getSimpleName() + '.' + m.getName());
+		assertObjectEquals("['DA1.da1','DA2.da2','DB.da1','DB.db','DC.da2','DC.dc','DD.da2','DD.dd']", s);
+
+		s = new TreeSet<String>();
+		for (Method m : ClassUtils.getAllMethods(DD.class, false))
+			if (! m.getName().startsWith("$"))
+				s.add(m.getDeclaringClass().getSimpleName() + '.' + m.getName());
+		assertObjectEquals("['DA1.da1','DA2.da2','DB.da1','DB.db','DC.da2','DC.dc','DD.da2','DD.dd']", s);
+	}
+
+	static interface DA1 {
+		void da1();
+	}
+	static interface DA2 extends DA1 {
+		void da2();
+	}
+	static interface DA3 {}
+	static interface DA4 {}
+	static abstract class DB implements DA1, DA2 {
+		@Override
+		public void da1() {}
+		public void db() {}
+	}
+	static class DC extends DB implements DA3 {
+		@Override
+		public void da2() {}
+		public void dc() {}
+	}
+	static class DD extends DC {
+		@Override
+		public void da2() {}
+		public void dd() {}
+	}
+
+	//====================================================================================================
+	// getAllFieldsParentFirst()
+	//====================================================================================================
+	@Test
+	public void getParentFieldsParentFirst() throws Exception {
+		Set<String> s = new TreeSet<String>();
+		for (Field f : ClassUtils.getAllFields(EB.class, true)) {
+			if (! f.getName().startsWith("$"))
+				s.add(f.getDeclaringClass().getSimpleName() + '.' + f.getName());
+		}
+		assertObjectEquals("['EA.a1','EB.a1','EB.b1']", s);
+
+		s = new TreeSet<String>();
+		for (Field f : ClassUtils.getAllFields(EB.class, false)) {
+			if (! f.getName().startsWith("$"))
+				s.add(f.getDeclaringClass().getSimpleName() + '.' + f.getName());
+		}
+		assertObjectEquals("['EA.a1','EB.a1','EB.b1']", s);
+	}
+
+	static class EA {
+		int a1;
+	}
+	static class EB extends EA {
+		int a1;
+		int b1;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
new file mode 100755
index 0000000..7bd042e
--- /dev/null
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
@@ -0,0 +1,37 @@
+// ***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.apache.juneau.internal.CollectionUtils.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.junit.*;
+
+@SuppressWarnings("javadoc")
+public class CollectionUtilsTest {
+
+	//====================================================================================================
+	// reverse(LinkedHashMap)
+	//====================================================================================================
+	@Test
+	public void testReverse() throws Exception {
+		assertNull(reverse((Map<?,?>)null));
+
+		assertObjectEquals("{b:2,a:1}", reverse(new ObjectMap("{a:1,b:2}")));
+		assertObjectEquals("{}", reverse(new ObjectMap("{}")));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/FilteredMapTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/FilteredMapTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/FilteredMapTest.java
new file mode 100755
index 0000000..db00d39
--- /dev/null
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/FilteredMapTest.java
@@ -0,0 +1,49 @@
+// ***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
+import org.junit.*;
+
+@SuppressWarnings("javadoc")
+public class FilteredMapTest {
+
+	Map<?,?> m3;
+
+	//====================================================================================================
+	// testBasic
+	//====================================================================================================
+	@Test
+	public void testBasic() throws Exception {
+		ObjectMap m = new ObjectMap("{a:'1',b:'2'}");
+
+		ClassMeta<Map<String,Object>> cm = BeanContext.DEFAULT.getClassMeta(Map.class, String.class, Object.class);
+		ClassMeta<Map<String,String>> cm2 = BeanContext.DEFAULT.getClassMeta(Map.class, String.class, String.class);
+
+		FilteredMap<String,Object> m2 = new FilteredMap<String,Object>(cm, m, new String[]{"a"});
+
+		assertObjectEquals("{a:'1'}", m2);
+
+		m2.entrySet().iterator().next().setValue("3");
+		assertObjectEquals("{a:'3'}", m2);
+
+		try { m3 = new FilteredMap<String,String>(cm2, null, new String[0]); fail(); } catch (IllegalArgumentException e) {}
+		try { m3 = new FilteredMap<String,Object>(cm, m, null); fail(); } catch (IllegalArgumentException e) {}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/IOPipeTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/IOPipeTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/IOPipeTest.java
new file mode 100755
index 0000000..de82158
--- /dev/null
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/IOPipeTest.java
@@ -0,0 +1,283 @@
+// ***************************************************************************************************************************
+// * 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.utils;
+
+import static org.junit.Assert.*;
+import static org.apache.juneau.internal.IOUtils.*;
+
+import java.io.*;
+
+import org.apache.juneau.utils.IOPipe.*;
+import org.junit.*;
+
+@SuppressWarnings("javadoc")
+public class IOPipeTest {
+
+	//====================================================================================================
+	// IOPipe(Object input, Object output)
+	//====================================================================================================
+	@Test
+	public void testConstructor() throws Exception {
+		try { IOPipe.create(null, new StringWriter()); fail(); } catch (IllegalArgumentException e) {}
+		try { IOPipe.create(new StringReader(""), null); fail(); } catch (IllegalArgumentException e) {}
+		try { IOPipe.create(new Integer(1), new StringWriter()); fail(); } catch (IllegalArgumentException e) {}
+		try { IOPipe.create("", new Integer(1)); fail(); } catch (IllegalArgumentException e) {}
+	}
+
+	//====================================================================================================
+	// closeOut()
+	// close(boolean in, boolean out)
+	//====================================================================================================
+	@Test
+	public void testClose() throws Exception {
+		TestReader in;
+		TestWriter out;
+		TestInputStream in2;
+		TestOutputStream out2;
+
+		in = new TestReader("foobar");
+		out = new TestWriter();
+		IOPipe.create(in, out).run();
+		assertTrue(in.closed);
+		assertFalse(out.closed);
+		assertEquals("foobar", out.toString());
+
+		in = new TestReader("foobar");
+		out = new TestWriter();
+		IOPipe.create(in, out).closeOut().run();
+		assertTrue(in.closed);
+		assertTrue(out.closed);
+		assertEquals("foobar", out.toString());
+
+		in = new TestReader("foobar");
+		out = new TestWriter();
+		IOPipe.create(in, out).close(false, true).run();
+		assertFalse(in.closed);
+		assertTrue(out.closed);
+		assertEquals("foobar", out.toString());
+
+		in2 = new TestInputStream("foobar");
+		out2 = new TestOutputStream();
+		IOPipe.create(in2, out2).run();
+		assertTrue(in2.closed);
+		assertFalse(out2.closed);
+		assertEquals("foobar", out2.toString());
+
+		in2 = new TestInputStream("foobar");
+		out2 = new TestOutputStream();
+		IOPipe.create(in2, out2).closeOut().run();
+		assertTrue(in2.closed);
+		assertTrue(out2.closed);
+		assertEquals("foobar", out2.toString());
+
+		in2 = new TestInputStream("foobar");
+		out2 = new TestOutputStream();
+		IOPipe.create(in2, out2).close(false, true).run();
+		assertFalse(in2.closed);
+		assertTrue(out2.closed);
+		assertEquals("foobar", out2.toString());
+
+		in = new TestReader("foobar");
+		out2 = new TestOutputStream();
+		IOPipe.create(in, out2).run();
+		assertTrue(in.closed);
+		assertFalse(out2.closed);
+		assertEquals("foobar", out.toString());
+
+		in = new TestReader("foobar");
+		out2 = new TestOutputStream();
+		IOPipe.create(in, out2).closeOut().run();
+		assertTrue(in.closed);
+		assertTrue(out2.closed);
+		assertEquals("foobar", out.toString());
+
+		in = new TestReader("foobar");
+		out2 = new TestOutputStream();
+		IOPipe.create(in, out2).close(false, true).run();
+		assertFalse(in.closed);
+		assertTrue(out2.closed);
+		assertEquals("foobar", out.toString());
+
+		in2 = new TestInputStream("foobar");
+		out = new TestWriter();
+		IOPipe.create(in2, out).run();
+		assertTrue(in2.closed);
+		assertFalse(out.closed);
+		assertEquals("foobar", out2.toString());
+
+		in2 = new TestInputStream("foobar");
+		out = new TestWriter();
+		IOPipe.create(in2, out).closeOut().run();
+		assertTrue(in2.closed);
+		assertTrue(out.closed);
+		assertEquals("foobar", out2.toString());
+
+		in2 = new TestInputStream("foobar");
+		out = new TestWriter();
+		IOPipe.create(in2, out).close(false, true).run();
+		assertFalse(in2.closed);
+		assertTrue(out.closed);
+		assertEquals("foobar", out2.toString());
+	}
+
+
+	public static class TestReader extends StringReader {
+		boolean closed;
+
+		public TestReader(String s) {
+			super(s);
+		}
+
+		@Override /* Reader */
+		public void close() {
+			closed = true;
+		}
+	}
+
+	public static class TestWriter extends StringWriter {
+		boolean closed;
+
+		public TestWriter() {
+			super();
+		}
+
+		@Override /* Writer */
+		public void close() {
+			closed = true;
+		}
+	}
+
+	public static class TestInputStream extends ByteArrayInputStream {
+		boolean closed;
+
+		public TestInputStream(String s) {
+			super(s.getBytes());
+		}
+
+		@Override /* InputStream */
+		public void close() throws IOException {
+			super.close();
+			closed = true;
+		}
+	}
+
+	public static class TestOutputStream extends ByteArrayOutputStream {
+		boolean closed;
+
+		public TestOutputStream() {
+			super();
+		}
+
+		@Override /* OutputStream */
+		public void close() throws IOException {
+			super.close();
+			closed = true;
+		}
+
+		@Override /* Object */
+		public String toString() {
+			return new String(this.toByteArray(), UTF8);
+		}
+	}
+
+	//====================================================================================================
+	// byLines()
+	// byLines(boolean)
+	//====================================================================================================
+	@Test
+	public void testByLines() throws Exception {
+		TestReader in;
+		TestWriter out;
+
+		in = new TestReader("foo\nbar");
+		out = new TestWriter() {
+			@Override public void write(String s) {
+				super.write("["+s+"]");
+			}
+		};
+		IOPipe.create(in, out).byLines().run();
+		assertEquals("[foo][][bar][]", out.toString().replaceAll("[\\r\\n]", ""));
+
+		in = new TestReader("foo\nbar");
+		out = new TestWriter() {
+			@Override public void write(String s) {
+				super.write("["+s+"]");
+			}
+		};
+		IOPipe.create(in, out).byLines(true).run();
+		assertEquals("[foo][][bar][]", out.toString().replaceAll("[\\r\\n]", ""));
+
+		in = new TestReader("foo\nbar");
+		out = new TestWriter() {
+			@Override public void write(String s) {
+				super.write("["+s+"]");
+			}
+		};
+		IOPipe.create(in, out).byLines(false).run();
+		assertEquals("foo\nbar", out.toString());
+	}
+
+	//====================================================================================================
+	// lineProcessor()
+	//====================================================================================================
+	@Test
+	public void testLineProcessor() throws Exception {
+		TestReader in;
+		TestWriter out;
+		LineProcessor lp = new LineProcessor() {
+			@Override /* LineProcessor */
+			public String process(String line) {
+				return "[" + line + "]";
+			}
+		};
+
+		in = new TestReader("foo\nbar");
+		out = new TestWriter();
+		IOPipe.create(in, out).lineProcessor(lp).run();
+		assertEquals("[foo][bar]", out.toString().replaceAll("[\\r\\n]", ""));
+
+		LineProcessor lp2 = new LineProcessor() {
+			@Override /* LineProcessor */
+			public String process(String line) {
+				return line.equals("foo") ? null : line;
+			}
+		};
+		in = new TestReader("foo\nbar");
+		out = new TestWriter();
+		IOPipe.create(in, out).lineProcessor(lp2).run();
+		assertEquals("bar", out.toString().replaceAll("[\\r\\n]", ""));
+
+		TestInputStream in2;
+		TestOutputStream out2;
+		in2 = new TestInputStream("foo\nbar");
+		out2 = new TestOutputStream();
+		IOPipe.create(in2, out2).lineProcessor(lp).run();
+		assertEquals("[foo][bar]", out2.toString().replaceAll("[\\r\\n]", ""));
+	}
+
+	//====================================================================================================
+	// buffSize()
+	//====================================================================================================
+	@Test
+	public void testBuffSize() throws Exception {
+		TestReader in;
+		TestWriter out;
+
+		in = new TestReader("foobar");
+		out = new TestWriter();
+		IOPipe.create(in, out).buffSize(1).run();
+		assertEquals("foobar", out.toString().replaceAll("[\\r\\n]", ""));
+
+		try { IOPipe.create(in, out).buffSize(0); fail(); } catch (IllegalArgumentException e) {}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/IOUtilsTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/IOUtilsTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/IOUtilsTest.java
new file mode 100755
index 0000000..11477af
--- /dev/null
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/IOUtilsTest.java
@@ -0,0 +1,104 @@
+// ***************************************************************************************************************************
+// * 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.utils;
+
+import static org.junit.Assert.*;
+import static org.apache.juneau.internal.IOUtils.*;
+
+import java.io.*;
+
+import org.junit.*;
+
+@SuppressWarnings("javadoc")
+public class IOUtilsTest {
+
+	//====================================================================================================
+	// read(File)
+	// read(InputStream, Charset)
+	// read(InputStream)
+	// read(Reader, int, int)
+	//====================================================================================================
+	@Test
+	public void testRead() throws Exception {
+
+		TestReader in;
+		TestWriter out;
+
+		in = new TestReader("foobar");
+		out = new TestWriter();
+		IOPipe.create(in, out).run();
+		assertTrue(in.closed);
+		assertFalse(out.closed);
+		assertEquals("foobar", out.toString());
+	}
+
+
+	public static class TestReader extends StringReader {
+		boolean closed;
+
+		public TestReader(String s) {
+			super(s);
+		}
+
+		@Override /* Reader */
+		public void close() {
+			closed = true;
+		}
+	}
+
+	public static class TestWriter extends StringWriter {
+		boolean closed;
+
+		public TestWriter() {
+			super();
+		}
+
+		@Override /* Writer */
+		public void close() {
+			closed = true;
+		}
+	}
+
+	public static class TestInputStream extends ByteArrayInputStream {
+		boolean closed;
+
+		public TestInputStream(String s) {
+			super(s.getBytes());
+		}
+
+		@Override /* InputStream */
+		public void close() throws IOException {
+			super.close();
+			closed = true;
+		}
+	}
+
+	public static class TestOutputStream extends ByteArrayOutputStream {
+		boolean closed;
+
+		public TestOutputStream() {
+			super();
+		}
+
+		@Override /* OutputStream */
+		public void close() throws IOException {
+			super.close();
+			closed = true;
+		}
+
+		@Override /* Object */
+		public String toString() {
+			return new String(this.toByteArray(), UTF8);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/IdentityListTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/IdentityListTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/IdentityListTest.java
new file mode 100755
index 0000000..9b95f19
--- /dev/null
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/IdentityListTest.java
@@ -0,0 +1,39 @@
+// ***************************************************************************************************************************
+// * 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.utils;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.apache.juneau.internal.*;
+import org.junit.*;
+
+@SuppressWarnings("javadoc")
+public class IdentityListTest {
+
+	//====================================================================================================
+	// test - Basic tests
+	//====================================================================================================
+	@Test
+	public void test() throws Exception {
+		List<String> l = new IdentityList<String>();
+		String a = "a";
+		l.add(a);
+		l.add(a);
+		l.add("b");
+		assertEquals(2, l.size());
+		assertTrue(l.contains("a"));
+		assertFalse(l.contains("c"));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/KeywordStoreTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/KeywordStoreTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/KeywordStoreTest.java
new file mode 100755
index 0000000..89ac7b4
--- /dev/null
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/KeywordStoreTest.java
@@ -0,0 +1,46 @@
+// ***************************************************************************************************************************
+// * 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.utils;
+
+import static org.junit.Assert.*;
+
+import org.apache.juneau.internal.*;
+import org.junit.*;
+
+@SuppressWarnings("javadoc")
+public class KeywordStoreTest {
+
+	//====================================================================================================
+	// test - Basic tests
+	//====================================================================================================
+	@Test
+	public void test() throws Exception {
+		KeywordSet ks = new KeywordSet("aaa", "zzz");
+		assertTrue(ks.contains("aaa"));
+		assertTrue(ks.contains("zzz"));
+		assertFalse(ks.contains("xxx"));
+		assertFalse(ks.contains("aaaa"));
+		assertFalse(ks.contains("zzzz"));
+		assertFalse(ks.contains("\u0000\u1000"));
+		assertFalse(ks.contains("z"));
+		assertFalse(ks.contains(null));
+		assertFalse(ks.contains("a|"));
+		assertFalse(ks.contains("|a"));
+		assertFalse(ks.contains("Aa"));
+		assertFalse(ks.contains("aA"));
+
+		for (String s : new String[]{"a","aA","Aa","a|","|a"}) {
+			try { ks = new KeywordSet(s); fail(); } catch (IllegalArgumentException e) {}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/MultiIterableTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/MultiIterableTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/MultiIterableTest.java
new file mode 100755
index 0000000..a544adc
--- /dev/null
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/MultiIterableTest.java
@@ -0,0 +1,71 @@
+// ***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
+import org.junit.*;
+
+@SuppressWarnings("javadoc")
+public class MultiIterableTest {
+
+	//====================================================================================================
+	// Basic tests
+	//====================================================================================================
+	@SuppressWarnings({ "unchecked", "rawtypes" })
+	@Test
+	public void test() throws Exception {
+		List
+			l1 = new ObjectList(),
+			l2 = new ObjectList("['a','b']"),
+			l3 = new ObjectList("['c']");
+
+		MultiIterable mi = new MultiIterable(l1.iterator(),l2.iterator());
+		mi.append(l3.iterator());
+
+		assertObjectEquals("['a','b','c']", mi.iterator());
+
+		mi = new MultiIterable(l1.iterator());
+		assertObjectEquals("[]", mi.iterator());
+
+		mi = new MultiIterable(l2.iterator(), l1.iterator());
+		assertObjectEquals("['a','b']", mi.iterator());
+
+		mi = new MultiIterable(l2.iterator(), l1.iterator(), l3.iterator());
+		assertObjectEquals("['a','b','c']", mi.iterator());
+
+		mi = new MultiIterable();
+		assertObjectEquals("[]", mi.iterator());
+
+		try { mi.append(null); fail(); } catch (IllegalArgumentException e) {}
+
+		mi = new MultiIterable(l1.iterator());
+		try { mi.iterator().next(); fail(); } catch (NoSuchElementException e) {}
+
+		mi = new MultiIterable(l1.iterator());
+		Iterator i = mi.iterator();
+		assertFalse(i.hasNext());
+		try { i.remove(); fail(); } catch (NoSuchElementException e) {}
+
+		mi = new MultiIterable(l2.iterator());
+		i = mi.iterator();
+		assertTrue(i.hasNext());
+		assertEquals("a", i.next());
+		i.remove();
+	}
+}