THRIFT-3360 Improve cross test servers and clients further

This closes #629
diff --git a/test/README.md b/test/README.md
index c1a73ec..066b34f 100755
--- a/test/README.md
+++ b/test/README.md
@@ -161,7 +161,9 @@
       #define TEST_STRUCTS       2  // 0000 0010
       #define TEST_CONTAINERS    4  // 0000 0100
       #define TEST_EXCEPTIONS    8  // 0000 1000
-      #define TEST_NOTUSED     240  // 1111 0000 (reserved bits)
+      #define TEST_UNKNOWN      64  // 0100 0000 (Failed to prepare environemt etc.)
+      #define TEST_TIMEOUT     128  // 1000 0000
+      #define TEST_NOTUSED      48  // 0011 0000 (reserved bits)
 
 Tests that have not been executed at all count as errors.
 
diff --git a/test/ThriftTest.thrift b/test/ThriftTest.thrift
index a749566..8eef23c 100644
--- a/test/ThriftTest.thrift
+++ b/test/ThriftTest.thrift
@@ -292,7 +292,7 @@
    * Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s'
    * @param string arg - a string indication what type of exception to throw
    * if arg0 == "Xception" throw Xception with errorCode = 1001 and message = "This is an Xception"
-   * elsen if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and message = "This is an Xception2"
+   * elsen if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and struct_thing.string_thing = "This is an Xception2"
    * else do not throw anything
    * @return Xtruct - an Xtruct with string_thing = arg1
    */
diff --git a/test/c_glib/src/test_client.c b/test/c_glib/src/test_client.c
index b1fe065..fd429c8 100644
--- a/test/c_glib/src/test_client.c
+++ b/test/c_glib/src/test_client.c
@@ -204,7 +204,7 @@
       gint byte_thing, i32_thing, inner_byte_thing, inner_i32_thing;
       gint64 i64_thing, inner_i64_thing;
 
-      TTestXtruct  *xtruct_out,  *xtruct_in,  *inner_xtruct_in;
+      TTestXtruct  *xtruct_out,  *xtruct_out2, *xtruct_in,  *inner_xtruct_in;
       TTestXtruct2 *xtruct2_out, *xtruct2_in;
 
       GHashTable *map_out, *map_in, *inner_map_in;
@@ -217,8 +217,9 @@
       GArray *list_out, *list_in;
 
       TTestNumberz numberz;
+      TTestNumberz numberz2;
 
-      TTestUserId user_id, *user_id_ptr;
+      TTestUserId user_id, *user_id_ptr, *user_id_ptr2;
 
       TTestInsanity *insanity_out, *insanity_in;
       GHashTable *user_map;
@@ -1021,17 +1022,28 @@
                     NULL);
 
       numberz = T_TEST_NUMBERZ_FIVE;
+      numberz2 = T_TEST_NUMBERZ_EIGHT;
       user_id_ptr = g_malloc (sizeof *user_id_ptr);
-      *user_id_ptr = 5000;
+      *user_id_ptr = 5;
+      user_id_ptr2 = g_malloc (sizeof *user_id_ptr);
+      *user_id_ptr2 = 8;
       g_hash_table_insert (user_map, (gpointer)numberz, user_id_ptr);
+      g_hash_table_insert (user_map, (gpointer)numberz2, user_id_ptr2);
       g_hash_table_unref (user_map);
 
       xtruct_out = g_object_new (T_TEST_TYPE_XTRUCT,
-                                 "string_thing", "Truck",
-                                 "byte_thing",   8,
-                                 "i32_thing",    8,
-                                 "i64_thing",    8LL,
+                                 "string_thing", "Hello2",
+                                 "byte_thing",   2,
+                                 "i32_thing",    2,
+                                 "i64_thing",    2LL,
                                  NULL);
+      xtruct_out2 = g_object_new (T_TEST_TYPE_XTRUCT,
+                                 "string_thing", "Goodbye4",
+                                 "byte_thing",   4,
+                                 "i32_thing",    4,
+                                 "i64_thing",    4LL,
+                                 NULL);
+      g_ptr_array_add (xtructs, xtruct_out2);
       g_ptr_array_add (xtructs, xtruct_out);
       g_ptr_array_unref (xtructs);
 
