Thrift now a TLP - INFRA-3116

git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.1.x@1028168 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/java/test/TestClient b/lib/java/test/TestClient
new file mode 100755
index 0000000..bd3c996
--- /dev/null
+++ b/lib/java/test/TestClient
@@ -0,0 +1,22 @@
+#!/bin/bash -v
+
+#
+# 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.
+#
+
+java -cp thrifttest.jar:../../lib/java/libthrift.jar org.apache.thrift.test.TestClient $*
diff --git a/lib/java/test/TestNonblockingServer b/lib/java/test/TestNonblockingServer
new file mode 100644
index 0000000..070991c
--- /dev/null
+++ b/lib/java/test/TestNonblockingServer
@@ -0,0 +1,22 @@
+#!/bin/bash -v
+
+#
+# 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.
+#
+
+java -server -Xmx256m -cp thrifttest.jar:../../lib/java/libthrift.jar org.apache.thrift.test.TestNonblockingServer $*
diff --git a/lib/java/test/TestServer b/lib/java/test/TestServer
new file mode 100755
index 0000000..0d36b58
--- /dev/null
+++ b/lib/java/test/TestServer
@@ -0,0 +1,22 @@
+#!/bin/bash -v
+
+#
+# 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.
+#
+
+java -server -cp thrifttest.jar:../../lib/java/libthrift.jar org.apache.thrift.test.TestServer $*
diff --git a/lib/java/test/org/apache/thrift/test/DeepCopyTest.java b/lib/java/test/org/apache/thrift/test/DeepCopyTest.java
new file mode 100644
index 0000000..a171cab
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/DeepCopyTest.java
@@ -0,0 +1,138 @@
+/*
+ * 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.thrift.test;
+
+import org.apache.thrift.TDeserializer;
+import org.apache.thrift.TSerializer;
+import org.apache.thrift.protocol.TBinaryProtocol;
+import thrift.test.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+public class DeepCopyTest {
+
+  private static final byte[] kUnicodeBytes = {
+    (byte)0xd3, (byte)0x80, (byte)0xe2, (byte)0x85, (byte)0xae, (byte)0xce,
+    (byte)0x9d, (byte)0x20, (byte)0xd0, (byte)0x9d, (byte)0xce, (byte)0xbf,
+    (byte)0xe2, (byte)0x85, (byte)0xbf, (byte)0xd0, (byte)0xbe, (byte)0xc9,
+    (byte)0xa1, (byte)0xd0, (byte)0xb3, (byte)0xd0, (byte)0xb0, (byte)0xcf,
+    (byte)0x81, (byte)0xe2, (byte)0x84, (byte)0x8e, (byte)0x20, (byte)0xce,
+    (byte)0x91, (byte)0x74, (byte)0x74, (byte)0xce, (byte)0xb1, (byte)0xe2,
+    (byte)0x85, (byte)0xbd, (byte)0xce, (byte)0xba, (byte)0x83, (byte)0xe2,
+    (byte)0x80, (byte)0xbc
+  };
+
+  public static void main(String[] args) throws Exception {
+    TSerializer   binarySerializer   = new   TSerializer(new TBinaryProtocol.Factory());
+    TDeserializer binaryDeserializer = new TDeserializer(new TBinaryProtocol.Factory());
+
+    OneOfEach ooe = new OneOfEach();
+    ooe.im_true = true;
+    ooe.im_false = false;
+    ooe.a_bite = (byte) 0xd6;
+    ooe.integer16 = 27000;
+    ooe.integer32 = 1 << 24;
+    ooe.integer64 = (long) 6000 * 1000 * 1000;
+    ooe.double_precision = Math.PI;
+    ooe.some_characters = "JSON THIS! \"\1";
+    ooe.zomg_unicode = new String(kUnicodeBytes, "UTF-8");
+    ooe.base64 = "string to bytes".getBytes();
+
+    Nesting n = new Nesting(new Bonk(), new OneOfEach());
+    n.my_ooe.integer16 = 16;
+    n.my_ooe.integer32 = 32;
+    n.my_ooe.integer64 = 64;
+    n.my_ooe.double_precision = (Math.sqrt(5) + 1) / 2;
+    n.my_ooe.some_characters = ":R (me going \"rrrr\")";
+    n.my_ooe.zomg_unicode = new String(kUnicodeBytes, "UTF-8");
+    n.my_bonk.type = 31337;
+    n.my_bonk.message = "I am a bonk... xor!";
+
+    HolyMoley hm = new HolyMoley();
+
+    hm.big = new ArrayList<OneOfEach>();
+    hm.big.add(ooe);
+    hm.big.add(n.my_ooe);
+    hm.big.get(0).a_bite = (byte) 0x22;
+    hm.big.get(1).a_bite = (byte) 0x23;
+
+    hm.contain = new HashSet<List<String>>();
+    ArrayList<String> stage1 = new ArrayList<String>(2);
+    stage1.add("and a one");
+    stage1.add("and a two");
+    hm.contain.add(stage1);
+    stage1 = new ArrayList<String>(3);
+    stage1.add("then a one, two");
+    stage1.add("three!");
+    stage1.add("FOUR!!");
+    hm.contain.add(stage1);
+    stage1 = new ArrayList<String>(0);
+    hm.contain.add(stage1);
+
+    ArrayList<Bonk> stage2 = new ArrayList<Bonk>();
+    hm.bonks = new HashMap<String, List<Bonk>>();
+    hm.bonks.put("nothing", stage2);
+    Bonk b = new Bonk();
+    b.type = 1;
+    b.message = "Wait.";
+    stage2.add(b);
+    b = new Bonk();
+    b.type = 2;
+    b.message = "What?";
+    stage2.add(b);
+    stage2 = new ArrayList<Bonk>();
+    hm.bonks.put("something", stage2);
+    b = new Bonk();
+    b.type = 3;
+    b.message = "quoth";
+    b = new Bonk();
+    b.type = 4;
+    b.message = "the raven";
+    b = new Bonk();
+    b.type = 5;
+    b.message = "nevermore";
+    hm.bonks.put("poe", stage2);
+
+
+    byte[] binaryCopy = binarySerializer.serialize(hm);
+    HolyMoley hmCopy = new HolyMoley();
+    binaryDeserializer.deserialize(hmCopy, binaryCopy);
+    HolyMoley hmCopy2 = new HolyMoley(hm);
+
+    if (!hm.equals(hmCopy))
+      throw new RuntimeException("copy constructor modified the original object!");
+    if (!hmCopy.equals(hmCopy2))
+      throw new RuntimeException("copy constructor generated incorrect copy");
+
+    hm.big.get(0).base64[0]++; // change binary value in original object
+    if (hm.equals(hmCopy2)) // make sure the change didn't propagate to the copied object
+      throw new RuntimeException("Binary field not copied correctly!");
+    hm.big.get(0).base64[0]--; // undo change
+
+    hmCopy2.bonks.get("nothing").get(1).message = "What else?";
+
+    if (hm.equals(hmCopy2))
+      throw new RuntimeException("A deep copy was not done!");
+
+  }
+}
diff --git a/lib/java/test/org/apache/thrift/test/EqualityTest.java b/lib/java/test/org/apache/thrift/test/EqualityTest.java
new file mode 100644
index 0000000..f01378f
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/EqualityTest.java
@@ -0,0 +1,661 @@
+/*
+ * 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.
+ */
+
+/*
+This program was generated by the following Python script:
+
+#!/usr/bin/python2.5
+
+# Remove this when Python 2.6 hits the streets.
+from __future__ import with_statement
+
+import sys
+import os.path
+
+
+# Quines the easy way.
+with open(sys.argv[0], 'r') as handle:
+  source = handle.read()
+
+with open(os.path.join(os.path.dirname(sys.argv[0]), 'EqualityTest.java'), 'w') as out:
+  print >> out, ("/""*" r"""
+ * 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.
+ """ "*""/")
+  print >> out
+  print >> out, "/""*"
+  print >> out, "This program was generated by the following Python script:"
+  print >> out
+  out.write(source)
+  print >> out, "*""/"
+
+  print >> out, r'''
+package org.apache.thrift.test;
+
+// Generated code
+import thrift.test.*;
+
+/'''r'''**
+ *'''r'''/
+public class EqualityTest {
+  public static void main(String[] args) throws Exception {
+    JavaTestHelper lhs, rhs;
+'''
+
+  vals = {
+    'int': ("1", "2"),
+    'obj': ("\"foo\"", "\"bar\""),
+    'bin': ("new byte[]{1,2}", "new byte[]{3,4}"),
+  }
+  matrix = (
+    (False,False),
+    (False,True ),
+    (True ,False),
+    (True ,True ),
+  )
+
+  for type in ('int', 'obj', 'bin'):
+    for option in ('req', 'opt'):
+      nulls = matrix[0:1] if type == 'int' else matrix[-1::-1]
+      issets = matrix
+      for is_null in nulls:
+        for is_set in issets:
+          # isset is implied for non-primitives, so only consider the case
+          # where isset and non-null match.
+          if type != 'int' and list(is_set) != [ not null for null in is_null ]:
+            continue
+          for equal in (True, False):
+            print >> out
+            print >> out, "    lhs = new JavaTestHelper();"
+            print >> out, "    rhs = new JavaTestHelper();"
+            print >> out, "    lhs." + option + "_" + type, "=", vals[type][0] + ";"
+            print >> out, "    rhs." + option + "_" + type, "=", vals[type][0 if equal else 1] + ";"
+            isset_setter = "set" + option[0].upper() + option[1:] + "_" + type + "IsSet"
+            if (type == 'int' and is_set[0]): print >> out, "    lhs." + isset_setter + "(true);"
+            if (type == 'int' and is_set[1]): print >> out, "    rhs." + isset_setter + "(true);"
+            if (is_null[0]): print >> out, "    lhs." + option + "_" + type, "= null;"
+            if (is_null[1]): print >> out, "    rhs." + option + "_" + type, "= null;"
+            this_present = not is_null[0] and (option == 'req' or is_set[0])
+            that_present = not is_null[1] and (option == 'req' or is_set[1])
+            print >> out, "    // this_present = " + repr(this_present)
+            print >> out, "    // that_present = " + repr(that_present)
+            is_equal = \
+                (not this_present and not that_present) or \
+                (this_present and that_present and equal)
+            eq_str = 'true' if is_equal else 'false'
+
+            print >> out, "    if (lhs.equals(rhs) != "+eq_str+")"
+            print >> out, "      throw new RuntimeException(\"Failure\");"
+            if is_equal:
+              print >> out, "    if (lhs.hashCode() != rhs.hashCode())"
+              print >> out, "      throw new RuntimeException(\"Failure\");"
+
+  print >> out, r'''
+  }
+}
+'''
+*/
+
+package org.apache.thrift.test;
+
+// Generated code
+import thrift.test.*;
+
+/**
+ */
+public class EqualityTest {
+  public static void main(String[] args) throws Exception {
+    JavaTestHelper lhs, rhs;
+
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_int = 1;
+    rhs.req_int = 1;
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_int = 1;
+    rhs.req_int = 2;
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_int = 1;
+    rhs.req_int = 1;
+    rhs.setReq_intIsSet(true);
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_int = 1;
+    rhs.req_int = 2;
+    rhs.setReq_intIsSet(true);
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_int = 1;
+    rhs.req_int = 1;
+    lhs.setReq_intIsSet(true);
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_int = 1;
+    rhs.req_int = 2;
+    lhs.setReq_intIsSet(true);
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_int = 1;
+    rhs.req_int = 1;
+    lhs.setReq_intIsSet(true);
+    rhs.setReq_intIsSet(true);
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_int = 1;
+    rhs.req_int = 2;
+    lhs.setReq_intIsSet(true);
+    rhs.setReq_intIsSet(true);
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_int = 1;
+    rhs.opt_int = 1;
+    // this_present = False
+    // that_present = False
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_int = 1;
+    rhs.opt_int = 2;
+    // this_present = False
+    // that_present = False
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_int = 1;
+    rhs.opt_int = 1;
+    rhs.setOpt_intIsSet(true);
+    // this_present = False
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_int = 1;
+    rhs.opt_int = 2;
+    rhs.setOpt_intIsSet(true);
+    // this_present = False
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_int = 1;
+    rhs.opt_int = 1;
+    lhs.setOpt_intIsSet(true);
+    // this_present = True
+    // that_present = False
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_int = 1;
+    rhs.opt_int = 2;
+    lhs.setOpt_intIsSet(true);
+    // this_present = True
+    // that_present = False
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_int = 1;
+    rhs.opt_int = 1;
+    lhs.setOpt_intIsSet(true);
+    rhs.setOpt_intIsSet(true);
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_int = 1;
+    rhs.opt_int = 2;
+    lhs.setOpt_intIsSet(true);
+    rhs.setOpt_intIsSet(true);
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_obj = "foo";
+    rhs.req_obj = "foo";
+    lhs.req_obj = null;
+    rhs.req_obj = null;
+    // this_present = False
+    // that_present = False
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_obj = "foo";
+    rhs.req_obj = "bar";
+    lhs.req_obj = null;
+    rhs.req_obj = null;
+    // this_present = False
+    // that_present = False
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_obj = "foo";
+    rhs.req_obj = "foo";
+    lhs.req_obj = null;
+    // this_present = False
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_obj = "foo";
+    rhs.req_obj = "bar";
+    lhs.req_obj = null;
+    // this_present = False
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_obj = "foo";
+    rhs.req_obj = "foo";
+    rhs.req_obj = null;
+    // this_present = True
+    // that_present = False
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_obj = "foo";
+    rhs.req_obj = "bar";
+    rhs.req_obj = null;
+    // this_present = True
+    // that_present = False
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_obj = "foo";
+    rhs.req_obj = "foo";
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_obj = "foo";
+    rhs.req_obj = "bar";
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_obj = "foo";
+    rhs.opt_obj = "foo";
+    lhs.opt_obj = null;
+    rhs.opt_obj = null;
+    // this_present = False
+    // that_present = False
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_obj = "foo";
+    rhs.opt_obj = "bar";
+    lhs.opt_obj = null;
+    rhs.opt_obj = null;
+    // this_present = False
+    // that_present = False
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_obj = "foo";
+    rhs.opt_obj = "foo";
+    lhs.opt_obj = null;
+    // this_present = False
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_obj = "foo";
+    rhs.opt_obj = "bar";
+    lhs.opt_obj = null;
+    // this_present = False
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_obj = "foo";
+    rhs.opt_obj = "foo";
+    rhs.opt_obj = null;
+    // this_present = True
+    // that_present = False
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_obj = "foo";
+    rhs.opt_obj = "bar";
+    rhs.opt_obj = null;
+    // this_present = True
+    // that_present = False
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_obj = "foo";
+    rhs.opt_obj = "foo";
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_obj = "foo";
+    rhs.opt_obj = "bar";
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_bin = new byte[]{1,2};
+    rhs.req_bin = new byte[]{1,2};
+    lhs.req_bin = null;
+    rhs.req_bin = null;
+    // this_present = False
+    // that_present = False
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_bin = new byte[]{1,2};
+    rhs.req_bin = new byte[]{3,4};
+    lhs.req_bin = null;
+    rhs.req_bin = null;
+    // this_present = False
+    // that_present = False
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_bin = new byte[]{1,2};
+    rhs.req_bin = new byte[]{1,2};
+    lhs.req_bin = null;
+    // this_present = False
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_bin = new byte[]{1,2};
+    rhs.req_bin = new byte[]{3,4};
+    lhs.req_bin = null;
+    // this_present = False
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_bin = new byte[]{1,2};
+    rhs.req_bin = new byte[]{1,2};
+    rhs.req_bin = null;
+    // this_present = True
+    // that_present = False
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_bin = new byte[]{1,2};
+    rhs.req_bin = new byte[]{3,4};
+    rhs.req_bin = null;
+    // this_present = True
+    // that_present = False
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_bin = new byte[]{1,2};
+    rhs.req_bin = new byte[]{1,2};
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.req_bin = new byte[]{1,2};
+    rhs.req_bin = new byte[]{3,4};
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_bin = new byte[]{1,2};
+    rhs.opt_bin = new byte[]{1,2};
+    lhs.opt_bin = null;
+    rhs.opt_bin = null;
+    // this_present = False
+    // that_present = False
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_bin = new byte[]{1,2};
+    rhs.opt_bin = new byte[]{3,4};
+    lhs.opt_bin = null;
+    rhs.opt_bin = null;
+    // this_present = False
+    // that_present = False
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_bin = new byte[]{1,2};
+    rhs.opt_bin = new byte[]{1,2};
+    lhs.opt_bin = null;
+    // this_present = False
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_bin = new byte[]{1,2};
+    rhs.opt_bin = new byte[]{3,4};
+    lhs.opt_bin = null;
+    // this_present = False
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_bin = new byte[]{1,2};
+    rhs.opt_bin = new byte[]{1,2};
+    rhs.opt_bin = null;
+    // this_present = True
+    // that_present = False
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_bin = new byte[]{1,2};
+    rhs.opt_bin = new byte[]{3,4};
+    rhs.opt_bin = null;
+    // this_present = True
+    // that_present = False
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_bin = new byte[]{1,2};
+    rhs.opt_bin = new byte[]{1,2};
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != true)
+      throw new RuntimeException("Failure");
+    if (lhs.hashCode() != rhs.hashCode())
+      throw new RuntimeException("Failure");
+
+    lhs = new JavaTestHelper();
+    rhs = new JavaTestHelper();
+    lhs.opt_bin = new byte[]{1,2};
+    rhs.opt_bin = new byte[]{3,4};
+    // this_present = True
+    // that_present = True
+    if (lhs.equals(rhs) != false)
+      throw new RuntimeException("Failure");
+
+  }
+}
+
diff --git a/lib/java/test/org/apache/thrift/test/Fixtures.java b/lib/java/test/org/apache/thrift/test/Fixtures.java
new file mode 100644
index 0000000..14ac44f
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/Fixtures.java
@@ -0,0 +1,127 @@
+/*
+ * 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.thrift.test;
+
+import java.util.*;
+import thrift.test.*;
+
+public class Fixtures {
+  
+  private static final byte[] kUnicodeBytes = {
+    (byte)0xd3, (byte)0x80, (byte)0xe2, (byte)0x85, (byte)0xae, (byte)0xce,
+    (byte)0x9d, (byte)0x20, (byte)0xd0, (byte)0x9d, (byte)0xce, (byte)0xbf,
+    (byte)0xe2, (byte)0x85, (byte)0xbf, (byte)0xd0, (byte)0xbe, (byte)0xc9,
+    (byte)0xa1, (byte)0xd0, (byte)0xb3, (byte)0xd0, (byte)0xb0, (byte)0xcf,
+    (byte)0x81, (byte)0xe2, (byte)0x84, (byte)0x8e, (byte)0x20, (byte)0xce,
+    (byte)0x91, (byte)0x74, (byte)0x74, (byte)0xce, (byte)0xb1, (byte)0xe2,
+    (byte)0x85, (byte)0xbd, (byte)0xce, (byte)0xba, (byte)0x83, (byte)0xe2,
+    (byte)0x80, (byte)0xbc
+  };
+  
+  
+  public static final OneOfEach oneOfEach;
+  public static final Nesting nesting;
+  public static final HolyMoley holyMoley;
+  public static final CompactProtoTestStruct compactProtoTestStruct;
+  
+  static {
+    try {
+      oneOfEach = new OneOfEach();
+      oneOfEach.im_true = true;
+      oneOfEach.im_false = false;
+      oneOfEach.a_bite = (byte) 0x03;
+      oneOfEach.integer16 = 27000;
+      oneOfEach.integer32 = 1 << 24;
+      oneOfEach.integer64 = (long) 6000 * 1000 * 1000;
+      oneOfEach.double_precision = Math.PI;
+      oneOfEach.some_characters = "JSON THIS! \"\1";
+      oneOfEach.zomg_unicode = new String(kUnicodeBytes, "UTF-8");
+
+      nesting = new Nesting(new Bonk(), new OneOfEach());
+      nesting.my_ooe.integer16 = 16;
+      nesting.my_ooe.integer32 = 32;
+      nesting.my_ooe.integer64 = 64;
+      nesting.my_ooe.double_precision = (Math.sqrt(5) + 1) / 2;
+      nesting.my_ooe.some_characters = ":R (me going \"rrrr\")";
+      nesting.my_ooe.zomg_unicode = new String(kUnicodeBytes, "UTF-8");
+      nesting.my_bonk.type = 31337;
+      nesting.my_bonk.message = "I am a bonk... xor!";
+
+      holyMoley = new HolyMoley();
+
+      holyMoley.big = new ArrayList<OneOfEach>();
+      holyMoley.big.add(new OneOfEach(oneOfEach));
+      holyMoley.big.add(nesting.my_ooe);
+      holyMoley.big.get(0).a_bite = (byte) 0x22;
+      holyMoley.big.get(1).a_bite = (byte) 0x23;
+
+      holyMoley.contain = new HashSet<List<String>>();
+      ArrayList<String> stage1 = new ArrayList<String>(2);
+      stage1.add("and a one");
+      stage1.add("and a two");
+      holyMoley.contain.add(stage1);
+      stage1 = new ArrayList<String>(3);
+      stage1.add("then a one, two");
+      stage1.add("three!");
+      stage1.add("FOUR!!");
+      holyMoley.contain.add(stage1);
+      stage1 = new ArrayList<String>(0);
+      holyMoley.contain.add(stage1);
+
+      ArrayList<Bonk> stage2 = new ArrayList<Bonk>();
+      holyMoley.bonks = new HashMap<String, List<Bonk>>();
+      // one empty
+      holyMoley.bonks.put("nothing", stage2);
+      
+      // one with two
+      stage2 = new ArrayList<Bonk>();
+      Bonk b = new Bonk();
+      b.type = 1;
+      b.message = "Wait.";
+      stage2.add(b);
+      b = new Bonk();
+      b.type = 2;
+      b.message = "What?";
+      stage2.add(b);      
+      holyMoley.bonks.put("something", stage2);
+      
+      // one with three
+      stage2 = new ArrayList<Bonk>();
+      b = new Bonk();
+      b.type = 3;
+      b.message = "quoth";
+      b = new Bonk();
+      b.type = 4;
+      b.message = "the raven";
+      b = new Bonk();
+      b.type = 5;
+      b.message = "nevermore";
+      holyMoley.bonks.put("poe", stage2);
+      
+      // superhuge compact proto test struct
+      compactProtoTestStruct = new CompactProtoTestStruct(thrift.test.Constants.COMPACT_TEST);
+      compactProtoTestStruct.a_binary = new byte[]{0,1,2,3,4,5,6,7,8};
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+  }
+  
+}
diff --git a/lib/java/test/org/apache/thrift/test/IdentityTest.java b/lib/java/test/org/apache/thrift/test/IdentityTest.java
new file mode 100644
index 0000000..c6453ce
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/IdentityTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.thrift.test;
+
+// Generated code
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.thrift.TDeserializer;
+import org.apache.thrift.TSerializer;
+import org.apache.thrift.protocol.TBinaryProtocol;
+
+import thrift.test.Bonk;
+import thrift.test.HolyMoley;
+import thrift.test.Nesting;
+import thrift.test.OneOfEach;
+
+/**
+ *
+ */
+public class IdentityTest {
+  public static Object deepCopy(Object oldObj) throws Exception {
+    ObjectOutputStream oos = null;
+    ObjectInputStream ois = null;
+    try {
+      ByteArrayOutputStream bos =
+        new ByteArrayOutputStream();
+      oos = new ObjectOutputStream(bos);
+      oos.writeObject(oldObj);
+      oos.flush();
+      ByteArrayInputStream bis =
+        new ByteArrayInputStream(bos.toByteArray());
+      ois = new ObjectInputStream(bis);
+      return ois.readObject();
+    } finally {
+      oos.close();
+      ois.close();
+    }
+  }
+
+  public static void main(String[] args) throws Exception {
+    TSerializer   binarySerializer   = new   TSerializer(new TBinaryProtocol.Factory());
+    TDeserializer binaryDeserializer = new TDeserializer(new TBinaryProtocol.Factory());
+
+    OneOfEach ooe = new OneOfEach();
+    ooe.im_true   = true;
+    ooe.im_false  = false;
+    ooe.a_bite    = (byte)0xd6;
+    ooe.integer16 = 27000;
+    ooe.integer32 = 1<<24;
+    ooe.integer64 = (long)6000 * 1000 * 1000;
+    ooe.double_precision = Math.PI;
+    ooe.some_characters  = "JSON THIS! \"\u0001";
+    ooe.base64 = new byte[]{1,2,3,(byte)255};
+
+    Nesting n = new Nesting();
+    n.my_ooe = (OneOfEach)deepCopy(ooe);
+    n.my_ooe.integer16 = 16;
+    n.my_ooe.integer32 = 32;
+    n.my_ooe.integer64 = 64;
+    n.my_ooe.double_precision = (Math.sqrt(5)+1)/2;
+    n.my_ooe.some_characters  = ":R (me going \"rrrr\")";
+    n.my_ooe.zomg_unicode     = "\u04c0\u216e\u039d\u0020\u041d\u03bf\u217f"+
+                                "\u043e\u0261\u0433\u0430\u03c1\u210e\u0020"+
+                                "\u0391\u0074\u0074\u03b1\u217d\u03ba\u01c3"+
+                                "\u203c";
+    n.my_bonk = new Bonk();
+    n.my_bonk.type    = 31337;
+    n.my_bonk.message = "I am a bonk... xor!";
+
+    HolyMoley hm = new HolyMoley();
+    hm.big = new ArrayList<OneOfEach>();
+    hm.contain = new HashSet<List<String>>();
+    hm.bonks = new HashMap<String,List<Bonk>>();
+
+    hm.big.add((OneOfEach)deepCopy(ooe));
+    hm.big.add((OneOfEach)deepCopy(n.my_ooe));
+    hm.big.get(0).a_bite = 0x22;
+    hm.big.get(1).a_bite = 0x33;
+
+    List<String> stage1 = new ArrayList<String>();
+    stage1.add("and a one");
+    stage1.add("and a two");
+    hm.contain.add(stage1);
+    stage1 = new ArrayList<String>();
+    stage1.add("then a one, two");
+    stage1.add("three!");
+    stage1.add("FOUR!!");
+    hm.contain.add(stage1);
+    stage1 = new ArrayList<String>();
+    hm.contain.add(stage1);
+
+    List<Bonk> stage2 = new ArrayList<Bonk>();
+    hm.bonks.put("nothing", stage2);
+    stage2.add(new Bonk());
+    stage2.get(0).type = 1;
+    stage2.get(0).message = "Wait.";
+    stage2.add(new Bonk());
+    stage2.get(1).type = 2;
+    stage2.get(1).message = "What?";
+    hm.bonks.put("something", stage2);
+    stage2 = new ArrayList<Bonk>();
+    stage2.add(new Bonk());
+    stage2.get(0).type = 3;
+    stage2.get(0).message = "quoth";
+    stage2.add(new Bonk());
+    stage2.get(1).type = 4;
+    stage2.get(1).message = "the raven";
+    stage2.add(new Bonk());
+    stage2.get(2).type = 5;
+    stage2.get(2).message = "nevermore";
+    hm.bonks.put("poe", stage2);
+
+    OneOfEach ooe2 = new OneOfEach();
+    binaryDeserializer.deserialize(
+        ooe2,
+        binarySerializer.serialize(ooe));
+
+    if (!ooe.equals(ooe2)) {
+      throw new RuntimeException("Failure: ooe (equals)");
+    }
+    if (ooe.hashCode() != ooe2.hashCode()) {
+      throw new RuntimeException("Failure: ooe (hash)");
+    }
+
+
+    Nesting n2 = new Nesting();
+    binaryDeserializer.deserialize(
+        n2,
+        binarySerializer.serialize(n));
+
+    if (!n.equals(n2)) {
+      throw new RuntimeException("Failure: n (equals)");
+    }
+    if (n.hashCode() != n2.hashCode()) {
+      throw new RuntimeException("Failure: n (hash)");
+    }
+
+    HolyMoley hm2 = new HolyMoley();
+    binaryDeserializer.deserialize(
+        hm2,
+        binarySerializer.serialize(hm));
+
+    if (!hm.equals(hm2)) {
+      throw new RuntimeException("Failure: hm (equals)");
+    }
+    if (hm.hashCode() != hm2.hashCode()) {
+      throw new RuntimeException("Failure: hm (hash)");
+    }
+
+  }
+}
diff --git a/lib/java/test/org/apache/thrift/test/JSONProtoTest.java b/lib/java/test/org/apache/thrift/test/JSONProtoTest.java
new file mode 100644
index 0000000..59f4ce1
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/JSONProtoTest.java
@@ -0,0 +1,183 @@
+/*
+ * 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.thrift.test;
+
+// Generated code
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.thrift.protocol.TJSONProtocol;
+import org.apache.thrift.transport.TMemoryBuffer;
+
+import thrift.test.Base64;
+import thrift.test.Bonk;
+import thrift.test.HolyMoley;
+import thrift.test.Nesting;
+import thrift.test.OneOfEach;
+
+/**
+ * Tests for the Java implementation of TJSONProtocol. Mirrors the C++ version
+ *
+ */
+public class JSONProtoTest {
+
+  private static final byte[] kUnicodeBytes = {
+    (byte)0xd3, (byte)0x80, (byte)0xe2, (byte)0x85, (byte)0xae, (byte)0xce,
+    (byte)0x9d, (byte)0x20, (byte)0xd0, (byte)0x9d, (byte)0xce, (byte)0xbf,
+    (byte)0xe2, (byte)0x85, (byte)0xbf, (byte)0xd0, (byte)0xbe, (byte)0xc9,
+    (byte)0xa1, (byte)0xd0, (byte)0xb3, (byte)0xd0, (byte)0xb0, (byte)0xcf,
+    (byte)0x81, (byte)0xe2, (byte)0x84, (byte)0x8e, (byte)0x20, (byte)0xce,
+    (byte)0x91, (byte)0x74, (byte)0x74, (byte)0xce, (byte)0xb1, (byte)0xe2,
+    (byte)0x85, (byte)0xbd, (byte)0xce, (byte)0xba, (byte)0x83, (byte)0xe2,
+    (byte)0x80, (byte)0xbc
+  };
+
+  public static void main(String [] args) throws Exception {
+   try {
+      System.out.println("In JSON Proto test");
+
+      OneOfEach ooe = new OneOfEach();
+      ooe.im_true   = true;
+      ooe.im_false  = false;
+      ooe.a_bite    = (byte)0xd6;
+      ooe.integer16 = 27000;
+      ooe.integer32 = 1<<24;
+      ooe.integer64 = (long)6000 * 1000 * 1000;
+      ooe.double_precision = Math.PI;
+      ooe.some_characters  = "JSON THIS! \"\1";
+      ooe.zomg_unicode     = new String(kUnicodeBytes, "UTF-8");
+
+
+      Nesting n = new Nesting(new Bonk(), new OneOfEach());
+      n.my_ooe.integer16 = 16;
+      n.my_ooe.integer32 = 32;
+      n.my_ooe.integer64 = 64;
+      n.my_ooe.double_precision = (Math.sqrt(5)+1)/2;
+      n.my_ooe.some_characters  = ":R (me going \"rrrr\")";
+      n.my_ooe.zomg_unicode     = new String(kUnicodeBytes, "UTF-8");
+      n.my_bonk.type    = 31337;
+      n.my_bonk.message = "I am a bonk... xor!";
+
+      HolyMoley hm = new HolyMoley();
+
+      hm.big = new ArrayList<OneOfEach>();
+      hm.big.add(ooe);
+      hm.big.add(n.my_ooe);
+      hm.big.get(0).a_bite = (byte)0x22;
+      hm.big.get(1).a_bite = (byte)0x23;
+
+      hm.contain = new HashSet<List<String>>();
+      ArrayList<String> stage1 = new ArrayList<String>(2);
+      stage1.add("and a one");
+      stage1.add("and a two");
+      hm.contain.add(stage1);
+      stage1 = new ArrayList<String>(3);
+      stage1.add("then a one, two");
+      stage1.add("three!");
+      stage1.add("FOUR!!");
+      hm.contain.add(stage1);
+      stage1 = new ArrayList<String>(0);
+      hm.contain.add(stage1);
+
+      ArrayList<Bonk> stage2 = new ArrayList<Bonk>();
+      hm.bonks = new HashMap<String, List<Bonk>>();
+      hm.bonks.put("nothing", stage2);
+      Bonk b = new Bonk();
+      b.type = 1;
+      b.message = "Wait.";
+      stage2.add(b);
+      b = new Bonk();
+      b.type = 2;
+      b.message = "What?";
+      stage2.add(b);
+      stage2 = new ArrayList<Bonk>();
+      hm.bonks.put("something", stage2);
+      b = new Bonk();
+      b.type = 3;
+      b.message = "quoth";
+      b = new Bonk();
+      b.type = 4;
+      b.message = "the raven";
+      b = new Bonk();
+      b.type = 5;
+      b.message = "nevermore";
+      hm.bonks.put("poe", stage2);
+
+      TMemoryBuffer buffer = new TMemoryBuffer(1024);
+      TJSONProtocol proto = new TJSONProtocol(buffer);
+
+      System.out.println("Writing ooe");
+      ooe.write(proto);
+      System.out.println("Reading ooe");
+      OneOfEach ooe2 = new OneOfEach();
+      ooe2.read(proto);
+
+      System.out.println("Comparing ooe");
+      if (!ooe.equals(ooe2)) {
+        throw new RuntimeException("ooe != ooe2");
+      }
+
+      System.out.println("Writing hm");
+      hm.write(proto);
+
+      System.out.println("Reading hm");
+      HolyMoley hm2 = new HolyMoley();
+      hm2.read(proto);
+
+      System.out.println("Comparing hm");
+      if (!hm.equals(hm2)) {
+        throw new RuntimeException("hm != hm2");
+      }
+
+      hm2.big.get(0).a_bite = (byte)0xFF;
+      if (hm.equals(hm2)) {
+        throw new RuntimeException("hm should not equal hm2");
+      }
+
+      Base64 base = new Base64();
+      base.a = 123;
+      base.b1 = "1".getBytes("UTF-8");
+      base.b2 = "12".getBytes("UTF-8");
+      base.b3 = "123".getBytes("UTF-8");
+      base.b4 = "1234".getBytes("UTF-8");
+      base.b5 = "12345".getBytes("UTF-8");
+      base.b6 = "123456".getBytes("UTF-8");
+
+      System.out.println("Writing base");
+      base.write(proto);
+
+      System.out.println("Reading base");
+      Base64 base2 = new Base64();
+      base2.read(proto);
+
+      System.out.println("Comparing base");
+      if (!base.equals(base2)) {
+        throw new RuntimeException("base != base2");
+      }
+
+    } catch (Exception ex) {
+      ex.printStackTrace();
+      throw ex;
+   }
+  }
+
+}
diff --git a/lib/java/test/org/apache/thrift/test/JavaBeansTest.java b/lib/java/test/org/apache/thrift/test/JavaBeansTest.java
new file mode 100644
index 0000000..b72bd38
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/JavaBeansTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.thrift.test;
+
+import java.util.LinkedList;
+import thrift.test.OneOfEachBeans;
+
+public class JavaBeansTest {
+  public static void main(String[] args) throws Exception {
+    // Test isSet methods
+    OneOfEachBeans ooe = new OneOfEachBeans();
+
+    // Nothing should be set
+    if (ooe.is_set_a_bite())
+      throw new RuntimeException("isSet method error: unset field returned as set!");
+    if (ooe.is_set_base64())
+      throw new RuntimeException("isSet method error: unset field returned as set!");
+    if (ooe.is_set_byte_list())
+      throw new RuntimeException("isSet method error: unset field returned as set!");
+    if (ooe.is_set_double_precision())
+      throw new RuntimeException("isSet method error: unset field returned as set!");
+    if (ooe.is_set_i16_list())
+      throw new RuntimeException("isSet method error: unset field returned as set!");
+    if (ooe.is_set_i64_list())
+      throw new RuntimeException("isSet method error: unset field returned as set!");
+    if (ooe.is_set_boolean_field())
+      throw new RuntimeException("isSet method error: unset field returned as set!");
+    if (ooe.is_set_integer16())
+      throw new RuntimeException("isSet method error: unset field returned as set!");
+    if (ooe.is_set_integer32())
+      throw new RuntimeException("isSet method error: unset field returned as set!");
+    if (ooe.is_set_integer64())
+      throw new RuntimeException("isSet method error: unset field returned as set!");
+    if (ooe.is_set_some_characters())
+      throw new RuntimeException("isSet method error: unset field returned as set!");
+
+    for (int i = 1; i < 12; i++){
+      if (ooe.isSet(i))
+        throw new RuntimeException("isSet method error: unset field " + i + " returned as set!");
+    }
+
+    // Everything is set
+    ooe.set_a_bite((byte) 1);
+    ooe.set_base64("bytes".getBytes());
+    ooe.set_byte_list(new LinkedList<Byte>());
+    ooe.set_double_precision(1);
+    ooe.set_i16_list(new LinkedList<Short>());
+    ooe.set_i64_list(new LinkedList<Long>());
+    ooe.set_boolean_field(true);
+    ooe.set_integer16((short) 1);
+    ooe.set_integer32(1);
+    ooe.set_integer64(1);
+    ooe.set_some_characters("string");
+
+    if (!ooe.is_set_a_bite())
+      throw new RuntimeException("isSet method error: set field returned as unset!");
+    if (!ooe.is_set_base64())
+      throw new RuntimeException("isSet method error: set field returned as unset!");
+    if (!ooe.is_set_byte_list())
+      throw new RuntimeException("isSet method error: set field returned as unset!");
+    if (!ooe.is_set_double_precision())
+      throw new RuntimeException("isSet method error: set field returned as unset!");
+    if (!ooe.is_set_i16_list())
+      throw new RuntimeException("isSet method error: set field returned as unset!");
+    if (!ooe.is_set_i64_list())
+      throw new RuntimeException("isSet method error: set field returned as unset!");
+    if (!ooe.is_set_boolean_field())
+      throw new RuntimeException("isSet method error: set field returned as unset!");
+    if (!ooe.is_set_integer16())
+      throw new RuntimeException("isSet method error: set field returned as unset!");
+    if (!ooe.is_set_integer32())
+      throw new RuntimeException("isSet method error: set field returned as unset!");
+    if (!ooe.is_set_integer64())
+      throw new RuntimeException("isSet method error: set field returned as unset!");
+    if (!ooe.is_set_some_characters())
+      throw new RuntimeException("isSet method error: set field returned as unset!");
+
+    for (int i = 1; i < 12; i++){
+      if (!ooe.isSet(i))
+        throw new RuntimeException("isSet method error: set field " + i + " returned as unset!");
+    }
+
+    // Should throw exception when field doesn't exist
+    boolean exceptionThrown = false;
+    try{
+      if (ooe.isSet(100));
+    } catch (IllegalArgumentException e){
+      exceptionThrown = true;
+    }
+    if (!exceptionThrown)
+      throw new RuntimeException("isSet method error: non-existent field provided as agument but no exception thrown!");
+  }
+}
diff --git a/lib/java/test/org/apache/thrift/test/MetaDataTest.java b/lib/java/test/org/apache/thrift/test/MetaDataTest.java
new file mode 100644
index 0000000..a018034
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/MetaDataTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.thrift.test;
+
+import java.util.Map;
+import org.apache.thrift.TFieldRequirementType;
+import org.apache.thrift.meta_data.FieldMetaData;
+import org.apache.thrift.meta_data.ListMetaData;
+import org.apache.thrift.meta_data.MapMetaData;
+import org.apache.thrift.meta_data.SetMetaData;
+import org.apache.thrift.meta_data.StructMetaData;
+import org.apache.thrift.protocol.TType;
+import thrift.test.*;
+
+public class MetaDataTest {
+  
+  public static void main(String[] args) throws Exception {
+    Map<Integer, FieldMetaData> mdMap = CrazyNesting.metaDataMap;
+    
+    // Check for struct fields existence
+    if (mdMap.size() != 3)
+      throw new RuntimeException("metadata map contains wrong number of entries!");
+    if (!mdMap.containsKey(CrazyNesting.SET_FIELD) || !mdMap.containsKey(CrazyNesting.LIST_FIELD) || !mdMap.containsKey(CrazyNesting.STRING_FIELD))
+      throw new RuntimeException("metadata map doesn't contain entry for a struct field!");
+    
+    // Check for struct fields contents
+    if (!mdMap.get(CrazyNesting.STRING_FIELD).fieldName.equals("string_field") ||
+            !mdMap.get(CrazyNesting.LIST_FIELD).fieldName.equals("list_field") ||
+            !mdMap.get(CrazyNesting.SET_FIELD).fieldName.equals("set_field"))
+      throw new RuntimeException("metadata map contains a wrong fieldname");
+    if (mdMap.get(CrazyNesting.STRING_FIELD).requirementType != TFieldRequirementType.DEFAULT ||
+            mdMap.get(CrazyNesting.LIST_FIELD).requirementType != TFieldRequirementType.REQUIRED ||
+            mdMap.get(CrazyNesting.SET_FIELD).requirementType != TFieldRequirementType.OPTIONAL)
+      throw new RuntimeException("metadata map contains the wrong requirement type for a field");
+    if (mdMap.get(CrazyNesting.STRING_FIELD).valueMetaData.type != TType.STRING ||
+            mdMap.get(CrazyNesting.LIST_FIELD).valueMetaData.type != TType.LIST ||
+            mdMap.get(CrazyNesting.SET_FIELD).valueMetaData.type != TType.SET)
+      throw new RuntimeException("metadata map contains the wrong requirement type for a field");
+    
+    // Check nested structures
+    if (!mdMap.get(CrazyNesting.LIST_FIELD).valueMetaData.isContainer())
+      throw new RuntimeException("value metadata for a list is stored as non-container!");
+    if (mdMap.get(CrazyNesting.LIST_FIELD).valueMetaData.isStruct())
+      throw new RuntimeException("value metadata for a list is stored as a struct!");
+    if (((MapMetaData)((ListMetaData)((SetMetaData)((MapMetaData)((MapMetaData)((ListMetaData)mdMap.get(CrazyNesting.LIST_FIELD).valueMetaData).elemMetaData).valueMetaData).valueMetaData).elemMetaData).elemMetaData).keyMetaData.type != TType.STRUCT)
+      throw new RuntimeException("metadata map contains wrong type for a value in a deeply nested structure");
+    if (((StructMetaData)((MapMetaData)((ListMetaData)((SetMetaData)((MapMetaData)((MapMetaData)((ListMetaData)mdMap.get(CrazyNesting.LIST_FIELD).valueMetaData).elemMetaData).valueMetaData).valueMetaData).elemMetaData).elemMetaData).keyMetaData).structClass != Insanity.class)
+      throw new RuntimeException("metadata map contains wrong class for a struct in a deeply nested structure");
+    
+    // Check that FieldMetaData contains a map with metadata for all generated struct classes
+    if (FieldMetaData.getStructMetaDataMap(CrazyNesting.class) == null ||
+            FieldMetaData.getStructMetaDataMap(Insanity.class) == null ||
+            FieldMetaData.getStructMetaDataMap(Xtruct.class) == null)
+      throw new RuntimeException("global metadata map doesn't contain an entry for a known struct");
+    if (FieldMetaData.getStructMetaDataMap(CrazyNesting.class) != CrazyNesting.metaDataMap ||
+            FieldMetaData.getStructMetaDataMap(Insanity.class) != Insanity.metaDataMap)
+      throw new RuntimeException("global metadata map contains wrong entry for a loaded struct");    
+  }
+}
diff --git a/lib/java/test/org/apache/thrift/test/OverloadNonblockingServer.java b/lib/java/test/org/apache/thrift/test/OverloadNonblockingServer.java
new file mode 100644
index 0000000..54d78e5
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/OverloadNonblockingServer.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.thrift.test;
+
+import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.transport.TSocket;
+
+
+public class OverloadNonblockingServer {
+
+  public static void main(String[] args) throws Exception {
+    int msg_size_mb = Integer.parseInt(args[0]);
+    int msg_size = msg_size_mb * 1024 * 1024;
+
+    TSocket socket = new TSocket("localhost", 9090);
+    TBinaryProtocol binprot = new TBinaryProtocol(socket);
+    socket.open();
+    binprot.writeI32(msg_size);
+    binprot.writeI32(1);
+    socket.flush();
+
+    System.in.read();
+    // Thread.sleep(30000);
+    for (int i = 0; i < msg_size_mb; i++) {
+      binprot.writeBinary(new byte[1024 * 1024]);
+    }
+
+    socket.close();
+  }
+}
diff --git a/lib/java/test/org/apache/thrift/test/ReadStruct.java b/lib/java/test/org/apache/thrift/test/ReadStruct.java
new file mode 100644
index 0000000..2dc042c
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/ReadStruct.java
@@ -0,0 +1,62 @@
+/*
+ * 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.thrift.test;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+
+import org.apache.thrift.protocol.TProtocol;
+import org.apache.thrift.protocol.TProtocolFactory;
+import org.apache.thrift.transport.TIOStreamTransport;
+import org.apache.thrift.transport.TTransport;
+
+import thrift.test.CompactProtoTestStruct;
+
+public class ReadStruct {
+  public static void main(String[] args) throws Exception {
+    if (args.length != 2) {
+      System.out.println("usage: java -cp build/classes org.apache.thrift.test.ReadStruct filename proto_factory_class");
+      System.out.println("Read in an instance of CompactProtocolTestStruct from 'file', making sure that it is equivalent to Fixtures.compactProtoTestStruct. Use a protocol from 'proto_factory_class'.");
+    }
+    
+    TTransport trans = new TIOStreamTransport(new BufferedInputStream(new FileInputStream(args[0])));
+    
+    TProtocolFactory factory = (TProtocolFactory)Class.forName(args[1]).newInstance();
+    
+    TProtocol proto = factory.getProtocol(trans);
+    
+    CompactProtoTestStruct cpts = new CompactProtoTestStruct();
+    
+    for (Integer fid : CompactProtoTestStruct.metaDataMap.keySet()) {
+      cpts.setFieldValue(fid, null);
+    }
+    
+    cpts.read(proto);
+    
+    if (cpts.equals(Fixtures.compactProtoTestStruct)) {
+      System.out.println("Object verified successfully!");
+    } else {
+      System.out.println("Object failed verification!");
+      System.out.println("Expected: " + Fixtures.compactProtoTestStruct + " but got " + cpts);
+    }
+    
+  }
+
+}
diff --git a/lib/java/test/org/apache/thrift/test/SerializationBenchmark.java b/lib/java/test/org/apache/thrift/test/SerializationBenchmark.java
new file mode 100644
index 0000000..b83b2f9
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/SerializationBenchmark.java
@@ -0,0 +1,87 @@
+/*
+ * 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.thrift.test;
+
+import java.io.ByteArrayInputStream;
+
+import org.apache.thrift.*;
+import org.apache.thrift.protocol.*;
+import org.apache.thrift.transport.*;
+
+import thrift.test.*;
+
+public class SerializationBenchmark {
+  private final static int HOW_MANY = 10000000;
+  
+  public static void main(String[] args) throws Exception {
+    TProtocolFactory factory = new TBinaryProtocol.Factory();
+
+    OneOfEach ooe = new OneOfEach();
+    ooe.im_true   = true;
+    ooe.im_false  = false;
+    ooe.a_bite    = (byte)0xd6;
+    ooe.integer16 = 27000;
+    ooe.integer32 = 1<<24;
+    ooe.integer64 = (long)6000 * 1000 * 1000;
+    ooe.double_precision = Math.PI;
+    ooe.some_characters  = "JSON THIS! \"\u0001";
+    ooe.base64 = new byte[]{1,2,3,(byte)255};
+
+    testSerialization(factory, ooe);
+    testDeserialization(factory, ooe, OneOfEach.class);
+  }
+  
+  public static void testSerialization(TProtocolFactory factory, TBase object) throws Exception {
+    TTransport trans = new TTransport() {
+      public void write(byte[] bin, int x, int y) throws TTransportException {}
+      public int read(byte[] bin, int x, int y) throws TTransportException {return 0;}
+      public void close() {}
+      public void open() {}
+      public boolean isOpen() {return true;}
+    };
+    
+    TProtocol proto = factory.getProtocol(trans);
+    
+    long startTime = System.currentTimeMillis();
+    for (int i = 0; i < HOW_MANY; i++) {
+      object.write(proto);
+    }
+    long endTime = System.currentTimeMillis();
+    
+    System.out.println("Test time: " + (endTime - startTime) + " ms");
+  }
+  
+  public static <T extends TBase> void testDeserialization(TProtocolFactory factory, T object, Class<T> klass) throws Exception {
+    TMemoryBuffer buf = new TMemoryBuffer(0);
+    object.write(factory.getProtocol(buf));
+    byte[] serialized = new byte[100*1024];
+    buf.read(serialized, 0, 100*1024);
+    
+    long startTime = System.currentTimeMillis();
+    for (int i = 0; i < HOW_MANY; i++) {
+      T o2 = klass.newInstance();
+      o2.read(factory.getProtocol(new TIOStreamTransport(new ByteArrayInputStream(serialized))));
+    }
+    long endTime = System.currentTimeMillis();
+    
+    System.out.println("Test time: " + (endTime - startTime) + " ms");
+  }
+}
\ No newline at end of file
diff --git a/lib/java/test/org/apache/thrift/test/TCompactProtocolTest.java b/lib/java/test/org/apache/thrift/test/TCompactProtocolTest.java
new file mode 100755
index 0000000..5d1c3cb
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/TCompactProtocolTest.java
@@ -0,0 +1,450 @@
+/*
+ * 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.thrift.test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.thrift.TBase;
+import org.apache.thrift.TException;
+import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.protocol.TCompactProtocol;
+import org.apache.thrift.protocol.TField;
+import org.apache.thrift.protocol.TMessage;
+import org.apache.thrift.protocol.TMessageType;
+import org.apache.thrift.protocol.TProtocol;
+import org.apache.thrift.protocol.TProtocolFactory;
+import org.apache.thrift.protocol.TStruct;
+import org.apache.thrift.protocol.TType;
+import org.apache.thrift.transport.TMemoryBuffer;
+
+import thrift.test.CompactProtoTestStruct;
+import thrift.test.HolyMoley;
+import thrift.test.Nesting;
+import thrift.test.OneOfEach;
+import thrift.test.Srv;
+
+public class TCompactProtocolTest {
+
+  static TProtocolFactory factory = new TCompactProtocol.Factory();
+
+  public static void main(String[] args) throws Exception {
+    testNakedByte();
+    for (int i = 0; i < 128; i++) {
+      testByteField((byte)i);
+      testByteField((byte)-i);
+    }
+    
+    testNakedI16((short)0);
+    testNakedI16((short)1);
+    testNakedI16((short)15000);
+    testNakedI16((short)0x7fff);
+    testNakedI16((short)-1);
+    testNakedI16((short)-15000);
+    testNakedI16((short)-0x7fff);
+    
+    testI16Field((short)0);
+    testI16Field((short)1);
+    testI16Field((short)7);
+    testI16Field((short)150);
+    testI16Field((short)15000);
+    testI16Field((short)0x7fff);
+    testI16Field((short)-1);
+    testI16Field((short)-7);
+    testI16Field((short)-150);
+    testI16Field((short)-15000);
+    testI16Field((short)-0x7fff);
+    
+    testNakedI32(0);
+    testNakedI32(1);
+    testNakedI32(15000);
+    testNakedI32(0xffff);
+    testNakedI32(-1);
+    testNakedI32(-15000);
+    testNakedI32(-0xffff);
+    
+    testI32Field(0);
+    testI32Field(1);
+    testI32Field(7);
+    testI32Field(150);
+    testI32Field(15000);
+    testI32Field(31337);
+    testI32Field(0xffff);
+    testI32Field(0xffffff);
+    testI32Field(-1);
+    testI32Field(-7);
+    testI32Field(-150);
+    testI32Field(-15000);
+    testI32Field(-0xffff);
+    testI32Field(-0xffffff);
+    
+    testNakedI64(0);
+    for (int i = 0; i < 62; i++) {
+      testNakedI64(1L << i);
+      testNakedI64(-(1L << i));
+    }
+
+    testI64Field(0);
+    for (int i = 0; i < 62; i++) {
+      testI64Field(1L << i);
+      testI64Field(-(1L << i));
+    }
+
+    testDouble();
+    
+    testNakedString("");
+    testNakedString("short");
+    testNakedString("borderlinetiny");
+    testNakedString("a bit longer than the smallest possible");
+    
+    testStringField("");
+    testStringField("short");
+    testStringField("borderlinetiny");
+    testStringField("a bit longer than the smallest possible");
+    
+    testNakedBinary(new byte[]{});
+    testNakedBinary(new byte[]{0,1,2,3,4,5,6,7,8,9,10});
+    testNakedBinary(new byte[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14});
+    testNakedBinary(new byte[128]);
+    
+    testBinaryField(new byte[]{});
+    testBinaryField(new byte[]{0,1,2,3,4,5,6,7,8,9,10});
+    testBinaryField(new byte[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14});
+    testBinaryField(new byte[128]);
+    
+    testSerialization(OneOfEach.class, Fixtures.oneOfEach);
+    testSerialization(Nesting.class, Fixtures.nesting);
+    testSerialization(HolyMoley.class, Fixtures.holyMoley);
+    testSerialization(CompactProtoTestStruct.class, Fixtures.compactProtoTestStruct);
+    
+    testMessage();
+    
+    testServerRequest();
+  }
+  
+  public static void testNakedByte() throws Exception {
+    TMemoryBuffer buf = new TMemoryBuffer(0);
+    TProtocol proto = factory.getProtocol(buf);
+    proto.writeByte((byte)123);
+    byte out = proto.readByte();
+    if (out != 123) {
+      throw new RuntimeException("Byte was supposed to be " + (byte)123 + " but was " + out);
+    }
+  }
+  
+  public static void testByteField(final byte b) throws Exception {
+    testStructField(new StructFieldTestCase(TType.BYTE, (short)15) {
+      public void writeMethod(TProtocol proto) throws TException {
+        proto.writeByte(b);
+      }
+      
+      public void readMethod(TProtocol proto) throws TException {
+        byte result = proto.readByte();
+        if (result != b) {
+          throw new RuntimeException("Byte was supposed to be " + (byte)b + " but was " + result);
+        }
+      }
+    });
+  }
+
+  public static void testNakedI16(short n) throws Exception {
+    TMemoryBuffer buf = new TMemoryBuffer(0);
+    TProtocol proto = factory.getProtocol(buf);
+    proto.writeI16(n);
+    // System.out.println(buf.inspect());
+    int out = proto.readI16();
+    if (out != n) {
+      throw new RuntimeException("I16 was supposed to be " + n + " but was " + out);
+    }
+  }
+
+  public static void testI16Field(final short n) throws Exception {
+    testStructField(new StructFieldTestCase(TType.I16, (short)15) {
+      public void writeMethod(TProtocol proto) throws TException {
+        proto.writeI16(n);
+      }
+      
+      public void readMethod(TProtocol proto) throws TException {
+        short result = proto.readI16();
+        if (result != n) {
+          throw new RuntimeException("I16 was supposed to be " + n + " but was " + result);
+        }
+      }
+    });
+  }
+  
+  public static void testNakedI32(int n) throws Exception {
+    TMemoryBuffer buf = new TMemoryBuffer(0);
+    TProtocol proto = factory.getProtocol(buf);
+    proto.writeI32(n);
+    // System.out.println(buf.inspect());
+    int out = proto.readI32();
+    if (out != n) {
+      throw new RuntimeException("I32 was supposed to be " + n + " but was " + out);
+    }
+  }
+  
+  public static void testI32Field(final int n) throws Exception {
+    testStructField(new StructFieldTestCase(TType.I32, (short)15) {
+      public void writeMethod(TProtocol proto) throws TException {
+        proto.writeI32(n);
+      }
+      
+      public void readMethod(TProtocol proto) throws TException {
+        int result = proto.readI32();
+        if (result != n) {
+          throw new RuntimeException("I32 was supposed to be " + n + " but was " + result);
+        }
+      }
+    });
+    
+  }
+
+  public static void testNakedI64(long n) throws Exception {
+    TMemoryBuffer buf = new TMemoryBuffer(0);
+    TProtocol proto = factory.getProtocol(buf);
+    proto.writeI64(n);
+    // System.out.println(buf.inspect());
+    long out = proto.readI64();
+    if (out != n) {
+      throw new RuntimeException("I64 was supposed to be " + n + " but was " + out);
+    }
+  }
+  
+  public static void testI64Field(final long n) throws Exception {
+    testStructField(new StructFieldTestCase(TType.I64, (short)15) {
+      public void writeMethod(TProtocol proto) throws TException {
+        proto.writeI64(n);
+      }
+      
+      public void readMethod(TProtocol proto) throws TException {
+        long result = proto.readI64();
+        if (result != n) {
+          throw new RuntimeException("I64 was supposed to be " + n + " but was " + result);
+        }
+      }
+    });
+  }
+    
+  public static void testDouble() throws Exception {
+    TMemoryBuffer buf = new TMemoryBuffer(1000);
+    TProtocol proto = factory.getProtocol(buf);
+    proto.writeDouble(123.456);
+    double out = proto.readDouble();
+    if (out != 123.456) {
+      throw new RuntimeException("Double was supposed to be " + 123.456 + " but was " + out);
+    }
+  }
+    
+  public static void testNakedString(String str) throws Exception {
+    TMemoryBuffer buf = new TMemoryBuffer(0);
+    TProtocol proto = factory.getProtocol(buf);
+    proto.writeString(str);
+    // System.out.println(buf.inspect());
+    String out = proto.readString();
+    if (!str.equals(out)) {
+      throw new RuntimeException("String was supposed to be '" + str + "' but was '" + out + "'");
+    }
+  }
+  
+  public static void testStringField(final String str) throws Exception {
+    testStructField(new StructFieldTestCase(TType.STRING, (short)15) {
+      public void writeMethod(TProtocol proto) throws TException {
+        proto.writeString(str);
+      }
+      
+      public void readMethod(TProtocol proto) throws TException {
+        String result = proto.readString();
+        if (!result.equals(str)) {
+          throw new RuntimeException("String was supposed to be " + str + " but was " + result);
+        }
+      }
+    });
+  }
+
+  public static void testNakedBinary(byte[] data) throws Exception {
+    TMemoryBuffer buf = new TMemoryBuffer(0);
+    TProtocol proto = factory.getProtocol(buf);
+    proto.writeBinary(data);
+    // System.out.println(buf.inspect());
+    byte[] out = proto.readBinary();
+    if (!Arrays.equals(data, out)) {
+      throw new RuntimeException("Binary was supposed to be '" + data + "' but was '" + out + "'");
+    }
+  }
+
+  public static void testBinaryField(final byte[] data) throws Exception {
+    testStructField(new StructFieldTestCase(TType.STRING, (short)15) {
+      public void writeMethod(TProtocol proto) throws TException {
+        proto.writeBinary(data);
+      }
+      
+      public void readMethod(TProtocol proto) throws TException {
+        byte[] result = proto.readBinary();
+        if (!Arrays.equals(data, result)) {
+          throw new RuntimeException("Binary was supposed to be '" + bytesToString(data) + "' but was '" + bytesToString(result) + "'");
+        }
+      }
+    });
+    
+  }
+
+  public static <T extends TBase> void testSerialization(Class<T> klass, T obj) throws Exception {
+    TMemoryBuffer buf = new TMemoryBuffer(0);
+    TBinaryProtocol binproto = new TBinaryProtocol(buf);
+    
+    try {
+      obj.write(binproto);
+      // System.out.println("Size in binary protocol: " + buf.length());
+    
+      buf = new TMemoryBuffer(0);
+      TProtocol proto = factory.getProtocol(buf);
+    
+      obj.write(proto);
+      System.out.println("Size in compact protocol: " + buf.length());
+      // System.out.println(buf.inspect());
+    
+      T objRead = klass.newInstance();
+      objRead.read(proto);
+      if (!obj.equals(objRead)) {
+        System.out.println("Expected: " + obj.toString());
+        System.out.println("Actual: " + objRead.toString());
+        // System.out.println(buf.inspect());
+        throw new RuntimeException("Objects didn't match!");
+      }
+    } catch (Exception e) {
+      System.out.println(buf.inspect());
+      throw e;
+    }
+  }
+
+  public static void testMessage() throws Exception {
+    List<TMessage> msgs = Arrays.asList(new TMessage[]{
+      new TMessage("short message name", TMessageType.CALL, 0),
+      new TMessage("1", TMessageType.REPLY, 12345),
+      new TMessage("loooooooooooooooooooooooooooooooooong", TMessageType.EXCEPTION, 1 << 16),
+      new TMessage("Janky", TMessageType.CALL, 0),
+    });
+    
+    for (TMessage msg : msgs) {
+      TMemoryBuffer buf = new TMemoryBuffer(0);
+      TProtocol proto = factory.getProtocol(buf);
+      TMessage output = null;
+      
+      proto.writeMessageBegin(msg);
+      proto.writeMessageEnd();
+
+      output = proto.readMessageBegin();
+
+      if (!msg.equals(output)) {
+        throw new RuntimeException("Message was supposed to be " + msg + " but was " + output);
+      }
+    }
+  }
+
+  public static void testServerRequest() throws Exception {
+    Srv.Iface handler = new Srv.Iface() {
+      public int Janky(int i32arg) throws TException {
+        return i32arg * 2;
+      }
+
+      public int primitiveMethod() throws TException {
+        // TODO Auto-generated method stub
+        return 0;
+      }
+
+      public CompactProtoTestStruct structMethod() throws TException {
+        // TODO Auto-generated method stub
+        return null;
+      }
+
+      public void voidMethod() throws TException {
+        // TODO Auto-generated method stub
+        
+      }
+    };
+    
+    Srv.Processor testProcessor = new Srv.Processor(handler);
+
+    TMemoryBuffer clientOutTrans = new TMemoryBuffer(0);
+    TProtocol clientOutProto = factory.getProtocol(clientOutTrans);
+    TMemoryBuffer clientInTrans = new TMemoryBuffer(0);
+    TProtocol clientInProto = factory.getProtocol(clientInTrans);
+    
+    Srv.Client testClient = new Srv.Client(clientInProto, clientOutProto);
+    
+    testClient.send_Janky(1);
+    // System.out.println(clientOutTrans.inspect());
+    testProcessor.process(clientOutProto, clientInProto);
+    // System.out.println(clientInTrans.inspect());
+    int result = testClient.recv_Janky();
+    if (result != 2) {
+      throw new RuntimeException("Got an unexpected result: " + result);
+    }
+  }
+
+  //
+  // Helper methods
+  //
+  
+  private static String bytesToString(byte[] bytes) {
+    String s = "";
+    for (int i = 0; i < bytes.length; i++) {
+      s += Integer.toHexString((int)bytes[i]) + " ";
+    }
+    return s;
+  }
+
+  private static void testStructField(StructFieldTestCase testCase) throws Exception {
+    TMemoryBuffer buf = new TMemoryBuffer(0);
+    TProtocol proto = factory.getProtocol(buf);
+    
+    TField field = new TField("test_field", testCase.type_, testCase.id_);
+    proto.writeStructBegin(new TStruct("test_struct"));
+    proto.writeFieldBegin(field);
+    testCase.writeMethod(proto);
+    proto.writeFieldEnd();
+    proto.writeStructEnd();
+    
+    // System.out.println(buf.inspect());
+
+    proto.readStructBegin();
+    TField readField = proto.readFieldBegin();
+    // TODO: verify the field is as expected
+    if (!field.equals(readField)) {
+      throw new RuntimeException("Expected " + field + " but got " + readField);
+    }
+    testCase.readMethod(proto);
+    proto.readStructEnd();
+  }
+  
+  public static abstract class StructFieldTestCase {
+    byte type_;
+    short id_;
+    public StructFieldTestCase(byte type, short id) {
+      type_ = type;
+      id_ = id;
+    }
+    
+    public abstract void writeMethod(TProtocol proto) throws TException;
+    public abstract void readMethod(TProtocol proto) throws TException;
+  }
+}
\ No newline at end of file
diff --git a/lib/java/test/org/apache/thrift/test/TestClient.java b/lib/java/test/org/apache/thrift/test/TestClient.java
new file mode 100644
index 0000000..4a95f7a
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/TestClient.java
@@ -0,0 +1,423 @@
+/*
+ * 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.thrift.test;
+
+// Generated code
+import thrift.test.*;
+
+import org.apache.thrift.TApplicationException;
+import org.apache.thrift.TSerializer;
+import org.apache.thrift.transport.TTransport;
+import org.apache.thrift.transport.TSocket;
+import org.apache.thrift.transport.THttpClient;
+import org.apache.thrift.transport.TFramedTransport;
+import org.apache.thrift.transport.TTransportException;
+import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.protocol.TSimpleJSONProtocol;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Test Java client for thrift. Essentially just a copy of the C++ version,
+ * this makes a variety of requests to enable testing for both performance and
+ * correctness of the output.
+ *
+ */
+public class TestClient {
+  public static void main(String [] args) {
+    try {
+      String host = "localhost";
+      int port = 9090;
+      String url = null;
+      int numTests = 1;
+      boolean framed = false;
+
+      int socketTimeout = 1000;
+
+      try {
+        for (int i = 0; i < args.length; ++i) {
+          if (args[i].equals("-h")) {
+            String[] hostport = (args[++i]).split(":");
+            host = hostport[0];
+            port = Integer.valueOf(hostport[1]);
+          } else if (args[i].equals("-f") || args[i].equals("-framed")) {
+            framed = true;
+          } else if (args[i].equals("-u")) {
+            url = args[++i];
+          } else if (args[i].equals("-n")) {
+            numTests = Integer.valueOf(args[++i]);
+          } else if (args[i].equals("-timeout")) {
+            socketTimeout = Integer.valueOf(args[++i]);
+          }
+        }
+      } catch (Exception x) {
+        x.printStackTrace();
+      }
+
+      TTransport transport;
+
+      if (url != null) {
+        transport = new THttpClient(url);
+      } else {
+        TSocket socket = new TSocket(host, port);
+        socket.setTimeout(socketTimeout);
+        transport = socket;
+        if (framed) {
+          transport = new TFramedTransport(transport);
+        }
+      }
+
+      TBinaryProtocol binaryProtocol =
+        new TBinaryProtocol(transport);
+      ThriftTest.Client testClient =
+        new ThriftTest.Client(binaryProtocol);
+      Insanity insane = new Insanity();
+
+      long timeMin = 0;
+      long timeMax = 0;
+      long timeTot = 0;
+
+      for (int test = 0; test < numTests; ++test) {
+
+        /**
+         * CONNECT TEST
+         */
+        System.out.println("Test #" + (test+1) + ", " + "connect " + host + ":" + port);
+        try {
+          transport.open();
+        } catch (TTransportException ttx) {
+          System.out.println("Connect failed: " + ttx.getMessage());
+          continue;
+        }
+
+        long start = System.nanoTime();
+
+        /**
+         * VOID TEST
+         */
+        try {
+          System.out.print("testVoid()");
+          testClient.testVoid();
+          System.out.print(" = void\n");
+        } catch (TApplicationException tax) {
+          tax.printStackTrace();
+        }
+
+        /**
+         * STRING TEST
+         */
+        System.out.print("testString(\"Test\")");
+        String s = testClient.testString("Test");
+        System.out.print(" = \"" + s + "\"\n");
+
+        /**
+         * BYTE TEST
+         */
+        System.out.print("testByte(1)");
+        byte i8 = testClient.testByte((byte)1);
+        System.out.print(" = " + i8 + "\n");
+
+        /**
+         * I32 TEST
+         */
+        System.out.print("testI32(-1)");
+        int i32 = testClient.testI32(-1);
+        System.out.print(" = " + i32 + "\n");
+
+        /**
+         * I64 TEST
+         */
+        System.out.print("testI64(-34359738368)");
+        long i64 = testClient.testI64(-34359738368L);
+        System.out.print(" = " + i64 + "\n");
+
+        /**
+         * DOUBLE TEST
+         */
+        System.out.print("testDouble(5.325098235)");
+        double dub = testClient.testDouble(5.325098235);
+        System.out.print(" = " + dub + "\n");
+
+        /**
+         * STRUCT TEST
+         */
+        System.out.print("testStruct({\"Zero\", 1, -3, -5})");
+        Xtruct out = new Xtruct();
+        out.string_thing = "Zero";
+        out.byte_thing = (byte) 1;
+        out.i32_thing = -3;
+        out.i64_thing = -5;
+        Xtruct in = testClient.testStruct(out);
+        System.out.print(" = {" + "\"" + in.string_thing + "\", " + in.byte_thing + ", " + in.i32_thing + ", " + in.i64_thing + "}\n");
+
+        /**
+         * NESTED STRUCT TEST
+         */
+        System.out.print("testNest({1, {\"Zero\", 1, -3, -5}), 5}");
+        Xtruct2 out2 = new Xtruct2();
+        out2.byte_thing = (short)1;
+        out2.struct_thing = out;
+        out2.i32_thing = 5;
+        Xtruct2 in2 = testClient.testNest(out2);
+        in = in2.struct_thing;
+        System.out.print(" = {" + in2.byte_thing + ", {" + "\"" + in.string_thing + "\", " + in.byte_thing + ", " + in.i32_thing + ", " + in.i64_thing + "}, " + in2.i32_thing + "}\n");
+
+        /**
+         * MAP TEST
+         */
+        Map<Integer,Integer> mapout = new HashMap<Integer,Integer>();
+        for (int i = 0; i < 5; ++i) {
+          mapout.put(i, i-10);
+        }
+        System.out.print("testMap({");
+        boolean first = true;
+        for (int key : mapout.keySet()) {
+          if (first) {
+            first = false;
+          } else {
+            System.out.print(", ");
+          }
+          System.out.print(key + " => " + mapout.get(key));
+        }
+        System.out.print("})");
+        Map<Integer,Integer> mapin = testClient.testMap(mapout);
+        System.out.print(" = {");
+        first = true;
+        for (int key : mapin.keySet()) {
+          if (first) {
+            first = false;
+          } else {
+            System.out.print(", ");
+          }
+          System.out.print(key + " => " + mapout.get(key));
+        }
+        System.out.print("}\n");
+
+        /**
+         * SET TEST
+         */
+        Set<Integer> setout = new HashSet<Integer>();
+        for (int i = -2; i < 3; ++i) {
+          setout.add(i);
+        }
+        System.out.print("testSet({");
+        first = true;
+        for (int elem : setout) {
+          if (first) {
+            first = false;
+          } else {
+            System.out.print(", ");
+          }
+          System.out.print(elem);
+        }
+        System.out.print("})");
+        Set<Integer> setin = testClient.testSet(setout);
+        System.out.print(" = {");
+        first = true;
+        for (int elem : setin) {
+          if (first) {
+            first = false;
+          } else {
+            System.out.print(", ");
+          }
+          System.out.print(elem);
+        }
+        System.out.print("}\n");
+
+        /**
+         * LIST TEST
+         */
+        List<Integer> listout = new ArrayList<Integer>();
+        for (int i = -2; i < 3; ++i) {
+          listout.add(i);
+        }
+        System.out.print("testList({");
+        first = true;
+        for (int elem : listout) {
+          if (first) {
+            first = false;
+          } else {
+            System.out.print(", ");
+          }
+          System.out.print(elem);
+        }
+        System.out.print("})");
+        List<Integer> listin = testClient.testList(listout);
+        System.out.print(" = {");
+        first = true;
+        for (int elem : listin) {
+          if (first) {
+            first = false;
+          } else {
+            System.out.print(", ");
+          }
+          System.out.print(elem);
+        }
+        System.out.print("}\n");
+
+        /**
+         * ENUM TEST
+         */
+        System.out.print("testEnum(ONE)");
+        int ret = testClient.testEnum(Numberz.ONE);
+        System.out.print(" = " + ret + "\n");
+
+        System.out.print("testEnum(TWO)");
+        ret = testClient.testEnum(Numberz.TWO);
+        System.out.print(" = " + ret + "\n");
+
+        System.out.print("testEnum(THREE)");
+        ret = testClient.testEnum(Numberz.THREE);
+        System.out.print(" = " + ret + "\n");
+
+        System.out.print("testEnum(FIVE)");
+        ret = testClient.testEnum(Numberz.FIVE);
+        System.out.print(" = " + ret + "\n");
+
+        System.out.print("testEnum(EIGHT)");
+        ret = testClient.testEnum(Numberz.EIGHT);
+        System.out.print(" = " + ret + "\n");
+
+        /**
+         * TYPEDEF TEST
+         */
+        System.out.print("testTypedef(309858235082523)");
+        long uid = testClient.testTypedef(309858235082523L);
+        System.out.print(" = " + uid + "\n");
+
+        /**
+         * NESTED MAP TEST
+         */
+        System.out.print("testMapMap(1)");
+        Map<Integer,Map<Integer,Integer>> mm =
+          testClient.testMapMap(1);
+        System.out.print(" = {");
+        for (int key : mm.keySet()) {
+          System.out.print(key + " => {");
+          Map<Integer,Integer> m2 = mm.get(key);
+          for (int k2 : m2.keySet()) {
+            System.out.print(k2 + " => " + m2.get(k2) + ", ");
+          }
+          System.out.print("}, ");
+        }
+        System.out.print("}\n");
+
+        /**
+         * INSANITY TEST
+         */
+        insane = new Insanity();
+        insane.userMap = new HashMap<Integer, Long>();
+        insane.userMap.put(Numberz.FIVE, (long)5000);
+        Xtruct truck = new Xtruct();
+        truck.string_thing = "Truck";
+        truck.byte_thing = (byte)8;
+        truck.i32_thing = 8;
+        truck.i64_thing = 8;
+        insane.xtructs = new ArrayList<Xtruct>();
+        insane.xtructs.add(truck);
+        System.out.print("testInsanity()");
+        Map<Long,Map<Integer,Insanity>> whoa =
+          testClient.testInsanity(insane);
+        System.out.print(" = {");
+        for (long key : whoa.keySet()) {
+          Map<Integer,Insanity> val = whoa.get(key);
+          System.out.print(key + " => {");
+
+          for (int k2 : val.keySet()) {
+            Insanity v2 = val.get(k2);
+            System.out.print(k2 + " => {");
+            Map<Integer, Long> userMap = v2.userMap;
+            System.out.print("{");
+            if (userMap != null) {
+              for (int k3 : userMap.keySet()) {
+                System.out.print(k3 + " => " + userMap.get(k3) + ", ");
+              }
+            }
+            System.out.print("}, ");
+
+            List<Xtruct> xtructs = v2.xtructs;
+            System.out.print("{");
+            if (xtructs != null) {
+              for (Xtruct x : xtructs) {
+                System.out.print("{" + "\"" + x.string_thing + "\", " + x.byte_thing + ", " + x.i32_thing + ", "+ x.i64_thing + "}, ");
+              }
+            }
+            System.out.print("}");
+
+            System.out.print("}, ");
+          }
+          System.out.print("}, ");
+        }
+        System.out.print("}\n");
+
+        // Test oneway
+        System.out.print("testOneway(3)...");
+        long startOneway = System.nanoTime();
+        testClient.testOneway(3);
+        long onewayElapsedMillis = (System.nanoTime() - startOneway) / 1000000;
+        if (onewayElapsedMillis > 200) {
+          throw new Exception("Oneway test failed: took " +
+                              Long.toString(onewayElapsedMillis) +
+                              "ms");
+        } else {
+          System.out.println("Success - took " +
+                             Long.toString(onewayElapsedMillis) +
+                             "ms");
+        }
+
+
+        long stop = System.nanoTime();
+        long tot = stop-start;
+
+        System.out.println("Total time: " + tot/1000 + "us");
+
+        if (timeMin == 0 || tot < timeMin) {
+          timeMin = tot;
+        }
+        if (tot > timeMax) {
+          timeMax = tot;
+        }
+        timeTot += tot;
+
+        transport.close();
+      }
+
+      long timeAvg = timeTot / numTests;
+
+      System.out.println("Min time: " + timeMin/1000 + "us");
+      System.out.println("Max time: " + timeMax/1000 + "us");
+      System.out.println("Avg time: " + timeAvg/1000 + "us");
+
+      String json = (new TSerializer(new TSimpleJSONProtocol.Factory())).toString(insane);
+
+      System.out.println("\nFor good meausre here is some JSON:\n" + json);
+
+    } catch (Exception x) {
+      x.printStackTrace();
+    }
+
+  }
+
+}
diff --git a/lib/java/test/org/apache/thrift/test/TestNonblockingServer.java b/lib/java/test/org/apache/thrift/test/TestNonblockingServer.java
new file mode 100644
index 0000000..2e6a178
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/TestNonblockingServer.java
@@ -0,0 +1,73 @@
+/*
+ * 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.thrift.test;
+
+import org.apache.thrift.server.THsHaServer;
+import org.apache.thrift.server.TNonblockingServer;
+import org.apache.thrift.server.TServer;
+import org.apache.thrift.transport.TNonblockingServerSocket;
+
+import thrift.test.ThriftTest;
+
+
+public class TestNonblockingServer extends TestServer {
+  public static void main(String [] args) {
+    try {
+      int port = 9090;
+      boolean hsha = false;
+
+      for (int i = 0; i < args.length; i++) {
+        if (args[i].equals("-p")) {
+          port = Integer.valueOf(args[i++]);
+        } else if (args[i].equals("-hsha")) {
+          hsha = true;
+        }
+      }
+
+      // Processor
+      TestHandler testHandler =
+        new TestHandler();
+      ThriftTest.Processor testProcessor =
+        new ThriftTest.Processor(testHandler);
+
+      // Transport
+      TNonblockingServerSocket tServerSocket =
+        new TNonblockingServerSocket(port);
+
+      TServer serverEngine;
+
+      if (hsha) {
+        // HsHa Server
+        serverEngine = new THsHaServer(testProcessor, tServerSocket);
+      } else {
+        // Nonblocking Server
+        serverEngine = new TNonblockingServer(testProcessor, tServerSocket);
+      }
+
+      // Run it
+      System.out.println("Starting the server on port " + port + "...");
+      serverEngine.serve();
+
+    } catch (Exception x) {
+      x.printStackTrace();
+    }
+    System.out.println("done.");
+  }
+}
diff --git a/lib/java/test/org/apache/thrift/test/TestServer.java b/lib/java/test/org/apache/thrift/test/TestServer.java
new file mode 100644
index 0000000..986f889
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/TestServer.java
@@ -0,0 +1,306 @@
+/*
+ * 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.thrift.test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.protocol.TProtocolFactory;
+import org.apache.thrift.server.TServer;
+import org.apache.thrift.server.TThreadPoolServer;
+import org.apache.thrift.transport.TServerSocket;
+
+import thrift.test.Insanity;
+import thrift.test.Numberz;
+import thrift.test.ThriftTest;
+import thrift.test.Xception;
+import thrift.test.Xception2;
+import thrift.test.Xtruct;
+import thrift.test.Xtruct2;
+
+public class TestServer {
+
+  public static class TestHandler implements ThriftTest.Iface {
+
+    public TestHandler() {}
+
+    public void testVoid() {
+      System.out.print("testVoid()\n");
+    }
+
+    public String testString(String thing) {
+      System.out.print("testString(\"" + thing + "\")\n");
+      return thing;
+    }
+
+    public byte testByte(byte thing) {
+      System.out.print("testByte(" + thing + ")\n");
+      return thing;
+    }
+
+    public int testI32(int thing) {
+      System.out.print("testI32(" + thing + ")\n");
+      return thing;
+    }
+
+    public long testI64(long thing) {
+      System.out.print("testI64(" + thing + ")\n");
+      return thing;
+    }
+
+    public double testDouble(double thing) {
+      System.out.print("testDouble(" + thing + ")\n");
+      return thing;
+    }
+
+    public Xtruct testStruct(Xtruct thing) {
+      System.out.print("testStruct({" +
+                       "\"" + thing.string_thing + "\", " +
+                       thing.byte_thing + ", " +
+                       thing.i32_thing + ", " +
+                       thing.i64_thing + "})\n");
+      return thing;
+    }
+
+    public Xtruct2 testNest(Xtruct2 nest) {
+      Xtruct thing = nest.struct_thing;
+      System.out.print("testNest({" +
+                       nest.byte_thing + ", {" +
+                       "\"" + thing.string_thing + "\", " +
+                       thing.byte_thing + ", " +
+                       thing.i32_thing + ", " +
+                       thing.i64_thing + "}, " +
+                       nest.i32_thing + "})\n");
+      return nest;
+    }
+
+    public Map<Integer,Integer> testMap(Map<Integer,Integer> thing) {
+      System.out.print("testMap({");
+      boolean first = true;
+      for (int key : thing.keySet()) {
+        if (first) {
+          first = false;
+        } else {
+          System.out.print(", ");
+        }
+        System.out.print(key + " => " + thing.get(key));
+      }
+      System.out.print("})\n");
+      return thing;
+    }
+
+    public Set<Integer> testSet(Set<Integer> thing) {
+      System.out.print("testSet({");
+      boolean first = true;
+      for (int elem : thing) {
+        if (first) {
+          first = false;
+        } else {
+          System.out.print(", ");
+        }
+        System.out.print(elem);
+      }
+      System.out.print("})\n");
+      return thing;
+    }
+
+    public List<Integer> testList(List<Integer> thing) {
+      System.out.print("testList({");
+      boolean first = true;
+      for (int elem : thing) {
+        if (first) {
+          first = false;
+        } else {
+          System.out.print(", ");
+        }
+        System.out.print(elem);
+      }
+      System.out.print("})\n");
+      return thing;
+    }
+
+    public int testEnum(int thing) {
+      System.out.print("testEnum(" + thing + ")\n");
+      return thing;
+    }
+
+    public long testTypedef(long thing) {
+      System.out.print("testTypedef(" + thing + ")\n");
+      return thing;
+    }
+
+    public Map<Integer,Map<Integer,Integer>> testMapMap(int hello) {
+      System.out.print("testMapMap(" + hello + ")\n");
+      Map<Integer,Map<Integer,Integer>> mapmap =
+        new HashMap<Integer,Map<Integer,Integer>>();
+
+      HashMap<Integer,Integer> pos = new HashMap<Integer,Integer>();
+      HashMap<Integer,Integer> neg = new HashMap<Integer,Integer>();
+      for (int i = 1; i < 5; i++) {
+        pos.put(i, i);
+        neg.put(-i, -i);
+      }
+
+      mapmap.put(4, pos);
+      mapmap.put(-4, neg);
+
+      return mapmap;
+    }
+
+    public Map<Long, Map<Integer,Insanity>> testInsanity(Insanity argument) {
+      System.out.print("testInsanity()\n");
+
+      Xtruct hello = new Xtruct();
+      hello.string_thing = "Hello2";
+      hello.byte_thing = 2;
+      hello.i32_thing = 2;
+      hello.i64_thing = 2;
+
+      Xtruct goodbye = new Xtruct();
+      goodbye.string_thing = "Goodbye4";
+      goodbye.byte_thing = (byte)4;
+      goodbye.i32_thing = 4;
+      goodbye.i64_thing = (long)4;
+
+      Insanity crazy = new Insanity();
+      crazy.userMap = new HashMap<Integer, Long>();
+      crazy.xtructs = new ArrayList<Xtruct>();
+
+      crazy.userMap.put(Numberz.EIGHT, (long)8);
+      crazy.xtructs.add(goodbye);
+
+      Insanity looney = new Insanity();
+      crazy.userMap.put(Numberz.FIVE, (long)5);
+      crazy.xtructs.add(hello);
+
+      HashMap<Integer,Insanity> first_map = new HashMap<Integer, Insanity>();
+      HashMap<Integer,Insanity> second_map = new HashMap<Integer, Insanity>();;
+
+      first_map.put(Numberz.TWO, crazy);
+      first_map.put(Numberz.THREE, crazy);
+
+      second_map.put(Numberz.SIX, looney);
+
+      Map<Long,Map<Integer,Insanity>> insane =
+        new HashMap<Long, Map<Integer,Insanity>>();
+      insane.put((long)1, first_map);
+      insane.put((long)2, second_map);
+
+      return insane;
+    }
+
+    public Xtruct testMulti(byte arg0, int arg1, long arg2, Map<Short,String> arg3, int arg4, long arg5) {
+      System.out.print("testMulti()\n");
+
+      Xtruct hello = new Xtruct();;
+      hello.string_thing = "Hello2";
+      hello.byte_thing = arg0;
+      hello.i32_thing = arg1;
+      hello.i64_thing = arg2;
+      return hello;
+    }
+
+    public void testException(String arg) throws Xception {
+      System.out.print("testException("+arg+")\n");
+      if (arg.equals("Xception")) {
+        Xception x = new Xception();
+        x.errorCode = 1001;
+        x.message = "This is an Xception";
+        throw x;
+      }
+      return;
+    }
+
+    public Xtruct testMultiException(String arg0, String arg1) throws Xception, Xception2 {
+      System.out.print("testMultiException(" + arg0 + ", " + arg1 + ")\n");
+      if (arg0.equals("Xception")) {
+        Xception x = new Xception();
+        x.errorCode = 1001;
+        x.message = "This is an Xception";
+        throw x;
+      } else if (arg0.equals("Xception2")) {
+        Xception2 x = new Xception2();
+        x.errorCode = 2002;
+        x.struct_thing = new Xtruct();
+        x.struct_thing.string_thing = "This is an Xception2";
+        throw x;
+      }
+
+      Xtruct result = new Xtruct();
+      result.string_thing = arg1;
+      return result;
+    }
+
+    public void testOneway(int sleepFor) {
+      System.out.println("testOneway(" + Integer.toString(sleepFor) +
+                         ") => sleeping...");
+      try {
+        Thread.sleep(sleepFor * 1000);
+        System.out.println("Done sleeping!");
+      } catch (InterruptedException ie) {
+        throw new RuntimeException(ie);
+      }
+    }
+
+  } // class TestHandler
+
+  public static void main(String [] args) {
+    try {
+      int port = 9090;
+      if (args.length > 1) {
+        port = Integer.valueOf(args[0]);
+      }
+
+      // Processor
+      TestHandler testHandler =
+        new TestHandler();
+      ThriftTest.Processor testProcessor =
+        new ThriftTest.Processor(testHandler);
+
+      // Transport
+      TServerSocket tServerSocket =
+        new TServerSocket(port);
+
+      // Protocol factory
+      TProtocolFactory tProtocolFactory =
+        new TBinaryProtocol.Factory();
+
+      TServer serverEngine;
+
+      // Simple Server
+      // serverEngine = new TSimpleServer(testProcessor, tServerSocket);
+
+      // ThreadPool Server
+      serverEngine = new TThreadPoolServer(testProcessor, tServerSocket, tProtocolFactory);
+
+      // Run it
+      System.out.println("Starting the server on port " + port + "...");
+      serverEngine.serve();
+
+    } catch (Exception x) {
+      x.printStackTrace();
+    }
+    System.out.println("done.");
+  }
+}
diff --git a/lib/java/test/org/apache/thrift/test/ToStringTest.java b/lib/java/test/org/apache/thrift/test/ToStringTest.java
new file mode 100644
index 0000000..569a61c
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/ToStringTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.thrift.test;
+
+import thrift.test.*;
+
+/**
+ */
+public class ToStringTest {
+  public static void main(String[] args) throws Exception {
+    JavaTestHelper object = new JavaTestHelper();
+    object.req_int = 0;
+    object.req_obj = "";
+
+
+    object.req_bin = new byte[] {
+      0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15,
+      16, -17, 18, -19, 20, -21, 22, -23, 24, -25, 26, -27, 28, -29,
+      30, -31, 32, -33, 34, -35, 36, -37, 38, -39, 40, -41, 42, -43, 44,
+      -45, 46, -47, 48, -49, 50, -51, 52, -53, 54, -55, 56, -57, 58, -59,
+      60, -61, 62, -63, 64, -65, 66, -67, 68, -69, 70, -71, 72, -73, 74,
+      -75, 76, -77, 78, -79, 80, -81, 82, -83, 84, -85, 86, -87, 88, -89,
+      90, -91, 92, -93, 94, -95, 96, -97, 98, -99, 100, -101, 102, -103,
+      104, -105, 106, -107, 108, -109, 110, -111, 112, -113, 114, -115,
+      116, -117, 118, -119, 120, -121, 122, -123, 124, -125, 126, -127,
+    };
+
+    if (!object.toString().equals(
+        "JavaTestHelper(req_int:0, req_obj:, req_bin:"+
+        "00 FF 02 FD 04 FB 06 F9 08 F7 0A F5 0C F3 0E F1 10 EF 12 ED 14 "+
+        "EB 16 E9 18 E7 1A E5 1C E3 1E E1 20 DF 22 DD 24 DB 26 D9 28 D7 "+
+        "2A D5 2C D3 2E D1 30 CF 32 CD 34 CB 36 C9 38 C7 3A C5 3C C3 3E "+
+        "C1 40 BF 42 BD 44 BB 46 B9 48 B7 4A B5 4C B3 4E B1 50 AF 52 AD "+
+        "54 AB 56 A9 58 A7 5A A5 5C A3 5E A1 60 9F 62 9D 64 9B 66 99 68 "+
+        "97 6A 95 6C 93 6E 91 70 8F 72 8D 74 8B 76 89 78 87 7A 85 7C 83 "+
+        "7E 81)")) {
+      throw new RuntimeException();
+    }
+ 
+    object.req_bin = new byte[] {
+      0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15,
+      16, -17, 18, -19, 20, -21, 22, -23, 24, -25, 26, -27, 28, -29,
+      30, -31, 32, -33, 34, -35, 36, -37, 38, -39, 40, -41, 42, -43, 44,
+      -45, 46, -47, 48, -49, 50, -51, 52, -53, 54, -55, 56, -57, 58, -59,
+      60, -61, 62, -63, 64, -65, 66, -67, 68, -69, 70, -71, 72, -73, 74,
+      -75, 76, -77, 78, -79, 80, -81, 82, -83, 84, -85, 86, -87, 88, -89,
+      90, -91, 92, -93, 94, -95, 96, -97, 98, -99, 100, -101, 102, -103,
+      104, -105, 106, -107, 108, -109, 110, -111, 112, -113, 114, -115,
+      116, -117, 118, -119, 120, -121, 122, -123, 124, -125, 126, -127,
+      0,
+    };
+
+    if (!object.toString().equals(
+        "JavaTestHelper(req_int:0, req_obj:, req_bin:"+
+        "00 FF 02 FD 04 FB 06 F9 08 F7 0A F5 0C F3 0E F1 10 EF 12 ED 14 "+
+        "EB 16 E9 18 E7 1A E5 1C E3 1E E1 20 DF 22 DD 24 DB 26 D9 28 D7 "+
+        "2A D5 2C D3 2E D1 30 CF 32 CD 34 CB 36 C9 38 C7 3A C5 3C C3 3E "+
+        "C1 40 BF 42 BD 44 BB 46 B9 48 B7 4A B5 4C B3 4E B1 50 AF 52 AD "+
+        "54 AB 56 A9 58 A7 5A A5 5C A3 5E A1 60 9F 62 9D 64 9B 66 99 68 "+
+        "97 6A 95 6C 93 6E 91 70 8F 72 8D 74 8B 76 89 78 87 7A 85 7C 83 "+
+        "7E 81 ...)")) {
+      throw new RuntimeException();
+    } 
+
+    object.req_bin = new byte[] {};
+    object.setOpt_binIsSet(true);
+
+
+    if (!object.toString().equals(
+        "JavaTestHelper(req_int:0, req_obj:, req_bin:)")) {
+      throw new RuntimeException();
+    } 
+  }
+}
+
diff --git a/lib/java/test/org/apache/thrift/test/WriteStruct.java b/lib/java/test/org/apache/thrift/test/WriteStruct.java
new file mode 100644
index 0000000..474c808
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/test/WriteStruct.java
@@ -0,0 +1,47 @@
+/*
+ * 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.thrift.test;
+
+import java.io.BufferedOutputStream;
+import java.io.FileOutputStream;
+
+import org.apache.thrift.protocol.TProtocol;
+import org.apache.thrift.protocol.TProtocolFactory;
+import org.apache.thrift.transport.TIOStreamTransport;
+import org.apache.thrift.transport.TTransport;
+
+public class WriteStruct {
+  public static void main(String[] args) throws Exception {
+    if (args.length != 2) {
+      System.out.println("usage: java -cp build/classes org.apache.thrift.test.WriteStruct filename proto_factory_class");
+      System.out.println("Write out an instance of Fixtures.compactProtocolTestStruct to 'file'. Use a protocol from 'proto_factory_class'.");
+    }
+    
+    TTransport trans = new TIOStreamTransport(new BufferedOutputStream(new FileOutputStream(args[0])));
+    
+    TProtocolFactory factory = (TProtocolFactory)Class.forName(args[1]).newInstance();
+    
+    TProtocol proto = factory.getProtocol(trans);
+    
+    Fixtures.compactProtoTestStruct.write(proto);
+    trans.flush();
+  }
+
+}