diff --git a/test/c_glib/src/thrift_test_handler.c b/test/c_glib/src/thrift_test_handler.c
index d82befb..a9983b5 100644
--- a/test/c_glib/src/thrift_test_handler.c
+++ b/test/c_glib/src/thrift_test_handler.c
@@ -472,8 +472,6 @@
                                    const TTestInsanity  *argument,
                                    GError              **error)
 {
-  TTestXtruct *hello;
-  TTestXtruct *goodbye;
   TTestXtruct *xtruct_in;
 
   gchar *string_thing = NULL;
@@ -483,7 +481,6 @@
 
   GPtrArray *xtructs;
 
-  TTestInsanity *crazy;
   TTestInsanity *looney;
 
   GHashTable *user_map;
@@ -502,50 +499,10 @@
   guint i;
 
   THRIFT_UNUSED_VAR (iface);
-  THRIFT_UNUSED_VAR (argument);
   THRIFT_UNUSED_VAR (error);
 
   printf ("testInsanity()\n");
 
-  hello = g_object_new (T_TEST_TYPE_XTRUCT,
-                        "string_thing", "Hello2",
-                        "byte_thing",   2,
-                        "i32_thing",    2,
-                        "i64_thing",    2,
-                        NULL);
-
-  goodbye = g_object_new (T_TEST_TYPE_XTRUCT,
-                          "string_thing", "Goodbye4",
-                          "byte_thing",   4,
-                          "i32_thing",    4,
-                          "i64_thing",    4,
-                          NULL);
-
-  crazy = g_object_new (T_TEST_TYPE_INSANITY, NULL);
-  g_object_get (crazy,
-                "userMap", &user_map,
-                "xtructs", &xtructs,
-                NULL);
-
-  user_id = g_malloc(sizeof *user_id);
-  *user_id = 8;
-  g_hash_table_insert (user_map,
-                       GINT_TO_POINTER (T_TEST_NUMBERZ_EIGHT),
-                       user_id);
-
-  g_ptr_array_add (xtructs, goodbye);
-
-  user_id = g_malloc(sizeof *user_id);
-  *user_id = 5;
-  g_hash_table_insert (user_map,
-                       GINT_TO_POINTER (T_TEST_NUMBERZ_FIVE),
-                       user_id);
-
-  g_ptr_array_add (xtructs, hello);
-
-  g_hash_table_unref (user_map);
-  g_ptr_array_unref (xtructs);
-
   first_map = g_hash_table_new_full (g_direct_hash,
                                      g_direct_equal,
                                      NULL,
@@ -557,17 +514,17 @@
 
   g_hash_table_insert (first_map,
                        GINT_TO_POINTER (T_TEST_NUMBERZ_TWO),
-                       crazy);
+                       argument);
   g_hash_table_insert (first_map,
                        GINT_TO_POINTER (T_TEST_NUMBERZ_THREE),
-                       crazy);
+                       argument);
 
-  /* Increment crazy's ref count since first_map now holds two
+  /* Increment argument's ref count since first_map now holds two
      references to it and would otherwise attempt to deallocate it
      twice during destruction. We do this instead of creating a copy
-     of crazy in order to mimic the C++ implementation (and since,
-     frankly, the world needs less crazy, not more). */
-  g_object_ref (crazy);
+     of argument in order to mimic the C++ implementation (and since,
+     frankly, the world needs less argument, not more). */
+  g_object_ref (argument);
 
   looney = g_object_new (T_TEST_TYPE_INSANITY, NULL);
   g_hash_table_insert (second_map,
diff --git a/test/cpp/src/TestClient.cpp b/test/cpp/src/TestClient.cpp
index 7c425a9..e709899 100644
--- a/test/cpp/src/TestClient.cpp
+++ b/test/cpp/src/TestClient.cpp
@@ -107,6 +107,12 @@
 }
 
 int main(int argc, char** argv) {
+  int ERR_BASETYPES = 1;
+  int ERR_STRUCTS = 2;
+  int ERR_CONTAINERS = 4;
+  int ERR_EXCEPTIONS = 8;
+  int ERR_UNKNOWN = 64;
+
   string file_path = boost::filesystem::system_complete(argv[0]).string();
   string dir_path = file_path.substr(0, file_path.size() - EXECUTABLE_FILE_NAME_LENGTH);
 #if _WIN32
@@ -149,7 +155,7 @@
 
   if (vm.count("help")) {
     cout << desc << "\n";
-    return 1;
+    return ERR_UNKNOWN;
   }
 
   try {
@@ -175,7 +181,7 @@
   } catch (std::exception& e) {
     cerr << e.what() << endl;
     cout << desc << "\n";
-    return 1;
+    return ERR_UNKNOWN;
   }
 
   if (vm.count("ssl")) {
@@ -267,10 +273,6 @@
   uint64_t time_tot = 0;
 
   int return_code = 0;
-  int ERR_BASETYPES = 1;
-  int ERR_STRUCTS = 2;
-  int ERR_CONTAINERS = 4;
-  int ERR_EXCEPTIONS = 8;
 
   int test = 0;
   for (test = 0; test < numTests; ++test) {
@@ -279,7 +281,7 @@
       transport->open();
     } catch (TTransportException& ttx) {
       printf("Connect failed: %s\n", ttx.what());
-      return 1;
+      return ERR_UNKNOWN;
     }
 
     /**
diff --git a/test/cpp/src/TestServer.cpp b/test/cpp/src/TestServer.cpp
index e5bc31e..66d3bb2 100644
--- a/test/cpp/src/TestServer.cpp
+++ b/test/cpp/src/TestServer.cpp
@@ -221,34 +221,14 @@
   }
 
   void testInsanity(map<UserId, map<Numberz::type, Insanity> >& insane, const Insanity& argument) {
-    (void)argument;
     printf("testInsanity()\n");
 
-    Xtruct hello;
-    hello.string_thing = "Hello2";
-    hello.byte_thing = 2;
-    hello.i32_thing = 2;
-    hello.i64_thing = 2;
-
-    Xtruct goodbye;
-    goodbye.string_thing = "Goodbye4";
-    goodbye.byte_thing = 4;
-    goodbye.i32_thing = 4;
-    goodbye.i64_thing = 4;
-
-    Insanity crazy;
-    crazy.userMap.insert(make_pair(Numberz::EIGHT, 8));
-    crazy.xtructs.push_back(goodbye);
-
     Insanity looney;
-    crazy.userMap.insert(make_pair(Numberz::FIVE, 5));
-    crazy.xtructs.push_back(hello);
-
     map<Numberz::type, Insanity> first_map;
     map<Numberz::type, Insanity> second_map;
 
-    first_map.insert(make_pair(Numberz::TWO, crazy));
-    first_map.insert(make_pair(Numberz::THREE, crazy));
+    first_map.insert(make_pair(Numberz::TWO, argument));
+    first_map.insert(make_pair(Numberz::THREE, argument));
 
     second_map.insert(make_pair(Numberz::SIX, looney));
 
diff --git a/test/hs/Makefile.am b/test/hs/Makefile.am
index e171248..b41a391 100644
--- a/test/hs/Makefile.am
+++ b/test/hs/Makefile.am
@@ -39,3 +39,5 @@
 all-local: stubs
 	ghc -igen-hs TestServer.hs
 	ghc -igen-hs TestClient.hs
+
+precross: all-local
diff --git a/test/hs/TestServer.hs b/test/hs/TestServer.hs
index a880a5e..90ec11e 100755
--- a/test/hs/TestServer.hs
+++ b/test/hs/TestServer.hs
@@ -235,7 +235,7 @@
     System.IO.putStrLn $ "testMultiException(" ++ show s1 ++ ", " ++ show s2 ++  ")"
     case s1 of
       "Xception"   -> throw $ Xception 1001 "This is an Xception"
-      "Xception2"  -> throw $ Xception2 2002 default_Xtruct
+      "Xception2"  -> throw $ Xception2 2002 $ Xtruct "This is an Xception2" 0 0 0
       "TException" -> throw ThriftException
       _ -> return default_Xtruct{ xtruct_string_thing = s2 }
 
diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json
index ee12ebf..9c56751 100644
--- a/test/known_failures_Linux.json
+++ b/test/known_failures_Linux.json
@@ -5,6 +5,9 @@
   "c_glib-csharp_binary_framed-ip",
   "c_glib-hs_binary_buffered-ip",
   "c_glib-hs_binary_framed-ip",
+  "c_glib-java_binary_buffered-ip",
+  "c_glib-java_binary_framed-fastframed-ip",
+  "c_glib-java_binary_framed-ip",
   "c_glib-nodejs_binary_buffered-ip",
   "c_glib-nodejs_binary_framed-ip",
   "c_glib-py_binary-accel_buffered-ip",
@@ -109,13 +112,21 @@
   "csharp-nodejs_json_buffered-ip-ssl",
   "csharp-nodejs_json_framed-ip",
   "csharp-nodejs_json_framed-ip-ssl",
+  "csharp-py_binary-accel_buffered-ip",
   "csharp-py_binary-accel_buffered-ip-ssl",
+  "csharp-py_binary-accel_framed-ip",
   "csharp-py_binary-accel_framed-ip-ssl",
+  "csharp-py_binary_buffered-ip",
   "csharp-py_binary_buffered-ip-ssl",
+  "csharp-py_binary_framed-ip",
   "csharp-py_binary_framed-ip-ssl",
+  "csharp-py_compact_buffered-ip",
   "csharp-py_compact_buffered-ip-ssl",
+  "csharp-py_compact_framed-ip",
   "csharp-py_compact_framed-ip-ssl",
+  "csharp-py_json_buffered-ip",
   "csharp-py_json_buffered-ip-ssl",
+  "csharp-py_json_framed-ip",
   "csharp-py_json_framed-ip-ssl",
   "csharp-rb_binary-accel_buffered-ip",
   "csharp-rb_binary-accel_framed-ip",
@@ -125,8 +136,6 @@
   "csharp-rb_compact_framed-ip",
   "csharp-rb_json_buffered-ip",
   "csharp-rb_json_framed-ip",
-  "go-c_glib_binary_buffered-ip",
-  "go-c_glib_binary_framed-ip",
   "go-cpp_json_buffered-ip",
   "go-cpp_json_buffered-ip-ssl",
   "go-cpp_json_framed-ip",
@@ -139,6 +148,12 @@
   "go-csharp_json_framed-ip-ssl",
   "go-hs_json_buffered-ip",
   "go-hs_json_framed-ip",
+  "go-java_json_buffered-ip",
+  "go-java_json_buffered-ip-ssl",
+  "go-java_json_framed-fastframed-ip",
+  "go-java_json_framed-fastframed-ip-ssl",
+  "go-java_json_framed-ip",
+  "go-java_json_framed-ip-ssl",
   "go-nodejs_binary_buffered-ip",
   "go-nodejs_binary_buffered-ip-ssl",
   "go-nodejs_binary_framed-ip",
@@ -161,12 +176,11 @@
   "hs-csharp_compact_framed-ip",
   "hs-csharp_json_buffered-ip",
   "hs-csharp_json_framed-ip",
-  "hs-go_binary_buffered-ip",
-  "hs-go_binary_framed-ip",
-  "hs-go_compact_buffered-ip",
-  "hs-go_compact_framed-ip",
   "hs-go_json_buffered-ip",
   "hs-go_json_framed-ip",
+  "hs-java_json_buffered-ip",
+  "hs-java_json_framed-fastframed-ip",
+  "hs-java_json_framed-ip",
   "hs-nodejs_binary_buffered-ip",
   "hs-nodejs_binary_framed-ip",
   "hs-nodejs_compact_buffered-ip",
@@ -194,8 +208,6 @@
   "java-rb_json_buffered-ip",
   "java-rb_json_fastframed-framed-ip",
   "java-rb_json_framed-ip",
-  "nodejs-c_glib_binary_buffered-ip",
-  "nodejs-c_glib_binary_framed-ip",
   "nodejs-cpp_binary_buffered-ip",
   "nodejs-cpp_binary_buffered-ip-ssl",
   "nodejs-cpp_binary_framed-ip",
@@ -226,7 +238,24 @@
   "nodejs-hs_compact_framed-ip",
   "nodejs-hs_json_buffered-ip",
   "nodejs-hs_json_framed-ip",
+  "nodejs-java_binary_buffered-ip",
+  "nodejs-java_binary_buffered-ip-ssl",
+  "nodejs-java_binary_framed-fastframed-ip",
+  "nodejs-java_binary_framed-fastframed-ip-ssl",
+  "nodejs-java_binary_framed-ip",
+  "nodejs-java_binary_framed-ip-ssl",
+  "nodejs-java_compact_buffered-ip",
+  "nodejs-java_compact_buffered-ip-ssl",
+  "nodejs-java_compact_framed-fastframed-ip",
+  "nodejs-java_compact_framed-fastframed-ip-ssl",
+  "nodejs-java_compact_framed-ip",
+  "nodejs-java_compact_framed-ip-ssl",
+  "nodejs-java_json_buffered-ip",
   "nodejs-java_json_buffered-ip-ssl",
+  "nodejs-java_json_framed-fastframed-ip",
+  "nodejs-java_json_framed-fastframed-ip-ssl",
+  "nodejs-java_json_framed-ip",
+  "nodejs-java_json_framed-ip-ssl",
   "nodejs-py_binary-accel_buffered-ip",
   "nodejs-py_binary-accel_buffered-ip-ssl",
   "nodejs-py_binary-accel_framed-ip",
@@ -278,16 +307,15 @@
   "py-rb_compact_framed-ip",
   "py-rb_json_buffered-ip",
   "py-rb_json_framed-ip",
-  "rb-c_glib_accel-binary_buffered-ip",
-  "rb-c_glib_accel-binary_framed-ip",
-  "rb-c_glib_binary_buffered-ip",
-  "rb-c_glib_binary_framed-ip",
   "rb-cpp_json_buffered-ip",
   "rb-cpp_json_framed-ip",
   "rb-csharp_json_buffered-ip",
   "rb-csharp_json_framed-ip",
   "rb-hs_json_buffered-ip",
   "rb-hs_json_framed-ip",
+  "rb-java_json_buffered-ip",
+  "rb-java_json_framed-fastframed-ip",
+  "rb-java_json_framed-ip",
   "rb-nodejs_json_buffered-ip",
   "rb-nodejs_json_framed-ip",
   "rb-rb_json_buffered-ip",
diff --git a/test/py/TestClient.py b/test/py/TestClient.py
index 51111a6..7fe48f6 100755
--- a/test/py/TestClient.py
+++ b/test/py/TestClient.py
@@ -175,24 +175,27 @@
     self.assertEqual(y, x)
 
   def testEnum(self):
+    print('testEnum')
     x = Numberz.FIVE
     y = self.client.testEnum(x)
     self.assertEqual(y, x)
 
   def testTypedef(self):
+    print('testTypedef')
     x = 0xffffffffffffff # 7 bytes of 0xff
     y = self.client.testTypedef(x)
     self.assertEqual(y, x)
 
+  @unittest.skip('Cannot use dict as dict key')
   def testMapMap(self):
+    print('testMapMap')
     # does not work: dict() is not a hashable type, so a dict() cannot be used as a key in another dict()
-    #x = { {1:10, 2:20}, {1:100, 2:200, 3:300}, {1:1000, 2:2000, 3:3000, 4:4000} }
-    try:
-      y = self.client.testMapMap()
-    except:
-      pass
+    x = {{1: 10, 2: 20}, {1: 100, 2: 200, 3: 300}, {1: 1000, 2: 2000, 3: 3000, 4: 4000}}
+    y = self.client.testMapMap(x)
+    self.assertEqual(y, x)
 
   def testMulti(self):
+    print('testMulti')
     xpected = Xtruct(string_thing='Hello2', byte_thing=74, i32_thing=0xff00ff, i64_thing=0xffffffffd0d0)
     y = self.client.testMulti(xpected.byte_thing,
           xpected.i32_thing,
@@ -203,11 +206,12 @@
     self.assertEqual(y, xpected)
 
   def testException(self):
+    print('testException')
     self.client.testException('Safe')
     try:
       self.client.testException('Xception')
       self.fail("should have gotten exception")
-    except Xception, x:
+    except Xception as x:
       self.assertEqual(x.errorCode, 1001)
       self.assertEqual(x.message, 'Xception')
       # TODO ensure same behavior for repr within generated python variants
@@ -216,12 +220,33 @@
       #self.assertEqual(x_repr, 'Xception(errorCode=1001, message=\'Xception\')')
 
     try:
-      self.client.testException("throw_undeclared")
-      self.fail("should have thrown exception")
-    except Exception: # type is undefined
+      self.client.testException('TException')
+      self.fail("should have gotten exception")
+    except TException as x:
       pass
 
+    # Should not throw
+    self.client.testException('success')
+
+  def testMultiException(self):
+    print('testMultiException')
+    try:
+      self.client.testMultiException('Xception', 'ignore')
+    except Xception as ex:
+      self.assertEqual(ex.errorCode, 1001)
+      self.assertEqual(ex.message, 'This is an Xception')
+
+    try:
+      self.client.testMultiException('Xception2', 'ignore')
+    except Xception2 as ex:
+      self.assertEqual(ex.errorCode, 2002)
+      self.assertEqual(ex.struct_thing.string_thing, 'This is an Xception2')
+
+    y = self.client.testMultiException('success', 'foobar')
+    self.assertEqual(y.string_thing, 'foobar')
+
   def testOneway(self):
+    print('testOneway')
     start = time.time()
     self.client.testOneway(1) # type is int, not float
     end = time.time()
@@ -229,6 +254,7 @@
                     "oneway sleep took %f sec" % (end - start))
 
   def testOnewayThenNormal(self):
+    print('testOnewayThenNormal')
     self.client.testOneway(1) # type is int, not float
     self.assertEqual(self.client.testString('Python'), 'Python')